Phase 3 (batch 8): route desktop Mode/Filter through controller commands

- FILT_* таблицы (BW/DEF/DEV/COUNT) перенесены MainForm -> Settings.pas
  (нужны контроллеру для headless-выбора фильтра); UI-подписи FILT_*_NAMES
  остались в MainForm (ссылки разрешаются через uses Settings).
- ApplyModeFilter (чистый DSP) перенесён в TRadioController; все вызовы в
  MainForm -> FController.ApplyModeFilter.
- Контроллер: ApplyModeDefaults (дефолтный фильтр/девиация под FMode,
  зеркало state-части UpdateFilterButtons) + наполнены команды SetMode
  (FMode + дефолт + DSP SetMode/TUN + ApplyModeFilter + band cache) и
  SetFilterIdx (FFilterBW по таблицам режима + ApplyModeFilter + band cache).
- BtnModeClick/BtnFilterClick — тонкие обёртки к командам; рендер
  (StyleButton + UpdateFilterButtons + SyncSpecViewFreq) в
  OnControllerState(rfMode/rfFilter).

OnModeFilterSelect (VFO overlay), SyncWebMode/SyncWebFilter (web/CAT),
RestoreBand пока зовут FController.ApplyModeFilter инлайн — мигрируют
в следующих батчах (как и в прошлых: web/overlay позже).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Uladzimir Karpenka
2026-06-04 16:34:35 +03:00
co-authored by Claude Opus 4.8
parent 05bb68ac58
commit f12d2a69ad
3 changed files with 131 additions and 105 deletions
+30 -103
View File
@@ -62,43 +62,18 @@ const
BAND_COUNT = 11;
MODE_COUNT = 8;
FILT_COUNT = 10;
// Группы фильтров по типу модуляции
// SSB: LSB/USB
// Полосы/дефолты фильтров (FILT_COUNT, FILT_*_BW, FILT_*_DEF, FILT_FM_*)
// перенесены в Settings.pas — нужны TRadioController. Здесь остаются только
// UI-подписи кнопок (NAMES).
FILT_SSB_NAMES: array[0..FILT_COUNT-1] of string =
('5.0k','4.4k','3.8k','3.3k','2.9k','2.7k','2.4k','2.1k','1.8k','1.0k');
FILT_SSB_BW: array[0..FILT_COUNT-1] of Integer =
(5000, 4400, 3800, 3300, 2900, 2700, 2400, 2100, 1800, 1000);
FILT_SSB_DEF = 5; // 2.7k
// CW: CWL/CWU
FILT_CW_NAMES: array[0..FILT_COUNT-1] of string =
('1.0k','800','600','500','400','250','150','100','50','25');
FILT_CW_BW: array[0..FILT_COUNT-1] of Integer =
(1000, 800, 600, 500, 400, 250, 150, 100, 50, 25);
FILT_CW_DEF = 3; // 500
// DSB
FILT_DSB_NAMES: array[0..FILT_COUNT-1] of string =
('16k','12k','10k','8.0k','6.6k','5.2k','4.0k','3.1k','2.9k','2.4k');
FILT_DSB_BW: array[0..FILT_COUNT-1] of Integer =
(16000, 12000, 10000, 8000, 6600, 5200, 4000, 3100, 2900, 2400);
FILT_DSB_DEF = 3; // 8.0k
// AM/SAM
FILT_AM_NAMES: array[0..FILT_COUNT-1] of string =
('20k','18k','16k','12k','10k','9.0k','8.0k','7.0k','6.0k','5.0k');
FILT_AM_BW: array[0..FILT_COUNT-1] of Integer =
(20000, 18000, 16000, 12000, 10000, 9000, 8000, 7000, 6000, 5000);
FILT_AM_DEF = 4; // 10k
// FM: NFM (2.5 kHz deviation / 11 kHz BW) and FM (5.0 kHz deviation / 16 kHz BW)
FILT_FM_COUNT = 2;
FILT_FM_NAMES: array[0..1] of string = ('NFM', 'FM');
FILT_FM_BW: array[0..1] of Integer = (11000, 16000);
FILT_FM_DEV: array[0..1] of Double = (2500.0, 5000.0);
FILT_FM_DEF = 0; // NFM
// CTCSS tones (38 standard tones, no None — toggle via CTCSS button)
// CTCSS_COUNT и CTCSS_TONES перенесены в FMRepeater (нужны TRadioController).
@@ -440,7 +415,6 @@ type
function MakeBandSettings: TBandSettings;
procedure FreqDispBChanged(Sender: TObject; NewFreq: Int64);
procedure BtnBandClick(Sender: TObject);
procedure ApplyModeFilter;
procedure BtnModeClick(Sender: TObject);
procedure BtnFilterClick(Sender: TObject);
procedure BtnCTunClick(Sender: TObject);
@@ -978,7 +952,7 @@ begin
FController.FFilter := B.FilterIdx;
FController.FFilterBW := B.FilterBW;
UpdateFilterButtons; // обновляет кнопки фильтра
ApplyModeFilter; // применяет Lo/Hi в WDSP с учётом нового FController.FMode
FController.ApplyModeFilter; // применяет Lo/Hi в WDSP с учётом нового FController.FMode
// --- AGC ---
FController.FAGCMode := B.AGCMode;
@@ -1432,6 +1406,17 @@ begin
rfNB: UpdateNBButton;
rfSNB: UpdateSNBButton;
rfANF: UpdateANFButton;
rfMode:
begin
for i := 0 to MODE_COUNT - 1 do StyleButton(BtnMode[i], i = FController.FMode);
UpdateFilterButtons; // подписи/дефолт фильтра + FM-панели под режим
SyncSpecViewFreq; // иначе полоса фильтра рисуется под старый режим
end;
rfFilter:
begin
for i := 0 to FILT_COUNT - 1 do StyleButton(BtnFilter[i], i = FController.FFilter);
SyncSpecViewFreq;
end;
rfAGCMode:
for i := 0 to 4 do StyleButton(BtnAGCMode[i], i = FController.FAGCMode);
rfVolume:
@@ -4249,7 +4234,7 @@ begin
begin
FController.FDSPEngine.SetMode(FController.FMode);
FController.FDSPEngine.SetVolume(FController.FVolume / 100.0);
ApplyModeFilter;
FController.ApplyModeFilter;
ApplyNoiseFilterButtonsToDSP;
// ChangeSampleRate пересоздаёт WDSP-канал — восстанавливаем все настройки
FController.FDSPEngine.SetAGCTop(FController.FAGCTop);
@@ -4282,7 +4267,7 @@ begin
SendDUCSpecificFromSettings;
// Применяем TX-цепь (фильтр, mic gain, EQ, leveler, ALC, comp, ...).
ApplyTXSettingsToDSP;
ApplyModeFilter;
FController.ApplyModeFilter;
// Принудительно обновляем AGC линии — гарантированно после всех SetAGC вызовов
if FController.FWDSPReady then
@@ -5209,76 +5194,18 @@ begin
RestoreBand(FController.FCurrentBand);
end;
procedure TMainForm.ApplyModeFilter;
var
Lo, Hi, Half: Integer;
begin
Half := FController.FFilterBW div 2;
case FController.FMode of
0: begin Lo := -FController.FFilterBW; Hi := -100; end; // LSB
1: begin Lo := 100; Hi := FController.FFilterBW; end; // USB
2: begin Lo := -Half; Hi := Half; end; // DSB
3: begin Lo := -Half; Hi := Half; end; // CWL
4: begin Lo := -Half; Hi := Half; end; // CWU
5: begin Lo := -Half; Hi := Half; end; // FM
6: begin Lo := -Half; Hi := Half; end; // AM
7: begin Lo := -Half; Hi := Half; end; // SAM
else Lo := -Half; Hi := Half;
end;
if FController.FWDSPReady then
begin
FController.FDSPEngine.SetFilter(Lo, Hi);
FController.FDSPEngine.SetTXFilter(Lo, Hi);
if FController.FMode = MODE_FM then
begin
FController.FDSPEngine.SetRXFMDeviation(FController.FFMDeviation);
FController.FDSPEngine.SetTXFMParams(FController.FFMDeviation, FController.FTXSettings.FMLowCut,
FController.FTXSettings.FMHighCut, FController.FTXSettings.FMEmphPosition);
FController.FDSPEngine.SetFMSquelch(FController.FFMSQOn, FController.FFMSQLevel);
end
else
FController.FDSPEngine.SetFMSquelch(False, 0);
end;
end;
procedure TMainForm.BtnModeClick(Sender: TObject);
var
i, N: Integer;
begin
N := (Sender as TFlatButton).Tag;
FController.FMode := N;
for i := 0 to MODE_COUNT - 1 do StyleButton(BtnMode[i], i = FController.FMode);
if FController.FWDSPReady then
begin
FController.FDSPEngine.SetMode(N);
// Если TUN активен — пересчитываем знак частоты под новый режим
if FController.FTuning then
FController.FDSPEngine.SetTXTone(True, FController.FTXSettings.TUNFreq, 1.0);
end;
UpdateFilterButtons; // обновляем подписи и дефолт фильтра под новый режим
ApplyModeFilter;
SyncSpecViewFreq; // FSpecView.Mode/FilterBW — иначе полоса рисуется под старый режим
// Логика (FMode, дефолтный фильтр, DSP SetMode/TUN/ApplyModeFilter, band cache)
// — в контроллере; рендер кнопок/фильтра/спектра — в OnControllerState(rfMode).
FController.SetMode((Sender as TFlatButton).Tag);
end;
procedure TMainForm.BtnFilterClick(Sender: TObject);
var
i, N: Integer;
begin
N := (Sender as TFlatButton).Tag;
FController.FFilter := N;
case FController.FMode of
0, 1: FController.FFilterBW := FILT_SSB_BW[N];
2: FController.FFilterBW := FILT_DSB_BW[N];
3, 4: FController.FFilterBW := FILT_CW_BW[N];
5: begin
FController.FFilterBW := FILT_FM_BW[N];
FController.FFMDeviation := FILT_FM_DEV[N];
end;
else FController.FFilterBW := FILT_AM_BW[N];
end;
for i := 0 to FILT_COUNT - 1 do StyleButton(BtnFilter[i], i = FController.FFilter);
ApplyModeFilter;
SyncSpecViewFreq;
// Логика (FFilter/FFilterBW по таблицам режима, ApplyModeFilter, band cache)
// — в контроллере; рендер — в OnControllerState(rfFilter).
FController.SetFilterIdx((Sender as TFlatButton).Tag);
end;
// ---------------------------------------------------------------------------
@@ -5558,7 +5485,7 @@ begin
if FController.FTuning then FController.FDSPEngine.SetTXTone(True, FController.FTXSettings.TUNFreq, 1.0);
end;
UpdateFilterButtons;
ApplyModeFilter;
FController.ApplyModeFilter;
SyncSpecViewFreq;
end;
@@ -6079,7 +6006,7 @@ begin
if FController.FWDSPReady then
begin
FController.FDSPEngine.SetMode(FController.FMode);
ApplyModeFilter;
FController.ApplyModeFilter;
end;
SyncSpecViewFreq;
if Assigned(FVfoOverlay) and FVfoOverlay.Visible then
@@ -6154,7 +6081,7 @@ begin
begin
FController.FDSPEngine.SetMode(FController.FMode);
FController.FDSPEngine.SetVolume(FController.FVolume / 100.0);
ApplyModeFilter;
FController.ApplyModeFilter;
ApplyNoiseFilterButtonsToDSP;
// ChangeSampleRate пересоздаёт WDSP-канал — восстанавливаем AGC
FController.FDSPEngine.SetAGCTop(FController.FAGCTop);
@@ -6222,7 +6149,7 @@ begin
for i := 0 to MODE_COUNT - 1 do StyleButton(BtnMode[i], i = FController.FMode);
if FController.FWDSPReady then FController.FDSPEngine.SetMode(FController.FMode);
UpdateFilterButtons;
ApplyModeFilter;
FController.ApplyModeFilter;
SyncSpecViewFreq;
FController.FBandCache[FController.FCurrentBand].Mode := FController.FMode;
end;
@@ -6259,7 +6186,7 @@ begin
else FController.FFilterBW := FILT_AM_BW[Idx];
end;
for j := 0 to FILT_COUNT-1 do StyleButton(BtnFilter[j], j = FController.FFilter);
ApplyModeFilter;
FController.ApplyModeFilter;
SyncSpecViewFreq;
FController.FBandCache[FController.FCurrentBand].FilterBW := FController.FFilterBW;
end;
@@ -6285,7 +6212,7 @@ begin
FController.FFilter := best;
if FController.FMode = 5 then FController.FFMDeviation := FILT_FM_DEV[best];
for j := 0 to FILT_COUNT-1 do StyleButton(BtnFilter[j], j = FController.FFilter);
ApplyModeFilter;
FController.ApplyModeFilter;
SyncSpecViewFreq;
FController.FBandCache[FController.FCurrentBand].FilterBW := FController.FFilterBW;
end;
@@ -7069,7 +6996,7 @@ begin
for i := 0 to MODE_COUNT - 1 do StyleButton(BtnMode[i], i = FController.FMode);
if FController.FWDSPReady then FController.FDSPEngine.SetMode(FController.FMode);
UpdateFilterButtons; // показывает/скрывает FM-панели, обновляет SQL UI
ApplyModeFilter;
FController.ApplyModeFilter;
FController.FFMCTCSSOn := E.LastCTCSSOn;
FController.FFMCTCSSAutoActive := E.LastCTCSSAutoActive;
if BtnFMCTCSS <> nil then StyleButton(BtnFMCTCSS, FController.FFMCTCSSOn);