mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 18:43:51 +00:00
Phase 3 (batch 16): move XVTR activate/deactivate into the controller
ActivateXvtrBand/DeactivateXvtr followed the Band pattern: the state + DSP + network now live on TRadioController; the UI renders via events. - ApplyXvtrToNetwork moved to the controller (XVTR enable bit / DisablePA / RX antenna). MainForm.ApplyXvtrToNetwork is a thin delegate. - ActivateXvtr builds a TBandSettings from the XVTR slot and runs it through the shared ApplyBandDSP (mode/filter/AGC/CTUN/FM), then sets VFO B (range-clamped) / VFO A / center / drive and pushes to the radio. Render is driven by Changed(rfXvtr) + Changed(rfActiveVfo). The slot has no stored filter bandwidth, so FilterBWFor(mode, idx) derives it from the per-mode table without changing the index. - DeactivateXvtr saves the slot via SaveCurrentBand (its XVTR branch already writes the whole slot) and exits; the HF return (RestoreBand + final active-VFO retune) stays in the UI wrapper. - SetXvtrBand is now a real dispatcher (>=0 activate, <0 deactivate). - rfBand render is XVTR-aware (clears HF band buttons while in XVTR); added an rfXvtr render case for the XVTR button highlight. - The thin UI wrappers keep only wideband-view + web push. ~150 lines of inline logic removed from MainForm; all callers (web/channel/band-click/ startup) are unchanged and go through the wrappers. Also fixes a latent filter-restore bug surfaced by the XVTR round-trip (transverter -> HF -> transverter): the rfMode render calls UpdateFilterButtons, which resets the non-FM filter to the mode default. That reset belongs to a mode change (the controller already applies it via ApplyModeDefaults), not to a passive render, so it clobbered the filter restored from the band/XVTR cache. rfMode now preserves FFilter/FFilterBW around UpdateFilterButtons. This also fixes the same loss on plain HF band switches for non-FM modes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
e09bc21bba
commit
831e5c3a31
+32
-142
@@ -1272,6 +1272,7 @@ end;
|
||||
procedure TMainForm.OnControllerState(Sender: TObject; Field: TRadioField);
|
||||
var
|
||||
i: Integer;
|
||||
SavedFilter, SavedFilterBW: Integer;
|
||||
begin
|
||||
FSyncingFromController := True;
|
||||
try
|
||||
@@ -1316,8 +1317,14 @@ begin
|
||||
end;
|
||||
end;
|
||||
rfBand:
|
||||
// В XVTR-режиме HF-кнопки гасим (активна XVTR-кнопка, см. rfXvtr).
|
||||
for i := 0 to BAND_COUNT - 1 do
|
||||
StyleButton(BtnBand[i], i = FController.FCurrentBand);
|
||||
StyleButton(BtnBand[i],
|
||||
(FController.FCurrentXvtr < 0) and (i = FController.FCurrentBand));
|
||||
rfXvtr:
|
||||
for i := 0 to CFG_XVTR_COUNT - 1 do
|
||||
if BtnXvtrBand[i] <> nil then
|
||||
StyleButton(BtnXvtrBand[i], i = FController.FCurrentXvtr);
|
||||
rfMute:
|
||||
begin
|
||||
StyleButton(BtnMute, FController.FMuted);
|
||||
@@ -1332,7 +1339,18 @@ begin
|
||||
rfMode:
|
||||
begin
|
||||
for i := 0 to MODE_COUNT - 1 do StyleButton(BtnMode[i], i = FController.FMode);
|
||||
UpdateFilterButtons; // подписи/дефолт фильтра + FM-панели под режим
|
||||
// UpdateFilterButtons (для не-FM) мутирует FFilter → сбрасывает на дефолт
|
||||
// режима. Это поведение нужно при СМЕНЕ режима (web/channel), но не при
|
||||
// пассивном рендере: RestoreBand/ActivateXvtr уже задали фильтр из кэша.
|
||||
// На реальной смене режима контроллер выставляет дефолт через
|
||||
// ApplyModeDefaults ДО rfMode, так что сохраняется именно он — поведение
|
||||
// не меняется. Последующий rfFilter стилит кнопки под восстановленный фильтр.
|
||||
SavedFilter := FController.FFilter;
|
||||
SavedFilterBW := FController.FFilterBW;
|
||||
UpdateFilterButtons; // подписи + FM-панели под режим
|
||||
FController.FFilter := SavedFilter;
|
||||
FController.FFilterBW := SavedFilterBW;
|
||||
for i := 0 to FILT_COUNT - 1 do StyleButton(BtnFilter[i], i = FController.FFilter);
|
||||
SyncSpecViewFreq; // иначе полоса фильтра рисуется под старый режим
|
||||
end;
|
||||
rfFilter:
|
||||
@@ -6386,24 +6404,9 @@ end;
|
||||
// XVTR DDC In (Alex bits 8+11) управляется через галочку XVTR в Antenna/Alex
|
||||
// tab для IF-диапазона (Alex.RxOnly[IF_band]=3) — аналогично Thetis.
|
||||
procedure TMainForm.ApplyXvtrToNetwork;
|
||||
var
|
||||
En: Boolean;
|
||||
DisablePA: Boolean;
|
||||
RxAnt: Byte;
|
||||
begin
|
||||
if (FController.FCurrentXvtr >= 0) and (FController.FCurrentXvtr < CFG_XVTR_COUNT) and
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].Enabled then
|
||||
begin
|
||||
En := True;
|
||||
DisablePA := FController.FXvtrSettings.Entries[FController.FCurrentXvtr].DisablePA;
|
||||
RxAnt := FController.FXvtrSettings.Entries[FController.FCurrentXvtr].RXAntenna;
|
||||
end
|
||||
else
|
||||
begin
|
||||
En := False; DisablePA := False; RxAnt := 0;
|
||||
end;
|
||||
if FController.FNetwork.Connected then
|
||||
FController.FNetwork.SetXvtrMode(En, DisablePA, RxAnt);
|
||||
// Логика перенесена в контроллер; обёртка для существующих вызовов в UI.
|
||||
FController.ApplyXvtrToNetwork;
|
||||
end;
|
||||
|
||||
// Перестраивает динамические XVTR-кнопки в PanelBands. Удаляет старые,
|
||||
@@ -6517,139 +6520,26 @@ end;
|
||||
// Активирует XVTR-band: устанавливает видимую частоту по LastFreq или
|
||||
// середине [FreqBegin..FreqEnd], применяет network XVTR-режим.
|
||||
procedure TMainForm.ActivateXvtrBand(Idx: Integer);
|
||||
var
|
||||
Vis: Double;
|
||||
i: Integer;
|
||||
E: TXvtrEntry;
|
||||
begin
|
||||
if (Idx < 0) or (Idx >= CFG_XVTR_COUNT) then Exit;
|
||||
if not FController.FXvtrSettings.Entries[Idx].Enabled then Exit;
|
||||
FController.FCurrentXvtr := Idx;
|
||||
E := FController.FXvtrSettings.Entries[Idx];
|
||||
// Выбор начальной частоты: LastFreq если в диапазоне, иначе середина
|
||||
Vis := E.LastFreq;
|
||||
if (Vis < E.FreqBegin) or (Vis > E.FreqEnd) then
|
||||
Vis := (E.FreqBegin + E.FreqEnd) / 2.0;
|
||||
// Отключаем кнопки HF band
|
||||
for i := 0 to BAND_COUNT - 1 do
|
||||
StyleButton(BtnBand[i], False);
|
||||
// Подсвечиваем активную XVTR-кнопку
|
||||
for i := 0 to CFG_XVTR_COUNT - 1 do
|
||||
if BtnXvtrBand[i] <> nil then
|
||||
StyleButton(BtnXvtrBand[i], i = Idx);
|
||||
// Применяем XVTR режим к сети (XVTR enable bit + DDC IN + DisablePA + RX ant)
|
||||
ApplyXvtrToNetwork;
|
||||
// Восстанавливаем Mode + FM Squelch + CTCSS для этого XVTR-слота
|
||||
FController.FFMSQOn := E.LastFMSQOn;
|
||||
FController.FFMSQLevel := E.LastFMSQLevel;
|
||||
FController.FMode := E.LastMode;
|
||||
FController.FFilter := E.LastFilterIdx;
|
||||
for i := 0 to MODE_COUNT - 1 do StyleButton(BtnMode[i], i = FController.FMode);
|
||||
if FController.FWDSPReady then FController.FDSPEngine.SetMode(FController.FMode);
|
||||
UpdateFilterButtons; // показывает/скрывает FM-панели, обновляет SQL UI
|
||||
FController.ApplyModeFilter;
|
||||
FController.FFMCTCSSOn := E.LastCTCSSOn;
|
||||
FController.FFMCTCSSAutoActive := E.LastCTCSSAutoActive;
|
||||
if BtnFMCTCSS <> nil then StyleButton(BtnFMCTCSS, FController.FFMCTCSSOn);
|
||||
SetFMCTCSSTone(E.LastCTCSSToneIdx);
|
||||
ApplyFMSquelch;
|
||||
FController.FFMStepOn := E.LastFMStepOn;
|
||||
SetFMStep(E.LastFMStepIdx);
|
||||
if BtnFMStep <> nil then StyleButton(BtnFMStep, FController.FFMStepOn);
|
||||
FController.FFMRptDir := E.LastFMRptDir;
|
||||
FController.FFMRptAutoActive := E.LastFMRptAutoActive;
|
||||
FController.FFMRptOffsetHz := E.LastFMRptOffsetHz;
|
||||
if FController.FFMRptOffsetHz <= 0 then
|
||||
FController.FFMRptOffsetHz := RptDefaultOffsetHz(E.FreqBegin);
|
||||
if BtnFMRptMinus <> nil then StyleButton(BtnFMRptMinus, FController.FFMRptDir = RPT_MINUS);
|
||||
if BtnFMRptPlus <> nil then StyleButton(BtnFMRptPlus, FController.FFMRptDir = RPT_PLUS);
|
||||
if EdFMRptOffset <> nil then EdFMRptOffset.Text := RptFormatOffset(FController.FFMRptOffsetHz);
|
||||
// AGC
|
||||
FController.FAGCMode := E.LastAGCMode;
|
||||
FController.FAGCTop := E.LastAGCTop;
|
||||
for i := 0 to 4 do StyleButton(BtnAGCMode[i], i = FController.FAGCMode);
|
||||
TrkAGC.Position := FController.FAGCTop;
|
||||
LblAGCTop.Caption := Format('%ddB', [FController.FAGCTop]);
|
||||
if FController.FWDSPReady then
|
||||
begin
|
||||
FController.FDSPEngine.SetAGCTop(FController.FAGCTop);
|
||||
FController.FDSPEngine.SetAGC(TWDSPAGCMode(FController.FAGCMode), 50.0);
|
||||
end;
|
||||
FSpecView.AGCTop := FController.FAGCTop;
|
||||
// CTUN
|
||||
FController.FCTun := E.LastCTun;
|
||||
StyleButton(BtnCTun, FController.FCTun);
|
||||
// VFO-B: своя сохранённая частота слота, клэмп в диапазон трансвертера.
|
||||
FController.FVfoB := EnsureRange(E.LastFreqB, E.FreqBegin, E.FreqEnd);
|
||||
FreqDispB.Frequency := Round(FController.FVfoB);
|
||||
// VFO на видимую частоту; FController.FCenterFreq тоже visible
|
||||
FController.FVfoA := Vis;
|
||||
FController.FCenterFreq := Vis;
|
||||
FreqDispA.Frequency := Round(FController.FVfoA);
|
||||
if FController.FWDSPReady then FController.FDSPEngine.SetShift(0.0);
|
||||
// Пересчитываем drive byte для нового XVTR слота и отправляем в сеть
|
||||
FController.FDriveLevel := CalcDriveByte;
|
||||
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;
|
||||
SyncSpecViewFreq;
|
||||
FSpecView.DrawSpectrum;
|
||||
PbSpectrum.Invalidate;
|
||||
FSpecView.DrawWaterfall;
|
||||
PbWaterfall.Invalidate;
|
||||
if PbRuler <> nil then PbRuler.Invalidate;
|
||||
// Вход в XVTR-слот (state+DSP+VFO+сеть) — в контроллере; рендер кнопок/частот/
|
||||
// спектра — через события (rfXvtr/rfBand/rfActiveVfo). Здесь только UI: wideband+web.
|
||||
FController.ActivateXvtr(Idx);
|
||||
UpdateWidebandFrequencyView;
|
||||
if PbWideband <> nil then PbWideband.Invalidate;
|
||||
if PbWidebandRuler <> nil then PbWidebandRuler.Invalidate;
|
||||
PushXvtrToWeb;
|
||||
end;
|
||||
|
||||
// Деактивирует XVTR — возвращает к HF-режиму.
|
||||
// FController.FCurrentBand был сохранён неизменным во время XVTR (см. ActivateXvtrBand,
|
||||
// ApplyVfoA, SaveCurrentBand) — он указывает на HF-диапазон, с которого
|
||||
// пользователь зашёл в трансвертер. RestoreBand вернёт VFO/Mode/Filter/AGC
|
||||
// /CTUN/Span этого диапазона и обновит подсветку HF band-кнопки.
|
||||
// Деактивирует XVTR — возвращает к HF-режиму. FController.FCurrentBand указывает
|
||||
// на HF-диапазон, с которого пользователь зашёл в трансвертер. RestoreBand вернёт
|
||||
// VFO/Mode/Filter/AGC/CTUN/Span этого диапазона и обновит подсветку HF band-кнопки.
|
||||
procedure TMainForm.DeactivateXvtr;
|
||||
var i: Integer;
|
||||
begin
|
||||
if FController.FCurrentXvtr < 0 then Exit;
|
||||
// Сохраняем полное состояние XVTR-слота (раньше сохранялся только LastFreq)
|
||||
if FController.FCurrentXvtr < CFG_XVTR_COUNT then
|
||||
begin
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastFreq := FController.FVfoA;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastFreqB := FController.FVfoB;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastMode := FController.FMode;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastFilterIdx := FController.FFilter;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastFMSQOn := FController.FFMSQOn;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastFMSQLevel := FController.FFMSQLevel;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastCTCSSOn := FController.FFMCTCSSOn;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastCTCSSToneIdx := FController.FFMCTCSSToneIdx;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastFMStepOn := FController.FFMStepOn;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastFMStepIdx := FController.FFMStepIdx;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastFMRptDir := FController.FFMRptDir;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastFMRptOffsetHz := FController.FFMRptOffsetHz;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastCTun := FController.FCTun;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastAGCMode := FController.FAGCMode;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastAGCTop := FController.FAGCTop;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastCTCSSAutoActive := FController.FFMCTCSSAutoActive;
|
||||
FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastFMRptAutoActive := FController.FFMRptAutoActive;
|
||||
if FController.FDevConnected then
|
||||
begin
|
||||
FController.FSettings.SaveXvtr(FController.FDevMAC, FController.FXvtrSettings);
|
||||
FController.FSettings.Save;
|
||||
end;
|
||||
end;
|
||||
FController.FCurrentXvtr := -1;
|
||||
// Сбрасываем подсветку XVTR-кнопок
|
||||
for i := 0 to CFG_XVTR_COUNT - 1 do
|
||||
if BtnXvtrBand[i] <> nil then
|
||||
StyleButton(BtnXvtrBand[i], False);
|
||||
ApplyXvtrToNetwork;
|
||||
// Восстанавливаем HF band: VFO/Mode/Filter/AGC/CTUN/Span из кэша.
|
||||
// RestoreBand сам обновит подсветку HF band-кнопки и сетевое состояние.
|
||||
// Сохранение слота + выход (+ гашение XVTR-кнопок через rfXvtr) — в контроллере.
|
||||
FController.DeactivateXvtr;
|
||||
// HF-возврат: состояние/DSP из кэша + финальная перестройка активного VFO
|
||||
// (через UI-путь RestoreBand: ResetWfAvgBuf + controller.RestoreBand + ApplyVfoA/SetVfoB).
|
||||
if (FController.FCurrentBand >= 0) and (FController.FCurrentBand < CFG_BAND_COUNT) then
|
||||
RestoreBand(FController.FCurrentBand);
|
||||
UpdateWidebandFrequencyView;
|
||||
|
||||
+120
-1
@@ -235,6 +235,18 @@ type
|
||||
// рендера. НЕ трогает частоты VFO/центр — это переиспользуется как RestoreBand
|
||||
// (с загрузкой VFO), так и SetActiveVfo (bandstack: смена бэнда без сброса VFO).
|
||||
procedure ApplyBandDSP(const B: TBandSettings);
|
||||
// Полоса фильтра для (режим, индекс фильтра) — выбор per-mode таблицы.
|
||||
function FilterBWFor(M, Idx: Integer): Integer;
|
||||
|
||||
// ---- XVTR (трансвертер) ----
|
||||
// ApplyXvtrToNetwork — XVTR enable bit + DisablePA + RX ant в сеть.
|
||||
// ActivateXvtr — вход в слот: state+DSP (через ApplyBandDSP) + VFO/центр + сеть;
|
||||
// рендер через rfXvtr/rfBand(XVTR-aware)/rfActiveVfo. UI: wideband+web.
|
||||
// DeactivateXvtr — сохраняет слот (SaveCurrentBand) и выходит; HF-возврат
|
||||
// (RestoreBand + финальная перестройка VFO) делает UI-обёртка.
|
||||
procedure ApplyXvtrToNetwork;
|
||||
procedure ActivateXvtr(Idx: Integer);
|
||||
procedure DeactivateXvtr;
|
||||
|
||||
// Полный HP-кадр в радио (RX/TX freq через трансвертор + drive + MOX).
|
||||
// Вызывается командами смены частоты/центра и UI после правки drive.
|
||||
@@ -463,6 +475,19 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TRadioController.FilterBWFor(M, Idx: Integer): Integer;
|
||||
// Полоса выбранного фильтра под режим. Зеркалит выбор таблицы в UpdateFilterButtons,
|
||||
// но НЕ меняет индекс (в отличие от ApplyModeDefaults) — нужно для XVTR-restore.
|
||||
begin
|
||||
case M of
|
||||
MODE_FM: Result := FILT_FM_BW[EnsureRange(Idx, 0, 1)];
|
||||
0, 1: Result := FILT_SSB_BW[EnsureRange(Idx, 0, FILT_COUNT - 1)];
|
||||
2: Result := FILT_DSB_BW[EnsureRange(Idx, 0, FILT_COUNT - 1)];
|
||||
3, 4: Result := FILT_CW_BW[EnsureRange(Idx, 0, FILT_COUNT - 1)];
|
||||
else Result := FILT_AM_BW[EnsureRange(Idx, 0, FILT_COUNT - 1)];
|
||||
end;
|
||||
end;
|
||||
|
||||
// =====================================================================
|
||||
// Команды (Фаза 1 — каркас). Полная логика переносится из TMainForm.
|
||||
// =====================================================================
|
||||
@@ -1018,8 +1043,102 @@ begin if FCurrentBand < CFG_BAND_COUNT - 1 then SetBand(FCurrentBand + 1); end;
|
||||
procedure TRadioController.BandDown;
|
||||
begin if FCurrentBand > 0 then SetBand(FCurrentBand - 1); end;
|
||||
|
||||
procedure TRadioController.ApplyXvtrToNetwork;
|
||||
// Передаёт XVTR-режим в сеть (enable bit + T/R relay suppression + RX ant).
|
||||
var
|
||||
En, DisablePA: Boolean;
|
||||
RxAnt: Byte;
|
||||
begin
|
||||
if (FCurrentXvtr >= 0) and (FCurrentXvtr < CFG_XVTR_COUNT) and
|
||||
FXvtrSettings.Entries[FCurrentXvtr].Enabled then
|
||||
begin
|
||||
En := True;
|
||||
DisablePA := FXvtrSettings.Entries[FCurrentXvtr].DisablePA;
|
||||
RxAnt := FXvtrSettings.Entries[FCurrentXvtr].RXAntenna;
|
||||
end
|
||||
else
|
||||
begin
|
||||
En := False; DisablePA := False; RxAnt := 0;
|
||||
end;
|
||||
if Assigned(FNetwork) and FNetwork.Connected then
|
||||
FNetwork.SetXvtrMode(En, DisablePA, RxAnt);
|
||||
end;
|
||||
|
||||
procedure TRadioController.ActivateXvtr(Idx: Integer);
|
||||
// Вход в XVTR-слот: state+DSP через общий ApplyBandDSP + VFO/центр/сеть.
|
||||
// Рендер: rfXvtr (XVTR-кнопки), rfBand (XVTR-aware гасит HF), rfActiveVfo
|
||||
// (дисплеи A/B + полный перерисов спектра). UI-обёртка добавляет wideband+web.
|
||||
var
|
||||
E: TXvtrEntry;
|
||||
B: TBandSettings;
|
||||
Vis: Double;
|
||||
begin
|
||||
if (Idx < 0) or (Idx >= CFG_XVTR_COUNT) then Exit;
|
||||
if not FXvtrSettings.Entries[Idx].Enabled then Exit;
|
||||
FCurrentXvtr := Idx;
|
||||
E := FXvtrSettings.Entries[Idx];
|
||||
// Начальная частота: LastFreq если в диапазоне, иначе середина.
|
||||
Vis := E.LastFreq;
|
||||
if (Vis < E.FreqBegin) or (Vis > E.FreqEnd) then
|
||||
Vis := (E.FreqBegin + E.FreqEnd) / 2.0;
|
||||
|
||||
ApplyXvtrToNetwork; // XVTR enable bit + DisablePA + RX ant
|
||||
|
||||
// Авто-флаги канала (не входят в TBandSettings/ApplyBandDSP).
|
||||
FFMCTCSSAutoActive := E.LastCTCSSAutoActive;
|
||||
FFMRptAutoActive := E.LastFMRptAutoActive;
|
||||
|
||||
// DSP-настройки слота — через общий путь Band (mode/filter/AGC/CTUN/FM + рендер).
|
||||
B.Mode := E.LastMode;
|
||||
B.FilterIdx := E.LastFilterIdx;
|
||||
B.FilterBW := FilterBWFor(E.LastMode, E.LastFilterIdx);
|
||||
B.AGCMode := E.LastAGCMode;
|
||||
B.AGCTop := E.LastAGCTop;
|
||||
B.CTun := E.LastCTun;
|
||||
B.SpanHz := FSampleRate;
|
||||
B.FMSQOn := E.LastFMSQOn;
|
||||
B.FMSQLevel := E.LastFMSQLevel;
|
||||
B.CTCSSOn := E.LastCTCSSOn;
|
||||
B.CTCSSToneIdx := E.LastCTCSSToneIdx;
|
||||
B.FMStepOn := E.LastFMStepOn;
|
||||
B.FMStepIdx := E.LastFMStepIdx;
|
||||
B.FMRptDir := E.LastFMRptDir;
|
||||
B.FMRptOffsetHz := E.LastFMRptOffsetHz;
|
||||
B.VfoA := Vis;
|
||||
B.VfoB := FVfoB;
|
||||
ApplyBandDSP(B);
|
||||
|
||||
// VFO: B — своя сохранённая частота слота (клэмп в диапазон); A = visible.
|
||||
FVfoB := EnsureRange(E.LastFreqB, E.FreqBegin, E.FreqEnd);
|
||||
FVfoA := Vis;
|
||||
FCenterFreq := Vis;
|
||||
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetShift(0.0);
|
||||
FDriveLevel := CalcDriveByte;
|
||||
PushNetworkState;
|
||||
|
||||
Changed(rfXvtr);
|
||||
Changed(rfActiveVfo);
|
||||
end;
|
||||
|
||||
procedure TRadioController.DeactivateXvtr;
|
||||
// Сохраняет текущий XVTR-слот и выходит в HF. Сам HF-возврат (RestoreBand +
|
||||
// финальная перестройка активного VFO) делает UI-обёртка — там же ResetWfAvgBuf.
|
||||
begin
|
||||
if FCurrentXvtr < 0 then Exit;
|
||||
SaveCurrentBand; // XVTR-ветка: пишет весь слот + SaveXvtr
|
||||
if FDevConnected then FSettings.Save;
|
||||
FCurrentXvtr := -1;
|
||||
ApplyXvtrToNetwork; // снять XVTR enable bit
|
||||
Changed(rfXvtr); // погасить XVTR-кнопки
|
||||
end;
|
||||
|
||||
procedure TRadioController.SetXvtrBand(Idx: Integer);
|
||||
begin FCurrentXvtr := Idx; Changed(rfXvtr); { TODO wiring } end;
|
||||
// Единая точка для GUI/Web/CAT: Idx>=0 — войти в слот, Idx<0 — выйти в HF.
|
||||
// ВНИМАНИЕ: HF-возврат при выходе делает UI-обёртка DeactivateXvtr (RestoreBand).
|
||||
begin
|
||||
if Idx >= 0 then ActivateXvtr(Idx)
|
||||
else DeactivateXvtr;
|
||||
end;
|
||||
|
||||
procedure TRadioController.SetSpan(Hz: Integer);
|
||||
begin FSpanHz := Hz; Changed(rfSpan); { TODO wiring } end;
|
||||
|
||||
Reference in New Issue
Block a user