Skip to content

Commit 7e9014d

Browse files
committed
Decoding the last byte of the payload with digital channels, failsafe and frame lost bits.
1 parent 6537e1d commit 7e9014d

File tree

3 files changed

+50
-20
lines changed

3 files changed

+50
-20
lines changed

HighLevelAnalyzer.py

+48-14
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ class Hla(HighLevelAnalyzer):
1717
'sbus_start_sync_byte': {
1818
'format': 'Start sync byte'
1919
},
20-
'sbus_payload': {
20+
'sbus_analog_payload': {
21+
'format': 'PAYLOAD: {{data.payload}}'
22+
},
23+
'sbus_digital_payload': {
2124
'format': 'PAYLOAD: {{data.payload}}'
2225
},
2326
'sbus_end_sync_byte': {
@@ -29,8 +32,9 @@ class Hla(HighLevelAnalyzer):
2932
class dec_fsm_e(enum.Enum):
3033
idle = 1
3134
#start_sync_byte = 2 # No being used - If sync byte is detected the state changes from idle -> payload
32-
payload = 3
33-
stop_sync_byte = 4
35+
analog_payload = 3
36+
digital_payload = 4
37+
stop_sync_byte = 5
3438

3539
# Protocol defines
3640
SBUS_START_SYNC_BYTE = b'\x0f' # 0x0F
@@ -63,25 +67,25 @@ def decode(self, frame: AnalyzerFrame):
6367
if self.sbus_frame_start == None and frame.data['data'] == self.SBUS_START_SYNC_BYTE and self.dec_fsm == self.dec_fsm_e.idle:
6468
print('Start sync byte detected.')
6569
self.sbus_frame_start = frame.start_time
66-
self.dec_fsm = self.dec_fsm_e.payload
70+
self.dec_fsm = self.dec_fsm_e.analog_payload
6771
self.sbus_frame_current_index += 1
6872
return AnalyzerFrame('START', frame.start_time, frame.end_time, {})
6973

70-
# Payload
71-
if self.dec_fsm == self.dec_fsm_e.payload:
74+
# Analog payload
75+
if self.dec_fsm == self.dec_fsm_e.analog_payload:
7276
payload = int.from_bytes(frame.data['data'], byteorder='big')
7377
if self.sbus_frame_current_index == 1: # First payload byte
7478
self.sbus_payload_start = frame.start_time
7579
self.sbus_payload.append(payload)
7680
self.sbus_frame_current_index += 1
7781
#print('Payload start ({}): {:2x}'.format(self.sbus_frame_current_index, payload))
78-
elif self.sbus_frame_current_index < 23: # ... still collecting payload bytes ...
82+
elif self.sbus_frame_current_index < 22: # ... still collecting payload bytes ...
7983
self.sbus_payload.append(payload)
8084
self.sbus_frame_current_index += 1
8185
#print('Adding payload ({}): {:2x}'.format(self.sbus_frame_current_index, payload))
82-
elif self.sbus_frame_current_index == 23: # Last payload byte received
86+
elif self.sbus_frame_current_index == 22: # Last analog payload byte received
8387
analyzerframe = None
84-
self.dec_fsm = self.dec_fsm_e.stop_sync_byte
88+
self.dec_fsm = self.dec_fsm_e.digital_payload
8589
self.sbus_payload_end = frame.end_time
8690
self.sbus_payload.append(payload)
8791
#print('Payload complete ({}): {:2x}'.format(self.sbus_frame_current_index, payload))
@@ -99,15 +103,45 @@ def decode(self, frame: AnalyzerFrame):
99103
channels.append(value)
100104
channels.append(value_ms)
101105
print(channels)
102-
payload_str = ('Ch1: {} ({} ms), Ch2: {} ({} ms), Ch3: {} ({} ms), Ch4: {} ({} ms), ' + \
103-
'Ch5: {} ({} ms), Ch6: {} ({} ms), Ch7: {} ({} ms), Ch8: {} ({} ms), ' + \
104-
'Ch9: {} ({} ms), Ch10: {} ({} ms), Ch11: {} ({} ms), Ch12: {} ({} ms), ' + \
105-
'Ch13: {} ({} ms), Ch14: {} ({} ms), Ch15: {} ({} ms), Ch16: {} ({} ms)').format(*channels)
106+
payload_str = ('Ch1:{} ({}µs), Ch2:{} ({}µs), Ch3:{} ({}µs), Ch4:{} ({}µs), ' + \
107+
'Ch5:{} ({}µs), Ch6:{} ({}µs), Ch7:{} ({}µs), Ch8:{} ({}µs), ' + \
108+
'Ch9:{} ({}µs), Ch10:{} ({}µs), Ch11:{} ({}µs), Ch12:{} ({}µs), ' + \
109+
'Ch13:{} ({}µs), Ch14:{} ({}µs), Ch15:{} ({}µs), Ch16:{} ({}µs)').format(*channels)
106110
print(payload_str)
107-
analyzerframe = AnalyzerFrame('sbus_payload', self.sbus_payload_start, frame.end_time, {
111+
analyzerframe = AnalyzerFrame('sbus_analog_payload', self.sbus_payload_start, frame.end_time, {
108112
'payload': payload_str})
109113
return analyzerframe
110114

115+
# Digital payload
116+
if self.dec_fsm == self.dec_fsm_e.digital_payload:
117+
self.dec_fsm = self.dec_fsm_e.stop_sync_byte
118+
payload = int.from_bytes(frame.data['data'], byteorder='big')
119+
print(payload)
120+
if payload == 0:
121+
return AnalyzerFrame('', frame.start_time, frame.end_time, {})
122+
else:
123+
payload_str = ''
124+
sep = False
125+
if (payload & 0x8) != 0:
126+
payload_str += "Failsafe"
127+
sep = True
128+
if (payload & 0x4) != 0:
129+
if sep:
130+
payload_str += ", "
131+
payload_str += "Frame lost"
132+
sep = True
133+
if (payload & 0x2) != 0:
134+
if sep:
135+
payload_str += ", "
136+
payload_str += "Ch18 on"
137+
sep = True
138+
if (payload & 0x1) != 0:
139+
if sep:
140+
payload_str += ", "
141+
payload_str += "Ch17 on"
142+
print(payload_str)
143+
return AnalyzerFrame('sbus_digital_payload', frame.start_time, frame.end_time, {'payload': payload_str})
144+
111145
# Stop sync byte
112146
if self.dec_fsm == self.dec_fsm_e.stop_sync_byte and frame.data['data'] == self.SBUS_STOP_SYNC_BYTE:
113147
print('Stop sync byte detected.')

README.md

+1-5
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,9 @@
33
Saleae Logic 2 High Level Analyzer : Futaba SBUS protocol analyzer
44

55
## Getting started
6-
1. Install the CRSF analyzer in Logic 2 from the extensions menu.
6+
1. Install the SBUS analyzer in Logic 2 from the extensions menu.
77
2. Create a new Async Serial analyzer, set the baud rate to 100000 bauds, 8 bits, 2 stop bits, even parity, LSB, inverted.
88
3. Create a new Futaba SBUS analyzer, configure it and pick the previously created Async Serial analyzer.
99

1010
![](images/complete_frame.jpg)
1111
![](images/detailed_frame.jpg)
12-
13-
## ToDo
14-
15-
Decode the 2 digital channels (channels 17 & 18), frame lost and failsafe flags

extension.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "Futaba SBUS",
33
"apiVersion": "1.0.0",
44
"author": "Pascal HEUDE",
5-
"version": "0.0.1",
5+
"version": "0.0.2",
66
"description": "Decode the Futaba SBUS protocol",
77
"extensions": {
88
"Futaba SBUS": {

0 commit comments

Comments
 (0)