/*! \page page_fec Forward Error Correction

\section fec_introductionIntroduction

This is the gr-fec package. It contains all of the forward error
correction (FEC) blocks, utilities, and examples. To use the FEC
blocks, the Python namespaces is in gnuradio.fec, which would be
normally imported as:

\code
    from gnuradio import fec
\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(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

*/
