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
|
||||
T: Double;
|
||||
ActiveFreq: Double;
|
||||
BandIdx: Integer;
|
||||
NewBand: Integer;
|
||||
begin
|
||||
T := FVfoA; FVfoA := FVfoB; FVfoB := T;
|
||||
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;
|
||||
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;
|
||||
Changed(rfVfoA);
|
||||
Changed(rfVfoB);
|
||||
@@ -1518,6 +1527,10 @@ end;
|
||||
|
||||
procedure TRadioController.SetFilterIdx(Idx: Integer);
|
||||
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;
|
||||
case FMode of
|
||||
0, 1: FFilterBW := FILT_SSB_BW[Idx];
|
||||
@@ -2225,7 +2238,7 @@ begin
|
||||
ApplyNoiseFilterButtonsToDSP;
|
||||
// ChangeSampleRate пересоздаёт WDSP-канал — восстанавливаем все настройки
|
||||
FDSPEngine.SetAGCTop(FAGCTop);
|
||||
FDSPEngine.SetAGC(TWDSPAGCMode(FAGCMode), 50.0);
|
||||
ApplyAGCToEngine; // единый маппинг UI-индекс→enum (не прямой каст)
|
||||
end;
|
||||
|
||||
// Сначала отправляем Run=1 — эмулятор/железо создают ddc_specific_thread
|
||||
@@ -2309,7 +2322,7 @@ begin
|
||||
if FTXSettings.TXSpecGridStep > 0 then
|
||||
FTXSpecGridStep := FTXSettings.TXSpecGridStep;
|
||||
FVolume := FLoadedGlobal.Volume;
|
||||
FActiveVfo := FLoadedGlobal.ActiveVfo;
|
||||
FActiveVfo := EnsureRange(FLoadedGlobal.ActiveVfo, 0, 1); // битый конфиг не должен дать невалидный VFO
|
||||
FPAMaxPower := FLoadedGlobal.PAMaxPower;
|
||||
for i := 0 to CFG_BAND_COUNT - 1 do
|
||||
FPABandCal[i] := FLoadedGlobal.PABandCal[i];
|
||||
@@ -2318,7 +2331,9 @@ begin
|
||||
// drive% (0..100) — раньше грузился через TrkDrive.Position; теперь напрямую,
|
||||
// слайдер выставит rfDevice-рендер. Калиброванный байт считаем после FCurrentBand.
|
||||
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;
|
||||
// SampleRate — глобальный, до RestoreBand
|
||||
if FLoadedGlobal.SampleRate > 0 then
|
||||
|
||||
Reference in New Issue
Block a user