Trying to write an I2C analyzer and can't tell if a NAK happens

I am trying to make my first I2C analyzer for a chip that I just got back (yeah, I am part of a team designing silicon). I am trying to teach Logic (2.4.10) about our specific packets.

I can get data and see the traffic, but I can’t tell if a byte was NAK’ed. According to this page, a “data” byte SHOULD have an ack boolean that should be false if a NAK was received.

The only problem is that the data field does not seem to exist.

image

My code looks like this…

    elif frame.type == "address":
        if frame.ack == true:
            self.address = frame.data["address"][0]

The frame.type exists, why doesn’t frame.ack exist? for an I2C byte?

I gets better. I have determined that the address of an I2C transaction is only the seven-bit version. The 8th bit which indicates read or write is stripped out, and apparently NOT AVAILABLE!

From the docs:

But I get this error:
image
So both read and ack are missing… :thinking:

I know that I must be doing something stupid. Here is the top of my Hla class:

from saleae.analyzers import HighLevelAnalyzer, AnalyzerFrame, StringSetting, NumberSetting, ChoicesSetting

Am I missing something?

@kevin.harrelson
Add a line to print or display “the frame” that you think you have?
The from saleae.analyzers import looks fine, but I’ll assume the missing spaces between the libs/mods to import is simply a cut n paste deal?
So you may wish to try this:
elif frame.type == “read” :
if frame.data[‘read’] == true

You will get the deal …

1 Like

Thank you for the hint. I have it figured out.

Here is my very simplified and dumbed-down code to demonstrate how to get the data out (note to Saleae employees, put something like this in your docs)…

from saleae.analyzers import HighLevelAnalyzer, AnalyzerFrame, StringSetting, NumberSetting, ChoicesSetting

class Hla(HighLevelAnalyzer):

def __init__(self):
    print("Test running.")

def decode(self, frame: AnalyzerFrame):
    print("\nGot frame type of " + frame.type)

    if frame.type == "address":
        print("Address is " + str(frame.data['address']))
        print("Ack is " + str(frame.data['ack']))
        print("Read is " + str(frame.data['read']))

    if frame.type == "data":
        print("Data is " + str(frame.data['data']))
        print("Ack is " + str(frame.data['ack']))
1 Like

Maybe of interest: for this sort of thing I use dispatch tables

        self.handlerDispatch = {
            "start": self.HandleStart,
            "address": self.HandleAddress,
            "data": self.HandleData,
            "stop": self.HandleStop,
            }
...
        if newFrame.type in self.handlerDispatch:
            # Handle the I2C phase data
            return self.handlerDispatch[newFrame.type](newFrame)

        # We don't handle this I2C phase type!
        return AnalyzerFrame \
            (
            'skipped', newFrame.start_time, newFrame.end_time,
            {'skipped': '!' + newFrame.type}
            )
2 Likes

@kevin.harrelson well done and nice going. It’s a great community supporting the many efforts with these analyzers. Am glad the hint helped.

Cheers

Billy

1 Like

I like this implementation also @P.Jaquiery , excellent chime in my friend

1 Like