summaryrefslogtreecommitdiff
path: root/gr-fec/doc/fec.dox
diff options
context:
space:
mode:
Diffstat (limited to 'gr-fec/doc/fec.dox')
-rw-r--r--gr-fec/doc/fec.dox348
1 files changed, 348 insertions, 0 deletions
diff --git a/gr-fec/doc/fec.dox b/gr-fec/doc/fec.dox
index c8114eeedb..7fbbdda6e3 100644
--- a/gr-fec/doc/fec.dox
+++ b/gr-fec/doc/fec.dox
@@ -21,4 +21,352 @@ by using:
help(fec)
\endcode
+
+\section fec_using Using the FEC API
+
+FEC is a complex issue to implement in a generic, generally usable
+way. To help with these issues, the FEC API operates on two levels:
+the coder variables and the coder deployments. The variables implement
+the encoding and decoding methods whereas the deployments set up the
+variables, make sure the input data is formatted properly, run the
+coder variable, and then pass on the data for follow-on processing.
+
+In a GNU Radio flowgraph, the deployments are GNU Radio blocks that we
+insert into the flowgraph. The deployments use the API of the coder
+variables to interact with the scheduler and set up the input/output
+item buffers that move data between blocks. The intent of the API is
+to be able to build the coding variables that are general enough for
+easy use in multiple situations. We then construct deployments to
+control the interaction between the data and the variable. GNU Radio
+provides deployments for a number of situations, but these should not
+be considered the only ways to deploy the decoders.
+
+
+\subsection fec_deployments Deployments
+
+Generally speaking, encoder deployments take in bits and produce
+bits (i.e., unpacked bytes with 1 bit per byte). Decoder deployments
+take in floats and produce bits. The floats are generally meant to
+represent soft decisions. If the demodulator does not produce soft
+decisions, an easy alternative is to convert the hard decision 0's and
+1's to -1 and +1 floats. The main departure from this model is when
+using a PDU-based modulator or demodulator, for which we can look at
+using the asynchronous message passing system. In this instance,
+passing bits is not natural, so we need to create a deployment that
+can handle packed bytes. GNU Radio has the gr::fec::asycn_encoder and
+gr::fec::async_decoder deployments that work in this mode.
+
+Some coding variables handle inputs and outputs differently than the
+described deployments. Using the FEC API provides concepts of input
+and output conversion properties that help us create deployments to
+convert the data streams to the required format of the variable.
+
+\subsubsection fec_deploy_simple Streaming Deployments
+
+For the encoder deployments, the gr::fec::encoder block is a
+relatively simple deployment for the encoding variables. It uses the
+encoding object information about the input/output sizes and
+input/output item sizes to set up the interaction with the
+scheduler. Typically, a coder will add redundancy to the stream making
+the output longer by some amount than the input stream. This block
+simply takes in an encoder object, specifically an object that derives
+from gr::fec::generic_encoder. It also takes in the input and output
+items sizes that the encoder will expect, which we can just ask the
+encoder for. Typically, the encodes expect unpacked bytes in and
+unpacked bytes out.
+
+The gr::fec::decoder block is a similarly simple deployment for the
+decoding variables. It uses the decoding variable information about
+the input/output sizes and input/output item sizes to set up the
+interaction with the scheduler. Since a decoder typically uses the
+redundancy from the input stream to correct for errors, the input
+stream will be longer than the output stream by the rate of the
+code. This block simply takes in an decoder object, specifically an
+object that derives from gr::fec::generic_decoder. It also takes in
+the input and output items sizes that the decoder will expect, which
+we can just ask the encoder for. The deployment expects a floating
+point stream input, though the decoder variables may take a float
+input or a byte. If using a byte format, it could be a hard decision
+or a quantized soft decision, depending on how the decoder object
+behaves.
+
+Normally, though, we don't work directly with these simple encoder()
+or decoder() deployments but a wrapper around those blocks. GNU
+Radio's gr-fec package comes with two Python deployments to make
+things easier: fec.extended_encoder and fec.extended_decoder. For one
+thing, these extended hier_block2 blocks take care of the puncturing
+and depuncturing operations often found in FEC codes. The other thing
+that these blocks do for us is read the API of the encoder/decoder
+variables to properly convert the data in or out, depending on how the
+coding object works.
+
+For instance, a generic_decoder takes in floating point values (which
+should be soft decisions). However, a decoder might instead want to
+work on 8-bit quantized soft decisions and so expects unsigned
+chars. Specifying 'uchar' as the
+gr::fec::generic_decoder::get_input_conversion() of the decoder block tells the
+fec.extended_decoder to convert the float to a byte.
+
+In GRC, we would add an "FEC Extended Encoder" to our transmitter or
+an "FEC Extended Decoder" to the receiver. We would then use one of
+the encoder or decoder FEC variable blocks to define the parameters of
+the particular code we want to use. We can find these codes under the
+[Error Coding] category in GRC. The encoders are found under
+[Encoders] and similarly the decoders under the [Decoders]
+categories. Putting these onto the canvas creates a variable that we
+can then pass to the extended encoder or decoder deployment blocks.
+
+Most of the parameters of the encoder and decoder definitions should
+be fairly obvious based on the type of code. See the documentation for
+each coding object for more details. In the following section \ref
+fec_parallelism, we explain the Parallelism and Dimension properties.
+
+See fec/fecapi_encoders.grc and fec/fecapi_decoders.grc in the
+installed examples for an example of how to work with these
+deployments given the three initial FEC coders available.
+
+\subsubsection fec_deploy_tag_stream Tagged Stream Deployments
+
+GNU Radio's gr-fec also comes with simple deployments for \ref
+page_tagged_stream_blocks blocks. These deployments work similarly to
+the normal streaming deployments but fit into a tagged stream system
+by setting a tagged stream tag to control the frame size. Like all
+tagged stream blocks, they expect the tag to be located in the stream
+in order to properly function.
+
+The simplest form of the tagged stream deployments are just the C++
+blocks gr::fec::tagged_encoder and gr::fec::tagged_decoder. These do
+not handle any input or output conversion. They expect the inputs to
+be already properly formatted for the encoding/decoding variables, and
+the outputs will be whatever the variable naturally produce.
+
+In the tagged stream deployments, the frame size set for a variable is
+no longer the static frame size like we expected in the streaming data
+implementations. Instead, we look at the frame size of the
+encoder/decoder variable during construction of the deployment as the
+maximum frame size, or a maximum transmission unit (MTU). This allows
+us to set up some internal memory to handle up to the required maximum
+length. When a tagged stream comes into this block, the frame size is
+then set based on that tagged stream information. If the frame is
+larger than the established MTU, a warning is sent out and the
+deployment only handles up to the MTU of the given frame.
+
+The extended Python tagged deployments, fec.extended_tagged_encoder
+and fec.extended_tagged_decoder, offer additional handling of the FEC
+API like we saw with the fec.extended_encoder and
+fec.extended_decoder. These extended deployments wrap up the
+puncturing and depuncturing as well as use the FEC API to do any input
+and output translation for the formatting of data streams. The
+fec.extended_tagged_encoder expects unpacked bits in and produces
+unpacked bits out. The fec.extended_tagged_decoder takes in floats
+(generally soft decisions from -1 to 1) and produces unpacked bits.
+
+See fec/fecapi_tagged_encoders.grc and fec/fecapi_tagged_decoders.grc
+in the installed examples for an example of how to work with these
+deployments given the three initial FEC coders available.
+
+
+
+\subsubsection fec_deploy_async Asynchronous Deployments
+
+The final standard deployment shipped with GNU Radio is for
+asynchronous \ref page_msg_passing and handling PDUs:
+gr::fec::async_encoder and gr::fec::async_decoder.
+
+Unlike the other deployments, these C++ deployments do not also have
+an extended Python deployment. Because this deployment uses message
+passing, we cannot easily build up a hierarchical block of message
+passing blocks to satisfy the input/output translations like we've
+done with the other forms of deployment. Instead, the input/output
+formatting is taken care of inside this deployment itself. Further,
+because this form of moving data anticipates data being moved in
+packets, these deployments cannot work with any FEC code that requires
+a history (see generic_decoder::get_history). Right now, this means
+that the async message passing deployments cannot work with
+convolutional codes (gr::fec::code::cc_encoder and
+gr::fec::code::cc_decoder) in streaming mode because it would require
+data from the next frame to finish off decoding the current frame.
+
+These deployments also work in two distinct modes. They can work in
+unpacked mode where inputs are messages of bits, or they may work in
+packed mode where messages are PDUs. The distinction is that the
+packed mode PDU's are the standard protocol data units (PDUs) that
+encompass full packets of data. This allows these async deployments to
+be used easily within PDU-based applications, such as encoding a
+packet with a CRC attached.
+
+When in packed or PDU mode, the encoder deployment has the option of
+reversing the bits during unpacking and packing. Like the extended
+deployments for the other data modes, these deployments manipulate the
+input data to the format expected by the encoding or decoding
+variables using calls to the FEC API. Because most of the coders work
+off unpacked bits, the incoming PDUs must first be unpacked into bits
+and the repacked again into the original PDU. The
+gr::blocks::kernel::pack_k_bits and gr::blocks::kernel::unpack_k_bits
+kernels are used here, and they can change the direction on how to
+pack and unpack. Because different data processing blocks, framing,
+deframing, and other operations may arbitrarily set the format of the
+bits and the ordering, we provide the options of unpacking and packing
+directions in the deployments. However, the gr::fec::async_decoder
+still expects the input to be soft decisions with one decision per
+item, so we only say whether this deployment outputs packed PDUs or
+not and the packing direction.
+
+For an example of using the asynchronous in PDU mode, see
+fec/fecapi_async_packed_decoders.grc. See
+fec/fecapi_async_to_stream.grc for an example of mixing the packed PDU
+mode encoder with a tagged stream decoder. This example shows the PDU
+input having a CRC32 appended to the uncoded stream that is then
+checked after the packet is decoded.
+
+For an example of the async deployment using unpacked bits, see
+fec/fecapi_async_encoders.grc and fec/fecapi_async_decoders.grc.
+
+
+\subsection fec_coding_vars Encoding/Decoding Variables
+
+GNU Radio currently has a minor subset of coders available:
+
+Coders:
+
+\li gr::fec::code::dummy_encoder
+\li gr::fec::code::repetition_encoder
+\li gr::fec::code::cc_encoder
+\li gr::fec::code::ccsds_encoder
+
+Decoders:
+\li gr::fec::code::dummy_decoder
+\li gr::fec::code::repetition_decoder
+\li gr::fec::code::cc_decoder
+
+
+When building a new FECAPI encoder or decoder variable, the dummy
+encoder/decoder block would be a good place to start. This coding set
+does no processing on the data. For the encoder, each bit is simply
+passed through directly. For the dummy decoder, the input data are
+floats, so -1's become 0 and 1's stay as 1, but nothing else is done
+to the data. Mainly, these blocks are used for references and to make
+it easy to compare implementations with and without codes by easily
+dropping in these objects instead of restructuring the entire
+flowgraph. The ber_curve_gen.grc example file uses the dummy codes to
+show the curve to compare against the actual codes.
+
+Although mentioned in the convolutional coder and decoder classes, it
+is worth another mention. The cc_encoder is a generic convolutional
+encoder that can take any value of K, rate, and polynomials to encode
+a data stream. However, the cc_decoder is not as general, even though
+it is technically parameterized as such. The cc_decoder block
+currently <i>only</i> uses K=7, rate=2, and two polynomials (because
+the rate is two). We can, in fact, alter the polynomials, but a
+default of [109, 79] is typically. Eventually, we will make this block
+more generic for different rates and constraint lengths and take this
+particular code implementation as the set CCSDS decoder, much like we
+have the ccsds_encoder class.
+
+
+\subsection fec_parallelism Parallelism
+
+The code variables in GNU Radio Companion have the ability to create
+multiple encoder/decoder variables by selecting the level of
+parallelism. It is up the encoder to understand how to handle the
+parallelism. The following discussion explains the difference between
+the two levels and how and when to use. Generally, normal applications
+will just use a single level of parallelism.
+
+The GRC variable declarations for the different coders has a setting
+for <i>Parallelism</i>, which can be either 1 or 2. If set to 1, then
+the resulting variable is a list of coder blocks with the same
+settings. If set to 2, then the resulting variable is a list of lists
+of coder blocks. The code that accepts these variables must understand
+how to handle the parallelism. Most applications would set this to 1.
+
+The standard fec.extended_encoder ("FEC Extended Encoder" in GRC) and
+fec.extended_decoder ("FEC Extended Decoder" in GRC) can handle a
+Parallelism of 1. They accept a list of coder variables as defined by
+Dimension 1 and can multithread the application based on the
+"Threading Type" setting:
+
+\li <b>None</b>: does no parallel threading of the coders. Even if
+Dimension 1 is > 1, the encoder/decoder will ignore this setting and
+only use the first object in the list.
+
+\li <b>Ordinary</b>: all "Dimension 1" number (N) of encoder/decoder
+blocks will be used in parallel. The hier_block2 will block
+deinterleave the packets into N streams (using
+gr::blocks::deinterleave with a value of blocksize as the frame length
+and no relative rate changes) and pass these to each of the N coders
+to process the frames in parallel. The output of each coder is then
+interleaved back together to make a single output stream.
+
+\li <b>Capillary</b>: all "Dimension 1" number (N) of encoder/decoder
+blocks will be used in parallel, much like in the <b>Ordinary</b>
+mode. In this mode, however, the frames get split up in a tree-like
+fashion, where each branch launches 2 more branches. This means that N
+must be a factor of 2 for this mode to work. It tends to handle the
+load of the encoders/decoders better than the <b>Ordinary</b> mode.
+
+Note that the threading modes only work when using constant-length
+frames. If using the coders in tagged stream mode where the frame
+lengths may change, the <b>Ordinary</b> and <b>Capillary</b> modes are
+not available.
+
+The GRC example "ber_curve_gen.grc" uses a Parallelism of 2. This
+creates a list of lists of coders. The first dimension of the list
+corresponds to the number of Es/N0 values being used in the BER
+simulation. This allows the application to process all values of Es/N0
+simultaneously. Dimension 2 in this case allows the same concept of
+parallelism discussed above with the <b>None</b>, <b>Ordinary</b>, and
+<b>Capillary</b> models of threading.
+
+
+\section fec_api The API of the FECAPI
+
+The FECAPI defined by the parent generic_encoder and generic_decoder
+classes defines a set of virtual functions, some pure virtual, to
+allow the encoders/decoders to interact with the GNU Radio blocks. See
+the associated documentation of the generic_encoder and
+generic_decoder classes to know more about each of the API functions,
+some of which a child class is <i>required</i> to implement.
+
+The functions of the encoder and decoder are:
+
+\li double gr::fec::generic_encoder::rate()
+\li int gr::fec::generic_encoder::get_input_size()
+\li int gr::fec::generic_encoder::get_output_size()
+\li int gr::fec::generic_encoder::get_history()
+\li float gr::fec::generic_encoder::get_shift()
+\li const char* gr::fec::generic_encoder::get_input_conversion()
+\li const char* gr::fec::generic_encoder::get_output_conversion()
+\li bool gr::fec::generic_encoder::set_frame_size(unsigned int frame_size)
+
+Note: there is no get_input_item_size (or output) as the encoders
+always expect to work on bits.
+
+\li double gr::fec::generic_decoder::rate()
+\li int gr::fec::generic_decoder::get_input_size()
+\li int gr::fec::generic_decoder::get_output_size()
+\li int gr::fec::generic_decoder::get_history()
+\li float gr::fec::generic_decoder::get_shift()
+\li int gr::fec::generic_decoder::get_input_item_size()
+\li int gr::fec::generic_decoder::get_output_item_size()
+\li const char* gr::fec::generic_decoder::get_input_conversion()
+\li const char* gr::fec::generic_decoder::get_output_conversion()
+\li bool gr::fec::generic_decoder::set_frame_size(unsigned int frame_size)
+
+Whenever an FECAPI object refers to the frame size, it always means
+the number of bits in the uncoded frame. This means the number of bits
+going into an encoder and the number of bits coming out of a decoder.
+
+\section fec_examples FEC Examples
+
+\li ber_curve_gen.grc
+\li ber_test.grc
+\li fecapi_decoders.grc
+\li fecapi_encoders.grc
+\li fecapi_tagged_decoders.grc
+\li fecapi_tagged_encoders.grc
+\li fecapi_async_decoders.grc
+\li fecapi_async_encoders.grc
+\li fecapi_async_to_stream.grc
+
*/