diff options
author | Tom Rondeau <tom@trondeau.com> | 2013-09-04 15:45:01 -0400 |
---|---|---|
committer | Tom Rondeau <tom@trondeau.com> | 2013-09-04 15:45:01 -0400 |
commit | e0561eaf4bdf8ad8467aa7765d7f601e9b792ddc (patch) | |
tree | adb50870ae9a5b7f829c57545ccb286d246934ff /gr-digital/doc/digital.dox | |
parent | 02fd90029a1ec465f7c8da4a0d97dcdb8b3f438f (diff) |
digital: Added a new constellation_soft_decoder block that produces soft decisions as floats instead of hard decisions.
Added documentation for how to use the new soft decision tools.
Diffstat (limited to 'gr-digital/doc/digital.dox')
-rw-r--r-- | gr-digital/doc/digital.dox | 457 |
1 files changed, 457 insertions, 0 deletions
diff --git a/gr-digital/doc/digital.dox b/gr-digital/doc/digital.dox index 2809c6a943..48feda3485 100644 --- a/gr-digital/doc/digital.dox +++ b/gr-digital/doc/digital.dox @@ -20,4 +20,461 @@ by using: 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 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_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. + + */ |