summaryrefslogtreecommitdiff
path: root/docs/doxygen/other/main_page.dox
diff options
context:
space:
mode:
Diffstat (limited to 'docs/doxygen/other/main_page.dox')
-rw-r--r--docs/doxygen/other/main_page.dox427
1 files changed, 335 insertions, 92 deletions
diff --git a/docs/doxygen/other/main_page.dox b/docs/doxygen/other/main_page.dox
index c5d5a44cb7..8895cd552d 100644
--- a/docs/doxygen/other/main_page.dox
+++ b/docs/doxygen/other/main_page.dox
@@ -37,127 +37,370 @@ More details on packages in GNU Radio:
\li \ref page_qtgui
\li \ref page_uhd
\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
-\section volk_main Using Volk in GNU Radio
-The \ref volk_guide page provides an overview of how to incorporate
-and use Volk in GNU Radio blocks.
+\section flowgraph Operating a Flowgraph
-Many blocks have already been converted to use Volk in their calls, so
-they can also serve as examples. See the gr_complex_to_xxx.h file for
-examples of various blocks that make use of Volk.
+The basic data structure in GNU Radio is the flowgraph, which
+represents the connections of the blocks through which a continuous
+stream of samples flows. The concept of a flowgraph is an acyclic
+directional graph with one or more source blocks (to insert samples
+into the flowgraph), one or more sink blocks (to terminate or export
+samples from the flowgraph), and any signal processing blocks in
+between.
+
+A program must at least create a GNU Radio 'top_block', which
+represents the top-most structure of the flowgraph. The top blocks
+provide the overall control and hold methods such as 'start,' 'stop,'
+and 'wait.'
+The general construction of a GNU Radio application is to create a
+gr_top_block, instantiate the blocks, connect the blocks together, and
+then start the gr_top_block. The following program shows how this is
+done. A single source and sink are used with a FIR filter between
+them.
-\section logging Logging
+\code
+ from gnuradio import gr, filter
+
+ class my_topblock(gr.top_block):
+ def __init__(self):
+ gr.top_block.__init__(self)
+
+ amp = 1
+ taps = filter.firdes.low_pass(1, 1, 0.1, 0.01)
+
+ self.src = gr.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.connect(self.src, self.flt, self.snk)
+
+ if __name__ == "__main__":
+ tb = my_topblock()
+ tb.start()
+ tb.wait()
+\endcode
-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
-available in most Linux distributions. This is an optional dependency
-and GNU Radio will work without it.
+The 'tb.start()' starts the data flowing through the flowgraph while
+the 'tb.wait()' is the equivalent of a thread's 'join' operation and
+blocks until the gr_top_block is done.
-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 and will
-turn off if log4cxx is not available.
+An alternative to using the 'start' and 'wait' methods, a 'run' method is
+also provided for convenience that is a blocking start call;
+equivalent to the above 'start' followed by a 'wait.'
-Logging is useful for blocks to print out certain amounts of data at
-different levels. These levels are:
- TRACE < DEBUG < INFO < WARN < ERROR < FATAL
+\subsection latency Latency and Throughput
-The order here determines the level of output. When using the Debug
-level, for instance, all Debug and higher messages are logged and
-Trace is ignored.
+By default, GNU Radio runs a scheduler that attempts to optimize
+throughput. Using a dynamic scheduler, blocks in a flowgraph pass
+chunks of items from sources to sinks. The sizes of these chunks will
+vary depending on the speed of processing. For each block, the number
+of items is can process is dependent on how much space it has in its
+output buffer(s) and how many items are available on the input
+buffer(s).
-\subsection use_logging Using the Logging Features
+The consequence of this is that often a block may be called with a very
+large number of items to process (several thousand). In terms of
+speed, this is efficient since now the majority of the processing time
+is taken up with processing samples. Smaller chunks mean more calls
+into the scheduler to retrieve more data. The downside to this is that
+it can lead to large latency while a block is processing a large chunk
+of data.
-In a GNU Radio block, you use the logging features by calling macros
-that are defined in gr_log.h, which must be included for use.
+To combat this problem, the gr_top_block can be passed a limit on the
+number of output items a block will ever receive. A block may get less
+than this number, but never more, and so it serves as an upper limit
+to the latency any block will exhibit. By limiting the number of items
+per call to a block, though, we increase the overhead of the
+scheduler, and so reduce the overall efficiency of the application.
-The logger must be properly configured, which is easiest by defining a
-configuration file. The log4cxx website 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:
+To set the maximum number of output items, we pass a value into the
+'start' or 'run' method of the gr_top_block:
+
+\code
+ tb.start(1000)
+ tb.wait()
+or
+ tb.run(1000)
+\endcode
- $prefix/etc/gnuradio/gr_log_default.xml
+Using this method, we place a global restriction on the size of items
+to all blocks. Each block, though, has the ability to overwrite this
+with its own limit. Using the 'set_max_noutput_items(m)' method for an
+individual block will overwrite the global setting. For example, in
+the following code, the global setting is 1000 items max, except for
+the FIR filter, which can receive up to 2000 items.
-However, we use the global GNU Radio configuration file to tell the
-system where this file is located. In the [LOG] section of the
-configuration file, the location of the logger's XML file can be
-specified. The default configuration file is found in:
+\code
+ tb.flt.set_max_noutput_items(2000)
+ tb.run(1000)
+\endcode
- $prefix/etc/gnuradio/conf.d/gnuradio-core.conf
+In some situations, you might actually want to restrict the size of
+the buffer itself. This can help to prevent a buffer who is blocked
+for data from just increasing the amount of items in its buffer, which
+will then cause an increased latency for new samples. You can set the
+size of an output buffer for each output port for every block.
-A local "~/.gnuradio/config.conf" file can be used to override any
-parameter in the global file.
+WARNING: This is an advanced feature in GNU Radio and should not be
+used without a full understanding of this concept as explained below.
-For the following examples, we will assume that our local
-"~/.gnuradio/config.conf" looks like this:
+To set the output buffer size of a block, you simply call:
\code
-[LOG]
-log_file = /opt/gr/etc/gnuadio/gr_log_default.xml
-log_level = All
+ tb.blk0.set_max_output_buffer(2000)
+ tb.blk1.set_max_output_buffer(1, 2000)
+ tb.start()
+ print tb.blk1.max_output_buffer(0)
+ print tb.blk1.max_output_buffer(1)
\endcode
-The startup and configuration process proceeds as follows.
+In the above example, all ports of blk0 are set to a buffer size of
+2000 in _items_ (not bytes), and blk1 only sets the size for output
+port 1, any and all other ports use the default. The third and fourth
+lines just print out the buffer sizes for ports 0 and 1 of blk1. This
+is done after start() is called because the values are updated based
+on what is actually allocated to the block's buffers.
+
+NOTES:
+
+1. Buffer length assignment is done once at runtime (i.e., when run()
+or start() is called). So to set the max buffer lengths, the
+set_max_output_buffer calls must be done before this.
+
+2. Once the flowgraph is started, the buffer lengths for a block are
+set and cannot be dynamically changed, even during a
+lock()/unlock(). If you need to change the buffer size, you will have
+to delete the block and rebuild it, and therefore must disconnect and
+reconnect the blocks.
+
+3. This can affect throughput. Large buffers are designed to improve
+the efficiency and speed of the program at the expense of
+latency. Limiting the size of the buffer may decrease performance.
+
+4. The real buffer size is actually based on a minimum granularity of
+the system. Typically, this is a page size, which is typically 4096
+bytes. This means that any buffer size that is specified with this
+command will get rounded up to the nearest granularity (e.g., page)
+size. When calling max_output_buffer(port) after the flowgraph is
+started, you will get how many items were actually allocated in the
+buffer, which may be different than what was initially specified.
+
+
+\section reconfigure Reconfiguring Flowgraphs
+
+It is possible to reconfigure the flowgraph at runtime. The
+reconfiguration is meant for changes in the flowgraph structure, not
+individual parameter settings of the blocks. For example, changing the
+constant in a gr_add_const_cc block can be done while the flowgraph is
+running using the 'set_k(k)' method.
+
+Reconfiguration is done by locking the flowgraph, which stops it from
+running and processing data, performing the reconfiguration, and then
+restarting the graph by unlocking it.
+
+The following example code shows a graph that first adds two
+gr_noise_source_c blocks and then replaces the gr_add_cc block with a
+gr_sub_cc block to then subtract the sources.
\code
- std::string log_file = gr_prefs::singleton()->get_string("LOG", "log_config", "");
- std::string log_level = gr_prefs::singleton()->get_string("LOG", "log_level", "off");
- GR_CONFIG_LOGGER(log_file);
- GR_LOG_GETLOGGER(LOG, <name>);
- GR_LOG_SET_LEVEL(LOG, log_level);
+from gnuradio import gr
+import time
+
+class mytb(gr.top_block):
+ def __init__(self):
+ gr.top_block.__init__(self)
+
+ self.src0 = gr.noise_source_c(gr.GR_GAUSSIAN, 1)
+ self.src1 = gr.noise_source_c(gr.GR_GAUSSIAN, 1)
+ self.add = gr.add_cc()
+ self.sub = gr.sub_cc()
+ self.head = gr.head(gr.sizeof_gr_complex, 1000000)
+ self.snk = gr.file_sink(gr.sizeof_gr_complex, "output.32fc")
+
+ self.connect(self.src0, (self.add,0))
+ self.connect(self.src1, (self.add,1))
+ self.connect(self.add, self.head)
+ self.connect(self.head, self.snk)
+
+def main():
+ tb = mytb()
+ tb.start()
+ time.sleep(0.01)
+
+ # Stop flowgraph and disconnect the add block
+ tb.lock()
+ tb.disconnect(tb.add, tb.head)
+ tb.disconnect(tb.src0, (tb.add,0))
+ tb.disconnect(tb.src1, (tb.add,1))
+
+ # Connect the sub block and restart
+ tb.connect(tb.sub, tb.head)
+ tb.connect(tb.src0, (tb.sub,0))
+ tb.connect(tb.src1, (tb.sub,1))
+ tb.unlock()
+
+ tb.wait()
+
+if __name__ == "__main__":
+ main()
\endcode
-The default config file has two names that can be used (as std::string
-types): "gr_log" and "gr_log_debug". The first one will print
-all levels of logging informaiton while the second one will only print
-Debug and above.
-
-Names of loggers are global, so "gr_log" as a name will be the same
-logger no matter where it is picked from.
-
-The "LOG" name for the logger is now a LoggerPtr object and can be
-named anything.
-
-For a given block, it is recommended that a new name be specified for
-individual control over the logger as loggers are globally held in a
-LoggerManager. Since log4cxx is hierarchical, a new name is created by
-appending a string to an existing logger. So a general logger used in
-the digital_costas_loop_cc.cc class, for instance, could look
-something like "gr_log.costas_loop". This will inherit all properties
-of the parent logger, "gr_log".
-
-After calling "GR_LOG_GETLOGGER", the LoggerPtr that was specified,
-"LOG" in the example above, is used to set the properties. The main
-setting we are generally interested in is the level of the
-logger. This will determine if this logger gets outputted or not. In
-this case, we are actually getting the gr_log level from the GNU Radio
-configuration file, stored in log_level. The macro GR_LOG_SET_LEVEL
-can take either a string or a log4cxx::LevelPtr object. The log_level
-variable in this case holds a string read in from the config file, and
-it's case insensitive. I can be "off", "all", "trace", "debug",
-"info", "warn", "error", or "fatal" to match with the levels above.
-
-In our example here, all logging information is displayed because the
-config file specifies "All". We can then easily turn off all reporting
-by setting this value to "Off".
-
-The various logging macros are defined in gr_log.h. Here are some
-simple exmaples of using them:
+During reconfiguration, the maximum noutput_items value can be changed
+either globally using the 'set_max_noutput_items(m)' on the gr_top_block
+object or locally using the 'set_max_noutput_items(m)' on any given
+block object.
+
+A block also has a 'unset_max_noutput_items()' method that unsets the
+local max noutput_items value so that block reverts back to using the
+global value.
+
+The following example expands the previous example but sets and resets
+the max noutput_items both locally and globally.
\code
- GR_LOG_TRACE(LOG, "TRACE message");
- GR_LOG_DEBUG(LOG, "DEBUG message");
- GR_LOG_INFO(LOG, "INFO 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");
+from gnuradio import gr
+import time
+
+class mytb(gr.top_block):
+ def __init__(self):
+ gr.top_block.__init__(self)
+
+ self.src0 = gr.noise_source_c(gr.GR_GAUSSIAN, 1)
+ self.src1 = gr.noise_source_c(gr.GR_GAUSSIAN, 1)
+ self.add = gr.add_cc()
+ self.sub = gr.sub_cc()
+ self.head = gr.head(gr.sizeof_gr_complex, 1000000)
+ self.snk = gr.file_sink(gr.sizeof_gr_complex, "output.32fc")
+
+ self.connect(self.src0, (self.add,0))
+ self.connect(self.src1, (self.add,1))
+ self.connect(self.add, self.head)
+ self.connect(self.head, self.snk)
+
+def main():
+ # Start the gr_top_block after setting some max noutput_items.
+ tb = mytb()
+ tb.src1.set_max_noutput_items(2000)
+ tb.start(100)
+ time.sleep(0.01)
+
+ # Stop flowgraph and disconnect the add block
+ tb.lock()
+
+ tb.disconnect(tb.add, tb.head)
+ tb.disconnect(tb.src0, (tb.add,0))
+ tb.disconnect(tb.src1, (tb.add,1))
+
+ # Connect the sub block
+ tb.connect(tb.sub, tb.head)
+ tb.connect(tb.src0, (tb.sub,0))
+ tb.connect(tb.src1, (tb.sub,1))
+
+ # Set new max_noutput_items for the gr_top_block
+ # and unset the local value for src1
+ tb.set_max_noutput_items(1000)
+ tb.src1.unset_max_noutput_items()
+ tb.unlock()
+
+ tb.wait()
+
+if __name__ == "__main__":
+ main()
\endcode
+
+\section volk_main Using Volk in GNU Radio
+
+The \ref volk_guide page provides an overview of how to incorporate
+and use Volk in GNU Radio blocks.
+
+Many blocks have already been converted to use Volk in their calls, so
+they can also serve as examples. See the gr_complex_to_xxx.h file for
+examples of various blocks that make use of Volk.
+
+
+\section prefs Configuration / Preference Files
+
+GNU Radio defines some of its basic behavior through a set of
+configuration files located in
+${prefix}/etc/gnuradio/conf.d. Different components have different
+files listed in here for the various properties. These will be read
+once when starting a GNU Radio application, so updates during runtime
+will not affect them.
+
+The configuration files use the following format:
+
+\code
+# Stuff from section 1
+[section1]
+var1 = value1
+var2 = value2 # value of 2
+
+# Stuff from section 2
+[section2]
+var3 = value3
+\endcode
+
+In this file, the hash mark ('#') indicates a comment and blank lines
+are ignored. Section labels are defined inside square brackets as a
+group distinguisher. All options must be associated with a section
+name. The options are listed one per line with the option name is
+given followed by an equals ('=') sign and then the value. All section
+and option names must not have white spaces (actually, all white
+spaces are ignored).
+
+The value of an option can be a string or number and retrieved through
+a few different interfaces. There is a single preference object
+created when GNU Radio is launched. In Python, you can get this by
+making a new variable:
+
+\code
+p = gr.prefs()
+\endcode
+
+Similarly, in C++, we get a reference to the object by explicitly
+calling for the singleton of the object:
+
+\code
+ gr_prefs *p = gr_prefs::singleton();
+\endcode
+
+The methods associated with this preferences object are (from class gr_prefs):
+
+\code
+ bool has_section(string section)
+ bool has_option(string section, string option)
+ string get_string(string section, string option, string default_val)
+ bool get_bool(string section, string option, bool default_val)
+ long get_long(string section, string option, long default_val)
+ double get_double(string section, string option, double default_val)
+\endcode
+
+When setting a Boolean value, we can use 0, 1, "True", "true",
+"False", "false", "On", "on", "Off", and "off".
+
+All configuration preferences in these files can also be overloaded by
+an environmental variable. The environmental variable is named based
+on the section and option name from the configuration file as:
+
+\code
+ GR_CONF_<SECTION>_<OPTION> = <value>
+\endcode
+
+The "GR_CONF_" is a prefix to identify this as a GNU Radio
+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.
+
*/