Files
templates/tools/dsview/decoders/set_uart/pd.py

90 lines
4.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import sigrokdecode as srd
from common.setgui_decoders.set_uart import StreamParser
class Decoder(srd.Decoder):
api_version = 3
id = 'set_uart'
name = 'SET UART'
longname = 'SET v2 / SETGUI v1 / ProtoCAN bridge'
desc = 'SET frames, fields and CRC over UART.'
license = 'gplv2+'
inputs = ['uart']
outputs = ['set']
tags = ['Embedded/industrial']
options = (
{'id': 'protocol', 'desc': 'Protocol', 'default': 'auto',
'values': ('auto', 'v2', 'v1', 'bridge')},
{'id': 'gap_ms', 'desc': 'Reset incomplete frame after gap (ms, 0 disables)', 'default': 100},
)
annotations = (('frame', 'Frame'), ('payload', 'Payload'), ('error', 'Error'))
annotation_rows = (('frames', 'Frames', (0,)), ('payload', 'Payload', (1,)), ('errors', 'Errors', (2,)))
def __init__(self):
self.reset()
# Состояние принадлежит одному запуску декодера. Сброс не должен
# переносить незавершённый кадр или частоту из предыдущей записи.
def reset(self):
self.parsers = {}
self.last = {}
self.samplerate = None
# DSView передаёт время в номерах отсчётов. Частота нужна общему ядру
# для перевода тайм-аутов и измерений в физические единицы.
def metadata(self, key, value):
if key == srd.SRD_CONF_SAMPLERATE:
self.samplerate = value
# Выходы регистрируются в жизненном цикле sigrok, а не в конструкторе.
# Аннотации предназначены для дорожек, структурированные события — для стека.
def start(self):
self.out_ann = self.register(srd.OUTPUT_ANN)
self.out_python = self.register(srd.OUTPUT_PYTHON)
def emit(self, events, direction):
for ss, es, frame, error in events:
prefix = ('RX', 'TX')[direction] + ' '
self.put(ss, es, self.out_ann, [2 if error else 0, [prefix + (error or frame['summary'])]])
if frame:
if frame['protocol'] == 'ProtoCAN bridge' and frame['flags'] & 1 and not frame['flags'] & 10:
# Imported only at decode time: both packages are installed together.
from common.setgui_decoders.set_can import legacy
try:
application = legacy(frame['can_id'], frame['payload'])
frame['application'] = application
self.put(ss, es, self.out_ann, [0, [application['summary']]])
except ValueError as exc:
self.put(ss, es, self.out_ann, [2, [str(exc)]])
frame['direction'] = direction
self.put(ss, es, self.out_python, ['FRAME', frame])
if frame['payload']:
self.put(ss, es, self.out_ann, [1, [prefix + ' '.join('%02X' % b for b in frame['payload'])]])
def decode(self, ss, es, data):
kind, direction, payload = data
if direction not in (0, 1):
return
# RX и TX имеют независимые парсеры: перемежающиеся байты двух направлений
# нельзя объединять в один прикладной кадр.
parser = self.parsers.setdefault(direction, StreamParser(self.options['protocol']))
if kind in ('INVALID STOPBIT', 'INVALID STARTBIT', 'PARITY ERROR', 'BREAK'):
self.emit(parser.flush(), direction)
self.put(ss, es, self.out_ann, [2, [kind]])
return
if kind != 'FRAME':
return
if not payload[1]:
self.emit(parser.flush(), direction)
self.put(ss, es, self.out_ann, [2, ['Invalid UART frame']])
return
gap = float(self.options['gap_ms'])
if self.samplerate and gap > 0 and direction in self.last and ss - self.last[direction] > self.samplerate * gap / 1000:
self.emit(parser.flush(), direction)
self.last[direction] = es
if not 0 <= payload[0] <= 255:
self.emit(parser.flush(), direction)
self.put(ss, es, self.out_ann, [2, ['Configure UART for 8 data bits']])
return
self.emit(parser.feed(payload[0], ss, es), direction)