diff options
Diffstat (limited to 'docs/doxygen/other')
-rw-r--r-- | docs/doxygen/other/extra_pages.dox | 2 | ||||
-rw-r--r-- | docs/doxygen/other/group_defs.dox | 66 | ||||
-rw-r--r-- | docs/doxygen/other/logger.dox | 205 | ||||
-rw-r--r-- | docs/doxygen/other/main_page.dox | 61 | ||||
-rw-r--r-- | docs/doxygen/other/pfb_intro.dox | 7 | ||||
-rw-r--r-- | docs/doxygen/other/tagged_stream_blocks.dox | 271 |
6 files changed, 582 insertions, 30 deletions
diff --git a/docs/doxygen/other/extra_pages.dox b/docs/doxygen/other/extra_pages.dox index d40c692e03..94c741864d 100644 --- a/docs/doxygen/other/extra_pages.dox +++ b/docs/doxygen/other/extra_pages.dox @@ -79,6 +79,8 @@ audio-osx and audio-windows to be either satisfied or built. \subsection dep_gr_comedi gr-comedi: Comedi hardware interface \li comedilib (>= 0.8) http://www.comedi.org/ +\subsection dep_gr_log gr-log: Logging Tools (Optional) +\li log4cpp (>= 1.0) http://log4cpp.sourceforge.net/ \section build_gr_cmake Building GNU Radio diff --git a/docs/doxygen/other/group_defs.dox b/docs/doxygen/other/group_defs.dox index 4aee49ec85..1c96abf3dc 100644 --- a/docs/doxygen/other/group_defs.dox +++ b/docs/doxygen/other/group_defs.dox @@ -8,32 +8,46 @@ * @{ */ -/*! \defgroup container_blk Top Block and Hierarchical Block Base Classes */ -/*! \defgroup source_blk Signal Sources */ -/*! \defgroup sink_blk Signal Sinks */ -/*! \defgroup filter_blk Filters */ -/*! \defgroup math_blk Mathematics */ -/*! \defgroup modulation_blk Signal Modulation */ -/*! \defgroup demodulation_blk Signal Demodulation */ -/*! \defgroup coding_blk Information Coding and Decoding*/ -/*! \defgroup sync_blk Synchronization */ -/*! \defgroup eq_blk Equalization */ -/*! \defgroup converter_blk Type Conversions */ -/*! \defgroup level_blk Signal Level Control (AGC) */ -/*! \defgroup dft_blk Fourier Transform */ -/*! \defgroup wavelet_blk Wavelet Transform */ -/*! \defgroup ofdm_blk OFDM Blocks */ -/*! \defgroup pager_blk Pager Blocks */ -/*! \defgroup misc_blk Miscellaneous Blocks */ -/*! \defgroup slicedice_blk Slicing and Dicing Streams */ -/*! \defgroup vocoder_blk Voice Encoders and Decoders */ -/*! \defgroup digital Digital Modulation Blocks */ -/*! \defgroup analog Analog Communications Blocks */ -/*! \defgroup qtgui_blk QT Graphical Interfaces */ -/*! \defgroup uhd_blk UHD Interface */ -/*! \defgroup audio_blk Audio Interface */ -/*! \defgroup pfb_blk Polyphase Filterbank */ -/*! \defgroup snr_blk SNR estimators */ +/*! \defgroup container_blk Top Block and Hierarchical Block Base Classes */ +/*! \defgroup audio_blk Audio Signals */ +/*! \defgroup boolean_operators_blk Boolean Operators */ +/*! \defgroup byte_operators_blk Byte Operators */ +/*! \defgroup channel_models_blk Channel Models */ +/*! \defgroup channelizers_blk Channelizers */ +/*! \defgroup coding_blk Information Coding and Decoding */ +/*! \defgroup debug_tools_blk Debug Tools */ +/*! \defgroup deprecated_blk Deprecated */ +/*! \defgroup equalizers_blk Equalizers */ +/*! \defgroup error_coding_blk Error Coding and Decoding */ +/*! \defgroup fcd_blk FCD Interface */ +/*! \defgroup file_operators_blk File Operators */ +/*! \defgroup filter_blk Filters */ +/*! \defgroup fourier_analysis_blk Fourier Analysis */ +/*! \defgroup instrumentation_blk Instrumentation Tools */ +/*! \defgroup level_controllers_blk Level Controllers */ +/*! \defgroup math_operators_blk Math Operators */ +/*! \defgroup measurement_tools_blk Measurement Tools */ +/*! \defgroup message_tools_blk Message Tools */ +/*! \defgroup misc_blk Miscellaneous */ +/*! \defgroup modulators_blk Modulators and Demodulators */ +/*! \defgroup networking_tools_blk Netwroking Tools */ +/*! \defgroup noaa_blk NOAA Blocks */ +/*! \defgroup ofdm_blk OFDM Blocks */ +/*! \defgroup packet_operators_blk Packet/Frame Operators */ +/*! \defgroup peak_detectors_blk Peak Detectors */ +/*! \defgroup pager_blk Pager Blocks */ +/*! \defgroup qtgui_blk QT Graphical Interfaces */ +/*! \defgroup resamplers_blk Resamplers */ +/*! \defgroup stream_operators_blk Streams Operators */ +/*! \defgroup stream_tag_tools_blk Stream Tag Tools */ +/*! \defgroup symbol_coding_blk Symbol Coding */ +/*! \defgroup synchronizers_blk Synchronizers */ +/*! \defgroup trellis_coding_blk Trellis Coding */ +/*! \defgroup type_converters_blk Data Type Converters */ +/*! \defgroup uhd_blk UHD Interface */ +/*! \defgroup waveform_generators_blk Waveform Generators */ +/*! \defgroup wavelet_blk Wavelet Transforms */ +/*! \defgroup wxgui_blk WX Graphical Interfaces */ /*! * \defgroup base_blk Base classes for GR Blocks diff --git a/docs/doxygen/other/logger.dox b/docs/doxygen/other/logger.dox new file mode 100644 index 0000000000..22458051db --- /dev/null +++ b/docs/doxygen/other/logger.dox @@ -0,0 +1,205 @@ +/*! \page page_logger Logging + +\section logging Logging + +GNU Radio has a logging interface to enable various levels of logging +information to be printed to the console or a file. The logger derives +from log4cpp (http://log4cpp.sourceforge.net/) which is readily +available in most Linux distributions. This is an optional dependency +and GNU Radio will work without it. + +When configuring GNU Radio, the -DENABLE_GR_LOG=On|Off option to cmake +will allow the user to toggle use of the logger on and off. The logger +defaults to "on" and will use log4cpp if it is available. If log4cpp +is not found, the default logging will output to standard output or +standard error, depending on the level of the log message. + +Logging is useful for blocks to print out certain amounts of data at +different levels. These levels are: + +<pre> + DEBUG < INFO < WARN < TRACE < ERROR < ALERT < CRIT < FATAL < EMERG +</pre> + + +The order here determines the level of output. These levels are +hierarchical in that specifying any level also includes any level +above it. For example, when using the WARN level, all WARN and +higher messages are logged while DEBUG and INFO are ignored. + +\subsection configfile Logging Configuration + +The logging configuration can be found in the gnuradio-core.conf file +under the [LOG] section. This allows us fairly complete control over +the logging facilities. The main configuration functions are to set up +the level of the loggers and set the default output behavior of the +loggers. + +There are two default loggers that all gr_block's have access to: +d_logger and d_debug_logger. The first is a standard logger meant to +output simple information about the block while it is running. The +debug logger is meant for debugging purposes and is added to make it +convenient to use a secondary logger that outputs to a different +stream or file. + +The four main configure options are: + +<pre> + log_level = debug + debug_level = debug + log_file = stdout + debug_file = stderr +</pre> + +This establishes the two loggers as having access to all levels of +logging events (DEBUG through EMERG). They are also configured not to +use files but instead output to the console. The standard logger will +output to standard out while the debug logger outputs to standard +error. + +Changing these last two lines to another value will create files that +are used to store the log messages. All messages are appended to the +file. + +When using either standard error or standard out, the messages for the +two different loggers will look like: + +<pre> + gr::log :\<level\>: \<block alias\> - \<message\> + gr::debug :\<level\>: \<block alias\> - \<message\> +</pre> + +When using a file, the only difference in the format is that the +message prefix of "gr::log" or "gr::debug" is not used. Instead, the +time in milliseconds from the start of the program is inserted. + +Remember that a local "~/.gnuradio/config.conf" file can be used to +override any parameter in the global file (see \ref prefs for more +details). + +To use these loggers inside of a GNU Radio block, we use the protected +data members of d_logger and d_debug_logger of gr_block and pass them +to our pre-defined macros: + +\code + GR_LOG_<level>(<logger>, "<Message to print>"); +\endcode + +Where \<level\> is one of the levels as mentioned above, \<logger\> is +either d_logger or d_debug_logger, and \<Message to print\> is the +message we want to output. If we wanted to output an INFO level +message to the standard logger and a WARN level message to the debug +logger, it would look like this: + +\code + GR_LOG_INFO(d_logger, "Some info about the block"); + GR_LOG_WARN(d_debug_logger, "Some warning about the block"); +\endcode + +When this is printed to wherever you are directing the output of the +logger, it will look like: + +<pre> + gr::log :INFO: <block's alias> - Some info about the block + gr::debug :WARN: <block's alias> - Some warning about the block +</pre> + +This provides us information about where the message came from, the +level of the message, and the block that generated the message. We use +the concept of the block's alias which by default (i.e., unless +otherwise set by the user) includes the name of the block and a unique +ID to distinguish it from other blocks of the same type. + +The various logging macros are defined in gr_logger.h. Here are some +simple examples of using them: + +\code + GR_LOG_DEBUG(LOG, "DEBUG message"); + GR_LOG_INFO(LOG, "INFO message"); + GR_LOG_NOTICE(LOG, "NOTICE message"); + GR_LOG_WARN(LOG, "WARNING message"); + GR_LOG_ERROR(LOG, "ERROR message"); + GR_LOG_CRIT(LOG, "CRIT message"); + GR_LOG_ALERT(LOG, "ALERT message"); + GR_LOG_FATAL(LOG, "FATAL message"); + GR_LOG_EMERG(LOG, "EMERG message"); +\endcode + +If the logger is not enabled, then these macros become nops and do +nothing (and d_logger and d_debug_logger are NULL pointers). If +logging is enabled but the log4cpp library is not found, then TRACE, +INFO, and NOTICE levels go to stdout and the rest to stderr. + + +\subsection adv_config Advanced Configuration Options + +If not using the simplified settings discussed above, where we can +direct the logger messages to either a file or one of the standard +outputs, we must use a more complicated configuration file. We do this +by specifying the "log_config" option in the [LOG] section. The +log4cpp documentation will provide more information on how +configuration works and looks. Mostly, a default configuration script +provided with GNU Radio can be used. After installation, the default +configuration script is located at: + +<pre> + $prefix/etc/gnuradio/gr_log_default.xml +</pre> + +For the following examples, we will assume that our local +"~/.gnuradio/config.conf" looks like this: + +\code +[LOG] +log_config = /opt/gr/etc/gnuadio/gr_log_default.xml +log_level = debug +debug_level = Off +\endcode + +Inside of the XML default configuration file, we define the parameters +for the two logger's, the standard logger the separate debug logger. + +If the levels of the two loggers are specified in our configuration +file, as in the above example, these levels override any levels +specified in the XML file. Here, we have turned on the standard logger +(d_logger) to all levels and turned off the debug logger +(d_debug_logger). So even if the debug logger is used in the code, it +will not actually output any information. Conversely, any level of +output passed to the standard logger will output because we have +turned this value to the lowest level "debug." + +If both an XML configuration file is set and the "log_file" or +"debug_file" options are set at the same time, both systems are +actually used. So you can configure file access and the pattern +through the XML file while also still outputting to stdout or stderr. + + +\section advlog Advanced Usage + +The description above for using the logging facilities is specific to +GNU Radio blocks. We have put the code necessary to access the +debugger into the gr_block parent class to simplify access and make +sure all blocks have the ability to quickly and easily use the logger. + +For non gr_block-based code, we have to get some information about the +logger in order to properly access it. Each logger only exists once as +a singleton in the system, but we need to get a pointer to the right +logger and then set it up for our local use. The following code +snippet shows how to do this to get access to the standard logger, +which has a root of "gr_log." (access to the debug logger is similar +except we would use "gr_log_debug." in the GR_LOG_GETLOGGER call): + +\code + gr_prefs *p = gr_prefs::singleton(); + std::string log_file = p->get_string("LOG", "log_config", ""); + std::string log_level = p->get_string("LOG", "log_level", "off"); + GR_CONFIG_LOGGER(log_file); + GR_LOG_GETLOGGER(LOG, "gr_log." + "my_logger_name"); + GR_LOG_SET_LEVEL(LOG, log_level); +\endcode + +This creates a pointer called LOG (which is instantiated as a +log4cpp:LoggerPtr in the macro) that we can now use locally as the +input to our logging macros like 'GR_LOG_INFO(LOG, "message")'. + +*/ diff --git a/docs/doxygen/other/main_page.dox b/docs/doxygen/other/main_page.dox index e7d4685f75..916ac9bdd1 100644 --- a/docs/doxygen/other/main_page.dox +++ b/docs/doxygen/other/main_page.dox @@ -39,11 +39,13 @@ More details on packages in GNU Radio: \li \ref page_vocoder More details on GNU Radio concepts: +\li \ref page_logger \li \ref page_pmt \li \ref page_msg_passing \li \ref page_metadata \li \ref volk_guide \li \ref page_pfb +\li \ref page_tagged_stream_blocks \section flowgraph Operating a Flowgraph @@ -402,4 +404,63 @@ configuration variable and the section and option names are in uppercase. The value is the same format that would be used in the config file itself. + + +\section oot_config_page Out-of-Tree Configuration + +New as of 3.6.5. + +Using gr_modtool, each package comes with the ability to easily locate +the gnuradio-core library using the 'find_package(GnuradioCore)' cmake +command. This only locates that the library and include directories +exist, which is enough for most simple projects. + +As projects become more complicated and start needing to rely on other +GNU Radio components like gnuradio-blocks or gnuradio-filter, for +example, and when they become dependent on certain API compatibility +versions of GNU Radio, we need something more. And so we have +introduced the GnuradioConfig.cmake file. + +When GNU Radio is installed, it also installs a GNU Radio-specific +cmake config file that we can use for more advanced compatibility +issues of our projects. This tool allows us to specific the API +compatible version and a set of components that are required. + +Taking the above example, say we have built against version 3.6.5 with +features that were introduced in this version and we need the blocks +and filter components as well as the main core library. We fist set a +cmake variable GR_REQUIRED_COMPONENTS to the components we need. We +then use the 'find_package' command and also set a minimum required +API compatible version. Since we are on the 3.6 API version, the +minimum required version is "3.6.5". The code in the CMakeLists.txt +file would look like this: + +\code + set(GR_REQUIRED_COMPONENTS RUNTIME BLOCKS FILTER) + find_package(Gnuradio 3.6.5) +\endcode + +Note that the capitalization is important on both lines. + +If the installed version of GNU Radio is 3.6.4 or some other API +version like 3.5 or 3.7, the Cmake configuration will fail with the +version error. Likewise, if libgnuradio-filter was not installed as +part of GNU Radio, the configuration will also fail. + +\subsection oot_config_path_page Install Path + +Cmake has to know where to find these configuration files. They are +installed into $prefix/lib/cmake/gnuradio. If $prefix is '/usr' or +'/usr/local', then everything should work fine. If the GNU Radio +install $prefix is something else, then Cmake must be told where to +find it. This can be done in two ways. If you are installing the +out-of-tree module into the same $prefix, then you would be setting +'-DCMAKE_INSTALL_PREFIX' on the configuration command line. This is +enough to tell Cmake where to look for the configuration files. + +The other way to do it is to set the CMAKE_PREFIX_PATH environmental +variable to $prefix. You can then install your component anywhere +you'd like and it will be able to find and configure against the +installed GNU Radio. + */ diff --git a/docs/doxygen/other/pfb_intro.dox b/docs/doxygen/other/pfb_intro.dox index 01d08b0fad..4f77e7cf76 100644 --- a/docs/doxygen/other/pfb_intro.dox +++ b/docs/doxygen/other/pfb_intro.dox @@ -5,14 +5,13 @@ Polyphase filterbanks (PFB) are a very powerful set of filtering tools that can efficiently perform many multi-rate signal processing tasks. GNU Radio has a set of polyphase filterbank blocks to be used -in all sorts of applications. These blocks and their documentation can -be found in \ref pfb_blk. +in all sorts of applications. \section Usage See the documentation for the individual blocks for details about what they can do and how they should be used. Furthermore, there are -examples for these blocks in <b>gnuradio-examples/python/pfb</b>. +examples for these blocks in <b>gr-filter/examples</b>. The main issue when using the PFB blocks is defining the prototype filter, which is passed to all of the blocks as a vector of \p @@ -20,7 +19,7 @@ taps. The taps from the prototype filter which get partitioned among the \p N channels of the channelizer. An example of creating a set of filter taps for a PFB channelizer is -found on line 49 of <b>gnuradio-examples/python/pfb/channelizer.py</b> +found on line 49 of <b>gr-filter/examples/channelizer.py</b> and reproduced below. Notice that the sample rate is the sample rate at the input to the channelizer while the bandwidth and transition width are defined for the channel bandwidths. This makes a fairly long diff --git a/docs/doxygen/other/tagged_stream_blocks.dox b/docs/doxygen/other/tagged_stream_blocks.dox new file mode 100644 index 0000000000..33e2bf6437 --- /dev/null +++ b/docs/doxygen/other/tagged_stream_blocks.dox @@ -0,0 +1,271 @@ +/*! \page page_tagged_stream_blocks Tagged Stream Blocks + +\section intro Introduction + +A tagged stream block is a block that works on streamed, but packetized input data. +Think of packet data transmission: A data packet consists of N bytes. However, in +traditional GNU Radio blocks, if we stream N bytes into a block, there's no way of +knowing the packet boundary. This might be relevant: Perhaps the modulator has to +prepend a synchronisation word before every packet, or append a CRC. So while some +blocks don't care about packet boundaries, other blocks do: These are <em>tagged +stream blocks</em>. + +These blocks are different from all the other GNU Radio block types (gr_block, gr_sync_block etc.) in that they are driven by the input: The PDU length tag tells the block how to +operate, whereas other blocks are output-driven (the scheduler tries to fill up the output +buffer are much as possible). + +\subsection howtheywork How do they work? + +As the name implies, tagged stream blocks use tags to identify PDU boundaries. +On the first item of a streamed PDU, there \em must be a tag with a specific +key, which stores the length of the PDU as a pmt_integer. If anything else, or no tag, +is on this first item, this will cause the flow graph to crash! + +The scheduler then takes care of everything. When the work function is called, it +is guaranteed to contain exactly one complete PDU and enough space in the output buffer for +the output. + +\subsection relatestootherblocks How do they relate to other block types (e.g. sync blocks)? + +Tagged stream blocks and sync blocks are really orthogonal concepts, and a block could be +both (gr::digital::ofdm_frame_equalizer_vcvc is such a block). However, because the work +function is defined differently in these block types, there is no way to derive a block +from both gr_tagged_stream_block and gr_sync_block. + +If a block needs the tagged stream mechanism (i.e. knowing about PDU boundaries), it must be +derived from gr_tagged_stream_block. If it's also a sync block, it is still possible to +set gr_block::set_relative_rate(1.0) and/or the fixed rate functions. + +The way gr_tagged_stream_block works, it is still beneficial to specify a relative rate, +if possible. + + +\section creating Creating a tagged stream block + +To create a tagged stream block, the block must be derived from gr_tagged_stream_block. +Here's a minimal example of how the header file could look: +\code +#include <digital/api.h> +#include <gr_tagged_stream_block.h> + +namespace gr { + namespace digital { + + class DIGITAL_API crc32_bb : virtual public gr_tagged_stream_block + { + public: + typedef boost::shared_ptr<crc32_bb> sptr; + + static sptr make(bool check=false, const std::string& len_tag_key="packet_len"); + }; + + } // namespace digital +} // namespace gr + +\endcode + +It is very similar to any other block definition. Two things are stand out: First, +gr_tagged_stream_block.h is included to allow deriving from gr_tagged_stream_block. + +The other thing is in the make function: the second argument is a string containing +the key of the length tags. This is not necessary (the block could get this information +hard-coded), but the usual way is to allow the user to change this tag, but give a +default value (in this case, \p packet_len). + +The implementation header (*_impl.h) also looks a bit different (again this is cropped to the relevant parts): +\code +#include <digital/crc32_bb.h> +namespace gr { + namespace digital { + + class crc32_bb_impl : public crc32_bb + { + public: + crc32_bb_impl(bool check, const std::string& len_tag_key); + ~crc32_bb_impl(); + + int calculate_output_stream_length(const gr_vector_int &ninput_items); + int work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace digital +} // namespace gr +\endcode + +First, the \p work function signature is new. The argument list looks like that from +gr_block::general_work() (note: the arguments mean the same, too), but it's called +\p work like with the other derived block types (such as gr_sync_block). Also, there's a new +function: \p calculate_output_stream_length() is, in a sense, the opposite function to +gr_block::forecast(). Given a number of input items, it calculates the required number of +output items. Note how this relates to the fact that these blocks are input-driven. + +These two overrides (\p work() and \p calculate_output_stream_length() ) are what you need +for most tagged stream blocks. There are cases when you don't need to override the latter +because the default behaviour is enough, and other cases where you have to override more +than these two functions. These are discussed in \ref adv_usage. + +Finally, this is part of the actual block implementation (heavily cropped again, to highlight the relevant parts): +\code +#include <gr_io_signature.h> +#include "crc32_bb_impl.h" + +namespace gr { + namespace digital { + + crc32_bb::sptr crc32_bb::make(bool check, const std::string& len_tag_key) + { + return gnuradio::get_initial_sptr (new crc32_bb_impl(check, len_tag_key)); + } + + crc32_bb_impl::crc32_bb_impl(bool check, const std::string& len_tag_key) + : gr_tagged_stream_block("crc32_bb", + gr_make_io_signature(1, 1, sizeof (char)), + gr_make_io_signature(1, 1, sizeof (char)), + len_tag_key), + d_check(check) + { + } + + int + crc32_bb_impl::calculate_output_stream_length(const gr_vector_int &ninput_items) + { + if (d_check) { + return ninput_items[0] - 4; + } else { + return ninput_items[0] + 4; + } + } + + int + crc32_bb_impl::work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const unsigned char *in = (const unsigned char *) input_items[0]; + unsigned char *out = (unsigned char *) output_items[0]; + + // Do all the signal processing... + // Don't call consume! + + return new_packet_length; + } + + } // namespace digital +} // namespace gr +\endcode + +The make function is not different to any other block. The constructor calls +gr_tagged_stream_block::gr_tagged_stream_block() as expected, but note that it passes the +key of the length tag to the parent constructor. + +The block in question is a CRC block, and it has two modes: It can check the CRC (which is +then dropped), or it can append a CRC to a sequence of bytes. The \p calculate_output_stream_length() function +is thus very simple: depending on how the block is configured, the output is either 4 bytes +longer or shorter than the input stream. + +The \p work() function looks very similar to any other work function. When writing the +signal processing code, the following things must be kept in mind: +- The work function is called for exactly one PDU, and no more (or less) may be processed +- \p ninput_items contains the exact number of items in this PDU (at every port). + These items \em will be consumed after \p work() exits. +- Don't call \p consume() or \p consume_each() yourself! gr_tagged_stream_block will do that + for you. +- You can call \p produce() or \p produce_each(), if you're doing something complicated. + Don't forget to return WORK_CALLED_PRODUCE in that case. + + +\subsection note_on_tp A note on tag propagation + +Despite using tags for a special purpose, all tags that are not the length tag are treated +exactly as before: use gr_block::set_tag_propagation_policy() in the constructor. + +In a lot of the cases, though, you will need to specify set_tag_propagation_policy(TPP_DONT) +and manually handle the tag propagation in \p work(). This is because the unknown length of +the PDUs at compile time prohibits us from setting a precise relative rate of the block, +which is a requirement for automatic tag propagation. +Only if the tagged stream block is also a sync block (including interpolators and decimators, +i.e. blocks with an integer rate change), can automatic tag propagation be reliably used. + +The CRC block seems to a very simple block, but it's already complicated enough to confuse +the automatic tag propagation. For example, what happens to tags which are on the CRC? Do +they get removed, or do they get moved to the last item before the CRC? Also, the input to +output rate is different for every PDU length. + +In this case, it is necessary for the developer to define a tag propagation policy and +implement it in \p work(). Also, it is good practice to specify that tag propagation policy +in the blocks documentation. + +The actual length tags \em are treated differently, though. Most importantly, you don't have +to write the new length tag yourself. The key for the output length tag is the same as that +on the input, if you don't want this, you must override gr_tagged_stream_block::update_length_tags(). + + +\section adv_usage Advanced Usage + +It is generally recommended to read the block documentation of gr_tagged_stream_block. + +A few special cases are described here: + +\subsection multiplelentags Multiple length tags + +In some cases, a single tag is not enough. One example is the OFDM receiver: one OFDM frame contains a certain number of OFDM symbols, and another number of bytes--these numbers are only +very loosely related, and one cannot be calculated from the other. + +gr::digital::ofdm_serializer_vcc is such a block. It is driven by the number of OFDM frames, +but the output is determined by the number of complex symbols. In order to use multiple length +tag keys, it overrides update_length_tags(). + +\subsection backtogrblock Falling back to gr_block behaviour + +If, at compile-time, it is uncertain whether or not a block should be a +gr_tagged_stream_block, there is the possibility of falling back to gr_block behaviour. + +To do this, simple don't pass an empty string as length tag key. Instead of crashing, +a tagged stream block will behave like a gr_block. + +This has some consequences: The work function must have all the elements of a +gr_block::general_work() function, including calls to consume(). Because such a block must +allow both modes of operation (PDUs with tags, and infinite-stream), the work function +must check which mode is currently relevant. Checking if +gr_tagged_stream_block::d_length_tag_key_str is empty is a good choice. + +gr::digital::ofdm_cyclic_prefixer implements this. + +\subsection otherwaysdetermineninput Other ways to determine the number of input items + +If the number of input items is not stored as a pmt::pmt_integer, but there is a way to determine +it, gr_tagged_stream_block::parse_length_tags() can be overridden to figure out the length +of the PDU. + +\section examples Examples + +\subsection CRC32 CRC32 + +Block: gr::digital::crc32_bb + +This is a very simple block, and a good example to start with. + +\subsection ofdmeq OFDM Frame Equalizer + +Block: gr::digital::ofdm_frame_equalizer_vcvc + +This block would be a sync block if tagged stream blocks didn't exist. It also uses more +than one tag to determine the output. + +\subsection muxer Tagged Stream Muxer + +Block: gr::blocks::tagged_stream_mux + +Use this to multiplex any number of tagged streams. + +\subsection ofdmprefixer Cyclic Prefixer (OFDM) + +Block: gr::digital::ofdm_cyclic_prefixer + +This block uses the gr_block behaviour fallback. + +*/ |