summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorMarc Lichtman <marcll@vt.edu>2018-11-02 00:53:52 -0400
committerMarc L <marcll@vt.edu>2019-06-07 12:45:14 -0400
commit73b074f121b0ab2ac38336916a60891c4d88d2cb (patch)
treede8f1782c897af3c278c224dcfbf96345c5c6f1d /docs
parentb6f15c59e96aa83142c47aeacd64da793dd8ba31 (diff)
docs: moved usage manual to wiki
docs: first snapshot of wiki's usage manual
Diffstat (limited to 'docs')
-rw-r--r--docs/doxygen/other/ofdm.dox152
-rw-r--r--docs/doxygen/other/oot_config.dox87
-rw-r--r--docs/doxygen/other/packet_txrx.dox91
-rw-r--r--docs/doxygen/other/pmt.dox506
-rw-r--r--docs/doxygen/other/python_blocks.dox163
-rw-r--r--docs/doxygen/other/usage.dox45
-rw-r--r--docs/exploring-gnuradio/exploring_gnuradio.dox135
-rw-r--r--docs/usage-manual/(exported from wiki) Block Thread Affinity and Priority.txt (renamed from docs/doxygen/other/thread_affinity.dox)79
-rw-r--r--docs/usage-manual/(exported from wiki) Configuration Files.txt (renamed from docs/doxygen/other/prefs.dox)76
-rw-r--r--docs/usage-manual/(exported from wiki) GNURadioCompanion.txt437
-rw-r--r--docs/usage-manual/(exported from wiki) Handling Flowgraphs.txt (renamed from docs/doxygen/other/operating_fg.dox)254
-rw-r--r--docs/usage-manual/(exported from wiki) Logging.txt (renamed from docs/doxygen/other/logger.dox)103
-rw-r--r--docs/usage-manual/(exported from wiki) Message Passing.txt (renamed from docs/doxygen/other/msg_passing.dox)261
-rw-r--r--docs/usage-manual/(exported from wiki) Metadata Information.txt (renamed from docs/doxygen/other/metadata.dox)201
-rw-r--r--docs/usage-manual/(exported from wiki) Performance Counters.txt (renamed from docs/doxygen/other/perf_counters.dox)87
-rw-r--r--docs/usage-manual/(exported from wiki) Polymorphic Types (PMTs).txt473
-rw-r--r--docs/usage-manual/(exported from wiki) Polyphase Filterbanks.txt (renamed from docs/doxygen/other/pfb_intro.dox)117
-rw-r--r--docs/usage-manual/(exported from wiki) QT GUI.txt282
-rw-r--r--docs/usage-manual/(exported from wiki) Stream Tags.txt (renamed from docs/doxygen/other/stream_tags.dox)147
-rw-r--r--docs/usage-manual/(exported from wiki) Tagged Stream Blocks.txt (renamed from docs/doxygen/other/tagged_stream_blocks.dox)316
-rw-r--r--docs/usage-manual/(exported from wiki) Types of Blocks.txt275
-rw-r--r--docs/usage-manual/(exported from wiki) VOLK Guide.txt (renamed from docs/doxygen/other/volk_guide.dox)101
-rw-r--r--docs/usage-manual/.gitignore1
-rw-r--r--docs/usage-manual/README.md6
-rw-r--r--docs/usage-manual/export-usage-manual.py53
25 files changed, 2368 insertions, 2080 deletions
diff --git a/docs/doxygen/other/ofdm.dox b/docs/doxygen/other/ofdm.dox
deleted file mode 100644
index 77d80a7441..0000000000
--- a/docs/doxygen/other/ofdm.dox
+++ /dev/null
@@ -1,152 +0,0 @@
-# Copyright (C) 2017 Free Software Foundation, Inc.
-#
-# Permission is granted to copy, distribute and/or modify this document
-# under the terms of the GNU Free Documentation License, Version 1.3
-# or any later version published by the Free Software Foundation;
-# with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
-# A copy of the license is included in the section entitled "GNU
-# Free Documentation License".
-
-/*! \page page_ofdm OFDM
-
-\section ofdm_introduction Introduction
-
-GNU Radio provides some blocks to transmit and receive OFDM-modulated signals.
-In the following, we assume the reader is familiar with OFDM and how it works,
-for an introduction to OFDM refer to standard textbooks on digital communication.
-
-The blocks are designed in a very generic fashion. As a developer, this means that
-often, a desired functionality can be achieved by correct parametrization of the
-available blocks, but in some cases, custom blocks have to be included. The design
-of the OFDM components is such that adding own functionality is possible with
-very little friction.
-
-\ref page_packet_data has an example of how to use OFDM in a packet-based
-receiver.
-
-\section ofdm_conventions Conventions and Notations
-
-\subsection ofdm_fftshift FFT Shifting
-
-In all cases where OFDM symbols are passed between blocks, the default behaviour
-is to FFT-Shift these symbols, i.e. that the DC carrier is in the middle (to be
-precise, it is on carrier \f$\lfloor N/2 \rfloor\f$ where N is the FFT length and
-carrier indexing starts at 0).
-
-The reason for this convention is that some blocks require FFT-shifted ordering
-of the symbols to function (such as gr::digital::ofdm_chanest_vcvc), and for
-consistency's sake, this was chosen as a default for all blocks that pass OFDM
-symbols. Also, when viewing OFDM symbols, FFT-shifted symbols are in their
-natural order, i.e. as they appear in the pass band.
-
-\subsection ofdm_indexing Carrier Indexing
-
-Carriers are always index starting at the DC carrier, which has the index 0
-(you usually don't want to occupy this carrier). The carriers right of the
-DC carrier (the ones at higher frequencies) are indexed with 1 through N/2-1
-(N being the FFT length again).
-
-The carriers left of the DC carrier (with lower frequencies) can be indexed
--N/2 through -1 or N/2 through N-1. Carrier indices N-1 and -1 are thus
-equivalent. The advantage of using negative carrier indices is that the
-FFT length can be changed without changing the carrier indexing.
-
-\subsection ofdm_carrieralloc Carrier and Symbol Allocation
-
-Many blocks require knowledge of which carriers are allocated, and whether they
-carry data or pilot symbols. GNU Radio blocks uses three objects for this, typically
-called \p occupied_carriers (for the data symbols), \p pilot_carriers and
-\p pilot_symbols (for the pilot symbols).
-
-Every one of these objects is a vector of vectors. \p occupied_carriers and
-\p pilot_carriers identify the position within a frame where data and pilot
-symbols are stored, respectively.
-
-\p occupied_carriers[0] identifies which carriers are occupied on the first
-OFDM symbol, \p occupied_carriers[1] does the same on the second OFDM symbol etc.
-
-Here's an example:
-\code
- occupied_carriers = ((-2, -1, 1, 3), (-3, -1, 1, 2))
- pilot_carriers = ((-3, 2), (-2, 3))
-\endcode
-Every OFDM symbol carries 4 data symbols. On the first OFDM symbol, they are on carriers -2, -1, 1 and 3.
-Carriers -3 and 2 are not used, so they are where the pilot symbols can be placed.
-On the second OFDM symbol, the occupied carriers are -3, -1, 1 and 2. The pilot
-symbols must thus be placed elsewhere, and are put on carriers -2 and 3.
-
-If there are more symbols in the OFDM frame than the length of \p occupied_carriers
-or \p pilot_carriers, they wrap around (in this example, the third OFDM symbol
-uses the allocation in \p occupied_carriers[0]).
-
-But how are the pilot symbols set? This is a valid parametrization:
-\code
- pilot_symbols = ((-1, 1j), (1, -1j), (-1, 1j), (-1j, 1))
-\endcode
-
-The position of these symbols are thos in \p pilot_carriers. So on the first OFDM
-symbol, carrier -3 will transmit a -1, and carrier 2 will transmit a 1j.
-Note that \p pilot_symbols is longer than \p pilot_carriers in this example--
-this is valid, the symbols in \p pilot_symbols[2] will be mapped according
-to \p pilot_carriers[0].
-
-\section ofdm_detectsync Detection and Synchronisation
-
-Before anything happens, an OFDM frame must be detected, the beginning of OFDM
-symbols must be identified, and frequency offset must be estimated.
-
-\section ofdm_tx Transmitting
-
-\image html ofdm_tx_core.png "Core elements of an OFDM transmitter"
-
-This image shows a very simple example of a transmitter. It is assumed that the
-input is a stream of complex scalars with a length tag, i.e. the transmitter
-will work on one frame at a time.
-
-The first block is the carrier allocator (gr::digital::ofdm_carrier_allocator_cvc).
-This sorts the incoming complex scalars onto OFDM carriers, and also places the
-pilot symbols onto the correct positions.
-There is also the option to pass OFDM symbols which are prepended in front of every
-frame (i.e. preamble symbols). These can be used for detection, synchronisation
-and channel estimation.
-
-The carrier allocator outputs OFDM symbols (i.e. complex vectors of FFT length).
-These must be converted to time domain signals before continuing, which is why
-they are piped into an (I)FFT block. Note that because all the OFDM symbols are
-treated in the shifted form, the IFFT block must be shifting as well.
-
-Finally, the cyclic prefix is added to the OFDM symbols. The gr::digital::ofdm_cyclic_prefixer
-can also perform pulse shaping on the OFDM symbols (raised cosine flanks in the
-time domain).
-
-\section ofdm_rx Receiving
-
-On the receiver side, some more effort is necessary. The following flow graph
-assumes that the input starts at the beginning of an OFDM frame and is prepended
-with a Schmidl & Cox preamble for coarse frequency correction and channel
-estimation. Also assumed is that the fine frequency offset is already corrected
-and that the cyclic prefix has been removed. The latter can be achieved by a
-gr::digital::header_payload_demux, the former can be done using a
-gr::digital::ofdm_sync_sc_cc.
-
-\image html ofdm_rx_core.png "Core elements of an OFDM receiver"
-
-First, an FFT shifts the OFDM symbols into the frequency domain, where the signal
-processing is performed (the OFDM frame is thus in the memory in matrix form).
-It is passed to a block that uses the preambles to perform channel estimation
-and coarse frequency offset. Both of these values are added to the output stream
-as tags; the preambles are then removed from the stream and not propagated.
-
-Note that this block does not correct the OFDM frame. Both the coarse frequency
-offset correction and the equalizing (using the initial channel state estimate)
-are done in the following block, gr::digital::ofdm_frame_equalizer_vcvc.
-The interesting property about this block is that it uses a
-gr::digital::ofdm_equalizer_base derived object to perform the actual equalization.
-
-The last block in the frequency domain is the gr::digital::ofdm_serializer_vcc,
-which is the inverse block to the carrier allocator.
-It plucks the data symbols from the \p occupied_carriers and outputs them as a
-stream of complex scalars. These can then be directly converted to bits, or passed
-to a forward error correction decoder.
-
-*/
diff --git a/docs/doxygen/other/oot_config.dox b/docs/doxygen/other/oot_config.dox
deleted file mode 100644
index d07c7a2808..0000000000
--- a/docs/doxygen/other/oot_config.dox
+++ /dev/null
@@ -1,87 +0,0 @@
-# Copyright (C) 2017 Free Software Foundation, Inc.
-#
-# Permission is granted to copy, distribute and/or modify this document
-# under the terms of the GNU Free Documentation License, Version 1.3
-# or any later version published by the Free Software Foundation;
-# with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
-# A copy of the license is included in the section entitled "GNU
-# Free Documentation License".
-
-/*! \page page_oot_config Out-of-Tree Configuration
-
-New as of 3.6.5.
-
-Using gr_modtool, each package comes with the ability to easily locate
-the gnuradio-runtime library using the 'find_package(GnuradioRuntime)'
-cmake command. This only locates the gnuradio-runtime library and
-include directory, which is enough for most simple projects.
-
-As projects become more complicated and start needing to rely on other
-GNU Radio components like gnuradio-blocks or gnuradio-filter, for
-example, and when they become dependent on certain API compatibility
-versions of GNU Radio, we need something more. And so we have
-introduced the GnuradioConfig.cmake file.
-
-When GNU Radio is installed, it also installs a GNU Radio-specific
-cmake config file that we can use for more advanced compatibility
-issues of our projects. This tool allows us to specific the API
-compatible version and a set of components that are required.
-
-Taking the above example, say we have built against version 3.6.5 with
-features that were introduced in this version and we need the blocks
-and filter components as well as the main core library. We fist set a
-cmake variable GR_REQUIRED_COMPONENTS to the components we need. We
-then use the 'find_package' command and also set a minimum required
-API compatible version. Since we are on the 3.6 API version, the
-minimum required version is "3.6.5". The code in the CMakeLists.txt
-file would look like this:
-
-\code
- set(GR_REQUIRED_COMPONENTS RUNTIME BLOCKS FILTER)
- find_package(Gnuradio 3.6.5)
-\endcode
-
-Note that the capitalization is important on both lines.
-
-If the installed version of GNU Radio is 3.6.4 or some other API
-version like 3.5 or 3.7, the Cmake configuration will fail with the
-version error. Likewise, if libgnuradio-filter was not installed as
-part of GNU Radio, the configuration will also fail.
-
-\section oot_config_path_page Install Path
-
-Cmake has to know where to find either the package config files or the
-GnuradioConfig.cmake script. The package config files are located in
-$prefix/lib/pkgconfig while all of the Cmake scripts from GNU Radio
-are installed into $prefix/lib/cmake/gnuradio.
-
-If the installed GNU Radio $prefix is '/usr' or '/usr/local', then
-everything should work fine. If the GNU Radio install $prefix is
-something else, then Cmake must be told where to find it. This can be
-done in a few ways:
-
-1. If you are installing the out-of-tree module into the same $prefix,
-then you would be setting '-DCMAKE_INSTALL_PREFIX' on the
-configuration command line. This is enough to tell Cmake where to look
-for the configuration files.
-
-2. Cmake will try to find the package config (*.pc) files. If it can,
-these files will instruct Cmake where to look for the rest of the
-configuration options. If this is not set, it can be set as:
-
-\code
- export PKG_CONFIG_PATH=$prefix/lib/pkgconfg:$PKG_CONFIG_PATH
-\endcode
-
-3. Set the CMAKE_PREFIX_PATH environmental variable to $prefix.
-
-\code
- export CMAKE_PREFIX_PATH=$prefix:$CMAKE_PREFIX_PATH
-\endcode
-
-
-With method 1, you will be installing your OOT project into the same
-$prefix as GNU Radio. With methods 2 and 3, you can install your
-component anywhere you like (using -DCMAKE_INSTALL_PREFIX).
-
-*/
diff --git a/docs/doxygen/other/packet_txrx.dox b/docs/doxygen/other/packet_txrx.dox
deleted file mode 100644
index 31417779c0..0000000000
--- a/docs/doxygen/other/packet_txrx.dox
+++ /dev/null
@@ -1,91 +0,0 @@
-# Copyright (C) 2017 Free Software Foundation, Inc.
-#
-# Permission is granted to copy, distribute and/or modify this document
-# under the terms of the GNU Free Documentation License, Version 1.3
-# or any later version published by the Free Software Foundation;
-# with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
-# A copy of the license is included in the section entitled "GNU
-# Free Documentation License".
-
-/*! \page page_packet_data Packet Data Transmission
-
-\section packet_data_introduction Introduction
-
-In many cases, the PHY layer of a digital transceiver uses <em>packets</em>to break
-down the transmission (as opposed to continuously broadcasting data), and GNU Radio
-natively supports this kind of transmission. The basic mechanisms which allow this
-are the \ref page_msg_passing and the \ref page_tagged_stream_blocks.
-
-With the tools provided in GNU Radio, simple digital packet transmission schemes
-are easily implemented, allowing the creation of packet-based communication links
-and even -networks.
-
-\section packet_data_structure Structure of a packet
-
-Typically, a packet consists of the following elements:
-
-- A preamble. This is used for detection, synchronization (in time and frequency) and possibly initial channel state estimation.
-- A header. This is of fixed length and stores information about the packet, such as (most importantly) its length, but potentially other information, such as the packet number, its intended recipient etc.
-- The payload.
-- A checksum, typically a CRC value, to validate the packet contents.
-
-At the transmitter stage, these are modulated and prepared for transmission (a forward error correction code may also be applied). Because the transmitter knows the packet length, is a trivial matter to create the transmit frames using the tagged stream blocks.
-
-The receiver has to perform a multitude of things to obtain the packet again.
-Most importantly, it has to convert an infinite stream (coming from the receiver
-device, e.g. a UHD source block) into a packetized, tagged stream.
-
-\section packet_data_hpdemuxer The Header/Payload Demuxer and header parser
-
-The key element to return back to packetized state is the gr::digital::header_payload_demux.
-At its first input, it receives a continuous stream of sample data, coming from
-the receiver device. It discards all the incoming samples, until the beginning
-of a packet is signalled, either by a stream tag, or a trigger signal on its second input.
-
-Once such a beginning is detected, the demultiplexer copies the preamble and header
-to the first output (it must know the exact length of these elements). The header
-can then be demodulated with any suitable set of GNU Radio blocks.
-
-To turn the information stored in the demodulated header bits into metadata
-which can be understood by GNU Radio, a gr::digital::packet_headerparser_b block
-is used to turn the header data into a message, which is passed back to the
-header/payload demuxer. The latter then knows the length of the payload, and
-passes that out on the second output, along with all the metadata obtained
-in the header demodulation chain.
-
-The knowledge of the header structure (i.e. how to turn a sequence of bits into
-a payload length etc.) is stored in an object of type gr::digital::packet_header_default.
-This must be passed to the header parser block.
-
-\section packet_data_ofdm Packet receiver example: OFDM
-
-\image html example_ofdm_packet_rx.png "Example: OFDM Packet Receiver"
-
-The image above shows an example of a simple OFDM receiver. It has no forward error correction,
-and uses the simplest possible frame structure.
-
-The four elements of the packet receiver are highlighted. The first part is the packet detector
-and synchronizer. The samples piped into the header/payload demuxer are fine frequency corrected,
-and a trigger signal is sent to mark the beginning of the burst.
-
-Next, the header demodulation receiver chain is activated. The FFT shifts OFDM symbols to the
-frequency domain. The coarse frequency offset and initial channel state are estimated from the
-preamble and are added to the stream as tags. The OFDM symbol containing the header is passed
-to an equalizer, which also corrects the coarse frequency offset. A serializer picks the data
-symbols from the OFDM symbol and outputs them as a sequence of scalar complex values, which
-are then demodulated into bits (in this case BPSK is used).
-
-The bits are interpreted by the header parser, which uses a gr::digital::packet_header_ofdm
-object to interpret the bits (the latter is derived form gr::digital::packet_header_default).
-The result from the header parser is then fed back to the demuxer, which now knows the length of
-payload and outputs that as a tagged stream.
-
-The payload demodulation chain is the same as the header demodulation chain, only the
-channel estimator block is unnecessary as the channel state information is still available
-as metadata on the payload tagged stream.
-
-This flow graph, as well as the corresponding transmitter, can be found in
-gr-digital/examples/ofdm/rx_ofdm.grc and gr-digital/examples/ofdm/tx_ofdm.grc
-
-
-*/
diff --git a/docs/doxygen/other/pmt.dox b/docs/doxygen/other/pmt.dox
deleted file mode 100644
index 1bc6cbecd4..0000000000
--- a/docs/doxygen/other/pmt.dox
+++ /dev/null
@@ -1,506 +0,0 @@
-# Copyright (C) 2017 Free Software Foundation, Inc.
-#
-# Permission is granted to copy, distribute and/or modify this document
-# under the terms of the GNU Free Documentation License, Version 1.3
-# or any later version published by the Free Software Foundation;
-# with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
-# A copy of the license is included in the section entitled "GNU
-# Free Documentation License".
-
-/*! \page page_pmt Polymorphic Types
-
-\section pmt_introduction Introduction
-
-Polymorphic Types are opaque data types that are designed as generic
-containers of data that can be safely passed around between blocks and
-threads in GNU Radio. They are heavily used in the stream tags and
-message passing interfaces. The most complete list of PMT function is,
-of course, the source code, specifically the header file pmt.h. This
-manual page summarizes the most important features and points of PMTs.
-
-Let's dive straight into some Python code and see how we can use
-PMTs:
-
-\code
->>> import pmt
->>> P = pmt.from_long(23)
->>> type(P)
-<class 'pmt.pmt_swig.swig_int_ptr'>
->>> print P
-23
->>> P2 = pmt.from_complex(1j)
->>> type(P2)
-<class 'pmt.pmt_swig.swig_int_ptr'>
->>> print P2
-0+1i
->>> pmt.is_complex(P2)
-True
-\endcode
-
-First, the pmt module is imported. We assign two values (P and P2)
-with PMTs using the from_long() and from_complex() calls,
-respectively. As we can see, they are both of the same type! This
-means we can pass these variables to C++ through SWIG, and C++ can
-handle this type accordingly.
-
-The same code as above in C++ would look like this:
-
-\code
-#include <pmt/pmt.h>
-// [...]
-pmt::pmt_t P = pmt::from_long(23);
-std::cout << P << std::endl;
-pmt::pmt_t P2 = pmt::from_complex(gr_complex(0, 1)); // Alternatively: pmt::from_complex(0, 1)
-std::cout << P2 << std::endl;
-std::cout << pmt::is_complex(P2) << std::endl;
-\endcode
-
-Two things stand out in both Python and C++. First, we can simply print
-the contents of a PMT. How is this possible? Well, the PMTs have
-in-built capability to cast their value to a string (this is not
-possible with all types, though). Second, PMTs must obviously know
-their type, so we can query that, e.g. by calling the is_complex()
-method.
-
-When assigning a non-PMT value to a PMT, we can use the from_*
-methods, and use the to_* methods to convert back:
-
-\code
-pmt::pmt_t P_int = pmt::from_long(42);
-int i = pmt::to_long(P_int);
-pmt::pmt_t P_double = pmt::from_double(0.2);
-double d = pmt::to_double(P_double);
-\endcode
-
-String types play a bit of a special role in PMTs, as we will see
-later, and have their own converter:
-
-\code
-pmt::pmt_t P_str = pmt::string_to_symbol("spam");
-pmt::pmt_t P_str2 = pmt::intern("spam");
-std::string str = pmt::symbol_to_string(P_str);
-\endcode
-
-The pmt::intern is another way of saying pmt::string_to_symbol.
-
-In Python, we can make use of the dynamic typing, and there's actually a
-helper function to do these conversions (C++ also has a helper
-function for converting to PMTs called pmt::mp(), but it's less
-powerful, and not quite as useful, because types are always strictly
-known in C++):
-
-\code
-P_int = pmt.to_pmt(42)
-i = pmt.to_python(P_int)
-P_double = pmt.to_pmt(0.2)
-d = pmt.to_double(P_double)
-\endcode
-
-On a side note, there are three useful PMT constants, which can be
-used in both Python and C++ domains. In C++, these can be used as
-such:
-
-\code
-pmt::pmt_t P_true = pmt::PMT_T;
-pmt::pmt_t P_false = pmt::PMT_F;
-pmt::pmt_t P_nil = pmt::PMT_NIL;
-\endcode
-
-In Python:
-
-\code
-P_true = pmt.PMT_T
-P_false = pmt.PMT_F
-P_nil = pmt.PMT_NIL
-\endcode
-
-pmt.PMT_T and pmt.PMT_F are boolean PMT types.
-
-To be able to go back to C++ data types, we need to be able to find
-out the type from a PMT. The family of is_* methods helps us do that:
-
-\code
-double d;
-if (pmt::is_integer(P)) {
- d = (double) pmt::to_long(P);
-} else if (pmt::is_real(P)) {
- d = pmt::to_double(P);
-} else {
- // We really expected an integer or a double here, so we don't know what to do
- throw std::runtime_error("expected an integer!");
-}
-\endcode
-
-It is important to do type checking since we cannot unpack a PMT of
-the wrong data type.
-
-We can compare PMTs without knowing their type by using the
-pmt::equal() function:
-
-\code
-if (pmt::eq(P_int, P_double)) {
- std::cout << "Equal!" << std::endl; // This line will never be reached
-\endcode
-
-The rest of this page provides more depth into how to handle different
-data types with the PMT library.
-
-
-
-\section pmt_datatype PMT Data Type
-
-All PMTs are of the type pmt::pmt_t. This is an opaque container and
-PMT functions must be used to manipulate and even do things like
-compare PMTs. PMTs are also \a immutable (except PMT vectors). We
-never change the data in a PMT; instead, we create a new PMT with the
-new data. The main reason for this is thread safety. We can pass PMTs
-as tags and messages between blocks and each receives its own copy
-that we can read from. However, we can never write to this object, and
-so if multiple blocks have a reference to the same PMT, there is no
-possibility of thread-safety issues of one reading the PMT data while
-another is writing the data. If a block is trying to write new data to
-a PMT, it actually creates a new PMT to put the data into. Thus we
-allow easy access to data in the PMT format without worrying about
-mutex locking and unlocking while manipulating them.
-
-PMTs can represent the following:
-
-- Boolean values of true/false
-- Strings (as symbols)
-- Integers (long and uint64)
-- Floats (as doubles)
-- Complex (as two doubles)
-- Pairs
-- Tuples
-- Vectors (of PMTs)
-- Uniform vectors (of any standard data type)
-- Dictionaries (list of key:value pairs)
-- Any (contains a boost::any pointer to hold anything)
-
-The PMT library also defines a set of functions that operate directly
-on PMTs such as:
-
-- Equal/equivalence between PMTs
-- Length (of a tuple or vector)
-- Map (apply a function to all elements in the PMT)
-- Reverse
-- Get a PMT at a position in a list
-- Serialize and deserialize
-- Printing
-
-The constants in the PMT library are:
-
-- pmt::PMT_T - a PMT True
-- pmt::PMT_F - a PMT False
-- pmt::PMT_NIL - an empty PMT (think Python's 'None')
-
-\section pmt_insert Inserting and Extracting Data
-
-Use pmt.h for a complete guide to the list of functions used to create
-PMTs and get the data from a PMT. When using these functions, remember
-that while PMTs are opaque and designed to hold any data, the data
-underneath is still a C++ typed object, and so the right type of
-set/get function must be used for the data type.
-
-Typically, a PMT object can be made from a scalar item using a call
-like "pmt::from_<type>". Similarly, when getting data out of a
-PMT, we use a call like "pmt::to_<type>". For example:
-
-\code
-double a = 1.2345;
-pmt::pmt_t pmt_a = pmt::from_double(a);
-double b = pmt::to_double(pmt_a);
-
-int c = 12345;
-pmt::pmt_t pmt_c = pmt::from_long(c);
-int d = pmt::to_long(pmt_c);
-\endcode
-
-As a side-note, making a PMT from a complex number is not obvious:
-
-\code
-std::complex<double> a(1.2, 3.4);
-pmt::pmt_t pmt_a = pmt::make_rectangular(a.real(), b.imag());
-std::complex<double> b = pmt::to_complex(pmt_a);
-\endcode
-
-Pairs, dictionaries, and vectors have different constructors and ways
-to manipulate them, and these are explained in their own sections.
-
-
-\section pmt_strings Strings
-
-PMTs have a way of representing short strings. These strings are
-actually stored as interned symbols in a hash table, so in other
-words, only one PMT object for a given string exists. If creating a
-new symbol from a string, if that string already exists in the hash
-table, the constructor will return a reference to the existing PMT.
-
-We create strings with the following functions, where the second
-function, pmt::intern, is simply an alias of the first.
-
-\code
-pmt::pmt_t str0 = pmt::string_to_symbol(std::string("some string"));
-pmt::pmt_t str1 = pmt::intern(std::string("some string"));
-\endcode
-
-The string can be retrieved using the inverse function:
-
-\code
-std::string s = pmt::symbol_to_string(str0);
-\endcode
-
-
-\section pmt_tests Tests and Comparisons
-
-The PMT library comes with a number of functions to test and compare
-PMT objects. In general, for any PMT data type, there is an equivalent
-"pmt::is_<type>". We can use these to test the PMT before trying
-to access the data inside. Expanding our examples above, we have:
-
-\code
-pmt::pmt_t str0 = pmt::string_to_symbol(std::string("some string"));
-if(pmt::is_symbol(str0))
- std::string s = pmt::symbol_to_string(str0);
-
-double a = 1.2345;
-pmt::pmt_t pmt_a = pmt::from_double(a);
-if(pmt::is_double(pmt_a))
- double b = pmt::to_double(pmt_a);
-
-int c = 12345;
-pmt::pmt_t pmt_c = pmt::from_long(c);
-if(pmt::is_long(pmt_a))
- int d = pmt::to_long(pmt_c);
-
-\\ This will fail the test. Otherwise, trying to coerce \b pmt_c as a
-\\ double when internally it is a long will result in an exception.
-if(pmt::is_double(pmt_a))
- double d = pmt::to_double(pmt_c);
-
-\endcode
-
-
-\section pmt_dict Dictionaries
-
-PMT dictionaries are lists of key:value pairs. They have a
-well-defined interface for creating, adding, removing, and accessing
-items in the dictionary. Note that every operation that changes the
-dictionary both takes a PMT dictionary as an argument and returns a
-PMT dictionary. The dictionary used as an input is not changed and the
-returned dictionary is a new PMT with the changes made there.
-
-The following is a list of PMT dictionary functions. Click through to
-get more information on what each does.
-
-- bool pmt::is_dict(const pmt_t &obj)
-- pmt_t pmt::make_dict()
-- pmt_t pmt::dict_add(const pmt_t &dict, const pmt_t &key, const pmt_t &value)
-- pmt_t pmt::dict_delete(const pmt_t &dict, const pmt_t &key)
-- bool pmt::dict_has_key(const pmt_t &dict, const pmt_t &key)
-- pmt_t pmt::dict_ref(const pmt_t &dict, const pmt_t &key, const pmt_t &not_found)
-- pmt_t pmt::dict_items(pmt_t dict)
-- pmt_t pmt::dict_keys(pmt_t dict)
-- pmt_t pmt::dict_values(pmt_t dict)
-
-This example does some basic manipulations of PMT dictionaries in
-Python. Notice that we pass the dictionary \a a and return the results
-to \a a. This still creates a new dictionary and removes the local
-reference to the old dictionary. This just keeps our number of
-variables small.
-
-\code
-import pmt
-
-key0 = pmt.intern("int")
-val0 = pmt.from_long(123)
-val1 = pmt.from_long(234)
-
-key1 = pmt.intern("double")
-val2 = pmt.from_double(5.4321)
-
-# Make an empty dictionary
-a = pmt.make_dict()
-
-# Add a key:value pair to the dictionary
-a = pmt.dict_add(a, key0, val0)
-print a
-
-# Add a new value to the same key;
-# new dict will still have one item with new value
-a = pmt.dict_add(a, key0, val1)
-print a
-
-# Add a new key:value pair
-a = pmt.dict_add(a, key1, val2)
-print a
-
-# Test if we have a key, then delete it
-print pmt.dict_has_key(a, key1)
-a = pmt.dict_delete(a, key1)
-print pmt.dict_has_key(a, key1)
-
-ref = pmt.dict_ref(a, key0, pmt.PMT_NIL)
-print ref
-
-# The following should never print
-if(pmt.dict_has_key(a, key0) and pmt.eq(ref, pmt.PMT_NIL)):
- print "Trouble! We have key0, but it returned PMT_NIL"
-\endcode
-
-\section pmt_vectors Vectors
-
-PMT vectors come in two forms: vectors of PMTs and vectors of uniform
-data. The standard PMT vector is a vector of PMTs, and each PMT can be
-of any internal type. On the other hand, uniform PMTs are of a
-specific data type which come in the form:
-
-- (u)int8
-- (u)int16
-- (u)int32
-- (u)int64
-- float32
-- float64
-- complex 32 (std::complex<float>)
-- complex 64 (std::complex<double>)
-
-That is, the standard sizes of integers, floats, and complex types of
-both signed and unsigned.
-
-Vectors have a well-defined interface that allows us to make, set,
-get, and fill them. We can also get the length of a vector with
-pmt::length.
-
-For standard vectors, these functions look like:
-
-- bool pmt::is_vector(pmt_t x)
-- pmt_t pmt::make_vector(size_t k, pmt_t fill)
-- pmt_t pmt::vector_ref(pmt_t vector, size_t k)
-- void pmt::vector_set(pmt_t vector, size_t k, pmt_t obj)
-- void pmt::vector_fill(pmt_t vector, pmt_t fill)
-
-Uniform vectors have the same types of functions, but they are data
-type-dependent. The following list tries to explain them where you
-substitute the specific data type prefix for \a dtype (prefixes being:
-u8, u16, u32, u64, s8, s16, s32, s64, f32, f64, c32, c64).
-
-- bool pmt::is_(dtype)vector(pmt_t x)
-- pmt_t pmt::make_(dtype)vector(size_t k, (dtype) fill)
-- pmt_t pmt::init_(dtype)vector(size_t k, const (dtype*) data)
-- pmt_t pmt::init_(dtype)vector(size_t k, const std::vector<dtype> data)
-- pmt_t pmt::(dtype)vector_ref(pmt_t vector, size_t k)
-- void pmt::(dtype)vector_set(pmt_t vector, size_t k, (dtype) x)
-- const dtype* pmt::(dtype)vector_elements(pmt_t vector, size_t &len)
-- dtype* pmt::(dtype)vector_writable_elements(pmt_t vector, size_t &len)
-
-\b Note: We break the contract with vectors. The 'set' functions
-actually change the data underneath. It is important to keep track of
-the implications of setting a new value as well as accessing the
-'vector_writable_elements' data. Since these are mostly standard data
-types, sets and gets are atomic, so it is unlikely to cause a great
-deal of harm. But it's only unlikely, not impossible. Best to use
-mutexes whenever manipulating data in a vector.
-
-
-\subsection pmt_blob BLOB
-
-A BLOB is a 'binary large object' type. In PMT's, this is actually
-just a thin wrapper around a u8vector.
-
-\section pmt_pairs Pairs
-
-Pairs are inspired by LISP 'cons' data types, so you will find the
-language here comes from LISP. A pair is just a pair of PMT
-objects. They are manipulated using the following functions:
-
-- bool pmt::is_pair(const pmt_t &obj): Return true if obj is a pair, else false
-- pmt_t pmt::cons(const pmt_t &x, const pmt_t &y): construct new pair
-- pmt_t pmt::car(const pmt_t &pair): get the car of the pair (first object)
-- pmt_t pmt::cdr(const pmt_t &pair): get the cdr of the pair (second object)
-- void pmt::set_car(pmt_t pair, pmt_t value): Stores value in the car field
-- void pmt::set_cdr(pmt_t pair, pmt_t value): Stores value in the cdr field
-
-
-\section pmt_serdes Serializing and Deserializing
-
-It is often important to hide the fact that we are working with PMTs
-to make them easier to transmit, store, write to file, etc. The PMT
-library has methods to serialize data into a string buffer or a
-string and then methods to deserialize the string buffer or string
-back into a PMT. We use this extensively in the metadata files (see
-\ref page_metadata).
-
-- bool pmt::serialize(pmt_t obj, std::streambuf &sink)
-- std::string pmt::serialize_str(pmt_t obj)
-- pmt_t pmt::deserialize(std::streambuf &source)
-- pmt_t pmt::deserialize_str(std::string str)
-
-For example, we will serialize the data above to make it into a string
-ready to be written to a file and then deserialize it back to its
-original PMT.
-
-\code
-import pmt
-
-key0 = pmt.intern("int")
-val0 = pmt.from_long(123)
-
-key1 = pmt.intern("double")
-val1 = pmt.from_double(5.4321)
-
-# Make an empty dictionary
-a = pmt.make_dict()
-
-# Add a key:value pair to the dictionary
-a = pmt.dict_add(a, key0, val0)
-a = pmt.dict_add(a, key1, val1)
-
-print a
-
-ser_str = pmt.serialize_str(a)
-print ser_str
-
-b = pmt.deserialize_str(ser_str)
-print b
-
-\endcode
-
-The line where we 'print ser_str' will print and parts will be
-readable, but the point of serializing is not to make a human-readable
-string. This is only done here as a test.
-
-
-\section pmt_printing Printing
-
-In Python, the __repr__ function of a PMT object is overloaded to call
-'pmt::write_string'. This means that any time we call a formatted
-printing operation on a PMT object, the PMT library will properly
-format the object for display.
-
-In C++, we can use the 'pmt::print(object)' function or print the
-contents is using the overloaded "<<" operator with a stream buffer
-object. In C++, we can inline print the contents of a PMT like:
-
-\code
-pmt::pmt_t a pmt::from_double(1.0);
-std::cout << "The PMT a contains " << a << std::endl;
-\endcode
-
-
-\section pmt_python Conversion between Python Objects and PMTs
-
-Although PMTs can be manipulated in Python using the Python versions
-of the C++ interfaces, there are some additional goodies that make it
-easier to work with PMTs in python. There are functions to automate
-the conversion between PMTs and Python types for booleans, strings,
-integers, longs, floats, complex numbers, dictionaries, lists, tuples
-and combinations thereof.
-
-Two functions capture most of this functionality:
-
-\code
-pmt.to_pmt # Converts a python object to a PMT.
-pmt.to_python # Converts a PMT into a python object.
-\endcode
-
-*/
diff --git a/docs/doxygen/other/python_blocks.dox b/docs/doxygen/other/python_blocks.dox
deleted file mode 100644
index 2381b0cad0..0000000000
--- a/docs/doxygen/other/python_blocks.dox
+++ /dev/null
@@ -1,163 +0,0 @@
-# Copyright (C) 2017 Free Software Foundation, Inc.
-#
-# Permission is granted to copy, distribute and/or modify this document
-# under the terms of the GNU Free Documentation License, Version 1.3
-# or any later version published by the Free Software Foundation;
-# with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
-# A copy of the license is included in the section entitled "GNU
-# Free Documentation License".
-
-/*! \page page_python_blocks Python Blocks
-
-How to create blocks in Python
-
-\section pyblocks_streaming Streaming Data Blocks
-
-We create blocks in Python very much like we would in C++, just with
-more Python. Figure out which type of block you want to create:
-
-\li general block (gr.basic_block)
-\li synchronous block (gr.sync_block)
-\li decimator (gr.sync_decimator)
-\li interpolator (gr.sync_interpolator)
-
-The block class inherits from one of these base classes, and then in
-defining the parent class, we set the I/O signature. However, unlike
-in C++ where we use the gr::io_signature class, here we can just
-create a Python list of the I/O data sizes using numpy data types:
-
-\li numpy.int8
-\li numpy.int16
-\li numpy.int32
-\li numpy.float32
-\li numpy.float64
-
-Like a normal C++ version of the block, we then create and initialize
-any variables in the constructor, define any setters and getters, and
-create the work function. The prototype for the work function is quite
-simple:
-
-\code
-def work(self, input_items, output_items)
-\endcode
-
-The input_items and output_items are lists of lists. The input_items
-contains a vector of input samples for every input stream, and the
-output_items is a vector for each output stream where we can place
-items. Then length of output_items[0] is equivalent to the
-noutput_items concept we are so familiar with from the C++ blocks.
-
-Following is an example Python block that adds two input streams
-together. This block is used in the qa_block_gateway.py test code.
-
-\code
-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])
-\endcode
-
-The block defines two input floating point streams by setting in_sig
-to "[numpy.float32, numpy.float32]" and a single output float stream
-in out_sig of "[numpy.float32]."
-
-The work function then just adds the two input streams together. The
-streams are input_items[0] and input_items[1]. The block still returns
-the concept of noutput_items like we use in C++, only we get it here
-by getting len(output_items[0]). Because this is a sync_block, we also
-know that the size of the input_items for both streams is the same as
-the size of the output_items vector.
-
-
-
-\section pyblocks_tags Using Stream Tags
-
-Python blocks have access to the stream tag system like their C++
-counterparts. The interface is almost identical except they behave
-just a bit more like we would expect in Python.
-
-To add tags to the data stream, we use the add_item_tag function:
-
-\code
-def work(self, input_items, output_items):
- ....
- add_item_tag(which_output, abs_offset,
- key, value, srcid)
- ....
-\endcode
-
-The abs_offset is an integer of the sample that the tag is attached
-to, and key and value are both PMTs to set the key:value pair of the
-tag information, and the srcid is an optional PMT to define the source
-of the block that generate the tag.
-
-We then can get tags using either the get_tags_in_range or
-get_tags_in_window. Again, like their C++ counter parts, the
-get_tags_in_range uses the absolute item offset numbering (using
-nitems_read) while the get_tags_in_window uses relative offsets within
-the current window of items available to the work function. The main
-difference from the C++ function is that instead of having the first
-argument be a vector where the tags are stored, the Python version
-just returns a list of tags. We would use it like this:
-
-\code
-def work(self, input_items, output_items):
- ....
- tags = get_tags_in_window(which_input, rel_start, rel_end)
- ....
-\endcode
-
-
-
-\section pyblocks_msgs Using Message Passing
-
-Again, like their C++ counterparts, Python blocks can use the
-asynchronous message passing interface. We define output message
-handlers using:
-
-\code
-self.message_port_register_out(pmt.intern("<port name>"))
-\endcode
-
-We can then post messages to this using the message_port_pub function:
-
-\code
-self.message_port_pub(pmt.intern("<port name>"), <pmt message>)
-\endcode
-
-We then register input messages and handlers in similar ways:
-
-\code
-self.message_port_register_in(pmt.intern("<port name>"))
-self.set_msg_handler(pmt.intern("<port name>"), <msg handler function>)
-\endcode
-
-Putting this together below is a very simple example:
-
-\code
-class msg_block(gr.basic_block):
- def __init__(self):
- gr.basic_block.__init__(
- self,
- name="msg_block",
- in_sig=None,
- out_sig=None)
-
- self.message_port_register_out(pmt.intern('msg_out'))
- self.message_port_register_in(pmt.intern('msg_in'))
- self.set_msg_handler(pmt.intern('msg_in'), self.handle_msg)
-
- def handle_msg(self, msg):
- self.message_port_pub(pmt.intern('msg_out'),
- pmt.intern('message received!'))
-\endcode
-
-*/
diff --git a/docs/doxygen/other/usage.dox b/docs/doxygen/other/usage.dox
index d0872c0a03..c02b88c3a0 100644
--- a/docs/doxygen/other/usage.dox
+++ b/docs/doxygen/other/usage.dox
@@ -1,4 +1,4 @@
-# Copyright (C) 2017 Free Software Foundation, Inc.
+# Copyright (C) 2018 Free Software Foundation, Inc.
#
# Permission is granted to copy, distribute and/or modify this document
# under the terms of the GNU Free Documentation License, Version 1.3
@@ -9,44 +9,39 @@
/*! \page page_usage Usage Manual
-Note: Once built, check out <a href="https://www.gnuradio.org/" target="_blank">gnuradio.org</a> for
-more tutorials on using the software system and examples.
+Note: The Usage Manual has been moved to the <a href="https://wiki.gnuradio.org" target="_blank">GNU Radio wiki</a>, along with all other documentation that is not specific to a block/class/function/etc.
-<b>Getting Started</b>
+For viewing offline, snapshots of these wiki pages are periodically exported and stored in gnuradio/docs/usage-manual/
+
+Here are links to the various Usage Manual pages (they are also linked on the home page of the wiki):
-\li \subpage build_guide - Installation notes, dependencies etc.
-\li \subpage page_exploring_gnuradio
-\li \subpage page_operating_fg
+<b>Getting Started</b>
+\li <a href="https://wiki.gnuradio.org/index.php/Handling_Flowgraphs" target="_blank">Handling Flowgraphs</a>
+\li <a href="https://wiki.gnuradio.org/index.php/GNURadioCompanion" target="_blank">GNU Radio Companion (GRC)</a>
<b>Metadata and Messages</b>
-\li \subpage page_pmt
-\li \subpage page_metadata
-\li \subpage page_msg_passing
-\li \subpage page_stream_tags
-\li \subpage page_tagged_stream_blocks
+\li <a href="https://wiki.gnuradio.org/index.php/Polymorphic_Types_(PMTs)" target="_blank">Polymorphic Types (PMTs)</a>
+\li <a href="https://wiki.gnuradio.org/index.php/Metadata_Information" target="_blank">Metadata Information</a>
+\li <a href="https://wiki.gnuradio.org/index.php/Message_Passing" target="_blank">Message Passing</a>
+\li <a href="https://wiki.gnuradio.org/index.php/Stream_Tags" target="_blank">Stream Tags</a>
+\li <a href="https://wiki.gnuradio.org/index.php/Tagged_Stream_Blocks" target="_blank">Tagged Stream Blocks</a>
<b>Advanced Development Topics</b>
-\li \subpage page_logger
-\li \subpage page_perf_counters
-\li \subpage page_affinity
-\li \subpage page_prefs
-\li \subpage page_python_blocks
+\li <a href="https://wiki.gnuradio.org/index.php/Logging" target="_blank">Logging</a>
+\li <a href="https://wiki.gnuradio.org/index.php/Performance_Counters" target="_blank">Performance Counters</a>
+\li <a href="https://wiki.gnuradio.org/index.php/Block_Thread_Affinity_and_Priority" target="_blank">Block Thread Affinity and Priority</a>
+\li <a href="https://wiki.gnuradio.org/index.php/Configuration_Files" target="_blank">Configuration Files</a>
+\li <a href="https://wiki.gnuradio.org/index.php/Types_of_Blocks" target="_blank">Types of Blocks</a>
<b>Signal Processing and Digital Communications</b>
-\li \subpage page_pfb
-\li \subpage page_ofdm
-\li \subpage page_packet_data
-
-<b>Out-of-tree Modules</b>
-
-\li \subpage page_oot_config
+\li <a href="https://wiki.gnuradio.org/index.php/Polyphase_Filterbanks" target="_blank">Polyphase Filterbanks</a>
<b>VOLK</b>
-\li \subpage volk_guide - How to incorporate and use VOLK in GNU Radio blocks
+\li <a href="https://wiki.gnuradio.org/index.php/VOLK_Guide" target="_blank">VOLK Guide</a>
*/
diff --git a/docs/exploring-gnuradio/exploring_gnuradio.dox b/docs/exploring-gnuradio/exploring_gnuradio.dox
deleted file mode 100644
index d762db443b..0000000000
--- a/docs/exploring-gnuradio/exploring_gnuradio.dox
+++ /dev/null
@@ -1,135 +0,0 @@
-/*! \page page_exploring_gnuradio Exploring GNU Radio
-
-Let's explore over two examples that are shipped with GNU Radio. We
-start off with a very simple dial tone generating example that is done
-in Python. The second example uses both GNU Radio Companion (GRC) and
-Python for different stages of the example.
-
-In either case, we will be actually working with Python code and the
-modules as they exist in Python. However, in the following discussion,
-we will refer to each block using the full C++ namespace so that we
-can easily link to the block's documentation inside the manual.
-
-The example files discussed in this page are installed with the
-documentation and are located in $prefix/share/doc/gnuradio-$version/.
-
-\section ex_dial_tone Dial Tone Example
-
-This example is found in the dial_tone.py file and constructs a very
-simple GNU Radio application that combines two sine waves to create a
-dial tone. It calls a function to construct the flowgraph which
-handles generating the signal sources.
-
-The build_graph function sets up the sampling rate, which we will use
-to set the rate of the audio sink as well as the amplitude, which we
-use to scale the signal to control the volume of the output. We then
-create a top_block. The top_block is the object that holds the
-flowgraph, the basic data structure of a GNU Radio application. We
-will use the top_block to connect together and hold the signal
-processing blocks, which we build next.
-
-This example uses three signal processing blocks. The first two are
-gr::analog::sig_source_f blocks, which generate sine waves at
-frequencies 350 and 440 Hz. We next create the connection to the
-speaker system using gr::audio::sink, which takes in the sample rate
-it will use to produce the output signal. The audio sink block can
-also take in a second parameter to set the output device name, which
-we use if there is a resource conflict or if using a sampling rate
-that the hardware won't naturally support. Common device names are
-"pulse" if using PulseAudio or "plughw:0,0", which is an ALSA device
-that can handle resampling.
-
-We next take the three blocks we've built and connect together the
-flowgraph. The flowgraph connects sources to sinks through other
-signal processing blocks. Here, we are directly connecting two sources
-to a single sink. The next example uses more complex flowgraphs to
-further explore these concepts. The two lines containing the
-"tb.connect" statements are where the connections are made. The
-flowgraph will look like:
-
-\verbatim
-sig_source_f (freq = 350) -->
- audio.sink
-sig_source_f (freq = 440) -->
-\endverbatim
-
-We're inputting two signals into a single block, which with the audio
-sink allows us to output in stereo. The two signals combine to form
-the dual frequencies of a standard dial tone.
-
-In the connection of the signal source to the audio sink, notice how
-we specify the sink as a Python tuple, (dst, X). Technically, we
-specify all connections as ((source block, port out), (sink block,
-port in)) because each block that outputs samples can have multiple
-output ports just as a block that receives samples can have multiple
-input ports. However, in the case of a gr::analog::sig_source_f, it
-only produces samples on a single output and so the output port of 0
-is implied. Otherwise, we could write this as "tb.connect((src0, 0),
-(dst,0))" for complete representation of the connection.
-
-When we are done connecting the blocks, we have a flowgraph in the
-object "tb". While it's connected, the sources are not generating any
-samples. We have to start running the flowgraph. In the main section,
-we return the top_block object and then call the "start" function on
-it. This is a non-blocking call that launches the flowgraph's main
-thread, which initiates the sources to start sending samples through
-the flowgraph. We then block until the user presses "Enter" at which
-point we call the flowgraph's "stop" function to shut it down.
-
-
-\section ex_fm_demod FM Demodulator
-
-This example can be done completely in GRC or both GRC and Python. We
-will generate an FM signal using GRC first and then using either a GRC
-program or an example in Python to demodulate and play it back.
-
-\subsection Modulator
-
-We first launch GRC using the terminal command
-"gnuradio-companion". This starts the graphical interface to create
-our flowgraphs. We won't explore the GRC interface here; just use it
-to generate a data file. With GRC launched, open the file
-"fm_tx.grc". Exploring this flowgraph, it generates the dial tone
-frequencies, adds them together, resamples the signal so we can use
-integer upsampling in the wideband FM transmitter block (WBFM
-Transmit) and output the data. While this is happening, we're also
-outputting the original signal to the audio system as well as viewing
-it in time and frequency at different stages.
-
-The intent of this example is to generate a frequency-modulated dial
-tone signal and save it to a file. While saving it to a file, we only
-want to generate a signal large enough to make use of it, but it doesn't
-have to be too large. So we put a gr::blocks::head block that limits
-the number of samples into the file sink. Once this block has seen N
-number of samples, it will stop the flowgraph. Meanwhile, we use a
-gr::blocks::skiphead block to ignore the first M samples, which helps
-us avoid the transients and group delay of the filters in the system.
-
-We run this either using the menu "Build->Execute" or using the play
-button on the toolbar. It will run for a short amount of time and stop
-once the head has seen the items set in the "nitems" parameter. The
-result is a file "dummy.dat" that contains the complex FM samples.
-
-\subsection Demodulator
-
-The demodulator part is shown in both a GRC graph and as a Python
-script. Both the GRC graph, "fm_rx.grc", and the Python script,
-"fm_demod.py", do the same thing and basically reverse the stages of
-the modulator. It uses a gr::blocks::file_source to read the
-"dummy.dat" file we created previously. This is sent to the FM
-demodulator, which is simply implemented here using the
-gr::analog::quadrature_demod_cf. This demodulates the signal and
-converts the complex FM signal to a float signal.
-
-We then resample it from the input signal at 200 ksps to the audio
-rate of 44.1 ksps. Because this resampling cannot be done using an
-integer decimation rate, we use an arbitrary resampler, the
-gr::filter::pfb_arb_resampler_fff block, that allows us to resample at
-any rate as well as filter the signal to the audio rate we want. The
-output of this block is filtered to a 15 kHz bandwidth at a sample
-rate of 44.1 ksps, which is ready for the gr::audio::sink block.
-
-Both the GRC and Python files can be explored further to better
-understand the operations of the blocks.
-
-*/
diff --git a/docs/doxygen/other/thread_affinity.dox b/docs/usage-manual/(exported from wiki) Block Thread Affinity and Priority.txt
index 405477b8d3..2358034b11 100644
--- a/docs/doxygen/other/thread_affinity.dox
+++ b/docs/usage-manual/(exported from wiki) Block Thread Affinity and Priority.txt
@@ -1,15 +1,19 @@
-# Copyright (C) 2017 Free Software Foundation, Inc.
-#
-# Permission is granted to copy, distribute and/or modify this document
-# under the terms of the GNU Free Documentation License, Version 1.3
-# or any later version published by the Free Software Foundation;
-# with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
-# A copy of the license is included in the section entitled "GNU
-# Free Documentation License".
-
-/*! \page page_affinity Block Thread Affinity and Priority
-
-\section affinity Block Thread Affinity
+<page>
+ <title>Block Thread Affinity and Priority</title>
+ <ns>0</ns>
+ <id>3489</id>
+ <revision>
+ <id>4226</id>
+ <parentid>4225</parentid>
+ <timestamp>2018-06-11T05:08:53Z</timestamp>
+ <contributor>
+ <username>777arc</username>
+ <id>632</id>
+ </contributor>
+ <comment>/* Setting Affinity for a gr::hier_block2 */</comment>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="4603">== Block Thread Affinity ==
In the thread-per-block scheduler, you can set the block's core
affinity. Each block can be pinned to a group cores or be set back
@@ -18,7 +22,6 @@ to use the standard kernel scheduler.
The implementation is done by adding new functions to the threading
section of the gnuradio-runtime library:
-\code
gr::thread::gr_thread_t get_current_thread_id();
void thread_bind_to_processor(unsigned int n);
void thread_bind_to_processor(const std::vector<unsigned int> &mask);
@@ -26,7 +29,6 @@ section of the gnuradio-runtime library:
void thread_bind_to_processor(gr::thread::gr_thread_t thread, const std::vector<unsigned int> &mask);
void thread_unbind();
void thread_unbind(gr::thread::gr_thread_t thread);
-\endcode
The ability to set a thread's affinity to a core or groups of cores is
not implemented in the Boost thread library, and so we have made our
@@ -47,34 +49,31 @@ the affinity for the current thread.
NOTE: Not available on OSX.
-
-\subsection affinity_api GNU Radio Block API
+=== GNU Radio Block API ===
Each block has two new data members:
-- threaded: a boolean value that is true if the block is attached to a
- thread.
-- thread: a gr::thread::gr_thread_t handle to the block's thread.
+* threaded: a boolean value that is true if the block is attached to a thread.
+* thread: a gr::thread::gr_thread_t handle to the block's thread.
A block can set and unset its affinity at any time using the
following member functions:
-- gr::block::set_processor_affinity(const std::vector<int> &mask)
-- gr::block::unset_processor_affinity()
+* gr::block::set_processor_affinity(const std::vector<int> &mask)
+* gr::block::unset_processor_affinity()
Where \p mask is a vector of core numbers to set the thread's affinity
to.
The current core affinity can be retrieved using the member function:
-- gr::block::processor_affinity()
+* gr::block::processor_affinity()
When set before the flowgraph is started, the scheduler will set the
thread's affinity when it is started. When already running, the
block's affinity will be immediately set.
-
-\subsection affinity_api_hier Setting Affinity for a gr::hier_block2
+=== Setting Affinity for a gr::hier_block2 ===
A hierarchical block (gr::hier_block2) also has a concept of setting
the block thread affinity. Because the hierarchical block itself does
@@ -85,9 +84,9 @@ to that affinity setting.
The gr::hier_block2 class supports the same API interface to the block
thread affinity:
-- gr::hier_block2::set_processor_affinity(const std::vector<int> &mask)
-- gr::hier_block2::unset_processor_affinity()
-- gr::hier_block2::processor_affinity()
+* gr::hier_block2::set_processor_affinity(const std::vector<int> &mask)
+* gr::hier_block2::unset_processor_affinity()
+* gr::hier_block2::processor_affinity()
Setting and unsetting the affinity does so recursively for every block
in the hierarchical block. It is of course possible to individually set
@@ -96,8 +95,7 @@ in this case, note that when asking for the current affinity value
using 'processor_affinity()', the code returns the current processor
affinity value of only the first block.
-
-\subsection affinity_api_grc GRC Access
+=== GRC Access ===
GRC supports the setting of the thread core affinity in a block's
options. Each block now has a field 'Core Affinity' that accepts a
@@ -107,26 +105,25 @@ constructed.
Note that GRC does not provide a callback function for changing the
thread core affinity while the flowgraph is running.
-
-
-\section priority_api Setting Thread Priority
+== Setting Thread Priority ==
Similarly to setting the core affinity for a given block, we can also
set the thread priority. This concept adds three new function calls to
all blocks:
-\li gr::block::set_thread_priority(int priority): Sets the current thread priority.
-\li gr::block::active_thread_priority(): Gets the active priority for the thread.
-\li gr::block::thread_priority(): Gets the stored thread priority.
+# gr::block::set_thread_priority(int priority): Sets the current thread priority.
+# gr::block::active_thread_priority(): Gets the active priority for the thread.
+# gr::block::thread_priority(): Gets the stored thread priority.
The range of the thread priority might be system dependent, so look to
-your system/OS documentation. Linux specifies this range in
-\b sched_setscheduler as a value between 1 and 99 where 1 is the lowest
+your system/OS documentation. Linux specifies this range in sched_setscheduler as a value between 1 and 99 where 1 is the lowest
priority and 99 is the highest. POSIX systems can retrieve these min
-and max values using \b sched_get_priority_min and \b
+and max values using sched_get_priority_min and
sched_get_priority_max and may only allow 32 distinct values to be
set.
-NOTE: Not available on Windows or OSX.
-
-*/
+NOTE: Not available on Windows or OSX.</text>
+ <sha1>aj61n4ohuw7m8gm3g0j4qaa5eamqvpm</sha1>
+ </revision>
+ </page>
+</mediawiki> \ No newline at end of file
diff --git a/docs/doxygen/other/prefs.dox b/docs/usage-manual/(exported from wiki) Configuration Files.txt
index d8c2782b1d..464524c62c 100644
--- a/docs/doxygen/other/prefs.dox
+++ b/docs/usage-manual/(exported from wiki) Configuration Files.txt
@@ -1,15 +1,18 @@
-# Copyright (C) 2017 Free Software Foundation, Inc.
-#
-# Permission is granted to copy, distribute and/or modify this document
-# under the terms of the GNU Free Documentation License, Version 1.3
-# or any later version published by the Free Software Foundation;
-# with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
-# A copy of the license is included in the section entitled "GNU
-# Free Documentation License".
-
-/*! \page page_prefs Configuration files
-
-\section prefs Configuration / Preference Files
+<page>
+ <title>Configuration Files</title>
+ <ns>0</ns>
+ <id>3490</id>
+ <revision>
+ <id>4228</id>
+ <timestamp>2018-06-11T05:11:22Z</timestamp>
+ <contributor>
+ <username>777arc</username>
+ <id>632</id>
+ </contributor>
+ <comment>Created page with "== Configuration / Preference Files == GNU Radio defines some of its basic behavior through a set of configuration files located in ${prefix}/etc/gnuradio/conf.d. Different c..."</comment>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="2711">== Configuration / Preference Files ==
GNU Radio defines some of its basic behavior through a set of
configuration files located in
@@ -20,16 +23,14 @@ will not affect them.
The configuration files use the following format:
-\code
-# Stuff from section 1
-[section1]
-var1 = value1
-var2 = value2 # value of 2
-
-# Stuff from section 2
-[section2]
-var3 = value3
-\endcode
+ # Stuff from section 1
+ [section1]
+ var1 = value1
+ var2 = value2 # value of 2
+
+ # Stuff from section 2
+ [section2]
+ var3 = value3
In this file, the hash mark ('#') indicates a comment and blank lines
are ignored. Section labels are defined inside square brackets as a
@@ -43,10 +44,8 @@ value will have its white space preserved and the quotes internally
will be stripped. As an example, on Apple desktops, an output device
of "Display Audio" is a possible output device and can be set as:
-\code
-[audio_osx]
-default_output_device = "Display Audio"
-\endcode
+ [audio_osx]
+ default_output_device = "Display Audio"
The result will pass Display Audio to the audio setup.
@@ -55,42 +54,35 @@ a few different interfaces. There is a single preference object
created when GNU Radio is launched. In Python, you can get this by
making a new variable:
-\code
-p = gr.prefs()
-\endcode
+ p = gr.prefs()
Similarly, in C++, we get a reference to the object by explicitly
calling for the singleton of the object:
-\code
- prefs *p = prefs::singleton();
-\endcode
+ prefs *p = prefs::singleton();
The methods associated with this preferences object are (from class gr::prefs):
-\code
bool has_section(string section)
bool has_option(string section, string option)
string get_string(string section, string option, string default_val)
bool get_bool(string section, string option, bool default_val)
long get_long(string section, string option, long default_val)
double get_double(string section, string option, double default_val)
-\endcode
-When setting a Boolean value, we can use 0, 1, "True", "true",
-"False", "false", "On", "on", "Off", and "off".
+When setting a Boolean value, we can use 0, 1, "True", "true", "False", "false", "On", "on", "Off", and "off".
All configuration preferences in these files can also be overloaded by
an environmental variable. The environmental variable is named based
on the section and option name from the configuration file as:
-\code
- GR_CONF_<SECTION>_<OPTION> = <value>
-\endcode
+ GR_CONF_<SECTION>_<OPTION> = <value>
The "GR_CONF_" is a prefix to identify this as a GNU Radio
configuration variable and the section and option names are in
uppercase. The value is the same format that would be used in the
-config file itself.
-
-*/
+config file itself.</text>
+ <sha1>3tjlcfewvu2log4t9s6q45upgqh8rwo</sha1>
+ </revision>
+ </page>
+</mediawiki> \ No newline at end of file
diff --git a/docs/usage-manual/(exported from wiki) GNURadioCompanion.txt b/docs/usage-manual/(exported from wiki) GNURadioCompanion.txt
new file mode 100644
index 0000000000..1be03e42f2
--- /dev/null
+++ b/docs/usage-manual/(exported from wiki) GNURadioCompanion.txt
@@ -0,0 +1,437 @@
+<page>
+ <title>GNURadioCompanion</title>
+ <ns>0</ns>
+ <id>47</id>
+ <revision>
+ <id>4311</id>
+ <parentid>4310</parentid>
+ <timestamp>2018-06-26T19:59:29Z</timestamp>
+ <contributor>
+ <username>777arc</username>
+ <id>632</id>
+ </contributor>
+ <comment>/* Special Thanks */</comment>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="22088">= GNU Radio Companion =
+
+GNU Radio Companion (GRC) is a graphical tool for creating signal flow graphs and generating flow-graph source code. There is a [[WorkingGroups|GNU Radio Companion Working Group]] handling the development.
+
+== New Features ==
+
+What has changed in GRC since the stable 0.70 release?
+
+* Bundled - GRC is now bundled with the gnuradio source. If all dependencies are met, grc will be installed with gnuradio. *See the Installation and Execution section.
+
+* Desktop Integration - GRC can be fully integrated into a desktop environment that supports freedesktop standards (courtesy of xdg-utils): icons, mime type, and menu items
+
+* Code Generation - GRC no longer uses a single executable to load a *.grc.xml file and dynamically build the flow graph. Rather, GRC uses Cheetah templates to generate the python source code for the flow graph. GRC can generate source code for WX GUI and non-GUI flow graphs as well as hierarchical blocks.
+
+* Documentation - GRC can extract documentation for GNU Radio blocks directly from the doxygen-generated xml files. You will need to configure your gnuradio installation with doxygen support to use this feature.
+
+* Variables - The variable editor window of past releases has been replaced with variable blocks. Variable blocks show up in the flow graph and act like any other block, except that they have no IO ports. The variable block maps a unique id (variable name) to a particular value. GRC also has several graphical variable blocks that allow one to create WX GUI flow graphs with graphical controls using sliders, text boxes, buttons, drop downs, and radio buttons.
+
+* Block Definitions - Every block in GRC has a corresponding xml file that contains parameters, IO ports, and a template for code generation. The id key and file name of each xml file matches up exactly with the name of the GNU Radio block to ensure future portability. GRC validates all blocks definitions upon execution, and will exit with error if any definitions fail the validation.
+
+* File Format - Given that the variables and block definitions have changed, the internal structure of the saved flow graph files has also changed. Fortunately, GRC can automatically convert older saved flow graph files to the new format. Unfortunately, the conversion cannot always be 100%.
+
+* Block Manipulation - Ever wish that you could take a block out of your transmit/receive chain, but not delete it? Blocks now have an enabled/disabled state. By default, a block is enabled. When disabled, a block is grayed out in the flow graph and will be ignored by the flow graph validator and by the source code generator. In addition, blocks may be cut, copied, and pasted within flow graphs and into other flow graphs.
+
+* Hierarchical Blocks - GRC can create hierarchical blocks out of the built-in blocks. *See the section on hierarchical blocks.
+
+== Requirements ==
+
+=== GRC Requirements ===
+
+Most (if not all) of these requirements can be found in the package manager of you linux distribution.
+
+* [Python 2.5 (or above) http://www.python.org/download/]
+
+* [Python-LXML 2.0 (or above) http://codespeak.net/lxml/installation.html]
+
+* [Cheetah Template Engine 2.0 (or above) http://www.cheetahtemplate.org/download.html]
+
+* [Python-GTK 2.10 (or above) http://www.pygtk.org/downloads.html]
+
+=== GNU Radio Requirements ===
+
+GRC is bundled with the current gnuradio trunk and will be included in the 3.2 release. I recommend configuring your GNU Radio installation with wx-python, usrp, and audio support. However, any configuration will work (see note). Follow the [http://gnuradio.org/trac/wiki/BuildGuide build-guide]
+
+Note: GRC will let you generate flow graphs with components that are not included in your local install. For example, you can generate a flow graph with a usrp source, but the code will error when executed unless GNU Radio is configured with usrp support.
+
+== Installation ==
+
+=== Installing GRC ===
+
+GRC is bundled with gnuradio, so following the [[InstallingGR|installation guide]] should be enough to install GRC. However, GRC will not be installed if you were missing any of the required components. Install any missing components and re-run configure/install:
+
+<pre>
+cmake ..
+make
+sudo make install
+</pre>
+GRC should appear in the list of configured components; if not, read the configure verbose for errors.
+
+=== Installing Documentation ===
+
+To view the blocks' documentation from inside GRC, install doxygen and configure gnuradio with doxygen support.
+
+=== Installing Icons, Mime Type, and Menu Items ===
+
+If you have an operating system that supports the freedesktop.org standards (Gnome, KDE, XFCE), then you may install the icons, mime type, and menu items bundled with GRC. After installing GRC, run the following command:
+
+<pre>
+cd /libexec/gnuradio/
+sudo ./grc_setup_freedesktop install
+</pre>
+
+== Execution ==
+
+GRC installs several executable python files into your system's path.
+
+=== Executing the Flow Graph Editor ===
+
+Open a terminal and enter the following:
+
+<pre>
+gnuradio-companion
+</pre>
+
+== Usage Tips ==
+
+* Add a block: double click on a block in the block selection window.
+
+* Connect blocks: click on the port of one block, then click on the port of another block.
+
+* Remove a connection: click on the connection, press delete, or drag the connection to remove.
+
+* Edit block parameters: double click on a block in the flow graph.
+
+* Select a block, hit up/down for quick type change.
+
+* For more short cuts, see the hot keys in the menu.
+
+* Flow graphs that are completely simulation (without audio or usrp blocks) will consume 100% CPU when executed, and the GUI elements will be unresponsive. These flow graphs must include a Misc->Throttle block to throttle the rate of the streaming data.
+
+== Variables ==
+
+Variables map symbolic names to values. In GRC, a variable can define a global constant or, a variable can be used in conjunction with a GUI to control a running flow graph.
+
+=== Variable Block ===
+
+The variable block is the most basic way to use a variable in GRC. The ID parameter of the variable block is the "symbolic name". The symbolic name must be alpha-numeric (underscores allowed) and begin with a letter. To use the variable, simply enter the symbolic name into a parameter of another block.
+
+=== Variable Controls ===
+
+Certain blocks have callback methods that allow their parameters to be changed while executing flow graph. Variable controls in GRC use variables in combination with callback methods to modify these parameters. If a parameter has a callback method, the parameter will be underlined in the block-properties dialog. The variable slider, variable text box, and the variable chooser block provide graphical widgets such as sliders, text boxes, radio buttons, and drop downs as variable controls. In addition, the variable sink block takes samples from a gnuradio stream and writes the samples to a variable.
+
+=== String Evaluation ===
+
+String parameters have a two-phase evaluation. First, GRC evaluates the parameter as-is. If the parameter does not evaluate to a string data type or the evaluation fails, then it is understood that the parameter had implied quotation. In this case, GRC will evaluate the parameter again with quotation marks; which will return a string with the exact code that was typed into the parameter window.
+
+To use a variable inside a string simply type the name of the variable into the parameter: ''my_var''. If the variable is not a string, cast the variable with python's str function: ''str(my_var)''. Standard python string functionality applies: ''"My Var = " + str(my_var)''.
+
+*Note: String parameter types also include the file open and file save types.
+
+== Filter Design ==
+
+Many blocks in gnuradio that take an array of complex or real taps as a parameter. GNU Radio provides a package to generate all kinds of filter and window taps. See the [http://gnuradio.org/doc/doxygen/classgr+firdes.html firdes package] from the gnuradio documentation.
+
+=== Firdes Taps Generators ===
+
+* low_pass(gain, samp_rate, cutoff_freq, width, [window], [beta])
+
+* high_pass(gain, samp_rate, cutoff_freq, width, [window], [beta])
+
+* band_pass(gain, samp_rate, low_cutoff_freq, high_cutoff_freq, width, [window], [beta])
+
+* complex_band_pass(gain, samp_rate, low_cutoff_freq, high_cutoff_freq, width, [window], [beta])
+
+* band_reject(gain, samp_rate, low_cutoff_freq, high_cutoff_freq, width, [window], [beta])
+
+* gaussian(gain, spb, bt, int ntaps)
+
+* hilbert(int ntaps, window, beta)
+
+* root_raised_cosine(gain, samp_rate, symbol_rate, alpha, int ntaps)
+
+* window(window, int ntaps, beta)
+
+=== Firdes Window Types ===
+
+* WIN_HAMMING
+
+* WIN_HANN
+
+* WIN_BLACKMAN
+
+* WIN_RECTANGULAR
+
+* WIN_KAISER
+
+=== Firdes Notes ===
+
+For the pass band functions, window defaults to the Hamming window. The beta parameter defaults to 6.76, and only applies to the Kaiser window.
+
+=== Firdes Usage Example ===
+
+Create a new "import" block, and enter the following for the import parameter:
+
+<pre>from gnuradio.filter import firdes</pre>
+Note: Most blocks with a taps parameter automatically import the firdes module. You only need to use the import block when firdes will not evaluate.
+
+Enter the following into the taps parameter of a filter block:
+
+<pre>
+firdes.low_pass(1.0, samp_rate, 1000, 100, firdes.WIN_HAMMING)
+</pre>
+=== Use Taps from a File ===
+
+Suppose that you have an array of filter taps stored in a file that you would like to use inside GRC:
+
+Create a new "import" block, and enter the following for the import parameter:
+
+<pre>
+import numpy
+</pre>
+Enter the following into the taps parameter of a filter block:
+
+<pre>
+numpy.fromfile('taps file path', numpy.complex64).tolist()
+</pre>
+This will read an entire binary file and parse every 64 bytes into a complex number. Use numpy.float32 for real taps. See the numpy.fromfile help for more advanced usage:
+
+<pre>
+Help on built-in function fromfile in numpy:
+
+numpy.fromfile = fromfile(...)
+ fromfile(file=, dtype=float, count=-1, sep=_) -> array.
+
+ Required arguments:
+ file -- open file object or string containing file name.
+
+ Keyword arguments:
+ dtype -- type and order of the returned array (default float)
+ count -- number of items to input (default all)
+ sep -- separater between items if file is a text file (default "")
+
+ Return an array of the given data type from a text or binary file. The
+ 'file' argument can be an open file or a string with the name of a file to
+ read from. If 'count' == -1 the entire file is read, otherwise count is the
+ number of items of the given type to read in. If 'sep' is "" it means to
+ read binary data from the file using the specified dtype, otherwise it gives
+ the separator between elements in a text file. The 'dtype' value is also
+ used to determine the size and order of the items in binary files.
+
+</pre>
+
+== Grid Positioning ==
+
+GRC offers several graphical sinks and graphical controls for creating wx-gui flow graphs. (scope sink, fft sink, number sink, waterfall sink, constellation sink, slider control, and chooser control) Each of these graphical elements have a grid position parameter for precise positioning.
+
+A grid position parameter is a list of 4 integers of the form (row, column, row span, column span). The row and column specify the position of the upper-left corner of the graphical element. The smallest position, the (0, 0) position, specifies the upper-left corner of the grid.
+
+If left blank, the grid parameter specifies that the graphical element will be automatically stacked into a vertical sizer. The vertical sizer is positioned directly above the grid sizer. If you do not want any elements to be added to the vertical sizer, leave no grid parameters blank.
+
+The row and column span specify the stretch, or the number of rows and columns that the graphical element can occupy. The row span specifies the number of rows down from the row positon, and the column span specifies the number of columns right of the column position. Therefore, the span must be at least (1, 1) to occupy the minimum of 1 grid cell.
+
+=== Example ===
+
+The user wishes to place a slider, centered directly above a graphical sink. The slider will be positioned at the 2nd column of the top row and with a column span of 2. The sink will be positioned on the 2nd row, and with a row span of 2 and a column span of 4. Notice the grid parameters below, and the resulting gui layout:
+
+'''The Elements:'''
+
+'''''' '''Slider Control: (0, 1, 1, 2)'''
+
+'''''' Graphical Sink: (1, 0, 2, 4)
+
+'''The Resulting GUI:'''
+
+{|
+|
+
+| 0,0
+|
+
+| '''0,1'''
+|
+
+| '''0,2'''
+|
+
+| 0,3
+|
+
+|-
+|
+
+| 1,0
+|
+
+| 1,1
+|
+
+| 1,2
+|
+
+| 1,3
+|
+
+|-
+|
+
+| 2,0
+|
+
+| 2,1
+|
+
+| 2,2
+|
+
+| 2,3
+|
+
+|}
+
+== Hierarchical Blocks ==
+
+GRC can create hierarchical blocks out of the built-in blocks. Hierarchical blocks can be instantiated inside of other grc flow graphs. The python code generated from a hierarchical block can itself be used in non-GRC flow graphs. Four important blocks are used in the creation of a hierarchical block: The options block, parameter blocks, and the pad source and pad sink.
+
+=== The Options Block ===
+
+In order to make a hierarchical block, the parameters in the options block must be set properly. The id of the options block sets the module name, and must be unique among the entire library of blocks (built-in and custom). The title parameter sets the display name for the block. The generate options must be set to "Hier Block". The category parameter sets the category for the new block. This category can be an existing category in the block selection window or a new category. Categories may be nested by specifying a name with slashes, ex: Custom/Filters. To put blocks into the root category, specify a single slash "/" (a blank category will hide your block).
+
+=== Parameter Blocks ===
+
+Parameter blocks specify variables in your hierarchical block that should be configurable in the top level block. Parameter blocks work much like variable blocks with a few exceptions: Parameters blocks cannot depend on variable blocks or other parameter blocks. Parameter blocks have a label parameter for display purposes. Parameter blocks take the place of a variable block, do not try to create a variable block with the same id as your parameter block.
+
+=== Pad Source and Sink Blocks ===
+
+The pad source and sink blocks create inputs and outputs for the hierarchical block. The pad blocks have configurable data types, vector lengths, and number of ports. A flow graph can have at most, one pad source, and one pad sink. A hierarchical block may have one pad sink and no pad source or no pad sink and one pad source, but it must have at least one pad block.
+
+=== Creating and Instantiating ===
+
+* Start with a blank slate and create a new (empty) flow graph.
+
+* Setup the options block as described above, with the id, title, generate options, and category.
+
+* Add parameter blocks for all variables you wish to configure/control outside of the block.
+
+* Create at most one pad source and one pad sink to match the IO type and connect them.
+
+* When finished, click the generate button, and close/reopen GRC.
+
+* The hierarchical block will appear in the block selection window.
+
+* Add the hierarchical block to a flow graph as your would any other block.
+
+=== Notes ===
+
+* After making changes to your hierarchical block, make sure to regenerate, and reopen GRC before usage.
+
+* The ID parameter of the block must be unique. If two blocks share the same ID, the last one to be generated will overwrite the other.
+
+* Custom hierarchical blocks may instantiate other custom hierarchical blocks. Just don't have a block instantiate itself!
+
+== Adding Custom Blocks ==
+
+Every block in GRC corresponds to an XML file that describes the block's parameters, inputs, outputs, and other attributes. Adding a custom block into GRC is simply a matter of creating one of these XML block definition files. A few caveats:
+
+* The block should be accessible from the python path. Meaning that the block can be accessed via an import statement.
+* The block follows the block diagram model: it has parameters, inputs, and outputs. If the block requires some kind of listening thread, or special callback methods to move the data (as in the blks2 packet stuff), it cannot be used in GRC (unless this "special" functionality can be encapsulated into a block that is block-diagram-safe).
+* If GRC is missing a block definition for a block that is currently in the trunk, or one of the block definitions is missing functionality, please mail the list. The block definitions in the GRC trunk must stay in sync with the actual GNU Radio blocks.
+
+=== Creating the XML Block Definition ===
+
+The best way to learn how to create the xml file is to learn by example. See the block definitions (source:grc/blocks) packaged with GRC, and read through a few files. Essentially, all block definitions are structured as follows:
+
+<pre>
+ My Block Name
+ my_package_my_block_ff
+ Filters
+ from gnuradio import my_package
+ my_package.my_block_ff($param1, $param2)
+ set_param1($param1)
+
+ Parameter 1
+ param1
+ real
+
+
+ Parameter 2
+ param2
+ 1
+ int
+
+
+ in
+ float
+ part
+
+
+ out
+ float
+
+
+ out
+ float
+</pre>
+
+* The example above will make a block with 2 parameters, 1 input, and 2 outputs.
+* The ordering of the tags is important, if tags are not ordered properly, the block will fail validation. See [https://github.com/gnuradio/gnuradio/blob/master/grc/core/block.dtd block.dtd] for specifics.
+* The '''name''' tags dictate the label text for the block, parameters, and ports.
+* The '''key''' tags are unique identifiers, they may not contain spaces. The block key must be globally unique among all blocks in GRC. The parameter keys must be unique only within the block.
+* The '''category''' tag is a unix-style path that represents the location of the block inside the block selection window. The path can be a new category (Custom), or represent a sub-category (Filters/Custom). To put a block into the root category, just use a single slash (/) for the root path.
+* The '''import''' tag (there can be multiple) must be a valid python import statement to the module containing your block.
+* The '''make''' tag contains the code necessary to construct your block. This code is essentially a cheetah template nested inside an xml tag. Upon code generation, the template performs a text substitution on the "$" parameters. For more advanced capabilities, see the [http://cheetahtemplate.org/users_guide/index.html cheetah template documentation.]
+* The '''callback''' tag registers a set-method from your custom block. Once the set-method is registered, the set-method can be called at runtime when a variable is changed. There can be any number of '''callback''' tags, one for each set-method of your block. Or no '''callback''' tags if this is not applicable.
+* For the '''param''' tags, the commonly used values for the '''type''' tags are: complex, real, int, complex_vector, real_vector, int_vector, string, and raw. The ''raw'' type allows any value to be used without performing type checking. The ''real'' type should be used for single and double precision floating point numbers. The ''int'' type should be used for longs, ints, shorts, and chars.
+* The hide tag controls how the parameter is displayed in GRC. It's either none, part (show in the prop dialog, not in the block on the canvas) or all.
+* The '''sink''' tag represents an input port, and the '''source''' tag represents an output port. The allowed values for the '''type''' tags are: complex, float, int, short, and byte. For ports with a vector length, specify a '''vlen''' tag after the '''type''' tag.
+* In case you want to create a block definition as done for the FECAPI, the '''key''' tag has to start with '''variable_''' in order to work correctly in GRC.
+
+=== Some Example Definitions ===
+
+* Simple Example: "Complex to Real" source:[https://github.com/gnuradio/gnuradio/blob/master/gr-blocks/grc/blocks_complex_to_real.xml|gr-blocks/grc/blocks_complex_to_real.xml]
+* Multiple Callbacks: "Costas Loop" source:[https://github.com/gnuradio/gnuradio/blob/master/gr-digital/grc/digital_costas_loop_cc.xml|gr-digital/grc/digital_costas_loop_cc.xml]
+* Vlen Example: "Throttle" source:[https://github.com/gnuradio/gnuradio/blob/master/gr-digital/grc/blocks_throttle.xml|gr-digital/grc/blocks_throttle.xml]
+* Advanced Make: "FFT" source:[https://github.com/gnuradio/gnuradio/blob/master/gr-fft/grc/fft_fft_vxx.xml|gr-fft/grc/fft_fft_vxx.xml]
+
+=== Installing the XML Block Definition ===
+
+There are many methods to tell grc about your new xml file. Choose one of the following methods...
+
+==== Method 1: Default Hier Block Location ====
+
+Create the _'''.xml_ file inside'''<sub>/.grc_gnuradio/* where</sub> is your home directory. If the directory does not exist, create it: ''mkdir ~/.grc_gnuradio/''
+
+==== Method 2: Configuration File ====
+
+Create or edit '''~/.gnuradio/config.conf''' and add the following lines:
+
+<pre>[grc]
+local_blocks_path=/path/to/my/blocks</pre>
+The local_blocks_path can contain multiple paths separated by colons: local_blocks_path=/path/to/blocks1:/path/to/blocks2
+
+==== Method 3: Environment Variable ====
+
+Set the '''GRC_BLOCKS_PATH''' environment variable to a path that contains your custom block wrapper. The GRC_BLOCKS_PATH can contain multiple paths separated by colons: GRC_BLOCKS_PATH=/path/to/blocks1:/path/to/blocks2
+
+== Special Thanks ==
+
+* '''[http://www.cer.jhu.edu/| CER Technology Fellowship]:''' initial funding
+* '''[http://www.ece.jhu.edu/~cooper/| A. Brinton Cooper]:''' starting the project
+* '''Patrick Mulligan:''' starting the project
+* '''William R. Kenan Jr. Fund:''' usrp & computers
+* '''Patrick Strasser:''' the GRC icon
+
+== Screen Shots ==
+
+[http://www.joshknows.com/grc#screenshots Screen Shots]
+
+Feel free to submit your own screen shots or flow graphs.</text>
+ <sha1>m9jzkey4r3k9dc2qhm3u4qpz4gbegaf</sha1>
+ </revision>
+ </page>
+</mediawiki> \ No newline at end of file
diff --git a/docs/doxygen/other/operating_fg.dox b/docs/usage-manual/(exported from wiki) Handling Flowgraphs.txt
index 62cc56fd4e..b5deada42a 100644
--- a/docs/doxygen/other/operating_fg.dox
+++ b/docs/usage-manual/(exported from wiki) Handling Flowgraphs.txt
@@ -1,15 +1,20 @@
-# Copyright (C) 2017 Free Software Foundation, Inc.
-#
-# Permission is granted to copy, distribute and/or modify this document
-# under the terms of the GNU Free Documentation License, Version 1.3
-# or any later version published by the Free Software Foundation;
-# with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
-# A copy of the license is included in the section entitled "GNU
-# Free Documentation License".
-
-/*! \page page_operating_fg Handling flow graphs
-
-\section flowgraph Operating a Flowgraph
+<page>
+ <title>Handling Flowgraphs</title>
+ <ns>0</ns>
+ <id>3480</id>
+ <revision>
+ <id>4291</id>
+ <parentid>4290</parentid>
+ <timestamp>2018-06-26T19:41:49Z</timestamp>
+ <contributor>
+ <username>777arc</username>
+ <id>632</id>
+ </contributor>
+ <minor/>
+ <comment>/* Reconfiguring Flowgraphs */</comment>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="10039">== Operating a Flowgraph ==
The basic data structure in GNU Radio is the flowgraph, which
represents the connections of the blocks through which a continuous
@@ -29,29 +34,27 @@ gr_top_block, instantiate the blocks, connect the blocks together, and
then start the gr_top_block. The following program shows how this is
done. A single source and sink are used with a FIR filter between
them.
-
-\code
+<syntaxhighlight lang="python">
from gnuradio import gr, blocks, filter, analog
-
+
class my_topblock(gr.top_block):
def __init__(self):
gr.top_block.__init__(self)
-
+
amp = 1
taps = filter.firdes.low_pass(1, 1, 0.1, 0.01)
-
+
self.src = analog.noise_source_c(analog.GR_GAUSSIAN, amp)
self.flt = filter.fir_filter_ccf(1, taps)
self.snk = blocks.null_sink(gr.sizeof_gr_complex)
-
+
self.connect(self.src, self.flt, self.snk)
-
+
if __name__ == "__main__":
tb = my_topblock()
tb.start()
tb.wait()
-\endcode
-
+</syntaxhighlight>
The 'tb.start()' starts the data flowing through the flowgraph while
the 'tb.wait()' is the equivalent of a thread's 'join' operation and
blocks until the gr_top_block is done.
@@ -60,8 +63,7 @@ An alternative to using the 'start' and 'wait' methods, a 'run' method is
also provided for convenience that is a blocking start call;
equivalent to the above 'start' followed by a 'wait.'
-
-\subsection latency Latency and Throughput
+=== Latency and Throughput ===
By default, GNU Radio runs a scheduler that attempts to optimize
throughput. Using a dynamic scheduler, blocks in a flowgraph pass
@@ -89,12 +91,10 @@ scheduler, and so reduce the overall efficiency of the application.
To set the maximum number of output items, we pass a value into the
'start' or 'run' method of the gr_top_block:
-\code
tb.start(1000)
tb.wait()
or
tb.run(1000)
-\endcode
Using this method, we place a global restriction on the size of items
to all blocks. Each block, though, has the ability to overwrite this
@@ -103,10 +103,8 @@ individual block will overwrite the global setting. For example, in
the following code, the global setting is 1000 items max, except for
the FIR filter, which can receive up to 2000 items.
-\code
tb.flt.set_max_noutput_items(2000)
tb.run(1000)
-\endcode
In some situations, you might actually want to restrict the size of
the buffer itself. This can help to prevent a buffer who is blocked
@@ -119,16 +117,14 @@ used without a full understanding of this concept as explained below.
To set the output buffer size of a block, you simply call:
-\code
tb.blk0.set_max_output_buffer(2000)
tb.blk1.set_max_output_buffer(1, 2000)
tb.start()
print tb.blk1.max_output_buffer(0)
print tb.blk1.max_output_buffer(1)
-\endcode
In the above example, all ports of blk0 are set to a buffer size of
-2000 in _items_ (not bytes), and blk1 only sets the size for output
+2000 in ''items'' (not bytes), and blk1 only sets the size for output
port 1, any and all other ports use the default. The third and fourth
lines just print out the buffer sizes for ports 0 and 1 of blk1. This
is done after start() is called because the values are updated based
@@ -158,8 +154,7 @@ When calling max_output_buffer(port) after the flowgraph is
started, you will get how many items were actually allocated in the
buffer, which may be different than what was initially specified.
-
-\section reconfigure Reconfiguring Flowgraphs
+== Reconfiguring Flowgraphs ==
It is possible to reconfigure the flowgraph at runtime. The
reconfiguration is meant for changes in the flowgraph structure, not
@@ -175,50 +170,48 @@ The following example code shows a graph that first adds two
gr::analog::noise_source_c blocks and then replaces the
gr::blocks::add_cc block with a gr::blocks::sub_cc block to then
subtract the sources.
-
-\code
-from gnuradio import gr, analog, blocks
-import time
-
-class mytb(gr.top_block):
- def __init__(self):
- gr.top_block.__init__(self)
-
- self.src0 = analog.noise_source_c(analog.GR_GAUSSIAN, 1)
- self.src1 = analog.noise_source_c(analog.GR_GAUSSIAN, 1)
- self.add = blocks.add_cc()
- self.sub = blocks.sub_cc()
- self.head = blocks.head(gr.sizeof_gr_complex, 1000000)
- self.snk = blocks.file_sink(gr.sizeof_gr_complex, "output.32fc")
-
- self.connect(self.src0, (self.add,0))
- self.connect(self.src1, (self.add,1))
- self.connect(self.add, self.head)
- self.connect(self.head, self.snk)
-
-def main():
- tb = mytb()
- tb.start()
- time.sleep(0.01)
-
- # Stop flowgraph and disconnect the add block
- tb.lock()
- tb.disconnect(tb.add, tb.head)
- tb.disconnect(tb.src0, (tb.add,0))
- tb.disconnect(tb.src1, (tb.add,1))
-
- # Connect the sub block and restart
- tb.connect(tb.sub, tb.head)
- tb.connect(tb.src0, (tb.sub,0))
- tb.connect(tb.src1, (tb.sub,1))
- tb.unlock()
-
- tb.wait()
-
-if __name__ == "__main__":
- main()
-\endcode
-
+<syntaxhighlight lang="python">
+ from gnuradio import gr, analog, blocks
+ import time
+
+ class mytb(gr.top_block):
+ def __init__(self):
+ gr.top_block.__init__(self)
+
+ self.src0 = analog.noise_source_c(analog.GR_GAUSSIAN, 1)
+ self.src1 = analog.noise_source_c(analog.GR_GAUSSIAN, 1)
+ self.add = blocks.add_cc()
+ self.sub = blocks.sub_cc()
+ self.head = blocks.head(gr.sizeof_gr_complex, 1000000)
+ self.snk = blocks.file_sink(gr.sizeof_gr_complex, "output.32fc")
+
+ self.connect(self.src0, (self.add,0))
+ self.connect(self.src1, (self.add,1))
+ self.connect(self.add, self.head)
+ self.connect(self.head, self.snk)
+
+ def main():
+ tb = mytb()
+ tb.start()
+ time.sleep(0.01)
+
+ # Stop flowgraph and disconnect the add block
+ tb.lock()
+ tb.disconnect(tb.add, tb.head)
+ tb.disconnect(tb.src0, (tb.add,0))
+ tb.disconnect(tb.src1, (tb.add,1))
+
+ # Connect the sub block and restart
+ tb.connect(tb.sub, tb.head)
+ tb.connect(tb.src0, (tb.sub,0))
+ tb.connect(tb.src1, (tb.sub,1))
+ tb.unlock()
+
+ tb.wait()
+
+ if __name__ == "__main__":
+ main()
+</syntaxhighlight>
During reconfiguration, the maximum noutput_items value can be changed
either globally using the 'set_max_noutput_items(m)' on the gr_top_block
object or locally using the 'set_max_noutput_items(m)' on any given
@@ -230,58 +223,57 @@ global value.
The following example expands the previous example but sets and resets
the max noutput_items both locally and globally.
-
-\code
-from gnuradio import gr, analog, blocks
-import time
-
-class mytb(gr.top_block):
- def __init__(self):
- gr.top_block.__init__(self)
-
- self.src0 = analog.noise_source_c(analog.GR_GAUSSIAN, 1)
- self.src1 = analog.noise_source_c(analog.GR_GAUSSIAN, 1)
- self.add = blocks.add_cc()
- self.sub = blocks.sub_cc()
- self.head = blocks.head(gr.sizeof_gr_complex, 1000000)
- self.snk = blocks.file_sink(gr.sizeof_gr_complex, "output.32fc")
-
- self.connect(self.src0, (self.add,0))
- self.connect(self.src1, (self.add,1))
- self.connect(self.add, self.head)
- self.connect(self.head, self.snk)
-
-def main():
- # Start the gr_top_block after setting some max noutput_items.
- tb = mytb()
- tb.src1.set_max_noutput_items(2000)
- tb.start(100)
- time.sleep(0.01)
-
- # Stop flowgraph and disconnect the add block
- tb.lock()
-
- tb.disconnect(tb.add, tb.head)
- tb.disconnect(tb.src0, (tb.add,0))
- tb.disconnect(tb.src1, (tb.add,1))
-
- # Connect the sub block
- tb.connect(tb.sub, tb.head)
- tb.connect(tb.src0, (tb.sub,0))
- tb.connect(tb.src1, (tb.sub,1))
-
- # Set new max_noutput_items for the gr_top_block
- # and unset the local value for src1
- tb.set_max_noutput_items(1000)
- tb.src1.unset_max_noutput_items()
- tb.unlock()
-
- tb.wait()
-
-if __name__ == "__main__":
- main()
-\endcode
-
-
-*/
-
+<syntaxhighlight lang="python">
+ from gnuradio import gr, analog, blocks
+ import time
+
+ class mytb(gr.top_block):
+ def __init__(self):
+ gr.top_block.__init__(self)
+
+ self.src0 = analog.noise_source_c(analog.GR_GAUSSIAN, 1)
+ self.src1 = analog.noise_source_c(analog.GR_GAUSSIAN, 1)
+ self.add = blocks.add_cc()
+ self.sub = blocks.sub_cc()
+ self.head = blocks.head(gr.sizeof_gr_complex, 1000000)
+ self.snk = blocks.file_sink(gr.sizeof_gr_complex, "output.32fc")
+
+ self.connect(self.src0, (self.add,0))
+ self.connect(self.src1, (self.add,1))
+ self.connect(self.add, self.head)
+ self.connect(self.head, self.snk)
+
+ def main():
+ # Start the gr_top_block after setting some max noutput_items.
+ tb = mytb()
+ tb.src1.set_max_noutput_items(2000)
+ tb.start(100)
+ time.sleep(0.01)
+
+ # Stop flowgraph and disconnect the add block
+ tb.lock()
+
+ tb.disconnect(tb.add, tb.head)
+ tb.disconnect(tb.src0, (tb.add,0))
+ tb.disconnect(tb.src1, (tb.add,1))
+
+ # Connect the sub block
+ tb.connect(tb.sub, tb.head)
+ tb.connect(tb.src0, (tb.sub,0))
+ tb.connect(tb.src1, (tb.sub,1))
+
+ # Set new max_noutput_items for the gr_top_block
+ # and unset the local value for src1
+ tb.set_max_noutput_items(1000)
+ tb.src1.unset_max_noutput_items()
+ tb.unlock()
+
+ tb.wait()
+
+ if __name__ == "__main__":
+ main()
+</syntaxhighlight></text>
+ <sha1>3arcnnd2d65pytajld93l8nvlqplnps</sha1>
+ </revision>
+ </page>
+</mediawiki> \ No newline at end of file
diff --git a/docs/doxygen/other/logger.dox b/docs/usage-manual/(exported from wiki) Logging.txt
index 00387768c0..acc288ab3f 100644
--- a/docs/doxygen/other/logger.dox
+++ b/docs/usage-manual/(exported from wiki) Logging.txt
@@ -1,29 +1,33 @@
-# Copyright (C) 2017 Free Software Foundation, Inc.
-#
-# Permission is granted to copy, distribute and/or modify this document
-# under the terms of the GNU Free Documentation License, Version 1.3
-# or any later version published by the Free Software Foundation;
-# with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
-# A copy of the license is included in the section entitled "GNU
-# Free Documentation License".
-
-/*! \page page_logger Logging
-
-\section logging Logging
-
-GNU Radio has a logging interface to enable various levels of logging
+<page>
+ <title>Logging</title>
+ <ns>0</ns>
+ <id>3484</id>
+ <revision>
+ <id>4183</id>
+ <timestamp>2018-05-15T19:17:50Z</timestamp>
+ <contributor>
+ <username>777arc</username>
+ <id>632</id>
+ </contributor>
+ <comment>first shot</comment>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="9367">GNU Radio has a logging interface to enable various levels of logging
information to be printed to the console or a file. The logger derives
-from log4cpp (http://log4cpp.sourceforge.net/) which is readily
+from [http://log4cpp.sourceforge.net log4cpp] which is readily
available in most Linux distributions. This is an optional dependency
and GNU Radio will work without it.
+When configuring GNU Radio, the -DENABLE_GR_LOG=On|Off option to cmake
+will allow the user to toggle use of the logger on and off. The logger
+defaults to "on" and will use log4cpp if it is available. If log4cpp
+is not found, the default logging will output to standard output or
+standard error, depending on the level of the log message.
+
Logging is useful for blocks to print out certain amounts of data at
different levels. These levels are:
-<pre>
DEBUG < INFO < WARN < TRACE < ERROR < ALERT < CRIT < FATAL < EMERG
-</pre>
-
The order here determines the level of output. These levels are
hierarchical in that specifying any level also includes any level
@@ -31,7 +35,7 @@ above it. For example, when using the INFO level, all INFO and
higher messages are logged and DEBUG is ignored. A level NOTSET is provided
to disable a logger.
-\subsection configfile Logging Configuration
+=== Logging Configuration ===
The logging configuration can be found in the gnuradio-runtime.conf file
under the [LOG] section. This allows us fairly complete control over
@@ -48,12 +52,10 @@ stream or file.
The four main configure options are:
-<pre>
log_level = debug
debug_level = debug
log_file = stdout
debug_file = stderr
-</pre>
This establishes the two loggers as having access to all levels of
logging events (DEBUG through EMERG). They are also configured not to
@@ -68,45 +70,36 @@ file.
When using either standard error or standard out, the messages for the
two different loggers will look like:
-<pre>
- gr::log :\<level\>: \<block alias\> - \<message\>
- gr::debug :\<level\>: \<block alias\> - \<message\>
-</pre>
+ gr::log :<level>: <block alias> - <message>
+ gr::debug :<level>: <block alias> - <message>
When using a file, the only difference in the format is that the
message prefix of "gr::log" or "gr::debug" is not used. Instead, the
time in milliseconds from the start of the program is inserted.
Remember that a local "~/.gnuradio/config.conf" file can be used to
-override any parameter in the global file (see \ref prefs for more
-details).
+override any parameter in the global file (see [[Configuration Files]] for more details).
To use these loggers inside of a GNU Radio block, we use the protected
data members of d_logger and d_debug_logger of gr_block and pass them
to our pre-defined macros:
-\code
GR_LOG_<level>(<logger>, "<Message to print>");
-\endcode
-Where \<level\> is one of the levels as mentioned above, \<logger\> is
-either d_logger or d_debug_logger, and \<Message to print\> is the
+Where <level> is one of the levels as mentioned above, <logger> is
+either d_logger or d_debug_logger, and <Message to print> is the
message we want to output. If we wanted to output an INFO level
message to the standard logger and a WARN level message to the debug
logger, it would look like this:
-\code
GR_LOG_INFO(d_logger, "Some info about the block");
GR_LOG_WARN(d_debug_logger, "Some warning about the block");
-\endcode
When this is printed to wherever you are directing the output of the
logger, it will look like:
-<pre>
gr::log :INFO: <block's alias> - Some info about the block
gr::debug :WARN: <block's alias> - Some warning about the block
-</pre>
This provides us information about where the message came from, the
level of the message, and the block that generated the message. We use
@@ -117,7 +110,6 @@ ID to distinguish it from other blocks of the same type.
The various logging macros are defined in gr_logger.h. Here are some
simple examples of using them:
-\code
GR_LOG_DEBUG(LOG, "DEBUG message");
GR_LOG_INFO(LOG, "INFO message");
GR_LOG_NOTICE(LOG, "NOTICE message");
@@ -127,15 +119,13 @@ simple examples of using them:
GR_LOG_ALERT(LOG, "ALERT message");
GR_LOG_FATAL(LOG, "FATAL message");
GR_LOG_EMERG(LOG, "EMERG message");
-\endcode
If the logger is not enabled, then these macros become nops and do
nothing (and d_logger and d_debug_logger are NULL pointers). If
logging is enabled but the log4cpp library is not found, then TRACE,
INFO, and NOTICE levels go to stdout and the rest to stderr.
-
-\subsection adv_config Advanced Configuration Options
+=== Advanced Configuration Options ===
If not using the simplified settings discussed above, where we can
direct the logger messages to either a file or one of the standard
@@ -146,19 +136,15 @@ configuration works and looks. Mostly, a default configuration script
provided with GNU Radio can be used. After installation, the default
configuration script is located at:
-<pre>
$prefix/etc/gnuradio/gr_log_default.conf
-</pre>
For the following examples, we will assume that our local
"~/.gnuradio/config.conf" looks like this:
-\code
-[LOG]
-log_config = /opt/gr/etc/gnuadio/gr_log_default.conf
-log_level = debug
-debug_level = Off
-\endcode
+ [LOG]
+ log_config = /opt/gr/etc/gnuadio/gr_log_default.conf
+ log_level = debug
+ debug_level = Off
Inside of the default configuration file, we define the parameters
for the two logger's, the standard logger the separate debug logger.
@@ -177,8 +163,7 @@ If both an XML configuration file is set and the "log_file" or
actually used. So you can configure file access and the pattern
through the XML file while also still outputting to stdout or stderr.
-
-\section advlog Advanced Usage
+== Advanced Usage ==
The description above for using the logging facilities is specific to
GNU Radio blocks. We have put the code necessary to access the
@@ -193,20 +178,18 @@ snippet shows how to do this to get access to the standard logger,
which has a root of "gr_log." (access to the debug logger is similar
except we would use "gr_log_debug." in the GR_LOG_GETLOGGER call):
-\code
prefs *p = prefs::singleton();
std::string log_file = p->get_string("LOG", "log_config", "");
std::string log_level = p->get_string("LOG", "log_level", "off");
GR_CONFIG_LOGGER(log_file);
GR_LOG_GETLOGGER(LOG, "gr_log." + "my_logger_name");
GR_LOG_SET_LEVEL(LOG, log_level);
-\endcode
This creates a pointer called LOG (which is instantiated as a
log4cpp:LoggerPtr in the macro) that we can now use locally as the
input to our logging macros like 'GR_LOG_INFO(LOG, "message")'.
-\subsection using_logging Using Logging in Out of Tree Modules
+=== Using Logging in Out of Tree Modules ===
In order to use the logging interface in an out of tree module based on a
gr_modtool template module, several CMake modifications are required.
@@ -224,24 +207,24 @@ directory of the OOT module.
Once these CMake changes are made, the GR logging interface will function
as documented on this page.
-\section logPy Logging from Python
+== Logging from Python ==
The logging capability has been brought out python via swig. The configuration
of the logger can be manipulated via the following calls:
-\code
+
from gnuradio import gr
gr.logger_config(filename,watch_period) # Configures the logger with conf file filename
names = gr.logger_get_names() # Returns the names of all loggers
gr.logger_reset_config() # Resets logger config by removing all appenders
-\endcode
Once the logger is configured you can manipulate a logger via a wrapper class gr.logger().
You can isntantiate this by the following. (Reference logger.h for list of methods)
-\code
+
from gnuradio import gr
log=gr.logger("nameOfLogger")
log.debug("Log a debug message")
- log.set_level("INFO");
-
-\endcode
-*/
+ log.set_level("INFO");</text>
+ <sha1>at9a5on70hlibjm75oo3rtgswcsu1u9</sha1>
+ </revision>
+ </page>
+</mediawiki> \ No newline at end of file
diff --git a/docs/doxygen/other/msg_passing.dox b/docs/usage-manual/(exported from wiki) Message Passing.txt
index 14de7bae4c..4654bd5dac 100644
--- a/docs/doxygen/other/msg_passing.dox
+++ b/docs/usage-manual/(exported from wiki) Message Passing.txt
@@ -1,15 +1,19 @@
-# Copyright (C) 2017 Free Software Foundation, Inc.
-#
-# Permission is granted to copy, distribute and/or modify this document
-# under the terms of the GNU Free Documentation License, Version 1.3
-# or any later version published by the Free Software Foundation;
-# with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
-# A copy of the license is included in the section entitled "GNU
-# Free Documentation License".
-
-/*! \page page_msg_passing Message Passing
-
-\section msg_passing_introduction Introduction
+<page>
+ <title>Message Passing</title>
+ <ns>0</ns>
+ <id>3481</id>
+ <revision>
+ <id>4294</id>
+ <parentid>4287</parentid>
+ <timestamp>2018-06-26T19:55:38Z</timestamp>
+ <contributor>
+ <username>777arc</username>
+ <id>632</id>
+ </contributor>
+ <comment>/* Code Examples */</comment>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="15505">== Introduction ==
GNU Radio was originally a streaming system with no other mechanism to
pass data between blocks. Streams of data are a model that work well
@@ -17,8 +21,7 @@ for samples, bits, etc., but are not really the right mechanism for
control data, metadata, or packet structures (at least at
some point in the processing chain).
-We solved part of this problem by introducing the tag stream (see \ref
-page_stream_tags). This is a parallel stream to the data
+We solved part of this problem by introducing the tag stream (see [[Stream Tags]]). This is a parallel stream to the data
streaming. The difference is that tags are designed to hold metadata
and control information. Tags are specifically associated with a
particular sample in the data stream and flow downstream alongside the
@@ -37,9 +40,9 @@ it does so on an asynchronous basis.
The message passing interface heavily relies on Polymorphic Types
(PMTs) in GNU Radio. For further information about these data
-structures, see the page \ref page_pmt.
+structures, see the page [[Polymorphic Types (PMTs)]].
-\section msg_passing_api Message Passing API
+== Message Passing API ==
The message passing interface is designed into the gr::basic_block,
which is the parent class for all blocks in GNU Radio. Each block has
@@ -49,35 +52,27 @@ distinguish between input and output ports.
A block has to declare its input and output message ports in its
constructor. The message ports are described by a name, which is in
-practice a PMT symbol (<em>i.e.</em>, an interned string). The API calls
+practice a PMT symbol (i.e., an interned string). The API calls
to register a new port are:
-\code
void message_port_register_in(pmt::pmt_t port_id)
void message_port_register_out(pmt::pmt_t port_id)
-\endcode
In Python:
-\code
self.message_port_register_in(pmt.intern("port name"))
self.message_port_register_out(pmt.intern("port name"))
-\endcode
The ports are now identifiable by that port name. Other blocks who may
want to post or receive messages on a port must subscribe to it. When
a block has a message to send, they are published on a particular
port using the following API:
-\code
void message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg);
-\endcode
In Python:
-\code
self.message_port_pub(pmt.intern("port name"), <pmt message>)
-\endcode
Subscribing is usually done in the form of connecting message ports
as part of the flowgraph, as discussed later. Internally, when message
@@ -90,8 +85,7 @@ block publishes a message, it simply iterates through all blocks that
have subscribed and uses the gr::basic_block::_post method to send the
message to that block's message queue.
-
-\subsection msg_passing_msg_handler Message Handler Functions
+=== Message Handler Functions ===
A subscriber block must declare a message handler function to process
the messages that are posted to it. After using the
@@ -99,16 +93,12 @@ gr::basic_block::message_port_register_in to declare a subscriber port, we
must then bind this port to the message handler. For this, we use
Boost's 'bind' function:
-\code
set_msg_handler(pmt::pmt_t port_id,
boost::bind(&block_class::message_handler_function, this, _1));
-\endcode
In Python:
-\code
self.set_msg_handler(pmt.intern("port name"), <msg handler function>)
-\endcode
When a new message is pushed onto a port's message queue,
it is this function that is used to process the message.
@@ -121,20 +111,15 @@ OOP practice) and the _1 is an indicator that the function expects 1
additional argument. The prototype for all message handling functions
is:
-\code
void block_class::message_handler_function(pmt::pmt_t msg);
-\endcode
In Python the equivalent function would be:
-\code
def handle_msg(self, msg):
-\endcode
We give examples of using this below.
-
-\subsection msg_passing_fg_connect Connecting Messages through the Flowgraph
+=== Connecting Messages through the Flowgraph ===
From the flowgraph level, we have instrumented a gr::hier_block2::msg_connect
method to make it easy to subscribe blocks to other blocks'
@@ -142,12 +127,10 @@ messages. Assume that the block \b src has an output message port named
\a pdus and the block \b dbg has an input port named \a print. The message
connection in the flowgraph (in Python) looks like the following:
-\code
self.tb.msg_connect(src, "pdus", dbg, "print")
-\endcode
-All messages published by the \b src block on port \a pdus will be
-received by \b dbg on port \a print. Note here how we are just using
+All messages published by the '''src''' block on port ''pdus'' will be
+received by '''dbg''' on port ''print''. Note here how we are just using
strings to define the ports, not PMT symbols. This is a convenience to
the user to be able to more easily type in the port names (for
reference, you can create a PMT symbol in Python using the
@@ -156,10 +139,8 @@ pmt::intern function as pmt.intern("string")).
Users can also query blocks for the names of their input and output
ports using the following API calls:
-\code
pmt::pmt_t message_ports_in();
pmt::pmt_t message_ports_out();
-\endcode
The return value for these are a PMT vector filled with PMT symbols,
so PMT operators must be used to manipulate them.
@@ -173,8 +154,7 @@ message. Posting messages also has the benefit of waking up the
block's thread if it is in a wait state. So if idle, as soon as a
message is posted, it will wake up and call the message handler.
-
-\section msg_passing_posting Posting from External Sources
+== Posting from External Sources ==
An important feature of the message passing architecture
is how it can be used to take in messages from an external source. We
@@ -188,16 +168,14 @@ messages as PDUs posted to it and convert them to a normal stream. The
payload will be sent on as a normal stream while the meta data will be
decoded into tags and sent on the tagged stream.
-So if we have created a \b src block as a PDU to stream, it has a \a
-pdus input port, which is how we will inject PDU messages into the
+So if we have created a '''src''' block as a PDU to stream, it has a
+''pdus'' input port, which is how we will inject PDU messages into the
flowgraph. These PDUs could come from another block or flowgraph, but
here, we will create and insert them by hand.
-\code
port = pmt.intern("pdus")
msg = pmt.cons(pmt.PMT_NIL, pmt.make_u8vector(16, 0xFF))
src.to_basic_block()._post(port, msg)
-\endcode
The PDU's metadata section is empty, hence the pmt::PMT_NIL
object. The payload is now just a simple vector of 16 bytes of all
@@ -210,31 +188,23 @@ All of these mechanisms are explored and tested in the QA code of the
file qa_pdu.py.
There are some examples of using the message passing infrastructure
-through GRC in gr-blocks/examples/msg_passing.
+through GRC in:
+ gr-blocks/examples/msg_passing
-\section msg_passing_commands Using messages as commands
+== Using Messages as Commands ==
One important use of messages is 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
+* 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).
+* 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.
@@ -243,18 +213,13 @@ It might be tempting to deviate from this format, e.g. the QT Frequency sink cou
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 it's 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.
+* 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 it's 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.
+== Code Examples ==
-\section msg_passing_examples Code Examples
+=== C++ ===
The following is snippets of code from blocks currently in GNU Radio
that take advantage of message passing. We will be using
@@ -262,53 +227,52 @@ gr::blocks::message_debug and gr::blocks::tagged_stream_to_pdu below
to show setting up both input and output message passing capabilities.
The gr::blocks::message_debug block is used for debugging the message
-passing system. It describes three input message ports: \a print, \a
-store, and \a pdu_print. The \a print port simply prints out all
-messages to standard out while the \a store port keeps a list of all
-messages posted to it. The \a pdu_print port specially formats PDU
-messages for printing to standard out. The \a store port works in
+passing system. It describes three input message ports: ''print'',
+''store'', and ''pdu_print''. The ''print'' port simply prints out all
+messages to standard out while the ''store'' port keeps a list of all
+messages posted to it. The ''pdu_print'' port specially formats PDU
+messages for printing to standard out. The ''store'' port works in
conjunction with a gr::blocks::message_debug::get_message(int i) call
-that allows us to retrieve message \p i afterward.
+that allows us to retrieve message i afterward.
The constructor of this block looks like this:
-\code
-{
- message_port_register_in(pmt::mp("print"));
- set_msg_handler(pmt::mp("print"),
- boost::bind(&message_debug_impl::print, this, _1));
-
- message_port_register_in(pmt::mp("store"));
- set_msg_handler(pmt::mp("store"),
- boost::bind(&message_debug_impl::store, this, _1));
-
- message_port_register_in(pmt::mp("print_pdu"));
- set_msg_handler(pmt::mp("print_pdu"),
- boost::bind(&message_debug_impl::print_pdu, this, _1));
-}
-\endcode
+<syntaxhighlight lang="cpp">
+ {
+ message_port_register_in(pmt::mp("print"));
+ set_msg_handler(pmt::mp("print"),
+ boost::bind(&message_debug_impl::print, this, _1));
+
+ message_port_register_in(pmt::mp("store"));
+ set_msg_handler(pmt::mp("store"),
+ boost::bind(&message_debug_impl::store, this, _1));
+
+ message_port_register_in(pmt::mp("print_pdu"));
+ set_msg_handler(pmt::mp("print_pdu"),
+ boost::bind(&message_debug_impl::print_pdu, this, _1));
+ }
+</syntaxhighlight>
The three message input ports are registered by their respective
names. We then use the gr::basic_block::set_msg_handler function to
identify this particular port name with a callback function. The
-Boost \a bind function (<a target="_blank"
-href="http://www.boost.org/doc/libs/1_52_0/libs/bind/bind.html">Boost::bind</a>)
+Boost ''bind'' function ([http://www.boost.org/doc/libs/1_52_0/libs/bind/bind.html Boost::bind])
here binds the callback to a function of this block's class. So now
the functions in the block's private implementation class,
gr::blocks::message_debug_impl::print,
gr::blocks::message_debug_impl::store, and
gr::blocks::message_debug_impl::print_pdu, are assigned to handle
-messages passed to them. Below is the \a print function for reference.
-
-\code
-void
-message_debug_impl::print(pmt::pmt_t msg)
-{
- std::cout << "***** MESSAGE DEBUG PRINT ********\n";
- pmt::print(msg);
- std::cout << "**********************************\n";
-}
-\endcode
+messages passed to them. Below is the ''print'' function for reference.
+
+<syntaxhighlight lang="cpp">
+ void
+ message_debug_impl::print(pmt::pmt_t msg)
+ {
+ std::cout << "***** MESSAGE DEBUG PRINT ********\n";
+ pmt::print(msg);
+ std::cout << "**********************************\n";
+ }
+</syntaxhighlight>
The function simply takes in the PMT message and prints it. The method
pmt::print is a function in the PMT library to print the
@@ -317,14 +281,12 @@ PMT in a friendly and (mostly) pretty manner.
The gr::blocks::tagged_stream_to_pdu block only defines a single
output message port. In this case, its constructor contains the line:
-\code
-{
- message_port_register_out(pdu_port_id);
-}
-\endcode
+ {
+ message_port_register_out(pdu_port_id);
+ }
-So we are only creating a single output port where \a pdu_port_id
-is defined in the file pdu.h as \a pdus.
+So we are only creating a single output port where ''pdu_port_id''
+is defined in the file pdu.h as ''pdus''.
This block's purpose is to take in a stream of samples along with
stream tags and construct a predefined PDU message from it. In GNU
@@ -341,25 +303,25 @@ In the end, when a PDU message is ready, the block calls its
gr::blocks::tagged_stream_to_pdu_impl::send_message function that is
shown below.
-\code
-void
-tagged_stream_to_pdu_impl::send_message()
-{
- if(pmt::length(d_pdu_vector) != d_pdu_length) {
- throw std::runtime_error("msg length not correct");
- }
-
- pmt::pmt_t msg = 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;
-}
-\endcode
+<syntaxhighlight lang="cpp">
+ void
+ tagged_stream_to_pdu_impl::send_message()
+ {
+ if(pmt::length(d_pdu_vector) != d_pdu_length) {
+ throw std::runtime_error("msg length not correct");
+ }
+
+ pmt::pmt_t msg = 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;
+ }
+</syntaxhighlight>
This function does a bit of checking to make sure the PDU is OK as
well as some cleanup in the end. But it is the line where the message
@@ -369,13 +331,34 @@ gr::basic_block::message_port_pub publishing method.
There is similarly a gr::blocks::pdu_to_tagged_stream block that essentially
does the opposite. It acts as a source to a flowgraph and waits for
-PDU messages to be posted to it on its input port \a pdus. It extracts
+PDU messages to be posted to it on its input port ''pdus''. It extracts
the metadata and data and processes them. The metadata dictionary is
split up into key:value pairs and stream tags are created out of
them. The data is then converted into an output stream of items and
passed along. The next section describes how PDUs can be passed into a
flowgraph using the gr::blocks::pdu_to_tagged_stream block.
-For a Python block example, see \ref pyblocks_msgs.
-
-*/
+=== Python ===
+
+A Python Block example:
+
+<syntaxhighlight lang="python">
+ class msg_block(gr.basic_block):
+ def __init__(self):
+ gr.basic_block.__init__(
+ self,
+ name="msg_block",
+ in_sig=None,
+ out_sig=None)
+
+ self.message_port_register_out(pmt.intern('msg_out'))
+ self.message_port_register_in(pmt.intern('msg_in'))
+ self.set_msg_handler(pmt.intern('msg_in'), self.handle_msg)
+
+ def handle_msg(self, msg):
+ self.message_port_pub(pmt.intern('msg_out'), pmt.intern('message received!'))
+</syntaxhighlight></text>
+ <sha1>2o3zxqazokbseo12y27nl24a8nuw50r</sha1>
+ </revision>
+ </page>
+</mediawiki> \ No newline at end of file
diff --git a/docs/doxygen/other/metadata.dox b/docs/usage-manual/(exported from wiki) Metadata Information.txt
index b58d2a6aee..410e6ad66f 100644
--- a/docs/doxygen/other/metadata.dox
+++ b/docs/usage-manual/(exported from wiki) Metadata Information.txt
@@ -1,15 +1,18 @@
-# Copyright (C) 2017 Free Software Foundation, Inc.
-#
-# Permission is granted to copy, distribute and/or modify this document
-# under the terms of the GNU Free Documentation License, Version 1.3
-# or any later version published by the Free Software Foundation;
-# with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
-# A copy of the license is included in the section entitled "GNU
-# Free Documentation License".
-
-/*! \page page_metadata Metadata Information
-
-\section metadata_introduction Introduction
+<page>
+ <title>Metadata Information</title>
+ <ns>0</ns>
+ <id>3479</id>
+ <revision>
+ <id>4293</id>
+ <parentid>4159</parentid>
+ <timestamp>2018-06-26T19:54:28Z</timestamp>
+ <contributor>
+ <username>777arc</username>
+ <id>632</id>
+ </contributor>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="14458">== Introduction ==
Metadata files have extra information in the form of headers that
carry metadata about the samples in the file. Raw, binary files carry
@@ -31,20 +34,20 @@ information regarding the header size and segment size.
The first static portion of the header file contains the following
information.
-- version: (char) version number (usually set to METADATA_VERSION)
-- rx_rate: (double) Stream's sample rate
-- rx_time: (pmt::pmt_t pair - (uint64_t, double)) Time stamp (format from UHD)
-- size: (int) item size in bytes - reflects vector length if any
-- type: (int) data type (enum below)
-- cplx: (bool) true if data is complex
-- strt: (uint64_t) start of data relative to current header
-- bytes: (uint64_t) size of following data segment in bytes
+* version: (char) version number (usually set to METADATA_VERSION)
+* rx_rate: (double) Stream's sample rate
+* rx_time: (pmt::pmt_t pair - (uint64_t, double)) Time stamp (format from UHD)
+* size: (int) item size in bytes - reflects vector length if any
+* type: (int) data type (enum below)
+* cplx: (bool) true if data is complex
+* strt: (uint64_t) start of data relative to current header
+* bytes: (uint64_t) size of following data segment in bytes
An optional extra section of the header stores information in any
received tags. The two main tags associated with headers are:
-- rx_rate: the sample rate of the stream.
-- rx_time: the time stamp of the first item in the segment.
+* rx_rate: the sample rate of the stream.
+* rx_time: the time stamp of the first item in the segment.
These tags were inspired by the UHD tag format.
@@ -61,21 +64,19 @@ that should be transmitted along with the data. It also grows whenever
it sees a stream tag, so the dictionary will contain any key:value
pairs out of tags from the flowgraph.
-
-\subsection metadata_types Types of Metadata Files
+=== Types of Metadata Files ===
GNU Radio currently supports two types of metadata files:
-- inline: headers are inline with the data in the same file.
-- detached: headers are in a separate header file from the data.
+# inline: headers are inline with the data in the same file.
+# detached: headers are in a separate header file from the data.
The inline method is the standard version. When a detached header is
used, the headers are simply inserted back-to-back in the detached
header file. The dat file, then, is the standard raw binary format
with no interruptions in the data.
-
-\subsection metadata_updating Updating Headers
+=== Updating Headers ===
While there is always a header that starts a metadata file, they are
updated throughout as well. There are two events that trigger a new
@@ -106,8 +107,7 @@ segment loss is observed, it will generate a new timestamp as a tag of
'rx_time'. We create a new file segment that reflects this change to
keep the sample times exact.
-
-\subsection metadata_implementation Implementation
+=== Implementation ===
Metadata files are created using gr::blocks::file_meta_sink. The
default behavior is to create a single file with inline headers as
@@ -121,8 +121,7 @@ output. The 'rx_rate' and 'rx_time' and all key:value pairs in the
extra header are converted into tags and added to the stream tags
interface.
-
-\section metadata_structure Structure
+== Structure ==
The file metadata consists of a static mandatory header and a dynamic
optional extras header. Each header is a separate PMT
@@ -137,14 +136,14 @@ To work with the PMTs for creating and extracting header information,
we use PMT operators. For example, we create a simplified version of
the header in C++ like this:
-\code
- const char METADATA_VERSION = 0x0;
- pmt::pmt_t header;
- header = pmt::make_dict();
- header = pmt::dict_add(header, pmt::mp("version"), pmt::mp(METADATA_VERSION));
- header = pmt::dict_add(header, pmt::mp("rx_rate"), pmt::mp(samp_rate));
- std::string hdr_str = pmt::serialize_str(header);
-\endcode
+<syntaxhighlight lang="cpp">
+ const char METADATA_VERSION = 0x0;
+ pmt::pmt_t header;
+ header = pmt::make_dict();
+ header = pmt::dict_add(header, pmt::mp("version"), pmt::mp(METADATA_VERSION));
+ header = pmt::dict_add(header, pmt::mp("rx_rate"), pmt::mp(samp_rate));
+ std::string hdr_str = pmt::serialize_str(header);
+</syntaxhighlight>
The call to pmt::dict_add adds a new key:value pair to the
dictionary. Notice that it both takes and returns the 'header'
@@ -172,14 +171,14 @@ arrays (e.g., 'char *s') get confused.
Assuming that 'std::string str' contains the full string as read from
a file, we can access the dictionary in C++ like this:
-\code
- pmt::pmt_t hdr = pmt::deserialize_str(str);
- if(pmt::dict_has_key(hdr, pmt::string_to_symbol("strt"))) {
- pmt::pmt_t r = pmt::dict_ref(hdr, pmt::string_to_symbol("strt"), pmt::PMT_NIL);
- uint64_t seg_start = pmt::to_uint64(r);
- uint64_t extra_len = seg_start - METADATA_HEADER_SIZE;
- }
-\endcode
+<syntaxhighlight lang="cpp">
+ pmt::pmt_t hdr = pmt::deserialize_str(str);
+ if(pmt::dict_has_key(hdr, pmt::string_to_symbol("strt"))) {
+ pmt::pmt_t r = pmt::dict_ref(hdr, pmt::string_to_symbol("strt"), pmt::PMT_NIL);
+ uint64_t seg_start = pmt::to_uint64(r);
+ uint64_t extra_len = seg_start - METADATA_HEADER_SIZE;
+ }
+</syntaxhighlight>
This example first deserializes the string into a PMT dictionary
again. This will throw an error if the string is malformed and cannot
@@ -200,40 +199,37 @@ the size of the serialized PMT dictionary in bytes, so we can easily
read this many bytes from the file. We can then deserialize and parse
this header just like the first.
-
-\subsection metadata_header Header Information
+=== Header Information ===
The header is a PMT dictionary with a known structure. This structure
may change, but we version the headers, so all headers of version X
must be the same length and structure. As of now, we only have version
0 headers, which look like the following:
-- version: (char) version number (usually set to METADATA_VERSION)
-- rx_rate: (double) Stream's sample rate
-- rx_time: (pmt::pmt_t pair - (uint64_t, double)) Time stamp (format from UHD)
-- size: (int) item size in bytes - reflects vector length if any.
-- type: (int) data type (enum below)
-- cplx: (bool) true if data is complex
-- strt: (uint64_t) start of data relative to current header
-- bytes: (uint64_t) size of following data segment in bytes
+* version: (char) version number (usually set to METADATA_VERSION)
+* rx_rate: (double) Stream's sample rate
+* rx_time: (pmt::pmt_t pair - (uint64_t, double)) Time stamp (format from UHD)
+* size: (int) item size in bytes - reflects vector length if any.
+* type: (int) data type (enum below)
+* cplx: (bool) true if data is complex
+* strt: (uint64_t) start of data relative to current header
+* bytes: (uint64_t) size of following data segment in bytes
The data types are indicated by an integer value from the following
enumeration type:
-\code
-enum gr_file_types {
- GR_FILE_BYTE=0,
- GR_FILE_CHAR=0,
- GR_FILE_SHORT=1,
- GR_FILE_INT,
- GR_FILE_LONG,
- GR_FILE_LONG_LONG,
- GR_FILE_FLOAT,
- GR_FILE_DOUBLE,
-};
-\endcode
-
-\subsection metadata_extras Extras Information
+ enum gr_file_types {
+ GR_FILE_BYTE=0,
+ GR_FILE_CHAR=0,
+ GR_FILE_SHORT=1,
+ GR_FILE_INT,
+ GR_FILE_LONG,
+ GR_FILE_LONG_LONG,
+ GR_FILE_FLOAT,
+ GR_FILE_DOUBLE,
+ };
+
+=== Extras Information ===
The extras section is an optional segment of the header. If 'strt' ==
METADATA_HEADER_SIZE, then there is no extras. Otherwise, it is simply
@@ -263,22 +259,19 @@ ability to do pmt::print on any PMT object to print it to
screen. Before converting from a PMT to its natural data type, it is
necessary to know the data type.
-
-\section metadata_utilities Utilities
+== Utilities ==
GNU Radio comes with a couple of utilities to help in debugging and
manipulating metadata files. There is a general parser in Python that
will convert the PMT header and extra header into Python
dictionaries. This utility is:
-- gr-blocks/python/parse_file_metadata.py
+* gr-blocks/python/parse_file_metadata.py
This program is installed into the Python directory under the
'gnuradio' module, so it can be accessed with:
-\code
-from gnuradio.blocks import parse_file_metadata
-\endcode
+ from gnuradio.blocks import parse_file_metadata
It defines HEADER_LENGTH as the static length of the metadata header
size. It also has dictionaries that can be used to convert from the
@@ -300,19 +293,18 @@ command-line argument. An option '-D' will handle detached header
files where the file of headers is expected to be the file name of the
data with '.hdr' appended to it.
-
-\section metadata_examples Examples
+== Examples ==
Examples are located in:
-- gr-blocks/examples/metadata
+* gr-blocks/examples/metadata
Currently, there are a few GRC example programs.
-- file_metadata_sink: create a metadata file from UHD samples.
-- file_metadata_source: read the metadata file as input to a simple graph.
-- file_metadata_vector_sink: create a metadata file from UHD samples.
-- file_metadata_vector_source: read the metadata file as input to a simple graph.
+* file_metadata_sink: create a metadata file from UHD samples.
+* file_metadata_source: read the metadata file as input to a simple graph.
+* file_metadata_vector_sink: create a metadata file from UHD samples.
+* file_metadata_vector_source: read the metadata file as input to a simple graph.
The file sink example can be switched to use a signal source instead
of a UHD source, but no extra tagged data is used in this mode.
@@ -329,22 +321,23 @@ metadata file. This example is just showing how we can insert a date
into the metadata to keep track of it later. The date in this case is
encoded as a vector of uint16 with [day, month, year].
-\code
- import pmt
- from gnuradio import blocks
-
- key = pmt.intern("date")
- val = pmt.init_u16vector(3, [13,12,2012])
-
- extras = pmt.make_dict()
- extras = pmt.dict_add(extras, key, val)
- extras_str = pmt.serialize_str(extras)
- self.sink = blocks.file_meta_sink(gr.sizeof_gr_complex,
- "/tmp/metadat_file.out",
- samp_rate, 1,
- blocks.GR_FILE_FLOAT, True,
- 1000000, extra_str, False)
-
-\endcode
-
-*/
+<syntaxhighlight lang="python">
+ import pmt
+ from gnuradio import blocks
+
+ key = pmt.intern("date")
+ val = pmt.init_u16vector(3, [13,12,2012])
+
+ extras = pmt.make_dict()
+ extras = pmt.dict_add(extras, key, val)
+ extras_str = pmt.serialize_str(extras)
+ self.sink = blocks.file_meta_sink(gr.sizeof_gr_complex,
+ "/tmp/metadat_file.out",
+ samp_rate, 1,
+ blocks.GR_FILE_FLOAT, True,
+ 1000000, extra_str, False)
+</syntaxhighlight></text>
+ <sha1>8f3uw6sq1s6a90diya9eycq96qyzdr3</sha1>
+ </revision>
+ </page>
+</mediawiki> \ No newline at end of file
diff --git a/docs/doxygen/other/perf_counters.dox b/docs/usage-manual/(exported from wiki) Performance Counters.txt
index 7562b11298..7735bfc840 100644
--- a/docs/doxygen/other/perf_counters.dox
+++ b/docs/usage-manual/(exported from wiki) Performance Counters.txt
@@ -1,15 +1,19 @@
-# Copyright (C) 2017 Free Software Foundation, Inc.
-#
-# Permission is granted to copy, distribute and/or modify this document
-# under the terms of the GNU Free Documentation License, Version 1.3
-# or any later version published by the Free Software Foundation;
-# with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
-# A copy of the license is included in the section entitled "GNU
-# Free Documentation License".
-
-/*! \page page_perf_counters Performance Counters
-
-\section pc_introduction Introduction
+<page>
+ <title>Performance Counters</title>
+ <ns>0</ns>
+ <id>3485</id>
+ <revision>
+ <id>4185</id>
+ <parentid>4184</parentid>
+ <timestamp>2018-05-15T19:32:41Z</timestamp>
+ <contributor>
+ <username>777arc</username>
+ <id>632</id>
+ </contributor>
+ <comment>/* Run-time Config */</comment>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="3590">== Introduction ==
Each block can have a set of Performance Counters that the schedule
keeps track of. These counters measure and store information about
@@ -17,24 +21,22 @@ different performance metrics of their operation. The concept is
fairly extensible, but currently, GNU Radio defines the following
Performance Counters:
-\li noutput_items: number of items the block can produce.
-\li nproduced: the number of items the block produced.
-\li input_buffers_full: % of how full each input buffer is.
-\li output_buffers_full: % of how full each output buffer is.
-\li work_time: number of CPU ticks during the call to general_work().
-\li work_time_total: Accumulated sum of work_time.
+# noutput_items: number of items the block can produce.
+# nproduced: the number of items the block produced.
+# input_buffers_full: % of how full each input buffer is.
+# output_buffers_full: % of how full each output buffer is.
+# work_time: number of CPU ticks during the call to general_work().
+# work_time_total: Accumulated sum of work_time.
For each Performance Counter except the work_time_total, we can
retrieve the instantaneous, average, and variance from the
block. Access to these counters is done through a simple set of
functions added to every block in the flowgraph:
-\code
float pc_<name>[_<type>]();
-\endcode
-In the above, the \<name\> field is one of the counters in the above
-list of counters. The optional \<type\> suffix is either 'avg' to get
+In the above, the <name> field is one of the counters in the above
+list of counters. The optional <type> suffix is either 'avg' to get
the average value or 'var' to get the variance. Without a suffix, the
function returns the most recent instantaneous value.
@@ -42,12 +44,9 @@ We can also reset the Performance Counters back to zero to remove any
history of the current average and variance calculations for a
particular block.
-\code
void reset_perf_counters();
-\endcode
-
-\section pc_config Compile-time and Run-time Configuration
+== Compile-time and Run-time Configuration ==
Because the Performance Counters are calculated during each call to
work for every block, they increase the computational cost and memory
@@ -58,16 +57,13 @@ a 24-block flowgraph), we err on the side of minimizing overhead in
the scheduler. To do so, we have added compile-time and run-time
configuration of the use of Performance Counters.
-
-\subsection pc_config_compile Compile-time Config
+=== Compile-time Config ===
By default, GNU Radio will build without Performance Counters
enabled. To enable Performance Counters, we pass the following flag to
cmake:
-\code
-DENABLE_PERFORMANCE_COUNTERS=True
-\endcode
Note that this affects the GNU Radio block class and the scheduler
itself. Out-of-tree projects will inherit directly from GNU Radio
@@ -75,33 +71,30 @@ because of the inheritance with gr::block. Turning on Performance
Counters for GNU Radio will require a recompilation of the OOT project
but no extra configuration.
-
-\subsection pc_config_runtime Run-time Config
+=== Run-time Config ===
Given the Performance Counters are enabled in GNU Radio at
compile-time, we can still control if they are used or not at
run-time. For this, we use the GNU Radio preferences file in the
-section [PerfCounters]. This section is installed into the
+section '''PerfCounters'''. This section is installed into the
gnuradio-runtime.conf file. As usual with the preferences, this
section or any of the individual options can be overridden in the
-user's config.conf file or using a GR_CONF_ environmental variable
-(see \ref prefs for more details).
-
-The options for the [PerfCounters] section are:
+user's config.conf file or using a GR_CONF_ environmental variable.
-\li on: Turn counters on/off at run-time.
-\li export: Allow counters to be exported over ControlPort.
-\li clock: sets the type of clock used when calculating work_time
-('thread' or 'monotonic').
+The options for the '''PerfCounters''' section are:
+# on: Turn counters on/off at run-time.
+# export: Allow counters to be exported over ControlPort.
+# clock: sets the type of clock used when calculating work_time ('thread' or 'monotonic').
-\section pc_perfmonitor Performance Monitor
+== Performance Monitor ==
-See \ref perfmonitor for some details of using a ControlPort-based
-monitor application, gr-perf-monitorx, for visualizing the
+See [ControlPort#Performance Monitor] for some details of using a ControlPort-based monitor application, gr-perf-monitorx, for visualizing the
counters. This application is particularly useful in learning which
blocks are the computationally complex blocks that could use extra
optimization or work to improve their performance. It can also be used
-to understand the current 'health' of the application.
-
-*/
+to understand the current 'health' of the application.</text>
+ <sha1>fwupl0jgeaweqt982b4ly5ycqonuce0</sha1>
+ </revision>
+ </page>
+</mediawiki> \ No newline at end of file
diff --git a/docs/usage-manual/(exported from wiki) Polymorphic Types (PMTs).txt b/docs/usage-manual/(exported from wiki) Polymorphic Types (PMTs).txt
new file mode 100644
index 0000000000..15f2a22450
--- /dev/null
+++ b/docs/usage-manual/(exported from wiki) Polymorphic Types (PMTs).txt
@@ -0,0 +1,473 @@
+<page>
+ <title>Polymorphic Types (PMTs)</title>
+ <ns>0</ns>
+ <id>3478</id>
+ <revision>
+ <id>4292</id>
+ <parentid>4157</parentid>
+ <timestamp>2018-06-26T19:45:45Z</timestamp>
+ <contributor>
+ <username>777arc</username>
+ <id>632</id>
+ </contributor>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="16713">== Introduction ==
+
+Polymorphic Types are opaque data types that are designed as generic
+containers of data that can be safely passed around between blocks and
+threads in GNU Radio. They are heavily used in the stream tags and
+message passing interfaces. The most complete list of PMT function is,
+of course, the source code, specifically the header file [https://gnuradio.org/doc/doxygen/pmt_8h.html pmt.h]. This page summarizes the most important features and points of PMTs.
+
+Let's dive straight into some Python code and see how we can use
+PMTs:
+<syntaxhighlight lang="python">
+ >>> import pmt
+ >>> P = pmt.from_long(23)
+ >>> type(P)
+ <class 'pmt.pmt_swig.swig_int_ptr'>
+ >>> print P
+ 23
+ >>> P2 = pmt.from_complex(1j)
+ >>> type(P2)
+ <class 'pmt.pmt_swig.swig_int_ptr'>
+ >>> print P2
+ 0+1i
+ >>> pmt.is_complex(P2)
+ True
+</syntaxhighlight>
+First, the pmt module is imported. We assign two values (P and P2)
+with PMTs using the from_long() and from_complex() calls,
+respectively. As we can see, they are both of the same type! This
+means we can pass these variables to C++ through SWIG, and C++ can
+handle this type accordingly.
+
+The same code as above in C++ would look like this:
+<syntaxhighlight lang="c++">
+ #include <pmt/pmt.h>
+ // [...]
+ pmt::pmt_t P = pmt::from_long(23);
+ std::cout << P << std::endl;
+ pmt::pmt_t P2 = pmt::from_complex(gr_complex(0, 1)); //
+ Alternatively: pmt::from_complex(0, 1)
+ std::cout << P2 << std::endl;
+ std::cout << pmt::is_complex(P2) << std::endl;
+</syntaxhighlight>
+Two things stand out in both Python and C++. First, we can simply print
+the contents of a PMT. How is this possible? Well, the PMTs have
+in-built capability to cast their value to a string (this is not
+possible with all types, though). Second, PMTs must obviously know
+their type, so we can query that, e.g. by calling the is_complex()
+method.
+
+When assigning a non-PMT value to a PMT, we can use the from_*
+methods, and use the to_* methods to convert back:
+<syntaxhighlight lang="c++">
+ pmt::pmt_t P_int = pmt::from_long(42);
+ int i = pmt::to_long(P_int);
+ pmt::pmt_t P_double = pmt::from_double(0.2);
+ double d = pmt::to_double(P_double);
+</syntaxhighlight>
+String types play a bit of a special role in PMTs, as we will see
+later, and have their own converter:
+<syntaxhighlight lang="c++">
+ pmt::pmt_t P_str = pmt::string_to_symbol("spam");
+ pmt::pmt_t P_str2 = pmt::intern("spam");
+ std::string str = pmt::symbol_to_string(P_str);
+</syntaxhighlight>
+The pmt::intern is another way of saying pmt::string_to_symbol.
+
+In Python, we can make use of the dynamic typing, and there's actually a
+helper function to do these conversions (C++ also has a helper
+function for converting to PMTs called pmt::mp(), but it's less
+powerful, and not quite as useful, because types are always strictly
+known in C++):
+<syntaxhighlight lang="python">
+ P_int = pmt.to_pmt(42)
+ i = pmt.to_python(P_int)
+ P_double = pmt.to_pmt(0.2)
+ d = pmt.to_double(P_double)
+</syntaxhighlight>
+On a side note, there are three useful PMT constants, which can be
+used in both Python and C++ domains. In C++, these can be used as
+such:
+<syntaxhighlight lang="c++">
+ pmt::pmt_t P_true = pmt::PMT_T;
+ pmt::pmt_t P_false = pmt::PMT_F;
+ pmt::pmt_t P_nil = pmt::PMT_NIL;
+</syntaxhighlight>
+In Python:
+<syntaxhighlight lang="python">
+ P_true = pmt.PMT_T
+ P_false = pmt.PMT_F
+ P_nil = pmt.PMT_NIL
+</syntaxhighlight>
+pmt.PMT_T and pmt.PMT_F are boolean PMT types.
+
+To be able to go back to C++ data types, we need to be able to find
+out the type from a PMT. The family of is_* methods helps us do that:
+<syntaxhighlight lang="c++">
+ double d;
+ if (pmt::is_integer(P)) {
+ d = (double) pmt::to_long(P);
+ } else if (pmt::is_real(P)) {
+ d = pmt::to_double(P);
+ } else {
+ // We really expected an integer or a double here, so we don't know what to do
+ throw std::runtime_error("expected an integer!");
+ }
+</syntaxhighlight>
+It is important to do type checking since we cannot unpack a PMT of
+the wrong data type.
+
+We can compare PMTs without knowing their type by using the
+pmt::equal() function:
+<syntaxhighlight lang="c++">
+ if (pmt::eq(P_int, P_double)) {
+ std::cout << "Equal!" << std::endl; // This line will never be reached
+</syntaxhighlight>
+The rest of this page provides more depth into how to handle different
+data types with the PMT library.
+
+== PMT Data Type ==
+
+All PMTs are of the type pmt::pmt_t. This is an opaque container and
+PMT functions must be used to manipulate and even do things like
+compare PMTs. PMTs are also ''immutable'' (except PMT vectors). We
+never change the data in a PMT; instead, we create a new PMT with the
+new data. The main reason for this is thread safety. We can pass PMTs
+as tags and messages between blocks and each receives its own copy
+that we can read from. However, we can never write to this object, and
+so if multiple blocks have a reference to the same PMT, there is no
+possibility of thread-safety issues of one reading the PMT data while
+another is writing the data. If a block is trying to write new data to
+a PMT, it actually creates a new PMT to put the data into. Thus we
+allow easy access to data in the PMT format without worrying about
+mutex locking and unlocking while manipulating them.
+
+PMTs can represent the following:
+
+* Boolean values of true/false
+* Strings (as symbols)
+* Integers (long and uint64)
+* Floats (as doubles)
+* Complex (as two doubles)
+* Pairs
+* Tuples
+* Vectors (of PMTs)
+* Uniform vectors (of any standard data type)
+* Dictionaries (list of key:value pairs)
+* Any (contains a boost::any pointer to hold anything)
+
+The PMT library also defines a set of functions that operate directly
+on PMTs such as:
+
+* Equal/equivalence between PMTs
+* Length (of a tuple or vector)
+* Map (apply a function to all elements in the PMT)
+* Reverse
+* Get a PMT at a position in a list
+* Serialize and deserialize
+* Printing
+
+The constants in the PMT library are:
+
+* pmt::PMT_T - a PMT True
+* pmt::PMT_F - a PMT False
+* pmt::PMT_NIL - an empty PMT (think Python's 'None')
+
+== Inserting and Extracting Data ==
+
+Use pmt.h for a complete guide to the list of functions used to create
+PMTs and get the data from a PMT. When using these functions, remember
+that while PMTs are opaque and designed to hold any data, the data
+underneath is still a C++ typed object, and so the right type of
+set/get function must be used for the data type.
+
+Typically, a PMT object can be made from a scalar item using a call
+like "pmt::from_<type>". Similarly, when getting data out of a
+PMT, we use a call like "pmt::to_<type>". For example:
+<syntaxhighlight lang="c++">
+ double a = 1.2345;
+ pmt::pmt_t pmt_a = pmt::from_double(a);
+ double b = pmt::to_double(pmt_a);
+
+ int c = 12345;
+ pmt::pmt_t pmt_c = pmt::from_long(c);
+ int d = pmt::to_long(pmt_c);
+</syntaxhighlight>
+As a side-note, making a PMT from a complex number is not obvious:
+<syntaxhighlight lang="c++">
+ std::complex<double> a(1.2, 3.4);
+ pmt::pmt_t pmt_a = pmt::make_rectangular(a.real(), b.imag());
+ std::complex<double> b = pmt::to_complex(pmt_a);
+</syntaxhighlight>
+Pairs, dictionaries, and vectors have different constructors and ways
+to manipulate them, and these are explained in their own sections.
+
+== Strings ==
+
+PMTs have a way of representing short strings. These strings are
+actually stored as interned symbols in a hash table, so in other
+words, only one PMT object for a given string exists. If creating a
+new symbol from a string, if that string already exists in the hash
+table, the constructor will return a reference to the existing PMT.
+
+We create strings with the following functions, where the second
+function, pmt::intern, is simply an alias of the first.
+<syntaxhighlight lang="c++">
+ pmt::pmt_t str0 = pmt::string_to_symbol(std::string("some string"));
+ pmt::pmt_t str1 = pmt::intern(std::string("some string"));
+</syntaxhighlight>
+The string can be retrieved using the inverse function:
+<syntaxhighlight lang="c++">
+ std::string s = pmt::symbol_to_string(str0);
+</syntaxhighlight>
+== Tests and Comparisons ==
+
+The PMT library comes with a number of functions to test and compare
+PMT objects. In general, for any PMT data type, there is an equivalent
+"pmt::is_<type>". We can use these to test the PMT before trying
+to access the data inside. Expanding our examples above, we have:
+<syntaxhighlight lang="c++">
+ pmt::pmt_t str0 = pmt::string_to_symbol(std::string("some string"));
+ if(pmt::is_symbol(str0))
+ std::string s = pmt::symbol_to_string(str0);
+
+ double a = 1.2345;
+ pmt::pmt_t pmt_a = pmt::from_double(a);
+ if(pmt::is_double(pmt_a))
+ double b = pmt::to_double(pmt_a);
+
+ int c = 12345;
+ pmt::pmt_t pmt_c = pmt::from_long(c);
+ if(pmt::is_long(pmt_a))
+ int d = pmt::to_long(pmt_c);
+
+ \\ This will fail the test. Otherwise, trying to coerce \b pmt_c as a
+ \\ double when internally it is a long will result in an exception.
+ if(pmt::is_double(pmt_a))
+ double d = pmt::to_double(pmt_c);
+</syntaxhighlight>
+
+== Dictionaries ==
+
+PMT dictionaries are lists of key:value pairs. They have a
+well-defined interface for creating, adding, removing, and accessing
+items in the dictionary. Note that every operation that changes the
+dictionary both takes a PMT dictionary as an argument and returns a
+PMT dictionary. The dictionary used as an input is not changed and the
+returned dictionary is a new PMT with the changes made there.
+
+The following is a list of PMT dictionary functions. View each function in the [https://www.gnuradio.org/doc/doxygen/index.html GNU Radio C++ Manual]
+to get more information on what each does.
+
+* bool pmt::is_dict(const pmt_t &obj)
+* pmt_t pmt::make_dict()
+* pmt_t pmt::dict_add(const pmt_t &dict, const pmt_t &key, const pmt_t &value)
+* pmt_t pmt::dict_delete(const pmt_t &dict, const pmt_t &key)
+* bool pmt::dict_has_key(const pmt_t &dict, const pmt_t &key)
+* pmt_t pmt::dict_ref(const pmt_t &dict, const pmt_t &key, const pmt_t &not_found)
+* pmt_t pmt::dict_items(pmt_t dict)
+* pmt_t pmt::dict_keys(pmt_t dict)
+* pmt_t pmt::dict_values(pmt_t dict)
+
+This example does some basic manipulations of PMT dictionaries in
+Python. Notice that we pass the dictionary \a a and return the results
+to \a a. This still creates a new dictionary and removes the local
+reference to the old dictionary. This just keeps our number of
+variables small.
+
+<syntaxhighlight lang="python">
+ import pmt
+
+ key0 = pmt.intern("int")
+ val0 = pmt.from_long(123)
+ val1 = pmt.from_long(234)
+
+ key1 = pmt.intern("double")
+ val2 = pmt.from_double(5.4321)
+
+ # Make an empty dictionary
+ a = pmt.make_dict()
+
+ # Add a key:value pair to the dictionary
+ a = pmt.dict_add(a, key0, val0)
+ print a
+
+ # Add a new value to the same key;
+ # new dict will still have one item with new value
+ a = pmt.dict_add(a, key0, val1)
+ print a
+
+ # Add a new key:value pair
+ a = pmt.dict_add(a, key1, val2)
+ print a
+
+ # Test if we have a key, then delete it
+ print pmt.dict_has_key(a, key1)
+ a = pmt.dict_delete(a, key1)
+ print pmt.dict_has_key(a, key1)
+
+ ref = pmt.dict_ref(a, key0, pmt.PMT_NIL)
+ print ref
+
+ # The following should never print
+ if(pmt.dict_has_key(a, key0) and pmt.eq(ref, pmt.PMT_NIL)):
+ print "Trouble! We have key0, but it returned PMT_NIL"
+</syntaxhighlight>
+
+== Vectors ==
+
+PMT vectors come in two forms: vectors of PMTs and vectors of uniform
+data. The standard PMT vector is a vector of PMTs, and each PMT can be
+of any internal type. On the other hand, uniform PMTs are of a
+specific data type which come in the form:
+
+* (u)int8
+* (u)int16
+* (u)int32
+* (u)int64
+* float32
+* float64
+* complex 32 (std::complex<float>)
+* complex 64 (std::complex<double>)
+
+That is, the standard sizes of integers, floats, and complex types of
+both signed and unsigned.
+
+Vectors have a well-defined interface that allows us to make, set,
+get, and fill them. We can also get the length of a vector with
+pmt::length.
+
+For standard vectors, these functions look like:
+
+* bool pmt::is_vector(pmt_t x)
+* pmt_t pmt::make_vector(size_t k, pmt_t fill)
+* pmt_t pmt::vector_ref(pmt_t vector, size_t k)
+* void pmt::vector_set(pmt_t vector, size_t k, pmt_t obj)
+* void pmt::vector_fill(pmt_t vector, pmt_t fill)
+
+Uniform vectors have the same types of functions, but they are data
+type-dependent. The following list tries to explain them where you
+substitute the specific data type prefix for \a dtype (prefixes being:
+u8, u16, u32, u64, s8, s16, s32, s64, f32, f64, c32, c64).
+
+* bool pmt::is_(dtype)vector(pmt_t x)
+* pmt_t pmt::make_(dtype)vector(size_t k, (dtype) fill)
+* pmt_t pmt::init_(dtype)vector(size_t k, const (dtype*) data)
+* pmt_t pmt::init_(dtype)vector(size_t k, const std::vector<dtype> data)
+* pmt_t pmt::(dtype)vector_ref(pmt_t vector, size_t k)
+* void pmt::(dtype)vector_set(pmt_t vector, size_t k, (dtype) x)
+* const dtype* pmt::(dtype)vector_elements(pmt_t vector, size_t &len)
+* dtype* pmt::(dtype)vector_writable_elements(pmt_t vector, size_t &len)
+
+'''Note:''' We break the contract with vectors. The 'set' functions
+actually change the data underneath. It is important to keep track of
+the implications of setting a new value as well as accessing the
+'vector_writable_elements' data. Since these are mostly standard data
+types, sets and gets are atomic, so it is unlikely to cause a great
+deal of harm. But it's only unlikely, not impossible. Best to use
+mutexes whenever manipulating data in a vector.
+
+=== BLOB ===
+
+A BLOB is a 'binary large object' type. In PMT's, this is actually
+just a thin wrapper around a u8vector.
+
+== Pairs ==
+
+Pairs are inspired by LISP 'cons' data types, so you will find the
+language here comes from LISP. A pair is just a pair of PMT
+objects. They are manipulated using the following functions:
+
+* bool pmt::is_pair(const pmt_t &obj): Return true if obj is a pair, else false
+* pmt_t pmt::cons(const pmt_t &x, const pmt_t &y): construct new pair
+* pmt_t pmt::car(const pmt_t &pair): get the car of the pair (first object)
+* pmt_t pmt::cdr(const pmt_t &pair): get the cdr of the pair (second object)
+* void pmt::set_car(pmt_t pair, pmt_t value): Stores value in the car field
+* void pmt::set_cdr(pmt_t pair, pmt_t value): Stores value in the cdr field
+
+== Serializing and Deserializing ==
+
+It is often important to hide the fact that we are working with PMTs
+to make them easier to transmit, store, write to file, etc. The PMT
+library has methods to serialize data into a string buffer or a
+string and then methods to deserialize the string buffer or string
+back into a PMT. We use this extensively in the metadata files (see
+[[Metadata Information]]).
+
+* bool pmt::serialize(pmt_t obj, std::streambuf &sink)
+* std::string pmt::serialize_str(pmt_t obj)
+* pmt_t pmt::deserialize(std::streambuf &source)
+* pmt_t pmt::deserialize_str(std::string str)
+
+For example, we will serialize the data above to make it into a string
+ready to be written to a file and then deserialize it back to its
+original PMT.
+
+<syntaxhighlight lang="python">
+ import pmt
+
+ key0 = pmt.intern("int")
+ val0 = pmt.from_long(123)
+
+ key1 = pmt.intern("double")
+ val1 = pmt.from_double(5.4321)
+
+ # Make an empty dictionary
+ a = pmt.make_dict()
+
+ # Add a key:value pair to the dictionary
+ a = pmt.dict_add(a, key0, val0)
+ a = pmt.dict_add(a, key1, val1)
+
+ print a
+
+ ser_str = pmt.serialize_str(a)
+ print ser_str
+
+ b = pmt.deserialize_str(ser_str)
+ print b
+</syntaxhighlight>
+
+The line where we 'print ser_str' will print and parts will be
+readable, but the point of serializing is not to make a human-readable
+string. This is only done here as a test.
+
+== Printing ==
+
+In Python, the __repr__ function of a PMT object is overloaded to call
+'pmt::write_string'. This means that any time we call a formatted
+printing operation on a PMT object, the PMT library will properly
+format the object for display.
+
+In C++, we can use the 'pmt::print(object)' function or print the
+contents is using the overloaded "<<" operator with a stream buffer
+object. In C++, we can inline print the contents of a PMT like:
+
+<syntaxhighlight lang="c++">
+ pmt::pmt_t a pmt::from_double(1.0);
+ std::cout << "The PMT a contains " << a << std::endl;
+</syntaxhighlight>
+
+== Conversion between Python Objects and PMTs ==
+
+Although PMTs can be manipulated in Python using the Python versions
+of the C++ interfaces, there are some additional goodies that make it
+easier to work with PMTs in python. There are functions to automate
+the conversion between PMTs and Python types for booleans, strings,
+integers, longs, floats, complex numbers, dictionaries, lists, tuples
+and combinations thereof.
+
+Two functions capture most of this functionality:
+
+<syntaxhighlight lang="python">
+ pmt.to_pmt # Converts a python object to a PMT.
+ pmt.to_python # Converts a PMT into a python object.
+</syntaxhighlight></text>
+ <sha1>c6dsjnpwev158d0di49ehocrpenc40z</sha1>
+ </revision>
+ </page>
+</mediawiki> \ No newline at end of file
diff --git a/docs/doxygen/other/pfb_intro.dox b/docs/usage-manual/(exported from wiki) Polyphase Filterbanks.txt
index 66c9891d75..baa2e7ffed 100644
--- a/docs/doxygen/other/pfb_intro.dox
+++ b/docs/usage-manual/(exported from wiki) Polyphase Filterbanks.txt
@@ -1,47 +1,54 @@
-# Copyright (C) 2017 Free Software Foundation, Inc.
-#
-# Permission is granted to copy, distribute and/or modify this document
-# under the terms of the GNU Free Documentation License, Version 1.3
-# or any later version published by the Free Software Foundation;
-# with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
-# A copy of the license is included in the section entitled "GNU
-# Free Documentation License".
-
-/*! \page page_pfb Polyphase Filterbanks
-
-\section pfb_introduction Introduction
+<page>
+ <title>Polyphase Filterbanks</title>
+ <ns>0</ns>
+ <id>3496</id>
+ <revision>
+ <id>4513</id>
+ <parentid>4318</parentid>
+ <timestamp>2018-11-02T02:03:09Z</timestamp>
+ <contributor>
+ <username>777arc</username>
+ <id>632</id>
+ </contributor>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="7339">== Introduction ==
Polyphase filterbanks (PFB) are a very powerful set of filtering tools
that can efficiently perform many multi-rate signal processing
tasks. GNU Radio has a set of polyphase filterbank blocks to be used
-in all sorts of applications.
+in all sorts of applications. See the documentation for the individual blocks for details about what
+they can do and how they should be used. Furthermore, there are
+examples for these blocks in <b>gr-filter/examples</b>:
-\section pfb_Usage
+# '''channelize.py''' creates an appropriate filter to channelizer 9 channels out of an original signal that is 9000 Hz wide, so each output channel is now 1000 Hz. The code then plots the PSD of the original signal to see the signals in the origina spectrum and then makes 9 plots for each of the channels.
+# '''chirp_channelize.py''' is similar to channelize.py but includes a VCO to create a chirp signal
+# '''decimate.py''' shows an example of using the PFB decimator
+# '''interpolate.py''' shows an example of using the PFB interpolator
+# '''reconstruction.py''' includes a PFB channelizer and PFB synthesizer
+# '''resampler.py''' demonstrates how to use the PFB resampler
+# '''synth_filter.py''' is a simple example of using the PFB synthesizer
+NOTE: you need the Matplotlib Python module installed to run these examples
-See the documentation for the individual blocks for details about what
-they can do and how they should be used. Furthermore, there are
-examples for these blocks in <b>gr-filter/examples</b>.
+== PFB Usage ==
The main issue when using the PFB blocks is defining the prototype
-filter, which is passed to all of the blocks as a vector of \p
+filter, which is passed to all of the blocks as a vector of
taps. The taps from the prototype filter which get partitioned among
-the \p N channels of the channelizer.
+the N channels of the channelizer.
An example of creating a set of filter taps for a PFB channelizer is
found on line 49 of <b>gr-filter/examples/channelizer.py</b>
and reproduced below. Notice that the sample rate is the sample rate
at the input to the channelizer while the bandwidth and transition
width are defined for the channel bandwidths. This makes a fairly long
-filter that is then split up between the \p N channels of the PFB.
+filter that is then split up between the N channels of the PFB.
-\code
self._fs = 9000 # input sample rate
self._M = 9 # Number of channels to channelize
-
self._taps = filter.firdes.low_pass_2(1, self._fs, 475.50, 50,
attenuation_dB=100,
- window=filter.firdes.WIN_BLACKMAN_hARRIS)
-\endcode
+ window=filter.firdes.WIN_BLACKMAN_hARRIS)
In this example, the signal into the channelizer is sampled at 9 ksps
(complex, so 9 kHz of bandwidth). The filter uses 9 channels, so each
@@ -63,19 +70,19 @@ but in other PFB blocks, this is not so obvious.
Two very useful blocks to use are the arbitrary resampler and the
clock synchronizer (for PAM signals). These PFBs are defined with a
set number of filters based on the fidelity required from them, not
-the rate changes. By default, the \p filter_size is set to 32 for
+the rate changes. By default, the filter_size is set to 32 for
these blocks, which is a reasonable default for most tasks. Because
the PFB uses this number of filters in the filterbank, the maximum
rate of the bank is defined from this (see the theory of a polyphase
interpolator for a justification of this). So the prototype filter is
-defined to use a sample rate of \p filter_size times the signal's
+defined to use a sample rate of filter_size times the signal's
sampling rate.
A helpful wrapper for the arbitrary resampler is found in
<b>gr-filter/python/pfb.py</b>,
which is exposed in Python as <b>filter.pfb.arb_resampler_ccf</b> and
<b>filter.pfb.arb_resampler_fff</b>. This block is set up so that the
-user only needs to pass it the real number \p rate as the resampling
+user only needs to pass it the real number rate as the resampling
rate. With just this information, this hierarchical block
automatically creates a filter that fully passes the signal bandwidth
being resampled but does not pass any out-of-band noise. See the code
@@ -87,22 +94,7 @@ examples (<b>gr-uhd/examples</b>) use this ability to create a
received matched filter or channel filter that also resamples the
signal.
-\section pfb_examples Examples
-
-The following is an example of the using the channelizer. It creates
-the appropriate filter to channelizer 9 channels out of an original
-signal that is 9000 Hz wide, so each output channel is now 1000
-Hz. The code then plots the PSD of the original signal to see the
-signals in the origina spectrum and then makes 9 plots for each of the
-channels.
-
-NOTE: you need the Matplotlib Python module installed to
-run this example.
-
-\include gr-filter/examples/channelize.py
-
-
-\section pfb_arb_resampler The PFB Arbitrary Resampler Kernel
+== The PFB Arbitrary Resampler Kernel ==
GNU Radio has a PFB arbitrary resampler block that can be used to
resample a signal to any arbitrary and real resampling rate. The
@@ -113,24 +105,23 @@ class that can be used as such.
The PFB arbitrary resampler is defined in pfb_arb_resampler.h and has
the following constructor:
-\code
-namespace gr {
- namespace filter {
- namespace kernel {
+ namespace gr {
+ namespace filter {
+ namespace kernel {
+
+ pfb_arb_resampler_XXX(float rate,
+ const std::vector<float> &taps,
+ unsigned int filter_size);
+
+ } /* namespace kernel */
+ } /* namespace filter */
+ } /* namespace gr */
- pfb_arb_resampler_XXX(float rate,
- const std::vector<float> &taps,
- unsigned int filter_size);
-
- } /* namespace kernel */
- } /* namespace filter */
-} /* namespace gr */
-\endcode
Currently, only a 'ccf' and 'fff' version are defined. This kernel,
-like the block itself, takes in the resampling \p rate as a floating
-point number. The \p taps are passed as the baseband prototype filter,
-and the quantization error of the filter is determined by the \p
+like the block itself, takes in the resampling rate as a floating
+point number. The taps are passed as the baseband prototype filter,
+and the quantization error of the filter is determined by the
filter_size parameter.
The prototype taps are generated like all other PFB filter
@@ -153,15 +144,15 @@ total number of taps small. A stopband attenuation of 60 dB was used
here, and again, this is a parameter we can adjust to alter the
performance and size of the filter.
-\code
firdes.low_pass_2(filter_size, filter_size, 0.5, 0.1, 60)
-\endcode
As is typical with the PFB filters, a filter size of 32 is generally
an appropriate trade-off of accuracy, performance, and memory. This
should provide an error roughly equivalent to the quanization error of
using 16-bit fixed point representation. Generally, increasing over 32
provides some accuracy benefits without a huge increase in
-computational demands.
-
-*/
+computational demands.</text>
+ <sha1>qgfvtgmqeoxutntovjunwzowmz49fvh</sha1>
+ </revision>
+ </page>
+</mediawiki> \ No newline at end of file
diff --git a/docs/usage-manual/(exported from wiki) QT GUI.txt b/docs/usage-manual/(exported from wiki) QT GUI.txt
new file mode 100644
index 0000000000..fab784567c
--- /dev/null
+++ b/docs/usage-manual/(exported from wiki) QT GUI.txt
@@ -0,0 +1,282 @@
+<page>
+ <title>QT GUI</title>
+ <ns>0</ns>
+ <id>3486</id>
+ <revision>
+ <id>4190</id>
+ <parentid>4189</parentid>
+ <timestamp>2018-05-15T19:45:25Z</timestamp>
+ <contributor>
+ <username>777arc</username>
+ <id>632</id>
+ </contributor>
+ <comment>/* C++ and Message-Passing Widgets */</comment>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="12387">== Introduction ==
+
+This is the gr-qtgui package. It contains various QT-based graphical
+user interface blocks that add graphical sinks to a GNU Radio
+flowgraph. The Python namespaces is in gnuradio.qtgui, which would be normally
+imported as:
+
+ from gnuradio import qtgui
+
+See the Doxygen documentation for details about the blocks available
+in this package. The relevant blocks are listed [https://gnuradio.org/doc/doxygen/group__qtgui__blk.html here].
+
+A quick listing of the details can be found in Python after importing
+by using:
+
+ help(qtgui)
+
+=== Blocks ===
+
+There are a number of available QTGUI blocks for different plotting
+purposes. These include:
+
+# Time Domain (gr::qtgui::time_sink_c and gr::qtgui::time_sink_f): x-axis is time, y-axis is amplitude.
+# Frequency Domain or PSD (gr::qtgui::freq_sink_c and gr::qtgui::freq_sink_f): x-axis is frequency, y-axis is magnitude in dB.
+# Waterfall or spectrogram (gr::qtgui::waterfall_sink_c and gr::qtgui::waterfall_sink_f): x-axis is frequency, y-axis is time,z-axis is intensity related to magnitude in dB.
+# Constellation (gr::qtgui::const_sink_c): polar plot of real vs. imaginary.
+# Time Raster (gr::qtgui::time_raster_sink_f and gr::qtgui::time_raster_sink_b): time vs. time with the z-axis being intensity basedon value of the sample.
+# Histogram (gr::qtgui::histogram_sink_f): Displays a histogram of the data stream.
+# Combined Sink (gr::qtgui::sink_c and gr::qtgui::sink_f): combines time, frequency, waterfall, and constellation plots into one widget.
+
+The time domain, frequency domain, and waterfall have both a complex
+and a floating point block. The constellation plot only makes sense
+with complex inputs. The time raster plots accept bits and floats.
+
+Because the time raster plots are designed to show structure over time
+in a signal, frame, packet, etc., they never drop samples. This is a
+fairly taxing job and performance can be an issue. Since it is
+expected that this block will work on a frame or packet structure, we
+tend to be at the lowest possible rate at this point, so that will
+help. Expect performance issues at high data rates.
+
+Note: There seem to be extra performance issues with the raster
+plotters in QWT version 5 that were fixed with QWT version 6. As such,
+the time raster plots have incredibly poor performance with QWT5 to
+the point of almost being unusable. In the future, we may restrict
+compilation and installation of these plots only if QWT6 or higher is
+discovered. For now, just be aware of this limitation.
+
+== Drop-Down Menu and Interacting with Plots ==
+
+All QTGUI sinks have interactive capabilities.
+
+# Zooming is done simply by clicking the left mouse button and dragging a rectangle around the area to zoom.
+# Zooming can be done in multiple steps.
+# A right mouse click will zoom out one step.
+# Ctrl+Right mouse click will zoom all the way out.
+# Ctrl+Middle mouse click and hold can drag the canvas around.
+# Mouse wheel up/down will zoom out/in on y axis (both axes in constellation plot).
+# Middle mouse button brings up a context menu.
+
+Each type of graph has a different set of menu items in the context
+menu. Most have some way to change the appearance of the lines or
+surfaces, such as changing the line width color, marker, and
+transparency. Other common features can set the sampling rate, turn a
+grid on and off, pause and unpause (stop/start) the display update, and
+save the current figure. Specific features are things like setting the
+number of points to display, setting the FFT size, FFT window, and any
+FFT averaging.
+
+=== Triggering Menu for Time Plots ===
+
+The time plots have triggering capabilities. Triggering can happen
+when the signal of a specific channel crosses (positive or negative
+slope) a certain level threshold. Or triggering can be done off a
+specific stream tag such that whenever a tag of a given key is found,
+the scope will trigger.
+
+In the signal level mode, the trigger can be either 'auto' or 'normal'
+where the latter will only trigger when the event is seen. The 'auto'
+mode will trigger on the event or every so often even if no trigger is
+found. The 'free' mode ignores triggering and continuously
+plots.
+
+By default, the triggers plot the triggering event at the x=0 (i.e.,
+the left-most point in the plot). A delay can be set to delay the
+signal along the x-axis to observe any signal before the triggering
+event. The delay feature works the same for both level and tag
+triggers. The delay is set according to time in seconds, not
+samples. So the delay can be calculated as the number of samples
+divided by the sample rate given to the block.
+
+All trigger settings (mode, slope, level, delay, channel, and tag key)
+are settable in the GRC properties boxes to easily set up a repeatable
+environment.
+
+A note on the trigger delay setting. This value is limited by the
+buffer size and/or the number of points being display. It is capped by
+the minimum of these two values. The buffer size issue is generally
+only a problem when plotting a large number of samples. However, if
+the delay is set large to begin with (in the GRC properties box or
+before top_block.start() is called), then the buffers are resized
+accordingly offering more freedom. This should be a problem in a
+limited number of scenarios, but a log INFO level message is produced
+when asking for the delay outside of the available range.
+
+== Dependencies ==
+
+The QT GUI blocks require the following dependencies.
+
+# QtCore (version >= 4.4)
+# QtGui (version >= 4.4)
+# QtOpenGL (version >= 4.4)
+# PyQt4 for Qt4 (version >= 4.4)
+# Qwt (version >= 5.2)
+
+== Usage ==
+
+To use the QTGUI interface, a bit of boiler-plate lines must be
+included. First, the sink is defined, then it must be exposed from C++
+into Python using the "sip.wrapinstance" command, and finally, the
+"show" method is run on the new Python object. This sets up the QT
+environment to show the widget, but the qApplication must also be
+launched.
+
+In the "main" function of the code, the qApp is retrieved. Then, after
+the GNU Radio top block is started (remember that start() is a
+non-blocking call to launch the main thread of the flowgraph), the
+qapp's "exec_()" function is called. This function is a blocking call
+while the GUI is alive.
+
+from PyQt4 import Qt
+from gnuradio import qtgui
+import sys, sip
+
+ class grclass(gr.top_block):
+ ....
+
+ self.snk = qtgui.sink_c(1024, #fftsize
+ samp_rate, #bw
+ "QT GUI Plot") #name
+
+ self.snk_win = sip.wrapinstance(self.snk.pyqwidget(), Qt.QWidget)
+ self.snk_win.show()
+
+ def main():
+ qapp = Qt.QApplication(sys.argv)
+ tb = grclass()
+ tb.start()
+ qapp.exec_()
+ tb.stop()
+
+There are graphical controls in all but the combined plotting
+tools. In the margins of the GUIs (that is, not on the canvas showing
+the signal itself), right-clicking the mouse will pull up a drop-down
+menu that will allow you to change difference parameters of the
+plots. These include things like the look of the lines (width, color,
+style, markers, etc.), the ability to start and stop the display, the
+ability to save to a file, and other plot-specific controls (FFT size
+for the frequency and waterfall plots, etc.).
+
+== Message Input Support ==
+
+All QTGUI sinks can accept and plot messages over their "in" message
+port. The message types must either be uniform vectors or PDUs. The
+data type held within the uniform vector or PDU must match the data
+type of the block itself. For example, a qtgui.time_sink_c will only
+handle vectors that pass the pmt::is_c32vector test while a
+qtgui.time_sink_f will only handle vectors that pass the
+pmt::is_f32vector test.
+
+The sinks must only be used with one type of input model: streaming or
+messages. You cannot use them both together or unknown behavior will
+occur.
+
+In the GNU Radio Companion, the QTGUI sink blocks can be set to
+message mode by changing the Type field. Most of the QTGUI sinks
+support multiple data types, even for messages, but GRC only displays
+the message type as the single gray color. Within the block's property
+box, you can set the type to handle the correct message data type
+(e.g., 'Complex Message' or 'Float Message'). When using a message
+type interface, GRC will hide certain parameters that are not usable
+or settable anymore. For example, when plotting a message in the time
+sink, the number of points shown in the time sink is determined by the
+length of the vector in the message. Presetting this in the GUI would
+have no effect.
+This behavior in GRC is for convenience and to try and reduce confusion
+about properties and settings in the message mode. However, all of the
+API hooks are still there, so it is possible to set all of this
+programmatically. The results would be harmless, however.
+
+Here is an example of setting up and using a message passing complex
+time sink block:
+
+ from gnuradio import gr, qtgui
+
+ tsnk = qtgui.time_sink_c(1024, samp_rate, "", 0)
+ tsnk.set_update_time(0.05)
+ tsnk.set_y_axis(-1.25, 1.25)
+ tsnk.set_y_label("Amp (V)", "")
+ tsnk.enable_autoscale(False)
+ tsnk.enable_grid(False)
+ tsnk.enable_control_panel(False)
+
+ tb = gr.top_block()
+ msg_block = ? # some PDU/message generating block
+ tb.msg_connect((msg_block, 'msg'), (tsnk, 'in'))
+
+== QTGUI Widgets ==
+
+The QTGUI component also includes a number of widgets that can be used
+to perform live updates of variables through standard QT input
+widgets. Most of the widgets are implemented directly in Python
+through PyQT. However, GNU Radio is introducing more widgets, written
+and therefore available in C++ that also produce messages. The
+Python-based widgets only act as variables and so as they are changed,
+any block using those widgets to set parameters has the callback (i.e.,
+set_value()) function's called.
+
+=== Python widgets: ===
+
+# Range: creates a slider and/or combo box to change to set/change the value of a parameter. This widget can set either float or int values.
+# Entry: An edit box that allows a user to directly set a new value for the parameter.
+# Chooser: Creates a drop-down menu of pre-set values.
+# Check Box: Creates a check box. The user sets what the value of the check means when enabled or disabled.
+# Push Button: Adds a button that changes state when pushed versus released (no sticky). The user sets up what the value is when pressed versus when released.
+# Label: Adds a Label widget to annotate the GUI. Generally not used as a variable.
+# Tab Widget: Adds a tab widget that can house other GUI widgets to format the interface. Use the GUI hint of the other QT widgets and instruments to specify if and where they exist in the tab widget using the format "tag widget name@index: row, col, row span, col span". Simply using "tab widget name@index" will put that widget into the specific index (starting at 0) of the tab widget while adding the "row, col, row span, col span" will allow the user to place them in the tab grid.
+
+=== C++ and Message-Passing Widgets ===
+
+The [https://gnuradio.org/doc/doxygen/classgr_1_1qtgui_1_1edit__box__msg.html Message Edit Box] is a QT edit box
+that emits a message when editing is done (e.g., user presses enter,
+tabs out of the widget, or mouse-clicks out of the widget). The
+message type is settable as are the contents. Messages can be sent as
+key:value pairs when Pair Mode is enabled. When Static Mode is
+enabled, the data type and the pair key (if in Pair Mode) are set at
+the start and cannot be changed at runtime.
+
+== Configuration ==
+
+There is currently a single configuration option in the preferences
+files to set the rendering engine of the QTGUI sinks. Located in
+etc/gnuradio/conf.d/gr-qtgui.conf:
+
+ [qtgui]
+ style = raster
+
+The available styles are:
+
+# opengl: the fastest but not likely to always work
+# raster: fast and stable; terrible X forwarding performance
+# native: most compute intensive; very good over X
+
+We default this setting to raster for the mix of performance and
+usability. When using QTGUI sinks through an X-forwarding session over
+SSH, switch to using 'native' for a significant speed boost on the
+remote end.
+
+We can also set a QT Style Sheet (QSS) file to adjust the look of our
+plotting tools. Set the 'qss' option of the 'qtgui' section in our
+configuration file to a QSS file. An example QSS file is distributed
+with the QTGUI examples found in
+share/gnuradio/examples/qt-gui/dark.qss.</text>
+ <sha1>6p0evs1odganpw5pf993ifhtdncao90</sha1>
+ </revision>
+ </page>
+</mediawiki> \ No newline at end of file
diff --git a/docs/doxygen/other/stream_tags.dox b/docs/usage-manual/(exported from wiki) Stream Tags.txt
index 146218796e..4130d2e432 100644
--- a/docs/doxygen/other/stream_tags.dox
+++ b/docs/usage-manual/(exported from wiki) Stream Tags.txt
@@ -1,15 +1,19 @@
-# Copyright (C) 2017 Free Software Foundation, Inc.
-#
-# Permission is granted to copy, distribute and/or modify this document
-# under the terms of the GNU Free Documentation License, Version 1.3
-# or any later version published by the Free Software Foundation;
-# with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
-# A copy of the license is included in the section entitled "GNU
-# Free Documentation License".
-
-/*! \page page_stream_tags Stream Tags
-
-\section stream_tags_introduction Introduction
+<page>
+ <title>Stream Tags</title>
+ <ns>0</ns>
+ <id>3482</id>
+ <revision>
+ <id>4286</id>
+ <parentid>4285</parentid>
+ <timestamp>2018-06-26T18:38:25Z</timestamp>
+ <contributor>
+ <username>777arc</username>
+ <id>632</id>
+ </contributor>
+ <comment>/* Getting tags from a Stream */</comment>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="10223">== Introduction ==
GNU Radio was originally a streaming system with no other mechanism to
pass data between blocks. Streams of data are a model that work well
@@ -17,43 +21,40 @@ for samples, bits, etc., but can lack for control and meta data.
Part of this is solved using the existing message passing interface, which
allows blocks to subscribe to messages published by any other block in
-the flowgraph (see \ref page_msg_passing). The main drawback to the
+the flowgraph (see [[Message Passing]]). The main drawback to the
message passing system is that is works asynchronously, meaning that
there is no guarantee when a message may arrive relative to the data
stream.
Stream tags are an isosynchronous data stream that runs parallel to
-the main data stream. A stream \a tag is generated by a block's work
+the main data stream. A stream ''tag'' is generated by a block's work
function and from there on flows downstream alongside a particular sample,
until it reaches a sink or is forced to stop propagating by another
block.
Stream tags are defined for a specific item in the data stream and are
-formed as a key:value pair. The \a key identifies what the \a value represents
-while the value holds the data that the tag contains. Both \a key and
-\a value are PMTs (\ref page_pmt) where the \a key is a PMT symbol while
-the \a value is any type of PMT and can therefore handle any data we wish
-to pass. An additional part of the tag is the \a srcid, which is a PMT
+formed as a key:value pair. The ''key'' identifies what the ''value'' represents
+while the value holds the data that the tag contains. Both ''key'' and
+''value'' are [[Polymorphic Types (PMTs)]] where the ''key'' is a PMT symbol while
+the ''value'' is any type of PMT and can therefore handle any data we wish
+to pass. An additional part of the tag is the ''srcid'', which is a PMT
symbol and is used to identify the block that created the tag (which
is usually the block's alias).
-
-\section stream_tags_block_api_extensions API Extensions to the gr::block
+== API Extensions to the gr::block ==
To enable the stream tags, we have extended the API of gr::block to
-understand \a absolute item numbers. In the data stream model, each
+understand ''absolute'' item numbers. In the data stream model, each
block's work function is given a buffer in the data stream that is
-referenced from 0 to N-1. This is a \a relative offset into the data
+referenced from 0 to N-1. This is a ''relative'' offset into the data
stream. The absolute reference starts from the beginning of the
flowgraph and continues to count up with every item. Each input stream
is associated with a concept of the 'number of items read' and each
output stream has a 'number of items written'. These are retrieved during
runtime using the two API calls:
-\code
-unsigned long int nitems_read(unsigned int which_input);
-unsigned long int nitems_written(unsigned int which_output);
-\endcode
+ unsigned long int nitems_read(unsigned int which_input);
+ unsigned long int nitems_written(unsigned int which_output);
Each tag is associated with some item in this absolute time scale that
is calculated using these functions.
@@ -62,12 +63,10 @@ Like the rest of the data stream, the number of items read/written are
only updated once during the call to work. So in a work function,
nitems_read/written will refer to the state of the data stream at the
start of the work function. We must therefore add to this value the
-current relative offset in the data stream. So if we are iterating \a
-i over all output items, we would write the stream tag to output ports
-at <em>nitems_written(0)+i</em> for the 0th output port.
+current relative offset in the data stream. So if we are iterating ''i'' over all output items, we would write the stream tag to output ports
+at nitems_written(0)+i for the 0th output port.
-
-\section stream_tags_api Stream Tags API
+== Stream Tags API ==
The stream tags API is split into two parts: adding tags to a stream,
and getting tags from a stream.
@@ -76,13 +75,11 @@ within a call to general_work/work. While they can be called at other points
in time by a block, the behavior outside of work is undefined without
exact knowledge of the item counts in the buffers.
-
-\subsection stream_tags_add_item_tag Adding a Tag to a Stream
+=== Adding a Tag to a Stream ===
We add a tag to a particular output stream of the block using:
-\li gr::block::add_item_tag: Adds an item tag to a particular output port
-using a gr::tag_t data type or by specifying the tag values.
+* gr::block::add_item_tag: Adds an item tag to a particular output port using a gr::tag_t data type or by specifying the tag values.
We can output them to multiple output streams if we want, but to do so
means calling this function once for each port. This function can be
@@ -91,45 +88,39 @@ explicitly given.
Again, a tag is defined as:
-\li offset: The offset, in absolute item time, of the tag in the data
-stream.
-\li key: the PMT symbol identifying the type of tag.
-\li value: the PMT holding the data of the tag.
-\li srcid: (optional) the PMT symbol identifying the block which
-created the tag.
+# offset: The offset, in absolute item time, of the tag in the data stream.
+# key: the PMT symbol identifying the type of tag.
+# value: the PMT holding the data of the tag.
+# srcid: (optional) the PMT symbol identifying the block which created the tag.
We can create a gr::tag_t structure to hold all of the above
information of a tag, which is probably the easiest/best way to do
it. The gr::tag_t struct is defined as having the same members as in
the above list. To add a gr::tag_t tag to a stream, use the function:
-\code
void add_item_tag(unsigned int which_output, const tag_t &tag);
-\endcode
The secondary API allows us to create a tag by explicitly listing all
of the tag information in the function call:
-\code
void 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);
-\endcode
+In Python, we can add a tag to a stream using:
+
+ add_item_tag(which_output, abs_offset, key, value, srcid) # note that the key and value are both PMTs
-\subsection stream_tags_get_item_tags Getting tags from a Stream
+=== Getting tags from a Stream ===
To get tags from a particular input stream, we have two
functions we can use:
-\li gr::block::get_tags_in_range: Gets all tags from a particular
-input port between a certain range of items (in absolute item time).
+# gr::block::get_tags_in_range: Gets all tags from a particular input port between a certain range of items (in absolute item time).
-\li gr::block::get_tags_in_window: Gets all tags from a particular
-input port between a certain range of items (in relative item time
-within the work function).
+# gr::block::get_tags_in_window: Gets all tags from a particular input port between a certain range of items (in relative item time within the work function).
The difference between these functions is working in absolute item
time versus relative item time. Both of these pass back vectors of
@@ -141,59 +132,57 @@ for getting the right tag's data.
For example, this call just returns any tags between the given range of items:
-\code
void get_tags_in_range(std::vector<tag_t> &v,
unsigned int which_input,
uint64_t abs_start,
uint64_t abs_end);
-\endcode
Adding a fifth argument to this function allows us to filter on the
-key \a key.
+key ''key''.
-\code
void get_tags_in_range(std::vector<tag_t> &v,
unsigned int which_input,
uint64_t abs_start,
uint64_t abs_end,
const pmt::pmt_t &key);
-\endcode
+In Python, the main difference from the C++ function is that instead of having the first
+argument be a vector where the tags are stored, the Python version
+just returns a list of tags. We would use it like this:
+
+ def work(self, input_items, output_items):
+ ....
+ tags = get_tags_in_window(which_input, rel_start, rel_end)
+ ....
-\section stream_tags_propagation Tag Propagation
+== Tag Propagation ==
Tags are propagated downstream from block to block like the normal
data streams. How tags are actually moved depends on a specific
propagation policy. We defined three types of policies:
-\li All-to-All: all tags from any input port are replicated to all
-output ports
-\li One-to-One: tags from input port \a i are only copied to output
-port \a i (depends on num inputs = num outputs).
-\li Dont: Does not propagate tags. Tags are either stopped here or the
-work function recreates them in some manner.
+# All-to-All: all tags from any input port are replicated to all output ports
+# One-to-One: tags from input port ''i'' are only copied to output port ''i'' (depends on num inputs = num outputs).
+# Dont: Does not propagate tags. Tags are either stopped here or the work function recreates them in some manner.
The default behavior of a block is the 'All-to-All' method of
propagation.
To set a different propagation policy, use the function:
-\code
void set_tag_propagation_policy(tag_propagation_policy_t p);
-\endcode
See the gr::block::tag_propagation_policy_t documentation for details
on this enum type.
-
-\subsection stream_tags_rate_changes Tag Propagation through Rate Changes
+=== Tag Propagation through Rate Changes ===
When a tag is propagated through a block that has a rate change, the
item's offset in the data stream will change. The scheduler uses the
block's gr::block::relative_rate concept to perform the update on the
tag's offset value. The relative rate of a block determines the
relationship between the input rate and output rate. Decimators that
-decimate by a factor of \a D have a relative rate of <em>1/D</em>.
+decimate by a factor of D have a relative rate of 1/D.
Synchronous blocks (gr::sync_block), decimators (gr::sync_decimator),
and interpolators (gr::sync_interpolator) all have pre-defined and
@@ -206,14 +195,14 @@ would have to use the TPP_DONT tag propagation policy and handle the
propagation internally.
In no case is the value of the tag modified when propagating through a
-block. This becomes relevant when using \ref page_tagged_stream_blocks.
+block. This becomes relevant when using [[Tagged Stream Blocks]].
-\section stream_tags_issues Notes on How to Use Tags
+== Notes on How to Use Tags ==
Tags can be very useful to an application, and their use is
spreading. USRP sources generate tag information on the time, sample
rate, and frequency of the board if anything changes. We have a meta
-data file source/sink (see \ref page_metadata) that use tags to store
+data file source/sink (see [[Metadata]]) that use tags to store
information about the data stream. But there are things to think about
when using tags in a block.
@@ -229,9 +218,9 @@ necessary and try to provide some control over how tags are generated
to control their frequency. A good example is the USRP source, which
generates a time tag. If it generated a tag with every sample, we
would have thousands of tags per second, which would add a significant
-amount of overhead. This is because if we started at time <em>t0</em> at
-sample rate <em>sr</em>, then after <em>N</em> samples, we know that
-we are now at time <em>t0 + N/sr</em>. So continuously producing new
+amount of overhead. This is because if we started at time t0 at
+sample rate sr, then after N samples, we know that
+we are now at time t0 + N/sr. So continuously producing new
tags adds no information.
The main issue we need to deal with in the above situation is when
@@ -240,6 +229,8 @@ we have no way of knowing in the flowgraph how many samples were
potentially lost, we have lost track of the timing information. The
USRP driver recognizes when packets have been dropped and uses this to
queue another tag, which allows us to resync. Likewise, any point the
-sample rate or frequency changes, a new tag is issued.
-
-*/
+sample rate or frequency changes, a new tag is issued.</text>
+ <sha1>q8so7nd8lqh1et3zmf8x28z6qxq2hwd</sha1>
+ </revision>
+ </page>
+</mediawiki> \ No newline at end of file
diff --git a/docs/doxygen/other/tagged_stream_blocks.dox b/docs/usage-manual/(exported from wiki) Tagged Stream Blocks.txt
index 1a10483323..91d09b0a15 100644
--- a/docs/doxygen/other/tagged_stream_blocks.dox
+++ b/docs/usage-manual/(exported from wiki) Tagged Stream Blocks.txt
@@ -1,33 +1,34 @@
-# Copyright (C) 2017 Free Software Foundation, Inc.
-#
-# Permission is granted to copy, distribute and/or modify this document
-# under the terms of the GNU Free Documentation License, Version 1.3
-# or any later version published by the Free Software Foundation;
-# with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
-# A copy of the license is included in the section entitled "GNU
-# Free Documentation License".
-
-/*! \page page_tagged_stream_blocks Tagged Stream Blocks
-
-\section tsb_introduction Introduction
+<page>
+ <title>Tagged Stream Blocks</title>
+ <ns>0</ns>
+ <id>3483</id>
+ <revision>
+ <id>4295</id>
+ <parentid>4181</parentid>
+ <timestamp>2018-06-26T19:56:49Z</timestamp>
+ <contributor>
+ <username>777arc</username>
+ <id>632</id>
+ </contributor>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="13353">== Introduction ==
A tagged stream block is a block that works on streamed, but packetized input data.
Think of packet data transmission: A data packet consists of N bytes. However, in
traditional GNU Radio blocks, if we stream N bytes into a block, there's no way of
knowing the packet boundary. This might be relevant: Perhaps the modulator has to
prepend a synchronisation word before every packet, or append a CRC. So while some
-blocks don't care about packet boundaries, other blocks do: These are <em>tagged
-stream blocks</em>.
+blocks don't care about packet boundaries, other blocks do: These are tagged
+stream blocks.
These blocks are different from all the other GNU Radio block types (gr::block,
-gr::sync_block etc.) in that they are driven by the input: The PDU length tag tells the block how to
-operate, whereas other blocks are output-driven (the scheduler tries to fill up the output
-buffer are much as possible).
+gr::sync_block etc.) in that they are driven by the input: The PDU length tag tells the block how to operate, whereas other blocks are output-driven (the scheduler tries to fill up the output buffer are much as possible).
-\subsection tsb_howtheywork How do they work?
+=== How do they work? ===
As the name implies, tagged stream blocks use tags to identify PDU boundaries.
-On the first item of a streamed PDU, there \em must be a tag with a specific
+On the first item of a streamed PDU, there ''must'' be a tag with a specific
key, which stores the length of the PDU as a PMT integer. If anything else, or no tag,
is on this first item, this will cause the flow graph to crash!
@@ -35,7 +36,7 @@ The scheduler then takes care of everything. When the work function is called, i
is guaranteed to contain exactly one complete PDU and enough space in the output buffer for
the output.
-\subsection tsb_relatestootherblocks How do they relate to other block types (e.g. sync blocks)?
+=== How do they relate to other block types (e.g. sync blocks)? ===
Tagged stream blocks and sync blocks are really orthogonal concepts, and a block could be
both (gr::digital::ofdm_frame_equalizer_vcvc is such a block). However, because the work
@@ -49,30 +50,29 @@ set gr::block::set_relative_rate(1.0) and/or the fixed rate functions.
The way gr::tagged_stream_block works, it is still beneficial to specify a relative rate,
if possible.
-
-\section tsb_creating Creating a tagged stream block
+== Creating a tagged stream block ==
To create a tagged stream block, the block must be derived from gr::tagged_stream_block.
Here's a minimal example of how the header file could look:
-\code
-#include <gnuradio/digital/api.h>
-#include <gnuradio/tagged_stream_block.h>
-
-namespace gr {
- namespace digital {
-
- class DIGITAL_API crc32_bb : virtual public tagged_stream_block
- {
- public:
- typedef boost::shared_ptr<crc32_bb> sptr;
- static sptr make(bool check=false, const std::string& len_tag_key="packet_len");
- };
-
- } // namespace digital
-} // namespace gr
-
-\endcode
+<syntaxhighlight lang="cpp">
+ #include <gnuradio/digital/api.h>
+ #include <gnuradio/tagged_stream_block.h>
+
+ namespace gr {
+ namespace digital {
+
+ class DIGITAL_API crc32_bb : virtual public tagged_stream_block
+ {
+ public:
+ typedef boost::shared_ptr<crc32_bb> sptr;
+
+ static sptr make(bool check=false, const std::string& len_tag_key="packet_len");
+ };
+
+ } // namespace digital
+ } // namespace gr
+</syntaxhighlight>
It is very similar to any other block definition. Two things are stand out: First,
gnuradio/tagged_stream_block.h is included to allow deriving from gr::tagged_stream_block.
@@ -80,125 +80,121 @@ gnuradio/tagged_stream_block.h is included to allow deriving from gr::tagged_str
The other thing is in the make function: the second argument is a string containing
the key of the length tags. This is not necessary (the block could get this information
hard-coded), but the usual way is to allow the user to change this tag, but give a
-default value (in this case, \p packet_len).
+default value (in this case, packet_len).
The implementation header (*_impl.h) also looks a bit different (again this is cropped to the relevant parts):
-\code
-#include <digital/crc32_bb.h>
-namespace gr {
- namespace digital {
-
- class crc32_bb_impl : public crc32_bb
- {
- public:
- crc32_bb_impl(bool check, const std::string& len_tag_key);
- ~crc32_bb_impl();
-
- int calculate_output_stream_length(const gr_vector_int &ninput_items);
- int work(int noutput_items,
- gr_vector_int &ninput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
- };
-
- } // namespace digital
-} // namespace gr
-\endcode
-
-First, the \p work function signature is new. The argument list looks like that from
+
+
+<syntaxhighlight lang="cpp">
+ #include <digital/crc32_bb.h>
+ namespace gr {
+ namespace digital {
+
+ class crc32_bb_impl : public crc32_bb
+ {
+ public:
+ crc32_bb_impl(bool check, const std::string& len_tag_key);
+ ~crc32_bb_impl();
+
+ int calculate_output_stream_length(const gr_vector_int &ninput_items);
+ int work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace digital
+ } // namespace gr
+</syntaxhighlight>
+
+First, the work function signature is new. The argument list looks like that from
gr::block::general_work() (note: the arguments mean the same, too), but it's called
-\p work like with the other derived block types (such as gr::sync_block). Also, there's a new
-function: \p calculate_output_stream_length() is, in a sense, the opposite function to
+work like with the other derived block types (such as gr::sync_block). Also, there's a new
+function: calculate_output_stream_length() is, in a sense, the opposite function to
gr::block::forecast(). Given a number of input items, it calculates the required number of
output items. Note how this relates to the fact that these blocks are input-driven.
-These two overrides (\p work() and \p calculate_output_stream_length() ) are what you need
+These two overrides (work() and calculate_output_stream_length()) are what you need
for most tagged stream blocks. There are cases when you don't need to override the latter
because the default behaviour is enough, and other cases where you have to override more
-than these two functions. These are discussed in \ref tsb_adv_usage.
+than these two functions. These are discussed in [[Tagged Stream Blocks#Advanced Usage|Advanced Usage]].
Finally, this is part of the actual block implementation (heavily cropped again, to highlight the relevant parts):
-\code
-#include <gnuradio/io_signature.h>
-#include "crc32_bb_impl.h"
-
-namespace gr {
- namespace digital {
-
- crc32_bb::sptr crc32_bb::make(bool check, const std::string& len_tag_key)
- {
- return gnuradio::get_initial_sptr (new crc32_bb_impl(check, len_tag_key));
- }
-
- crc32_bb_impl::crc32_bb_impl(bool check, const std::string& len_tag_key)
- : tagged_stream_block("crc32_bb",
- io_signature::make(2, 1, sizeof (char)),
- io_signature::make(1, 1, sizeof (char)),
- len_tag_key),
- d_check(check)
- {
- }
-
- int
- crc32_bb_impl::calculate_output_stream_length(const gr_vector_int &ninput_items)
- {
- if (d_check) {
- return ninput_items[0] - 4;
- } else {
- return ninput_items[0] + 4;
- }
- }
-
- int
- crc32_bb_impl::work (int noutput_items,
- gr_vector_int &ninput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
- {
- const unsigned char *in = (const unsigned char *) input_items[0];
- unsigned char *out = (unsigned char *) output_items[0];
-
- // Do all the signal processing...
- // Don't call consume!
-
- return new_packet_length;
- }
-
- } // namespace digital
-} // namespace gr
-\endcode
+
+
+<syntaxhighlight lang="cpp">
+ #include <gnuradio/io_signature.h>
+ #include "crc32_bb_impl.h"
+
+ namespace gr {
+ namespace digital {
+
+ crc32_bb::sptr crc32_bb::make(bool check, const std::string& len_tag_key)
+ {
+ return gnuradio::get_initial_sptr (new crc32_bb_impl(check, len_tag_key));
+ }
+
+ crc32_bb_impl::crc32_bb_impl(bool check, const std::string& len_tag_key)
+ : tagged_stream_block("crc32_bb",
+ io_signature::make(2, 1, sizeof (char)),
+ io_signature::make(1, 1, sizeof (char)),
+ len_tag_key),
+ d_check(check)
+ {
+ }
+
+ int
+ crc32_bb_impl::calculate_output_stream_length(const gr_vector_int &ninput_items)
+ {
+ if (d_check) {
+ return ninput_items[0] - 4;
+ } else {
+ return ninput_items[0] + 4;
+ }
+ }
+
+ int
+ crc32_bb_impl::work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const unsigned char *in = (const unsigned char *) input_items[0];
+ unsigned char *out = (unsigned char *) output_items[0];
+
+ // Do all the signal processing...
+ // Don't call consume!
+
+ return new_packet_length;
+ }
+
+ } // namespace digital
+ } // namespace gr
+</syntaxhighlight>
The make function is not different to any other block. The constructor calls
gr::tagged_stream_block::tagged_stream_block() as expected, but note that it passes the
key of the length tag to the parent constructor.
The block in question is a CRC block, and it has two modes: It can check the CRC (which is
-then removed), or it can append a CRC to a sequence of bytes. The \p calculate_output_stream_length() function
-is thus very simple: depending on how the block is configured, the output is either 4 bytes
-longer or shorter than the input stream.
+then removed), or it can append a CRC to a sequence of bytes. The calculate_output_stream_length() function is thus very simple: depending on how the block is configured, the output is either 4 bytes longer or shorter than the input stream.
-The \p work() function looks very similar to any other work function. When writing the
+The work() function looks very similar to any other work function. When writing the
signal processing code, the following things must be kept in mind:
- The work function is called for exactly one PDU, and no more (or less) may be processed
-- \p ninput_items contains the exact number of items in this PDU (at every port).
- These items \em will be consumed after \p work() exits.
-- Don't call \p consume() or \p consume_each() yourself! gr::tagged_stream_block will do that
- for you.
-- You can call \p produce() or \p produce_each(), if you're doing something complicated.
- Don't forget to return WORK_CALLED_PRODUCE in that case.
-
+- ninput_items contains the exact number of items in this PDU (at every port). These items ''will'' be consumed after work() exits.
+- Don't call consume() or consume_each() yourself! gr::tagged_stream_block will do that for you.
+- You can call produce() or produce_each(), if you're doing something complicated. Don't forget to return WORK_CALLED_PRODUCE in that case.
-\subsection tsb_note_on_tp A note on tag propagation
+=== A note on tag propagation ===
Despite using tags for a special purpose, all tags that are not the length tag are treated
exactly as before: use gr::block::set_tag_propagation_policy() in the constructor.
In a lot of the cases, though, you will need to specify set_tag_propagation_policy(TPP_DONT)
-and manually handle the tag propagation in \p work(). This is because the unknown length of
+and manually handle the tag propagation in work(). This is because the unknown length of
the PDUs at compile time prohibits us from setting a precise relative rate of the block,
-which is a requirement for automatic tag propagation.
-Only if the tagged stream block is also a sync block (including interpolators and decimators,
-i.e. blocks with an integer rate change), can automatic tag propagation be reliably used.
+which is a requirement for automatic tag propagation. Only if the tagged stream block is also a sync block (including interpolators and decimators, i.e. blocks with an integer rate change), can automatic tag propagation be reliably used.
It is a general rule of GNU Radio blocks that they "properly" propagate tags, whatever this
means for a specific application.
@@ -209,22 +205,21 @@ they get removed, or do they get moved to the last item before the CRC? Also, th
output rate is different for every PDU length.
In this case, it is necessary for the developer to define a tag propagation policy and
-implement it in \p work(). Also, it is good practice to specify that tag propagation policy
+implement it in work(). Also, it is good practice to specify that tag propagation policy
in the blocks documentation.
-The actual length tags \em are treated differently, though. Most importantly, you don't have
+The actual length tags ''are'' treated differently, though. Most importantly, you don't have
to write the new length tag yourself. The key for the output length tag is the same as that
on the input, if you don't want this, you must override gr::tagged_stream_block::update_length_tags().
-
-\section tsb_connecting Connecting regular streaming blocks and tagged stream blocks
+== Connecting regular streaming blocks and tagged stream blocks ==
From the scheduler's point of view, all blocks are equivalent, and as long as the I/O
signatures are compatible, all of these blocks can be connected.
However, it is important to note that tagged stream blocks expect correctly tagged
streams, i.e. a length tag with a number of items at the beginning of every packet.
-If this is not the case, the <em>flow graph will crash</em>.
+If this is not the case, the '''flow graph will crash'''.
The most common cases are discussed separately:
Connecting a tagged stream block to a regular stream block: This is never a problem,
@@ -239,14 +234,13 @@ packet size might be changed to a different value from the tag value.
Mixing block types: This is possible if none of the regular stream blocks change
the rate. The ofdm_tx and ofdm_rx hierarchical blocks do this.
-
-\section tsb_adv_usage Advanced Usage
+== Advanced Usage ==
It is generally recommended to read the block documentation of gr::tagged_stream_block.
A few special cases are described here:
-\subsection tsb_multiplelentags Multiple length tags
+=== Multiple length tags ===
In some cases, a single tag is not enough. One example is the OFDM receiver: one OFDM frame contains a certain number of OFDM symbols, and another number of bytes--these numbers are only
very loosely related, and one cannot be calculated from the other.
@@ -255,7 +249,7 @@ gr::digital::ofdm_serializer_vcc is such a block. It is driven by the number of
but the output is determined by the number of complex symbols. In order to use multiple length
tag keys, it overrides gr::tagged_stream_block::update_length_tags().
-\subsection tsb_backtogrblock Falling back to gr::block behaviour
+=== Falling back to gr::block behavior ===
If, at compile-time, it is uncertain whether or not a block should be a
gr::tagged_stream_block, there is the possibility of falling back to gr::block behaviour.
@@ -271,50 +265,48 @@ gr::tagged_stream_block::d_length_tag_key_str is empty is a good choice.
gr::digital::ofdm_cyclic_prefixer implements this.
-\subsection tsb_otherwaysdetermineninput Other ways to determine the number of input items
+=== Other ways to determine the number of input items ===
If the number of input items is not stored as a pmt::pmt_integer, but there is a way to determine
it, gr::tagged_stream_block::parse_length_tags() can be overridden to figure out the length
of the PDU.
-\section tsb_examples Examples
+== Examples ==
-\subsection tsb_CRC32 CRC32
+=== CRC32 ===
-Block: gr::digital::crc32_bb
+Block: [https://github.com/gnuradio/gnuradio/blob/master/gr-digital/lib/crc32_bb_impl.cc crc32_bb]
This is a very simple block, and a good example to start with.
-\subsection tsb_ofdmeq OFDM Frame Equalizer
+=== OFDM Frame Equalizer ===
-Block: gr::digital::ofdm_frame_equalizer_vcvc
+Block: [https://github.com/gnuradio/gnuradio/blob/master/gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.cc ofdm_frame_equalizer_vcvc]
This block would be a sync block if tagged stream blocks didn't exist. It also uses more
than one tag to determine the output.
-\subsection tsb_muxer Tagged Stream Muxer
+=== Tagged Stream Muxer ===
-Block: gr::blocks::tagged_stream_mux
+Block: [https://github.com/gnuradio/gnuradio/blob/master/gr-blocks/lib/tagged_stream_mux_impl.cc tagged_stream_mux]
Use this to multiplex any number of tagged streams.
-\subsection tsb_ofdmprefixer Cyclic Prefixer (OFDM)
+=== Cyclic Prefixer (OFDM) ===
-Block: gr::digital::ofdm_cyclic_prefixer
+Block: [https://github.com/gnuradio/gnuradio/blob/master/gr-digital/lib/ofdm_cyclic_prefixer_impl.cc ofdm_cyclic_prefixer]
-This block uses the gr::block behaviour fallback.
+This block uses the gr::block behavior fallback.
-\section tsb_troubleshooting Troubleshooting
+=== Troubleshooting ===
-<b>My flow graph crashes with the error message "Missing length tag".</b>
+'''My flow graph crashes with the error message "Missing length tag".'''
This means the input of a tagged stream block was not correctly tagged.
The most common cause is when connecting a regular streaming block to a tagged
stream block. You can check the log output for the item number and port where
-this happened.
-
-
-
-
-
-*/
+this happened.</text>
+ <sha1>bxtmw5rv49ajotlmqajew2eq22qmbry</sha1>
+ </revision>
+ </page>
+</mediawiki> \ No newline at end of file
diff --git a/docs/usage-manual/(exported from wiki) Types of Blocks.txt b/docs/usage-manual/(exported from wiki) Types of Blocks.txt
new file mode 100644
index 0000000000..a68dee4180
--- /dev/null
+++ b/docs/usage-manual/(exported from wiki) Types of Blocks.txt
@@ -0,0 +1,275 @@
+<page>
+ <title>Types of Blocks</title>
+ <ns>0</ns>
+ <id>3495</id>
+ <revision>
+ <id>4281</id>
+ <parentid>4280</parentid>
+ <timestamp>2018-06-26T18:32:20Z</timestamp>
+ <contributor>
+ <username>777arc</username>
+ <id>632</id>
+ </contributor>
+ <comment>/* Synchronous Block */</comment>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="8059">== Introduction ==
+
+To take advantage of the gnuradio framework, users will create various blocks to implement the desired data processing. There are several types of blocks to choose from:
+
+* Synchronous Blocks (1:1)
+* Decimation Blocks (N:1)
+* Interpolation Blocks (1:M)
+* Basic (a.k.a. General) Blocks (N:M)
+
+== Synchronous Block ==
+
+The sync block allows users to write blocks that consume and produce an equal number of items per port. A sync block may have any number of inputs or outputs. When a sync block has zero inputs, its called a source. When a sync block has zero outputs, its called a sink.
+
+An example sync block in C++:
+
+<syntaxhighlight lang="cpp">
+#include <gr_sync_block.h>
+
+class my_sync_block : public gr_sync_block
+{
+public:
+ my_sync_block(...):
+ gr_sync_block("my block",
+ gr_make_io_signature(1, 1, sizeof(int32_t)),
+ gr_make_io_signature(1, 1, sizeof(int32_t)))
+ {
+ //constructor stuff
+ }
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ //work stuff...
+ return noutput_items;
+ }
+};
+</syntaxhighlight>
+
+Some observations:
+
+* noutput_items is the length in items of all input and output buffers
+* an input signature of gr_make_io_signature(0, 0, 0) makes this a source block
+* an output signature of gr_make_io_signature(0, 0, 0) makes this a sink block
+
+An example sync block in Python:
+
+<syntaxhighlight lang="python">
+class my_sync_block(gr.sync_block):
+ def __init__(self):
+ gr.sync_block.__init__(self,
+ name = "my sync block",
+ 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])
+</syntaxhighlight>
+
+The input_items and output_items are lists of lists. The input_items
+contains a vector of input samples for every input stream, and the
+output_items is a vector for each output stream where we can place
+items. Then length of output_items[0] is equivalent to the
+noutput_items concept we are so familiar with from the C++ blocks.
+
+Some observations:
+* The length of all input vector and all output vectors is identical
+* in_sig=None would turn this into a source block
+* out_sig=None would turn this into a sink block. In this case, use len(input_items [0]) since output_items is empty!
+* Unlike in C++ where we use the gr::io_signature class, here we can just create a Python list of the I/O data sizes using numpy data types, e.g.: numpy.int8, numpy.int16, numpy.float32
+
+== Decimation Block ==
+
+The decimation block is another type of fixed rate block where the number of input items is a fixed multiple of the number of output items.
+
+An example decimation block in c++
+
+<syntaxhighlight lang="cpp">
+#include <gr_sync_decimator.h>
+
+class my_decim_block : public gr_sync_decimator
+{
+public:
+ my_decim_block(...):
+ gr_sync_decimator("my decim block",
+ in_sig,
+ out_sig,
+ decimation)
+ {
+ //constructor stuff
+ }
+
+ //work function here...
+};
+</syntaxhighlight>
+
+Some observations:
+
+* The gr_sync_decimator constructor takes a 4th parameter, the decimation factor
+* The user should assume that the number of input items = noutput_items*decimation
+
+An example decimation block in Python:
+
+<syntaxhighlight lang="python">
+class my_decim_block(gr.block):
+ def __init__(self, args):
+ gr.block.__init__(self,
+ name="my block",
+ in_sig=[numpy.float32],
+ out_sig=[numpy.float32])
+ self.set_relative_rate(1.0/decimation)
+
+ #work function here...
+</syntaxhighlight>
+
+Some observations:
+
+* The set_relative_rate call configures the input/output relationship
+* To set an interpolation, use self.set_relative_rate(interpolation)
+* The following will be true len(input_items[i]) = len(output_items[j])*decimation
+
+== Interpolation Block ==
+
+The interpolation block is another type of fixed rate block where the number of output items is a fixed multiple of the number of input items.
+
+An example interpolation block in c++
+
+<syntaxhighlight lang="cpp">
+#include <gr_sync_interpolator.h>
+
+class my_interp_block : public gr_sync_interpolator
+{
+public:
+ my_interp_block(...):
+ gr_sync_interpolator("my interp block",
+ in_sig,
+ out_sig,
+ interpolation)
+ {
+ //constructor stuff
+ }
+
+ //work function here...
+};
+</syntaxhighlight>
+Some observations:
+
+* The gr_sync_interpolator constructor takes a 4th parameter, the interpolation factor
+* The user should assume that the number of input items = noutput_items/interpolation
+
+An example interpolation block in Python:
+
+<syntaxhighlight lang="python">
+class my_interp_block(gr.block):
+ def __init__(self, args):
+ gr.block.__init__(self,
+ name="my block",
+ in_sig=[numpy.float32],
+ out_sig=[numpy.float32])
+ self.set_relative_rate(interpolation)
+
+ #work function here...
+</syntaxhighlight>
+
+== Basic Block ==
+
+The basic block provides no relation between the number of input items and the number of output items. All other blocks are just simplifications of the basic block. Users should choose to inherit from basic block when the other blocks are not suitable.
+
+The adder revisited as a basic block in C++:
+
+<syntaxhighlight lang="cpp">
+#include <gr_block.h>
+
+class my_basic_block : public gr_block
+{
+public:
+ my_basic_adder_block(...):
+ gr_block("another adder block",
+ in_sig,
+ out_sig)
+ {
+ //constructor stuff
+ }
+
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ //cast buffers
+ const float* in0 = reinterpret_cast(input_items[0]);
+ const float* in1 = reinterpret_cast(input_items[1]);
+ float* out = reinterpret_cast(output_items[0]);
+
+ //process data
+ for(size_t i = 0; i < noutput_items; i++) {
+ out[i] = in0[i] + in1[i];
+ }
+
+ //consume the inputs
+ this->consume(0, noutput_items); //consume port 0 input
+ this->consume(1, noutput_items); //consume port 1 input
+ //this->consume_each(noutput_items); //or shortcut to consume on all inputs
+
+ //return produced
+ return noutput_items;
+ }
+};
+</syntaxhighlight>
+
+Some observations:
+
+* This class overloads the general_work() method, not work()
+* The general work has a parameter: ninput_items
+** ninput_items is a vector describing the length of each input buffer
+* Before return, general_work must manually consume the used inputs
+* The number of items in the input buffers is assumed to be noutput_items
+** Users may alter this behaviour by overloading the forecast() method
+
+The adder revisited as a basic block in Python:
+
+<syntaxhighlight lang="python">
+from gnuradio import gr
+import gnuradio.extras
+
+class my_basic_adder_block(gr.block):
+ def __init__(self, args):
+ gr.block.__init__(self,
+ name="another_adder_block",
+ in_sig=[...],
+ out_sig=[...])
+ self.set_auto_consume(False)
+
+ def forecast(self, noutput_items, ninput_items_required):
+ #setup size of input_items[i] for work call
+ for i in range(len(ninput_items_required)):
+ ninput_items_required[i] = noutput_items
+
+ def work(self, input_items, output_items):
+ #buffer references
+ in0 = input_items[0][:len(output_items[0])]
+ in1 = input_items[1][:len(output_items[0])]
+ out = output_items[0]
+
+ #process data
+ out[:] = in0 + in1
+
+ //consume the inputs
+ self.consume(0, len(in0)) //consume port 0 input
+ self.consume(1, len(in1)) //consume port 1 input
+ #self.consume_each(len(out)) //or shortcut to consume on all inputs
+
+ #return produced
+ return len(out)
+</syntaxhighlight></text>
+ <sha1>2twbp3b6eokenw23qolevp25jtaqk31</sha1>
+ </revision>
+ </page>
+</mediawiki> \ No newline at end of file
diff --git a/docs/doxygen/other/volk_guide.dox b/docs/usage-manual/(exported from wiki) VOLK Guide.txt
index 1f8f128e4b..7e9ef1161e 100644
--- a/docs/doxygen/other/volk_guide.dox
+++ b/docs/usage-manual/(exported from wiki) VOLK Guide.txt
@@ -1,21 +1,25 @@
-# Copyright (C) 2017 Free Software Foundation, Inc.
-#
-# Permission is granted to copy, distribute and/or modify this document
-# under the terms of the GNU Free Documentation License, Version 1.3
-# or any later version published by the Free Software Foundation;
-# with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
-# A copy of the license is included in the section entitled "GNU
-# Free Documentation License".
-
-/*! \page volk_guide Instructions for using VOLK in GNU Radio
+<page>
+ <title>VOLK Guide</title>
+ <ns>0</ns>
+ <id>3491</id>
+ <revision>
+ <id>4296</id>
+ <parentid>4232</parentid>
+ <timestamp>2018-06-26T19:57:30Z</timestamp>
+ <contributor>
+ <username>777arc</username>
+ <id>632</id>
+ </contributor>
+ <comment>/* Calling VOLK kernels in Work() */</comment>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="6023">== Introduction ==
Note: Many blocks have already been converted to use VOLK in their calls, so
they can also serve as examples. See the
gr::blocks::complex_to_<type>.h files for examples of various blocks
that make use of VOLK.
-\section volk_intro Introduction
-
VOLK is the Vector-Optimized Library of Kernels. It is a library that
contains kernels of hand-written SIMD code for different mathematical
operations. Since each SIMD architecture can be greatly different and
@@ -38,23 +42,19 @@ multiplication of a vector of floating point numbers (each item in the
vector is multiplied by the same value). This kernel has the following
proto-kernels that are defined for 'generic,' 'avx,' 'sse,' and 'neon'
-\code
void volk_32f_s32f_multiply_32f_a_generic
void volk_32f_s32f_multiply_32f_a_sse
void volk_32f_s32f_multiply_32f_a_avx
void volk_32f_s32f_multiply_32f_a_neon
-\endcode
These proto-kernels means that on platforms with AVX support, VOLK can
select this option or the SSE option, depending on which is faster. If
all else fails, VOLK can fall back on the generic proto-kernel, which
will always work.
-See <a
-href="http://libvolk.org</a> for details on the VOLK naming scheme.
-
+See [http://libvolk.org libvolk.org] for details on the VOLK naming scheme.
-\section volk_alignment Setting and Using Memory Alignment Information
+== Setting and Using Memory Alignment Information ==
For VOLK to work as best as possible, we want to use memory-aligned
SIMD calls, which means we have to have some way of knowing and
@@ -62,11 +62,9 @@ controlling the alignment of the buffers passed to gr_block's work
function. We set the alignment requirement for SIMD aligned memory
calls with:
-\code
const int alignment_multiple =
volk_get_alignment() / output_item_size;
set_alignment(std::max(1,alignment_multiple));
-\endcode
The VOLK function 'volk_get_alignment' provides the alignment of the
the machine architecture. We then base the alignment on the number of
@@ -88,8 +86,7 @@ indicate as much so that the block can then decide what best to
do. The next section discusses the use of the aligned/unaligned
information in a gr_block's work function.
-
-\section volk_work Calling VOLK kernels in Work()
+== Calling VOLK kernels in Work() ==
The buffers passed to work/general_work in a gr_block are not
guaranteed to be aligned, but they will mostly be aligned whenever
@@ -100,26 +97,24 @@ buffer alignments and call the correct version of the kernel for
us. From the user-level view of VOLK, calling the dispatcher allows us
to ignore the concept of aligned versus unaligned. This looks like:
-\code
-int
-gr_some_block::work (int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
-{
- const float *in = (const float *) input_items[0];
- float *out = (float *) output_items[0];
-
- // Call the dispatcher to check alignment and call the _a or _u
- // version of the kernel.
- volk_32f_something_32f(out, in, noutput_items);
-
- return noutput_items;
-}
-\endcode
-
-
-
-\section volk_tuning Tuning VOLK Performance
+<syntaxhighlight lang="cpp">
+ int
+ gr_some_block::work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const float *in = (const float *) input_items[0];
+ float *out = (float *) output_items[0];
+
+ // Call the dispatcher to check alignment and call the _a or _u
+ // version of the kernel.
+ volk_32f_something_32f(out, in, noutput_items);
+
+ return noutput_items;
+ }
+</syntaxhighlight>
+
+== Tuning VOLK Performance ==
VOLK comes with a profiler that will build a config file for the best
SIMD architecture for your processor. Run volk_profile that is
@@ -129,7 +124,7 @@ will write to $HOME/.volk/volk_config the best architecture for the
VOLK function. This file is read when using a function to know the
best version of the function to execute.
-\subsection volk_hand_tuning Hand-Tuning Performance
+=== Hand-Tuning Performance ===
If you know a particular architecture works best for your processor,
you can specify the particular architecture to use in the VOLK
@@ -137,9 +132,7 @@ preferences file: $HOME/.volk/volk_config
The file looks like:
-\code
- volk_<FUNCTION_NAME> <ARCHITECTURE>
-\endcode
+ volk_<FUNCTION_NAME> <ARCHITECTURE>
Where the "FUNCTION_NAME" is the particular function that you want to
over-ride the default value and "ARCHITECTURE" is the VOLK SIMD
@@ -148,13 +141,13 @@ example, the following config file tells VOLK to use SSE3 for the
aligned and unaligned versions of a function that multiplies two
complex streams together.
-\code
- volk_32fc_x2_multiply_32fc_a sse3
- volk_32fc_x2_multiply_32fc_u sse3
-\endcode
+ volk_32fc_x2_multiply_32fc_a sse3
+ volk_32fc_x2_multiply_32fc_u sse3
-\b Tip: if benchmarking GNU Radio blocks, it can be useful to have a
+'''Tip:''' If benchmarking GNU Radio blocks, it can be useful to have a
volk_config file that sets all architectures to 'generic' as a way to
-test the vectorized versus non-vectorized implementations.
-
-*/
+test the vectorized versus non-vectorized implementations.</text>
+ <sha1>l1efbbjitjppeec1a99mjnlyimos14e</sha1>
+ </revision>
+ </page>
+</mediawiki> \ No newline at end of file
diff --git a/docs/usage-manual/.gitignore b/docs/usage-manual/.gitignore
new file mode 100644
index 0000000000..283f43cb08
--- /dev/null
+++ b/docs/usage-manual/.gitignore
@@ -0,0 +1 @@
+geckodriver.log
diff --git a/docs/usage-manual/README.md b/docs/usage-manual/README.md
new file mode 100644
index 0000000000..4b98452acd
--- /dev/null
+++ b/docs/usage-manual/README.md
@@ -0,0 +1,6 @@
+To export the usage manual off the wiki and update the snapshot stored in the repo:
+* pip install selenium
+* download the latest version of geckodriver form here https://github.com/mozilla/geckodriver/releases
+* extract/move it into /usr/local/bin
+* python export-usage-manual.py
+* the usage manual text files in this directory should now be updated
diff --git a/docs/usage-manual/export-usage-manual.py b/docs/usage-manual/export-usage-manual.py
new file mode 100644
index 0000000000..02d3fb620a
--- /dev/null
+++ b/docs/usage-manual/export-usage-manual.py
@@ -0,0 +1,53 @@
+from selenium import webdriver
+from selenium.webdriver.common.keys import Keys
+import time
+import HTMLParser
+import os
+
+# Settings
+pages_to_save = ['GNURadioCompanion',
+ 'Handling Flowgraphs',
+ 'Types of Blocks',
+ 'Metadata Information',
+ 'Stream Tags',
+ 'Block Thread Affinity and Priority',
+ 'Configuration Files',
+ 'VOLK Guide',
+ 'Polymorphic Types (PMTs)',
+ 'Message Passing',
+ 'QT GUI',
+ 'Logging',
+ 'Performance Counters',
+ 'Tagged Stream Blocks',
+ 'Polyphase Filterbanks']
+
+# set up web driver
+driver = webdriver.Firefox()
+for page_name in pages_to_save:
+ driver.get("https://wiki.gnuradio.org/index.php/Special:Export")
+
+ # fill in text box
+ text_area = driver.find_element_by_xpath("//*[@name='pages']")
+ text_area.send_keys(page_name)
+
+ # uncheck "save as file" box
+ check_box = driver.find_element_by_xpath("//*[@name='wpDownload']")
+ check_box.click()
+
+ # hit Export
+ submit_button = driver.find_element_by_xpath("//*[@value='Export']")
+ submit_button.click()
+
+ # get HTML of new page
+ raw_html = driver.page_source
+ start_index = raw_html.find('<page>')
+ cropped_html = raw_html[start_index:]
+
+ # save text to file
+ h = HTMLParser.HTMLParser()
+ cropped_html_text = h.unescape(cropped_html) # makes it so stuff like &gt shows up as a greater than sign
+ text_file = open("(exported from wiki) " + page_name + ".txt", "w")
+ text_file.write(cropped_html_text)
+ text_file.close()
+
+driver.close()