mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:27:33 +00:00
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:
+73
-5
@@ -48,6 +48,9 @@ type
|
||||
TCATSetIntProc = procedure(V: Integer) of object;
|
||||
TCATSetBoolProc = procedure(V: Boolean) of object;
|
||||
TCATProc = procedure of object;
|
||||
// Andromeda front panel input
|
||||
TCATPanelEncoderProc = procedure(Enc, Step: Integer) of object;
|
||||
TCATPanelButtonProc = procedure(Btn: Integer; State, LongPress: Boolean) of object;
|
||||
|
||||
TCATContext = record
|
||||
GetVfoA: TCATGetDoubleFunc;
|
||||
@@ -106,6 +109,11 @@ type
|
||||
SetAGCTop: TCATSetIntProc; // AGC-T порог, dB
|
||||
GetCTun: TCATGetBoolFunc; // Click-tune (CTUN) вкл/выкл
|
||||
SetCTun: TCATSetBoolProc;
|
||||
// Andromeda front panel input (ZZZD/ZZZU/ZZZE/ZZZP/ZZZS)
|
||||
OnPanelVfoStep: TCATSetIntProc; // знаковое число шагов энкодера VFO
|
||||
OnPanelEncoder: TCATPanelEncoderProc; // номер энкодера (0-based) + знаковый шаг
|
||||
OnPanelButton: TCATPanelButtonProc; // номер кнопки (0-based) + state/long-press
|
||||
OnPanelVersion: TCATSetIntProc; // версия HW/SW панели (рукопожатие)
|
||||
end;
|
||||
|
||||
TCATEngine = class
|
||||
@@ -321,6 +329,8 @@ type
|
||||
function ZZYR(const s: string): string;
|
||||
function ZZZA(const s: string): string;
|
||||
function ZZZB: string;
|
||||
function ZZZD(const s: string): string;
|
||||
function ZZZE(const s: string): string;
|
||||
function ZZZM(const s: string): string;
|
||||
function ZZZP(const s: string): string;
|
||||
function ZZZQ(const s: string): string;
|
||||
@@ -1348,8 +1358,8 @@ begin
|
||||
else if ext = 'YR' then ans := ZZYR(s)
|
||||
else if ext = 'ZA' then ans := ZZZA(s)
|
||||
else if ext = 'ZB' then begin ZZZB; ans := ''; end
|
||||
else if ext = 'ZD' then ans := '' // STUB: system D
|
||||
else if ext = 'ZE' then ans := '' // STUB: system E
|
||||
else if ext = 'ZD' then ans := ZZZD(s)
|
||||
else if ext = 'ZE' then ans := ZZZE(s)
|
||||
else if ext = 'ZM' then ans := ZZZM(s)
|
||||
else if ext = 'ZN' then ans := '' // STUB: system N
|
||||
else if ext = 'ZO' then ans := ZZZO(s)
|
||||
@@ -2242,20 +2252,78 @@ begin if Length(s) > 0 then Result := '' else Result := '0'; end;
|
||||
function TCATEngine.ZZZA(const s: string): string;
|
||||
begin if Length(s) > 0 then Result := '' else Result := '0'; end;
|
||||
function TCATEngine.ZZZB: string; begin Result := ''; end;
|
||||
|
||||
function TCATEngine.ZZZD(const s: string): string;
|
||||
// ZZZD: Andromeda — энкодер VFO повёрнут вниз на nn шагов (write-only).
|
||||
begin
|
||||
if Length(s) > 0 then begin
|
||||
if Assigned(FCtx.OnPanelVfoStep) then FCtx.OnPanelVfoStep(-StrToIntDef(s, 0));
|
||||
Result := '';
|
||||
end else
|
||||
Result := CAT_ERROR;
|
||||
end;
|
||||
|
||||
function TCATEngine.ZZZE(const s: string): string;
|
||||
// ZZZE: Andromeda — поворот энкодера. Кодировка Thetis: верхние 2 цифры — номер
|
||||
// энкодера (01..20 = +шаг, 51..70 = −шаг), нижняя цифра — величина шага.
|
||||
var raw, enc, step: Integer;
|
||||
begin
|
||||
if Length(s) > 0 then begin
|
||||
raw := StrToIntDef(s, 0);
|
||||
step := raw mod 10;
|
||||
enc := raw div 10;
|
||||
if (enc >= 1) and (enc <= 20) then begin
|
||||
if Assigned(FCtx.OnPanelEncoder) then FCtx.OnPanelEncoder(enc - 1, step);
|
||||
end else if (enc >= 51) and (enc <= 70) then begin
|
||||
if Assigned(FCtx.OnPanelEncoder) then FCtx.OnPanelEncoder(enc - 51, -step);
|
||||
end;
|
||||
Result := '';
|
||||
end else
|
||||
Result := CAT_ERROR;
|
||||
end;
|
||||
|
||||
function TCATEngine.ZZZM(const s: string): string;
|
||||
begin if Length(s) > 0 then Result := '' else Result := '0'; end;
|
||||
|
||||
function TCATEngine.ZZZP(const s: string): string;
|
||||
begin if Length(s) > 0 then Result := '' else Result := '0'; end;
|
||||
// ZZZP: Andromeda — нажатие кнопки (write-only). Кодировка: nn*10 + state,
|
||||
// state: 0=отпущена, 1=нажата, 2=long-press. nn — номер кнопки (1-based).
|
||||
var raw, btn: Integer; state, long: Boolean;
|
||||
begin
|
||||
if Length(s) > 0 then begin
|
||||
raw := StrToIntDef(s, 0);
|
||||
state := (raw mod 10) = 1;
|
||||
long := (raw mod 10) = 2;
|
||||
btn := raw div 10;
|
||||
if Assigned(FCtx.OnPanelButton) then FCtx.OnPanelButton(btn - 1, state, long);
|
||||
Result := '';
|
||||
end else
|
||||
Result := CAT_ERROR;
|
||||
end;
|
||||
function TCATEngine.ZZZQ(const s: string): string;
|
||||
begin if Length(s) > 0 then Result := '' else Result := '0'; end;
|
||||
function TCATEngine.ZZZR(const s: string): string;
|
||||
begin if Length(s) > 0 then Result := '' else Result := '0'; end;
|
||||
function TCATEngine.ZZZS(const s: string): string;
|
||||
begin if Length(s) > 0 then Result := '' else Result := '0'; end;
|
||||
// ZZZS: Andromeda — панель сообщает версию HW/SW (write-only, рукопожатие).
|
||||
begin
|
||||
if Length(s) > 0 then begin
|
||||
if Assigned(FCtx.OnPanelVersion) then FCtx.OnPanelVersion(StrToIntDef(s, 0));
|
||||
Result := '';
|
||||
end else
|
||||
Result := CAT_ERROR;
|
||||
end;
|
||||
function TCATEngine.ZZZT(const s: string): string;
|
||||
begin if Length(s) > 0 then Result := '' else Result := '0'; end;
|
||||
function TCATEngine.ZZZU(const s: string): string;
|
||||
begin if Length(s) > 0 then Result := '' else Result := '0'; end;
|
||||
// ZZZU: Andromeda — энкодер VFO повёрнут вверх на nn шагов (write-only).
|
||||
begin
|
||||
if Length(s) > 0 then begin
|
||||
if Assigned(FCtx.OnPanelVfoStep) then FCtx.OnPanelVfoStep(StrToIntDef(s, 0));
|
||||
Result := '';
|
||||
end else
|
||||
Result := CAT_ERROR;
|
||||
end;
|
||||
function TCATEngine.ZZZV(const s: string): string;
|
||||
begin if Length(s) > 0 then Result := '' else Result := '0'; end;
|
||||
function TCATEngine.ZZZW(const s: string): string;
|
||||
|
||||
Reference in New Issue
Block a user