summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmake/Modules/GrSwig.cmake41
-rw-r--r--docs/doxygen/other/msg_passing.dox40
-rw-r--r--gnuradio-runtime/swig/gr_types.i20
-rw-r--r--gr-blocks/include/gnuradio/blocks/peak_detector2_fb.h24
-rw-r--r--grc/base/Block.py2
-rw-r--r--grc/base/FlowGraph.py18
6 files changed, 108 insertions, 37 deletions
diff --git a/cmake/Modules/GrSwig.cmake b/cmake/Modules/GrSwig.cmake
index abf4dc4612..ef3a76eb4c 100644
--- a/cmake/Modules/GrSwig.cmake
+++ b/cmake/Modules/GrSwig.cmake
@@ -105,17 +105,36 @@ endfunction(GR_SWIG_MAKE_DOCS)
macro(GR_SWIG_MAKE name)
set(ifiles ${ARGN})
- # Shimming this in here to take care of a SWIG bug with handling
- # vector<size_t> and vector<unsigned int> (on 32-bit machines) and
- # vector<long unsigned int> (on 64-bit machines). Use this to test
- # the size of size_t, then set SIZE_T_32 if it's a 32-bit machine
- # or not if it's 64-bit. The logic in gr_type.i handles the rest.
- INCLUDE(CheckTypeSize)
- CHECK_TYPE_SIZE("size_t" SIZEOF_SIZE_T)
- CHECK_TYPE_SIZE("unsigned int" SIZEOF_UINT)
- if(${SIZEOF_SIZE_T} EQUAL ${SIZEOF_UINT})
- list(APPEND GR_SWIG_FLAGS -DSIZE_T_32)
- endif(${SIZEOF_SIZE_T} EQUAL ${SIZEOF_UINT})
+ # Take care of a SWIG < 3.0 bug with handling std::vector<size_t>,
+ # by mapping to the correct sized type on the runtime system, one
+ # of "unsigned int", "unsigned long", or "unsigned long long".
+ # Compare the sizeof(size_t) with the sizeof the other types, and
+ # pick the first one in the list with the same sizeof. The logic
+ # in gnuradio-runtime/swig/gr_types.i handles the rest. It is
+ # probably not necessary to do this assignment all of the time,
+ # but it's easier to do it this way than to figure out the
+ # conditions when it is necessary -- and doing it this way won't
+ # hurt. This bug seems to have been fixed with SWIG >= 3.0, and
+ # mostly happens when not doing a native build (e.g., on Mac OS X
+ # when using a 64-bit CPU but building for 32-bit).
+
+ if(SWIG_VERSION VERSION_LESS "3.0.0")
+ include(CheckTypeSize)
+ check_type_size("size_t" SIZEOF_SIZE_T)
+ check_type_size("unsigned int" SIZEOF_UINT)
+ check_type_size("unsigned long" SIZEOF_UL)
+ check_type_size("unsigned long long" SIZEOF_ULL)
+
+ if(${SIZEOF_SIZE_T} EQUAL ${SIZEOF_UINT})
+ list(APPEND GR_SWIG_FLAGS -DSIZE_T_UINT)
+ elseif(${SIZEOF_SIZE_T} EQUAL ${SIZEOF_UL})
+ list(APPEND GR_SWIG_FLAGS -DSIZE_T_UL)
+ elseif(${SIZEOF_SIZE_T} EQUAL ${SIZEOF_ULL})
+ list(APPEND GR_SWIG_FLAGS -DSIZE_T_ULL)
+ else()
+ message(FATAL_ERROR "GrSwig: Unable to find replace for std::vector<size_t>; this should never happen!")
+ endif()
+ endif()
#do swig doc generation if specified
if(GR_SWIG_DOC_FILE)
diff --git a/docs/doxygen/other/msg_passing.dox b/docs/doxygen/other/msg_passing.dox
index df116c2ba1..494ca03921 100644
--- a/docs/doxygen/other/msg_passing.dox
+++ b/docs/doxygen/other/msg_passing.dox
@@ -311,4 +311,44 @@ file qa_pdu.py.
There are some examples of using the message passing infrastructure
through GRC in gr-blocks/examples/msg_passing.
+\section msg_passing_commands Using messages as commands
+
+Messages can be used to send commands to blocks. Examples for this include:
+
+- gr::qtgui::freq_sink_c: The scaling of the frequency axis can be changed by messages
+- gr::uhd::usrp_source and gr::uhd::usrp_sink: Many transceiver-related settings can
+ be manipulated through command messages, such as frequency, gain and LO offset
+- gr::digital::header_payload_demux, which receives an acknowledgement from a header parser
+ block on how many payload items there are to process
+
+There is no special PMT type to encode commands, however, it is strongly recommended
+to use one of the following formats:
+
+- pmt::cons(KEY, VALUE): This format is useful for commands that take a single value.
+ Think of KEY and VALUE as the argument name and value, respectively. For the case of
+ the QT GUI Frequency Sink, KEY would be "freq" and VALUE would be the new center frequency
+ in Hz.
+- pmt::dict((KEY1: VALUE1), (KEY2: VALUE2), ...): This is basically the same as the
+ previous format, but you can provide multiple key/value pairs. This is particularly
+ useful when a single command takes multiple arguments which can't be broken into
+ multiple command messages (e.g., the USRP blocks might have both a timestamp and a
+ center frequency in a command message, which are closely associated).
+
+In both cases, all KEYs should be pmt::symbols (i.e. strings). VALUEs can be
+whatever the block requires.
+
+It might be tempting to deviate from this format, e.g. the QT Frequency sink could
+simply take a float value as a command message, and it would still work fine.
+However, there are some very good reasons to stick to this format:
+
+- Interoperability: The more people use the standard format, the more likely it
+ is that blocks from different sources can work together
+- Inspectability: A message debug block will display more useful information about
+ a message if its containing both a value and a key
+- Intuition: This format is pretty versatile and unlikely to create situations
+ where it is not sufficient (especially considering that values are PMTs themselves).
+ As a counterexample, using positional arguments (something like "the first argument
+ is the frequency, the second the gain") is easily forgotten, or changed in one place
+ and not another, etc.
+
*/
diff --git a/gnuradio-runtime/swig/gr_types.i b/gnuradio-runtime/swig/gr_types.i
index 8ae953b904..e329a4ce9f 100644
--- a/gnuradio-runtime/swig/gr_types.i
+++ b/gnuradio-runtime/swig/gr_types.i
@@ -80,15 +80,19 @@ namespace std {
%template(gr_vector_vector_complexf) std::vector< std::vector< std::complex<float> > >;
%template(gr_vector_vector_complexd) std::vector< std::vector< std::complex<double> > >;
-// Fix for Issue #529
-#ifdef SIZE_T_32
- // On 32-bit systems, whenever we see std::vector<size_t>, replace it
- // with vector<unsigned int>
+// Fix for Issue #529: replace std::vector<size_t> with its equivalent
+// in element size, one of "unsigned int", "unsigned long", or
+// "unsigned long long". The replacement depends on the sizeof each
+// type, as determined in GrSwig.cmake GR_SWIG_MAKE. For SWIG >=
+// 3.0.0, none of these will be defined because this issue seems to
+// have been fixed.
+
+#if defined(SIZE_T_UINT)
%apply std::vector<unsigned int> { std::vector<size_t> };
-#else
- // On 64-bit systems, whenever we see std::vector<size_t>, replace it
- // with vector<long unsigned int>
- %apply std::vector<long unsigned int> { std::vector<size_t> };
+#elif defined(SIZE_T_UL)
+ %apply std::vector<unsigned long> { std::vector<size_t> };
+#elif defined(SIZE_T_ULL)
+ %apply std::vector<unsigned long long> { std::vector<size_t> };
#endif
#endif /* SWIG_GR_TYPES_I */
diff --git a/gr-blocks/include/gnuradio/blocks/peak_detector2_fb.h b/gr-blocks/include/gnuradio/blocks/peak_detector2_fb.h
index da2d9fc740..541dd8aa09 100644
--- a/gr-blocks/include/gnuradio/blocks/peak_detector2_fb.h
+++ b/gr-blocks/include/gnuradio/blocks/peak_detector2_fb.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2007,2013 Free Software Foundation, Inc.
+ * Copyright 2007,2013,2015 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -36,7 +36,7 @@ namespace gr {
* \details
* If a peak is detected, this block outputs a 1, or it outputs
* 0's. A separate debug output may be connected, to view the
- * internal EWMA described below.
+ * internal estimated mean described below.
*/
class BLOCKS_API peak_detector2_fb : virtual public sync_block
{
@@ -47,13 +47,21 @@ namespace gr {
/*!
* Build a peak detector block with float in, byte out.
*
- * \param threshold_factor_rise The threshold factor determins
- * when a peak is present. An EWMA average of the signal is
- * calculated and when the value of the signal goes over
- * threshold_factor_rise*average, we call the peak.
+ * \param threshold_factor_rise The threshold factor determines
+ * when a peak is present. An average of the input signal
+ * is calculated (through a single-pole autoregressive
+ * filter) and when the value of the input signal goes
+ * over threshold_factor_rise*average, we assume we are
+ * in the neighborhood of a peak. The block will then
+ * find the position of the maximum within a window of
+ * look_ahead samples starting at the point where the
+ * threshold was crossed upwards.
* \param look_ahead The look-ahead value is used when the
- * threshold is found to locate the peak within this range.
- * \param alpha The gain value of a single-pole moving average filter.
+ * threshold is crossed upwards to locate the peak within
+ * this range.
+ * \param alpha One minus the pole of a single-pole
+ * autoregressive filter that evaluates the average of
+ * the input signal.
*/
static sptr make(float threshold_factor_rise=7,
int look_ahead=1000, float alpha=0.001);
diff --git a/grc/base/Block.py b/grc/base/Block.py
index afe326bbf4..b367e60e69 100644
--- a/grc/base/Block.py
+++ b/grc/base/Block.py
@@ -414,7 +414,7 @@ class Block(Element):
"""
n = odict()
n['key'] = self.get_key()
- n['param'] = map(lambda p: p.export_data(), self.get_params())
+ n['param'] = map(lambda p: p.export_data(), sorted(self.get_params(), key=str))
if 'bus' in map(lambda a: a.get_type(), self.get_sinks()):
n['bus_sink'] = str(1);
if 'bus' in map(lambda a: a.get_type(), self.get_sources()):
diff --git a/grc/base/FlowGraph.py b/grc/base/FlowGraph.py
index fb25b46821..790aed07f6 100644
--- a/grc/base/FlowGraph.py
+++ b/grc/base/FlowGraph.py
@@ -126,13 +126,13 @@ class FlowGraph(Element):
def get_block(self, id): return filter(lambda b: b.get_id() == id, self.get_blocks())[0]
def get_blocks_unordered(self): return filter(lambda e: e.is_block(), self.get_elements())
def get_blocks(self):
- blocks = self.get_blocks_unordered();
- for i in range(len(blocks)):
- if blocks[i].get_key() == 'variable':
- blk = blocks[i];
- blocks.remove(blk);
- blocks.insert(1, blk);
- return blocks;
+ # refactored the slow, ugly version
+ # don't know why we need this here, using it for sorted export_data()
+ return sorted(self.get_blocks_unordered(), key=lambda b: (
+ b.get_key() != 'options', # options to the front
+ not b.get_key().startswith('variable'), # then vars
+ str(b)
+ ))
def get_connections(self): return filter(lambda e: e.is_connection(), self.get_elements())
def get_children(self): return self.get_elements()
def get_elements(self):
@@ -250,8 +250,8 @@ class FlowGraph(Element):
"""
n = odict()
n['timestamp'] = self._timestamp
- n['block'] = [block.export_data() for block in self.get_blocks()]
- n['connection'] = [connection.export_data() for connection in self.get_connections()]
+ n['block'] = [b.export_data() for b in self.get_blocks()] # already sorted
+ n['connection'] = [c.export_data() for c in sorted(self.get_connections(), key=str)]
instructions = odict({
'created': self.get_parent().get_version_short(),
'format': FLOW_GRAPH_FILE_FORMAT_VERSION,