mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 18:43:51 +00:00
Add configurable VFO frequency range with GHz support
- Settings > Display: new "VFO Display" control to select max frequency range (999 MHz / 9.999 GHz / 99.999 GHz), persisted as freq_mhz_digits - FreqDisplay: extend digit map [0..10] to support up to 11 digit positions; keyboard navigation adapts to MinMhzDigits dynamically - MainForm/LayoutTopVfoBlock: VFO panel width scales automatically with selected digit count using dynamic text measurement - Web VFO: fix broken HTML (class attr not closed before data-s — wheel and hover were completely non-functional); rewrite fmtVfo to use variable MHz digit count synced from server state; fix missing </span> for .vfo-hz - WebServer: publish freq_mhz_digits in state JSON; updated from ApplyFreqMhzDigits so desktop and web stay in sync - Fix Int32 overflow on frequencies above ~2.15 GHz: CATEngine.Pad V param Int64, FormatFreq/FormatFreqSV Mhz var Int64 (Mhz*1000000 overflowed) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+2
-2
@@ -88,7 +88,7 @@ type
|
||||
FCtx: TCATContext;
|
||||
FLock: TCriticalSection;
|
||||
|
||||
function Pad(V, W: Integer): string;
|
||||
function Pad(V: Int64; W: Integer): string;
|
||||
function FreqToStr(Hz: Double): string;
|
||||
function StrToFreq(const S: string): Double;
|
||||
function ModeToK(M: Integer): Integer;
|
||||
@@ -311,7 +311,7 @@ begin if B then Result := '1' else Result := '0'; end;
|
||||
|
||||
{ ── Helpers ──────────────────────────────────────────────────────────────── }
|
||||
|
||||
function TCATEngine.Pad(V, W: Integer): string;
|
||||
function TCATEngine.Pad(V: Int64; W: Integer): string;
|
||||
begin
|
||||
Result := IntToStr(Abs(V));
|
||||
while Length(Result) < W do Result := '0' + Result;
|
||||
|
||||
+9
-9
@@ -36,8 +36,8 @@ type
|
||||
FCenterText: Boolean;
|
||||
FOnChange: TFreqChangeEvent;
|
||||
|
||||
FHoverDigit: Integer; // 0=единицы .. 8=100МГц, -1=нет
|
||||
FDigitX: array[0..8] of Integer; // X левого края каждой цифры
|
||||
FHoverDigit: Integer; // 0=единицы .. 10=10ГГц, -1=нет
|
||||
FDigitX: array[0..10] of Integer; // X левого края каждой цифры
|
||||
FDigitW: Integer;
|
||||
FCharH: Integer;
|
||||
|
||||
@@ -125,7 +125,7 @@ var
|
||||
begin
|
||||
Result := -1;
|
||||
if FDigitW = 0 then Exit;
|
||||
for i := 0 to 8 do
|
||||
for i := 0 to 10 do
|
||||
if (X >= FDigitX[i]) and (X < FDigitX[i] + FDigitW) then
|
||||
begin
|
||||
Result := i;
|
||||
@@ -137,14 +137,14 @@ end;
|
||||
// Цифры нумеруются справа налево: digit0=единицы, digit8=сотни млн
|
||||
procedure TFreqDisplay.BuildDigitMap(const S: string; StartX: Integer);
|
||||
var
|
||||
Xs: array[0..11] of Integer; // X каждого символа строки (макс 12 симв)
|
||||
Xs: array[0..13] of Integer; // X каждого символа строки (макс 14 симв)
|
||||
ci: Integer;
|
||||
xi: Integer;
|
||||
dIdx: Integer;
|
||||
len: Integer;
|
||||
begin
|
||||
len := Length(S);
|
||||
if len > 12 then len := 12;
|
||||
if len > 13 then len := 13;
|
||||
|
||||
xi := StartX;
|
||||
for ci := 0 to len - 1 do
|
||||
@@ -159,7 +159,7 @@ begin
|
||||
begin
|
||||
if S[ci + 1] <> '.' then
|
||||
begin
|
||||
if dIdx <= 8 then
|
||||
if dIdx <= 10 then
|
||||
FDigitX[dIdx] := Xs[ci];
|
||||
Inc(dIdx);
|
||||
end;
|
||||
@@ -185,7 +185,7 @@ var
|
||||
ch: Char;
|
||||
dIdx: Integer;
|
||||
col: TColor;
|
||||
DiChar: array[0..11] of Integer;
|
||||
DiChar: array[0..13] of Integer;
|
||||
tmpIdx: Integer;
|
||||
len: Integer;
|
||||
begin
|
||||
@@ -234,7 +234,7 @@ begin
|
||||
|
||||
// Строим обратную карту символ → digit index
|
||||
len := Length(S);
|
||||
if len > 12 then len := 12;
|
||||
if len > 13 then len := 13;
|
||||
tmpIdx := 0;
|
||||
for ci := len - 1 downto 0 do
|
||||
begin
|
||||
@@ -385,7 +385,7 @@ begin
|
||||
VK_DOWN: begin ChangeByDigit(d, -1); Key := 0; end;
|
||||
VK_LEFT: begin
|
||||
if FHoverDigit < 0 then FHoverDigit := 3;
|
||||
if FHoverDigit < 8 then Inc(FHoverDigit);
|
||||
if FHoverDigit < FMinMhzDigits + 5 then Inc(FHoverDigit);
|
||||
Invalidate; Key := 0;
|
||||
end;
|
||||
VK_RIGHT: begin
|
||||
|
||||
+26
-3
@@ -278,6 +278,7 @@ type
|
||||
FBandCache: array[0..CFG_BAND_COUNT-1] of TBandSettings; // кэш диапазонов
|
||||
FDevConnected: Boolean; // True после первого подключения
|
||||
FLightTheme: Boolean; // True = светлая тема
|
||||
FFreqMhzDigits: Integer; // 3=999MHz, 4=9.999GHz, 5=99.999GHz
|
||||
FCenterFreq: Double; // центр спектра = LO (DDC). При CTUN ON не меняется при кручении VFO
|
||||
FSpanHz: Double;
|
||||
FSampleRate: Integer; // текущий DDC sample rate (Hz)
|
||||
@@ -630,6 +631,7 @@ type
|
||||
function BuildMicLineSelectByte: Byte;
|
||||
procedure ApplyVisibility(ShowSpectrum, ShowWaterfall: Boolean);
|
||||
procedure ApplyFPS(FPS: Integer);
|
||||
procedure ApplyFreqMhzDigits(Digits: Integer);
|
||||
|
||||
published
|
||||
// Обработчики событий формы — должны быть в published для RTTI/LFM
|
||||
@@ -919,6 +921,7 @@ begin
|
||||
Result.DisplayDuplex := FDisplayDuplex;
|
||||
Result.DisplayFPS := FDisplayFPS;
|
||||
Result.LightTheme := FLightTheme;
|
||||
Result.FreqMhzDigits := FFreqMhzDigits;
|
||||
// Audio device names
|
||||
Result.AudioOutDevice := FAudioOutDevName;
|
||||
Result.AudioInDevice := FAudioInDevName;
|
||||
@@ -1182,6 +1185,7 @@ begin
|
||||
FShowSpectrum := True;
|
||||
FShowWaterfall := True;
|
||||
FDisplayFPS := 60;
|
||||
FFreqMhzDigits := 3;
|
||||
FSplitterRatio := 0.40;
|
||||
FSplitterDrag := False;
|
||||
|
||||
@@ -1992,7 +1996,7 @@ begin
|
||||
Canvas.Font.Style := [fsBold];
|
||||
FreqDispA.Left := VFO_BTN_W + VFO_BTN_FREQ_GAP - VFO_FREQ_LEFT_PAD;
|
||||
FreqDispB.Left := VFO_B_LEFT_PAD + VFO_BTN_W + VFO_BTN_FREQ_GAP - VFO_FREQ_LEFT_PAD;
|
||||
FreqTextW := Canvas.TextWidth('000.000.000');
|
||||
FreqTextW := Canvas.TextWidth(StringOfChar('0', Max(3, FFreqMhzDigits)) + '.000.000');
|
||||
NeedFreqAW := FreqDispA.Left + FreqTextW + VFO_FREQ_LEFT_PAD + VFO_FREQ_RIGHT_PAD;
|
||||
NeedFreqBW := FreqDispB.Left + FreqTextW + VFO_FREQ_LEFT_PAD + VFO_FREQ_RIGHT_PAD;
|
||||
TopVfoAW := NeedFreqAW;
|
||||
@@ -2448,12 +2452,13 @@ end;
|
||||
|
||||
function TMainForm.FormatFreq(Hz: Double): string;
|
||||
var
|
||||
Mhz, KHz, Rest: Integer;
|
||||
Mhz: Int64;
|
||||
KHz, Rest: Integer;
|
||||
begin
|
||||
Mhz := Trunc(Hz / 1000000);
|
||||
KHz := Trunc((Hz - Mhz * 1000000) / 1000);
|
||||
Rest := Trunc(Hz) mod 1000;
|
||||
Result := Format('%3d.%3.3d.%3.3d', [Mhz, KHz, Rest]);
|
||||
Result := Format('%d.%3.3d.%3.3d', [Mhz, KHz, Rest]);
|
||||
end;
|
||||
|
||||
procedure TMainForm.UpdateVfoDisplay;
|
||||
@@ -3568,6 +3573,7 @@ begin
|
||||
if BtnDUP <> nil then StyleButton(BtnDUP, FDisplayDuplex);
|
||||
if G_Settings.DisplayFPS > 0 then
|
||||
ApplyFPS(G_Settings.DisplayFPS);
|
||||
ApplyFreqMhzDigits(EnsureRange(G_Settings.FreqMhzDigits, 3, 5));
|
||||
// Настройки дисплея и сетки
|
||||
if G_Settings.FFTSize > 0 then
|
||||
begin
|
||||
@@ -6116,6 +6122,21 @@ begin
|
||||
FDSPEngine.SetDisplayFPS(FPS);
|
||||
end;
|
||||
|
||||
procedure TMainForm.ApplyFreqMhzDigits(Digits: Integer);
|
||||
const
|
||||
MaxFreqs: array[3..5] of Int64 = (999999999, 9999999999, 99999999999);
|
||||
begin
|
||||
Digits := EnsureRange(Digits, 3, 5);
|
||||
FFreqMhzDigits := Digits;
|
||||
FreqDispA.MinMhzDigits := Digits;
|
||||
FreqDispB.MinMhzDigits := Digits;
|
||||
FreqDispA.MaxFreq := MaxFreqs[Digits];
|
||||
FreqDispB.MaxFreq := MaxFreqs[Digits];
|
||||
if Assigned(FWebServer) then
|
||||
FWebServer.FreqMhzDigits := Digits;
|
||||
LayoutTopVfoBlock;
|
||||
end;
|
||||
|
||||
procedure TMainForm.BtnSettingsClick(Sender: TObject);
|
||||
var
|
||||
SF: TSettingsForm;
|
||||
@@ -6134,6 +6155,7 @@ begin
|
||||
SF.OnPAChange := OnPASettingsChange;
|
||||
SF.OnCATChange := OnCATSettingsChange;
|
||||
SF.OnThemeChange := SetLightTheme;
|
||||
SF.OnFreqMhzDigitsChange := ApplyFreqMhzDigits;
|
||||
SF.OnTXChange := OnTXSettingsChange;
|
||||
SF.OnAlexChange := OnAlexSettingsChange;
|
||||
SF.OnXvtrChange := OnXvtrSettingsChange;
|
||||
@@ -6158,6 +6180,7 @@ begin
|
||||
SF.LoadVisibility(FShowSpectrum, FShowWaterfall);
|
||||
SF.LoadFPS(FDisplayFPS);
|
||||
SF.LoadLightTheme(FLightTheme);
|
||||
SF.LoadFreqMhzDigits(FFreqMhzDigits);
|
||||
// Загружаем текущие значения
|
||||
if FWDSPReady then
|
||||
SF.LoadValues(
|
||||
|
||||
@@ -194,6 +194,8 @@ type
|
||||
DisplayFPS: Integer; // spectrum/waterfall timer fps (1..100)
|
||||
// --- Theme ---
|
||||
LightTheme: Boolean; // False = dark (default), True = light
|
||||
// --- VFO display digits ---
|
||||
FreqMhzDigits: Integer; // minimum MHz digit count: 3=999MHz, 4=9.999GHz, 5=99.999GHz
|
||||
// --- PA (Power Amplifier) settings ---
|
||||
PAMaxPower: Double; // максимальная выходная мощность, Вт (5..200)
|
||||
PABandCal: array[0..CFG_BAND_COUNT-1] of Double; // калибровка на диапазон 38.8..100.0
|
||||
@@ -346,6 +348,7 @@ begin
|
||||
G.ShowWaterfall := True;
|
||||
G.DisplayDuplex := False;
|
||||
G.DisplayFPS := 60;
|
||||
G.FreqMhzDigits := 3;
|
||||
// CAT defaults
|
||||
for i := 0 to 3 do begin
|
||||
G.CATSerialEnabled[i] := False;
|
||||
@@ -557,6 +560,7 @@ begin
|
||||
G.DisplayDuplex := JB(GObj,'display_duplex',False);
|
||||
G.DisplayFPS := JI(GObj,'display_fps',60);
|
||||
G.LightTheme := JB(GObj,'light_theme',False);
|
||||
G.FreqMhzDigits := EnsureRange(JI(GObj,'freq_mhz_digits',3), 3, 5);
|
||||
// PA settings
|
||||
G.PAMaxPower := JD(GObj,'pa_max_power',100.0);
|
||||
for i := 0 to CFG_BAND_COUNT-1 do
|
||||
@@ -636,6 +640,7 @@ begin
|
||||
JW(O,'display_duplex',G.DisplayDuplex);
|
||||
JW(O,'display_fps',G.DisplayFPS);
|
||||
JW(O,'light_theme',G.LightTheme);
|
||||
JW(O,'freq_mhz_digits',G.FreqMhzDigits);
|
||||
// PA settings
|
||||
JW(O,'pa_max_power',G.PAMaxPower);
|
||||
for i := 0 to CFG_BAND_COUNT-1 do
|
||||
|
||||
@@ -36,6 +36,7 @@ type
|
||||
// TX-настройки целиком (любая правка → один callback с актуальной структурой)
|
||||
TOnTXSettingsChange = procedure(const T: TTXSettings) of object;
|
||||
|
||||
TOnFreqMhzDigitsChange = procedure(Digits: Integer) of object;
|
||||
TOnDisplayParamChange = procedure(FFTSize, WindowType, SpecDetector,
|
||||
SpecAvgMode: Integer; SpecAvgTimeMS: Double) of object;
|
||||
TOnWaterfallParamChange = procedure(WfDetector, WfAvgMode: Integer;
|
||||
@@ -109,6 +110,7 @@ type
|
||||
FChkShowWaterfall: TCheckBox;
|
||||
FCmbFPS: TComboBox;
|
||||
FChkLightTheme: TCheckBox;
|
||||
FCmbFreqMhzDigits: TComboBox;
|
||||
|
||||
// ---- PA Settings tab controls ----
|
||||
FEdMaxPower: TSpinEdit;
|
||||
@@ -244,6 +246,7 @@ type
|
||||
FOnVisibilityChange: TOnVisibilityChange;
|
||||
FOnFPSChange: TOnFPSChange;
|
||||
FOnThemeChange: TOnThemeChange;
|
||||
FOnFreqMhzDigitsChange: TOnFreqMhzDigitsChange;
|
||||
FOnTXChange: TOnTXSettingsChange;
|
||||
|
||||
FLoading: Boolean;
|
||||
@@ -298,6 +301,7 @@ type
|
||||
procedure OnVisibilityChkChange(Sender: TObject);
|
||||
procedure OnFPSCmbChange(Sender: TObject);
|
||||
procedure OnLightThemeChkChange(Sender: TObject);
|
||||
procedure OnFreqMhzDigitsCmbChange(Sender: TObject);
|
||||
procedure OnMaxPowerChange(Sender: TObject);
|
||||
procedure OnBandCalChange(Sender: TObject);
|
||||
procedure OnCATSerialChange(Sender: TObject);
|
||||
@@ -335,6 +339,7 @@ type
|
||||
procedure LoadVisibility(ShowSpectrum, ShowWaterfall: Boolean);
|
||||
procedure LoadFPS(FPS: Integer);
|
||||
procedure LoadLightTheme(ALight: Boolean);
|
||||
procedure LoadFreqMhzDigits(Digits: Integer);
|
||||
procedure LoadPASettings(MaxPower: Double; const BandCal: array of Double);
|
||||
procedure LoadCATSettings(
|
||||
const SerEnabled: array of Boolean;
|
||||
@@ -357,6 +362,7 @@ type
|
||||
property OnVisibilityChange: TOnVisibilityChange read FOnVisibilityChange write FOnVisibilityChange;
|
||||
property OnFPSChange: TOnFPSChange read FOnFPSChange write FOnFPSChange;
|
||||
property OnThemeChange: TOnThemeChange read FOnThemeChange write FOnThemeChange;
|
||||
property OnFreqMhzDigitsChange: TOnFreqMhzDigitsChange read FOnFreqMhzDigitsChange write FOnFreqMhzDigitsChange;
|
||||
property OnTXChange: TOnTXSettingsChange read FOnTXChange write FOnTXChange;
|
||||
end;
|
||||
|
||||
@@ -783,6 +789,15 @@ begin
|
||||
FChkLightTheme.Font.Name := UI_FONT;
|
||||
FChkLightTheme.Font.Size := 9;
|
||||
FChkLightTheme.OnChange := OnLightThemeChkChange;
|
||||
|
||||
Grp := MakeGroupPanel(FPageDisplay, 'VFO Display', MARGIN, 378, 650, 92);
|
||||
|
||||
MakeLbl(Grp, 'Frequency range', PAD, R1 + 5, LW);
|
||||
FCmbFreqMhzDigits := MakeCombo(Grp, CX, R1, 240, OnFreqMhzDigitsCmbChange);
|
||||
FCmbFreqMhzDigits.Items.Add('up to 999 MHz (3 digits)');
|
||||
FCmbFreqMhzDigits.Items.Add('up to 9.999 GHz (4 digits)');
|
||||
FCmbFreqMhzDigits.Items.Add('up to 99.999 GHz (5 digits)');
|
||||
FCmbFreqMhzDigits.ItemIndex := 0;
|
||||
end;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -2014,6 +2029,23 @@ begin
|
||||
else ApplyTheme(DarkTheme);
|
||||
end;
|
||||
|
||||
procedure TSettingsForm.LoadFreqMhzDigits(Digits: Integer);
|
||||
begin
|
||||
FLoading := True;
|
||||
try
|
||||
FCmbFreqMhzDigits.ItemIndex := EnsureRange(Digits - 3, 0, 2);
|
||||
finally
|
||||
FLoading := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSettingsForm.OnFreqMhzDigitsCmbChange(Sender: TObject);
|
||||
begin
|
||||
if FLoading then Exit;
|
||||
if Assigned(FOnFreqMhzDigitsChange) then
|
||||
FOnFreqMhzDigitsChange(FCmbFreqMhzDigits.ItemIndex + 3);
|
||||
end;
|
||||
|
||||
procedure TSettingsForm.LoadPASettings(MaxPower: Double;
|
||||
const BandCal: array of Double);
|
||||
var i, n: Integer;
|
||||
|
||||
+2
-2
@@ -371,12 +371,12 @@ begin
|
||||
end;
|
||||
|
||||
function FormatFreqSV(Hz: Double): string;
|
||||
var Mhz, KHz, Rest: Integer;
|
||||
var Mhz: Int64; KHz, Rest: Integer;
|
||||
begin
|
||||
Mhz := Trunc(Hz / 1000000);
|
||||
KHz := Trunc((Hz - Mhz * 1000000) / 1000);
|
||||
Rest := Trunc(Hz) mod 1000;
|
||||
Result := Format('%3d.%3.3d.%3.3d', [Mhz, KHz, Rest]);
|
||||
Result := Format('%d.%3.3d.%3.3d', [Mhz, KHz, Rest]);
|
||||
end;
|
||||
|
||||
// ════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
+18
-11
@@ -323,22 +323,28 @@ begin
|
||||
'q("muteIc").onclick=()=>{cur.mute=!cur.mute;q("muteIc").textContent=cur.mute?"\uD83D\uDD07":"\uD83D\uDD0A";cmd("set_mute",cur.mute);};' +
|
||||
|
||||
'let stA=0,stAmem=100,stB=0,stBmem=100;' +
|
||||
'let freqMhzDigits=3,freqMaxHz=999999999;' +
|
||||
'function fmtVfo(hz,step){' +
|
||||
'const s=String(Math.max(0,Math.round(hz||0))).padStart(9,"0");' +
|
||||
'const N=freqMhzDigits+6;' +
|
||||
'const s=String(Math.max(0,Math.round(hz||0))).padStart(N,"0");' +
|
||||
'let h="",seenNZ=false;' +
|
||||
'for(let i=0;i<6;i++){' +
|
||||
'const st=Math.pow(10,8-i);' +
|
||||
'for(let i=0;i<freqMhzDigits;i++){' +
|
||||
'const st=Math.pow(10,freqMhzDigits+5-i);' +
|
||||
'if(s[i]!=="0")seenNZ=true;' +
|
||||
'const lead=(!seenNZ)?" lead":"";' +
|
||||
'const sel=(step>0&&st===step)?" sel":"";' +
|
||||
'h+="<span class=\"dg"+lead+sel+" data-s=\""+st+"\">"+s[i]+"</span>";' +
|
||||
'if(i===2)h+="<span class=\"sp\">.</span>";}' +
|
||||
'h+="<span class=\"dg"+lead+sel+"\" data-s=\""+st+"\">"+s[i]+"</span>";}' +
|
||||
'h+="<span class=\"sp\">.</span>";' +
|
||||
'h+="<span class=\"vfo-hz\">";' +
|
||||
'for(let i=6;i<9;i++){const st=Math.pow(10,8-i);' +
|
||||
'for(let i=freqMhzDigits;i<freqMhzDigits+3;i++){' +
|
||||
'const st=Math.pow(10,freqMhzDigits+5-i);' +
|
||||
'const sel=(step>0&&st===step)?" sel":"";' +
|
||||
'h+="<span class=\"dg"+sel+" data-s=\""+st+"\">"+s[i]+"</span>";}' +
|
||||
'return h;}' +
|
||||
'h+="<span class=\"dg"+sel+"\" data-s=\""+st+"\">"+s[i]+"</span>";}' +
|
||||
'h+="<span class=\"sp\">.</span><span class=\"vfo-hz\">";' +
|
||||
'for(let i=freqMhzDigits+3;i<N;i++){' +
|
||||
'const st=Math.pow(10,freqMhzDigits+5-i);' +
|
||||
'const sel=(step>0&&st===step)?" sel":"";' +
|
||||
'h+="<span class=\"dg"+sel+"\" data-s=\""+st+"\">"+s[i]+"</span>";}' +
|
||||
'h+="</span>";return h;}' +
|
||||
'function renderVfos(){q("vDispA").innerHTML=fmtVfo(vfoA,stA);q("vDispB").innerHTML=fmtVfo(vfoB,stB);}' +
|
||||
|
||||
'function bindVfo(dispId,getHz,setHz,getSt,setSt,getMem,setMem,onSend){' +
|
||||
@@ -348,12 +354,12 @@ begin
|
||||
'el.addEventListener("mouseleave",()=>{if(getSt()!==0){setSt(0);renderVfos();}});' +
|
||||
'el.addEventListener("wheel",e=>{e.preventDefault();e.stopPropagation();audioKick();' +
|
||||
'const dir=e.deltaY<0?1:-1,st=getSt()||getMem()||100;' +
|
||||
'const nf=cl(Math.round(getHz())+st*dir,30000,60000000);' +
|
||||
'const nf=cl(Math.round(getHz())+st*dir,30000,freqMaxHz);' +
|
||||
'setHz(nf);onSend(nf);},{passive:false});' +
|
||||
'el.addEventListener("dblclick",()=>{' +
|
||||
'const s=prompt("Set Hz",String(Math.round(getHz())));if(!s)return;' +
|
||||
'const f=parseInt(s.replace(/[^0-9]/g,""),10);if(!isFinite(f))return;' +
|
||||
'const nf=cl(f,30000,60000000);setHz(nf);renderVfos();onSend(nf);' +
|
||||
'const nf=cl(f,30000,freqMaxHz);setHz(nf);renderVfos();onSend(nf);' +
|
||||
'});}' +
|
||||
'bindVfo("vDispA",()=>vfoA,v=>{vfoA=v;},()=>stA,v=>{stA=v;},()=>stAmem,v=>{stAmem=v;},' +
|
||||
'function(nf){renderVfos();pend("freq");if(activeVfo==="A"){localCenter=nf;ws2({cmd:"freq",hz:nf});}else ws2({cmd:"freq_b",hz:nf});});' +
|
||||
@@ -483,6 +489,7 @@ begin
|
||||
'}' +
|
||||
'if(!isPending("freq")){vfoA=cur.vfo_a_hz||vfoA;}' +
|
||||
'if(msg.vfo_b_hz!=null)vfoB=msg.vfo_b_hz;' +
|
||||
'if(msg.freq_mhz_digits!=null){freqMhzDigits=Math.max(3,Math.min(5,msg.freq_mhz_digits|0));freqMaxHz=Math.pow(10,freqMhzDigits+6)-1;}' +
|
||||
'if(msg.active_vfo!=null&&!isPending("freq")){' +
|
||||
'const sv=msg.active_vfo===0?"A":"B";' +
|
||||
'if(sv!==activeVfo){activeVfo=sv;' +
|
||||
|
||||
+5
-2
@@ -242,6 +242,7 @@ type
|
||||
FOnTun: TWebCmdTun;
|
||||
FTuning: Boolean;
|
||||
FDuplex: Boolean;
|
||||
FFreqMhzDigits: Integer; // 3=999MHz, 4=9.999GHz, 5=99.999GHz
|
||||
FXvtrBands: TWebXvtrArray; // список enabled XVTR (для web-UI)
|
||||
FCurrentXvtr: Integer; // -1 = HF, иначе индекс активного XVTR
|
||||
FOnXvtrBand: TWebCmdXvtrBand;
|
||||
@@ -292,6 +293,7 @@ type
|
||||
AttnIdx: Integer; Tuning: Boolean; Duplex: Boolean);
|
||||
|
||||
property WebClientActive: Boolean read FWebClientActive;
|
||||
property FreqMhzDigits: Integer read FFreqMhzDigits write FFreqMhzDigits;
|
||||
|
||||
property OnFreq: TWebCmdFreq read FOnFreq write FOnFreq;
|
||||
property OnMode: TWebCmdMode read FOnMode write FOnMode;
|
||||
@@ -420,6 +422,7 @@ begin
|
||||
FSMeter := -120;
|
||||
FBandIdx := 5;
|
||||
FCurrentXvtr := -1;
|
||||
FFreqMhzDigits := 3;
|
||||
SetLength(FXvtrBands, 0);
|
||||
end;
|
||||
|
||||
@@ -1233,7 +1236,7 @@ begin
|
||||
'"running":%s,"mute":%s,"ctun":%s,' +
|
||||
'"nr_mode":%d,"nr":%s,"nb_mode":%d,"nb":%s,"snb":%s,"anf":%s,"connected":%s,' +
|
||||
'"transmitting":%s,"drive":%d,"attn_idx":%d,"tuning":%s,"dup":%s,' +
|
||||
'"xvtr_current":%d,"xvtr_bands":%s}',
|
||||
'"xvtr_current":%d,"xvtr_bands":%s,"freq_mhz_digits":%d}',
|
||||
[FFreq, FVfoB, FActiveVfo,
|
||||
FMode, MODE_N[FMode mod 8],
|
||||
FFilterIdx, FFilterBW,
|
||||
@@ -1257,7 +1260,7 @@ begin
|
||||
FAttnIdx,
|
||||
BoolToStr(FTuning, 'true', 'false'),
|
||||
BoolToStr(FDuplex, 'true', 'false'),
|
||||
FCurrentXvtr, XvtrJson
|
||||
FCurrentXvtr, XvtrJson, FFreqMhzDigits
|
||||
], FS);
|
||||
finally
|
||||
FStateLock.Leave;
|
||||
|
||||
Reference in New Issue
Block a user