mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
fix UpdateRptAutoState
This commit is contained in:
+173
-1
@@ -37,7 +37,8 @@ uses
|
||||
StatusBar,
|
||||
PlatformUtils,
|
||||
WinFirewall,
|
||||
BoardUtils, WisdomBuilder, UISync;
|
||||
BoardUtils, WisdomBuilder, UISync,
|
||||
FlatEdit, FMRepeater;
|
||||
|
||||
const
|
||||
CLR_BG = TColor($00101010);
|
||||
@@ -254,6 +255,9 @@ type
|
||||
FFMSQLevel: Integer;
|
||||
FFMStepOn: Boolean;
|
||||
FFMStepIdx: Integer;
|
||||
FFMRptDir: Integer; // RPT_NONE / RPT_MINUS / RPT_PLUS
|
||||
FFMRptOffsetHz: Double;
|
||||
FFMRptAutoActive: Boolean; // True = текущий minus включён автоматически
|
||||
FWfManualHigh: Double;
|
||||
FWfManualLow: Double;
|
||||
FWfAGCOffset: Double;
|
||||
@@ -373,6 +377,10 @@ type
|
||||
BtnFMStep: TFlatButton;
|
||||
BtnFMStepSel: TFlatButton;
|
||||
FStepDropDown: TFlatDropDown;
|
||||
PanelFMRpt: TPanel;
|
||||
BtnFMRptMinus: TFlatButton;
|
||||
BtnFMRptPlus: TFlatButton;
|
||||
EdFMRptOffset: TFlatEdit;
|
||||
|
||||
PanelAGC: TPanel;
|
||||
BtnAGCMode: array[0..4] of TFlatButton; // FAST MED SLOW LONG OFF
|
||||
@@ -498,6 +506,11 @@ type
|
||||
procedure BtnFMCTCSSToneClick(Sender: TObject);
|
||||
procedure SetFMCTCSSTone(Idx: Integer);
|
||||
procedure CloseCTCSSPopup;
|
||||
procedure BtnFMRptMinusClick(Sender: TObject);
|
||||
procedure BtnFMRptPlusClick(Sender: TObject);
|
||||
procedure EdFMRptOffsetChange(Sender: TObject);
|
||||
procedure ApplyFMRpt;
|
||||
procedure UpdateRptAutoState;
|
||||
procedure SetFMStep(Idx: Integer);
|
||||
procedure CloseFMStepPopup;
|
||||
procedure BtnFMStepClick(Sender: TObject);
|
||||
@@ -859,6 +872,8 @@ begin
|
||||
Result.CTCSSToneIdx := FFMCTCSSToneIdx;
|
||||
Result.FMStepOn := FFMStepOn;
|
||||
Result.FMStepIdx := FFMStepIdx;
|
||||
Result.FMRptDir := FFMRptDir;
|
||||
Result.FMRptOffsetHz := FFMRptOffsetHz;
|
||||
// Waterfall AGC/NF — глобальные (не диапазонные)
|
||||
end;
|
||||
|
||||
@@ -959,6 +974,8 @@ 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;
|
||||
@@ -1022,6 +1039,13 @@ begin
|
||||
FFMStepOn := B.FMStepOn;
|
||||
SetFMStep(B.FMStepIdx);
|
||||
if BtnFMStep <> nil then StyleButton(BtnFMStep, FFMStepOn);
|
||||
FFMRptDir := B.FMRptDir;
|
||||
FFMRptOffsetHz := B.FMRptOffsetHz;
|
||||
if FFMRptOffsetHz <= 0 then
|
||||
FFMRptOffsetHz := RptDefaultOffsetHz(B.VfoA);
|
||||
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);
|
||||
|
||||
// --- CTUN ---
|
||||
FCTun := B.CTun;
|
||||
@@ -1111,6 +1135,9 @@ begin
|
||||
FFMSQLevel := 30;
|
||||
FFMStepOn := True;
|
||||
FFMStepIdx := FM_STEP_DEF;
|
||||
FFMRptDir := RPT_NONE;
|
||||
FFMRptOffsetHz := RPT_DEFAULT_2M;
|
||||
FFMRptAutoActive := False;
|
||||
FSpectrumBufCount := 1024;
|
||||
FWaterfallBufCount := 1024;
|
||||
FWaterfallFrameInterval := 2;
|
||||
@@ -1917,6 +1944,31 @@ begin
|
||||
FStepDropDown.SetItemIndex(FFMStepIdx);
|
||||
FStepDropDown.OnSelect := OnStepDropDownSelect;
|
||||
|
||||
// FM Repeater offset panel (visible only in FM mode, below CTCSS)
|
||||
PanelFMRpt := TPanel.Create(Self);
|
||||
PanelFMRpt.Parent := PanelLeft;
|
||||
PanelFMRpt.SetBounds(0, Y, LEFT_W, 50);
|
||||
PanelFMRpt.BevelOuter := bvNone;
|
||||
PanelFMRpt.Visible := False;
|
||||
MakeLbl(PanelFMRpt, 'RPT', 4, 2);
|
||||
BtnFMRptMinus := MakeBtn(PanelFMRpt, '-',
|
||||
LeftPanelButtonLeft(LEFT_W, 5, 0), 16,
|
||||
LeftPanelButtonWidth(LEFT_W, 5, 0), BTN_H, BtnFMRptMinusClick);
|
||||
StyleButton(BtnFMRptMinus, False);
|
||||
BtnFMRptPlus := MakeBtn(PanelFMRpt, '+',
|
||||
LeftPanelButtonLeft(LEFT_W, 5, 4), 16,
|
||||
LeftPanelButtonWidth(LEFT_W, 5, 4), BTN_H, BtnFMRptPlusClick);
|
||||
StyleButton(BtnFMRptPlus, False);
|
||||
W := LeftPanelButtonLeft(LEFT_W, 5, 1);
|
||||
EdFMRptOffset := TFlatEdit.Create(Self);
|
||||
EdFMRptOffset.Parent := PanelFMRpt;
|
||||
EdFMRptOffset.Left := W;
|
||||
EdFMRptOffset.Top := 18;
|
||||
EdFMRptOffset.Width := LeftPanelButtonLeft(LEFT_W, 5, 4) - W - LEFT_PANEL_BTN_GAP;
|
||||
EdFMRptOffset.Height := BTN_H - 4;
|
||||
EdFMRptOffset.Text := RptFormatOffset(FFMRptOffsetHz);
|
||||
EdFMRptOffset.OnChange := EdFMRptOffsetChange;
|
||||
|
||||
// ---- Right panel ----
|
||||
PanelRight := TPanel.Create(Self);
|
||||
PanelRight.Parent := Self;
|
||||
@@ -2501,6 +2553,8 @@ begin
|
||||
if PanelFMSQ <> nil then DP(PanelFMSQ);
|
||||
if PanelFMCTCSS <> nil then DP(PanelFMCTCSS);
|
||||
if PanelFMStep <> nil then DP(PanelFMStep);
|
||||
if PanelFMRpt <> nil then DP(PanelFMRpt);
|
||||
if EdFMRptOffset <> nil then EdFMRptOffset.SetAppTheme(T);
|
||||
DP(PanelRXBlock); DP(PanelAGC); DP(PanelTX);
|
||||
DP(PanelRight);
|
||||
|
||||
@@ -2541,6 +2595,8 @@ begin
|
||||
if TrkFMSQ <> nil then DS(TrkFMSQ);
|
||||
if BtnFMCTCSS <> nil then StyleButton(BtnFMCTCSS, BtnFMCTCSS.Active);
|
||||
if BtnFMCTCSSTone <> nil then StyleButton(BtnFMCTCSSTone, False);
|
||||
if BtnFMRptMinus <> nil then StyleButton(BtnFMRptMinus, BtnFMRptMinus.Active);
|
||||
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);
|
||||
StyleButton(BtnNR, BtnNR.Active);
|
||||
@@ -4383,6 +4439,13 @@ begin
|
||||
if FStepDropDown <> nil then FStepDropDown.SetItemIndex(FFMStepIdx);
|
||||
PanelFMStep.Visible := True;
|
||||
end;
|
||||
if PanelFMRpt <> nil then
|
||||
begin
|
||||
StyleButton(BtnFMRptMinus, FFMRptDir = RPT_MINUS);
|
||||
StyleButton(BtnFMRptPlus, FFMRptDir = RPT_PLUS);
|
||||
EdFMRptOffset.Text := RptFormatOffset(FFMRptOffsetHz);
|
||||
PanelFMRpt.Visible := True;
|
||||
end;
|
||||
RelayoutBelowBands;
|
||||
Exit;
|
||||
end;
|
||||
@@ -4392,6 +4455,7 @@ begin
|
||||
if PanelFMSQ <> nil then PanelFMSQ.Visible := False;
|
||||
if PanelFMCTCSS <> nil then PanelFMCTCSS.Visible := False;
|
||||
if PanelFMStep <> nil then begin CloseFMStepPopup; PanelFMStep.Visible := False; end;
|
||||
if PanelFMRpt <> nil then PanelFMRpt.Visible := False;
|
||||
for i := 0 to FILT_COUNT - 1 do
|
||||
begin
|
||||
BtnFilter[i].Left := LeftPanelButtonLeft(PanelFilter.Width, 5, i mod 5);
|
||||
@@ -4529,6 +4593,9 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
// Auto-enable repeater minus for 2 m repeater input segment
|
||||
if FMode = MODE_FM then UpdateRptAutoState;
|
||||
|
||||
// DDC: передаём FCenterFreq (при CTUN OFF = FVfoA, при CTUN ON = фиксирован)
|
||||
if FNetwork.Connected and FNetwork.Running then
|
||||
begin
|
||||
@@ -5141,6 +5208,95 @@ begin
|
||||
CloseFMStepPopup;
|
||||
end;
|
||||
|
||||
procedure TMainForm.BtnFMRptMinusClick(Sender: TObject);
|
||||
begin
|
||||
if FFMRptDir = RPT_MINUS then
|
||||
FFMRptDir := RPT_NONE
|
||||
else
|
||||
FFMRptDir := RPT_MINUS;
|
||||
FFMRptAutoActive := False; // ручное действие снимает авто-флаг
|
||||
StyleButton(BtnFMRptMinus, FFMRptDir = RPT_MINUS);
|
||||
StyleButton(BtnFMRptPlus, FFMRptDir = RPT_PLUS);
|
||||
BtnFMRptMinus.Repaint;
|
||||
BtnFMRptPlus.Repaint;
|
||||
ApplyFMRpt;
|
||||
SaveCurrentBand;
|
||||
end;
|
||||
|
||||
procedure TMainForm.BtnFMRptPlusClick(Sender: TObject);
|
||||
begin
|
||||
if FFMRptDir = RPT_PLUS then
|
||||
FFMRptDir := RPT_NONE
|
||||
else
|
||||
FFMRptDir := RPT_PLUS;
|
||||
FFMRptAutoActive := False; // ручное действие снимает авто-флаг
|
||||
StyleButton(BtnFMRptMinus, FFMRptDir = RPT_MINUS);
|
||||
StyleButton(BtnFMRptPlus, FFMRptDir = RPT_PLUS);
|
||||
BtnFMRptMinus.Repaint;
|
||||
BtnFMRptPlus.Repaint;
|
||||
ApplyFMRpt;
|
||||
SaveCurrentBand;
|
||||
end;
|
||||
|
||||
procedure TMainForm.EdFMRptOffsetChange(Sender: TObject);
|
||||
var Hz: Double;
|
||||
begin
|
||||
Hz := RptParseOffset(EdFMRptOffset.Text);
|
||||
if Hz > 0.0 then
|
||||
begin
|
||||
FFMRptOffsetHz := Hz;
|
||||
if FFMRptDir <> RPT_NONE then
|
||||
begin
|
||||
ApplyFMRpt;
|
||||
SaveCurrentBand;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.ApplyFMRpt;
|
||||
begin
|
||||
if FNetwork.Connected and FNetwork.Running then
|
||||
begin
|
||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz),
|
||||
FDriveLevel, FTransmitting, True, True);
|
||||
FNetwork.SendFullHP;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.UpdateRptAutoState;
|
||||
var InRange: Boolean;
|
||||
begin
|
||||
InRange := RptAutoDir(FVfoA) = RPT_MINUS;
|
||||
if InRange then
|
||||
begin
|
||||
// Auto-enable minus only when currently off.
|
||||
if FFMRptDir = RPT_NONE then
|
||||
begin
|
||||
FFMRptDir := RPT_MINUS;
|
||||
FFMRptAutoActive := True;
|
||||
if BtnFMRptMinus <> nil then
|
||||
begin
|
||||
StyleButton(BtnFMRptMinus, True);
|
||||
BtnFMRptMinus.Repaint;
|
||||
end;
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// Auto-disable only if this minus was set automatically.
|
||||
if (FFMRptDir = RPT_MINUS) and FFMRptAutoActive then
|
||||
begin
|
||||
FFMRptDir := RPT_NONE;
|
||||
FFMRptAutoActive := False;
|
||||
if BtnFMRptMinus <> nil then
|
||||
begin
|
||||
StyleButton(BtnFMRptMinus, False);
|
||||
BtnFMRptMinus.Repaint;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.CloseFMStepPopup;
|
||||
begin
|
||||
if FStepDropDown <> nil then FStepDropDown.ClosePopup;
|
||||
@@ -5283,6 +5439,11 @@ begin
|
||||
if FSplitTxB then Result := FVfoB
|
||||
else if FActiveVfo = 0 then Result := FVfoA
|
||||
else Result := FVfoB;
|
||||
if FMode = MODE_FM then
|
||||
case FFMRptDir of
|
||||
RPT_MINUS: Result := Result - FFMRptOffsetHz;
|
||||
RPT_PLUS: Result := Result + FFMRptOffsetHz;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.ApplyMOX(Active: Boolean);
|
||||
@@ -6527,6 +6688,10 @@ begin
|
||||
begin
|
||||
PanelFMCTCSS.Top := Y; Y := Y + PanelFMCTCSS.Height + 2;
|
||||
end;
|
||||
if (PanelFMRpt <> nil) and PanelFMRpt.Visible then
|
||||
begin
|
||||
PanelFMRpt.Top := Y; Y := Y + PanelFMRpt.Height + 2;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.RebuildXvtrButtons;
|
||||
@@ -6650,6 +6815,13 @@ begin
|
||||
FFMStepOn := E.LastFMStepOn;
|
||||
SetFMStep(E.LastFMStepIdx);
|
||||
if BtnFMStep <> nil then StyleButton(BtnFMStep, FFMStepOn);
|
||||
FFMRptDir := E.LastFMRptDir;
|
||||
FFMRptOffsetHz := E.LastFMRptOffsetHz;
|
||||
if FFMRptOffsetHz <= 0 then
|
||||
FFMRptOffsetHz := RptDefaultOffsetHz(E.FreqBegin);
|
||||
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);
|
||||
// AGC
|
||||
FAGCMode := E.LastAGCMode;
|
||||
FAGCTop := E.LastAGCTop;
|
||||
|
||||
@@ -40,6 +40,8 @@ type
|
||||
CTCSSToneIdx: Integer; // 0..37
|
||||
FMStepOn: Boolean;
|
||||
FMStepIdx: Integer; // 0..3 (6.25/12.5/20/25 kHz)
|
||||
FMRptDir: Integer; // RPT_NONE/RPT_MINUS/RPT_PLUS
|
||||
FMRptOffsetHz: Double; // Hz, 0 = use band default
|
||||
end;
|
||||
|
||||
// TX-настройки per-device. Хранятся в JSON-секции "tx" под MAC,
|
||||
@@ -150,6 +152,8 @@ type
|
||||
LastCTun: Boolean;
|
||||
LastAGCMode: Integer;
|
||||
LastAGCTop: Integer;
|
||||
LastFMRptDir: Integer;
|
||||
LastFMRptOffsetHz: Double;
|
||||
end;
|
||||
|
||||
TXvtrSettings = record
|
||||
@@ -356,6 +360,8 @@ begin
|
||||
B.CTCSSToneIdx := 0;
|
||||
B.FMStepOn := True;
|
||||
B.FMStepIdx := 3; // 25 kHz
|
||||
B.FMRptDir := 0;
|
||||
B.FMRptOffsetHz := 0.0;
|
||||
end;
|
||||
|
||||
class procedure TSettingsManager.DefaultGlobal(out G: TGlobalSettings);
|
||||
@@ -737,6 +743,7 @@ begin
|
||||
JW(O,'fmsq_on',B.FMSQOn); JW(O,'fmsq_level',B.FMSQLevel);
|
||||
JW(O,'ctcss_on',B.CTCSSOn); JW(O,'ctcss_idx',B.CTCSSToneIdx);
|
||||
JW(O,'fmstep_on',B.FMStepOn); JW(O,'fmstep_idx',B.FMStepIdx);
|
||||
JW(O,'fmrpt_dir',B.FMRptDir); JW(O,'fmrpt_offset',B.FMRptOffsetHz);
|
||||
end;
|
||||
|
||||
function TSettingsManager.LoadBand(const MAC: array of Byte; BandIdx: Integer;
|
||||
@@ -763,6 +770,8 @@ begin
|
||||
B.CTCSSToneIdx := EnsureRange(JI(O,'ctcss_idx', B.CTCSSToneIdx), 0, 37);
|
||||
B.FMStepOn := JB(O,'fmstep_on', B.FMStepOn);
|
||||
B.FMStepIdx := EnsureRange(JI(O,'fmstep_idx', B.FMStepIdx), 0, 3);
|
||||
B.FMRptDir := EnsureRange(JI(O,'fmrpt_dir', B.FMRptDir), 0, 2);
|
||||
B.FMRptOffsetHz := JD(O,'fmrpt_offset', B.FMRptOffsetHz);
|
||||
end;
|
||||
|
||||
procedure TSettingsManager.SaveWindowBounds(L, T, W, H, DPI: Integer; Maximized: Boolean);
|
||||
@@ -1173,6 +1182,8 @@ begin
|
||||
X.Entries[i].LastCTun := False;
|
||||
X.Entries[i].LastAGCMode := 1;
|
||||
X.Entries[i].LastAGCTop := 90;
|
||||
X.Entries[i].LastFMRptDir := 0;
|
||||
X.Entries[i].LastFMRptOffsetHz := 0.0;
|
||||
end;
|
||||
// Шаблоны (пользователь должен сам Enable, чтобы трансверторы появились)
|
||||
X.Entries[0].ButtonText := '2m';
|
||||
@@ -1229,6 +1240,8 @@ begin
|
||||
X.Entries[i].LastCTun := JB(EObj, 'last_ctun', X.Entries[i].LastCTun);
|
||||
X.Entries[i].LastAGCMode := EnsureRange(JI(EObj, 'last_agc_mode', X.Entries[i].LastAGCMode), 0, 4);
|
||||
X.Entries[i].LastAGCTop := EnsureRange(JI(EObj, 'last_agc_top', X.Entries[i].LastAGCTop), 0, 120);
|
||||
X.Entries[i].LastFMRptDir := EnsureRange(JI(EObj, 'last_fmrpt_dir', X.Entries[i].LastFMRptDir), 0, 2);
|
||||
X.Entries[i].LastFMRptOffsetHz := JD(EObj, 'last_fmrpt_offset', X.Entries[i].LastFMRptOffsetHz);
|
||||
// Валидация: LastFreq должен быть в [FreqBegin..FreqEnd]
|
||||
if (X.Entries[i].LastFreq < X.Entries[i].FreqBegin) or
|
||||
(X.Entries[i].LastFreq > X.Entries[i].FreqEnd) then
|
||||
@@ -1270,6 +1283,8 @@ begin
|
||||
JW(EObj, 'last_ctun', X.Entries[i].LastCTun);
|
||||
JW(EObj, 'last_agc_mode', X.Entries[i].LastAGCMode);
|
||||
JW(EObj, 'last_agc_top', X.Entries[i].LastAGCTop);
|
||||
JW(EObj, 'last_fmrpt_dir', X.Entries[i].LastFMRptDir);
|
||||
JW(EObj, 'last_fmrpt_offset', X.Entries[i].LastFMRptOffsetHz);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user