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

203 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Поддержка передней панели 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<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*`).