mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
Add channel memory: CH button, dropdown, editor form, smart CTCSS/RPT auto-clear
- New ChannelStore.pas: TChannel record + JSON persistence (channels.json) - New ChannelsForm.pas: full channel editor (list + fields, pre-fills from current radio state) - CH button in RX block: left-click opens dropdown, right-click opens editor - Active channel: button highlights with channel name, deactivates on VFO move - ApplyChannel: auto-switches XVTR/HF band based on channel frequency; saves old band state before switching to prevent cache corruption - SaveCurrentBand: skip save when VFO > 61 MHz (prevents HF cache corruption from VHF channel application without XVTR) - DeactivateXvtr: save full XVTR state (was only saving LastFreq) - CTCSS/RPT from channel marked as auto: cleared automatically when tuning away from channel frequency; survives band switches via FXvtrSettings auto-flags - TXvtrEntry: add LastCTCSSAutoActive, LastFMRptAutoActive fields Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+302
-17
@@ -38,7 +38,8 @@ uses
|
||||
PlatformUtils,
|
||||
WinFirewall,
|
||||
BoardUtils, WisdomBuilder, UISync,
|
||||
FlatEdit, FMRepeater;
|
||||
FlatEdit, FMRepeater,
|
||||
ChannelStore, ChannelsForm;
|
||||
|
||||
const
|
||||
CLR_BG = TColor($00101010);
|
||||
@@ -257,7 +258,8 @@ type
|
||||
FFMStepIdx: Integer;
|
||||
FFMRptDir: Integer; // RPT_NONE / RPT_MINUS / RPT_PLUS
|
||||
FFMRptOffsetHz: Double;
|
||||
FFMRptAutoActive: Boolean; // True = текущий minus включён автоматически
|
||||
FFMRptAutoActive: Boolean; // True = RPT включён автоматически (авто или из канала)
|
||||
FFMCTCSSAutoActive: Boolean; // True = CTCSS включён из канала (не вручную)
|
||||
FWfManualHigh: Double;
|
||||
FWfManualLow: Double;
|
||||
FWfAGCOffset: Double;
|
||||
@@ -403,6 +405,11 @@ type
|
||||
BtnTUN: TFlatButton;
|
||||
|
||||
PanelRXBlock: TPanel;
|
||||
BtnChannels: TFlatButton;
|
||||
FChannelsDropDown: TFlatDropDown;
|
||||
FChannelStore: TChannelStore;
|
||||
FChannelsForm: TObject; // TChannelsForm (cast при использовании)
|
||||
FActiveChannelIdx: Integer; // -1 = нет активного канала
|
||||
|
||||
// ---- Right panel ----
|
||||
PanelRight: TPanel;
|
||||
@@ -517,6 +524,14 @@ type
|
||||
procedure BtnFMStepSelClick(Sender: TObject);
|
||||
procedure OnCTCSSDropDownSelect(Sender: TObject; Idx: Integer);
|
||||
procedure OnStepDropDownSelect(Sender: TObject; Idx: Integer);
|
||||
procedure BtnChannelsClick(Sender: TObject);
|
||||
procedure BtnChannelsMouseDown(Sender: TObject; Button: TMouseButton;
|
||||
Shift: TShiftState; X, Y: Integer);
|
||||
procedure OnChannelsDropDownSelect(Sender: TObject; Idx: Integer);
|
||||
procedure RefreshChannelsDropDown;
|
||||
procedure OnChannelStoreChanged(Sender: TObject);
|
||||
procedure ApplyChannel(const Ch: TChannel);
|
||||
procedure CheckChannelActive;
|
||||
procedure PbSpectrumMouseDown(Sender: TObject; Button: TMouseButton;
|
||||
Shift: TShiftState; X, Y: Integer);
|
||||
procedure PbSpectrumMouseMove(Sender: TObject; Shift: TShiftState;
|
||||
@@ -974,15 +989,20 @@ begin
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastCTCSSToneIdx := FFMCTCSSToneIdx;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastFMStepOn := FFMStepOn;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastFMStepIdx := FFMStepIdx;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastFMRptDir := FFMRptDir;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastFMRptOffsetHz := FFMRptOffsetHz;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastCTun := FCTun;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastAGCMode := FAGCMode;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastAGCTop := FAGCTop;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastFMRptDir := FFMRptDir;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastFMRptOffsetHz := FFMRptOffsetHz;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastCTun := FCTun;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastAGCMode := FAGCMode;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastAGCTop := FAGCTop;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastCTCSSAutoActive := FFMCTCSSAutoActive;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastFMRptAutoActive := FFMRptAutoActive;
|
||||
end;
|
||||
FSettings.SaveXvtr(FDevMAC, FXvtrSettings);
|
||||
Exit;
|
||||
end;
|
||||
// Не сохраняем, если VFO ушёл в VHF/UHF область (например, после применения
|
||||
// канала на 2м без XVTR) — иначе HF-кэш диапазона будет перезаписан VHF-частотой.
|
||||
if FVfoA > 61000000 then Exit;
|
||||
FBandCache[FCurrentBand] := MakeBandSettings;
|
||||
FSettings.SaveBand(FDevMAC, FCurrentBand, FBandCache[FCurrentBand]);
|
||||
end;
|
||||
@@ -1135,9 +1155,10 @@ begin
|
||||
FFMSQLevel := 30;
|
||||
FFMStepOn := True;
|
||||
FFMStepIdx := FM_STEP_DEF;
|
||||
FFMRptDir := RPT_NONE;
|
||||
FFMRptOffsetHz := RPT_DEFAULT_2M;
|
||||
FFMRptAutoActive := False;
|
||||
FFMRptDir := RPT_NONE;
|
||||
FFMRptOffsetHz := RPT_DEFAULT_2M;
|
||||
FFMRptAutoActive := False;
|
||||
FFMCTCSSAutoActive := False;
|
||||
FSpectrumBufCount := 1024;
|
||||
FWaterfallBufCount := 1024;
|
||||
FWaterfallFrameInterval := 2;
|
||||
@@ -1152,6 +1173,8 @@ begin
|
||||
FTXSpecRange := 80.0;
|
||||
FTXSpecGridStep := 10.0;
|
||||
FSettingsForm := nil;
|
||||
FChannelsForm := nil;
|
||||
FActiveChannelIdx := -1;
|
||||
FillChar(FDevMAC, SizeOf(FDevMAC), 0);
|
||||
|
||||
// Инициализируем кэш диапазонов умолчаниями
|
||||
@@ -1162,6 +1185,10 @@ begin
|
||||
// Загружаем JSON настройки
|
||||
FSettings := TSettingsManager.Create;
|
||||
FSettings.Load;
|
||||
|
||||
// Загружаем список каналов
|
||||
FChannelStore := TChannelStore.Create(CHANNELS_FILE);
|
||||
FChannelStore.Load;
|
||||
if FSettings.LoadStartupPreview(StartupVfoA, StartupVfoB, StartupRate) then
|
||||
begin
|
||||
FVfoA := StartupVfoA;
|
||||
@@ -1411,6 +1438,7 @@ begin
|
||||
FSettings.SaveStartupPreview(FVfoA, FVfoB, FSampleRate);
|
||||
FSettings.Save;
|
||||
FSettings.Free;
|
||||
FreeAndNil(FChannelStore);
|
||||
FWebServer.Stop;
|
||||
FWebServer.Free;
|
||||
if Assigned(FCATTcp) then begin FCATTcp.Stop; FreeAndNil(FCATTcp); end;
|
||||
@@ -1719,6 +1747,17 @@ begin
|
||||
BtnCTun.Tag := 0;
|
||||
StyleButton(BtnCTun, FCTun);
|
||||
|
||||
BtnChannels := MakeBtn(PanelRXBlock, 'Channel',
|
||||
LeftPanelButtonLeft(LEFT_W, 3, 1), 16,
|
||||
LeftPanelButtonWidth(LEFT_W, 3, 1),
|
||||
BTN_H, BtnChannelsClick);
|
||||
BtnChannels.OnMouseDown := BtnChannelsMouseDown;
|
||||
StyleButton(BtnChannels, False);
|
||||
|
||||
FChannelsDropDown := TFlatDropDown.Create(BtnChannels, PanelLeft, 1, BTN_SM);
|
||||
FChannelsDropDown.OnSelect := OnChannelsDropDownSelect;
|
||||
RefreshChannelsDropDown;
|
||||
|
||||
MakeLbl(PanelRXBlock, 'VOL', 4, 50);
|
||||
TrkVolume := TFlatSlider.Create(Self);
|
||||
TrkVolume.Parent := PanelRXBlock; TrkVolume.Left := 34; TrkVolume.Top := 46;
|
||||
@@ -2599,6 +2638,8 @@ begin
|
||||
if BtnFMRptPlus <> nil then StyleButton(BtnFMRptPlus, BtnFMRptPlus.Active);
|
||||
if FCTCSSDropDown <> nil then FCTCSSDropDown.ApplyStyle(StyleButton, T.Panel);
|
||||
if FStepDropDown <> nil then FStepDropDown.ApplyStyle(StyleButton, T.Panel);
|
||||
if BtnChannels <> nil then StyleButton(BtnChannels, False);
|
||||
if FChannelsDropDown <> nil then FChannelsDropDown.ApplyStyle(StyleButton, T.Panel);
|
||||
StyleButton(BtnNR, BtnNR.Active);
|
||||
StyleButton(BtnNB, BtnNB.Active);
|
||||
StyleButton(BtnSNB, BtnSNB.Active);
|
||||
@@ -4593,6 +4634,26 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
// Если нет активного канала, но CTCSS/RPT были установлены каналом (авто-флаги),
|
||||
// сбрасываем их при первом же изменении частоты
|
||||
if FActiveChannelIdx < 0 then
|
||||
begin
|
||||
if FFMCTCSSAutoActive then
|
||||
begin
|
||||
FFMCTCSSAutoActive := False;
|
||||
FFMCTCSSOn := False;
|
||||
if BtnFMCTCSS <> nil then StyleButton(BtnFMCTCSS, False);
|
||||
if FWDSPReady then FDSPEngine.SetTXCTCSS(False, CTCSS_TONES[FFMCTCSSToneIdx]);
|
||||
end;
|
||||
if FFMRptAutoActive then
|
||||
begin
|
||||
FFMRptDir := RPT_NONE;
|
||||
FFMRptAutoActive := False;
|
||||
if BtnFMRptMinus <> nil then StyleButton(BtnFMRptMinus, False);
|
||||
if BtnFMRptPlus <> nil then StyleButton(BtnFMRptPlus, False);
|
||||
end;
|
||||
end;
|
||||
|
||||
// Auto-enable repeater minus for 2 m repeater input segment
|
||||
if FMode = MODE_FM then UpdateRptAutoState;
|
||||
|
||||
@@ -4613,6 +4674,8 @@ begin
|
||||
FWaterfallDirty := True;
|
||||
PbWaterfall.Invalidate;
|
||||
end;
|
||||
|
||||
CheckChannelActive;
|
||||
end;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -5206,6 +5269,7 @@ procedure TMainForm.CloseCTCSSPopup;
|
||||
begin
|
||||
if FCTCSSDropDown <> nil then FCTCSSDropDown.ClosePopup;
|
||||
CloseFMStepPopup;
|
||||
if FChannelsDropDown <> nil then FChannelsDropDown.ClosePopup;
|
||||
end;
|
||||
|
||||
procedure TMainForm.BtnFMRptMinusClick(Sender: TObject);
|
||||
@@ -5299,7 +5363,8 @@ end;
|
||||
|
||||
procedure TMainForm.CloseFMStepPopup;
|
||||
begin
|
||||
if FStepDropDown <> nil then FStepDropDown.ClosePopup;
|
||||
if FStepDropDown <> nil then FStepDropDown.ClosePopup;
|
||||
if FChannelsDropDown <> nil then FChannelsDropDown.ClosePopup;
|
||||
end;
|
||||
|
||||
procedure TMainForm.SetFMStep(Idx: Integer);
|
||||
@@ -5331,6 +5396,208 @@ begin
|
||||
SaveCurrentBand;
|
||||
end;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Channels dropdown / store
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
procedure TMainForm.RefreshChannelsDropDown;
|
||||
var
|
||||
names: array of string;
|
||||
i: Integer;
|
||||
begin
|
||||
if (FChannelStore = nil) or (FChannelsDropDown = nil) then Exit;
|
||||
SetLength(names, FChannelStore.Count);
|
||||
for i := 0 to FChannelStore.Count - 1 do
|
||||
names[i] := FChannelStore.GetChannel(i).Name;
|
||||
FChannelsDropDown.SetItems(names);
|
||||
if (FActiveChannelIdx >= 0) and (FActiveChannelIdx < FChannelStore.Count) then
|
||||
FChannelsDropDown.SetItemIndex(FActiveChannelIdx)
|
||||
else if BtnChannels <> nil then
|
||||
BtnChannels.Caption := 'Channel';
|
||||
end;
|
||||
|
||||
procedure TMainForm.OnChannelStoreChanged(Sender: TObject);
|
||||
begin
|
||||
RefreshChannelsDropDown;
|
||||
end;
|
||||
|
||||
procedure TMainForm.BtnChannelsClick(Sender: TObject);
|
||||
begin
|
||||
if FChannelStore.Count = 0 then Exit;
|
||||
FCTCSSDropDown.ClosePopup;
|
||||
FStepDropDown.ClosePopup;
|
||||
FChannelsDropDown.Toggle;
|
||||
end;
|
||||
|
||||
procedure TMainForm.BtnChannelsMouseDown(Sender: TObject; Button: TMouseButton;
|
||||
Shift: TShiftState; X, Y: Integer);
|
||||
var
|
||||
Def: TChannel;
|
||||
begin
|
||||
if Button <> mbRight then Exit;
|
||||
FChannelsDropDown.ClosePopup;
|
||||
if FChannelsForm = nil then
|
||||
FChannelsForm := TChannelsForm.Create(Self, FChannelStore, OnChannelStoreChanged);
|
||||
// Передаём текущее состояние радио как значения по умолчанию для нового канала
|
||||
TChannelStore.DefaultChannel(Def);
|
||||
Def.RXFreq := FVfoA;
|
||||
Def.TXFreq := ActiveTXFreqHz;
|
||||
Def.Mode := FMode;
|
||||
Def.RptDir := FFMRptDir;
|
||||
Def.RptOffsetHz := FFMRptOffsetHz;
|
||||
Def.CTCSSOn := FFMCTCSSOn;
|
||||
Def.CTCSSToneIdx := FFMCTCSSToneIdx;
|
||||
Def.Power := 100;
|
||||
Def.Name := '';
|
||||
TChannelsForm(FChannelsForm).SetCurrentDefaults(Def);
|
||||
TChannelsForm(FChannelsForm).ApplyTheme(DarkTheme);
|
||||
TChannelsForm(FChannelsForm).Show;
|
||||
end;
|
||||
|
||||
procedure TMainForm.OnChannelsDropDownSelect(Sender: TObject; Idx: Integer);
|
||||
var Ch: TChannel;
|
||||
begin
|
||||
if (FChannelStore = nil) or (Idx < 0) or (Idx >= FChannelStore.Count) then Exit;
|
||||
Ch := FChannelStore.GetChannel(Idx);
|
||||
FActiveChannelIdx := Idx;
|
||||
StyleButton(BtnChannels, True);
|
||||
BtnChannels.Caption := Ch.Name;
|
||||
BtnChannels.Repaint;
|
||||
ApplyChannel(Ch);
|
||||
end;
|
||||
|
||||
procedure TMainForm.ApplyChannel(const Ch: TChannel);
|
||||
var
|
||||
i, NewBand, XvtrIdx: Integer;
|
||||
begin
|
||||
// Сохраняем текущее состояние до любых изменений
|
||||
SaveCurrentBand;
|
||||
|
||||
// Ищем подходящий XVTR-слот по частоте канала
|
||||
XvtrIdx := -1;
|
||||
for i := 0 to CFG_XVTR_COUNT - 1 do
|
||||
if FXvtrSettings.Entries[i].Enabled and
|
||||
(Ch.RXFreq >= FXvtrSettings.Entries[i].FreqBegin) and
|
||||
(Ch.RXFreq <= FXvtrSettings.Entries[i].FreqEnd) then
|
||||
begin
|
||||
XvtrIdx := i;
|
||||
Break;
|
||||
end;
|
||||
|
||||
NewBand := -1;
|
||||
|
||||
if XvtrIdx >= 0 then
|
||||
begin
|
||||
// Канал на трансвертерном диапазоне — активируем XVTR если не активен
|
||||
if FCurrentXvtr <> XvtrIdx then
|
||||
ActivateXvtrBand(XvtrIdx);
|
||||
end
|
||||
else
|
||||
begin
|
||||
// Канал на HF (или неизвестная частота)
|
||||
// Если были на XVTR — выходим из него, иначе ApplyVfoA заклэмпит частоту
|
||||
if FCurrentXvtr >= 0 then
|
||||
DeactivateXvtr;
|
||||
NewBand := FreqToBandIdx(Ch.RXFreq);
|
||||
if (NewBand >= 0) and (NewBand <> FCurrentBand) then
|
||||
begin
|
||||
StyleButton(BtnBand[FCurrentBand], False);
|
||||
FCurrentBand := NewBand;
|
||||
StyleButton(BtnBand[FCurrentBand], True);
|
||||
FDriveLevel := CalcDriveByte;
|
||||
end;
|
||||
end;
|
||||
|
||||
// Режим (после ActivateXvtrBand/DeactivateXvtr FMode обновился — сравниваем снова)
|
||||
if FMode <> Ch.Mode then
|
||||
begin
|
||||
FMode := Ch.Mode;
|
||||
for i := 0 to MODE_COUNT - 1 do StyleButton(BtnMode[i], i = FMode);
|
||||
if FWDSPReady then
|
||||
begin
|
||||
FDSPEngine.SetMode(FMode);
|
||||
if FTuning then FDSPEngine.SetTXTone(True, FTXSettings.TUNFreq, 1.0);
|
||||
end;
|
||||
UpdateFilterButtons;
|
||||
ApplyModeFilter;
|
||||
SyncSpecViewFreq;
|
||||
end;
|
||||
|
||||
// FM-параметры
|
||||
if FMode = MODE_FM then
|
||||
begin
|
||||
FFMCTCSSOn := Ch.CTCSSOn;
|
||||
FFMCTCSSAutoActive := Ch.CTCSSOn; // CTCSS из канала — авто, сбросится при уходе с частоты
|
||||
SetFMCTCSSTone(Ch.CTCSSToneIdx);
|
||||
if BtnFMCTCSS <> nil then
|
||||
begin
|
||||
StyleButton(BtnFMCTCSS, FFMCTCSSOn);
|
||||
BtnFMCTCSS.Repaint;
|
||||
end;
|
||||
if FWDSPReady then
|
||||
FDSPEngine.SetTXCTCSS(FFMCTCSSOn, CTCSS_TONES[FFMCTCSSToneIdx]);
|
||||
FFMRptDir := Ch.RptDir;
|
||||
FFMRptOffsetHz := Ch.RptOffsetHz;
|
||||
FFMRptAutoActive := Ch.RptDir <> RPT_NONE; // RPT из канала — авто, сбросится при уходе
|
||||
if BtnFMRptMinus <> nil then StyleButton(BtnFMRptMinus, FFMRptDir = RPT_MINUS);
|
||||
if BtnFMRptPlus <> nil then StyleButton(BtnFMRptPlus, FFMRptDir = RPT_PLUS);
|
||||
if EdFMRptOffset <> nil then EdFMRptOffset.Text := RptFormatOffset(FFMRptOffsetHz);
|
||||
end;
|
||||
|
||||
// Частота VFO A
|
||||
ApplyVfoA(Round(Ch.RXFreq));
|
||||
|
||||
// Сохраняем состояние
|
||||
if XvtrIdx >= 0 then
|
||||
SaveCurrentBand // сохраняем в XVTR-слот (CTCSS/RPT/Mode из канала)
|
||||
else if NewBand >= 0 then
|
||||
SaveCurrentBand; // сохраняем в HF band-кэш
|
||||
end;
|
||||
|
||||
procedure TMainForm.CheckChannelActive;
|
||||
var Ch: TChannel;
|
||||
begin
|
||||
if FActiveChannelIdx < 0 then Exit;
|
||||
if (FChannelStore = nil) or (FActiveChannelIdx >= FChannelStore.Count) then
|
||||
begin
|
||||
FActiveChannelIdx := -1;
|
||||
Exit;
|
||||
end;
|
||||
Ch := FChannelStore.GetChannel(FActiveChannelIdx);
|
||||
if Round(FVfoA) <> Round(Ch.RXFreq) then
|
||||
begin
|
||||
FActiveChannelIdx := -1;
|
||||
StyleButton(BtnChannels, False);
|
||||
BtnChannels.Caption := 'Channel';
|
||||
BtnChannels.Repaint;
|
||||
|
||||
// Сбрасываем CTCSS если он был включён каналом (не вручную)
|
||||
if FFMCTCSSAutoActive then
|
||||
begin
|
||||
FFMCTCSSAutoActive := False;
|
||||
FFMCTCSSOn := False;
|
||||
if BtnFMCTCSS <> nil then
|
||||
begin
|
||||
StyleButton(BtnFMCTCSS, False);
|
||||
BtnFMCTCSS.Repaint;
|
||||
end;
|
||||
if FWDSPReady then
|
||||
FDSPEngine.SetTXCTCSS(False, CTCSS_TONES[FFMCTCSSToneIdx]);
|
||||
end;
|
||||
|
||||
// Сбрасываем RPT если он был включён каналом (не вручную), затем
|
||||
// даём UpdateRptAutoState переоценить авто-MINUS для текущей частоты
|
||||
if FFMRptAutoActive then
|
||||
begin
|
||||
FFMRptDir := RPT_NONE;
|
||||
FFMRptAutoActive := False;
|
||||
if BtnFMRptMinus <> nil then StyleButton(BtnFMRptMinus, False);
|
||||
if BtnFMRptPlus <> nil then StyleButton(BtnFMRptPlus, False);
|
||||
UpdateRptAutoState;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.SetFMCTCSSTone(Idx: Integer);
|
||||
begin
|
||||
FFMCTCSSToneIdx := Idx;
|
||||
@@ -5341,7 +5608,8 @@ end;
|
||||
|
||||
procedure TMainForm.BtnFMCTCSSClick(Sender: TObject);
|
||||
begin
|
||||
FFMCTCSSOn := not FFMCTCSSOn;
|
||||
FFMCTCSSOn := not FFMCTCSSOn;
|
||||
FFMCTCSSAutoActive := False; // ручное действие снимает авто-флаг
|
||||
StyleButton(BtnFMCTCSS, FFMCTCSSOn);
|
||||
BtnFMCTCSS.Repaint; // Flush visual state before WDSP call
|
||||
if FWDSPReady then
|
||||
@@ -6808,15 +7076,17 @@ begin
|
||||
if FWDSPReady then FDSPEngine.SetMode(FMode);
|
||||
UpdateFilterButtons; // показывает/скрывает FM-панели, обновляет SQL UI
|
||||
ApplyModeFilter;
|
||||
FFMCTCSSOn := E.LastCTCSSOn;
|
||||
FFMCTCSSOn := E.LastCTCSSOn;
|
||||
FFMCTCSSAutoActive := E.LastCTCSSAutoActive;
|
||||
if BtnFMCTCSS <> nil then StyleButton(BtnFMCTCSS, FFMCTCSSOn);
|
||||
SetFMCTCSSTone(E.LastCTCSSToneIdx);
|
||||
ApplyFMSquelch;
|
||||
FFMStepOn := E.LastFMStepOn;
|
||||
SetFMStep(E.LastFMStepIdx);
|
||||
if BtnFMStep <> nil then StyleButton(BtnFMStep, FFMStepOn);
|
||||
FFMRptDir := E.LastFMRptDir;
|
||||
FFMRptOffsetHz := E.LastFMRptOffsetHz;
|
||||
FFMRptDir := E.LastFMRptDir;
|
||||
FFMRptAutoActive := E.LastFMRptAutoActive;
|
||||
FFMRptOffsetHz := E.LastFMRptOffsetHz;
|
||||
if FFMRptOffsetHz <= 0 then
|
||||
FFMRptOffsetHz := RptDefaultOffsetHz(E.FreqBegin);
|
||||
if BtnFMRptMinus <> nil then StyleButton(BtnFMRptMinus, FFMRptDir = RPT_MINUS);
|
||||
@@ -6871,10 +7141,25 @@ procedure TMainForm.DeactivateXvtr;
|
||||
var i: Integer;
|
||||
begin
|
||||
if FCurrentXvtr < 0 then Exit;
|
||||
// Запоминаем LastFreq для bandstack
|
||||
// Сохраняем полное состояние XVTR-слота (раньше сохранялся только LastFreq)
|
||||
if FCurrentXvtr < CFG_XVTR_COUNT then
|
||||
begin
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastFreq := FVfoA;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastFreq := FVfoA;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastMode := FMode;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastFilterIdx := FFilter;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastFMSQOn := FFMSQOn;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastFMSQLevel := FFMSQLevel;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastCTCSSOn := FFMCTCSSOn;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastCTCSSToneIdx := FFMCTCSSToneIdx;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastFMStepOn := FFMStepOn;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastFMStepIdx := FFMStepIdx;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastFMRptDir := FFMRptDir;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastFMRptOffsetHz := FFMRptOffsetHz;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastCTun := FCTun;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastAGCMode := FAGCMode;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastAGCTop := FAGCTop;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastCTCSSAutoActive := FFMCTCSSAutoActive;
|
||||
FXvtrSettings.Entries[FCurrentXvtr].LastFMRptAutoActive := FFMRptAutoActive;
|
||||
if FDevConnected then
|
||||
begin
|
||||
FSettings.SaveXvtr(FDevMAC, FXvtrSettings);
|
||||
|
||||
Reference in New Issue
Block a user