mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
fix: four logic bugs in RadioController
1. StartRunning applied AGC mode via a raw enum cast (TWDSPAGCMode(FAGCMode)) instead of the index→enum table, inverting Fast↔Off on every connect/go-live (GUI and daemon). Now uses ApplyAGCToEngine like the rest of the unit. 2. SetFilterIdx indexed the per-mode BW/deviation tables with an unchecked Idx (FM tables hold only 2 entries) — out-of-bounds when driven from CAT/web. Now clamps Idx per mode (EnsureRange). 3. ConnectDevice loaded FActiveVfo / FCurrentBand straight from config without range validation; a corrupt/old blob could leave FCurrentBand invalid and make later SetMode/SetFilterIdx write past FBandCache. Both now clamped. 4. VfoSwap did not run the bandstack DSP restore that SetActiveVfo does, so a swap to a VFO on another band kept the old mode/filter/AGC while the band button highlighted the new band. Now mirrors SetActiveVfo. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+25
-10
@@ -1472,18 +1472,27 @@ procedure TRadioController.VfoSwap;
|
|||||||
var
|
var
|
||||||
T: Double;
|
T: Double;
|
||||||
ActiveFreq: Double;
|
ActiveFreq: Double;
|
||||||
BandIdx: Integer;
|
NewBand: Integer;
|
||||||
begin
|
begin
|
||||||
T := FVfoA; FVfoA := FVfoB; FVfoB := T;
|
T := FVfoA; FVfoA := FVfoB; FVfoB := T;
|
||||||
ActiveFreq := ActiveVfoHz;
|
ActiveFreq := ActiveVfoHz;
|
||||||
|
// Bandstack: если активный после свопа VFO на другом ham-бэнде — сохраняем
|
||||||
|
// покидаемый бэнд и восстанавливаем DSP нового (mode/filter/AGC/CTUN/FM), как
|
||||||
|
// SetActiveVfo. Иначе своп на другой диапазон оставлял бы старые mode/фильтр/AGC
|
||||||
|
// при подсвеченной кнопке нового бэнда (рассинхрон).
|
||||||
|
if FCurrentXvtr < 0 then
|
||||||
|
begin
|
||||||
|
NewBand := FreqToBandIdx(ActiveFreq);
|
||||||
|
if (NewBand >= 0) and (NewBand <> FCurrentBand) then
|
||||||
|
begin
|
||||||
|
SaveCurrentBand;
|
||||||
|
FCurrentBand := NewBand;
|
||||||
|
ApplyBandDSP(FBandCache[NewBand]); // несёт Changed(rfBand) + рендер DSP-полей
|
||||||
|
FDriveLevel := CalcDriveByte; // PA-калибровка нового бэнда
|
||||||
|
end;
|
||||||
|
end;
|
||||||
FCenterFreq := ActiveFreq;
|
FCenterFreq := ActiveFreq;
|
||||||
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetShift(0.0);
|
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetShift(0.0);
|
||||||
BandIdx := FreqToBandIdx(ActiveFreq);
|
|
||||||
if (BandIdx >= 0) and (BandIdx <> FCurrentBand) then
|
|
||||||
begin
|
|
||||||
FCurrentBand := BandIdx;
|
|
||||||
Changed(rfBand);
|
|
||||||
end;
|
|
||||||
PushNetworkState;
|
PushNetworkState;
|
||||||
Changed(rfVfoA);
|
Changed(rfVfoA);
|
||||||
Changed(rfVfoB);
|
Changed(rfVfoB);
|
||||||
@@ -1518,6 +1527,10 @@ end;
|
|||||||
|
|
||||||
procedure TRadioController.SetFilterIdx(Idx: Integer);
|
procedure TRadioController.SetFilterIdx(Idx: Integer);
|
||||||
begin
|
begin
|
||||||
|
// Клампим индекс под текущий режим (как FilterBWFor) — публичная команда,
|
||||||
|
// Idx может прийти из CAT/web без проверки; FM-таблицы всего на 2 элемента.
|
||||||
|
if FMode = MODE_FM then Idx := EnsureRange(Idx, 0, FILT_FM_COUNT - 1)
|
||||||
|
else Idx := EnsureRange(Idx, 0, FILT_COUNT - 1);
|
||||||
FFilter := Idx;
|
FFilter := Idx;
|
||||||
case FMode of
|
case FMode of
|
||||||
0, 1: FFilterBW := FILT_SSB_BW[Idx];
|
0, 1: FFilterBW := FILT_SSB_BW[Idx];
|
||||||
@@ -2225,7 +2238,7 @@ begin
|
|||||||
ApplyNoiseFilterButtonsToDSP;
|
ApplyNoiseFilterButtonsToDSP;
|
||||||
// ChangeSampleRate пересоздаёт WDSP-канал — восстанавливаем все настройки
|
// ChangeSampleRate пересоздаёт WDSP-канал — восстанавливаем все настройки
|
||||||
FDSPEngine.SetAGCTop(FAGCTop);
|
FDSPEngine.SetAGCTop(FAGCTop);
|
||||||
FDSPEngine.SetAGC(TWDSPAGCMode(FAGCMode), 50.0);
|
ApplyAGCToEngine; // единый маппинг UI-индекс→enum (не прямой каст)
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Сначала отправляем Run=1 — эмулятор/железо создают ddc_specific_thread
|
// Сначала отправляем Run=1 — эмулятор/железо создают ddc_specific_thread
|
||||||
@@ -2309,7 +2322,7 @@ begin
|
|||||||
if FTXSettings.TXSpecGridStep > 0 then
|
if FTXSettings.TXSpecGridStep > 0 then
|
||||||
FTXSpecGridStep := FTXSettings.TXSpecGridStep;
|
FTXSpecGridStep := FTXSettings.TXSpecGridStep;
|
||||||
FVolume := FLoadedGlobal.Volume;
|
FVolume := FLoadedGlobal.Volume;
|
||||||
FActiveVfo := FLoadedGlobal.ActiveVfo;
|
FActiveVfo := EnsureRange(FLoadedGlobal.ActiveVfo, 0, 1); // битый конфиг не должен дать невалидный VFO
|
||||||
FPAMaxPower := FLoadedGlobal.PAMaxPower;
|
FPAMaxPower := FLoadedGlobal.PAMaxPower;
|
||||||
for i := 0 to CFG_BAND_COUNT - 1 do
|
for i := 0 to CFG_BAND_COUNT - 1 do
|
||||||
FPABandCal[i] := FLoadedGlobal.PABandCal[i];
|
FPABandCal[i] := FLoadedGlobal.PABandCal[i];
|
||||||
@@ -2318,7 +2331,9 @@ begin
|
|||||||
// drive% (0..100) — раньше грузился через TrkDrive.Position; теперь напрямую,
|
// drive% (0..100) — раньше грузился через TrkDrive.Position; теперь напрямую,
|
||||||
// слайдер выставит rfDevice-рендер. Калиброванный байт считаем после FCurrentBand.
|
// слайдер выставит rfDevice-рендер. Калиброванный байт считаем после FCurrentBand.
|
||||||
FDrivePercent := EnsureRange(FLoadedGlobal.DriveLevel, 0, 100);
|
FDrivePercent := EnsureRange(FLoadedGlobal.DriveLevel, 0, 100);
|
||||||
FCurrentBand := FLoadedGlobal.LastBand;
|
// Клампим LastBand — иначе битый/старый конфиг → RestoreBand выйдет по гарду,
|
||||||
|
// а последующие SetMode/SetFilterIdx запишут в FBandCache[невалид] за массив.
|
||||||
|
FCurrentBand := EnsureRange(FLoadedGlobal.LastBand, 0, CFG_BAND_COUNT - 1);
|
||||||
FDriveLevel := CalcDriveByte;
|
FDriveLevel := CalcDriveByte;
|
||||||
// SampleRate — глобальный, до RestoreBand
|
// SampleRate — глобальный, до RestoreBand
|
||||||
if FLoadedGlobal.SampleRate > 0 then
|
if FLoadedGlobal.SampleRate > 0 then
|
||||||
|
|||||||
Reference in New Issue
Block a user