mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 18:43:51 +00:00
Fix CTUN not working on VFO B
Two A-hardcoded spots broke CTUN whenever VFO B was the active receiver: - SetVfoB forced shift=0 (no CTUN handling), so click/wheel/edit on B re-centered the DDC instead of shifting the demodulator. - SetCTun, on disable, re-centered on FVfoA regardless of active VFO. Extract the CTUN shift/center/edge-scroll logic into a shared private ApplyTuneCore(VfoHz) used by both SetVfoA and SetVfoB, and add ActiveVfoHz. SetCTun now centers on ActiveVfoHz. CTUN behaves identically on A and B. This also was a latent gap pre-refactor (the old inline VFO B tune blocks never honored CTUN). 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
9d48f26dd8
commit
8f0ba64d67
+55
-45
@@ -110,6 +110,8 @@ type
|
||||
procedure Changed(Field: TRadioField);
|
||||
procedure ApplyAGCToEngine; // применяет FAGCMode к WDSP (единый маппинг)
|
||||
procedure ApplyModeDefaults; // дефолтный фильтр/девиация под текущий FMode
|
||||
function ActiveVfoHz: Double; // частота активного VFO (A или B)
|
||||
procedure ApplyTuneCore(VfoHz: Double); // CTUN shift/center/scroll для актив. VFO
|
||||
public
|
||||
// ============================================================
|
||||
// ПУБЛИЧНЫЕ ПОЛЯ (миграционные — имена совпадают с TMainForm).
|
||||
@@ -496,16 +498,54 @@ begin
|
||||
Result := Min(Round(audio_vol * 1.02 * 255.0), 255);
|
||||
end;
|
||||
|
||||
function TRadioController.ActiveVfoHz: Double;
|
||||
begin
|
||||
if FActiveVfo = 0 then Result := FVfoA else Result := FVfoB;
|
||||
end;
|
||||
|
||||
procedure TRadioController.ApplyTuneCore(VfoHz: Double);
|
||||
// Общее ядро перестройки приёмника на частоту АКТИВНОГО VFO (A или B).
|
||||
// CTUN OFF: DDC = VfoHz, сдвиг 0.
|
||||
// CTUN ON: DDC фиксирован, демодулятор сдвигаем на VfoHz-FCenterFreq;
|
||||
// если полоса фильтра вышла за край дисплея — прокручиваем центр.
|
||||
// Ставит FCenterFreq / shift / FLastVfoScrolled.
|
||||
var
|
||||
Offset, FiltLo, FiltHi, HalfSpan: Double;
|
||||
begin
|
||||
FLastVfoScrolled := False;
|
||||
if not FCTun then
|
||||
begin
|
||||
FCenterFreq := VfoHz;
|
||||
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetShift(0.0);
|
||||
end
|
||||
else
|
||||
begin
|
||||
Offset := VfoHz - FCenterFreq;
|
||||
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetShift(Offset);
|
||||
HalfSpan := FSpanHz / 2;
|
||||
case FMode of
|
||||
0: begin FiltLo := Offset - FFilterBW; FiltHi := Offset - 100; end;
|
||||
1: begin FiltLo := Offset + 100; FiltHi := Offset + FFilterBW; end;
|
||||
else begin FiltLo := Offset - FFilterBW/2; FiltHi := Offset + FFilterBW/2; end;
|
||||
end;
|
||||
if (FiltHi > HalfSpan) or (FiltLo < -HalfSpan) then
|
||||
begin
|
||||
if FiltHi > HalfSpan then
|
||||
FCenterFreq := VfoHz - HalfSpan * 0.5
|
||||
else
|
||||
FCenterFreq := VfoHz + HalfSpan * 0.5;
|
||||
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetShift(VfoHz - FCenterFreq);
|
||||
FLastVfoScrolled := True;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TRadioController.SetVfoA(Hz: Double);
|
||||
// Чистое ядро перестройки VFO A: XVTR-клэмп, CTUN shift/center (с прокруткой
|
||||
// центра при выходе полосы фильтра за край), детект диапазона, FM авто-RPT,
|
||||
// проталкивание в сеть. Рендер (FreqDisp/спектр/band-кнопки) — в UI через
|
||||
// OnControllerState(rfVfoA/rfBand). Канальную оркестрацию (авто-CTCSS,
|
||||
// pre-channel drive) делает вызывающий UI-путь.
|
||||
// Перестройка VFO A: XVTR-клэмп, CTUN ядро, детект диапазона, FM авто-RPT,
|
||||
// проталкивание в сеть. Рендер — в UI через OnControllerState(rfVfoA/rfBand).
|
||||
// Канальную оркестрацию (авто-CTCSS, pre-channel drive) делает UI-путь.
|
||||
var
|
||||
NewFreq: Int64;
|
||||
Offset: Double;
|
||||
FiltLo, FiltHi, HalfSpan: Double;
|
||||
BandIdx: Integer;
|
||||
begin
|
||||
NewFreq := Round(Hz);
|
||||
@@ -519,36 +559,7 @@ begin
|
||||
NewFreq := Round(FXvtrSettings.Entries[FCurrentXvtr].FreqEnd);
|
||||
end;
|
||||
FVfoA := NewFreq;
|
||||
FLastVfoScrolled := False;
|
||||
|
||||
if not FCTun then
|
||||
begin
|
||||
// CTUN OFF: DDC = VFO, сдвига нет
|
||||
FCenterFreq := FVfoA;
|
||||
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetShift(0.0);
|
||||
end
|
||||
else
|
||||
begin
|
||||
// CTUN ON: DDC фиксирован, демодулятор сдвигаем на FVfoA-FCenterFreq
|
||||
Offset := FVfoA - FCenterFreq;
|
||||
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetShift(Offset);
|
||||
// Полоса фильтра вышла за край дисплея → прокручиваем центр
|
||||
HalfSpan := FSpanHz / 2;
|
||||
case FMode of
|
||||
0: begin FiltLo := Offset - FFilterBW; FiltHi := Offset - 100; end;
|
||||
1: begin FiltLo := Offset + 100; FiltHi := Offset + FFilterBW; end;
|
||||
else begin FiltLo := Offset - FFilterBW/2; FiltHi := Offset + FFilterBW/2; end;
|
||||
end;
|
||||
if (FiltHi > HalfSpan) or (FiltLo < -HalfSpan) then
|
||||
begin
|
||||
if FiltHi > HalfSpan then
|
||||
FCenterFreq := FVfoA - HalfSpan * 0.5
|
||||
else
|
||||
FCenterFreq := FVfoA + HalfSpan * 0.5;
|
||||
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetShift(FVfoA - FCenterFreq);
|
||||
FLastVfoScrolled := True;
|
||||
end;
|
||||
end;
|
||||
ApplyTuneCore(FVfoA);
|
||||
|
||||
// Детект диапазона (только HF: в XVTR клэмп держит VFO внутри band,
|
||||
// FreqToBandIdx вернёт -1 для VHF/UHF).
|
||||
@@ -571,17 +582,16 @@ begin
|
||||
end;
|
||||
|
||||
procedure TRadioController.SetVfoB(Hz: Double);
|
||||
// VFO B всегда сохраняется. Если B активен — перестраиваем приёмник (DDC=VFO B,
|
||||
// без CTUN, сдвиг 0), детектим диапазон и толкаем в сеть. Если B неактивен
|
||||
// (split, слушаем A) — только сохраняем частоту (используется для TX).
|
||||
// VFO B всегда сохраняется. Если B активен — перестраиваем приёмник через
|
||||
// ApplyTuneCore (с учётом CTUN), детектим диапазон и толкаем в сеть. Если B
|
||||
// неактивен (split, слушаем A) — только сохраняем частоту (для TX).
|
||||
// Рендер FreqDispB/спектра — в UI через OnControllerState(rfVfoB).
|
||||
var BandIdx: Integer;
|
||||
begin
|
||||
FVfoB := Hz;
|
||||
if FActiveVfo = 1 then
|
||||
begin
|
||||
FCenterFreq := FVfoB;
|
||||
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetShift(0.0);
|
||||
ApplyTuneCore(FVfoB);
|
||||
if FCurrentXvtr < 0 then
|
||||
begin
|
||||
BandIdx := FreqToBandIdx(FVfoB);
|
||||
@@ -788,9 +798,9 @@ begin
|
||||
FBandCache[FCurrentBand].CTun := FCTun;
|
||||
if not FCTun then
|
||||
begin
|
||||
// Выключили CTUN: центрируемся на VFO, shift=0. (Включение CTUN не трогает
|
||||
// движок — FCenterFreq остаётся как есть, спектр не прыгает.)
|
||||
FCenterFreq := FVfoA;
|
||||
// Выключили CTUN: центрируемся на АКТИВНОМ VFO, shift=0. (Включение CTUN не
|
||||
// трогает движок — FCenterFreq остаётся как есть, спектр не прыгает.)
|
||||
FCenterFreq := ActiveVfoHz;
|
||||
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetShift(0.0);
|
||||
PushNetworkState;
|
||||
end;
|
||||
|
||||
Reference in New Issue
Block a user