From 5b7eda291eafe8ff041f81dbc638fa31d17832e4 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Tue, 30 Jun 2026 21:27:08 +0300 Subject: [PATCH] =?UTF-8?q?fix(spectrum):=20=D1=81=D0=BE=D1=85=D1=80=D0=B0?= =?UTF-8?q?=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5/=D0=B2=D0=BE=D1=81=D1=81=D1=82?= =?UTF-8?q?=D0=B0=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B7?= =?UTF-8?q?=D1=83=D0=BC=D0=B0=20=D0=B4=D0=BB=D1=8F=20=D1=82=D1=80=D0=B0?= =?UTF-8?q?=D0=BD=D1=81=D0=B2=D0=B5=D1=80=D1=82=D0=BE=D1=80=D0=BE=D0=B2=20?= =?UTF-8?q?(XVTR)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Зум был per-band только для HF (TBandSettings). XVTR-слоты хранятся отдельно (TXvtrEntry) и зум туда не попадал — при входе в трансвертер не восстанавливался. - TXvtrEntry: LastZoomFactor/LastPanSlider + Default/Load/Save (JSON). - SaveCurrentBand (XVTR-ветка): пишет зум/пан в слот. - ActivateXvtr: восстанавливает зум слота + SetZoomPan (re-arm анализатора). Покрывает все входы (кнопка, старт по LastXvtr, CAT/web). - ApplyZoom: кэширует в активный слот — XVTR при активном трансверторе, иначе HF-band. Co-Authored-By: Claude Opus 4.8 --- RadioController.pas | 20 +++++++++++++++++++- Settings.pas | 8 ++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/RadioController.pas b/RadioController.pas index 06e3816..3567bf5 100644 --- a/RadioController.pas +++ b/RadioController.pas @@ -1512,6 +1512,8 @@ begin FXvtrSettings.Entries[i].LastAGCTop := FAGCTop; FXvtrSettings.Entries[i].LastCTCSSAutoActive := FFMCTCSSAutoActive; FXvtrSettings.Entries[i].LastFMRptAutoActive := FFMRptAutoActive; + FXvtrSettings.Entries[i].LastZoomFactor := FZoomFactor; + FXvtrSettings.Entries[i].LastPanSlider := FPanSlider; end; FSettings.SaveXvtr(FDevMAC, FXvtrSettings); Exit; @@ -2289,6 +2291,12 @@ begin B.VfoB := FVfoB; ApplyBandDSP(B); + // Zoom/pan слота: восстанавливаем и переармируем анализатор. + FZoomFactor := EnsureRange(E.LastZoomFactor, 0.0, 1.0); + FPanSlider := EnsureRange(E.LastPanSlider, 0.0, 1.0); + if Assigned(FDSPEngine) then FDSPEngine.SetZoomPan(FZoomFactor, FPanSlider); + Changed(rfZoom); + // VFO: B — своя сохранённая частота слота (клэмп в диапазон); A = visible. FVfoB := EnsureRange(E.LastFreqB, E.FreqBegin, E.FreqEnd); FVfoA := Vis; @@ -2403,7 +2411,17 @@ begin FPanSlider := EnsureRange(APan, 0.0, 1.0); if Assigned(FDSPEngine) then FDSPEngine.SetZoomPan(FZoomFactor, FPanSlider); - if (FCurrentBand >= 0) and (FCurrentBand < CFG_BAND_COUNT) then + // Кэшируем в активный слот (XVTR-слот при активном трансверторе, иначе HF-band); + // персист на диск — в SaveCurrentBand при смене/выходе. + if FCurrentXvtr >= 0 then + begin + if FCurrentXvtr < CFG_XVTR_COUNT then + begin + FXvtrSettings.Entries[FCurrentXvtr].LastZoomFactor := FZoomFactor; + FXvtrSettings.Entries[FCurrentXvtr].LastPanSlider := FPanSlider; + end; + end + else if (FCurrentBand >= 0) and (FCurrentBand < CFG_BAND_COUNT) then begin FBandCache[FCurrentBand].ZoomFactor := FZoomFactor; FBandCache[FCurrentBand].PanSlider := FPanSlider; diff --git a/Settings.pas b/Settings.pas index 7cd894c..69b44e3 100644 --- a/Settings.pas +++ b/Settings.pas @@ -190,6 +190,8 @@ type LastFMRptOffsetHz: Double; LastCTCSSAutoActive: Boolean; // CTCSS был включён каналом (авто) LastFMRptAutoActive: Boolean; // RPT был включён каналом (авто) + LastZoomFactor: Double; // зум спектра/водопада 0.0..1.0 (0.0 = без зума) + LastPanSlider: Double; // положение окна зума 0..1 (0.5 = центр) end; TXvtrSettings = record @@ -1279,6 +1281,8 @@ begin X.Entries[i].LastFMRptOffsetHz := 0.0; X.Entries[i].LastCTCSSAutoActive := False; X.Entries[i].LastFMRptAutoActive := False; + X.Entries[i].LastZoomFactor := 0.0; + X.Entries[i].LastPanSlider := 0.5; end; // Шаблоны (пользователь должен сам Enable, чтобы трансверторы появились) X.Entries[0].ButtonText := '2m'; @@ -1356,6 +1360,8 @@ begin X.Entries[i].LastFMRptOffsetHz := JD(EObj, 'last_fmrpt_offset', X.Entries[i].LastFMRptOffsetHz); X.Entries[i].LastCTCSSAutoActive := JB(EObj, 'last_ctcss_auto', X.Entries[i].LastCTCSSAutoActive); X.Entries[i].LastFMRptAutoActive := JB(EObj, 'last_fmrpt_auto', X.Entries[i].LastFMRptAutoActive); + X.Entries[i].LastZoomFactor := EnsureRange(JD(EObj, 'last_zoom_factor', X.Entries[i].LastZoomFactor), 0.0, 1.0); + X.Entries[i].LastPanSlider := EnsureRange(JD(EObj, 'last_pan_slider', X.Entries[i].LastPanSlider), 0.0, 1.0); // Валидация: Last freqs должны быть в [FreqBegin..FreqEnd] if (X.Entries[i].LastFreq < X.Entries[i].FreqBegin) or (X.Entries[i].LastFreq > X.Entries[i].FreqEnd) then @@ -1452,6 +1458,8 @@ begin JW(EObj, 'last_fmrpt_offset', X.Entries[i].LastFMRptOffsetHz); JW(EObj, 'last_ctcss_auto', X.Entries[i].LastCTCSSAutoActive); JW(EObj, 'last_fmrpt_auto', X.Entries[i].LastFMRptAutoActive); + JW(EObj, 'last_zoom_factor', X.Entries[i].LastZoomFactor); + JW(EObj, 'last_pan_slider', X.Entries[i].LastPanSlider); end; end;