Add FM mode improvements: NFM/FM filters, CTCSS, squelch; ADC and web settings

FM modulation:
- Replace 10 generic FM filter buttons with NFM (2.5kHz dev/11kHz BW) and FM
  (5.0kHz dev/16kHz BW); deviation applied to both RX and TX via WDSP
- Add FM squelch panel (SQL toggle + slider 0..100, per-band save/restore)
  with WDSP SetRXAFMSQRun/SetRXAFMSQThreshold (threshold = level/200.0)
- Add CTCSS panel with on/off toggle and custom flat-button tone picker popup
  (38 standard tones 67.0..250.3 Hz, default 67.0); tone selection and enable
  state saved per band via SetTXACTCSS*
- FM panels (SQL, CTCSS) shown only in FM mode, layout via RelayoutBelowBands
- PanelFilter height shrinks in FM mode so panels sit tight below filters
- FlatButton: handle CMTextChanged to invalidate on Caption change

ADC settings (Dither/Random):
- Add DitherEnabled/RandomEnabled to TGlobalSettings (default true)
- Pass as bitmask to ConfigureDDCs DDC Specific packet bytes 5/6
- Exposed in Settings → Advanced tab with live apply via ApplyADCSettings

Web server settings:
- Add TWebSettings (enabled, port, bind_addr, user, pass) stored globally
- WebServer: configurable port/bind IP via ParseIPv4; Reconfigure method
- Exposed in Settings → Advanced tab with live apply via ApplyWebSettings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-18 19:01:17 +03:00
co-authored by Claude Sonnet 4.6
parent 1368f249c4
commit 68d05657e6
7 changed files with 698 additions and 43 deletions
+178 -8
View File
@@ -48,6 +48,9 @@ type
TOnFPSChange = procedure(FPS: Integer) of object;
TOnThemeChange = procedure(LightTheme: Boolean) of object;
TOnWfAGCNFChange = procedure(WfAGC, WfNF: Boolean) of object;
TOnADCChange = procedure(Dither, Random: Boolean) of object;
TOnWebSettingsChange = procedure(Enabled: Boolean; Port: Integer;
const BindAddr, User, Pass: string) of object;
TOnCATChange = procedure(
const SerEnabled: array of Boolean;
const SerPort: array of string;
@@ -234,12 +237,23 @@ type
FCATTcpEn: TCheckBox;
FCATTcpPort: TSpinEdit;
// ---- Advanced tab controls ----
FChkDither: TCheckBox;
FChkRandom: TCheckBox;
FChkWebEnabled: TCheckBox;
FEdWebPort: TSpinEdit;
FEdWebBind: TEdit;
FEdWebUser: TEdit;
FEdWebPass: TEdit;
// ---- Close button ----
FBtnClose: TFlatButton;
// ---- Callbacks ----
FOnCATChange: TOnCATChange;
FOnPAChange: TOnPASettingsChange;
FOnADCChange: TOnADCChange;
FOnWebSettingsChange: TOnWebSettingsChange;
FOnDisplayChange: TOnDisplayParamChange;
FOnWaterfallChange: TOnWaterfallParamChange;
FOnGridChange: TOnGridParamChange;
@@ -262,6 +276,9 @@ type
procedure BuildCATTab;
procedure BuildTransmitTab;
procedure BuildAlexTab;
procedure BuildAdvancedTab;
procedure OnADCChkChange(Sender: TObject);
procedure OnWebAnyChange(Sender: TObject);
procedure CollectAlexFromUI;
procedure FireAlexChange;
procedure OnAlexAnyChange(Sender: TObject);
@@ -354,6 +371,9 @@ type
procedure LoadAlexSettings(const A: TAlexSettings; BoardType: Integer);
procedure LoadXvtrSettings(const X: TXvtrSettings);
procedure LoadWfAGCNF(AGC, NF: Boolean);
procedure LoadADCSettings(Dither, Random: Boolean);
procedure LoadWebSettings(Enabled: Boolean; Port: Integer;
const BindAddr, User, Pass: string);
property OnCATChange: TOnCATChange read FOnCATChange write FOnCATChange;
property OnAlexChange: TOnAlexChange read FOnAlexChange write FOnAlexChange;
@@ -370,6 +390,8 @@ type
property OnFreqMhzDigitsChange: TOnFreqMhzDigitsChange read FOnFreqMhzDigitsChange write FOnFreqMhzDigitsChange;
property OnTXChange: TOnTXSettingsChange read FOnTXChange write FOnTXChange;
property OnWfAGCNFChange: TOnWfAGCNFChange read FOnWfAGCNFChange write FOnWfAGCNFChange;
property OnADCChange: TOnADCChange read FOnADCChange write FOnADCChange;
property OnWebSettingsChange: TOnWebSettingsChange read FOnWebSettingsChange write FOnWebSettingsChange;
end;
implementation
@@ -606,6 +628,7 @@ begin
BuildRX1Tab;
BuildTransmitTab;
BuildPATab;
BuildAdvancedTab;
BuildCATTab;
BuildAlexTab;
BuildXvtrTab;
@@ -1561,6 +1584,23 @@ begin
FEdBandCal[i].Tag := i;
end;
end;
procedure TSettingsForm.BuildAdvancedTab;
const
MARGIN = 22;
GRP_PAD = 18;
LBL_W = 110;
ED_W = 200;
BTN_H = 22;
ROW_H = 28;
var
Grp: TPanel;
Chk: TCheckBox;
Ed: TEdit;
Spin: TSpinEdit;
Y: Integer;
begin
with TLabel.Create(Self) do
begin
Parent := FPageAdvanced;
@@ -1572,14 +1612,144 @@ begin
Font.Color := CLR_TEXT;
end;
with TLabel.Create(Self) do
begin
Parent := FPageAdvanced;
Caption := 'Transmit, CAT and DSP-only settings will appear here when they are wired to runtime settings.';
SetBounds(MARGIN, 48, 680, 20);
Font.Name := UI_FONT;
Font.Size := 9;
Font.Color := CLR_TEXTDIM;
// ── ADC ───────────────────────────────────────────────────────────────────
Grp := MakeGroupPanel(FPageAdvanced, 'ADC', MARGIN, 62, 420, 82);
Chk := TCheckBox.Create(Self);
Chk.Parent := Grp;
Chk.Caption := 'Dither Enabled';
Chk.SetBounds(GRP_PAD, 24, 260, BTN_H);
Chk.Font.Name := UI_FONT;
Chk.Font.Size := 9;
Chk.Font.Color := CLR_TEXT;
Chk.Checked := True;
Chk.OnChange := OnADCChkChange;
FChkDither := Chk;
Chk := TCheckBox.Create(Self);
Chk.Parent := Grp;
Chk.Caption := 'Random Enabled';
Chk.SetBounds(GRP_PAD, 50, 260, BTN_H);
Chk.Font.Name := UI_FONT;
Chk.Font.Size := 9;
Chk.Font.Color := CLR_TEXT;
Chk.Checked := True;
Chk.OnChange := OnADCChkChange;
FChkRandom := Chk;
// ── Web Server ────────────────────────────────────────────────────────────
Grp := MakeGroupPanel(FPageAdvanced, 'Web Server', MARGIN, 160, 420, 196);
Y := 24;
Chk := TCheckBox.Create(Self);
Chk.Parent := Grp;
Chk.Caption := 'Enabled';
Chk.SetBounds(GRP_PAD, Y, 260, BTN_H);
Chk.Font.Name := UI_FONT;
Chk.Font.Size := 9;
Chk.Font.Color := CLR_TEXT;
Chk.Checked := True;
Chk.OnChange := OnWebAnyChange;
FChkWebEnabled := Chk;
Y := Y + ROW_H + 4;
MakeLbl(Grp, 'Port:', GRP_PAD, Y + 4, LBL_W);
Spin := TSpinEdit.Create(Self);
Spin.Parent := Grp;
Spin.SetBounds(GRP_PAD + LBL_W, Y, 90, BTN_H + 2);
Spin.Color := CLR_INPUT;
Spin.Font.Color := CLR_INPUT_TEXT;
Spin.Font.Name := UI_FONT;
Spin.Font.Size := 9;
Spin.MinValue := 1;
Spin.MaxValue := 65535;
Spin.Value := 8080;
Spin.OnChange := OnWebAnyChange;
FEdWebPort := Spin;
Y := Y + ROW_H;
MakeLbl(Grp, 'Interface:', GRP_PAD, Y + 4, LBL_W);
Ed := TEdit.Create(Self);
Ed.Parent := Grp;
Ed.SetBounds(GRP_PAD + LBL_W, Y, ED_W, BTN_H + 2);
Ed.Color := CLR_INPUT;
Ed.Font.Color := CLR_INPUT_TEXT;
Ed.Font.Name := UI_FONT;
Ed.Font.Size := 9;
Ed.Text := '0.0.0.0';
Ed.OnChange := OnWebAnyChange;
FEdWebBind := Ed;
Y := Y + ROW_H;
MakeLbl(Grp, 'Username:', GRP_PAD, Y + 4, LBL_W);
Ed := TEdit.Create(Self);
Ed.Parent := Grp;
Ed.SetBounds(GRP_PAD + LBL_W, Y, ED_W, BTN_H + 2);
Ed.Color := CLR_INPUT;
Ed.Font.Color := CLR_INPUT_TEXT;
Ed.Font.Name := UI_FONT;
Ed.Font.Size := 9;
Ed.Text := 'admin';
Ed.OnChange := OnWebAnyChange;
FEdWebUser := Ed;
Y := Y + ROW_H;
MakeLbl(Grp, 'Password:', GRP_PAD, Y + 4, LBL_W);
Ed := TEdit.Create(Self);
Ed.Parent := Grp;
Ed.SetBounds(GRP_PAD + LBL_W, Y, ED_W, BTN_H + 2);
Ed.Color := CLR_INPUT;
Ed.Font.Color := CLR_INPUT_TEXT;
Ed.Font.Name := UI_FONT;
Ed.Font.Size := 9;
Ed.PasswordChar := '*';
Ed.Text := 'hpsdr';
Ed.OnChange := OnWebAnyChange;
FEdWebPass := Ed;
end;
procedure TSettingsForm.OnADCChkChange(Sender: TObject);
begin
if FLoading then Exit;
if Assigned(FOnADCChange) then
FOnADCChange(FChkDither.Checked, FChkRandom.Checked);
end;
procedure TSettingsForm.OnWebAnyChange(Sender: TObject);
begin
if FLoading then Exit;
if Assigned(FOnWebSettingsChange) then
FOnWebSettingsChange(
FChkWebEnabled.Checked,
FEdWebPort.Value,
FEdWebBind.Text,
FEdWebUser.Text,
FEdWebPass.Text);
end;
procedure TSettingsForm.LoadADCSettings(Dither, Random: Boolean);
begin
FLoading := True;
try
FChkDither.Checked := Dither;
FChkRandom.Checked := Random;
finally
FLoading := False;
end;
end;
procedure TSettingsForm.LoadWebSettings(Enabled: Boolean; Port: Integer;
const BindAddr, User, Pass: string);
begin
FLoading := True;
try
FChkWebEnabled.Checked := Enabled;
FEdWebPort.Value := EnsureRange(Port, 1, 65535);
FEdWebBind.Text := BindAddr;
FEdWebUser.Text := User;
FEdWebPass.Text := Pass;
finally
FLoading := False;
end;
end;