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

Hi Jack,

I've tried modifying your byte-matcher to stack on top of UART, but I cannot get it working.

I realise this is probably ancient history for you (3 years since you published this), but is there any chance you could explain what changes are necessary?

I am unsure what to change the following section to:

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

Regards,

Simon
NZ

@JackNewman12
Copy link
Author

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 the data 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:

  ptype, mosi, miso = data
  if ptype != "DATA":
            return

with

  ptype, tx, rx= data
  if ptype != "RX":   # or TX if you want that
            return

to get it working for UART.

But thats just a guess.

Regards,
Jack

@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