ОАП связывает 16-битный адрес регистра с его типом, назначением, доступом и
-масштабом. В ProtoCAN используется MsgType=0x3, а MsgBody содержит адрес
-первого регистра.
-Общее адресное пространство: GAS и GAS SLOT
+Дата редакции: 2026-10-23. Номер типа однозначно определяет единицу адресации:
-| Поле |
-Требование |
+MsgType |
+Имя |
+MsgBody |
+Payload |
-| AddressHex |
-0x0000…0xFFFF, уникальное значение |
+0x3 |
+GAS |
+адрес первого 16-битного регистра |
+1…4 последовательных регистра, DLC 2/4/6/8 |
-| AddressDec |
-десятичный эквивалент AddressHex |
-
-
-| Group |
-функциональная группа |
-
-
-| Name |
-однозначное имя параметра |
-
-
-| Type |
-u16, i16, u32, i32, float32, bitmap или массив |
-
-
-| Registers |
-число занятых 16-битных регистров |
-
-
-| Access |
-R, W или RW |
-
-
-| Unit |
-физическая единица либо — |
-
-
-| Scale |
-множитель/делитель представления |
-
-
-| Default |
-значение после сброса, если применимо |
-
-
-| Description |
-семантика, диапазон и особые значения |
+0x4 |
+GAS SLOT |
+адрес слота |
+Word0 — маска; Word1…Word3 — три значения; DLC 8 |
-Правила ведения
+В обоих случаях запрос чтения — extended data frame с DLC=0, Route=0.
+Ответ имеет Route=1, тот же узел и адрес. Прикладного ACK записи нет;
+успех применения уставки проверяется прикладным ответом или последующим чтением.
+RTR, error frame, стандартный 11-битный ID и нечётные длины не исполняются.
+GAS 0x3: отдельные регистры
+MsgBody=RegisterAddress[15:0]. Адреса 0…65535 (0x0000…0xFFFF)
+обозначают 65 536 отдельных 16-битных регистров, логически 128 КиБ на узел.
+Это адреса протокола, а не указатели RAM MCU; provider подключает только существующие регионы.
+Payload содержит значения с адресов addr, addr+1, addr+2, addr+3
+в порядке little-endian. Количество равно DLC/2, допускаются DLC 2, 4, 6, 8.
+Для изменения одной уставки по адресу 0x0001 на 0x1234 передаются
+MsgBody=0x0001, DLC=2, Data=34 12; соседние слова не изменяются.
+Чтение возвращает до четырёх существующих последовательных регистров,
+останавливаясь на первом недоступном адресе или границе 0xFFFF.
+Запись, пересекающая 0xFFFF, отвергается до изменения данных.
+Регионы карты, права и значения проверяет pcan_gas; callback остаётся
+ответственностью приложения. Блочная запись может остановиться на первом отказе provider:
+атомарность нескольких регистров не обещается. Связанные u32/float32 и команды
+требуют согласованной прикладной операции. Основной контракт: c/set-protocol/docs/legacy/GAS.md.
+GAS 167/v1, GAS Logger, GAS_WATCH2, NAND и Altera Logic сохраняют регистровые адреса.
+Номер mode задаёт адрес узла; его нельзя автоматически прибавлять к адресу регистра.
+GAS SLOT 0x4: маска в Word0
+MsgBody=SlotAddress[15:0]. Восемь октетов имеют фиксированное расположение:
+
+
+
+| Октеты |
+Wire-слово |
+Назначение |
+
+
+
+
+| 0…1 |
+Word0 |
+16-битная маска, little-endian |
+
+
+| 2…3 |
+Word1 |
+первое значение |
+
+
+| 4…5 |
+Word2 |
+второе значение |
+
+
+| 6…7 |
+Word3 |
+третье значение |
+
+
+
+Биты маски 1, 2, 3 соответствуют Word1, Word2, Word3. Бит 0 и биты 4…15
+зарезервированы и должны быть нулевыми. Маска непустая; все допустимые маски:
+0x0002, 0x0004, 0x0006, 0x0008, 0x000A, 0x000C, 0x000E.
+При записи отмеченные значения применяются, неотмеченные позиции игнорируются
+и сохраняют текущие значения устройства. Нули не являются специальными маркерами.
+При чтении маска ответа отмечает достоверные/доступные значения.
+Например, изменить только Word2 на 0x1234: Data=04 00 00 00 34 12 00 00.
+Word1 и Word3 сохраняются. Полная запись трёх значений использует маску 0x000E.
+Передаются всегда восемь октетов, кроме пустого запроса чтения. Сжатия или сегментации нет.
+Provider проверяет все выбранные права и значения до первого изменения, затем применяет
+выбранные слова под общей блокировкой. Невыбранные readonly-поля не записываются.
+Ядро не выполняет опасное чтение-изменение-запись слота на стороне клиента.
+Полное пространство 0x4 содержит 65 536 слотов × 3 значения = 196 608 слов = 384 КиБ.
+Word0 — метаданные кадра, не четвёртый хранимый регистр. Координата значения —
+(SlotAddress, WordIndex), где WordIndex=1…3. Любой узел поддерживается общими
+pcan_gas_slot_id() и pcan_gas_slot_handle_address(); адрес слота не ограничен страницами PERIPH.
+Тип 0x4 MODBUS_COIL заменён этим сервисом. Modbus 0x5/0x6/0x7 сохраняет номера.
+Старое оборудование с Coil 0x4 требует согласованного обновления; автоопределения формата нет.
+PERIPH: проекция 200 слов на слоты 0x4
+mode=0…31; DeviceType=1+mode/16, DeviceID=mode mod 16.
+SlotAddress=(mode<<8)|LocalSlot. Маски не занимают места в карте значений.
+На mode сохранены 200 слов, поэтому используются 67 слотов LocalSlot=0x00…0x42:
+66 полных слотов и два значения последнего. В последнем разрешена только маска
+из битов 1/2 (0x0002, 0x0004, 0x0006); Word3 не существует.
+LocalSlot=0x43…0xFF — резерв. Узел и старший октет слота должны совпадать.
+Смещение технологического слова: n=3*LocalSlot+(WordIndex-1).
+Обратное преобразование: LocalSlot=n/3, WordIndex=1+n mod 3.
+Соседние native-сервисы могут оказаться в одном слоте, поэтому provider проверяет
+доступ и наличие каждой отмеченной позиции отдельно.
+
+
+
+| mode |
+Назначение |
+DeviceType / DeviceID |
+Слоты 0x4 |
+Запрос первого слота |
+
+
+
+
+| 0 |
+Резерв |
+0x01 / 0x00 |
+0x0000…0x0042 |
+0x11040000 |
+
+
+| 1 |
+Трансформатор 1 |
+0x01 / 0x01 |
+0x0100…0x0142 |
+0x11140100 |
+
+
+| 2 |
+Трансформатор 2 |
+0x01 / 0x02 |
+0x0200…0x0242 |
+0x11240200 |
+
+
+| 3 |
+Силовой узел 1 |
+0x01 / 0x03 |
+0x0300…0x0342 |
+0x11340300 |
+
+
+| 4 |
+Силовой узел 2 |
+0x01 / 0x04 |
+0x0400…0x0442 |
+0x11440400 |
+
+
+| 5 |
+УМП1 |
+0x01 / 0x05 |
+0x0500…0x0542 |
+0x11540500 |
+
+
+| 6 |
+УМП2 |
+0x01 / 0x06 |
+0x0600…0x0642 |
+0x11640600 |
+
+
+| 7 |
+ENG1 |
+0x01 / 0x07 |
+0x0700…0x0742 |
+0x11740700 |
+
+
+| 8 |
+Задатчик / пульт |
+0x01 / 0x08 |
+0x0800…0x0842 |
+0x11840800 |
+
+
+| 9 |
+Шкаф |
+0x01 / 0x09 |
+0x0900…0x0942 |
+0x11940900 |
+
+
+| 10 |
+Общий адрес: служебная роль |
+0x01 / 0x0A |
+0x0A00…0x0A42 |
+0x11A40A00 |
+
+
+| 11 |
+Терминал: служебная роль |
+0x01 / 0x0B |
+0x0B00…0x0B42 |
+0x11B40B00 |
+
+
+| 12 |
+Резерв назначения |
+0x01 / 0x0C |
+0x0C00…0x0C42 |
+0x11C40C00 |
+
+
+| 13 |
+Резерв назначения |
+0x01 / 0x0D |
+0x0D00…0x0D42 |
+0x11D40D00 |
+
+
+| 14 |
+Резерв назначения |
+0x01 / 0x0E |
+0x0E00…0x0E42 |
+0x11E40E00 |
+
+
+| 15 |
+Резерв назначения |
+0x01 / 0x0F |
+0x0F00…0x0F42 |
+0x11F40F00 |
+
+
+| 16 |
+Резерв назначения |
+0x02 / 0x00 |
+0x1000…0x1042 |
+0x12041000 |
+
+
+| 17 |
+Резерв назначения |
+0x02 / 0x01 |
+0x1100…0x1142 |
+0x12141100 |
+
+
+| 18 |
+Резерв назначения |
+0x02 / 0x02 |
+0x1200…0x1242 |
+0x12241200 |
+
+
+| 19 |
+Резерв назначения |
+0x02 / 0x03 |
+0x1300…0x1342 |
+0x12341300 |
+
+
+| 20 |
+Резерв назначения |
+0x02 / 0x04 |
+0x1400…0x1442 |
+0x12441400 |
+
+
+| 21 |
+Резерв назначения |
+0x02 / 0x05 |
+0x1500…0x1542 |
+0x12541500 |
+
+
+| 22 |
+Резерв назначения |
+0x02 / 0x06 |
+0x1600…0x1642 |
+0x12641600 |
+
+
+| 23 |
+Резерв назначения |
+0x02 / 0x07 |
+0x1700…0x1742 |
+0x12741700 |
+
+
+| 24 |
+Резерв назначения |
+0x02 / 0x08 |
+0x1800…0x1842 |
+0x12841800 |
+
+
+| 25 |
+Резерв назначения |
+0x02 / 0x09 |
+0x1900…0x1942 |
+0x12941900 |
+
+
+| 26 |
+Резерв назначения |
+0x02 / 0x0A |
+0x1A00…0x1A42 |
+0x12A41A00 |
+
+
+| 27 |
+Резерв назначения |
+0x02 / 0x0B |
+0x1B00…0x1B42 |
+0x12B41B00 |
+
+
+| 28 |
+Резерв назначения |
+0x02 / 0x0C |
+0x1C00…0x1C42 |
+0x12C41C00 |
+
+
+| 29 |
+Резерв назначения |
+0x02 / 0x0D |
+0x1D00…0x1D42 |
+0x12D41D00 |
+
+
+| 30 |
+Резерв назначения |
+0x02 / 0x0E |
+0x1E00…0x1E42 |
+0x12E41E00 |
+
+
+| 31 |
+Резерв назначения |
+0x02 / 0x0F |
+0x1F00…0x1F42 |
+0x12F41F00 |
+
+
+
+Назначения mode из periph_28335
+Источники: 28335_periph/Source/Internal/Include/package.h, peripher.c:get_Mode(), cntrl_adr.c. Код платы Desk не участвует в вычислении адреса.
+
+
+
+| mode |
+Назначение |
+Исходный символ |
+
+
+
+
+| 0 |
+Резерв |
+Перемычками текущей платы не задаётся |
+
+
+| 1 / 2 |
+Трансформаторные узлы 1 / 2 |
+adr_TRN1 / adr_TRN2 |
+
+
+| 3 / 4 |
+Силовые узлы 1 / 2 |
+adr_POW1 / adr_POW2 |
+
+
+| 5 / 6 |
+УМП1 / УМП2 |
+adr_LOA1 / adr_LOA2, Desk=dsk_LOAD=6 |
+
+
+| 7 |
+ENG1 |
+adr_ENG1 |
+
+
+| 8 |
+Задатчик / пульт |
+adr_PULT; имя «Задатчик» принято в реестре PERIPH |
+
+
+| 9 |
+Шкаф |
+adr_SHKF |
+
+
+| 10 |
+Общий адрес, служебная роль |
+CNTRL_ADDR_UNIVERSAL, ADDR_FOR_ALL; не отдельная плата |
+
+
+| 11 |
+Терминал, служебная роль |
+ADDR_TERMINAL; не доказательство отдельной платы |
+
+
+| 12…31 |
+Резерв назначения |
+Перемычки текущей платы дают только 1…16 |
+
+
+
+Соответствия native-сервисам PERIPH
+
+
+
+| Смещение n |
+Native-адрес |
+Назначение |
+Доступ |
+
+
+
+
+| 0…127 |
+0x0000…0x007F |
+технологические данные, уставки, команды |
+по provider |
+
+
+| 128…143 |
+0x1000…0x100F |
+статус регистратора УМП |
+R |
+
+
+| 144…155 |
+0x1200…0x120B |
+паспорт прошивки |
+R |
+
+
+| 156…163 |
+0x1300…0x1307 |
+защита УМП |
+W только 0x1302/0x1303 |
+
+
+| 164…167 |
+0x1000…0x1003 |
+команды регистратора |
+по операции |
+
+
+| 168…199 |
+нет |
+резерв |
+отказ |
+
+
+
+pcan_gas_slot_native() принимает WordIndex=1…3; WordIndex=0 является маской
+и не переводится в регистр. Наличие сервиса, права и блокировку проверяет приложение.
+GAS 0x3 сохраняет собственные адреса подключённых регионов; эта проекция относится только к 0x4.
+Архив УМП, окна 120/124 слова и физическая EEPROM сохраняют native-контракты.
+Реализация и реестр
-- Адрес не переиспользуется с другим смыслом после выпуска стабильной версии.
-- Многорегистровое значение занимает непрерывный диапазон.
-- Порядок 16-битных слов для 32-битного значения фиксируется в строке типа.
-- Резервные диапазоны явно отмечаются и не используются без изменения версии.
-- Удалённый параметр помечается deprecated, а не исчезает молча.
-- Изменение адреса, типа или масштаба отражается в
CHANGELOG.md.
+- GAS 0x3:
pcan_gas.h/.c, существующие ABI и клиенты.
+- GAS SLOT 0x4:
pcan_gas_slot.h/.c; тонкие Python GasSlots и Android/JNI GasSlots.
+- Формат определяется MsgType, параметр
gas_profile не используется.
+- C28x хранит wire-октеты в
uint_least8_t; DLC измеряется октетами линии.
+- Перенос в другую единицу адресации или fallback после отказа запрещены.
-Экспорт
-Для программной генерации каталог следует экспортировать из XLSX в CSV с
-UTF-8 и фиксированными английскими именами колонок. CSV должен проверяться на:
-
-- уникальность адресов;
-- пересечение многорегистровых значений;
-- допустимые типы и права доступа;
-- равенство шестнадцатеричного и десятичного адреса;
-- попадание адреса в диапазон
0x0000…0xFFFF.
-
-До появления автоматического экспортёра нормативным источником адресов
-остаётся XLSX, а HTML/Markdown считаются представлением.
+XLSX «Интерфейс протокола» содержит оба типа; «Общее адресное пространство» —
+проекцию 0x4 и native-адреса её значений; «ОАП legacy» сохраняет исходный словный реестр 0x3.
+Уникальный ключ реестра включает узел, MsgType, адрес и для 0x4 WordIndex.
+Права, тип, единица, масштаб и порядок слов u32/float32 задаются явно.
+Эталоны: examples/gas-slot-vectors.json; регистровые проверки — test_gas_register.c.
История изменений ProtoCAN
Формат основан на Keep a Changelog. Версия относится к спецификации, а не к
версии прошивки отдельного прибора.
[Unreleased]
+Changed — 2026-10-23
+
+- GAS 0x3 возвращён к адресации отдельных 16-битных регистров 0…65535, DLC 0/2/4/6/8.
+- Слотный GAS перенесён на 0x4 вместо MODBUS_COIL; Word0 содержит маску битов 1…3, Word1…Word3 — значения.
+- PERIPH сохраняет 200 значений на mode в 67 слотах; последний содержит два значения.
+- Формат выбирается номером MsgType; Python/JNI, STM32, Modbus routing, тесты, XLSX и HTML согласованы.
+
Added
- Структурированный комплект документации
doc/setcan/protocan.
diff --git a/doc/setcan/protocan/CHANGELOG.md b/doc/setcan/protocan/CHANGELOG.md
index 73c921e..827ff7a 100644
--- a/doc/setcan/protocan/CHANGELOG.md
+++ b/doc/setcan/protocan/CHANGELOG.md
@@ -5,6 +5,13 @@
## [Unreleased]
+### Changed — 2026-10-23
+
+- GAS 0x3 возвращён к адресации отдельных 16-битных регистров 0…65535, DLC 0/2/4/6/8.
+- Слотный GAS перенесён на 0x4 вместо MODBUS_COIL; Word0 содержит маску битов 1…3, Word1…Word3 — значения.
+- PERIPH сохраняет 200 значений на mode в 67 слотах; последний содержит два значения.
+- Формат выбирается номером MsgType; Python/JNI, STM32, Modbus routing, тесты, XLSX и HTML согласованы.
+
### Added
- Структурированный комплект документации `doc/setcan/protocan`.
diff --git a/doc/setcan/protocan/OAP.md b/doc/setcan/protocan/OAP.md
index 28918bf..9bab425 100644
--- a/doc/setcan/protocan/OAP.md
+++ b/doc/setcan/protocan/OAP.md
@@ -1,56 +1,162 @@
-# Общее адресное пространство
+# Общее адресное пространство: GAS и GAS SLOT
-Статус: **Stable, данные ведутся в XLSX**
-Порядок значений: **16-битные регистры, little-endian в CAN payload**
+Дата редакции: **2026-10-23**. Номер типа однозначно определяет единицу адресации:
-Редактируемый источник реестра:
-[`Протокол CAN и ОАП.xlsx`](../Протокол%20CAN%20и%20ОАП.xlsx).
+| MsgType | Имя | MsgBody | Payload |
+|---|---|---|---|
+| `0x3` | GAS | адрес первого 16-битного регистра | 1…4 последовательных регистра, DLC 2/4/6/8 |
+| `0x4` | GAS SLOT | адрес слота | Word0 — маска; Word1…Word3 — три значения; DLC 8 |
-Просматриваемая большая таблица находится в
-[`Протокол CAN и ОАП.html`](../Протокол%20CAN%20и%20ОАП.html) и
-[`Протокол CAN и ОАП.md`](../Протокол%20CAN%20и%20ОАП.md).
+В обоих случаях запрос чтения — extended data frame с `DLC=0`, `Route=0`.
+Ответ имеет `Route=1`, тот же узел и адрес. Прикладного ACK записи нет;
+успех применения уставки проверяется прикладным ответом или последующим чтением.
+RTR, error frame, стандартный 11-битный ID и нечётные длины не исполняются.
-## Назначение
+## GAS 0x3: отдельные регистры
-ОАП связывает 16-битный адрес регистра с его типом, назначением, доступом и
-масштабом. В ProtoCAN используется `MsgType=0x3`, а `MsgBody` содержит адрес
-первого регистра.
+`MsgBody=RegisterAddress[15:0]`. Адреса `0…65535` (`0x0000…0xFFFF`)
+обозначают **65 536 отдельных 16-битных регистров**, логически 128 КиБ на узел.
+Это адреса протокола, а не указатели RAM MCU; provider подключает только существующие регионы.
-## Обязательные поля реестра
+Payload содержит значения с адресов `addr`, `addr+1`, `addr+2`, `addr+3`
+в порядке little-endian. Количество равно `DLC/2`, допускаются DLC 2, 4, 6, 8.
+Для изменения одной уставки по адресу `0x0001` на `0x1234` передаются
+`MsgBody=0x0001`, `DLC=2`, Data=`34 12`; соседние слова не изменяются.
+Чтение возвращает до четырёх существующих последовательных регистров,
+останавливаясь на первом недоступном адресе или границе `0xFFFF`.
+Запись, пересекающая `0xFFFF`, отвергается до изменения данных.
-| Поле | Требование |
-|---|---|
-| AddressHex | `0x0000…0xFFFF`, уникальное значение |
-| AddressDec | десятичный эквивалент AddressHex |
-| Group | функциональная группа |
-| Name | однозначное имя параметра |
-| Type | `u16`, `i16`, `u32`, `i32`, `float32`, bitmap или массив |
-| Registers | число занятых 16-битных регистров |
-| Access | `R`, `W` или `RW` |
-| Unit | физическая единица либо `—` |
-| Scale | множитель/делитель представления |
-| Default | значение после сброса, если применимо |
-| Description | семантика, диапазон и особые значения |
+Регионы карты, права и значения проверяет `pcan_gas`; callback остаётся
+ответственностью приложения. Блочная запись может остановиться на первом отказе provider:
+атомарность нескольких регистров не обещается. Связанные `u32/float32` и команды
+требуют согласованной прикладной операции. Основной контракт: `c/set-protocol/docs/legacy/GAS.md`.
+GAS 167/v1, GAS Logger, GAS_WATCH2, NAND и Altera Logic сохраняют регистровые адреса.
+Номер mode задаёт адрес узла; его нельзя автоматически прибавлять к адресу регистра.
-## Правила ведения
+## GAS SLOT 0x4: маска в Word0
-- Адрес не переиспользуется с другим смыслом после выпуска стабильной версии.
-- Многорегистровое значение занимает непрерывный диапазон.
-- Порядок 16-битных слов для 32-битного значения фиксируется в строке типа.
-- Резервные диапазоны явно отмечаются и не используются без изменения версии.
-- Удалённый параметр помечается deprecated, а не исчезает молча.
-- Изменение адреса, типа или масштаба отражается в `CHANGELOG.md`.
+`MsgBody=SlotAddress[15:0]`. Восемь октетов имеют фиксированное расположение:
-## Экспорт
+| Октеты | Wire-слово | Назначение |
+|---|---|---|
+| 0…1 | Word0 | 16-битная маска, little-endian |
+| 2…3 | Word1 | первое значение |
+| 4…5 | Word2 | второе значение |
+| 6…7 | Word3 | третье значение |
-Для программной генерации каталог следует экспортировать из XLSX в CSV с
-UTF-8 и фиксированными английскими именами колонок. CSV должен проверяться на:
+Биты маски 1, 2, 3 соответствуют Word1, Word2, Word3. Бит 0 и биты 4…15
+зарезервированы и должны быть нулевыми. Маска непустая; все допустимые маски:
+`0x0002`, `0x0004`, `0x0006`, `0x0008`, `0x000A`, `0x000C`, `0x000E`.
+При записи отмеченные значения применяются, неотмеченные позиции игнорируются
+и сохраняют текущие значения устройства. Нули не являются специальными маркерами.
+При чтении маска ответа отмечает достоверные/доступные значения.
-- уникальность адресов;
-- пересечение многорегистровых значений;
-- допустимые типы и права доступа;
-- равенство шестнадцатеричного и десятичного адреса;
-- попадание адреса в диапазон `0x0000…0xFFFF`.
+Например, изменить только Word2 на `0x1234`: Data=`04 00 00 00 34 12 00 00`.
+Word1 и Word3 сохраняются. Полная запись трёх значений использует маску `0x000E`.
+Передаются всегда восемь октетов, кроме пустого запроса чтения. Сжатия или сегментации нет.
+Provider проверяет все выбранные права и значения до первого изменения, затем применяет
+выбранные слова под общей блокировкой. Невыбранные readonly-поля не записываются.
+Ядро не выполняет опасное чтение-изменение-запись слота на стороне клиента.
-До появления автоматического экспортёра нормативным источником адресов
-остаётся XLSX, а HTML/Markdown считаются представлением.
+Полное пространство 0x4 содержит **65 536 слотов × 3 значения = 196 608 слов = 384 КиБ**.
+Word0 — метаданные кадра, не четвёртый хранимый регистр. Координата значения —
+`(SlotAddress, WordIndex)`, где `WordIndex=1…3`. Любой узел поддерживается общими
+`pcan_gas_slot_id()` и `pcan_gas_slot_handle_address()`; адрес слота не ограничен страницами PERIPH.
+Тип `0x4 MODBUS_COIL` заменён этим сервисом. Modbus `0x5/0x6/0x7` сохраняет номера.
+Старое оборудование с Coil 0x4 требует согласованного обновления; автоопределения формата нет.
+
+## PERIPH: проекция 200 слов на слоты 0x4
+
+`mode=0…31`; `DeviceType=1+mode/16`, `DeviceID=mode mod 16`.
+`SlotAddress=(mode<<8)|LocalSlot`. Маски не занимают места в карте значений.
+На mode сохранены 200 слов, поэтому используются 67 слотов `LocalSlot=0x00…0x42`:
+66 полных слотов и два значения последнего. В последнем разрешена только маска
+из битов 1/2 (`0x0002`, `0x0004`, `0x0006`); Word3 не существует.
+`LocalSlot=0x43…0xFF` — резерв. Узел и старший октет слота должны совпадать.
+
+Смещение технологического слова: `n=3*LocalSlot+(WordIndex-1)`.
+Обратное преобразование: `LocalSlot=n/3`, `WordIndex=1+n mod 3`.
+Соседние native-сервисы могут оказаться в одном слоте, поэтому provider проверяет
+доступ и наличие каждой отмеченной позиции отдельно.
+
+| mode | Назначение | DeviceType / DeviceID | Слоты 0x4 | Запрос первого слота |
+|---:|---|---|---|---|
+| 0 | Резерв | `0x01 / 0x00` | `0x0000…0x0042` | `0x11040000` |
+| 1 | Трансформатор 1 | `0x01 / 0x01` | `0x0100…0x0142` | `0x11140100` |
+| 2 | Трансформатор 2 | `0x01 / 0x02` | `0x0200…0x0242` | `0x11240200` |
+| 3 | Силовой узел 1 | `0x01 / 0x03` | `0x0300…0x0342` | `0x11340300` |
+| 4 | Силовой узел 2 | `0x01 / 0x04` | `0x0400…0x0442` | `0x11440400` |
+| 5 | УМП1 | `0x01 / 0x05` | `0x0500…0x0542` | `0x11540500` |
+| 6 | УМП2 | `0x01 / 0x06` | `0x0600…0x0642` | `0x11640600` |
+| 7 | ENG1 | `0x01 / 0x07` | `0x0700…0x0742` | `0x11740700` |
+| 8 | Задатчик / пульт | `0x01 / 0x08` | `0x0800…0x0842` | `0x11840800` |
+| 9 | Шкаф | `0x01 / 0x09` | `0x0900…0x0942` | `0x11940900` |
+| 10 | Общий адрес: служебная роль | `0x01 / 0x0A` | `0x0A00…0x0A42` | `0x11A40A00` |
+| 11 | Терминал: служебная роль | `0x01 / 0x0B` | `0x0B00…0x0B42` | `0x11B40B00` |
+| 12 | Резерв назначения | `0x01 / 0x0C` | `0x0C00…0x0C42` | `0x11C40C00` |
+| 13 | Резерв назначения | `0x01 / 0x0D` | `0x0D00…0x0D42` | `0x11D40D00` |
+| 14 | Резерв назначения | `0x01 / 0x0E` | `0x0E00…0x0E42` | `0x11E40E00` |
+| 15 | Резерв назначения | `0x01 / 0x0F` | `0x0F00…0x0F42` | `0x11F40F00` |
+| 16 | Резерв назначения | `0x02 / 0x00` | `0x1000…0x1042` | `0x12041000` |
+| 17 | Резерв назначения | `0x02 / 0x01` | `0x1100…0x1142` | `0x12141100` |
+| 18 | Резерв назначения | `0x02 / 0x02` | `0x1200…0x1242` | `0x12241200` |
+| 19 | Резерв назначения | `0x02 / 0x03` | `0x1300…0x1342` | `0x12341300` |
+| 20 | Резерв назначения | `0x02 / 0x04` | `0x1400…0x1442` | `0x12441400` |
+| 21 | Резерв назначения | `0x02 / 0x05` | `0x1500…0x1542` | `0x12541500` |
+| 22 | Резерв назначения | `0x02 / 0x06` | `0x1600…0x1642` | `0x12641600` |
+| 23 | Резерв назначения | `0x02 / 0x07` | `0x1700…0x1742` | `0x12741700` |
+| 24 | Резерв назначения | `0x02 / 0x08` | `0x1800…0x1842` | `0x12841800` |
+| 25 | Резерв назначения | `0x02 / 0x09` | `0x1900…0x1942` | `0x12941900` |
+| 26 | Резерв назначения | `0x02 / 0x0A` | `0x1A00…0x1A42` | `0x12A41A00` |
+| 27 | Резерв назначения | `0x02 / 0x0B` | `0x1B00…0x1B42` | `0x12B41B00` |
+| 28 | Резерв назначения | `0x02 / 0x0C` | `0x1C00…0x1C42` | `0x12C41C00` |
+| 29 | Резерв назначения | `0x02 / 0x0D` | `0x1D00…0x1D42` | `0x12D41D00` |
+| 30 | Резерв назначения | `0x02 / 0x0E` | `0x1E00…0x1E42` | `0x12E41E00` |
+| 31 | Резерв назначения | `0x02 / 0x0F` | `0x1F00…0x1F42` | `0x12F41F00` |
+
+## Назначения mode из periph_28335
+
+Источники: `28335_periph/Source/Internal/Include/package.h`, `peripher.c:get_Mode()`, `cntrl_adr.c`. Код платы `Desk` не участвует в вычислении адреса.
+
+| mode | Назначение | Исходный символ |
+|---:|---|---|
+| 0 | Резерв | Перемычками текущей платы не задаётся |
+| 1 / 2 | Трансформаторные узлы 1 / 2 | `adr_TRN1 / adr_TRN2` |
+| 3 / 4 | Силовые узлы 1 / 2 | `adr_POW1 / adr_POW2` |
+| 5 / 6 | УМП1 / УМП2 | `adr_LOA1 / adr_LOA2`, `Desk=dsk_LOAD=6` |
+| 7 | ENG1 | `adr_ENG1` |
+| 8 | Задатчик / пульт | `adr_PULT`; имя «Задатчик» принято в реестре PERIPH |
+| 9 | Шкаф | `adr_SHKF` |
+| 10 | Общий адрес, служебная роль | `CNTRL_ADDR_UNIVERSAL`, `ADDR_FOR_ALL`; не отдельная плата |
+| 11 | Терминал, служебная роль | `ADDR_TERMINAL`; не доказательство отдельной платы |
+| 12…31 | Резерв назначения | Перемычки текущей платы дают только 1…16 |
+
+## Соответствия native-сервисам PERIPH
+
+| Смещение n | Native-адрес | Назначение | Доступ |
+|---|---|---|---|
+| 0…127 | `0x0000…0x007F` | технологические данные, уставки, команды | по provider |
+| 128…143 | `0x1000…0x100F` | статус регистратора УМП | R |
+| 144…155 | `0x1200…0x120B` | паспорт прошивки | R |
+| 156…163 | `0x1300…0x1307` | защита УМП | W только `0x1302/0x1303` |
+| 164…167 | `0x1000…0x1003` | команды регистратора | по операции |
+| 168…199 | нет | резерв | отказ |
+
+`pcan_gas_slot_native()` принимает WordIndex=1…3; WordIndex=0 является маской
+и не переводится в регистр. Наличие сервиса, права и блокировку проверяет приложение.
+GAS 0x3 сохраняет собственные адреса подключённых регионов; эта проекция относится только к 0x4.
+Архив УМП, окна 120/124 слова и физическая EEPROM сохраняют native-контракты.
+
+## Реализация и реестр
+
+- GAS 0x3: `pcan_gas.h/.c`, существующие ABI и клиенты.
+- GAS SLOT 0x4: `pcan_gas_slot.h/.c`; тонкие Python `GasSlots` и Android/JNI `GasSlots`.
+- Формат определяется MsgType, параметр `gas_profile` не используется.
+- C28x хранит wire-октеты в `uint_least8_t`; DLC измеряется октетами линии.
+- Перенос в другую единицу адресации или fallback после отказа запрещены.
+
+XLSX «Интерфейс протокола» содержит оба типа; «Общее адресное пространство» —
+проекцию 0x4 и native-адреса её значений; «ОАП legacy» сохраняет исходный словный реестр 0x3.
+Уникальный ключ реестра включает узел, MsgType, адрес и для 0x4 WordIndex.
+Права, тип, единица, масштаб и порядок слов u32/float32 задаются явно.
+Эталоны: `examples/gas-slot-vectors.json`; регистровые проверки — `test_gas_register.c`.
diff --git a/doc/setcan/protocan/PROTOCOL.md b/doc/setcan/protocan/PROTOCOL.md
index aea4627..644c707 100644
--- a/doc/setcan/protocan/PROTOCOL.md
+++ b/doc/setcan/protocan/PROTOCOL.md
@@ -1,7 +1,7 @@
# ProtoCAN — базовый протокол
Статус: **Stable с зарезервированным загрузочным расширением**
-Версия: **1.0**
+Версия: **2.1: GAS 0x3 и масочный GAS SLOT 0x4**
Порядок байтов payload: **little-endian**, если явно не указано иное
## Назначение
@@ -59,8 +59,8 @@ can_id =
| `0x0` | `BROADCAST` | ПМ → все | зависит от команды | stable |
| `0x1` | `DISCRETE` | оба | 0…8 | stable |
| `0x2` | `ANALOG` | оба | 0…8 | stable |
-| `0x3` | `GAS` | оба | 0/2/4/6/8 | stable |
-| `0x4` | `MODBUS_COIL` | оба | 0…8 | stable |
+| `0x3` | `GAS` | оба | 0/2/4/6/8 | регистры 0…65535 |
+| `0x4` | `GAS_SLOT` | оба | 0/8 | Word0 — маска, Word1…Word3 — значения |
| `0x5` | `MODBUS_DISCRETE` | оба | 0…8 | stable |
| `0x6` | `MODBUS_HOLDING` | оба | 0…8 | stable |
| `0x7` | `MODBUS_INPUT` | оба | 0…8 | stable |
@@ -82,14 +82,21 @@ can_id =
| broadcast | команда `[15:4]`, параметр `[3:0]` |
| discrete/analog | подтип `[15:12]`, значение/адрес `[11:0]` |
| Modbus | начальный адрес `[15:4]`, количество `[3:0]` |
-| GAS | адрес первого 16-битного регистра `[15:0]` |
+| GAS 0x3 | адрес первого 16-битного регистра `[15:0]` |
+| GAS SLOT 0x4 | адрес слота `[15:0]`; маска — в Word0 payload, значения — Word1…Word3 |
| error | дополнительная информация `[15:8]`, код `[7:0]` |
| settings | номер сборки `[15:8]`, позиция `[7:0]` |
| boot control/status | `SessionID[15:8]`, команда `[7:0]` |
| boot data | `BlockIndex[15:0]` |
+Контракт обоих GAS: [OAP.md](OAP.md). Тип 0x3 адресует отдельные слова; тип 0x4 имеет маску битов 1…3 в Word0 и три значения. Для PERIPH 0x4 используются 67 слотов `0xMM00…0xMM42`, последний содержит два значения. Старый Coil 0x4 заменён; формат определяется MsgType.
+
## Общие правила обмена
+Профиль синхронизации часов и сообщения платы о завершении инициализации:
+[GLOBAL_TIME.md](GLOBAL_TIME.md). Он сохраняет штатный BROADCAST RTCSETUP
+и определяет общий пакет готовности поверх DISCRETE/FLAGS.
+
- Многобайтовые значения в `DATA` передаются little-endian.
- Узел игнорирует адресованные кадры с чужим `DeviceType/DeviceID`.
- Прибор принимает команды ПМ с `Route=0`; ПМ принимает ответы с `Route=1`.
diff --git a/doc/setcan/protocan/README.md b/doc/setcan/protocan/README.md
index 841978e..b696bdb 100644
--- a/doc/setcan/protocan/README.md
+++ b/doc/setcan/protocan/README.md
@@ -1,8 +1,8 @@
# Документация ProtoCAN
Статус комплекта: **Draft**
-Версия комплекта: **1.0**
-Дата редакции: **2026-08-29**
+Версия комплекта: **2.1**
+Дата редакции: **2026-10-23**
Транспорт: **Classic CAN 2.0B, Extended ID, DLC 0…8**
Этот каталог разделяет нормативное описание протокола, загрузчик и реестр
@@ -41,3 +41,7 @@
Все документы и тестовые векторы включаются в единый файл
`doc/setcan/index.html`.
Скрипт не изменяет исходные Markdown/XLSX и пригоден для запуска в CI.
+
+## GAS: регистры 0x3 и слоты 0x4
+
+[Адресация GAS](OAP.md): `0x3` — отдельные 16-битные регистры `0…65535`, запись 1…4 слов. `0x4` — слот с Word0-маской и тремя значениями; PERIPH сохраняет 200 слов в 67 слотах `0xMM00…0xMM42`. Формат определяется MsgType, без настройки профиля.
diff --git a/doc/setcan/Протокол CAN и ОАП.html b/doc/setcan/Протокол CAN и ОАП.html
index e4c7fbc..2c53c82 100644
--- a/doc/setcan/Протокол CAN и ОАП.html
+++ b/doc/setcan/Протокол CAN и ОАП.html
@@ -1,32 +1,259 @@
-
-
-
-
-
-Протокол CAN и ОАП
-
-
-Протокол CAN и ОАП
+ProtoCAN — GAS 0x3 и GAS SLOT 0x4Протокол CAN и ОАП
Таблицы перенесены из Протокол CAN и ОАП.xlsx. Цвета, объединённые ячейки и структура листов сохранены средствами HTML внутри Markdown.
+Адреса PERIPH обновлены по листу «Интерфейс протокола», A44:F79:
+Type 0x01 содержит PERIPH 0–15, Type 0x02 — PERIPH 16–31;
+Device ID равен младшим четырём битам номера PERIPH.
+УМП1 — 0x01/0x05, УМП2 — 0x01/0x06, задатчик — 0x01/0x08.
+Назначения остальных mode уточнены по periph_28335: 1/2 — трансформаторы, 3/4 — силовые узлы, 7 — ENG1, 9 — шкаф; 10/11 — служебные роли. Общий Boot-адрес 0x03/0x07 отменён.
+Полный реестр назначений применяется и к загрузчику, и к GUI.
-
+
+
+GAS: регистры 0x3 и масочные слоты 0x4
+Нормативная спецификация: OAP.md. GAS 0x3: адрес первого регистра 0…65535, DLC 0/2/4/6/8. GAS SLOT 0x4: Word0 — маска битов 1…3, Word1…Word3 — три значения, DLC 0/8. PERIPH сохраняет 200 значений в 67 слотах; последний содержит два. Словный реестр ниже сохраняет адреса GAS 0x3.
+
+
+
+| mode |
+Назначение |
+Type / ID |
+Слоты 0x4 |
+CAN запрос |
+
+
+
+
+| 0 |
+Резерв |
+0x01 / 0x00 |
+0x0000…0x0042 |
+0x11040000 |
+
+
+| 1 |
+Трансформатор 1 |
+0x01 / 0x01 |
+0x0100…0x0142 |
+0x11140100 |
+
+
+| 2 |
+Трансформатор 2 |
+0x01 / 0x02 |
+0x0200…0x0242 |
+0x11240200 |
+
+
+| 3 |
+Силовой узел 1 |
+0x01 / 0x03 |
+0x0300…0x0342 |
+0x11340300 |
+
+
+| 4 |
+Силовой узел 2 |
+0x01 / 0x04 |
+0x0400…0x0442 |
+0x11440400 |
+
+
+| 5 |
+УМП1 |
+0x01 / 0x05 |
+0x0500…0x0542 |
+0x11540500 |
+
+
+| 6 |
+УМП2 |
+0x01 / 0x06 |
+0x0600…0x0642 |
+0x11640600 |
+
+
+| 7 |
+ENG1 |
+0x01 / 0x07 |
+0x0700…0x0742 |
+0x11740700 |
+
+
+| 8 |
+Задатчик / пульт |
+0x01 / 0x08 |
+0x0800…0x0842 |
+0x11840800 |
+
+
+| 9 |
+Шкаф |
+0x01 / 0x09 |
+0x0900…0x0942 |
+0x11940900 |
+
+
+| 10 |
+Общий адрес: служебная роль |
+0x01 / 0x0A |
+0x0A00…0x0A42 |
+0x11A40A00 |
+
+
+| 11 |
+Терминал: служебная роль |
+0x01 / 0x0B |
+0x0B00…0x0B42 |
+0x11B40B00 |
+
+
+| 12 |
+Резерв назначения |
+0x01 / 0x0C |
+0x0C00…0x0C42 |
+0x11C40C00 |
+
+
+| 13 |
+Резерв назначения |
+0x01 / 0x0D |
+0x0D00…0x0D42 |
+0x11D40D00 |
+
+
+| 14 |
+Резерв назначения |
+0x01 / 0x0E |
+0x0E00…0x0E42 |
+0x11E40E00 |
+
+
+| 15 |
+Резерв назначения |
+0x01 / 0x0F |
+0x0F00…0x0F42 |
+0x11F40F00 |
+
+
+| 16 |
+Резерв назначения |
+0x02 / 0x00 |
+0x1000…0x1042 |
+0x12041000 |
+
+
+| 17 |
+Резерв назначения |
+0x02 / 0x01 |
+0x1100…0x1142 |
+0x12141100 |
+
+
+| 18 |
+Резерв назначения |
+0x02 / 0x02 |
+0x1200…0x1242 |
+0x12241200 |
+
+
+| 19 |
+Резерв назначения |
+0x02 / 0x03 |
+0x1300…0x1342 |
+0x12341300 |
+
+
+| 20 |
+Резерв назначения |
+0x02 / 0x04 |
+0x1400…0x1442 |
+0x12441400 |
+
+
+| 21 |
+Резерв назначения |
+0x02 / 0x05 |
+0x1500…0x1542 |
+0x12541500 |
+
+
+| 22 |
+Резерв назначения |
+0x02 / 0x06 |
+0x1600…0x1642 |
+0x12641600 |
+
+
+| 23 |
+Резерв назначения |
+0x02 / 0x07 |
+0x1700…0x1742 |
+0x12741700 |
+
+
+| 24 |
+Резерв назначения |
+0x02 / 0x08 |
+0x1800…0x1842 |
+0x12841800 |
+
+
+| 25 |
+Резерв назначения |
+0x02 / 0x09 |
+0x1900…0x1942 |
+0x12941900 |
+
+
+| 26 |
+Резерв назначения |
+0x02 / 0x0A |
+0x1A00…0x1A42 |
+0x12A41A00 |
+
+
+| 27 |
+Резерв назначения |
+0x02 / 0x0B |
+0x1B00…0x1B42 |
+0x12B41B00 |
+
+
+| 28 |
+Резерв назначения |
+0x02 / 0x0C |
+0x1C00…0x1C42 |
+0x12C41C00 |
+
+
+| 29 |
+Резерв назначения |
+0x02 / 0x0D |
+0x1D00…0x1D42 |
+0x12D41D00 |
+
+
+| 30 |
+Резерв назначения |
+0x02 / 0x0E |
+0x1E00…0x1E42 |
+0x12E41E00 |
+
+
+| 31 |
+Резерв назначения |
+0x02 / 0x0F |
+0x1F00…0x1F42 |
+0x12F41F00 |
+
+
+
Прошивка приборов по CAN
-Ниже зафиксирован формат планируемого загрузочного сервиса. Значения
-MsgType=0x9..0xD зарезервированы в протоколе, но обработчики загрузчика в
-текущих protocan.c/.h ещё не реализованы.
+Загрузчик MsgType=0x9…0xD реализован в c/protocan-boot. Актуальные команды, A/B и single-slot: BOOTLOADER.md. Ниже сохранена историческая таблица; при расхождении применяется актуальная спецификация.
Загрузчик работает поверх classic CAN 2.0B с Extended ID. Управляющий модуль
использует Route=0, прибор отвечает с Route=1. Команды стирания и записи
всегда должны быть адресованы конкретной паре DeviceType/DeviceID;
@@ -704,8 +931,8 @@ DATA[4..7] RunningCRC32, uint32 little-endian
| 0x1. Стандартный |
0х1. Устройство |
-0x1 |
-0x0 - 0xF устройств |
+0x01 PERIPH |
+0x0–0xF; PERIPH 0–15 0x5: УМП1; 0x6: УМП2; 0x8: Задатчик |
0x1. Запрос на вкл/выкл |
Выбор "страницы" из 64 устройств (Битовые флаги в Data) |
|
@@ -716,8 +943,8 @@ DATA[4..7] RunningCRC32, uint32 little-endian
| |
|
-0x2 |
-0x0 - 0xF устройств |
+0x02 PERIPH |
+0x0–0xF; PERIPH 16–31 |
0x2. Рестарт устройств |
Выбор "страницы" из 64 устройств (Битовые флаги в Data) |
|
@@ -955,14 +1182,14 @@ DATA[4..7] RunningCRC32, uint32 little-endian
|
|
0x3. Общее адресное пространство |
-Адрес регистра (Стартовый адрес, если DLC COUNT > 2) (0, 0x0000 - 65535, 0xFFFF) |
+GAS: адрес первого 16-битного регистра 0x0000…0xFFFF; до четырёх последовательных значений. |
|
0/2/4/6/8 |
|
-Четвёртый регистр |
-Третий регистр |
-Второй регистр |
-Первый регистр |
+Регистр addr+3 |
+Регистр addr+2 |
+Регистр addr+1 |
+Регистр addr+0 |
| |
@@ -971,13 +1198,12 @@ DATA[4..7] RunningCRC32, uint32 little-endian
|
|
|
-0x4. Modbus Coil |
-Стартовый адрес регистра (0x0 - 0xFFF) |
-Кол-во регистров (0-15) |
+0x4. GAS SLOT |
+Адрес слота 0x0000…0xFFFF |
|
- |
+0/8 |
|
-NULL |
+Word3 | Word2 | Word1 | Word0: маска битов 1…3 |
| |
@@ -1421,8 +1647,8 @@ DATA[4..7] RunningCRC32, uint32 little-endian