fix(xvtr): правки в трансвертере больше не травят память КВ-диапазона

При входе в слот трансвертера FCurrentBand не меняется — он продолжает
указывать на тот КВ-диапазон, с которого зашли. Поэтому всё, что помнится
по диапазону, из трансвертера писалось в чужую ячейку: модуляция, слот
фильтра, режим и порог АРУ, CTUN. Поставил в трансвертере FM — 40 метров
запомнили FM.

Развилка «мы сейчас в трансвертере?» в проекте уже была, но стояла только
у двух писателей из семи — у шагового аттенюатора и у зума. Их правили
когда-то по симптому, отчего баг и возвращался: затыкали поле, а не класс.

Заведена XvtrSlotActive, через неё идут все оставшиеся писатели. Слот
трансвертера соответствующие поля уже имел (LastMode, LastFilterIdx,
LastAGCMode, LastAGCTop, LastCTun) — они просто не заполнялись живыми
правками, только снимком на выходе из слота.

SpanHz в кэше оставлен как есть: поле помечено легаси, при восстановлении
диапазона его никто не читает.

Уже испорченные записи конфига правка не лечит: чтобы починить диапазон,
надо встать на него, выставить нужную модуляцию и уйти — SaveCurrentBand
перезапишет ячейку.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-10 14:33:22 +03:00
co-authored by Claude Opus 5
parent 45d10698ee
commit 827902f3e2
+26 -5
View File
@@ -609,6 +609,12 @@ type
procedure SendDUCSpecificFromSettings; // DUC Specific (mic/keyer/atten) в сеть
procedure ApplyTXSettingsToDSP; // TX-цепь (фильтр/gain/EQ/comp/...) → WDSP
// ---- Телеграф ----------------------------------------------------------
// Живой контекст «где мы сейчас»: в трансвертере правки запоминаются в его
// слоте, иначе в кэше диапазона. ★Развилка обязана стоять у КАЖДОГО поля,
// которое помнится по диапазону: пока её не было у режима/фильтра/AGC/CTUN,
// трансвертер травил ими тот HF-диапазон, на котором стоял до входа
// (FCurrentBand при входе в слот не меняется).
function XvtrSlotActive: Boolean;
function TXProhibited: Boolean; // DoNotTx-бэнд / RX-only XVTR
function CWTXActive: Boolean; // передачей владеет FPGA-кейер
function CWOptionsByte: Byte; // DUC Specific байт 5
@@ -4068,7 +4074,8 @@ begin
begin
// Частота за окном — сбрасываем CTUN и центрируемся на ней.
FCTun := False;
FBandCache[FCurrentBand].CTun := False;
if XvtrSlotActive then FXvtrSettings.Entries[FCurrentXvtr].LastCTun := False
else FBandCache[FCurrentBand].CTun := False;
FCenterFreq := ActiveFreq;
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetShift(0.0);
NeedPush := True;
@@ -4175,7 +4182,8 @@ begin
end;
if Assigned(FDMRDec) then FDMRDec.SetEnabled(FMode = MODE_DMR);
ApplyModeDefaults; // дефолтный фильтр/девиация под режим
FBandCache[FCurrentBand].Mode := FMode;
if XvtrSlotActive then FXvtrSettings.Entries[FCurrentXvtr].LastMode := FMode
else FBandCache[FCurrentBand].Mode := FMode;
// Профиль привязан к паре «флаг + модуляция»: если передаём с главного,
// новый режим приносит свой профиль. До пуша в WDSP — ApplyTXChainSettings
// внутри SetTXMode ниже перешьёт цепь уже с новыми значениями.
@@ -4221,6 +4229,11 @@ end;
procedure TRadioController.CacheFilterToBand;
begin
if XvtrSlotActive then
begin
FXvtrSettings.Entries[FCurrentXvtr].LastFilterIdx := FFilter;
Exit;
end;
FBandCache[FCurrentBand].FilterIdx := FFilter;
FBandCache[FCurrentBand].FilterBW := FFilterBW; // легаси-поле, для старых конфигов
end;
@@ -4356,7 +4369,8 @@ begin
if (M < 0) or (M > 4) then Exit;
FAGCMode := M;
ApplyAGCToEngine;
FBandCache[FCurrentBand].AGCMode := FAGCMode;
if XvtrSlotActive then FXvtrSettings.Entries[FCurrentXvtr].LastAGCMode := FAGCMode
else FBandCache[FCurrentBand].AGCMode := FAGCMode;
Changed(rfAGCMode);
end;
@@ -4366,7 +4380,8 @@ begin
FAGCTop := DB;
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetAGCTop(FAGCTop);
ApplyAGCToEngine; // ре-применяем режим с новым уровнем
FBandCache[FCurrentBand].AGCTop := FAGCTop;
if XvtrSlotActive then FXvtrSettings.Entries[FCurrentXvtr].LastAGCTop := FAGCTop
else FBandCache[FCurrentBand].AGCTop := FAGCTop;
Changed(rfAGCTop);
end;
@@ -4989,7 +5004,8 @@ end;
procedure TRadioController.SetCTun(On_: Boolean);
begin
FCTun := On_;
FBandCache[FCurrentBand].CTun := FCTun;
if XvtrSlotActive then FXvtrSettings.Entries[FCurrentXvtr].LastCTun := FCTun
else FBandCache[FCurrentBand].CTun := FCTun;
if not FCTun then
begin
// Выключили CTUN: центрируемся на АКТИВНОМ VFO, shift=0. (Включение CTUN не
@@ -5101,6 +5117,11 @@ begin
FDSPEngine.SetANF(FANF);
end;
function TRadioController.XvtrSlotActive: Boolean;
begin
Result := (FCurrentXvtr >= 0) and (FCurrentXvtr < CFG_XVTR_COUNT);
end;
function TRadioController.TXProhibited: Boolean;
// Единая точка запретов передачи: диапазон с DoNotTx (Alex) и RX-only слот
// трансвертера. Раньше эта пара была скопирована в SetMOX/SetTune/SetTwoTone —