diff --git a/BoardUtils.pas b/BoardUtils.pas
new file mode 100644
index 0000000..f219c55
--- /dev/null
+++ b/BoardUtils.pas
@@ -0,0 +1,29 @@
+unit BoardUtils;
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+interface
+
+function BoardTypeName(BoardType: Integer): string;
+
+implementation
+
+uses SysUtils;
+
+function BoardTypeName(BoardType: Integer): string;
+begin
+ case BoardType of
+ 1: Result := 'HERMES (ANAN-10/100)';
+ 2: Result := 'HERMES-E (ANAN-10E/100B)';
+ 3: Result := 'ANGELIA (ANAN-100D)';
+ 4: Result := 'ORION (ANAN-200D)';
+ 5: Result := 'ORION MkII (ANAN-7000/8000)';
+ 6: Result := 'HERMES-LITE 2';
+ 10: Result := 'SATURN (G2)';
+ else Result := Format('Unknown Board #%d', [BoardType]);
+ end;
+end;
+
+end.
diff --git a/DeviceForm.pas b/DeviceForm.pas
index a99d9d2..96a03c8 100644
--- a/DeviceForm.pas
+++ b/DeviceForm.pas
@@ -6,10 +6,8 @@ interface
uses
Classes, SysUtils, FlatButton, FlatEdit, FlatListBox, AppTheme, Forms, Controls, Graphics, Dialogs,
- StdCtrls, ExtCtrls, ComCtrls, IniFiles;
-
-// Декодирование типа платы (совпадает с MainForm.BoardTypeName)
-function BoardTypeName(BoardType: Integer): string;
+ StdCtrls, ExtCtrls, ComCtrls, IniFiles,
+ BoardUtils;
const
DEVICE_CFG_FILE = 'hpsdr_devices.ini';
@@ -114,20 +112,6 @@ type
implementation
-function BoardTypeName(BoardType: Integer): string;
-begin
- case BoardType of
- 1: Result := 'HERMES (ANAN-10/100)';
- 2: Result := 'HERMES-E (ANAN-10E/100B)';
- 3: Result := 'ANGELIA (ANAN-100D)';
- 4: Result := 'ORION (ANAN-200D)';
- 5: Result := 'ORION MkII (ANAN-7000/8000)';
- 6: Result := 'HERMES-LITE 2';
- 10: Result := 'SATURN (G2)';
- else Result := Format('Unknown Board #%d', [BoardType]);
- end;
-end;
-
const
CLR_BG = TColor($00121212);
CLR_PANEL = TColor($001A1A1A);
diff --git a/MainForm.pas b/MainForm.pas
index c69c4d4..9872db9 100644
--- a/MainForm.pas
+++ b/MainForm.pas
@@ -26,7 +26,6 @@ uses
FlatButton, FlatSlider, FlatDropDown, AppTheme, Forms, Controls, Graphics, Dialogs,
StdCtrls, ExtCtrls, Buttons, Menus, Math, Types,
OpenGLContext,
- FlatProgressBar,
LCLIntf, LCLType, GraphType,
HPSDRProtocol, HPSDRNetwork,
WDSP, WDSPEngine, AudioOutput, AudioInput,
@@ -37,7 +36,8 @@ uses
WidebandView,
StatusBar,
PlatformUtils,
- WinFirewall;
+ WinFirewall,
+ BoardUtils, WisdomBuilder, UISync;
const
CLR_BG = TColor($00101010);
@@ -138,45 +138,6 @@ type
Display: string;
end;
- // Синхронизирующий объект для OnDeviceFound
- TDeviceFoundSync = class
- private
- FForm: TObject; // TMainForm, через forward ref
- FDev: THPSDRDevice;
- FEntry: string;
- public
- constructor Create(AForm: TObject; const D: THPSDRDevice; const E: string);
- procedure Execute;
- end;
-
- // Синхронизирующий объект для HP Status
- TStatusUISync = class
- private
- FForm: TObject;
- FFwdW: Double;
- FSWRV: Double;
- FSupplyV: Double;
- FSupplyA: Double;
- FPLLLock: Boolean;
- FHWPTT: Boolean;
- FADCOverload: Byte;
- public
- constructor Create(AForm: TObject; FW, SW, SV, SA: Double; PLL, HWPTT: Boolean;
- ADCOverload: Byte);
- procedure Execute;
- end;
-
- // Синхронизирующий объект для DDC IQ
- TDDCSeqSync = class
- private
- FForm: TObject;
- FDDCIdx: Integer;
- FSeq: LongWord;
- public
- constructor Create(AForm: TObject; Idx: Integer; Seq: LongWord);
- procedure Execute;
- end;
-
{ TMainForm }
TMainForm = class(TForm)
private
@@ -750,30 +711,6 @@ type
var Handled: Boolean);
end;
- TWisdomBuildThread = class(TThread)
- private
- FDirectory: string;
- FError: string;
- protected
- procedure Execute; override;
- public
- constructor Create(const ADirectory: string);
- property ErrorText: string read FError;
- end;
-
- TWisdomProgressDialog = class(TForm)
- private
- FInfoLabel: TLabel;
- FProgress: TFlatProgressBar;
- FTimer: TTimer;
- FThread: TWisdomBuildThread;
- FPhase: Integer;
- procedure TimerTick(Sender: TObject);
- public
- constructor Create(AOwner: TComponent; AThread: TWisdomBuildThread;
- const ATheme: TAppTheme); reintroduce;
- end;
-
var
MainForm: TMainForm;
@@ -783,20 +720,6 @@ uses SettingsForm;
{$R *.lfm}
-function HasOpenGLSpectrumSwitch: Boolean;
-var
- I: Integer;
- S: string;
-begin
- Result := False;
- for I := 1 to ParamCount do
- begin
- S := LowerCase(ParamStr(I));
- if (S = '--opengl') or (S = '-opengl') or (S = '/opengl') then
- Exit(True);
- end;
-end;
-
function TMainForm.LeftPanelButtonWidth(PanelWidth, ColCount,
ColIndex: Integer): Integer;
var
@@ -822,179 +745,10 @@ begin
LEFT_PANEL_BTN_GAP);
end;
-constructor TWisdomBuildThread.Create(const ADirectory: string);
-begin
- inherited Create(False);
- FreeOnTerminate := False;
- FDirectory := ADirectory;
- FError := '';
-end;
-
-procedure TWisdomBuildThread.Execute;
-var
- DirA: AnsiString;
-begin
- try
- if not Assigned(@WDSPwisdom) then Exit;
- DirA := AnsiString(FDirectory);
- WDSPwisdom(PAnsiChar(DirA));
- except
- on E: Exception do
- FError := E.ClassName + ': ' + E.Message;
- end;
-end;
-
-constructor TWisdomProgressDialog.Create(AOwner: TComponent;
- AThread: TWisdomBuildThread; const ATheme: TAppTheme);
-begin
- inherited CreateNew(AOwner);
- FThread := AThread;
- FPhase := 0;
-
- Caption := 'WDSP Wisdom';
- Width := 520;
- Height := 140;
- Position := poScreenCenter;
- BorderStyle := bsDialog;
- BorderIcons := [];
- Color := ATheme.BG;
- Font.Name := 'Courier New';
- Font.Size := 9;
- Font.Color := ATheme.Text;
-
- FInfoLabel := TLabel.Create(Self);
- FInfoLabel.Parent := Self;
- FInfoLabel.SetBounds(16, 16, 480, 40);
- FInfoLabel.AutoSize := False;
- FInfoLabel.WordWrap := True;
- FInfoLabel.Font.Color := ATheme.Text;
- FInfoLabel.Caption :=
- 'Creating FFTW wisdom for WDSP. This is done once and may take a while on the first run.';
-
- FProgress := TFlatProgressBar.Create(Self);
- FProgress.Parent := Self;
- FProgress.SetBounds(16, 72, 480, 22);
- FProgress.Min := 0;
- FProgress.Max := 100;
- FProgress.Position := 0;
- FProgress.SetAppTheme(ATheme);
-
- FTimer := TTimer.Create(Self);
- FTimer.Interval := 250;
- FTimer.OnTimer := TimerTick;
- FTimer.Enabled := True;
-end;
-
-procedure TWisdomProgressDialog.TimerTick(Sender: TObject);
-var
- P: PAnsiChar;
- S: string;
-begin
- FPhase := (FPhase + 7) mod 101;
- FProgress.Position := FPhase;
-
- if Assigned(@wisdom_get_status) then
- begin
- P := wisdom_get_status;
- if P <> nil then
- begin
- S := Trim(string(AnsiString(P)));
- if S <> '' then
- FInfoLabel.Caption := S;
- end;
- end;
-
- if Assigned(FThread) and FThread.Finished then
- begin
- FTimer.Enabled := False;
- ModalResult := mrOk;
- end;
-end;
-
-// ===========================================================================
-// Общая функция декодирования типа платы — используется везде
-// ===========================================================================
-
-function BoardTypeName(BoardType: Integer): string;
-begin
- case BoardType of
- 1: Result := 'HERMES (ANAN-10/100)';
- 2: Result := 'HERMES-E (ANAN-10E/100B)';
- 3: Result := 'ANGELIA (ANAN-100D)';
- 4: Result := 'ORION (ANAN-200D)';
- 5: Result := 'ORION MkII (ANAN-7000/8000)';
- 6: Result := 'HERMES-LITE 2';
- 10: Result := 'SATURN (G2)';
- else Result := Format('Unknown Board #%d', [BoardType]);
- end;
-end;
-
-// ===========================================================================
-// Sync helpers
-// ===========================================================================
-
-constructor TDeviceFoundSync.Create(AForm: TObject;
- const D: THPSDRDevice; const E: string);
-begin
- inherited Create;
- FForm := AForm;
- FDev := D;
- FEntry := E;
-end;
-
-procedure TDeviceFoundSync.Execute;
-begin
- TMainForm(FForm).DoAddDevice(FDev, FEntry);
-end;
-
-constructor TStatusUISync.Create(AForm: TObject;
- FW, SW, SV, SA: Double; PLL, HWPTT: Boolean; ADCOverload: Byte);
-begin
- inherited Create;
- FForm := AForm;
- FFwdW := FW;
- FSWRV := SW;
- FSupplyV := SV;
- FSupplyA := SA;
- FPLLLock := PLL;
- FHWPTT := HWPTT;
- FADCOverload := ADCOverload;
-end;
-
-procedure TStatusUISync.Execute;
-begin
- TMainForm(FForm).DoUpdateStatus(FFwdW, FSWRV, FSupplyV, FSupplyA, FPLLLock, FHWPTT,
- FADCOverload);
-end;
-
-constructor TDDCSeqSync.Create(AForm: TObject; Idx: Integer; Seq: LongWord);
-begin
- inherited Create;
- FForm := AForm;
- FDDCIdx := Idx;
- FSeq := Seq;
-end;
-
-procedure TDDCSeqSync.Execute;
-begin
- TMainForm(FForm).DoUpdateDDCSeqOrNoDevice(FDDCIdx, FSeq);
-end;
-
-// ===========================================================================
-// FormCreate / FormDestroy
-// ===========================================================================
-
-
// ===========================================================================
// Settings helpers
// ===========================================================================
-function CurrentScreenDPI: Integer;
-begin
- Result := Screen.PixelsPerInch;
- if Result <= 0 then Result := 96;
-end;
-
procedure TMainForm.RestoreWindowBounds;
var
L, T, Wd, Ht, SavedDPI, CurDPI: Integer;
@@ -3394,7 +3148,7 @@ begin
Entry := Format('%s %s FW:%d DDC:%d',
[Dev.IPAddress, BoardName,
Dev.FirmwareVersion, Dev.NumDDCs]);
- Sync := TDeviceFoundSync.Create(Self, Dev, Entry);
+ Sync := TDeviceFoundSync.Create(DoAddDevice, Dev, Entry);
try
M := Sync.Execute;
TThread.Synchronize(nil, M);
@@ -3483,7 +3237,7 @@ begin
end else
SWRV := 1.0;
if not IsTx then FwdW := 0;
- Sync := TStatusUISync.Create(Self, FwdW, SWRV, SupplyV, SupplyA,
+ Sync := TStatusUISync.Create(DoUpdateStatus, FwdW, SWRV, SupplyV, SupplyA,
(Status.StatusBits and HPS_PLL_LOCKED) <> 0,
(Status.StatusBits and HPS_PTT) <> 0,
Status.ADCOverload);
@@ -3886,7 +3640,7 @@ begin
if Length(Devs) = 0 then
begin
// DDCIdx = -1 is the sentinel for "no device found"
- Sync := TDDCSeqSync.Create(FForm, -1, 0);
+ Sync := TDDCSeqSync.Create(FForm.DoUpdateDDCSeqOrNoDevice, -1, 0);
try
M := Sync.Execute;
TThread.Synchronize(nil, M);
diff --git a/PlatformUtils.pas b/PlatformUtils.pas
index 0ab1404..55d955d 100644
--- a/PlatformUtils.pas
+++ b/PlatformUtils.pas
@@ -11,11 +11,13 @@ unit PlatformUtils;
interface
function QtPlatformAllowsOpenGLControls: Boolean;
+function HasOpenGLSpectrumSwitch: Boolean;
+function CurrentScreenDPI: Integer;
implementation
uses
- SysUtils;
+ SysUtils, Forms;
function QtPlatformAllowsOpenGLControls: Boolean;
var
@@ -39,4 +41,24 @@ begin
Result := SessionType <> 'wayland';
end;
+function HasOpenGLSpectrumSwitch: Boolean;
+var
+ I: Integer;
+ S: string;
+begin
+ Result := False;
+ for I := 1 to ParamCount do
+ begin
+ S := LowerCase(ParamStr(I));
+ if (S = '--opengl') or (S = '-opengl') or (S = '/opengl') then
+ Exit(True);
+ end;
+end;
+
+function CurrentScreenDPI: Integer;
+begin
+ Result := Screen.PixelsPerInch;
+ if Result <= 0 then Result := 96;
+end;
+
end.
diff --git a/UISync.pas b/UISync.pas
new file mode 100644
index 0000000..557cef7
--- /dev/null
+++ b/UISync.pas
@@ -0,0 +1,105 @@
+unit UISync;
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+interface
+
+uses
+ Classes, HPSDRNetwork;
+
+type
+ TAddDeviceProc = procedure(const Dev: THPSDRDevice; const Entry: string) of object;
+ TUpdateStatusProc = procedure(FwdW, SWRV, SupplyV, SupplyA: Double;
+ PLLLock, HWPTT: Boolean; ADCOverload: Byte) of object;
+ TUpdateDDCSeqOrNoDeviceProc = procedure(DDCIdx: Integer; Seq: LongWord) of object;
+
+ TDeviceFoundSync = class
+ private
+ FCallback: TAddDeviceProc;
+ FDev: THPSDRDevice;
+ FEntry: string;
+ public
+ constructor Create(ACallback: TAddDeviceProc; const D: THPSDRDevice;
+ const E: string);
+ procedure Execute;
+ end;
+
+ TStatusUISync = class
+ private
+ FCallback: TUpdateStatusProc;
+ FFwdW: Double;
+ FSWRV: Double;
+ FSupplyV: Double;
+ FSupplyA: Double;
+ FPLLLock: Boolean;
+ FHWPTT: Boolean;
+ FADCOverload: Byte;
+ public
+ constructor Create(ACallback: TUpdateStatusProc;
+ FW, SW, SV, SA: Double; PLL, HWPTT: Boolean; ADCOverload: Byte);
+ procedure Execute;
+ end;
+
+ TDDCSeqSync = class
+ private
+ FCallback: TUpdateDDCSeqOrNoDeviceProc;
+ FDDCIdx: Integer;
+ FSeq: LongWord;
+ public
+ constructor Create(ACallback: TUpdateDDCSeqOrNoDeviceProc;
+ Idx: Integer; Seq: LongWord);
+ procedure Execute;
+ end;
+
+implementation
+
+constructor TDeviceFoundSync.Create(ACallback: TAddDeviceProc;
+ const D: THPSDRDevice; const E: string);
+begin
+ inherited Create;
+ FCallback := ACallback;
+ FDev := D;
+ FEntry := E;
+end;
+
+procedure TDeviceFoundSync.Execute;
+begin
+ FCallback(FDev, FEntry);
+end;
+
+constructor TStatusUISync.Create(ACallback: TUpdateStatusProc;
+ FW, SW, SV, SA: Double; PLL, HWPTT: Boolean; ADCOverload: Byte);
+begin
+ inherited Create;
+ FCallback := ACallback;
+ FFwdW := FW;
+ FSWRV := SW;
+ FSupplyV := SV;
+ FSupplyA := SA;
+ FPLLLock := PLL;
+ FHWPTT := HWPTT;
+ FADCOverload := ADCOverload;
+end;
+
+procedure TStatusUISync.Execute;
+begin
+ FCallback(FFwdW, FSWRV, FSupplyV, FSupplyA, FPLLLock, FHWPTT, FADCOverload);
+end;
+
+constructor TDDCSeqSync.Create(ACallback: TUpdateDDCSeqOrNoDeviceProc;
+ Idx: Integer; Seq: LongWord);
+begin
+ inherited Create;
+ FCallback := ACallback;
+ FDDCIdx := Idx;
+ FSeq := Seq;
+end;
+
+procedure TDDCSeqSync.Execute;
+begin
+ FCallback(FDDCIdx, FSeq);
+end;
+
+end.
diff --git a/WisdomBuilder.pas b/WisdomBuilder.pas
new file mode 100644
index 0000000..906cf75
--- /dev/null
+++ b/WisdomBuilder.pas
@@ -0,0 +1,129 @@
+unit WisdomBuilder;
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+interface
+
+uses
+ Classes, SysUtils, Forms, Controls, ExtCtrls, StdCtrls,
+ WDSP, AppTheme, FlatProgressBar;
+
+type
+ TWisdomBuildThread = class(TThread)
+ private
+ FDirectory: string;
+ FError: string;
+ protected
+ procedure Execute; override;
+ public
+ constructor Create(const ADirectory: string);
+ property ErrorText: string read FError;
+ end;
+
+ TWisdomProgressDialog = class(TForm)
+ private
+ FInfoLabel: TLabel;
+ FProgress: TFlatProgressBar;
+ FTimer: TTimer;
+ FThread: TWisdomBuildThread;
+ FPhase: Integer;
+ procedure TimerTick(Sender: TObject);
+ public
+ constructor Create(AOwner: TComponent; AThread: TWisdomBuildThread;
+ const ATheme: TAppTheme); reintroduce;
+ end;
+
+implementation
+
+constructor TWisdomBuildThread.Create(const ADirectory: string);
+begin
+ inherited Create(False);
+ FreeOnTerminate := False;
+ FDirectory := ADirectory;
+ FError := '';
+end;
+
+procedure TWisdomBuildThread.Execute;
+var
+ DirA: AnsiString;
+begin
+ try
+ if not Assigned(@WDSPwisdom) then Exit;
+ DirA := AnsiString(FDirectory);
+ WDSPwisdom(PAnsiChar(DirA));
+ except
+ on E: Exception do
+ FError := E.ClassName + ': ' + E.Message;
+ end;
+end;
+
+constructor TWisdomProgressDialog.Create(AOwner: TComponent;
+ AThread: TWisdomBuildThread; const ATheme: TAppTheme);
+begin
+ inherited CreateNew(AOwner);
+ FThread := AThread;
+ FPhase := 0;
+
+ Caption := 'WDSP Wisdom';
+ Width := 520;
+ Height := 140;
+ Position := poScreenCenter;
+ BorderStyle := bsDialog;
+ BorderIcons := [];
+ Color := ATheme.BG;
+ Font.Name := 'Courier New';
+ Font.Size := 9;
+ Font.Color := ATheme.Text;
+
+ FInfoLabel := TLabel.Create(Self);
+ FInfoLabel.Parent := Self;
+ FInfoLabel.SetBounds(16, 16, 480, 40);
+ FInfoLabel.AutoSize := False;
+ FInfoLabel.WordWrap := True;
+ FInfoLabel.Font.Color := ATheme.Text;
+ FInfoLabel.Caption :=
+ 'Creating FFTW wisdom for WDSP. This is done once and may take a while on the first run.';
+
+ FProgress := TFlatProgressBar.Create(Self);
+ FProgress.Parent := Self;
+ FProgress.SetBounds(16, 72, 480, 22);
+ FProgress.Min := 0;
+ FProgress.Max := 100;
+ FProgress.Position := 0;
+ FProgress.SetAppTheme(ATheme);
+
+ FTimer := TTimer.Create(Self);
+ FTimer.Interval := 250;
+ FTimer.OnTimer := TimerTick;
+ FTimer.Enabled := True;
+end;
+
+procedure TWisdomProgressDialog.TimerTick(Sender: TObject);
+var
+ P: PAnsiChar;
+ S: string;
+begin
+ FPhase := (FPhase + 7) mod 101;
+ FProgress.Position := FPhase;
+
+ if Assigned(@wisdom_get_status) then
+ begin
+ P := wisdom_get_status;
+ if P <> nil then
+ begin
+ S := Trim(string(AnsiString(P)));
+ if S <> '' then
+ FInfoLabel.Caption := S;
+ end;
+ end;
+
+ if Assigned(FThread) and FThread.Finished then
+ begin
+ FTimer.Enabled := False;
+ ModalResult := mrOk;
+ end;
+end;
+
+end.
diff --git a/ewsdr.lpi b/ewsdr.lpi
index 55ed8f9..551070f 100644
--- a/ewsdr.lpi
+++ b/ewsdr.lpi
@@ -214,6 +214,18 @@
+
+
+
+
+
+
+
+
+
+
+
+