mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
Phase 4: extract CAT into its own adapter (CATAdapter.pas)
CAT becomes a peer adapter over the controller, alongside WebAdapter. TCATAdapter owns the CAT engine + serial/TCP transports and builds the TCATContext: getters read FController directly (CAT thread), setters/commands call controller commands marshaled via FController.Invoke. No MainForm or WebAdapter dependency — the historical CAT->WebAdapter.OnXxx coupling (Mode/AGC/Band/etc.) is gone; CAT talks only to the controller. MainForm keeps CAT *settings* (FCATLastGlobal + OnCATSettingsChange + SettingsForm wiring), now calling FCATAdapter.ApplySettings on change/connect. Removed InitCATEngine, CATApplySettings, all CATGet*/CATSet*/CATDo*/SyncCAT* and the FCATEngine/FCATSerial/FCATTcp/FCATSyncFreq fields. Fixes a latent bug: CATSetFilterIdx routed a filter index through the web BW handler as a negative-encoded value, but that branch was dead since batch 21 — CAT now calls FController.SetFilterIdx directly. Adds StoreVfoA (store VFO A without retune when B is active) and uses the now-real SetBand/BandUp/BandDown/TuneActiveBy commands. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
daee5672a9
commit
682025e99b
+324
@@ -0,0 +1,324 @@
|
|||||||
|
unit CATAdapter;
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// TCATAdapter — адаптер CAT (Kenwood TS-2000) поверх TRadioController.
|
||||||
|
//
|
||||||
|
// Равноправный клиент контроллера наряду с WebAdapter и будущей Arduino-панелью.
|
||||||
|
// Владеет CAT-движком (TCATEngine) + транспортами (serial/TCP) и строит TCATContext:
|
||||||
|
// • геттеры читают состояние FController напрямую (CAT-поток, read-only);
|
||||||
|
// • сеттеры/команды зовут команды контроллера, маршалинг через FController.Invoke
|
||||||
|
// (GUI = TThread.Synchronize; демон подставит свою очередь).
|
||||||
|
// Никаких обращений к MainForm/WebAdapter — CAT говорит только с контроллером.
|
||||||
|
//
|
||||||
|
// Конфиг serial/TCP применяется снаружи через ApplySettings (UI-настройки CAT
|
||||||
|
// остаются в MainForm/SettingsForm и зовут ApplySettings при изменении/connect).
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes, SysUtils,
|
||||||
|
RadioController, CATEngine, CATSerial, CATTcp, Settings, WDSPEngine;
|
||||||
|
|
||||||
|
type
|
||||||
|
TCATAdapter = class
|
||||||
|
private
|
||||||
|
FController: TRadioController;
|
||||||
|
FEngine: TCATEngine;
|
||||||
|
FSerial: TCATSerialManager;
|
||||||
|
FTcp: TCATTcpServer;
|
||||||
|
// Параметры команды для маршалинга в поток контроллера (через Invoke).
|
||||||
|
FSyncFreq: Double;
|
||||||
|
FSyncInt: Integer;
|
||||||
|
FSyncBool: Boolean;
|
||||||
|
|
||||||
|
// ── Геттеры (CAT-поток, read-only) ──
|
||||||
|
function GetVfoA: Double;
|
||||||
|
function GetVfoB: Double;
|
||||||
|
function GetMode: Integer;
|
||||||
|
function GetActiveVfo: Integer;
|
||||||
|
function GetAGCMode: Integer;
|
||||||
|
function GetVolume: Integer;
|
||||||
|
function GetDriveLevel: Integer;
|
||||||
|
function GetFilterIdx: Integer;
|
||||||
|
function GetFilterBW: Integer;
|
||||||
|
function GetNRMode: Integer;
|
||||||
|
function GetNBMode: Integer;
|
||||||
|
function GetSNB: Boolean;
|
||||||
|
function GetANF: Boolean;
|
||||||
|
function GetTX: Boolean;
|
||||||
|
function GetRunning: Boolean;
|
||||||
|
function GetSMeter: Double;
|
||||||
|
function GetBand: Integer;
|
||||||
|
|
||||||
|
// ── Сеттеры/команды (из CAT-потока → Invoke в поток контроллера) ──
|
||||||
|
procedure SetVfoA(V: Double);
|
||||||
|
procedure SetVfoB(V: Double);
|
||||||
|
procedure SetMode(V: Integer);
|
||||||
|
procedure SetActiveVfo(V: Integer);
|
||||||
|
procedure SetAGCMode(V: Integer);
|
||||||
|
procedure SetVolume(V: Integer);
|
||||||
|
procedure SetDriveLevel(V: Integer);
|
||||||
|
procedure SetFilterIdx(V: Integer);
|
||||||
|
procedure SetNRMode(V: Integer);
|
||||||
|
procedure SetNBMode(V: Integer);
|
||||||
|
procedure SetSNB(V: Boolean);
|
||||||
|
procedure SetANF(V: Boolean);
|
||||||
|
procedure SetTransmitting(V: Boolean);
|
||||||
|
procedure DoBandUp;
|
||||||
|
procedure DoBandDown;
|
||||||
|
procedure DoTuneUp;
|
||||||
|
procedure DoTuneDown;
|
||||||
|
procedure DoBandByIndex(Idx: Integer);
|
||||||
|
|
||||||
|
// ── Sync-методы (выполняются в потоке контроллера) ──
|
||||||
|
procedure SyncVfoA;
|
||||||
|
procedure SyncVfoB;
|
||||||
|
procedure SyncMode;
|
||||||
|
procedure SyncActiveVfo;
|
||||||
|
procedure SyncAGC;
|
||||||
|
procedure SyncVolume;
|
||||||
|
procedure SyncDrive;
|
||||||
|
procedure SyncFilterIdx;
|
||||||
|
procedure SyncNR;
|
||||||
|
procedure SyncNB;
|
||||||
|
procedure SyncSNB;
|
||||||
|
procedure SyncANF;
|
||||||
|
procedure SyncMOX;
|
||||||
|
procedure SyncBandUp;
|
||||||
|
procedure SyncBandDown;
|
||||||
|
procedure SyncTuneUp;
|
||||||
|
procedure SyncTuneDown;
|
||||||
|
procedure SyncBandByIndex;
|
||||||
|
public
|
||||||
|
constructor Create(AController: TRadioController);
|
||||||
|
destructor Destroy; override;
|
||||||
|
// Применить serial/TCP-конфиг из глобальных настроек (вызывает UI на change/connect).
|
||||||
|
procedure ApplySettings(const G: TGlobalSettings);
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
constructor TCATAdapter.Create(AController: TRadioController);
|
||||||
|
var
|
||||||
|
Ctx: TCATContext;
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
FController := AController;
|
||||||
|
|
||||||
|
FillChar(Ctx, SizeOf(Ctx), 0);
|
||||||
|
Ctx.GetVfoA := @GetVfoA;
|
||||||
|
Ctx.GetVfoB := @GetVfoB;
|
||||||
|
Ctx.GetMode := @GetMode;
|
||||||
|
Ctx.GetActiveVfo := @GetActiveVfo;
|
||||||
|
Ctx.GetAGCMode := @GetAGCMode;
|
||||||
|
Ctx.GetVolume := @GetVolume;
|
||||||
|
Ctx.GetDriveLevel := @GetDriveLevel;
|
||||||
|
Ctx.GetFilterIdx := @GetFilterIdx;
|
||||||
|
Ctx.GetFilterBW := @GetFilterBW;
|
||||||
|
Ctx.GetNRMode := @GetNRMode;
|
||||||
|
Ctx.GetNBMode := @GetNBMode;
|
||||||
|
Ctx.GetSNBEnabled := @GetSNB;
|
||||||
|
Ctx.GetANFEnabled := @GetANF;
|
||||||
|
Ctx.GetTransmitting := @GetTX;
|
||||||
|
Ctx.GetRunning := @GetRunning;
|
||||||
|
Ctx.GetSMeter := @GetSMeter;
|
||||||
|
Ctx.GetCurrentBand := @GetBand;
|
||||||
|
Ctx.SetVfoA := @SetVfoA;
|
||||||
|
Ctx.SetVfoB := @SetVfoB;
|
||||||
|
Ctx.SetMode := @SetMode;
|
||||||
|
Ctx.SetActiveVfo := @SetActiveVfo;
|
||||||
|
Ctx.SetAGCMode := @SetAGCMode;
|
||||||
|
Ctx.SetVolume := @SetVolume;
|
||||||
|
Ctx.SetDriveLevel := @SetDriveLevel;
|
||||||
|
Ctx.SetFilterIdx := @SetFilterIdx;
|
||||||
|
Ctx.SetNRMode := @SetNRMode;
|
||||||
|
Ctx.SetNBMode := @SetNBMode;
|
||||||
|
Ctx.SetSNBEnabled := @SetSNB;
|
||||||
|
Ctx.SetANFEnabled := @SetANF;
|
||||||
|
Ctx.SetTransmitting := @SetTransmitting;
|
||||||
|
Ctx.DoBandUp := @DoBandUp;
|
||||||
|
Ctx.DoBandDown := @DoBandDown;
|
||||||
|
Ctx.DoTuneUp := @DoTuneUp;
|
||||||
|
Ctx.DoTuneDown := @DoTuneDown;
|
||||||
|
Ctx.DoBandByIndex := @DoBandByIndex;
|
||||||
|
|
||||||
|
FEngine := TCATEngine.Create(Ctx);
|
||||||
|
FSerial := TCATSerialManager.Create(FEngine);
|
||||||
|
FTcp := TCATTcpServer.Create(FEngine);
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TCATAdapter.Destroy;
|
||||||
|
begin
|
||||||
|
if Assigned(FTcp) then begin FTcp.Stop; FreeAndNil(FTcp); end;
|
||||||
|
if Assigned(FSerial) then begin FSerial.StopAll; FreeAndNil(FSerial); end;
|
||||||
|
FreeAndNil(FEngine);
|
||||||
|
inherited Destroy;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.ApplySettings(const G: TGlobalSettings);
|
||||||
|
var
|
||||||
|
Cfgs: array[0..3] of TCATSerialConfig;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
for i := 0 to 3 do
|
||||||
|
begin
|
||||||
|
Cfgs[i].Enabled := G.CATSerialEnabled[i];
|
||||||
|
Cfgs[i].PortName := G.CATSerialPort[i];
|
||||||
|
Cfgs[i].BaudRate := G.CATSerialBaud[i];
|
||||||
|
Cfgs[i].DataBits := G.CATSerialDataBits[i];
|
||||||
|
Cfgs[i].StopBits := G.CATSerialStopBits[i];
|
||||||
|
case G.CATSerialParity[i] of
|
||||||
|
1: Cfgs[i].Parity := cspOdd;
|
||||||
|
2: Cfgs[i].Parity := cspEven;
|
||||||
|
else Cfgs[i].Parity := cspNone;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
FSerial.ApplyConfig(Cfgs);
|
||||||
|
FTcp.Stop;
|
||||||
|
if G.CATTcpEnabled then
|
||||||
|
begin
|
||||||
|
FTcp.Port := G.CATTcpPort;
|
||||||
|
FTcp.Start;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// ── Геттеры ──────────────────────────────────────────────────────────────────
|
||||||
|
function TCATAdapter.GetVfoA: Double; begin Result := FController.FVfoA; end;
|
||||||
|
function TCATAdapter.GetVfoB: Double; begin Result := FController.FVfoB; end;
|
||||||
|
function TCATAdapter.GetMode: Integer; begin Result := FController.FMode; end;
|
||||||
|
function TCATAdapter.GetActiveVfo: Integer; begin Result := FController.FActiveVfo; end;
|
||||||
|
function TCATAdapter.GetAGCMode: Integer; begin Result := FController.FAGCMode; end;
|
||||||
|
function TCATAdapter.GetVolume: Integer; begin Result := FController.FVolume; end;
|
||||||
|
function TCATAdapter.GetDriveLevel: Integer; begin Result := FController.FDrivePercent; end;
|
||||||
|
function TCATAdapter.GetFilterIdx: Integer; begin Result := FController.FFilter; end;
|
||||||
|
function TCATAdapter.GetFilterBW: Integer; begin Result := FController.FFilterBW; end;
|
||||||
|
function TCATAdapter.GetNRMode: Integer; begin Result := FController.FNRMode; end;
|
||||||
|
function TCATAdapter.GetNBMode: Integer; begin Result := FController.FNBMode; end;
|
||||||
|
function TCATAdapter.GetSNB: Boolean; begin Result := FController.FSNB; end;
|
||||||
|
function TCATAdapter.GetANF: Boolean; begin Result := FController.FANF; end;
|
||||||
|
function TCATAdapter.GetTX: Boolean; begin Result := FController.FTransmitting; end;
|
||||||
|
function TCATAdapter.GetRunning: Boolean; begin Result := FController.FRunning; end;
|
||||||
|
function TCATAdapter.GetSMeter: Double; begin Result := FController.FLastSMeter; end;
|
||||||
|
function TCATAdapter.GetBand: Integer; begin Result := FController.FCurrentBand; end;
|
||||||
|
|
||||||
|
// ── Сеттеры (маршалинг) ──────────────────────────────────────────────────────
|
||||||
|
procedure TCATAdapter.SetVfoA(V: Double);
|
||||||
|
begin FSyncFreq := V; FController.Invoke(@SyncVfoA); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SyncVfoA;
|
||||||
|
begin
|
||||||
|
// A активен — полная перестройка (CTUN/band/сеть + канальная оркестрация через
|
||||||
|
// OnAfterTune). B активен — только сохраняем/отображаем A (приёмник на B).
|
||||||
|
if FController.FActiveVfo = 0 then FController.SetVfoA(FSyncFreq)
|
||||||
|
else FController.StoreVfoA(FSyncFreq);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SetVfoB(V: Double);
|
||||||
|
begin FSyncFreq := V; FController.Invoke(@SyncVfoB); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SyncVfoB;
|
||||||
|
begin FController.SetVfoB(FSyncFreq); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SetMode(V: Integer);
|
||||||
|
begin FSyncInt := V; FController.Invoke(@SyncMode); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SyncMode;
|
||||||
|
begin
|
||||||
|
if (FSyncInt < 0) or (FSyncInt > MODE_SAM) then Exit;
|
||||||
|
FController.SetMode(FSyncInt);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SetActiveVfo(V: Integer);
|
||||||
|
begin FSyncInt := V; FController.Invoke(@SyncActiveVfo); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SyncActiveVfo;
|
||||||
|
begin FController.SetActiveVfo(FSyncInt); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SetAGCMode(V: Integer);
|
||||||
|
begin FSyncInt := V; FController.Invoke(@SyncAGC); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SyncAGC;
|
||||||
|
begin FController.SetAGCMode(FSyncInt); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SetVolume(V: Integer);
|
||||||
|
begin FSyncInt := V; FController.Invoke(@SyncVolume); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SyncVolume;
|
||||||
|
begin FController.SetVolume(FSyncInt); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SetDriveLevel(V: Integer);
|
||||||
|
begin FSyncInt := V; FController.Invoke(@SyncDrive); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SyncDrive;
|
||||||
|
begin FController.SetDrive(FSyncInt); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SetFilterIdx(V: Integer);
|
||||||
|
begin FSyncInt := V; FController.Invoke(@SyncFilterIdx); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SyncFilterIdx;
|
||||||
|
begin FController.SetFilterIdx(FSyncInt); end; // прямой индекс пресета
|
||||||
|
|
||||||
|
procedure TCATAdapter.SetNRMode(V: Integer);
|
||||||
|
begin FSyncInt := V; FController.Invoke(@SyncNR); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SyncNR;
|
||||||
|
begin FController.SetNR(FSyncInt); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SetNBMode(V: Integer);
|
||||||
|
begin FSyncInt := V; FController.Invoke(@SyncNB); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SyncNB;
|
||||||
|
begin FController.SetNB(FSyncInt); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SetSNB(V: Boolean);
|
||||||
|
begin FSyncBool := V; FController.Invoke(@SyncSNB); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SyncSNB;
|
||||||
|
begin FController.SetSNB(FSyncBool); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SetANF(V: Boolean);
|
||||||
|
begin FSyncBool := V; FController.Invoke(@SyncANF); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SyncANF;
|
||||||
|
begin FController.SetANF(FSyncBool); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SetTransmitting(V: Boolean);
|
||||||
|
begin FSyncBool := V; FController.Invoke(@SyncMOX); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SyncMOX;
|
||||||
|
begin FController.SetMOX(FSyncBool); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.DoBandUp;
|
||||||
|
begin FController.Invoke(@SyncBandUp); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SyncBandUp;
|
||||||
|
begin FController.BandUp; end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.DoBandDown;
|
||||||
|
begin FController.Invoke(@SyncBandDown); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SyncBandDown;
|
||||||
|
begin FController.BandDown; end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.DoTuneUp;
|
||||||
|
begin FController.Invoke(@SyncTuneUp); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SyncTuneUp;
|
||||||
|
begin FController.TuneActiveBy(10); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.DoTuneDown;
|
||||||
|
begin FController.Invoke(@SyncTuneDown); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SyncTuneDown;
|
||||||
|
begin FController.TuneActiveBy(-10); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.DoBandByIndex(Idx: Integer);
|
||||||
|
begin FSyncInt := Idx; FController.Invoke(@SyncBandByIndex); end;
|
||||||
|
|
||||||
|
procedure TCATAdapter.SyncBandByIndex;
|
||||||
|
begin FController.SetBand(FSyncInt); end;
|
||||||
|
|
||||||
|
end.
|
||||||
+9
-234
@@ -31,7 +31,7 @@ uses
|
|||||||
WDSP, WDSPEngine, AudioOutput, AudioInput,
|
WDSP, WDSPEngine, AudioOutput, AudioInput,
|
||||||
Settings,
|
Settings,
|
||||||
WebServer, WebAdapter,
|
WebServer, WebAdapter,
|
||||||
CATEngine, CATSerial, CATTcp,
|
CATAdapter,
|
||||||
SpectrumView, SpectrumViewOpengl,
|
SpectrumView, SpectrumViewOpengl,
|
||||||
WidebandView,
|
WidebandView,
|
||||||
StatusBar,
|
StatusBar,
|
||||||
@@ -177,11 +177,8 @@ type
|
|||||||
FWebUser: string;
|
FWebUser: string;
|
||||||
FWebPass: string;
|
FWebPass: string;
|
||||||
// --- CAT ---
|
// --- CAT ---
|
||||||
FCATEngine: TCATEngine;
|
FCATAdapter: TCATAdapter; // адаптер CAT поверх контроллера (движок+транспорты+контекст)
|
||||||
FCATSerial: TCATSerialManager;
|
FCATLastGlobal: TGlobalSettings; // текущие CAT-настройки (UI/persist; ApplySettings → адаптер)
|
||||||
FCATTcp: TCATTcpServer;
|
|
||||||
FCATSyncFreq: Double;
|
|
||||||
FCATLastGlobal: TGlobalSettings; // текущие CAT-настройки (для сохранения)
|
|
||||||
// Временные поля для передачи параметров в Synchronize-методы
|
// Временные поля для передачи параметров в Synchronize-методы
|
||||||
FWebSyncFreq: Double;
|
FWebSyncFreq: Double;
|
||||||
FWebSyncInt: Integer;
|
FWebSyncInt: Integer;
|
||||||
@@ -453,39 +450,7 @@ type
|
|||||||
procedure PushDeviceListToWeb; // store → FWebServer.SetDeviceList
|
procedure PushDeviceListToWeb; // store → FWebServer.SetDeviceList
|
||||||
// Synchronize-обёртки (выполняются в UI-потоке) — только host-зависимые
|
// Synchronize-обёртки (выполняются в UI-потоке) — только host-зависимые
|
||||||
procedure SyncWebRun;
|
procedure SyncWebRun;
|
||||||
// --- CAT callbacks -------------------------------------------------------
|
// --- CAT settings (UI/persist; контекст+движок — в TCATAdapter) ----------
|
||||||
function CATGetVfoA: Double;
|
|
||||||
function CATGetVfoB: Double;
|
|
||||||
function CATGetMode: Integer;
|
|
||||||
function CATGetActiveVfo: Integer;
|
|
||||||
function CATGetAGCMode: Integer;
|
|
||||||
function CATGetVolume: Integer;
|
|
||||||
function CATGetDriveLevel: Integer;
|
|
||||||
function CATGetFilterIdx: Integer;
|
|
||||||
function CATGetFilterBW: Integer;
|
|
||||||
function CATGetNRMode: Integer;
|
|
||||||
function CATGetNBMode: Integer;
|
|
||||||
function CATGetSNB: Boolean;
|
|
||||||
function CATGetANF: Boolean;
|
|
||||||
function CATGetTX: Boolean;
|
|
||||||
function CATGetRunning: Boolean;
|
|
||||||
function CATGetSMeter: Double;
|
|
||||||
function CATGetBand: Integer;
|
|
||||||
procedure CATSetVfoA(V: Double);
|
|
||||||
procedure CATSetVfoB(V: Double);
|
|
||||||
procedure CATSetFilterIdx(V: Integer);
|
|
||||||
procedure CATDoBandUp;
|
|
||||||
procedure CATDoBandDown;
|
|
||||||
procedure CATDoTuneUp;
|
|
||||||
procedure CATDoTuneDown;
|
|
||||||
procedure SyncCATVfoA;
|
|
||||||
procedure SyncCATVfoB;
|
|
||||||
procedure SyncCATBandUp;
|
|
||||||
procedure SyncCATBandDown;
|
|
||||||
procedure SyncCATTuneUp;
|
|
||||||
procedure SyncCATTuneDown;
|
|
||||||
procedure InitCATEngine;
|
|
||||||
procedure CATApplySettings(const G: TGlobalSettings);
|
|
||||||
procedure OnCATSettingsChange(
|
procedure OnCATSettingsChange(
|
||||||
const SerEnabled: array of Boolean;
|
const SerEnabled: array of Boolean;
|
||||||
const SerPort: array of string;
|
const SerPort: array of string;
|
||||||
@@ -908,8 +873,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
FController.FSettings.LoadCATSettings(FCATLastGlobal);
|
FController.FSettings.LoadCATSettings(FCATLastGlobal);
|
||||||
FLightTheme := FController.FSettings.LoadTheme;
|
FLightTheme := FController.FSettings.LoadTheme;
|
||||||
InitCATEngine;
|
FCATAdapter := TCATAdapter.Create(FController);
|
||||||
CATApplySettings(FCATLastGlobal);
|
FCATAdapter.ApplySettings(FCATLastGlobal);
|
||||||
FSMeterPeak := -130;
|
FSMeterPeak := -130;
|
||||||
FSMeterMin := -130;
|
FSMeterMin := -130;
|
||||||
FSMeterAvg := -130;
|
FSMeterAvg := -130;
|
||||||
@@ -1079,9 +1044,7 @@ begin
|
|||||||
FWebServer.Stop;
|
FWebServer.Stop;
|
||||||
FreeAndNil(FWebAdapter); // адаптер не владеет сервером — освобождаем после Stop
|
FreeAndNil(FWebAdapter); // адаптер не владеет сервером — освобождаем после Stop
|
||||||
FWebServer.Free;
|
FWebServer.Free;
|
||||||
if Assigned(FCATTcp) then begin FCATTcp.Stop; FreeAndNil(FCATTcp); end;
|
FreeAndNil(FCATAdapter); // его Destroy останавливает+освобождает CAT движок/транспорты
|
||||||
if Assigned(FCATSerial) then begin FCATSerial.StopAll; FreeAndNil(FCATSerial); end;
|
|
||||||
FreeAndNil(FCATEngine);
|
|
||||||
// Ядро освобождаем последним — его Destroy закрывает и освобождает движки
|
// Ядро освобождаем последним — его Destroy закрывает и освобождает движки
|
||||||
// (FreeEngines) и FSettings.
|
// (FreeEngines) и FSettings.
|
||||||
FreeAndNil(FController);
|
FreeAndNil(FController);
|
||||||
@@ -1350,7 +1313,7 @@ begin
|
|||||||
// Тема — app-global (своё хранилище LoadTheme/SaveTheme), не из device-блоба:
|
// Тема — app-global (своё хранилище LoadTheme/SaveTheme), не из device-блоба:
|
||||||
// возвращаем живое значение в persist-буфер, чтобы blob нёс актуальную тему.
|
// возвращаем живое значение в persist-буфер, чтобы blob нёс актуальную тему.
|
||||||
FController.FLoadedGlobal.LightTheme := FLightTheme;
|
FController.FLoadedGlobal.LightTheme := FLightTheme;
|
||||||
CATApplySettings(FController.FLoadedGlobal);
|
FCATAdapter.ApplySettings(FController.FLoadedGlobal);
|
||||||
RebuildXvtrButtons;
|
RebuildXvtrButtons;
|
||||||
PushXvtrToWeb;
|
PushXvtrToWeb;
|
||||||
TrkDrive.Position := FController.FDrivePercent; // слайдер ← drive%
|
TrkDrive.Position := FController.FDrivePercent; // слайдер ← drive%
|
||||||
@@ -5542,78 +5505,6 @@ end;
|
|||||||
// CAT subsystem
|
// CAT subsystem
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
|
|
||||||
procedure TMainForm.InitCATEngine;
|
|
||||||
var
|
|
||||||
Ctx: TCATContext;
|
|
||||||
begin
|
|
||||||
FillChar(Ctx, SizeOf(Ctx), 0);
|
|
||||||
Ctx.GetVfoA := CATGetVfoA;
|
|
||||||
Ctx.GetVfoB := CATGetVfoB;
|
|
||||||
Ctx.GetMode := CATGetMode;
|
|
||||||
Ctx.GetActiveVfo := CATGetActiveVfo;
|
|
||||||
Ctx.GetAGCMode := CATGetAGCMode;
|
|
||||||
Ctx.GetVolume := CATGetVolume;
|
|
||||||
Ctx.GetDriveLevel := CATGetDriveLevel;
|
|
||||||
Ctx.GetFilterIdx := CATGetFilterIdx;
|
|
||||||
Ctx.GetFilterBW := CATGetFilterBW;
|
|
||||||
Ctx.GetNRMode := CATGetNRMode;
|
|
||||||
Ctx.GetNBMode := CATGetNBMode;
|
|
||||||
Ctx.GetSNBEnabled := CATGetSNB;
|
|
||||||
Ctx.GetANFEnabled := CATGetANF;
|
|
||||||
Ctx.GetTransmitting := CATGetTX;
|
|
||||||
Ctx.GetRunning := CATGetRunning;
|
|
||||||
Ctx.GetSMeter := CATGetSMeter;
|
|
||||||
Ctx.GetCurrentBand := CATGetBand;
|
|
||||||
Ctx.SetVfoA := CATSetVfoA;
|
|
||||||
Ctx.SetVfoB := CATSetVfoB;
|
|
||||||
Ctx.SetMode := FWebAdapter.OnMode;
|
|
||||||
Ctx.SetActiveVfo := FWebAdapter.OnActiveVfo;
|
|
||||||
Ctx.SetAGCMode := FWebAdapter.OnAGC;
|
|
||||||
Ctx.SetVolume := FWebAdapter.OnVolume;
|
|
||||||
Ctx.SetDriveLevel := FWebAdapter.OnDrive;
|
|
||||||
Ctx.SetFilterIdx := CATSetFilterIdx;
|
|
||||||
Ctx.SetNRMode := FWebAdapter.OnNR;
|
|
||||||
Ctx.SetNBMode := FWebAdapter.OnNB;
|
|
||||||
Ctx.SetSNBEnabled := FWebAdapter.OnSNB;
|
|
||||||
Ctx.SetANFEnabled := FWebAdapter.OnANF;
|
|
||||||
Ctx.SetTransmitting := FWebAdapter.OnMOX;
|
|
||||||
Ctx.DoBandUp := CATDoBandUp;
|
|
||||||
Ctx.DoBandDown := CATDoBandDown;
|
|
||||||
Ctx.DoTuneUp := CATDoTuneUp;
|
|
||||||
Ctx.DoTuneDown := CATDoTuneDown;
|
|
||||||
Ctx.DoBandByIndex := FWebAdapter.OnBand;
|
|
||||||
FCATEngine := TCATEngine.Create(Ctx);
|
|
||||||
FCATSerial := TCATSerialManager.Create(FCATEngine);
|
|
||||||
FCATTcp := TCATTcpServer.Create(FCATEngine);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TMainForm.CATApplySettings(const G: TGlobalSettings);
|
|
||||||
var
|
|
||||||
Cfgs: array[0..3] of TCATSerialConfig;
|
|
||||||
i: Integer;
|
|
||||||
begin
|
|
||||||
for i := 0 to 3 do
|
|
||||||
begin
|
|
||||||
Cfgs[i].Enabled := G.CATSerialEnabled[i];
|
|
||||||
Cfgs[i].PortName := G.CATSerialPort[i];
|
|
||||||
Cfgs[i].BaudRate := G.CATSerialBaud[i];
|
|
||||||
Cfgs[i].DataBits := G.CATSerialDataBits[i];
|
|
||||||
Cfgs[i].StopBits := G.CATSerialStopBits[i];
|
|
||||||
case G.CATSerialParity[i] of
|
|
||||||
1: Cfgs[i].Parity := cspOdd;
|
|
||||||
2: Cfgs[i].Parity := cspEven;
|
|
||||||
else Cfgs[i].Parity := cspNone;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
FCATSerial.ApplyConfig(Cfgs);
|
|
||||||
FCATTcp.Stop;
|
|
||||||
if G.CATTcpEnabled then
|
|
||||||
begin
|
|
||||||
FCATTcp.Port := G.CATTcpPort;
|
|
||||||
FCATTcp.Start;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TMainForm.OnCATSettingsChange(
|
procedure TMainForm.OnCATSettingsChange(
|
||||||
const SerEnabled: array of Boolean;
|
const SerEnabled: array of Boolean;
|
||||||
const SerPort: array of string;
|
const SerPort: array of string;
|
||||||
@@ -5642,126 +5533,10 @@ begin
|
|||||||
FController.FLoadedGlobal.CATSerialParity := FCATLastGlobal.CATSerialParity;
|
FController.FLoadedGlobal.CATSerialParity := FCATLastGlobal.CATSerialParity;
|
||||||
FController.FLoadedGlobal.CATTcpEnabled := FCATLastGlobal.CATTcpEnabled;
|
FController.FLoadedGlobal.CATTcpEnabled := FCATLastGlobal.CATTcpEnabled;
|
||||||
FController.FLoadedGlobal.CATTcpPort := FCATLastGlobal.CATTcpPort;
|
FController.FLoadedGlobal.CATTcpPort := FCATLastGlobal.CATTcpPort;
|
||||||
CATApplySettings(FCATLastGlobal);
|
FCATAdapter.ApplySettings(FCATLastGlobal);
|
||||||
FController.FSettings.SaveCATSettings(FCATLastGlobal);
|
FController.FSettings.SaveCATSettings(FCATLastGlobal);
|
||||||
FController.SaveGlobalSettings;
|
FController.SaveGlobalSettings;
|
||||||
FController.FSettings.Save;
|
FController.FSettings.Save;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- Getters (called from CAT thread — read only, no sync needed) -----------
|
|
||||||
|
|
||||||
function TMainForm.CATGetVfoA: Double; begin Result := FController.FVfoA; end;
|
|
||||||
function TMainForm.CATGetVfoB: Double; begin Result := FController.FVfoB; end;
|
|
||||||
function TMainForm.CATGetMode: Integer; begin Result := FController.FMode; end;
|
|
||||||
function TMainForm.CATGetActiveVfo: Integer; begin Result := FController.FActiveVfo; end;
|
|
||||||
function TMainForm.CATGetAGCMode: Integer; begin Result := FController.FAGCMode; end;
|
|
||||||
function TMainForm.CATGetVolume: Integer; begin Result := FController.FVolume; end;
|
|
||||||
function TMainForm.CATGetDriveLevel: Integer;begin Result := FController.FDrivePercent; end;
|
|
||||||
function TMainForm.CATGetFilterIdx: Integer; begin Result := FController.FFilter; end;
|
|
||||||
function TMainForm.CATGetFilterBW: Integer; begin Result := FController.FFilterBW; end;
|
|
||||||
function TMainForm.CATGetNRMode: Integer; begin Result := FController.FNRMode; end;
|
|
||||||
function TMainForm.CATGetNBMode: Integer; begin Result := FController.FNBMode; end;
|
|
||||||
function TMainForm.CATGetSNB: Boolean; begin Result := FController.FSNB; end;
|
|
||||||
function TMainForm.CATGetANF: Boolean; begin Result := FController.FANF; end;
|
|
||||||
function TMainForm.CATGetTX: Boolean; begin Result := FController.FTransmitting; end;
|
|
||||||
function TMainForm.CATGetRunning: Boolean; begin Result := FController.FRunning; end;
|
|
||||||
function TMainForm.CATGetSMeter: Double; begin Result := FController.FLastSMeter; end;
|
|
||||||
function TMainForm.CATGetBand: Integer; begin Result := FController.FCurrentBand; end;
|
|
||||||
|
|
||||||
// --- Setters ----------------------------------------------------------------
|
|
||||||
|
|
||||||
procedure TMainForm.CATSetVfoA(V: Double);
|
|
||||||
begin
|
|
||||||
FCATSyncFreq := V;
|
|
||||||
TThread.Synchronize(nil, SyncCATVfoA);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TMainForm.CATSetVfoB(V: Double);
|
|
||||||
begin
|
|
||||||
FCATSyncFreq := V;
|
|
||||||
TThread.Synchronize(nil, SyncCATVfoB);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TMainForm.CATSetFilterIdx(V: Integer);
|
|
||||||
begin
|
|
||||||
// OnFilter: negative value encodes 0-based index as -(idx+1)
|
|
||||||
FWebAdapter.OnFilter(-(V + 1));
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TMainForm.CATDoBandUp;
|
|
||||||
begin TThread.Synchronize(nil, SyncCATBandUp); end;
|
|
||||||
|
|
||||||
procedure TMainForm.CATDoBandDown;
|
|
||||||
begin TThread.Synchronize(nil, SyncCATBandDown); end;
|
|
||||||
|
|
||||||
procedure TMainForm.CATDoTuneUp;
|
|
||||||
begin TThread.Synchronize(nil, SyncCATTuneUp); end;
|
|
||||||
|
|
||||||
procedure TMainForm.CATDoTuneDown;
|
|
||||||
begin TThread.Synchronize(nil, SyncCATTuneDown); end;
|
|
||||||
|
|
||||||
// --- Sync methods (run in main thread) --------------------------------------
|
|
||||||
|
|
||||||
procedure TMainForm.SyncCATVfoA;
|
|
||||||
var BandIdx: Integer;
|
|
||||||
begin
|
|
||||||
FController.FVfoA := FCATSyncFreq;
|
|
||||||
if FController.FActiveVfo = 0 then
|
|
||||||
begin
|
|
||||||
ApplyVfoA(Round(FController.FVfoA));
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
// VFO A is not active — just update display and band indicator
|
|
||||||
FreqDispA.Frequency := Round(FController.FVfoA);
|
|
||||||
BandIdx := FreqToBandIdx(FController.FVfoA);
|
|
||||||
if (BandIdx >= 0) and (BandIdx <> FController.FCurrentBand) then
|
|
||||||
begin
|
|
||||||
StyleButton(BtnBand[FController.FCurrentBand], False);
|
|
||||||
FController.FCurrentBand := BandIdx;
|
|
||||||
StyleButton(BtnBand[FController.FCurrentBand], True);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TMainForm.SyncCATVfoB;
|
|
||||||
begin
|
|
||||||
// Унифицировано с десктопом/вебом: та же команда SetVfoB.
|
|
||||||
FController.SetVfoB(FCATSyncFreq);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TMainForm.SyncCATBandUp;
|
|
||||||
begin
|
|
||||||
if FController.FCurrentBand < BAND_COUNT - 1 then
|
|
||||||
FWebAdapter.OnBand(FController.FCurrentBand + 1);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TMainForm.SyncCATBandDown;
|
|
||||||
begin
|
|
||||||
if FController.FCurrentBand > 0 then
|
|
||||||
FWebAdapter.OnBand(FController.FCurrentBand - 1);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TMainForm.SyncCATTuneUp;
|
|
||||||
begin
|
|
||||||
if FController.FActiveVfo = 0 then
|
|
||||||
ApplyVfoA(Round(FController.FVfoA) + 10)
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
FCATSyncFreq := FController.FVfoB + 10;
|
|
||||||
SyncCATVfoB;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TMainForm.SyncCATTuneDown;
|
|
||||||
begin
|
|
||||||
if FController.FActiveVfo = 0 then
|
|
||||||
ApplyVfoA(Round(FController.FVfoA) - 10)
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
FCATSyncFreq := FController.FVfoB - 10;
|
|
||||||
SyncCATVfoB;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|||||||
@@ -350,6 +350,7 @@ type
|
|||||||
|
|
||||||
// Частоты / VFO
|
// Частоты / VFO
|
||||||
procedure SetVfoA(Hz: Double);
|
procedure SetVfoA(Hz: Double);
|
||||||
|
procedure StoreVfoA(Hz: Double); // сохранить частоту A без перестройки (когда активен B)
|
||||||
procedure SetVfoB(Hz: Double);
|
procedure SetVfoB(Hz: Double);
|
||||||
procedure SetActiveVfo(Idx: Integer);
|
procedure SetActiveVfo(Idx: Integer);
|
||||||
procedure TuneActiveBy(DeltaHz: Double); // энкодер VFO
|
procedure TuneActiveBy(DeltaHz: Double); // энкодер VFO
|
||||||
@@ -1249,6 +1250,27 @@ begin
|
|||||||
if Assigned(FOnAfterTune) then FOnAfterTune;
|
if Assigned(FOnAfterTune) then FOnAfterTune;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TRadioController.StoreVfoA(Hz: Double);
|
||||||
|
// Сохранить частоту VFO A БЕЗ перестройки приёмника (когда активен B — слушаем B,
|
||||||
|
// A только хранится/отображается). Симметрично «неактивной» ветке SetVfoB.
|
||||||
|
// Рендер FreqDispA — через rfVfoA (спектр он не трогает, т.к. SyncSpecViewFreq
|
||||||
|
// держит активный VFO B); смена band-кнопки — через rfBand.
|
||||||
|
var BandIdx: Integer;
|
||||||
|
begin
|
||||||
|
FVfoA := Hz;
|
||||||
|
if FCurrentXvtr < 0 then
|
||||||
|
begin
|
||||||
|
BandIdx := FreqToBandIdx(FVfoA);
|
||||||
|
if (BandIdx >= 0) and (BandIdx <> FCurrentBand) then
|
||||||
|
begin
|
||||||
|
FCurrentBand := BandIdx;
|
||||||
|
FDriveLevel := CalcDriveByte;
|
||||||
|
Changed(rfBand);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
Changed(rfVfoA);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TRadioController.SetVfoB(Hz: Double);
|
procedure TRadioController.SetVfoB(Hz: Double);
|
||||||
// VFO B всегда сохраняется. Если B активен — перестраиваем приёмник через
|
// VFO B всегда сохраняется. Если B активен — перестраиваем приёмник через
|
||||||
// ApplyTuneCore (с учётом CTUN), детектим диапазон и толкаем в сеть. Если B
|
// ApplyTuneCore (с учётом CTUN), детектим диапазон и толкаем в сеть. Если B
|
||||||
|
|||||||
Reference in New Issue
Block a user