Phase 3 (batch 13): route active-VFO switch through controller command

- TRadioController.SetActiveVfo(Idx): switches the active RX VFO and retunes
  the receiver to its frequency. CTUN handling preserved: if the new VFO's
  freq is visible in the current window, only the demodulator shift changes
  (DDC/network untouched); otherwise CTUN is dropped and the window centers
  on the freq. HF band-detect + network push as before. Fires
  Changed(rfActiveVfo) (+ rfBand / rfCTun when those change).
- OnControllerState(rfActiveVfo): UpdateVfoDisplay (freq displays + RX/TX
  button highlights) and a full spectrum/waterfall/ruler redraw.

MainForm.ActivateVfo is now a thin delegate; all callers (VFO select/TX
buttons, freq-display clicks, web ActivateVfo) go through it unchanged.
Band-detect keeps the historical no-drive-recalc behavior. Builds clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Uladzimir Karpenka
2026-06-04 20:47:35 +03:00
co-authored by Claude Opus 4.8
parent af85ddece6
commit 9f7a48f89a
2 changed files with 65 additions and 74 deletions
+14 -73
View File
@@ -1410,6 +1410,17 @@ begin
if PbWaterfall <> nil then PbWaterfall.Invalidate; if PbWaterfall <> nil then PbWaterfall.Invalidate;
end; end;
end; end;
rfActiveVfo:
begin
UpdateVfoDisplay; // дисплеи A/B + подсветка RX/TX-кнопок
FSpecView.InvalidateRulerCache;
SyncSpecViewFreq;
FSpecView.DrawSpectrum;
PbSpectrum.Invalidate;
FSpecView.DrawWaterfall;
PbWaterfall.Invalidate;
if PbRuler <> nil then PbRuler.Invalidate;
end;
rfVfoB: rfVfoB:
begin begin
FreqDispB.Frequency := Round(FController.FVfoB); FreqDispB.Frequency := Round(FController.FVfoB);
@@ -4358,80 +4369,10 @@ end;
// Перестройка на частоту выбранного VFO. CTUN не трогаем. // Перестройка на частоту выбранного VFO. CTUN не трогаем.
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
procedure TMainForm.ActivateVfo(Idx: Integer); procedure TMainForm.ActivateVfo(Idx: Integer);
var
ActiveFreq: Int64;
NewBand: Integer;
Offset: Double;
HalfSpan: Double;
FreqVisible: Boolean;
begin begin
FController.FActiveVfo := Idx; // Движок (переключение RX-VFO, CTUN-логика, центр/сеть, диапазон) — в
// контроллере; рендер — OnControllerState(rfActiveVfo/rfBand/rfCTun).
// Частота нового активного VFO FController.SetActiveVfo(Idx);
if FController.FActiveVfo = 0 then
ActiveFreq := Round(FController.FVfoA)
else
ActiveFreq := Round(FController.FVfoB);
// Обновляем визуальный дисплей
UpdateVfoDisplay;
if FController.FCTun then
begin
// CTUN включён: проверяем, видна ли новая частота на текущем спектре
HalfSpan := FController.FSpanHz / 2;
Offset := ActiveFreq - FController.FCenterFreq;
FreqVisible := (Offset > -HalfSpan) and (Offset < HalfSpan);
if FreqVisible then
begin
// Частота видна в окне — просто меняем shift, DDC не трогаем
if FController.FWDSPReady then FController.FDSPEngine.SetShift(Offset);
// Сеть не трогаем — DDC (FController.FCenterFreq) остаётся прежним
end
else
begin
// Частота за пределами спектра — центрируем окно и сбрасываем CTUN
FController.FCTun := False;
StyleButton(BtnCTun, False);
FController.FBandCache[FController.FCurrentBand].CTun := False;
FController.FCenterFreq := ActiveFreq;
if FController.FWDSPReady then FController.FDSPEngine.SetShift(0.0);
if FController.FNetwork.Connected and FController.FNetwork.Running then
begin
FController.FNetwork.UpdateState(XvtrTranslate(FController.FCenterFreq), XvtrTranslate(ActiveTXFreqHz), FController.FDriveLevel, FController.FTransmitting, True, True);
FController.FNetwork.SendFullHP;
end;
end;
end
else
begin
// CTUN выключен: перестраиваем DDC на новую частоту
FController.FCenterFreq := ActiveFreq;
if FController.FWDSPReady then FController.FDSPEngine.SetShift(0.0);
if FController.FNetwork.Connected and FController.FNetwork.Running then
begin
FController.FNetwork.UpdateState(XvtrTranslate(FController.FCenterFreq), XvtrTranslate(ActiveTXFreqHz), FController.FDriveLevel, FController.FTransmitting, True, True);
FController.FNetwork.SendFullHP;
end;
end;
// Переключаем кнопку диапазона по новой частоте
NewBand := FreqToBandIdx(ActiveFreq);
if (NewBand >= 0) and (NewBand <> FController.FCurrentBand) then
begin
StyleButton(BtnBand[FController.FCurrentBand], False);
FController.FCurrentBand := NewBand;
StyleButton(BtnBand[FController.FCurrentBand], True);
end;
FSpecView.InvalidateRulerCache;
SyncSpecViewFreq;
FSpecView.DrawSpectrum;
PbSpectrum.Invalidate;
FSpecView.DrawWaterfall;
PbWaterfall.Invalidate;
if PbRuler <> nil then PbRuler.Invalidate;
end; end;
procedure TMainForm.FreqDispAClick(Sender: TObject); procedure TMainForm.FreqDispAClick(Sender: TObject);
+51 -1
View File
@@ -610,7 +610,57 @@ begin
end; end;
procedure TRadioController.SetActiveVfo(Idx: Integer); procedure TRadioController.SetActiveVfo(Idx: Integer);
begin FActiveVfo := Idx; Changed(rfActiveVfo); { TODO wiring: ActivateVfo } end; // Переключение активного (RX) VFO с перестройкой приёмника на его частоту.
// CTUN: если частота нового VFO видна в текущем окне — только меняем shift
// (DDC/сеть не трогаем); иначе CTUN сбрасывается и центрируемся на частоте.
// Рендер (дисплеи/спектр/band/CTUN-кнопка) — в UI через OnControllerState.
var
ActiveFreq: Double;
HalfSpan, Offset: Double;
FreqVisible: Boolean;
BandIdx: Integer;
begin
FActiveVfo := Idx;
ActiveFreq := ActiveVfoHz;
if FCTun then
begin
HalfSpan := FSpanHz / 2;
Offset := ActiveFreq - FCenterFreq;
FreqVisible := (Offset > -HalfSpan) and (Offset < HalfSpan);
if FreqVisible then
begin
// Частота видна — просто сдвигаем демодулятор, DDC/сеть не трогаем.
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetShift(Offset);
end
else
begin
// Частота за окном — сбрасываем CTUN и центрируемся на ней.
FCTun := False;
FBandCache[FCurrentBand].CTun := False;
FCenterFreq := ActiveFreq;
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetShift(0.0);
PushNetworkState;
Changed(rfCTun);
end;
end
else
begin
FCenterFreq := ActiveFreq;
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetShift(0.0);
PushNetworkState;
end;
// Детект диапазона по новой частоте (без пересчёта drive — как исторически).
BandIdx := FreqToBandIdx(ActiveFreq);
if (BandIdx >= 0) and (BandIdx <> FCurrentBand) then
begin
FCurrentBand := BandIdx;
Changed(rfBand);
end;
Changed(rfActiveVfo);
end;
procedure TRadioController.TuneActiveBy(DeltaHz: Double); procedure TRadioController.TuneActiveBy(DeltaHz: Double);
begin begin