Files
templates/python/logic_analyzer/decoders/tms_uart.py
Andrey a5e46d4627 Расширить обмен по шинам, CAN-адаптеры и обработку графиков
Добавить очереди операций PBUS/SBUS, общую консоль, настройки Candle и SLCAN, декодеры DSView и обработку плотных графиков. Обновить протокол Бальзам и проверки общих компонентов.
2026-10-17 14:36:14 +03:00

30 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.
from collections import deque # Кольцевой буфер хранит только координаты одного максимального кадра.
from . import template_protocols # Подключает поставляемые пакеты templates в отдельном Python-процессе DSView.
from set_devices import tms_terminal as tms # Раскладки, CRC и потоковый поиск границ используются из действующего парсера терминала.
LAYOUTS = tuple(tms.PRESETS) + ('custom',) # Имена готовых раскладок совпадают с настройками терминала SETGUI.
class TmsStreamParser: # Адаптирует общий байтовый парсер к событиям с координатами sigrok.
def __init__(self, preset=tms.DEFAULT_PRESET, digit_bytes=38, analog_count=34, crc='MODBUS'): # Значения 38/34 соответствуют штатной раскладке message2.h.
selected = tms.PRESETS[preset] if preset != 'custom' else tms.Layout(digit_bytes, analog_count, crc) # Индивидуальная раскладка проверяется существующей моделью Layout.
self.layout = tms.Layout(selected.digit_bytes, selected.analog_count, crc) # CRC выбирается отдельно, поскольку в источниках есть MODBUS и CCITT-FALSE.
self.parser = tms.TmsParser(self.layout) # Поиск границ и подтверждение CRC выполняет общий парсер.
self.positions = deque(maxlen=self.layout.frame_size) # Число хранимых координат ограничено длиной одного кадра в байтах.
def flush(self): # Пауза либо ошибка UART запрещает объединять части разных посылок.
self.parser.reset() # Общий парсер отбрасывает недособранные байты и состояние синхронизации.
self.positions.clear() # Координаты старого хвоста также исключаются из следующего события.
return [] # Формат без сигнатуры не позволяет отличить неполный кадр от произвольного шума.
def feed(self, value, ss, es): # Один UART-байт приходит вместе с точными границами в отсчётах.
self.positions.append((ss, es)) # Последние frame_size позиций соответствуют окну поиска общего парсера.
events = [] # За один байт может завершиться один кадр фиксированной длины.
for record in self.parser.feed(bytes([value])): # Только CRC-подтверждённые записи выдаются прикладному слою.
fields = [('Команда', record.command), ('Адрес', str(record.address)), ('CRC', '%04X' % record.crc_frame)] # Служебные поля берутся из готовой модели TmsRecord.
fields += [(tms.analog_name(index), str(word)) for index, word in enumerate(record.analogs)] # Имена аналогов и знаковые int16 совпадают с терминалом SETGUI.
fields += [('Дискреты', ', '.join(record.set_bits()) or 'нет активных битов')] # Активные биты выдаются с исходной нумерацией байтов и битов.
result = dict(protocol='TMS UART', summary=record.summary, payload=record.raw[2:-3], raw=record.raw, fields=fields, analogs=record.analogs, digits=record.digits) # CRC и завершающий байт исключены из полезной нагрузки по контракту TMS_TO_TERMINAL.
events.append((self.positions[0][0], es, result, None)) # Начало подтверждённого окна сохраняется даже после пропущенного шума.
self.positions.clear() # Координаты завершённого кадра не удерживаются до следующей посылки.
return events # События имеют тот же контракт, что парсер SET UART.