mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
add trancverter
This commit is contained in:
+448
-55
@@ -160,6 +160,8 @@ type
|
||||
FAudioInDevName: string; // текущее имя входного устройства (TX mic)
|
||||
FTXSettings: TTXSettings; // полный TX-конфиг (загружается per-MAC)
|
||||
FAlexSettings: TAlexSettings; // per-band antenna/routing config (Alex board)
|
||||
FXvtrSettings: TXvtrSettings; // transverter slots (per-device)
|
||||
FCurrentXvtr: Integer; // -1 = HF, 0..CFG_XVTR_COUNT-1 = active XVTR
|
||||
FWDSPReady: Boolean; // True когда WDSP открыт и работает
|
||||
|
||||
// ---- State ----
|
||||
@@ -317,6 +319,9 @@ type
|
||||
|
||||
PanelBands: TPanel;
|
||||
BtnBand: array[0..BAND_COUNT-1] of TFlatButton;
|
||||
// Динамические кнопки XVTR (создаются/удаляются по мере того,
|
||||
// как пользователь enabled/disabled слоты в Settings → Transverter).
|
||||
BtnXvtrBand: array[0..CFG_XVTR_COUNT-1] of TFlatButton;
|
||||
|
||||
PanelMode: TPanel;
|
||||
BtnMode: array[0..MODE_COUNT-1] of TFlatButton;
|
||||
@@ -497,6 +502,7 @@ type
|
||||
procedure WebOnAttn(Idx: Integer);
|
||||
procedure WebOnTun(On_: Boolean);
|
||||
procedure WebOnMic(Samples: PSingle; Count: Integer);
|
||||
procedure WebOnXvtrBand(Idx: Integer);
|
||||
// Synchronize-обёртки (выполняются в UI-потоке)
|
||||
procedure SyncWebFreq;
|
||||
procedure SyncWebMode;
|
||||
@@ -504,6 +510,7 @@ type
|
||||
procedure SyncWebAGC;
|
||||
procedure SyncWebAGCTop;
|
||||
procedure SyncWebBand;
|
||||
procedure SyncWebXvtrBand;
|
||||
procedure SyncWebSpan;
|
||||
procedure SyncWebVolume;
|
||||
procedure SyncWebWfAGC;
|
||||
@@ -562,6 +569,16 @@ type
|
||||
const SerBaud, SerDataBits, SerStopBits, SerParity: array of Integer;
|
||||
TcpEnabled: Boolean; TcpPort: Integer);
|
||||
procedure OnAlexSettingsChange(const A: TAlexSettings);
|
||||
procedure OnXvtrSettingsChange(const X: TXvtrSettings);
|
||||
procedure PushXvtrToWeb;
|
||||
// XVTR helpers
|
||||
function FindXvtrIdxForFreq(FreqHz: Double): Integer;
|
||||
function XvtrTranslate(VisibleHz: Double): Double;
|
||||
procedure ApplyXvtrToNetwork;
|
||||
procedure RebuildXvtrButtons;
|
||||
procedure BtnXvtrBandClick(Sender: TObject);
|
||||
procedure ActivateXvtrBand(Idx: Integer);
|
||||
procedure DeactivateXvtr;
|
||||
// -------------------------------------------------------------------------
|
||||
procedure BtnWfAGCClick(Sender: TObject);
|
||||
procedure BtnWfNFClick(Sender: TObject);
|
||||
@@ -865,6 +882,7 @@ begin
|
||||
Result.WfAGCEnabled := FWfAGCEnabled;
|
||||
Result.WfNFEnabled := FWfNFEnabled;
|
||||
Result.LastBand := FCurrentBand;
|
||||
Result.LastXvtr := FCurrentXvtr;
|
||||
Result.SampleRate := FSampleRate;
|
||||
// Display settings
|
||||
if FWDSPReady then
|
||||
@@ -918,6 +936,18 @@ end;
|
||||
procedure TMainForm.SaveCurrentBand;
|
||||
begin
|
||||
if not FDevConnected then Exit;
|
||||
// В XVTR-режиме НЕ трогаем HF band-cache: FBandCache[FCurrentBand]
|
||||
// относится к HF-диапазону, на котором пользователь был ДО активации
|
||||
// трансвертера, и FVfoA сейчас на XVTR-частоте (144.x, 432.x и т.д.).
|
||||
// Запись в FBandCache[FCurrentBand] стерла бы корректное HF-состояние.
|
||||
// Вместо этого сохраняем LastFreq в XVTR-настройках.
|
||||
if FCurrentXvtr >= 0 then
|
||||
begin
|
||||
if (FCurrentXvtr < CFG_XVTR_COUNT) then
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastFreq := FVfoA;
|
||||
FSettings.SaveXvtr(FDevMAC, FXvtrSettings);
|
||||
Exit;
|
||||
end;
|
||||
FBandCache[FCurrentBand] := MakeBandSettings;
|
||||
FSettings.SaveBand(FDevMAC, FCurrentBand, FBandCache[FCurrentBand]);
|
||||
end;
|
||||
@@ -997,6 +1027,10 @@ begin
|
||||
FSettings.SaveGlobal(FDevMAC, MakeGlobalSettings);
|
||||
if FDevConnected then
|
||||
FSettings.SaveTX(FDevMAC, FTXSettings);
|
||||
// Запомнить LastFreq XVTR для следующего запуска
|
||||
if (FCurrentXvtr >= 0) and (FCurrentXvtr < CFG_XVTR_COUNT) then
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastFreq := FVfoA;
|
||||
FSettings.SaveXvtr(FDevMAC, FXvtrSettings);
|
||||
FSettings.Save;
|
||||
end;
|
||||
end;
|
||||
@@ -1107,7 +1141,9 @@ begin
|
||||
FWebServer.OnAttn := WebOnAttn;
|
||||
FWebServer.OnTun := WebOnTun;
|
||||
FWebServer.OnWebMic := WebOnMic;
|
||||
FWebServer.OnXvtrBand := WebOnXvtrBand;
|
||||
FWebServer.Start;
|
||||
PushXvtrToWeb;
|
||||
FillChar(FCATLastGlobal, SizeOf(FCATLastGlobal), 0);
|
||||
FCATLastGlobal.CATTcpPort := 19090;
|
||||
for i := 0 to 3 do
|
||||
@@ -1175,9 +1211,11 @@ begin
|
||||
FNetwork.OnHPStatus := OnHPStatusCB;
|
||||
FNetwork.OnDDCIQ := OnDDCIQCB;
|
||||
FNetwork.OnMicPacket := OnMicPacketCB;
|
||||
// Дефолты TX и Alex (на случай если устройство ещё не выбрано).
|
||||
// Дефолты TX, Alex и XVTR (на случай если устройство ещё не выбрано).
|
||||
TSettingsManager.DefaultTX(FTXSettings);
|
||||
TSettingsManager.DefaultAlex(FAlexSettings);
|
||||
TSettingsManager.DefaultXvtr(FXvtrSettings);
|
||||
FCurrentXvtr := -1;
|
||||
|
||||
BuildUI;
|
||||
StyleSpanButton(BtnSpan48k, FSampleRate = 48000);
|
||||
@@ -1242,7 +1280,7 @@ begin
|
||||
FMeterTimer.Enabled := False;
|
||||
FSpectrumTimer.Enabled := False;
|
||||
if FNetwork.Running then
|
||||
FNetwork.SetRunAndFreq(False, FCenterFreq, FCenterFreq, 0);
|
||||
FNetwork.SetRunAndFreq(False, XvtrTranslate(FCenterFreq), XvtrTranslate(FCenterFreq), 0);
|
||||
FNetwork.Disconnect;
|
||||
FNetwork.Free;
|
||||
FAudioOut.Close;
|
||||
@@ -1280,8 +1318,8 @@ begin
|
||||
begin
|
||||
if FRunning then
|
||||
begin
|
||||
FNetwork.UpdateState(FCenterFreq, ActiveTXFreqHz, 0, False, True, True);
|
||||
FNetwork.SetRunAndFreq(False, FCenterFreq, FCenterFreq, 0);
|
||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), 0, False, True, True);
|
||||
FNetwork.SetRunAndFreq(False, XvtrTranslate(FCenterFreq), XvtrTranslate(FCenterFreq), 0);
|
||||
FRunning := False;
|
||||
FTransmitting := False;
|
||||
if FWDSPReady then FDSPEngine.SetTXRun(False);
|
||||
@@ -1529,10 +1567,12 @@ begin
|
||||
|
||||
LayoutTopVfoBlock;
|
||||
|
||||
// Band selector
|
||||
// Band selector. Высота резервирует 2 дополнительных ряда под XVTR-кнопки
|
||||
// (создаются динамически в RebuildXvtrButtons). В каждом ряду до 6 кнопок,
|
||||
// итого до 12 XVTR-кнопок (наш CFG_XVTR_COUNT = 8 умещается с запасом).
|
||||
PanelBands := TPanel.Create(Self);
|
||||
PanelBands.Parent := PanelLeft;
|
||||
PanelBands.SetBounds(0, Y, LEFT_W, 74);
|
||||
PanelBands.SetBounds(0, Y, LEFT_W, 74 + 54);
|
||||
PanelBands.BevelOuter := bvNone;
|
||||
MakeLbl(PanelBands, 'BAND', 4, 2);
|
||||
W := (LEFT_W - 6) div 6;
|
||||
@@ -1545,8 +1585,11 @@ begin
|
||||
B.Tag := i;
|
||||
BtnBand[i] := B;
|
||||
end;
|
||||
// XVTR кнопки создаются позже (в RebuildXvtrButtons), их Tag = -(idx+1)
|
||||
for i := 0 to CFG_XVTR_COUNT - 1 do
|
||||
BtnXvtrBand[i] := nil;
|
||||
|
||||
Inc(Y, 76);
|
||||
Inc(Y, 76 + 54);
|
||||
|
||||
// Mode selector
|
||||
PanelMode := TPanel.Create(Self);
|
||||
@@ -2669,7 +2712,7 @@ begin
|
||||
BtnStartStop.Caption := 'START';
|
||||
StyleButton(BtnStartStop, False);
|
||||
FRunning := False;
|
||||
FNetwork.SetRunAndFreq(False, FCenterFreq, FCenterFreq, 0);
|
||||
FNetwork.SetRunAndFreq(False, XvtrTranslate(FCenterFreq), XvtrTranslate(FCenterFreq), 0);
|
||||
StatusBar1.Panels[4].Text := 'ТРАНСИВЕР НЕДОСТУПЕН';
|
||||
BtnMOX.Enabled := False;
|
||||
Exit;
|
||||
@@ -2680,7 +2723,7 @@ begin
|
||||
BtnStartStop.Caption := 'START';
|
||||
StyleButton(BtnStartStop, False);
|
||||
FRunning := False;
|
||||
FNetwork.SetRunAndFreq(False, FCenterFreq, FCenterFreq, 0);
|
||||
FNetwork.SetRunAndFreq(False, XvtrTranslate(FCenterFreq), XvtrTranslate(FCenterFreq), 0);
|
||||
StatusBar1.Panels[4].Text := 'ПОТЕРЯ СВЯЗИ С ТРАНСИВЕРОМ';
|
||||
BtnMOX.Enabled := False;
|
||||
Exit;
|
||||
@@ -3321,8 +3364,8 @@ begin
|
||||
// --- STOP ---
|
||||
if FRunning then
|
||||
begin
|
||||
FNetwork.UpdateState(FCenterFreq, ActiveTXFreqHz, 0, False, True, True);
|
||||
FNetwork.SetRunAndFreq(False, FCenterFreq, FCenterFreq, 0);
|
||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), 0, False, True, True);
|
||||
FNetwork.SetRunAndFreq(False, XvtrTranslate(FCenterFreq), XvtrTranslate(FCenterFreq), 0);
|
||||
FRunning := False;
|
||||
FTransmitting := False;
|
||||
if FWDSPReady then FDSPEngine.SetTXRun(False);
|
||||
@@ -3337,6 +3380,10 @@ begin
|
||||
SaveCurrentBand;
|
||||
FSettings.SaveGlobal(FDevMAC, MakeGlobalSettings);
|
||||
FSettings.SaveAlex(FDevMAC, FAlexSettings);
|
||||
// XVTR LastFreq → актуальная видимая частота в момент остановки
|
||||
if (FCurrentXvtr >= 0) and (FCurrentXvtr < CFG_XVTR_COUNT) then
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastFreq := FVfoA;
|
||||
FSettings.SaveXvtr(FDevMAC, FXvtrSettings);
|
||||
end;
|
||||
FSettings.SaveStartupPreview(FVfoA, FVfoB, FSampleRate);
|
||||
FSettings.Save;
|
||||
@@ -3474,6 +3521,12 @@ begin
|
||||
// Alex-настройки per-device (антенны/маршрутизация)
|
||||
FSettings.LoadAlex(FDevMAC, FAlexSettings);
|
||||
FNetwork.SetAlexConfig(FAlexSettings);
|
||||
// XVTR-настройки per-device (трансвертеры)
|
||||
FSettings.LoadXvtr(FDevMAC, FXvtrSettings);
|
||||
FCurrentXvtr := -1;
|
||||
RebuildXvtrButtons;
|
||||
ApplyXvtrToNetwork;
|
||||
PushXvtrToWeb;
|
||||
FTXSpecRefLevel := FTXSettings.TXSpecRefLevel;
|
||||
FTXSpecRange := FTXSettings.TXSpecRange;
|
||||
if FTXSettings.TXSpecGridStep > 0 then
|
||||
@@ -3566,6 +3619,14 @@ begin
|
||||
end;
|
||||
RestoreBand(FCurrentBand);
|
||||
|
||||
// Восстанавливаем XVTR-режим, если он был активен при выходе.
|
||||
// FCurrentBand уже загружен (HF-диапазон, на который пользователь зашёл
|
||||
// до XVTR), его FBandCache не пострадает — ActivateXvtrBand только
|
||||
// выставит FVfoA на XVTR-частоту и FCurrentXvtr.
|
||||
if (G_Settings.LastXvtr >= 0) and (G_Settings.LastXvtr < CFG_XVTR_COUNT)
|
||||
and FXvtrSettings.Entries[G_Settings.LastXvtr].Enabled then
|
||||
ActivateXvtrBand(G_Settings.LastXvtr);
|
||||
|
||||
StatusBar1.Panels[0].Text := 'IP: ' + FNetwork.Device.IPAddress;
|
||||
StatusBar1.Panels[1].Text := 'Board: ' + BoardTypeName(FNetwork.Device.BoardType);
|
||||
|
||||
@@ -3609,8 +3670,8 @@ begin
|
||||
// Сначала отправляем Run=1 — эмулятор/железо создают ddc_specific_thread
|
||||
// (порт 1025) и rx_thread (порт 1035+) только после получения HP Run=1.
|
||||
// DDC Specific и DUC Specific отправляем ПОСЛЕ, иначе порты ещё не открыты.
|
||||
FNetwork.UpdateState(FCenterFreq, ActiveTXFreqHz, FDriveLevel, False, True, True);
|
||||
FNetwork.SetRunAndFreq(True, FCenterFreq, FCenterFreq, FDriveLevel);
|
||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), FDriveLevel, False, True, True);
|
||||
FNetwork.SetRunAndFreq(True, XvtrTranslate(FCenterFreq), XvtrTranslate(FCenterFreq), FDriveLevel);
|
||||
FRunning := True;
|
||||
FRXStartTime := GetTickCount64;
|
||||
FRXLastPktTime := 0;
|
||||
@@ -3720,7 +3781,7 @@ begin
|
||||
if FWDSPReady then FDSPEngine.SetShift(0.0);
|
||||
if FNetwork.Connected and FNetwork.Running then
|
||||
begin
|
||||
FNetwork.UpdateState(FCenterFreq, ActiveTXFreqHz, FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.SendFullHP;
|
||||
end;
|
||||
end;
|
||||
@@ -3732,7 +3793,7 @@ begin
|
||||
if FWDSPReady then FDSPEngine.SetShift(0.0);
|
||||
if FNetwork.Connected and FNetwork.Running then
|
||||
begin
|
||||
FNetwork.UpdateState(FCenterFreq, ActiveTXFreqHz, FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.SendFullHP;
|
||||
end;
|
||||
end;
|
||||
@@ -3782,7 +3843,7 @@ begin
|
||||
|
||||
if FNetwork.Connected and FNetwork.Running then
|
||||
begin
|
||||
FNetwork.UpdateState(FCenterFreq, ActiveTXFreqHz, FDriveLevel,
|
||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), FDriveLevel,
|
||||
FTransmitting, True, True);
|
||||
FNetwork.SendFullHP;
|
||||
end;
|
||||
@@ -3804,7 +3865,7 @@ begin
|
||||
|
||||
if FNetwork.Connected and FNetwork.Running then
|
||||
begin
|
||||
FNetwork.UpdateState(FCenterFreq, ActiveTXFreqHz, FDriveLevel,
|
||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), FDriveLevel,
|
||||
FTransmitting, True, True);
|
||||
FNetwork.SendFullHP;
|
||||
end;
|
||||
@@ -3830,7 +3891,7 @@ begin
|
||||
if FWDSPReady then FDSPEngine.SetShift(0.0);
|
||||
if FNetwork.Connected and FNetwork.Running then
|
||||
begin
|
||||
FNetwork.UpdateState(FCenterFreq, ActiveTXFreqHz, FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.SendFullHP;
|
||||
end;
|
||||
// Обновляем диапазон
|
||||
@@ -3914,6 +3975,15 @@ var
|
||||
Scrolled: Boolean;
|
||||
BandIdx: Integer;
|
||||
begin
|
||||
// Клэмп в пределах XVTR-band — не даём VFO уйти за FreqBegin/FreqEnd
|
||||
if (FCurrentXvtr >= 0) and (FCurrentXvtr < CFG_XVTR_COUNT) and
|
||||
FXvtrSettings.Entries[FCurrentXvtr].Enabled then
|
||||
begin
|
||||
if NewFreq < FXvtrSettings.Entries[FCurrentXvtr].FreqBegin then
|
||||
NewFreq := Round(FXvtrSettings.Entries[FCurrentXvtr].FreqBegin);
|
||||
if NewFreq > FXvtrSettings.Entries[FCurrentXvtr].FreqEnd then
|
||||
NewFreq := Round(FXvtrSettings.Entries[FCurrentXvtr].FreqEnd);
|
||||
end;
|
||||
FVfoA := NewFreq;
|
||||
Scrolled := False;
|
||||
|
||||
@@ -3962,19 +4032,24 @@ begin
|
||||
// Обновляем VFO дисплей
|
||||
FreqDispA.Frequency := Round(FVfoA);
|
||||
|
||||
// Обновляем кнопку диапазона если частота перешла в другой диапазон
|
||||
BandIdx := FreqToBandIdx(FVfoA);
|
||||
if (BandIdx >= 0) and (BandIdx <> FCurrentBand) then
|
||||
// Обновляем кнопку диапазона если частота перешла в другой диапазон.
|
||||
// В XVTR-режиме HF band-кнопки не подсвечиваем (мы клэмпим VFO внутри
|
||||
// XVTR-диапазона — FreqToBandIdx всегда вернёт -1 для VHF/UHF).
|
||||
if FCurrentXvtr < 0 then
|
||||
begin
|
||||
StyleButton(BtnBand[FCurrentBand], False);
|
||||
FCurrentBand := BandIdx;
|
||||
StyleButton(BtnBand[FCurrentBand], True);
|
||||
BandIdx := FreqToBandIdx(FVfoA);
|
||||
if (BandIdx >= 0) and (BandIdx <> FCurrentBand) then
|
||||
begin
|
||||
StyleButton(BtnBand[FCurrentBand], False);
|
||||
FCurrentBand := BandIdx;
|
||||
StyleButton(BtnBand[FCurrentBand], True);
|
||||
end;
|
||||
end;
|
||||
|
||||
// DDC: передаём FCenterFreq (при CTUN OFF = FVfoA, при CTUN ON = фиксирован)
|
||||
if FNetwork.Connected and FNetwork.Running then
|
||||
begin
|
||||
FNetwork.UpdateState(FCenterFreq, ActiveTXFreqHz, FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.SendFullHP;
|
||||
end;
|
||||
|
||||
@@ -4011,7 +4086,7 @@ begin
|
||||
FDSPEngine.SetShift(0.0);
|
||||
if FNetwork.Connected and FNetwork.Running then
|
||||
begin
|
||||
FNetwork.UpdateState(FCenterFreq, ActiveTXFreqHz, FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.SendFullHP;
|
||||
end;
|
||||
end
|
||||
@@ -4062,6 +4137,14 @@ end;
|
||||
procedure TMainForm.ApplyTUN(Active: Boolean);
|
||||
begin
|
||||
if Active = FTuning then Exit;
|
||||
// Safety: те же блокировки что в ApplyMOX. TUN — это TX через WDSP PostGen,
|
||||
// он тоже должен молчать на бэндах с DoNotTx или на RX-only XVTR.
|
||||
if Active and FDevConnected and (FCurrentXvtr < 0)
|
||||
and FAlexSettings.DoNotTx[EnsureRange(FCurrentBand, 0, 10)] then
|
||||
Exit;
|
||||
if Active and (FCurrentXvtr >= 0) and (FCurrentXvtr < CFG_XVTR_COUNT)
|
||||
and FXvtrSettings.Entries[FCurrentXvtr].RXOnly then
|
||||
Exit;
|
||||
if Active then
|
||||
begin
|
||||
// Включаем тон ДО запуска TX-аудио, чтобы первые сэмплы уже шли с тоном
|
||||
@@ -4088,7 +4171,7 @@ begin
|
||||
FDSPEngine.SetDriveLevel(TrkDrive.Position / 100.0);
|
||||
if FNetwork.Connected and FNetwork.Running then
|
||||
begin
|
||||
FNetwork.UpdateState(FCenterFreq, ActiveTXFreqHz, FDriveLevel,
|
||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), FDriveLevel,
|
||||
FTransmitting, True, True);
|
||||
FNetwork.SendFullHP;
|
||||
end;
|
||||
@@ -4131,7 +4214,7 @@ begin
|
||||
if FWDSPReady then FDSPEngine.SetShift(0.0);
|
||||
if FNetwork.Connected and FNetwork.Running then
|
||||
begin
|
||||
FNetwork.UpdateState(FCenterFreq, ActiveTXFreqHz, FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.SendFullHP;
|
||||
end;
|
||||
BandIdx := FreqToBandIdx(FVfoB);
|
||||
@@ -4171,7 +4254,7 @@ begin
|
||||
end;
|
||||
if FNetwork.Connected and FNetwork.Running then
|
||||
begin
|
||||
FNetwork.UpdateState(FCenterFreq, ActiveTXFreqHz, FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.SendFullHP;
|
||||
end;
|
||||
FSpectrumDirty := True;
|
||||
@@ -4189,7 +4272,7 @@ begin
|
||||
if FWDSPReady then FDSPEngine.SetShift(0.0);
|
||||
if FNetwork.Connected and FNetwork.Running then
|
||||
begin
|
||||
FNetwork.UpdateState(FCenterFreq, ActiveTXFreqHz, FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.SendFullHP;
|
||||
end;
|
||||
FSpectrumDirty := True;
|
||||
@@ -4328,19 +4411,23 @@ var
|
||||
begin
|
||||
NewBand := (Sender as TFlatButton).Tag;
|
||||
if (NewBand < 0) or (NewBand >= BAND_COUNT) then Exit;
|
||||
if NewBand = FCurrentBand then Exit; // уже на этом диапазоне
|
||||
// Если в XVTR-режиме — DeactivateXvtr вернёт HF-состояние (RestoreBand
|
||||
// на сохранённом FCurrentBand). Если NewBand совпадает с восстановленным
|
||||
// FCurrentBand, дальше делать ничего не нужно.
|
||||
if FCurrentXvtr >= 0 then
|
||||
begin
|
||||
DeactivateXvtr;
|
||||
if NewBand = FCurrentBand then Exit;
|
||||
end
|
||||
else if NewBand = FCurrentBand then
|
||||
Exit;
|
||||
|
||||
// Сохраняем настройки текущего диапазона перед сменой
|
||||
if FDevConnected then
|
||||
begin
|
||||
SaveCurrentBand;
|
||||
FSettings.Save;
|
||||
end;
|
||||
|
||||
// Переключаем диапазон
|
||||
FCurrentBand := NewBand;
|
||||
|
||||
// Восстанавливаем настройки нового диапазона
|
||||
RestoreBand(FCurrentBand);
|
||||
end;
|
||||
|
||||
@@ -4421,7 +4508,7 @@ begin
|
||||
if FWDSPReady then FDSPEngine.SetShift(0.0);
|
||||
if FNetwork.Connected and FNetwork.Running then
|
||||
begin
|
||||
FNetwork.UpdateState(FCenterFreq, ActiveTXFreqHz, FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.SendFullHP;
|
||||
end;
|
||||
|
||||
@@ -4453,7 +4540,7 @@ begin
|
||||
if FWDSPReady then FDSPEngine.SetShift(0.0);
|
||||
if FNetwork.Connected and FNetwork.Running then
|
||||
begin
|
||||
FNetwork.UpdateState(FCenterFreq, ActiveTXFreqHz, FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.SendFullHP;
|
||||
end;
|
||||
FSpecView.InvalidateRulerCache;
|
||||
@@ -4490,9 +4577,13 @@ var
|
||||
WasTransmitting: Boolean;
|
||||
begin
|
||||
// Safety: block TX on bands marked DoNotTx in Alex config
|
||||
if Active and FDevConnected
|
||||
if Active and FDevConnected and (FCurrentXvtr < 0)
|
||||
and FAlexSettings.DoNotTx[EnsureRange(FCurrentBand, 0, 10)] then
|
||||
Exit;
|
||||
// Safety: block TX on RX-only transverter
|
||||
if Active and (FCurrentXvtr >= 0) and (FCurrentXvtr < CFG_XVTR_COUNT)
|
||||
and FXvtrSettings.Entries[FCurrentXvtr].RXOnly then
|
||||
Exit;
|
||||
WasTransmitting := FTransmitting;
|
||||
FTransmitting := Active;
|
||||
FDUCPendingCount := 0;
|
||||
@@ -4517,7 +4608,7 @@ begin
|
||||
if FTransmitting and FNetwork.Connected and FNetwork.Running then
|
||||
begin
|
||||
FNetwork.ClearDUCIQQueue;
|
||||
FNetwork.UpdateState(FCenterFreq, ActiveTXFreqHz, FDriveLevel,
|
||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), FDriveLevel,
|
||||
True, True, True);
|
||||
FNetwork.SendFullHP;
|
||||
end;
|
||||
@@ -4563,7 +4654,7 @@ begin
|
||||
end;
|
||||
if (not FTransmitting) and FNetwork.Connected and FNetwork.Running then
|
||||
begin
|
||||
FNetwork.UpdateState(FCenterFreq, ActiveTXFreqHz, FDriveLevel,
|
||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), FDriveLevel,
|
||||
FTransmitting, True, True);
|
||||
FNetwork.ClearDUCIQQueue;
|
||||
FNetwork.SendFullHP;
|
||||
@@ -4828,7 +4919,7 @@ begin
|
||||
FCenterFreq := FVfoB;
|
||||
if FWDSPReady then FDSPEngine.SetShift(0.0);
|
||||
if FRunning then
|
||||
FNetwork.SetRunAndFreq(True, FCenterFreq, FCenterFreq, FDriveLevel);
|
||||
FNetwork.SetRunAndFreq(True, XvtrTranslate(FCenterFreq), XvtrTranslate(FCenterFreq), FDriveLevel);
|
||||
BandIdx := FreqToBandIdx(FVfoB);
|
||||
if (BandIdx >= 0) and (BandIdx <> FCurrentBand) then
|
||||
begin
|
||||
@@ -4967,12 +5058,40 @@ end;
|
||||
procedure TMainForm.SyncWebBand;
|
||||
begin
|
||||
if (FWebSyncInt < 0) or (FWebSyncInt >= BAND_COUNT) then Exit;
|
||||
if FWebSyncInt = FCurrentBand then Exit;
|
||||
// Выйти из XVTR при переходе на HF из web. DeactivateXvtr вернёт HF-состояние.
|
||||
if FCurrentXvtr >= 0 then
|
||||
begin
|
||||
DeactivateXvtr;
|
||||
if FWebSyncInt = FCurrentBand then Exit;
|
||||
end
|
||||
else if FWebSyncInt = FCurrentBand then
|
||||
Exit;
|
||||
if FDevConnected then begin SaveCurrentBand; FSettings.Save; end;
|
||||
FCurrentBand := FWebSyncInt;
|
||||
RestoreBand(FCurrentBand);
|
||||
end;
|
||||
|
||||
procedure TMainForm.WebOnXvtrBand(Idx: Integer);
|
||||
begin
|
||||
FWebSyncInt := Idx;
|
||||
FWebSyncM := SyncWebXvtrBand;
|
||||
TThread.Synchronize(nil, FWebSyncM);
|
||||
end;
|
||||
|
||||
procedure TMainForm.SyncWebXvtrBand;
|
||||
begin
|
||||
if FWebSyncInt < 0 then
|
||||
begin
|
||||
DeactivateXvtr;
|
||||
Exit;
|
||||
end;
|
||||
if (FWebSyncInt >= CFG_XVTR_COUNT) then Exit;
|
||||
if not FXvtrSettings.Entries[FWebSyncInt].Enabled then Exit;
|
||||
if FWebSyncInt = FCurrentXvtr then Exit;
|
||||
if FDevConnected then begin SaveCurrentBand; FSettings.Save; end;
|
||||
ActivateXvtrBand(FWebSyncInt);
|
||||
end;
|
||||
|
||||
procedure TMainForm.WebOnSpan(Hz: Integer);
|
||||
begin
|
||||
FWebSyncInt := Hz;
|
||||
@@ -5182,7 +5301,7 @@ begin
|
||||
if not FCTun then
|
||||
if FWDSPReady then FDSPEngine.SetShift(0.0);
|
||||
if FRunning then
|
||||
FNetwork.SetRunAndFreq(True, FCenterFreq, FCenterFreq, FDriveLevel);
|
||||
FNetwork.SetRunAndFreq(True, XvtrTranslate(FCenterFreq), XvtrTranslate(FCenterFreq), FDriveLevel);
|
||||
BandIdx := FreqToBandIdx(FVfoB);
|
||||
if (BandIdx >= 0) and (BandIdx <> FCurrentBand) then
|
||||
begin
|
||||
@@ -5233,7 +5352,7 @@ begin
|
||||
else FDSPEngine.SetShift(FVfoB - FCenterFreq);
|
||||
end;
|
||||
if FNetwork.Connected and FNetwork.Running then
|
||||
FNetwork.UpdateState(FCenterFreq, ActiveTXFreqHz, FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), FDriveLevel, FTransmitting, True, True);
|
||||
FSpecView.InvalidateRulerCache;
|
||||
FSpectrumDirty := True;
|
||||
end;
|
||||
@@ -5322,26 +5441,53 @@ begin
|
||||
FDSPEngine.SetDriveLevel(TrkDrive.Position / 100.0);
|
||||
if FNetwork.Connected and FNetwork.Running then
|
||||
begin
|
||||
FNetwork.UpdateState(FCenterFreq, ActiveTXFreqHz, FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.SendFullHP;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TMainForm.CalcDriveByte: Byte;
|
||||
var
|
||||
Cal: Double;
|
||||
Pos: Integer;
|
||||
Cal: Double;
|
||||
Pos: Integer;
|
||||
XvtrActive: Boolean;
|
||||
begin
|
||||
if (FCurrentBand >= 0) and (FCurrentBand < BAND_COUNT) and (FPABandCal[FCurrentBand] > 0.0) then
|
||||
Cal := FPABandCal[FCurrentBand]
|
||||
else
|
||||
Cal := 100.0;
|
||||
// В режиме TUN используем отдельный per-device уровень (см. TTXSettings.TUNLevel),
|
||||
// чтобы tune не зависел от Drive-слайдера. Per-band калибровка — общая для обоих.
|
||||
|
||||
XvtrActive := (FCurrentXvtr >= 0) and (FCurrentXvtr < CFG_XVTR_COUNT) and
|
||||
FXvtrSettings.Entries[FCurrentXvtr].Enabled;
|
||||
|
||||
// Pos — итоговый процент драйва 0..100 ДО per-band калибровки.
|
||||
//
|
||||
// Логика (как в Thetis):
|
||||
// • Регулярный TX:
|
||||
// HF → Pos = TrkDrive.Position
|
||||
// XVTR → Pos = TrkDrive.Position × (XVTR.TXPower / 100)
|
||||
// (TXPower работает как верхний предел драйва на трансверторе)
|
||||
// • TUN (кнопка):
|
||||
// HF → Pos = TUNLevel (TTXSettings.TUNLevel)
|
||||
// XVTR, UseXVTRTunePower=False → Pos = TUNLevel (поведение как HF)
|
||||
// XVTR, UseXVTRTunePower=True → Pos = XVTR.TXPower
|
||||
// (галка ЗАМЕНЯЕТ TUNLevel на XVTR power — Thetis-семантика)
|
||||
if FTuning then
|
||||
Pos := EnsureRange(FTXSettings.TUNLevel, 0, 100)
|
||||
begin
|
||||
if XvtrActive and FXvtrSettings.UseXVTRTunePower then
|
||||
Pos := EnsureRange(FXvtrSettings.Entries[FCurrentXvtr].TXPower, 0, 100)
|
||||
else
|
||||
Pos := EnsureRange(FTXSettings.TUNLevel, 0, 100);
|
||||
end
|
||||
else
|
||||
Pos := TrkDrive.Position;
|
||||
begin
|
||||
if XvtrActive then
|
||||
Pos := Round(TrkDrive.Position
|
||||
* FXvtrSettings.Entries[FCurrentXvtr].TXPower / 100.0)
|
||||
else
|
||||
Pos := TrkDrive.Position;
|
||||
end;
|
||||
|
||||
Result := Round(Pos / 100.0 * Cal / 100.0 * 255.0);
|
||||
end;
|
||||
|
||||
@@ -5392,7 +5538,7 @@ begin
|
||||
end;
|
||||
FDriveLevel := CalcDriveByte;
|
||||
if FNetwork.Connected and FNetwork.Running then
|
||||
FNetwork.UpdateState(FCenterFreq, ActiveTXFreqHz, FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), FDriveLevel, FTransmitting, True, True);
|
||||
end;
|
||||
|
||||
procedure TMainForm.OnTXSettingsChange(const T: TTXSettings);
|
||||
@@ -5434,7 +5580,7 @@ begin
|
||||
FDSPEngine.SetDriveLevel(FTXSettings.TUNLevel / 100.0);
|
||||
if FNetwork.Connected and FNetwork.Running then
|
||||
begin
|
||||
FNetwork.UpdateState(FCenterFreq, ActiveTXFreqHz, FDriveLevel,
|
||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), FDriveLevel,
|
||||
FTransmitting, True, True);
|
||||
FNetwork.SendFullHP;
|
||||
end;
|
||||
@@ -5460,6 +5606,251 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
// ===========================================================================
|
||||
// XVTR (Transverter) integration
|
||||
// ===========================================================================
|
||||
|
||||
// Ищет XVTR слот, в чьё [FreqBegin..FreqEnd] попадает данная видимая частота.
|
||||
// Возвращает индекс 0..CFG_XVTR_COUNT-1 или -1.
|
||||
function TMainForm.FindXvtrIdxForFreq(FreqHz: Double): Integer;
|
||||
var i: Integer;
|
||||
begin
|
||||
Result := -1;
|
||||
for i := 0 to CFG_XVTR_COUNT - 1 do
|
||||
with FXvtrSettings.Entries[i] do
|
||||
if Enabled and (FreqHz >= FreqBegin) and (FreqHz <= FreqEnd) then
|
||||
Exit(i);
|
||||
end;
|
||||
|
||||
// Транслирует видимую частоту в IF (то, что слышит/передаёт трансивер).
|
||||
// Если активный XVTR не задан — возвращает входную частоту без изменений.
|
||||
function TMainForm.XvtrTranslate(VisibleHz: Double): Double;
|
||||
begin
|
||||
Result := VisibleHz;
|
||||
if (FCurrentXvtr < 0) or (FCurrentXvtr >= CFG_XVTR_COUNT) then Exit;
|
||||
if not FXvtrSettings.Entries[FCurrentXvtr].Enabled then Exit;
|
||||
// f_IF = f_visible - LOOffset + LOError
|
||||
Result := VisibleHz
|
||||
- FXvtrSettings.Entries[FCurrentXvtr].LOOffset
|
||||
+ FXvtrSettings.Entries[FCurrentXvtr].LOError;
|
||||
end;
|
||||
|
||||
// Передаёт XVTR-режим в сетевой слой. Вызывается при смене XVTR или его
|
||||
// настроек. Управляет XVTR Enable bit, DDC IN routing, T/R relay suppression.
|
||||
procedure TMainForm.ApplyXvtrToNetwork;
|
||||
var
|
||||
En: Boolean;
|
||||
UseDDCIn: Boolean;
|
||||
DisablePA: Boolean;
|
||||
RxAnt: Byte;
|
||||
begin
|
||||
if (FCurrentXvtr >= 0) and (FCurrentXvtr < CFG_XVTR_COUNT) and
|
||||
FXvtrSettings.Entries[FCurrentXvtr].Enabled then
|
||||
begin
|
||||
En := True;
|
||||
// XVTRRF=True означает что трансвертер использует HF тракт — не нужно
|
||||
// переключаться на отдельный XVTR DDC IN на Alex. Default False →
|
||||
// подключаем XVTR-IF к выделенному пину XVTR DDC IN.
|
||||
UseDDCIn := not FXvtrSettings.Entries[FCurrentXvtr].XVTRRF;
|
||||
DisablePA := FXvtrSettings.Entries[FCurrentXvtr].DisablePA;
|
||||
RxAnt := FXvtrSettings.Entries[FCurrentXvtr].RXAntenna;
|
||||
end
|
||||
else
|
||||
begin
|
||||
En := False; UseDDCIn := False; DisablePA := False; RxAnt := 0;
|
||||
end;
|
||||
if FNetwork.Connected then
|
||||
FNetwork.SetXvtrMode(En, UseDDCIn, DisablePA, RxAnt);
|
||||
end;
|
||||
|
||||
// Перестраивает динамические XVTR-кнопки в PanelBands. Удаляет старые,
|
||||
// создаёт новые для enabled слотов в 3-м и 4-м ряду PanelBands.
|
||||
procedure TMainForm.RebuildXvtrButtons;
|
||||
const
|
||||
BTN_H_LOC = 24;
|
||||
var
|
||||
i, Pos: Integer;
|
||||
W: Integer;
|
||||
B: TFlatButton;
|
||||
Cap: string;
|
||||
begin
|
||||
// Уничтожаем все старые
|
||||
for i := 0 to CFG_XVTR_COUNT - 1 do
|
||||
if BtnXvtrBand[i] <> nil then
|
||||
begin
|
||||
BtnXvtrBand[i].Free;
|
||||
BtnXvtrBand[i] := nil;
|
||||
end;
|
||||
if PanelBands = nil then Exit;
|
||||
W := (PanelBands.Width - 6) div 6;
|
||||
Pos := 0; // позиция среди enabled слотов
|
||||
for i := 0 to CFG_XVTR_COUNT - 1 do
|
||||
if FXvtrSettings.Entries[i].Enabled then
|
||||
begin
|
||||
if Pos >= 12 then Break; // 2 ряда по 6 кнопок
|
||||
Cap := FXvtrSettings.Entries[i].ButtonText;
|
||||
if Cap = '' then Cap := 'X' + IntToStr(i + 1);
|
||||
B := TFlatButton.Create(Self);
|
||||
B.Parent := PanelBands;
|
||||
B.Caption := Cap;
|
||||
B.Left := 2 + (Pos mod 6) * W;
|
||||
B.Top := 16 + (2 + (Pos div 6)) * 27;
|
||||
B.Width := W - 2;
|
||||
B.Height := BTN_H_LOC;
|
||||
B.OnClick := BtnXvtrBandClick;
|
||||
B.Tag := -(i + 1); // отрицательное значение = XVTR индекс
|
||||
BtnXvtrBand[i] := B;
|
||||
StyleButton(B, i = FCurrentXvtr);
|
||||
Inc(Pos);
|
||||
end;
|
||||
end;
|
||||
|
||||
// Обработчик клика по XVTR-кнопке. Tag = -(idx+1).
|
||||
procedure TMainForm.BtnXvtrBandClick(Sender: TObject);
|
||||
var
|
||||
TagVal, Idx: Integer;
|
||||
begin
|
||||
TagVal := (Sender as TFlatButton).Tag;
|
||||
Idx := -TagVal - 1;
|
||||
if (Idx < 0) or (Idx >= CFG_XVTR_COUNT) then Exit;
|
||||
if not FXvtrSettings.Entries[Idx].Enabled then Exit;
|
||||
if FCurrentXvtr = Idx then Exit; // уже на этом XVTR
|
||||
// Сохраняем текущий band перед сменой (как BtnBandClick)
|
||||
if FDevConnected then
|
||||
begin
|
||||
SaveCurrentBand;
|
||||
FSettings.Save;
|
||||
end;
|
||||
ActivateXvtrBand(Idx);
|
||||
end;
|
||||
|
||||
// Активирует XVTR-band: устанавливает видимую частоту по LastFreq или
|
||||
// середине [FreqBegin..FreqEnd], применяет network XVTR-режим.
|
||||
procedure TMainForm.ActivateXvtrBand(Idx: Integer);
|
||||
var
|
||||
Vis: Double;
|
||||
i: Integer;
|
||||
begin
|
||||
if (Idx < 0) or (Idx >= CFG_XVTR_COUNT) then Exit;
|
||||
if not FXvtrSettings.Entries[Idx].Enabled then Exit;
|
||||
FCurrentXvtr := Idx;
|
||||
// Выбор начальной частоты: LastFreq если в диапазоне, иначе середина
|
||||
Vis := FXvtrSettings.Entries[Idx].LastFreq;
|
||||
if (Vis < FXvtrSettings.Entries[Idx].FreqBegin) or
|
||||
(Vis > FXvtrSettings.Entries[Idx].FreqEnd) then
|
||||
Vis := (FXvtrSettings.Entries[Idx].FreqBegin +
|
||||
FXvtrSettings.Entries[Idx].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;
|
||||
// VFO на видимую частоту; FCenterFreq тоже visible (как и для HF — DDC переход
|
||||
// в IF происходит только в момент UpdateState/SetRunAndFreq через XvtrTranslate).
|
||||
FVfoA := Vis;
|
||||
FCenterFreq := Vis;
|
||||
FreqDispA.Frequency := Round(FVfoA);
|
||||
// Сбросить CTUN — не имеет смысла в начальном состоянии XVTR-band
|
||||
if FCTun then
|
||||
begin
|
||||
FCTun := False;
|
||||
StyleButton(BtnCTun, False);
|
||||
end;
|
||||
if FWDSPReady then FDSPEngine.SetShift(0.0);
|
||||
// Применяем драйв (если есть кастомный TX power для этого XVTR)
|
||||
// Сделано на стороне ActiveTXFreqHz / TX path — здесь только обновляем дисплей.
|
||||
// Отправляем в сеть с трансляцией
|
||||
if FNetwork.Connected and FNetwork.Running then
|
||||
begin
|
||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz),
|
||||
FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.SendFullHP;
|
||||
end;
|
||||
SyncSpecViewFreq;
|
||||
FSpecView.DrawSpectrum;
|
||||
PbSpectrum.Invalidate;
|
||||
FSpecView.DrawWaterfall;
|
||||
PbWaterfall.Invalidate;
|
||||
if PbRuler <> nil then PbRuler.Invalidate;
|
||||
PushXvtrToWeb;
|
||||
end;
|
||||
|
||||
// Деактивирует XVTR — возвращает к HF-режиму.
|
||||
// FCurrentBand был сохранён неизменным во время XVTR (см. ActivateXvtrBand,
|
||||
// ApplyVfoA, SaveCurrentBand) — он указывает на HF-диапазон, с которого
|
||||
// пользователь зашёл в трансвертер. RestoreBand вернёт VFO/Mode/Filter/AGC
|
||||
// /CTUN/Span этого диапазона и обновит подсветку HF band-кнопки.
|
||||
procedure TMainForm.DeactivateXvtr;
|
||||
var i: Integer;
|
||||
begin
|
||||
if FCurrentXvtr < 0 then Exit;
|
||||
// Запоминаем LastFreq для bandstack
|
||||
if FCurrentXvtr < CFG_XVTR_COUNT then
|
||||
begin
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastFreq := FVfoA;
|
||||
if FDevConnected then
|
||||
begin
|
||||
FSettings.SaveXvtr(FDevMAC, FXvtrSettings);
|
||||
FSettings.Save;
|
||||
end;
|
||||
end;
|
||||
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-кнопки и сетевое состояние.
|
||||
if (FCurrentBand >= 0) and (FCurrentBand < CFG_BAND_COUNT) then
|
||||
RestoreBand(FCurrentBand);
|
||||
PushXvtrToWeb;
|
||||
end;
|
||||
|
||||
procedure TMainForm.OnXvtrSettingsChange(const X: TXvtrSettings);
|
||||
begin
|
||||
FXvtrSettings := X;
|
||||
RebuildXvtrButtons;
|
||||
// Если активный XVTR стал disabled — выйти из XVTR режима
|
||||
if (FCurrentXvtr >= 0) and
|
||||
((FCurrentXvtr >= CFG_XVTR_COUNT) or
|
||||
(not FXvtrSettings.Entries[FCurrentXvtr].Enabled)) then
|
||||
DeactivateXvtr;
|
||||
// Перепрошить XVTR в сеть (если параметры текущего изменились)
|
||||
ApplyXvtrToNetwork;
|
||||
PushXvtrToWeb;
|
||||
if FDevConnected then
|
||||
begin
|
||||
FSettings.SaveXvtr(FDevMAC, FXvtrSettings);
|
||||
FSettings.Save;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.PushXvtrToWeb;
|
||||
var
|
||||
Arr: TWebXvtrArray;
|
||||
i, Cnt: Integer;
|
||||
begin
|
||||
if FWebServer = nil then Exit;
|
||||
Cnt := 0;
|
||||
for i := 0 to CFG_XVTR_COUNT - 1 do
|
||||
if FXvtrSettings.Entries[i].Enabled then Inc(Cnt);
|
||||
SetLength(Arr, Cnt);
|
||||
Cnt := 0;
|
||||
for i := 0 to CFG_XVTR_COUNT - 1 do
|
||||
if FXvtrSettings.Entries[i].Enabled then
|
||||
begin
|
||||
Arr[Cnt].Idx := i;
|
||||
Arr[Cnt].Name := FXvtrSettings.Entries[i].ButtonText;
|
||||
Inc(Cnt);
|
||||
end;
|
||||
FWebServer.SetXvtrBands(Arr, FCurrentXvtr);
|
||||
end;
|
||||
|
||||
procedure TMainForm.TrkVolumeChange(Sender: TObject);
|
||||
begin
|
||||
FVolume := TrkVolume.Position;
|
||||
@@ -5745,11 +6136,13 @@ begin
|
||||
SF.OnThemeChange := SetLightTheme;
|
||||
SF.OnTXChange := OnTXSettingsChange;
|
||||
SF.OnAlexChange := OnAlexSettingsChange;
|
||||
SF.OnXvtrChange := OnXvtrSettingsChange;
|
||||
end;
|
||||
SF := TSettingsForm(FSettingsForm);
|
||||
SF.LoadTXSettings(FTXSettings);
|
||||
SF.LoadAlexSettings(FAlexSettings,
|
||||
IfThen(FNetwork.Connected, FNetwork.Device.BoardType, FPendingBoardType));
|
||||
SF.LoadXvtrSettings(FXvtrSettings);
|
||||
SF.LoadPASettings(FPAMaxPower, FPABandCal);
|
||||
SF.LoadCATSettings(
|
||||
FCATLastGlobal.CATSerialEnabled,
|
||||
@@ -5996,7 +6389,7 @@ begin
|
||||
FCenterFreq := FVfoB;
|
||||
if FWDSPReady then FDSPEngine.SetShift(0.0);
|
||||
if FRunning then
|
||||
FNetwork.SetRunAndFreq(True, FCenterFreq, FCenterFreq, FDriveLevel);
|
||||
FNetwork.SetRunAndFreq(True, XvtrTranslate(FCenterFreq), XvtrTranslate(FCenterFreq), FDriveLevel);
|
||||
BandIdx := FreqToBandIdx(FVfoB);
|
||||
if (BandIdx >= 0) and (BandIdx <> FCurrentBand) then
|
||||
begin
|
||||
|
||||
Reference in New Issue
Block a user