mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
Fix XVTR/FM frequency, mode and step persistence
- Fix web spectrum scroll resetting freq to XVTR minimum (same root cause as desktop: hardcoded 60 MHz clamp; now delegates to server) - Save/restore FM mode, NFM/WFM filter, squelch, CTCSS per XVTR slot and per HF band (CTCSSOn/ToneIdx added to TBandSettings; full state added to TXvtrEntry; ActivateXvtrBand restores all on slot switch) - Fix UpdateFilterButtons always resetting NFM/WFM to default on mode restore; now preserves saved filter index - Add FM Step tuning: panel with STEP toggle + 6.25/12.5/20/25 kHz selector (popup); mouse wheel uses selected step in FM mode; state saved per band and XVTR slot Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+56
-10
@@ -29,8 +29,12 @@ type
|
||||
AGCTop: Integer;
|
||||
CTun: Boolean;
|
||||
SpanHz: Double;
|
||||
FMSQOn: Boolean;
|
||||
FMSQLevel: Integer; // 0..100 → WDSP threshold 0.0..0.5
|
||||
FMSQOn: Boolean;
|
||||
FMSQLevel: Integer; // 0..100 → WDSP threshold 0.0..0.5
|
||||
CTCSSOn: Boolean;
|
||||
CTCSSToneIdx: Integer; // 0..37
|
||||
FMStepOn: Boolean;
|
||||
FMStepIdx: Integer; // 0..3 (6.25/12.5/20/25 kHz)
|
||||
end;
|
||||
|
||||
// TX-настройки per-device. Хранятся в JSON-секции "tx" под MAC,
|
||||
@@ -131,7 +135,15 @@ type
|
||||
TXPower: Integer; // 0..100 % (drive level специально для XVTR)
|
||||
DisablePA: Boolean; // True — отключить внутренний PA при TX (XVTR имеет свой)
|
||||
RXAntenna: Byte; // 0=по-умолчанию(основной band), 1=ANT1, 2=ANT2, 3=ANT3
|
||||
LastFreq: Double; // Hz — последняя tuned visible частота (BandStack)
|
||||
LastFreq: Double; // Hz — последняя tuned visible частота (BandStack)
|
||||
LastMode: Integer; // Mode (LSB=0,USB=1,…FM=5)
|
||||
LastFilterIdx: Integer; // FM: 0=NFM, 1=WFM; иначе 0..FILT_COUNT-1
|
||||
LastFMSQOn: Boolean;
|
||||
LastFMSQLevel: Integer;
|
||||
LastCTCSSOn: Boolean;
|
||||
LastCTCSSToneIdx: Integer;
|
||||
LastFMStepOn: Boolean;
|
||||
LastFMStepIdx: Integer;
|
||||
end;
|
||||
|
||||
TXvtrSettings = record
|
||||
@@ -327,8 +339,12 @@ begin
|
||||
B.AGCTop := 90;
|
||||
B.CTun := False;
|
||||
B.SpanHz := 192000;
|
||||
B.FMSQOn := False;
|
||||
B.FMSQLevel := 30;
|
||||
B.FMSQOn := False;
|
||||
B.FMSQLevel := 30;
|
||||
B.CTCSSOn := False;
|
||||
B.CTCSSToneIdx := 0;
|
||||
B.FMStepOn := True;
|
||||
B.FMStepIdx := 3; // 25 kHz
|
||||
end;
|
||||
|
||||
class procedure TSettingsManager.DefaultGlobal(out G: TGlobalSettings);
|
||||
@@ -697,6 +713,8 @@ begin
|
||||
JW(O,'agc_mode',B.AGCMode); JW(O,'agc_top',B.AGCTop);
|
||||
JW(O,'ctun',B.CTun); JW(O,'span_hz',B.SpanHz);
|
||||
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);
|
||||
end;
|
||||
|
||||
function TSettingsManager.LoadBand(const MAC: array of Byte; BandIdx: Integer;
|
||||
@@ -717,8 +735,12 @@ begin
|
||||
B.AGCTop := JI(O,'agc_top', B.AGCTop);
|
||||
B.CTun := JB(O,'ctun', B.CTun);
|
||||
B.SpanHz := JD(O,'span_hz', B.SpanHz);
|
||||
B.FMSQOn := JB(O,'fmsq_on', B.FMSQOn);
|
||||
B.FMSQLevel := JI(O,'fmsq_level', B.FMSQLevel);
|
||||
B.FMSQOn := JB(O,'fmsq_on', B.FMSQOn);
|
||||
B.FMSQLevel := JI(O,'fmsq_level', B.FMSQLevel);
|
||||
B.CTCSSOn := JB(O,'ctcss_on', B.CTCSSOn);
|
||||
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);
|
||||
end;
|
||||
|
||||
procedure TSettingsManager.SaveWindowBounds(L, T, W, H: Integer);
|
||||
@@ -1090,7 +1112,15 @@ begin
|
||||
X.Entries[i].TXPower := 100;
|
||||
X.Entries[i].DisablePA := False;
|
||||
X.Entries[i].RXAntenna := 0;
|
||||
X.Entries[i].LastFreq := 0.0;
|
||||
X.Entries[i].LastFreq := 0.0;
|
||||
X.Entries[i].LastMode := 1; // USB — VHF SSB calling default
|
||||
X.Entries[i].LastFilterIdx := 0; // NFM
|
||||
X.Entries[i].LastFMSQOn := False;
|
||||
X.Entries[i].LastFMSQLevel := 30;
|
||||
X.Entries[i].LastCTCSSOn := False;
|
||||
X.Entries[i].LastCTCSSToneIdx := 0;
|
||||
X.Entries[i].LastFMStepOn := True;
|
||||
X.Entries[i].LastFMStepIdx := 3; // 25 kHz
|
||||
end;
|
||||
// Шаблоны (пользователь должен сам Enable, чтобы трансверторы появились)
|
||||
X.Entries[0].ButtonText := '2m';
|
||||
@@ -1135,7 +1165,15 @@ begin
|
||||
X.Entries[i].TXPower := EnsureRange(JI(EObj, 'tx_pwr', X.Entries[i].TXPower), 0, 100);
|
||||
X.Entries[i].DisablePA := JB(EObj, 'dis_pa', X.Entries[i].DisablePA);
|
||||
X.Entries[i].RXAntenna := EnsureRange(JI(EObj, 'rx_ant', X.Entries[i].RXAntenna), 0, 3);
|
||||
X.Entries[i].LastFreq := JD(EObj, 'last_freq', X.Entries[i].LastFreq);
|
||||
X.Entries[i].LastFreq := JD(EObj, 'last_freq', X.Entries[i].LastFreq);
|
||||
X.Entries[i].LastMode := EnsureRange(JI(EObj, 'last_mode', X.Entries[i].LastMode), 0, 7);
|
||||
X.Entries[i].LastFilterIdx := EnsureRange(JI(EObj, 'last_filt', X.Entries[i].LastFilterIdx), 0, 9);
|
||||
X.Entries[i].LastFMSQOn := JB(EObj, 'last_fmsq_on', X.Entries[i].LastFMSQOn);
|
||||
X.Entries[i].LastFMSQLevel := EnsureRange(JI(EObj, 'last_fmsq_lvl', X.Entries[i].LastFMSQLevel), 0, 100);
|
||||
X.Entries[i].LastCTCSSOn := JB(EObj, 'last_ctcss_on', X.Entries[i].LastCTCSSOn);
|
||||
X.Entries[i].LastCTCSSToneIdx := EnsureRange(JI(EObj, 'last_ctcss_idx', X.Entries[i].LastCTCSSToneIdx), 0, 37);
|
||||
X.Entries[i].LastFMStepOn := JB(EObj, 'last_fmstep_on', X.Entries[i].LastFMStepOn);
|
||||
X.Entries[i].LastFMStepIdx := EnsureRange(JI(EObj, 'last_fmstep_idx', X.Entries[i].LastFMStepIdx), 0, 3);
|
||||
// Валидация: LastFreq должен быть в [FreqBegin..FreqEnd]
|
||||
if (X.Entries[i].LastFreq < X.Entries[i].FreqBegin) or
|
||||
(X.Entries[i].LastFreq > X.Entries[i].FreqEnd) then
|
||||
@@ -1165,7 +1203,15 @@ begin
|
||||
JW(EObj, 'tx_pwr', X.Entries[i].TXPower);
|
||||
JW(EObj, 'dis_pa', X.Entries[i].DisablePA);
|
||||
JW(EObj, 'rx_ant', Integer(X.Entries[i].RXAntenna));
|
||||
JW(EObj, 'last_freq', X.Entries[i].LastFreq);
|
||||
JW(EObj, 'last_freq', X.Entries[i].LastFreq);
|
||||
JW(EObj, 'last_mode', X.Entries[i].LastMode);
|
||||
JW(EObj, 'last_filt', X.Entries[i].LastFilterIdx);
|
||||
JW(EObj, 'last_fmsq_on', X.Entries[i].LastFMSQOn);
|
||||
JW(EObj, 'last_fmsq_lvl', X.Entries[i].LastFMSQLevel);
|
||||
JW(EObj, 'last_ctcss_on', X.Entries[i].LastCTCSSOn);
|
||||
JW(EObj, 'last_ctcss_idx',X.Entries[i].LastCTCSSToneIdx);
|
||||
JW(EObj, 'last_fmstep_on', X.Entries[i].LastFMStepOn);
|
||||
JW(EObj, 'last_fmstep_idx',X.Entries[i].LastFMStepIdx);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user