Skip to content

Instantly share code, notes, and snippets.

@JackNewman12
Last active February 4, 2023 18:52
Show Gist options
  • Save JackNewman12/0f3a0dbe556ee8ea8bcaffc530d20885 to your computer and use it in GitHub Desktop.
Save JackNewman12/0f3a0dbe556ee8ea8bcaffc530d20885 to your computer and use it in GitHub Desktop.
A quick pulseview decoder for matching a series of bytes
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]])
@stretchkerr
Copy link

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