diff options
Diffstat (limited to 'gr-fec/doc/fec.dox')
-rw-r--r-- | gr-fec/doc/fec.dox | 348 |
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 + */ |