diff options
Diffstat (limited to 'docs/doxygen/other')
-rw-r--r-- | docs/doxygen/other/extra_pages.dox | 6 | ||||
-rw-r--r-- | docs/doxygen/other/logger.dox | 76 | ||||
-rw-r--r-- | docs/doxygen/other/main_page.dox | 11 | ||||
-rw-r--r-- | docs/doxygen/other/metadata.dox | 2 | ||||
-rw-r--r-- | docs/doxygen/other/pmt.dox | 4 | ||||
-rw-r--r-- | docs/doxygen/other/tagged_stream_blocks.dox | 271 | ||||
-rw-r--r-- | docs/doxygen/other/thread_affinity.dox | 8 |
7 files changed, 337 insertions, 41 deletions
diff --git a/docs/doxygen/other/extra_pages.dox b/docs/doxygen/other/extra_pages.dox index 44cdf9d483..8d9b69a87b 100644 --- a/docs/doxygen/other/extra_pages.dox +++ b/docs/doxygen/other/extra_pages.dox @@ -80,7 +80,7 @@ audio-osx and audio-windows to be either satisfied or built. \li comedilib (>= 0.8) http://www.comedi.org/ \subsection dep_gr_log gr-log: Logging Tools (Optional) -\li log4cxx (>= 0.10.0) http://logging.apache.org/log4cxx +\li log4cpp (>= 1.0) http://log4cpp.sourceforge.net/ \section build_gr_cmake Building GNU Radio @@ -122,11 +122,11 @@ built or installed. The -DENABLE_DEFAULT=False can be used to disable all components. Individual components can then be selectively turned back -on. For example, just buidling the Volk and Gruel libraries can be +on. For example, just buidling the Volk library can be done with this: \code -cmake -DENABLE_DEFAULT=Off -DENABLE_VOLK=True -DENABLE_GRUEL=True <srcdir> +cmake -DENABLE_DEFAULT=Off -DENABLE_VOLK=True <srcdir> \endcode diff --git a/docs/doxygen/other/logger.dox b/docs/doxygen/other/logger.dox index f98a64657b..f5228cfc55 100644 --- a/docs/doxygen/other/logger.dox +++ b/docs/doxygen/other/logger.dox @@ -4,25 +4,29 @@ 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 log4cxx (http://logging.apache.org/log4cxx) which is readily +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 log4cxx if it is available. If log4cxx +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: - TRACE < DEBUG < INFO < WARN < ERROR < FATAL +<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 Debug level, all Debug and -higher messages are logged and Trace is ignored. +above it. For example, when using the INFO level, all INFO and +higher messages are logged and DEBUG is ignored. A level NOTSET is provided +to disable a logger. \subsection configfile Logging Configuration @@ -42,14 +46,14 @@ stream or file. The four main configure options are: <pre> - log_level = all - debug_level = all + 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 (TRACE through FATAL). They are also configured not to +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. @@ -111,20 +115,21 @@ The various logging macros are defined in gr_logger.h. Here are some simple examples of using them: \code - GR_LOG_TRACE(LOG, "TRACE message"); 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_FATAL(LOG, "FATAL message"); - GR_ERRORIF(LOG, a>b, "CONDITIONAL ERROR message"); - GR_ASSERT(LOG, a>b, "ASSERT 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 log4cxx library is not found, then TRACE, -DEBUG, and INFO levels go to stdout and the rest to stderr. +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 @@ -133,14 +138,13 @@ 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 -log4cxx documentation (found through -http://logging.apache.org/log4cxx/) 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: +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 + $prefix/etc/gnuradio/gr_log_default.conf </pre> For the following examples, we will assume that our local @@ -148,12 +152,12 @@ For the following examples, we will assume that our local \code [LOG] -log_config = /opt/gr/etc/gnuadio/gr_log_default.xml -log_level = All +log_config = /opt/gr/etc/gnuadio/gr_log_default.conf +log_level = debug debug_level = Off \endcode -Inside of the XML default configuration file, we define the parameters +Inside of the 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 @@ -163,7 +167,7 @@ specified in the XML file. Here, we have turned on the standard 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 "all." +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 @@ -196,7 +200,27 @@ except we would use "gr_log_debug." in the GR_LOG_GETLOGGER call): \endcode This creates a pointer called LOG (which is instantiated as a -log4cxx:LoggerPtr in the macro) that we can now use locally as the -input to our logging macros like 'GR_LOG_TRACE(LOG, "message")'. +log4cpp:LoggerPtr in the macro) that we can now use locally as the +input to our logging macros like 'GR_LOG_INFO(LOG, "message")'. + +\section logPy Logging from Python + +The logging capability has been brought out python via swig. The configuration +of the logger can be manipulated via the following calls: +\code + from gnuradio import gr + gr.logger_config(filename,watch_period) # Configures the logger with conf file filename + names = gr.logger_get_logger_names() # Returns the names of all loggers + gr.logger_reset_config() # Resets logger config by removing all appenders +\endcode +Once the logger is configured you can manipulate a logger via a wrapper class gr.logger(). +You can isntantiate this by the following. (Reference gr_logger.h for list of methods) +\code + from gnuradio import gr + log=gr.logger("nameOfLogger") + log.debug("Log a debug message") + log.set_level("INFO"); + +\endcode */ diff --git a/docs/doxygen/other/main_page.dox b/docs/doxygen/other/main_page.dox index 6f422dfd8f..3ad9e68021 100644 --- a/docs/doxygen/other/main_page.dox +++ b/docs/doxygen/other/main_page.dox @@ -45,6 +45,7 @@ More details on GNU Radio concepts: \li \ref page_metadata \li \ref volk_guide \li \ref page_pfb +\li \ref page_tagged_stream_blocks \section flowgraph Operating a Flowgraph @@ -80,7 +81,7 @@ them. self.src = analog.noise_source_c(gr.GR_GAUSSIAN, amp) self.flt = filter.fir_filter_ccf(1, taps) - self.snk = gr.null_sink(gr.sizeof_gr_complex) + self.snk = blocks.null_sink(gr.sizeof_gr_complex) self.connect(self.src, self.flt, self.snk) @@ -226,8 +227,8 @@ class mytb(gr.top_block): self.src1 = analog.noise_source_c(analog.GR_GAUSSIAN, 1) self.add = blocks.add_cc() self.sub = blocks.sub_cc() - self.head = gr.head(gr.sizeof_gr_complex, 1000000) - self.snk = gr.file_sink(gr.sizeof_gr_complex, "output.32fc") + self.head = blocks.head(gr.sizeof_gr_complex, 1000000) + self.snk = blocks.file_sink(gr.sizeof_gr_complex, "output.32fc") self.connect(self.src0, (self.add,0)) self.connect(self.src1, (self.add,1)) @@ -281,8 +282,8 @@ class mytb(gr.top_block): self.src1 = analog.noise_source_c(analog.GR_GAUSSIAN, 1) self.add = blocks.add_cc() self.sub = blocks.sub_cc() - self.head = gr.head(gr.sizeof_gr_complex, 1000000) - self.snk = gr.file_sink(gr.sizeof_gr_complex, "output.32fc") + self.head = blocks.head(gr.sizeof_gr_complex, 1000000) + self.snk = blocks.file_sink(gr.sizeof_gr_complex, "output.32fc") self.connect(self.src0, (self.add,0)) self.connect(self.src1, (self.add,1)) diff --git a/docs/doxygen/other/metadata.dox b/docs/doxygen/other/metadata.dox index 76553c696a..03ebe591e4 100644 --- a/docs/doxygen/other/metadata.dox +++ b/docs/doxygen/other/metadata.dox @@ -309,7 +309,7 @@ into the metadata to keep track of later. The date in this case is encoded as a vector of uint16 with [day, month, year]. \code - from gruel import pmt + import pmt from gnuradio import blocks key = pmt.intern("date") diff --git a/docs/doxygen/other/pmt.dox b/docs/doxygen/other/pmt.dox index ba97863a08..04f58aafc8 100644 --- a/docs/doxygen/other/pmt.dox +++ b/docs/doxygen/other/pmt.dox @@ -173,7 +173,7 @@ reference to the old dictionary. This just keeps our number of variables small. \code -from gruel import pmt +import pmt key0 = pmt.intern("int") val0 = pmt.from_long(123) @@ -303,7 +303,7 @@ ready to be written to a file and then deserialize it back to its original PMT. \code -from gruel import pmt +import pmt key0 = pmt.intern("int") val0 = pmt.from_long(123) 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. + +*/ diff --git a/docs/doxygen/other/thread_affinity.dox b/docs/doxygen/other/thread_affinity.dox index 235266febd..2f31d9ce53 100644 --- a/docs/doxygen/other/thread_affinity.dox +++ b/docs/doxygen/other/thread_affinity.dox @@ -6,8 +6,8 @@ In the thread-per-block scheduler, you can set the block's core affinity. Each block can be pinned to a group cores or be set back to use the standard kernel scheduler. -The implementation is done by adding new functions to the GRUEL -library: +The implementation is done by adding new functions to the threading +section of the gnuradio-runtime library: \code gr_thread_t get_current_thread_id(); @@ -21,7 +21,7 @@ library: The ability to set a thread's affinity to a core or groups of cores is not implemented in the Boost thread library, and so we have made our -own portability library. In particular, the gruel::gr_thread_t type is +own portability library. In particular, the gr::thread::gr_thread_t type is defined as the thread type for the given system. The other functions are designed to be portable as well by calling the specific implementation for the thread affinity for a particular platform. @@ -43,7 +43,7 @@ Each block has two new data members: - threaded: a boolean value that is true if the block is attached to a thread. -- thread: a gruel::gr_thread_t handle to the block's thread. +- thread: a gr::thread::gr_thread_t handle to the block's thread. A block can set and unset it's affinity at any time using the following member functions: |