Bidirectional Apache Labs Andromeda/G2 front-panel protocol on top of CAT. Panel logic lives in dedicated units; existing files get only thin hooks. New units: - AndromedaMap.pas — data only: action enums + default button/encoder layout tables and LED (ZZZI) numbers (mirroring the Thetis defaults) - AndromedaPanel.pas — TAndromedaPanel: inbound panel events -> controller actions (marshalled via Invoke), state subscription -> ZZZI push via SendProc Hooks: - CATEngine: parse ZZZD/ZZZU/ZZZE/ZZZP/ZZZS into generic TCATContext callbacks - CATAdapter: creates the panel, routes engine callbacks to it, supplies the SendProc to the Andromeda port, AddStateListener, ZZZS handshake - CATSerial: Andromeda flag in port config + HasAndromeda/SendToAndromeda - RadioController: AddStateListener (multicast, does not steal MainForm's OnStateChanged) - Settings/SettingsForm/MainForm: CATSerialAndromeda[0..3] + persistence + checkbox First version: serial transport, hardcoded default mapping, LED indicators (MOX/Tune/CTUN/VFO A-B/Split/NB/NR/SNB/ANF/Squelch). Doc: doc/ANDROMEDA.md. TODO: default button mapping does not match the physical panel (hardcoded) — to be fixed later; also ZZMF/LCD text, TCP G2V2 transport, configurable mapping. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
12 KiB
Поддержка передней панели 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-подсистемы.
1. Что такое Andromeda и чем отличается от обычного CAT
Andromeda — это не отдельный набор команд, а двунаправленный протокол панели поверх CAT-фрейминга. В отличие от обычного CAT (реактивный «запрос → ответ»), панель требует, чтобы хост сам инициативно отправлял обновления подсветки.
ZZZD/ZZZU/ZZZE/ZZZP/ZZZS (панель → хост: ввод)
┌─────────┐ ───────────────────────────► ┌──────────┐
│ Панель │ │ EWSDR │
│ G2 / │ ◄─────────────────────────── │ (хост) │
│Andromeda│ ZZZI / ZZMF / ZZZS; └──────────┘
└─────────┘ (хост → панель: подсветка, LCD, рукопожатие)
| Направление | Команды | Назначение |
|---|---|---|
| Панель → хост | ZZZS<v> |
панель сообщает версию HW/SW (рукопожатие) |
ZZZU<nn> / ZZZD<nn> |
энкодер VFO повёрнут вверх/вниз на nn шагов | |
ZZZE<eees> |
энкодер #ee повёрнут (01–20 = +шаг, 51–70 = −шаг) | |
ZZZP<bbs> |
кнопка #bb: s=1 нажата, 2 long-press, 0 отпущена | |
| Хост → панель | ZZZI<nn><s> |
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(); отправка в порт потокобезопасна (serialSendStrпод своим локом).
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. Как включить
- Подключить панель как обычный serial CAT-порт (USB).
- Settings → CAT → выбрать нужный Serial Port, поставить Enable и параметры порта (скорость и т.д. — как требует панель).
- Поставить галку «Andromeda / G2 front panel» на этом порту.
- При применении настроек 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*).