mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 17:27:32 +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:
@@ -0,0 +1,134 @@
|
||||
unit AndromedaMap;
|
||||
|
||||
{
|
||||
AndromedaMap.pas — таблицы раскладки передней панели Apache Labs Andromeda / G2.
|
||||
|
||||
Только ДАННЫЕ: перечисления действий и дефолтные таблицы
|
||||
«номер кнопки → действие», «номер энкодера → параметр»,
|
||||
«индикатор → номер LED (ZZZI)». Без логики и без зависимостей от
|
||||
контроллера — этим занимается AndromedaPanel.pas.
|
||||
|
||||
Соответствие протоколу Thetis:
|
||||
• действия кнопок/энкодеров — подмножество EButtonBarActions / EEncoderActions;
|
||||
• номера LED-индикаторов (ZZZI nn) зеркалят дефолтную таблицу Thetis
|
||||
(MakeNewAndromedaDataset): 1=MOX, 3=Tune, 7=CTUN и т.д. Свободные слоты
|
||||
12..17 заняты функциями ewsdr (Split/NB/NR/SNB/ANF/Squelch).
|
||||
}
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
type
|
||||
// Действие кнопки панели (подмножество, поддержанное ewsdr).
|
||||
TAndButton = (
|
||||
abNone, abMOX, abTune, abBandUp, abBandDown, abModeUp, abModeDown,
|
||||
abMute, abNB, abNR, abSNB, abANF, abVFOSplit, abVFOSwap, abCTUN,
|
||||
abCTCSS, abSquelch, abFilterUp, abFilterDown);
|
||||
|
||||
// Параметр, управляемый поворотным энкодером панели.
|
||||
TAndEncoder = (
|
||||
aeNone, aeAFGain, aeAGCLevel, aeDrive, aeSquelch,
|
||||
aeFilterWidth, aeMulti);
|
||||
|
||||
// Индикатор (LED) панели. Порядок зеркалит EIndicatorActions Thetis.
|
||||
TAndIndicator = (
|
||||
aiNone, aiMOX, aiTune, aiRIT, aiXIT, aiSplit, aiCTune, aiVFOSync,
|
||||
aiVFOAB, aiVFOLock, aiNB, aiNR, aiSNB, aiANF, aiSquelch,
|
||||
aiCompander, aiPuresignal, aiDiversity, aiATUReady, aiShift);
|
||||
|
||||
const
|
||||
// Размеры дефолтных таблиц (кнопки/энкодеры нумеруются с 0 после разбора ZZZP/ZZZE).
|
||||
AND_MAX_BUTTONS = 32;
|
||||
AND_MAX_ENCODERS = 20;
|
||||
|
||||
// Раскладка кнопок: индекс = номер кнопки (0-based), значение = действие.
|
||||
// Неназначенные → abNone. Дефолт ewsdr (правится при появлении конкретной панели).
|
||||
AND_BUTTON_MAP: array[0..AND_MAX_BUTTONS-1] of TAndButton = (
|
||||
abMOX, // 0
|
||||
abTune, // 1
|
||||
abBandUp, // 2
|
||||
abBandDown, // 3
|
||||
abModeUp, // 4
|
||||
abModeDown, // 5
|
||||
abNB, // 6
|
||||
abNR, // 7
|
||||
abANF, // 8
|
||||
abSNB, // 9
|
||||
abVFOSplit, // 10
|
||||
abVFOSwap, // 11
|
||||
abCTUN, // 12
|
||||
abMute, // 13
|
||||
abCTCSS, // 14
|
||||
abSquelch, // 15
|
||||
abFilterUp, // 16
|
||||
abFilterDown, // 17
|
||||
abNone, abNone, abNone, abNone, abNone, abNone, abNone, abNone,
|
||||
abNone, abNone, abNone, abNone, abNone, abNone);
|
||||
|
||||
// Раскладка энкодеров: индекс = номер энкодера (0-based), значение = параметр.
|
||||
AND_ENCODER_MAP: array[0..AND_MAX_ENCODERS-1] of TAndEncoder = (
|
||||
aeAFGain, // 0
|
||||
aeAGCLevel, // 1
|
||||
aeDrive, // 2
|
||||
aeSquelch, // 3
|
||||
aeFilterWidth, // 4
|
||||
aeNone, aeNone, aeNone, aeNone, aeNone,
|
||||
aeNone, aeNone, aeNone, aeNone, aeNone,
|
||||
aeNone, aeNone, aeNone, aeNone, aeMulti);
|
||||
|
||||
// Номер LED (ZZZI nn) для каждого индикатора; 0 = панель этот индикатор не имеет.
|
||||
// 1..11 — дефолт Thetis; 12..17 — функции ewsdr на свободных слотах.
|
||||
AND_INDICATOR_NUM: array[TAndIndicator] of Integer = (
|
||||
{aiNone} 0,
|
||||
{aiMOX} 1,
|
||||
{aiTune} 3,
|
||||
{aiRIT} 8,
|
||||
{aiXIT} 9,
|
||||
{aiSplit} 12,
|
||||
{aiCTune} 7,
|
||||
{aiVFOSync} 0,
|
||||
{aiVFOAB} 10,
|
||||
{aiVFOLock} 11,
|
||||
{aiNB} 13,
|
||||
{aiNR} 14,
|
||||
{aiSNB} 15,
|
||||
{aiANF} 16,
|
||||
{aiSquelch} 17,
|
||||
{aiCompander} 0,
|
||||
{aiPuresignal} 0,
|
||||
{aiDiversity} 0,
|
||||
{aiATUReady} 2,
|
||||
{aiShift} 6);
|
||||
|
||||
{ Возвращает действие для номера кнопки (0-based); abNone вне диапазона. }
|
||||
function ButtonAction(BtnIndex: Integer): TAndButton;
|
||||
{ Возвращает параметр для номера энкодера (0-based); aeNone вне диапазона. }
|
||||
function EncoderParam(EncIndex: Integer): TAndEncoder;
|
||||
{ Номер ZZZI для индикатора; 0 если панель его не отображает. }
|
||||
function IndicatorNum(Ind: TAndIndicator): Integer;
|
||||
|
||||
implementation
|
||||
|
||||
function ButtonAction(BtnIndex: Integer): TAndButton;
|
||||
begin
|
||||
if (BtnIndex >= 0) and (BtnIndex < AND_MAX_BUTTONS) then
|
||||
Result := AND_BUTTON_MAP[BtnIndex]
|
||||
else
|
||||
Result := abNone;
|
||||
end;
|
||||
|
||||
function EncoderParam(EncIndex: Integer): TAndEncoder;
|
||||
begin
|
||||
if (EncIndex >= 0) and (EncIndex < AND_MAX_ENCODERS) then
|
||||
Result := AND_ENCODER_MAP[EncIndex]
|
||||
else
|
||||
Result := aeNone;
|
||||
end;
|
||||
|
||||
function IndicatorNum(Ind: TAndIndicator): Integer;
|
||||
begin
|
||||
Result := AND_INDICATOR_NUM[Ind];
|
||||
end;
|
||||
|
||||
end.
|
||||
Reference in New Issue
Block a user