mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 18:43:51 +00:00
Phase 3 (batch 15): move band save/restore into the controller
Per the architecture decision, band state lifecycle belongs on the controller (it operates entirely on controller state + engines; persistence is already delegated to Settings.pas). A separate unit would need friend access to ~20 fields + engines — worse coupling. - MakeBandSettings, SaveCurrentBand: moved verbatim (pure over controller state; SaveCurrentBand handles the XVTR-slot vs HF band-cache split and delegates the write to FSettings). MainForm.SaveCurrentBand is now a thin delegate (22 call sites unchanged); MakeBandSettings removed from MainForm. - RestoreBand: state + DSP application moved to the controller; rendering is driven by per-field Changed events (rfBand/rfMode/rfFilter/rfAGC*/rfFM*/ rfCTun/rfVfoB). The FM filter-index sanitize (which UpdateFilterButtons did inline as a render side-effect) is extracted into a pure SanitizeFilterForMode so the DSP ApplyModeFilter still runs on the sanitized BW (preserves original ordering). Fixes the same AGC index-cast bug as earlier batches (now ApplyAGCToEngine). - MainForm.RestoreBand is a thin wrapper: ResetWfAvgBuf (band-switch-only, not per-tune) + controller.RestoreBand + ApplyVfoA(FVfoA) for the final tune with channel orchestration (auto-CTCSS / pre-channel drive). - Added rfFMStep render case (BtnFMStep on/off was styled ad-hoc). Builds clean, links. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
a8a192a3a3
commit
24102343ea
+15
-135
@@ -412,7 +412,6 @@ type
|
||||
procedure RestoreWindowBounds;
|
||||
procedure SaveWindowBounds;
|
||||
function MakeGlobalSettings: TGlobalSettings;
|
||||
function MakeBandSettings: TBandSettings;
|
||||
procedure FreqDispBChanged(Sender: TObject; NewFreq: Int64);
|
||||
procedure BtnBandClick(Sender: TObject);
|
||||
procedure BtnModeClick(Sender: TObject);
|
||||
@@ -787,28 +786,6 @@ begin
|
||||
FController.FSettings.SaveWindowBounds(L, T, Wd, Ht, DPI, Maximized);
|
||||
end;
|
||||
|
||||
function TMainForm.MakeBandSettings: TBandSettings;
|
||||
begin
|
||||
Result.VfoA := FController.FVfoA;
|
||||
Result.VfoB := FController.FVfoB;
|
||||
Result.Mode := FController.FMode;
|
||||
Result.FilterIdx := FController.FFilter;
|
||||
Result.FilterBW := FController.FFilterBW;
|
||||
Result.AGCMode := FController.FAGCMode;
|
||||
Result.AGCTop := FController.FAGCTop;
|
||||
Result.CTun := FController.FCTun;
|
||||
Result.SpanHz := FController.FSpanHz;
|
||||
Result.FMSQOn := FController.FFMSQOn;
|
||||
Result.FMSQLevel := FController.FFMSQLevel;
|
||||
Result.CTCSSOn := FController.FFMCTCSSOn;
|
||||
Result.CTCSSToneIdx := FController.FFMCTCSSToneIdx;
|
||||
Result.FMStepOn := FController.FFMStepOn;
|
||||
Result.FMStepIdx := FController.FFMStepIdx;
|
||||
Result.FMRptDir := FController.FFMRptDir;
|
||||
Result.FMRptOffsetHz := FController.FFMRptOffsetHz;
|
||||
// Waterfall AGC/NF — глобальные (не диапазонные)
|
||||
end;
|
||||
|
||||
function TMainForm.MakeGlobalSettings: TGlobalSettings;
|
||||
var i: Integer;
|
||||
begin
|
||||
@@ -889,124 +866,21 @@ end;
|
||||
|
||||
procedure TMainForm.SaveCurrentBand;
|
||||
begin
|
||||
if not FController.FDevConnected then Exit;
|
||||
// В XVTR-режиме НЕ трогаем HF band-cache: FController.FBandCache[FController.FCurrentBand]
|
||||
// относится к HF-диапазону, на котором пользователь был ДО активации
|
||||
// трансвертера, и FController.FVfoA сейчас на XVTR-частоте (144.x, 432.x и т.д.).
|
||||
// Запись в FController.FBandCache[FController.FCurrentBand] стерла бы корректное HF-состояние.
|
||||
// Вместо этого сохраняем LastFreq в XVTR-настройках.
|
||||
if FController.FCurrentXvtr >= 0 then
|
||||
begin
|
||||
if (FController.FCurrentXvtr < CFG_XVTR_COUNT) then
|
||||
begin
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastFreq := FController.FVfoA;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastMode := FController.FMode;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastFilterIdx := FController.FFilter;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastFMSQOn := FController.FFMSQOn;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastFMSQLevel := FController.FFMSQLevel;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastCTCSSOn := FController.FFMCTCSSOn;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastCTCSSToneIdx := FController.FFMCTCSSToneIdx;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastFMStepOn := FController.FFMStepOn;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastFMStepIdx := FController.FFMStepIdx;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastFMRptDir := FController.FFMRptDir;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastFMRptOffsetHz := FController.FFMRptOffsetHz;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastCTun := FController.FCTun;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastAGCMode := FController.FAGCMode;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastAGCTop := FController.FAGCTop;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastCTCSSAutoActive := FController.FFMCTCSSAutoActive;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastFMRptAutoActive := FController.FFMRptAutoActive;
|
||||
end;
|
||||
FController.FSettings.SaveXvtr(FController.FDevMAC, FController.FXvtrSettings);
|
||||
Exit;
|
||||
end;
|
||||
// Не сохраняем, если VFO ушёл в VHF/UHF область (например, после применения
|
||||
// канала на 2м без XVTR) — иначе HF-кэш диапазона будет перезаписан VHF-частотой.
|
||||
if FController.FVfoA > 61000000 then Exit;
|
||||
FController.FBandCache[FController.FCurrentBand] := MakeBandSettings;
|
||||
FController.FSettings.SaveBand(FController.FDevMAC, FController.FCurrentBand, FController.FBandCache[FController.FCurrentBand]);
|
||||
// Логика сохранения (band-cache/XVTR-слот + конфиг) — в контроллере.
|
||||
FController.SaveCurrentBand;
|
||||
end;
|
||||
|
||||
procedure TMainForm.RestoreBand(BandIdx: Integer);
|
||||
var
|
||||
B: TBandSettings;
|
||||
i: Integer;
|
||||
begin
|
||||
if (BandIdx < 0) or (BandIdx >= CFG_BAND_COUNT) then Exit;
|
||||
B := FController.FBandCache[BandIdx];
|
||||
|
||||
// --- Кнопки диапазонов ---
|
||||
for i := 0 to BAND_COUNT - 1 do
|
||||
StyleButton(BtnBand[i], i = BandIdx);
|
||||
// Сбрасываем waterfall thresholds при смене диапазона
|
||||
// Сброс порогов водопада — только при явной смене диапазона (не на каждом
|
||||
// пересечении границы при тюнинге, поэтому здесь, а не в rfBand-рендере).
|
||||
FSpecView.ResetWfAvgBuf;
|
||||
|
||||
// --- Режим: сначала устанавливаем FController.FMode, потом кнопки и WDSP ---
|
||||
FController.FMode := B.Mode;
|
||||
for i := 0 to MODE_COUNT - 1 do
|
||||
StyleButton(BtnMode[i], i = FController.FMode);
|
||||
if FController.FWDSPReady then
|
||||
FController.FDSPEngine.SetMode(FController.FMode);
|
||||
|
||||
// --- Фильтр ---
|
||||
FController.FFilter := B.FilterIdx;
|
||||
FController.FFilterBW := B.FilterBW;
|
||||
UpdateFilterButtons; // обновляет кнопки фильтра
|
||||
FController.ApplyModeFilter; // применяет Lo/Hi в WDSP с учётом нового FController.FMode
|
||||
|
||||
// --- AGC ---
|
||||
FController.FAGCMode := B.AGCMode;
|
||||
FController.FAGCTop := B.AGCTop;
|
||||
for i := 0 to 4 do
|
||||
StyleButton(BtnAGCMode[i], i = FController.FAGCMode);
|
||||
TrkAGC.Position := FController.FAGCTop;
|
||||
LblAGCTop.Caption := Format('%ddB', [FController.FAGCTop]);
|
||||
if FController.FWDSPReady then
|
||||
begin
|
||||
FController.FDSPEngine.SetAGCTop(FController.FAGCTop);
|
||||
FController.FDSPEngine.SetAGC(TWDSPAGCMode(FController.FAGCMode), 50.0);
|
||||
end;
|
||||
FSpecView.AGCTop := FController.FAGCTop;
|
||||
|
||||
// --- FM Squelch + CTCSS ---
|
||||
FController.FFMSQOn := B.FMSQOn;
|
||||
FController.FFMSQLevel := B.FMSQLevel;
|
||||
// UI update happens inside UpdateFilterButtons (called above) when mode=FM
|
||||
FController.FFMCTCSSOn := B.CTCSSOn;
|
||||
if BtnFMCTCSS <> nil then StyleButton(BtnFMCTCSS, FController.FFMCTCSSOn);
|
||||
SetFMCTCSSTone(B.CTCSSToneIdx);
|
||||
ApplyFMSquelch;
|
||||
FController.FFMStepOn := B.FMStepOn;
|
||||
SetFMStep(B.FMStepIdx);
|
||||
if BtnFMStep <> nil then StyleButton(BtnFMStep, FController.FFMStepOn);
|
||||
FController.FFMRptDir := B.FMRptDir;
|
||||
FController.FFMRptOffsetHz := B.FMRptOffsetHz;
|
||||
if FController.FFMRptOffsetHz <= 0 then
|
||||
FController.FFMRptOffsetHz := RptDefaultOffsetHz(B.VfoA);
|
||||
if BtnFMRptMinus <> nil then StyleButton(BtnFMRptMinus, FController.FFMRptDir = RPT_MINUS);
|
||||
if BtnFMRptPlus <> nil then StyleButton(BtnFMRptPlus, FController.FFMRptDir = RPT_PLUS);
|
||||
if EdFMRptOffset <> nil then EdFMRptOffset.Text := RptFormatOffset(FController.FFMRptOffsetHz);
|
||||
|
||||
// --- CTUN ---
|
||||
FController.FCTun := B.CTun;
|
||||
StyleButton(BtnCTun, FController.FCTun);
|
||||
if FController.FWDSPReady and not FController.FCTun then
|
||||
FController.FDSPEngine.SetShift(0.0);
|
||||
|
||||
// --- Sample Rate / Span ---
|
||||
// SampleRate — глобальный, не per-band. Не восстанавливаем из диапазона.
|
||||
FController.FSpanHz := FController.FSampleRate;
|
||||
if Assigned(FSampleRateOverlay) then
|
||||
FSampleRateOverlay.SetCurrentRate(FController.FSampleRate);
|
||||
|
||||
// --- VFO A: центрируем на новой частоте, сбрасываем shift ---
|
||||
FController.FCenterFreq := B.VfoA; // DDC = центр диапазона
|
||||
FController.FVfoB := B.VfoB;
|
||||
FreqDispB.Frequency := Round(FController.FVfoB);
|
||||
|
||||
// Пересчитываем drive byte для нового диапазона перед отправкой в сеть
|
||||
FController.FDriveLevel := CalcDriveByte;
|
||||
// ApplyVfoA обновит сеть, FreqDisp, shift, Ruler — перерисует.
|
||||
ApplyVfoA(Round(B.VfoA));
|
||||
// Состояние + DSP + события рендера — в контроллере.
|
||||
FController.RestoreBand(BandIdx);
|
||||
// Финальная перестройка VFO A с канальной оркестрацией (auto-CTCSS,
|
||||
// pre-channel drive) — через UI-путь ApplyVfoA.
|
||||
ApplyVfoA(Round(FController.FVfoA));
|
||||
end;
|
||||
|
||||
procedure TMainForm.SaveAllAndExit;
|
||||
@@ -1492,6 +1366,12 @@ begin
|
||||
if (FController.FMode = MODE_FM) and (FSpecView <> nil) then
|
||||
FSpecView.FMGridStepHz := FM_STEP_HZ[FController.FFMStepIdx];
|
||||
end;
|
||||
rfFMStep:
|
||||
if BtnFMStep <> nil then
|
||||
begin
|
||||
StyleButton(BtnFMStep, FController.FFMStepOn);
|
||||
BtnFMStep.Repaint;
|
||||
end;
|
||||
rfFMSQ:
|
||||
begin
|
||||
StyleButton(BtnFMSQ, FController.FFMSQOn);
|
||||
|
||||
Reference in New Issue
Block a user