In Part 1 of this series, we created a new module called my_module for use in a simple cognitive radio application that required a basic state machine.

We continue developing the application in this blog post. Our first step is to go to the folder we created in part 1 and create a block called cognitive. Enter the following commands in the gr-my_module directory:

gr-my_module % gr_modtool add -t general cognitive
GNU Radio module name identified: my_module
Language: C++
Block/code identifier: cognitive
Enter valid argument list, including default arguments:
Add Python QA code?

[Y/n] n
Add C++ QA code? [y/N] n
Adding file cognitive_impl.h’…
Adding file cognitive_impl.cc’…
Adding file ‘cognitive.h’…
Editing swig/my_module_swig.i…
Adding file ‘my_module_cognitive.xml’…
Editing grc/CMakeLists.txt…

Basically we created the source files for our block, without adding any quality-assurance (QA) code. As an intermediate step, we could add some QA code to perform a unitary test of our block but let’s just head straight for the programming. You can always go check the out-of-tree modules online tutorial for more information on how to use this feature (http://gnuradio.org/redmine/projects/gnuradio/wiki/OutOfTreeModules).

gr_modtool provides us with three files that define the block in the lib folder: lib/cognitive_impl.h, lib/cognitive_impl.cc, and include/my_module/cognitive.h. The next step is to modify them to implement our state machine.

First, let’s declare a variable named `state`, which will contain the actual state of our system, and a counter. To do so, edit line 32 in lib/cognitive_impl.h and add those variables as private items of this class:

variables table

The second step is to modify lib/cognitive_impl.cc to do our bidding. gr_modtool hints at where we have to change code by adding <++> symbols. First, at line 45, modify the code to get the following:

coding GNU radio

In the constructor, we initialized state to 0 and cnt to 0, which is the initial state of our state machine. The set_max_noutput_items function is derived from the gr::block class and tells the block that we want one output sample per work function call. The set_max_output_buffer sets the maximum size of the output buffers of all the output ports (you can find the gr::block class reference at http://gnuradio.org/doc/doxygen-3.7/classgr_1_1block.html). An interesting section of the above code is the definition of the input and output signatures. In our case, we have one input and one output port that allows the float data type.

Another interesting section of the code which needs to be changed depending on the application is the following:

coding GNU radio

The forecast function tells how many input items are required to produce noutput_items. In our case, they’re the same. The index 0 indicates that this is for the first port. For good examples of the forecast function, look at the gr::block, gr::sync_block, gr::sync_decimator and the gr::sync_interpolator class source code.

Finally, there’s the general_work function, which is the method that does the actual signal processing:
coding GNU radio

This is the code that implements the state machine. Basically, for each input item, the general_work function is called. It outputs one item, the frequency at which the transmitter and the receiver needs to operate.

In the part 3 of this blog series, we will wrap all this up by compiling the code and creating the GNU Radio Companion block, which we can use as a state machine inside an existing model.