mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 19:45:09 +00:00
Add full CAT support (serial + TCP)
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>
This commit is contained in:
+251
-1
@@ -43,6 +43,14 @@ type
|
||||
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)
|
||||
@@ -56,12 +64,14 @@ type
|
||||
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;
|
||||
@@ -96,10 +106,21 @@ type
|
||||
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;
|
||||
@@ -116,6 +137,7 @@ type
|
||||
procedure BuildDisplayTab;
|
||||
procedure BuildRX1Tab;
|
||||
procedure BuildPATab;
|
||||
procedure BuildCATTab;
|
||||
procedure ApplyTheme;
|
||||
procedure NavClick(Sender: TObject);
|
||||
procedure SelectPage(APage: TWinControl; ANav: TFlatButton);
|
||||
@@ -147,6 +169,9 @@ type
|
||||
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;
|
||||
@@ -179,7 +204,13 @@ type
|
||||
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;
|
||||
@@ -209,6 +240,9 @@ const
|
||||
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');
|
||||
|
||||
@@ -391,6 +425,7 @@ begin
|
||||
FNavWaterfall := MakeNavButton('Waterfall', 182);
|
||||
FNavPA := MakeNavButton('Power Amplifier', 218);
|
||||
FNavAdvanced := MakeNavButton('Advanced', 254);
|
||||
FNavCAT := MakeNavButton('CAT', 290);
|
||||
|
||||
FContentPanel := TPanel.Create(Self);
|
||||
FContentPanel.Parent := Self;
|
||||
@@ -404,11 +439,13 @@ begin
|
||||
FPageWaterfall := MakeScrollPage;
|
||||
FPagePA := MakeScrollPage;
|
||||
FPageAdvanced := MakeScrollPage;
|
||||
FPageCAT := MakeScrollPage;
|
||||
|
||||
BuildAudioTab;
|
||||
BuildDisplayTab;
|
||||
BuildRX1Tab;
|
||||
BuildPATab;
|
||||
BuildCATTab;
|
||||
|
||||
FBtnClose := TFlatButton.Create(Self);
|
||||
FBtnClose.Parent := Self;
|
||||
@@ -435,7 +472,8 @@ begin
|
||||
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 = FNavAdvanced then SelectPage(FPageAdvanced, FNavAdvanced)
|
||||
else if Sender = FNavCAT then SelectPage(FPageCAT, FNavCAT);
|
||||
end;
|
||||
|
||||
procedure TSettingsForm.SelectPage(APage: TWinControl; ANav: TFlatButton);
|
||||
@@ -446,6 +484,7 @@ begin
|
||||
FPageWaterfall.Visible := APage = FPageWaterfall;
|
||||
FPagePA.Visible := APage = FPagePA;
|
||||
FPageAdvanced.Visible := APage = FPageAdvanced;
|
||||
FPageCAT.Visible := APage = FPageCAT;
|
||||
|
||||
FNavAudio.Active := ANav = FNavAudio;
|
||||
FNavDisplay.Active := ANav = FNavDisplay;
|
||||
@@ -453,6 +492,7 @@ begin
|
||||
FNavWaterfall.Active := ANav = FNavWaterfall;
|
||||
FNavPA.Active := ANav = FNavPA;
|
||||
FNavAdvanced.Active := ANav = FNavAdvanced;
|
||||
FNavCAT.Active := ANav = FNavCAT;
|
||||
end;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -859,6 +899,7 @@ begin
|
||||
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;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -1294,4 +1335,213 @@ 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.
|
||||
|
||||
Reference in New Issue
Block a user