Реализовать наносекундное управление IGBT для HOPE STM32G474 и клиент обмена с проверкой версии и записанных параметров. Расширить Android/JNI API DEIF, настройки и локальную симуляцию; добавить тесты и документацию.
133 lines
11 KiB
Markdown
133 lines
11 KiB
Markdown
# Общее ядро DEIF XDi / CANopen
|
||
|
||
Единственная реализация профиля DEIF находится в `include/deif_xdi.h` и
|
||
`src/deif_xdi.c`. Desktop использует её через `python/set_devices/deif_native.py`,
|
||
Android — через `ports/android/set_deif_jni.c` и `deif/DeifXdi.kt`.
|
||
Кодеки, адресация, числовой каталог, NMT, сроки, SDO и выбор азимута
|
||
не реализуются повторно в Python или Kotlin.
|
||
|
||
Основание профиля: DEIF XDi-net/CANopen reference manual 4189350066D,
|
||
§§1–3, §9.11, Appendix 3 и Appendix 5. Набор переменных соответствует
|
||
наблюдаемой библиотеке: азимут, RPM, RPM%, мощность AC2 и POWER%.
|
||
Абсолютная мощность остаётся RAW до подтверждения её физической единицы.
|
||
|
||
## Два режима
|
||
|
||
- **Пассивный наблюдатель** принимает данные без включения симуляции,
|
||
ничего не отправляет, скрывает устаревшее показание через пять секунд.
|
||
- **CAN-SLAVE** принимает данные от внешнего MASTER и производит Boot-up,
|
||
heartbeat, EMCY и ответы на явно поддерживаемые SDO. После 3000 мс без
|
||
обновления поля сохраняет последнее валидное число и сообщает Data lost;
|
||
мигание выполняет GUI по готовой маске устаревших входов.
|
||
|
||
Пассивный режим предназначен в том числе для обычного приёма показаний
|
||
без занятия собственного Node-ID в сети. На MPDO в активном режиме
|
||
также нет ответного PDO. В нормальном обмене SLAVE передаёт heartbeat.
|
||
|
||
## Азимут
|
||
|
||
Фактическое значение `0x3001:02` и сетевое задание `0x3001:07` хранятся
|
||
независимо. `setp_deif_angle` возвращает значение и его тип:
|
||
|
||
- `0` — пригодного показания нет;
|
||
- `1` — фактический угол;
|
||
- `2` — принятое задание, которое GUI обязан подписывать как задание.
|
||
|
||
При исходной привязке фактического угла до первого кадра `0x02` допускается
|
||
показывать принятое `0x07`. После первого фактического кадра задание его
|
||
не подменяет. Ошибочный фактический I16 также не заменяется старым заданием.
|
||
Явная ручная привязка к `0x07` остаётся индикатором задания.
|
||
Локальный черновик MASTER не входит в состояние C-модели.
|
||
|
||
Эталонный кадр `STD 0x201 / 01 01 30 07 84 03 00 00` должен показывать
|
||
**90° · задание** и при выключенной симуляции. Node-ID физического SLAVE
|
||
не является источником этой SAM-рассылки: источник здесь Node 1.
|
||
|
||
## Адресация и сервисы
|
||
|
||
SAM согласует источник с COB-ID и поддерживает legacy broadcast `0x27F`.
|
||
DAM проверяет собственный Node-ID и выбранный RPDO. XDi-net резервирует
|
||
RPDO1 для SAM и Node 127 для сервисного прибора. Чистый CANopen допускает
|
||
DAM RPDO1. Все кадры профиля являются Classic CAN STD data frames.
|
||
|
||
После Boot-up выдаётся Pre-operational; стандартный self-start занимает
|
||
1000 мс. Исходный период heartbeat — 500 мс. NMT Start/Stop/Pre-operational,
|
||
Reset node и Reset communication принимаются только для собственного узла
|
||
либо broadcast 0. Reset communication сохраняет прикладные значения и
|
||
возвращает несохранённые коммуникационные параметры к исходным значениям.
|
||
|
||
SDO обслуживается в Operational и Pre-operational, в Stopped не отвечает.
|
||
Чтение: `0x1000:00`, `0x1001:00`, `0x1017:00`, `0x1018:00/01` и привязанные
|
||
I16-переменные. До обновления переменной возвращается `0x7FFF`.
|
||
Запись: U16 `0x1017:00`. Ноль отключает HB только вне XDi-net.
|
||
Неизвестный индекс, подиндекс, неподдерживаемая запись или команда дают
|
||
стандартный SDO abort. Серийный номер и код конкретного изделия не выдумываются.
|
||
|
||
Это явный поднабор профиля индикации, а не полный EDS прошивки. LSS,
|
||
segmented SDO, EEPROM, произвольные конфигурационные записи, TPDO mapping,
|
||
двухканальное резервирование и механика привода не моделируются.
|
||
|
||
## Контракт портов
|
||
|
||
Память состояния выделяет вызывающий через `setp_deif_state_size`.
|
||
Буфер должен иметь выравнивание не слабее `uint64_t`; ctypes использует
|
||
массив `uint64`, JNI — direct ByteBuffer. Private-layout состояния не
|
||
передаётся между языками и не сериализуется.
|
||
|
||
Все часы передаются как монотонные миллисекунды. C не вызывает ОС,
|
||
не использует Qt/JVM и не выделяет динамическую память. Каждый прибор
|
||
имеет отдельный контекст. JNI-порт сериализует операции экземпляра.
|
||
|
||
`setp_deif_poll` выдаёт готовые кадры однократно. Порт обслуживает его
|
||
регулярно и после запросов SDO; очередь ограничена 16 событиями. Экранная
|
||
пауза CAN-журнала не должна останавливать протокол. Потеря подключения,
|
||
ошибка TX и закрытие владельца останавливают активный сервер.
|
||
|
||
`setp_deif_make/master/service/angle_command` создают готовые сообщения.
|
||
`setp_deif_selector_info/readdress/route` обслуживают редакторы профиля:
|
||
UI не извлекает endian, смещения или адресные маски самостоятельно.
|
||
Локализованные тексты и мигание готовых показаний остаются в GUI.
|
||
|
||
При отсутствии нативного ядра порт выдаёт явную ошибку. Python/Kotlin
|
||
fallback протокола отсутствует. Windows source build может использовать
|
||
дополнительную сборку того же C-ядра `setprotocol_deif.dll`; путь задаёт
|
||
приложение либо стандартный загрузчик находит компонент рядом с основной
|
||
DLL. Новый автономный EXE использует собственную основную DLL с DEIF.
|
||
|
||
## Android/JVM: настройки и локальный стенд
|
||
|
||
`DeifSettings` хранит профиль SLAVE, независимые параметры MASTER,
|
||
выбор пяти отправляемых объектов, калибровки управления, единицу POWER
|
||
и ручные привязки. Сериализация не сохраняет запуск симуляции или таймеров.
|
||
`readdressed` переносит связанные SAM/DAM-адреса через C, сохраняя отдельные
|
||
ручные источники, индексы объектов и масштабы.
|
||
|
||
`DeifWorkspace` объединяет пассивное наблюдение, физический CAN-SLAVE
|
||
и автономный стенд. Он получает монотонное время от приложения и возвращает
|
||
готовые кадры раздельными маршрутами MASTER и SLAVE. Локальная симуляция
|
||
не возвращает физические кадры; остановленный локальный SLAVE отклоняет
|
||
MASTER и команды экрана вместо переключения на адаптер.
|
||
NMT разрешён только работающему локальному SLAVE. Физический сервер
|
||
отклоняет запуск встроенного MASTER.
|
||
|
||
`DeifXdi.master/make/service/selector/bind/binding/selectorInfo/readdress/validate`
|
||
являются тонкими вызовами существующего C ABI. Порты не строят COB-ID,
|
||
индексы, little-endian I16, NMT или диммер повторно. Перевод касания
|
||
в заданный пользователем масштаб относится к управлению интерфейсом;
|
||
интерактивная отрисовка, отдельное подтверждение яркости и палитры,
|
||
хранилище настроек, USB и жизненный цикл остаются у приложения.
|
||
|
||
`DeifWorkspaceTest` проверяет точные builders, автономный приём интерактивных
|
||
заданий, отсутствие физического TX на локальном стенде, ограничения NMT,
|
||
независимые периоды MASTER/heartbeat, ошибки JNI, сохранение профиля
|
||
и перенос адресов без потери ручных привязок.
|
||
|
||
## Проверки
|
||
|
||
`tests/fixtures/deif-xdi-v1.tsv` — единые эталонные байты для C, Python и JNI.
|
||
Их используют `tests/test_deif_xdi.c`, `python/tests/test_deif_shared.py` и
|
||
`ports/android/tests/.../deif/DeifXdiTest.kt`. Отдельно проверяются пассивные
|
||
90°, независимый фактический угол, Boot-up, NMT, heartbeat и отсутствие
|
||
выдуманного ответного PDO. Desktop дополнительно проверяет миграцию старой
|
||
пустой привязки без включения симуляции и без физического TX.
|