Last active
February 4, 2023 18:52
-
-
Save JackNewman12/0f3a0dbe556ee8ea8bcaffc530d20885 to your computer and use it in GitHub Desktop.
A quick pulseview decoder for matching a series of bytes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sigrokdecode as srd | |
import collections | |
# Matches to find. | |
# A list of tuples that contain (ByteToMatch, Name) | |
Matches = [ | |
([0x20, 0x20], "Match One!"), | |
([0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], "Match Two!"), | |
([0xFF, 0xAA, 0xCC, 0x55], "Match Three!"), | |
] | |
# Standard Decoder | |
class Decoder(srd.Decoder): | |
# Decoder stuff that needs to exist for pulseview to be happy | |
api_version = 3 | |
id = "ByteMatch" | |
name = "Byte Matcher" | |
longname = "A Byte Matcher" | |
desc = "This decoder searches for arbitrary set of bytes" | |
license = "MIT" | |
inputs = ["spi"] # CHANGE THE DECODE YOU WANT TO STACK ONTOP OF | |
outputs = [] | |
tags = ["IC", "Memory"] | |
annotations = (("Matches", "Matches"),) | |
annotation_rows = (("Matches", "Matches", (0,)),) | |
options = () | |
def __init__(self): | |
# Circular buffers for keeping track of the last few bytes | |
# Make the buffers the size of the largest match | |
MaxLength = max([len(bytes) for bytes, name in Matches]) | |
# The last few bytes | |
self.LastBytes = collections.deque(maxlen=MaxLength) | |
# The last few start-samples | |
self.LastSamples = collections.deque(maxlen=MaxLength) | |
def reset(self): | |
# Reset the circular buffers | |
self.LastBytes.clear() | |
self.LastSamples.clear() | |
def start(self): | |
# Standard Pulseview Stuff | |
self.out_ann = self.register(srd.OUTPUT_ANN) | |
def decode(self, startSample, endSample, data): | |
# Grab the data from your lower level decoder. | |
ptype, mosi, miso = data | |
# In this case I only care about full bytes from the decoder (DATA). | |
# Do not care about indiviual bits (BITS) | |
if ptype != "DATA": | |
return | |
# Keep track of the byte we just saw and the sample it started at (for annotations) | |
self.LastBytes.append(miso) | |
self.LastSamples.append(startSample) | |
# Just search for a match in the array | |
for match in Matches: | |
data, annotation = match | |
# If the last few bytes in the buffers match our target array | |
if data == list(self.LastBytes)[-1 * len(data) :]: | |
startSample = ( | |
# Cover edge case where we match on the very first byte in the data | |
self.LastSamples[-1 * len(data)] | |
if len(self.LastSamples) >= len(data) | |
else 0 | |
) | |
# Print the annotation at orignal start sample and the current sample | |
self.put(startSample, endSample, self.out_ann, [0, [annotation]]) |
Thanks for your quick reply Jack. I'll keep trying.
Simon
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi Simon,
Wow this is ancient history for sure and forgot I even posted this script.
So in the sigrokdecoder (at least in the 3+ year old version I was using) you would get
decode()
called for various inputs.In this case you would get 8x callbacks for each item in the
bits
field (the blue line in the decoder), and you would then get 1x callback with thedata
field (in this case I would have told sigrock that my SPI bus had 8 bit transactions).I only cared about matching the hexidecimal string. i.e. a buggy message from a device or the start of a custom header. So there was no use processing the
BITS
field.No idea what sigrock looks like these days but my best guess is you would need to replace:
with
to get it working for UART.
But thats just a guess.
Regards,
Jack