Skip to content

Commit

Permalink
feat: Serial-Over-I2C Protocol Analyzer
Browse files Browse the repository at this point in the history
  • Loading branch information
zfields committed Dec 22, 2024
0 parents commit 09ce7db
Show file tree
Hide file tree
Showing 9 changed files with 253 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__pycache__
181 changes: 181 additions & 0 deletions BluesSerialOverI2CAnalyzer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
# Blues Serial-Over-I2C Protocol Analyzer
# For more information and documentation, please go to https://dev.blues.io/guides-and-tutorials/notecard-guides/serial-over-i2c-protocol/

from saleae.analyzers import HighLevelAnalyzer, AnalyzerFrame, NumberSetting

# High level analyzers must subclass the HighLevelAnalyzer class.
class Hla(HighLevelAnalyzer):

# Parameters
notecard_i2c_addr = NumberSetting(min_value=0, max_value=127)

# An optional list of types this analyzer produces, providing a way to customize the way frames are displayed in Logic 2.
result_types = {
'addr': {
'format': '{{data.sender}}'
},
'hdr': {
'format': '{{data.action}}: {{data.length}}'
},
'note': {
'format': '{{data.Note}}'
},
'query': {
'format': 'Query Notecard'
},
'request': {
'format': 'Request: {{data.length}}'
}
}

def __init__(self):

self.data = {
'note': [],
'start_time': None
}
self.hdr1 = None
self.hdr2 = None
self.ignore = False
self.request_start_time = None
self.read = None

if self.notecard_i2c_addr == 0x00:
self.notecard_i2c_addr = 0x17

print(f"=======================================")
print(f"Blues Serial-Over-I2C Protocol Analyzer")
print()
print('Settings:')
print(f"- Notecard I2C Address: 0x{int(self.notecard_i2c_addr):02X}")
print()
print(f"https://dev.blues.io/guides-and-tutorials/notecard-guides/serial-over-i2c-protocol/")

def decode(self, frame: AnalyzerFrame):

if frame.type == 'start':
# /--------------------------------------/
# /------/ START FRAME DATA ITEMS /------/
# /--------------------------------------/
# /--------------------------------------/

self.data = {
'note': [],
'start_time': None
}
self.hdr1 = None
self.hdr2 = None
self.ignore = False
self.request_start_time = None
self.read = None

elif frame.type == 'address':
# /----------------------------------------/
# /------/ ADDRESS FRAME DATA ITEMS /------/
# /----------------------------------------/
# Key: ack, Value: True
# Key: address, Value: b'\x17'
# Key: read, Value: False
# /----------------------------------------/
if (frame.data['address'][0] != self.notecard_i2c_addr):
self.ignore = True
return None

print(f"=======================================")
self.read = frame.data['read']

sender = 'Host MCU' if not frame.data['read'] else 'Notecard'
print(f"Sender: {sender}")
return AnalyzerFrame('addr', frame.start_time, frame.end_time, {
'sender': sender
})

elif frame.type == 'data':
# /-------------------------------------/
# /------/ DATA FRAME DATA ITEMS /------/
# /-------------------------------------/
# Key: ack, Value: True
# Key: data, Value: b'^'
# /-------------------------------------/
if self.ignore:
return None

if self.read: # Notecard Response
# Special Handling for Header Byte 1
if self.hdr1 == None:
self.hdr1 = frame.data['data'][0]

# Handle Notecard Response
print(f"Queued: {self.hdr1}")
return AnalyzerFrame('hdr', frame.start_time, frame.end_time, {
'action': 'Queued',
'length': self.hdr1
})

# Special Handling for Header Byte 2
elif self.hdr2 == None:
self.hdr2 = frame.data['data'][0]

# Handle Notecard Response
print(f"Sending: {self.hdr2}")
return AnalyzerFrame('hdr', frame.start_time, frame.end_time, {
'action': 'Sending',
'length': self.hdr2
})

else: # Host MCU Request
# Special Handling for Header Byte 1
if self.hdr1 == None:
self.hdr1 = frame.data['data'][0]

# Handle Host MCU Request
if self.hdr1 == 0:
self.request_start_time = frame.start_time
return None
else:
print(f"Sending: {self.hdr1}")
return AnalyzerFrame('hdr', frame.start_time, frame.end_time, {
'action': 'Sending',
'length': self.hdr1
})

# Special Handling for Header Byte 2
elif self.hdr2 == None:
self.hdr2 = frame.data['data'][0]

# Handle Host MCU Request
if self.request_start_time != None:
if self.hdr2 == 0:
# Handle Query Request
print(f"Query Notecard")
return AnalyzerFrame('query', self.request_start_time, frame.end_time, None)
else:
# Handle Request Bytes
print(f"Request: {self.hdr2}")
return AnalyzerFrame('request', self.request_start_time, frame.end_time, {
'length': self.hdr2
})

# Handle Note Bytes (Request or Response)
if self.data['start_time'] == None:
self.data['start_time'] = frame.start_time

self.data['note'].append(frame.data['data'])

elif frame.type == 'stop':
# /-------------------------------------/
# /------/ STOP FRAME DATA ITEMS /------/
# /-------------------------------------/
# /-------------------------------------/

if len(self.data['note']) > 0:
note = ''.join([byte.decode('ascii') for byte in self.data['note']]).rstrip('\n')
print(f"Note: {note}")
return AnalyzerFrame('note', self.data['start_time'], frame.end_time, {
'Note': note
})
else:
return None

# Return the data frame itself
return None
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 Blues Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
Serial-over-I2C Protocol Analyzer
=================================

This repository provides an extension to the Saleae Logic application to support on the wire inspection of the Blues Serial-over-I2C protocol.

Getting started
---------------

To install the extension, navigate to the "Extensions" tab in Saleae Logic application.

![Extensions Tab](images/extensions_tab.png)

This extension is known as a High Level Analyzer. This means the analyzer performs further analysis beyond a Low Level Analyzer (i.e. I2C).

In order to use this extension, you must first enable the I2C analyzer. Then you may enable this extension and bind it to the I2C analyzer in the settings pane.

![Settings Pane](images/settings_pane.png)

> _**NOTE:** When enabling the extension, you will be prompted to enter the I2C Address of the Notecard. If you wish to use the Notecard's default address (23), you can leave this value marked zero (0)._
> _**WARNING:** If the I2C address of the Notecard does not match the value supplied to the extension, then all traffic will be ignored._
Using the extension
-------------------

Once you have enabled the extension, you will see a new row in the UI that describes the behavior of the Serial-Over-I2C protocol.

![Analyzer Time Graph](images/analyzer_time_graph.png)

You may also look at the Terminal output of the Analyzers panel to see the dialogue between the Notecard and Host MCU.

![Terminal Output](images/analyzers_pane.png)

Having Trouble?
---------------

If you encounter any problems, you may file an issue on the [GitHub repository](https://github.com/blues/saleae-logic-extension.git), or ask any questions in our [Community Forum](https://discuss.blues.com/).
13 changes: 13 additions & 0 deletions extension.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "Blues Serial-Over-I2C Analyzer",
"apiVersion": "1.0.0",
"author": "Blues",
"version": "1.0.0",
"description": "A High Level Analyzer for the Blues Serial-Over-I2C protocol",
"extensions": {
"Serial-Over-I2C Protocol": {
"type": "HighLevelAnalyzer",
"entryPoint": "BluesSerialOverI2CAnalyzer.Hla"
}
}
}
Binary file added images/analyzer_time_graph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/analyzers_pane.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/extensions_tab.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/settings_pane.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 09ce7db

Please sign in to comment.