diff --git a/Doc/GAS_ADDRESS_ALLOCATION.md b/Doc/GAS_ADDRESS_ALLOCATION.md new file mode 100644 index 0000000..da59606 --- /dev/null +++ b/Doc/GAS_ADDRESS_ALLOCATION.md @@ -0,0 +1,97 @@ +# Сквозная нумерация GAS: распределение адресов + +Дата: **9 октября 2026 года**. + +УКСС выделен диапазон **0…11999**: общий блок 0 и блоки узлов 1…11, по **1000 ID** каждый. Соответствие технологических слов Modbus текущему профилю 167/v1 и новым ID УМП приведено в [GAS_MODBUS_MAP.md](GAS_MODBUS_MAP.md). Новая нумерация назначена в документации; в прошивке пока действует профиль 167/v1. + +## Диапазоны проектов + +В новой схеме числа без префикса `0x` — **десятичные**. Каждому номеру узла соответствует блок 1000 адресов с базой `номер × 1000`. + +| Проект / семейство | Первый ID | Последний ID включительно | Число адресов | Статус | +|---|---:|---:|---:|---| +| УКСС | 0 | 11999 | 12000 | Выделено: 12 блоков по 1000 ID | +| Остальные проекты | 12000 | 65535 | 53536 | Свободно для последующего распределения | + +Границы УКСС в hex: `0x0000…0x2EDF`; свободная область начинается с `0x2EE0`. + +Резерв диапазона не означает, что каждый адрес уже реализован. Адреса обозначают логические 16-битные слова; память для незадействованных ID не выделяется. Параметр шириной 32 бита занимает два последовательных слова. Служебные слова также должны входить в выделенный диапазон проекта. + +## Узлы УКСС + +Номера узлов: **1…11**; **5 и 6 — УМП**. Назначения 1…9 подтверждены в [package.h](../Source/Internal/Include/package.h); служебные адреса 10/11 определены в [cntrl_adr.c](../Source/Internal/cntrl_adr.c). + +| Номер | Назначение в текущем коде | Обозначение | +|---:|---|---| +| 1 | Трансформаторный узел 1 | `adr_TRN1` | +| 2 | Трансформаторный узел 2 | `adr_TRN2` | +| 3 | Силовой узел 1 | `adr_POW1` | +| 4 | Силовой узел 2 | `adr_POW2` | +| 5 | УМП 1, LOAD | `adr_LOA1` | +| 6 | УМП 2, LOAD | `adr_LOA2` | +| 7 | Узел ENG1 | `adr_ENG1` | +| 8 | Пульт | `adr_PULT` | +| 9 | Шкаф | `adr_SHKF` | +| 10 | Универсальный адрес / адрес общей посылки | `CNTRL_ADDR_UNIVERSAL`, `ADDR_FOR_ALL` | +| 11 | Адрес терминала | `ADDR_TERMINAL` | + +Номер узла, тип платы `Desk` и ID параметра GAS — отдельные величины. Например, УМП 1 имеет `Mode = 5`, а тип обеих плат УМП равен `dsk_LOAD = 6`. Блок номера 10 зарезервирован для роли общего адреса; существующий номер 10 не идентифицирует отдельную физическую плату. + +## Назначенные блоки УКСС + +Границы включительные. Все блоки содержат по 1000 слов, пересечений нет. + +| Область | Первый ID, dec | Последний ID, dec | База, hex | +|---|---:|---:|---| +| Блок 0: общий резерв УКСС | 0 | 999 | `0x0000` | +| Трансформаторный узел 1, номер 1 | 1000 | 1999 | `0x03E8` | +| Трансформаторный узел 2, номер 2 | 2000 | 2999 | `0x07D0` | +| Силовой узел 1, номер 3 | 3000 | 3999 | `0x0BB8` | +| Силовой узел 2, номер 4 | 4000 | 4999 | `0x0FA0` | +| УМП 1, номер 5 | 5000 | 5999 | `0x1388` | +| УМП 2, номер 6 | 6000 | 6999 | `0x1770` | +| Узел ENG1, номер 7 | 7000 | 7999 | `0x1B58` | +| Пульт, номер 8 | 8000 | 8999 | `0x1F40` | +| Шкаф, номер 9 | 9000 | 9999 | `0x2328` | +| Резерв роли общего адреса, номер 10 | 10000 | 10999 | `0x2710` | +| Терминал, номер 11 | 11000 | 11999 | `0x2AF8` | + +Правило адресации: + +```text +GAS_ID = номер_узла × 1000 + смещение +номер_узла = 0…11 +смещение = 0…999 +``` + +## Технологические слова УМП + +Для штатного технологического Modbus-адреса `n = 0…127` в новой карте назначено смещение `n`: + +```text +УМП 1, номер 5: GAS_ID = 5000 + n → 5000…5127 +УМП 2, номер 6: GAS_ID = 6000 + n → 6000…6127 +``` + +| Параметр | Штатный Modbus, hex | УМП 1: новый GAS, dec | УМП 2: новый GAS, dec | +|---|---|---:|---:| +| Первое технологическое слово | `0x0000` | 5000 | 6000 | +| `DAC_go` | `0x0050` | 5080 | 6080 | +| `DAC_stop` | `0x0051` | 5081 | 6081 | +| `LOAD_CAN_TIMEOUT` | `0x0052` | 5082 | 6082 | +| `LOAD_STATUS` | `0x007C` | 5124 | 6124 | +| `LOAD_ATTEMPTS` | `0x007D` | 5125 | 6125 | +| `LastMode` | `0x007E` | 5126 | 6126 | +| `Commands` | `0x007F` | 5127 | 6127 | + +Смещения **128…999** в каждом блоке остаются резервом для расширений. Служебные параметры и новые данные в этих смещениях пока не назначены. Полная таблица всех 128 технологических слов: [GAS_MODBUS_MAP.md](GAS_MODBUS_MAP.md). + +## Связь с текущей прошивкой + +В существующей реализации база технологических GAS-регистров равна **`0x5000` = 20480**, а дескриптор находится на **`0x5F00` = 24320**. Это локальное окно профиля 167/v1, выбранное независимо от новой схемы сквозной нумерации. + +Текущее `0x5000` не означает `5 × 1000`: последнее вычисление даёт **5000 десятичных = `0x1388`**. Для адресации УМП 1 и УМП 2 по номеру узла потребуются разные базы, определяемые по `Mode`. + +Штатные адреса Modbus, служебные окна регистратора, паспорта, защиты и EEPROM уже имеют собственные значения. При переносе сквозной карты нужно определить соответствие GAS ↔ адрес протокола: глобальный ID может отличаться от прежнего Modbus-адреса. Это позволяет отдельно согласовать новую нумерацию и совместимость существующих клиентов. + +Диапазон УКСС и размеры блоков назначены. Перенос этих ID в обработчики прошивки и размещение служебных параметров в резерве — отдельные изменения реализации. diff --git a/Doc/GAS_MODBUS_MAP.md b/Doc/GAS_MODBUS_MAP.md new file mode 100644 index 0000000..ca9a56a --- /dev/null +++ b/Doc/GAS_MODBUS_MAP.md @@ -0,0 +1,267 @@ +# GAS ↔ Modbus: карта регистров Бальзам 167 + +Профиль: **GAS 167/v1**. Соответствие проверено по исходникам проекта на **9 октября 2026 года**. + +УКСС выделен сквозной диапазон **0…11999** с блоком **1000 ID** на номер узла: [GAS_ADDRESS_ALLOCATION.md](GAS_ADDRESS_ALLOCATION.md). В полной таблице приведены текущие адреса прошивки 167/v1 и новые назначенные ID УМП 1/2. Новая нумерация пока не перенесена в прошивку. + +GAS предоставляет доступ к тем же значениям `modbus[]`, что и штатные адреса Modbus. В Modbus RTU можно обращаться как по прежнему адресу `0x0000…0x007F`, так и по GAS-адресу `0x5000…0x507F`. Это два адреса одного слова RAM; отдельной копии параметров нет. + +**GAS доступен только при `EEPROM_M95M02=1`.** В текущем [eeprom_config.h](../Source/Internal/Include/eeprom_config.h) по умолчанию задано `0` — сборка для AT25256B, в которой GAS-окна отсутствуют. Фактическая сборка может переопределять этот параметр. + +## Правило соответствия + +```text +Для штатного адреса n = 0…127: + GAS-адрес = 0x5000 + n + Штатный Modbus = GAS-адрес - 0x5000 + Источник значения = modbus[n] + +Пример: modbus[0x52] → штатный адрес 0x0052 (82) + → GAS-адрес 0x5052 (20562) + +Новая сквозная карта (десятичные ID): + УМП 1, номер 5: GAS_ID = 5000 + n + УМП 2, номер 6: GAS_ID = 6000 + n + modbus[0x52] → УМП 1: 5082; УМП 2: 6082 +``` + +Столбцы Modbus и GAS 167/v1 содержат **нулевые адреса из поля запроса**, без прибавления единицы и без префикса `4xxxx`. Столбцы «Новый ID УМП 1/2» содержат назначенные ID новой сквозной карты; текущая прошивка ещё не обслуживает их как новые GAS-адреса. Каждый адрес обозначает одно **16-битное слово raw**. Знаковость, единицы и масштаб зависят от параметра и типа платы `Desk`; GAS передаёт исходное слово. + +| Область | Штатный Modbus | GAS / адрес обращения через Modbus RTU | Слова | Доступ | +|---|---|---|---:|---| +| Технологические регистры | `0x0000…0x007F` | `0x5000…0x507F` | 128 | RW с исключениями LOAD | +| Информация GAS-профиля | Нет штатного аналога | `0x5F00…0x5F07` | 8 | RO | + +`RW` в документе означает, что обработчик разрешает FC06. Измерения и статусы могут затем обновляться прошивкой; разрешение записи само по себе не делает такой регистр уставкой. `RO` означает, что обработчик отклоняет запись. + +## Полное соответствие 128 технологических регистров + +Имена взяты из [package.h](../Source/Internal/Include/package.h), [measure.c](../Source/Internal/measure.c), [ADC.c](../Source/Internal/ADC.c) и [DAC.c](../Source/Internal/DAC.c). Индексы `sens_*` начинаются с нуля. Конкретное назначение каналов зависит от платы; таблица не назначает всем платам одинаковые физические каналы. + +Перекрывающиеся имена относятся к одному слову и используются в разных режимах. Например, `0x0052` входит в общий диапазон `sens_lo_edge[]`, а на LOAD служит `LOAD_CAN_TIMEOUT`. + +| Modbus, hex | Modbus, dec | GAS 167/v1, hex | GAS 167/v1, dec | Новый ID УМП 1, dec | Новый ID УМП 2, dec | Имя / источник | Доступ | +|---|---:|---|---:|---:|---:|---|---| +| `0x0000` | 0 | `0x5000` | 20480 | 5000 | 6000 | `sens_error[0]`; `InputRep0/1/2` — биты A/B/C | RW | +| `0x0001` | 1 | `0x5001` | 20481 | 5001 | 6001 | `sens_error[1]` | RW | +| `0x0002` | 2 | `0x5002` | 20482 | 5002 | 6002 | `sens_error[2]` | RW | +| `0x0003` | 3 | `0x5003` | 20483 | 5003 | 6003 | `sens_error[3]` | RW | +| `0x0004` | 4 | `0x5004` | 20484 | 5004 | 6004 | `sens_error[4]` | RW | +| `0x0005` | 5 | `0x5005` | 20485 | 5005 | 6005 | `sens_error[5]` | RW | +| `0x0006` | 6 | `0x5006` | 20486 | 5006 | 6006 | `sens_error[6]` | RW | +| `0x0007` | 7 | `0x5007` | 20487 | 5007 | 6007 | `sens_error[7]` | RW | +| `0x0008` | 8 | `0x5008` | 20488 | 5008 | 6008 | `sens_error[8]` | RW | +| `0x0009` | 9 | `0x5009` | 20489 | 5009 | 6009 | `sens_error[9]` | RW | +| `0x000A` | 10 | `0x500A` | 20490 | 5010 | 6010 | `sens_error[10]` | RW | +| `0x000B` | 11 | `0x500B` | 20491 | 5011 | 6011 | `sens_error[11]` | RW | +| `0x000C` | 12 | `0x500C` | 20492 | 5012 | 6012 | `sens_error[12]` | RW | +| `0x000D` | 13 | `0x500D` | 20493 | 5013 | 6013 | `sens_error[13]` | RW | +| `0x000E` | 14 | `0x500E` | 20494 | 5014 | 6014 | `sens_error[14]` | RW | +| `0x000F` | 15 | `0x500F` | 20495 | 5015 | 6015 | `sens_error[15]` | RW | +| `0x0010` | 16 | `0x5010` | 20496 | 5016 | 6016 | `sens_error[16]`; `Inputs` | RW | +| `0x0011` | 17 | `0x5011` | 20497 | 5017 | 6017 | `sens_error[17]` | RW | +| `0x0012` | 18 | `0x5012` | 20498 | 5018 | 6018 | `sens_error[18]` | RW | +| `0x0013` | 19 | `0x5013` | 20499 | 5019 | 6019 | `sens_error[19]` | RW | +| `0x0014` | 20 | `0x5014` | 20500 | 5020 | 6020 | `sens_error[20]` | RW | +| `0x0015` | 21 | `0x5015` | 20501 | 5021 | 6021 | `sens_error[21]` | RW | +| `0x0016` | 22 | `0x5016` | 20502 | 5022 | 6022 | `sens_error[22]`; `Buttons` | RW | +| `0x0017` | 23 | `0x5017` | 20503 | 5023 | 6023 | `sens_error[23]`; `Jumpers` | RW | +| `0x0018` | 24 | `0x5018` | 20504 | 5024 | 6024 | `sens_data[0]` | RW | +| `0x0019` | 25 | `0x5019` | 20505 | 5025 | 6025 | `sens_data[1]` | RW | +| `0x001A` | 26 | `0x501A` | 20506 | 5026 | 6026 | `sens_data[2]` | RW | +| `0x001B` | 27 | `0x501B` | 20507 | 5027 | 6027 | `sens_data[3]` | RW | +| `0x001C` | 28 | `0x501C` | 20508 | 5028 | 6028 | `sens_data[4]`; LOAD: расчётный выход 4–20 мА, raw ×10 | RW | +| `0x001D` | 29 | `0x501D` | 20509 | 5029 | 6029 | `sens_data[5]`; LOAD: измеренный вход 4–20 мА, raw ×10 | RW | +| `0x001E` | 30 | `0x501E` | 20510 | 5030 | 6030 | `sens_data[6]` | RW | +| `0x001F` | 31 | `0x501F` | 20511 | 5031 | 6031 | `sens_data[7]` | RW | +| `0x0020` | 32 | `0x5020` | 20512 | 5032 | 6032 | `sens_data[8]` | RW | +| `0x0021` | 33 | `0x5021` | 20513 | 5033 | 6033 | `sens_data[9]` | RW | +| `0x0022` | 34 | `0x5022` | 20514 | 5034 | 6034 | `sens_data[10]` | RW | +| `0x0023` | 35 | `0x5023` | 20515 | 5035 | 6035 | `sens_data[11]` | RW | +| `0x0024` | 36 | `0x5024` | 20516 | 5036 | 6036 | `sens_data[12]` | RW | +| `0x0025` | 37 | `0x5025` | 20517 | 5037 | 6037 | `sens_data[13]` | RW | +| `0x0026` | 38 | `0x5026` | 20518 | 5038 | 6038 | `sens_data[14]` | RW | +| `0x0027` | 39 | `0x5027` | 20519 | 5039 | 6039 | `sens_data[15]` | RW | +| `0x0028` | 40 | `0x5028` | 20520 | 5040 | 6040 | `sens_data[16]` | RW | +| `0x0029` | 41 | `0x5029` | 20521 | 5041 | 6041 | `sens_data[17]` | RW | +| `0x002A` | 42 | `0x502A` | 20522 | 5042 | 6042 | `sens_data[18]` | RW | +| `0x002B` | 43 | `0x502B` | 20523 | 5043 | 6043 | `sens_data[19]` | RW | +| `0x002C` | 44 | `0x502C` | 20524 | 5044 | 6044 | `sens_data[20]` | RW | +| `0x002D` | 45 | `0x502D` | 20525 | 5045 | 6045 | `sens_data[21]` | RW | +| `0x002E` | 46 | `0x502E` | 20526 | 5046 | 6046 | `sens_data[22]` | RW | +| `0x002F` | 47 | `0x502F` | 20527 | 5047 | 6047 | `sens_data[23]` | RW | +| `0x0030` | 48 | `0x5030` | 20528 | 5048 | 6048 | `sens_hi_edge[0]` | RW | +| `0x0031` | 49 | `0x5031` | 20529 | 5049 | 6049 | `sens_hi_edge[1]` | RW | +| `0x0032` | 50 | `0x5032` | 20530 | 5050 | 6050 | `sens_hi_edge[2]` | RW | +| `0x0033` | 51 | `0x5033` | 20531 | 5051 | 6051 | `sens_hi_edge[3]` | RW | +| `0x0034` | 52 | `0x5034` | 20532 | 5052 | 6052 | `sens_hi_edge[4]` | RW | +| `0x0035` | 53 | `0x5035` | 20533 | 5053 | 6053 | `sens_hi_edge[5]` | RW | +| `0x0036` | 54 | `0x5036` | 20534 | 5054 | 6054 | `sens_hi_edge[6]` | RW | +| `0x0037` | 55 | `0x5037` | 20535 | 5055 | 6055 | `sens_hi_edge[7]` | RW | +| `0x0038` | 56 | `0x5038` | 20536 | 5056 | 6056 | `sens_hi_edge[8]` | RW | +| `0x0039` | 57 | `0x5039` | 20537 | 5057 | 6057 | `sens_hi_edge[9]` | RW | +| `0x003A` | 58 | `0x503A` | 20538 | 5058 | 6058 | `sens_hi_edge[10]` | RW | +| `0x003B` | 59 | `0x503B` | 20539 | 5059 | 6059 | `sens_hi_edge[11]` | RW | +| `0x003C` | 60 | `0x503C` | 20540 | 5060 | 6060 | `sens_hi_edge[12]` | RW | +| `0x003D` | 61 | `0x503D` | 20541 | 5061 | 6061 | `sens_hi_edge[13]` | RW | +| `0x003E` | 62 | `0x503E` | 20542 | 5062 | 6062 | `sens_hi_edge[14]` | RW | +| `0x003F` | 63 | `0x503F` | 20543 | 5063 | 6063 | `sens_hi_edge[15]` | RW | +| `0x0040` | 64 | `0x5040` | 20544 | 5064 | 6064 | `sens_hi_edge[16]` | RW | +| `0x0041` | 65 | `0x5041` | 20545 | 5065 | 6065 | `sens_hi_edge[17]` | RW | +| `0x0042` | 66 | `0x5042` | 20546 | 5066 | 6066 | `sens_hi_edge[18]` | RW | +| `0x0043` | 67 | `0x5043` | 20547 | 5067 | 6067 | `sens_hi_edge[19]` | RW | +| `0x0044` | 68 | `0x5044` | 20548 | 5068 | 6068 | `sens_hi_edge[20]` | RW | +| `0x0045` | 69 | `0x5045` | 20549 | 5069 | 6069 | `sens_hi_edge[21]` | RW | +| `0x0046` | 70 | `0x5046` | 20550 | 5070 | 6070 | `sens_hi_edge[22]` | RW | +| `0x0047` | 71 | `0x5047` | 20551 | 5071 | 6071 | `sens_hi_edge[23]` | RW | +| `0x0048` | 72 | `0x5048` | 20552 | 5072 | 6072 | `sens_lo_edge[0]` | RW | +| `0x0049` | 73 | `0x5049` | 20553 | 5073 | 6073 | `sens_lo_edge[1]` | RW | +| `0x004A` | 74 | `0x504A` | 20554 | 5074 | 6074 | `sens_lo_edge[2]` | RW | +| `0x004B` | 75 | `0x504B` | 20555 | 5075 | 6075 | `sens_lo_edge[3]` | RW | +| `0x004C` | 76 | `0x504C` | 20556 | 5076 | 6076 | `sens_lo_edge[4]` | RW | +| `0x004D` | 77 | `0x504D` | 20557 | 5077 | 6077 | `sens_lo_edge[5]` | RW | +| `0x004E` | 78 | `0x504E` | 20558 | 5078 | 6078 | `sens_lo_edge[6]` | RW | +| `0x004F` | 79 | `0x504F` | 20559 | 5079 | 6079 | `sens_lo_edge[7]` | RW | +| `0x0050` | 80 | `0x5050` | 20560 | 5080 | 6080 | `sens_lo_edge[8]`; LOAD: `DAC_go` — параметр начала рампы | RW | +| `0x0051` | 81 | `0x5051` | 20561 | 5081 | 6081 | `sens_lo_edge[9]`; LOAD: `DAC_stop` — параметр конца рампы | RW | +| `0x0052` | 82 | `0x5052` | 20562 | 5082 | 6082 | `sens_lo_edge[10]`; LOAD: `LOAD_CAN_TIMEOUT`, мс | RW; LOAD: 1…60000 | +| `0x0053` | 83 | `0x5053` | 20563 | 5083 | 6083 | `sens_lo_edge[11]` | RW | +| `0x0054` | 84 | `0x5054` | 20564 | 5084 | 6084 | `sens_lo_edge[12]` | RW | +| `0x0055` | 85 | `0x5055` | 20565 | 5085 | 6085 | `sens_lo_edge[13]` | RW | +| `0x0056` | 86 | `0x5056` | 20566 | 5086 | 6086 | `sens_lo_edge[14]` | RW | +| `0x0057` | 87 | `0x5057` | 20567 | 5087 | 6087 | `sens_lo_edge[15]` | RW | +| `0x0058` | 88 | `0x5058` | 20568 | 5088 | 6088 | `sens_lo_edge[16]` | RW | +| `0x0059` | 89 | `0x5059` | 20569 | 5089 | 6089 | `sens_lo_edge[17]` | RW | +| `0x005A` | 90 | `0x505A` | 20570 | 5090 | 6090 | `sens_lo_edge[18]` | RW | +| `0x005B` | 91 | `0x505B` | 20571 | 5091 | 6091 | `sens_lo_edge[19]` | RW | +| `0x005C` | 92 | `0x505C` | 20572 | 5092 | 6092 | `sens_lo_edge[20]` | RW | +| `0x005D` | 93 | `0x505D` | 20573 | 5093 | 6093 | `sens_lo_edge[21]` | RW | +| `0x005E` | 94 | `0x505E` | 20574 | 5094 | 6094 | `sens_lo_edge[22]` | RW | +| `0x005F` | 95 | `0x505F` | 20575 | 5095 | 6095 | `sens_lo_edge[23]` | RW | +| `0x0060` | 96 | `0x5060` | 20576 | 5096 | 6096 | `Cancount[m_FAST]` — пауза быстрых посылок CAN | RW | +| `0x0061` | 97 | `0x5061` | 20577 | 5097 | 6097 | `Cancount[m_SLOW]` — пауза медленных посылок CAN | RW | +| `0x0062` | 98 | `0x5062` | 20578 | 5098 | 6098 | `Brightness` / `Bright[0]` — яркость | RW | +| `0x0063` | 99 | `0x5063` | 20579 | 5099 | 6099 | `Owncount` / `Bright[1]`; LOAD: исходное значение АЦП | RW | +| `0x0064` | 100 | `0x5064` | 20580 | 5100 | 6100 | `Bright[2]`; `Current_count`: исходное значение канала 0 | RW | +| `0x0065` | 101 | `0x5065` | 20581 | 5101 | 6101 | `Bright[3]`; `Current_count`: исходное значение канала 1 | RW | +| `0x0066` | 102 | `0x5066` | 20582 | 5102 | 6102 | `Bright[4]`; `Current_count`: исходное значение канала 2 | RW | +| `0x0067` | 103 | `0x5067` | 20583 | 5103 | 6103 | `Bright[5]`; `Current_count`: исходное значение канала 3 | RW | +| `0x0068` | 104 | `0x5068` | 20584 | 5104 | 6104 | `lev_count[]`, запись из `Current_count`; назначение по режиму | RW | +| `0x0069` | 105 | `0x5069` | 20585 | 5105 | 6105 | `lev_count[]`, запись из `Current_count`; назначение по режиму | RW | +| `0x006A` | 106 | `0x506A` | 20586 | 5106 | 6106 | `lev_count[]`, запись из `Current_count`; назначение по режиму | RW | +| `0x006B` | 107 | `0x506B` | 20587 | 5107 | 6107 | `lev_count[]`, запись из `Current_count`; назначение по режиму | RW | +| `0x006C` | 108 | `0x506C` | 20588 | 5108 | 6108 | `lev_count[]`, запись из `Current_count`; назначение по режиму | RW | +| `0x006D` | 109 | `0x506D` | 20589 | 5109 | 6109 | `lev_count[]`, запись из `Current_count`; назначение по режиму | RW | +| `0x006E` | 110 | `0x506E` | 20590 | 5110 | 6110 | `DAC_20` — калибровка входа 20 мА | RW | +| `0x006F` | 111 | `0x506F` | 20591 | 5111 | 6111 | `DAC_04` — калибровка входа 4 мА | RW | +| `0x0070` | 112 | `0x5070` | 20592 | 5112 | 6112 | `Zero_lev[0]` — нулевой уровень канала тока 0 | RW | +| `0x0071` | 113 | `0x5071` | 20593 | 5113 | 6113 | `Zero_lev[1]` — нулевой уровень канала тока 1 | RW | +| `0x0072` | 114 | `0x5072` | 20594 | 5114 | 6114 | `Zero_lev[2]` — нулевой уровень канала тока 2 | RW | +| `0x0073` | 115 | `0x5073` | 20595 | 5115 | 6115 | `Zero_lev[3]` — нулевой уровень канала тока 3 | RW | +| `0x0074` | 116 | `0x5074` | 20596 | 5116 | 6116 | `Caliber[0]`: `K380_1` / `KPOW_1` | RW | +| `0x0075` | 117 | `0x5075` | 20597 | 5117 | 6117 | `Caliber[1]`: `K380_2` / `KPOW_2` | RW | +| `0x0076` | 118 | `0x5076` | 20598 | 5118 | 6118 | `Caliber[2]`: `KPOW_3` | RW | +| `0x0077` | 119 | `0x5077` | 20599 | 5119 | 6119 | `Caliber[3]`: `KPOW_4` | RW | +| `0x0078` | 120 | `0x5078` | 20600 | 5120 | 6120 | `Caliber[4]` / `TCaliber[0]`; LOAD: `DAC_max()` | RW | +| `0x0079` | 121 | `0x5079` | 20601 | 5121 | 6121 | `Caliber[5]` / `TCaliber[1]`; LOAD: `DAC_min()` | RW | +| `0x007A` | 122 | `0x507A` | 20602 | 5122 | 6122 | `Caliber[6]` / `TCaliber[2]`; LOAD: `DAC_cal()` | RW | +| `0x007B` | 123 | `0x507B` | 20603 | 5123 | 6123 | `Caliber[7]` / `TCaliber[3]`; LOAD: текущий 12-битный код ЦАП | RW | +| `0x007C` | 124 | `0x507C` | 20604 | 5124 | 6124 | `NormaU` = `Caliber[8]`; LOAD: `LOAD_STATUS` | RO для LOAD; иначе RW | +| `0x007D` | 125 | `0x507D` | 20605 | 5125 | 6125 | `DeltaU` = `Caliber[9]`; LOAD: `LOAD_ATTEMPTS` | RO для LOAD; иначе RW | +| `0x007E` | 126 | `0x507E` | 20606 | 5126 | 6126 | `LastMode` | RW | +| `0x007F` | 127 | `0x507F` | 20607 | 5127 | 6127 | `Commands` — битовая маска команд | RW | + +Слово `modbus[128]` в массиве используется для CRC сохраняемых параметров и **не входит** в эту карту. `0x5080` не является допустимым GAS-адресом. + +## Информация GAS-профиля + +Эти слова читаются через FC03 непосредственно по адресам `0x5F00…0x5F07`. Для них нет соответствующих штатных регистров `0x0000…0x007F`. + +| GAS = адрес Modbus, hex | Адрес, dec | Значение | Назначение | +|---|---:|---|---| +| `0x5F00` | 24320 | `0x4741` | Сигнатура `GA` | +| `0x5F01` | 24321 | `0x5331` | Сигнатура `S1` | +| `0x5F02` | 24322 | `1` | Версия контракта GAS | +| `0x5F03` | 24323 | `167` | Профиль устройства | +| `0x5F04` | 24324 | `0x5000` | База технологических GAS-регистров | +| `0x5F05` | 24325 | `128` | Число технологических регистров | +| `0x5F06` | 24326 | `0x0007` | Возможности: бит 0 — RTU, бит 1 — служебный CAN, бит 2 — FC06 | +| `0x5F07` | 24327 | `1` | Аппаратный вариант EEPROM M95M02 | + +Все восемь слов — **RO**. В сборке AT25256B GAS-адреса, включая этот блок, отклоняются с кодом недопустимого адреса. + +## Маски команд и состояния LOAD + +Регистр `Commands`: штатный Modbus **`0x007F`**, GAS **`0x507F`**. Операция FC06 записывает всё слово; обработчик вызывает `ump_log_rs()`. Смысл и выполнение команд определяет прошивка. + +| Бит | Маска | Имя в исходниках | +|---:|---|---| +| 0 | `0x0001` | `cTestLamp` | +| 1 | `0x0002` | `cDefParam` | +| 2 | `0x0004` | `cSaveParam` | +| 3 | `0x0008` | `cLoadParam` | +| 4 | `0x0010` | `cTermoCal` | +| 5 | `0x0020` | `cKoefCalc` | +| 6 | `0x0040` | `cUMPreset` | +| 7 | `0x0080` | `cUMPstart` | +| 8 | `0x0100` | `cInitDac` | +| 9 | `0x0200` | `cCalibrDac` | +| 10 | `0x0400` | `cSecretBt` | +| 11 | `0x0800` | `cLiteFire` | +| 12 | `0x1000` | `cRawMeat` | +| 13 | `0x2000` | Имя команды в package.h не задано | +| 14 | `0x4000` | Имя команды в package.h не задано | +| 15 | `0x8000` | `cReset` | + +Для `Desk == dsk_LOAD` регистр `LOAD_STATUS` (`0x007C` / `0x507C`) формируется в [DAC.c](../Source/Internal/DAC.c): + +| Бит | Маска | Смысл | +|---:|---|---| +| 0 | `0x0001` | Состояние `LOAD_FAULT`: ошибка после пяти попыток пуска | +| 1 | `0x0002` | Нет свежего напряжения ЗПТ | +| 2 | `0x0004` | Состояние `LOAD_RELOAD`: сброс перед повторным пуском | +| 3 | `0x0008` | Состояние `LOAD_RUN`: работа рампы | +| 4 | `0x0010` | Имитация потери ЗПТ: приём напряжения из CAN игнорируется | +| 5 | `0x0020` | Имитация 0 В для защиты; реальные значения CAN в логгере сохраняются | + +`LOAD_ATTEMPTS` (`0x007D` / `0x507D`) содержит число попыток пуска. Оба слова доступны только для чтения на LOAD. + +## Запросы и ограничения + +| Операция | Штатные адреса `0x0000…0x007F` | GAS-адреса | +|---|---|---| +| FC03 | 1…125 слов в пределах 128 регистров | 1…124 слова; весь блок внутри одного GAS-региона | +| FC06 | Одно 16-битное слово | Одно 16-битное слово; ответ сохраняет GAS-адрес | +| FC04 / FC16 | Не используются этими обработчиками для данной карты | GAS-provider поддерживает функции 3 и 6 | +| LOAD: запись `LOAD_STATUS`, `LOAD_ATTEMPTS` | Код 2 | Код 2 | +| LOAD: запись `LOAD_CAN_TIMEOUT` вне 1…60000 мс | Код 3 | Код 3 | + +GAS-provider возвращает код 1 для неподдерживаемой функции, код 2 для недопустимого адреса, пересечения границы или записи RO-блока; код 3 — для количества слов 0 или >124 и недопустимого LOAD-timeout. В RTU запросы к этой карте маршрутизируются обработчиками FC03/FC06. + +В RTU данные одного слова передаются старшим байтом вперёд. Формат ответа GAS-расширения отличается от исторического ответа низких адресов: у GAS нет дополнительных хвостовых нулей. + +Примеры ниже задают функцию, адрес и количество/значение; это параметры запроса, без адреса устройства и CRC: + +| Действие | Штатный Modbus | Через GAS | +|---|---|---| +| Прочитать информацию профиля | Нет аналога | `FC03(0x5F00, 8)` | +| Прочитать слово 0 | `FC03(0x0000, 1)` | `FC03(0x5000, 1)` | +| Прочитать все 128 слов | `FC03(0x0000, 125)` + `FC03(0x007D, 3)` | `FC03(0x5000, 124)` + `FC03(0x507C, 4)` | +| Прочитать timeout LOAD | `FC03(0x0052, 1)` | `FC03(0x5052, 1)` | +| Задать timeout LOAD = 1000 мс | `FC06(0x0052, 1000)` | `FC06(0x5052, 1000)` | +| Прочитать статус и попытки LOAD | `FC03(0x007C, 2)` | `FC03(0x507C, 2)` | + +Два запроса на чтение всей карты дают два отдельных снимка. FC06 меняет RAM; сохранение параметров в EEPROM выполняется штатным механизмом прошивки. + +Эти же GAS-адреса доступны через **служебный CAN УМП** с маркером `0x1F00`, token и функцией 3/6. CAN-чтение принимает чётное количество **2…124 слова**; каждый фрагмент ответа содержит два слова. Формат запроса приведён в [GAS_167_M95M02.md](GAS_167_M95M02.md). + +Другие расширения Modbus — регистратор `0x1000…0x117B`, паспорт `0x1200…0x120B`, защита `0x1300…0x1307` и EEPROM `0x8000…0xFFFF` — имеют собственные обработчики. Формула `GAS = 0x5000 + Modbus` применяется только к штатным **128 технологическим словам**. + +## Источники + +- [gas167.h](../Source/Internal/Include/gas167.h) — базы, размеры, версия и лимит GAS. +- [gas167.c](../Source/Internal/gas167.c) — прямое соответствие `modbus[]`, информация профиля и ограничения записи. +- [package.h](../Source/Internal/Include/package.h) — группы регистров, имена и маски команд. +- [message.c](../Source/Internal/message.c) — FC03/FC06, инициализация и сохранение параметров. +- [measure.c](../Source/Internal/measure.c), [ADC.c](../Source/Internal/ADC.c), [DAC.c](../Source/Internal/DAC.c) — значения измерений и особенности LOAD. +- [GAS_167_M95M02.md](GAS_167_M95M02.md) — включение GAS, форматы транспорта и проверки реализации.