mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 19:45:09 +00:00
New units: CATEngine (Kenwood + Thetis ZZ* commands), CATSerial (up to 4 serial ports), CATTcp (multi-client TCP server on port 4992). MainForm wired with TCATContext callbacks reusing existing WebOn* handlers. SettingsForm gets a new CAT tab with 4 serial port groups and TCP section. Settings.pas extended with CAT config fields (per-device, JSON-persisted). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1548 lines
48 KiB
ObjectPascal
1548 lines
48 KiB
ObjectPascal
unit SettingsForm;
|
||
|
||
{
|
||
SettingsForm.pas — диалог настроек EWSDR SDR приложения.
|
||
|
||
Вкладки: General | Audio | Display | DSP | Transmit | PA Settings | CAT
|
||
Display имеет подвкладки: General | RX1 | RX2 | TX
|
||
|
||
Все изменения применяются МГНОВЕННО через events:
|
||
OnDisplayChange — изменены FFT/Window/Detector/Avg параметры
|
||
OnWaterfallChange — изменены параметры водопада
|
||
OnGridChange — изменена сетка спектра
|
||
OnAudioChange — изменено аудио устройство/буфер
|
||
OnSampleRateChange — изменён audio output sample rate (только PortAudio, DDC не трогается)
|
||
|
||
Для применения настроек: создайте форму, зарегистрируйте callbacks,
|
||
потом вызовите Show или ShowModal.
|
||
}
|
||
|
||
{$IFDEF FPC}
|
||
{$MODE Delphi}
|
||
{$ENDIF}
|
||
|
||
interface
|
||
|
||
uses
|
||
Classes, SysUtils, Math,
|
||
Forms, Controls, Graphics, Dialogs,
|
||
StdCtrls, ExtCtrls, Spin,
|
||
FlatButton, AudioOutput, AudioInput;
|
||
|
||
type
|
||
// PA: MaxPower в Вт, BandCal[0..10] — калибровка 38.8..100.0 на диапазон
|
||
TOnPASettingsChange = procedure(MaxPower: Double;
|
||
const BandCal: array of Double) of object;
|
||
|
||
TOnDisplayParamChange = procedure(FFTSize, WindowType, SpecDetector,
|
||
SpecAvgMode: Integer; SpecAvgTimeMS: Double) of object;
|
||
TOnWaterfallParamChange = procedure(WfDetector, WfAvgMode: Integer;
|
||
WfAvgTimeMS, WfHigh, WfLow, WfAGCOffset: Double) of object;
|
||
TOnGridParamChange = procedure(RefLevel, Range, GridStep: Double) of object;
|
||
TOnAudioDevChange = procedure(DevIndex: Integer; const DevName: string) of object;
|
||
TOnAudioInDevChange = procedure(DevIndex: Integer; const DevName: string) of object;
|
||
TOnVisibilityChange = procedure(ShowSpectrum, ShowWaterfall: Boolean) of object;
|
||
TOnFPSChange = procedure(FPS: Integer) of object;
|
||
TOnCATChange = procedure(
|
||
const SerEnabled: array of Boolean;
|
||
const SerPort: array of string;
|
||
const SerBaud: array of Integer;
|
||
const SerDataBits: array of Integer;
|
||
const SerStopBits: array of Integer;
|
||
const SerParity: array of Integer;
|
||
TcpEnabled: Boolean; TcpPort: Integer) of object;
|
||
|
||
{ TSettingsForm }
|
||
TSettingsForm = class(TForm)
|
||
private
|
||
// ---- Layout ----
|
||
FNavPanel: TPanel;
|
||
FContentPanel: TPanel;
|
||
FPageAudio: TScrollBox;
|
||
FPageDisplay: TScrollBox;
|
||
FPageSpectrum: TScrollBox;
|
||
FPageWaterfall: TScrollBox;
|
||
FPagePA: TScrollBox;
|
||
FPageAdvanced: TScrollBox;
|
||
FPageCAT: TScrollBox;
|
||
FNavAudio: TFlatButton;
|
||
FNavDisplay: TFlatButton;
|
||
FNavSpectrum: TFlatButton;
|
||
FNavWaterfall: TFlatButton;
|
||
FNavPA: TFlatButton;
|
||
FNavAdvanced: TFlatButton;
|
||
FNavCAT: TFlatButton;
|
||
|
||
// ---- Audio tab controls ----
|
||
FCmbRXDev: TComboBox;
|
||
FRXDevIndices: array[0..63] of Integer;
|
||
FRXDevCount: Integer;
|
||
FCmbTXDev: TComboBox;
|
||
FTXDevIndices: array[0..63] of Integer;
|
||
FTXDevCount: Integer;
|
||
|
||
// ---- RX1 sub-tab controls ----
|
||
FCmbFFTSize: TComboBox;
|
||
FCmbWindow: TComboBox;
|
||
FCmbSpecDet: TComboBox;
|
||
FCmbSpecAvg: TComboBox;
|
||
FSpecAvgTime: TFloatSpinEdit;
|
||
FCmbWfDet: TComboBox;
|
||
FCmbWfAvg: TComboBox;
|
||
FWfAvgTime: TFloatSpinEdit;
|
||
FWfHigh: TFloatSpinEdit;
|
||
FWfLow: TFloatSpinEdit;
|
||
FWfAGCOffset: TFloatSpinEdit;
|
||
FEdRefLevel: TEdit;
|
||
FEdRange: TEdit;
|
||
FCmbGridStep: TComboBox;
|
||
|
||
// ---- General display tab controls ----
|
||
FChkShowSpectrum: TCheckBox;
|
||
FChkShowWaterfall: TCheckBox;
|
||
FCmbFPS: TComboBox;
|
||
|
||
// ---- PA Settings tab controls ----
|
||
FEdMaxPower: TSpinEdit;
|
||
FEdBandCal: array[0..10] of TFloatSpinEdit;
|
||
|
||
// ---- CAT tab controls ----
|
||
FCATSerialEn: array[0..3] of TCheckBox;
|
||
FCATSerialPort: array[0..3] of TEdit;
|
||
FCATSerialBaud: array[0..3] of TComboBox;
|
||
FCATSerialDataBits: array[0..3] of TComboBox;
|
||
FCATSerialStopBits: array[0..3] of TComboBox;
|
||
FCATSerialParity: array[0..3] of TComboBox;
|
||
FCATTcpEn: TCheckBox;
|
||
FCATTcpPort: TSpinEdit;
|
||
|
||
// ---- Close button ----
|
||
FBtnClose: TFlatButton;
|
||
|
||
// ---- Callbacks ----
|
||
FOnCATChange: TOnCATChange;
|
||
FOnPAChange: TOnPASettingsChange;
|
||
FOnDisplayChange: TOnDisplayParamChange;
|
||
FOnWaterfallChange: TOnWaterfallParamChange;
|
||
FOnGridChange: TOnGridParamChange;
|
||
FOnAudioDevChange: TOnAudioDevChange;
|
||
FOnAudioInDevChange: TOnAudioInDevChange;
|
||
FOnVisibilityChange: TOnVisibilityChange;
|
||
FOnFPSChange: TOnFPSChange;
|
||
|
||
FLoading: Boolean;
|
||
|
||
procedure BuildUI;
|
||
procedure BuildAudioTab;
|
||
procedure BuildDisplayTab;
|
||
procedure BuildRX1Tab;
|
||
procedure BuildPATab;
|
||
procedure BuildCATTab;
|
||
procedure ApplyTheme;
|
||
procedure NavClick(Sender: TObject);
|
||
procedure SelectPage(APage: TWinControl; ANav: TFlatButton);
|
||
|
||
function MakeLbl(AParent: TWinControl; const Cap: string;
|
||
ALeft, ATop, AW: Integer): TLabel;
|
||
function MakeCombo(AParent: TWinControl; ALeft, ATop, AW: Integer;
|
||
OnChange: TNotifyEvent): TComboBox;
|
||
function MakeGroupPanel(AParent: TWinControl; const Cap: string;
|
||
ALeft, ATop, AW, AH: Integer): TPanel;
|
||
function MakeScrollPage: TScrollBox;
|
||
function MakeNavButton(const Cap: string; ATop: Integer): TFlatButton;
|
||
|
||
procedure OnFFTSizeChange(Sender: TObject);
|
||
procedure OnWindowChange(Sender: TObject);
|
||
procedure OnSpecDetChange(Sender: TObject);
|
||
procedure OnSpecAvgModeChange(Sender: TObject);
|
||
procedure OnSpecAvgTimeChange(Sender: TObject);
|
||
procedure OnWfDetChange(Sender: TObject);
|
||
procedure OnWfAvgModeChange(Sender: TObject);
|
||
procedure OnWfAvgTimeChange(Sender: TObject);
|
||
procedure OnWfThresholdChange(Sender: TObject);
|
||
procedure OnRefLevelChange(Sender: TObject);
|
||
procedure OnRangeChange(Sender: TObject);
|
||
procedure OnGridStepChange(Sender: TObject);
|
||
procedure OnRXDevChange(Sender: TObject);
|
||
procedure OnTXDevChange(Sender: TObject);
|
||
procedure OnVisibilityChkChange(Sender: TObject);
|
||
procedure OnFPSCmbChange(Sender: TObject);
|
||
procedure OnMaxPowerChange(Sender: TObject);
|
||
procedure OnBandCalChange(Sender: TObject);
|
||
procedure OnCATSerialChange(Sender: TObject);
|
||
procedure OnCATTcpChange(Sender: TObject);
|
||
procedure FireCATChange;
|
||
procedure BtnCloseClick(Sender: TObject);
|
||
|
||
procedure FireDisplayChange;
|
||
procedure FireWaterfallChange;
|
||
procedure FireGridChange;
|
||
|
||
function GetSpecAvgTimeMS: Double;
|
||
function GetWfAvgTimeMS: Double;
|
||
function GetWfHigh: Double;
|
||
function GetWfLow: Double;
|
||
function GetWfAGCOffset: Double;
|
||
function GetRefLevel: Double;
|
||
function GetRange: Double;
|
||
function GetGridStep: Double;
|
||
function GetFFTSize: Integer;
|
||
|
||
public
|
||
constructor Create(AOwner: TComponent); override;
|
||
|
||
procedure LoadValues(
|
||
FFTSize, WinType, SpecDet, SpecAvgMode: Integer;
|
||
SpecAvgTimeMS: Double;
|
||
WfDet, WfAvgMode: Integer;
|
||
WfAvgTimeMS, WfHigh, WfLow, WfAGCOffset: Double;
|
||
RefLevel, Range, GridStep: Double;
|
||
const AudioOutDevName: string;
|
||
const AudioInDevName: string);
|
||
|
||
procedure RefreshAudioDevices(AudioOut: TAudioOutput; AudioIn: TAudioInput);
|
||
procedure LoadVisibility(ShowSpectrum, ShowWaterfall: Boolean);
|
||
procedure LoadFPS(FPS: Integer);
|
||
procedure LoadPASettings(MaxPower: Double; const BandCal: array of Double);
|
||
procedure LoadCATSettings(
|
||
const SerEnabled: array of Boolean;
|
||
const SerPort: array of string;
|
||
const SerBaud, SerDataBits, SerStopBits, SerParity: array of Integer;
|
||
TcpEnabled: Boolean; TcpPort: Integer);
|
||
|
||
property OnCATChange: TOnCATChange read FOnCATChange write FOnCATChange;
|
||
property OnPAChange: TOnPASettingsChange read FOnPAChange write FOnPAChange;
|
||
property OnDisplayChange: TOnDisplayParamChange read FOnDisplayChange write FOnDisplayChange;
|
||
property OnWaterfallChange: TOnWaterfallParamChange read FOnWaterfallChange write FOnWaterfallChange;
|
||
property OnGridChange: TOnGridParamChange read FOnGridChange write FOnGridChange;
|
||
property OnAudioDevChange: TOnAudioDevChange read FOnAudioDevChange write FOnAudioDevChange;
|
||
property OnAudioInDevChange: TOnAudioInDevChange read FOnAudioInDevChange write FOnAudioInDevChange;
|
||
property OnVisibilityChange: TOnVisibilityChange read FOnVisibilityChange write FOnVisibilityChange;
|
||
property OnFPSChange: TOnFPSChange read FOnFPSChange write FOnFPSChange;
|
||
end;
|
||
|
||
implementation
|
||
|
||
const
|
||
CLR_BG = TColor($00121212);
|
||
CLR_PANEL = TColor($001A1A1A);
|
||
CLR_TEXT = TColor($00E0E0E0);
|
||
CLR_TEXTDIM = TColor($00888888);
|
||
CLR_BORDER = TColor($00303030);
|
||
CLR_ACCENT = TColor($0040FF80);
|
||
CLR_INPUT = TColor($00FFFFFF);
|
||
CLR_INPUT_TEXT = TColor($00202020);
|
||
{$IFDEF MSWINDOWS}
|
||
UI_FONT = 'Segoe UI';
|
||
{$ELSE}
|
||
UI_FONT = 'Sans';
|
||
{$ENDIF}
|
||
BTN_H = 24;
|
||
GRP_TITLE_H = 22; // высота заголовка в group-панелях (title label + divider)
|
||
|
||
CAT_BAUD_VALS: array[0..7] of Integer = (1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200);
|
||
CAT_BAUD_NAMES: array[0..7] of string = ('1200','2400','4800','9600','19200','38400','57600','115200');
|
||
|
||
FFT_SIZES: array[0..6] of Integer = (4096, 8192, 16384, 32768, 65536, 131072, 262144);
|
||
FFT_NAMES: array[0..6] of string = ('4096','8192','16384','32768','65536','131072','262144');
|
||
|
||
WINDOW_NAMES: array[0..6] of string = (
|
||
'Rectangular', '4-term Blackman-Harris', 'Hann',
|
||
'Flat-top', 'Hamming', 'Kaiser', '7-term Blackman-Harris');
|
||
|
||
DETECTOR_NAMES: array[0..4] of string = (
|
||
'Peak', 'Rosenfell', 'Average', 'Sample', 'RMS');
|
||
|
||
AVGMODE_NAMES: array[0..3] of string = (
|
||
'None', 'Recursive', 'Time Window', 'Log Recursive');
|
||
AVGMODE_VALUES: array[0..3] of Integer = (0, 1, 2, 3);
|
||
WF_AVGMODE_NAMES: array[0..3] of string = (
|
||
'None', 'Recursive', 'Time Window', 'Log Recursive');
|
||
WF_AVGMODE_VALUES: array[0..3] of Integer = (0, 1, 2, 3);
|
||
|
||
GRID_STEPS: array[0..4] of Double = (5.0, 10.0, 20.0, 30.0, 40.0);
|
||
GRID_STEP_NAMES: array[0..4] of string = ('5 dB','10 dB','20 dB','30 dB','40 dB');
|
||
|
||
FPS_VALUES: array[0..12] of Integer = (5, 10, 15, 20, 25, 30, 40, 50, 60, 75, 80, 90, 100);
|
||
FPS_NAMES: array[0..12] of string = ('5 fps','10 fps','15 fps','20 fps','25 fps','30 fps',
|
||
'40 fps','50 fps','60 fps','75 fps','80 fps','90 fps','100 fps');
|
||
|
||
PA_BAND_NAMES: array[0..10] of string =
|
||
('160m','80m','60m','40m','30m','20m','17m','15m','12m','10m','6m');
|
||
|
||
{ TSettingsForm }
|
||
|
||
constructor TSettingsForm.Create(AOwner: TComponent);
|
||
begin
|
||
inherited CreateNew(AOwner);
|
||
Caption := 'Settings';
|
||
Width := 900;
|
||
Height := 660;
|
||
Position := poScreenCenter;
|
||
BorderStyle := bsSizeable;
|
||
Color := CLR_BG;
|
||
Font.Name := UI_FONT;
|
||
Font.Size := 9;
|
||
Font.Color := CLR_TEXT;
|
||
FLoading := False;
|
||
FRXDevCount := 0;
|
||
BuildUI;
|
||
ApplyTheme;
|
||
end;
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Helpers
|
||
// ---------------------------------------------------------------------------
|
||
|
||
function TSettingsForm.MakeLbl(AParent: TWinControl; const Cap: string;
|
||
ALeft, ATop, AW: Integer): TLabel;
|
||
begin
|
||
Result := TLabel.Create(Self);
|
||
Result.Parent := AParent;
|
||
Result.Caption := Cap;
|
||
Result.Left := ALeft;
|
||
Result.Top := ATop;
|
||
if AW > 0 then Result.Width := AW;
|
||
Result.Font.Color := CLR_TEXTDIM;
|
||
Result.Font.Name := UI_FONT;
|
||
Result.Font.Size := 9;
|
||
end;
|
||
|
||
function TSettingsForm.MakeCombo(AParent: TWinControl; ALeft, ATop, AW: Integer;
|
||
OnChange: TNotifyEvent): TComboBox;
|
||
begin
|
||
Result := TComboBox.Create(Self);
|
||
Result.Parent := AParent;
|
||
Result.Left := ALeft;
|
||
Result.Top := ATop;
|
||
Result.Width := AW;
|
||
Result.Height := BTN_H;
|
||
Result.Style := csDropDownList;
|
||
Result.Color := CLR_INPUT;
|
||
Result.Font.Color := CLR_INPUT_TEXT;
|
||
Result.Font.Name := UI_FONT;
|
||
Result.Font.Size := 9;
|
||
Result.OnChange := OnChange;
|
||
end;
|
||
|
||
// Создаёт панель-группу с заголовком и разделителем (вместо TGroupBox).
|
||
// На Windows TGroupBox рисует фрейм системными цветами, TPanel — нет.
|
||
function TSettingsForm.MakeGroupPanel(AParent: TWinControl; const Cap: string;
|
||
ALeft, ATop, AW, AH: Integer): TPanel;
|
||
var
|
||
TitleLbl: TLabel;
|
||
Divider: TPanel;
|
||
begin
|
||
Result := TPanel.Create(Self);
|
||
Result.Parent := AParent;
|
||
Result.SetBounds(ALeft, ATop, AW, AH);
|
||
Result.BevelOuter := bvNone;
|
||
Result.Color := CLR_PANEL;
|
||
|
||
TitleLbl := TLabel.Create(Self);
|
||
TitleLbl.Parent := Result;
|
||
TitleLbl.Caption := Cap;
|
||
TitleLbl.SetBounds(8, 5, AW - 16, 14);
|
||
TitleLbl.Font.Color := CLR_ACCENT;
|
||
TitleLbl.Font.Name := UI_FONT;
|
||
TitleLbl.Font.Size := 9;
|
||
TitleLbl.Font.Style := [fsBold];
|
||
|
||
Divider := TPanel.Create(Self);
|
||
Divider.Parent := Result;
|
||
Divider.SetBounds(0, GRP_TITLE_H, AW + 200, 1);
|
||
Divider.BevelOuter := bvNone;
|
||
Divider.Color := CLR_BORDER;
|
||
end;
|
||
|
||
function TSettingsForm.MakeScrollPage: TScrollBox;
|
||
begin
|
||
Result := TScrollBox.Create(Self);
|
||
Result.Parent := FContentPanel;
|
||
Result.Align := alClient;
|
||
Result.BorderStyle := bsNone;
|
||
Result.Color := CLR_BG;
|
||
Result.AutoScroll := True;
|
||
Result.Visible := False;
|
||
end;
|
||
|
||
function TSettingsForm.MakeNavButton(const Cap: string; ATop: Integer): TFlatButton;
|
||
begin
|
||
Result := TFlatButton.Create(Self);
|
||
Result.Parent := FNavPanel;
|
||
Result.Caption := Cap;
|
||
Result.SetBounds(10, ATop, 166, 32);
|
||
Result.Anchors := [akLeft, akTop, akRight];
|
||
Result.OnClick := NavClick;
|
||
Result.ClrNorm := CLR_PANEL;
|
||
Result.ClrBorder := CLR_PANEL;
|
||
Result.ClrHot := TColor($00242424);
|
||
Result.ClrActive := TColor($00204030);
|
||
Result.ClrText := CLR_TEXT;
|
||
Result.ClrTextAct := CLR_ACCENT;
|
||
Result.Font.Name := UI_FONT;
|
||
Result.Font.Size := 9;
|
||
Result.Font.Style := [];
|
||
end;
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// BuildUI
|
||
// ---------------------------------------------------------------------------
|
||
|
||
procedure TSettingsForm.BuildUI;
|
||
begin
|
||
FNavPanel := TPanel.Create(Self);
|
||
FNavPanel.Parent := Self;
|
||
FNavPanel.Align := alLeft;
|
||
FNavPanel.Width := 188;
|
||
FNavPanel.BevelOuter := bvNone;
|
||
FNavPanel.Color := TColor($00151515);
|
||
|
||
with TLabel.Create(Self) do
|
||
begin
|
||
Parent := FNavPanel;
|
||
Caption := 'Settings';
|
||
SetBounds(14, 14, 160, 24);
|
||
Font.Name := UI_FONT;
|
||
Font.Size := 14;
|
||
Font.Style := [fsBold];
|
||
Font.Color := CLR_TEXT;
|
||
end;
|
||
|
||
with TLabel.Create(Self) do
|
||
begin
|
||
Parent := FNavPanel;
|
||
Caption := 'EWSDR';
|
||
SetBounds(14, 39, 160, 18);
|
||
Font.Name := UI_FONT;
|
||
Font.Size := 9;
|
||
Font.Color := CLR_TEXTDIM;
|
||
end;
|
||
|
||
FNavAudio := MakeNavButton('Audio', 74);
|
||
FNavDisplay := MakeNavButton('Display', 110);
|
||
FNavSpectrum := MakeNavButton('Spectrum', 146);
|
||
FNavWaterfall := MakeNavButton('Waterfall', 182);
|
||
FNavPA := MakeNavButton('Power Amplifier', 218);
|
||
FNavAdvanced := MakeNavButton('Advanced', 254);
|
||
FNavCAT := MakeNavButton('CAT', 290);
|
||
|
||
FContentPanel := TPanel.Create(Self);
|
||
FContentPanel.Parent := Self;
|
||
FContentPanel.Align := alClient;
|
||
FContentPanel.BevelOuter := bvNone;
|
||
FContentPanel.Color := CLR_BG;
|
||
|
||
FPageAudio := MakeScrollPage;
|
||
FPageDisplay := MakeScrollPage;
|
||
FPageSpectrum := MakeScrollPage;
|
||
FPageWaterfall := MakeScrollPage;
|
||
FPagePA := MakeScrollPage;
|
||
FPageAdvanced := MakeScrollPage;
|
||
FPageCAT := MakeScrollPage;
|
||
|
||
BuildAudioTab;
|
||
BuildDisplayTab;
|
||
BuildRX1Tab;
|
||
BuildPATab;
|
||
BuildCATTab;
|
||
|
||
FBtnClose := TFlatButton.Create(Self);
|
||
FBtnClose.Parent := Self;
|
||
FBtnClose.Caption := 'Close';
|
||
FBtnClose.SetBounds(Width - 106, Height - 40, 92, 28);
|
||
FBtnClose.Anchors := [akRight, akBottom];
|
||
FBtnClose.OnClick := BtnCloseClick;
|
||
FBtnClose.ClrNorm := CLR_PANEL;
|
||
FBtnClose.ClrBorder := TColor($00404040);
|
||
FBtnClose.ClrHot := TColor($00303030);
|
||
FBtnClose.ClrActive := TColor($00003300);
|
||
FBtnClose.ClrText := CLR_TEXT;
|
||
FBtnClose.ClrTextAct:= CLR_ACCENT;
|
||
FBtnClose.Font.Name := UI_FONT;
|
||
FBtnClose.Font.Size := 9;
|
||
|
||
SelectPage(FPageAudio, FNavAudio);
|
||
end;
|
||
|
||
procedure TSettingsForm.NavClick(Sender: TObject);
|
||
begin
|
||
if Sender = FNavAudio then SelectPage(FPageAudio, FNavAudio)
|
||
else if Sender = FNavDisplay then SelectPage(FPageDisplay, FNavDisplay)
|
||
else if Sender = FNavSpectrum then SelectPage(FPageSpectrum, FNavSpectrum)
|
||
else if Sender = FNavWaterfall then SelectPage(FPageWaterfall, FNavWaterfall)
|
||
else if Sender = FNavPA then SelectPage(FPagePA, FNavPA)
|
||
else if Sender = FNavAdvanced then SelectPage(FPageAdvanced, FNavAdvanced)
|
||
else if Sender = FNavCAT then SelectPage(FPageCAT, FNavCAT);
|
||
end;
|
||
|
||
procedure TSettingsForm.SelectPage(APage: TWinControl; ANav: TFlatButton);
|
||
begin
|
||
FPageAudio.Visible := APage = FPageAudio;
|
||
FPageDisplay.Visible := APage = FPageDisplay;
|
||
FPageSpectrum.Visible := APage = FPageSpectrum;
|
||
FPageWaterfall.Visible := APage = FPageWaterfall;
|
||
FPagePA.Visible := APage = FPagePA;
|
||
FPageAdvanced.Visible := APage = FPageAdvanced;
|
||
FPageCAT.Visible := APage = FPageCAT;
|
||
|
||
FNavAudio.Active := ANav = FNavAudio;
|
||
FNavDisplay.Active := ANav = FNavDisplay;
|
||
FNavSpectrum.Active := ANav = FNavSpectrum;
|
||
FNavWaterfall.Active := ANav = FNavWaterfall;
|
||
FNavPA.Active := ANav = FNavPA;
|
||
FNavAdvanced.Active := ANav = FNavAdvanced;
|
||
FNavCAT.Active := ANav = FNavCAT;
|
||
end;
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// BuildAudioTab
|
||
// ---------------------------------------------------------------------------
|
||
|
||
procedure TSettingsForm.BuildAudioTab;
|
||
const
|
||
MARGIN = 22;
|
||
PAD = 18;
|
||
R1 = 42;
|
||
STEP = 42;
|
||
LW = 150;
|
||
CX = PAD + LW + 12;
|
||
CMB_W = 460;
|
||
|
||
var
|
||
Grp: TPanel;
|
||
begin
|
||
with TLabel.Create(Self) do
|
||
begin
|
||
Parent := FPageAudio;
|
||
Caption := 'Audio';
|
||
SetBounds(MARGIN, 18, 400, 28);
|
||
Font.Name := UI_FONT;
|
||
Font.Size := 16;
|
||
Font.Style := [fsBold];
|
||
Font.Color := CLR_TEXT;
|
||
end;
|
||
|
||
with TLabel.Create(Self) do
|
||
begin
|
||
Parent := FPageAudio;
|
||
Caption := 'Input and output devices used by the receiver and transmitter.';
|
||
SetBounds(MARGIN, 48, 560, 20);
|
||
Font.Name := UI_FONT;
|
||
Font.Size := 9;
|
||
Font.Color := CLR_TEXTDIM;
|
||
end;
|
||
|
||
Grp := MakeGroupPanel(FPageAudio, 'Audio Devices', MARGIN, 86, 650, 142);
|
||
|
||
MakeLbl(Grp, 'TX input device', PAD, R1 + 5, LW);
|
||
FCmbTXDev := MakeCombo(Grp, CX, R1, CMB_W, OnTXDevChange);
|
||
FCmbTXDev.Items.Add('None');
|
||
|
||
MakeLbl(Grp, 'RX output device', PAD, R1 + STEP + 5, LW);
|
||
FCmbRXDev := MakeCombo(Grp, CX, R1 + STEP, CMB_W, OnRXDevChange);
|
||
FCmbRXDev.Items.Add('Default');
|
||
end;
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// BuildDisplayTab
|
||
// ---------------------------------------------------------------------------
|
||
|
||
procedure TSettingsForm.BuildDisplayTab;
|
||
const
|
||
MARGIN = 22;
|
||
PAD = 18;
|
||
R1 = 42;
|
||
CHKW = 220;
|
||
LW = 150;
|
||
CX = PAD + LW + 12;
|
||
|
||
var
|
||
i: Integer;
|
||
Grp: TPanel;
|
||
begin
|
||
with TLabel.Create(Self) do
|
||
begin
|
||
Parent := FPageDisplay;
|
||
Caption := 'Display';
|
||
SetBounds(MARGIN, 18, 400, 28);
|
||
Font.Name := UI_FONT;
|
||
Font.Size := 16;
|
||
Font.Style := [fsBold];
|
||
Font.Color := CLR_TEXT;
|
||
end;
|
||
|
||
with TLabel.Create(Self) do
|
||
begin
|
||
Parent := FPageDisplay;
|
||
Caption := 'General visual options. Spectrum and waterfall processing are split into their own pages.';
|
||
SetBounds(MARGIN, 48, 680, 20);
|
||
Font.Name := UI_FONT;
|
||
Font.Size := 9;
|
||
Font.Color := CLR_TEXTDIM;
|
||
end;
|
||
|
||
Grp := MakeGroupPanel(FPageDisplay, 'Visible Panes', MARGIN, 86, 650, 86);
|
||
|
||
FChkShowSpectrum := TCheckBox.Create(Self);
|
||
FChkShowSpectrum.Parent := Grp;
|
||
FChkShowSpectrum.Caption := 'Spectrum';
|
||
FChkShowSpectrum.SetBounds(PAD, R1, CHKW, 22);
|
||
FChkShowSpectrum.Checked := True;
|
||
FChkShowSpectrum.Font.Color := CLR_TEXT;
|
||
FChkShowSpectrum.Font.Name := UI_FONT;
|
||
FChkShowSpectrum.Font.Size := 9;
|
||
FChkShowSpectrum.OnChange := OnVisibilityChkChange;
|
||
|
||
FChkShowWaterfall := TCheckBox.Create(Self);
|
||
FChkShowWaterfall.Parent := Grp;
|
||
FChkShowWaterfall.Caption := 'Waterfall';
|
||
FChkShowWaterfall.SetBounds(PAD + CHKW + 20, R1, CHKW, 22);
|
||
FChkShowWaterfall.Checked := True;
|
||
FChkShowWaterfall.Font.Color := CLR_TEXT;
|
||
FChkShowWaterfall.Font.Name := UI_FONT;
|
||
FChkShowWaterfall.Font.Size := 9;
|
||
FChkShowWaterfall.OnChange := OnVisibilityChkChange;
|
||
|
||
Grp := MakeGroupPanel(FPageDisplay, 'Performance', MARGIN, 186, 650, 92);
|
||
|
||
MakeLbl(Grp, 'Refresh rate', PAD, R1 + 5, LW);
|
||
FCmbFPS := MakeCombo(Grp, CX, R1, 140, OnFPSCmbChange);
|
||
for i := 0 to High(FPS_NAMES) do
|
||
FCmbFPS.Items.Add(FPS_NAMES[i]);
|
||
FCmbFPS.ItemIndex := 8;
|
||
end;
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// BuildRX1Tab
|
||
// ---------------------------------------------------------------------------
|
||
|
||
procedure TSettingsForm.BuildRX1Tab;
|
||
const
|
||
MARGIN = 22;
|
||
PAD = 18;
|
||
LW = 150;
|
||
CX = PAD + LW + 12;
|
||
CMB_W = 230;
|
||
CMB_W_LONG = 300;
|
||
SPW = 96;
|
||
EDT_W = 96;
|
||
STEP = 42;
|
||
R1 = 42;
|
||
|
||
var
|
||
Grp: TPanel;
|
||
i: Integer;
|
||
|
||
function MkFloat(AX, AY, AW: Integer; AValue, AMin, AMax, AInc: Double;
|
||
AOnChange: TNotifyEvent): TFloatSpinEdit;
|
||
begin
|
||
Result := TFloatSpinEdit.Create(Self);
|
||
Result.Parent := Grp;
|
||
Result.SetBounds(AX, AY, AW, BTN_H);
|
||
Result.Value := AValue; Result.MinValue := AMin;
|
||
Result.MaxValue := AMax; Result.Increment := AInc;
|
||
Result.DecimalPlaces := 1;
|
||
Result.Color := CLR_INPUT; Result.Font.Color := CLR_INPUT_TEXT;
|
||
Result.Font.Name := UI_FONT; Result.Font.Size := 9;
|
||
Result.OnChange := AOnChange;
|
||
end;
|
||
|
||
function MkEdit(AX, AY, AW: Integer; const AText: string;
|
||
AOnExit: TNotifyEvent): TEdit;
|
||
begin
|
||
Result := TEdit.Create(Self);
|
||
Result.Parent := Grp;
|
||
Result.SetBounds(AX, AY, AW, BTN_H);
|
||
Result.Color := CLR_INPUT; Result.Font.Color := CLR_INPUT_TEXT;
|
||
Result.Font.Name := UI_FONT; Result.Font.Size := 9;
|
||
Result.Text := AText; Result.OnExit := AOnExit;
|
||
end;
|
||
|
||
begin
|
||
with TLabel.Create(Self) do
|
||
begin
|
||
Parent := FPageSpectrum;
|
||
Caption := 'Spectrum';
|
||
SetBounds(MARGIN, 18, 400, 28);
|
||
Font.Name := UI_FONT;
|
||
Font.Size := 16;
|
||
Font.Style := [fsBold];
|
||
Font.Color := CLR_TEXT;
|
||
end;
|
||
|
||
with TLabel.Create(Self) do
|
||
begin
|
||
Parent := FPageSpectrum;
|
||
Caption := 'Analyzer, detector, averaging and grid parameters for RX1.';
|
||
SetBounds(MARGIN, 48, 620, 20);
|
||
Font.Name := UI_FONT;
|
||
Font.Size := 9;
|
||
Font.Color := CLR_TEXTDIM;
|
||
end;
|
||
|
||
Grp := MakeGroupPanel(FPageSpectrum, 'Analyzer', MARGIN, 86, 650, 128);
|
||
MakeLbl(Grp, 'FFT Size:', PAD, R1 + 5, LW);
|
||
FCmbFFTSize := MakeCombo(Grp, CX, R1, CMB_W, OnFFTSizeChange);
|
||
for i := 0 to High(FFT_NAMES) do FCmbFFTSize.Items.Add(FFT_NAMES[i]);
|
||
MakeLbl(Grp, 'Window:', PAD, R1 + STEP + 5, LW);
|
||
FCmbWindow := MakeCombo(Grp, CX, R1 + STEP, CMB_W_LONG, OnWindowChange);
|
||
for i := 0 to High(WINDOW_NAMES) do FCmbWindow.Items.Add(WINDOW_NAMES[i]);
|
||
|
||
Grp := MakeGroupPanel(FPageSpectrum, 'Detection && Averaging', MARGIN, 230, 650, 170);
|
||
MakeLbl(Grp, 'Detector:', PAD, R1 + 5, LW);
|
||
FCmbSpecDet := MakeCombo(Grp, CX, R1, CMB_W, OnSpecDetChange);
|
||
for i := 0 to High(DETECTOR_NAMES) do FCmbSpecDet.Items.Add(DETECTOR_NAMES[i]);
|
||
MakeLbl(Grp, 'Avg Mode:', PAD, R1 + STEP + 5, LW);
|
||
FCmbSpecAvg := MakeCombo(Grp, CX, R1 + STEP, CMB_W, OnSpecAvgModeChange);
|
||
for i := 0 to High(AVGMODE_NAMES) do FCmbSpecAvg.Items.Add(AVGMODE_NAMES[i]);
|
||
MakeLbl(Grp, 'Avg Time (ms):', PAD, R1 + 2 * STEP + 5, LW);
|
||
FSpecAvgTime := MkFloat(CX, R1 + 2 * STEP, SPW, 30.0, 0.0, 5000.0, 10.0, OnSpecAvgTimeChange);
|
||
|
||
Grp := MakeGroupPanel(FPageSpectrum, 'Grid', MARGIN, 416, 650, 170);
|
||
MakeLbl(Grp, 'Reference level:', PAD, R1 + 5, LW);
|
||
FEdRefLevel := MkEdit(CX, R1, EDT_W, '-20', OnRefLevelChange);
|
||
MakeLbl(Grp, 'Range (dB):', PAD, R1 + STEP + 5, LW);
|
||
FEdRange := MkEdit(CX, R1 + STEP, EDT_W, '110', OnRangeChange);
|
||
MakeLbl(Grp, 'Grid step:', PAD, R1 + 2 * STEP + 5, LW);
|
||
FCmbGridStep := MakeCombo(Grp, CX, R1 + 2 * STEP, 130, OnGridStepChange);
|
||
for i := 0 to High(GRID_STEP_NAMES) do FCmbGridStep.Items.Add(GRID_STEP_NAMES[i]);
|
||
FCmbGridStep.ItemIndex := 1;
|
||
|
||
with TLabel.Create(Self) do
|
||
begin
|
||
Parent := FPageWaterfall;
|
||
Caption := 'Waterfall';
|
||
SetBounds(MARGIN, 18, 400, 28);
|
||
Font.Name := UI_FONT;
|
||
Font.Size := 16;
|
||
Font.Style := [fsBold];
|
||
Font.Color := CLR_TEXT;
|
||
end;
|
||
|
||
with TLabel.Create(Self) do
|
||
begin
|
||
Parent := FPageWaterfall;
|
||
Caption := 'Waterfall detector, smoothing and color scale thresholds.';
|
||
SetBounds(MARGIN, 48, 620, 20);
|
||
Font.Name := UI_FONT;
|
||
Font.Size := 9;
|
||
Font.Color := CLR_TEXTDIM;
|
||
end;
|
||
|
||
Grp := MakeGroupPanel(FPageWaterfall, 'Detection && Averaging', MARGIN, 86, 650, 170);
|
||
MakeLbl(Grp, 'Detector:', PAD, R1 + 5, LW);
|
||
FCmbWfDet := MakeCombo(Grp, CX, R1, CMB_W, OnWfDetChange);
|
||
for i := 0 to High(DETECTOR_NAMES) do FCmbWfDet.Items.Add(DETECTOR_NAMES[i]);
|
||
MakeLbl(Grp, 'Avg Mode:', PAD, R1 + STEP + 5, LW);
|
||
FCmbWfAvg := MakeCombo(Grp, CX, R1 + STEP, CMB_W, OnWfAvgModeChange);
|
||
for i := 0 to High(WF_AVGMODE_NAMES) do FCmbWfAvg.Items.Add(WF_AVGMODE_NAMES[i]);
|
||
MakeLbl(Grp, 'Avg Time (ms):', PAD, R1 + 2 * STEP + 5, LW);
|
||
FWfAvgTime := MkFloat(CX, R1 + 2 * STEP, SPW, 120.0, 0.0, 5000.0, 10.0, OnWfAvgTimeChange);
|
||
|
||
Grp := MakeGroupPanel(FPageWaterfall, 'Color Scale', MARGIN, 272, 650, 170);
|
||
MakeLbl(Grp, 'High (dBm):', PAD, R1 + 5, LW);
|
||
FWfHigh := MkFloat(CX, R1, SPW, -80.0, -160.0, 20.0, 1.0, OnWfThresholdChange);
|
||
MakeLbl(Grp, 'Low (dBm):', PAD, R1 + STEP + 5, LW);
|
||
FWfLow := MkFloat(CX, R1 + STEP, SPW, -130.0, -180.0, 0.0, 1.0, OnWfThresholdChange);
|
||
MakeLbl(Grp, 'AGC Offset (dB):', PAD, R1 + 2 * STEP + 5, LW);
|
||
FWfAGCOffset := MkFloat(CX, R1 + 2 * STEP, SPW, 0.0, -40.0, 40.0, 0.5, OnWfThresholdChange);
|
||
end;
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// BuildPATab
|
||
// ---------------------------------------------------------------------------
|
||
|
||
procedure TSettingsForm.BuildPATab;
|
||
const
|
||
MARGIN = 22;
|
||
LBL_W = 46;
|
||
ED_W = 72;
|
||
COL_W = LBL_W + ED_W + 8;
|
||
COLS = 4;
|
||
ROW_H = 32;
|
||
GRP_PAD = 18;
|
||
R1 = 42;
|
||
GRP_H = 222;
|
||
|
||
function MakeFloatSpin(AParent: TWinControl; ALeft, ATop: Integer;
|
||
AChange: TNotifyEvent): TFloatSpinEdit;
|
||
var E: TFloatSpinEdit;
|
||
begin
|
||
E := TFloatSpinEdit.Create(Self);
|
||
E.Parent := AParent;
|
||
E.SetBounds(ALeft, ATop, ED_W, BTN_H + 2);
|
||
E.Color := CLR_INPUT;
|
||
E.Font.Color := CLR_INPUT_TEXT;
|
||
E.Font.Name := UI_FONT;
|
||
E.Font.Size := 9;
|
||
E.MinValue := 38.8;
|
||
E.MaxValue := 100.0;
|
||
E.Increment := 0.1;
|
||
E.DecimalPlaces := 1;
|
||
E.Value := 100.0;
|
||
E.OnChange := AChange;
|
||
Result := E;
|
||
end;
|
||
|
||
var
|
||
Grp: TPanel;
|
||
Lbl: TLabel;
|
||
Spin: TSpinEdit;
|
||
i, r, c, X, Y: Integer;
|
||
begin
|
||
with TLabel.Create(Self) do
|
||
begin
|
||
Parent := FPagePA;
|
||
Caption := 'Power Amplifier';
|
||
SetBounds(MARGIN, 18, 400, 28);
|
||
Font.Name := UI_FONT;
|
||
Font.Size := 16;
|
||
Font.Style := [fsBold];
|
||
Font.Color := CLR_TEXT;
|
||
end;
|
||
|
||
with TLabel.Create(Self) do
|
||
begin
|
||
Parent := FPagePA;
|
||
Caption := 'Output limit and per-band calibration values.';
|
||
SetBounds(MARGIN, 48, 620, 20);
|
||
Font.Name := UI_FONT;
|
||
Font.Size := 9;
|
||
Font.Color := CLR_TEXTDIM;
|
||
end;
|
||
|
||
Grp := MakeGroupPanel(FPagePA, 'Power && Calibration', MARGIN, 86, 650, GRP_H);
|
||
|
||
// Max Power
|
||
Lbl := TLabel.Create(Self);
|
||
Lbl.Parent := Grp;
|
||
Lbl.Caption := 'Max power (W)';
|
||
Lbl.SetBounds(GRP_PAD, R1 + 6, 132, 18);
|
||
Lbl.Font.Color := CLR_TEXTDIM;
|
||
Lbl.Font.Name := UI_FONT;
|
||
Lbl.Font.Size := 9;
|
||
|
||
Spin := TSpinEdit.Create(Self);
|
||
Spin.Parent := Grp;
|
||
Spin.SetBounds(GRP_PAD + 150, R1, ED_W, BTN_H + 2);
|
||
Spin.Color := CLR_INPUT;
|
||
Spin.Font.Color := CLR_INPUT_TEXT;
|
||
Spin.Font.Name := UI_FONT;
|
||
Spin.Font.Size := 9;
|
||
Spin.MinValue := 5;
|
||
Spin.MaxValue := 200;
|
||
Spin.Increment := 1;
|
||
Spin.Value := 100;
|
||
Spin.OnChange := OnMaxPowerChange;
|
||
FEdMaxPower := Spin;
|
||
|
||
// Calibration label
|
||
Lbl := TLabel.Create(Self);
|
||
Lbl.Parent := Grp;
|
||
Lbl.Caption := 'Calibration per band, 38.8 ... 100.0';
|
||
Lbl.SetBounds(GRP_PAD, R1 + ROW_H + 12, 320, 18);
|
||
Lbl.Font.Color := CLR_TEXTDIM;
|
||
Lbl.Font.Name := UI_FONT;
|
||
Lbl.Font.Size := 9;
|
||
|
||
// Band grid 4 columns × 3 rows
|
||
for i := 0 to 10 do
|
||
begin
|
||
r := i div COLS;
|
||
c := i mod COLS;
|
||
X := GRP_PAD + c * (COL_W + 4);
|
||
Y := R1 + ROW_H + 34 + r * ROW_H;
|
||
|
||
Lbl := TLabel.Create(Self);
|
||
Lbl.Parent := Grp;
|
||
Lbl.Caption := PA_BAND_NAMES[i] + ':';
|
||
Lbl.SetBounds(X, Y + 5, LBL_W, 18);
|
||
Lbl.Font.Color := CLR_TEXTDIM;
|
||
Lbl.Font.Name := UI_FONT;
|
||
Lbl.Font.Size := 9;
|
||
|
||
FEdBandCal[i] := MakeFloatSpin(Grp, X + LBL_W, Y, OnBandCalChange);
|
||
FEdBandCal[i].Tag := i;
|
||
end;
|
||
|
||
with TLabel.Create(Self) do
|
||
begin
|
||
Parent := FPageAdvanced;
|
||
Caption := 'Advanced';
|
||
SetBounds(MARGIN, 18, 400, 28);
|
||
Font.Name := UI_FONT;
|
||
Font.Size := 16;
|
||
Font.Style := [fsBold];
|
||
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;
|
||
end;
|
||
end;
|
||
|
||
procedure TSettingsForm.ApplyTheme;
|
||
begin
|
||
Color := CLR_BG;
|
||
if Assigned(FNavPanel) then FNavPanel.Color := TColor($00151515);
|
||
if Assigned(FContentPanel) then FContentPanel.Color := CLR_BG;
|
||
if Assigned(FPageAudio) then FPageAudio.Color := CLR_BG;
|
||
if Assigned(FPageDisplay) then FPageDisplay.Color := CLR_BG;
|
||
if Assigned(FPageSpectrum) then FPageSpectrum.Color := CLR_BG;
|
||
if Assigned(FPageWaterfall) then FPageWaterfall.Color := CLR_BG;
|
||
if Assigned(FPagePA) then FPagePA.Color := CLR_BG;
|
||
if Assigned(FPageAdvanced) then FPageAdvanced.Color := CLR_BG;
|
||
if Assigned(FPageCAT) then FPageCAT.Color := CLR_BG;
|
||
end;
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// LoadValues
|
||
// ---------------------------------------------------------------------------
|
||
|
||
procedure TSettingsForm.LoadValues(
|
||
FFTSize, WinType, SpecDet, SpecAvgMode: Integer;
|
||
SpecAvgTimeMS: Double;
|
||
WfDet, WfAvgMode: Integer;
|
||
WfAvgTimeMS, WfHigh, WfLow, WfAGCOffset: Double;
|
||
RefLevel, Range, GridStep: Double;
|
||
const AudioOutDevName: string;
|
||
const AudioInDevName: string);
|
||
var
|
||
i, Idx: Integer;
|
||
begin
|
||
FLoading := True;
|
||
try
|
||
Idx := 5;
|
||
for i := 0 to High(FFT_SIZES) do
|
||
if FFT_SIZES[i] = FFTSize then begin Idx := i; Break; end;
|
||
FCmbFFTSize.ItemIndex := Idx;
|
||
|
||
if (WinType >= 0) and (WinType < FCmbWindow.Items.Count) then
|
||
FCmbWindow.ItemIndex := WinType
|
||
else
|
||
FCmbWindow.ItemIndex := 2;
|
||
|
||
if (SpecDet >= 0) and (SpecDet < FCmbSpecDet.Items.Count) then
|
||
FCmbSpecDet.ItemIndex := SpecDet
|
||
else
|
||
FCmbSpecDet.ItemIndex := 0;
|
||
|
||
Idx := 3;
|
||
for i := 0 to High(AVGMODE_VALUES) do
|
||
if AVGMODE_VALUES[i] = SpecAvgMode then begin Idx := i; Break; end;
|
||
FCmbSpecAvg.ItemIndex := Idx;
|
||
FSpecAvgTime.Value := EnsureRange(SpecAvgTimeMS, 0.0, 5000.0);
|
||
|
||
if (WfDet >= 0) and (WfDet < FCmbWfDet.Items.Count) then
|
||
FCmbWfDet.ItemIndex := WfDet
|
||
else
|
||
FCmbWfDet.ItemIndex := 0;
|
||
|
||
Idx := 3;
|
||
for i := 0 to High(WF_AVGMODE_VALUES) do
|
||
if WF_AVGMODE_VALUES[i] = WfAvgMode then begin Idx := i; Break; end;
|
||
FCmbWfAvg.ItemIndex := Idx;
|
||
FWfAvgTime.Value := EnsureRange(WfAvgTimeMS, 0.0, 5000.0);
|
||
FWfHigh.Value := EnsureRange(WfHigh, -160.0, 20.0);
|
||
FWfLow.Value := EnsureRange(WfLow, -180.0, 0.0);
|
||
FWfAGCOffset.Value := EnsureRange(WfAGCOffset, -40.0, 40.0);
|
||
|
||
FEdRefLevel.Text := FormatFloat('0.#', RefLevel);
|
||
FEdRange.Text := FormatFloat('0.#', Range);
|
||
Idx := 1;
|
||
for i := 0 to High(GRID_STEPS) do
|
||
if Abs(GRID_STEPS[i] - GridStep) < 0.5 then begin Idx := i; Break; end;
|
||
FCmbGridStep.ItemIndex := Idx;
|
||
|
||
if AudioOutDevName = '' then
|
||
FCmbRXDev.ItemIndex := 0
|
||
else
|
||
begin
|
||
Idx := FCmbRXDev.Items.IndexOf(AudioOutDevName);
|
||
if Idx >= 0 then FCmbRXDev.ItemIndex := Idx
|
||
else FCmbRXDev.ItemIndex := 0;
|
||
end;
|
||
|
||
if AudioInDevName = '' then
|
||
FCmbTXDev.ItemIndex := 0
|
||
else
|
||
begin
|
||
Idx := FCmbTXDev.Items.IndexOf(AudioInDevName);
|
||
if Idx >= 0 then FCmbTXDev.ItemIndex := Idx
|
||
else FCmbTXDev.ItemIndex := 0;
|
||
end;
|
||
finally
|
||
FLoading := False;
|
||
end;
|
||
end;
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// RefreshAudioDevices
|
||
// ---------------------------------------------------------------------------
|
||
|
||
procedure TSettingsForm.RefreshAudioDevices(AudioOut: TAudioOutput; AudioIn: TAudioInput);
|
||
var
|
||
Names: TStringList;
|
||
Cnt, i: Integer;
|
||
OldRXSel: string;
|
||
OldTXSel: string;
|
||
begin
|
||
Names := TStringList.Create;
|
||
try
|
||
if AudioOut <> nil then
|
||
begin
|
||
OldRXSel := FCmbRXDev.Text;
|
||
FCmbRXDev.Items.Clear;
|
||
FCmbRXDev.Items.Add('Default');
|
||
FRXDevCount := 0;
|
||
|
||
Cnt := 0;
|
||
Names.Clear;
|
||
if AudioOut.EnumOutputDevices(Names, FRXDevIndices, Cnt) then
|
||
begin
|
||
FRXDevCount := Cnt;
|
||
for i := 0 to Cnt - 1 do
|
||
FCmbRXDev.Items.Add(Names[i]);
|
||
end;
|
||
if (FRXDevCount = 0) and (AudioOut.LastError <> '') then
|
||
FCmbRXDev.Items.Add('PortAudio: ' + AudioOut.LastError);
|
||
|
||
i := FCmbRXDev.Items.IndexOf(OldRXSel);
|
||
if i >= 0 then FCmbRXDev.ItemIndex := i
|
||
else FCmbRXDev.ItemIndex := 0;
|
||
end;
|
||
|
||
if AudioIn <> nil then
|
||
begin
|
||
OldTXSel := FCmbTXDev.Text;
|
||
FCmbTXDev.Items.Clear;
|
||
FCmbTXDev.Items.Add('None');
|
||
FTXDevCount := 0;
|
||
|
||
Cnt := 0;
|
||
Names.Clear;
|
||
if AudioIn.EnumInputDevices(Names, FTXDevIndices, Cnt) then
|
||
begin
|
||
FTXDevCount := Cnt;
|
||
for i := 0 to Cnt - 1 do
|
||
FCmbTXDev.Items.Add(Names[i]);
|
||
end;
|
||
if (FTXDevCount = 0) and (AudioIn.LastError <> '') then
|
||
FCmbTXDev.Items.Add('PortAudio: ' + AudioIn.LastError);
|
||
|
||
i := FCmbTXDev.Items.IndexOf(OldTXSel);
|
||
if i >= 0 then FCmbTXDev.ItemIndex := i
|
||
else FCmbTXDev.ItemIndex := 0;
|
||
end;
|
||
finally
|
||
Names.Free;
|
||
end;
|
||
end;
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Value accessors
|
||
// ---------------------------------------------------------------------------
|
||
|
||
function TSettingsForm.GetFFTSize: Integer;
|
||
var Idx: Integer;
|
||
begin
|
||
Idx := FCmbFFTSize.ItemIndex;
|
||
if (Idx >= 0) and (Idx <= High(FFT_SIZES)) then
|
||
Result := FFT_SIZES[Idx]
|
||
else
|
||
Result := 4096;
|
||
end;
|
||
|
||
function TSettingsForm.GetSpecAvgTimeMS: Double;
|
||
begin
|
||
Result := EnsureRange(FSpecAvgTime.Value, 0.0, 5000.0);
|
||
end;
|
||
|
||
function TSettingsForm.GetWfAvgTimeMS: Double;
|
||
begin
|
||
Result := EnsureRange(FWfAvgTime.Value, 0.0, 5000.0);
|
||
end;
|
||
|
||
function TSettingsForm.GetWfHigh: Double;
|
||
begin
|
||
Result := EnsureRange(FWfHigh.Value, -160.0, 20.0);
|
||
end;
|
||
|
||
function TSettingsForm.GetWfLow: Double;
|
||
begin
|
||
Result := EnsureRange(FWfLow.Value, -180.0, 0.0);
|
||
end;
|
||
|
||
function TSettingsForm.GetWfAGCOffset: Double;
|
||
begin
|
||
Result := EnsureRange(FWfAGCOffset.Value, -40.0, 40.0);
|
||
end;
|
||
|
||
function TSettingsForm.GetRefLevel: Double;
|
||
var V: Double; Err: Integer;
|
||
begin
|
||
Val(FEdRefLevel.Text, V, Err);
|
||
if Err <> 0 then V := -20.0;
|
||
Result := EnsureRange(V, -200.0, 0.0);
|
||
end;
|
||
|
||
function TSettingsForm.GetRange: Double;
|
||
var V: Double; Err: Integer;
|
||
begin
|
||
Val(FEdRange.Text, V, Err);
|
||
if Err <> 0 then V := 110.0;
|
||
Result := EnsureRange(V, 10.0, 200.0);
|
||
end;
|
||
|
||
function TSettingsForm.GetGridStep: Double;
|
||
var Idx: Integer;
|
||
begin
|
||
Idx := FCmbGridStep.ItemIndex;
|
||
if (Idx >= 0) and (Idx <= High(GRID_STEPS)) then
|
||
Result := GRID_STEPS[Idx]
|
||
else
|
||
Result := 10.0;
|
||
end;
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Fire helpers
|
||
// ---------------------------------------------------------------------------
|
||
|
||
procedure TSettingsForm.FireDisplayChange;
|
||
var
|
||
AvgIdx: Integer;
|
||
AvgVal: Integer;
|
||
begin
|
||
if FLoading then Exit;
|
||
if not Assigned(FOnDisplayChange) then Exit;
|
||
AvgIdx := FCmbSpecAvg.ItemIndex;
|
||
if (AvgIdx >= 0) and (AvgIdx <= High(AVGMODE_VALUES)) then
|
||
AvgVal := AVGMODE_VALUES[AvgIdx]
|
||
else
|
||
AvgVal := 3;
|
||
FOnDisplayChange(
|
||
GetFFTSize,
|
||
FCmbWindow.ItemIndex,
|
||
FCmbSpecDet.ItemIndex,
|
||
AvgVal,
|
||
GetSpecAvgTimeMS);
|
||
end;
|
||
|
||
procedure TSettingsForm.FireWaterfallChange;
|
||
var
|
||
AvgIdx: Integer;
|
||
AvgVal: Integer;
|
||
begin
|
||
if FLoading then Exit;
|
||
if not Assigned(FOnWaterfallChange) then Exit;
|
||
AvgIdx := FCmbWfAvg.ItemIndex;
|
||
if (AvgIdx >= 0) and (AvgIdx <= High(WF_AVGMODE_VALUES)) then
|
||
AvgVal := WF_AVGMODE_VALUES[AvgIdx]
|
||
else
|
||
AvgVal := 1;
|
||
FOnWaterfallChange(
|
||
FCmbWfDet.ItemIndex,
|
||
AvgVal,
|
||
GetWfAvgTimeMS,
|
||
GetWfHigh,
|
||
GetWfLow,
|
||
GetWfAGCOffset);
|
||
end;
|
||
|
||
procedure TSettingsForm.FireGridChange;
|
||
begin
|
||
if FLoading then Exit;
|
||
if not Assigned(FOnGridChange) then Exit;
|
||
FOnGridChange(GetRefLevel, GetRange, GetGridStep);
|
||
end;
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Event handlers
|
||
// ---------------------------------------------------------------------------
|
||
|
||
procedure TSettingsForm.OnFFTSizeChange(Sender: TObject);
|
||
begin FireDisplayChange; end;
|
||
|
||
procedure TSettingsForm.OnWindowChange(Sender: TObject);
|
||
begin FireDisplayChange; end;
|
||
|
||
procedure TSettingsForm.OnSpecDetChange(Sender: TObject);
|
||
begin FireDisplayChange; end;
|
||
|
||
procedure TSettingsForm.OnSpecAvgModeChange(Sender: TObject);
|
||
begin FireDisplayChange; end;
|
||
|
||
procedure TSettingsForm.OnSpecAvgTimeChange(Sender: TObject);
|
||
begin FireDisplayChange; end;
|
||
|
||
procedure TSettingsForm.OnWfDetChange(Sender: TObject);
|
||
begin FireWaterfallChange; end;
|
||
|
||
procedure TSettingsForm.OnWfAvgModeChange(Sender: TObject);
|
||
begin FireWaterfallChange; end;
|
||
|
||
procedure TSettingsForm.OnWfAvgTimeChange(Sender: TObject);
|
||
begin FireWaterfallChange; end;
|
||
|
||
procedure TSettingsForm.OnWfThresholdChange(Sender: TObject);
|
||
begin FireWaterfallChange; end;
|
||
|
||
procedure TSettingsForm.OnRefLevelChange(Sender: TObject);
|
||
begin FireGridChange; end;
|
||
|
||
procedure TSettingsForm.OnRangeChange(Sender: TObject);
|
||
begin FireGridChange; end;
|
||
|
||
procedure TSettingsForm.OnGridStepChange(Sender: TObject);
|
||
begin FireGridChange; end;
|
||
|
||
procedure TSettingsForm.OnRXDevChange(Sender: TObject);
|
||
var
|
||
Idx: Integer;
|
||
DevIdx: Integer;
|
||
DevName: string;
|
||
begin
|
||
if FLoading then Exit;
|
||
if not Assigned(FOnAudioDevChange) then Exit;
|
||
Idx := FCmbRXDev.ItemIndex;
|
||
if Idx <= 0 then
|
||
FOnAudioDevChange(-1, '')
|
||
else
|
||
begin
|
||
DevName := FCmbRXDev.Items[Idx];
|
||
DevIdx := Idx - 1;
|
||
if (DevIdx >= 0) and (DevIdx < FRXDevCount) then
|
||
FOnAudioDevChange(FRXDevIndices[DevIdx], DevName)
|
||
else
|
||
FOnAudioDevChange(-1, '');
|
||
end;
|
||
end;
|
||
|
||
procedure TSettingsForm.OnTXDevChange(Sender: TObject);
|
||
var
|
||
Idx: Integer;
|
||
DevIdx: Integer;
|
||
DevName: string;
|
||
begin
|
||
if FLoading then Exit;
|
||
if not Assigned(FOnAudioInDevChange) then Exit;
|
||
Idx := FCmbTXDev.ItemIndex;
|
||
if Idx <= 0 then
|
||
FOnAudioInDevChange(-1, '')
|
||
else
|
||
begin
|
||
DevName := FCmbTXDev.Items[Idx];
|
||
DevIdx := Idx - 1;
|
||
if (DevIdx >= 0) and (DevIdx < FTXDevCount) then
|
||
FOnAudioInDevChange(FTXDevIndices[DevIdx], DevName)
|
||
else
|
||
FOnAudioInDevChange(-1, '');
|
||
end;
|
||
end;
|
||
|
||
procedure TSettingsForm.LoadVisibility(ShowSpectrum, ShowWaterfall: Boolean);
|
||
begin
|
||
FLoading := True;
|
||
try
|
||
FChkShowSpectrum.Checked := ShowSpectrum;
|
||
FChkShowWaterfall.Checked := ShowWaterfall;
|
||
finally
|
||
FLoading := False;
|
||
end;
|
||
end;
|
||
|
||
procedure TSettingsForm.OnVisibilityChkChange(Sender: TObject);
|
||
begin
|
||
if FLoading then Exit;
|
||
if not Assigned(FOnVisibilityChange) then Exit;
|
||
FOnVisibilityChange(FChkShowSpectrum.Checked, FChkShowWaterfall.Checked);
|
||
end;
|
||
|
||
procedure TSettingsForm.OnFPSCmbChange(Sender: TObject);
|
||
var
|
||
Idx: Integer;
|
||
begin
|
||
if FLoading then Exit;
|
||
if not Assigned(FOnFPSChange) then Exit;
|
||
Idx := FCmbFPS.ItemIndex;
|
||
if (Idx >= 0) and (Idx <= High(FPS_VALUES)) then
|
||
FOnFPSChange(FPS_VALUES[Idx]);
|
||
end;
|
||
|
||
procedure TSettingsForm.LoadFPS(FPS: Integer);
|
||
var
|
||
i, Idx: Integer;
|
||
begin
|
||
FLoading := True;
|
||
try
|
||
Idx := 8;
|
||
for i := 0 to High(FPS_VALUES) do
|
||
if FPS_VALUES[i] = FPS then begin Idx := i; Break; end;
|
||
FCmbFPS.ItemIndex := Idx;
|
||
finally
|
||
FLoading := False;
|
||
end;
|
||
end;
|
||
|
||
procedure TSettingsForm.LoadPASettings(MaxPower: Double;
|
||
const BandCal: array of Double);
|
||
var i, n: Integer;
|
||
begin
|
||
FLoading := True;
|
||
try
|
||
FEdMaxPower.Value := Round(EnsureRange(MaxPower, 5.0, 200.0));
|
||
n := Min(10, High(BandCal));
|
||
for i := 0 to n do
|
||
FEdBandCal[i].Value := EnsureRange(BandCal[i], 38.8, 100.0);
|
||
finally
|
||
FLoading := False;
|
||
end;
|
||
end;
|
||
|
||
procedure TSettingsForm.OnMaxPowerChange(Sender: TObject);
|
||
var
|
||
BandCal: array[0..10] of Double;
|
||
i: Integer;
|
||
begin
|
||
if FLoading then Exit;
|
||
if not Assigned(FOnPAChange) then Exit;
|
||
for i := 0 to 10 do
|
||
BandCal[i] := FEdBandCal[i].Value;
|
||
FOnPAChange(FEdMaxPower.Value, BandCal);
|
||
end;
|
||
|
||
procedure TSettingsForm.OnBandCalChange(Sender: TObject);
|
||
var
|
||
BandCal: array[0..10] of Double;
|
||
i: Integer;
|
||
begin
|
||
if FLoading then Exit;
|
||
if not Assigned(FOnPAChange) then Exit;
|
||
for i := 0 to 10 do
|
||
BandCal[i] := FEdBandCal[i].Value;
|
||
FOnPAChange(FEdMaxPower.Value, BandCal);
|
||
end;
|
||
|
||
procedure TSettingsForm.BtnCloseClick(Sender: TObject);
|
||
begin
|
||
Close;
|
||
end;
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// BuildCATTab
|
||
// ---------------------------------------------------------------------------
|
||
|
||
procedure TSettingsForm.BuildCATTab;
|
||
const
|
||
MARGIN = 22;
|
||
PAD = 18;
|
||
LW = 120;
|
||
CX = PAD + LW + 8;
|
||
GRP_W = 320;
|
||
GRP_H = 240;
|
||
GRP_GAP = 16;
|
||
CMB_W = 140;
|
||
EDT_W = 160;
|
||
R1 = 42;
|
||
STEP = 32;
|
||
var
|
||
i, col, row, gx, gy, j: Integer;
|
||
Grp: TPanel;
|
||
Chk: TCheckBox;
|
||
Ed: TEdit;
|
||
Cmb: TComboBox;
|
||
Spin: TSpinEdit;
|
||
begin
|
||
with TLabel.Create(Self) do
|
||
begin
|
||
Parent := FPageCAT;
|
||
Caption := 'CAT';
|
||
SetBounds(MARGIN, 18, 400, 28);
|
||
Font.Name := UI_FONT; Font.Size := 16;
|
||
Font.Style := [fsBold]; Font.Color := CLR_TEXT;
|
||
end;
|
||
with TLabel.Create(Self) do
|
||
begin
|
||
Parent := FPageCAT;
|
||
Caption := 'Computer Aided Transceiver — serial port and TCP server settings.';
|
||
SetBounds(MARGIN, 48, 680, 20);
|
||
Font.Name := UI_FONT; Font.Size := 9; Font.Color := CLR_TEXTDIM;
|
||
end;
|
||
|
||
for i := 0 to 3 do
|
||
begin
|
||
row := i div 2;
|
||
col := i mod 2;
|
||
gx := MARGIN + col * (GRP_W + GRP_GAP);
|
||
gy := 86 + row * (GRP_H + GRP_GAP);
|
||
|
||
Grp := MakeGroupPanel(FPageCAT, 'Serial Port ' + IntToStr(i + 1), gx, gy, GRP_W, GRP_H);
|
||
|
||
Chk := TCheckBox.Create(Self);
|
||
Chk.Parent := Grp;
|
||
Chk.Caption := 'Enable';
|
||
Chk.SetBounds(PAD, R1, GRP_W - PAD * 2, 22);
|
||
Chk.Font.Color := CLR_TEXT;
|
||
Chk.Font.Name := UI_FONT; Chk.Font.Size := 9;
|
||
Chk.Tag := i;
|
||
Chk.OnChange := OnCATSerialChange;
|
||
FCATSerialEn[i] := Chk;
|
||
|
||
MakeLbl(Grp, 'Port:', PAD, R1 + STEP + 6, LW);
|
||
Ed := TEdit.Create(Self);
|
||
Ed.Parent := Grp;
|
||
Ed.SetBounds(CX, R1 + STEP, EDT_W, BTN_H);
|
||
Ed.Color := CLR_INPUT; Ed.Font.Color := CLR_INPUT_TEXT;
|
||
Ed.Font.Name := UI_FONT; Ed.Font.Size := 9;
|
||
Ed.Tag := i;
|
||
Ed.OnChange := OnCATSerialChange;
|
||
{$IFDEF MSWINDOWS}
|
||
Ed.Text := 'COM' + IntToStr(i + 1);
|
||
{$ELSE}
|
||
Ed.Text := '/dev/ttyS' + IntToStr(i);
|
||
{$ENDIF}
|
||
FCATSerialPort[i] := Ed;
|
||
|
||
MakeLbl(Grp, 'Baud rate:', PAD, R1 + 2 * STEP + 6, LW);
|
||
Cmb := MakeCombo(Grp, CX, R1 + 2 * STEP, CMB_W, OnCATSerialChange);
|
||
Cmb.Tag := i;
|
||
for j := 0 to High(CAT_BAUD_NAMES) do Cmb.Items.Add(CAT_BAUD_NAMES[j]);
|
||
Cmb.ItemIndex := 3; // 9600
|
||
FCATSerialBaud[i] := Cmb;
|
||
|
||
MakeLbl(Grp, 'Data bits:', PAD, R1 + 3 * STEP + 6, LW);
|
||
Cmb := MakeCombo(Grp, CX, R1 + 3 * STEP, CMB_W, OnCATSerialChange);
|
||
Cmb.Tag := i;
|
||
Cmb.Items.Add('7'); Cmb.Items.Add('8');
|
||
Cmb.ItemIndex := 1; // 8
|
||
FCATSerialDataBits[i] := Cmb;
|
||
|
||
MakeLbl(Grp, 'Stop bits:', PAD, R1 + 4 * STEP + 6, LW);
|
||
Cmb := MakeCombo(Grp, CX, R1 + 4 * STEP, CMB_W, OnCATSerialChange);
|
||
Cmb.Tag := i;
|
||
Cmb.Items.Add('1'); Cmb.Items.Add('2');
|
||
Cmb.ItemIndex := 0; // 1
|
||
FCATSerialStopBits[i] := Cmb;
|
||
|
||
MakeLbl(Grp, 'Parity:', PAD, R1 + 5 * STEP + 6, LW);
|
||
Cmb := MakeCombo(Grp, CX, R1 + 5 * STEP, CMB_W, OnCATSerialChange);
|
||
Cmb.Tag := i;
|
||
Cmb.Items.Add('None'); Cmb.Items.Add('Odd'); Cmb.Items.Add('Even');
|
||
Cmb.ItemIndex := 0; // None
|
||
FCATSerialParity[i] := Cmb;
|
||
end;
|
||
|
||
// TCP server group below the two rows of serial port panels
|
||
gy := 86 + 2 * (GRP_H + GRP_GAP);
|
||
Grp := MakeGroupPanel(FPageCAT, 'TCP CAT Server', MARGIN, gy, GRP_W * 2 + GRP_GAP, 116);
|
||
|
||
FCATTcpEn := TCheckBox.Create(Self);
|
||
FCATTcpEn.Parent := Grp;
|
||
FCATTcpEn.Caption := 'Enable TCP server (default port 4992)';
|
||
FCATTcpEn.SetBounds(PAD, R1, 300, 22);
|
||
FCATTcpEn.Font.Color := CLR_TEXT;
|
||
FCATTcpEn.Font.Name := UI_FONT; FCATTcpEn.Font.Size := 9;
|
||
FCATTcpEn.OnChange := OnCATTcpChange;
|
||
|
||
MakeLbl(Grp, 'Port:', PAD, R1 + STEP + 6, LW);
|
||
Spin := TSpinEdit.Create(Self);
|
||
Spin.Parent := Grp;
|
||
Spin.SetBounds(CX, R1 + STEP, 100, 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 := 4992;
|
||
Spin.OnChange := OnCATTcpChange;
|
||
FCATTcpPort := Spin;
|
||
end;
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// CAT event handlers
|
||
// ---------------------------------------------------------------------------
|
||
|
||
procedure TSettingsForm.FireCATChange;
|
||
var
|
||
SerEn: array[0..3] of Boolean;
|
||
SerPort: array[0..3] of string;
|
||
SerBaud, SerData, SerStop, SerPar: array[0..3] of Integer;
|
||
i, Idx: Integer;
|
||
begin
|
||
if FLoading then Exit;
|
||
if not Assigned(FOnCATChange) then Exit;
|
||
for i := 0 to 3 do
|
||
begin
|
||
SerEn[i] := FCATSerialEn[i].Checked;
|
||
SerPort[i] := FCATSerialPort[i].Text;
|
||
Idx := FCATSerialBaud[i].ItemIndex;
|
||
if (Idx >= 0) and (Idx <= High(CAT_BAUD_VALS)) then
|
||
SerBaud[i] := CAT_BAUD_VALS[Idx]
|
||
else
|
||
SerBaud[i] := 9600;
|
||
if FCATSerialDataBits[i].ItemIndex = 0 then SerData[i] := 7 else SerData[i] := 8;
|
||
if FCATSerialStopBits[i].ItemIndex = 1 then SerStop[i] := 2 else SerStop[i] := 1;
|
||
SerPar[i] := FCATSerialParity[i].ItemIndex;
|
||
end;
|
||
FOnCATChange(SerEn, SerPort, SerBaud, SerData, SerStop, SerPar,
|
||
FCATTcpEn.Checked, FCATTcpPort.Value);
|
||
end;
|
||
|
||
procedure TSettingsForm.OnCATSerialChange(Sender: TObject);
|
||
begin FireCATChange; end;
|
||
|
||
procedure TSettingsForm.OnCATTcpChange(Sender: TObject);
|
||
begin FireCATChange; end;
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// LoadCATSettings
|
||
// ---------------------------------------------------------------------------
|
||
|
||
procedure TSettingsForm.LoadCATSettings(
|
||
const SerEnabled: array of Boolean;
|
||
const SerPort: array of string;
|
||
const SerBaud, SerDataBits, SerStopBits, SerParity: array of Integer;
|
||
TcpEnabled: Boolean; TcpPort: Integer);
|
||
var
|
||
i, j, Idx: Integer;
|
||
begin
|
||
FLoading := True;
|
||
try
|
||
for i := 0 to 3 do
|
||
begin
|
||
if i <= High(SerEnabled) then FCATSerialEn[i].Checked := SerEnabled[i];
|
||
if i <= High(SerPort) then FCATSerialPort[i].Text := SerPort[i];
|
||
if i <= High(SerBaud) then
|
||
begin
|
||
Idx := 3;
|
||
for j := 0 to High(CAT_BAUD_VALS) do
|
||
if CAT_BAUD_VALS[j] = SerBaud[i] then begin Idx := j; Break; end;
|
||
FCATSerialBaud[i].ItemIndex := Idx;
|
||
end;
|
||
if i <= High(SerDataBits) then
|
||
begin
|
||
if SerDataBits[i] = 7 then FCATSerialDataBits[i].ItemIndex := 0
|
||
else FCATSerialDataBits[i].ItemIndex := 1;
|
||
end;
|
||
if i <= High(SerStopBits) then
|
||
begin
|
||
if SerStopBits[i] = 2 then FCATSerialStopBits[i].ItemIndex := 1
|
||
else FCATSerialStopBits[i].ItemIndex := 0;
|
||
end;
|
||
if i <= High(SerParity) then
|
||
FCATSerialParity[i].ItemIndex := EnsureRange(SerParity[i], 0, 2);
|
||
end;
|
||
FCATTcpEn.Checked := TcpEnabled;
|
||
FCATTcpPort.Value := EnsureRange(TcpPort, 1, 65535);
|
||
finally
|
||
FLoading := False;
|
||
end;
|
||
end;
|
||
|
||
end.
|