Python Block Tags

TODO:
 * tag blocker
 * block to read tag, then change the output
 * make a picture associating tags with samples
 * describe how tag indexing works (both read, write)

This tutorial demonstrates how to create two Embedded Python Blocks for detecting when the input signal crosses the threshold and writing a tag for it and then reading the tag in a separate block and updating the output with the time since the last detection.

The previous tutorial, Python Block Message Passing demonstrates how to send and receive messages using the Embedded Python Block. The next tutorial, Low Pass Filter Example, demonstrates how to use filtering blocks in GNU Radio.

Tags Overview
Tags are a way to convey information alongside digitized RF samples in a time-synchronous fashion. Tags are particularly useful when downstream blocks need to know upon which sample the receiver was tuned to a new frequency, or for including timestamps with specific samples.

Where messages convey information in an asynchronous fashion with no clock-based time guarantee, tags are information which are associated with specific RF samples. Tags ride alongside digitized RF samples in data streams and vectors, including Complex Float 32, Float 32, Byte and all of the other formats.

More information about tags can be found here: Stream Tags

Creating Test Signal
A test signal is needed. Begin by dragging in the blocks for the input signal:
 * GLFSR Source
 * Repeat
 * Multiply Const
 * Add Const
 * Single Pole IIR Filter
 * Throttle
 * QT GUI Time Sink

Change the following parameters:
 * GLFSR Source, Degree: 32
 * Repeat, Interpolation: 128
 * Multiply Const, Constant: 0.5
 * Add Const, Constant: 0.5
 * Single Pole IIR Filter, Alpha: 0.05
 * QT GUI Time Sink
 * Number of Points: 2048
 * Autoscale: Yes
 * Y min: 0
 * samp_rate Variable, Value: 3200

Change all of the blocks to be Float input and output. Connect them all according to the following flowgraph:



Run the flowgraph. A randomized sequence of filtered 0s and 1s is generated:



Threshold Detector: Defining the Block
Drag in a Python Block and double-click it to edit the source code. Recall that Embedded Python Blocks use indentation in multiples of 4 spaces.

Change the example_param variable name and add a new parameter report_period:

def __init__(self, threshold=1.0, report_period=128):

Update the block name:

name='Threshold Detector',

Change the input and output types to Float:

in_sig=[np.float32], out_sig=[np.float32]

Change the variable name from self.example_param:

self.threshold = threshold self.report_period = report_period

Remove the multiplication by self.example_param:

output_items[0][:] = input_items[0]

The code should now look like the following:



Save the code (CTRL + S) and return to GRC. The block will now look like the following:



If the block did not update properly there may be a problem with the Python syntax. Double-click the Embedded Python Block to view any potential syntax errors. The following image gives an example of where the synax errors are located:



Add a Virtual Sink and Virtual Source block to the flowgraph. Change the following block properties:
 * Threshold Detector
 * Threshold: 0.75
 * Report Period: 128
 * Virtual Sink, Stream ID: signal
 * Virtual Source, Stream ID: signal

Connect the blocks according to the flowgraph:



Threshold Detector: Writing Tags
The internals of the Threshold Detector now need to be written. Recall that Embedded Python Blocks use indentation in multiples of 4 spaces.

Import the pmt library:

import pmt

Add two new variables, self.timer and self.readyForTag under the __init__ function:

self.timer = 0 self.readyForTag = True



The work function needs to be modified. Create a for loop to iterate through all of the input samples:

for index in range(len(input_items[0])):

Three sections of code need to be written. The first block writes the amplitude level into a tag named detect once the threshold is met or exceeded. The tag will only be written if the self.readyForTag state variable is True. Once a tag is written the state variable self.readyForTag is set to False.

if (input_items[0][index] >= self.threshold and self.readyForTag == True): # define the key as 'detect' key = pmt.intern('detect') # get the detection value value = pmt.from_float(np.round(float(input_items[0][index]),2)) # tag index to be written writeIndex = self.nitems_written(0) + index # add the tag object (key, value pair) self.add_item_tag(0, writeIndex, key, value ) # tag has been written, set state self.readyForTag = False
 * 1) write the tag

The next block of code is used to run the timer. The timer increases by 1 for each input sample as long as self.readyForTag is False:

if (self.readyForTag == False): self.timer = self.timer + 1
 * 1) increase  the timer by 1

The third block of code controls the state variable self.readyForTag. Once self.timer reaches the maximum value the timer is reset and the state variable self.readyForTag is set to True:

if (self.timer >= self.report_period): # reset timer self.timer = 0 # reset state once timer hits max value self.readyForTag = True
 * 1) set flag to write



Run the flowgraph. Tags will be displayed in the QT GUI Time Sink:



Detection Counter: Defining the Block
A new Embedded Python Block will be created to read the read the tags, count the number of samples since the last tag, and produce that number as an output.

Drag and drop a new Python Block into the GRC workspace. Do not copy and paste the existing python block, it will only create a second copy of Threshold Detector.

Double-click on the Embedded Python Block and edit the code.

Remove the self.example_param parameter: def __init__(self):

Change the name: name='Detection Counter',

Make the input and output ports Floats: in_sig=[np.float32], out_sig=[np.float32]

Remove the line self.example_param = example_param and the multiplication by self.example_param: output_items[0][:] = input_items[0]



Save the code (CTRL + S). Connect the Detection Counter block after the Threshold Detection:



Detection Counter: Reading Tags
The Detection Counter block needs to be modified to read the tags.

The next tutorial, Low Pass Filter Example, demonstrates how to use filtering blocks in GNU Radio.