Editing OutOfTreeModules

Jump to: navigation, search

Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then save the changes below to finish undoing the edit.
Latest revision Your text
Line 1: Line 1:
[[Category:Guide]]
+
= Out-of-tree modules =
  
 +
'''Extending GNU Radio with own functionality and blocks'''
  
'''Extending GNU Radio with own functionality and blocks'''
+
{{>toc}}
  
 
This article borrows heavily from the original (but very outdated) "How to write a block?" written by Eric Blossom.
 
This article borrows heavily from the original (but very outdated) "How to write a block?" written by Eric Blossom.
Line 10: Line 11:
 
An out-of-tree module is a GNU Radio component that does not live within the GNU Radio source tree. Typically, if you want to extend GNU Radio with your own functions and blocks, such a module is what you create (i.e. you wouldn't usually add stuff to the actual GNU Radio source tree unless you're planning to submit it to the devs for upstream integration). This allows you to maintain the code yourself and have additional functionality alongside the main code.
 
An out-of-tree module is a GNU Radio component that does not live within the GNU Radio source tree. Typically, if you want to extend GNU Radio with your own functions and blocks, such a module is what you create (i.e. you wouldn't usually add stuff to the actual GNU Radio source tree unless you're planning to submit it to the devs for upstream integration). This allows you to maintain the code yourself and have additional functionality alongside the main code.
  
A lot of OOT projects are hosted at [http://cgran.org CGRAN] -- the Comprehensive GNU Radio Archive Network. CGRAN projects are all available through our tool [http://gnuradio.org/pybombs PyBOMBS]. In fact, when you add your project to the [https://github.com/gnuradio/gr-etcetera PyBOMBS recipe repo], it will automatically update the CGRAN website.
+
A lot of OOT projects are hosted at [http://cgran.org CGRAN] -- the Comprehensive GNU Radio Archive Network. CGRAN projects are all available through our tool [http://gnuradio.org/pybombs PyBOMBS]. In fact, when you add your project to the [https://github.com/gnuradio/gr-etcetera PyBOMBS recipe repo], it will automatically update the CGRAN website. For more information about setting up your project and adding it to PyBOMBS, see our tutorial on [[OutOfTreeModulesConfig|Configuring OOT Projects]]. This will help you craft your CMake files for best chances of installation, edit the MANIFEST file of your project to properly display information on CGRAN, and create the recipe file for adding the project to PyBOMBS.
  
For example of such a module is the [https://www.cgran.org/1870/ spectral estimation toolbox], which extends GNU Radio with spectral estimation features. When installed, you have more blocks available (e.g. in the [[GNURadioCompanion|GNU Radio companion]]) which behave just like the rest of GNU Radio; however, the developers are different people.
+
For example of such a module is the [http://cgran.org/pages/gr-specest.html spectral estimation toolbox], which extends GNU Radio with spectral estimation features. When installed, you have more blocks available (e.g. in the [[GNURadioCompanion|GNU Radio companion]]) which behave just like the rest of GNU Radio; however, the developers are different people.
  
 
== Tools and resources at my disposal ==
 
== Tools and resources at my disposal ==
Line 24: Line 25:
 
Note that gr_modtool makes a lot of assumptions on what the code looks like. The more your module is custom and has specific changes, the less useful gr_modtool will be, but it is probably the best place to start with any new module or block.
 
Note that gr_modtool makes a lot of assumptions on what the code looks like. The more your module is custom and has specific changes, the less useful gr_modtool will be, but it is probably the best place to start with any new module or block.
  
gr_modtool is now available in the GNU Radio source tree and is installed by default.
+
gr_modtool is now available in the GNU Radio source tree, and is installed by default.
  
 
=== Developer resources on the wiki ===
 
=== Developer resources on the wiki ===
  
 
Most important is definitely the [[BlocksCodingGuide|block coding guide]]. While this is written for the GNU Radio main tree, this should also be applied to all modules. Specifically, have a look at the naming conventions!
 
Most important is definitely the [[BlocksCodingGuide|block coding guide]]. While this is written for the GNU Radio main tree, this should also be applied to all modules. Specifically, have a look at the naming conventions!
 +
 +
If you're reading this, you're most likely familiar with all the GNU Radio jargon, but just in case you're not, have a peak at the [[TutorialsCoreConcepts|core concepts tutorial]]. This contains definitive must-knows. Also, the [[TutorialsWritePythonApplications|tutorial on writing Python applications]] explains a lot of the key features.
  
 
=== CMake, make, etc. ===
 
=== CMake, make, etc. ===
  
GNU Radio uses CMake as a build system. Building a module, therefore, requires you to have cmake installed, and whatever build manager you prefer (most often this is 'make', but you could also be using Eclipse or MS Visual Studio).
+
GNU Radio uses CMake as a build system. Building a module therefore requires you to have cmake installed, and whatever build manager you prefer (most often this is 'make', but you could also be using Eclipse or MS Visual Studio).
  
 
== Tutorial 1: Creating an out-of-tree module ==
 
== Tutorial 1: Creating an out-of-tree module ==
Line 57: Line 60:
 
You probably know already that GNU Radio blocks are available in Python even if they were written in C++. This is done by the help of SWIG, the simplified wrapper and interface generator, which automatically creates glue code to make this possible. SWIG needs some instructions on how to do this, which are put into the <code>swig/</code> subdirectory. Unless doing something extra clever with your block, you will not need to go into the <code>swig/</code> directory; gr_modtool handles all of that for us.
 
You probably know already that GNU Radio blocks are available in Python even if they were written in C++. This is done by the help of SWIG, the simplified wrapper and interface generator, which automatically creates glue code to make this possible. SWIG needs some instructions on how to do this, which are put into the <code>swig/</code> subdirectory. Unless doing something extra clever with your block, you will not need to go into the <code>swig/</code> directory; gr_modtool handles all of that for us.
  
If you want your blocks to be available in the [[GNURadioCompanion|GNU Radio companion]], the graphical UI for GNU Radio, you need to add descriptions of the blocks and put them into <code>grc/</code>. Prior to version 3.8 these descriptions were XML files, but from 3.8 onward they use [[YAML_GRC|YAML instead]].
+
If you want your blocks to be available in the [[GNURadioCompanion|GNU Radio companion]], the graphical UI for GNU Radio, you need to add XML descriptions of the blocks and put them into <code>grc/</code>.
  
 
For documentation, <code>docs/</code> contains some instructions on how to extract documentation from the C++ files and Python files (we use Doxygen and Sphinx for this) and also make sure they're available as docstrings in Python. Of course, you can add custom documentation here as well.
 
For documentation, <code>docs/</code> contains some instructions on how to extract documentation from the C++ files and Python files (we use Doxygen and Sphinx for this) and also make sure they're available as docstrings in Python. Of course, you can add custom documentation here as well.
Line 63: Line 66:
 
The <code>apps/</code> subdir contains any complete applications (both for GRC and standalone executables) which are installed to the system alongside with the blocks.
 
The <code>apps/</code> subdir contains any complete applications (both for GRC and standalone executables) which are installed to the system alongside with the blocks.
  
The directory, <code>examples/</code> can be used to save (guess what) examples, which are a great addendum to documentation because other developers can simply look straight at the code to see how your blocks are used.
+
The directory, <code>examples/</code> can be used to save (guess what) examples, which are a great addendum to documentation, because other developers can simply look straight at the code to see how your blocks are used.
  
 
The build system brings some baggage along, as well: the <code>CMakeLists.txt</code> file (one of which is present in every subdirectory) and the <code>cmake/</code> folder. You can ignore the latter for now, as it brings along mainly instructions for CMake on how to find GNU Radio libraries etc. The CMakeLists.txt files need to be edited a lot in order to make sure your module builds correctly.
 
The build system brings some baggage along, as well: the <code>CMakeLists.txt</code> file (one of which is present in every subdirectory) and the <code>cmake/</code> folder. You can ignore the latter for now, as it brings along mainly instructions for CMake on how to find GNU Radio libraries etc. The CMakeLists.txt files need to be edited a lot in order to make sure your module builds correctly.
Line 84: Line 87:
 
Again, <code>gr_modtool</code> does the job. On the command line, go to the <code>gr-howto</code> directory and enter:
 
Again, <code>gr_modtool</code> does the job. On the command line, go to the <code>gr-howto</code> directory and enter:
  
<pre>gr-howto % gr_modtool add -t general -l cpp square_ff
+
<pre>gr-howto % gr_modtool add -t general square_ff
 
GNU Radio module name identified: howto
 
GNU Radio module name identified: howto
 +
Language: C++
 
Block/code identifier: square_ff
 
Block/code identifier: square_ff
Language: C++
 
Please specify the copyright holder:
 
 
Enter valid argument list, including default arguments:  
 
Enter valid argument list, including default arguments:  
 
Add Python QA code? [Y/n]  
 
Add Python QA code? [Y/n]  
Line 100: Line 102:
 
Adding file 'howto_square_ff.xml'...
 
Adding file 'howto_square_ff.xml'...
 
Editing grc/CMakeLists.txt...</pre>
 
Editing grc/CMakeLists.txt...</pre>
On the command line, we specify that we're adding a block, its type is 'general' (because we don't know what block types are, yet) and it is called <code>square_ff</code>. The block should be created in C++ and it currently has no specified copyright holder (by default, gr-module author is the copyright holder).  <code>gr_modtool</code> then asks you if your block takes any arguments (it doesn't, so we leave that empty), whether or not we want QA code for Python (yes, we do) and for C++ (no, we don't right now).
+
On the command line, we specify that we're adding a block, its type is 'general' (because we don't know what block types are, yet) and it is called <code>square_ff</code>. <code>gr_modtool</code> then asks you if your block takes any arguments (it doesn't, so we leave that empty), whether or not we want QA code for Python (yes, we do) and for C++ (no, we don't right now).
  
 
Now, have another look at the different CMakeLists.txt files and see what <code>gr_modtool</code> did. You can also see a lot of new files, which now have to be edited if we want the block to work.
 
Now, have another look at the different CMakeLists.txt files and see what <code>gr_modtool</code> did. You can also see a lot of new files, which now have to be edited if we want the block to work.
Line 160: Line 162:
 
Now that we've got a test case, let's write the C++ code. All signal processing blocks are derived from <code>gr::block</code> or one of its subclasses. Go check out the [http://gnuradio.org/doc/doxygen/classgr_1_1block.html block documentation] on the Doxygen-generated manual.
 
Now that we've got a test case, let's write the C++ code. All signal processing blocks are derived from <code>gr::block</code> or one of its subclasses. Go check out the [http://gnuradio.org/doc/doxygen/classgr_1_1block.html block documentation] on the Doxygen-generated manual.
  
<code>gr_modtool</code> already provided us with three files that define the block: <code>lib/square_ff_impl.h</code>, <code>lib/square_ff_impl.cc</code> and <code>include/howto/square_ff.h</code>. All we have to do is modify to them to do our bidding. After you've finished with this tutorial ''please'' read and understand the [https://wiki.gnuradio.org/index.php/BlocksCodingGuide Blocks Coding Guide] to find out how these files are structured and why!
+
<code>gr_modtool</code> already provided us with three files that define the block: <code>lib/square_ff_impl.h</code>, <code>lib/square_ff_impl.cc</code> and <code>include/howto/square_ff.h</code>. All we have to do is modify to them to do our bidding. After you've finished with this tutorial ''please'' read and understand the [http://gnuradio.org/redmine/projects/gnuradio/wiki/BlocksCodingGuide Blocks Coding Guide] to find out how these files are structured and why!
  
 
First of all, we have a look at our header files. Because the block we're writing is so simple, we don't have to actually change them (the header file in <code>include/</code> is often quite complete after running <code>gr_modtool</code>, unless we need to add some public methods such as mutator methods, i.e., getters and setters). That leaves us with <code>lib/square_ff_impl.cc</code>.
 
First of all, we have a look at our header files. Because the block we're writing is so simple, we don't have to actually change them (the header file in <code>include/</code> is often quite complete after running <code>gr_modtool</code>, unless we need to add some public methods such as mutator methods, i.e., getters and setters). That leaves us with <code>lib/square_ff_impl.cc</code>.
Line 211: Line 213:
 
=== Using CMake ===
 
=== Using CMake ===
  
If you've never used CMake before, this is a good time to give it a try. The typical workflow of a CMake-based project as seen from the command line is this (if using PyBOMBS, first read '''Build Tree vs. Install Tree'''):
+
If you've never used CMake before, this is good time to give it a try. The typical workflow of a CMake-based project as seen from the command line is this (if using PyBOMBS, first read '''Build Tree vs. Install Tree'''):
  
 
<pre>$ mkdir build    # We're currently in the module's top directory
 
<pre>$ mkdir build    # We're currently in the module's top directory
Line 336: Line 338:
 
Then, we use <code>gr_modtool</code> to add the block files, skipping the QA code (because we already have that):
 
Then, we use <code>gr_modtool</code> to add the block files, skipping the QA code (because we already have that):
  
<pre>gr-howto % gr_modtool add -t sync -l cpp square2_ff
+
<pre>gr-howto % gr_modtool add -t sync square2_ff
 
GNU Radio module name identified: howto
 
GNU Radio module name identified: howto
 +
Language: C++
 
Block/code identifier: square2_ff
 
Block/code identifier: square2_ff
Language: C++
 
Please specify the copyright holder:
 
 
Enter valid argument list, including default arguments:  
 
Enter valid argument list, including default arguments:  
 
Add Python QA code? [Y/n] n
 
Add Python QA code? [Y/n] n
Line 412: Line 413:
 
     return noutput_items;
 
     return noutput_items;
 
   }</pre>
 
   }</pre>
So, given history, vectors, multiple input ports etc., is this really all you need? Yes, it is! Because sync blocks have a fixed output to input rate, all you need to know is the number of output items, and you can calculate how many input items are available.
+
So, given history, vectors, multiple input ports etc., is this really all you need? Yes it is! Because sync blocks have a fixed output to input rate, all you need to know is the number of output items, and you can calculate how many input items are available.
  
 
Example - the adder block: source:gr-blocks/lib/add_XX_impl.cc.t
 
Example - the adder block: source:gr-blocks/lib/add_XX_impl.cc.t
Line 420: Line 421:
 
Example - interpolation in gr::blocks::unpack_k_bits_bb: source:gr-blocks/lib/unpack_k_bits_bb_impl.cc [https://github.com/gnuradio/gnuradio/blob/master/gr-blocks/lib/unpack_k_bits_bb_impl.cc source]
 
Example - interpolation in gr::blocks::unpack_k_bits_bb: source:gr-blocks/lib/unpack_k_bits_bb_impl.cc [https://github.com/gnuradio/gnuradio/blob/master/gr-blocks/lib/unpack_k_bits_bb_impl.cc source]
  
This is a block which picks apart bytes and produces the individual bits. Again, it is unknown at compile time how many bits per byte there are. However, there's a fixed number of output items per input item, so we can simply divide <code>noutput_items/d_k</code> to get the correct number of input items. It will always be correct because GNU Radio knows the input to output ratio and will make sure that <code>noutput_items</code> is always a multiple of this integer ratio.
+
This is a block which picks apart bytes and produces the individual bits. Again, it is unknown at compile time how many bits per byte there are. However, there's a fixed number of output items per input item, so we can simply divide <code>noutput_items/d_k</code> to get the correct number of input items. It will always be correct, because GNU Radio knows the input to output ratio and will make sure that <code>noutput_items</code> is always an multiple of this integer ratio.
  
 
Example - history in source:gr-digital/lib/diff_phasor_cc_impl.cc
 
Example - history in source:gr-digital/lib/diff_phasor_cc_impl.cc
Line 434: Line 435:
 
Congratulations! If your test fails, your QA code has already paid for itself. Obviously, you want to fix everything before you continue.
 
Congratulations! If your test fails, your QA code has already paid for itself. Obviously, you want to fix everything before you continue.
  
You can use the command <code>ctest -V</code> (instead of <code>make test</code>, again, all in your <code>build/</code> subdirectory) to get all the output from the tests. You can also use <code>ctest -V -R REGEX</code> to only run tests that match REGEX, if you have many tests and want to narrow it down. If you can't figure out the problem from the output of your QA code, put in <code>print</code> statements and show intermediary results.
+
You can use the command <code>ctest -V</code> (instead of <code>make test</code>, again, all in your <code>build/</code> subdirectory) to get all the output from the tests. You can also use <code>ctest -V -R REGEX</code> to only run tests that match REGEX, if you have many tests and want to narrow it down. If you can't figure out the problem from the output of your QA code, put in <code>print</code> statements and show intermediary results. If you need more info on debugging blocks, check out the [[TutorialsDebugging|debugging tutorial]].
  
 
=== Making your blocks available in GRC ===
 
=== Making your blocks available in GRC ===
Line 463: Line 464:
  
 
<pre>
 
<pre>
<block>                                                                                                                                                                                                   
+
   Square2 ff
   <name>Square ff</name>
+
   howto_square2_ff
   <key>howto_square_ff</key>
+
   HOWTO
   <category>[HOWTO]</category>
+
   import howto
   <import>import howto</import>
+
   howto.square2_ff()
   <make>howto.square_ff()</make>
+
    
   <sink>
+
     in
     <name>in</name>
+
     float
     <type>float</type>
+
    
   </sink>
+
    
   <source>
+
     out
     <name>out</name>
+
     float
     <type>float</type>
+
    
   </source>
+
 
</block>
 
 
</pre>
 
</pre>
 
Perhaps you want to change the autogenerated name to something nicer.
 
Perhaps you want to change the autogenerated name to something nicer.
 
<b>Note:</b> The category name <b>must</b> be enclosed in square brackets to work!
 
  
 
If you do a <code>make install</code> from the build directory, you can use the block in GRC. If GRC is already running, you can hit the &quot;Reload Blocks&quot; button in the GRC toolbar; it's a blue circular arrow on the right-hand side. You should now see a &quot;HOWTO&quot; category in the block tree.
 
If you do a <code>make install</code> from the build directory, you can use the block in GRC. If GRC is already running, you can hit the &quot;Reload Blocks&quot; button in the GRC toolbar; it's a blue circular arrow on the right-hand side. You should now see a &quot;HOWTO&quot; category in the block tree.
Line 541: Line 539:
 
=== Sources and sinks ===
 
=== Sources and sinks ===
  
Sources and sinks are derived from <code>gr::sync_block</code>. The only thing different about them is that sources have no inputs and sinks have no outputs. This is reflected in the <code>gr::io_signature::make</code> that are passed to the <code>gr::sync_block</code> constructor. Take a look at [source:gr-blocks/lib/file_source_impl.cc file_source.{h,cc}] and file_sink_impl.{h,cc} for some very straight-forward examples.
+
Sources and sinks are derived from <code>gr::sync_block</code>. The only thing different about them is that sources have no inputs and sinks have no outputs. This is reflected in the <code>gr::io_signature::make</code> that are passed to the <code>gr::sync_block</code> constructor. Take a look at [source:gr-blocks/lib/file_source_impl.cc file_source.{h,cc}] and file_sink_impl.{h,cc} for some very straight-forward examples. See also the tutorial on [[TutorialsWritePythonApplications|writing Python applications]].
  
 
=== Hierarchical blocks ===
 
=== Hierarchical blocks ===
  
<code>gr_modtool</code> supports skeleton code for hierarchical blocks both in Python and C''++.
+
For the concept of hierarchical blocks, see [[TutorialsWritePythonApplications#Hierarchical-blocks|this]]. Of course, they can also be written in C+''. <code>gr_modtool</code> supports skeleton code for hierarchical blocks both in Python and C''+.
  
<pre>~/gr-howto % gr_modtool.py add -t hier -l cpp hierblockcpp_ff
+
<pre>~/gr-howto % gr_modtool.py add -t hier hierblockcpp_ff
 
GNU Radio module name identified: howto
 
GNU Radio module name identified: howto
 +
Language: C++
 
Block/code identifier: hierblockcpp_ff
 
Block/code identifier: hierblockcpp_ff
Language: C++
 
Please specify the copyright holder:
 
 
Enter valid argument list, including default arguments:
 
Enter valid argument list, including default arguments:
 
Add Python QA code? [Y/n]
 
Add Python QA code? [Y/n]
Line 624: Line 621:
 
<pre>gr-howto % gr_modtool add -t sync -l python square3_ff
 
<pre>gr-howto % gr_modtool add -t sync -l python square3_ff
 
GNU Radio module name identified: howto
 
GNU Radio module name identified: howto
 +
Language: Python
 
Block/code identifier: square3_ff
 
Block/code identifier: square3_ff
Language: Python
 
Please specify the copyright holder:
 
 
Enter valid argument list, including default arguments:  
 
Enter valid argument list, including default arguments:  
 
Add Python QA code? [Y/n] n
 
Add Python QA code? [Y/n] n
Line 684: Line 680:
 
Check out the QA code for the Python blocks for some good examples:
 
Check out the QA code for the Python blocks for some good examples:
  
* [https://github.com/gnuradio/gnuradio/blob/master/gr-blocks/python/blocks/qa_block_gateway.py gr-blocks/python/blocks/qa_block_gateway.py]
+
* source:gr-blocks/python/blocks/qa_block_gateway.py
 +
 
 +
== Debugging blocks ==
 +
 
 +
Debugging GNU Radio is available as a [[TutorialsDebugging|separate tutorial]].

Please note that all contributions to GNU Radio are considered to be released under the Creative Commons Attribution-ShareAlike (see GNU Radio:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!

To edit this page, please answer the question that appears below (more info):

Cancel | Editing help (opens in new window)