Files
ewsdr/doc/ANDROMEDA.md
T
ew8bakandClaude Opus 4.8 0e550dd9f9 fix(cat): align Andromeda panel mapping with real G2 hardware (Thetis)
Button/encoder indices follow Thetis MakeNewAndromedaDataset (our 0-based
index = Thetis Number - 1), verified against andromeda_test/AndDecode.pas.
The old map assumed sequential 0,1,2.. and truncated at 32; the real panel
sends sparse indices up to 47.

- AndromedaMap: AND_MAX_BUTTONS 32->48, renumbered button/encoder tables;
  new actions abVFOAtoB/abVFOBtoA/abVFOLock/abStartStop/abShift.
- RadioController: VFO Lock (FVfoLock, rfVfoLock, SetVfoLock, gate in
  TuneActiveBy).
- AndromedaPanel: wire A>B/B>A/SDR-ON/Lock; Shift band-keypad layer
  (#28 latch, #29..39 -> SetBand 160m..6m, non-sticky); aiVFOLock/aiShift
  indicators.
- Filter High/Low (#4/#5) left as width approximation per decision.
- doc/ANDROMEDA.md updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 16:11:12 +03:00

14 KiB
Raw Blame History

Поддержка передней панели 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 = +шаг, 5170 = −шаг)
ZZZP<bbs> кнопка #bb: s=1 нажата, 2 long-press, 0 отпущена
Хост → панель ZZZI<nn><s> LED-индикатор #nn (0019) вкл (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)

Раскладка зашита в коде и зеркалит дефолтную таблицу Thetis (MakeNewAndromedaDataset): наш 0-based индекс = «Pushbutton/Encoder Number» Thetis 1. Номера проверены на реальной панели (см. andromeda_test/AndDecode.pas). Правится в AndromedaMap.pas.

Кнопки (ZZZP, индекс 0-based после разбора)

# Действие # Действие
0 RX1 Mute 35 A>B (под shift → 17m)
28 Shift (band-keypad) 36 B>A (под shift → 15m)
29 Band Up (под shift → 160m) 37 Split (под shift → 12m)
30 Mode Up (под shift → 80m) 38 (под shift → 10m)
31 Filter Up (под shift → 60m) 39 (под shift → 6m)
32 Band Down (под shift → 40m) 42 VFO Swap (toggle A/B)
33 Mode Down (под shift → 30m) 43 VFO Lock
34 Filter Down (под shift → 20m) 44 CTUN
45 SDR ON (start/stop)
46 MOX
47 TUN

Не назначены (нет тракта в ewsdr): 2 (RX2 Mute), 40 (band GEN), 41 (RIT/XIT). NB/NR/ANF/SNB/CTCSS/Squelch у реальной панели на кнопках не выведены (в Thetis — на тачскрине), действия в enum сохранены для кастомной раскладки.

Shift / band-keypad

Кнопка #28 — модификатор-защёлка (как eBBShift в Thetis). Пока активен (LED aiShift #6), кнопки band-группы #29..39 выбирают диапазон напрямую (SetBand 0..10: 160m…6m); #40 = GEN — в ewsdr отсутствует. Снимается повторным Shift либо автоматически после выбора диапазона (non-sticky). Логика — в TAndromedaPanel.HandleButton.

Энкодеры (ZZZE, индекс 0-based)

# Параметр Шаг
0 AF Gain (громкость) ±1
1 AGC-T (в Thetis — слайдер «RF») ±1 dB
4 Filter High → ширина фильтра ±50 Гц (AND_BW_STEP_HZ)
11 Drive (мощность) ±1 %
VFO энкодер VFO (ZZZU/ZZZD) ±10 Гц/шаг (AND_VFO_STEP_HZ)

#4/#5 на панели — независимые края фильтра (Filter High/Low). В ewsdr фильтр симметричный (SetFilterBW), поэтому #4 крутит ширину, #5 пока не задействован. Энкодеры RX2 AF/AGC (#2/#3), diversity (#6/#7), RIT/XIT (#8/#9) — нет тракта.

Индикаторы (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, VFO Lock, Shift, Split, NB, NR, SNB, ANF, Squelch. Остальные слоты дефолтной таблицы Thetis (ATU/RIT/XIT) в 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, дедуп повторов).
  • Раскладка — зашитый дефолт, выверена по Thetis и реальной панели.
  • Shift / band-keypad — прямой выбор диапазона (#29..39 → SetBand), LED aiShift.
  • VFO Lock — блокировка перестройки (SetVfoLock, гейт в TuneActiveBy), LED aiVFOLock.
  • A>B / B>A / Toggle A/B, SDR ON (start/stop) — на штатных кнопках панели.
  • UI-чекбокс на каждый serial-порт + персист.

Осталось / возможные улучшения

Задача Заметки
Filter High/Low (ZZZE #4/#5) независимые края фильтра; сейчас #4 = ширина, #5 не задействован. Нужны FFilterLow/High + переработка ApplyModeFilter и passband дисплея (sideband-aware, как в Thetis)
Sticky shift сейчас shift всегда non-sticky (снимается band-нажатием); в Thetis есть AndromedaStickyShift
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*).