Files
templates/python/set_devices/deif_emulator.py
T
Andrey 41e24629ce Расширить DEIF, загрузку CAN и общую обработку сигналов
Добавить общее ядро DEIF, эмуляцию приборов и переносимые панели Python/Qt.
Расширить загрузчики F2812 и F28335, обновление Flash и профиль STM Invertor.
Добавить альтернативный МНК Eigen, модели неисправностей и диагностику сигналов.
Обновить справочники устройств, проекты CCS и регрессионные проверки.
2026-10-24 15:40:51 +03:00

37 lines
4.7 KiB
Python

"""Регистровый контракт аппаратного эмулятора DEIF из set_emu_deif.h.""" # Один контракт используется всеми MCU и настольными клиентами.
from dataclasses import dataclass # Неизменяемый снимок отделяет подтверждённое состояние платы от редактируемой формы.
DEIF_BASE = 0x1600 # Начало окна управления DEIF в set_emu_server.c, адрес измеряется в 16-битных словах.
DEIF_WORDS = 52 # SET_DEIF_WORDS версии 1 включает профиль, RAW, привязки OD и диагностику.
DEIF_FIELDS = ("Угол, RAW", "Обороты, RAW", "Обороты %, RAW", "Мощность, RAW", "Мощность %, RAW", "Задание угла, RAW") # Порядок соответствует raw[6] переносимой C-модели; физические единицы зависят от словаря прибора.
DEIF_INDICES = (0x3001, 0x3081, 0x3091, 0x3421, 0x3431, 0x3001) # Начальные OD экземпляра 1 взяты из set_deif_init; последний объект имеет подиндекс 7.
@dataclass(frozen=True) # Клиент публикует только целиком проверенный снимок без последующих изменений.
class DeifSnapshot: # Тип не зависит от Qt, HAL, конкретного MCU и способа доставки регистров.
words: tuple # Содержит 52 беззнаковых слова, прочитанных одной командой FC03.
mode: int # Режим из конфигурации STM: 4 Master, 5 Slave либо иной остановленный режим.
@property # Роль берётся из ответа платы, а не из ранее выбранного пункта GUI.
def role(self): # Возвращает 1 Master либо 2 Slave согласно set_emu_deif.h.
return self.words[3] # Слово 3 не совпадает с номерами режимов 4 и 5 блока STM.
@property # Проверка запущенного состояния нужна для запрета изменения сетевого профиля.
def running(self): # Возвращает логическое состояние модели без запуска либо остановки.
return bool(self.words[2]) # Слово 2 равно 1 только после подтверждённой команды пуска.
@property # Знаковое представление сохраняет отрицательные RAW и служебные коды DEIF.
def raw(self): # Возвращает шесть значений I16 в порядке DEIF_FIELDS.
return tuple(value if value < 0x8000 else value - 0x10000 for value in self.words[16:22]) # Старший бит задаёт знак 16-битного дополнения до двух.
def decode_snapshot(words, mode): # Проверяет совместимость прошивки до разрешения любых записей DEIF.
values = tuple(words) # Не сохраняет ссылку на изменяемый транспортный буфер.
if len(values) != DEIF_WORDS or values[:2] != (0x4446, 1): # Сигнатура DF и версия 1 заданы set_deif_read, не совпадают с конфигурацией STM.
raise ValueError("Нужна прошивка с сервисом DEIF Master/Slave версии 1") # Старая прошивка не получает команд в неизвестное окно.
if values[2] not in (0, 1) or values[3] not in (1, 2): # Повреждённые running и role не должны превращаться в разрешение записи.
raise ValueError("STM вернула неверное состояние DEIF") # Отказ сохраняет форму неподтверждённой.
if mode in (4, 5) and values[3] != mode - 3: # Конфигурация и окно состояния должны описывать одну роль текущего экземпляра.
raise ValueError("Роль DEIF не совпадает с режимом STM; повторите чтение") # Между чтениями другая сессия могла изменить режим платы.
return DeifSnapshot(values, mode) # Единственная точка создания проверенного снимка для UI и тестов.