Creating Python OOT with gr-modtool: Difference between revisions
Mattcarrick (talk | contribs) |
Mattcarrick (talk | contribs) |
||
Line 179: | Line 179: | ||
# and should usually not be changed. | # and should usually not be changed. | ||
file_format: 1</syntaxhighlight> | file_format: 1</syntaxhighlight> | ||
The YAML file needs to be updated to match the ''addSubSelector.py'' file that was just modified. |
Revision as of 17:56, 8 March 2022
Beginner Tutorials
Introducing GNU Radio Flowgraph Fundamentals
Creating and Modifying Python Blocks DSP Blocks
SDR Hardware |
TODO: fill out some introductory info TODO: add this tutorial to the nav bar
This tutorial was written using GNU Radio v3.10.1.1.
Creating an OOT Module
Open a terminal and navigate to an appropriate directory for writing software, such as the home directory:
$ cd $HOME
GNU Radio comes packaged with gr_modtool, software used to create out-of-tree (OOT) modules. An OOT module can be thought of as a collection of custom GNU Radio blocks. Create an OOT module named customModule using gr_modtool:
$ gr_modtool newmod customModule
The directory gr-customModule is created which contains all of the skeleton code for an OOT module, however it does not yet have any blocks. Move into the gr-customModule directory:
$ cd gr-customModule
List all of the files and directories within the OOT module:
$ ls
The directory listing will be as follows:
apps/ cmake/ CMakeLists.txt docs/ examples/ grc/ include/ lib/ MANIFEST.md python/
Creating an OOT Block
Now a block needs to be created within gr-customModule. The custom block will either add or subtract based on an input parameter, so the block is named addSubSelect:
$ gr_modtool add addSubSelect
The command will start a questionnaire about how to the block is to be defined: what block type, language and parameters:
GNU Radio module name identified: customModule ('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')
Select the sync block, which produces an output for every input:
Enter block type: sync
Enter python as the language:
Language (python/cpp): python Language: Python Block/code identifier: addSubSelect
Enter the name or organization of the copyright holder:
Please specify the copyright holder: YourName
Now enter the argument list:
Enter valid argument list, including default arguments:
Enter the argument list as if writing the Python code directly. In this case the selector will determine whether or not the block performs addition or subtraction. A default argument of True is given:
selector=True
Determine whether or not you want the Python quality assurance (QA) code:
Add Python QA code? [Y/n] n
New files will be generated:
Adding file 'python/customModule/addSubSelect.py'... Adding file 'grc/customModule_addSubSelect.block.yml'... Editing grc/CMakeLists.txt...
Two new files were created, addSubSelect.py which defines the operation of the block and customModule_addSubSelect.block.yml which defines the interface of the block for GNU Radio Companion (GRC). The CMakeLists.txt file was modified so the two files will be installed when the module is compiled and installed.
Modifying Python File
Open the python file with a text editor:
gedit python/customModule/addSubSelect.py &
The following code will be listed:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright 2022 YourName.
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
import numpy
from gnuradio import gr
class addSubSelect(gr.sync_block):
"""
docstring for block addSubSelect
"""
def __init__(self, selector=True):
gr.sync_block.__init__(self,
name="addSubSelect",
in_sig=[<+numpy.float32+>, ],
out_sig=[<+numpy.float32+>, ])
def work(self, input_items, output_items):
in0 = input_items[0]
out = output_items[0]
# <+signal processing here+>
out[:] = in0
return len(output_items[0])
Both the __init__() function and work() function need to be modified. The __init__() function is modified to define the input type. The addSubSelect block will accept two complex inputs and produce a complex output, therefore the in_sig and out_sig parameters need to be changed. The selector parameter also needs to be saved as a member variable:
def __init__(self, selector=True):
gr.sync_block.__init__(self,
name="addSubSelect",
in_sig=[np.complex,np.complex],
out_sig=[np.complex])
self.selector = selector
The work() function is modified to either add or subtract the two inputs based on the selector parameter:
def work(self, input_items, output_items):
in0 = input_items[0]
in1 = input_items[1]
if (self.selector):
output_items[0] = in0 + in1
else:
output_items[0] = in0 - in1
return len(output_items[0])
Modifying YAML File
Open the .yml file with a text editor:
gedit grc/customModule_addSubSelect.block.yml &
The following YAML is displayed:
id: customModule_addSubSelect
label: addSubSelect
category: '[customModule]'
templates:
imports: from gnuradio import customModule
make: customModule.addSubSelect(${selector})
# Make one 'parameters' list entry for every parameter you want settable from the GUI.
# Keys include:
# * id (makes the value accessible as keyname, e.g. in the make entry)
# * label (label shown in the GUI)
# * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)
# * default
parameters:
- id: parametername_replace_me
label: FIX ME:
dtype: string
default: You need to fill in your grc/customModule_addSubSelect.block.yaml
#- id: ...
# label: ...
# dtype: ...
# Make one 'inputs' list entry per input and one 'outputs' list entry per output.
# Keys include:
# * label (an identifier for the GUI)
# * domain (optional - stream or message. Default is stream)
# * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)
# * vlen (optional - data stream vector length. Default is 1)
# * optional (optional - set to 1 for optional inputs. Default is 0)
inputs:
#- label: ...
# domain: ...
# dtype: ...
# vlen: ...
# optional: ...
outputs:
#- label: ...
# domain: ...
# dtype: ...
# vlen: ...
# optional: ...
# 'file_format' specifies the version of the GRC yml format used in the file
# and should usually not be changed.
file_format: 1
The YAML file needs to be updated to match the addSubSelector.py file that was just modified.