mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 18:43:51 +00:00
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>
203 lines
14 KiB
Markdown
203 lines
14 KiB
Markdown
# Поддержка передней панели 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 = +шаг, 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()`;
|
||
отправка в порт потокобезопасна (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*`).
|