High-Level Analyzer (HLA) Extensions
Learn how to modify your new High Level Analyzer
This guide assumes that you have familiarity with the Python programming language. It is what will be used to customize our HLA.
Overview
This guide assumes you have generated a new High-Level Analyzer. In this guide you will learn about:
The files included in the HLA template extension and what they are.
The different parts of
HighLevelAnalyzer.py
.How to process input analyzer frames and output new analyzer frames.
High Level Analyzer Files
In your new High Level Analyzer (HLA) extension folder you will find 3 files:
README.md
Documentation for your extension, shown within Logic 2 when you select an extension, and what users will see if you put your extension on the Marketplace.
extension.json
Every extension must have this file in its root directory.
Contains metadata about the extension, and the HLAs and Measurement scripts that are included with the extension.
See Extension File Format for more information.
HighLevelAnalyzer.py
Python source code for your HLA.
For the purposes of this document, we will be focusing on HighLevelAnalyzer.py
HighLevelAnalyzer.py Breakdown
Let's break down the contents of HighLevelAnalyzer.py
.
Imports
Declaration and Settings
All HLAs must subclass HighLevelAnalyzer, and additionally output AnalyzerFrames. The Setting
classes are included so we can specify settings options within the Logic 2 UI.
This declares our new HLA class, which extends from HighLevelAnalyzer, and 3 settings options that will be shown within the Logic 2 UI. Note: if the name of the class MyHla() is used it must be referenced in the accompanying json file. Note that Hla() is the default value.
Output formats
This specifies how we want output AnalyzerFrames to be displayed within the Logic 2 UI. We will come back to this later.
Initialization
This is called when your HLA is first created, before processing begins. The values for the settings options declared at the top of this class will be available as instance variables here. In this case, the settings values will be printed out and visible within the Logic 2 terminal view.
Data Processing
This is where the bulk of the work will be done. This function is called every time the input to this HLA produces a new frame. It is also where we can return and output new frames, to be displayed within the Logic 2 UI. In this case we are outputting a new frame of type 'mytype'
, which spans the same period of time as the input frame, and has 1 data value 'input_type'
that contains the value of the type
of the input frame.
HLA Debugging Tips
Although we don't have the ability to attach debuggers to Python extensions at the moment, here are some suggestions to help debug your HLA.
Use
print()
statements to print debug messages to our in-app terminal. More information on our in-app terminal can be found below.
Use the Wall Clock Format and Timing Markers to locate the exact frame listed in your error message.
Use the reload source button in the app to quickly re-run your HLA after editing your source code.
Example - Writing an HLA to search for a value
Now that we've gone over the different parts of an HLA, we will be updating our example HLA to search for a value from an Async Serial analyzer.
Example Data
In the Extensions Quickstart you should have downloaded and opened a capture of i2c data. For this quickstart we will be using a capture of Async Serial data that repeats the message "Hello Saleae".
Remove Unneeded Code
To start, let's remove most of the code from the example HLA, and replace the settings with a single search_for
setting, which we will be using later.
If you open the example data from above and add this analyzer, selecting the Async Serial analyzer as input, you should see the following when zooming in:
Our HLA (top) is outputting a frame for every frame from the input analyzer (bottom), and displaying their types.
Understanding the Input Frames
The goal is to search for a message within the input analyzer, but first we need to understand what frames the input analyzer (Async Serial in this case) produces so we can know what frames will be passed into the decode(frame:
AnalyzerFrame
)
function.
The frame formats are documented under Analyzer Frame Types, where we can find Async Serial.
The Async Serial output is simple - it only outputs one frame type, data
, with 3 fields: data
, error
, and address
. The serial data we are looking at will not be configured to produce frames with the address
field, so we can ignore that.
To recap, the decode(frame)
function in our HLA will be called once for each frame from the Async Serial analyzer, where:
frame.type
will always bedata
frame.data['data']
will be a `bytes` object with the data for that frameframe.data['error']
will be set if there was an error
Updating `decode()` to search for "H" or "l"
Now that we we understand the input data, let's update our HLA to search for the character "H"
.
After applying the changes, you can open the menu for your HLA and select Reload Source Files
to reload your HLA:
You should now only see HLA frames where the Async Serial frame is an H
or l
:
Replace the hardcoded search with a setting
Now that we can search for characters, it would be much more flexible to allow the user to choose the characters to search for - this is where our search_for
setting that we added earlier comes in.
Instead of using the hardcoded 'Hl'
, let's replace that with the value of search_for
:
Now if you can specify the characters to search for in your HLA settings:
Updating the display string
To update the display string shown in the analyzer bubbles, the format
string in result_types
variable will need to be updated. 'mytype'
will also be updated to 'match'
to better represent that the frame represents a matched character.
And in decode()
: we need to update the data in AnalyzerFrame
to include 'char'
, and update the frame 'type'
to 'match'
.
After reloading your HLA you should see the new display strings:
Using time
AnalyzerFrame
s include a start_time
and end_time
. These get passed as the second and third parameter of AnalyzerFrame
, and can be used to control the time span of a frame. Let's use it to fill in the gaps between the matching frames.
Let's add a __init__()
to initialize the 2 time variables we will use to track the span of time that doesn't have a match:
And update decode()
to track these variables:
And lastly, add an entry in result_types
for our new AnalyzerFrame
type 'nomatch'
:
The final output after reloading:
What's Next?
Find out about other analyzers and the AnalyzerFrames they output in the Analyzer Frame Types documentation.
Use the API Documentation as a reference.
Browse the Saleae Marketplace in Logic 2 for more ideas and examples of extensions you can create.
Publish your extension to the Saleae Marketplace!
Last updated