feat(cat): Andromeda/G2 front panel support (serial, LED indicators)

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>
This commit is contained in:
2026-06-26 11:40:10 +03:00
co-authored by Claude Opus 4.8
parent 4a92624e9b
commit 2d7290e44d
10 changed files with 704 additions and 9 deletions
+5
View File
@@ -476,6 +476,7 @@ type
const SerEnabled: array of Boolean;
const SerPort: array of string;
const SerBaud, SerDataBits, SerStopBits, SerParity: array of Integer;
const SerAndromeda: array of Boolean;
TcpEnabled: Boolean; TcpPort: Integer);
procedure OnAlexSettingsChange(const A: TAlexSettings);
procedure OnXvtrSettingsChange(const X: TXvtrSettings);
@@ -5872,6 +5873,7 @@ begin
FCATLastGlobal.CATSerialDataBits,
FCATLastGlobal.CATSerialStopBits,
FCATLastGlobal.CATSerialParity,
FCATLastGlobal.CATSerialAndromeda,
FCATLastGlobal.CATTcpEnabled,
FCATLastGlobal.CATTcpPort);
// Перечисляем PA устройства
@@ -5940,6 +5942,7 @@ procedure TMainForm.OnCATSettingsChange(
const SerEnabled: array of Boolean;
const SerPort: array of string;
const SerBaud, SerDataBits, SerStopBits, SerParity: array of Integer;
const SerAndromeda: array of Boolean;
TcpEnabled: Boolean; TcpPort: Integer);
var i: Integer;
begin
@@ -5951,6 +5954,7 @@ begin
if i <= High(SerDataBits) then FCATLastGlobal.CATSerialDataBits[i] := SerDataBits[i];
if i <= High(SerStopBits) then FCATLastGlobal.CATSerialStopBits[i] := SerStopBits[i];
if i <= High(SerParity) then FCATLastGlobal.CATSerialParity[i] := SerParity[i];
if i <= High(SerAndromeda)then FCATLastGlobal.CATSerialAndromeda[i]:= SerAndromeda[i];
end;
FCATLastGlobal.CATTcpEnabled := TcpEnabled;
FCATLastGlobal.CATTcpPort := TcpPort;
@@ -5962,6 +5966,7 @@ begin
FController.FLoadedGlobal.CATSerialDataBits := FCATLastGlobal.CATSerialDataBits;
FController.FLoadedGlobal.CATSerialStopBits := FCATLastGlobal.CATSerialStopBits;
FController.FLoadedGlobal.CATSerialParity := FCATLastGlobal.CATSerialParity;
FController.FLoadedGlobal.CATSerialAndromeda := FCATLastGlobal.CATSerialAndromeda;
FController.FLoadedGlobal.CATTcpEnabled := FCATLastGlobal.CATTcpEnabled;
FController.FLoadedGlobal.CATTcpPort := FCATLastGlobal.CATTcpPort;
FCATAdapter.ApplySettings(FCATLastGlobal);