# Поддержка передней панели Andromeda / G2 в EWSDR Ветка разработки: `feature/cat-commands-expansion`. Дата последнего обновления: 2026-06-26. Документ описывает поддержку аппаратной передней панели Apache Labs **Andromeda / ANAN-G2** (поворотные энкодеры, кнопки, LED-индикаторы, LCD). За эталон протокола взят Thetis (`Andromeda/Andromeda.cs`, `CAT/CATCommands.cs`). См. также [CAT_STATUS.md](CAT_STATUS.md) — общий статус CAT-подсистемы. --- ## 1. Что такое Andromeda и чем отличается от обычного CAT Andromeda — это **не отдельный набор команд**, а двунаправленный протокол панели поверх CAT-фрейминга. В отличие от обычного CAT (реактивный «запрос → ответ»), панель требует, чтобы хост **сам инициативно отправлял** обновления подсветки. ``` ZZZD/ZZZU/ZZZE/ZZZP/ZZZS (панель → хост: ввод) ┌─────────┐ ───────────────────────────► ┌──────────┐ │ Панель │ │ EWSDR │ │ G2 / │ ◄─────────────────────────── │ (хост) │ │Andromeda│ ZZZI / ZZMF / ZZZS; └──────────┘ └─────────┘ (хост → панель: подсветка, LCD, рукопожатие) ``` | Направление | Команды | Назначение | |---|---|---| | **Панель → хост** | `ZZZS` | панель сообщает версию HW/SW (рукопожатие) | | | `ZZZU` / `ZZZD` | энкодер VFO повёрнут вверх/вниз на nn шагов | | | `ZZZE` | энкодер #ee повёрнут (01–20 = +шаг, 51–70 = −шаг) | | | `ZZZP` | кнопка #bb: s=1 нажата, 2 long-press, 0 отпущена | | **Хост → панель** | `ZZZI` | LED-индикатор #nn (00–19) вкл (1)/выкл (0) | | | `ZZMF<30 цифр>` | текст мультифункц. энкодера на LCD (пока **не реализован**) | | | `ZZZS;` | запрос версии у панели | --- ## 2. Архитектура реализации Логика панели вынесена в отдельные юниты; в существующих файлах — только тонкие хуки. Зависимости однонаправленные, без циклов. ``` ┌────────────────────┐ serial-порт ──────► │ TCATEngine │ разбор ZZZ* → generic callbacks (Andromeda) │ (CATEngine.pas) │ (OnPanelVfoStep/Encoder/Button/Version) └─────────┬──────────┘ │ callbacks ┌─────────▼──────────┐ создаёт/связывает │ TCATAdapter │ ◄───────────────────┐ │ (CATAdapter.pas) │ │ └─────────┬──────────┘ │ SendProc (ZZZI/ZZZS;) │ ▲ AddStateListener │ на Andromeda-порт ▼ │ (push индикаторов) │ ┌────────────────────┐ ┌────────────┴───────┐ │ TAndromedaPanel │ ───────►│ TRadioController │ │ (AndromedaPanel.pas)│ Invoke │ (ядро) │ │ использует ▼ │ действия└────────────────────┘ │ AndromedaMap.pas │ (таблицы раскладки — только данные) └────────────────────┘ ``` | Файл | Роль | |---|---| | **`AndromedaMap.pas`** | Только данные: enum'ы `TAndButton` / `TAndEncoder` / `TAndIndicator`, дефолтные таблицы раскладки кнопок/энкодеров и номера LED (`ZZZI`). Без логики и зависимостей. | | **`AndromedaPanel.pas`** | `TAndromedaPanel` — «мозг»: входящие события → действия контроллера (свой маршалинг через `FController.Invoke`); подписка на состояние контроллера → построение `ZZZI` → отправка через callback `SendProc`. Зависит только от `RadioController` + `AndromedaMap`. | | `CATEngine.pas` | Разбор входящих `ZZZD/ZZZU/ZZZE/ZZZP/ZZZS` в 4 generic-callback'а `TCATContext`. Движок остаётся чистым парсером, про Andromeda «не знает». | | `CATAdapter.pas` | Тонкий клей: создаёт панель, маршрутизирует callback'и движка в неё, даёт `SendProc` на Andromeda-порт, регистрирует панель как слушателя состояния, инициирует рукопожатие. | | `CATSerial.pas` | Флаг `Andromeda` в конфиге порта + `HasAndromeda` / `SendToAndromeda`. | | `RadioController.pas` | `AddStateListener` — multicast-наблюдатель состояния (push не «ворует» единственный `OnStateChanged`, занятый MainForm). | | `Settings.pas` / `SettingsForm.pas` / `MainForm.pas` | Поле `CATSerialAndromeda[0..3]`, персист, чекбокс на каждом serial-порту. | ### Потоки - Входящие хэндлеры (`HandleVfoStep/Encoder/Button/Version`) зовутся из потока CAT-транспорта и маршалят действия в поток контроллера через `FController.Invoke` (GUI = `TThread.Synchronize`). - Слушатель состояния и `SendProc` работают из потока, вызвавшего `Changed()`; отправка в порт потокобезопасна (serial `SendStr` под своим локом). --- ## 3. Раскладка по умолчанию (AndromedaMap.pas) Раскладка **зашита в коде** (первая версия). Правится в `AndromedaMap.pas`. ### Кнопки (`ZZZP`, индекс 0-based после разбора) | # | Действие | # | Действие | |---|---|---|---| | 0 | MOX | 9 | SNB | | 1 | Tune (TUN) | 10 | Split (TX VFO-B) | | 2 | Band Up | 11 | VFO Swap (актив. A/B) | | 3 | Band Down | 12 | CTUN | | 4 | Mode Up | 13 | Mute | | 5 | Mode Down | 14 | CTCSS | | 6 | NB | 15 | Squelch on/off | | 7 | NR | 16 | Filter Up | | 8 | ANF | 17 | Filter Down | ### Энкодеры (`ZZZE`, индекс 0-based) | # | Параметр | Шаг | |---|---|---| | 0 | AF Gain (громкость) | ±1 | | 1 | AGC-T | ±1 dB | | 2 | Drive (мощность) | ±1 % | | 3 | Squelch level | ±1 | | 4 | Filter width | ±50 Гц (`AND_BW_STEP_HZ`) | | VFO | энкодер VFO (`ZZZU/ZZZD`) | ±10 Гц/шаг (`AND_VFO_STEP_HZ`) | ### Индикаторы (`ZZZI`, номера зеркалят дефолт Thetis) | LED # | Индикатор | LED # | Индикатор | |---|---|---|---| | 1 | MOX | 12 | Split | | 2 | ATU Ready *(нет в ewsdr)* | 13 | NB | | 3 | Tune | 14 | NR | | 6 | Shift *(нет)* | 15 | SNB | | 7 | CTUN | 16 | ANF | | 8/9 | RIT/XIT *(нет)* | 17 | Squelch | | 10 | VFO A/B | | | | 11 | VFO Lock *(нет)* | | | Драйвятся реально: **MOX, Tune, CTUN, VFO A/B, Split, NB, NR, SNB, ANF, Squelch**. Остальные слоты дефолтной таблицы Thetis (ATU/Shift/RIT/XIT/VFOLock) в ewsdr функций не имеют и не зажигаются. --- ## 4. Как включить 1. Подключить панель как обычный serial CAT-порт (USB). 2. Settings → CAT → выбрать нужный Serial Port, поставить **Enable** и параметры порта (скорость и т.д. — как требует панель). 3. Поставить галку **«Andromeda / G2 front panel»** на этом порту. 4. При применении настроек EWSDR пошлёт `ZZZS;`; панель ответит версией — после этого включается push индикаторов и панель управляет радио. Только **один** порт может быть Andromeda-портом (первый помеченный). Настройки сохраняются ключами `cat_serial_androm_N` / `ser_androm_N` (N = 0..3) в JSON-конфиге. --- ## 5. Что сделано / что осталось ### Сделано (первая версия) - Транспорт: **serial** (USB CAT). - Вход: `ZZZD/ZZZU` (VFO), `ZZZE` (энкодеры), `ZZZP` (кнопки), `ZZZS` (рукопожатие). - Выход: **`ZZZI`** — LED-индикаторы (push от `OnStateChanged`, дедуп повторов). - Раскладка — зашитый дефолт. - UI-чекбокс на каждый serial-порт + персист. ### Осталось / возможные улучшения | Задача | Заметки | |---|---| | **`ZZMF`** — текст на LCD мультифункц. энкодера | кодировка: 15 ASCII-символов парами цифр (код−32) | | **TCP-транспорт (G2 V2 panel)** | сейчас только serial; нужен режим в `CATTcp` | | **Настраиваемая раскладка** | сейчас зашита; вынести в конфиг/UI (как `AndromedaEditForm` в Thetis) | | **Long-press кнопок** | принимается (`ZZZP` state=2), но действий пока нет — обрабатывается только нажатие (state=1) | | **Индикаторы RIT/XIT/PureSignal/Diversity/ATU** | нет соответствующих функций в `TRadioController` | | **Мультифункц. энкодер (`aeMulti`)** | назначение не задано | --- ## 6. Точки расширения (чек-лист) - **Добавить действие кнопки/энкодера:** новый элемент в `TAndButton`/`TAndEncoder` (AndromedaMap.pas) + ветка в `TAndromedaPanel.SyncButton`/`SyncEncoder` (AndromedaPanel.pas) + правка таблицы `AND_BUTTON_MAP`/`AND_ENCODER_MAP`. - **Добавить индикатор:** элемент `TAndIndicator` + номер в `AND_INDICATOR_NUM` + push в `SyncAllIndicators` и в `OnControllerState` (по нужному `rf*`-полю). - **Изменить раскладку:** только `AndromedaMap.pas` (таблицы-константы). - Сверяться с форматами Thetis: `Andromeda/Andromeda.cs` (логика панели, `EIndicatorActions`/`EButtonBarActions`/`EEncoderActions`) и `CAT/CATCommands.cs` (`ZZZ*`).