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
+80 -2
View File
@@ -109,6 +109,7 @@ type
FOnStateChanged: TRadioStateEvent;
procedure Changed(Field: TRadioField);
procedure ApplyAGCToEngine; // применяет FAGCMode к WDSP (единый маппинг)
procedure ApplyModeDefaults; // дефолтный фильтр/девиация под текущий FMode
public
// ============================================================
// ПУБЛИЧНЫЕ ПОЛЯ (миграционные — имена совпадают с TMainForm).
@@ -210,6 +211,10 @@ type
function XvtrTranslate(VisibleHz: Double): Double;
function ActiveTXFreqHz: Double;
// Применяет текущие FMode/FFilterBW/FM-параметры к DSP (RX/TX фильтр,
// FM-девиация, squelch). Вызывается командами и UI-путями смены режима.
procedure ApplyModeFilter;
// ====================================================================
// КОМАНДЫ — единый API для GUI / Web / CAT / Arduino.
// Фаза 1: обновляют поле + шлют событие; логика движка — TODO-wiring.
@@ -372,6 +377,51 @@ begin
end;
end;
procedure TRadioController.ApplyModeFilter;
var
Lo, Hi, Half: Integer;
begin
Half := FFilterBW div 2;
case FMode of
0: begin Lo := -FFilterBW; Hi := -100; end; // LSB
1: begin Lo := 100; Hi := FFilterBW; end; // USB
else Lo := -Half; Hi := Half; // DSB/CW/FM/AM/SAM
end;
if FWDSPReady and Assigned(FDSPEngine) then
begin
FDSPEngine.SetFilter(Lo, Hi);
FDSPEngine.SetTXFilter(Lo, Hi);
if FMode = MODE_FM then
begin
FDSPEngine.SetRXFMDeviation(FFMDeviation);
FDSPEngine.SetTXFMParams(FFMDeviation, FTXSettings.FMLowCut,
FTXSettings.FMHighCut, FTXSettings.FMEmphPosition);
FDSPEngine.SetFMSquelch(FFMSQOn, FFMSQLevel);
end
else
FDSPEngine.SetFMSquelch(False, 0);
end;
end;
// Выбирает дефолтный фильтр (индекс + полоса + FM-девиация) под текущий FMode.
// Зеркалит state-часть UI UpdateFilterButtons, чтобы смена режима была
// корректной и без UI (headless). FM сохраняет текущий NFM/WFM, прочие — дефолт.
procedure TRadioController.ApplyModeDefaults;
begin
case FMode of
MODE_FM:
begin
if FFilter > 1 then FFilter := FILT_FM_DEF;
FFilterBW := FILT_FM_BW[FFilter];
FFMDeviation := FILT_FM_DEV[FFilter];
end;
0, 1: begin FFilter := FILT_SSB_DEF; FFilterBW := FILT_SSB_BW[FFilter]; end;
2: begin FFilter := FILT_DSB_DEF; FFilterBW := FILT_DSB_BW[FFilter]; end;
3, 4: begin FFilter := FILT_CW_DEF; FFilterBW := FILT_CW_BW[FFilter]; end;
else begin FFilter := FILT_AM_DEF; FFilterBW := FILT_AM_BW[FFilter]; end;
end;
end;
// =====================================================================
// Команды (Фаза 1 — каркас). Полная логика переносится из TMainForm.
// =====================================================================
@@ -405,10 +455,38 @@ 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;
begin
FMode := M;
ApplyModeDefaults; // дефолтный фильтр/девиация под режим
FBandCache[FCurrentBand].Mode := FMode;
if FWDSPReady and Assigned(FDSPEngine) then
begin
FDSPEngine.SetMode(FMode);
// Если TUN активен — пересчитываем знак частоты под новый режим
if FTuning then FDSPEngine.SetTXTone(True, FTXSettings.TUNFreq, 1.0);
end;
ApplyModeFilter;
Changed(rfMode);
end;
procedure TRadioController.SetFilterIdx(Idx: Integer);
begin FFilter := Idx; Changed(rfFilter); { TODO wiring } end;
begin
FFilter := Idx;
case FMode of
0, 1: FFilterBW := FILT_SSB_BW[Idx];
2: FFilterBW := FILT_DSB_BW[Idx];
3, 4: FFilterBW := FILT_CW_BW[Idx];
MODE_FM:
begin
FFilterBW := FILT_FM_BW[Idx];
FFMDeviation := FILT_FM_DEV[Idx];
end;
else FFilterBW := FILT_AM_BW[Idx];
end;
FBandCache[FCurrentBand].FilterBW := FFilterBW;
ApplyModeFilter;
Changed(rfFilter);
end;
procedure TRadioController.SetFilterBW(BWHz: Integer);
begin FFilterBW := BWHz; Changed(rfFilterBW); { TODO wiring } end;