Async serial custom analyzer

First off, I am a NOOB regarding Python. But I don’t think that what I want to do should be too hard and I am an intermediate programmer in general. That being said here is what I am working on…

I have a small PIC processor that spits out debug bytes real time at 500kbaud. The bytes are location markers in the code on the PIC, and sometimes have a 1 or 2 byte payload, but usually not. I’ve used this for debugging for quite a while so I can debug while the chip is running real time. I have always used the Logic to watch and translate the serial line to decimal, then I would manually go to the table that translates the numbers into human readable labels to see what was going on.

I would like to write an extension to do the translation for me instead. I went through the Async example. I want to bring in decimal data instead of ASCII. Then I figure I can use a tuple table of my labels to print out what they mean. Once I get that down I can decide what to do with the bytes that have payloads.

So, I may have several questions, but my first is: In the example it was bringing in data with:
ch = frame.data[‘data’].decode(‘ascii’)

What is the frame.data when it comes in? If the analyzer is set to decimal can I just use the frame.data directly? Like:
debug_code = frame.data[‘data’]

Then I could output:

#Shortened List for the example
DebugMessageList = ( # This is actually a tuple, not a list, but who knows what a tuple is?
“UnUsed”,
“Initialize_Variables”, # 1
“Version_Load”, # 2
“Begin_BT_Setup”) # 3

result_types = {
    'format':'{{DebugMessageList[debug_code]}}'

I know this is dumbed down, but is this headed the right direction? I am trying not to write a book here!

Hi @awolfe!

But I don’t think that what I want to do should be too hard and I am an intermediate programmer in general.

Agreed! Any feedback you have about pain points is helpful. The goal is to make the process smooth and easy, but admittedly we aren’t there yet.

What is the frame.data when it comes in? If the analyzer is set to decimal can I just use the frame.data directly?

The documentation at https://support.saleae.com/extensions/analyzer-frame-types/serial-analyzer should give some insight into the actual values in frame.data. frame.data is a dictionary whose contents depend on the analyzer being used. In this case, the serial analyzer has 3 fields: data, error, and address.

data will always be the Python type bytes. The type of this field is not affected by what you set in the application, but I can see where that is confusing (we’ll work on making this more clear).

In your case, it sounds like the values are always a single byte. For that, you can do debug_code = frame.data['data'][0] to get the first byte in the data. If you have multiple bytes that you want to convert to an int, you can use int.from_bytes(frame.data['data'], 'big') (or ‘little’, depending on the endianness)

For the format string, you can only access values in the AnalyzerFrame that you return from your decode function. The simplest solution here is to put the debug string in the frame itself:

        return AnalyzerFrame('debug', frame.start_time, frame.end_time, {
            'debug_msg': DebugMessageList[debug_code]
        })

Technically you don’t need to provide a format string - the default is to list out the values in the frame - but if you do want a custom format, you can do this:

result_types = {
    'debug':'{{data.debug_msg}}'

Hope that helps! Please let me know if you have any more questions.

Ryan

Thanks for the info! That was helpful…
image

I now have some output… I’ll see if I have any questions in the next step.

2 Likes

@huffman I am continuing to refine this. I have it showing the debug message directly now by just using the following return:

return AnalyzerFrame(DebugMessageList[debug_code], frame.start_time, frame.end_time, {})

As I was testing it I was noticing a couple things. The data shows up in the data table if I select it to, but sometimes it misses data for some reason. Here is an example:

Leave_Shutoff should be in the table directly above Start_Motor_Forward, but it isn’t for some reason.

The other thing is that even though there is select box for it to be sent to the terminal window, that doesn’t seem to be working. Is that expected?

In general it is working great and I am now working on adding the instances where there are payload bytes along with particular debug messages.

Thanks for the cool tools!

I have it showing the debug message directly now by just using the following return:

Great idea! I didn’t think about using the debug msg as the frame type.

Leave_Shutoff should be in the table directly above Start_Motor_Forward, but it isn’t for some reason.

That’s a bug, I’ve reported it internally. Thanks!

The other thing is that even though there is select box for it to be sent to the terminal window, that doesn’t seem to be working. Is that expected?

Yes, currently terminal support for HLAs is limited. Any print(...) statements in your python script will show up in the terminal, though. You could do that in your decode(...) function.

In general it is working great and I am now working on adding the instances where there are payload bytes along with particular debug messages.

Awesome! Let us know if you have more questions.

Ryan

@awolfe Thanks for reporting that bug with the Data Table. We’re looking into it right now but could use your help. Would you mind sending over the following?

  • Your HLA files
  • A capture file (.sal format) that shows the Data Table issue

If they are files you don’t want to make public here, you can also send it over using the link below. Your files and message would go to me directly through a support ticket.

I am just heading out for the Christmas holiday. I will be back in on the 28th. I saved a copy of the changes I have made since earlier (they were a ways from working yet), and undid back to where it was when I posted last…

In the zip is the extension:
Signature Board Debug.zip (4.8 KB)

Here is the capture file:
Async Serial Data.sal (58.4 KB)

I hope that helps.
Hope you all have a Merry Christmas!

Thanks for sending those over! We’ll be taking a look at this bug in the meantime. Hope you have a Merry Christmas as well!

Hi Ryan,

I have worked on this some more today… I am stuck, and it is probably a simple newbie issue. I want to keep a byte count, for when a debug message has a payload. I need to initialize the byte count before I start incrementing it. However, the compiler is complaining about where I am initializing it. I have tried moving it around some, but I don’t want it to initialize every time I receive a byte. I want it to initialize when the analyzer begins to analyze all the data in the stream. I included the entire module so maybe you could get a better idea of what I am trying to accomplish.

When you get a chance, please check out the attached code. Here is the compile error. image

Signature Board Debug.zip (5.4 KB)

Thanks for your help!

Hi @awolfe,

In Python you will need to use self.byte_count to access class and instance variables, like this: self.byte_count = self.byte_count + 1.

I’d also recommend checking out https://docs.python.org/3/tutorial/classes.html#class-and-instance-variables for information on class and instance variables. You are using a class variable, which is generally fine for HighLevelAnalyzers, but only because Logic2 runs each analyzer in a separate environment, so they aren’t sharing the same byte_count value. But, if you end up creating other classes, you’ll want to know the difference.

Hope that helps! And excited to see that you are making progress!

Ryan

Hi @huffman,

I’ve got it mostly working for what I wanted for now, but I just got this error on a new capture: image

I assume it is because there is a power on event in the data stream and it is not handling it correctly. Do I need to handle that somewhere in my code and how? I have again attached the latest code and the capture that caused the error.
Signature Board Debug.zip (5.9 KB) Async Serial Data 2.sal (47.4 KB)

Thanks for all your help!

From a quick look, it seems like you returned a Set as data (line 157). I don’t think this type is supported

You are right. Thank you!

1 Like