summaryrefslogtreecommitdiff
path: root/gr-digital/doc
diff options
context:
space:
mode:
authorBogdan Radulescu <bogdan@nimblex.net>2018-02-03 13:30:58 +0100
committerMartin Braun <martin.braun@ettus.com>2018-02-03 13:30:58 +0100
commit3c177dbe3b93dc9a5db27f9b53417a28a1ead6ad (patch)
treef25c24b0d2127d0dc750e53e669e4d5c2e071116 /gr-digital/doc
parenta0adcd3347c7ffd6ef3c42ce7705a23978774d3b (diff)
Rename subdir doc to docs where appropriate
This makes the subdir naming consistent across modules.
Diffstat (limited to 'gr-digital/doc')
-rw-r--r--gr-digital/doc/CMakeLists.txt23
-rw-r--r--gr-digital/doc/README.digital13
-rw-r--r--gr-digital/doc/digital.dox502
-rw-r--r--gr-digital/doc/packet_comms.dox653
4 files changed, 0 insertions, 1191 deletions
diff --git a/gr-digital/doc/CMakeLists.txt b/gr-digital/doc/CMakeLists.txt
deleted file mode 100644
index 5383236da0..0000000000
--- a/gr-digital/doc/CMakeLists.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright 2011 Free Software Foundation, Inc.
-#
-# This file is part of GNU Radio
-#
-# GNU Radio is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GNU Radio is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GNU Radio; see the file COPYING. If not, write to
-# the Free Software Foundation, Inc., 51 Franklin Street,
-# Boston, MA 02110-1301, USA.
-
-install(
- FILES README.digital
- DESTINATION ${GR_PKG_DOC_DIR}
-)
diff --git a/gr-digital/doc/README.digital b/gr-digital/doc/README.digital
deleted file mode 100644
index f4d40f3a05..0000000000
--- a/gr-digital/doc/README.digital
+++ /dev/null
@@ -1,13 +0,0 @@
-This is the gr-digital package. It contains all of the digital
-modulation blocks, utilities, and examples. To use the digital blocks,
-the Python namespaces is in gnuradio.digital, which would be normally
-imported as:
-
- from gnuradio import digital
-
-See the Doxygen documentation for details about the blocks available
-in this package. A quick listing of the details can be found in Python
-after importing by using:
-
- help(digital)
-
diff --git a/gr-digital/doc/digital.dox b/gr-digital/doc/digital.dox
deleted file mode 100644
index 08e63008b3..0000000000
--- a/gr-digital/doc/digital.dox
+++ /dev/null
@@ -1,502 +0,0 @@
-/*! \page page_digital Digital Modulation
-
-\section digtial_introduction Introduction
-This is the gr-digital package. It contains all of the digital
-modulation blocks, utilities, and examples. To use the digital blocks,
-the Python namespaces is in gnuradio.digital, which would be normally
-imported as:
-
-\code
- from gnuradio import digital
-\endcode
-
-See the Doxygen documentation for details about the blocks available
-in this package.
-
-A quick listing of the details can be found in Python after importing
-by using:
-
-\code
- help(digital)
-\endcode
-
-\section digital_constellations Constellation Objects
-
-GNU Radio supports the creation and use of Constellation objects for
-many of its digital communications needs. We define these
-constellations with a set of constellation points in complex space and
-the symbol mappings to those points. For a constellation that has 4
-symbols, it then has log2(4) = 2 bits/symbol. We define this
-constellation with:
-
-<pre>
- constel_points = [c0, c1, c2, c3]
- symbols = [s0, s1, s2, s3]
-</pre>
-
-In this case: \f$c_i \in C\f$ and \f$s_i \in [00, 01, 10,
-11]\f$. Also, the mapping is a 1-to-1 for the items in both lists, so
-the symbol \f$s_0\f$ is positioned in complex space at the point
-\f$c_0\f$.
-
-In the code itself, the symbols are referred to as the
-'pre_diff_code' since this is the mapping before the application of
-differential modulation, if used.
-
-The constellation object classes are defined in constellation.h. There
-is a hierarchy of classes for different purposes and which represent
-special classes of constellations. The all derive from the virtual
-class gr::digital::constellation. All constellations we will make are
-based on classes derived from this base:
-
-<pre>
-gr::digital::constellation
- --> gr::digital::constellation_calcdist
- --> gr::digital::constellation_sector
- --> gr::digital::constellation_rect
- --> gr::digital::constellation_expl_rect
- --> gr::digital::constellation_psk
- --> gr::digital::constellation_bpsk
- --> gr::digital::constellation_qpsk
- --> gr::digital::constellation_dqpsk
- --> gr::digital::constellation_8psk
-</pre>
-
-Each constellation class has a set of attributes and functions useful
-for manipulating the constellations and for converting symbols to and
-from complex points. One of the more important functions is the
-gr::digital::constellation::decision_maker function that takes in a
-sample in complex space and returns the symbol that it maps to. How
-this calculation is performed generally distinguishes the
-constellation classes from each other.
-
-The gr::digital::constellation_calcdist is the most generic
-constellation class we can create. This takes in the constellation
-points, symbol mapping, a rotational symmetry, and the number of
-dimensions. The decision_maker function takes in a complex sample x
-and calculates the Euclidean distance between x and each point in the
-constellation map of the object. The constellation point that has the
-minimum Euclidean distance to x is selected as the best match. The
-decision_maker will then return the symbol value that matches to this
-selected constellation point.
-
-We then have a concept of a constellation with a well-defined concept
-of sectors in the gr::digital::constellation_sector. This is farther
-refined if we know that the constellation is rectangular and can use
-the gr::digital::constellation_rect class. These classes have an
-overloaded decision_maker function that is specific to how the sectors
-are defined in the constructor. Essentially, the decision making math
-for this class is less costly than calculating the Euclidean distance
-for each point in the space. So if we can sectorize our constellation,
-using this class will be computationally cheaper.
-
-Finally, we have a set of pre-defined, hard-coded constellations for
-BPSK (gr::digital::constellation_bpsk), QPSK
-(gr::digital::constellation_qpsk), DQPSK
-(gr::digital::constellation_dqpsk), and 8PSK
-(gr::digital::constellation_8psk). These derive directly from
-gr::digital::constellation and specifically overload the decision_maker
-function. We have very simple metrics for calculating decisions for
-each of these constellations. For BPSK, we simply slice on the real
-axis. Samples are based solely on whether the real part of the complex
-symbol x is greater than or less than 0. Similar, simple, decision
-makers are defined for the others.
-
-Note that these specific constellations for the PSK modulations are
-defined for only one mapping of the constellation points to the
-symbols. Each is Gray coded, but for a specific Gray coding that is
-hard-coded into the class.
-
-
-\subsection digital_grc_constellations Constellation Objects in GRC
-
-GRC provides two constellation representations that we can use to more
-easily define and interact with constellation objects. These are
-located in the 'Modulators' category as 'Constellation Object' and
-'Constellation Rect. Object'. These allow us to easily specify the
-constellation points, symbol list, and other properties of the
-constellation objects. They return the base() of the object, so the
-variable's ID can be used directly with blocks that accept
-constellation objects.
-
-These constellation blocks also allow us to specify the soft decision
-LUT if using the constellation object for soft decision outputs. The
-input can either be 'None' (default), a list of the soft bits that
-were generated externally or by another function, or 'auto' where the
-block will automatically calculate the soft decisions based on the
-constellation points and symbol map.
-
-
-\section digital_python_helpers Python Constellation Helper Functions
-
-A series of helper functions are defined in Python to create
-different, common constellations. There are various functions that
-have various levels of complexity in their definitions.
-
-\subsection digital_python_helpers_psk PSK Python Helpers
-
-There are two modules imported directly into gnuradio.digital. The
-first is gr-digital/python/digital/psk.py and the second is
-gr-digital/python/digital/psk_constellations.py. The
-gr-digital/python/digital/psk.py module defines the following
-constellations:
-
-<pre>
- psk_constellation(m, mod_code, differential)
-</pre>
-
-This function defines a PSK modulation of order 'm' (that is, there
-are m number of constellation points / symbols). The 'mod_code' is
-either mod_codes.GRAY_CODE or mode_codes.NO_CODE to set the symbol
-mapping up as either Gray coded or not. The 'differential' argument is
-either True to use differential coding or False for non-differential
-coding.
-
-This function creates and returns a constellation object that can then
-be used by any block that takes a constellation
-(gr::digital::constellation_decoder_cb,
-gr::digital::constellation_receiver_cb,
-gr::digital::constellation_soft_decoder_cf, or
-gr::digital::lms_dd_equalizer_cc).
-
-The gr-digital/python/digital/psk.py module also holds functions
-similar to digital.psk_constellation but that create a full modulator
-and demodulator chain derived from digital.generic_mod_demod.
-
-<pre>
- psk_mod(constellation_points, mod_code, differential, *args, **kwargs)
- psk_demod(constellation_points, mod_code, differential, *args, **kwargs)
-</pre>
-
-The args and kwargs are parameters of the generic_mod or generic_demod
-passed directly to them. See \ref digital_generic_mod_demod for
-details of this interface.
-
-There is another Python file full of helper functions to create
-different constellations. This is found in the
-gr-digital/python/digital/psk_constellation.py file. This file
-provides functions that build the vectors of constellation points and
-symbol mappings that can be used to create a constellation
-object. These are particularly helpful when using the Constellation
-Obj. and Constellation Rect. GUI elements in GRC.
-
-The gr-digital/python/digital/psk_constellation.py file has extensive
-documentation that describes the naming scheme used for the different
-constellations that will not be repeated here. The main thing to
-understand is that these functions define constellations of the same
-order with different Gray code mappings. The function names are:
-
-<pre>
- (const_points, symbol_map) = psk_M_0xk_<permutation>()
-</pre>
-
-Where M is the order of the modulation (2 for BPSK, 4 for QPSK,
-etc.), and k and \<permutation\> define a particular encoding for the
-Gray code mapping used. The documentation in the file explains how
-these two concepts define the Gray code mapping.
-
-These functions are also simply named "psk_M_n" when n is an integer
-from 0 to N-1 for however many mappings are defined for that
-modulation. Not all modulations are fully defined, and the value
-for n has no other meaning except as a counter.
-
-The functions return a tuple of lists. The first list in the tuple is
-the list of complex constellation points and the second list contains
-the symbols mapped to those points. These lists can then be passed to
-a constellation class directly to create a constellation of any Gray
-code mapping needed.
-
-While not all Gray code mappings of the modulations are defined, there
-is a generator function to automatically build any rotation of a basis
-constellation:
-
-<pre>
- (const_points, symbol_map) = \
- constellation_map_generator(basis_cpoints, basis_symbols, k, pi)
-</pre>
-
-We provide a basis constellation map and symbol map as the fundamental
-rotation of the constellation points. This function uses the k and pi
-inputs (see the discussion in psk_constellation.py for what these
-mean) to return a new rotation of the constellation's symbols. If the
-basis symbols are Gray coded than the output symbols will also be Gray
-coded. Note that this algorithm specifically depends on the
-constellation in complex space to be square to preserve the Gray code
-property.
-
-
-\subsection digital_python_helpers_qam QAM Python Helpers
-
-Similar to defining PSK modulations, GNU Radio also has helpers for
-some QAM modulations, found in gr-digital/python/digital/qam.py and
-gr-digital/python/digital/qam_constellations.py. Similar functions to
-what has been described for PSK exist here:
-
-<pre>
- qam_constellation(constellation_points, differential, mod_code,
- large_ampls_to_corners)
- qam_mod(constellation_points, differential, mod_code, *args, **kwargs)
- qam_demod(constellation_points, differential, mod_code,
- large_ampls_to_corner, *args, **kwargs)
-</pre>
-
-The parameters to these functions is the same as for the PSK
-equivalents. The new argument 'large_ampls_to_corner' is defined in
-the documentation as:
-
-<pre>
- large_ampls_to_corners: If this is set to True then when the
- constellation is making decisions, points that are far outside
- the constellation are mapped to the closest corner rather than
- the closet constellation point. This can help with phase
- locking.
-</pre>
-
-Similarly, gr-digital/python/digital/qam_constellations.py defines a of
-QAM constellation functions that return a tuple containing the
-constellation points and the symbol mappings. The naming scheme is
-defined in depth in the module itself and is similar to the equivalent
-set of PSK functions.
-
-Currently, only a subset of 16QAM symbol mappings are defined, but we
-can use of the constellation_map_generator function described in the
-previous section to define more mapping rotations for and square QAM
-modulation.
-
-
-\section digital_generic_mod_demod The Generic Modulator/Demodulator
-Hierarchical Blocks
-
-Since digital modulation and demodulation are complex functions, the
-different parts can be done by different existing GNU Radio blocks. We
-have combined these into a generic modulator and generic demodulator
-hierarchical blocks to make access and use much easier. This file can
-be found as gr-digital/python/digital/generic_mod_demod.py.
-
-\subsection digital_generic_mod Generic Modulator
-
-The modulator constructor looks like:
-
-<pre>
- digital.generic_mod(constellation, differential, samples_per_symbol,
- pre_diff_code, excess_bw, verbose, log)
-</pre>
-
-The 'constellation' arg is a constellation object as defined above in
-\ref digital_constellations and can represent any constellation
-mapping. The 'differential' arg is a bool to turn differential coding
-on/off. The block also performs pulse shaping and interpolates the
-pulse-shaped filter to some number of 'samples_per_symbol'. The pulse
-shaping is a root raised cosine filter defined by the excess
-bandwidth (or alpha) parameter called 'excess_bw.'
-
-We can also turn on a verbose mode to output information to the
-user. The 'log' parameter toggles logging data on/off. When logging is
-turned on, it stores every stage of the modulation to a different file
-so that each stage can be independently analyzed.
-
-
-\subsection digital_generic_demod Generic Demodulator
-
-The demodulator looks like:
-
-<pre>
- digital.generic_demod(constellation, differential, samples_per_symbol,
- pre_diff_code, excess_bw, freq_bw, timing_bw,
- phase_bw, verbose, log)
-</pre>
-
-The additional parameters to the demodulator are the loop bandwidths
-for the different signal recovery loops used internally. There are
-separate loops for frequency acquisition, timing acquisition, and fine
-frequency / phase acquisition, controlled in tern by each of the
-three 'X_bw' arguments. Otherwise, the arguments are the same as the
-modulator.
-
-
-\subsection digital_generic_guts Guts of the Modulator and Demodulator
-
-The generic modulator looks like the following:
-
-<pre>
- blocks.packed_to_unpacked_bb: takes in packed bytes
- digital.map_bb: maps baseband symbols to the pre-differential encoding
- digital.diff_encoder_bb: differentially encode symbols
- digital.chunks_to_symbols_bc: convert symbols to complex samples
- filter.pfb_arb_resampler_ccf: perform upsampling to samps/symbol and pulse shape
-</pre>
-
-The mapping and chunks-to-symbols stages are done using the
-information provided by the constellation object.
-
-Note that the modulator takes in packed bytes, which means that all 8
-bits per byte are used and unpacked into k bits per symbol.
-
-The generic demodulator looks like the following:
-
-<pre>
- digital.fll_band_edge_cc: Performs coarse frequency correction
- digital.pfb_clock_sync_ccf: Matched filtering and timing recovery
- digital.constellation_receiver_cb: Phase tracking and decision making (hard bits)
- digital.diff_decoder_bb: Differential decoding
- digital.map_bb: Map to pre-differential symbols
- blocks.unpack_k_bits_bb: Unpack k bits/symbol to a stream of bits
-</pre>
-
-This block outputs unpacked bits, so each output item represents a
-single bit of data. A block like 'pack_k_bits' can be used following
-this to convert the data back into bytes.
-
-
-\section digital_constellation_modulator Constellation Modulator
-
-The Constellation Modulator, Constellation Receiver, and Constellation
-Decoder can all take Constellation Objects to define what they are
-meant to transmit and receive.
-
-The gr::digital::constellation_modulator block takes as a parameter
-the reference to the constellation object. The block is very generic
-in that the mapping from bits to symbols is done based on the
-constellation object passed to it. The modulator block requires packed
-bits as the input stream (that is, all 8 bits of the stream contain
-information).
-
-The other parameters of this block include a setting as to whether or
-not to differentially encode the symbols, the number of samples per
-symbols, and the excess bandwidth of the transmitted pulse-shaped
-signal.
-
-We can set up the transmitter using the constellation modulator block
-and use the same constellation object at the receiver so we know the
-same constellation settings are being used.
-
-\section digital_softbits Support for Soft Decisions
-
-To support soft decisions of the receivers instead of the current hard
-decisions, the constellation objects also accept a soft decision
-look-up table (LUT) or can be told to generate a LUT based on the
-constellation points and symbol map.
-
-All constellation objects can accept a new LUT using the
-gr::digital::constellation::set_soft_dec_lut function. This function
-takes in a LUT, which is a vector of floating point tuples (in C++ it
-is just a vector\<vector\<float\>\>) and a precision value that
-specifies how accurate the LUT is to a given number of bits.
-
-The constellation objects also have two functions to calculate the
-soft decisions from their constellation and symbol map. The
-gr::digital::constellation::calc_soft_dec takes a complex number (and
-optional noise power) and returns the soft decisions as a list of
-floats. This function is used internally in the
-gr::digital::constellation::gen_soft_dec_lut, which takes in the LUT's
-precision (as a number of bits) and an optional noise power estimate,
-if known. This function calculates the soft decisions itself. These
-functions are very expensive because each constellation point is taken
-into account during the calculation. We provide the
-gr::digital::constellation::set_soft_dec_lut in order to allow users
-to use one of the many known approximations to more quickly generate
-the soft decision LUT.
-
-The gr::digital::constellation::calc_soft_dec function could be used
-instead of drawing directly from a LUT, which is probably only
-important if the noise floor or channel estimates are likely to change
-and we want to account for this in the decisions. The basic
-implementation of the soft decision calculation is the full
-calculation based on the distance between the sample and all points in
-the constellation space. If using this function for real-time
-decisions, a new object should inherit from the
-gr::digital::constellation class (or whichever child class is being
-used) and redefine this function with a faster approximation
-calculation.
-
-Note: If no soft decision LUT is defined but
-gr::digital::constellation::soft_decision_maker is called then the
-full calculation from gr::digital::constellation::calc_soft_dec is
-used by default.
-
-The LUT is a list of tuples, where each index of the list is some
-quantized (to some number of bits of precision) point in the
-constellation space. At each index, there is a tuple of \e k soft
-bit values for a constellation with \e k bits/symbol.
-
-To help with this, the file
-gr-digital/python/digital/soft_dec_lut_gen.py can be used to create
-these tables. The function digital.soft_dec_table_generator(generator,
-precision) function generates a LUT based on some generator function
-and the number of bits of precision required. This file contains
-documentation explaining the system better. Or the
-digital.soft_dec_table(constel, symbols, prec, npwr=1) can be used
-which takes in the constellation map and symbols to do the full raw
-calculation of the softbits as opposed to a generator function.
-
-To further aid the LUT creation, the digital module also defines a
-number of functions that can be used as soft decision generators for
-the soft_dec_table function. These functions are found in
-psk_constellations.py and qam_constellations.py. These files were
-already mentioned as they contain a set of functions that return
-tuples of constellation points and Gray-mapped symbols for different
-modulations. But these files contain a second set of functions
-prefixed by 'sd_' which are soft decision LUT generator functions Each
-LUT generator takes in a complex value and returns the tuple of soft
-decisions for that point in complex space. To aid with this,
-soft_dec_lut_gen.py defines a 'calc_from_table' function that takes in
-a complex sample, the precision of the table, and the LUT itself and
-returns the tuple of soft decisions in the LUT that is closest to the
-given symbol. Each of these functions can be found directly from the
-'digital' Python module.
-
-The LUTs are defined from min to max constellation points in both the
-real and imaginary axes. That means that signals coming in outside of
-these bounds are clipped to 1. So there is no added certainty for
-values beyond these bounds.
-
-The gr::digital::constellation_soft_decoder_cf block takes in a
-constellation object where a soft decision LUT is defined. It takes in
-complex samples and produces a stream of floats of soft decisions. The
-soft decision outputs are not grouped together, it is just a stream of
-floats. So this block acts as an interpolator that takes in 1 complex
-sample and return \e k float for \e k bits per symbol.
-
-
-\subsection soft_dec_api Review of the Soft Decision API/Functions
-
-Files of interest:
-\li psk_constellations.py: PSK constellations and soft decision generators
-\li qam_constellations.py: QAM constellations and soft decision generators
-\li soft_dec_lut_gen.py: Functions to build soft decision LUTs and test them
-\li test_soft_decisions.py: A script that generates a random complex
-sample and calculates the soft decisions using various methods. Plots
-the sample against the full constellation. Requires matplotlib installed.
-
-Functions:
-\li digital.sd_psk_2_*: Returns (constellation, symbol_map) lists for
-different rotations for BPSK.
-\li digital.sd_psk_4_*: Returns (constellation, symbol_map) lists for
-different rotations for QPSK.
-\li digital.sd_qam_16_*: Returns (constellation, symbol_map) lists for
-different rotations for 16QAM.
-\li digital.soft_dec_table_generator: Takes in a generator function
-(like the digital.sd_XXX above) and creates a LUT to a specific precision.
-\li digital.soft_dec_table: Takes in a constellation/symbol map and
-uses digital.calc_soft_dec to generate a LUT to a specific precision.
-\li digital.calc_soft_dec: Takes a complex sample and calculates the
-soft decisions for a given constellation/symbol mapping.
-\li digital.calc_soft_dec_from_table: Given a sample and a LUT,
-returns the soft decisions of the LUT for the nearest point to the
-sample.
-
-C++ Interface:
-\li gr::digital::constellation::gen_soft_dec_lut: uses calc_soft_dec
-to internally generate a soft decision LUT.
-\li gr::digital::constellation::calc_soft_dec: calculates the soft
-decisions for a given sample from the full constellation/symbol map.
-\li gr::digital::constellation::set_soft_dec_lut: Set the soft
-decision LUT from an externally-calculated LUT.
-\li gr::digital::constellation::has_soft_dec_lut: has the LUT been
-set/generated or not.
-\li gr::digital::constellation::soft_decision_maker: Used by
-gr::digital::constellation_soft_decoder to convert samples to soft
-decisions. If a LUT is defined, uses it; else, uses calc_soft_dec.
-
-
-*/
diff --git a/gr-digital/doc/packet_comms.dox b/gr-digital/doc/packet_comms.dox
deleted file mode 100644
index 9b9f59fbd7..0000000000
--- a/gr-digital/doc/packet_comms.dox
+++ /dev/null
@@ -1,653 +0,0 @@
-/*! \page page_packet_comms Packet Communications
-
-\section packet_introduction Introduction
-
-This page describes...
-
-The point of these examples and the work is to provide a canonical
-tool for exploring burst digital communications. Providing the entire
-PHY chain in GRC is to help us more easily explore and extract
-portions of the transmit and receive chains to better understand,
-tweak, and optimize the system.
-
-
-\section packet_tx Understanding the Transmitter
-
-The transmitter PHY layer defines the following properties of the
-transmitted frame:
-
-- Data integrity check, generally a \ref gr::digital::crc32_async_bb
- "CRC". Standard practice would be to calculate a CRC32 of the
- payload and append this to the end of the frame.
-
-- \ref page_fec "Forward Error Correction (FEC)". For correcting bit
- errors during reception, we use FEC codes, which have different
- properties for complexity, correcting capabilities, and amounts of
- added redundancy. See our \ref page_fec "FEC-API page" in the manual
- for more on how to use these and what types of codes are already
- available.
-
-- Frame formatting. We expect the data to have been delivered to the
- transmitter from some higher layer (MAC/Network), which we treat as
- the payload. The PHY layer then puts on a bit of its own framing in
- order to properly transmit it for other radios to receive
- correctly. This often involves some information about the payload
- format, such as the length, the type of FEC code used, and the type
- of modulation or modulation parameters. The PHY layer frame will
- also often add a known word to the front to help with
- synchronization and identification. We use the Packet Header
- Formatter block for this, which is completely defined by a packet
- formatter object. See the gr::digital::header_format_base class
- to understand more about how these formatters are created and used.
-
- The \ref gr::digital::protocol_formatter_async "Protocol Formatter"
- has two output paths, both emitted as PDUs from message ports. The
- first message port is "header" that emits the header created for the
- payload based on the formatter object. The second message port is
- "payload" which is just the input payload PDU re-emitted. This
- creates two paths, which allows us to separately modulate the header
- and payload differently as well as encode the header with a
- different FEC code. We often want to do this to provide a much
- simpler and more robust modulation and FEC structure to the header
- to ensure that it is correctly received and then use a different
- modulation and code for the payload to maximize throughput.
-
- NOTE: If the header formatter adds the known word / access code
- here, and then we apply an FEC code to the header, then we have the
- problem that the known word is also encoded. The receiver must be
- made aware of this and correctly look for the encoded known
- word. The packet_tx hier block example is a case where this
- happens. If we use a repetition encoder, the access code is now
- three bits out for every bit in. The packet_rx receiver example has
- to account for this in the Correlation Estimator block that is
- correlating against the known word.
-
-- Modulators. We create a modulator path for both the header and
- payload. We define the operations of these two paths completely
- using a \ref gr::digital::constellation "Constellation Object" (see
- the \ref digital_constellations "Digital Modulation" manual page for
- more information). The constellation objects define the mapping from
- bits to complex symbols. You can use these objects in various ways,
- but the packet_tx.grc example provides one way. After moving from
- the PDU to tagged stream mode, the \ref gr::blocks::repack_bits_bb
- "Repack Bits block" takes the packed 8-bits/byte data and converts
- this into "chunks" of the number of bits per symbol of the
- modulation (using the \ref
- gr::digital::constellation::bits_per_symbol() "bits_per_symbol()"
- property of the constellation object). We then map these chunks into
- some known mapping function, most often a form of Gray Coding, using
- the \ref gr::digital::map_bb "Map block" and the constellation object's \ref
- gr::digital::constellation::pre_diff_code() "pre_diff_code()"
- function. We then move these remapped chunks to complex symbols,
- again as defined by the constellation object through the \ref
- gr::digital::constellation::points() "points()" function in the
- \ref gr::digital::chunks_to_symbols_bc "Chunks to Symbols block".
-
-- Combine the header and payload. We need to take both the header and
- payload paths back together into a single stream. In packet_tx.grc,
- we are working with tagged streams, so both paths keep track of the
- size of their segments. Using the Tagged Stream Mux block, we
- recombine these two paths into one.
-
-- Burst Shaping and Filtering. The next stage shapes the packet for
- burst transmission. We apply two blocks to shape the burst
- appropriately.
-
- First, the \ref gr::digital::burst_shaper_cc "Burst Shaping block"
- handles the structure of the burst by applying two different forms
- of padding. First, there is a window that is applied to the time
- domain of the burst. This involves a ramping up stage from 0 and a
- ramping down stage back to 0. We define a window as a vector, and
- the \ref gr::fft::window "fft.window" set of window functions is
- useful here, such as using a Hann or Kaiser window. The size of the
- window is split in half to apply the left half of the window for the
- ramp-up and the right half of the window for the ramp-down. The
- window has two different modes: to insert or not insert phasing
- symbols. When inserting phasing symbols, a sequence of 1's and -1's
- is inserted for the duration of the ramp-up and ramp-down
- periods. So a window size of 20 will produce 10 alternative 1's and
- -1's on the front of the burst and another 10 alternating symbols on
- the rear of the burst. The window is then applied to these phasing
- symbols and does not affect the burst symbols directly. If we are
- not using the phasing symbols, the the window is applied to the
- front and back of the burst directly.
-
- The Burst Shaper can also add padded 0's to the front or back of the
- burst. This allows us to provide some extra control over the
- structure of the burst. In particular, it can be useful to add
- post-padding 0's that is the length of the delay of the pulse
- shaping filter that will come next. This makes sure that the full
- burst of samples is pushed through the filter and transmitted
- completely.
-
-
-\verbatim
- ____________________
- / \
- / \
- / \
- ______/ \____
- | E | D | C | B | A |
-
- A: Pre-padding 0's
- B: Ramp-up window
- C: Frame
- D: Ramp-down window
- E: Post-padding 0's
-\endverbatim
-
-
- When using phasing symbols, C is the entire frame and sections B
- and D are filled with alternative 1's and -1's.
-
- When not using phase symbols, the frame extends B through C to D.
-
- After creating this burst shape, we then put the burst through a
- pulse shaping filter. This filter both shapes the complex samples
- into appropriate symbols for transmission based on a spectral mask
- as well as up-samples the burst to the specified number of samples
- per symbol. In packet_tx, we are using a Polyphase Arbitrary
- Resampler to perform this task for us, which means that we can
- specify and real value for the number of samples/symbol, as long as
- it is greater than or equal to 2.0.
-
- Typical pulse shape filters are \ref
- gr::filter::firdes::root_raised_cosine "Root Raised Cosine (RRC)"
- filters and \ref gr::filter::firdes::gaussian "Gaussian" filters.
-
- Because the pulse shape filter up-samples, in packet_tx, we use a
- \ref gr::blocks::tagged_stream_multiply_length "Tagged Stream Multiply Length Tag block".
- The resampler block knows nothing about
- tagged streams, so when it up-samples, the \ref
- page_tagged_stream_blocks "tagged stream block (TSB)" tag value does
- not change. We need to change this tag's value, too, and so we use
- the multiply length tag block for this purpose. This is helpful when
- working with UHD devices, like in uhd_packet_tx.grc, because we can
- explicitly tell the UHD USRP Sink block to expect a tagged stream to
- manage the transmission of the burst.
-
-\subsection packet_tx_params Parameters of the packet_tx Example
-
-The canonical example for handling narrowband M-PSK or M-QAM is the
-packet_tx.grc hierarchical block.
-
-- Header FEC Code (hdr_enc)
-- Payload FEC Code (pld_enc)
-- Header Constellation Object (hdr_const)
-- Payload Constellation Object (pld_const)
-- Protocol Formatter Object (formatter)
-- Samples per symbol (sps as a float)
-- Pulse shaping filter (psf_taps, designed for the polyphase arbitrary
- resampler)
-
-We can see all of these objects and settings in the
-packet_loopback_hier.grc example and uhd_packet_tx.grc if using a
-UHD-compatibly radio front end.
-
-\subsection packet_tx_examples Examples
-
-The following examples exist to showcase how to control each stage of
-the transmit processing.
-
-- tx_stage0.grc: simple creation of PDUs to input into the
- transmitter. By default, this generates \ref gr::blocks::random_pdu
- "random PDUs" for testing. However, we can switch in the \ref
- gr::blocks::tuntap_pdu "TUNTAP PDU" block to create a tun or tap
- device as the input of samples from some OS application. Note that
- you will need root privileges to create a tun/tap device and
- configure it.
-
-
-- tx_stage1.grc: Adding a CRC to the frame. The Message Debug prints
- the before and after adding the \ref gr::digital::crc32_async_bb
- "CRC32", so we can see the original PDU and then the PDU with the
- added 4 bytes of check.
-
-
-- tx_stage2.grc: Adding \ref page_fec "forward error correction". This
- adds an \ref gr::fec::async_encoder "FEC Async Encoder" block to
- compare pre- and post-encoding. Three different FEC encoders are
- available immediately in this example with the repetition encoder
- enabled by default. This encoder just repeats every bit 3 times, so
- it is easy to see the behavior before and after encoding. Simply
- disable this FEC code and enabling one of the others will change the
- encoding behavior.
-
-
-- tx_stage3.grc: takes the payload with the CRC32 check and creates
- the packet structure. Both the header and payload are printed out,
- where the payload is the input payload+CRC and the header is defined
- by the 'formatter' object. The default formatter just applies an
- access code (using the default 64-bit
- digital.packet_utils.default_access_code code) and then it
- calculates the payload length (in bytes) as a 16-bit value. This
- 16-bit length field is duplicated, so in the receiver it can check
- both 16-bit fields to make sure they agree. This formatter also
- takes a threshold value. The transmitter does not use this
- threshold. That parameter is used in the receiver to know how many
- bits can be wrong in the access code and still pass.
-
- Disabling the \ref gr::digital::header_format_default
- "default header definition" and enabling the other 'formatter' to
- change the protocol. This other protocol definition is the \ref
- gr::digital::header_format_counter "counter header". It adds the
- access code and payload length fields as the header like the default
- formatter. This formatter includes two other fields as well: the
- number of bits/symbol used in the payload modulator (as a 16-bit
- field) and a 16-bit counter. Each packet transmitted increments this
- counter by 1, which means we can keep track of how many packets we
- have sent and/or received.
-
-- tx_stage4.grc: Here we add the modulation to both the header and
- payload paths, defined by the hdr_const and pld_const objects,
- respectively. Both are defined as BPSK constellations by
- default. The output is shown in two \ref page_qtgui "QTGUI display"
- graphs. We see the samples in time first, and this is triggering off
- the TSB tag "packet_len". When the time display updates, we can see
- the same pattern right after the tag, which is the header, and then
- the changing samples are the random values in the payload.
-
- When we look at this Freq tab of this example, we just see a mostly
- flat frequency response over the entire frequency range. This
- response is due to the samples just being +1's and -1's with no
- transition between them and sampled at 1 sampler per symbol. This is
- not something that we can just transmit as a burst. The square
- pulses we use provide horrible out-of-band (OOB) emissions if we put
- this over the air directly, and each burst would go from 0 to +/-1
- within the coarse of a single sample, which again provides large OOB
- emissions. We need to shape the bursts properly from here.
-
-- tx_stage5.grc: Adds the \ref gr::digital::burst_shaper_cc "Burst Shaper"
- block. The default parameters are to use a Hann window of 50 symbols
- and to add 10 0's as pre- and post-padding. We can adjust any of
- these values to explore what the output burst looks like. We can
- stop the time sink from updating and turn on the markers for the
- Re{Data 0} channel to easily count the samples and observe the
- effect of the window.
-
- As an aside, the window of 50 produces 25 phasing samples on either
- side. This is a lot, but we did this to help show off the way the
- window looks a bit more clearly.
-
-- tx_stage6.grc: We then need to up-sample the signal by the number of
- samples/symbol (sps) and apply our pulse-shaping filter. Again, we
- are using some larger numbers than we really would in an actual
- scenario to make it visually clear what is happening. The psf_taps
- filter creates an RRC filter designed for the 32-arm (set by nfilts)
- polyphase filterbank resampler. In this RRC Filter Taps object, we
- set the number of taps to be 15*sps*nfilts. The sps and nfilts are
- properties of the sample stream and upsampling factor. The value 15
- is the number of symbols to represent in this filter; basically that
- we are going to look over the history effects of 15 samples to
- manage the inter-symbol interference (ISI). That is a long RRC filter
- but done so to make the simulation look better. Five or seven is a
- more realistic value. Similarly, we set sps=4 here to make the time
- and frequency plots look better. Normally, we would want this closer
- to 2.
-
- Now looking at the time domain plot, we see the filtered samples,
- which are not as pretty as before. They have over- and under-shoots,
- and if we turned on the line markers, we would not see the original
- bits easily through this. That is the effect of the RRC filter,
- which introduces ISI into the transmitted stream. However, when we
- look at the frequency domain, we see a much better shape, which we
- can transmit as part of our channel assignment.
-
-- tx_stage6a.grc: An aside here to study the RRC filters more. This
- example adds a second RRC filter (without any resampling) that
- matches the transmitter's RRC filter. The matched filter means that
- the samples are filtered by two RRC filters, which together make a
- raised cosine (RC) filter. This RC filter is what is known as a
- Nyquist filter and has the properties of 0 (or very close to 0)
- ISI. Though we introduced ISI in the transmit RRC filter, the second
- stage at the receiver undoes that ISI making for a clean, filtered
- signal. Turning on marker in the time domain shows two clean lines
- at +1 and -1. The receiver just needs to know which of the sps
- samples to grad to get the original symbol that was transmitted. But
- that is the job of the receiver.
-
-At this point, we have an encoded, modulated, and shaped burst ready
-to be transmitted out of a radio. The uhd_packet_tx.grc example puts
-all this together, where we have packaged up most of the transmitter
-behavior into packet_tx.grc. We then generate random PDU's, put them
-through the packet_tx block, and then through a Multiply Const block
-and into a USRP sink. The Multiply Const block is used for digital
-scaling of the signal to allow us power control on top of the
-transmitter gain inside the USRP radio itself.
-
-
-\section packet_rx Understanding the Receiver
-
-The receiver is far more complicated. The work involved here is
-largely in the detection and synchronization of the received
-frames. We must assume that frames are coming in as bursts with
-potentially random time intervals.
-
-It is important to understand that it is very difficult to make a
-simple protocol work in all scenarios. We have to assume that some
-packets will be lost through either a missed detection at the start or
-poor synchronization statistics during processing of the burst.
-
-The generic receiver example can be found in packet_rx.grc. This hier
-block provides the main detection, synchronization, header/payload
-management, demodulation, and decoding of the PHY frames. The input to
-this hier block should be not be too far off in frequency. The GNU
-Radio block \ref gr::digital::fll_band_edge_cc "FLL Band-Edge" tends
-to work well enough, though this is unnecessary if the radio are
-synchronized in frequency some other way (e.g., with a GPSDO such as
-is available on USRPs).
-
-The main flow of samples here is to detect a frame by discovering its
-known word, which also provides initial estimates on timing and phase
-offsets of the received frame. We then go through a clock sync block
-to perform matched filtering and sample time correction to produce
-resampled symbols at 1 sample/symbol. Now we have samples that are
-split between the header and payload. We might have information inside
-of the header that helps the receiver understand the payload. For
-instance, the length of the payload is generally encoded in the
-header. So we have to demux the header and payload.
-
-We assume that we know the length of the header in symbols, which we
-pass on to the header demodulator chain. Knowing the header
-modulation, we synchronize the phase and frequency, demodulate the
-symbols into soft bits, decode those soft bits based on the known
-header's FEC code, and then parse the header information. The header
-parser extracts information about the payload, such as the number of
-symbols in the payload and possibly the number of bits/symbol used in
-the payload modulation.
-
-The \ref gr::digital::header_payload_demux "Header/Payload Demux"
-block sends the appropriate number of samples to the payload demod
-chain. This chain does its own phase/freq synchronization for the
-appropriate constellation used in the payload, decodes the samples to
-soft bits, performs the FEC decoding, and then does the CRC32
-check. If this passes, the payload is sent out of the hier block as a
-PDU with the PHY layer framing stripped.
-
-When looking at the packet_rx.grc example, notice that we have
-instrumented a number of debug ports along the way. These ports are
-designed to make it possible for us to externally hook up graphing and
-debug blocks in whatever way we are comfortable with to see the signal
-along the path and more easily debug.
-
-
-\subsection packet_rx_correst Correlation Estimator
-
-The first stage of the receiver searches for the known word prepended
-to every burst from the transmitter. The known word has gone through
-two stages of processing: encoding with the header's FEC (optional)
-and modulated by the header's modulator. The correlation of the known
-word is done at the input sample stage, so we have to recreate the
-modulated and possible encoded known word at the receiver.
-
-To simplify dealing with the encoding process, in packet_rx.grc, we
-assume one of two types of codes: dummy code (or not coded) and a 3x
-repetition code. We then just simply calculated the preamble's bits
-for both cases. Depending on the header decoder (hdr_dec) used, the
-hier block knows which preamble to use.
-
-Next, we need to take the known, encoded word and modulate it with the
-header's modulator and pulse shaping filter. We create a simple
-modulator in the variable 'rxmod' that takes the header \ref
-gr::digital::constellation "constellation object" (hdr_const), the
-number of samples per symbol, and the pulse shape filter's bandwidth
-parameter (eb). The \ref gr::digital::modulate_vector_bc "Modulate Vector"
-block than combines this 'rxmod' modulator with the 'preamble'
-known word into a vector of complex symbols, here called
-'modulated_sync_word'. This variable is then passed to the \ref
-gr::digital::corr_est_cc "Correlation Estimator" block.
-
-One tricky thing about burst communications and network setups is the
-power of the received samples is unknown and time varying. It is
-preferential to try to auto-detect the burst and scale the signal to
-+/-1 before coming in to packet_rx. There is still a lot of work to be
-done for AGC loops in the hardware and automatic scaling in
-software. The Correlation Estimator tries to deal with this. We use a
-threshold as an approximate probability of detection. This value
-should be set very high; the default here is 99.9%. The correlation
-tends to scale well as the amplitudes change and for relatively low
-SNR conditions. Still, it is always possible to miss a detection event
-or have a false positive.
-
-Another thing that the Correlation Estimator can do for us is provide
-information for digital scaling the samples. When received over
-hardware, the signals tend to be very small, but most of our follow-on
-processing assumes they are about +/-1. The Correlation Estimator
-finds the amplitude of the sample where the correlation peak was
-found, inverts it, and sends it as a tag with the key 'amp_est'. We
-can use this down stream to adjust the amplitude by rescaling the
-samples from this value. For our packet_rx example, we use the \ref
-gr::blocks::multiply_by_tag_value_cc "Multiply by Tag Value" block,
-which updates its multiplicitive factor based on the tag. Much of this
-could be handled by a good AGC routine in the hardware.
-
-Finally, the main purpose of the Correlation Estimator block is to
-provide the down-stream synchronization blocks with initial estimates
-of the timing and phase offset. The peak of the magnitude of the
-correlation event corresponds to the sampling timing of the data
-stream.
-
-\verbatim
- 1. /\ 2. _
- / \ / \
- __/ \__ __/ \__
-\endverbatim
-
-The above two drawings show two different correlation scenarios. In
-scenario 1, the timing is exact and the sample at the peak of that
-curve is the proper sample time of the last symbol of the known
-word. In scenario 2, there is a timing offset where the correct timing
-offset is half-way between two samples. This would be a timing offset
-of 0.5 (or -0.5). Knowing where that estimated offset is helps our
-timing recover blocks start near the correct sample offset and then
-track from there.
-
-The magnitude of the correlation helps us discover the timing
-offset. The correlation itself is a complex vector. So where the peak
-of the magnitude happens, we can look to the complex value of the
-correlation at the same point and the phase difference between the
-real and imaginary parts is the phase offset of the signal.
-
-The Correlation Estimator block calculates the time and phase offsets
-and creates stream tags for "time_est" and "phase_est". It also
-creates two other tags: "corr_start" and "corr_est," both of which
-contain the value of the peak of the magnitude of the
-correlation. Because there is a delay in the correlation algorithm
-that is affected by the size of the correlation, we need to adjust
-where the correlation event occurs to where the tags are actually
-placed on the output stream. The block places the "corr_start" tag on
-the sample where the correlation actually occurred. It then places the
-other three tags offset by some "Tag marking delay," which is a
-user-calculated value to place the tags at the correct spot in the
-data stream for the actual start of the known word's first symbol.
-
-In packet_rx, we empirically discovered the tag marking delay for
-different values of the samples/symbol ('sps') variable and made a
-list 'mark_delays' that is index by 'sps' to properly set 'mark_delay'
-for the start of the known word. Getting is correct has a huge effect
-on the timing recover loop, which can take a while to converge if it
-starts offset in time by a sample.
-
-See the example example_corr_est.grc to explore the Correlation
-Estimator blocks more.
-
-
-\subsection packet_rx_timing Timing Recovery
-
-After detecting the frame and estimating the time and phase estimates,
-we have to actually perform the timing synchronization step. The
-packet_rx example uses the
-\ref gr::digital::pfb_clock_sync_ccf "Polyphase Clock Sync" block to
-do this. This PFB clock sync (PCS) block typically performs blind
-timing recovery on a series of samples. It is composed of 'nfilt'
-filters in a filterbank where each filter represents a different phase
-from [0, 2pi) in steps of 2pi/nfilts. The algorithm finds the correct
-arm of the filterbank that corresponds to the time shift of the
-samples. It also knows to look for a "time_est" stream tag and use
-that information to set its phase arm estimate. If we have a time
-estimate like scenario 1 above, we have perfect timing and so would
-select the 0th arm of the filterbank. In scenario 2, we are off by
-half a sample, so we select arm nfilts/2. The PCS is a tracking loop,
-so it will start with the initial estimate and then keep track of the
-timing as well as hone-in on actual timing information of the symbol
-stream.
-
-The PCS block uses a filterbank concept to perform its tracking
-operation. The filters within the filterbank operate best when they
-are phase offsets of the matched filter. So not only does the
-block recover the timing, it also performs the matched filtering and
-produces the optimal 1 sample/symbol output. These are then optimally
-sampled symbols in the complex constellation space. They need to be
-mapped back to bits and decoded. But first, we need to parse the
-header in order to discover information about the payload.
-
-See the example example_corr_est_and_clock_sync.grc to play with the
-parameters of time synchronization.
-
-
-\subsection packet_rx_hpd Header/Payload Demux
-
-Because the header and payload can be modulated differently, the rest
-of the symbol processing has to be split into two chains. We do this
-using the \ref gr::digital::header_payload_demux "Header/Payload Demux"
-block (HPD). We assume that we know the protocol, and so the format,
-coding, and modulation of the header. Generally speaking, these are
-all controlled through three different objects:
-
-- formatter: An object that described the header structure, derived
- from gr::digital::header_format_base.
-
-- hdr_const: An object that describes the bit and symbol mapping,
- derived from gr::digital::constellation.
-
-- hdr_dec: An object that describes the FEC code, derived from
- gr::fec::generic_decoder.
-
-Through these, we can ask for any parameter to set up the following
-stages of processing.
-
-The HPD block is fairly complicated and we will only use it in one
-kind of configuration here. See the manual page for the \ref
-gr::digital::header_payload_demux "HPD" block itself for more
-details. In our use of the HPD block, it receives the data stream and
-looks for a Trigger Tag Key. We will use 'time_est', one of the tags
-produced by the Correlation Estimator to indicate the sample that
-starts the header. When the HPD block sees this trigger key, it passes
-along a known number of symbols out of the 'header' stream port. We
-know the number of symbols based on the formatter, constellation, and
-FEC decoder objects. The formatter objects knows the number of bits in
-the header via the header_nbits() function, the constellation knows
-how many bits per symbol (via bits_per_symbol()), and the FEC decoder
-knows the encoding rate (via 1/rate()). The number of symbols in the
-header is therefore:
-
- (header_nbits() * 1/rate()) / bits_per_symbol()
-
-The HPD then sends this many symbols on to be processed. It holds up
-any more processing until triggered to do so with information through
-the 'header_data' input message port. The header processing chain will
-end with the Packet Parser producing the message here.
-
-When the 'header_data' input message port receives valid information,
-it releases the payload out of the 'payload' stream port. The main
-thing that the 'header_data' input message port receives is
-information about the length of the payload. The HPD parameter 'Length
-tag key' is matched to the message received in 'header_data', which is
-then used to gate the output of samples as the payload. In our case,
-we specify the length as the number of symbols through the message key
-'payload symbols'. This tag then becomes the tagged stream key for the
-payload chain.
-
-
-\subsection packet_rx_hdr_chain Header Processing Chain
-
-The header processing chain is kicked off when the HPD block receives
-the trigger stream tag (i.e., 'time_est'). We must first correct the
-phase and fine frequency offset of the received samples. The
-Correlation Estimator block will help us with this through the
-'phase_est' tag. The \ref gr::digital::costas_loop_cc "Costas Loop"
-looks for this tag, and, when found, it will take this estimate and
-reset its own internal phase value, which greatly speed up
-acquisition. The Costas loop will then track the phase and frequency
-over the course of the header.
-
-With the constellation locked in time, phase, and frequency, we can
-not decode the complex symbols. We use a \ref
-gr::digital::constellation_soft_decoder_cf "Constellation Soft Decoder"
-block for this, which uses the 'hdr_const' object to know the mappings
-from complex space to bits. Specifically, it performs a soft decoding,
-so the outputs are soft decision bits, which is useful for FEC
-decoding that is performed next.
-
-The \ref gr::fec::decoder "FEC decoder" operates on the soft decisions
-based on the hdr_dec object. Because of the bounded nature of the
-header, we would expect simple block codes used here as well as a
-fairly robust and easy to process code. In the current examples, we
-only provide no code (via the \ref gr::fec::code::dummy_encoder
-"Dummy Encoder" / \ref gr::fec::code::dummy_decoder "Dummy Decoder"
-classes) or a repetition code (via the
-\ref gr::fec::code::repetition_encoder "Repetition Encoder" / \ref
-gr::fec::code::repetition_decoder "Repetition Decoder" classes). The
-output of the FEC decoder block is a bit stream where each item is
-either a 1 or a 0.
-
-The last step in the header processing stage is to parse that bit
-stream back into the header. The \ref gr::digital::protocol_parser_b
-"Packet Parser" block does this by receiving a bit stream, passing it
-to the \ref gr::digital::header_format_base::parse "parse" function of
-the packet formatter object, and emitting a message with the
-information about the parsed data.
-
-The packet parsing is explained in detail in the \ref
-gr::digital::header_format_base "Packet Formatter Base" class. The
-parse function packs together the received bits into the different
-header fields, checks that the header is correct, and the constructs a
-PMT dictionary of the header information, such as the payload length
-and other possible information like the type of constellation or FEC
-coding used on the payload bits. This is the message that gets passed
-back to the HPD block to guide the payload processing.
-
-If the packet formatter parsing operation fails by not getting enough
-data or if the data is corrupted, it will return false. When the
-Packet Parser sees this, it emits a message that just contains a \ref
-page_pmt "PMT" False (pmt::PMT_F), which resets the HPD block to start
-looking for another header trigger event.
-
-If the header parsing completes successfully, the HPD block gets a
-message with information about the payload. Most importantly, it gets
-information about how many symbols make up the payload. It then sends
-a tagged stream to the payload processing chain with this many
-symbols.
-
-
-\subsection packet_rx_pld_chain Payload Processing Chain
-
-The payload processing chain behaves very similarly to the header
-processing chain for the first few blocks. It starts by locking the
-phase and frequency in another \ref gr::digital::costas_loop_cc
-"Costas loop", and then perform \ref
-gr::digital::constellation_soft_decoder_cf "soft decoding" on the
-symbols using the 'pld_const' object. Because we come in as symbols
-and out as soft decisions, the constellation soft decoder will produce
-\ref gr::digital::constellation::bits_per_symbol() "bits_per_symbol()"
-times as many outputs as inputs, but the soft decoder will not change
-the tag stream information. To compensate for this, we use a \ref
-gr::blocks::tagged_stream_multiply_length
-"Tagged Stream Multiply Length" block to update the tagged stream tag
-"payload symbols". We then move from the tagged stream mode into PDU
-mode and perform the FEC decoding through the \ref
-gr::fec::async_decoder "asynchronous FEC decoder". This decoder is
-nice in that it comes in with soft bits and produces packed
-bytes. These packed bytes are now the full payload with the CRC32
-appended. The \ref gr::digital::crc32_async_bb "Async CRC32" block in
-"Check CRC" mode will take this PDU of packed bytes, calculate the CRC
-and check it against the final four bytes of the payload. If they
-match, the PDU is stripped of the CRC bytes and the frame is passed
-out of the hier block. This PDU frame is now ready for use in higher
-layers of processing.
-
-This takes us through the entire processing chain on the
-receiver. From here, it is a matter of tweaking parameters and playing
-with options and other setups to improve behavior.
-
-*/