feat(puresignal): PureSignal-предыскажение для openHPSDR P2 + кнопки PS/2TON

Протокол (по pihpsdr new_protocol.c): на PTT при PS DDC0<-ADC0 (RX-feedback),
DDC1<-ADC2 (TX DAC loopback), 192к/24бит, sync DDC1->DDC0 (byte 1363=0x02,
interleaved в потоке DDC0), частоты DDC0/1 = TX в HP-пакете, Alex0 bit18
(мост обратной связи). Caps.HasPureSignal для плат с DDCBase=2
(Angelia/Orion/Orion2/Saturn); попутно NumADCs=2 для Angelia.

WDSPEngine: PushPSFeedback (деинтерлив -> pscc(TXA, tx=DDC1, rx=DDC0) из
сетевого потока), PS-параметры calcc в кэше с переприменением после
пересоздания TXA; SetTXTwoTone (PostGen mode 1, 700/1900, 0.49+0.49,
инверсия LSB/CWL/DIGL, мьют mic как TUN).

RadioController: state machine команд (порт Thetis PSForm timer1) в
PureSignalTick @10Гц + auto-attenuate (AttOnTX по уровню feedback, цель
~152, через DUC Specific); SetPSMox и перестройка feedback-DDC на T/R;
маршрутизация DDC0 в pscc из OnDDCIQ; SetTwoTone с гейтами safety.

UI: кнопки PS (ЛКМ = поповер настроек, ПКМ = быстрый toggle) и 2TON в
блоке TX; поповер TPureSignalPopup (дочерний контрол, Wayland-safe):
PS ON/OFF, CAL, RESET, 2TON, лампа/уровень feedback, cals, corr,
GetPk/SetPk, MOX/CAL wait, PH#, Auto-atten, Relax ptol, Pin/Map/Stbl,
Tint, тона двухтональника. Персист ps_* в tx-секции per-device.

Не проверено на железе; Save/Restore коррекции не реализованы.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-16 11:55:26 +03:00
co-authored by Claude Fable 5
parent a84de32294
commit 3acd569da5
8 changed files with 1284 additions and 14 deletions
+89 -1
View File
@@ -33,7 +33,7 @@ uses
WebServer, WebAdapter,
CATAdapter,
SpectrumView, SpectrumViewOpengl,
PanZoomBar, PanafallPanel, PanDisplayPopup, FlatPopupMenu,
PanZoomBar, PanafallPanel, PanDisplayPopup, PureSignalPopup, FlatPopupMenu,
WidebandView,
StatusBar,
PlatformUtils,
@@ -337,6 +337,9 @@ type
TrkDrive: TFlatSlider;
BtnMOX: TFlatButton;
BtnTUN: TFlatButton;
BtnPS: TFlatButton; // PureSignal: ЛКМ = вкл/выкл, ПКМ = поповер настроек
Btn2Ton: TFlatButton; // двухтональник (IMD/проверка PS)
FPSPopup: TObject; // TPureSignalPopup (cast при использовании)
PanelRXBlock: TPanel;
BtnChannels: TFlatButton;
@@ -460,6 +463,13 @@ type
procedure UpdateBandPlanOverlay; // вкл/выкл полоски бэндплана QO-100 по InQO100
procedure BtnTUNClick(Sender: TObject);
procedure ApplyTUN(Active: Boolean);
// PureSignal: ЛКМ по PS = вкл/выкл, ПКМ = поповер настроек.
procedure BtnPSClick(Sender: TObject);
procedure BtnPSMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Btn2TonClick(Sender: TObject);
procedure OnPSPopupChanged(Sender: TObject); // персист PS-параметров
procedure UpdatePSButtons; // стиль/доступность PS/2TON
procedure UpdateFilterButtons;
procedure BtnFMSQClick(Sender: TObject);
procedure TrkFMSQChange(Sender: TObject);
@@ -1369,6 +1379,8 @@ begin
end; // (DUC-очередь сбрасывает SetMOX)
rfTuning:
StyleButton(BtnTUN, FController.FTuning);
rfPureSignal, rfTwoTone:
UpdatePSButtons; // подсветка PS/2TON + обновление статусов поповера
rfRunning:
// Run-состояние: кнопка START/STOP, доступность MOX, запрет сна.
// Текст offline-статуса контекстно-зависим (Disconnected / Connection
@@ -1952,6 +1964,14 @@ begin
BtnTUN := MakeBtn(PanelTX, 'TUN',
LeftPanelButtonLeft(LEFT_W, 4, 1), 16,
LeftPanelButtonWidth(LEFT_W, 4, 1), BTN_SM, BtnTUNClick);
// PureSignal: ЛКМ = вкл/выкл, ПКМ = поповер настроек/управления.
BtnPS := MakeBtn(PanelTX, 'PS',
LeftPanelButtonLeft(LEFT_W, 4, 2), 16,
LeftPanelButtonWidth(LEFT_W, 4, 2), BTN_SM, BtnPSClick);
BtnPS.OnMouseDown := BtnPSMouseDown;
Btn2Ton := MakeBtn(PanelTX, '2TON',
LeftPanelButtonLeft(LEFT_W, 4, 3), 16,
LeftPanelButtonWidth(LEFT_W, 4, 3), BTN_SM, Btn2TonClick);
UpdateTXControlAvailability;
BtnDUP := MakeBtn(PanelTX, 'DUP',
@@ -3291,6 +3311,9 @@ begin
FController.ServiceBeaconLock;
// Pluto: опрос температуры/RSSI (троттлинг внутри; no-op для HPSDR).
FController.ServicePlutoTelemetry;
// PureSignal: state machine команд + auto-attenuate + опрос GetPSInfo
// (no-op на бэкендах без PS; рендер кнопок/поповера через rfPureSignal).
FController.PureSignalTick;
// Сглаженное среднее (EMA)
FSMeterAvg := FSMeterAvg * (1.0 - AVG_ALPHA) + FController.FLastSMeter * AVG_ALPHA;
@@ -3534,6 +3557,25 @@ begin
(FController.ActiveTXMode <> MODE_DMR);
BtnMOX.Enabled := Allowed;
BtnTUN.Enabled := Allowed;
UpdatePSButtons;
end;
procedure TMainForm.UpdatePSButtons;
// PS: доступен на openHPSDR-платах с feedback-DDC (Caps.HasPureSignal) при
// Run. 2TON — обычный TX-тест, доступен как MOX/TUN.
var
PSAllowed, TXAllowed: Boolean;
begin
if (BtnPS = nil) or (Btn2Ton = nil) or (FController = nil) then Exit;
TXAllowed := FController.FRunning and
(FController.ActiveTXMode <> MODE_DMR);
PSAllowed := TXAllowed and FController.PSAvailable;
BtnPS.Enabled := PSAllowed;
Btn2Ton.Enabled := TXAllowed;
StyleButton(BtnPS, FController.FPSEnabled or FController.PSSingleCalActive);
StyleButton(Btn2Ton, FController.FTwoTone);
if (FPSPopup <> nil) and TPureSignalPopup(FPSPopup).Visible then
TPureSignalPopup(FPSPopup).RefreshStatus;
end;
procedure TMainForm.UpdateStatusField3;
@@ -4481,6 +4523,52 @@ begin
ApplyTUN(not FController.FTuning);
end;
// ---------------------------------------------------------------------------
// PureSignal: кнопка PS (ЛКМ = вкл/выкл, ПКМ = поповер настроек) + 2TON
// ---------------------------------------------------------------------------
procedure TMainForm.BtnPSClick(Sender: TObject);
begin
if not FController.PSAvailable then Exit;
FController.SetPureSignal(not FController.FPSEnabled); // рендер через rfPureSignal
end;
procedure TMainForm.BtnPSMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
Pop: TPureSignalPopup;
begin
if Button <> mbRight then Exit;
if not FController.PSAvailable then Exit;
if FPSPopup = nil then
begin
Pop := TPureSignalPopup.Create(Self);
Pop.OnChanged := OnPSPopupChanged;
FPSPopup := Pop;
end
else
Pop := TPureSignalPopup(FPSPopup);
if Pop.Visible then
Pop.Hide
else
Pop.PopupBelow(FController, BtnPS);
end;
procedure TMainForm.Btn2TonClick(Sender: TObject);
begin
FController.SetTwoTone(not FController.FTwoTone); // рендер через rfTwoTone
end;
procedure TMainForm.OnPSPopupChanged(Sender: TObject);
// Правка PS-параметров в поповере: применение к WDSP делает сам поповер
// (ApplyPSSettingsToDSP), здесь — только персист per-device.
begin
if FController.FDevConnected then
begin
FController.FSettings.SaveTX(FController.FDevMAC, FController.FTXSettings);
FController.FSettings.Save;
end;
end;
// ---------------------------------------------------------------------------
// Клик/драг по спектру/водопаду
// ---------------------------------------------------------------------------