Добавить общие графики, декодер KONOR и порт STM32 bxCAN
This commit is contained in:
80
c/set-protocol/docs/GUI_PLOT.md
Normal file
80
c/set-protocol/docs/GUI_PLOT.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# Общая работа с графиками Android и SETGUI
|
||||
|
||||
Численная логика находится в `include/set_plot.h` и `src/set_plot.c`.
|
||||
Это модуль C99 без Qt, Android, транспорта, динамической памяти и глобального
|
||||
состояния. Он собирается в существующую библиотеку SETProtocol; отдельная DLL
|
||||
для графиков не требуется. Версия ABI графиков — `set_plot_abi_version() == 1`.
|
||||
|
||||
| Общее в templates | Адаптер приложения |
|
||||
|---|---|
|
||||
| Нормализованная область просмотра, масштаб 1…128, ограничение панорамирования | Размер поля и отступы в пикселях |
|
||||
| Независимый масштаб X/Y с сохранением координаты под пальцами | События Compose или Qt, колесо, кнопки |
|
||||
| Выбор преобладающей оси по изменению расстояния между пальцами | Накопление движения до порога; фиксация выбранной оси до конца жеста |
|
||||
| Перевод значения в долю экрана и обратно, инверсия Y | Canvas/QPainter и оформление шкал |
|
||||
| Перемещение маркера от начальной координаты, ограничение видимой областью | Захват линии пальцем/мышью, редактор положения |
|
||||
| Разность B−A, D−C и множитель единиц, шаги шкалы 1/2/5 | Подписи, цвета, миллисекунды/герцы/единицы сигнала |
|
||||
| Модели маркеров и их размещение в Kotlin/Python-портах | Жизненный цикл экрана, очистка и выбор источника |
|
||||
|
||||
Модель маркеров: A/B — координаты X и вертикальные линии во всю высоту поля;
|
||||
C/D — координаты Y и горизонтальные линии. Они могут пересекаться: отрицательная
|
||||
разность сохраняется. Начальные координаты — 1/3 и 2/3 диапазона. При изменении
|
||||
масштаба уже установленные координаты сохраняются. «Маркеры в видимую область»
|
||||
заново размещает их. Координаты и область просмотра времени/спектра независимы.
|
||||
|
||||
`set_plot_eval()` принимает операцию из `enum set_plot_operation`, точное число
|
||||
входных `double` и буфер вывода. Контракт каждой операции указан в заголовке.
|
||||
Возвращает число записанных элементов, 0 — неправильные аргументы. Некорректный
|
||||
коэффициент масштабирования оставляет корректный viewport неизменным.
|
||||
NaN/Inf и вырожденные диапазоны не передаются дальше в отрисовку.
|
||||
FRACTION/VALUE не обрезают координаты: это позволяет правильно отсекать линии
|
||||
по границе поля, а не создавать ложные горизонтальные участки на его краю.
|
||||
DRAG, напротив, ограничивает положение маркера видимым диапазоном.
|
||||
|
||||
## Порты
|
||||
|
||||
- Android/JVM: `ports/android/kotlin/ru/setcorp/setprotocol/trends/NativePlot.kt`,
|
||||
`PlotViewport.kt`, `TrendMarkers.kt`; тонкий JNI — `ports/android/set_plot_jni.c`.
|
||||
Android использует `System.loadLibrary("setprotocol")`. Для JVM-тестов можно
|
||||
передать абсолютный путь DLL/SO системным свойством `setplot.library`.
|
||||
- Python: `python/protocan/plot.py`: `PlotMath(library)`, `Viewport`, `Bounds`,
|
||||
`Markers`. Приложение передаёт уже загруженную SETProtocol `ctypes.CDLL`.
|
||||
Зависимости — стандартная библиотека; Qt в этот модуль не импортируется.
|
||||
|
||||
Новые изменения не должны добавлять вторую реализацию численных операций
|
||||
в Kotlin/Python или в приложение. Состояние и адаптация событий остаются в портах.
|
||||
Добавление операции требует обновления C ABI, обоих портов и общих эталонов.
|
||||
|
||||
## Интеграция приложений
|
||||
|
||||
Android: `TrendGraph` использует общие viewport, bounds и маркеры, а Compose
|
||||
рисует линии и панель. При измерениях время отображается в миллисекундах от
|
||||
начала выбранного участка; сохранённые X-координаты включают абсолютное начало.
|
||||
|
||||
SETGUI: `ui/plot_interaction.py` адаптирует общий модуль к Qt. Его используют
|
||||
`SignalPlot` (ТМС и датчики), `TrendPlot` (логи) и `SpectrumPlot`.
|
||||
Колесо по вертикали масштабирует Y, Shift+колесо и горизонтальное колесо — X;
|
||||
сенсорный pinch выбирает ось по движению. Временные графики хранят метку приёма
|
||||
каждого отсчёта. Пропущенные значения не растягивают остальные серии:
|
||||
все сигналы имеют единую шкалу времени. При повторном построении ТМС из журнала
|
||||
используются исходные метки приёма. Дискретные дорожки имеют общую X-шкалу,
|
||||
а маркеры уровня Y относятся к аналоговому полю.
|
||||
|
||||
Расчёт FFT не является частью этого модуля. Android вычисляет спектр через
|
||||
`set_spectrum.c`; вкладка спектра SETGUI получает готовые уровни в дБмВ от
|
||||
прибора. Общая интерактивная часть не меняет эти данные или единицы.
|
||||
|
||||
## Проверка и сборка
|
||||
|
||||
- CMake/CTest: `shared_plot` проверяет ABI, размеры буферов и координаты.
|
||||
- `tests/fixtures/plot-v1.json` содержит общие численные эталоны. Их читают
|
||||
`PlotContractTest` (фактический JNI) и `python/tests/test_plot.py` (ctypes).
|
||||
- Host DLL/SO для Python: `python tools/build_host.py --output <путь>`.
|
||||
- Для JVM: та же команда с `--java-home <JDK>` добавляет JNI-порт графиков.
|
||||
Нужен C-компилятор (MSVC на Windows, cc/clang/gcc на Unix) и JDK с `jni.h`.
|
||||
- Android-проект автоматически собирает host-библиотеку перед JVM-тестами;
|
||||
интерпретатор Python можно задать свойством Gradle `setflash.python`.
|
||||
- SETGUI проверяет события мыши, колеса и двух пальцев через QtTest без
|
||||
физического прибора; численные тесты не требуют GUI.
|
||||
|
||||
Исходники должны приходить из одного коммита подмодуля `templates` в обоих
|
||||
проектах. Локальная замена файлов без обновления gitlink не закрепляет версию.
|
||||
53
c/set-protocol/docs/GUI_SPECTRUM.md
Normal file
53
c/set-protocol/docs/GUI_SPECTRUM.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# Shared GUI spectrum
|
||||
|
||||
`include/set_spectrum.h` / `src/set_spectrum.c` implement the same numerical
|
||||
pipeline for desktop and Android. CMake, `tools/build_host.py`, and the Android
|
||||
NDK build include it. The wire protocol is unchanged. The host-only analyzer
|
||||
allocates at most two FFT arrays (2×N doubles), releasing them before return.
|
||||
|
||||
The last N samples are used: the largest power of two within available data and
|
||||
`max_size`, 16…16384. Timestamps are seconds; inputs are immutable. Fs is measured
|
||||
from the selected endpoints. Non-monotonic/duplicate times and interval deviations
|
||||
over 50% of the mean are rejected. Lesser jitter is linearly interpolated onto an
|
||||
even grid (this can affect high-frequency amplitude; inspect returned jitter).
|
||||
|
||||
Processing order: interpolation, optional mean subtraction, filter, periodic
|
||||
window, forward FFT, one-sided peak amplitude. Windows: rectangular, Hann,
|
||||
Hamming, Blackman, Flat Top. Amplitudes are divided by window sum, doubled except
|
||||
DC and Nyquist. Output is not RMS/PSD/dB. Coherent gain correction is exact for
|
||||
bin-centered tones away from DC/Nyquist; off-bin tones still have scalloping.
|
||||
|
||||
Filters run before the window, on the unmodified sample copy. LP/HP are second
|
||||
order Butterworth; band pass cascades HP and LP; notch uses Q=30.
|
||||
Coefficients: [W3C Audio EQ Cookbook](https://www.w3.org/TR/audio-eq-cookbook/).
|
||||
Initial state is the first sample's steady state, not a carried streaming state;
|
||||
block-start transients may occur. Cutoffs must be strictly within (0, Fs/2).
|
||||
|
||||
## Python
|
||||
|
||||
```python
|
||||
from protocan.spectrum import NativeSpectrum, Window, Filter
|
||||
|
||||
# lib = an existing ctypes.CDLL from protocan.native.NativeProtocol
|
||||
spectrum = NativeSpectrum(lib).analyze(times_seconds, values,
|
||||
window=Window.HANN, filter=Filter.LOW_PASS, high_hz=100,
|
||||
max_size=4096, remove_mean=True)
|
||||
plot(spectrum.frequencies, spectrum.amplitudes)
|
||||
```
|
||||
|
||||
Adapter errors are ValueError, not empty/misleading arrays. No NumPy/Qt dependency.
|
||||
|
||||
## Android
|
||||
|
||||
`SpectrumAnalyzer.analyze(List<TrendPoint>, SpectrumOptions)` calls JNI using
|
||||
relative seconds from millisecond timestamps. `TrendSpectrum` contains N, Fs,
|
||||
maximum relative jitter, amplitudes or a displayable error. Call on a worker
|
||||
dispatcher. `PlotViewport` provides axis-independent zoom/pan, focus anchoring,
|
||||
128× limit and bounds clamping without any Compose dependency.
|
||||
|
||||
## Checks
|
||||
|
||||
Build CMake with tests and run CTest in Debug (assertions enabled). Python
|
||||
`tests/test_spectrum.py` runs against an explicitly supplied `SETPROTOCOL_LIBRARY`:
|
||||
independent direct DFT, amplitude correction, DC/Nyquist, off-bin leakage, filter
|
||||
bands, timing rejection/interpolation, bounded tail selection and immutable inputs.
|
||||
78
c/set-protocol/docs/GUI_TRENDS.md
Normal file
78
c/set-protocol/docs/GUI_TRENDS.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# Общие тренды для Android GUI и SETGUI
|
||||
|
||||
Модуль задаёт совместимые настройки и числовые источники графиков. Он не
|
||||
рисует экран, не открывает файлы или порты и не управляет прошивкой устройства.
|
||||
|
||||
Слои: GUI → Kotlin/Python adapter → `set_trends.c` → уже разобранные кадры.
|
||||
Транспорт, таймер опроса, выбор файла, хранение настроек и Canvas/Qt остаются
|
||||
в приложении. У ядра нет callbacks, динамической памяти или глобального состояния.
|
||||
|
||||
| Файл | Назначение и зависимости |
|
||||
|---|---|
|
||||
| `include/set_trends.h`, `src/set_trends.c` | C99: фильтрация GAS/raw CAN, signed/unsigned word, payload подписки SET GUI; использует `pcan_id` и ABI export macro |
|
||||
| `ports/android/kotlin/ru/setcorp/setprotocol/trends/` | Модель, валидация JSON, ограниченная история, GAS_WATCH; JVM + org.json, без Android/Compose |
|
||||
| `ports/android/setprotocol_jni.c` | Только преобразование JNI-аргументов |
|
||||
| `python/protocan/trends.py` | Модель, JSON, история и `NativeTrends`; Python 3.9+, stdlib, без Qt |
|
||||
| `tests/fixtures/trends-v1.json` | Один образец для тестов обоих GUI и обмена настройками |
|
||||
|
||||
## Формат файла
|
||||
|
||||
UTF-8 JSON: `format = "setflash-trends"`, `version = 1`, `profiles` — словарь.
|
||||
Ключи профилей стабильны: `TMS2812`, `SET_V1`, `CAN_BRIDGE`, `GS_USB_CAN`,
|
||||
`SLCAN`, `CANGAROO_SLCAN`, `BALZAM_CAN`. Приложение явно сопоставляет своё
|
||||
подключение с этим ключом; импорт не меняет подключение.
|
||||
|
||||
Поля сигнала обязательны: `id`, `order`, `name`, `source`, `address`, `color`,
|
||||
`visible`, `valueType`, `deviceType`, `device`, `byteOffset`, `extended`.
|
||||
`id` уникален во всём файле. `order` — 1…9999, уникален внутри профиля.
|
||||
`name` — непустое изменяемое имя (до 100 символов), `color` — `#RRGGBB`.
|
||||
`visible` управляет только отрисовкой, не сбором. История и соединение в файл
|
||||
не входят. Максимум 64 сигнала на профиль и 1 МиБ на файл. Неизвестные версии,
|
||||
профили, источники и неверные значения отклоняются до замены настроек.
|
||||
|
||||
| Профиль / источник | Адрес и значение |
|
||||
|---|---|
|
||||
| TMS2812 / TMS_MEMORY | 32-битный адрес слова, CMD_PEEK; контроллер из подключения |
|
||||
| SET_V1 / SET_GAS | 16-битный GAS; GAS_WATCH_SET `0x12`, DATA `0x13` |
|
||||
| SET_V1 / SET_SENSOR | ROM DS18B20, 16 HEX-цифр (дефисы допустимы), °C |
|
||||
| Современные CAN / CAN_GAS | GAS 0…65535, DeviceType 0…7, DeviceID 0…15 |
|
||||
| Все CAN / CAN_RAW | CAN ID, STD/EXT, byteOffset 0…6; слово Little-endian |
|
||||
|
||||
Числовые адреса — десятичные либо HEX с `0x`. Регистры трактуются как
|
||||
`UINT16` или `INT16`. Для RAW/CAN_GAS C-функция возвращает значение либо
|
||||
`SET_TREND_NO_VALUE`, никогда не подставляет ноль вместо отсутствующего кадра.
|
||||
|
||||
CAN — пассивный приём, без записи GAS и автоматической отправки запросов.
|
||||
GAS принимает только входящие FROM_DEVICE; TX/RTR/ошибки исключены.
|
||||
SET GUI оформляет подписку в порядке адресов. ACK должен подтвердить весь
|
||||
список: при частичном принятии нельзя определить пропущенные адреса, поэтому
|
||||
строить график по смещённым индексам запрещено. При паузе порт приложения
|
||||
отправляет подписку с периодом 0, когда транспорт доступен и не занят прошивкой.
|
||||
|
||||
## Быстрый старт SETGUI
|
||||
|
||||
```python
|
||||
from protocan.native import NativeProtocol
|
||||
from protocan.trends import TrendSignal, NativeTrends, encode_settings
|
||||
|
||||
core = NativeProtocol() # библиотека, пересобранная с set_trends.c
|
||||
decoder = NativeTrends(core.lib)
|
||||
signal = TrendSignal("current", source="CAN_GAS", address="0x1235")
|
||||
text = encode_settings({"CAN_BRIDGE": [signal]})
|
||||
value = decoder.can_value(signal, 0x1FD31234, 1, bytes([1, 0, 254, 255]))
|
||||
assert value == 65534.0
|
||||
# GUI сохраняет text выбранным способом и передаёт value своему графику.
|
||||
```
|
||||
|
||||
Android подключает Kotlin-каталог напрямую через Gradle и C-файлы через NDK.
|
||||
Приложение SETGUI может импортировать модуль через уже используемый путь
|
||||
`third_party/templates/python`; в этом изменении его экран не изменяется.
|
||||
После публикации новой ревизии templates оба проекта должны обновить сабмодуль
|
||||
и пересобрать собственные native-библиотеки — вручную копировать реализации не нужно.
|
||||
|
||||
## Проверки
|
||||
|
||||
- CMake/CTest: `shared_trends`, плюс существующие protocol/ABI тесты.
|
||||
- JVM: `TrendSettingsJsonTest`, `GuiGasWatchTest`; один JSON fixture с Python.
|
||||
- Python: `PYTHONPATH=python python -m unittest discover -s python/tests`.
|
||||
Для проверки настоящего C-декодера задайте `SETPROTOCOL_LIBRARY` путём DLL/SO.
|
||||
@@ -48,7 +48,7 @@ uint16_t n = pcan_gas_read_block(&map, 0x0000, block, 4);
|
||||
Тип сообщения `PCAN_MSG_GAS` (`0b0011`). Адрес первого регистра лежит
|
||||
в `MsgBody`, данные — до 4 регистров подряд, младшим байтом вперёд.
|
||||
Это ровно то, что делает `PROTOCAN_SEND_GENERAL_ADDRESS_SPACE()`
|
||||
в `SETCAN/Src/protocan.c`, поэтому обмен совместим с существующими
|
||||
в `ports/stm32-bxcan/protocan.c` (бывший SETCAN), поэтому обмен совместим с существующими
|
||||
устройствами.
|
||||
|
||||
| Кадр | DLC | Смысл |
|
||||
|
||||
Reference in New Issue
Block a user