mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
First sliders through the controller, exercising the FSyncingFromController re-entrancy guard: - SetVolume/SetAGCTop clamp, apply to the DSP engine, update band cache, and fire OnStateChanged. SetAGCTop reuses ApplyAGCToEngine (the unified AGC index->enum mapping), fixing the same bad TWDSPAGCMode(index) cast that TrkAGCChange/SyncWebAGCTop used when re-applying AGC on level change. - OnControllerState updates the slider/label/spectrum (rfAGCTop also refreshes the FSpecView AGC line, now consistent for web-initiated changes too) and the FSpecView waterfall flags (rfWfAGC/rfWfNF). - TrkVolumeChange/TrkAGCChange (guarded), SyncWebVolume/AGCTop/WfAGC/WfNF, and ApplyWfAGCNF all call the commands. Builds clean (cocoa). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
547 lines
21 KiB
ObjectPascal
547 lines
21 KiB
ObjectPascal
unit RadioController;
|
|
|
|
{
|
|
EWSDR — Radio Controller (headless ядро)
|
|
|
|
Назначение
|
|
----------
|
|
TRadioController — «мозг» трансивера БЕЗ привязки к UI/LCL-формам. Владеет
|
|
состоянием радио и движками (сеть HPSDR, WDSP, аудио, настройки, каналы) и
|
|
предоставляет единый интерфейс управления для ЛЮБОГО фронтенда: GUI, Web, CAT,
|
|
аппаратная панель Arduino.
|
|
|
|
• Команды (SetMode, SetVfoA, TuneActiveBy, StartStop, …) — единая точка входа.
|
|
Абсолютные (Set*) удобны UI/Web; относительные (*By/Up/Down) — энкодерам.
|
|
• GetSnapshot → TRadioSnapshot — весь стейт одной записью (синхронизация
|
|
нового фронтенда при подключении: LED/дисплеи панели, веб-клиент).
|
|
• OnStateChanged(Field) — гранулярное уведомление об изменении поля; все
|
|
фронтенды остаются синхронны, кто бы ни инициировал изменение.
|
|
|
|
Маршалинг потоков
|
|
-----------------
|
|
Команды из сетевых/serial/web-потоков идут через OnInvoke (GUI = обёртка над
|
|
TThread.Synchronize; демон = своя очередь/прямой вызов), чтобы вызовы движка
|
|
шли из одного потока без зависимости от GUI-цикла LCL.
|
|
|
|
СТАТУС МИГРАЦИИ (Фаза 1)
|
|
------------------------
|
|
Состояние и движки вынесены сюда как ПУБЛИЧНЫЕ ПОЛЯ с теми же именами, что были
|
|
в TMainForm (FVfoA, FNetwork, FDSPEngine, …), чтобы проводка MainForm свелась к
|
|
механической замене FXxx -> FController.FXxx без изменения поведения. Логика
|
|
операций (ApplyModeFilter, BtnStartStopClick, ApplyVfoA, …) пока остаётся в
|
|
MainForm; команды контроллера обновляют поле + шлют событие и будут наполнены
|
|
логикой на следующих фазах (помечено TODO-wiring). Поля станут приватными,
|
|
когда MainForm перестанет писать в них напрямую.
|
|
|
|
ВЛАДЕНИЕ ДВИЖКАМИ (Фаза 1): объекты создаёт и освобождает MainForm (в
|
|
FormCreate/FormDestroy), сохраняя в поля контроллера. Перенос создания в
|
|
Create/Destroy контроллера — отдельная фаза (нужен для режима демона).
|
|
|
|
FPC 3.2+ / режим Delphi. Без inline var и анонимных процедур.
|
|
}
|
|
|
|
{$IFDEF FPC}
|
|
{$MODE Delphi}
|
|
{$ENDIF}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils,
|
|
HPSDRProtocol, HPSDRNetwork,
|
|
WDSPEngine, AudioOutput, AudioInput,
|
|
Settings, ChannelStore;
|
|
|
|
type
|
|
// Поле, которое изменилось — для гранулярных уведомлений наружу.
|
|
TRadioField = (
|
|
rfVfoA, rfVfoB, rfActiveVfo,
|
|
rfMode, rfFilter, rfFilterBW,
|
|
rfAGCMode, rfAGCTop,
|
|
rfVolume, rfMute, rfDrive, rfAtten,
|
|
rfBand, rfXvtr,
|
|
rfCenterFreq, rfSpan, rfSampleRate,
|
|
rfCTun, rfDuplex,
|
|
rfRunning, rfConnected, rfTransmitting, rfTuning,
|
|
rfNR, rfNB, rfSNB, rfANF,
|
|
rfWfAGC, rfWfNF, rfDither, rfRandom,
|
|
rfFMDeviation, rfFMCTCSS, rfFMCTCSSTone, rfFMSQ, rfFMSQLevel,
|
|
rfFMStep, rfFMStepIdx, rfFMRpt,
|
|
rfChannel,
|
|
rfSMeter, rfPower, rfSWR, rfSupply, rfPLL, // телеметрия
|
|
rfDevice // подключённое устройство сменилось
|
|
);
|
|
|
|
TRadioStateEvent = procedure(Sender: TObject; Field: TRadioField) of object;
|
|
|
|
// Маршалинг произвольного метода в поток контроллера (GUI: TThread.Synchronize).
|
|
TUIInvokeEvent = procedure(M: TThreadMethod) of object;
|
|
|
|
// Снимок состояния для синхронизации нового фронтенда (Arduino/Web на connect).
|
|
TRadioSnapshot = record
|
|
VfoA, VfoB, CenterFreq, SpanHz: Double;
|
|
SampleRate: Integer;
|
|
ActiveVfo: Integer;
|
|
Mode, Filter, FilterBW: Integer;
|
|
AGCMode, AGCTop: Integer;
|
|
Volume, Drive, Atten: Integer;
|
|
Band, Xvtr: Integer;
|
|
Muted, CTun, Duplex: Boolean;
|
|
Running, Connected, Transmitting, Tuning: Boolean;
|
|
NRMode, NBMode: Integer;
|
|
SNB, ANF: Boolean;
|
|
WfAGC, WfNF: Boolean;
|
|
FMStepOn: Boolean;
|
|
FMStepIdx: Integer;
|
|
FMCTCSSOn: Boolean;
|
|
FMCTCSSToneIdx: Integer;
|
|
FMSQOn: Boolean;
|
|
FMSQLevel: Integer;
|
|
FMRptDir: Integer;
|
|
SMeter, FwdW, SWR, SupplyV, SupplyA: Double;
|
|
PLLLock: Boolean;
|
|
end;
|
|
|
|
{ TRadioController }
|
|
TRadioController = class
|
|
private
|
|
FOnInvoke: TUIInvokeEvent;
|
|
FOnStateChanged: TRadioStateEvent;
|
|
procedure Changed(Field: TRadioField);
|
|
procedure ApplyAGCToEngine; // применяет FAGCMode к WDSP (единый маппинг)
|
|
public
|
|
// ============================================================
|
|
// ПУБЛИЧНЫЕ ПОЛЯ (миграционные — имена совпадают с TMainForm).
|
|
// Внешний чистый доступ для адаптеров — через команды / GetSnapshot /
|
|
// OnStateChanged. Прямая запись извне — временная мера на время Фазы 1.
|
|
// ============================================================
|
|
|
|
// ---- Движки (владение: см. шапку юнита) ----
|
|
FNetwork: THPSDRNetwork;
|
|
FDSPEngine: TWDSPEngine;
|
|
FAudioOut: TAudioOutput;
|
|
FAudioIn: TAudioInput;
|
|
FSettings: TSettingsManager;
|
|
FChannelStore: TChannelStore;
|
|
FWDSPReady: Boolean;
|
|
|
|
// ---- Частоты / режим / фильтр / AGC ----
|
|
FVfoA, FVfoB: Double;
|
|
FActiveVfo: Integer;
|
|
FMode: Integer;
|
|
FFilter: Integer;
|
|
FFilterBW: Integer;
|
|
FAGCMode: Integer;
|
|
FAGCTop: Integer;
|
|
FCTun: Boolean;
|
|
FCenterFreq: Double;
|
|
FSpanHz: Double;
|
|
FSampleRate: Integer;
|
|
FCurrentBand: Integer;
|
|
FCurrentXvtr: Integer;
|
|
|
|
// ---- Аудио / TX ----
|
|
FVolume: Integer;
|
|
FMuted: Boolean;
|
|
FDrivePercent: Integer; // драйв 0..100 % (UI-уровень, источник истины)
|
|
FDriveLevel: Byte; // вычисляемый hardware-байт (CalcDriveByte)
|
|
FAtten: Integer;
|
|
FPAMaxPower: Double;
|
|
FRunning: Boolean;
|
|
FTransmitting: Boolean;
|
|
FTuning: Boolean;
|
|
FSplitTxB: Boolean;
|
|
FDisplayDuplex: Boolean;
|
|
FHWPTTActive: Boolean;
|
|
FHWPTTStartedTX: Boolean;
|
|
FSendAudioToRadio: Boolean;
|
|
FAudioOutDevName: string;
|
|
FAudioInDevName: string;
|
|
FDevConnected: Boolean;
|
|
|
|
// ---- DSP-фильтры шума / водопад ----
|
|
FNRMode, FNBMode: Integer; // источник истины (раньше Btn*.Tag)
|
|
FSNB, FANF: Boolean; // источник истины (раньше Btn*.Tag)
|
|
FWfAGCEnabled: Boolean;
|
|
FWfNFEnabled: Boolean;
|
|
FDitherEnabled: Boolean;
|
|
FRandomEnabled: Boolean;
|
|
|
|
// ---- FM ----
|
|
FFMDeviation: Double;
|
|
FFMCTCSSOn: Boolean;
|
|
FFMCTCSSToneIdx: Integer;
|
|
FFMSQOn: Boolean;
|
|
FFMSQLevel: Integer;
|
|
FFMStepOn: Boolean;
|
|
FFMStepIdx: Integer;
|
|
FFMRptDir: Integer;
|
|
FFMRptOffsetHz: Double;
|
|
FFMRptAutoActive: Boolean;
|
|
FFMCTCSSAutoActive: Boolean;
|
|
|
|
// ---- Конфиги / устройство (per-MAC) ----
|
|
FTXSettings: TTXSettings;
|
|
FAlexSettings: TAlexSettings;
|
|
FXvtrSettings: TXvtrSettings;
|
|
FBandCache: array[0..CFG_BAND_COUNT-1] of TBandSettings;
|
|
FPABandCal: array[0..CFG_BAND_COUNT-1] of Double;
|
|
FVHFBandCal: array[0..CFG_XVTR_COUNT-1] of Double;
|
|
FDevMAC: array[0..5] of Byte;
|
|
|
|
// ---- Телеметрия (наполняется в Фазе 3/4 вместе с сетевыми колбэками) ----
|
|
FLastSMeter, FLastFwdW, FLastSWR, FLastSupplyV, FLastSupplyA: Double;
|
|
FLastPLLLock: Boolean;
|
|
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
|
|
// Маршалинг команды в поток контроллера (GUI: TThread.Synchronize).
|
|
procedure Invoke(M: TThreadMethod);
|
|
|
|
// Снимок всего состояния (для синхронизации нового фронтенда).
|
|
function GetSnapshot: TRadioSnapshot;
|
|
|
|
// ====================================================================
|
|
// КОМАНДЫ — единый API для GUI / Web / CAT / Arduino.
|
|
// Фаза 1: обновляют поле + шлют событие; логика движка — TODO-wiring.
|
|
// ====================================================================
|
|
|
|
// Частоты / VFO
|
|
procedure SetVfoA(Hz: Double);
|
|
procedure SetVfoB(Hz: Double);
|
|
procedure SetActiveVfo(Idx: Integer);
|
|
procedure TuneActiveBy(DeltaHz: Double); // энкодер VFO
|
|
procedure SetCenter(Hz: Double);
|
|
procedure VfoSwap;
|
|
procedure VfoACopyB;
|
|
procedure VfoBCopyA;
|
|
|
|
// Режим / фильтр / AGC
|
|
procedure SetMode(M: Integer);
|
|
procedure SetFilterIdx(Idx: Integer);
|
|
procedure SetFilterBW(BWHz: Integer);
|
|
procedure SetAGCMode(M: Integer);
|
|
procedure SetAGCTop(DB: Integer);
|
|
procedure AGCTopBy(Delta: Integer);
|
|
|
|
// Громкость / mute / drive / аттенюатор
|
|
procedure SetVolume(V: Integer);
|
|
procedure VolumeBy(Delta: Integer);
|
|
procedure SetMute(On_: Boolean);
|
|
procedure ToggleMute;
|
|
procedure SetDrive(V: Integer);
|
|
procedure DriveBy(Delta: Integer);
|
|
procedure SetAtten(Idx: Integer);
|
|
|
|
// Диапазоны / трансвертеры / спан
|
|
procedure SetBand(Idx: Integer);
|
|
procedure BandUp;
|
|
procedure BandDown;
|
|
procedure SetXvtrBand(Idx: Integer); // -1 = выход в HF
|
|
procedure SetSpan(Hz: Integer);
|
|
procedure SetSampleRate(Hz: Integer);
|
|
|
|
// Отображение / приём
|
|
procedure SetCTun(On_: Boolean);
|
|
procedure SetDuplex(On_: Boolean);
|
|
procedure SetWfAGC(On_: Boolean);
|
|
procedure SetWfNF(On_: Boolean);
|
|
|
|
// DSP-фильтры шума
|
|
procedure SetNR(Mode: Integer);
|
|
procedure SetNB(Mode: Integer);
|
|
procedure SetSNB(On_: Boolean);
|
|
procedure SetANF(On_: Boolean);
|
|
|
|
// Передача
|
|
procedure SetMOX(On_: Boolean);
|
|
procedure SetTune(On_: Boolean); // TUN
|
|
|
|
// FM
|
|
procedure SetFMStep(Idx: Integer);
|
|
procedure SetFMCTCSS(On_: Boolean);
|
|
procedure SetFMCTCSSTone(Idx: Integer);
|
|
procedure SetFMSquelch(On_: Boolean);
|
|
procedure SetFMSquelchLevel(V: Integer);
|
|
procedure SetFMRpt(Dir: Integer);
|
|
|
|
// Каналы
|
|
procedure ApplyChannel(Idx: Integer);
|
|
|
|
// Жизненный цикл движка / устройства
|
|
procedure StartStop;
|
|
procedure SetRun(On_: Boolean);
|
|
procedure ConnectDevice(const Dev: THPSDRDevice);
|
|
procedure Discover;
|
|
|
|
// ---- События наружу ----
|
|
property OnInvoke: TUIInvokeEvent read FOnInvoke write FOnInvoke;
|
|
property OnStateChanged: TRadioStateEvent read FOnStateChanged write FOnStateChanged;
|
|
end;
|
|
|
|
implementation
|
|
|
|
constructor TRadioController.Create;
|
|
begin
|
|
inherited Create;
|
|
// Дефолты (дублируют TMainForm.FormCreate; в GUI перезапишутся, в демоне нужны).
|
|
FVfoA := 14200000; FVfoB := 7100000; FActiveVfo := 0;
|
|
FMode := 1; FFilter := 5; FFilterBW := 2700;
|
|
FAGCMode := 1; FAGCTop := 90;
|
|
FVolume := 70; FDrivePercent := 50; FDriveLevel := 0; FAtten := 0;
|
|
FCenterFreq := FVfoA; FSpanHz := 192000; FSampleRate := 192000;
|
|
FCurrentBand := 5; FCurrentXvtr := -1;
|
|
FPAMaxPower := 100.0;
|
|
FWfAGCEnabled := True; FDitherEnabled := True; FRandomEnabled := True;
|
|
FFMStepOn := True;
|
|
FLastSMeter := -130; FLastSWR := 1; FLastSupplyV := -1; FLastSupplyA := -1;
|
|
FillChar(FDevMAC, SizeOf(FDevMAC), 0);
|
|
end;
|
|
|
|
destructor TRadioController.Destroy;
|
|
begin
|
|
// Фаза 1: движки освобождает MainForm. Здесь ничего не освобождаем.
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TRadioController.Changed(Field: TRadioField);
|
|
begin
|
|
if Assigned(FOnStateChanged) then FOnStateChanged(Self, Field);
|
|
end;
|
|
|
|
procedure TRadioController.Invoke(M: TThreadMethod);
|
|
begin
|
|
if Assigned(FOnInvoke) then FOnInvoke(M)
|
|
else if Assigned(M) then M(); // нет хозяина-маршалера — прямой вызов
|
|
end;
|
|
|
|
function TRadioController.GetSnapshot: TRadioSnapshot;
|
|
begin
|
|
FillChar(Result, SizeOf(Result), 0);
|
|
Result.VfoA := FVfoA; Result.VfoB := FVfoB;
|
|
Result.CenterFreq := FCenterFreq; Result.SpanHz := FSpanHz;
|
|
Result.SampleRate := FSampleRate; Result.ActiveVfo := FActiveVfo;
|
|
Result.Mode := FMode; Result.Filter := FFilter; Result.FilterBW := FFilterBW;
|
|
Result.AGCMode := FAGCMode; Result.AGCTop := FAGCTop;
|
|
Result.Volume := FVolume; Result.Drive := FDrivePercent; Result.Atten := FAtten;
|
|
Result.Band := FCurrentBand; Result.Xvtr := FCurrentXvtr;
|
|
Result.Muted := FMuted; Result.CTun := FCTun; Result.Duplex := FDisplayDuplex;
|
|
Result.Running := FRunning; Result.Connected := FDevConnected;
|
|
Result.Transmitting := FTransmitting; Result.Tuning := FTuning;
|
|
Result.NRMode := FNRMode; Result.NBMode := FNBMode;
|
|
Result.SNB := FSNB; Result.ANF := FANF;
|
|
Result.WfAGC := FWfAGCEnabled; Result.WfNF := FWfNFEnabled;
|
|
Result.FMStepOn := FFMStepOn; Result.FMStepIdx := FFMStepIdx;
|
|
Result.FMCTCSSOn := FFMCTCSSOn; Result.FMCTCSSToneIdx := FFMCTCSSToneIdx;
|
|
Result.FMSQOn := FFMSQOn; Result.FMSQLevel := FFMSQLevel;
|
|
Result.FMRptDir := FFMRptDir;
|
|
Result.SMeter := FLastSMeter; Result.FwdW := FLastFwdW; Result.SWR := FLastSWR;
|
|
Result.SupplyV := FLastSupplyV; Result.SupplyA := FLastSupplyA;
|
|
Result.PLLLock := FLastPLLLock;
|
|
end;
|
|
|
|
// =====================================================================
|
|
// Команды (Фаза 1 — каркас). Полная логика переносится из TMainForm.
|
|
// =====================================================================
|
|
|
|
procedure TRadioController.SetVfoA(Hz: Double);
|
|
begin FVfoA := Hz; Changed(rfVfoA); { TODO wiring: ApplyVfoA } end;
|
|
|
|
procedure TRadioController.SetVfoB(Hz: Double);
|
|
begin FVfoB := Hz; Changed(rfVfoB); { TODO wiring } end;
|
|
|
|
procedure TRadioController.SetActiveVfo(Idx: Integer);
|
|
begin FActiveVfo := Idx; Changed(rfActiveVfo); { TODO wiring: ActivateVfo } end;
|
|
|
|
procedure TRadioController.TuneActiveBy(DeltaHz: Double);
|
|
begin
|
|
if FActiveVfo = 0 then SetVfoA(FVfoA + DeltaHz)
|
|
else SetVfoB(FVfoB + DeltaHz);
|
|
end;
|
|
|
|
procedure TRadioController.SetCenter(Hz: Double);
|
|
begin FCenterFreq := Hz; Changed(rfCenterFreq); { TODO wiring } end;
|
|
|
|
procedure TRadioController.VfoSwap;
|
|
var T: Double;
|
|
begin T := FVfoA; FVfoA := FVfoB; FVfoB := T; Changed(rfVfoA); Changed(rfVfoB); { TODO wiring } end;
|
|
|
|
procedure TRadioController.VfoACopyB;
|
|
begin FVfoA := FVfoB; Changed(rfVfoA); { TODO wiring } end;
|
|
|
|
procedure TRadioController.VfoBCopyA;
|
|
begin FVfoB := FVfoA; Changed(rfVfoB); { TODO wiring } end;
|
|
|
|
procedure TRadioController.SetMode(M: Integer);
|
|
begin FMode := M; Changed(rfMode); { TODO wiring: ApplyModeFilter } end;
|
|
|
|
procedure TRadioController.SetFilterIdx(Idx: Integer);
|
|
begin FFilter := Idx; Changed(rfFilter); { TODO wiring } end;
|
|
|
|
procedure TRadioController.SetFilterBW(BWHz: Integer);
|
|
begin FFilterBW := BWHz; Changed(rfFilterBW); { TODO wiring } end;
|
|
|
|
procedure TRadioController.ApplyAGCToEngine;
|
|
const
|
|
// UI-индекс 0..4 (FAST/MED/SLOW/LONG/OFF) -> WDSP enum. Единый маппинг для
|
|
// всех фронтендов (раньше web/слайдер ошибочно кастовали индекс прямо в enum).
|
|
AGCModes: array[0..4] of TWDSPAGCMode = (agcFast, agcMedium, agcSlow, agcLong, agcOff);
|
|
begin
|
|
if FWDSPReady and Assigned(FDSPEngine) and (FAGCMode >= 0) and (FAGCMode <= 4) then
|
|
FDSPEngine.SetAGC(AGCModes[FAGCMode], 50.0);
|
|
end;
|
|
|
|
procedure TRadioController.SetAGCMode(M: Integer);
|
|
begin
|
|
if (M < 0) or (M > 4) then Exit;
|
|
FAGCMode := M;
|
|
ApplyAGCToEngine;
|
|
FBandCache[FCurrentBand].AGCMode := FAGCMode;
|
|
Changed(rfAGCMode);
|
|
end;
|
|
|
|
procedure TRadioController.SetAGCTop(DB: Integer);
|
|
begin
|
|
if DB < 20 then DB := 20 else if DB > 120 then DB := 120;
|
|
FAGCTop := DB;
|
|
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetAGCTop(FAGCTop);
|
|
ApplyAGCToEngine; // ре-применяем режим с новым уровнем
|
|
FBandCache[FCurrentBand].AGCTop := FAGCTop;
|
|
Changed(rfAGCTop);
|
|
end;
|
|
|
|
procedure TRadioController.AGCTopBy(Delta: Integer);
|
|
begin SetAGCTop(FAGCTop + Delta); end;
|
|
|
|
procedure TRadioController.SetVolume(V: Integer);
|
|
begin
|
|
if V < 0 then V := 0 else if V > 100 then V := 100;
|
|
FVolume := V;
|
|
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetVolume(FVolume / 100.0);
|
|
Changed(rfVolume);
|
|
end;
|
|
|
|
procedure TRadioController.VolumeBy(Delta: Integer);
|
|
begin SetVolume(FVolume + Delta); end;
|
|
|
|
procedure TRadioController.SetMute(On_: Boolean);
|
|
begin
|
|
FMuted := On_;
|
|
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetMute(FMuted);
|
|
Changed(rfMute);
|
|
end;
|
|
|
|
procedure TRadioController.ToggleMute;
|
|
begin SetMute(not FMuted); end;
|
|
|
|
procedure TRadioController.SetDrive(V: Integer);
|
|
begin FDrivePercent := V; Changed(rfDrive); { TODO wiring: CalcDriveByte + WDSP } end;
|
|
|
|
procedure TRadioController.DriveBy(Delta: Integer);
|
|
begin SetDrive(FDrivePercent + Delta); end;
|
|
|
|
procedure TRadioController.SetAtten(Idx: Integer);
|
|
begin FAtten := Idx; Changed(rfAtten); { TODO wiring } end;
|
|
|
|
procedure TRadioController.SetBand(Idx: Integer);
|
|
begin FCurrentBand := Idx; Changed(rfBand); { TODO wiring: RestoreBand } end;
|
|
|
|
procedure TRadioController.BandUp;
|
|
begin if FCurrentBand < CFG_BAND_COUNT - 1 then SetBand(FCurrentBand + 1); end;
|
|
|
|
procedure TRadioController.BandDown;
|
|
begin if FCurrentBand > 0 then SetBand(FCurrentBand - 1); end;
|
|
|
|
procedure TRadioController.SetXvtrBand(Idx: Integer);
|
|
begin FCurrentXvtr := Idx; Changed(rfXvtr); { TODO wiring } end;
|
|
|
|
procedure TRadioController.SetSpan(Hz: Integer);
|
|
begin FSpanHz := Hz; Changed(rfSpan); { TODO wiring } end;
|
|
|
|
procedure TRadioController.SetSampleRate(Hz: Integer);
|
|
begin FSampleRate := Hz; Changed(rfSampleRate); { TODO wiring: RecreateDSPEngine } end;
|
|
|
|
procedure TRadioController.SetCTun(On_: Boolean);
|
|
begin FCTun := On_; Changed(rfCTun); { TODO wiring } end;
|
|
|
|
procedure TRadioController.SetDuplex(On_: Boolean);
|
|
begin FDisplayDuplex := On_; Changed(rfDuplex); { TODO wiring } end;
|
|
|
|
procedure TRadioController.SetWfAGC(On_: Boolean);
|
|
begin FWfAGCEnabled := On_; Changed(rfWfAGC); end;
|
|
|
|
procedure TRadioController.SetWfNF(On_: Boolean);
|
|
begin FWfNFEnabled := On_; Changed(rfWfNF); end;
|
|
|
|
procedure TRadioController.SetNR(Mode: Integer);
|
|
begin
|
|
if Mode < 0 then Mode := 0 else if Mode > 4 then Mode := 4;
|
|
FNRMode := Mode;
|
|
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetNRMode(FNRMode);
|
|
Changed(rfNR);
|
|
end;
|
|
|
|
procedure TRadioController.SetNB(Mode: Integer);
|
|
begin
|
|
if Mode < 0 then Mode := 0 else if Mode > 2 then Mode := 2;
|
|
FNBMode := Mode;
|
|
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetNBMode(FNBMode);
|
|
Changed(rfNB);
|
|
end;
|
|
|
|
procedure TRadioController.SetSNB(On_: Boolean);
|
|
begin
|
|
FSNB := On_;
|
|
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetSNB(FSNB);
|
|
Changed(rfSNB);
|
|
end;
|
|
|
|
procedure TRadioController.SetANF(On_: Boolean);
|
|
begin
|
|
FANF := On_;
|
|
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetANF(FANF);
|
|
Changed(rfANF);
|
|
end;
|
|
|
|
procedure TRadioController.SetMOX(On_: Boolean);
|
|
begin FTransmitting := On_; Changed(rfTransmitting); { TODO wiring: ApplyMOX } end;
|
|
|
|
procedure TRadioController.SetTune(On_: Boolean);
|
|
begin FTuning := On_; Changed(rfTuning); { TODO wiring: ApplyTUN } end;
|
|
|
|
procedure TRadioController.SetFMStep(Idx: Integer);
|
|
begin FFMStepIdx := Idx; Changed(rfFMStepIdx); { TODO wiring } end;
|
|
|
|
procedure TRadioController.SetFMCTCSS(On_: Boolean);
|
|
begin FFMCTCSSOn := On_; Changed(rfFMCTCSS); { TODO wiring } end;
|
|
|
|
procedure TRadioController.SetFMCTCSSTone(Idx: Integer);
|
|
begin FFMCTCSSToneIdx := Idx; Changed(rfFMCTCSSTone); { TODO wiring } end;
|
|
|
|
procedure TRadioController.SetFMSquelch(On_: Boolean);
|
|
begin FFMSQOn := On_; Changed(rfFMSQ); { TODO wiring } end;
|
|
|
|
procedure TRadioController.SetFMSquelchLevel(V: Integer);
|
|
begin FFMSQLevel := V; Changed(rfFMSQLevel); { TODO wiring } end;
|
|
|
|
procedure TRadioController.SetFMRpt(Dir: Integer);
|
|
begin FFMRptDir := Dir; Changed(rfFMRpt); { TODO wiring } end;
|
|
|
|
procedure TRadioController.ApplyChannel(Idx: Integer);
|
|
begin Changed(rfChannel); { TODO wiring } end;
|
|
|
|
procedure TRadioController.StartStop;
|
|
begin SetRun(not FRunning); end;
|
|
|
|
procedure TRadioController.SetRun(On_: Boolean);
|
|
begin FRunning := On_; Changed(rfRunning); { TODO wiring: логика BtnStartStopClick } end;
|
|
|
|
procedure TRadioController.ConnectDevice(const Dev: THPSDRDevice);
|
|
begin { TODO wiring: DoConnectDevice } Changed(rfDevice); end;
|
|
|
|
procedure TRadioController.Discover;
|
|
begin { TODO wiring: FNetwork.Discover } end;
|
|
|
|
end.
|