feat(vfo): кнопка SQL + ползунок FM-squelch в DSP-меню флага (main + слайсы)

В fly-out DSP появляется ряд SQL (тумблер + порог 0..100) только в режиме FM.
Squelch работает per-slice: у слайсов свои WDSP-каналы, поэтому добавлены
поля/сеттеры FMSQ в TSliceChan/TCtrlSlice, ApplyFMSQToChan и восстановление
при переоткрытии канала. Роутинг события по SliceId (0=RXA, иначе слайс).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-08 12:51:02 +03:00
co-authored by Claude Opus 4.8
parent ce9cfd730f
commit b2b3339a2a
4 changed files with 158 additions and 2 deletions
+19 -1
View File
@@ -524,6 +524,7 @@ type
procedure UpdateVfoOverlayVisibility; // флаг A виден: панель скрыта ИЛИ есть слайсы B+
procedure OnModeFilterSelect(Mode: Integer; FilterBW: Integer);
procedure OnVfoOverlayDSPChange(NRMode, NBMode: Integer; SNBOn, ANFOn: Boolean);
procedure OnVfoOverlaySquelchChange(SQLOn: Boolean; SQLLevel: Integer);
procedure OnVfoOverlayAGCChange(AGCMode: Integer);
procedure OnVfoOverlayVolume(Vol: Integer);
procedure OnVfoOverlayMute(Sender: TObject);
@@ -1515,10 +1516,12 @@ begin
// панели флаг правит себя сам (DoHit), синк не нужен. Только дискретные поля —
// SetState/SetDSPState безусловно инвалидируют (не звать на потоковых rfVfoA).
if Assigned(FVfoOverlay) and FVfoOverlay.Visible and (not FPanelHidden) and
(Field in [rfMode, rfFilter, rfNR, rfNB, rfSNB, rfANF, rfAGCMode]) then
(Field in [rfMode, rfFilter, rfNR, rfNB, rfSNB, rfANF, rfAGCMode,
rfFMSQ, rfFMSQLevel]) then
begin
FVfoOverlay.SetState(FController.FMode, FController.FFilterBW, FController.FVfoA, FController.FLastSMeter);
FVfoOverlay.SetDSPState(FController.FNRMode, FController.FNBMode, FController.FSNB, FController.FANF, FController.FAGCMode);
FVfoOverlay.SetSquelchState(FController.FFMSQOn, FController.FFMSQLevel);
end;
finally
FSyncingFromController := False;
@@ -5128,6 +5131,7 @@ begin
FVfoOverlay.Height := FVfoOverlay.BaseHeight; // растёт сам при открытии fly-out
FVfoOverlay.SetState(FController.FMode, FController.FFilterBW, FController.FVfoA, FController.FLastSMeter);
FVfoOverlay.SetDSPState(FController.FNRMode, FController.FNBMode, FController.FSNB, FController.FANF, FController.FAGCMode);
FVfoOverlay.SetSquelchState(FController.FFMSQOn, FController.FFMSQLevel);
FVfoOverlay.Visible := True;
PushVfoOverlayExtState;
PushVfoOverlayAudioDevices;
@@ -5292,6 +5296,7 @@ begin
begin
FVfoOverlay.SetState(FController.FMode, FController.FFilterBW, FController.FVfoA, FController.FLastSMeter);
FVfoOverlay.SetDSPState(FController.FNRMode, FController.FNBMode, FController.FSNB, FController.FANF, FController.FAGCMode);
FVfoOverlay.SetSquelchState(FController.FFMSQOn, FController.FFMSQLevel);
PositionVfoOverlay; // перепозиционируем при смене LSB↔USB
end;
end;
@@ -5310,6 +5315,17 @@ begin
FController.SetANF(ANFOn);
end;
procedure TMainForm.OnVfoOverlaySquelchChange(SQLOn: Boolean; SQLLevel: Integer);
begin
if CurSliceId <> 0 then
begin
FController.SetSliceFMSquelch(CurSliceId, SQLOn, SQLLevel);
Exit;
end;
FController.SetFMSquelchLevel(SQLLevel);
FController.SetFMSquelch(SQLOn);
end;
procedure TMainForm.OnVfoOverlayAGCChange(AGCMode: Integer);
begin
if CurSliceId <> 0 then
@@ -5436,6 +5452,7 @@ procedure TMainForm.WireOverlayEvents(O: TVfoOverlay);
begin
O.OnSelect := OnModeFilterSelect;
O.OnDSPChange := OnVfoOverlayDSPChange;
O.OnSquelchChange := OnVfoOverlaySquelchChange;
O.OnAGCChange := OnVfoOverlayAGCChange;
O.OnVolume := OnVfoOverlayVolume;
O.OnMute := OnVfoOverlayMute;
@@ -5565,6 +5582,7 @@ begin
end;
O.SetState(S.Mode, BW, S.TargetHz, FController.SliceSMeter(SliceId));
O.SetDSPState(0, 0, False, False, FController.FAGCMode);
O.SetSquelchState(S.FMSQOn, S.FMSQLevel);
O.SetExtState(Round(S.Volume * 100), S.Muted, False, False, False);
// Список аудио-устройств (общий PA-список) + текущее устройство слайса.
if Assigned(FController.FAudioOut) then