mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
add nb nr
This commit is contained in:
+161
-50
@@ -315,6 +315,7 @@ type
|
|||||||
TrkVolume: TTrackBar;
|
TrkVolume: TTrackBar;
|
||||||
BtnNR: TFlatButton;
|
BtnNR: TFlatButton;
|
||||||
BtnNB: TFlatButton;
|
BtnNB: TFlatButton;
|
||||||
|
BtnSNB: TFlatButton;
|
||||||
BtnANF: TFlatButton;
|
BtnANF: TFlatButton;
|
||||||
BtnMute: TFlatButton;
|
BtnMute: TFlatButton;
|
||||||
|
|
||||||
@@ -436,8 +437,14 @@ type
|
|||||||
procedure BtnVfoBCopyAClick(Sender: TObject);
|
procedure BtnVfoBCopyAClick(Sender: TObject);
|
||||||
procedure BtnMOXClick(Sender: TObject);
|
procedure BtnMOXClick(Sender: TObject);
|
||||||
procedure BtnMuteClick(Sender: TObject);
|
procedure BtnMuteClick(Sender: TObject);
|
||||||
|
procedure UpdateNRButton;
|
||||||
|
procedure UpdateNBButton;
|
||||||
|
procedure UpdateSNBButton;
|
||||||
|
procedure UpdateANFButton;
|
||||||
|
procedure ApplyNoiseFilterButtonsToDSP;
|
||||||
procedure BtnNRClick(Sender: TObject);
|
procedure BtnNRClick(Sender: TObject);
|
||||||
procedure BtnNBClick(Sender: TObject);
|
procedure BtnNBClick(Sender: TObject);
|
||||||
|
procedure BtnSNBClick(Sender: TObject);
|
||||||
procedure BtnANFClick(Sender: TObject);
|
procedure BtnANFClick(Sender: TObject);
|
||||||
procedure BtnSpanClick(Sender: TObject);
|
procedure BtnSpanClick(Sender: TObject);
|
||||||
// Веб-интерфейс: callbacks от TWebServer
|
// Веб-интерфейс: callbacks от TWebServer
|
||||||
@@ -454,8 +461,9 @@ type
|
|||||||
procedure WebOnRun(On_: Boolean);
|
procedure WebOnRun(On_: Boolean);
|
||||||
procedure WebOnMute(On_: Boolean);
|
procedure WebOnMute(On_: Boolean);
|
||||||
procedure WebOnCtun(On_: Boolean);
|
procedure WebOnCtun(On_: Boolean);
|
||||||
procedure WebOnNR(On_: Boolean);
|
procedure WebOnNR(Mode: Integer);
|
||||||
procedure WebOnNB(On_: Boolean);
|
procedure WebOnNB(Mode: Integer);
|
||||||
|
procedure WebOnSNB(On_: Boolean);
|
||||||
procedure WebOnANF(On_: Boolean);
|
procedure WebOnANF(On_: Boolean);
|
||||||
// Synchronize-обёртки (выполняются в UI-потоке)
|
// Synchronize-обёртки (выполняются в UI-потоке)
|
||||||
procedure SyncWebFreq;
|
procedure SyncWebFreq;
|
||||||
@@ -473,6 +481,7 @@ type
|
|||||||
procedure SyncWebCtun;
|
procedure SyncWebCtun;
|
||||||
procedure SyncWebNR;
|
procedure SyncWebNR;
|
||||||
procedure SyncWebNB;
|
procedure SyncWebNB;
|
||||||
|
procedure SyncWebSNB;
|
||||||
procedure SyncWebANF;
|
procedure SyncWebANF;
|
||||||
procedure BtnWfAGCClick(Sender: TObject);
|
procedure BtnWfAGCClick(Sender: TObject);
|
||||||
procedure BtnWfNFClick(Sender: TObject);
|
procedure BtnWfNFClick(Sender: TObject);
|
||||||
@@ -618,9 +627,10 @@ begin
|
|||||||
Result.Volume := FVolume;
|
Result.Volume := FVolume;
|
||||||
Result.DriveLevel := FDriveLevel;
|
Result.DriveLevel := FDriveLevel;
|
||||||
Result.ActiveVfo := FActiveVfo;
|
Result.ActiveVfo := FActiveVfo;
|
||||||
Result.NREnabled := BtnNR.Tag = 1;
|
Result.NRMode := BtnNR.Tag;
|
||||||
Result.NBEnabled := BtnNB.Tag = 1;
|
Result.NBMode := BtnNB.Tag;
|
||||||
Result.ANFEnabled := BtnANF.Tag = 1;
|
Result.SNBEnabled := BtnSNB.Tag <> 0;
|
||||||
|
Result.ANFEnabled := BtnANF.Tag <> 0;
|
||||||
Result.AGCSlope := 0;
|
Result.AGCSlope := 0;
|
||||||
Result.AGCHangThreshold := 100;
|
Result.AGCHangThreshold := 100;
|
||||||
Result.WfAGCEnabled := FWfAGCEnabled;
|
Result.WfAGCEnabled := FWfAGCEnabled;
|
||||||
@@ -717,7 +727,8 @@ end;
|
|||||||
|
|
||||||
procedure TMainForm.FormCreate(Sender: TObject);
|
procedure TMainForm.FormCreate(Sender: TObject);
|
||||||
var
|
var
|
||||||
bi_: Integer;
|
bi_, StartupRate: Integer;
|
||||||
|
StartupVfoA, StartupVfoB: Double;
|
||||||
begin
|
begin
|
||||||
FVfoA := 14200000;
|
FVfoA := 14200000;
|
||||||
FVfoB := 7100000;
|
FVfoB := 7100000;
|
||||||
@@ -757,6 +768,17 @@ begin
|
|||||||
// Загружаем JSON настройки
|
// Загружаем JSON настройки
|
||||||
FSettings := TSettingsManager.Create;
|
FSettings := TSettingsManager.Create;
|
||||||
FSettings.Load;
|
FSettings.Load;
|
||||||
|
if FSettings.LoadStartupPreview(StartupVfoA, StartupVfoB, StartupRate) then
|
||||||
|
begin
|
||||||
|
FVfoA := StartupVfoA;
|
||||||
|
FVfoB := StartupVfoB;
|
||||||
|
FCenterFreq := FVfoA;
|
||||||
|
if StartupRate > 0 then
|
||||||
|
begin
|
||||||
|
FSampleRate := StartupRate;
|
||||||
|
FSpanHz := StartupRate;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
// Восстанавливаем размер/позицию окна при старте (до подключения устройства)
|
// Восстанавливаем размер/позицию окна при старте (до подключения устройства)
|
||||||
RestoreWindowBounds;
|
RestoreWindowBounds;
|
||||||
// S-метр позиционируем после рестора размера окна
|
// S-метр позиционируем после рестора размера окна
|
||||||
@@ -780,6 +802,7 @@ begin
|
|||||||
FWebServer.OnCtun := WebOnCtun;
|
FWebServer.OnCtun := WebOnCtun;
|
||||||
FWebServer.OnNR := WebOnNR;
|
FWebServer.OnNR := WebOnNR;
|
||||||
FWebServer.OnNB := WebOnNB;
|
FWebServer.OnNB := WebOnNB;
|
||||||
|
FWebServer.OnSNB := WebOnSNB;
|
||||||
FWebServer.OnANF := WebOnANF;
|
FWebServer.OnANF := WebOnANF;
|
||||||
FWebServer.Start;
|
FWebServer.Start;
|
||||||
FSMeterPeak := -130;
|
FSMeterPeak := -130;
|
||||||
@@ -824,6 +847,12 @@ begin
|
|||||||
FNetwork.OnMicPacket := OnMicPacketCB;
|
FNetwork.OnMicPacket := OnMicPacketCB;
|
||||||
|
|
||||||
BuildUI;
|
BuildUI;
|
||||||
|
StyleSpanButton(BtnSpan48k, FSampleRate = 48000);
|
||||||
|
StyleSpanButton(BtnSpan96k, FSampleRate = 96000);
|
||||||
|
StyleSpanButton(BtnSpan192k, FSampleRate = 192000);
|
||||||
|
StyleSpanButton(BtnSpan384k, FSampleRate = 384000);
|
||||||
|
StyleSpanButton(BtnSpan768k, FSampleRate = 768000);
|
||||||
|
StyleSpanButton(BtnSpan1536k, FSampleRate = 1536000);
|
||||||
ResizeSMeter;
|
ResizeSMeter;
|
||||||
ApplyDarkTheme;
|
ApplyDarkTheme;
|
||||||
UpdateVfoDisplay;
|
UpdateVfoDisplay;
|
||||||
@@ -835,7 +864,7 @@ begin
|
|||||||
// BufSize=512: FBufSize=2048 @ 192kHz, FAudioBufSize=512 @ 48kHz.
|
// BufSize=512: FBufSize=2048 @ 192kHz, FAudioBufSize=512 @ 48kHz.
|
||||||
// Уменьшение с 1024 вдвое сокращает время построения downsampler в OpenChannel RXA
|
// Уменьшение с 1024 вдвое сокращает время построения downsampler в OpenChannel RXA
|
||||||
// (~1300ms → ~650ms). Латентность: 512/48000 ≈ 10.7ms — допустимо для SDR.
|
// (~1300ms → ~650ms). Латентность: 512/48000 ≈ 10.7ms — допустимо для SDR.
|
||||||
FDSPEngine := TWDSPEngine.Create(192000, 48000, 512);
|
FDSPEngine := TWDSPEngine.Create(FSampleRate, 48000, 512);
|
||||||
FDSPEngine.OnAudio := OnAudioReady;
|
FDSPEngine.OnAudio := OnAudioReady;
|
||||||
FDSPEngine.OnSpectrum := OnSpectrumReady;
|
FDSPEngine.OnSpectrum := OnSpectrumReady;
|
||||||
|
|
||||||
@@ -898,6 +927,7 @@ begin
|
|||||||
FSettings.SaveGlobal(FDevMAC, MakeGlobalSettings);
|
FSettings.SaveGlobal(FDevMAC, MakeGlobalSettings);
|
||||||
end;
|
end;
|
||||||
// Размер окна сохраняем всегда (не зависит от подключения)
|
// Размер окна сохраняем всегда (не зависит от подключения)
|
||||||
|
FSettings.SaveStartupPreview(FVfoA, FVfoB, FSampleRate);
|
||||||
FSettings.SaveWindowBounds(Left, Top, Width, Height);
|
FSettings.SaveWindowBounds(Left, Top, Width, Height);
|
||||||
FSettings.Save;
|
FSettings.Save;
|
||||||
FSettings.Free;
|
FSettings.Free;
|
||||||
@@ -1133,22 +1163,21 @@ begin
|
|||||||
PanelRX.Parent := PanelLeft;
|
PanelRX.Parent := PanelLeft;
|
||||||
PanelRX.SetBounds(0, Y, LEFT_W, 120);
|
PanelRX.SetBounds(0, Y, LEFT_W, 120);
|
||||||
PanelRX.BevelOuter := bvNone;
|
PanelRX.BevelOuter := bvNone;
|
||||||
MakeLbl(PanelRX, 'RX', 4, 2);
|
|
||||||
|
|
||||||
// AGC mode — 5 кнопок в ряд
|
// AGC mode — 5 кнопок в ряд
|
||||||
MakeLbl(PanelRX, 'AGC', 4, 18);
|
MakeLbl(PanelRX, 'AGC', 4, 4);
|
||||||
W := (LEFT_W - 36) div 5;
|
W := (LEFT_W - 10) div 5;
|
||||||
BtnAGCMode[0] := MakeBtn(PanelRX,'FAST', 34+0*(W+1),14,W,BTN_SM,BtnAGCModeClick); BtnAGCMode[0].Tag:=0;
|
BtnAGCMode[0] := MakeBtn(PanelRX,'FAST', 2, 22, W, BTN_SM, BtnAGCModeClick); BtnAGCMode[0].Tag:=0;
|
||||||
BtnAGCMode[1] := MakeBtn(PanelRX,'MED', 34+1*(W+1),14,W,BTN_SM,BtnAGCModeClick); BtnAGCMode[1].Tag:=1;
|
BtnAGCMode[1] := MakeBtn(PanelRX,'MED', W+4, 22, W, BTN_SM, BtnAGCModeClick); BtnAGCMode[1].Tag:=1;
|
||||||
BtnAGCMode[2] := MakeBtn(PanelRX,'SLOW', 34+2*(W+1),14,W,BTN_SM,BtnAGCModeClick); BtnAGCMode[2].Tag:=2;
|
BtnAGCMode[2] := MakeBtn(PanelRX,'SLOW', 2*W+6, 22, W, BTN_SM, BtnAGCModeClick); BtnAGCMode[2].Tag:=2;
|
||||||
BtnAGCMode[3] := MakeBtn(PanelRX,'LONG', 34+3*(W+1),14,W,BTN_SM,BtnAGCModeClick); BtnAGCMode[3].Tag:=3;
|
BtnAGCMode[3] := MakeBtn(PanelRX,'LONG', 3*W+8, 22, W, BTN_SM, BtnAGCModeClick); BtnAGCMode[3].Tag:=3;
|
||||||
BtnAGCMode[4] := MakeBtn(PanelRX,'OFF', 34+4*(W+1),14,W,BTN_SM,BtnAGCModeClick); BtnAGCMode[4].Tag:=4;
|
BtnAGCMode[4] := MakeBtn(PanelRX,'OFF', 4*W+10, 22, W, BTN_SM, BtnAGCModeClick); BtnAGCMode[4].Tag:=4;
|
||||||
for i := 0 to 4 do StyleButton(BtnAGCMode[i], i = FAGCMode);
|
for i := 0 to 4 do StyleButton(BtnAGCMode[i], i = FAGCMode);
|
||||||
|
|
||||||
// AGC level slider
|
// AGC level slider
|
||||||
MakeLbl(PanelRX, 'THRESH', 4, 41);
|
MakeLbl(PanelRX, 'THRESH', 4, 50);
|
||||||
TrkAGC := TTrackBar.Create(Self);
|
TrkAGC := TTrackBar.Create(Self);
|
||||||
TrkAGC.Parent := PanelRX; TrkAGC.Left := 56; TrkAGC.Top := 37;
|
TrkAGC.Parent := PanelRX; TrkAGC.Left := 56; TrkAGC.Top := 46;
|
||||||
TrkAGC.Width := LEFT_W - 96; TrkAGC.Height := 20;
|
TrkAGC.Width := LEFT_W - 96; TrkAGC.Height := 20;
|
||||||
TrkAGC.Min := 20; TrkAGC.Max := 120; // 20..120 → −20..-120 dBm
|
TrkAGC.Min := 20; TrkAGC.Max := 120; // 20..120 → −20..-120 dBm
|
||||||
TrkAGC.Position := FAGCTop;
|
TrkAGC.Position := FAGCTop;
|
||||||
@@ -1157,26 +1186,27 @@ begin
|
|||||||
|
|
||||||
LblAGCTop := TLabel.Create(Self);
|
LblAGCTop := TLabel.Create(Self);
|
||||||
LblAGCTop.Parent := PanelRX;
|
LblAGCTop.Parent := PanelRX;
|
||||||
LblAGCTop.Left := LEFT_W - 38; LblAGCTop.Top := 41;
|
LblAGCTop.Left := LEFT_W - 38; LblAGCTop.Top := 50;
|
||||||
LblAGCTop.Caption := Format('-%ddB', [FAGCTop]);
|
LblAGCTop.Caption := Format('-%ddB', [FAGCTop]);
|
||||||
LblAGCTop.Font.Color := CLR_TEXT; LblAGCTop.Font.Name := 'Courier New';
|
LblAGCTop.Font.Color := CLR_TEXT; LblAGCTop.Font.Name := 'Courier New';
|
||||||
LblAGCTop.Font.Size := 7;
|
LblAGCTop.Font.Size := 7;
|
||||||
|
|
||||||
// VOL
|
// VOL
|
||||||
MakeLbl(PanelRX, 'VOL', 4, 65);
|
MakeLbl(PanelRX, 'VOL', 4, 74);
|
||||||
TrkVolume := TTrackBar.Create(Self);
|
TrkVolume := TTrackBar.Create(Self);
|
||||||
TrkVolume.Parent := PanelRX; TrkVolume.Left := 34; TrkVolume.Top := 61;
|
TrkVolume.Parent := PanelRX; TrkVolume.Left := 34; TrkVolume.Top := 70;
|
||||||
TrkVolume.Width := LEFT_W - 38; TrkVolume.Height := 20;
|
TrkVolume.Width := LEFT_W - 38; TrkVolume.Height := 20;
|
||||||
TrkVolume.Min := 0; TrkVolume.Max := 100;
|
TrkVolume.Min := 0; TrkVolume.Max := 100;
|
||||||
TrkVolume.Position := FVolume; TrkVolume.TickStyle := tsNone;
|
TrkVolume.Position := FVolume; TrkVolume.TickStyle := tsNone;
|
||||||
TrkVolume.OnChange := TrkVolumeChange;
|
TrkVolume.OnChange := TrkVolumeChange;
|
||||||
|
|
||||||
// NR NB ANF MUTE
|
// NR NB SNB ANF MUTE
|
||||||
W := (LEFT_W - 8) div 4;
|
W := (LEFT_W - 10) div 5;
|
||||||
BtnNR := MakeBtn(PanelRX, 'NR', 2, 88, W, BTN_SM, BtnNRClick);
|
BtnNR := MakeBtn(PanelRX, 'NR', 2, 96, W, BTN_SM, BtnNRClick);
|
||||||
BtnNB := MakeBtn(PanelRX, 'NB', W+4, 88, W, BTN_SM, BtnNBClick);
|
BtnNB := MakeBtn(PanelRX, 'NB', W+4, 96, W, BTN_SM, BtnNBClick);
|
||||||
BtnANF := MakeBtn(PanelRX, 'ANF',2*W+6, 88, W, BTN_SM, BtnANFClick);
|
BtnSNB := MakeBtn(PanelRX, 'SNB', 2*W+6, 96, W, BTN_SM, BtnSNBClick);
|
||||||
BtnMute:= MakeBtn(PanelRX, 'MUTE',3*W+8,88, W, BTN_SM, BtnMuteClick);
|
BtnANF := MakeBtn(PanelRX, 'ANF', 3*W+8, 96, W, BTN_SM, BtnANFClick);
|
||||||
|
BtnMute:= MakeBtn(PanelRX, 'MUTE', 4*W+10, 96, W, BTN_SM, BtnMuteClick);
|
||||||
|
|
||||||
Inc(Y, 124);
|
Inc(Y, 124);
|
||||||
|
|
||||||
@@ -2661,7 +2691,7 @@ begin
|
|||||||
FCurrentBand,
|
FCurrentBand,
|
||||||
FRunning and FNetwork.Connected,
|
FRunning and FNetwork.Connected,
|
||||||
FRunning, FMuted, FCTun,
|
FRunning, FMuted, FCTun,
|
||||||
BtnNR.Tag = 1, BtnNB.Tag = 1, BtnANF.Tag = 1,
|
BtnNR.Tag, BtnNB.Tag, BtnSNB.Tag <> 0, BtnANF.Tag <> 0,
|
||||||
FCenterFreq, FFilter);
|
FCenterFreq, FFilter);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -3067,9 +3097,10 @@ begin
|
|||||||
FSampleRate := G_Settings.SampleRate;
|
FSampleRate := G_Settings.SampleRate;
|
||||||
FSpanHz := FSampleRate;
|
FSpanHz := FSampleRate;
|
||||||
end;
|
end;
|
||||||
BtnNR.Tag := Ord(G_Settings.NREnabled); StyleButton(BtnNR, G_Settings.NREnabled);
|
BtnNR.Tag := EnsureRange(G_Settings.NRMode, 0, 4); UpdateNRButton;
|
||||||
BtnNB.Tag := Ord(G_Settings.NBEnabled); StyleButton(BtnNB, G_Settings.NBEnabled);
|
BtnNB.Tag := EnsureRange(G_Settings.NBMode, 0, 2); UpdateNBButton;
|
||||||
BtnANF.Tag := Ord(G_Settings.ANFEnabled); StyleButton(BtnANF, G_Settings.ANFEnabled);
|
BtnSNB.Tag := Ord(G_Settings.SNBEnabled); UpdateSNBButton;
|
||||||
|
BtnANF.Tag := Ord(G_Settings.ANFEnabled); UpdateANFButton;
|
||||||
FWfAGCEnabled := G_Settings.WfAGCEnabled; StyleButton(BtnWfAGC, FWfAGCEnabled);
|
FWfAGCEnabled := G_Settings.WfAGCEnabled; StyleButton(BtnWfAGC, FWfAGCEnabled);
|
||||||
FWfNFEnabled := G_Settings.WfNFEnabled; StyleButton(BtnWfNF, FWfNFEnabled);
|
FWfNFEnabled := G_Settings.WfNFEnabled; StyleButton(BtnWfNF, FWfNFEnabled);
|
||||||
RestoreBand(FCurrentBand);
|
RestoreBand(FCurrentBand);
|
||||||
@@ -3109,6 +3140,7 @@ begin
|
|||||||
FDSPEngine.SetMode(FMode);
|
FDSPEngine.SetMode(FMode);
|
||||||
FDSPEngine.SetVolume(FVolume / 100.0);
|
FDSPEngine.SetVolume(FVolume / 100.0);
|
||||||
ApplyModeFilter;
|
ApplyModeFilter;
|
||||||
|
ApplyNoiseFilterButtonsToDSP;
|
||||||
// ChangeSampleRate пересоздаёт WDSP-канал — восстанавливаем все настройки
|
// ChangeSampleRate пересоздаёт WDSP-канал — восстанавливаем все настройки
|
||||||
FDSPEngine.SetAGCTop(FAGCTop);
|
FDSPEngine.SetAGCTop(FAGCTop);
|
||||||
FDSPEngine.SetAGC(TWDSPAGCMode(FAGCMode), 50.0);
|
FDSPEngine.SetAGC(TWDSPAGCMode(FAGCMode), 50.0);
|
||||||
@@ -3617,28 +3649,81 @@ begin
|
|||||||
if FWDSPReady then FDSPEngine.SetMute(FMuted);
|
if FWDSPReady then FDSPEngine.SetMute(FMuted);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TMainForm.UpdateNRButton;
|
||||||
|
begin
|
||||||
|
case BtnNR.Tag of
|
||||||
|
1: BtnNR.Caption := 'NR';
|
||||||
|
2: BtnNR.Caption := 'NR2';
|
||||||
|
3: BtnNR.Caption := 'NR3';
|
||||||
|
4: BtnNR.Caption := 'NR4';
|
||||||
|
else
|
||||||
|
BtnNR.Caption := 'NR';
|
||||||
|
end;
|
||||||
|
StyleButton(BtnNR, BtnNR.Tag <> 0);
|
||||||
|
BtnNR.Invalidate;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMainForm.UpdateNBButton;
|
||||||
|
begin
|
||||||
|
case BtnNB.Tag of
|
||||||
|
1: BtnNB.Caption := 'NB';
|
||||||
|
2: BtnNB.Caption := 'NB2';
|
||||||
|
else
|
||||||
|
BtnNB.Caption := 'NB';
|
||||||
|
end;
|
||||||
|
StyleButton(BtnNB, BtnNB.Tag <> 0);
|
||||||
|
BtnNB.Invalidate;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMainForm.UpdateSNBButton;
|
||||||
|
begin
|
||||||
|
BtnSNB.Caption := 'SNB';
|
||||||
|
StyleButton(BtnSNB, BtnSNB.Tag <> 0);
|
||||||
|
BtnSNB.Invalidate;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMainForm.UpdateANFButton;
|
||||||
|
begin
|
||||||
|
BtnANF.Caption := 'ANF';
|
||||||
|
StyleButton(BtnANF, BtnANF.Tag <> 0);
|
||||||
|
BtnANF.Invalidate;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMainForm.ApplyNoiseFilterButtonsToDSP;
|
||||||
|
begin
|
||||||
|
if not FWDSPReady then Exit;
|
||||||
|
FDSPEngine.SetNRMode(BtnNR.Tag);
|
||||||
|
FDSPEngine.SetNBMode(BtnNB.Tag);
|
||||||
|
FDSPEngine.SetSNB(BtnSNB.Tag <> 0);
|
||||||
|
FDSPEngine.SetANF(BtnANF.Tag <> 0);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TMainForm.BtnNRClick(Sender: TObject);
|
procedure TMainForm.BtnNRClick(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
// Используем BtnNR напрямую — корректно работает и при вызове из веб-синхронизации (Sender=nil)
|
BtnNR.Tag := (BtnNR.Tag + 1) mod 5;
|
||||||
BtnNR.Tag := 1 - BtnNR.Tag;
|
UpdateNRButton;
|
||||||
StyleButton(BtnNR, BtnNR.Tag = 1);
|
if FWDSPReady then FDSPEngine.SetNRMode(BtnNR.Tag);
|
||||||
if FWDSPReady then FDSPEngine.SetNR(BtnNR.Tag = 1);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMainForm.BtnNBClick(Sender: TObject);
|
procedure TMainForm.BtnNBClick(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
// Используем BtnNB напрямую — корректно работает и при вызове из веб-синхронизации (Sender=nil)
|
BtnNB.Tag := (BtnNB.Tag + 1) mod 3;
|
||||||
BtnNB.Tag := 1 - BtnNB.Tag;
|
UpdateNBButton;
|
||||||
StyleButton(BtnNB, BtnNB.Tag = 1);
|
if FWDSPReady then FDSPEngine.SetNBMode(BtnNB.Tag);
|
||||||
if FWDSPReady then FDSPEngine.SetNB(BtnNB.Tag = 1);
|
end;
|
||||||
|
|
||||||
|
procedure TMainForm.BtnSNBClick(Sender: TObject);
|
||||||
|
begin
|
||||||
|
BtnSNB.Tag := 1 - BtnSNB.Tag;
|
||||||
|
UpdateSNBButton;
|
||||||
|
if FWDSPReady then FDSPEngine.SetSNB(BtnSNB.Tag <> 0);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMainForm.BtnANFClick(Sender: TObject);
|
procedure TMainForm.BtnANFClick(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
// Используем BtnANF напрямую — корректно работает и при вызове из веб-синхронизации (Sender=nil)
|
|
||||||
BtnANF.Tag := 1 - BtnANF.Tag;
|
BtnANF.Tag := 1 - BtnANF.Tag;
|
||||||
StyleButton(BtnANF, BtnANF.Tag = 1);
|
UpdateANFButton;
|
||||||
if FWDSPReady then FDSPEngine.SetANF(BtnANF.Tag = 1);
|
if FWDSPReady then FDSPEngine.SetANF(BtnANF.Tag <> 0);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@@ -3766,6 +3851,7 @@ begin
|
|||||||
FDSPEngine.SetMode(FMode);
|
FDSPEngine.SetMode(FMode);
|
||||||
FDSPEngine.SetVolume(FVolume / 100.0);
|
FDSPEngine.SetVolume(FVolume / 100.0);
|
||||||
ApplyModeFilter;
|
ApplyModeFilter;
|
||||||
|
ApplyNoiseFilterButtonsToDSP;
|
||||||
// ChangeSampleRate пересоздаёт WDSP-канал — восстанавливаем AGC
|
// ChangeSampleRate пересоздаёт WDSP-канал — восстанавливаем AGC
|
||||||
FDSPEngine.SetAGCTop(FAGCTop);
|
FDSPEngine.SetAGCTop(FAGCTop);
|
||||||
FDSPEngine.SetAGC(TWDSPAGCMode(FAGCMode), 50.0);
|
FDSPEngine.SetAGC(TWDSPAGCMode(FAGCMode), 50.0);
|
||||||
@@ -4046,32 +4132,57 @@ end;
|
|||||||
|
|
||||||
// ── NR ────────────────────────────────────────────────────────────────────
|
// ── NR ────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
procedure TMainForm.WebOnNR(On_: Boolean);
|
procedure TMainForm.WebOnNR(Mode: Integer);
|
||||||
begin
|
begin
|
||||||
FWebSyncBool := On_;
|
FWebSyncInt := Mode;
|
||||||
FWebSyncM := SyncWebNR;
|
FWebSyncM := SyncWebNR;
|
||||||
TThread.Synchronize(nil, FWebSyncM);
|
TThread.Synchronize(nil, FWebSyncM);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMainForm.SyncWebNR;
|
procedure TMainForm.SyncWebNR;
|
||||||
begin
|
begin
|
||||||
if FWebSyncBool <> (BtnNR.Tag = 1) then
|
if FWebSyncInt < 0 then FWebSyncInt := 0;
|
||||||
BtnNRClick(BtnNR);
|
if FWebSyncInt > 4 then FWebSyncInt := 4;
|
||||||
|
if BtnNR.Tag <> FWebSyncInt then
|
||||||
|
begin
|
||||||
|
BtnNR.Tag := FWebSyncInt;
|
||||||
|
UpdateNRButton;
|
||||||
|
if FWDSPReady then FDSPEngine.SetNRMode(BtnNR.Tag);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// ── NB ────────────────────────────────────────────────────────────────────
|
// ── NB ────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
procedure TMainForm.WebOnNB(On_: Boolean);
|
procedure TMainForm.WebOnNB(Mode: Integer);
|
||||||
begin
|
begin
|
||||||
FWebSyncBool := On_;
|
FWebSyncInt := Mode;
|
||||||
FWebSyncM := SyncWebNB;
|
FWebSyncM := SyncWebNB;
|
||||||
TThread.Synchronize(nil, FWebSyncM);
|
TThread.Synchronize(nil, FWebSyncM);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMainForm.SyncWebNB;
|
procedure TMainForm.SyncWebNB;
|
||||||
begin
|
begin
|
||||||
if FWebSyncBool <> (BtnNB.Tag = 1) then
|
if FWebSyncInt < 0 then FWebSyncInt := 0;
|
||||||
BtnNBClick(BtnNB);
|
if FWebSyncInt > 2 then FWebSyncInt := 2;
|
||||||
|
if BtnNB.Tag <> FWebSyncInt then
|
||||||
|
begin
|
||||||
|
BtnNB.Tag := FWebSyncInt;
|
||||||
|
UpdateNBButton;
|
||||||
|
if FWDSPReady then FDSPEngine.SetNBMode(BtnNB.Tag);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMainForm.WebOnSNB(On_: Boolean);
|
||||||
|
begin
|
||||||
|
FWebSyncBool := On_;
|
||||||
|
FWebSyncM := SyncWebSNB;
|
||||||
|
TThread.Synchronize(nil, FWebSyncM);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMainForm.SyncWebSNB;
|
||||||
|
begin
|
||||||
|
if FWebSyncBool <> (BtnSNB.Tag <> 0) then
|
||||||
|
BtnSNBClick(BtnSNB);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// ── ANF ───────────────────────────────────────────────────────────────────
|
// ── ANF ───────────────────────────────────────────────────────────────────
|
||||||
@@ -4085,7 +4196,7 @@ end;
|
|||||||
|
|
||||||
procedure TMainForm.SyncWebANF;
|
procedure TMainForm.SyncWebANF;
|
||||||
begin
|
begin
|
||||||
if FWebSyncBool <> (BtnANF.Tag = 1) then
|
if FWebSyncBool <> (BtnANF.Tag <> 0) then
|
||||||
BtnANFClick(BtnANF);
|
BtnANFClick(BtnANF);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|||||||
+33
-5
@@ -34,8 +34,9 @@ type
|
|||||||
Volume: Integer;
|
Volume: Integer;
|
||||||
DriveLevel: Integer;
|
DriveLevel: Integer;
|
||||||
ActiveVfo: Integer;
|
ActiveVfo: Integer;
|
||||||
NREnabled: Boolean;
|
NRMode: Integer;
|
||||||
NBEnabled: Boolean;
|
NBMode: Integer;
|
||||||
|
SNBEnabled: Boolean;
|
||||||
ANFEnabled: Boolean;
|
ANFEnabled: Boolean;
|
||||||
AGCSlope: Integer;
|
AGCSlope: Integer;
|
||||||
AGCHangThreshold: Integer;
|
AGCHangThreshold: Integer;
|
||||||
@@ -82,6 +83,8 @@ type
|
|||||||
// Размер окна — не привязан к MAC, хранится в корне JSON
|
// Размер окна — не привязан к MAC, хранится в корне JSON
|
||||||
procedure SaveWindowBounds(L, T, W, H: Integer);
|
procedure SaveWindowBounds(L, T, W, H: Integer);
|
||||||
procedure LoadWindowBounds(out L, T, W, H: Integer);
|
procedure LoadWindowBounds(out L, T, W, H: Integer);
|
||||||
|
procedure SaveStartupPreview(VfoA, VfoB: Double; SampleRate: Integer);
|
||||||
|
function LoadStartupPreview(out VfoA, VfoB: Double; out SampleRate: Integer): Boolean;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@@ -110,6 +113,7 @@ class procedure TSettingsManager.DefaultGlobal(out G: TGlobalSettings);
|
|||||||
begin
|
begin
|
||||||
FillChar(G, SizeOf(G), 0);
|
FillChar(G, SizeOf(G), 0);
|
||||||
G.Volume := 70; G.DriveLevel := 50; G.ActiveVfo := 0;
|
G.Volume := 70; G.DriveLevel := 50; G.ActiveVfo := 0;
|
||||||
|
G.NRMode := 0; G.NBMode := 0; G.SNBEnabled := False; G.ANFEnabled := False;
|
||||||
G.AGCSlope := 0; G.AGCHangThreshold := 100; G.LastBand := 5;
|
G.AGCSlope := 0; G.AGCHangThreshold := 100; G.LastBand := 5;
|
||||||
G.SampleRate := 192000;
|
G.SampleRate := 192000;
|
||||||
end;
|
end;
|
||||||
@@ -235,8 +239,9 @@ begin
|
|||||||
G.Volume := JI(GObj,'volume',70);
|
G.Volume := JI(GObj,'volume',70);
|
||||||
G.DriveLevel := JI(GObj,'drive_level',50);
|
G.DriveLevel := JI(GObj,'drive_level',50);
|
||||||
G.ActiveVfo := JI(GObj,'active_vfo',0);
|
G.ActiveVfo := JI(GObj,'active_vfo',0);
|
||||||
G.NREnabled := JB(GObj,'nr_enabled',False);
|
G.NRMode := JI(GObj,'nr_mode',Ord(JB(GObj,'nr_enabled',False)));
|
||||||
G.NBEnabled := JB(GObj,'nb_enabled',False);
|
G.NBMode := JI(GObj,'nb_mode',Ord(JB(GObj,'nb_enabled',False)));
|
||||||
|
G.SNBEnabled := JB(GObj,'snb_enabled',False);
|
||||||
G.ANFEnabled := JB(GObj,'anf_enabled',False);
|
G.ANFEnabled := JB(GObj,'anf_enabled',False);
|
||||||
G.AGCSlope := JI(GObj,'agc_slope',0);
|
G.AGCSlope := JI(GObj,'agc_slope',0);
|
||||||
G.AGCHangThreshold := JI(GObj,'agc_hang_threshold',100);
|
G.AGCHangThreshold := JI(GObj,'agc_hang_threshold',100);
|
||||||
@@ -268,7 +273,9 @@ begin
|
|||||||
O := GetGlobalObj(GetDevObj(MacToStr(MAC)));
|
O := GetGlobalObj(GetDevObj(MacToStr(MAC)));
|
||||||
JW(O,'volume',G.Volume); JW(O,'drive_level',G.DriveLevel);
|
JW(O,'volume',G.Volume); JW(O,'drive_level',G.DriveLevel);
|
||||||
JW(O,'active_vfo',G.ActiveVfo);
|
JW(O,'active_vfo',G.ActiveVfo);
|
||||||
JW(O,'nr_enabled',G.NREnabled); JW(O,'nb_enabled',G.NBEnabled);
|
JW(O,'nr_mode',G.NRMode); JW(O,'nb_mode',G.NBMode);
|
||||||
|
JW(O,'nr_enabled',G.NRMode <> 0); JW(O,'nb_enabled',G.NBMode <> 0);
|
||||||
|
JW(O,'snb_enabled',G.SNBEnabled);
|
||||||
JW(O,'anf_enabled',G.ANFEnabled);
|
JW(O,'anf_enabled',G.ANFEnabled);
|
||||||
JW(O,'agc_slope',G.AGCSlope);
|
JW(O,'agc_slope',G.AGCSlope);
|
||||||
JW(O,'agc_hang_threshold',G.AGCHangThreshold);
|
JW(O,'agc_hang_threshold',G.AGCHangThreshold);
|
||||||
@@ -333,4 +340,25 @@ begin
|
|||||||
H := JI(O, 'height', 900);
|
H := JI(O, 'height', 900);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TSettingsManager.SaveStartupPreview(VfoA, VfoB: Double; SampleRate: Integer);
|
||||||
|
var O: TJSONObject;
|
||||||
|
begin
|
||||||
|
O := EnsureObj(FRoot, 'startup');
|
||||||
|
JW(O, 'vfo_a', VfoA);
|
||||||
|
JW(O, 'vfo_b', VfoB);
|
||||||
|
JW(O, 'sample_rate', SampleRate);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSettingsManager.LoadStartupPreview(out VfoA, VfoB: Double; out SampleRate: Integer): Boolean;
|
||||||
|
var O: TJSONObject;
|
||||||
|
begin
|
||||||
|
Result := FRoot.Find('startup') <> nil;
|
||||||
|
if not Result then Exit;
|
||||||
|
|
||||||
|
O := EnsureObj(FRoot, 'startup');
|
||||||
|
VfoA := JD(O, 'vfo_a', 14200000);
|
||||||
|
VfoB := JD(O, 'vfo_b', 7100000);
|
||||||
|
SampleRate := JI(O, 'sample_rate', 192000);
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|||||||
+158
-10
@@ -55,6 +55,39 @@ const
|
|||||||
AGC_MEDIUM = 3;
|
AGC_MEDIUM = 3;
|
||||||
AGC_FAST = 4;
|
AGC_FAST = 4;
|
||||||
|
|
||||||
|
// RX filter modes
|
||||||
|
NR_MODE_OFF = 0;
|
||||||
|
NR_MODE_1 = 1;
|
||||||
|
NR_MODE_2 = 2;
|
||||||
|
NR_MODE_3 = 3;
|
||||||
|
NR_MODE_4 = 4;
|
||||||
|
|
||||||
|
NB_MODE_OFF = 0;
|
||||||
|
NB_MODE_1 = 1;
|
||||||
|
NB_MODE_2 = 2;
|
||||||
|
|
||||||
|
FILTER_NR_AGC_POSITION = 1;
|
||||||
|
FILTER_NB_TAU = 0.00001;
|
||||||
|
FILTER_NB_ADVTIME = 0.00001;
|
||||||
|
FILTER_NB_HANGTIME = 0.00001;
|
||||||
|
FILTER_NB_THRESHOLD = 4.95;
|
||||||
|
FILTER_NB2_MODE = 0;
|
||||||
|
FILTER_NR2_GAIN_METHOD = 2;
|
||||||
|
FILTER_NR2_NPE_METHOD = 0;
|
||||||
|
FILTER_NR2_POST_RUN = 0;
|
||||||
|
FILTER_NR2_POST_TAPER = 12;
|
||||||
|
FILTER_NR2_POST_NLEVEL = 15.0;
|
||||||
|
FILTER_NR2_POST_FACTOR = 15.0;
|
||||||
|
FILTER_NR2_POST_RATE = 5.0;
|
||||||
|
FILTER_NR2_TRAINED_THRESHOLD = -0.5;
|
||||||
|
FILTER_NR2_TRAINED_T2 = 0.2;
|
||||||
|
FILTER_NR4_REDUCTION_AMOUNT = 10.0;
|
||||||
|
FILTER_NR4_SMOOTHING_FACTOR = 20.0;
|
||||||
|
FILTER_NR4_WHITENING_FACTOR = 0.0;
|
||||||
|
FILTER_NR4_NOISE_RESCALE = 2.0;
|
||||||
|
FILTER_NR4_POST_THRESHOLD = -3.0;
|
||||||
|
FILTER_NR4_NOISE_SCALING_TYPE = 0;
|
||||||
|
|
||||||
// S-meter types для GetRXAMeter
|
// S-meter types для GetRXAMeter
|
||||||
RXA_S_PK = 0; // peak, dBm
|
RXA_S_PK = 0; // peak, dBm
|
||||||
RXA_S_AV = 1; // average, dBm
|
RXA_S_AV = 1; // average, dBm
|
||||||
@@ -140,8 +173,9 @@ type
|
|||||||
FAGCThresh: Double; // читается из WDSP (GetRXAAGCThresh)
|
FAGCThresh: Double; // читается из WDSP (GetRXAAGCThresh)
|
||||||
FLastSpectrumW: Integer; // последняя известная ширина спектра (пикс)
|
FLastSpectrumW: Integer; // последняя известная ширина спектра (пикс)
|
||||||
FShiftHz: Double; // NCO shift для CTUN
|
FShiftHz: Double; // NCO shift для CTUN
|
||||||
FNREnabled: Boolean;
|
FNRMode: Integer;
|
||||||
FNBEnabled: Boolean;
|
FNBMode: Integer;
|
||||||
|
FSNBEnabled: Boolean;
|
||||||
FANFEnabled: Boolean;
|
FANFEnabled: Boolean;
|
||||||
FMuted: Boolean;
|
FMuted: Boolean;
|
||||||
FVolume: Double;
|
FVolume: Double;
|
||||||
@@ -153,6 +187,11 @@ type
|
|||||||
procedure PushIQItemToDSP(const Item: TIQQueueItem);
|
procedure PushIQItemToDSP(const Item: TIQQueueItem);
|
||||||
procedure OpenAnalyzer;
|
procedure OpenAnalyzer;
|
||||||
procedure CloseAnalyzer;
|
procedure CloseAnalyzer;
|
||||||
|
procedure ApplyNRState;
|
||||||
|
procedure ApplyNBState;
|
||||||
|
procedure ApplySNBState;
|
||||||
|
procedure ApplyANFState;
|
||||||
|
procedure ApplyNoiseFilterState;
|
||||||
|
|
||||||
public
|
public
|
||||||
constructor Create(SampleRate: Integer = 192000;
|
constructor Create(SampleRate: Integer = 192000;
|
||||||
@@ -181,8 +220,11 @@ type
|
|||||||
procedure UpdateAGCLines(SpectrumW: Integer); // читает hang/thresh из WDSP для линии на спектре
|
procedure UpdateAGCLines(SpectrumW: Integer); // читает hang/thresh из WDSP для линии на спектре
|
||||||
procedure SetSpectrumWidth(W: Integer); // обновляет FLastSpectrumW для корректных AGC линий
|
procedure SetSpectrumWidth(W: Integer); // обновляет FLastSpectrumW для корректных AGC линий
|
||||||
procedure SetShift(ShiftHz: Double); // CTUN NCO сдвиг
|
procedure SetShift(ShiftHz: Double); // CTUN NCO сдвиг
|
||||||
|
procedure SetNRMode(Mode: Integer);
|
||||||
procedure SetNR(Enable: Boolean);
|
procedure SetNR(Enable: Boolean);
|
||||||
|
procedure SetNBMode(Mode: Integer);
|
||||||
procedure SetNB(Enable: Boolean);
|
procedure SetNB(Enable: Boolean);
|
||||||
|
procedure SetSNB(Enable: Boolean);
|
||||||
procedure SetANF(Enable: Boolean);
|
procedure SetANF(Enable: Boolean);
|
||||||
procedure SetVolume(Vol: Double);
|
procedure SetVolume(Vol: Double);
|
||||||
procedure SetMute(Mute: Boolean);
|
procedure SetMute(Mute: Boolean);
|
||||||
@@ -212,6 +254,9 @@ type
|
|||||||
property Mode: Integer read FMode;
|
property Mode: Integer read FMode;
|
||||||
property FilterLow: Integer read FFilterLow;
|
property FilterLow: Integer read FFilterLow;
|
||||||
property FilterHigh: Integer read FFilterHigh;
|
property FilterHigh: Integer read FFilterHigh;
|
||||||
|
property NRMode: Integer read FNRMode;
|
||||||
|
property NBMode: Integer read FNBMode;
|
||||||
|
property SNBEnabled: Boolean read FSNBEnabled;
|
||||||
property LastError: string read FLastError;
|
property LastError: string read FLastError;
|
||||||
property SMeter: Double read FSMeter;
|
property SMeter: Double read FSMeter;
|
||||||
property OnAudio: TOnAudioReady read FOnAudio write FOnAudio;
|
property OnAudio: TOnAudioReady read FOnAudio write FOnAudio;
|
||||||
@@ -317,6 +362,10 @@ begin
|
|||||||
FAGCTop := -90.0;
|
FAGCTop := -90.0;
|
||||||
FVolume := 0.7;
|
FVolume := 0.7;
|
||||||
FSMeter := -130.0;
|
FSMeter := -130.0;
|
||||||
|
FNRMode := NR_MODE_OFF;
|
||||||
|
FNBMode := NB_MODE_OFF;
|
||||||
|
FSNBEnabled := False;
|
||||||
|
FANFEnabled := False;
|
||||||
FRXAccPos := 0;
|
FRXAccPos := 0;
|
||||||
|
|
||||||
SetLength(FRXIn, FBufSize * 2); // in_size пар @ FSampleRate (4096*2)
|
SetLength(FRXIn, FBufSize * 2); // in_size пар @ FSampleRate (4096*2)
|
||||||
@@ -438,6 +487,10 @@ begin
|
|||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
create_anbEXT(RXA_CHAN, 1, FBufSize, FSampleRate, 0.0001, 0.0001, 0.0001, 0.05, 20);
|
||||||
|
create_nobEXT(RXA_CHAN, 1, 0, FBufSize, FSampleRate, 0.0001, 0.0001, 0.0001, 0.05, 20);
|
||||||
|
|
||||||
|
SetRXABandpassWindow(RXA_CHAN, 1);
|
||||||
SetRXAMode(RXA_CHAN, ModeToWDSP(FMode));
|
SetRXAMode(RXA_CHAN, ModeToWDSP(FMode));
|
||||||
SetRXAShiftRun(RXA_CHAN, 1);
|
SetRXAShiftRun(RXA_CHAN, 1);
|
||||||
SetRXAShiftFreq(RXA_CHAN, 0.0);
|
SetRXAShiftFreq(RXA_CHAN, 0.0);
|
||||||
@@ -474,6 +527,7 @@ begin
|
|||||||
SetTXAPanelSelect(TXA_CHAN, 1);
|
SetTXAPanelSelect(TXA_CHAN, 1);
|
||||||
|
|
||||||
FInitialized := True;
|
FInitialized := True;
|
||||||
|
ApplyNoiseFilterState;
|
||||||
Result := True;
|
Result := True;
|
||||||
|
|
||||||
// Запускаем DSP поток после успешной инициализации WDSP
|
// Запускаем DSP поток после успешной инициализации WDSP
|
||||||
@@ -505,6 +559,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
CloseAnalyzer;
|
CloseAnalyzer;
|
||||||
|
destroy_anbEXT(RXA_CHAN);
|
||||||
|
destroy_nobEXT(RXA_CHAN);
|
||||||
CloseChannel(RXA_CHAN);
|
CloseChannel(RXA_CHAN);
|
||||||
CloseChannel(TXA_CHAN);
|
CloseChannel(TXA_CHAN);
|
||||||
FInitialized := False;
|
FInitialized := False;
|
||||||
@@ -760,25 +816,117 @@ begin
|
|||||||
FSampleRate);
|
FSampleRate);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TWDSPEngine.ApplyNRState;
|
||||||
|
begin
|
||||||
|
if not FInitialized then Exit;
|
||||||
|
|
||||||
|
SetRXAANRVals(RXA_CHAN, 64, 16, 16e-4, 10e-7);
|
||||||
|
SetRXAANRPosition(RXA_CHAN, FILTER_NR_AGC_POSITION);
|
||||||
|
SetRXAANRRun(RXA_CHAN, Ord(FNRMode = NR_MODE_1));
|
||||||
|
|
||||||
|
SetRXAEMNRPosition(RXA_CHAN, FILTER_NR_AGC_POSITION);
|
||||||
|
SetRXAEMNRgainMethod(RXA_CHAN, FILTER_NR2_GAIN_METHOD);
|
||||||
|
SetRXAEMNRnpeMethod(RXA_CHAN, FILTER_NR2_NPE_METHOD);
|
||||||
|
SetRXAEMNRtrainZetaThresh(RXA_CHAN, FILTER_NR2_TRAINED_THRESHOLD);
|
||||||
|
SetRXAEMNRtrainT2(RXA_CHAN, FILTER_NR2_TRAINED_T2);
|
||||||
|
SetRXAEMNRpost2Taper(RXA_CHAN, FILTER_NR2_POST_TAPER);
|
||||||
|
SetRXAEMNRpost2Nlevel(RXA_CHAN, FILTER_NR2_POST_NLEVEL);
|
||||||
|
SetRXAEMNRpost2Factor(RXA_CHAN, FILTER_NR2_POST_FACTOR);
|
||||||
|
SetRXAEMNRpost2Rate(RXA_CHAN, FILTER_NR2_POST_RATE);
|
||||||
|
SetRXAEMNRaeRun(RXA_CHAN, 1);
|
||||||
|
SetRXAEMNRpost2Run(RXA_CHAN, FILTER_NR2_POST_RUN);
|
||||||
|
SetRXAEMNRRun(RXA_CHAN, Ord(FNRMode = NR_MODE_2));
|
||||||
|
|
||||||
|
SetRXARNNRPosition(RXA_CHAN, FILTER_NR_AGC_POSITION);
|
||||||
|
SetRXARNNRRun(RXA_CHAN, Ord(FNRMode = NR_MODE_3));
|
||||||
|
|
||||||
|
SetRXASBNRreductionAmount(RXA_CHAN, FILTER_NR4_REDUCTION_AMOUNT);
|
||||||
|
SetRXASBNRsmoothingFactor(RXA_CHAN, FILTER_NR4_SMOOTHING_FACTOR);
|
||||||
|
SetRXASBNRwhiteningFactor(RXA_CHAN, FILTER_NR4_WHITENING_FACTOR);
|
||||||
|
SetRXASBNRnoiseRescale(RXA_CHAN, FILTER_NR4_NOISE_RESCALE);
|
||||||
|
SetRXASBNRpostFilterThreshold(RXA_CHAN, FILTER_NR4_POST_THRESHOLD);
|
||||||
|
SetRXASBNRnoiseScalingType(RXA_CHAN, FILTER_NR4_NOISE_SCALING_TYPE);
|
||||||
|
SetRXASBNRPosition(RXA_CHAN, FILTER_NR_AGC_POSITION);
|
||||||
|
SetRXASBNRRun(RXA_CHAN, Ord(FNRMode = NR_MODE_4));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TWDSPEngine.ApplyNBState;
|
||||||
|
begin
|
||||||
|
if not FInitialized then Exit;
|
||||||
|
|
||||||
|
SetEXTANBTau(RXA_CHAN, FILTER_NB_TAU);
|
||||||
|
SetEXTANBHangtime(RXA_CHAN, FILTER_NB_HANGTIME);
|
||||||
|
SetEXTANBAdvtime(RXA_CHAN, FILTER_NB_ADVTIME);
|
||||||
|
SetEXTANBThreshold(RXA_CHAN, FILTER_NB_THRESHOLD);
|
||||||
|
SetEXTANBRun(RXA_CHAN, Ord(FNBMode = NB_MODE_1));
|
||||||
|
|
||||||
|
SetEXTNOBMode(RXA_CHAN, FILTER_NB2_MODE);
|
||||||
|
SetEXTNOBTau(RXA_CHAN, FILTER_NB_TAU);
|
||||||
|
SetEXTNOBHangtime(RXA_CHAN, FILTER_NB_HANGTIME);
|
||||||
|
SetEXTNOBAdvtime(RXA_CHAN, FILTER_NB_ADVTIME);
|
||||||
|
SetEXTNOBThreshold(RXA_CHAN, FILTER_NB_THRESHOLD);
|
||||||
|
SetEXTNOBRun(RXA_CHAN, Ord(FNBMode = NB_MODE_2));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TWDSPEngine.ApplySNBState;
|
||||||
|
begin
|
||||||
|
if not FInitialized then Exit;
|
||||||
|
SetRXASNBARun(RXA_CHAN, Ord(FSNBEnabled));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TWDSPEngine.ApplyANFState;
|
||||||
|
begin
|
||||||
|
if not FInitialized then Exit;
|
||||||
|
SetRXAANFPosition(RXA_CHAN, FILTER_NR_AGC_POSITION);
|
||||||
|
SetRXAANFRun(RXA_CHAN, Ord(FANFEnabled));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TWDSPEngine.ApplyNoiseFilterState;
|
||||||
|
begin
|
||||||
|
ApplyNRState;
|
||||||
|
ApplyNBState;
|
||||||
|
ApplySNBState;
|
||||||
|
ApplyANFState;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TWDSPEngine.SetNRMode(Mode: Integer);
|
||||||
|
begin
|
||||||
|
if Mode < NR_MODE_OFF then Mode := NR_MODE_OFF;
|
||||||
|
if Mode > NR_MODE_4 then Mode := NR_MODE_4;
|
||||||
|
FNRMode := Mode;
|
||||||
|
ApplyNRState;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.SetNR(Enable: Boolean);
|
procedure TWDSPEngine.SetNR(Enable: Boolean);
|
||||||
begin
|
begin
|
||||||
FNREnabled := Enable;
|
if Enable then SetNRMode(NR_MODE_1)
|
||||||
if not FInitialized then Exit;
|
else SetNRMode(NR_MODE_OFF);
|
||||||
SetRXAEMNRRun(RXA_CHAN, Ord(Enable));
|
end;
|
||||||
|
|
||||||
|
procedure TWDSPEngine.SetNBMode(Mode: Integer);
|
||||||
|
begin
|
||||||
|
if Mode < NB_MODE_OFF then Mode := NB_MODE_OFF;
|
||||||
|
if Mode > NB_MODE_2 then Mode := NB_MODE_2;
|
||||||
|
FNBMode := Mode;
|
||||||
|
ApplyNBState;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.SetNB(Enable: Boolean);
|
procedure TWDSPEngine.SetNB(Enable: Boolean);
|
||||||
begin
|
begin
|
||||||
FNBEnabled := Enable;
|
if Enable then SetNBMode(NB_MODE_1)
|
||||||
if not FInitialized then Exit;
|
else SetNBMode(NB_MODE_OFF);
|
||||||
SetEXTANBRun(RXA_CHAN, Ord(Enable));
|
end;
|
||||||
|
|
||||||
|
procedure TWDSPEngine.SetSNB(Enable: Boolean);
|
||||||
|
begin
|
||||||
|
FSNBEnabled := Enable;
|
||||||
|
ApplySNBState;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.SetANF(Enable: Boolean);
|
procedure TWDSPEngine.SetANF(Enable: Boolean);
|
||||||
begin
|
begin
|
||||||
FANFEnabled := Enable;
|
FANFEnabled := Enable;
|
||||||
if not FInitialized then Exit;
|
ApplyANFState;
|
||||||
SetRXAANFRun(RXA_CHAN, Ord(Enable));
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.SetVolume(Vol: Double);
|
procedure TWDSPEngine.SetVolume(Vol: Double);
|
||||||
|
|||||||
+14
-7
@@ -126,6 +126,7 @@ begin
|
|||||||
'</select>' +
|
'</select>' +
|
||||||
'<select id="attSel"><option value="0" selected>0 dB</option><option value="1">-10 dB</option><option value="2">-20 dB</option></select>' +
|
'<select id="attSel"><option value="0" selected>0 dB</option><option value="1">-10 dB</option><option value="2">-20 dB</option></select>' +
|
||||||
'<button id="nbBtn">NB</button>' +
|
'<button id="nbBtn">NB</button>' +
|
||||||
|
'<button id="snbBtn">SNB</button>' +
|
||||||
'<button id="anfBtn">ANF</button>' +
|
'<button id="anfBtn">ANF</button>' +
|
||||||
'<button id="nrBtn">NR</button>' +
|
'<button id="nrBtn">NR</button>' +
|
||||||
'<span class="sl-sep">|</span>' +
|
'<span class="sl-sep">|</span>' +
|
||||||
@@ -185,6 +186,10 @@ begin
|
|||||||
'function sw(id,on){const b=q(id);if(b)b.classList.toggle("on",!!on);}' +
|
'function sw(id,on){const b=q(id);if(b)b.classList.toggle("on",!!on);}' +
|
||||||
'function ws2(obj){if(ws&&ws.readyState===1)ws.send(JSON.stringify(obj));}' +
|
'function ws2(obj){if(ws&&ws.readyState===1)ws.send(JSON.stringify(obj));}' +
|
||||||
'function cmd(c,v){ws2({cmd:c,on:v});}' +
|
'function cmd(c,v){ws2({cmd:c,on:v});}' +
|
||||||
|
'function updNrBtn(){const b=q("nrBtn");if(!b)return;const m=cur.nr_mode|0;b.textContent=(m===2)?"NR2":(m===3)?"NR3":(m===4)?"NR4":"NR";sw("nrBtn",m!==0);}' +
|
||||||
|
'function updNbBtn(){const b=q("nbBtn");if(!b)return;const m=cur.nb_mode|0;b.textContent=(m===2)?"NB2":"NB";sw("nbBtn",m!==0);}' +
|
||||||
|
'function updSnbBtn(){sw("snbBtn",!!cur.snb);}' +
|
||||||
|
'function updAnfBtn(){sw("anfBtn",!!cur.anf);}' +
|
||||||
|
|
||||||
'const MODE_N=["LSB","USB","DSB","CWL","CWU","FM","AM","SAM"];' +
|
'const MODE_N=["LSB","USB","DSB","CWL","CWU","FM","AM","SAM"];' +
|
||||||
'const GRP_MAP={ssb:[0,1],cw:[3,4],fm:[5,5],am:[6,7]};' +
|
'const GRP_MAP={ssb:[0,1],cw:[3,4],fm:[5,5],am:[6,7]};' +
|
||||||
@@ -203,9 +208,10 @@ begin
|
|||||||
'q("txSl").oninput=function(e){var v=q("txVal");if(v)v.textContent=e.target.value;};' +
|
'q("txSl").oninput=function(e){var v=q("txVal");if(v)v.textContent=e.target.value;};' +
|
||||||
|
|
||||||
// DSP кнопки — cur обновляется локально сразу, не ждём ответа сервера
|
// DSP кнопки — cur обновляется локально сразу, не ждём ответа сервера
|
||||||
'q("nrBtn").onclick=function(){cur.nr=!cur.nr;sw("nrBtn",cur.nr);pend("nr");cmd("set_nr",cur.nr);};' +
|
'q("nrBtn").onclick=function(){cur.nr_mode=((cur.nr_mode|0)+1)%5;cur.nr=cur.nr_mode!==0;updNrBtn();pend("nr");ws2({cmd:"set_nr_mode",mode:cur.nr_mode});};' +
|
||||||
'q("nbBtn").onclick=function(){cur.nb=!cur.nb;sw("nbBtn",cur.nb);pend("nb");cmd("set_nb",cur.nb);};' +
|
'q("nbBtn").onclick=function(){cur.nb_mode=((cur.nb_mode|0)+1)%3;cur.nb=cur.nb_mode!==0;updNbBtn();pend("nb");ws2({cmd:"set_nb_mode",mode:cur.nb_mode});};' +
|
||||||
'q("anfBtn").onclick=function(){cur.anf=!cur.anf;sw("anfBtn",cur.anf);pend("anf");cmd("set_anf",cur.anf);};' +
|
'q("snbBtn").onclick=function(){cur.snb=!cur.snb;updSnbBtn();pend("snb");cmd("set_snb",cur.snb);};' +
|
||||||
|
'q("anfBtn").onclick=function(){cur.anf=!cur.anf;updAnfBtn();pend("anf");cmd("set_anf",cur.anf);};' +
|
||||||
|
|
||||||
// START/STOP
|
// START/STOP
|
||||||
'function updRunBtn(r){var b=q("startStopBtn");if(!b)return;b.textContent=r?"STOP":"START";b.classList.toggle("rx-tx",!!r);b.classList.toggle("on",!r);}' +
|
'function updRunBtn(r){var b=q("startStopBtn");if(!b)return;b.textContent=r?"STOP":"START";b.classList.toggle("rx-tx",!!r);b.classList.toggle("on",!r);}' +
|
||||||
@@ -324,7 +330,7 @@ begin
|
|||||||
'function isPending(field){return !!(pendingCmds[field]&&pendingCmds[field]>Date.now());}' +
|
'function isPending(field){return !!(pendingCmds[field]&&pendingCmds[field]>Date.now());}' +
|
||||||
|
|
||||||
// Маппинг: server JSON field → pend key
|
// Маппинг: server JSON field → pend key
|
||||||
'var PEND_MAP={vfo_a_hz:"freq",nr:"nr",nb:"nb",anf:"anf",running:"run",mode:"mode",agc_mode:"agc"};' +
|
'var PEND_MAP={vfo_a_hz:"freq",nr:"nr",nr_mode:"nr",nb:"nb",nb_mode:"nb",snb:"snb",anf:"anf",running:"run",mode:"mode",agc_mode:"agc"};' +
|
||||||
|
|
||||||
'function applyState(msg){' +
|
'function applyState(msg){' +
|
||||||
// Мержим только поля которые не pending
|
// Мержим только поля которые не pending
|
||||||
@@ -337,9 +343,10 @@ begin
|
|||||||
'const as=q("agcSel");if(as&&cur.agc_mode!=null&&!isPending("agc"))as.value=cur.agc_mode;' +
|
'const as=q("agcSel");if(as&&cur.agc_mode!=null&&!isPending("agc"))as.value=cur.agc_mode;' +
|
||||||
'const vs=q("volSl");if(vs&&!vs.matches(":active")){vs.value=cur.volume||70;var vv=q("volVal");if(vv)vv.textContent=cur.volume||70;}' +
|
'const vs=q("volSl");if(vs&&!vs.matches(":active")){vs.value=cur.volume||70;var vv=q("volVal");if(vv)vv.textContent=cur.volume||70;}' +
|
||||||
'const rs=q("rfSl");if(rs&&!rs.matches(":active")){rs.value=cur.agc_top||90;var rv=q("rfVal");if(rv)rv.textContent=(cur.agc_top||90)+"dB";}' +
|
'const rs=q("rfSl");if(rs&&!rs.matches(":active")){rs.value=cur.agc_top||90;var rv=q("rfVal");if(rv)rv.textContent=(cur.agc_top||90)+"dB";}' +
|
||||||
'if(!isPending("nr"))sw("nrBtn",!!cur.nr);' +
|
'if(!isPending("nr"))updNrBtn();' +
|
||||||
'if(!isPending("nb"))sw("nbBtn",!!cur.nb);' +
|
'if(!isPending("nb"))updNbBtn();' +
|
||||||
'if(!isPending("anf"))sw("anfBtn",!!cur.anf);' +
|
'if(!isPending("snb"))updSnbBtn();' +
|
||||||
|
'if(!isPending("anf"))updAnfBtn();' +
|
||||||
'if(!isPending("run"))updRunBtn(!!cur.running);' +
|
'if(!isPending("run"))updRunBtn(!!cur.running);' +
|
||||||
// syncModGrp syncs dropdown AND calls updModTglLabel internally
|
// syncModGrp syncs dropdown AND calls updModTglLabel internally
|
||||||
'if(!isPending("mode")){syncModGrp(cur.mode||0);}' +
|
'if(!isPending("mode")){syncModGrp(cur.mode||0);}' +
|
||||||
|
|||||||
+55
-21
@@ -117,8 +117,9 @@ type
|
|||||||
TWebCmdRun = procedure(On_: Boolean) of object;
|
TWebCmdRun = procedure(On_: Boolean) of object;
|
||||||
TWebCmdMute = procedure(On_: Boolean) of object;
|
TWebCmdMute = procedure(On_: Boolean) of object;
|
||||||
TWebCmdCtun = procedure(On_: Boolean) of object;
|
TWebCmdCtun = procedure(On_: Boolean) of object;
|
||||||
TWebCmdNR = procedure(On_: Boolean) of object;
|
TWebCmdNRMode = procedure(Mode: Integer) of object;
|
||||||
TWebCmdNB = procedure(On_: Boolean) of object;
|
TWebCmdNBMode = procedure(Mode: Integer) of object;
|
||||||
|
TWebCmdSNB = procedure(On_: Boolean) of object;
|
||||||
TWebCmdANF = procedure(On_: Boolean) of object;
|
TWebCmdANF = procedure(On_: Boolean) of object;
|
||||||
|
|
||||||
// ── Главный класс сервера ─────────────────────────────────────────────────
|
// ── Главный класс сервера ─────────────────────────────────────────────────
|
||||||
@@ -169,8 +170,9 @@ type
|
|||||||
FTrxRunning: Boolean;
|
FTrxRunning: Boolean;
|
||||||
FMuted: Boolean;
|
FMuted: Boolean;
|
||||||
FCtun: Boolean;
|
FCtun: Boolean;
|
||||||
FNR: Boolean;
|
FNRMode: Integer;
|
||||||
FNB: Boolean;
|
FNBMode: Integer;
|
||||||
|
FSNB: Boolean;
|
||||||
FANF: Boolean;
|
FANF: Boolean;
|
||||||
FCenterHz: Double;
|
FCenterHz: Double;
|
||||||
FFilterIdx: Integer;
|
FFilterIdx: Integer;
|
||||||
@@ -190,8 +192,9 @@ type
|
|||||||
FOnRun: TWebCmdRun;
|
FOnRun: TWebCmdRun;
|
||||||
FOnMute: TWebCmdMute;
|
FOnMute: TWebCmdMute;
|
||||||
FOnCtun: TWebCmdCtun;
|
FOnCtun: TWebCmdCtun;
|
||||||
FOnNR: TWebCmdNR;
|
FOnNR: TWebCmdNRMode;
|
||||||
FOnNB: TWebCmdNB;
|
FOnNB: TWebCmdNBMode;
|
||||||
|
FOnSNB: TWebCmdSNB;
|
||||||
FOnANF: TWebCmdANF;
|
FOnANF: TWebCmdANF;
|
||||||
|
|
||||||
FWebClientActive: Boolean;
|
FWebClientActive: Boolean;
|
||||||
@@ -232,7 +235,8 @@ type
|
|||||||
SpanHz: Double; Volume: Integer;
|
SpanHz: Double; Volume: Integer;
|
||||||
WfAGC, WfNF: Boolean; BandIdx: Integer;
|
WfAGC, WfNF: Boolean; BandIdx: Integer;
|
||||||
TrxConnected: Boolean;
|
TrxConnected: Boolean;
|
||||||
TrxRunning, Muted, Ctun, NR, NB, ANF: Boolean;
|
TrxRunning, Muted, Ctun: Boolean;
|
||||||
|
NRMode, NBMode: Integer; SNB, ANF: Boolean;
|
||||||
CenterHz: Double; FilterIdx: Integer);
|
CenterHz: Double; FilterIdx: Integer);
|
||||||
|
|
||||||
property WebClientActive: Boolean read FWebClientActive;
|
property WebClientActive: Boolean read FWebClientActive;
|
||||||
@@ -250,8 +254,9 @@ type
|
|||||||
property OnRun: TWebCmdRun read FOnRun write FOnRun;
|
property OnRun: TWebCmdRun read FOnRun write FOnRun;
|
||||||
property OnMute: TWebCmdMute read FOnMute write FOnMute;
|
property OnMute: TWebCmdMute read FOnMute write FOnMute;
|
||||||
property OnCtun: TWebCmdCtun read FOnCtun write FOnCtun;
|
property OnCtun: TWebCmdCtun read FOnCtun write FOnCtun;
|
||||||
property OnNR: TWebCmdNR read FOnNR write FOnNR;
|
property OnNR: TWebCmdNRMode read FOnNR write FOnNR;
|
||||||
property OnNB: TWebCmdNB read FOnNB write FOnNB;
|
property OnNB: TWebCmdNBMode read FOnNB write FOnNB;
|
||||||
|
property OnSNB: TWebCmdSNB read FOnSNB write FOnSNB;
|
||||||
property OnANF: TWebCmdANF read FOnANF write FOnANF;
|
property OnANF: TWebCmdANF read FOnANF write FOnANF;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -905,15 +910,39 @@ begin
|
|||||||
end
|
end
|
||||||
else if Cmd = 'set_nr' then
|
else if Cmd = 'set_nr' then
|
||||||
begin
|
begin
|
||||||
On_ := JsonGetBool(Json, 'on', FNR);
|
On_ := JsonGetBool(Json, 'on', FNRMode <> 0);
|
||||||
FStateLock.Enter; FNR := On_; FStateLock.Leave;
|
ModeValue := Ord(On_);
|
||||||
if Assigned(FOnNR) then FOnNR(On_);
|
FStateLock.Enter; FNRMode := ModeValue; FStateLock.Leave;
|
||||||
|
if Assigned(FOnNR) then FOnNR(ModeValue);
|
||||||
|
end
|
||||||
|
else if Cmd = 'set_nr_mode' then
|
||||||
|
begin
|
||||||
|
ModeValue := JsonGetInt(Json, 'mode', FNRMode);
|
||||||
|
if ModeValue < 0 then ModeValue := 0;
|
||||||
|
if ModeValue > 4 then ModeValue := 4;
|
||||||
|
FStateLock.Enter; FNRMode := ModeValue; FStateLock.Leave;
|
||||||
|
if Assigned(FOnNR) then FOnNR(ModeValue);
|
||||||
end
|
end
|
||||||
else if Cmd = 'set_nb' then
|
else if Cmd = 'set_nb' then
|
||||||
begin
|
begin
|
||||||
On_ := JsonGetBool(Json, 'on', FNB);
|
On_ := JsonGetBool(Json, 'on', FNBMode <> 0);
|
||||||
FStateLock.Enter; FNB := On_; FStateLock.Leave;
|
ModeValue := Ord(On_);
|
||||||
if Assigned(FOnNB) then FOnNB(On_);
|
FStateLock.Enter; FNBMode := ModeValue; FStateLock.Leave;
|
||||||
|
if Assigned(FOnNB) then FOnNB(ModeValue);
|
||||||
|
end
|
||||||
|
else if Cmd = 'set_nb_mode' then
|
||||||
|
begin
|
||||||
|
ModeValue := JsonGetInt(Json, 'mode', FNBMode);
|
||||||
|
if ModeValue < 0 then ModeValue := 0;
|
||||||
|
if ModeValue > 2 then ModeValue := 2;
|
||||||
|
FStateLock.Enter; FNBMode := ModeValue; FStateLock.Leave;
|
||||||
|
if Assigned(FOnNB) then FOnNB(ModeValue);
|
||||||
|
end
|
||||||
|
else if Cmd = 'set_snb' then
|
||||||
|
begin
|
||||||
|
On_ := JsonGetBool(Json, 'on', FSNB);
|
||||||
|
FStateLock.Enter; FSNB := On_; FStateLock.Leave;
|
||||||
|
if Assigned(FOnSNB) then FOnSNB(On_);
|
||||||
end
|
end
|
||||||
else if Cmd = 'set_anf' then
|
else if Cmd = 'set_anf' then
|
||||||
begin
|
begin
|
||||||
@@ -1015,7 +1044,7 @@ begin
|
|||||||
'"span_hz":%.0f,"center_hz":%.0f,"volume":%d,' +
|
'"span_hz":%.0f,"center_hz":%.0f,"volume":%d,' +
|
||||||
'"wf_agc":%s,"wf_nf":%s,"band_idx":%d,"smeter_dbm":%.1f,' +
|
'"wf_agc":%s,"wf_nf":%s,"band_idx":%d,"smeter_dbm":%.1f,' +
|
||||||
'"running":%s,"mute":%s,"ctun":%s,' +
|
'"running":%s,"mute":%s,"ctun":%s,' +
|
||||||
'"nr":%s,"nb":%s,"anf":%s,"connected":%s}',
|
'"nr_mode":%d,"nr":%s,"nb_mode":%d,"nb":%s,"snb":%s,"anf":%s,"connected":%s}',
|
||||||
[FFreq, FMode, MODE_N[FMode mod 8],
|
[FFreq, FMode, MODE_N[FMode mod 8],
|
||||||
FFilterIdx, FFilterBW,
|
FFilterIdx, FFilterBW,
|
||||||
FAGCMode, FAGCTop,
|
FAGCMode, FAGCTop,
|
||||||
@@ -1026,8 +1055,11 @@ begin
|
|||||||
BoolToStr(FTrxRunning, 'true', 'false'),
|
BoolToStr(FTrxRunning, 'true', 'false'),
|
||||||
BoolToStr(FMuted, 'true', 'false'),
|
BoolToStr(FMuted, 'true', 'false'),
|
||||||
BoolToStr(FCtun, 'true', 'false'),
|
BoolToStr(FCtun, 'true', 'false'),
|
||||||
BoolToStr(FNR, 'true', 'false'),
|
FNRMode,
|
||||||
BoolToStr(FNB, 'true', 'false'),
|
BoolToStr(FNRMode <> 0, 'true', 'false'),
|
||||||
|
FNBMode,
|
||||||
|
BoolToStr(FNBMode <> 0, 'true', 'false'),
|
||||||
|
BoolToStr(FSNB, 'true', 'false'),
|
||||||
BoolToStr(FANF, 'true', 'false'),
|
BoolToStr(FANF, 'true', 'false'),
|
||||||
BoolToStr(FConnected, 'true', 'false')
|
BoolToStr(FConnected, 'true', 'false')
|
||||||
]);
|
]);
|
||||||
@@ -1091,7 +1123,8 @@ procedure TWebServer.PushSpectrum(
|
|||||||
SpanHz: Double; Volume: Integer;
|
SpanHz: Double; Volume: Integer;
|
||||||
WfAGC, WfNF: Boolean; BandIdx: Integer;
|
WfAGC, WfNF: Boolean; BandIdx: Integer;
|
||||||
TrxConnected: Boolean;
|
TrxConnected: Boolean;
|
||||||
TrxRunning, Muted, Ctun, NR, NB, ANF: Boolean;
|
TrxRunning, Muted, Ctun: Boolean;
|
||||||
|
NRMode, NBMode: Integer; SNB, ANF: Boolean;
|
||||||
CenterHz: Double; FilterIdx: Integer);
|
CenterHz: Double; FilterIdx: Integer);
|
||||||
var N, i: Integer;
|
var N, i: Integer;
|
||||||
begin
|
begin
|
||||||
@@ -1116,8 +1149,9 @@ begin
|
|||||||
FTrxRunning := TrxRunning;
|
FTrxRunning := TrxRunning;
|
||||||
FMuted := Muted;
|
FMuted := Muted;
|
||||||
FCtun := Ctun;
|
FCtun := Ctun;
|
||||||
FNR := NR;
|
FNRMode := NRMode;
|
||||||
FNB := NB;
|
FNBMode := NBMode;
|
||||||
|
FSNB := SNB;
|
||||||
FANF := ANF;
|
FANF := ANF;
|
||||||
FCenterHz := CenterHz;
|
FCenterHz := CenterHz;
|
||||||
FFilterIdx := FilterIdx;
|
FFilterIdx := FilterIdx;
|
||||||
|
|||||||
Reference in New Issue
Block a user