From 4b95874e18fa2faa31495e7c1a258fd63494a72b Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Mon, 5 Nov 2012 17:19:49 -0500 Subject: filter: removing '.version' lines in ASM code for compat with CLANG. --- gnuradio-core/src/lib/filter/3dnow_float_dotprod_really_simple.S | 2 +- gnuradio-core/src/lib/filter/3dnow_float_dotprod_simple.S | 2 +- gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow.S | 2 +- gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow64.S | 2 +- gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext.S | 2 +- gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext64.S | 2 +- gnuradio-core/src/lib/filter/ccomplex_dotprod_sse.S | 2 +- gnuradio-core/src/lib/filter/ccomplex_dotprod_sse64.S | 2 +- gnuradio-core/src/lib/filter/complex_dotprod_3dnow.S | 2 +- gnuradio-core/src/lib/filter/complex_dotprod_3dnow64.S | 2 +- gnuradio-core/src/lib/filter/complex_dotprod_3dnowext.S | 2 +- gnuradio-core/src/lib/filter/complex_dotprod_3dnowext64.S | 2 +- gnuradio-core/src/lib/filter/complex_dotprod_sse.S | 2 +- gnuradio-core/src/lib/filter/complex_dotprod_sse64.S | 2 +- gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow.S | 2 +- gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow64.S | 2 +- gnuradio-core/src/lib/filter/fcomplex_dotprod_sse.S | 2 +- gnuradio-core/src/lib/filter/fcomplex_dotprod_sse64.S | 2 +- gnuradio-core/src/lib/filter/float_dotprod_3dnow.S | 2 +- gnuradio-core/src/lib/filter/float_dotprod_3dnow64.S | 2 +- gnuradio-core/src/lib/filter/float_dotprod_sse.S | 2 +- gnuradio-core/src/lib/filter/float_dotprod_sse64.S | 2 +- gnuradio-core/src/lib/filter/short_dotprod_mmx.S | 2 +- gnuradio-core/src/lib/filter/short_dotprod_mmx64.S | 2 +- 24 files changed, 24 insertions(+), 24 deletions(-) diff --git a/gnuradio-core/src/lib/filter/3dnow_float_dotprod_really_simple.S b/gnuradio-core/src/lib/filter/3dnow_float_dotprod_really_simple.S index 0cd686736..546a4a6f3 100644 --- a/gnuradio-core/src/lib/filter/3dnow_float_dotprod_really_simple.S +++ b/gnuradio-core/src/lib/filter/3dnow_float_dotprod_really_simple.S @@ -52,7 +52,7 @@ .file "3dnow_float_dotprod_really_simple.s" - .version "01.01" +// .version "01.01" .text .p2align 4 .globl sse_float_dotprod diff --git a/gnuradio-core/src/lib/filter/3dnow_float_dotprod_simple.S b/gnuradio-core/src/lib/filter/3dnow_float_dotprod_simple.S index 5af3fc5c9..c721c3601 100644 --- a/gnuradio-core/src/lib/filter/3dnow_float_dotprod_simple.S +++ b/gnuradio-core/src/lib/filter/3dnow_float_dotprod_simple.S @@ -52,7 +52,7 @@ .file "3dnow_float_dotprod_simple.s" - .version "01.01" +// .version "01.01" .text .p2align 4 .globl sse_float_dotprod diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow.S b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow.S index 8844e5108..f66356337 100644 --- a/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow.S +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow.S @@ -55,7 +55,7 @@ #include "assembly.h" .file "ccomplex_dotprod_3dnow.S" - .version "01.01" +// .version "01.01" .text .p2align 4 .globl GLOB_SYMB(ccomplex_dotprod_3dnow) diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow64.S b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow64.S index d92fe17a3..e81d21993 100644 --- a/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow64.S +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow64.S @@ -56,7 +56,7 @@ .file "ccomplex_dotprod_3dnow64.S" - .version "01.01" +// .version "01.01" .text .p2align 4 .globl GLOB_SYMB(ccomplex_dotprod_3dnow) diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext.S b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext.S index c4a02d7fb..22c390bdd 100644 --- a/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext.S +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext.S @@ -55,7 +55,7 @@ #include "assembly.h" .file "ccomplex_dotprod_3dnowext.S" - .version "01.01" +// .version "01.01" .text .p2align 4 .globl GLOB_SYMB(ccomplex_dotprod_3dnowext) diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext64.S b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext64.S index c4f9e1970..75608914b 100644 --- a/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext64.S +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext64.S @@ -55,7 +55,7 @@ #include "assembly.h" .file "ccomplex_dotprod_3dnowext64.S" - .version "01.01" +// .version "01.01" .text .p2align 4 .globl GLOB_SYMB(ccomplex_dotprod_3dnowext) diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse.S b/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse.S index b50a3690d..3d16c352e 100644 --- a/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse.S +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse.S @@ -55,7 +55,7 @@ #include "assembly.h" .file "ccomplex_dotprod_sse.S" - .version "01.01" +// .version "01.01" .text .p2align 4 .globl GLOB_SYMB(ccomplex_dotprod_sse) diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse64.S b/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse64.S index ef89ae638..95ac3dac3 100644 --- a/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse64.S +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse64.S @@ -56,7 +56,7 @@ .file "ccomplex_dotprod_sse64.S" - .version "01.01" +// .version "01.01" .text .p2align 4 .globl GLOB_SYMB(ccomplex_dotprod_sse) diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_3dnow.S b/gnuradio-core/src/lib/filter/complex_dotprod_3dnow.S index df7761c40..be49bb863 100644 --- a/gnuradio-core/src/lib/filter/complex_dotprod_3dnow.S +++ b/gnuradio-core/src/lib/filter/complex_dotprod_3dnow.S @@ -53,7 +53,7 @@ #include "assembly.h" .file "complex_dotprod_3dnow.S" - .version "01.01" +// .version "01.01" .text .p2align 4 .globl GLOB_SYMB(complex_dotprod_3dnow) diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_3dnow64.S b/gnuradio-core/src/lib/filter/complex_dotprod_3dnow64.S index ac5a7d1be..f1c813078 100644 --- a/gnuradio-core/src/lib/filter/complex_dotprod_3dnow64.S +++ b/gnuradio-core/src/lib/filter/complex_dotprod_3dnow64.S @@ -54,7 +54,7 @@ .file "complex_dotprod_3dnow64.S" - .version "01.01" +// .version "01.01" .text .p2align 4 .globl GLOB_SYMB(complex_dotprod_3dnow) diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext.S b/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext.S index 1d4be32c3..52f04f10c 100644 --- a/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext.S +++ b/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext.S @@ -53,7 +53,7 @@ #include "assembly.h" .file "complex_dotprod_3dnowext.S" - .version "01.01" +// .version "01.01" .text .p2align 4 .globl GLOB_SYMB(complex_dotprod_3dnowext) diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext64.S b/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext64.S index 018fefe28..6d7ad5ad4 100644 --- a/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext64.S +++ b/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext64.S @@ -54,7 +54,7 @@ .file "complex_dotprod_3dnowext64.S" - .version "01.01" +// .version "01.01" .text .p2align 4 .globl GLOB_SYMB(complex_dotprod_3dnowext) diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_sse.S b/gnuradio-core/src/lib/filter/complex_dotprod_sse.S index fff1057dd..fb998cc45 100644 --- a/gnuradio-core/src/lib/filter/complex_dotprod_sse.S +++ b/gnuradio-core/src/lib/filter/complex_dotprod_sse.S @@ -56,7 +56,7 @@ .file "complex_dotprod_sse.S" - .version "01.01" +// .version "01.01" .text .p2align 4 .globl GLOB_SYMB(complex_dotprod_sse) diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_sse64.S b/gnuradio-core/src/lib/filter/complex_dotprod_sse64.S index 77f0c3178..67d3519e4 100644 --- a/gnuradio-core/src/lib/filter/complex_dotprod_sse64.S +++ b/gnuradio-core/src/lib/filter/complex_dotprod_sse64.S @@ -56,7 +56,7 @@ .file "complex_dotprod_sse64.S" - .version "01.01" +// .version "01.01" .text .p2align 4 .globl GLOB_SYMB(complex_dotprod_sse) diff --git a/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow.S b/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow.S index a4e69461e..536e46dc1 100644 --- a/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow.S +++ b/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow.S @@ -53,7 +53,7 @@ .file "fcomplex_dotprod_3dnow.S" - .version "01.01" +// .version "01.01" .text .p2align 4 .globl GLOB_SYMB(fcomplex_dotprod_3dnow) diff --git a/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow64.S b/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow64.S index 9bbf56301..d9a695949 100644 --- a/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow64.S +++ b/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow64.S @@ -53,7 +53,7 @@ .file "fcomplex_dotprod_3dnow64.S" - .version "01.01" +// .version "01.01" .text .p2align 4 .globl GLOB_SYMB(fcomplex_dotprod_3dnow) diff --git a/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse.S b/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse.S index e516f0a61..4c5e956f2 100644 --- a/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse.S +++ b/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse.S @@ -56,7 +56,7 @@ .file "fcomplex_dotprod_sse.S" - .version "01.01" +// .version "01.01" .text .p2align 4 .globl GLOB_SYMB(fcomplex_dotprod_sse) diff --git a/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse64.S b/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse64.S index 605d87130..53a4f25e0 100644 --- a/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse64.S +++ b/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse64.S @@ -56,7 +56,7 @@ .file "fcomplex_dotprod_sse64.S" - .version "01.01" +// .version "01.01" .text .p2align 4 .globl GLOB_SYMB(fcomplex_dotprod_sse) diff --git a/gnuradio-core/src/lib/filter/float_dotprod_3dnow.S b/gnuradio-core/src/lib/filter/float_dotprod_3dnow.S index 914b652af..cdebe9bc3 100644 --- a/gnuradio-core/src/lib/filter/float_dotprod_3dnow.S +++ b/gnuradio-core/src/lib/filter/float_dotprod_3dnow.S @@ -54,7 +54,7 @@ .file "float_dotprod_3dnow.S" - .version "01.01" +// .version "01.01" .text .p2align 4 .globl GLOB_SYMB(float_dotprod_3dnow) diff --git a/gnuradio-core/src/lib/filter/float_dotprod_3dnow64.S b/gnuradio-core/src/lib/filter/float_dotprod_3dnow64.S index 6670553a3..1e859d75a 100644 --- a/gnuradio-core/src/lib/filter/float_dotprod_3dnow64.S +++ b/gnuradio-core/src/lib/filter/float_dotprod_3dnow64.S @@ -54,7 +54,7 @@ .file "float_dotprod_3dnow64.S" - .version "01.01" +// .version "01.01" .text .p2align 4 .globl GLOB_SYMB(float_dotprod_3dnow) diff --git a/gnuradio-core/src/lib/filter/float_dotprod_sse.S b/gnuradio-core/src/lib/filter/float_dotprod_sse.S index beddc75b0..66604526d 100644 --- a/gnuradio-core/src/lib/filter/float_dotprod_sse.S +++ b/gnuradio-core/src/lib/filter/float_dotprod_sse.S @@ -54,7 +54,7 @@ .file "float_dotprod_sse.S" - .version "01.01" +// .version "01.01" .text .p2align 4 .globl GLOB_SYMB(float_dotprod_sse) diff --git a/gnuradio-core/src/lib/filter/float_dotprod_sse64.S b/gnuradio-core/src/lib/filter/float_dotprod_sse64.S index 3d425b26b..0dd0764c5 100644 --- a/gnuradio-core/src/lib/filter/float_dotprod_sse64.S +++ b/gnuradio-core/src/lib/filter/float_dotprod_sse64.S @@ -54,7 +54,7 @@ .file "float_dotprod_sse64.S" - .version "01.01" +// .version "01.01" .text .p2align 4 .globl GLOB_SYMB(float_dotprod_sse) diff --git a/gnuradio-core/src/lib/filter/short_dotprod_mmx.S b/gnuradio-core/src/lib/filter/short_dotprod_mmx.S index 48f634a18..0f6801e4b 100644 --- a/gnuradio-core/src/lib/filter/short_dotprod_mmx.S +++ b/gnuradio-core/src/lib/filter/short_dotprod_mmx.S @@ -37,7 +37,7 @@ .file "short_dotprod_mmx.S" - .version "01.01" +// .version "01.01" .text .p2align 3 .globl GLOB_SYMB(short_dotprod_mmx) diff --git a/gnuradio-core/src/lib/filter/short_dotprod_mmx64.S b/gnuradio-core/src/lib/filter/short_dotprod_mmx64.S index c8c9da30a..bafd0e04e 100644 --- a/gnuradio-core/src/lib/filter/short_dotprod_mmx64.S +++ b/gnuradio-core/src/lib/filter/short_dotprod_mmx64.S @@ -37,7 +37,7 @@ .file "short_dotprod_mmx64.S" - .version "01.01" +// .version "01.01" .text .p2align 3 .globl GLOB_SYMB(short_dotprod_mmx) -- cgit From 9b8bbbb8f198a9ede11003f7a15ce7f50b219005 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 19 Nov 2012 19:37:42 -0800 Subject: uhd: include gnuradio paths for swig build first This fixes a potential issue where swig sees old installed headers, where it should be seeing in-tree headers. --- gr-uhd/swig/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gr-uhd/swig/CMakeLists.txt b/gr-uhd/swig/CMakeLists.txt index 795b46567..6d99af350 100644 --- a/gr-uhd/swig/CMakeLists.txt +++ b/gr-uhd/swig/CMakeLists.txt @@ -28,8 +28,8 @@ set(GR_SWIG_FLAGS -DGR_HAVE_UHD) #needed to parse uhd_swig.i set(GR_SWIG_TARGET_DEPS core_swig) set(GR_SWIG_INCLUDE_DIRS - ${GR_UHD_INCLUDE_DIRS} ${GNURADIO_CORE_SWIG_INCLUDE_DIRS} + ${GR_UHD_INCLUDE_DIRS} ) set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/uhd_swig_doc.i) -- cgit From 4d6b277c28b8161ff7db9bade127bab5e03a38ef Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Thu, 22 Nov 2012 09:59:57 -0500 Subject: cmake: Allow user to set Python installation directory from cmake. cmake -DGR_PYTHON_DIR= --- cmake/Modules/GrPython.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/Modules/GrPython.cmake b/cmake/Modules/GrPython.cmake index 14f2b29cd..791114e05 100644 --- a/cmake/Modules/GrPython.cmake +++ b/cmake/Modules/GrPython.cmake @@ -96,11 +96,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) ######################################################################## -- cgit From 83e1adf6f3efee641a994a9f4bb8dc2f827c873b Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Thu, 22 Nov 2012 10:42:03 -0500 Subject: runtime: moved setting of min/max buffer sizes from gr_basic_block to gr_block. --- gnuradio-core/src/lib/runtime/gr_basic_block.cc | 4 +- gnuradio-core/src/lib/runtime/gr_basic_block.h | 77 +--------------------- gnuradio-core/src/lib/runtime/gr_basic_block.i | 6 -- gnuradio-core/src/lib/runtime/gr_block.cc | 4 +- gnuradio-core/src/lib/runtime/gr_block.h | 74 +++++++++++++++++++++ gnuradio-core/src/lib/runtime/gr_block.i | 8 +++ gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc | 20 ++++-- 7 files changed, 101 insertions(+), 92 deletions(-) diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.cc b/gnuradio-core/src/lib/runtime/gr_basic_block.cc index 3d809aa8b..d7263b92d 100644 --- a/gnuradio-core/src/lib/runtime/gr_basic_block.cc +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.cc @@ -45,9 +45,7 @@ gr_basic_block::gr_basic_block(const std::string &name, d_input_signature(input_signature), d_output_signature(output_signature), d_unique_id(s_next_id++), - d_color(WHITE), - d_max_output_buffer(std::max(output_signature->max_streams(),1), -1), - d_min_output_buffer(std::max(output_signature->max_streams(),1), -1) + d_color(WHITE) { s_ncurrently_allocated++; } diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.h b/gnuradio-core/src/lib/runtime/gr_basic_block.h index b8e8148b2..cb6a983c4 100644 --- a/gnuradio-core/src/lib/runtime/gr_basic_block.h +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.h @@ -29,9 +29,8 @@ #include #include #include -#include #include -#include +#include /*! * \brief The abstract base class for all signal processing blocks. @@ -62,21 +61,7 @@ private: }; msg_handler_t d_msg_handler; - - /* - * Used to expand the vectors that hold the min/max buffer sizes. - * - * Specifically, when -1 is used, the vectors are just initialized - * with 1 value; this is used by the flat_flowgraph to expand when - * required to add a new value for new ports on these blocks. - */ - void expand_minmax_buffer(int port) { - if((size_t)port >= d_max_output_buffer.size()) - set_max_output_buffer(port, -1); - if((size_t)port >= d_min_output_buffer.size()) - set_min_output_buffer(port, -1); - } - + protected: friend class gr_flowgraph; friend class gr_flat_flowgraph; // TODO: will be redundant @@ -89,8 +74,6 @@ protected: gr_io_signature_sptr d_output_signature; long d_unique_id; vcolor d_color; - std::vector d_max_output_buffer; - std::vector d_min_output_buffer; gr_basic_block(void){} //allows pure virtual interface sub-classes @@ -123,62 +106,6 @@ public: gr_io_signature_sptr output_signature() const { return d_output_signature; } gr_basic_block_sptr to_basic_block(); // Needed for Python type coercion - /*! - * \brief Returns max buffer size on output port \p i. - */ - long max_output_buffer(size_t i) { - if(i >= d_max_output_buffer.size()) - throw std::invalid_argument("gr_basic_block::max_output_buffer: port out of range."); - return d_max_output_buffer[i]; - } - - /*! - * \brief Sets max buffer size on all output ports. - */ - void set_max_output_buffer(long max_output_buffer) { - for(int i=0; imax_streams(); i++) { - set_max_output_buffer(i, max_output_buffer); - } - } - - /*! - * \brief Sets max buffer size on output port \p port. - */ - void set_max_output_buffer(int port, long max_output_buffer) { - if((size_t)port >= d_max_output_buffer.size()) - d_max_output_buffer.push_back(max_output_buffer); - else - d_max_output_buffer[port] = max_output_buffer; - } - - /*! - * \brief Returns min buffer size on output port \p i. - */ - long min_output_buffer(size_t i) { - if(i >= d_min_output_buffer.size()) - throw std::invalid_argument("gr_basic_block::min_output_buffer: port out of range."); - return d_min_output_buffer[i]; - } - - /*! - * \brief Sets min buffer size on all output ports. - */ - void set_min_output_buffer(long min_output_buffer) { - for(int i=0; imax_streams(); i++) { - set_min_output_buffer(i, min_output_buffer); - } - } - - /*! - * \brief Sets min buffer size on output port \p port. - */ - void set_min_output_buffer(int port, long min_output_buffer) { - if((size_t)port >= d_min_output_buffer.size()) - d_min_output_buffer.push_back(min_output_buffer); - else - d_min_output_buffer[port] = min_output_buffer; - } - /*! * \brief Confirm that ninputs and noutputs is an acceptable combination. * diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.i b/gnuradio-core/src/lib/runtime/gr_basic_block.i index 7713f2fe1..e43cc114c 100644 --- a/gnuradio-core/src/lib/runtime/gr_basic_block.i +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.i @@ -42,12 +42,6 @@ public: long unique_id() const; gr_basic_block_sptr to_basic_block(); bool check_topology (int ninputs, int noutputs); - long max_output_buffer(int i); - void set_max_output_buffer(long max_output_buffer); - void set_max_output_buffer(int port, long max_output_buffer); - long min_output_buffer(int i); - void set_min_output_buffer(long min_output_buffer); - void set_min_output_buffer(int port, long min_output_buffer); }; %rename(block_ncurrently_allocated) gr_basic_block_ncurrently_allocated; diff --git a/gnuradio-core/src/lib/runtime/gr_block.cc b/gnuradio-core/src/lib/runtime/gr_block.cc index 7e01c0ba8..a88052ee0 100644 --- a/gnuradio-core/src/lib/runtime/gr_block.cc +++ b/gnuradio-core/src/lib/runtime/gr_block.cc @@ -42,7 +42,9 @@ gr_block::gr_block (const std::string &name, d_fixed_rate(false), d_max_noutput_items_set(false), d_max_noutput_items(0), - d_tag_propagation_policy(TPP_ALL_TO_ALL) + d_tag_propagation_policy(TPP_ALL_TO_ALL), + d_max_output_buffer(std::max(output_signature->max_streams(),1), -1), + d_min_output_buffer(std::max(output_signature->max_streams(),1), -1) { } diff --git a/gnuradio-core/src/lib/runtime/gr_block.h b/gnuradio-core/src/lib/runtime/gr_block.h index c89138bb3..98339080d 100644 --- a/gnuradio-core/src/lib/runtime/gr_block.h +++ b/gnuradio-core/src/lib/runtime/gr_block.h @@ -288,6 +288,76 @@ class GR_CORE_API gr_block : public gr_basic_block { */ bool is_set_max_noutput_items(); + /* + * Used to expand the vectors that hold the min/max buffer sizes. + * + * Specifically, when -1 is used, the vectors are just initialized + * with 1 value; this is used by the flat_flowgraph to expand when + * required to add a new value for new ports on these blocks. + */ + void expand_minmax_buffer(int port) { + if((size_t)port >= d_max_output_buffer.size()) + set_max_output_buffer(port, -1); + if((size_t)port >= d_min_output_buffer.size()) + set_min_output_buffer(port, -1); + } + + /*! + * \brief Returns max buffer size on output port \p i. + */ + long max_output_buffer(size_t i) { + if(i >= d_max_output_buffer.size()) + throw std::invalid_argument("gr_basic_block::max_output_buffer: port out of range."); + return d_max_output_buffer[i]; + } + + /*! + * \brief Sets max buffer size on all output ports. + */ + void set_max_output_buffer(long max_output_buffer) { + for(int i = 0; i < output_signature()->max_streams(); i++) { + set_max_output_buffer(i, max_output_buffer); + } + } + + /*! + * \brief Sets max buffer size on output port \p port. + */ + void set_max_output_buffer(int port, long max_output_buffer) { + if((size_t)port >= d_max_output_buffer.size()) + d_max_output_buffer.push_back(max_output_buffer); + else + d_max_output_buffer[port] = max_output_buffer; + } + + /*! + * \brief Returns min buffer size on output port \p i. + */ + long min_output_buffer(size_t i) { + if(i >= d_min_output_buffer.size()) + throw std::invalid_argument("gr_basic_block::min_output_buffer: port out of range."); + return d_min_output_buffer[i]; + } + + /*! + * \brief Sets min buffer size on all output ports. + */ + void set_min_output_buffer(long min_output_buffer) { + for(int i=0; imax_streams(); i++) { + set_min_output_buffer(i, min_output_buffer); + } + } + + /*! + * \brief Sets min buffer size on output port \p port. + */ + void set_min_output_buffer(int port, long min_output_buffer) { + if((size_t)port >= d_min_output_buffer.size()) + d_min_output_buffer.push_back(min_output_buffer); + else + d_min_output_buffer[port] = min_output_buffer; + } + // ---------------------------------------------------------------------------- private: @@ -384,6 +454,10 @@ class GR_CORE_API gr_block : public gr_basic_block { uint64_t abs_end, const pmt::pmt_t &key); + std::vector d_max_output_buffer; + std::vector d_min_output_buffer; + + // These are really only for internal use, but leaving them public avoids // having to work up an ever-varying list of friend GR_CORE_APIs diff --git a/gnuradio-core/src/lib/runtime/gr_block.i b/gnuradio-core/src/lib/runtime/gr_block.i index e9341e8cb..db6c1d04a 100644 --- a/gnuradio-core/src/lib/runtime/gr_block.i +++ b/gnuradio-core/src/lib/runtime/gr_block.i @@ -58,6 +58,14 @@ class gr_block : public gr_basic_block { void unset_max_noutput_items(); bool is_set_max_noutput_items(); + // Methods to manage block's min/max buffer sizes. + long max_output_buffer(int i); + void set_max_output_buffer(long max_output_buffer); + void set_max_output_buffer(int port, long max_output_buffer); + long min_output_buffer(int i); + void set_min_output_buffer(long min_output_buffer); + void set_min_output_buffer(int port, long min_output_buffer); + // internal use gr_block_detail_sptr detail () const { return d_detail; } void set_detail (gr_block_detail_sptr detail) { d_detail = detail; } diff --git a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc index b70135b85..b82ef46af 100644 --- a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc +++ b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc @@ -79,19 +79,25 @@ gr_flat_flowgraph::allocate_block_detail(gr_basic_block_sptr block) int ninputs = calc_used_ports(block, true).size(); int noutputs = calc_used_ports(block, false).size(); gr_block_detail_sptr detail = gr_make_block_detail(ninputs, noutputs); + gr_block_sptr grblock = cast_to_block_sptr(block); if (GR_FLAT_FLOWGRAPH_DEBUG) std::cout << "Creating block detail for " << block << std::endl; for (int i = 0; i < noutputs; i++) { - block->expand_minmax_buffer(i); + if(grblock) { + grblock->expand_minmax_buffer(i); + } + gr_buffer_sptr buffer = allocate_buffer(block, i); if (GR_FLAT_FLOWGRAPH_DEBUG) std::cout << "Allocated buffer for output " << block << ":" << i << std::endl; detail->set_output(i, buffer); - // Update the block's max_output_buffer based on what was actually allocated. - block->set_max_output_buffer(i, buffer->bufsize()); + if(grblock) { + // Update the block's max_output_buffer based on what was actually allocated. + grblock->set_max_output_buffer(i, buffer->bufsize()); + } } return detail; @@ -119,15 +125,15 @@ gr_flat_flowgraph::allocate_buffer(gr_basic_block_sptr block, int port) gr_basic_block_vector_t blocks = calc_downstream_blocks(block, port); // limit buffer size if indicated - if(block->max_output_buffer(port) > 0) { + if(grblock->max_output_buffer(port) > 0) { // std::cout << "constraining output items to " << block->max_output_buffer(port) << "\n"; - nitems = std::min((long)nitems, (long)block->max_output_buffer(port)); + nitems = std::min((long)nitems, (long)grblock->max_output_buffer(port)); nitems -= nitems%grblock->output_multiple(); if( nitems < 1 ) throw std::runtime_error("problems allocating a buffer with the given max output buffer constraint!"); } - else if(block->min_output_buffer(port) > 0) { - nitems = std::max((long)nitems, (long)block->min_output_buffer(port)); + else if(grblock->min_output_buffer(port) > 0) { + nitems = std::max((long)nitems, (long)grblock->min_output_buffer(port)); nitems -= nitems%grblock->output_multiple(); if( nitems < 1 ) throw std::runtime_error("problems allocating a buffer with the given min output buffer constraint!"); -- cgit From 1294d9b540b9f68f038b18f706867d87c08be4c8 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 22 Nov 2012 10:51:26 -0800 Subject: gruel: remove erroneous include path from cmake --- gruel/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/gruel/CMakeLists.txt b/gruel/CMakeLists.txt index 3e8c5166e..627135abe 100644 --- a/gruel/CMakeLists.txt +++ b/gruel/CMakeLists.txt @@ -37,7 +37,6 @@ include(GrMiscUtils) GR_SET_GLOBAL(GRUEL_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src/include ${CMAKE_CURRENT_BINARY_DIR}/src/include - ${Boost_INCLUDE_DIRS} ) ######################################################################## -- cgit From b71c875803986664611d2988193f2768bf08f207 Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Thu, 22 Nov 2012 10:56:27 -0800 Subject: filter: don't install .grc file as python file --- gr-filter/examples/CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/gr-filter/examples/CMakeLists.txt b/gr-filter/examples/CMakeLists.txt index d94e5c16e..84a93d55f 100644 --- a/gr-filter/examples/CMakeLists.txt +++ b/gr-filter/examples/CMakeLists.txt @@ -31,9 +31,15 @@ GR_PYTHON_INSTALL(PROGRAMS interpolate.py reconstruction.py resampler.py - resampler_demo.grc synth_filter.py synth_to_chan.py DESTINATION ${GR_PKG_FILTER_EXAMPLES_DIR} COMPONENT "filter_python" ) + +install( + FILES + resampler_demo.grc + DESTINATION ${GR_PKG_FILTER_EXAMPLES_DIR} + COMPONENT "filter_python" +) -- cgit From 5a6f3e4bc8fc6af84bb09294b77bb4456c4c77f0 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Thu, 22 Nov 2012 14:10:31 -0500 Subject: runtime: changed check after cast to gr_block. --- gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc index b82ef46af..e04deb948 100644 --- a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc +++ b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc @@ -79,25 +79,24 @@ gr_flat_flowgraph::allocate_block_detail(gr_basic_block_sptr block) int ninputs = calc_used_ports(block, true).size(); int noutputs = calc_used_ports(block, false).size(); gr_block_detail_sptr detail = gr_make_block_detail(ninputs, noutputs); + gr_block_sptr grblock = cast_to_block_sptr(block); + if(!grblock) + throw std::runtime_error("allocate_block_detail found non-gr_block"); if (GR_FLAT_FLOWGRAPH_DEBUG) std::cout << "Creating block detail for " << block << std::endl; for (int i = 0; i < noutputs; i++) { - if(grblock) { - grblock->expand_minmax_buffer(i); - } + grblock->expand_minmax_buffer(i); gr_buffer_sptr buffer = allocate_buffer(block, i); if (GR_FLAT_FLOWGRAPH_DEBUG) std::cout << "Allocated buffer for output " << block << ":" << i << std::endl; detail->set_output(i, buffer); - if(grblock) { - // Update the block's max_output_buffer based on what was actually allocated. - grblock->set_max_output_buffer(i, buffer->bufsize()); - } + // Update the block's max_output_buffer based on what was actually allocated. + grblock->set_max_output_buffer(i, buffer->bufsize()); } return detail; -- cgit From 2d1d05a8c4cd2f9597bcebe7f0801b5a8948aeab Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Sat, 24 Nov 2012 09:36:47 -0800 Subject: blocks: fix required libs in .pc file --- gr-blocks/gnuradio-blocks.pc.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gr-blocks/gnuradio-blocks.pc.in b/gr-blocks/gnuradio-blocks.pc.in index abcfe017b..c24564157 100644 --- a/gr-blocks/gnuradio-blocks.pc.in +++ b/gr-blocks/gnuradio-blocks.pc.in @@ -5,7 +5,7 @@ includedir=@includedir@ Name: gnuradio-blocks Description: GNU Radio basic block library -Requires: gnuradio-core gnuradio-audio +Requires: gnuradio-core Version: @LIBVER@ Libs: -L${libdir} -lgnuradio-blocks Cflags: -I${includedir} -- cgit From 0d0f6eb364bda1fc6c2d2820e2d8412af3be8c5c Mon Sep 17 00:00:00 2001 From: Ben Reynwar Date: Sat, 24 Nov 2012 19:02:20 -0700 Subject: cmake: Find Qwt6 installed on OSX using macports. --- cmake/Modules/FindQwt.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/Modules/FindQwt.cmake b/cmake/Modules/FindQwt.cmake index f2cf3440d..db5ca6d27 100644 --- a/cmake/Modules/FindQwt.cmake +++ b/cmake/Modules/FindQwt.cmake @@ -11,6 +11,7 @@ find_path (QWT_INCLUDE_DIRS /usr/include/qwt-qt4 /usr/include/qwt /opt/local/include/qwt + /opt/local/lib/qwt.framework/Headers /sw/include/qwt ) @@ -20,6 +21,7 @@ find_library (QWT_LIBRARIES /usr/local/lib /usr/lib /opt/local/lib + /opt/local/lib/qwt.framework /sw/lib ) -- cgit From 9f83463dd5915b307c475a86b8ea46341e63cba6 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 25 Nov 2012 22:52:21 -0800 Subject: core: this should have deparated w/ gr-wavelet --- gnuradio-core/src/lib/swig/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/gnuradio-core/src/lib/swig/CMakeLists.txt b/gnuradio-core/src/lib/swig/CMakeLists.txt index 5b740d916..72a2534f7 100644 --- a/gnuradio-core/src/lib/swig/CMakeLists.txt +++ b/gnuradio-core/src/lib/swig/CMakeLists.txt @@ -26,7 +26,6 @@ link_directories(${Boost_LIBRARY_DIRS}) set(GR_SWIG_INCLUDE_DIRS ${Boost_INCLUDE_DIRS} - ${GSL_INCLUDE_DIRS} ${GRUEL_INCLUDE_DIRS} ${GNURADIO_CORE_SWIG_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR} -- cgit From 9ea88b7b2af1cda2dae9ef5ab733bc1644cd42a3 Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Mon, 26 Nov 2012 06:40:12 -0800 Subject: blocks: fix initializer order warning --- gr-blocks/lib/keep_m_in_n_impl.cc | 4 ++-- gr-blocks/lib/keep_m_in_n_impl.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gr-blocks/lib/keep_m_in_n_impl.cc b/gr-blocks/lib/keep_m_in_n_impl.cc index b3efdd962..312b09c25 100644 --- a/gr-blocks/lib/keep_m_in_n_impl.cc +++ b/gr-blocks/lib/keep_m_in_n_impl.cc @@ -39,10 +39,10 @@ namespace gr { : gr_block("keep_m_in_n", gr_make_io_signature (1, 1, itemsize), gr_make_io_signature (1, 1, itemsize)), - d_itemsize(itemsize), d_m(m), d_n(n), - d_offset(offset) + d_offset(offset), + d_itemsize(itemsize) { // sanity checking assert(d_m > 0); diff --git a/gr-blocks/lib/keep_m_in_n_impl.h b/gr-blocks/lib/keep_m_in_n_impl.h index 5e264dba0..0b8819489 100644 --- a/gr-blocks/lib/keep_m_in_n_impl.h +++ b/gr-blocks/lib/keep_m_in_n_impl.h @@ -30,8 +30,8 @@ namespace gr { class BLOCKS_API keep_m_in_n_impl : public keep_m_in_n { - int d_n; int d_m; + int d_n; int d_count; int d_offset; int d_itemsize; -- cgit From 552b310e49d3584cb61aec18bd9db1f6abf4e3ac Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Mon, 26 Nov 2012 10:34:55 -0500 Subject: core: fixed memory leak issue in arbitrary resampler blocks. --- gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc | 1 + gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.cc | 1 + 2 files changed, 2 insertions(+) diff --git a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc index 06e98447e..ee09fef44 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc +++ b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc @@ -86,6 +86,7 @@ gr_pfb_arb_resampler_ccf::~gr_pfb_arb_resampler_ccf () { for(unsigned int i = 0; i < d_int_rate; i++) { delete d_filters[i]; + delete d_diff_filters[i]; } } diff --git a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.cc b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.cc index 9a9b86992..f01af2e6f 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.cc +++ b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.cc @@ -86,6 +86,7 @@ gr_pfb_arb_resampler_fff::~gr_pfb_arb_resampler_fff () { for(unsigned int i = 0; i < d_int_rate; i++) { delete d_filters[i]; + delete d_diff_filters[i]; } } -- cgit From 61b99449eeaaebe5ccc10758549add9c9e23f710 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Tue, 27 Nov 2012 17:18:28 -0800 Subject: Revert "Revert "Merge remote branch 'jblum-github/python_blocks2' into master"" This reverts commit 3a142bebafdc018bccc80cf124a375b53db03581. Since updating __init__.py for ticket 181, we should have fixed the same bug that was being seen here. Conflicts: gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt --- gnuradio-core/CMakeLists.txt | 4 +- gnuradio-core/src/lib/general/CMakeLists.txt | 1 + gnuradio-core/src/lib/general/general.i | 3 +- gnuradio-core/src/lib/general/gr_block_gateway.cc | 184 ++++++++++++++++ gnuradio-core/src/lib/general/gr_block_gateway.h | 212 +++++++++++++++++++ gnuradio-core/src/lib/general/gr_block_gateway.i | 46 ++++ .../src/python/gnuradio/gr/CMakeLists.txt | 8 + gnuradio-core/src/python/gnuradio/gr/__init__.py | 3 +- gnuradio-core/src/python/gnuradio/gr/gateway.py | 215 +++++++++++++++++++ .../src/python/gnuradio/gr/qa_block_gateway.py | 235 +++++++++++++++++++++ 10 files changed, 907 insertions(+), 4 deletions(-) create mode 100644 gnuradio-core/src/lib/general/gr_block_gateway.cc create mode 100644 gnuradio-core/src/lib/general/gr_block_gateway.h create mode 100644 gnuradio-core/src/lib/general/gr_block_gateway.i create mode 100644 gnuradio-core/src/python/gnuradio/gr/gateway.py create mode 100644 gnuradio-core/src/python/gnuradio/gr/qa_block_gateway.py diff --git a/gnuradio-core/CMakeLists.txt b/gnuradio-core/CMakeLists.txt index 4e76b3c5a..5f26216d3 100644 --- a/gnuradio-core/CMakeLists.txt +++ b/gnuradio-core/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2010-2011 Free Software Foundation, Inc. +# Copyright 2010-2012 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -64,7 +64,7 @@ GR_SET_GLOBAL(GNURADIO_CORE_INCLUDE_DIRS GR_SET_GLOBAL(GNURADIO_CORE_SWIG_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/gruel/src/swig - ${CMAKE_BINARY_DIR}/gruel/src/swig/ + ${CMAKE_BINARY_DIR}/gruel/src/swig ${CMAKE_CURRENT_SOURCE_DIR}/src/lib/swig ${GNURADIO_CORE_INCLUDE_DIRS} ) diff --git a/gnuradio-core/src/lib/general/CMakeLists.txt b/gnuradio-core/src/lib/general/CMakeLists.txt index 3cf7f74e4..074f583a7 100644 --- a/gnuradio-core/src/lib/general/CMakeLists.txt +++ b/gnuradio-core/src/lib/general/CMakeLists.txt @@ -187,6 +187,7 @@ set(gr_core_general_triple_threats gr_agc2_ff gr_align_on_samplenumbers_ss gr_bin_statistics_f + gr_block_gateway gr_bytes_to_syms gr_char_to_float gr_char_to_short diff --git a/gnuradio-core/src/lib/general/general.i b/gnuradio-core/src/lib/general/general.i index 790549c4d..e5a9e970d 100644 --- a/gnuradio-core/src/lib/general/general.i +++ b/gnuradio-core/src/lib/general/general.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. + * Copyright 2004-2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -266,3 +266,4 @@ %include "gr_add_ff.i" %include "gr_vector_map.i" %include "gr_tag_debug.i" +%include "gr_block_gateway.i" diff --git a/gnuradio-core/src/lib/general/gr_block_gateway.cc b/gnuradio-core/src/lib/general/gr_block_gateway.cc new file mode 100644 index 000000000..79b42803a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_block_gateway.cc @@ -0,0 +1,184 @@ +/* + * Copyright 2011-2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include + +/*********************************************************************** + * Helper routines + **********************************************************************/ +template +void copy_pointers(OutType &out, const InType &in){ + out.resize(in.size()); + for (size_t i = 0; i < in.size(); i++){ + out[i] = (void *)(in[i]); + } +} + +/*********************************************************************** + * The gr_block gateway implementation class + **********************************************************************/ +class gr_block_gateway_impl : public gr_block_gateway{ +public: + gr_block_gateway_impl( + gr_feval_ll *handler, + const std::string &name, + gr_io_signature_sptr in_sig, + gr_io_signature_sptr out_sig, + const gr_block_gw_work_type work_type, + const unsigned factor + ): + gr_block(name, in_sig, out_sig), + _handler(handler), + _work_type(work_type) + { + switch(_work_type){ + case GR_BLOCK_GW_WORK_GENERAL: + _decim = 1; //not relevant, but set anyway + _interp = 1; //not relevant, but set anyway + break; + + case GR_BLOCK_GW_WORK_SYNC: + _decim = 1; + _interp = 1; + this->set_fixed_rate(true); + break; + + case GR_BLOCK_GW_WORK_DECIM: + _decim = factor; + _interp = 1; + break; + + case GR_BLOCK_GW_WORK_INTERP: + _decim = 1; + _interp = factor; + this->set_output_multiple(_interp); + break; + } + } + + /******************************************************************* + * Overloads for various scheduler-called functions + ******************************************************************/ + void forecast( + int noutput_items, + gr_vector_int &ninput_items_required + ){ + switch(_work_type){ + case GR_BLOCK_GW_WORK_GENERAL: + _message.action = gr_block_gw_message_type::ACTION_FORECAST; + _message.forecast_args_noutput_items = noutput_items; + _message.forecast_args_ninput_items_required = ninput_items_required; + _handler->calleval(0); + ninput_items_required = _message.forecast_args_ninput_items_required; + return; + + default: + unsigned ninputs = ninput_items_required.size(); + for (unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = fixed_rate_noutput_to_ninput(noutput_items); + return; + } + } + + int general_work( + int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items + ){ + switch(_work_type){ + case GR_BLOCK_GW_WORK_GENERAL: + _message.action = gr_block_gw_message_type::ACTION_GENERAL_WORK; + _message.general_work_args_noutput_items = noutput_items; + _message.general_work_args_ninput_items = ninput_items; + copy_pointers(_message.general_work_args_input_items, input_items); + _message.general_work_args_output_items = output_items; + _handler->calleval(0); + return _message.general_work_args_return_value; + + default: + int r = work (noutput_items, input_items, output_items); + if (r > 0) consume_each(r*_decim/_interp); + return r; + } + } + + int work( + int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items + ){ + _message.action = gr_block_gw_message_type::ACTION_WORK; + _message.work_args_ninput_items = fixed_rate_noutput_to_ninput(noutput_items); + if (_message.work_args_ninput_items == 0) return -1; + _message.work_args_noutput_items = noutput_items; + copy_pointers(_message.work_args_input_items, input_items); + _message.work_args_output_items = output_items; + _handler->calleval(0); + return _message.work_args_return_value; + } + + int fixed_rate_noutput_to_ninput(int noutput_items){ + return (noutput_items*_decim/_interp) + history() - 1; + } + + int fixed_rate_ninput_to_noutput(int ninput_items){ + return std::max(0, ninput_items - (int)history() + 1)*_interp/_decim; + } + + bool start(void){ + _message.action = gr_block_gw_message_type::ACTION_START; + _handler->calleval(0); + return _message.start_args_return_value; + } + + bool stop(void){ + _message.action = gr_block_gw_message_type::ACTION_STOP; + _handler->calleval(0); + return _message.stop_args_return_value; + } + + gr_block_gw_message_type &gr_block_message(void){ + return _message; + } + +private: + gr_feval_ll *_handler; + gr_block_gw_message_type _message; + const gr_block_gw_work_type _work_type; + unsigned _decim, _interp; +}; + +boost::shared_ptr gr_make_block_gateway( + gr_feval_ll *handler, + const std::string &name, + gr_io_signature_sptr in_sig, + gr_io_signature_sptr out_sig, + const gr_block_gw_work_type work_type, + const unsigned factor +){ + return boost::shared_ptr( + new gr_block_gateway_impl(handler, name, in_sig, out_sig, work_type, factor) + ); +} diff --git a/gnuradio-core/src/lib/general/gr_block_gateway.h b/gnuradio-core/src/lib/general/gr_block_gateway.h new file mode 100644 index 000000000..ae91d41b5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_block_gateway.h @@ -0,0 +1,212 @@ +/* + * Copyright 2011-2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GRBLOCK_GATEWAY_H +#define INCLUDED_GRBLOCK_GATEWAY_H + +#include +#include +#include + +/*! + * The work type enum tells the gateway what kind of block to implement. + * The choices are familiar gnuradio block overloads (sync, decim, interp). + */ +enum gr_block_gw_work_type{ + GR_BLOCK_GW_WORK_GENERAL, + GR_BLOCK_GW_WORK_SYNC, + GR_BLOCK_GW_WORK_DECIM, + GR_BLOCK_GW_WORK_INTERP, +}; + +/*! + * Shared message structure between python and gateway. + * Each action type represents a scheduler-called function. + */ +struct gr_block_gw_message_type{ + enum action_type{ + ACTION_GENERAL_WORK, //dispatch work + ACTION_WORK, //dispatch work + ACTION_FORECAST, //dispatch forecast + ACTION_START, //dispatch start + ACTION_STOP, //dispatch stop + }; + + action_type action; + + int general_work_args_noutput_items; + std::vector general_work_args_ninput_items; + std::vector general_work_args_input_items; //TODO this should be const void*, but swig cant int cast it right + std::vector general_work_args_output_items; + int general_work_args_return_value; + + int work_args_ninput_items; + int work_args_noutput_items; + std::vector work_args_input_items; //TODO this should be const void*, but swig cant int cast it right + std::vector work_args_output_items; + int work_args_return_value; + + int forecast_args_noutput_items; + std::vector forecast_args_ninput_items_required; + + bool start_args_return_value; + + bool stop_args_return_value; +}; + +/*! + * The gateway block which performs all the magic. + * + * The gateway provides access to all the gr_block routines. + * The methods prefixed with gr_block__ are renamed + * to class methods without the prefix in python. + */ +class GR_CORE_API gr_block_gateway : virtual public gr_block{ +public: + //! Provide access to the shared message object + virtual gr_block_gw_message_type &gr_block_message(void) = 0; + + long gr_block__unique_id(void) const{ + return gr_block::unique_id(); + } + + std::string gr_block__name(void) const{ + return gr_block::name(); + } + + unsigned gr_block__history(void) const{ + return gr_block::history(); + } + + void gr_block__set_history(unsigned history){ + return gr_block::set_history(history); + } + + void gr_block__set_fixed_rate(bool fixed_rate){ + return gr_block::set_fixed_rate(fixed_rate); + } + + bool gr_block__fixed_rate(void) const{ + return gr_block::fixed_rate(); + } + + void gr_block__set_output_multiple(int multiple){ + return gr_block::set_output_multiple(multiple); + } + + int gr_block__output_multiple(void) const{ + return gr_block::output_multiple(); + } + + void gr_block__consume(int which_input, int how_many_items){ + return gr_block::consume(which_input, how_many_items); + } + + void gr_block__consume_each(int how_many_items){ + return gr_block::consume_each(how_many_items); + } + + void gr_block__produce(int which_output, int how_many_items){ + return gr_block::produce(which_output, how_many_items); + } + + void gr_block__set_relative_rate(double relative_rate){ + return gr_block::set_relative_rate(relative_rate); + } + + double gr_block__relative_rate(void) const{ + return gr_block::relative_rate(); + } + + uint64_t gr_block__nitems_read(unsigned int which_input){ + return gr_block::nitems_read(which_input); + } + + uint64_t gr_block__nitems_written(unsigned int which_output){ + return gr_block::nitems_written(which_output); + } + + gr_block::tag_propagation_policy_t gr_block__tag_propagation_policy(void){ + return gr_block::tag_propagation_policy(); + } + + void gr_block__set_tag_propagation_policy(gr_block::tag_propagation_policy_t p){ + return gr_block::set_tag_propagation_policy(p); + } + + void gr_block__add_item_tag( + unsigned int which_output, const gr_tag_t &tag + ){ + return gr_block::add_item_tag(which_output, tag); + } + + void gr_block__add_item_tag( + unsigned int which_output, + uint64_t abs_offset, + const pmt::pmt_t &key, + const pmt::pmt_t &value, + const pmt::pmt_t &srcid=pmt::PMT_F + ){ + return gr_block::add_item_tag(which_output, abs_offset, key, value, srcid); + } + + std::vector gr_block__get_tags_in_range( + unsigned int which_input, + uint64_t abs_start, + uint64_t abs_end + ){ + std::vector tags; + gr_block::get_tags_in_range(tags, which_input, abs_start, abs_end); + return tags; + } + + std::vector gr_block__get_tags_in_range( + unsigned int which_input, + uint64_t abs_start, + uint64_t abs_end, + const pmt::pmt_t &key + ){ + std::vector tags; + gr_block::get_tags_in_range(tags, which_input, abs_start, abs_end, key); + return tags; + } +}; + +/*! + * Make a new gateway block. + * \param handler the swig director object with callback + * \param name the name of the block (Ex: "Shirley") + * \param in_sig the input signature for this block + * \param out_sig the output signature for this block + * \param work_type the type of block overload to implement + * \param factor the decimation or interpolation factor + * \return a new gateway block + */ +GR_CORE_API boost::shared_ptr gr_make_block_gateway( + gr_feval_ll *handler, + const std::string &name, + gr_io_signature_sptr in_sig, + gr_io_signature_sptr out_sig, + const gr_block_gw_work_type work_type, + const unsigned factor +); + +#endif /* INCLUDED_GRBLOCK_GATEWAY_H */ diff --git a/gnuradio-core/src/lib/general/gr_block_gateway.i b/gnuradio-core/src/lib/general/gr_block_gateway.i new file mode 100644 index 000000000..8adafdfea --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_block_gateway.i @@ -0,0 +1,46 @@ +/* + * Copyright 2011-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. + */ + +//////////////////////////////////////////////////////////////////////// +// standard includes +//////////////////////////////////////////////////////////////////////// +%include +%include +%include + +//////////////////////////////////////////////////////////////////////// +// block headers +//////////////////////////////////////////////////////////////////////// +%{ +#include +%} + +//////////////////////////////////////////////////////////////////////// +// data type support +//////////////////////////////////////////////////////////////////////// +%template(int_vector_t) std::vector; +%template(void_star_vector_t) std::vector; + +//////////////////////////////////////////////////////////////////////// +// block magic +//////////////////////////////////////////////////////////////////////// +GR_SWIG_BLOCK_MAGIC(gr,block_gateway); +%include diff --git a/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt b/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt index 6a0555021..62f3d7e46 100644 --- a/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt +++ b/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt @@ -23,6 +23,7 @@ include(GrPython) GR_PYTHON_INSTALL(FILES __init__.py exceptions.py + gateway.py gr_threading.py gr_threading_23.py gr_threading_24.py @@ -42,6 +43,13 @@ include(GrTest) file(GLOB py_qa_test_files "qa_*.py") foreach(py_qa_test_file ${py_qa_test_files}) get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE) + set(GR_TEST_PYTHON_DIRS + ${CMAKE_SOURCE_DIR}/gruel/src/python + ${CMAKE_BINARY_DIR}/gruel/src/swig + ${CMAKE_BINARY_DIR}/gnuradio-core/src/python + ${CMAKE_BINARY_DIR}/gnuradio-core/src/lib/swig + ) + set(GR_TEST_TARGET_DEPS volk gruel gnuradio-core) GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file}) endforeach(py_qa_test_file) endif(ENABLE_TESTING) diff --git a/gnuradio-core/src/python/gnuradio/gr/__init__.py b/gnuradio-core/src/python/gnuradio/gr/__init__.py index e5a8fdbf9..5d01ea11b 100644 --- a/gnuradio-core/src/python/gnuradio/gr/__init__.py +++ b/gnuradio-core/src/python/gnuradio/gr/__init__.py @@ -1,5 +1,5 @@ # -# Copyright 2003,2004,2006,2008,2009,2010 Free Software Foundation, Inc. +# Copyright 2003-2012 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -28,6 +28,7 @@ from gnuradio_core import * from exceptions import * from hier_block2 import * from top_block import * +from gateway import basic_block, sync_block, decim_block, interp_block # create a couple of aliases serial_to_parallel = stream_to_vector diff --git a/gnuradio-core/src/python/gnuradio/gr/gateway.py b/gnuradio-core/src/python/gnuradio/gr/gateway.py new file mode 100644 index 000000000..244b8b592 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/gateway.py @@ -0,0 +1,215 @@ +# +# Copyright 2011-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. +# + +import gnuradio_core as gr_core +from gnuradio_core import io_signature, io_signaturev +from gnuradio_core import gr_block_gw_message_type +from gnuradio_core import block_gateway +import numpy + +######################################################################## +# Magic to turn pointers into numpy arrays +# http://docs.scipy.org/doc/numpy/reference/arrays.interface.html +######################################################################## +def pointer_to_ndarray(addr, dtype, nitems): + class array_like: + __array_interface__ = { + 'data' : (int(addr), False), + 'typestr' : dtype.base.str, + 'descr' : dtype.base.descr, + 'shape' : (nitems,) + dtype.shape, + 'strides' : None, + 'version' : 3 + } + return numpy.asarray(array_like()).view(dtype.base) + +######################################################################## +# Handler that does callbacks from C++ +######################################################################## +class gateway_handler(gr_core.feval_ll): + + #dont put a constructor, it wont work + + def init(self, callback): + self._callback = callback + + def eval(self, arg): + try: self._callback() + except Exception as ex: + print("handler caught exception: %s"%ex) + import traceback; traceback.print_exc() + raise ex + return 0 + +######################################################################## +# The guts that make this into a gr block +######################################################################## +class gateway_block(object): + + def __init__(self, name, in_sig, out_sig, work_type, factor): + + #ensure that the sigs are iterable dtypes + def sig_to_dtype_sig(sig): + if sig is None: sig = () + return map(numpy.dtype, sig) + self.__in_sig = sig_to_dtype_sig(in_sig) + self.__out_sig = sig_to_dtype_sig(out_sig) + + #cache the ranges to iterate when dispatching work + self.__in_indexes = range(len(self.__in_sig)) + self.__out_indexes = range(len(self.__out_sig)) + + #convert the signatures into gr.io_signatures + def sig_to_gr_io_sigv(sig): + if not len(sig): return io_signature(0, 0, 0) + return io_signaturev(len(sig), len(sig), [s.itemsize for s in sig]) + gr_in_sig = sig_to_gr_io_sigv(self.__in_sig) + gr_out_sig = sig_to_gr_io_sigv(self.__out_sig) + + #create internal gateway block + self.__handler = gateway_handler() + self.__handler.init(self.__gr_block_handle) + self.__gateway = block_gateway( + self.__handler, name, gr_in_sig, gr_out_sig, work_type, factor) + self.__message = self.__gateway.gr_block_message() + + #register gr_block functions + prefix = 'gr_block__' + for attr in [x for x in dir(self.__gateway) if x.startswith(prefix)]: + setattr(self, attr.replace(prefix, ''), getattr(self.__gateway, attr)) + self.pop_msg_queue = lambda: gr_core.gr_block_gw_pop_msg_queue_safe(self.__gateway) + + def to_basic_block(self): + """ + Makes this block connectable by hier/top block python + """ + return self.__gateway.to_basic_block() + + def __gr_block_handle(self): + """ + Dispatch tasks according to the action type specified in the message. + """ + if self.__message.action == gr_block_gw_message_type.ACTION_GENERAL_WORK: + self.__message.general_work_args_return_value = self.general_work( + + input_items=[pointer_to_ndarray( + self.__message.general_work_args_input_items[i], + self.__in_sig[i], + self.__message.general_work_args_ninput_items[i] + ) for i in self.__in_indexes], + + output_items=[pointer_to_ndarray( + self.__message.general_work_args_output_items[i], + self.__out_sig[i], + self.__message.general_work_args_noutput_items + ) for i in self.__out_indexes], + ) + + elif self.__message.action == gr_block_gw_message_type.ACTION_WORK: + self.__message.work_args_return_value = self.work( + + input_items=[pointer_to_ndarray( + self.__message.work_args_input_items[i], + self.__in_sig[i], + self.__message.work_args_ninput_items + ) for i in self.__in_indexes], + + output_items=[pointer_to_ndarray( + self.__message.work_args_output_items[i], + self.__out_sig[i], + self.__message.work_args_noutput_items + ) for i in self.__out_indexes], + ) + + elif self.__message.action == gr_block_gw_message_type.ACTION_FORECAST: + self.forecast( + noutput_items=self.__message.forecast_args_noutput_items, + ninput_items_required=self.__message.forecast_args_ninput_items_required, + ) + + elif self.__message.action == gr_block_gw_message_type.ACTION_START: + self.__message.start_args_return_value = self.start() + + elif self.__message.action == gr_block_gw_message_type.ACTION_STOP: + self.__message.stop_args_return_value = self.stop() + + def forecast(self, noutput_items, ninput_items_required): + """ + forecast is only called from a general block + this is the default implementation + """ + for ninput_item in ninput_items_required: + ninput_item = noutput_items + self.history() - 1; + return + + def general_work(self, *args, **kwargs): + """general work to be overloaded in a derived class""" + raise NotImplementedError("general work not implemented") + + def work(self, *args, **kwargs): + """work to be overloaded in a derived class""" + raise NotImplementedError("work not implemented") + + def start(self): return True + def stop(self): return True + +######################################################################## +# Wrappers for the user to inherit from +######################################################################## +class basic_block(gateway_block): + def __init__(self, name, in_sig, out_sig): + gateway_block.__init__(self, + name=name, + in_sig=in_sig, + out_sig=out_sig, + work_type=gr_core.GR_BLOCK_GW_WORK_GENERAL, + factor=1, #not relevant factor + ) + +class sync_block(gateway_block): + def __init__(self, name, in_sig, out_sig): + gateway_block.__init__(self, + name=name, + in_sig=in_sig, + out_sig=out_sig, + work_type=gr_core.GR_BLOCK_GW_WORK_SYNC, + factor=1, + ) + +class decim_block(gateway_block): + def __init__(self, name, in_sig, out_sig, decim): + gateway_block.__init__(self, + name=name, + in_sig=in_sig, + out_sig=out_sig, + work_type=gr_core.GR_BLOCK_GW_WORK_DECIM, + factor=decim, + ) + +class interp_block(gateway_block): + def __init__(self, name, in_sig, out_sig, interp): + gateway_block.__init__(self, + name=name, + in_sig=in_sig, + out_sig=out_sig, + work_type=gr_core.GR_BLOCK_GW_WORK_INTERP, + factor=interp, + ) diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_block_gateway.py b/gnuradio-core/src/python/gnuradio/gr/qa_block_gateway.py new file mode 100644 index 000000000..911879f6f --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_block_gateway.py @@ -0,0 +1,235 @@ +# +# Copyright 2011-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. +# + +from gnuradio import gr, gr_unittest +import pmt +import numpy + +class add_2_f32_1_f32(gr.sync_block): + def __init__(self): + gr.sync_block.__init__( + self, + name = "add 2 f32", + in_sig = [numpy.float32, numpy.float32], + out_sig = [numpy.float32], + ) + + def work(self, input_items, output_items): + output_items[0][:] = input_items[0] + input_items[1] + return len(output_items[0]) + +class add_2_fc32_1_fc32(gr.sync_block): + def __init__(self): + gr.sync_block.__init__( + self, + name = "add 2 fc32", + in_sig = [numpy.complex64, numpy.complex64], + out_sig = [numpy.complex64], + ) + + def work(self, input_items, output_items): + output_items[0][:] = input_items[0] + input_items[1] + return len(output_items[0]) + +class convolve(gr.sync_block): + """ + A demonstration using block history to properly perform a convolution. + """ + def __init__(self): + gr.sync_block.__init__( + self, + name = "convolve", + in_sig = [numpy.float32], + out_sig = [numpy.float32] + ) + self._taps = [1, 0, 0, 0] + self.set_history(len(self._taps)) + + def work(self, input_items, output_items): + output_items[0][:] = numpy.convolve(input_items[0], self._taps, mode='valid') + return len(output_items[0]) + +class decim2x(gr.decim_block): + def __init__(self): + gr.decim_block.__init__( + self, + name = "decim2x", + in_sig = [numpy.float32], + out_sig = [numpy.float32], + decim = 2 + ) + + def work(self, input_items, output_items): + output_items[0][:] = input_items[0][::2] + return len(output_items[0]) + +class interp2x(gr.interp_block): + def __init__(self): + gr.interp_block.__init__( + self, + name = "interp2x", + in_sig = [numpy.float32], + out_sig = [numpy.float32], + interp = 2 + ) + + def work(self, input_items, output_items): + output_items[0][1::2] = input_items[0] + output_items[0][::2] = input_items[0] + return len(output_items[0]) + +class tag_source(gr.sync_block): + def __init__(self): + gr.sync_block.__init__( + self, + name = "tag source", + in_sig = None, + out_sig = [numpy.float32], + ) + + def work(self, input_items, output_items): + num_output_items = len(output_items[0]) + + #put code here to fill the output items... + + #make a new tag on the middle element every time work is called + count = self.nitems_written(0) + num_output_items/2 + key = pmt.pmt_string_to_symbol("example_key") + value = pmt.pmt_string_to_symbol("example_value") + self.add_item_tag(0, count, key, value) + + return num_output_items + +class tag_sink(gr.sync_block): + def __init__(self): + gr.sync_block.__init__( + self, + name = "tag sink", + in_sig = [numpy.float32], + out_sig = None, + ) + self.key = None + + def work(self, input_items, output_items): + num_input_items = len(input_items[0]) + + #put code here to process the input items... + + #print all the tags received in this work call + nread = self.nitems_read(0) + tags = self.get_tags_in_range(0, nread, nread+num_input_items) + for tag in tags: + #print tag.offset + #print pmt.pmt_symbol_to_string(tag.key) + #print pmt.pmt_symbol_to_string(tag.value) + self.key = pmt.pmt_symbol_to_string(tag.key) + + return num_input_items + +class fc32_to_f32_2(gr.sync_block): + def __init__(self): + gr.sync_block.__init__( + self, + name = "fc32_to_f32_2", + in_sig = [numpy.complex64], + out_sig = [(numpy.float32, 2)], + ) + + def work(self, input_items, output_items): + output_items[0][::,0] = numpy.real(input_items[0]) + output_items[0][::,1] = numpy.imag(input_items[0]) + return len(output_items[0]) + +class test_block_gateway(gr_unittest.TestCase): + + def test_add_f32(self): + tb = gr.top_block() + src0 = gr.vector_source_f([1, 3, 5, 7, 9], False) + src1 = gr.vector_source_f([0, 2, 4, 6, 8], False) + adder = add_2_f32_1_f32() + sink = gr.vector_sink_f() + tb.connect((src0, 0), (adder, 0)) + tb.connect((src1, 0), (adder, 1)) + tb.connect(adder, sink) + tb.run() + self.assertEqual(sink.data(), (1, 5, 9, 13, 17)) + + def test_add_fc32(self): + tb = gr.top_block() + src0 = gr.vector_source_c([1, 3j, 5, 7j, 9], False) + src1 = gr.vector_source_c([0, 2j, 4, 6j, 8], False) + adder = add_2_fc32_1_fc32() + sink = gr.vector_sink_c() + tb.connect((src0, 0), (adder, 0)) + tb.connect((src1, 0), (adder, 1)) + tb.connect(adder, sink) + tb.run() + self.assertEqual(sink.data(), (1, 5j, 9, 13j, 17)) + + def test_convolve(self): + tb = gr.top_block() + src = gr.vector_source_f([1, 2, 3, 4, 5, 6, 7, 8], False) + cv = convolve() + sink = gr.vector_sink_f() + tb.connect(src, cv, sink) + tb.run() + self.assertEqual(sink.data(), (1, 2, 3, 4, 5, 6, 7, 8)) + + def test_decim2x(self): + tb = gr.top_block() + src = gr.vector_source_f([1, 2, 3, 4, 5, 6, 7, 8], False) + d2x = decim2x() + sink = gr.vector_sink_f() + tb.connect(src, d2x, sink) + tb.run() + self.assertEqual(sink.data(), (1, 3, 5, 7)) + + def test_interp2x(self): + tb = gr.top_block() + src = gr.vector_source_f([1, 3, 5, 7, 9], False) + i2x = interp2x() + sink = gr.vector_sink_f() + tb.connect(src, i2x, sink) + tb.run() + self.assertEqual(sink.data(), (1, 1, 3, 3, 5, 5, 7, 7, 9, 9)) + + def test_tags(self): + src = tag_source() + sink = tag_sink() + head = gr.head(gr.sizeof_float, 50000) #should be enough items to get a tag through + tb = gr.top_block() + tb.connect(src, head, sink) + tb.run() + self.assertEqual(sink.key, "example_key") + + def test_fc32_to_f32_2(self): + tb = gr.top_block() + src = gr.vector_source_c([1+2j, 3+4j, 5+6j, 7+8j, 9+10j], False) + convert = fc32_to_f32_2() + v2s = gr.vector_to_stream(gr.sizeof_float, 2) + sink = gr.vector_sink_f() + tb.connect(src, convert, v2s, sink) + tb.run() + self.assertEqual(sink.data(), (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) + +if __name__ == '__main__': + gr_unittest.run(test_block_gateway, "test_block_gateway.xml") + -- cgit From cdf8cb7fd8f8e835a23b7f9e6b62014f86bcf24a Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Wed, 28 Nov 2012 09:39:48 -0800 Subject: utils: adding GRCC - a GNU Radio Companion command-line compiler tool. --- gr-utils/src/python/CMakeLists.txt | 1 + gr-utils/src/python/grcc | 56 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100755 gr-utils/src/python/grcc diff --git a/gr-utils/src/python/CMakeLists.txt b/gr-utils/src/python/CMakeLists.txt index 90caeb234..e5d99d8b6 100644 --- a/gr-utils/src/python/CMakeLists.txt +++ b/gr-utils/src/python/CMakeLists.txt @@ -50,6 +50,7 @@ GR_PYTHON_INSTALL( gr_plot_short gr_plot_qt gr_filter_design + grcc DESTINATION ${GR_RUNTIME_DIR} COMPONENT "utils" ) diff --git a/gr-utils/src/python/grcc b/gr-utils/src/python/grcc new file mode 100755 index 000000000..3ad5505d1 --- /dev/null +++ b/gr-utils/src/python/grcc @@ -0,0 +1,56 @@ +#!/usr/bin/env python +# +# Copyright 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. +# + +try: + from grc.python.Platform import Platform +except ImportError: + from gnuradio.grc.python.Platform import Platform + +from optparse import OptionParser +import os, sys + +class grcc: + def __init__(self, grcfile, out_dir): + self.platform = Platform() + data = self.platform.parse_flow_graph(grcfile) + + self.fg = self.platform.get_new_flow_graph() + self.fg.import_data(data) + self.fg.validate() + + gen = self.platform.get_generator()(self.fg, out_dir) + gen.write() + +if __name__ == "__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." + + parser = OptionParser(conflict_handler="resolve", usage=usage, description=description) + parser.add_option("-d", "--directory", type="string", default='{0}/.grc_gnuradio/'.format(os.environ["HOME"]), + help="Specify the directory to output the compile program [default=%default]") + (options, args) = parser.parse_args () + + if(len(args) != 1): + sys.stderr.write("Please specify a GRC file name to compile.\n") + sys.exit(1) + + g = grcc(args[0], options.directory+"/") -- cgit From abc6ff52be07b544c90f415eb335666be55d0665 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Wed, 28 Nov 2012 13:29:17 -0800 Subject: cmake: adding cmake function to help us run GRCC. --- cmake/Modules/GrMiscUtils.cmake | 67 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/cmake/Modules/GrMiscUtils.cmake b/cmake/Modules/GrMiscUtils.cmake index a73e3e6d7..3e80846d6 100644 --- a/cmake/Modules/GrMiscUtils.cmake +++ b/cmake/Modules/GrMiscUtils.cmake @@ -208,3 +208,70 @@ function(GR_GEN_TARGET_DEPS name var) set(${var} "DEPENDS;${name};COMMAND;${name}" PARENT_SCOPE) endif() endfunction(GR_GEN_TARGET_DEPS) + + +######################################################################## +# 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/src/python/grcc) + + # GRCC uses some stuff in grc and gnuradio-core, so we force + # the known paths here + list(APPEND PYTHONPATHS + ${CMAKE_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/gnuradio-core/src/python + ${CMAKE_SOURCE_DIR}/gnuradio-core/src/lib/swig + ${CMAKE_BINARY_DIR}/gnuradio-core/src/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) -- cgit From 0737dd4449c54523921d140db57a3541cd0befa0 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Wed, 28 Nov 2012 13:29:45 -0800 Subject: digital: fixing GRC file id names to build other than top_block.py. --- gr-digital/examples/demod/ber_simulation.grc | 2 +- gr-digital/examples/demod/digital_freq_lock.grc | 2 +- gr-digital/examples/demod/pam_sync.grc | 2 +- gr-digital/examples/demod/pam_timing.grc | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gr-digital/examples/demod/ber_simulation.grc b/gr-digital/examples/demod/ber_simulation.grc index b7c6a624b..daf8bfde0 100644 --- a/gr-digital/examples/demod/ber_simulation.grc +++ b/gr-digital/examples/demod/ber_simulation.grc @@ -5,7 +5,7 @@ options id - ber_sim + ber_simulation _enabled diff --git a/gr-digital/examples/demod/digital_freq_lock.grc b/gr-digital/examples/demod/digital_freq_lock.grc index df105dd7f..09d3085dd 100644 --- a/gr-digital/examples/demod/digital_freq_lock.grc +++ b/gr-digital/examples/demod/digital_freq_lock.grc @@ -5,7 +5,7 @@ options id - top_block + digital_freq_lock _enabled diff --git a/gr-digital/examples/demod/pam_sync.grc b/gr-digital/examples/demod/pam_sync.grc index f870a0b06..dbd4befa6 100644 --- a/gr-digital/examples/demod/pam_sync.grc +++ b/gr-digital/examples/demod/pam_sync.grc @@ -5,7 +5,7 @@ options id - top_block + pam_sync _enabled diff --git a/gr-digital/examples/demod/pam_timing.grc b/gr-digital/examples/demod/pam_timing.grc index 14a7d403e..c253d9a9f 100644 --- a/gr-digital/examples/demod/pam_timing.grc +++ b/gr-digital/examples/demod/pam_timing.grc @@ -5,7 +5,7 @@ options id - top_block + pam_timing _enabled -- cgit From fbef82839ef85bfd7837f8534af2a3a74018930a Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Wed, 28 Nov 2012 14:06:57 -0800 Subject: utils: updating GRCC with a -e flag to execute the program after building. --- gr-utils/src/python/grcc | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/gr-utils/src/python/grcc b/gr-utils/src/python/grcc index 3ad5505d1..7e5665dc0 100755 --- a/gr-utils/src/python/grcc +++ b/gr-utils/src/python/grcc @@ -30,6 +30,7 @@ import os, sys class grcc: def __init__(self, grcfile, out_dir): + self.out_dir = out_dir self.platform = Platform() data = self.platform.parse_flow_graph(grcfile) @@ -37,8 +38,12 @@ class grcc: self.fg.import_data(data) self.fg.validate() - gen = self.platform.get_generator()(self.fg, out_dir) - gen.write() + self.gen = self.platform.get_generator()(self.fg, out_dir) + self.gen.write() + + def exec_program(self): + progname = self.fg.get_option('id') + os.system("{0}/{1}.py".format(self.out_dir, progname)) if __name__ == "__main__": usage="%prog: [options] filename" @@ -47,6 +52,8 @@ if __name__ == "__main__": parser = OptionParser(conflict_handler="resolve", usage=usage, description=description) parser.add_option("-d", "--directory", type="string", default='{0}/.grc_gnuradio/'.format(os.environ["HOME"]), help="Specify the directory to output the compile program [default=%default]") + parser.add_option("-e", "--execute", action="store_true", default=False, + help="Run the program after compiling [default=%default]") (options, args) = parser.parse_args () if(len(args) != 1): @@ -54,3 +61,6 @@ if __name__ == "__main__": sys.exit(1) g = grcc(args[0], options.directory+"/") + + if(options.execute): + g.exec_program() -- cgit From ff81c844713b5234622ceb906af219a569d0914f Mon Sep 17 00:00:00 2001 From: Tim O'Shea Date: Wed, 28 Nov 2012 14:52:36 -0800 Subject: adding patterned interleaver block --- gr-blocks/grc/blocks_patterned_interleaver.xml | 66 ++++++++++++++++++ gr-blocks/include/blocks/CMakeLists.txt | 1 + gr-blocks/include/blocks/patterned_interleaver.h | 23 +++++++ gr-blocks/lib/CMakeLists.txt | 1 + gr-blocks/lib/patterned_interleaver_impl.cc | 87 ++++++++++++++++++++++++ gr-blocks/lib/patterned_interleaver_impl.h | 61 +++++++++++++++++ gr-blocks/swig/blocks_swig.i | 3 + 7 files changed, 242 insertions(+) create mode 100644 gr-blocks/grc/blocks_patterned_interleaver.xml create mode 100644 gr-blocks/include/blocks/patterned_interleaver.h create mode 100644 gr-blocks/lib/patterned_interleaver_impl.cc create mode 100644 gr-blocks/lib/patterned_interleaver_impl.h diff --git a/gr-blocks/grc/blocks_patterned_interleaver.xml b/gr-blocks/grc/blocks_patterned_interleaver.xml new file mode 100644 index 000000000..8dd0fac41 --- /dev/null +++ b/gr-blocks/grc/blocks_patterned_interleaver.xml @@ -0,0 +1,66 @@ + + + + Patterned Interleaver + blocks_patterned_interleaver + from gnuradio import blocks + blocks.patterned_interleaver($type.size*$vlen, $pattern) + + IO Type + type + enum + + + + + + + + Pattern + pattern + [0,0,1,2] + int_vector + + + Vec Length + vlen + 1 + int + + $vlen >= 1 + + in + $type + $vlen + 1+max($pattern) + + + out + $type + $vlen + + diff --git a/gr-blocks/include/blocks/CMakeLists.txt b/gr-blocks/include/blocks/CMakeLists.txt index ac674528f..787fddba3 100644 --- a/gr-blocks/include/blocks/CMakeLists.txt +++ b/gr-blocks/include/blocks/CMakeLists.txt @@ -118,6 +118,7 @@ install(FILES multiply_const_cc.h multiply_const_ff.h nlog10_ff.h + patterned_interleaver.h repeat.h short_to_char.h short_to_float.h diff --git a/gr-blocks/include/blocks/patterned_interleaver.h b/gr-blocks/include/blocks/patterned_interleaver.h new file mode 100644 index 000000000..cfcdac6e7 --- /dev/null +++ b/gr-blocks/include/blocks/patterned_interleaver.h @@ -0,0 +1,23 @@ +#ifndef INCLUDED_BLOCKS_PATTERNED_INTERLEAVER_H +#define INCLUDED_BLOCKS_PATTERNED_INTERLEAVER_H + +#include +#include + +namespace gr { + namespace blocks { + + class BLOCKS_API patterned_interleaver : virtual public gr_block + { + public: + + typedef boost::shared_ptr sptr; + + static sptr make(size_t itemsize, std::vector pattern); + }; + + } +} + +#endif + diff --git a/gr-blocks/lib/CMakeLists.txt b/gr-blocks/lib/CMakeLists.txt index 0b6c89298..3a8ffac75 100644 --- a/gr-blocks/lib/CMakeLists.txt +++ b/gr-blocks/lib/CMakeLists.txt @@ -160,6 +160,7 @@ list(APPEND gr_blocks_sources multiply_const_cc_impl.cc multiply_const_ff_impl.cc nlog10_ff_impl.cc + patterned_interleaver_impl.cc repeat_impl.cc short_to_char_impl.cc short_to_float_impl.cc diff --git a/gr-blocks/lib/patterned_interleaver_impl.cc b/gr-blocks/lib/patterned_interleaver_impl.cc new file mode 100644 index 000000000..c53ba03d7 --- /dev/null +++ b/gr-blocks/lib/patterned_interleaver_impl.cc @@ -0,0 +1,87 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "patterned_interleaver_impl.h" +#include + +namespace gr { + namespace blocks { + + patterned_interleaver::sptr patterned_interleaver::make(size_t itemsize, std::vector pattern) + { + return gnuradio::get_initial_sptr(new patterned_interleaver_impl(itemsize, pattern)); + } + + patterned_interleaver_impl::patterned_interleaver_impl(size_t itemsize, std::vector pattern) + : gr_block ("patterned_interleaver", + gr_make_io_signature (pattern_max(pattern)+1, pattern_max(pattern)+1, itemsize), + gr_make_io_signature (1, 1, itemsize)), + d_pattern(pattern), d_counts( pattern_max(pattern)+1, 0), d_itemsize(itemsize) + { + BOOST_FOREACH( int i, d_pattern) + { d_counts[i]++; } + set_output_multiple(d_pattern.size()); + } + + int + patterned_interleaver_impl::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + size_t nblks = noutput_items/d_pattern.size(); + + std::vector ii; + for(size_t i=0; i +#include + +namespace gr { + namespace blocks { + + class BLOCKS_API patterned_interleaver_impl : public patterned_interleaver + { + public: + patterned_interleaver_impl(size_t itemsize, std::vector pattern); + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + int pattern_max(std::vector pattern){ + int mval(0); + BOOST_FOREACH( int i, pattern) + { mval = std::max(mval, i); } + return mval; + } + + void forecast (int noutput_items, + gr_vector_int &ninput_items_required); + + std::vector d_pattern; + std::vector d_counts; + size_t d_itemsize; + + }; + + } /* namespace blocks */ +} /* namespace gr */ + +#endif diff --git a/gr-blocks/swig/blocks_swig.i b/gr-blocks/swig/blocks_swig.i index 45b259498..7ec6bb423 100644 --- a/gr-blocks/swig/blocks_swig.i +++ b/gr-blocks/swig/blocks_swig.i @@ -93,6 +93,7 @@ #include "blocks/not_bb.h" #include "blocks/not_ss.h" #include "blocks/not_ii.h" +#include "blocks/patterned_interleaver.h" #include "blocks/or_bb.h" #include "blocks/or_ss.h" #include "blocks/or_ii.h" @@ -181,6 +182,7 @@ %include "blocks/not_bb.h" %include "blocks/not_ss.h" %include "blocks/not_ii.h" +%include "blocks/patterned_interleaver.h" %include "blocks/or_bb.h" %include "blocks/or_ss.h" %include "blocks/or_ii.h" @@ -268,6 +270,7 @@ GR_SWIG_BLOCK_MAGIC2(blocks, nlog10_ff); GR_SWIG_BLOCK_MAGIC2(blocks, not_bb); GR_SWIG_BLOCK_MAGIC2(blocks, not_ss); GR_SWIG_BLOCK_MAGIC2(blocks, not_ii); +GR_SWIG_BLOCK_MAGIC2(blocks, patterned_interleaver); GR_SWIG_BLOCK_MAGIC2(blocks, or_bb); GR_SWIG_BLOCK_MAGIC2(blocks, or_ss); GR_SWIG_BLOCK_MAGIC2(blocks, or_ii); -- cgit From 680c889aec7db3b18a8c81c5405ed141f1b078c7 Mon Sep 17 00:00:00 2001 From: Tim O'Shea Date: Wed, 28 Nov 2012 19:57:59 -0800 Subject: patterned qa added, bugs fixed --- gr-blocks/lib/patterned_interleaver_impl.cc | 8 ++-- gr-blocks/python/qa_patterned_interleaver.py | 56 ++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 4 deletions(-) create mode 100755 gr-blocks/python/qa_patterned_interleaver.py diff --git a/gr-blocks/lib/patterned_interleaver_impl.cc b/gr-blocks/lib/patterned_interleaver_impl.cc index c53ba03d7..437c733a1 100644 --- a/gr-blocks/lib/patterned_interleaver_impl.cc +++ b/gr-blocks/lib/patterned_interleaver_impl.cc @@ -63,14 +63,14 @@ namespace gr { for(size_t i=0; i +#include #include +#include using namespace pmt; @@ -45,7 +47,10 @@ gr_basic_block::gr_basic_block(const std::string &name, d_input_signature(input_signature), d_output_signature(output_signature), d_unique_id(s_next_id++), - d_color(WHITE) + d_symbolic_id(global_block_registry.block_register(this)), + d_symbol_name(global_block_registry.register_symbolic_name(this)), + d_color(WHITE), + message_subscribers(pmt::pmt_make_dict()) { s_ncurrently_allocated++; } @@ -53,6 +58,7 @@ gr_basic_block::gr_basic_block(const std::string &name, gr_basic_block::~gr_basic_block() { s_ncurrently_allocated--; + global_block_registry.block_unregister(this); } gr_basic_block_sptr @@ -60,3 +66,112 @@ gr_basic_block::to_basic_block() { return shared_from_this(); } + +void +gr_basic_block::set_block_alias(std::string name) +{ + global_block_registry.register_symbolic_name(this, name); +} + +// ** Message passing interface ** + +// - register a new input message port +void gr_basic_block::message_port_register_in(pmt::pmt_t port_id){ + msg_queue[port_id] = msg_queue_t(); + } + +// - register a new output message port +void gr_basic_block::message_port_register_out(pmt::pmt_t port_id){ + if(!pmt::pmt_is_symbol(port_id)){ throw std::runtime_error("bad port id"); } + if(pmt::pmt_dict_has_key(message_subscribers, port_id)){ throw std::runtime_error("port already in use"); } + message_subscribers = pmt::pmt_dict_add(message_subscribers, port_id, pmt::PMT_NIL); + } + +// - publish a message on a message port +void gr_basic_block::message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg){ + if(!pmt::pmt_dict_has_key(message_subscribers, port_id)){ throw std::runtime_error("port does not exist"); } + pmt::pmt_t currlist = pmt::pmt_dict_ref(message_subscribers,port_id,pmt::PMT_NIL); + // iterate through subscribers on port + while( pmt::pmt_is_pair(currlist) ){ + pmt::pmt_t target = pmt::pmt_car(currlist); + + pmt::pmt_t block = pmt::pmt_car(target); + pmt::pmt_t port = pmt::pmt_cdr(target); + + currlist = pmt::pmt_cdr(currlist); + gr_basic_block_sptr blk = global_block_registry.block_lookup(block); + //blk->post(msg); + blk->post(port, msg); + } + } + +// - subscribe to a message port +void gr_basic_block::message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target){ + if(!pmt::pmt_dict_has_key(message_subscribers, port_id)){ + std::stringstream ss; + ss << "Port does not exist: \"" << pmt::pmt_write_string(port_id) << "\" on block: " << pmt::pmt_write_string(target) << std::endl; + throw std::runtime_error(ss.str()); + } + pmt::pmt_t currlist = pmt::pmt_dict_ref(message_subscribers,port_id,pmt::PMT_NIL); + message_subscribers = pmt::pmt_dict_add(message_subscribers,port_id,pmt::pmt_list_add(currlist,target)); + } + +void gr_basic_block::message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target){ + if(!pmt::pmt_dict_has_key(message_subscribers, port_id)){ + std::stringstream ss; + ss << "Port does not exist: \"" << pmt::pmt_write_string(port_id) << "\" on block: " << pmt::pmt_write_string(target) << std::endl; + throw std::runtime_error(ss.str()); + } + pmt::pmt_t currlist = pmt::pmt_dict_ref(message_subscribers,port_id,pmt::PMT_NIL); + message_subscribers = pmt::pmt_dict_add(message_subscribers,port_id,pmt::pmt_list_rm(currlist,target)); + } + +void +gr_basic_block::_post(pmt_t which_port, pmt_t msg) +{ + insert_tail(which_port, msg); + //notify_msg(); +} + +void +gr_basic_block::insert_tail(pmt::pmt_t which_port, pmt::pmt_t msg) +{ + gruel::scoped_lock guard(mutex); + + msg_queue[which_port].push_back(msg); + + // wake up thread if BLKD_IN or BLKD_OUT + //input_cond.notify_one(); + //output_cond.notify_one(); + // TODO: reconsider the need for notification of input and output conditions! +} + +pmt_t +gr_basic_block::delete_head_nowait(pmt::pmt_t which_port) +{ + gruel::scoped_lock guard(mutex); + + if (empty_p(which_port)) + return pmt_t(); + + pmt_t m(msg_queue[which_port].front()); + msg_queue[which_port].pop_front(); + + return m; +} + +/* + * Caller must already be holding the mutex + */ +pmt_t +gr_basic_block::delete_head_nowait_already_holding_mutex(pmt::pmt_t which_port) +{ + if (empty_p(which_port)) + return pmt_t(); + + pmt_t m(msg_queue[which_port].front()); + msg_queue[which_port].pop_front(); + + return m; +} + diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.h b/gnuradio-core/src/lib/runtime/gr_basic_block.h index cb6a983c4..31026a2e4 100644 --- a/gnuradio-core/src/lib/runtime/gr_basic_block.h +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.h @@ -30,7 +30,11 @@ #include #include #include +#include +#include #include +#include +#include /*! * \brief The abstract base class for all signal processing blocks. @@ -54,14 +58,23 @@ private: * The thread-safety guarantees mentioned in set_msg_handler are implemented * by the callers of this method. */ - void dispatch_msg(pmt::pmt_t msg) + void dispatch_msg(pmt::pmt_t which_port, pmt::pmt_t msg) { - if (d_msg_handler) // Is there a handler? - d_msg_handler(msg); // Yes, invoke it. + // AA Update this + if (d_msg_handlers.find(which_port) != d_msg_handlers.end()) // Is there a handler? + d_msg_handlers[which_port](msg); // Yes, invoke it. }; - msg_handler_t d_msg_handler; + //msg_handler_t d_msg_handler; + typedef std::map d_msg_handlers_t; + d_msg_handlers_t d_msg_handlers; + typedef std::deque msg_queue_t; + typedef std::map msg_queue_map_t; + msg_queue_map_t msg_queue; + gruel::mutex mutex; //< protects all vars + + protected: friend class gr_flowgraph; friend class gr_flat_flowgraph; // TODO: will be redundant @@ -73,6 +86,9 @@ protected: gr_io_signature_sptr d_input_signature; gr_io_signature_sptr d_output_signature; long d_unique_id; + long d_symbolic_id; + std::string d_symbol_name; + std::string d_symbol_alias; vcolor d_color; gr_basic_block(void){} //allows pure virtual interface sub-classes @@ -98,13 +114,65 @@ protected: void set_color(vcolor color) { d_color = color; } vcolor color() const { return d_color; } + // Message passing interface + std::vector message_inputs; + pmt::pmt_t message_subscribers; + public: virtual ~gr_basic_block(); long unique_id() const { return d_unique_id; } + long symbolic_id() const { return d_symbolic_id; } std::string name() const { return d_name; } + std::string symbol_name() const { return d_symbol_name; } gr_io_signature_sptr input_signature() const { return d_input_signature; } gr_io_signature_sptr output_signature() const { return d_output_signature; } gr_basic_block_sptr to_basic_block(); // Needed for Python type coercion + bool alias_set() { return !d_symbol_alias.empty(); } + std::string alias(){ return alias_set()?d_symbol_alias:symbol_name(); } + pmt::pmt_t alias_pmt(){ return pmt::pmt_intern(alias()); } + void set_block_alias(std::string name); + + // ** Message passing interface ** + void message_port_register_in(pmt::pmt_t port_id); + void message_port_register_out(pmt::pmt_t port_id); + void message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg); + void message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target); + void message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target); + + /*! + * Accept msg, place in queue, arrange for thread to be awakened if it's not already. + */ + void _post(pmt::pmt_t which_port, pmt::pmt_t msg); + + + //! is the queue empty? + //bool empty_p(const pmt::pmt_t &which_port) const { return msg_queue[which_port].empty(); } + bool empty_p(pmt::pmt_t which_port) { return msg_queue[which_port].empty(); } + bool empty_p() { + bool rv = true; + BOOST_FOREACH(msg_queue_map_t::value_type &i, msg_queue){ rv &= msg_queue[i.first].empty(); } + return rv; + } + + //| Acquires and release the mutex + void insert_tail( pmt::pmt_t which_port, pmt::pmt_t msg); + /*! + * \returns returns pmt at head of queue or pmt_t() if empty. + */ + pmt::pmt_t delete_head_nowait( pmt::pmt_t which_port); + /*! + * \returns returns pmt at head of queue or pmt_t() if empty. + * Caller must already be holding the mutex + */ + pmt::pmt_t delete_head_nowait_already_holding_mutex( pmt::pmt_t which_port); + + msg_queue_t::iterator get_iterator(pmt::pmt_t which_port){ + return msg_queue[which_port].begin(); + } + void erase_msg(pmt::pmt_t which_port, msg_queue_t::iterator it){ + msg_queue[which_port].erase(it); + } + /*! * \brief Confirm that ninputs and noutputs is an acceptable combination. @@ -147,8 +215,13 @@ public: * If the block inherits from gr_hier_block2, the runtime system will * ensure that no reentrant calls are made to msg_handler. */ - template void set_msg_handler(T msg_handler){ - d_msg_handler = msg_handler_t(msg_handler); + //template void set_msg_handler(T msg_handler){ + // d_msg_handler = msg_handler_t(msg_handler); + //} + template void set_msg_handler(pmt::pmt_t which_port, T msg_handler){ + if(msg_queue.find(which_port) == msg_queue.end()){ + throw std::runtime_error("attempt to set_msg_handler() on bad input message port!"); } + d_msg_handlers[which_port] = msg_handler_t(msg_handler); } }; diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.i b/gnuradio-core/src/lib/runtime/gr_basic_block.i index e43cc114c..0a8473ba2 100644 --- a/gnuradio-core/src/lib/runtime/gr_basic_block.i +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.i @@ -37,11 +37,14 @@ protected: public: virtual ~gr_basic_block(); std::string name() const; + std::string symbol_name() const; gr_io_signature_sptr input_signature() const; gr_io_signature_sptr output_signature() const; long unique_id() const; gr_basic_block_sptr to_basic_block(); bool check_topology (int ninputs, int noutputs); + std::string alias(); + void set_block_alias(std::string name); }; %rename(block_ncurrently_allocated) gr_basic_block_ncurrently_allocated; diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.cc b/gnuradio-core/src/lib/runtime/gr_block_detail.cc index 2792cd471..337c9518e 100644 --- a/gnuradio-core/src/lib/runtime/gr_block_detail.cc +++ b/gnuradio-core/src/lib/runtime/gr_block_detail.cc @@ -127,12 +127,6 @@ gr_block_detail::produce_each (int how_many_items) } -void -gr_block_detail::_post(pmt_t msg) -{ - d_tpb.insert_tail(msg); -} - uint64_t gr_block_detail::nitems_read(unsigned int which_input) { diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.h b/gnuradio-core/src/lib/runtime/gr_block_detail.h index c96f00db8..16d9f4d42 100644 --- a/gnuradio-core/src/lib/runtime/gr_block_detail.h +++ b/gnuradio-core/src/lib/runtime/gr_block_detail.h @@ -85,11 +85,6 @@ class GR_CORE_API gr_block_detail { */ void produce_each (int how_many_items); - /*! - * Accept msg, place in queue, arrange for thread to be awakened if it's not already. - */ - void _post(pmt::pmt_t msg); - // Return the number of items read on input stream which_input uint64_t nitems_read(unsigned int which_input); diff --git a/gnuradio-core/src/lib/runtime/gr_block_registry.cc b/gnuradio-core/src/lib/runtime/gr_block_registry.cc new file mode 100644 index 000000000..2478e0019 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_block_registry.cc @@ -0,0 +1,58 @@ +#include +#include + +gr_block_registry global_block_registry; + +gr_block_registry::gr_block_registry(){ + d_ref_map = pmt::pmt_make_dict(); +} + +long gr_block_registry::block_register(gr_basic_block* block){ + if(d_map.find(block->name()) == d_map.end()){ + d_map[block->name()] = blocksubmap_t(); + d_map[block->name()][0] = block; + return 0; + } else { + for(size_t i=0; i<=d_map[block->name()].size(); i++){ + if(d_map[block->name()].find(i) == d_map[block->name()].end()){ + d_map[block->name()][i] = block; + return i; + } + } + } + throw std::runtime_error("should not reach this"); +} + +void gr_block_registry::block_unregister(gr_basic_block* block){ + d_map[block->name()].erase( d_map[block->name()].find(block->symbolic_id())); + d_ref_map = pmt::pmt_dict_delete(d_ref_map, pmt::pmt_intern(block->symbol_name())); + if(block->alias_set()){ + d_ref_map = pmt::pmt_dict_delete(d_ref_map, pmt::pmt_intern(block->alias())); + } +} + +std::string gr_block_registry::register_symbolic_name(gr_basic_block* block){ + std::stringstream ss; + ss << block->name() << block->symbolic_id(); + //std::cout << "register_symbolic_name: " << ss.str() << std::endl; + register_symbolic_name(block, ss.str()); + return ss.str(); +} + +void gr_block_registry::register_symbolic_name(gr_basic_block* block, std::string name){ + if(pmt_dict_has_key(d_ref_map, pmt::pmt_intern(name))){ + throw std::runtime_error("symbol already exists, can not re-use!"); + } + d_ref_map = pmt_dict_add(d_ref_map, pmt::pmt_intern(name), pmt::pmt_make_any(block)); +} + +gr_basic_block_sptr gr_block_registry::block_lookup(pmt::pmt_t symbol){ + pmt::pmt_t ref = pmt_dict_ref(d_ref_map, symbol, pmt::PMT_NIL); + if(pmt::pmt_eq(ref, pmt::PMT_NIL)){ + throw std::runtime_error("block lookup failed! block not found!"); + } + gr_basic_block* blk = boost::any_cast( pmt::pmt_any_ref(ref) ); + return blk->shared_from_this(); +} + + diff --git a/gnuradio-core/src/lib/runtime/gr_block_registry.h b/gnuradio-core/src/lib/runtime/gr_block_registry.h new file mode 100644 index 000000000..8f1982984 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_block_registry.h @@ -0,0 +1,36 @@ +#ifndef GR_BLOCK_REGISTRY_H +#define GR_BLOCK_REGISTRY_H + +#include + +#ifndef GR_BASIC_BLOCK_H +class gr_basic_block; +#endif + +class gr_block_registry { + public: + gr_block_registry(); + + long block_register(gr_basic_block* block); + void block_unregister(gr_basic_block* block); + + std::string register_symbolic_name(gr_basic_block* block); + void register_symbolic_name(gr_basic_block* block, std::string name); + + gr_basic_block_sptr block_lookup(pmt::pmt_t symbol); + + private: + + //typedef std::map< long, gr_basic_block_sptr > blocksubmap_t; + typedef std::map< long, gr_basic_block* > blocksubmap_t; + typedef std::map< std::string, blocksubmap_t > blockmap_t; + + blockmap_t d_map; + pmt::pmt_t d_ref_map; + +}; + +extern gr_block_registry global_block_registry; + +#endif + diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.cc b/gnuradio-core/src/lib/runtime/gr_hier_block2.cc index 756852df8..a19bfe195 100644 --- a/gnuradio-core/src/lib/runtime/gr_hier_block2.cc +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.cc @@ -80,6 +80,36 @@ gr_hier_block2::connect(gr_basic_block_sptr src, int src_port, d_detail->connect(src, src_port, dst, dst_port); } +void +gr_hier_block2::msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport, + gr_basic_block_sptr dst, pmt::pmt_t dstport) +{ + if(!pmt::pmt_is_symbol(srcport)){throw std::runtime_error("bad port id"); } + d_detail->msg_connect(src, srcport, dst, dstport); +} + +void +gr_hier_block2::msg_connect(gr_basic_block_sptr src, std::string srcport, + gr_basic_block_sptr dst, std::string dstport) +{ + d_detail->msg_connect(src, pmt::mp(srcport), dst, pmt::mp(dstport)); +} + +void +gr_hier_block2::msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport, + gr_basic_block_sptr dst, pmt::pmt_t dstport) +{ + if(!pmt::pmt_is_symbol(srcport)){throw std::runtime_error("bad port id"); } + d_detail->msg_disconnect(src, srcport, dst, dstport); +} + +void +gr_hier_block2::msg_disconnect(gr_basic_block_sptr src, std::string srcport, + gr_basic_block_sptr dst, std::string dstport) +{ + d_detail->msg_disconnect(src, pmt::mp(srcport), dst, pmt::mp(dstport)); +} + void gr_hier_block2::disconnect(gr_basic_block_sptr block) { diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.h b/gnuradio-core/src/lib/runtime/gr_hier_block2.h index 123178724..e8364a740 100644 --- a/gnuradio-core/src/lib/runtime/gr_hier_block2.h +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.h @@ -97,6 +97,21 @@ public: void connect(gr_basic_block_sptr src, int src_port, gr_basic_block_sptr dst, int dst_port); + /*! + * \brief Add gr-blocks or hierarchical blocks to internal graph and wire together + * + * This adds (if not done earlier by another connect) a pair of gr-blocks or + * hierarchical blocks to the internal message port subscription + */ + void msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport, + gr_basic_block_sptr dst, pmt::pmt_t dstport); + void msg_connect(gr_basic_block_sptr src, std::string srcport, + gr_basic_block_sptr dst, std::string dstport); + void msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport, + gr_basic_block_sptr dst, pmt::pmt_t dstport); + void msg_disconnect(gr_basic_block_sptr src, std::string srcport, + gr_basic_block_sptr dst, std::string dstport); + /*! * \brief Remove a gr-block or hierarchical block from the internal flowgraph. * diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.i b/gnuradio-core/src/lib/runtime/gr_hier_block2.i index eefb965b4..7c0e62f28 100644 --- a/gnuradio-core/src/lib/runtime/gr_hier_block2.i +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.i @@ -38,6 +38,8 @@ gr_hier_block2_sptr gr_make_hier_block2(const std::string name, // better interface in scripting land. %rename(primitive_connect) gr_hier_block2::connect; %rename(primitive_disconnect) gr_hier_block2::disconnect; +%rename(primitive_msg_connect) gr_hier_block2::msg_connect; +%rename(primitive_msg_disconnect) gr_hier_block2::msg_disconnect; class gr_hier_block2 : public gr_basic_block { @@ -54,6 +56,19 @@ public: void connect(gr_basic_block_sptr src, int src_port, gr_basic_block_sptr dst, int dst_port) throw (std::invalid_argument); + void msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport, + gr_basic_block_sptr dst, pmt::pmt_t dstport) + throw (std::runtime_error); + void msg_connect(gr_basic_block_sptr src, std::string srcport, + gr_basic_block_sptr dst, std::string dstport) + throw (std::runtime_error); + void msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport, + gr_basic_block_sptr dst, pmt::pmt_t dstport) + throw (std::runtime_error); + void msg_disconnect(gr_basic_block_sptr src, std::string srcport, + gr_basic_block_sptr dst, std::string dstport) + throw (std::runtime_error); + void disconnect(gr_basic_block_sptr block) throw (std::invalid_argument); void disconnect(gr_basic_block_sptr src, int src_port, diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc index 76c5ce06f..099b2f8e8 100644 --- a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc @@ -143,6 +143,28 @@ gr_hier_block2_detail::connect(gr_basic_block_sptr src, int src_port, // TODO: connects to NC } +void +gr_hier_block2_detail::msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport, + gr_basic_block_sptr dst, pmt::pmt_t dstport) +{ + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "connecting message port..." << std::endl; + + // register the subscription + src->message_port_sub(srcport, pmt::pmt_cons(dst->alias_pmt(), dstport)); +} + +void +gr_hier_block2_detail::msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport, + gr_basic_block_sptr dst, pmt::pmt_t dstport) +{ + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "disconnecting message port..." << std::endl; + + // register the subscription + src->message_port_unsub(srcport, pmt::pmt_cons(dst->alias_pmt(), dstport)); +} + void gr_hier_block2_detail::disconnect(gr_basic_block_sptr block) { diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h index f4f950e9d..f2d2b3c4e 100644 --- a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h @@ -39,6 +39,10 @@ public: void connect(gr_basic_block_sptr block); void connect(gr_basic_block_sptr src, int src_port, gr_basic_block_sptr dst, int dst_port); + void msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport, + gr_basic_block_sptr dst, pmt::pmt_t dstport); + void msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport, + gr_basic_block_sptr dst, pmt::pmt_t dstport); void disconnect(gr_basic_block_sptr block); void disconnect(gr_basic_block_sptr, int src_port, gr_basic_block_sptr, int dst_port); diff --git a/gnuradio-core/src/lib/runtime/gr_msg_accepter.cc b/gnuradio-core/src/lib/runtime/gr_msg_accepter.cc index 5018ee9e6..93d5fb20e 100644 --- a/gnuradio-core/src/lib/runtime/gr_msg_accepter.cc +++ b/gnuradio-core/src/lib/runtime/gr_msg_accepter.cc @@ -41,12 +41,12 @@ gr_msg_accepter::~gr_msg_accepter() } void -gr_msg_accepter::post(pmt_t msg) +gr_msg_accepter::post(pmt_t which_port, pmt_t msg) { // Notify derived class, handled case by case gr_block *p = dynamic_cast(this); if (p) { - p->detail()->_post(msg); + p->_post(which_port,msg); return; } gr_hier_block2 *p2 = dynamic_cast(this); diff --git a/gnuradio-core/src/lib/runtime/gr_msg_accepter.h b/gnuradio-core/src/lib/runtime/gr_msg_accepter.h index 3e5c97638..a497ba6e7 100644 --- a/gnuradio-core/src/lib/runtime/gr_msg_accepter.h +++ b/gnuradio-core/src/lib/runtime/gr_msg_accepter.h @@ -36,7 +36,7 @@ public: gr_msg_accepter(); ~gr_msg_accepter(); - void post(pmt::pmt_t msg); + void post(pmt::pmt_t which_port, pmt::pmt_t msg); }; diff --git a/gnuradio-core/src/lib/runtime/gr_tpb_detail.cc b/gnuradio-core/src/lib/runtime/gr_tpb_detail.cc index 46b33d91f..46eb6bbe0 100644 --- a/gnuradio-core/src/lib/runtime/gr_tpb_detail.cc +++ b/gnuradio-core/src/lib/runtime/gr_tpb_detail.cc @@ -68,43 +68,3 @@ gr_tpb_detail::notify_neighbors(gr_block_detail *d) notify_upstream(d); } -void -gr_tpb_detail::insert_tail(pmt::pmt_t msg) -{ - gruel::scoped_lock guard(mutex); - - msg_queue.push_back(msg); - - // wake up thread if BLKD_IN or BLKD_OUT - input_cond.notify_one(); - output_cond.notify_one(); -} - -pmt_t -gr_tpb_detail::delete_head_nowait() -{ - gruel::scoped_lock guard(mutex); - - if (empty_p()) - return pmt_t(); - - pmt_t m(msg_queue.front()); - msg_queue.pop_front(); - - return m; -} - -/* - * Caller must already be holding the mutex - */ -pmt_t -gr_tpb_detail::delete_head_nowait_already_holding_mutex() -{ - if (empty_p()) - return pmt_t(); - - pmt_t m(msg_queue.front()); - msg_queue.pop_front(); - - return m; -} diff --git a/gnuradio-core/src/lib/runtime/gr_tpb_detail.h b/gnuradio-core/src/lib/runtime/gr_tpb_detail.h index b6e342dee..69feb6007 100644 --- a/gnuradio-core/src/lib/runtime/gr_tpb_detail.h +++ b/gnuradio-core/src/lib/runtime/gr_tpb_detail.h @@ -39,9 +39,6 @@ struct GR_CORE_API gr_tpb_detail { bool output_changed; gruel::condition_variable output_cond; -private: - std::deque msg_queue; - public: gr_tpb_detail() : input_changed(false), output_changed(false) { } @@ -55,6 +52,12 @@ public: //! Called by us to notify both upstream and downstream void notify_neighbors(gr_block_detail *d); + //! Called by pmt msg posters + void notify_msg(){ + input_cond.notify_one(); + output_cond.notify_one(); + } + //! Called by us void clear_changed() { @@ -63,23 +66,6 @@ public: output_changed = false; } - //! is the queue empty? - bool empty_p() const { return msg_queue.empty(); } - - //| Acquires and release the mutex - void insert_tail(pmt::pmt_t msg); - - /*! - * \returns returns pmt at head of queue or pmt_t() if empty. - */ - pmt::pmt_t delete_head_nowait(); - - /*! - * \returns returns pmt at head of queue or pmt_t() if empty. - * Caller must already be holding the mutex - */ - pmt::pmt_t delete_head_nowait_already_holding_mutex(); - private: //! Used by notify_downstream diff --git a/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc b/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc index a5aabb379..1bd3014ad 100644 --- a/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc +++ b/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc @@ -25,6 +25,7 @@ #include #include #include +#include using namespace pmt; @@ -42,8 +43,14 @@ gr_tpb_thread_body::gr_tpb_thread_body(gr_block_sptr block, int max_noutput_item boost::this_thread::interruption_point(); // handle any queued up messages - while ((msg = d->d_tpb.delete_head_nowait())) - block->dispatch_msg(msg); + //BOOST_FOREACH( pmt::pmt_t port, block->msg_queue.keys() ) + + BOOST_FOREACH( gr_basic_block::msg_queue_map_t::value_type &i, block->msg_queue ) + { + while ((msg = block->delete_head_nowait(i.first))){ + block->dispatch_msg(i.first,msg); + } + } d->d_tpb.clear_changed(); s = d_exec.run_one_iteration(); @@ -67,15 +74,18 @@ gr_tpb_thread_body::gr_tpb_thread_body(gr_block_sptr block, int max_noutput_item while (!d->d_tpb.input_changed){ // wait for input or message - while(!d->d_tpb.input_changed && d->d_tpb.empty_p()) + while(!d->d_tpb.input_changed && block->empty_p()) d->d_tpb.input_cond.wait(guard); // handle all pending messages - while ((msg = d->d_tpb.delete_head_nowait_already_holding_mutex())){ - guard.unlock(); // release lock while processing msg - block->dispatch_msg(msg); - guard.lock(); - } + BOOST_FOREACH( gr_basic_block::msg_queue_map_t::value_type &i, block->msg_queue ) + { + while ((msg = block->delete_head_nowait_already_holding_mutex(i.first))){ + guard.unlock(); // release lock while processing msg + block->dispatch_msg(i.first, msg); + guard.lock(); + } + } } } break; @@ -87,15 +97,18 @@ gr_tpb_thread_body::gr_tpb_thread_body(gr_block_sptr block, int max_noutput_item while (!d->d_tpb.output_changed){ // wait for output room or message - while(!d->d_tpb.output_changed && d->d_tpb.empty_p()) + while(!d->d_tpb.output_changed && block->empty_p()) d->d_tpb.output_cond.wait(guard); // handle all pending messages - while ((msg = d->d_tpb.delete_head_nowait_already_holding_mutex())){ - guard.unlock(); // release lock while processing msg - block->dispatch_msg(msg); - guard.lock(); - } + BOOST_FOREACH( gr_basic_block::msg_queue_map_t::value_type &i, block->msg_queue ) + { + while ((msg = block->delete_head_nowait_already_holding_mutex(i.first))){ + guard.unlock(); // release lock while processing msg + block->dispatch_msg(i.first,msg); + guard.lock(); + } + } } } break; diff --git a/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc b/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc index 25ae0b1e1..dc8f0f8a9 100644 --- a/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc +++ b/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc @@ -65,14 +65,15 @@ void qa_set_msg_handler::t0() tb->start(); // Send them... + pmt_t port(pmt_intern("port")); for (int i = 0; i < NMSGS; i++){ - send(nop, mp(mp("example-msg"), mp(i))); + send(nop, port, mp(mp("example-msg"), mp(i))); } // And send a message to null_source to confirm that the default // message handling action (which should be a nop) doesn't dump // core. - send(src, mp(mp("example-msg"), mp(0))); + send(src, port, mp(mp("example-msg"), mp(0))); // Give the messages a chance to be processed boost::this_thread::sleep(boost::posix_time::milliseconds(100)); diff --git a/gnuradio-core/src/python/gnuradio/gr/top_block.py b/gnuradio-core/src/python/gnuradio/gr/top_block.py index 43af8073b..dc1f443aa 100644 --- a/gnuradio-core/src/python/gnuradio/gr/top_block.py +++ b/gnuradio-core/src/python/gnuradio/gr/top_block.py @@ -123,6 +123,12 @@ class top_block(object): for i in range (1, len (points)): self._connect(points[i-1], points[i]) + def msg_connect(self, src, srcport, dst, dstport): + self.primitive_msg_connect(src.to_basic_block(), srcport, dst.to_basic_block(), dstport); + + def msg_disconnect(self, src, srcport, dst, dstport): + self.primitive_msg_disconnect(src.to_basic_block(), srcport, dst.to_basic_block(), dstport); + def _connect(self, src, dst): (src_block, src_port) = self._coerce_endpoint(src) (dst_block, dst_port) = self._coerce_endpoint(dst) diff --git a/grc/python/Connection.py b/grc/python/Connection.py index 218baf074..341dd2d82 100644 --- a/grc/python/Connection.py +++ b/grc/python/Connection.py @@ -31,6 +31,9 @@ class Connection(_Connection, _GUIConnection): def is_msg(self): return self.get_source().get_type() == self.get_sink().get_type() == 'msg' + def is_message(self): + return self.get_source().get_type() == self.get_sink().get_type() == 'message' + def validate(self): """ Validate the connections. diff --git a/grc/python/Constants.py b/grc/python/Constants.py index 1a65caf1c..09c308196 100644 --- a/grc/python/Constants.py +++ b/grc/python/Constants.py @@ -58,6 +58,7 @@ CORE_TYPES = ( #name, key, sizeof, color ('Integer 16', 's16', 2, '#FFFF66'), ('Integer 8', 's8', 1, '#FF66FF'), ('Message Queue', 'msg', 0, '#777777'), + ('Async Message', 'message', 0, '#777777'), ('Wildcard', '', 0, '#FFFFFF'), ) diff --git a/grc/python/Generator.py b/grc/python/Generator.py index 2a6fe51d5..616ea00fc 100644 --- a/grc/python/Generator.py +++ b/grc/python/Generator.py @@ -116,8 +116,9 @@ Add a Misc->Throttle block to your flow graph to avoid CPU congestion.''') #list of regular blocks (all blocks minus the special ones) blocks = filter(lambda b: b not in (imports + parameters), blocks) #list of connections where each endpoint is enabled - connections = filter(lambda c: not c.is_msg(), self._flow_graph.get_enabled_connections()) + connections = filter(lambda c: not (c.is_msg() or c.is_message()), self._flow_graph.get_enabled_connections()) messages = filter(lambda c: c.is_msg(), self._flow_graph.get_enabled_connections()) + messages2 = filter(lambda c: c.is_message(), self._flow_graph.get_enabled_connections()) #list of variable names var_ids = [var.get_id() for var in parameters + variables] #prepend self. @@ -142,6 +143,7 @@ Add a Misc->Throttle block to your flow graph to avoid CPU congestion.''') 'blocks': blocks, 'connections': connections, 'messages': messages, + 'messages2': messages2, 'generate_options': self._generate_options, 'var_id2cbs': var_id2cbs, } diff --git a/grc/python/flow_graph.tmpl b/grc/python/flow_graph.tmpl index 17feb01f6..af55ad641 100644 --- a/grc/python/flow_graph.tmpl +++ b/grc/python/flow_graph.tmpl @@ -189,6 +189,17 @@ gr.io_signaturev($(len($io_sigs)), $(len($io_sigs)), [$(', '.join($size_strs))]) self.connect($make_port_sig($source), $make_port_sig($sink)) #end if #end for +######################################################## +##Create Asynch Message Connections +######################################################## +#if $messages2 + $DIVIDER + # Asynch Message Connections + $DIVIDER +#end if +#for $msg in $messages2 + self.msg_connect(self.$msg.get_source().get_parent().get_id(), "$msg.get_source().get_name()", self.$msg.get_sink().get_parent().get_id(), "$msg.get_sink().get_name()") +#end for ######################################################## ##Create Callbacks diff --git a/gruel/src/include/gruel/msg_accepter.h b/gruel/src/include/gruel/msg_accepter.h index 2dc1a6859..65abd5a6b 100644 --- a/gruel/src/include/gruel/msg_accepter.h +++ b/gruel/src/include/gruel/msg_accepter.h @@ -43,7 +43,7 @@ namespace gruel { * call will not wait for the message either to arrive at the * destination or to be received. */ - virtual void post(pmt::pmt_t msg) = 0; + virtual void post(pmt::pmt_t which_port, pmt::pmt_t msg) = 0; }; typedef boost::shared_ptr msg_accepter_sptr; diff --git a/gruel/src/include/gruel/msg_passing.h b/gruel/src/include/gruel/msg_passing.h index 0cc0cd111..7230dfc5b 100644 --- a/gruel/src/include/gruel/msg_passing.h +++ b/gruel/src/include/gruel/msg_passing.h @@ -45,9 +45,9 @@ namespace gruel { * \returns msg */ static inline pmt::pmt_t - send(msg_accepter_sptr accepter, const pmt::pmt_t &msg) + send(msg_accepter_sptr accepter, const pmt::pmt_t &which_port, const pmt::pmt_t &msg) { - accepter->post(msg); + accepter->post(which_port, msg); return msg; } @@ -64,9 +64,9 @@ namespace gruel { * \returns msg */ static inline pmt::pmt_t - send(msg_accepter *accepter, const pmt::pmt_t &msg) + send(msg_accepter *accepter, const pmt::pmt_t &which_port, const pmt::pmt_t &msg) { - accepter->post(msg); + accepter->post(which_port, msg); return msg; } @@ -83,9 +83,9 @@ namespace gruel { * \returns msg */ static inline pmt::pmt_t - send(msg_accepter &accepter, const pmt::pmt_t &msg) + send(msg_accepter &accepter, const pmt::pmt_t &which_port, const pmt::pmt_t &msg) { - accepter.post(msg); + accepter.post(which_port, msg); return msg; } @@ -102,9 +102,9 @@ namespace gruel { * \returns msg */ static inline pmt::pmt_t - send(pmt::pmt_t accepter, const pmt::pmt_t &msg) + send(pmt::pmt_t accepter, const pmt::pmt_t &which_port, const pmt::pmt_t &msg) { - return send(pmt_msg_accepter_ref(accepter), msg); + return send(pmt_msg_accepter_ref(accepter), which_port, msg); } } /* namespace gruel */ diff --git a/gruel/src/include/gruel/pmt.h b/gruel/src/include/gruel/pmt.h index 1e8b38627..a462155c5 100644 --- a/gruel/src/include/gruel/pmt.h +++ b/gruel/src/include/gruel/pmt.h @@ -729,6 +729,10 @@ GRUEL_API pmt_t pmt_list6(const pmt_t& x1, const pmt_t& x2, const pmt_t& x3, con */ GRUEL_API pmt_t pmt_list_add(pmt_t list, const pmt_t& item); +/*! + * \brief Return \p list with \p item removed from it. + */ +GRUEL_API pmt_t pmt_list_rm(pmt_t list, const pmt_t& item); /* * ------------------------------------------------------------------------ @@ -805,6 +809,15 @@ GRUEL_API std::string pmt_serialize_str(pmt_t obj); */ GRUEL_API pmt_t pmt_deserialize_str(std::string str); +/*! + * \brief Provide a comparator function object to allow pmt use in stl types + */ +class pmt_comperator { + public: + bool operator()(pmt::pmt_t const& p1, pmt::pmt_t const& p2) const + { return pmt::pmt_eqv(p1,p2)?false:p1.get()>p2.get(); } + }; + } /* namespace pmt */ #include diff --git a/gruel/src/lib/pmt/pmt.cc b/gruel/src/lib/pmt/pmt.cc index 1d9125d4e..3eb39ed7b 100644 --- a/gruel/src/lib/pmt/pmt.cc +++ b/gruel/src/lib/pmt/pmt.cc @@ -1324,6 +1324,22 @@ pmt_list_add(pmt_t list, const pmt_t& item) return pmt_reverse(pmt_cons(item, pmt_reverse(list))); } +pmt_t +pmt_list_rm(pmt_t list, const pmt_t& item) +{ + if(pmt_is_pair(list)){ + pmt_t left = pmt_car(list); + pmt_t right = pmt_cdr(list); + if(!pmt_equal(left, item)){ + return pmt_cons(left, pmt_list_rm(right, item)); + } else { + return pmt_list_rm(right, item); + } + } else { + return list; + } +} + pmt_t pmt_caar(pmt_t pair) { diff --git a/gruel/src/lib/pmt/qa_pmt_prims.cc b/gruel/src/lib/pmt/qa_pmt_prims.cc index 6212b8ea4..1bf5fcfb1 100644 --- a/gruel/src/lib/pmt/qa_pmt_prims.cc +++ b/gruel/src/lib/pmt/qa_pmt_prims.cc @@ -472,7 +472,7 @@ class qa_pmt_msg_accepter_nop : public gruel::msg_accepter { public: qa_pmt_msg_accepter_nop(){}; ~qa_pmt_msg_accepter_nop(); - void post(pmt_t){}; + void post(pmt_t,pmt_t){}; }; qa_pmt_msg_accepter_nop::~qa_pmt_msg_accepter_nop(){} @@ -495,9 +495,10 @@ qa_pmt_prims::test_msg_accepter() CPPUNIT_ASSERT_THROW(pmt_msg_accepter_ref(p0), pmt_wrong_type); // just confirm interfaces on send are OK - gruel::send(ma0.get(), sym); - gruel::send(ma0, sym); - gruel::send(p1, sym); + pmt_t port(pmt_intern("port")); + gruel::send(ma0.get(), port, sym); + gruel::send(ma0, port, sym); + gruel::send(p1, port, sym); } diff --git a/gruel/src/swig/pmt_swig.i b/gruel/src/swig/pmt_swig.i index 45cfceadc..d46143424 100644 --- a/gruel/src/swig/pmt_swig.i +++ b/gruel/src/swig/pmt_swig.i @@ -696,6 +696,10 @@ pmt_t pmt_list6(const pmt_t& x1, const pmt_t& x2, const pmt_t& x3, const pmt_t& */ pmt_t pmt_list_add(pmt_t list, const pmt_t& item); +/*! + * \brief Return \p list with \p item removed + */ +pmt_t pmt_list_rm(pmt_t list, const pmt_t& item); /* * ------------------------------------------------------------------------ -- cgit From 4478cb86a5dc9fccf66c2cdd5806419b70c3837e Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Thu, 29 Nov 2012 19:46:29 -0800 Subject: Adding PDU to tagged stream and tagged stream to PDU blocks along with QA python non-stream-connected blocks still need a new thread context --- gnuradio-core/src/lib/io/CMakeLists.txt | 5 + gnuradio-core/src/lib/io/gr_message_debug.cc | 71 +++++++++++ gnuradio-core/src/lib/io/gr_message_debug.h | 59 +++++++++ gnuradio-core/src/lib/io/gr_message_debug.i | 30 +++++ gnuradio-core/src/lib/io/gr_pdu.cc | 43 +++++++ gnuradio-core/src/lib/io/gr_pdu.h | 38 ++++++ gnuradio-core/src/lib/io/gr_pdu.i | 30 +++++ .../src/lib/io/gr_pdu_to_tagged_stream.cc | 131 +++++++++++++++++++ gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.h | 63 ++++++++++ gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.i | 31 +++++ .../src/lib/io/gr_tagged_stream_to_pdu.cc | 139 +++++++++++++++++++++ gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.h | 76 +++++++++++ gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.i | 31 +++++ gnuradio-core/src/lib/io/io.i | 8 ++ gnuradio-core/src/lib/runtime/gr_basic_block.cc | 22 +--- gnuradio-core/src/lib/runtime/gr_basic_block.h | 21 ++-- gnuradio-core/src/lib/runtime/gr_basic_block.i | 3 + gnuradio-core/src/lib/runtime/gr_block.cc | 3 + gnuradio-core/src/lib/runtime/gr_block_registry.cc | 18 +++ gnuradio-core/src/lib/runtime/gr_block_registry.h | 10 +- .../src/lib/runtime/gr_tpb_thread_body.cc | 4 +- gnuradio-core/src/python/gnuradio/gr/qa_pdu.py | 70 +++++++++++ 22 files changed, 873 insertions(+), 33 deletions(-) create mode 100644 gnuradio-core/src/lib/io/gr_message_debug.cc create mode 100644 gnuradio-core/src/lib/io/gr_message_debug.h create mode 100644 gnuradio-core/src/lib/io/gr_message_debug.i create mode 100644 gnuradio-core/src/lib/io/gr_pdu.cc create mode 100644 gnuradio-core/src/lib/io/gr_pdu.h create mode 100644 gnuradio-core/src/lib/io/gr_pdu.i create mode 100644 gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc create mode 100644 gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.h create mode 100644 gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.i create mode 100644 gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.cc create mode 100644 gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.h create mode 100644 gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.i create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_pdu.py diff --git a/gnuradio-core/src/lib/io/CMakeLists.txt b/gnuradio-core/src/lib/io/CMakeLists.txt index 3dea13396..7041f2820 100644 --- a/gnuradio-core/src/lib/io/CMakeLists.txt +++ b/gnuradio-core/src/lib/io/CMakeLists.txt @@ -38,6 +38,7 @@ list(APPEND gnuradio_core_sources ${CMAKE_CURRENT_SOURCE_DIR}/microtune_xxxx.cc ${CMAKE_CURRENT_SOURCE_DIR}/ppio_ppdev.cc ${CMAKE_CURRENT_SOURCE_DIR}/gri_wavfile.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_pdu.cc ) ######################################################################## @@ -59,6 +60,7 @@ install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/microtune_xxxx.h ${CMAKE_CURRENT_SOURCE_DIR}/ppio_ppdev.h ${CMAKE_CURRENT_SOURCE_DIR}/gri_wavfile.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_pdu.h DESTINATION ${GR_INCLUDE_DIR}/gnuradio COMPONENT "core_devel" ) @@ -85,9 +87,11 @@ set(gr_core_io_triple_threats gr_file_source gr_file_descriptor_sink gr_file_descriptor_source + gr_message_debug gr_message_sink gr_message_source gr_message_burst_source + gr_pdu_to_tagged_stream microtune_xxxx_eval_board microtune_4702_eval_board microtune_4937_eval_board @@ -98,6 +102,7 @@ set(gr_core_io_triple_threats gr_wavfile_source gr_wavfile_sink gr_tagged_file_sink + gr_tagged_stream_to_pdu ) foreach(file_tt ${gr_core_io_triple_threats}) diff --git a/gnuradio-core/src/lib/io/gr_message_debug.cc b/gnuradio-core/src/lib/io/gr_message_debug.cc new file mode 100644 index 000000000..84c11c46e --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_debug.cc @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// public constructor that returns a shared_ptr + +gr_message_debug_sptr +gr_make_message_debug () +{ + return gnuradio::get_initial_sptr(new gr_message_debug()); +} + +void gr_message_debug::print(pmt::pmt_t msg){ + std::cout << "******* DEBUG PRINT ********\n"; + pmt::pmt_print(msg); +} + + +gr_message_debug::gr_message_debug () + : gr_sync_block("message_debug", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(0, 0, 0)) +{ + message_port_register_in(pmt::mp("print")); + set_msg_handler(pmt::mp("print"), boost::bind(&gr_message_debug::print, this, _1)); +} + +gr_message_debug::~gr_message_debug() +{ +} + +int +gr_message_debug::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + return 0; // FIXME: replace with default NOP work function in gr_block +} diff --git a/gnuradio-core/src/lib/io/gr_message_debug.h b/gnuradio-core/src/lib/io/gr_message_debug.h new file mode 100644 index 000000000..37d8b7a4d --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_debug.h @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 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_MESSAGE_DEBUG_H +#define INCLUDED_GR_MESSAGE_DEBUG_H + +#include +#include +#include +#include + +class gr_message_debug; +typedef boost::shared_ptr gr_message_debug_sptr; + +GR_CORE_API gr_message_debug_sptr gr_make_message_debug (); + +/*! + * \brief Gather received items into messages and insert into msgq + * \ingroup sink_blk + */ +class GR_CORE_API gr_message_debug : public gr_sync_block +{ + private: + friend GR_CORE_API gr_message_debug_sptr + gr_make_message_debug(); + + void print(pmt::pmt_t msg); + + protected: + gr_message_debug (); + + public: + ~gr_message_debug (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_MESSAGE_DEBUG_H */ diff --git a/gnuradio-core/src/lib/io/gr_message_debug.i b/gnuradio-core/src/lib/io/gr_message_debug.i new file mode 100644 index 000000000..7bd547c91 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_debug.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 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(gr,message_debug); + +%{ +#include +%} + +%include "gr_message_debug.h" + diff --git a/gnuradio-core/src/lib/io/gr_pdu.cc b/gnuradio-core/src/lib/io/gr_pdu.cc new file mode 100644 index 000000000..c5290b610 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_pdu.cc @@ -0,0 +1,43 @@ + +#include + +size_t gr_pdu_itemsize(gr_pdu_vector_type type){ + switch(type){ + case BYTE: + return 1; + case FLOAT: + return sizeof(float); + case COMPLEX: + return sizeof(gr_complex); + default: + throw std::runtime_error("bad type!"); + } +} + +bool gr_pdu_type_matches(gr_pdu_vector_type type, pmt::pmt_t v){ + switch(type){ + case BYTE: + return pmt::pmt_is_u8vector(v); + case FLOAT: + return pmt::pmt_is_f32vector(v); + case COMPLEX: + return pmt::pmt_is_c32vector(v); + default: + throw std::runtime_error("bad type!"); + } +} + +pmt::pmt_t gr_pdu_make_vector(gr_pdu_vector_type type, const uint8_t* buf, size_t items){ + switch(type){ + case BYTE: + return pmt::pmt_init_u8vector(items, buf); + case FLOAT: + return pmt::pmt_init_f32vector(items, (const float*)buf); + case COMPLEX: + return pmt::pmt_init_c32vector(items, (const gr_complex*)buf); + default: + throw std::runtime_error("bad type!"); + } +} + + diff --git a/gnuradio-core/src/lib/io/gr_pdu.h b/gnuradio-core/src/lib/io/gr_pdu.h new file mode 100644 index 000000000..3bea83740 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_pdu.h @@ -0,0 +1,38 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 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_PDU_H +#define GR_PDU_H + +#include +#include + +#define pdu_port_id pmt::mp("pdus") +#define pdu_length_tag pmt::mp("pdu_length") + +enum gr_pdu_vector_type { BYTE, FLOAT, COMPLEX }; + +size_t gr_pdu_itemsize(gr_pdu_vector_type type); +bool gr_pdu_type_matches(gr_pdu_vector_type type, pmt::pmt_t v); +pmt::pmt_t gr_pdu_make_vector(gr_pdu_vector_type type, const uint8_t* buf, size_t items); + +#endif diff --git a/gnuradio-core/src/lib/io/gr_pdu.i b/gnuradio-core/src/lib/io/gr_pdu.i new file mode 100644 index 000000000..7cb3c62c7 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_pdu.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 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 +%} + +enum gr_pdu_vector_type { BYTE, FLOAT, COMPLEX }; + + + diff --git a/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc new file mode 100644 index 000000000..26c1babd6 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc @@ -0,0 +1,131 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +// public constructor that returns a shared_ptr + +gr_pdu_to_tagged_stream_sptr +gr_make_pdu_to_tagged_stream(gr_pdu_vector_type t) +{ + return gnuradio::get_initial_sptr(new gr_pdu_to_tagged_stream(t)); +} + +gr_pdu_to_tagged_stream::gr_pdu_to_tagged_stream (gr_pdu_vector_type t) + : gr_sync_block("pdu_to_tagged_stream", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(1, 1, gr_pdu_itemsize(t))), + d_vectortype(t), d_itemsize(gr_pdu_itemsize(t)) +{ + message_port_register_in(pdu_port_id); +} + +gr_pdu_to_tagged_stream::~gr_pdu_to_tagged_stream() +{ +} + +int +gr_pdu_to_tagged_stream::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + 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); + 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::pmt_is_pair(msg)){ + throw std::runtime_error("received a malformed pdu message!"); + } + + printf("got a msg\n"); + pmt::pmt_print(msg); + + // grab the components of the pdu message + pmt::pmt_t meta(pmt::pmt_car(msg)); // make sure this is NIL || Dict ? + pmt::pmt_t vect(pmt::pmt_cdr(msg)); // make sure this is a vector? + + // compute offset for output tag + uint64_t offset = nitems_written(0) + nout; + + // add a tag for pdu length + add_item_tag(0, offset, pdu_length_tag, pmt::pmt_from_long( pmt::pmt_length(vect) ), pmt::mp(alias())); + + // if we recieved metadata add it as tags + if( !pmt_eq(meta, pmt::PMT_NIL) ){ + pmt::pmt_t pair(pmt::pmt_dict_keys( meta )); + while( !pmt_eq(pair, pmt::PMT_NIL) ){ + pmt::pmt_t k(pmt::pmt_cdr(pair)); + pmt::pmt_t v(pmt::pmt_dict_ref(meta, k, pmt::PMT_NIL)); + add_item_tag(0, offset, k, v, pmt::mp(alias())); + } + } + + // copy vector output + size_t ncopy = std::min((size_t)noutput_items, (size_t)pmt::pmt_length(vect)); + size_t nsave = pmt::pmt_length(vect) - ncopy; + + // copy output + size_t io(0); + nout += ncopy; + memcpy(out, pmt_uniform_vector_elements(vect,io), ncopy*d_itemsize); + + // save leftover items if needed for next work call + if(nsave > 0){ + d_remain.resize(nsave*d_itemsize, 0); + memcpy(&d_remain[0], pmt_uniform_vector_elements(vect,ncopy), nsave*d_itemsize); + } + + } + + return nout; +} diff --git a/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.h b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.h new file mode 100644 index 000000000..3eb2a078b --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.h @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 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_PDU_TO_TAGGED_STREAM_H +#define INCLUDED_GR_PDU_TO_TAGGED_STREAM_H + +#include +#include +#include +#include +#include + +class gr_pdu_to_tagged_stream; +typedef boost::shared_ptr gr_pdu_to_tagged_stream_sptr; + +GR_CORE_API gr_pdu_to_tagged_stream_sptr gr_make_pdu_to_tagged_stream (gr_pdu_vector_type t); + +/*! + * \brief Turn received messages into a stream + * \ingroup source_blk + */ +class GR_CORE_API gr_pdu_to_tagged_stream : public gr_sync_block +{ + private: + gr_pdu_vector_type d_vectortype; + size_t d_itemsize; + std::vector d_remain; + + friend GR_CORE_API gr_pdu_to_tagged_stream_sptr + gr_make_pdu_to_tagged_stream(gr_pdu_vector_type t); + + protected: + gr_pdu_to_tagged_stream (gr_pdu_vector_type t); + + public: + ~gr_pdu_to_tagged_stream (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + +}; + +#endif /* INCLUDED_GR_PDU_TO_TAGGED_SOURCE_H */ diff --git a/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.i b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.i new file mode 100644 index 000000000..ddf1d8c05 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.i @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 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(gr,pdu_to_tagged_stream); + +%{ +#include +%} + +%include + + diff --git a/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.cc b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.cc new file mode 100644 index 000000000..05ed8adc0 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.cc @@ -0,0 +1,139 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +// public constructor that returns a shared_ptr + +gr_tagged_stream_to_pdu_sptr +gr_make_tagged_stream_to_pdu(gr_pdu_vector_type t) +{ + return gnuradio::get_initial_sptr(new gr_tagged_stream_to_pdu(t)); +} + +gr_tagged_stream_to_pdu::gr_tagged_stream_to_pdu (gr_pdu_vector_type t) + : gr_sync_block("tagged_stream_to_pdu", + gr_make_io_signature(1, 1, gr_pdu_itemsize(t)), + gr_make_io_signature(0, 0, 0)), + d_vectortype(t), d_itemsize(gr_pdu_itemsize(t)), d_inpdu(false), + d_pdu_meta(pmt::PMT_NIL), d_pdu_vector(pmt::PMT_NIL) +{ + message_port_register_out(pdu_port_id); +} + +gr_tagged_stream_to_pdu::~gr_tagged_stream_to_pdu() +{ + printf("destructor running\n"); +} + +int +gr_tagged_stream_to_pdu::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const uint8_t *in = (const uint8_t*) input_items[0]; + uint64_t abs_N = nitems_read(0); + + // if we are not in a pdu already, start a new one + if(!d_inpdu){ + get_tags_in_range(d_tags, 0, abs_N, abs_N+1); + bool found_length_tag(false); + for(d_tags_itr = d_tags.begin(); (d_tags_itr != d_tags.end()) && (!found_length_tag); d_tags_itr++){ + if( pmt::pmt_equal( (*d_tags_itr).key, pdu_length_tag ) ){ + if( (*d_tags_itr).offset != abs_N ){ + throw std::runtime_error("expected next pdu length tag on a different item..."); + } + found_length_tag = true; + d_pdu_length = pmt::pmt_to_long( (*d_tags_itr).value ); + d_pdu_remain = d_pdu_length; + d_pdu_meta = pmt::pmt_make_dict(); + break; + } // if have length tag + } // iter over tags + if(!found_length_tag){ + throw std::runtime_error("tagged stream does not contain a pdu_length tag!"); + } + } + + size_t ncopy = std::min((size_t)noutput_items, d_pdu_remain); + + // copy any tags in this range into our meta object + get_tags_in_range(d_tags, 0, abs_N, abs_N+ncopy); + for(d_tags_itr = d_tags.begin(); d_tags_itr != d_tags.end(); d_tags_itr++){ + if( ! pmt_equal( (*d_tags_itr).key, pdu_length_tag ) ){ + d_pdu_meta = pmt_dict_add(d_pdu_meta, (*d_tags_itr).key, (*d_tags_itr).value); + } + } + + // copy samples for this vector into either a pmt or our save buffer + if(ncopy == d_pdu_remain){ // we will send this pdu + if(d_save.size() == 0){ + d_pdu_vector = gr_pdu_make_vector(d_vectortype, in, ncopy); + send_message(); + } else { + size_t oldsize = d_save.size(); + d_save.resize((oldsize + ncopy)*d_itemsize, 0); + memcpy( &d_save[oldsize*d_itemsize], in, ncopy*d_itemsize ); + d_pdu_vector = gr_pdu_make_vector(d_vectortype, &d_save[0], d_pdu_length); + send_message(); + d_save.clear(); + } + } else { + d_inpdu = true; + size_t oldsize = d_save.size(); + d_save.resize( (oldsize+ncopy)*d_itemsize ); + memcpy( &d_save[oldsize*d_itemsize], in, ncopy*d_itemsize ); + d_pdu_remain -= ncopy; + } + + return ncopy; +} + +void gr_tagged_stream_to_pdu::send_message(){ + + if(pmt::pmt_length(d_pdu_vector) != d_pdu_length){ + throw std::runtime_error("msg length not correct"); + } + + pmt::pmt_t msg = pmt::pmt_cons( d_pdu_meta, d_pdu_vector ); + message_port_pub( pdu_port_id, msg ); + + d_pdu_meta = pmt::PMT_NIL; + d_pdu_vector = pmt::PMT_NIL; + d_pdu_length = 0; + d_pdu_remain = 0; + d_inpdu = false; +} diff --git a/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.h b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.h new file mode 100644 index 000000000..6a40e1c0c --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.h @@ -0,0 +1,76 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 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_TAGGED_STREAM_TO_PDU_H +#define INCLUDED_GR_TAGGED_STREAM_TO_PDU_H + +#include +#include +#include +#include +#include + +class gr_tagged_stream_to_pdu; +typedef boost::shared_ptr gr_tagged_stream_to_pdu_sptr; + +GR_CORE_API gr_tagged_stream_to_pdu_sptr gr_make_tagged_stream_to_pdu (gr_pdu_vector_type t); + +/*! + * \brief Turn received messages into a stream + * \ingroup source_blk + */ +class GR_CORE_API gr_tagged_stream_to_pdu : public gr_sync_block +{ + private: + gr_pdu_vector_type d_vectortype; + size_t d_itemsize; + + std::vector d_save; + + std::vector d_tags; + std::vector::iterator d_tags_itr; + + bool d_inpdu; + + size_t d_pdu_length; + size_t d_pdu_remain; + pmt::pmt_t d_pdu_meta; + pmt::pmt_t d_pdu_vector; + + friend GR_CORE_API gr_tagged_stream_to_pdu_sptr + gr_make_tagged_stream_to_pdu(gr_pdu_vector_type t); + + protected: + gr_tagged_stream_to_pdu (gr_pdu_vector_type t); + + public: + ~gr_tagged_stream_to_pdu (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void send_message(); + +}; + +#endif /* INCLUDED_GR_PDU_TO_TAGGED_SOURCE_H */ diff --git a/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.i b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.i new file mode 100644 index 000000000..66bd875aa --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.i @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 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(gr,tagged_stream_to_pdu); + +%{ +#include +%} + +%include + + diff --git a/gnuradio-core/src/lib/io/io.i b/gnuradio-core/src/lib/io/io.i index 5cd352905..871ce1356 100644 --- a/gnuradio-core/src/lib/io/io.i +++ b/gnuradio-core/src/lib/io/io.i @@ -45,6 +45,10 @@ #include #include #include +#include +#include +#include +#include %} %include "gr_file_sink_base.i" @@ -67,4 +71,8 @@ %include "gr_wavfile_sink.i" %include "gr_wavfile_source.i" %include "gr_tagged_file_sink.i" +%include "gr_pdu_to_tagged_stream.i" +%include "gr_tagged_stream_to_pdu.i" +%include "gr_message_debug.i" +%include "gr_pdu.i" diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.cc b/gnuradio-core/src/lib/runtime/gr_basic_block.cc index 3d08b63d1..7d2f275e8 100644 --- a/gnuradio-core/src/lib/runtime/gr_basic_block.cc +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.cc @@ -52,6 +52,7 @@ gr_basic_block::gr_basic_block(const std::string &name, d_color(WHITE), message_subscribers(pmt::pmt_make_dict()) { + mutex.unlock(); s_ncurrently_allocated++; } @@ -130,7 +131,7 @@ void gr_basic_block::_post(pmt_t which_port, pmt_t msg) { insert_tail(which_port, msg); - //notify_msg(); + global_block_registry.notify_blk(alias()); } void @@ -151,8 +152,9 @@ gr_basic_block::delete_head_nowait(pmt::pmt_t which_port) { gruel::scoped_lock guard(mutex); - if (empty_p(which_port)) - return pmt_t(); + if (empty_p(which_port)){ + return pmt::pmt_t(); + } pmt_t m(msg_queue[which_port].front()); msg_queue[which_port].pop_front(); @@ -160,18 +162,4 @@ gr_basic_block::delete_head_nowait(pmt::pmt_t which_port) return m; } -/* - * Caller must already be holding the mutex - */ -pmt_t -gr_basic_block::delete_head_nowait_already_holding_mutex(pmt::pmt_t which_port) -{ - if (empty_p(which_port)) - return pmt_t(); - - pmt_t m(msg_queue[which_port].front()); - msg_queue[which_port].pop_front(); - - return m; -} diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.h b/gnuradio-core/src/lib/runtime/gr_basic_block.h index 31026a2e4..2ee8161c1 100644 --- a/gnuradio-core/src/lib/runtime/gr_basic_block.h +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.h @@ -115,7 +115,6 @@ protected: vcolor color() const { return d_color; } // Message passing interface - std::vector message_inputs; pmt::pmt_t message_subscribers; public: @@ -139,15 +138,18 @@ public: void message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target); void message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target); - /*! - * Accept msg, place in queue, arrange for thread to be awakened if it's not already. - */ - void _post(pmt::pmt_t which_port, pmt::pmt_t msg); - + /*! + * Accept msg, place in queue, arrange for thread to be awakened if it's not already. + */ + void _post(pmt::pmt_t which_port, pmt::pmt_t msg); //! is the queue empty? //bool empty_p(const pmt::pmt_t &which_port) const { return msg_queue[which_port].empty(); } - bool empty_p(pmt::pmt_t which_port) { return msg_queue[which_port].empty(); } + bool empty_p(pmt::pmt_t which_port) { + if(msg_queue.find(which_port) == msg_queue.end()) + throw std::runtime_error("port does not exist!"); + return msg_queue[which_port].empty(); + } bool empty_p() { bool rv = true; BOOST_FOREACH(msg_queue_map_t::value_type &i, msg_queue){ rv &= msg_queue[i.first].empty(); } @@ -160,11 +162,6 @@ public: * \returns returns pmt at head of queue or pmt_t() if empty. */ pmt::pmt_t delete_head_nowait( pmt::pmt_t which_port); - /*! - * \returns returns pmt at head of queue or pmt_t() if empty. - * Caller must already be holding the mutex - */ - pmt::pmt_t delete_head_nowait_already_holding_mutex( pmt::pmt_t which_port); msg_queue_t::iterator get_iterator(pmt::pmt_t which_port){ return msg_queue[which_port].begin(); diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.i b/gnuradio-core/src/lib/runtime/gr_basic_block.i index 0a8473ba2..d6d6c3d16 100644 --- a/gnuradio-core/src/lib/runtime/gr_basic_block.i +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.i @@ -23,6 +23,8 @@ class gr_basic_block; typedef boost::shared_ptr gr_basic_block_sptr; %template(gr_basic_block_sptr) boost::shared_ptr; +%include "pmt_swig.i" +using namespace pmt; // support vectors of these... namespace std { @@ -45,6 +47,7 @@ public: bool check_topology (int ninputs, int noutputs); std::string alias(); void set_block_alias(std::string name); + void _post(pmt_t which_port, pmt_t msg); }; %rename(block_ncurrently_allocated) gr_basic_block_ncurrently_allocated; diff --git a/gnuradio-core/src/lib/runtime/gr_block.cc b/gnuradio-core/src/lib/runtime/gr_block.cc index a88052ee0..dc77128a3 100644 --- a/gnuradio-core/src/lib/runtime/gr_block.cc +++ b/gnuradio-core/src/lib/runtime/gr_block.cc @@ -28,6 +28,7 @@ #include #include #include +#include gr_block::gr_block (const std::string &name, gr_io_signature_sptr input_signature, @@ -46,10 +47,12 @@ gr_block::gr_block (const std::string &name, d_max_output_buffer(std::max(output_signature->max_streams(),1), -1), d_min_output_buffer(std::max(output_signature->max_streams(),1), -1) { + global_block_registry.register_primitive(alias(), this); } gr_block::~gr_block () { + global_block_registry.unregister_primitive(alias()); } // stub implementation: 1:1 diff --git a/gnuradio-core/src/lib/runtime/gr_block_registry.cc b/gnuradio-core/src/lib/runtime/gr_block_registry.cc index 2478e0019..ff23d97eb 100644 --- a/gnuradio-core/src/lib/runtime/gr_block_registry.cc +++ b/gnuradio-core/src/lib/runtime/gr_block_registry.cc @@ -1,5 +1,9 @@ #include #include +#include +#include +#include +#include gr_block_registry global_block_registry; @@ -56,3 +60,17 @@ gr_basic_block_sptr gr_block_registry::block_lookup(pmt::pmt_t symbol){ } +void gr_block_registry::register_primitive(std::string blk, gr_block* ref){ + primitive_map[blk] = ref; +} + +void gr_block_registry::unregister_primitive(std::string blk){ + primitive_map.erase(primitive_map.find(blk)); +} + +void gr_block_registry::notify_blk(std::string blk){ + if(primitive_map.find(blk) == primitive_map.end()){ return; } + if(primitive_map[blk]->detail().get()) + primitive_map[blk]->detail()->d_tpb.notify_msg(); +} + diff --git a/gnuradio-core/src/lib/runtime/gr_block_registry.h b/gnuradio-core/src/lib/runtime/gr_block_registry.h index 8f1982984..6a2d939e5 100644 --- a/gnuradio-core/src/lib/runtime/gr_block_registry.h +++ b/gnuradio-core/src/lib/runtime/gr_block_registry.h @@ -5,6 +5,7 @@ #ifndef GR_BASIC_BLOCK_H class gr_basic_block; +class gr_block; #endif class gr_block_registry { @@ -18,7 +19,11 @@ class gr_block_registry { void register_symbolic_name(gr_basic_block* block, std::string name); gr_basic_block_sptr block_lookup(pmt::pmt_t symbol); - + + void register_primitive(std::string blk, gr_block* ref); + void unregister_primitive(std::string blk); + void notify_blk(std::string blk); + private: //typedef std::map< long, gr_basic_block_sptr > blocksubmap_t; @@ -27,7 +32,8 @@ class gr_block_registry { blockmap_t d_map; pmt::pmt_t d_ref_map; - + std::map< std::string, gr_block*> primitive_map; + }; extern gr_block_registry global_block_registry; diff --git a/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc b/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc index 1bd3014ad..ff2afca10 100644 --- a/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc +++ b/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc @@ -80,7 +80,7 @@ gr_tpb_thread_body::gr_tpb_thread_body(gr_block_sptr block, int max_noutput_item // handle all pending messages BOOST_FOREACH( gr_basic_block::msg_queue_map_t::value_type &i, block->msg_queue ) { - while ((msg = block->delete_head_nowait_already_holding_mutex(i.first))){ + while ((msg = block->delete_head_nowait(i.first))){ guard.unlock(); // release lock while processing msg block->dispatch_msg(i.first, msg); guard.lock(); @@ -103,7 +103,7 @@ gr_tpb_thread_body::gr_tpb_thread_body(gr_block_sptr block, int max_noutput_item // handle all pending messages BOOST_FOREACH( gr_basic_block::msg_queue_map_t::value_type &i, block->msg_queue ) { - while ((msg = block->delete_head_nowait_already_holding_mutex(i.first))){ + while ((msg = block->delete_head_nowait(i.first))){ guard.unlock(); // release lock while processing msg block->dispatch_msg(i.first,msg); guard.lock(); diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py b/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py new file mode 100755 index 000000000..64eb80a8f --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python +# +# Copyright 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. +# + +from gnuradio import gr, gr_unittest +from gruel import pmt +import time; +class test_pdu(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_000(self): + # Just run some data through and make sure it doesn't puke. + src_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + + src = gr.pdu_to_tagged_stream(gr.BYTE); + snk3 = gr.tagged_stream_to_pdu(gr.BYTE); + snk2 = gr.vector_sink_b(); + snk = gr.tag_debug(1, "test"); + + dbg = gr.message_debug(); + + self.tb.connect(src, snk) + self.tb.connect(src, snk2) + self.tb.connect(src, snk3) + + self.tb.msg_connect(snk3, "pdus", dbg, "print"); + self.tb.start() + + # make our reference and message pmts + port = pmt.pmt_intern("pdus"); + msg = pmt.pmt_cons( pmt.PMT_NIL, pmt.pmt_make_u8vector(16, 0xFF) ); + + print "printing port & msg" + pmt.pmt_print(port); + pmt.pmt_print(msg); + + # post the message + src.to_basic_block()._post( port, msg ); + + time.sleep(1); + self.tb.stop(); + self.tb.wait(); + + print snk2.data(); + +if __name__ == '__main__': + gr_unittest.run(test_pdu, "test_pdu.xml") -- cgit From 6cc818260128df57c51a41e4e6aa459de5faf4fe Mon Sep 17 00:00:00 2001 From: Tim O'Shea Date: Fri, 30 Nov 2012 22:31:43 -0800 Subject: core: gr_blocks can now have only message ports with no general_work() * msg only blocks now get thread context * added blocking msg queue delete call * added gr_message_strobe block * added grc definitions for message_debug, message_strobe, pdu_to_tagged_stream, tagged_stream_to_pdu. * allow message fan-in connections in GRC --- gnuradio-core/src/lib/general/CMakeLists.txt | 1 + gnuradio-core/src/lib/general/general.i | 2 + gnuradio-core/src/lib/general/gr_message_strobe.cc | 83 ++++++++++++++++++++++ gnuradio-core/src/lib/general/gr_message_strobe.h | 65 +++++++++++++++++ gnuradio-core/src/lib/general/gr_message_strobe.i | 30 ++++++++ gnuradio-core/src/lib/io/gr_message_debug.cc | 4 +- .../src/lib/io/gr_pdu_to_tagged_stream.cc | 7 +- gnuradio-core/src/lib/runtime/gr_basic_block.cc | 29 ++++++-- gnuradio-core/src/lib/runtime/gr_basic_block.h | 9 +++ gnuradio-core/src/lib/runtime/gr_block.cc | 9 +++ gnuradio-core/src/lib/runtime/gr_block.h | 2 +- gnuradio-core/src/lib/runtime/gr_flowgraph.cc | 9 +++ gnuradio-core/src/lib/runtime/gr_flowgraph.h | 3 + .../src/lib/runtime/gr_hier_block2_detail.cc | 9 +++ .../src/lib/runtime/gr_tpb_thread_body.cc | 9 ++- .../src/lib/runtime/qa_set_msg_handler.cc | 5 -- grc/blocks/block_tree.xml | 7 ++ grc/blocks/gr_message_debug.xml | 17 +++++ grc/blocks/gr_message_strobe.xml | 35 +++++++++ grc/blocks/gr_pdu_to_tagged_stream.xml | 40 +++++++++++ grc/blocks/gr_tagged_stream_to_pdu.xml | 40 +++++++++++ grc/python/Constants.py | 2 +- grc/python/Port.py | 2 +- gruel/src/include/gruel/msg_accepter.h | 2 +- 24 files changed, 401 insertions(+), 20 deletions(-) create mode 100644 gnuradio-core/src/lib/general/gr_message_strobe.cc create mode 100644 gnuradio-core/src/lib/general/gr_message_strobe.h create mode 100644 gnuradio-core/src/lib/general/gr_message_strobe.i create mode 100644 grc/blocks/gr_message_debug.xml create mode 100644 grc/blocks/gr_message_strobe.xml create mode 100644 grc/blocks/gr_pdu_to_tagged_stream.xml create mode 100644 grc/blocks/gr_tagged_stream_to_pdu.xml diff --git a/gnuradio-core/src/lib/general/CMakeLists.txt b/gnuradio-core/src/lib/general/CMakeLists.txt index 074f583a7..4c99acfc3 100644 --- a/gnuradio-core/src/lib/general/CMakeLists.txt +++ b/gnuradio-core/src/lib/general/CMakeLists.txt @@ -299,6 +299,7 @@ set(gr_core_general_triple_threats gr_burst_tagger gr_correlate_access_code_tag_bb gr_tag_debug + gr_message_strobe ) foreach(file_tt ${gr_core_general_triple_threats}) diff --git a/gnuradio-core/src/lib/general/general.i b/gnuradio-core/src/lib/general/general.i index e5a9e970d..1446088a2 100644 --- a/gnuradio-core/src/lib/general/general.i +++ b/gnuradio-core/src/lib/general/general.i @@ -143,6 +143,7 @@ #include #include #include +#include %} %include "gri_control_loop.i" @@ -267,3 +268,4 @@ %include "gr_vector_map.i" %include "gr_tag_debug.i" %include "gr_block_gateway.i" +%include "gr_message_strobe.i" diff --git a/gnuradio-core/src/lib/general/gr_message_strobe.cc b/gnuradio-core/src/lib/general/gr_message_strobe.cc new file mode 100644 index 000000000..371f472ef --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_message_strobe.cc @@ -0,0 +1,83 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// public constructor that returns a shared_ptr + +gr_message_strobe_sptr +gr_make_message_strobe (pmt::pmt_t msg, float period_ms) +{ + return gnuradio::get_initial_sptr(new gr_message_strobe(msg, period_ms)); +} + +gr_message_strobe::gr_message_strobe (pmt::pmt_t msg, float period_ms) + : gr_sync_block("message_strobe", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(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(new boost::thread(boost::bind(&gr_message_strobe::run, this))); + + message_port_register_in(pmt::mp("set_msg")); + set_msg_handler(pmt::mp("set_msg"), boost::bind(&gr_message_strobe::set_msg, this, _1)); +} + +gr_message_strobe::~gr_message_strobe() +{ + d_finished = true; + d_thread->interrupt(); + d_thread->join(); +} + +void gr_message_strobe::run(){ + while(!d_finished) { + boost::this_thread::sleep(boost::posix_time::milliseconds(d_period_ms)); + if(d_finished){ return; } +// std::cout << "strobing...\n"; + message_port_pub( pmt::mp("strobe"), d_msg ); + } +} + +int +gr_message_strobe::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + return 0; // FIXME: replace with default NOP work function in gr_block +} diff --git a/gnuradio-core/src/lib/general/gr_message_strobe.h b/gnuradio-core/src/lib/general/gr_message_strobe.h new file mode 100644 index 000000000..a5151a30b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_message_strobe.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 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_MESSAGE_STROBE_H +#define INCLUDED_GR_MESSAGE_STROBE_H + +#include +#include +#include +#include + +class gr_message_strobe; +typedef boost::shared_ptr gr_message_strobe_sptr; + +GR_CORE_API gr_message_strobe_sptr gr_make_message_strobe (pmt::pmt_t msg, float period_ms); + +/*! + * \brief Gather received items into messages and insert into msgq + * \ingroup sink_blk + */ +class GR_CORE_API gr_message_strobe : public gr_sync_block +{ + private: + friend GR_CORE_API gr_message_strobe_sptr + gr_make_message_strobe(pmt::pmt_t msg, float period_ms); + boost::shared_ptr d_thread; + bool d_finished; + float d_period_ms; + pmt::pmt_t d_msg; + + void run(); + + protected: + gr_message_strobe (pmt::pmt_t msg, float period_ms); + + public: + ~gr_message_strobe (); + + void set_msg(pmt::pmt_t msg){ d_msg = msg; } + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_MESSAGE_STROBE_H */ diff --git a/gnuradio-core/src/lib/general/gr_message_strobe.i b/gnuradio-core/src/lib/general/gr_message_strobe.i new file mode 100644 index 000000000..490aa8e8a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_message_strobe.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 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(gr,message_strobe); + +%{ +#include +%} + +%include "gr_message_strobe.h" + diff --git a/gnuradio-core/src/lib/io/gr_message_debug.cc b/gnuradio-core/src/lib/io/gr_message_debug.cc index 84c11c46e..99f4a1f7b 100644 --- a/gnuradio-core/src/lib/io/gr_message_debug.cc +++ b/gnuradio-core/src/lib/io/gr_message_debug.cc @@ -44,8 +44,9 @@ gr_make_message_debug () } void gr_message_debug::print(pmt::pmt_t msg){ - std::cout << "******* DEBUG PRINT ********\n"; + std::cout << "******* MESSAGE DEBUG PRINT ********\n"; pmt::pmt_print(msg); + std::cout << "************************************\n"; } @@ -67,5 +68,6 @@ gr_message_debug::work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { + printf("gr_message_debug::work\n"); return 0; // FIXME: replace with default NOP work function in gr_block } diff --git a/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc index 26c1babd6..06a1c9596 100644 --- a/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc +++ b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc @@ -77,7 +77,8 @@ gr_pdu_to_tagged_stream::work(int noutput_items, if(noutput_items > 0){ // grab a message if one exists - pmt::pmt_t msg( delete_head_nowait( pdu_port_id ) ); + //pmt::pmt_t msg( delete_head_nowait( pdu_port_id ) ); + pmt::pmt_t msg( delete_head_blocking( pdu_port_id ) ); if(msg.get() == NULL ){ return nout; } @@ -87,8 +88,8 @@ gr_pdu_to_tagged_stream::work(int noutput_items, throw std::runtime_error("received a malformed pdu message!"); } - printf("got a msg\n"); - pmt::pmt_print(msg); +// printf("got a msg\n"); +// pmt::pmt_print(msg); // grab the components of the pdu message pmt::pmt_t meta(pmt::pmt_car(msg)); // make sure this is NIL || Dict ? diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.cc b/gnuradio-core/src/lib/runtime/gr_basic_block.cc index 7d2f275e8..69f2e09f9 100644 --- a/gnuradio-core/src/lib/runtime/gr_basic_block.cc +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006 Free Software Foundation, Inc. + * Copyright 2006,2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -28,6 +28,7 @@ #include #include #include +#include using namespace pmt; @@ -79,6 +80,7 @@ gr_basic_block::set_block_alias(std::string name) // - register a new input message port void gr_basic_block::message_port_register_in(pmt::pmt_t port_id){ msg_queue[port_id] = msg_queue_t(); + msg_queue_ready[port_id] = boost::shared_ptr(new boost::condition_variable()); } // - register a new output message port @@ -131,7 +133,6 @@ void gr_basic_block::_post(pmt_t which_port, pmt_t msg) { insert_tail(which_port, msg); - global_block_registry.notify_blk(alias()); } void @@ -139,12 +140,16 @@ gr_basic_block::insert_tail(pmt::pmt_t which_port, pmt::pmt_t msg) { gruel::scoped_lock guard(mutex); + if( (msg_queue.find(which_port) == msg_queue.end()) || (msg_queue_ready.find(which_port) == msg_queue_ready.end())){ + std::cout << "target port = " << pmt::pmt_symbol_to_string(which_port) << std::endl; + throw std::runtime_error("attempted to insert_tail on invalid queue!"); + } + msg_queue[which_port].push_back(msg); + msg_queue_ready[which_port]->notify_one(); // wake up thread if BLKD_IN or BLKD_OUT - //input_cond.notify_one(); - //output_cond.notify_one(); - // TODO: reconsider the need for notification of input and output conditions! + global_block_registry.notify_blk(alias()); } pmt_t @@ -162,4 +167,18 @@ gr_basic_block::delete_head_nowait(pmt::pmt_t which_port) return m; } +pmt_t +gr_basic_block::delete_head_blocking(pmt::pmt_t which_port) +{ + gruel::scoped_lock guard(mutex); + + while (empty_p(which_port)){ + msg_queue_ready[which_port]->wait(guard); + } + + pmt_t m(msg_queue[which_port].front()); + msg_queue[which_port].pop_front(); + return m; +} + diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.h b/gnuradio-core/src/lib/runtime/gr_basic_block.h index 2ee8161c1..e0fd5d2af 100644 --- a/gnuradio-core/src/lib/runtime/gr_basic_block.h +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.h @@ -35,6 +35,7 @@ #include #include #include +#include /*! * \brief The abstract base class for all signal processing blocks. @@ -72,6 +73,9 @@ private: typedef std::deque msg_queue_t; typedef std::map msg_queue_map_t; msg_queue_map_t msg_queue; +// boost::condition_variable msg_queue_ready; + std::map, pmt::pmt_comperator> msg_queue_ready; + gruel::mutex mutex; //< protects all vars @@ -163,6 +167,11 @@ public: */ pmt::pmt_t delete_head_nowait( pmt::pmt_t which_port); + /*! + * \returns returns pmt at head of queue or pmt_t() if empty. + */ + pmt::pmt_t delete_head_blocking( pmt::pmt_t which_port); + msg_queue_t::iterator get_iterator(pmt::pmt_t which_port){ return msg_queue[which_port].begin(); } diff --git a/gnuradio-core/src/lib/runtime/gr_block.cc b/gnuradio-core/src/lib/runtime/gr_block.cc index dc77128a3..43aebf0bf 100644 --- a/gnuradio-core/src/lib/runtime/gr_block.cc +++ b/gnuradio-core/src/lib/runtime/gr_block.cc @@ -251,3 +251,12 @@ operator << (std::ostream& os, const gr_block *m) return os; } +int +gr_block::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + throw std::runtime_error("gr_block::general_work() not implemented"); + return 0; +} diff --git a/gnuradio-core/src/lib/runtime/gr_block.h b/gnuradio-core/src/lib/runtime/gr_block.h index 98339080d..57e3fda90 100644 --- a/gnuradio-core/src/lib/runtime/gr_block.h +++ b/gnuradio-core/src/lib/runtime/gr_block.h @@ -124,7 +124,7 @@ class GR_CORE_API gr_block : public gr_basic_block { virtual int general_work (int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) = 0; + gr_vector_void_star &output_items); /*! * \brief Called to enable drivers, etc for i/o devices. diff --git a/gnuradio-core/src/lib/runtime/gr_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc index 78e1bc99a..69c304a3d 100644 --- a/gnuradio-core/src/lib/runtime/gr_flowgraph.cc +++ b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc @@ -180,6 +180,11 @@ gr_flowgraph::calc_used_blocks() { gr_basic_block_vector_t tmp; + // make sure free standing message blocks are included + for (gr_basic_block_vector_t::iterator it=d_msgblocks.begin(); it!=d_msgblocks.end(); it++){ + tmp.push_back(*it); + } + // Collect all blocks in the edge list for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { tmp.push_back(p->src().block()); @@ -472,3 +477,7 @@ gr_flowgraph::topological_dfs_visit(gr_basic_block_sptr block, gr_basic_block_ve output.push_back(block); } +void gr_flowgraph::add_msg_block(gr_basic_block_sptr blk){ + d_msgblocks.push_back(blk); +} + diff --git a/gnuradio-core/src/lib/runtime/gr_flowgraph.h b/gnuradio-core/src/lib/runtime/gr_flowgraph.h index a2c1580eb..860cb0ff1 100644 --- a/gnuradio-core/src/lib/runtime/gr_flowgraph.h +++ b/gnuradio-core/src/lib/runtime/gr_flowgraph.h @@ -110,6 +110,8 @@ public: void disconnect(gr_basic_block_sptr src_block, int src_port, gr_basic_block_sptr dst_block, int dst_port); + void add_msg_block(gr_basic_block_sptr blk); + // Validate connectivity, raise exception if invalid void validate(); @@ -128,6 +130,7 @@ public: // Return vector of vectors of disjointly connected blocks, topologically // sorted. std::vector partition(); + gr_basic_block_vector_t d_msgblocks; protected: gr_basic_block_vector_t d_blocks; diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc index 099b2f8e8..ff2a5db8c 100644 --- a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc @@ -152,6 +152,14 @@ gr_hier_block2_detail::msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport, // register the subscription src->message_port_sub(srcport, pmt::pmt_cons(dst->alias_pmt(), dstport)); + + // add block uniquely to list to internal blocks + if (std::find(d_blocks.begin(), d_blocks.end(), dst) == d_blocks.end()){ + d_blocks.push_back(dst); + } + + // make sure we instantiate a thread for this block + d_fg->add_msg_block(dst); } void @@ -449,6 +457,7 @@ gr_hier_block2_detail::flatten_aux(gr_flat_flowgraph_sptr sfg) const } } } + sfg->d_msgblocks = d_fg->d_msgblocks; // Construct unique list of blocks used either in edges, inputs, // outputs, or by themselves. I still hate STL. diff --git a/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc b/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc index ff2afca10..9f17a48a8 100644 --- a/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc +++ b/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc @@ -32,7 +32,7 @@ using namespace pmt; gr_tpb_thread_body::gr_tpb_thread_body(gr_block_sptr block, int max_noutput_items) : d_exec(block, max_noutput_items) { - // std::cerr << "gr_tpb_thread_body: " << block << std::endl; + //std::cerr << "gr_tpb_thread_body: " << block << std::endl; gr_block_detail *d = block->detail().get(); gr_block_executor::state s; @@ -53,7 +53,12 @@ gr_tpb_thread_body::gr_tpb_thread_body(gr_block_sptr block, int max_noutput_item } d->d_tpb.clear_changed(); - s = d_exec.run_one_iteration(); + // run one iteration if we are a connected stream block + if(d->noutputs() >0 || d->ninputs()>0){ + s = d_exec.run_one_iteration(); + } else { + s = gr_block_executor::BLKD_IN; + } switch(s){ case gr_block_executor::READY: // Tell neighbors we made progress. diff --git a/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc b/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc index dc8f0f8a9..c84a219bd 100644 --- a/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc +++ b/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc @@ -70,11 +70,6 @@ void qa_set_msg_handler::t0() send(nop, port, mp(mp("example-msg"), mp(i))); } - // And send a message to null_source to confirm that the default - // message handling action (which should be a nop) doesn't dump - // core. - send(src, port, mp(mp("example-msg"), mp(0))); - // Give the messages a chance to be processed boost::this_thread::sleep(boost::posix_time::milliseconds(100)); diff --git a/grc/blocks/block_tree.xml b/grc/blocks/block_tree.xml index d7ec82e4a..95bd7bb3c 100644 --- a/grc/blocks/block_tree.xml +++ b/grc/blocks/block_tree.xml @@ -37,6 +37,13 @@ virtual_sink gr_tag_debug + + Message Tools + gr_message_debug + gr_message_strobe + gr_pdu_to_tagged_stream + gr_tagged_stream_to_pdu + Operators gr_add_xx diff --git a/grc/blocks/gr_message_debug.xml b/grc/blocks/gr_message_debug.xml new file mode 100644 index 000000000..9478f5304 --- /dev/null +++ b/grc/blocks/gr_message_debug.xml @@ -0,0 +1,17 @@ + + + + Message Debug + gr_message_debug + from gnuradio import gr + gr.message_debug() + + print + message + 1 + + diff --git a/grc/blocks/gr_message_strobe.xml b/grc/blocks/gr_message_strobe.xml new file mode 100644 index 000000000..60a7724df --- /dev/null +++ b/grc/blocks/gr_message_strobe.xml @@ -0,0 +1,35 @@ + + + + Message Strobe + gr_message_strobe + from gnuradio import gr + from gruel import pmt + gr.message_strobe($msg, $period) + + Message PMT + msg + pmt.pmt_intern("TEST") + raw + + + Period (ms) + period + 1000 + real + + + set_msg + message + 1 + + + strobe + message + 1 + + diff --git a/grc/blocks/gr_pdu_to_tagged_stream.xml b/grc/blocks/gr_pdu_to_tagged_stream.xml new file mode 100644 index 000000000..fc1c4d16a --- /dev/null +++ b/grc/blocks/gr_pdu_to_tagged_stream.xml @@ -0,0 +1,40 @@ + + + + PDU to Tagged Stream + gr_pdu_to_tagged_stream + from gnuradio import gr + gr.pdu_to_tagged_stream($type.tv) + + Item Type + type + enum + + + + + + pdus + message + + + out + $type + + diff --git a/grc/blocks/gr_tagged_stream_to_pdu.xml b/grc/blocks/gr_tagged_stream_to_pdu.xml new file mode 100644 index 000000000..e70a01608 --- /dev/null +++ b/grc/blocks/gr_tagged_stream_to_pdu.xml @@ -0,0 +1,40 @@ + + + + Tagged Stream to PDU + gr_tagged_stream_to_pdu + from gnuradio import gr + gr.tagged_stream_to_pdu($type.tv) + + Item Type + type + enum + + + + + + in + $type + + + pdus + message + + diff --git a/grc/python/Constants.py b/grc/python/Constants.py index 09c308196..b8dc9a96a 100644 --- a/grc/python/Constants.py +++ b/grc/python/Constants.py @@ -58,7 +58,7 @@ CORE_TYPES = ( #name, key, sizeof, color ('Integer 16', 's16', 2, '#FFFF66'), ('Integer 8', 's8', 1, '#FF66FF'), ('Message Queue', 'msg', 0, '#777777'), - ('Async Message', 'message', 0, '#777777'), + ('Async Message', 'message', 0, '#C0C0C0'), ('Wildcard', '', 0, '#FFFFFF'), ) diff --git a/grc/python/Port.py b/grc/python/Port.py index 9f8b50d05..738a33ba7 100644 --- a/grc/python/Port.py +++ b/grc/python/Port.py @@ -116,7 +116,7 @@ class Port(_Port, _GUIPort): _Port.validate(self) if not self.get_enabled_connections() and not self.get_optional(): self.add_error_message('Port is not connected.') - if not self.is_source() and len(self.get_enabled_connections()) > 1: + if not self.is_source() and (not self.get_type() == "message") and len(self.get_enabled_connections()) > 1: self.add_error_message('Port has too many connections.') #message port logic if self.get_type() == 'msg': diff --git a/gruel/src/include/gruel/msg_accepter.h b/gruel/src/include/gruel/msg_accepter.h index 65abd5a6b..45acb3c78 100644 --- a/gruel/src/include/gruel/msg_accepter.h +++ b/gruel/src/include/gruel/msg_accepter.h @@ -37,7 +37,7 @@ namespace gruel { virtual ~msg_accepter(); /*! - * \brief send \p msg to \p msg_accepter + * \brief send \p msg to \p msg_accepter on port \p which_port * * Sending a message is an asynchronous operation. The \p post * call will not wait for the message either to arrive at the -- cgit From 5dc1ccc01120a6f32f83f5e5fa79bc34b83f1619 Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Sat, 1 Dec 2012 13:49:33 -0800 Subject: core: cleanup on pdu/msg blocks --- gnuradio-core/src/lib/general/gr_message_strobe.cc | 18 +++-------- gnuradio-core/src/lib/general/gr_message_strobe.h | 15 ++++----- gnuradio-core/src/lib/io/gr_message_debug.cc | 17 +++------- gnuradio-core/src/lib/io/gr_message_debug.h | 12 +++----- gnuradio-core/src/lib/io/gr_message_debug.i | 2 +- gnuradio-core/src/lib/io/gr_pdu.cc | 36 +++++++++++++++++++--- gnuradio-core/src/lib/io/gr_pdu.h | 2 +- .../src/lib/io/gr_pdu_to_tagged_stream.cc | 2 +- gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.h | 4 +-- gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.i | 2 +- .../src/lib/io/gr_tagged_stream_to_pdu.cc | 12 +++----- gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.h | 4 +-- gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.i | 2 +- 13 files changed, 64 insertions(+), 64 deletions(-) diff --git a/gnuradio-core/src/lib/general/gr_message_strobe.cc b/gnuradio-core/src/lib/general/gr_message_strobe.cc index 371f472ef..6a9f807d1 100644 --- a/gnuradio-core/src/lib/general/gr_message_strobe.cc +++ b/gnuradio-core/src/lib/general/gr_message_strobe.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005,2010 Free Software Foundation, Inc. + * Copyright 2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -44,9 +44,9 @@ gr_make_message_strobe (pmt::pmt_t msg, float period_ms) } gr_message_strobe::gr_message_strobe (pmt::pmt_t msg, float period_ms) - : gr_sync_block("message_strobe", - gr_make_io_signature(0, 0, 0), - gr_make_io_signature(0, 0, 0)), + : gr_block("message_strobe", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(0, 0, 0)), d_finished(false), d_period_ms(period_ms), d_msg(msg) @@ -69,15 +69,7 @@ void gr_message_strobe::run(){ while(!d_finished) { boost::this_thread::sleep(boost::posix_time::milliseconds(d_period_ms)); if(d_finished){ return; } -// std::cout << "strobing...\n"; + message_port_pub( pmt::mp("strobe"), d_msg ); } } - -int -gr_message_strobe::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - return 0; // FIXME: replace with default NOP work function in gr_block -} diff --git a/gnuradio-core/src/lib/general/gr_message_strobe.h b/gnuradio-core/src/lib/general/gr_message_strobe.h index a5151a30b..89046ffc0 100644 --- a/gnuradio-core/src/lib/general/gr_message_strobe.h +++ b/gnuradio-core/src/lib/general/gr_message_strobe.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -24,7 +24,7 @@ #define INCLUDED_GR_MESSAGE_STROBE_H #include -#include +#include #include #include @@ -34,14 +34,15 @@ typedef boost::shared_ptr gr_message_strobe_sptr; GR_CORE_API gr_message_strobe_sptr gr_make_message_strobe (pmt::pmt_t msg, float period_ms); /*! - * \brief Gather received items into messages and insert into msgq - * \ingroup sink_blk + * \brief Send message at defined interval + * \ingroup msg_blk */ -class GR_CORE_API gr_message_strobe : public gr_sync_block +class GR_CORE_API gr_message_strobe : public gr_block { private: friend GR_CORE_API gr_message_strobe_sptr gr_make_message_strobe(pmt::pmt_t msg, float period_ms); + boost::shared_ptr d_thread; bool d_finished; float d_period_ms; @@ -56,10 +57,6 @@ class GR_CORE_API gr_message_strobe : public gr_sync_block ~gr_message_strobe (); void set_msg(pmt::pmt_t msg){ d_msg = msg; } - - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); }; #endif /* INCLUDED_GR_MESSAGE_STROBE_H */ diff --git a/gnuradio-core/src/lib/io/gr_message_debug.cc b/gnuradio-core/src/lib/io/gr_message_debug.cc index 99f4a1f7b..d98954576 100644 --- a/gnuradio-core/src/lib/io/gr_message_debug.cc +++ b/gnuradio-core/src/lib/io/gr_message_debug.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005,2010 Free Software Foundation, Inc. + * Copyright 2005,2010,2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -51,9 +51,9 @@ void gr_message_debug::print(pmt::pmt_t msg){ gr_message_debug::gr_message_debug () - : gr_sync_block("message_debug", - gr_make_io_signature(0, 0, 0), - gr_make_io_signature(0, 0, 0)) + : gr_block("message_debug", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(0, 0, 0)) { message_port_register_in(pmt::mp("print")); set_msg_handler(pmt::mp("print"), boost::bind(&gr_message_debug::print, this, _1)); @@ -62,12 +62,3 @@ gr_message_debug::gr_message_debug () gr_message_debug::~gr_message_debug() { } - -int -gr_message_debug::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - printf("gr_message_debug::work\n"); - return 0; // FIXME: replace with default NOP work function in gr_block -} diff --git a/gnuradio-core/src/lib/io/gr_message_debug.h b/gnuradio-core/src/lib/io/gr_message_debug.h index 37d8b7a4d..120694a91 100644 --- a/gnuradio-core/src/lib/io/gr_message_debug.h +++ b/gnuradio-core/src/lib/io/gr_message_debug.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2005,2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -24,7 +24,7 @@ #define INCLUDED_GR_MESSAGE_DEBUG_H #include -#include +#include #include #include @@ -34,10 +34,10 @@ typedef boost::shared_ptr gr_message_debug_sptr; GR_CORE_API gr_message_debug_sptr gr_make_message_debug (); /*! - * \brief Gather received items into messages and insert into msgq + * \brief Print received messages to stdout * \ingroup sink_blk */ -class GR_CORE_API gr_message_debug : public gr_sync_block +class GR_CORE_API gr_message_debug : public gr_block { private: friend GR_CORE_API gr_message_debug_sptr @@ -50,10 +50,6 @@ class GR_CORE_API gr_message_debug : public gr_sync_block public: ~gr_message_debug (); - - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); }; #endif /* INCLUDED_GR_MESSAGE_DEBUG_H */ diff --git a/gnuradio-core/src/lib/io/gr_message_debug.i b/gnuradio-core/src/lib/io/gr_message_debug.i index 7bd547c91..65d3bfc4a 100644 --- a/gnuradio-core/src/lib/io/gr_message_debug.i +++ b/gnuradio-core/src/lib/io/gr_message_debug.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * diff --git a/gnuradio-core/src/lib/io/gr_pdu.cc b/gnuradio-core/src/lib/io/gr_pdu.cc index c5290b610..f33eed0a3 100644 --- a/gnuradio-core/src/lib/io/gr_pdu.cc +++ b/gnuradio-core/src/lib/io/gr_pdu.cc @@ -1,7 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include -size_t gr_pdu_itemsize(gr_pdu_vector_type type){ +size_t +gr_pdu_itemsize(gr_pdu_vector_type type){ switch(type){ case BYTE: return 1; @@ -14,7 +40,8 @@ size_t gr_pdu_itemsize(gr_pdu_vector_type type){ } } -bool gr_pdu_type_matches(gr_pdu_vector_type type, pmt::pmt_t v){ +bool +gr_pdu_type_matches(gr_pdu_vector_type type, pmt::pmt_t v){ switch(type){ case BYTE: return pmt::pmt_is_u8vector(v); @@ -27,7 +54,8 @@ bool gr_pdu_type_matches(gr_pdu_vector_type type, pmt::pmt_t v){ } } -pmt::pmt_t gr_pdu_make_vector(gr_pdu_vector_type type, const uint8_t* buf, size_t items){ +pmt::pmt_t +gr_pdu_make_vector(gr_pdu_vector_type type, const uint8_t* buf, size_t items){ switch(type){ case BYTE: return pmt::pmt_init_u8vector(items, buf); @@ -39,5 +67,3 @@ pmt::pmt_t gr_pdu_make_vector(gr_pdu_vector_type type, const uint8_t* buf, size_ throw std::runtime_error("bad type!"); } } - - diff --git a/gnuradio-core/src/lib/io/gr_pdu.h b/gnuradio-core/src/lib/io/gr_pdu.h index 3bea83740..67519c89d 100644 --- a/gnuradio-core/src/lib/io/gr_pdu.h +++ b/gnuradio-core/src/lib/io/gr_pdu.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * diff --git a/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc index 06a1c9596..5c319dc39 100644 --- a/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc +++ b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005,2010 Free Software Foundation, Inc. + * Copyright 2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * diff --git a/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.h b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.h index 3eb2a078b..3105a3d38 100644 --- a/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.h +++ b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -42,7 +42,7 @@ class GR_CORE_API gr_pdu_to_tagged_stream : public gr_sync_block { private: gr_pdu_vector_type d_vectortype; - size_t d_itemsize; + size_t d_itemsize; std::vector d_remain; friend GR_CORE_API gr_pdu_to_tagged_stream_sptr diff --git a/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.i b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.i index ddf1d8c05..ec760b309 100644 --- a/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.i +++ b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * diff --git a/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.cc b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.cc index 05ed8adc0..8211b7672 100644 --- a/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.cc +++ b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005,2010 Free Software Foundation, Inc. + * Copyright 2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -34,8 +34,6 @@ #include #include - - // public constructor that returns a shared_ptr gr_tagged_stream_to_pdu_sptr @@ -51,18 +49,18 @@ gr_tagged_stream_to_pdu::gr_tagged_stream_to_pdu (gr_pdu_vector_type t) d_vectortype(t), d_itemsize(gr_pdu_itemsize(t)), d_inpdu(false), d_pdu_meta(pmt::PMT_NIL), d_pdu_vector(pmt::PMT_NIL) { - message_port_register_out(pdu_port_id); + message_port_register_out(pdu_port_id); } gr_tagged_stream_to_pdu::~gr_tagged_stream_to_pdu() { - printf("destructor running\n"); + printf("destructor running\n"); } int gr_tagged_stream_to_pdu::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { const uint8_t *in = (const uint8_t*) input_items[0]; uint64_t abs_N = nitems_read(0); diff --git a/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.h b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.h index 6a40e1c0c..c3fff3581 100644 --- a/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.h +++ b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -42,7 +42,7 @@ class GR_CORE_API gr_tagged_stream_to_pdu : public gr_sync_block { private: gr_pdu_vector_type d_vectortype; - size_t d_itemsize; + size_t d_itemsize; std::vector d_save; diff --git a/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.i b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.i index 66bd875aa..f12987b74 100644 --- a/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.i +++ b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * -- cgit From 84c9f1125124876d6beab360053416999e308d2e Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Sat, 1 Dec 2012 14:56:04 -0800 Subject: cmake: fix typo in cmake swig module --- cmake/Modules/GrSwig.cmake | 2 +- gr-howto-write-a-block/cmake/Modules/GrSwig.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/Modules/GrSwig.cmake b/cmake/Modules/GrSwig.cmake index 175d0d759..a1642ef85 100644 --- a/cmake/Modules/GrSwig.cmake +++ b/cmake/Modules/GrSwig.cmake @@ -110,7 +110,7 @@ macro(GR_SWIG_MAKE name) #do swig doc generation if specified 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}) + set(GR_SWIG_DOCS_TARGET_DEPS ${GR_SWIG_TARGET_DEPS}) GR_SWIG_MAKE_DOCS(${GR_SWIG_DOC_FILE} ${GR_SWIG_DOC_DIRS}) add_custom_target(${name}_swig_doc DEPENDS ${GR_SWIG_DOC_FILE}) list(APPEND GR_SWIG_TARGET_DEPS ${name}_swig_doc) diff --git a/gr-howto-write-a-block/cmake/Modules/GrSwig.cmake b/gr-howto-write-a-block/cmake/Modules/GrSwig.cmake index 6ba5ee3a5..51a753ec5 100644 --- a/gr-howto-write-a-block/cmake/Modules/GrSwig.cmake +++ b/gr-howto-write-a-block/cmake/Modules/GrSwig.cmake @@ -108,7 +108,7 @@ macro(GR_SWIG_MAKE name) #do swig doc generation if specified 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}) + set(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}) endif() -- cgit From 7b58aac684e3b0f698e26c623f9bf002b735d8df Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Sat, 1 Dec 2012 22:13:18 -0800 Subject: Revert "Force swig compile ordering in gnuradio-core" This reverts commit 86dd49f2b301fdd7e817632eeb2dcaf25c86af4c. --- cmake/Modules/GrSwig.cmake | 2 -- 1 file changed, 2 deletions(-) diff --git a/cmake/Modules/GrSwig.cmake b/cmake/Modules/GrSwig.cmake index a1642ef85..3d1c5d47f 100644 --- a/cmake/Modules/GrSwig.cmake +++ b/cmake/Modules/GrSwig.cmake @@ -105,8 +105,6 @@ endfunction(GR_SWIG_MAKE_DOCS) macro(GR_SWIG_MAKE name) set(ifiles ${ARGN}) - list(APPEND GR_SWIG_TARGET_DEPS ${GR_SWIG_LIBRARIES}) - #do swig doc generation if specified if (GR_SWIG_DOC_FILE) set(GR_SWIG_DOCS_SOURCE_DEPS ${GR_SWIG_SOURCE_DEPS}) -- cgit From 8ac7a172052b8175c18ba6897d612c4b2fe2720c Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Mon, 3 Dec 2012 14:48:20 -0500 Subject: QA: update the 'import pmt' statement to always draw the pmt module from the build directory. --- gnuradio-core/src/python/gnuradio/gr/qa_pdu.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py b/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py index 64eb80a8f..83c7748af 100755 --- a/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py +++ b/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py @@ -21,8 +21,9 @@ # from gnuradio import gr, gr_unittest -from gruel import pmt -import time; +import pmt +import time + class test_pdu(gr_unittest.TestCase): def setUp(self): -- cgit From f334b636ed46c62b23582ed512bb07dfb51399ef Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Mon, 3 Dec 2012 14:49:02 -0500 Subject: core: the mutex is unlocked to begin with and GR doesn't seem to like us forcing it unlocked here. --- gnuradio-core/src/lib/runtime/gr_basic_block.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.cc b/gnuradio-core/src/lib/runtime/gr_basic_block.cc index 69f2e09f9..2c77c1c0c 100644 --- a/gnuradio-core/src/lib/runtime/gr_basic_block.cc +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.cc @@ -53,7 +53,6 @@ gr_basic_block::gr_basic_block(const std::string &name, d_color(WHITE), message_subscribers(pmt::pmt_make_dict()) { - mutex.unlock(); s_ncurrently_allocated++; } -- cgit From 197aa3c917c8750729e20ead831bb3a3dbce322e Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Mon, 3 Dec 2012 14:57:00 -0500 Subject: Docs: Fixing Doxygen markup for missing constructor parameters. --- gr-blocks/include/blocks/multiply_const_cc.h | 1 + gr-blocks/include/blocks/multiply_const_ff.h | 1 + gr-blocks/include/blocks/stream_mux.h | 2 +- gruel/src/include/gruel/msg_passing.h | 4 ++++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/gr-blocks/include/blocks/multiply_const_cc.h b/gr-blocks/include/blocks/multiply_const_cc.h index 032a765a4..9572eaec7 100644 --- a/gr-blocks/include/blocks/multiply_const_cc.h +++ b/gr-blocks/include/blocks/multiply_const_cc.h @@ -46,6 +46,7 @@ namespace gr { /*! * \brief Create an instance of multiply_const_cc * \param k complex multiplicative constant + * \param vlen Vector length of incoming stream */ static sptr make(gr_complex k, size_t vlen=1); diff --git a/gr-blocks/include/blocks/multiply_const_ff.h b/gr-blocks/include/blocks/multiply_const_ff.h index e755f59bf..d2d5e805c 100644 --- a/gr-blocks/include/blocks/multiply_const_ff.h +++ b/gr-blocks/include/blocks/multiply_const_ff.h @@ -46,6 +46,7 @@ namespace gr { /*! * \brief Create an instance of multiply_const_ff * \param k real multiplicative constant + * \param vlen Vector length of incoming stream */ static sptr make(float k, size_t vlen=1); diff --git a/gr-blocks/include/blocks/stream_mux.h b/gr-blocks/include/blocks/stream_mux.h index 905ea3c9f..58d564f9f 100644 --- a/gr-blocks/include/blocks/stream_mux.h +++ b/gr-blocks/include/blocks/stream_mux.h @@ -53,7 +53,7 @@ namespace gr { * \ingroup converter_blk * * \param itemsize the item size of the stream - * \param length a vector (list/tuple) specifying the number of + * \param lengths a vector (list/tuple) specifying the number of * items from each stream the mux together. * Warning: this requires that at least as many items * per stream are available or the system will wait diff --git a/gruel/src/include/gruel/msg_passing.h b/gruel/src/include/gruel/msg_passing.h index 7230dfc5b..25f30118f 100644 --- a/gruel/src/include/gruel/msg_passing.h +++ b/gruel/src/include/gruel/msg_passing.h @@ -36,6 +36,7 @@ namespace gruel { * \brief send message to msg_accepter * * \param accepter is the target of the send. + * \param which_port A pmt symbol describing the port by name. * \param msg is the message to send. It's usually a pmt tuple. * * Sending a message is an asynchronous operation. The \p send @@ -55,6 +56,7 @@ namespace gruel { * \brief send message to msg_accepter * * \param accepter is the target of the send. + * \param which_port A pmt symbol describing the port by name. * \param msg is the message to send. It's usually a pmt tuple. * * Sending a message is an asynchronous operation. The \p send @@ -74,6 +76,7 @@ namespace gruel { * \brief send message to msg_accepter * * \param accepter is the target of the send. + * \param which_port A pmt symbol describing the port by name. * \param msg is the message to send. It's usually a pmt tuple. * * Sending a message is an asynchronous operation. The \p send @@ -93,6 +96,7 @@ namespace gruel { * \brief send message to msg_accepter * * \param accepter is the target of the send. precond: pmt_is_msg_accepter(accepter) + * \param which_port A pmt symbol describing the port by name. * \param msg is the message to send. It's usually a pmt tuple. * * Sending a message is an asynchronous operation. The \p send -- cgit From ef74b48c155bfcec2f560c9a4a23592814699eda Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Mon, 3 Dec 2012 22:53:16 -0500 Subject: build: cleaned up some warnings. --- gnuradio-core/src/lib/general/gr_simple_correlator.cc | 4 ++++ gnuradio-core/src/lib/gengen/gr_vector_insert_X.cc.t | 2 +- gr-analog/lib/fmdet_cf_impl.cc | 10 +++++----- gr-atsc/src/lib/qa_atsci_single_viterbi.cc | 2 +- gr-fcd/lib/fcd_source_c_impl.cc | 2 +- gr-pager/lib/pager_flex_parse.cc | 6 +++--- 6 files changed, 15 insertions(+), 11 deletions(-) diff --git a/gnuradio-core/src/lib/general/gr_simple_correlator.cc b/gnuradio-core/src/lib/general/gr_simple_correlator.cc index 9c2ebef15..b9209e74f 100644 --- a/gnuradio-core/src/lib/general/gr_simple_correlator.cc +++ b/gnuradio-core/src/lib/general/gr_simple_correlator.cc @@ -158,11 +158,13 @@ gr_simple_correlator::general_work (int noutput_items, 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){ @@ -212,7 +214,9 @@ gr_simple_correlator::general_work (int noutput_items, 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; diff --git a/gnuradio-core/src/lib/gengen/gr_vector_insert_X.cc.t b/gnuradio-core/src/lib/gengen/gr_vector_insert_X.cc.t index 37963cdfe..20968afe2 100644 --- a/gnuradio-core/src/lib/gengen/gr_vector_insert_X.cc.t +++ b/gnuradio-core/src/lib/gengen/gr_vector_insert_X.cc.t @@ -44,7 +44,7 @@ // some sanity checks assert(offset < periodicity); assert(offset >= 0); - assert(periodicity > data.size()); + assert((size_t)periodicity > data.size()); } int diff --git a/gr-analog/lib/fmdet_cf_impl.cc b/gr-analog/lib/fmdet_cf_impl.cc index d3a58966b..c92ea2889 100644 --- a/gr-analog/lib/fmdet_cf_impl.cc +++ b/gr-analog/lib/fmdet_cf_impl.cc @@ -49,11 +49,11 @@ namespace gr { d_S1(0.1), d_S2(0.1), d_S3(0.1), d_S4(0.1) { - const float h[] = { 0.003118678733, -0.012139843428, 0.027270898036, - -0.051318579352, 0.090406910552, -0.162926865366, - 0.361885392563, 0.000000000000, -0.361885392563, - 0.162926865366, -0.090406910552, 0.051318579352, - -0.027270898036, 0.012139843428, -0.003118678733}; + //const float h[] = { 0.003118678733, -0.012139843428, 0.027270898036, + // -0.051318579352, 0.090406910552, -0.162926865366, + // 0.361885392563, 0.000000000000, -0.361885392563, + // 0.162926865366, -0.090406910552, 0.051318579352, + // -0.027270898036, 0.012139843428, -0.003118678733}; //std::vector taps(15); diff --git a/gr-atsc/src/lib/qa_atsci_single_viterbi.cc b/gr-atsc/src/lib/qa_atsci_single_viterbi.cc index ca0cf7464..699dce952 100644 --- a/gr-atsc/src/lib/qa_atsci_single_viterbi.cc +++ b/gr-atsc/src/lib/qa_atsci_single_viterbi.cc @@ -236,7 +236,7 @@ qa_atsci_single_viterbi::t1 () // FIXME, should we be able to tell how many errs too? if (differs) { - const int ERRTOL = 12; /* Or relate to delay? */ + //const int ERRTOL = 12; /* Or relate to delay? */ int shouldfix = 1; //int lasti = -ERRTOL; diff --git a/gr-fcd/lib/fcd_source_c_impl.cc b/gr-fcd/lib/fcd_source_c_impl.cc index 34a221827..81ccee092 100644 --- a/gr-fcd/lib/fcd_source_c_impl.cc +++ b/gr-fcd/lib/fcd_source_c_impl.cc @@ -176,7 +176,7 @@ void fcd_source_c_impl::set_lna_gain(float gain) // Set mixer gain void fcd_source_c_impl::set_mixer_gain(float gain) { - FCD_MODE_ENUM fme; + __GR_ATTR_UNUSED FCD_MODE_ENUM fme; unsigned char g; if ( gain > 4.0 ) { diff --git a/gr-pager/lib/pager_flex_parse.cc b/gr-pager/lib/pager_flex_parse.cc index 9418c4461..d7c308ddb 100644 --- a/gr-pager/lib/pager_flex_parse.cc +++ b/gr-pager/lib/pager_flex_parse.cc @@ -156,16 +156,16 @@ void pager_flex_parse::parse_data() void pager_flex_parse::parse_alphanumeric(int mw1, int mw2, int j) { int frag; - bool cont; + //bool cont; if (!d_laddr) { frag = (d_datawords[mw1] >> 11) & 0x03; - cont = (d_datawords[mw1] >> 10) & 0x01; + //cont = (d_datawords[mw1] >> 10) & 0x01; mw1++; } else { frag = (d_datawords[j+1] >> 11) & 0x03; - cont = (d_datawords[j+1] >> 10) & 0x01; + //cont = (d_datawords[j+1] >> 10) & 0x01; mw2--; } -- cgit From 32e9190a47109d51639b897c11a75bfd6f30f3f7 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 1 Dec 2012 23:31:13 -0800 Subject: swig: tweaks for swig makedepend * only search %include/import in .i files * when in regular headers use #include * stop adding all inc paths when file found --- cmake/Modules/GrSwig.cmake | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/cmake/Modules/GrSwig.cmake b/cmake/Modules/GrSwig.cmake index 3d1c5d47f..b9bf0bb0b 100644 --- a/cmake/Modules/GrSwig.cmake +++ b/cmake/Modules/GrSwig.cmake @@ -205,21 +205,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__': -- cgit From e26d2cf197aeb077f321c73e7a057a58d7117f38 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 3 Dec 2012 14:58:14 -0800 Subject: core: moving Boost_INCLUDE_DIRS to be last --- gnuradio-core/CMakeLists.txt | 1 + gnuradio-core/src/lib/swig/CMakeLists.txt | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gnuradio-core/CMakeLists.txt b/gnuradio-core/CMakeLists.txt index 4e76b3c5a..d773280e6 100644 --- a/gnuradio-core/CMakeLists.txt +++ b/gnuradio-core/CMakeLists.txt @@ -60,6 +60,7 @@ GR_SET_GLOBAL(GNURADIO_CORE_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}/src/lib/swig ${CMAKE_CURRENT_SOURCE_DIR}/src/lib/swig ${CMAKE_CURRENT_SOURCE_DIR}/src/lib/hier + ${Boost_INCLUDE_DIRS} ) GR_SET_GLOBAL(GNURADIO_CORE_SWIG_INCLUDE_DIRS diff --git a/gnuradio-core/src/lib/swig/CMakeLists.txt b/gnuradio-core/src/lib/swig/CMakeLists.txt index 72a2534f7..734547131 100644 --- a/gnuradio-core/src/lib/swig/CMakeLists.txt +++ b/gnuradio-core/src/lib/swig/CMakeLists.txt @@ -25,10 +25,9 @@ include_directories(${Boost_INCLUDE_DIRS}) link_directories(${Boost_LIBRARY_DIRS}) set(GR_SWIG_INCLUDE_DIRS - ${Boost_INCLUDE_DIRS} + ${CMAKE_CURRENT_BINARY_DIR} ${GRUEL_INCLUDE_DIRS} ${GNURADIO_CORE_SWIG_INCLUDE_DIRS} - ${CMAKE_CURRENT_BINARY_DIR} ) set(GR_SWIG_LIBRARIES gnuradio-core) -- cgit From a47c5485e477a2b29a839c785fea45f29da07919 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Tue, 4 Dec 2012 15:49:19 -0500 Subject: docs: Removing some obsoleted Doxygen commands per issue #498. These were set to the defaults and so should not affect previous versions of Doxygen. --- docs/doxygen/Doxyfile.in | 12 ------------ docs/doxygen/Doxyfile.swig_doc.in | 17 ----------------- docs/doxygen/doxyxml/example/Doxyfile | 17 ----------------- gr-howto-write-a-block/docs/doxygen/Doxyfile.in | 12 ------------ .../docs/doxygen/Doxyfile.swig_doc.in | 17 ----------------- .../docs/doxygen/doxyxml/example/Doxyfile | 17 ----------------- 6 files changed, 92 deletions(-) diff --git a/docs/doxygen/Doxyfile.in b/docs/doxygen/Doxyfile.in index ad3c2d01f..78a7a5d16 100644 --- a/docs/doxygen/Doxyfile.in +++ b/docs/doxygen/Doxyfile.in @@ -455,12 +455,6 @@ MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = NO - # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. @@ -862,12 +856,6 @@ HTML_FOOTER = HTML_STYLESHEET = -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports diff --git a/docs/doxygen/Doxyfile.swig_doc.in b/docs/doxygen/Doxyfile.swig_doc.in index 94e14bda1..8f6182ca8 100644 --- a/docs/doxygen/Doxyfile.swig_doc.in +++ b/docs/doxygen/Doxyfile.swig_doc.in @@ -470,12 +470,6 @@ MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = NO - # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. @@ -796,12 +790,6 @@ HTML_FOOTER = HTML_STYLESHEET = -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports @@ -950,11 +938,6 @@ ENUM_VALUES_PER_LINE = 4 GENERATE_TREEVIEW = NO -# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list. - -USE_INLINE_TREES = NO - # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. diff --git a/docs/doxygen/doxyxml/example/Doxyfile b/docs/doxygen/doxyxml/example/Doxyfile index 9780043be..dd2e5c77e 100644 --- a/docs/doxygen/doxyxml/example/Doxyfile +++ b/docs/doxygen/doxyxml/example/Doxyfile @@ -476,12 +476,6 @@ MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = NO - # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. @@ -808,12 +802,6 @@ HTML_STYLESHEET = HTML_TIMESTAMP = YES -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports @@ -978,11 +966,6 @@ ENUM_VALUES_PER_LINE = 4 GENERATE_TREEVIEW = NO -# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list. - -USE_INLINE_TREES = NO - # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. diff --git a/gr-howto-write-a-block/docs/doxygen/Doxyfile.in b/gr-howto-write-a-block/docs/doxygen/Doxyfile.in index cb6a913bb..6ee69ee35 100644 --- a/gr-howto-write-a-block/docs/doxygen/Doxyfile.in +++ b/gr-howto-write-a-block/docs/doxygen/Doxyfile.in @@ -455,12 +455,6 @@ MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = NO - # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. @@ -807,12 +801,6 @@ HTML_FOOTER = HTML_STYLESHEET = -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports diff --git a/gr-howto-write-a-block/docs/doxygen/Doxyfile.swig_doc.in b/gr-howto-write-a-block/docs/doxygen/Doxyfile.swig_doc.in index 50b8aa81d..121c3e858 100644 --- a/gr-howto-write-a-block/docs/doxygen/Doxyfile.swig_doc.in +++ b/gr-howto-write-a-block/docs/doxygen/Doxyfile.swig_doc.in @@ -470,12 +470,6 @@ MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = NO - # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. @@ -796,12 +790,6 @@ HTML_FOOTER = HTML_STYLESHEET = -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports @@ -950,11 +938,6 @@ ENUM_VALUES_PER_LINE = 4 GENERATE_TREEVIEW = NO -# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list. - -USE_INLINE_TREES = NO - # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. diff --git a/gr-howto-write-a-block/docs/doxygen/doxyxml/example/Doxyfile b/gr-howto-write-a-block/docs/doxygen/doxyxml/example/Doxyfile index 9780043be..dd2e5c77e 100644 --- a/gr-howto-write-a-block/docs/doxygen/doxyxml/example/Doxyfile +++ b/gr-howto-write-a-block/docs/doxygen/doxyxml/example/Doxyfile @@ -476,12 +476,6 @@ MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = NO - # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. @@ -808,12 +802,6 @@ HTML_STYLESHEET = HTML_TIMESTAMP = YES -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports @@ -978,11 +966,6 @@ ENUM_VALUES_PER_LINE = 4 GENERATE_TREEVIEW = NO -# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list. - -USE_INLINE_TREES = NO - # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. -- cgit From 53be45f118e6e73d2a50fe0ba4622d6dfe96117c Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Thu, 6 Dec 2012 12:52:35 -0500 Subject: core: updated the message debug block to have a 'store' port where messages can be retrieved afterwards. Updated qa_pdu to use the new 'store' port for testing the resulting message. --- gnuradio-core/src/lib/io/gr_message_debug.cc | 39 +++++++++++++++++--- gnuradio-core/src/lib/io/gr_message_debug.h | 49 +++++++++++++++++++++++++- gnuradio-core/src/python/gnuradio/gr/qa_pdu.py | 49 +++++++++++++++++--------- grc/blocks/gr_message_debug.xml | 7 +++- 4 files changed, 121 insertions(+), 23 deletions(-) diff --git a/gnuradio-core/src/lib/io/gr_message_debug.cc b/gnuradio-core/src/lib/io/gr_message_debug.cc index d98954576..7d28ff18e 100644 --- a/gnuradio-core/src/lib/io/gr_message_debug.cc +++ b/gnuradio-core/src/lib/io/gr_message_debug.cc @@ -43,20 +43,49 @@ gr_make_message_debug () return gnuradio::get_initial_sptr(new gr_message_debug()); } -void gr_message_debug::print(pmt::pmt_t msg){ - std::cout << "******* MESSAGE DEBUG PRINT ********\n"; - pmt::pmt_print(msg); - std::cout << "************************************\n"; +void +gr_message_debug::print(pmt::pmt_t msg) +{ + std::cout << "******* MESSAGE DEBUG PRINT ********\n"; + pmt::pmt_print(msg); + std::cout << "************************************\n"; +} + +void +gr_message_debug::store(pmt::pmt_t msg) +{ + gruel::scoped_lock guard(d_mutex); + d_messages.push_back(msg); +} + +int +gr_message_debug::num_messages() +{ + return (int)d_messages.size(); } +pmt::pmt_t +gr_message_debug::get_message(int i) +{ + gruel::scoped_lock guard(d_mutex); + + if((size_t)i >= d_messages.size()) { + throw std::runtime_error("gr_message_debug: index for message out of bounds.\n"); + } -gr_message_debug::gr_message_debug () + return d_messages[i]; +} + +gr_message_debug::gr_message_debug() : gr_block("message_debug", gr_make_io_signature(0, 0, 0), gr_make_io_signature(0, 0, 0)) { message_port_register_in(pmt::mp("print")); set_msg_handler(pmt::mp("print"), boost::bind(&gr_message_debug::print, this, _1)); + + message_port_register_in(pmt::mp("store")); + set_msg_handler(pmt::mp("store"), boost::bind(&gr_message_debug::store, 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 120694a91..1ffef1b02 100644 --- a/gnuradio-core/src/lib/io/gr_message_debug.h +++ b/gnuradio-core/src/lib/io/gr_message_debug.h @@ -27,11 +27,12 @@ #include #include #include +#include class gr_message_debug; typedef boost::shared_ptr gr_message_debug_sptr; -GR_CORE_API gr_message_debug_sptr gr_make_message_debug (); +GR_CORE_API gr_message_debug_sptr gr_make_message_debug(); /*! * \brief Print received messages to stdout @@ -43,13 +44,59 @@ class GR_CORE_API gr_message_debug : public gr_block friend GR_CORE_API gr_message_debug_sptr gr_make_message_debug(); + /*! + * \brief 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 msg A pmt message passed from the scheduler's message handling. + */ void print(pmt::pmt_t msg); + /*! + * \brief Messages received in this port are stored in a vector. + * + * This port receives messages from the scheduler's message handling + * mechanism and stores it in a vector. Messages can be retrieved + * later using the 'get_message' function. This message handler + * function is only meant to be used by the scheduler to handle + * messages posted to port 'store'. + * + * \param msg A pmt message passed from the scheduler's message handling. + */ + void store(pmt::pmt_t msg); + + gruel::mutex d_mutex; + std::vector d_messages; + protected: gr_message_debug (); public: ~gr_message_debug (); + + /*! + * \brief Reports the number of messages received by this block. + */ + int num_messages(); + + /*! + * \brief Get a message (as a PMT) from the message vector at index \p i. + * + * Messages passed to the 'store' port will be stored in a + * vector. This function retrieves those messages by index. They are + * index in order of when they were received (all messages are just + * pushed onto the back of a vector). This is mostly useful in + * debugging message passing graphs and in QA code. + * + * \param i The index in the vector for the message to retrieve. + * + * \return a message at index \p i as a pmt_t. + */ + pmt::pmt_t get_message(int i); }; #endif /* INCLUDED_GR_MESSAGE_DEBUG_H */ diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py b/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py index 83c7748af..da1331d96 100755 --- a/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py +++ b/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py @@ -36,36 +36,53 @@ class test_pdu(gr_unittest.TestCase): # Just run some data through and make sure it doesn't puke. src_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) - src = gr.pdu_to_tagged_stream(gr.BYTE); - snk3 = gr.tagged_stream_to_pdu(gr.BYTE); - snk2 = gr.vector_sink_b(); - snk = gr.tag_debug(1, "test"); + src = gr.pdu_to_tagged_stream(gr.BYTE) + snk3 = gr.tagged_stream_to_pdu(gr.BYTE) + snk2 = gr.vector_sink_b() + snk = gr.tag_debug(1, "test") - dbg = gr.message_debug(); + dbg = gr.message_debug() self.tb.connect(src, snk) self.tb.connect(src, snk2) self.tb.connect(src, snk3) - self.tb.msg_connect(snk3, "pdus", dbg, "print"); + self.tb.msg_connect(snk3, "pdus", dbg, "store") self.tb.start() # make our reference and message pmts - port = pmt.pmt_intern("pdus"); - msg = pmt.pmt_cons( pmt.PMT_NIL, pmt.pmt_make_u8vector(16, 0xFF) ); + port = pmt.pmt_intern("pdus") + msg = pmt.pmt_cons( pmt.PMT_NIL, pmt.pmt_make_u8vector(16, 0xFF) ) - print "printing port & msg" - pmt.pmt_print(port); - pmt.pmt_print(msg); + #print "printing port & msg" + #pmt.pmt_print(port) + #pmt.pmt_print(msg) # post the message - src.to_basic_block()._post( port, msg ); + src.to_basic_block()._post( port, msg ) - time.sleep(1); - self.tb.stop(); - self.tb.wait(); + while(dbg.num_messages() < 1): + time.sleep(0.5) + self.tb.stop() + self.tb.wait() - print snk2.data(); + # Get the vector of data from the vector sink + result_data = snk2.data() + + # Get the vector of data from the message sink + # Convert the message PMT as a pair into its vector + result_msg = dbg.get_message(0) + msg_vec = pmt.pmt_cdr(result_msg) + pmt.pmt_print(msg_vec) + + # Convert the PMT vector into a Python list + msg_data = [] + for i in xrange(16): + msg_data.append(pmt.pmt_u8vector_ref(msg_vec, i)) + + actual_data = 16*[0xFF,] + self.assertEqual(actual_data, list(result_data)) + self.assertEqual(actual_data, msg_data) if __name__ == '__main__': gr_unittest.run(test_pdu, "test_pdu.xml") diff --git a/grc/blocks/gr_message_debug.xml b/grc/blocks/gr_message_debug.xml index 9478f5304..705a7cc5f 100644 --- a/grc/blocks/gr_message_debug.xml +++ b/grc/blocks/gr_message_debug.xml @@ -12,6 +12,11 @@ print message - 1 + 1 + + + store + message + 1 -- cgit From 69990c3fb6d4c7a0daee0229407241aa1959095a Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Thu, 6 Dec 2012 14:10:39 -0500 Subject: core: Adding function to retrieve the symbol names of a blocks message ports. Updated qa_pdu tests to verify this. --- gnuradio-core/src/lib/runtime/gr_basic_block.cc | 129 ++++++++++++++++-------- gnuradio-core/src/lib/runtime/gr_basic_block.h | 17 ++++ gnuradio-core/src/lib/runtime/gr_basic_block.i | 2 + gnuradio-core/src/python/gnuradio/gr/qa_pdu.py | 21 ++++ 4 files changed, 127 insertions(+), 42 deletions(-) diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.cc b/gnuradio-core/src/lib/runtime/gr_basic_block.cc index 2c77c1c0c..0f7875a12 100644 --- a/gnuradio-core/src/lib/runtime/gr_basic_block.cc +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.cc @@ -77,56 +77,101 @@ gr_basic_block::set_block_alias(std::string name) // ** Message passing interface ** // - register a new input message port -void gr_basic_block::message_port_register_in(pmt::pmt_t port_id){ - msg_queue[port_id] = msg_queue_t(); - msg_queue_ready[port_id] = boost::shared_ptr(new boost::condition_variable()); - } +void +gr_basic_block::message_port_register_in(pmt::pmt_t port_id) +{ + if(!pmt::pmt_is_symbol(port_id)) { + throw std::runtime_error("message_port_register_in: bad port id"); + } + msg_queue[port_id] = msg_queue_t(); + msg_queue_ready[port_id] = boost::shared_ptr(new boost::condition_variable()); +} + +pmt::pmt_t +gr_basic_block::message_ports_in() +{ + pmt::pmt_t port_names = pmt::pmt_make_vector(msg_queue.size(), pmt::PMT_NIL); + msg_queue_map_itr itr = msg_queue.begin(); + for(size_t i = 0; i < msg_queue.size(); i++) { + pmt::pmt_vector_set(port_names, i, (*itr).first); + itr++; + } + return port_names; +} // - register a new output message port -void gr_basic_block::message_port_register_out(pmt::pmt_t port_id){ - if(!pmt::pmt_is_symbol(port_id)){ throw std::runtime_error("bad port id"); } - if(pmt::pmt_dict_has_key(message_subscribers, port_id)){ throw std::runtime_error("port already in use"); } - message_subscribers = pmt::pmt_dict_add(message_subscribers, port_id, pmt::PMT_NIL); - } +void +gr_basic_block::message_port_register_out(pmt::pmt_t port_id) +{ + if(!pmt::pmt_is_symbol(port_id)) { + throw std::runtime_error("message_port_register_out: bad port id"); + } + if(pmt::pmt_dict_has_key(message_subscribers, port_id)) { + throw std::runtime_error("message_port_register_out: port already in use"); + } + message_subscribers = pmt::pmt_dict_add(message_subscribers, port_id, pmt::PMT_NIL); +} + +pmt::pmt_t +gr_basic_block::message_ports_out() +{ + size_t len = pmt::pmt_length(message_subscribers); + pmt::pmt_t port_names = pmt::pmt_make_vector(len, pmt::PMT_NIL); + pmt::pmt_t keys = pmt::pmt_dict_keys(message_subscribers); + for(size_t i = 0; i < len; i++) { + pmt::pmt_vector_set(port_names, i, pmt::pmt_nth(i, keys)); + } + return port_names; +} // - publish a message on a message port -void gr_basic_block::message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg){ - if(!pmt::pmt_dict_has_key(message_subscribers, port_id)){ throw std::runtime_error("port does not exist"); } - pmt::pmt_t currlist = pmt::pmt_dict_ref(message_subscribers,port_id,pmt::PMT_NIL); - // iterate through subscribers on port - while( pmt::pmt_is_pair(currlist) ){ - pmt::pmt_t target = pmt::pmt_car(currlist); - - pmt::pmt_t block = pmt::pmt_car(target); - pmt::pmt_t port = pmt::pmt_cdr(target); +void gr_basic_block::message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg) +{ + if(!pmt::pmt_dict_has_key(message_subscribers, port_id)) { + throw std::runtime_error("port does not exist"); + } + + pmt::pmt_t currlist = pmt::pmt_dict_ref(message_subscribers, port_id, pmt::PMT_NIL); + // iterate through subscribers on port + while(pmt::pmt_is_pair(currlist)) { + pmt::pmt_t target = pmt::pmt_car(currlist); + + pmt::pmt_t block = pmt::pmt_car(target); + pmt::pmt_t port = pmt::pmt_cdr(target); - currlist = pmt::pmt_cdr(currlist); - gr_basic_block_sptr blk = global_block_registry.block_lookup(block); - //blk->post(msg); - blk->post(port, msg); - } - } + currlist = pmt::pmt_cdr(currlist); + gr_basic_block_sptr blk = global_block_registry.block_lookup(block); + //blk->post(msg); + blk->post(port, msg); + } +} // - subscribe to a message port -void gr_basic_block::message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target){ - if(!pmt::pmt_dict_has_key(message_subscribers, port_id)){ - std::stringstream ss; - ss << "Port does not exist: \"" << pmt::pmt_write_string(port_id) << "\" on block: " << pmt::pmt_write_string(target) << std::endl; - throw std::runtime_error(ss.str()); - } - pmt::pmt_t currlist = pmt::pmt_dict_ref(message_subscribers,port_id,pmt::PMT_NIL); - message_subscribers = pmt::pmt_dict_add(message_subscribers,port_id,pmt::pmt_list_add(currlist,target)); - } +void gr_basic_block::message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target) +{ + if(!pmt::pmt_dict_has_key(message_subscribers, port_id)) { + std::stringstream ss; + ss << "Port does not exist: \"" << pmt::pmt_write_string(port_id) + << "\" on block: " << pmt::pmt_write_string(target) << std::endl; + throw std::runtime_error(ss.str()); + } + + pmt::pmt_t currlist = pmt::pmt_dict_ref(message_subscribers,port_id,pmt::PMT_NIL); + message_subscribers = pmt::pmt_dict_add(message_subscribers,port_id,pmt::pmt_list_add(currlist,target)); +} -void gr_basic_block::message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target){ - if(!pmt::pmt_dict_has_key(message_subscribers, port_id)){ - std::stringstream ss; - ss << "Port does not exist: \"" << pmt::pmt_write_string(port_id) << "\" on block: " << pmt::pmt_write_string(target) << std::endl; - throw std::runtime_error(ss.str()); - } - pmt::pmt_t currlist = pmt::pmt_dict_ref(message_subscribers,port_id,pmt::PMT_NIL); - message_subscribers = pmt::pmt_dict_add(message_subscribers,port_id,pmt::pmt_list_rm(currlist,target)); - } +void gr_basic_block::message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target) +{ + if(!pmt::pmt_dict_has_key(message_subscribers, port_id)) { + std::stringstream ss; + ss << "Port does not exist: \"" << pmt::pmt_write_string(port_id) + << "\" on block: " << pmt::pmt_write_string(target) << std::endl; + throw std::runtime_error(ss.str()); + } + + pmt::pmt_t currlist = pmt::pmt_dict_ref(message_subscribers,port_id,pmt::PMT_NIL); + message_subscribers = pmt::pmt_dict_add(message_subscribers,port_id,pmt::pmt_list_rm(currlist,target)); +} void gr_basic_block::_post(pmt_t which_port, pmt_t msg) diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.h b/gnuradio-core/src/lib/runtime/gr_basic_block.h index e0fd5d2af..00e9c2192 100644 --- a/gnuradio-core/src/lib/runtime/gr_basic_block.h +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.h @@ -72,6 +72,7 @@ private: typedef std::deque msg_queue_t; typedef std::map msg_queue_map_t; + typedef std::map::iterator msg_queue_map_itr; msg_queue_map_t msg_queue; // boost::condition_variable msg_queue_ready; std::map, pmt::pmt_comperator> msg_queue_ready; @@ -142,6 +143,22 @@ public: void message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target); void message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target); + /*! + * \brief Get input message port names. + * + * Returns the available input message ports for a block. The + * return object is a PMT vector that is filled with PMT symbols. + */ + pmt::pmt_t message_ports_in(); + + /*! + * \brief Get output message port names. + * + * Returns the available output message ports for a block. The + * return object is a PMT vector that is filled with PMT symbols. + */ + pmt::pmt_t message_ports_out(); + /*! * Accept msg, place in queue, arrange for thread to be awakened if it's not already. */ diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.i b/gnuradio-core/src/lib/runtime/gr_basic_block.i index d6d6c3d16..62f16462d 100644 --- a/gnuradio-core/src/lib/runtime/gr_basic_block.i +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.i @@ -48,6 +48,8 @@ public: std::string alias(); void set_block_alias(std::string name); void _post(pmt_t which_port, pmt_t msg); + pmt_t message_ports_in(); + pmt_t message_ports_out(); }; %rename(block_ncurrently_allocated) gr_basic_block_ncurrently_allocated; diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py b/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py index da1331d96..bf02d12c1 100755 --- a/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py +++ b/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py @@ -43,6 +43,27 @@ class test_pdu(gr_unittest.TestCase): dbg = gr.message_debug() + # 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(po), 0) + + pi = snk3.message_ports_in() + po = snk3.message_ports_out() + self.assertEqual(pmt.pmt_length(pi), 0) + self.assertEqual(pmt.pmt_length(po), 1) + + #print "Message Debug input ports: " + #pmt.pmt_print(pi) + #print "Message Debug output ports: " + #pmt.pmt_print(po) + + #print "Stream to PDU input ports: " + #pmt.pmt_print(pi) + #print "Stream to PDU output ports: " + #pmt.pmt_print(po) + self.tb.connect(src, snk) self.tb.connect(src, snk2) self.tb.connect(src, snk3) -- cgit From 52ca5e2765b7a4532d26502b5b76b7c85c5019d7 Mon Sep 17 00:00:00 2001 From: Tim O'Shea Date: Fri, 7 Dec 2012 09:28:41 -0800 Subject: core: added gr_tuntap_pdu, gr_socket_pdu, and msg passing enhancements --- CMakeLists.txt | 7 + gnuradio-core/src/lib/io/CMakeLists.txt | 4 + gnuradio-core/src/lib/io/gr_message_debug.cc | 34 +- gnuradio-core/src/lib/io/gr_message_debug.h | 1 + gnuradio-core/src/lib/io/gr_pdu.cc | 70 ++-- gnuradio-core/src/lib/io/gr_pdu.h | 1 + gnuradio-core/src/lib/io/gr_socket_pdu.cc | 157 ++++++++ gnuradio-core/src/lib/io/gr_socket_pdu.h | 203 +++++++++++ gnuradio-core/src/lib/io/gr_socket_pdu.i | 33 ++ gnuradio-core/src/lib/io/gr_stream_pdu_base.cc | 117 ++++++ gnuradio-core/src/lib/io/gr_stream_pdu_base.h | 62 ++++ gnuradio-core/src/lib/io/gr_tuntap_pdu.cc | 143 ++++++++ gnuradio-core/src/lib/io/gr_tuntap_pdu.h | 66 ++++ gnuradio-core/src/lib/io/gr_tuntap_pdu.i | 30 ++ gnuradio-core/src/lib/io/io.i | 5 + gnuradio-core/src/lib/runtime/gr_basic_block.cc | 41 +-- gnuradio-core/src/lib/runtime/gr_basic_block.h | 406 +++++++++++---------- gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc | 34 +- gnuradio-core/src/lib/runtime/gr_flat_flowgraph.h | 4 +- gnuradio-core/src/lib/runtime/gr_flowgraph.cc | 40 +- gnuradio-core/src/lib/runtime/gr_flowgraph.h | 61 +++- gnuradio-core/src/lib/runtime/gr_hier_block2.cc | 5 +- gnuradio-core/src/lib/runtime/gr_hier_block2.h | 33 ++ gnuradio-core/src/lib/runtime/gr_hier_block2.i | 6 + .../src/lib/runtime/gr_hier_block2_detail.cc | 90 ++++- .../src/lib/runtime/gr_hier_block2_detail.h | 1 + .../src/python/gnuradio/gr/hier_block2.py | 13 + grc/blocks/block_tree.xml | 2 + grc/blocks/gr_message_debug.xml | 5 + grc/blocks/gr_socket_pdu.xml | 62 ++++ grc/blocks/gr_tuntap_pdu.xml | 34 ++ grc/blocks/pad_sink.xml | 9 +- grc/blocks/pad_source.xml | 9 +- grc/python/FlowGraph.py | 10 + grc/python/convert_hier.py | 20 +- grc/python/flow_graph.tmpl | 17 +- gruel/src/include/gruel/pmt.h | 6 + gruel/src/lib/pmt/pmt.cc | 16 + gruel/src/swig/pmt_swig.i | 5 + volk/CMakeLists.txt | 10 +- volk/apps/CMakeLists.txt | 2 +- 41 files changed, 1595 insertions(+), 279 deletions(-) create mode 100644 gnuradio-core/src/lib/io/gr_socket_pdu.cc create mode 100644 gnuradio-core/src/lib/io/gr_socket_pdu.h create mode 100644 gnuradio-core/src/lib/io/gr_socket_pdu.i create mode 100644 gnuradio-core/src/lib/io/gr_stream_pdu_base.cc create mode 100644 gnuradio-core/src/lib/io/gr_stream_pdu_base.h create mode 100644 gnuradio-core/src/lib/io/gr_tuntap_pdu.cc create mode 100644 gnuradio-core/src/lib/io/gr_tuntap_pdu.h create mode 100644 gnuradio-core/src/lib/io/gr_tuntap_pdu.i create mode 100644 grc/blocks/gr_socket_pdu.xml create mode 100644 grc/blocks/gr_tuntap_pdu.xml diff --git a/CMakeLists.txt b/CMakeLists.txt index 9af8d7eb9..bc076b9e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,13 @@ include(GrVersion) #setup version info SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O2") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O2") +######################################################################## +# Environment setup +######################################################################## +IF(NOT DEFINED BOOST_ROOT) + SET(BOOST_ROOT ${CMAKE_INSTALL_PREFIX}) +ENDIF() + ######################################################################## # Import executables from a native build (for cross compiling) # http://www.vtk.org/Wiki/CMake_Cross_Compiling#Using_executables_in_the_build_created_during_the_build diff --git a/gnuradio-core/src/lib/io/CMakeLists.txt b/gnuradio-core/src/lib/io/CMakeLists.txt index 7041f2820..59ca06b5a 100644 --- a/gnuradio-core/src/lib/io/CMakeLists.txt +++ b/gnuradio-core/src/lib/io/CMakeLists.txt @@ -39,6 +39,7 @@ list(APPEND gnuradio_core_sources ${CMAKE_CURRENT_SOURCE_DIR}/ppio_ppdev.cc ${CMAKE_CURRENT_SOURCE_DIR}/gri_wavfile.cc ${CMAKE_CURRENT_SOURCE_DIR}/gr_pdu.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_stream_pdu_base.cc ) ######################################################################## @@ -61,6 +62,7 @@ install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ppio_ppdev.h ${CMAKE_CURRENT_SOURCE_DIR}/gri_wavfile.h ${CMAKE_CURRENT_SOURCE_DIR}/gr_pdu.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_stream_pdu_base.h DESTINATION ${GR_INCLUDE_DIR}/gnuradio COMPONENT "core_devel" ) @@ -103,6 +105,8 @@ set(gr_core_io_triple_threats gr_wavfile_sink gr_tagged_file_sink gr_tagged_stream_to_pdu + gr_tuntap_pdu + gr_socket_pdu ) foreach(file_tt ${gr_core_io_triple_threats}) diff --git a/gnuradio-core/src/lib/io/gr_message_debug.cc b/gnuradio-core/src/lib/io/gr_message_debug.cc index 7d28ff18e..27f4c65fd 100644 --- a/gnuradio-core/src/lib/io/gr_message_debug.cc +++ b/gnuradio-core/src/lib/io/gr_message_debug.cc @@ -58,6 +58,30 @@ gr_message_debug::store(pmt::pmt_t msg) d_messages.push_back(msg); } +void +gr_message_debug::print_verbose(pmt::pmt_t msg) +{ + pmt::pmt_t meta = pmt::pmt_car(msg); + pmt::pmt_t vector = pmt::pmt_cdr(msg); + std::cout << "* MESSAGE DEBUG PRINT PDU VERBOSE *\n"; + pmt::pmt_print(meta); + size_t len = pmt::pmt_length(vector); + std::cout << "pdu_length = " << len << std::endl; + std::cout << "contents = " << std::endl; + size_t offset(0); + const uint8_t* d = (const uint8_t*) pmt_uniform_vector_elements(vector, offset); + for(size_t i=0; i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// public constructor that returns a shared_ptr +gr_socket_pdu_sptr +gr_make_socket_pdu (std::string type, std::string addr, std::string port, int MTU) +{ + return gnuradio::get_initial_sptr(new gr_socket_pdu(type,addr,port,MTU)); +} + +gr_socket_pdu::gr_socket_pdu (std::string type, std::string addr, std::string port, int MTU) + : gr_stream_pdu_base(MTU) +{ + + if( (type == "TCP_SERVER") || (type == "TCP_CLIENT")){ + boost::asio::ip::tcp::resolver resolver(_io_service); + boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), addr, port); + _tcp_endpoint = *resolver.resolve(query); + } + if( (type == "UDP_SERVER") || (type == "UDP_CLIENT")){ + boost::asio::ip::udp::resolver resolver(_io_service); + boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), addr, port); + if( (type == "UDP_SERVER") ){ + _udp_endpoint = *resolver.resolve(query); + } else { + _udp_endpoint_other = *resolver.resolve(query); + } + } + + // register ports + message_port_register_out(pmt::mp("pdus")); + message_port_register_in(pmt::mp("pdus")); + + // set up socketry + if (type == "TCP_SERVER"){ + _acceptor_tcp.reset(new boost::asio::ip::tcp::acceptor(_io_service, _tcp_endpoint)); + _acceptor_tcp->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); + start_tcp_accept(); + // bind tcp server send handler + set_msg_handler(pmt::mp("pdus"), boost::bind(&gr_socket_pdu::tcp_server_send, this, _1)); + } else if(type =="TCP_CLIENT"){ + boost::system::error_code error = boost::asio::error::host_not_found; + _tcp_socket.reset(new boost::asio::ip::tcp::socket(_io_service)); + _tcp_socket->connect(_tcp_endpoint, error); + if(error){ + throw boost::system::system_error(error); + } + set_msg_handler(pmt::mp("pdus"), boost::bind(&gr_socket_pdu::tcp_client_send, this, _1)); + _tcp_socket->async_read_some( + boost::asio::buffer(rxbuf), + boost::bind(&gr_socket_pdu::handle_tcp_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); + + } else if(type =="UDP_SERVER"){ + _udp_socket.reset(new boost::asio::ip::udp::socket(_io_service, _udp_endpoint)); + _udp_socket->async_receive_from( boost::asio::buffer(rxbuf), _udp_endpoint_other, + boost::bind(&gr_socket_pdu::handle_udp_read, this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + set_msg_handler(pmt::mp("pdus"), boost::bind(&gr_socket_pdu::udp_send, this, _1)); + } else if(type =="UDP_CLIENT"){ + _udp_socket.reset(new boost::asio::ip::udp::socket(_io_service, _udp_endpoint)); + _udp_socket->async_receive_from( boost::asio::buffer(rxbuf), _udp_endpoint_other, + boost::bind(&gr_socket_pdu::handle_udp_read, this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + set_msg_handler(pmt::mp("pdus"), boost::bind(&gr_socket_pdu::udp_send, this, _1)); + } else { + throw std::runtime_error("unknown socket type!"); + } + + // start thread for io_service + d_thread = boost::shared_ptr(new boost::thread(boost::bind(&gr_socket_pdu::run_io_service, this))); + d_started = true; +} + +void tcp_connection::handle_read(const boost::system::error_code& error/*error*/, size_t bytes_transferred) + { + if(!error) + { + pmt::pmt_t vector = pmt::pmt_init_u8vector(bytes_transferred, (const uint8_t*)&buf[0]); + pmt::pmt_t pdu = pmt::pmt_cons( pmt::PMT_NIL, vector); + + d_block->message_port_pub( pmt::mp("pdus"), pdu ); + + socket_.async_read_some( + boost::asio::buffer(buf), + boost::bind(&tcp_connection::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); + + } else { + std::cout << "error occurred\n"; + } + + } + + +void gr_socket_pdu::tcp_server_send(pmt::pmt_t msg){ + pmt::pmt_t vector = pmt::pmt_cdr(msg); + for(size_t i=0; isend(vector); + } +} + +void gr_socket_pdu::tcp_client_send(pmt::pmt_t msg){ + pmt::pmt_t vector = pmt::pmt_cdr(msg); + size_t len = pmt::pmt_length(vector); + size_t offset(0); + boost::array txbuf; + memcpy(&txbuf[0], pmt::pmt_uniform_vector_elements(vector, offset), len); + _tcp_socket->send(boost::asio::buffer(txbuf,len)); +} + +void gr_socket_pdu::udp_send(pmt::pmt_t msg){ + pmt::pmt_t vector = pmt::pmt_cdr(msg); + size_t len = pmt::pmt_length(vector); + size_t offset(0); + boost::array txbuf; + memcpy(&txbuf[0], pmt::pmt_uniform_vector_elements(vector, offset), len); + if(_udp_endpoint_other.address().to_string() != "0.0.0.0") + _udp_socket->send_to(boost::asio::buffer(txbuf,len), _udp_endpoint_other); +} diff --git a/gnuradio-core/src/lib/io/gr_socket_pdu.h b/gnuradio-core/src/lib/io/gr_socket_pdu.h new file mode 100644 index 000000000..3a96a3f97 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_socket_pdu.h @@ -0,0 +1,203 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_SOCKET_PDU_H +#define INCLUDED_GR_SOCKET_PDU_H + +#include +#include +#include +#include +#include +#include + +#include + +class gr_socket_pdu; +typedef boost::shared_ptr gr_socket_pdu_sptr; + +GR_CORE_API gr_socket_pdu_sptr gr_make_socket_pdu (std::string type, std::string addr, std::string port, int MTU=10000); + +class tcp_connection + : public boost::enable_shared_from_this +{ +public: + typedef boost::shared_ptr pointer; + gr_socket_pdu *d_block; + boost::array buf; + + static pointer create(boost::asio::io_service& io_service) + { + return pointer(new tcp_connection(io_service)); + } + + boost::asio::ip::tcp::socket& socket() + { + return socket_; + } + + void start(gr_socket_pdu* parent) + { + d_block = parent; +// message_ = "connected to gr_socket_pdu\n"; +// boost::asio::async_write(socket_, boost::asio::buffer(message_), +// boost::bind(&tcp_connection::handle_write, shared_from_this(), +// boost::asio::placeholders::error, +// boost::asio::placeholders::bytes_transferred)); + + socket_.async_read_some( + boost::asio::buffer(buf), + boost::bind(&tcp_connection::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); + } + void send(pmt::pmt_t vector){ + size_t len = pmt::pmt_length(vector); + size_t offset(0); + boost::array txbuf; + memcpy(&txbuf[0], pmt::pmt_uniform_vector_elements(vector, offset), len); + boost::asio::async_write(socket_, boost::asio::buffer(txbuf, len), + boost::bind(&tcp_connection::handle_write, shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + } + + ~tcp_connection(){ +// std::cout << "tcp_connection destroyed\n"; + } + +private: + tcp_connection(boost::asio::io_service& io_service) + : socket_(io_service) + { + } + + void handle_read(const boost::system::error_code& error/*error*/, size_t bytes_transferred); + + void handle_write(const boost::system::error_code& /*error*/, + size_t /*bytes_transferred*/) + { + } + + boost::asio::ip::tcp::socket socket_; + std::string message_; +}; + + +/*! + * \brief Gather received items into messages and insert into msgq + * \ingroup sink_blk + */ +class GR_CORE_API gr_socket_pdu : public gr_stream_pdu_base +{ + private: + friend GR_CORE_API gr_socket_pdu_sptr + gr_make_socket_pdu(std::string type, std::string addr, std::string port, int MTU); + + boost::asio::io_service _io_service; + + boost::array rxbuf; + + // tcp specific + boost::asio::ip::tcp::endpoint _tcp_endpoint; + + // specific to tcp server + boost::shared_ptr _acceptor_tcp; + std::vector d_tcp_connections; + void tcp_server_send(pmt::pmt_t msg); + void tcp_client_send(pmt::pmt_t msg); + void udp_send(pmt::pmt_t msg); + + // specific to tcp client + boost::shared_ptr _tcp_socket; + + // specific to udp client/server + boost::asio::ip::udp::endpoint _udp_endpoint; + boost::asio::ip::udp::endpoint _udp_endpoint_other; + boost::shared_ptr _udp_socket; + + void handle_receive(const boost::system::error_code& error, std::size_t ){ + } + + void start_tcp_accept(){ + tcp_connection::pointer new_connection = + tcp_connection::create(_acceptor_tcp->get_io_service()); + + _acceptor_tcp->async_accept(new_connection->socket(), + boost::bind(&gr_socket_pdu::handle_tcp_accept, this, new_connection, + boost::asio::placeholders::error)); + } + + void handle_tcp_accept(tcp_connection::pointer new_connection, const boost::system::error_code& error){ + if (!error) + { + new_connection->start(this); + d_tcp_connections.push_back(new_connection); + start_tcp_accept(); + } else { + std::cout << error << std::endl; + } + } + + void run_io_service(){ + _io_service.run(); + } + + void handle_udp_read(const boost::system::error_code& error/*error*/, size_t bytes_transferred){ + if(!error){ + pmt::pmt_t vector = pmt::pmt_init_u8vector(bytes_transferred, (const uint8_t*)&rxbuf[0]); + pmt::pmt_t pdu = pmt::pmt_cons( pmt::PMT_NIL, vector); + + message_port_pub( pmt::mp("pdus"), pdu ); + + _udp_socket->async_receive_from( boost::asio::buffer(rxbuf), _udp_endpoint_other, + boost::bind(&gr_socket_pdu::handle_udp_read, this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + } else { + throw boost::system::system_error(error); +// std::cout << "error occurred\n"; + } + } + void handle_tcp_read(const boost::system::error_code& error/*error*/, size_t bytes_transferred){ + if(!error) + { + pmt::pmt_t vector = pmt::pmt_init_u8vector(bytes_transferred, (const uint8_t*)&rxbuf[0]); + pmt::pmt_t pdu = pmt::pmt_cons( pmt::PMT_NIL, vector); + + message_port_pub( pmt::mp("pdus"), pdu ); + + _tcp_socket->async_read_some( + boost::asio::buffer(rxbuf), + boost::bind(&gr_socket_pdu::handle_tcp_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); + + } else { + //std::cout << "error occurred\n"; + throw boost::system::system_error(error); + } + } + + protected: + gr_socket_pdu (std::string type, std::string addr, std::string port, int MTU=10000); + public: + ~gr_socket_pdu () {} +}; + +#endif /* INCLUDED_GR_TUNTAP_PDU_H */ diff --git a/gnuradio-core/src/lib/io/gr_socket_pdu.i b/gnuradio-core/src/lib/io/gr_socket_pdu.i new file mode 100644 index 000000000..3e20b63e2 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_socket_pdu.i @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 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(gr,socket_pdu); + +%ignore tcp_connection; + +%{ +#include +%} + +%include "gr_stream_pdu_base.h" +%include "gr_socket_pdu.h" + diff --git a/gnuradio-core/src/lib/io/gr_stream_pdu_base.cc b/gnuradio-core/src/lib/io/gr_stream_pdu_base.cc new file mode 100644 index 000000000..cff7296cb --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_stream_pdu_base.cc @@ -0,0 +1,117 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const long timeout_us = 100*1000; //100ms + +gr_stream_pdu_base::gr_stream_pdu_base (int MTU) + : gr_sync_block("stream_pdu_base", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(0, 0, 0)), + d_finished(false), d_started(false), d_fd(-1) +{ + // reserve space for rx buffer + d_rxbuf.resize(MTU,0); +} + +gr_stream_pdu_base::~gr_stream_pdu_base() +{ + stop_rxthread(); +} + +void gr_stream_pdu_base::stop_rxthread(){ + d_finished = true; + if(d_started){ + d_thread->interrupt(); + d_thread->join(); + } + } + +void gr_stream_pdu_base::start_rxthread(pmt::pmt_t _rxport){ + rxport = _rxport; + d_thread = boost::shared_ptr(new boost::thread(boost::bind(&gr_stream_pdu_base::run, this))); + d_started = true; + } + +void gr_stream_pdu_base::run(){ + while(!d_finished) { + if(not wait_ready()){ continue; } + const int result = read( d_fd, &d_rxbuf[0], d_rxbuf.size() ); + if(result <= 0){ throw std::runtime_error("gr_stream_pdu_base, bad socket read!"); } + pmt::pmt_t vector = pmt::pmt_init_u8vector(result, &d_rxbuf[0]); + pmt::pmt_t pdu = pmt::pmt_cons( pmt::PMT_NIL, vector); + message_port_pub(rxport, pdu); + } +} + +void gr_stream_pdu_base::send(pmt::pmt_t msg){ + pmt::pmt_t vector = pmt::pmt_cdr(msg); + size_t offset(0); + size_t itemsize(gr_pdu_itemsize(type_from_pmt(vector))); + int len( pmt::pmt_length(vector)*itemsize ); + + const int rv = write(d_fd, pmt::pmt_uniform_vector_elements(vector, offset), len); + if(rv != len){ + std::cerr << boost::format("WARNING: gr_stream_pdu_base::send(pdu) write failed! (d_fd=%d, len=%d, rv=%d)") + % d_fd % len % rv << std::endl; + } +} + +int +gr_stream_pdu_base::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + throw std::runtime_error("should not be called.\n"); + return 0; +} + +bool gr_stream_pdu_base::wait_ready(){ + //setup timeval for timeout + timeval tv; + tv.tv_sec = 0; + tv.tv_usec = timeout_us; + + //setup rset for timeout + fd_set rset; + FD_ZERO(&rset); + FD_SET(d_fd, &rset); + + //call select with timeout on receive socket + return ::select(d_fd+1, &rset, NULL, NULL, &tv) > 0; +} diff --git a/gnuradio-core/src/lib/io/gr_stream_pdu_base.h b/gnuradio-core/src/lib/io/gr_stream_pdu_base.h new file mode 100644 index 000000000..dc5dc5c2e --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_stream_pdu_base.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_STREAM_PDU_BASE_H +#define INCLUDED_GR_STREAM_PDU_BASE_H + +#include +#include +#include +#include + +#include + + +/*! + * \brief Gather received items into messages and insert into msgq + * \ingroup sink_blk + */ +class GR_CORE_API gr_stream_pdu_base : public gr_sync_block +{ + public: + boost::shared_ptr d_thread; + bool d_finished; + bool d_started; + std::vector d_rxbuf; + void run(); + int d_fd; + gr_stream_pdu_base (int MTU=10000); + ~gr_stream_pdu_base (); + void send(pmt::pmt_t msg); + bool wait_ready(); + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + void start_rxthread(pmt::pmt_t _rxport); + void stop_rxthread(); + private: + pmt::pmt_t rxport; +}; + +typedef boost::shared_ptr gr_stream_pdu_base_sptr; + +#endif /* INCLUDED_GR_TUNTAP_PDU_H */ diff --git a/gnuradio-core/src/lib/io/gr_tuntap_pdu.cc b/gnuradio-core/src/lib/io/gr_tuntap_pdu.cc new file mode 100644 index 000000000..44de1a5f7 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_tuntap_pdu.cc @@ -0,0 +1,143 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if (defined(linux) || defined(__linux) || defined(__linux__)) + +#include +#include +#include +#include + +#include +#include + + +// public constructor that returns a shared_ptr + +gr_tuntap_pdu_sptr +gr_make_tuntap_pdu (std::string dev, int MTU) +{ + return gnuradio::get_initial_sptr(new gr_tuntap_pdu(dev, MTU)); +} + +gr_tuntap_pdu::gr_tuntap_pdu (std::string dev, int MTU) + : gr_stream_pdu_base(MTU) +{ + + // make the tuntap + char dev_cstr[1024]; + memset(dev_cstr, 0x00, 1024); + strncpy(dev_cstr, dev.c_str(), std::min(sizeof(dev_cstr), dev.size())); + d_fd = tun_alloc(dev_cstr); + if(d_fd <= 0){ + throw std::runtime_error("TunTap make: tun_alloc failed (are you running as root?)"); + } + + std::cout << boost::format( + "Allocated virtual ethernet interface: %s\n" + "You must now use ifconfig to set its IP address. E.g.,\n" + " $ sudo ifconfig %s 192.168.200.1\n" + "Be sure to use a different address in the same subnet for each machine.\n" + ) % dev % dev << std::endl; + + // set up output message port + message_port_register_out(pmt::mp("pdus")); + start_rxthread(pmt::mp("pdus")); + + // set up input message port + message_port_register_in(pmt::mp("pdus")); + set_msg_handler(pmt::mp("pdus"), boost::bind(&gr_tuntap_pdu::send, this, _1)); +} + + +int gr_tuntap_pdu::tun_alloc(char *dev, int flags) { + struct ifreq ifr; + int fd, err; + const char *clonedev = "/dev/net/tun"; + + /* Arguments taken by the function: + * + * char *dev: the name of an interface (or '\0'). MUST have enough + * space to hold the interface name if '\0' is passed + * int flags: interface flags (eg, IFF_TUN etc.) + */ + + /* open the clone device */ + if( (fd = open(clonedev, O_RDWR)) < 0 ) { + return fd; + } + + /* preparation of the struct ifr, of type "struct ifreq" */ + memset(&ifr, 0, sizeof(ifr)); + + ifr.ifr_flags = flags; /* IFF_TUN or IFF_TAP, plus maybe IFF_NO_PI */ + + if (*dev) { + /* if a device name was specified, put it in the structure; otherwise, + * the kernel will try to allocate the "next" device of the + * specified type */ + strncpy(ifr.ifr_name, dev, IFNAMSIZ); + } + + /* try to create the device */ + if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) { + close(fd); + return err; + } + + /* if the operation was successful, write back the name of the + * interface to the variable "dev", so the caller can know + * it. Note that the caller MUST reserve space in *dev (see calling + * code below) */ + strcpy(dev, ifr.ifr_name); + + /* this is the special file descriptor that the caller will use to talk + * with the virtual interface */ + return fd; +} + +#else //if not linux + +boost::shared_ptr gr_make_tuntap_pdu (std::string dev, int MTU){ + boost::shared_ptr rv; + throw std::runtime_error("tuntap only implemented on linux"); + return rv; +} + +#endif diff --git a/gnuradio-core/src/lib/io/gr_tuntap_pdu.h b/gnuradio-core/src/lib/io/gr_tuntap_pdu.h new file mode 100644 index 000000000..0e8071c30 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_tuntap_pdu.h @@ -0,0 +1,66 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_TUNTAP_PDU_H +#define INCLUDED_GR_TUNTAP_PDU_H + +#include +#include +#include +#include +#include + +#if (defined(linux) || defined(__linux) || defined(__linux__)) + +#include + +class gr_tuntap_pdu; +typedef boost::shared_ptr gr_tuntap_pdu_sptr; + +GR_CORE_API gr_tuntap_pdu_sptr gr_make_tuntap_pdu (std::string dev, int MTU=10000); + +/*! + * \brief Gather received items into messages and insert into msgq + * \ingroup sink_blk + */ +class GR_CORE_API gr_tuntap_pdu : public gr_stream_pdu_base +{ + private: + friend GR_CORE_API gr_tuntap_pdu_sptr + gr_make_tuntap_pdu(std::string dev, int MTU); + int tun_alloc(char* dev, int flags = IFF_TAP | IFF_NO_PI); + std::string d_dev; + protected: + gr_tuntap_pdu (std::string dev, int MTU=10000); + + public: + ~gr_tuntap_pdu () {} + +}; + +#else // if not linux + +GR_CORE_API boost::shared_ptr gr_make_tuntap_pdu (std::string dev, int MTU=0); + +#endif + +#endif /* INCLUDED_GR_TUNTAP_PDU_H */ diff --git a/gnuradio-core/src/lib/io/gr_tuntap_pdu.i b/gnuradio-core/src/lib/io/gr_tuntap_pdu.i new file mode 100644 index 000000000..589bbc385 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_tuntap_pdu.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 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(gr,tuntap_pdu); + +%{ +#include +%} + +%include "gr_tuntap_pdu.h" + diff --git a/gnuradio-core/src/lib/io/io.i b/gnuradio-core/src/lib/io/io.i index 871ce1356..e2de4eb97 100644 --- a/gnuradio-core/src/lib/io/io.i +++ b/gnuradio-core/src/lib/io/io.i @@ -49,6 +49,8 @@ #include #include #include +#include +#include %} %include "gr_file_sink_base.i" @@ -75,4 +77,7 @@ %include "gr_tagged_stream_to_pdu.i" %include "gr_message_debug.i" %include "gr_pdu.i" +%include "gr_tuntap_pdu.i" +%include "gr_socket_pdu.i" + diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.cc b/gnuradio-core/src/lib/runtime/gr_basic_block.cc index 0f7875a12..6ff57a1d6 100644 --- a/gnuradio-core/src/lib/runtime/gr_basic_block.cc +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.cc @@ -38,7 +38,7 @@ static long s_ncurrently_allocated = 0; long gr_basic_block_ncurrently_allocated() { - return s_ncurrently_allocated; + return s_ncurrently_allocated; } gr_basic_block::gr_basic_block(const std::string &name, @@ -53,25 +53,25 @@ gr_basic_block::gr_basic_block(const std::string &name, d_color(WHITE), message_subscribers(pmt::pmt_make_dict()) { - s_ncurrently_allocated++; + s_ncurrently_allocated++; } gr_basic_block::~gr_basic_block() { - s_ncurrently_allocated--; - global_block_registry.block_unregister(this); + s_ncurrently_allocated--; + global_block_registry.block_unregister(this); } gr_basic_block_sptr gr_basic_block::to_basic_block() { - return shared_from_this(); + return shared_from_this(); } void gr_basic_block::set_block_alias(std::string name) { - global_block_registry.register_symbolic_name(this, name); + global_block_registry.register_symbolic_name(this, name); } // ** Message passing interface ** @@ -147,28 +147,29 @@ void gr_basic_block::message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg) } // - subscribe to a message port -void gr_basic_block::message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target) -{ - if(!pmt::pmt_dict_has_key(message_subscribers, port_id)) { +void +gr_basic_block::message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target){ + if(!pmt::pmt_dict_has_key(message_subscribers, port_id)){ std::stringstream ss; - ss << "Port does not exist: \"" << pmt::pmt_write_string(port_id) - << "\" on block: " << pmt::pmt_write_string(target) << std::endl; + ss << "Port does not exist: \"" << pmt::pmt_write_string(port_id) << "\" on block: " << pmt::pmt_write_string(target) << std::endl; throw std::runtime_error(ss.str()); } - pmt::pmt_t currlist = pmt::pmt_dict_ref(message_subscribers,port_id,pmt::PMT_NIL); - message_subscribers = pmt::pmt_dict_add(message_subscribers,port_id,pmt::pmt_list_add(currlist,target)); + + // ignore re-adds of the same target + if(!pmt::pmt_list_has(currlist, target)) + message_subscribers = pmt::pmt_dict_add(message_subscribers,port_id,pmt::pmt_list_add(currlist,target)); } -void gr_basic_block::message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target) -{ - if(!pmt::pmt_dict_has_key(message_subscribers, port_id)) { +void +gr_basic_block::message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target){ + if(!pmt::pmt_dict_has_key(message_subscribers, port_id)){ std::stringstream ss; - ss << "Port does not exist: \"" << pmt::pmt_write_string(port_id) - << "\" on block: " << pmt::pmt_write_string(target) << std::endl; + ss << "Port does not exist: \"" << pmt::pmt_write_string(port_id) << "\" on block: " << pmt::pmt_write_string(target) << std::endl; throw std::runtime_error(ss.str()); } - + + // ignore unsubs of unknown targets pmt::pmt_t currlist = pmt::pmt_dict_ref(message_subscribers,port_id,pmt::PMT_NIL); message_subscribers = pmt::pmt_dict_add(message_subscribers,port_id,pmt::pmt_list_rm(currlist,target)); } @@ -224,5 +225,3 @@ gr_basic_block::delete_head_blocking(pmt::pmt_t which_port) msg_queue[which_port].pop_front(); return m; } - - diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.h b/gnuradio-core/src/lib/runtime/gr_basic_block.h index 00e9c2192..f3b7b835b 100644 --- a/gnuradio-core/src/lib/runtime/gr_basic_block.h +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.h @@ -36,6 +36,7 @@ #include #include #include +#include /*! * \brief The abstract base class for all signal processing blocks. @@ -50,202 +51,215 @@ class GR_CORE_API gr_basic_block : public gr_msg_accepter, public boost::enable_shared_from_this { - typedef boost::function msg_handler_t; - -private: - /* - * This function is called by the runtime system to dispatch messages. - * - * The thread-safety guarantees mentioned in set_msg_handler are implemented - * by the callers of this method. - */ - void dispatch_msg(pmt::pmt_t which_port, pmt::pmt_t msg) - { - // AA Update this - if (d_msg_handlers.find(which_port) != d_msg_handlers.end()) // Is there a handler? - d_msg_handlers[which_port](msg); // Yes, invoke it. - }; - - //msg_handler_t d_msg_handler; - typedef std::map d_msg_handlers_t; - d_msg_handlers_t d_msg_handlers; - - typedef std::deque msg_queue_t; - typedef std::map msg_queue_map_t; - typedef std::map::iterator msg_queue_map_itr; - msg_queue_map_t msg_queue; -// boost::condition_variable msg_queue_ready; - std::map, pmt::pmt_comperator> msg_queue_ready; - - gruel::mutex mutex; //< protects all vars - - -protected: - friend class gr_flowgraph; - friend class gr_flat_flowgraph; // TODO: will be redundant - friend class gr_tpb_thread_body; - - enum vcolor { WHITE, GREY, BLACK }; - - std::string d_name; - gr_io_signature_sptr d_input_signature; - gr_io_signature_sptr d_output_signature; - long d_unique_id; - long d_symbolic_id; - std::string d_symbol_name; - std::string d_symbol_alias; - vcolor d_color; - - gr_basic_block(void){} //allows pure virtual interface sub-classes - - //! Protected constructor prevents instantiation by non-derived classes - gr_basic_block(const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature); - - //! may only be called during constructor - void set_input_signature(gr_io_signature_sptr iosig) { - d_input_signature = iosig; + typedef boost::function msg_handler_t; + + private: + /* + * This function is called by the runtime system to dispatch messages. + * + * The thread-safety guarantees mentioned in set_msg_handler are implemented + * by the callers of this method. + */ + void dispatch_msg(pmt::pmt_t which_port, pmt::pmt_t msg) + { + // AA Update this + if (d_msg_handlers.find(which_port) != d_msg_handlers.end()) // Is there a handler? + d_msg_handlers[which_port](msg); // Yes, invoke it. + }; + + //msg_handler_t d_msg_handler; + typedef std::map d_msg_handlers_t; + d_msg_handlers_t d_msg_handlers; + + typedef std::deque msg_queue_t; + typedef std::map msg_queue_map_t; + typedef std::map::iterator msg_queue_map_itr; + std::map, pmt::pmt_comperator> msg_queue_ready; + + gruel::mutex mutex; //< protects all vars + + protected: + friend class gr_flowgraph; + friend class gr_flat_flowgraph; // TODO: will be redundant + friend class gr_tpb_thread_body; + + enum vcolor { WHITE, GREY, BLACK }; + + std::string d_name; + gr_io_signature_sptr d_input_signature; + gr_io_signature_sptr d_output_signature; + long d_unique_id; + long d_symbolic_id; + std::string d_symbol_name; + std::string d_symbol_alias; + vcolor d_color; + msg_queue_map_t msg_queue; + + gr_basic_block(void){} //allows pure virtual interface sub-classes + + //! Protected constructor prevents instantiation by non-derived classes + gr_basic_block(const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); + + //! may only be called during constructor + void set_input_signature(gr_io_signature_sptr iosig) { + d_input_signature = iosig; + } + + //! may only be called during constructor + void set_output_signature(gr_io_signature_sptr iosig) { + d_output_signature = iosig; + } + + /*! + * \brief Allow the flowgraph to set for sorting and partitioning + */ + void set_color(vcolor color) { d_color = color; } + vcolor color() const { return d_color; } + + // Message passing interface + pmt::pmt_t message_subscribers; + + public: + virtual ~gr_basic_block(); + long unique_id() const { return d_unique_id; } + long symbolic_id() const { return d_symbolic_id; } + std::string name() const { return d_name; } + std::string symbol_name() const { return d_symbol_name; } + gr_io_signature_sptr input_signature() const { return d_input_signature; } + gr_io_signature_sptr output_signature() const { return d_output_signature; } + gr_basic_block_sptr to_basic_block(); // Needed for Python type coercion + bool alias_set() { return !d_symbol_alias.empty(); } + std::string alias(){ return alias_set()?d_symbol_alias:symbol_name(); } + pmt::pmt_t alias_pmt(){ return pmt::pmt_intern(alias()); } + void set_block_alias(std::string name); + + // ** Message passing interface ** + void message_port_register_in(pmt::pmt_t port_id); + void message_port_register_out(pmt::pmt_t port_id); + void message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg); + void message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target); + void message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target); + + virtual bool message_port_is_hier(pmt::pmt_t port_id) { std::cout << "is_hier\n"; return false; } + virtual bool message_port_is_hier_in(pmt::pmt_t port_id) { std::cout << "is_hier_in\n"; return false; } + virtual bool message_port_is_hier_out(pmt::pmt_t port_id) { std::cout << "is_hier_out\n"; return false; } + + /*! + * \brief Get input message port names. + * + * Returns the available input message ports for a block. The + * return object is a PMT vector that is filled with PMT symbols. + */ + pmt::pmt_t message_ports_in(); + + /*! + * \brief Get output message port names. + * + * Returns the available output message ports for a block. The + * return object is a PMT vector that is filled with PMT symbols. + */ + pmt::pmt_t message_ports_out(); + + /*! + * Accept msg, place in queue, arrange for thread to be awakened if it's not already. + */ + void _post(pmt::pmt_t which_port, pmt::pmt_t msg); + + //! is the queue empty? + //bool empty_p(const pmt::pmt_t &which_port) const { return msg_queue[which_port].empty(); } + bool empty_p(pmt::pmt_t which_port) { + if(msg_queue.find(which_port) == msg_queue.end()) + throw std::runtime_error("port does not exist!"); + return msg_queue[which_port].empty(); + } + bool empty_p() { + bool rv = true; + BOOST_FOREACH(msg_queue_map_t::value_type &i, msg_queue){ rv &= msg_queue[i.first].empty(); } + return rv; + } + + //| Acquires and release the mutex + void insert_tail( pmt::pmt_t which_port, pmt::pmt_t msg); + /*! + * \returns returns pmt at head of queue or pmt_t() if empty. + */ + pmt::pmt_t delete_head_nowait( pmt::pmt_t which_port); + + /*! + * \returns returns pmt at head of queue or pmt_t() if empty. + */ + pmt::pmt_t delete_head_blocking( pmt::pmt_t which_port); + + msg_queue_t::iterator get_iterator(pmt::pmt_t which_port){ + return msg_queue[which_port].begin(); + } + + void erase_msg(pmt::pmt_t which_port, msg_queue_t::iterator it){ + msg_queue[which_port].erase(it); + } + + virtual bool has_msg_port(pmt::pmt_t which_port){ + if(msg_queue.find(which_port) != msg_queue.end()){ + return true; } - - //! may only be called during constructor - void set_output_signature(gr_io_signature_sptr iosig) { - d_output_signature = iosig; - } - - /*! - * \brief Allow the flowgraph to set for sorting and partitioning - */ - void set_color(vcolor color) { d_color = color; } - vcolor color() const { return d_color; } - - // Message passing interface - pmt::pmt_t message_subscribers; - -public: - virtual ~gr_basic_block(); - long unique_id() const { return d_unique_id; } - long symbolic_id() const { return d_symbolic_id; } - std::string name() const { return d_name; } - std::string symbol_name() const { return d_symbol_name; } - gr_io_signature_sptr input_signature() const { return d_input_signature; } - gr_io_signature_sptr output_signature() const { return d_output_signature; } - gr_basic_block_sptr to_basic_block(); // Needed for Python type coercion - bool alias_set() { return !d_symbol_alias.empty(); } - std::string alias(){ return alias_set()?d_symbol_alias:symbol_name(); } - pmt::pmt_t alias_pmt(){ return pmt::pmt_intern(alias()); } - void set_block_alias(std::string name); - - // ** Message passing interface ** - void message_port_register_in(pmt::pmt_t port_id); - void message_port_register_out(pmt::pmt_t port_id); - void message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg); - void message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target); - void message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target); - - /*! - * \brief Get input message port names. - * - * Returns the available input message ports for a block. The - * return object is a PMT vector that is filled with PMT symbols. - */ - pmt::pmt_t message_ports_in(); - - /*! - * \brief Get output message port names. - * - * Returns the available output message ports for a block. The - * return object is a PMT vector that is filled with PMT symbols. - */ - pmt::pmt_t message_ports_out(); - - /*! - * Accept msg, place in queue, arrange for thread to be awakened if it's not already. - */ - void _post(pmt::pmt_t which_port, pmt::pmt_t msg); - - //! is the queue empty? - //bool empty_p(const pmt::pmt_t &which_port) const { return msg_queue[which_port].empty(); } - bool empty_p(pmt::pmt_t which_port) { - if(msg_queue.find(which_port) == msg_queue.end()) - throw std::runtime_error("port does not exist!"); - return msg_queue[which_port].empty(); - } - bool empty_p() { - bool rv = true; - BOOST_FOREACH(msg_queue_map_t::value_type &i, msg_queue){ rv &= msg_queue[i.first].empty(); } - return rv; - } - - //| Acquires and release the mutex - void insert_tail( pmt::pmt_t which_port, pmt::pmt_t msg); - /*! - * \returns returns pmt at head of queue or pmt_t() if empty. - */ - pmt::pmt_t delete_head_nowait( pmt::pmt_t which_port); - - /*! - * \returns returns pmt at head of queue or pmt_t() if empty. - */ - pmt::pmt_t delete_head_blocking( pmt::pmt_t which_port); - - msg_queue_t::iterator get_iterator(pmt::pmt_t which_port){ - return msg_queue[which_port].begin(); - } - void erase_msg(pmt::pmt_t which_port, msg_queue_t::iterator it){ - msg_queue[which_port].erase(it); - } - - - /*! - * \brief Confirm that ninputs and noutputs is an acceptable combination. - * - * \param ninputs number of input streams connected - * \param noutputs number of output streams connected - * - * \returns true if this is a valid configuration for this block. - * - * This function is called by the runtime system whenever the - * topology changes. Most classes do not need to override this. - * This check is in addition to the constraints specified by the input - * and output gr_io_signatures. - */ - virtual bool check_topology(int ninputs, int noutputs) { return true; } - - /*! - * \brief Set the callback that is fired when messages are available. - * - * \p msg_handler can be any kind of function pointer or function object - * that has the signature: - *
-     *    void msg_handler(pmt::pmt msg);
-     * 
- * - * (You may want to use boost::bind to massage your callable into the - * correct form. See gr_nop.{h,cc} for an example that sets up a class - * method as the callback.) - * - * Blocks that desire to handle messages must call this method in their - * constructors to register the handler that will be invoked when messages - * are available. - * - * If the block inherits from gr_block, the runtime system will ensure that - * msg_handler is called in a thread-safe manner, such that work and - * msg_handler will never be called concurrently. This allows msg_handler - * to update state variables without having to worry about thread-safety - * issues with work, general_work or another invocation of msg_handler. - * - * If the block inherits from gr_hier_block2, the runtime system will - * ensure that no reentrant calls are made to msg_handler. - */ - //template void set_msg_handler(T msg_handler){ - // d_msg_handler = msg_handler_t(msg_handler); - //} - template void set_msg_handler(pmt::pmt_t which_port, T msg_handler){ - if(msg_queue.find(which_port) == msg_queue.end()){ - throw std::runtime_error("attempt to set_msg_handler() on bad input message port!"); } - d_msg_handlers[which_port] = msg_handler_t(msg_handler); + if(pmt::pmt_dict_has_key(message_subscribers, which_port)){ + return true; } + return false; + } + + + /*! + * \brief Confirm that ninputs and noutputs is an acceptable combination. + * + * \param ninputs number of input streams connected + * \param noutputs number of output streams connected + * + * \returns true if this is a valid configuration for this block. + * + * This function is called by the runtime system whenever the + * topology changes. Most classes do not need to override this. + * This check is in addition to the constraints specified by the input + * and output gr_io_signatures. + */ + virtual bool check_topology(int ninputs, int noutputs) { return true; } + + /*! + * \brief Set the callback that is fired when messages are available. + * + * \p msg_handler can be any kind of function pointer or function object + * that has the signature: + *
+   *    void msg_handler(pmt::pmt msg);
+   * 
+ * + * (You may want to use boost::bind to massage your callable into the + * correct form. See gr_nop.{h,cc} for an example that sets up a class + * method as the callback.) + * + * Blocks that desire to handle messages must call this method in their + * constructors to register the handler that will be invoked when messages + * are available. + * + * If the block inherits from gr_block, the runtime system will ensure that + * msg_handler is called in a thread-safe manner, such that work and + * msg_handler will never be called concurrently. This allows msg_handler + * to update state variables without having to worry about thread-safety + * issues with work, general_work or another invocation of msg_handler. + * + * If the block inherits from gr_hier_block2, the runtime system will + * ensure that no reentrant calls are made to msg_handler. + */ + //template void set_msg_handler(T msg_handler){ + // d_msg_handler = msg_handler_t(msg_handler); + //} + template void set_msg_handler(pmt::pmt_t which_port, T msg_handler){ + if(msg_queue.find(which_port) == msg_queue.end()){ + throw std::runtime_error("attempt to set_msg_handler() on bad input message port!"); } + d_msg_handlers[which_port] = msg_handler_t(msg_handler); + } }; inline bool operator<(gr_basic_block_sptr lhs, gr_basic_block_sptr rhs) @@ -260,8 +274,8 @@ GR_CORE_API long gr_basic_block_ncurrently_allocated(); inline std::ostream &operator << (std::ostream &os, gr_basic_block_sptr basic_block) { - os << basic_block->name() << "(" << basic_block->unique_id() << ")"; - return os; + os << basic_block->name() << "(" << basic_block->unique_id() << ")"; + return os; } #endif /* INCLUDED_GR_BASIC_BLOCK_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc index e04deb948..c19863f34 100644 --- a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc +++ b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc @@ -31,8 +31,9 @@ #include #include #include +#include -#define GR_FLAT_FLOWGRAPH_DEBUG 0 +#define GR_FLAT_FLOWGRAPH_DEBUG 0 // 32Kbyte buffer size between blocks #define GR_FIXED_BUFFER_SIZE (32*(1L<<10)) @@ -71,6 +72,15 @@ gr_flat_flowgraph::setup_connections() block->set_is_unaligned(false); } + // Connect message ports connetions + for(gr_msg_edge_viter_t i = d_msg_edges.begin(); i != d_msg_edges.end(); i++){ + if(GR_FLAT_FLOWGRAPH_DEBUG) + std::cout << boost::format("flat_fg connecting msg primitives: (%s, %s)->(%s, %s)\n") % + i->src().block() % i->src().port() % + i->dst().block() % i->dst().port(); + i->src().block()->message_port_sub( i->src().port(), pmt::pmt_cons(i->dst().block()->alias_pmt(), i->dst().port()) ); + } + } gr_block_detail_sptr @@ -350,3 +360,25 @@ gr_flat_flowgraph::make_block_vector(gr_basic_block_vector_t &blocks) return result; } + + +void gr_flat_flowgraph::replace_endpoint(const gr_msg_endpoint &e, const gr_msg_endpoint &r, bool is_src){ + size_t n_replr(0); + if(GR_FLAT_FLOWGRAPH_DEBUG) + std::cout << boost::format("gr_flat_flowgraph::replace_endpoint( %s, %s, %d )\n") % e.block()% r.block()% is_src; + for(size_t i=0; ihas_msg_port(e.port())) + throw std::invalid_argument("invalid msg port in connect() or disconnect()"); +} + void gr_flowgraph::check_dst_not_used(const gr_endpoint &dst) { @@ -181,8 +191,10 @@ gr_flowgraph::calc_used_blocks() gr_basic_block_vector_t tmp; // make sure free standing message blocks are included - for (gr_basic_block_vector_t::iterator it=d_msgblocks.begin(); it!=d_msgblocks.end(); it++){ - tmp.push_back(*it); + for (gr_msg_edge_viter_t p = d_msg_edges.begin(); p != d_msg_edges.end(); p++) { +// for now only blocks receiving messages get a thread context - uncomment to allow senders to also obtain one +// tmp.push_back(p->src().block()); + tmp.push_back(p->dst().block()); } // Collect all blocks in the edge list @@ -477,7 +489,27 @@ gr_flowgraph::topological_dfs_visit(gr_basic_block_sptr block, gr_basic_block_ve output.push_back(block); } -void gr_flowgraph::add_msg_block(gr_basic_block_sptr blk){ - d_msgblocks.push_back(blk); +void gr_flowgraph::connect(const gr_msg_endpoint &src, const gr_msg_endpoint &dst){ + check_valid_port(src); + check_valid_port(dst); + for (gr_msg_edge_viter_t p = d_msg_edges.begin(); p != d_msg_edges.end(); p++) { + if(p->src() == src && p->dst() == dst){ + throw std::runtime_error("connect called on already connected edge!"); + } + } + d_msg_edges.push_back(gr_msg_edge(src,dst)); } +void gr_flowgraph::disconnect(const gr_msg_endpoint &src, const gr_msg_endpoint &dst){ + check_valid_port(src); + check_valid_port(dst); + for (gr_msg_edge_viter_t p = d_msg_edges.begin(); p != d_msg_edges.end(); p++) { + if(p->src() == src && p->dst() == dst){ + d_msg_edges.erase(p); + return; + } + } + throw std::runtime_error("disconnect called on non-connected edge!"); +} + + diff --git a/gnuradio-core/src/lib/runtime/gr_flowgraph.h b/gnuradio-core/src/lib/runtime/gr_flowgraph.h index 860cb0ff1..bef70f626 100644 --- a/gnuradio-core/src/lib/runtime/gr_flowgraph.h +++ b/gnuradio-core/src/lib/runtime/gr_flowgraph.h @@ -52,6 +52,31 @@ inline bool gr_endpoint::operator==(const gr_endpoint &other) const d_port == other.d_port); } +class GR_CORE_API gr_msg_endpoint +{ +private: + gr_basic_block_sptr d_basic_block; + pmt::pmt_t d_port; + bool d_is_hier; +public: + gr_msg_endpoint() : d_basic_block(), d_port(pmt::PMT_NIL) { } + gr_msg_endpoint(gr_basic_block_sptr block, pmt::pmt_t port, bool is_hier=false){ d_basic_block = block; d_port = port; d_is_hier = is_hier;} + gr_basic_block_sptr block() const { return d_basic_block; } + pmt::pmt_t port() const { return d_port; } + bool is_hier() const { return d_is_hier; } + void set_hier(bool h) { d_is_hier = h; } + + bool operator==(const gr_msg_endpoint &other) const; + +}; + +inline bool gr_msg_endpoint::operator==(const gr_msg_endpoint &other) const +{ + return (d_basic_block == other.d_basic_block && + pmt::pmt_equal(d_port, other.d_port)); +} + + // Hold vectors of gr_endpoint objects typedef std::vector gr_endpoint_vector_t; typedef std::vector::iterator gr_endpoint_viter_t; @@ -75,11 +100,35 @@ private: gr_endpoint d_dst; }; + // Hold vectors of gr_edge objects typedef std::vector gr_edge_vector_t; typedef std::vector::iterator gr_edge_viter_t; +/*! + *\brief Class representing a msg connection between to graph msg endpoints + * + */ +class GR_CORE_API gr_msg_edge +{ +public: + gr_msg_edge() : d_src(), d_dst() { }; + gr_msg_edge(const gr_msg_endpoint &src, const gr_msg_endpoint &dst) : d_src(src), d_dst(dst) { } + ~gr_msg_edge() {} + + const gr_msg_endpoint &src() const { return d_src; } + const gr_msg_endpoint &dst() const { return d_dst; } + +private: + gr_msg_endpoint d_src; + gr_msg_endpoint d_dst; +}; + +// Hold vectors of gr_edge objects +typedef std::vector gr_msg_edge_vector_t; +typedef std::vector::iterator gr_msg_edge_viter_t; + // Create a shared pointer to a heap allocated flowgraph // (types defined in gr_runtime_types.h) GR_CORE_API gr_flowgraph_sptr gr_make_flowgraph(); @@ -110,7 +159,11 @@ public: void disconnect(gr_basic_block_sptr src_block, int src_port, gr_basic_block_sptr dst_block, int dst_port); - void add_msg_block(gr_basic_block_sptr blk); + // Connect two msg endpoints + void connect(const gr_msg_endpoint &src, const gr_msg_endpoint &dst); + + // Disconnect two msg endpoints + void disconnect(const gr_msg_endpoint &src, const gr_msg_endpoint &dst); // Validate connectivity, raise exception if invalid void validate(); @@ -120,6 +173,9 @@ public: // Return vector of edges const gr_edge_vector_t &edges() const { return d_edges; } + + // Return vector of msg edges + const gr_msg_edge_vector_t &msg_edges() const { return d_msg_edges; } // Return vector of connected blocks gr_basic_block_vector_t calc_used_blocks(); @@ -130,11 +186,11 @@ public: // Return vector of vectors of disjointly connected blocks, topologically // sorted. std::vector partition(); - gr_basic_block_vector_t d_msgblocks; protected: gr_basic_block_vector_t d_blocks; gr_edge_vector_t d_edges; + gr_msg_edge_vector_t d_msg_edges; gr_flowgraph(); std::vector calc_used_ports(gr_basic_block_sptr block, bool check_inputs); @@ -146,6 +202,7 @@ protected: private: void check_valid_port(gr_io_signature_sptr sig, int port); + void check_valid_port(const gr_msg_endpoint &e); void check_dst_not_used(const gr_endpoint &dst); void check_type_match(const gr_endpoint &src, const gr_endpoint &dst); gr_edge_vector_t calc_connections(gr_basic_block_sptr block, bool check_inputs); // false=use outputs diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.cc b/gnuradio-core/src/lib/runtime/gr_hier_block2.cc index a19bfe195..8c2794c63 100644 --- a/gnuradio-core/src/lib/runtime/gr_hier_block2.cc +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.cc @@ -44,7 +44,9 @@ gr_hier_block2::gr_hier_block2(const std::string &name, gr_io_signature_sptr input_signature, gr_io_signature_sptr output_signature) : gr_basic_block(name, input_signature, output_signature), - d_detail(new gr_hier_block2_detail(this)) + d_detail(new gr_hier_block2_detail(this)), + hier_message_ports_in(pmt::PMT_NIL), + hier_message_ports_out(pmt::PMT_NIL) { // This bit of magic ensures that self() works in the constructors of derived classes. gnuradio::detail::sptr_magic::create_and_stash_initial_sptr(this); @@ -141,6 +143,7 @@ gr_hier_block2::unlock() d_detail->unlock(); } + gr_flat_flowgraph_sptr gr_hier_block2::flatten() const { diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.h b/gnuradio-core/src/lib/runtime/gr_hier_block2.h index e8364a740..f80dd73e4 100644 --- a/gnuradio-core/src/lib/runtime/gr_hier_block2.h +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.h @@ -166,6 +166,39 @@ public: gr_flat_flowgraph_sptr flatten() const; gr_hier_block2_sptr to_hier_block2(); // Needed for Python type coercion + + bool has_msg_port(pmt::pmt_t which_port){ + return message_port_is_hier(which_port) || gr_basic_block::has_msg_port(which_port); + } + + bool message_port_is_hier(pmt::pmt_t port_id){ + return message_port_is_hier_in(port_id) || message_port_is_hier_out(port_id); + } + bool message_port_is_hier_in(pmt::pmt_t port_id){ + return pmt::pmt_list_has(hier_message_ports_in, port_id); + } + bool message_port_is_hier_out(pmt::pmt_t port_id){ + return pmt::pmt_list_has(hier_message_ports_out, port_id); + } + + pmt::pmt_t hier_message_ports_in; + pmt::pmt_t hier_message_ports_out; + + void message_port_register_hier_in(pmt::pmt_t port_id){ + if(pmt::pmt_list_has(hier_message_ports_in, port_id)) + throw std::invalid_argument("hier msg in port by this name already registered"); + if(msg_queue.find(port_id) != msg_queue.end()) + throw std::invalid_argument("block already has a primitive input port by this name"); + hier_message_ports_in = pmt::pmt_list_add(hier_message_ports_in, port_id); + } + void message_port_register_hier_out(pmt::pmt_t port_id){ + if(pmt::pmt_list_has(hier_message_ports_out, port_id)) + throw std::invalid_argument("hier msg out port by this name already registered"); + if(pmt::pmt_dict_has_key(message_subscribers, port_id)) + throw std::invalid_argument("block already has a primitive output port by this name"); + hier_message_ports_out = pmt::pmt_list_add(hier_message_ports_out, port_id); + } + }; inline gr_hier_block2_sptr cast_to_hier_block2_sptr(gr_basic_block_sptr block) { diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.i b/gnuradio-core/src/lib/runtime/gr_hier_block2.i index 7c0e62f28..a857394ca 100644 --- a/gnuradio-core/src/lib/runtime/gr_hier_block2.i +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.i @@ -40,6 +40,8 @@ gr_hier_block2_sptr gr_make_hier_block2(const std::string name, %rename(primitive_disconnect) gr_hier_block2::disconnect; %rename(primitive_msg_connect) gr_hier_block2::msg_connect; %rename(primitive_msg_disconnect) gr_hier_block2::msg_disconnect; +%rename(primitive_message_port_register_hier_in) gr_hier_block2::message_port_register_hier_in; +%rename(primitive_message_port_register_hier_out) gr_hier_block2::message_port_register_hier_out; class gr_hier_block2 : public gr_basic_block { @@ -78,5 +80,9 @@ public: void lock(); void unlock(); + void message_port_register_hier_in(pmt::pmt_t port_id); + void message_port_register_hier_out(pmt::pmt_t port_id); + + gr_hier_block2_sptr to_hier_block2(); // Needed for Python type coercion }; diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc index ff2a5db8c..e70553ddc 100644 --- a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc @@ -27,6 +27,7 @@ #include #include #include +#include #define GR_HIER_BLOCK2_DETAIL_DEBUG 0 @@ -53,6 +54,7 @@ gr_hier_block2_detail::gr_hier_block2_detail(gr_hier_block2 *owner) : d_outputs = gr_endpoint_vector_t(max_outputs); } + gr_hier_block2_detail::~gr_hier_block2_detail() { d_owner = 0; // Don't use delete, we didn't allocate @@ -151,15 +153,39 @@ gr_hier_block2_detail::msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport, std::cout << "connecting message port..." << std::endl; // register the subscription - src->message_port_sub(srcport, pmt::pmt_cons(dst->alias_pmt(), dstport)); +// this is done later... +// src->message_port_sub(srcport, pmt::pmt_cons(dst->alias_pmt(), dstport)); // add block uniquely to list to internal blocks if (std::find(d_blocks.begin(), d_blocks.end(), dst) == d_blocks.end()){ + d_blocks.push_back(src); d_blocks.push_back(dst); } - // make sure we instantiate a thread for this block - d_fg->add_msg_block(dst); + bool hier_out = (d_owner == src.get()) && src->message_port_is_hier_out(srcport);; + bool hier_in = (d_owner == dst.get()) && dst->message_port_is_hier_in(dstport); + + gr_hier_block2_sptr src_block(cast_to_hier_block2_sptr(src)); + gr_hier_block2_sptr dst_block(cast_to_hier_block2_sptr(dst)); + + if (src_block && src.get() != d_owner) { + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "connect: src is hierarchical, setting parent to " << this << std::endl; + src_block->d_detail->d_parent_detail = this; + } + + if (dst_block && dst.get() != d_owner) { + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "connect: dst is hierarchical, setting parent to " << this << std::endl; + dst_block->d_detail->d_parent_detail = this; + } + + // add edge for this message connection + if(GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << boost::format("connect( (%s, %s, %d), (%s, %s, %d) )\n") % + src % srcport % hier_out % + dst % dstport % hier_in; + d_fg->connect( gr_msg_endpoint(src, srcport, hier_out), gr_msg_endpoint(dst, dstport, hier_in)); } void @@ -169,8 +195,13 @@ gr_hier_block2_detail::msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcpor if (GR_HIER_BLOCK2_DETAIL_DEBUG) std::cout << "disconnecting message port..." << std::endl; - // register the subscription + // unregister the subscription - if already subscribed src->message_port_unsub(srcport, pmt::pmt_cons(dst->alias_pmt(), dstport)); + + // remove edge for this message connection + bool hier_out = (d_owner == src.get()) && src->message_port_is_hier_out(srcport);; + bool hier_in = (d_owner == dst.get()) && dst->message_port_is_hier_in(dstport); + d_fg->disconnect( gr_msg_endpoint(src, srcport, hier_out), gr_msg_endpoint(dst, dstport, hier_in)); } void @@ -435,11 +466,16 @@ void gr_hier_block2_detail::flatten_aux(gr_flat_flowgraph_sptr sfg) const { if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << "Flattening " << d_owner->name() << std::endl; + std::cout << " ** Flattening " << d_owner->name() << std::endl; // Add my edges to the flow graph, resolving references to actual endpoints gr_edge_vector_t edges = d_fg->edges(); + gr_msg_edge_vector_t msg_edges = d_fg->msg_edges(); gr_edge_viter_t p; + gr_msg_edge_viter_t q,u; + + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "Flattening stream connections: " << std::endl; for (p = edges.begin(); p != edges.end(); p++) { if (GR_HIER_BLOCK2_DETAIL_DEBUG) @@ -457,7 +493,46 @@ gr_hier_block2_detail::flatten_aux(gr_flat_flowgraph_sptr sfg) const } } } - sfg->d_msgblocks = d_fg->d_msgblocks; + + // loop through flattening hierarchical connections + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "Flattening msg connections: " << std::endl; + + for(q = msg_edges.begin(); q != msg_edges.end(); q++) { + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << boost::format(" flattening edge ( %s, %s, %d) -> ( %s, %s, %d)\n") % q->src().block() % q->src().port() % q->src().is_hier() % q->dst().block() % q->dst().port() % q->dst().is_hier(); + + bool normal_connection = true; + + // resolve existing connections to hier ports + if(q->dst().is_hier()){ + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << boost::format(" resolve hier output (%s, %s)") % q->dst().block() % q->dst().port() << std::endl; + sfg->replace_endpoint( q->dst(), q->src(), true ); + normal_connection = false; + } + + if(q->src().is_hier()){ + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << boost::format(" resolve hier input (%s, %s)") % q->src().block() % q->src().port() << std::endl; + sfg->replace_endpoint( q->src(), q->dst(), false ); + normal_connection = false; + } + + // propogate non hier connections through + if(normal_connection){ + sfg->connect( q->src(), q->dst() ); + } + } + +/* // connect primitive edges in the new fg + for(q = msg_edges.begin(); q != msg_edges.end(); q++) { + if( (!q->src().is_hier()) && (!q->dst().is_hier()) ){ + sfg->connect( q->src(), q->dst() ); + } else { + std::cout << "not connecting hier connection!" << std::endl; + } + }*/ // Construct unique list of blocks used either in edges, inputs, // outputs, or by themselves. I still hate STL. @@ -499,7 +574,7 @@ gr_hier_block2_detail::flatten_aux(gr_flat_flowgraph_sptr sfg) const // Recurse hierarchical children for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { gr_hier_block2_sptr hier_block2(cast_to_hier_block2_sptr(*p)); - if (hier_block2) { + if (hier_block2 && (hier_block2.get() != d_owner)) { if (GR_HIER_BLOCK2_DETAIL_DEBUG) std::cout << "flatten_aux: recursing into hierarchical block " << hier_block2 << std::endl; hier_block2->d_detail->flatten_aux(sfg); @@ -530,3 +605,4 @@ gr_hier_block2_detail::unlock() else d_owner->unlock(); } + diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h index f2d2b3c4e..b38dae301 100644 --- a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h @@ -61,6 +61,7 @@ private: gr_endpoint_vector_t d_outputs; // Single internal endpoint per external output gr_basic_block_vector_t d_blocks; + void connect_input(int my_port, int port, gr_basic_block_sptr block); void connect_output(int my_port, int port, gr_basic_block_sptr block); void disconnect_input(int my_port, int port, gr_basic_block_sptr block); diff --git a/gnuradio-core/src/python/gnuradio/gr/hier_block2.py b/gnuradio-core/src/python/gnuradio/gr/hier_block2.py index 0c45f1691..f5f0c00f5 100644 --- a/gnuradio-core/src/python/gnuradio/gr/hier_block2.py +++ b/gnuradio-core/src/python/gnuradio/gr/hier_block2.py @@ -20,6 +20,7 @@ # from gnuradio_core import hier_block2_swig +from gruel import pmt # # This hack forces a 'has-a' relationship to look like an 'is-a' one. @@ -111,3 +112,15 @@ class hier_block2(object): self._hb.primitive_disconnect(src_block.to_basic_block(), src_port, dst_block.to_basic_block(), dst_port) + def msg_connect(self, src, srcport, dst, dstport): + self.primitive_msg_connect(src.to_basic_block(), srcport, dst.to_basic_block(), dstport); + + def msg_disconnect(self, src, srcport, dst, dstport): + self.primitive_msg_disconnect(src.to_basic_block(), srcport, dst.to_basic_block(), dstport); + + def message_port_register_hier_in(self, portname): + self.primitive_message_port_register_hier_in(pmt.pmt_intern(portname)); + + def message_port_register_hier_out(self, portname): + self.primitive_message_port_register_hier_out(pmt.pmt_intern(portname)); + diff --git a/grc/blocks/block_tree.xml b/grc/blocks/block_tree.xml index 95bd7bb3c..183883959 100644 --- a/grc/blocks/block_tree.xml +++ b/grc/blocks/block_tree.xml @@ -43,6 +43,8 @@ gr_message_strobe gr_pdu_to_tagged_stream gr_tagged_stream_to_pdu + gr_tuntap_pdu + gr_socket_pdu
Operators diff --git a/grc/blocks/gr_message_debug.xml b/grc/blocks/gr_message_debug.xml index 705a7cc5f..4d73fbd9c 100644 --- a/grc/blocks/gr_message_debug.xml +++ b/grc/blocks/gr_message_debug.xml @@ -19,4 +19,9 @@ message 1 + + print_pdu_verbose + message + 1 + diff --git a/grc/blocks/gr_socket_pdu.xml b/grc/blocks/gr_socket_pdu.xml new file mode 100644 index 000000000..a175c3699 --- /dev/null +++ b/grc/blocks/gr_socket_pdu.xml @@ -0,0 +1,62 @@ + + + + Socket PDU + gr_socket_pdu + from gnuradio import gr + gr.socket_pdu($type, $host, $port, $mtu) + + Type + type + TCP_SERVER + enum + + + + + + + Host + host + + string + + + Port + port + 52001 + string + + + MTU + mtu + 10000 + int + + + pdus + message + 1 + + + pdus + message + 1 + + diff --git a/grc/blocks/gr_tuntap_pdu.xml b/grc/blocks/gr_tuntap_pdu.xml new file mode 100644 index 000000000..f169345af --- /dev/null +++ b/grc/blocks/gr_tuntap_pdu.xml @@ -0,0 +1,34 @@ + + + + TunTap PDU + gr_tuntap_pdu + from gnuradio import gr + gr.tuntap_pdu($ifn, $mtu) + + Interface Name + ifn + tun0 + string + + + MTU + mtu + 10000 + int + + + pdus + message + 1 + + + pdus + message + 1 + + diff --git a/grc/blocks/pad_sink.xml b/grc/blocks/pad_sink.xml index f89eaa53c..f0e10a339 100644 --- a/grc/blocks/pad_sink.xml +++ b/grc/blocks/pad_sink.xml @@ -7,7 +7,9 @@ Pad Sink pad_sink - + #if str($type) == "message" +None;self.message_port_register_hier_in($label) +#end if Label label @@ -43,6 +45,11 @@ byte size:gr.sizeof_char + +