mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 19:45:09 +00:00
feat: web RF-AGC + QO-100 RX MUTE controls (Pluto)
Прокинул в web-интерфейс управление, которого там не хватало (раньше только отображение): - RF-AGC (Pluto hw-gain): дропдаун режима FAST/SLOW/HYB/MAN + слайдер GAIN 0–73 дБ (активен только в MAN, драг переводит в manual). Виден по BackendCaps.HasHWGain (= Pluto подключён). Команды set_rx_gain_mode / set_rx_gain → SetRxGainMode / SetRxGain. - RX MUTE (QO-100 self-monitor): toggle-кнопка рядом с BCN, видна по InQO100, подсветка по состоянию. Команда set_rx_mute → SetRxMuteOnTx. Гейтинг зеркалит десктоп. Работает в GUI-web-сервере и headless-демоне. Проверено на железе пользователем. WebServer: команды + state-поля (rf_agc_visible/rx_gain_mode/rx_gain_db, rx_mute_visible/rx_mute_on) + SetRxGainStatus/SetRxMuteStatus. WebAdapter: колбэки OnRxGain*/OnRxMute (Invoke на поток контроллера) + публикация в PushState. MainForm + ewsdrd.lpr: привязка колбэков. WebPageHtml: виджеты, JS-обработчики, updRfAgc/updRxMute, PEND_MAP. Также актуализирован doc/PLUTO_INTEGRATION_PLAN.md: TX-тракт и режим QO-100 помечены проверенными на железе; раскрыт TODO «XO ppm-калибровка» (ручной TxLOOffset как текущий обходной путь, xo_correction/GPSDO как постоянное решение). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+75
-2
@@ -154,6 +154,10 @@ type
|
||||
// QO-100 beacon lock: вкл/выкл лок и наведение (клик по маяку, доля 0..1 по ширине).
|
||||
TWebCmdBeacon = procedure(On_: Boolean) of object;
|
||||
TWebCmdBeaconSeed = procedure(Frac: Double) of object;
|
||||
// Pluto RF-AGC (hw gain): режим FAST/SLOW/HYB/MAN + ручной gain дБ. RX MUTE — QO-100 self-monitor.
|
||||
TWebCmdRxGainMode = procedure(Mode: Integer) of object;
|
||||
TWebCmdRxGain = procedure(Db: Integer) of object;
|
||||
TWebCmdRxMute = procedure(On_: Boolean) of object;
|
||||
// Активность web-клиента изменилась (подключился/отключился последний клиент).
|
||||
// Хозяин зеркалит это в ядро (FController.FWebClientActive) для выбора mic-source.
|
||||
TWebClientActiveEvent = procedure(Active: Boolean) of object;
|
||||
@@ -330,6 +334,18 @@ type
|
||||
FOnBeacon: TWebCmdBeacon;
|
||||
FOnBeaconSeed: TWebCmdBeaconSeed;
|
||||
|
||||
// Pluto RF-AGC (hw gain) + QO-100 RX MUTE. Зеркалится в state как
|
||||
// rf_agc_visible/rx_gain_mode/rx_gain_db и rx_mute_visible/rx_mute_on;
|
||||
// команды set_rx_gain_mode/set_rx_gain/set_rx_mute.
|
||||
FRfAgcVisible: Boolean; // RF-AGC доступен (Pluto подключён, HasHWGain)
|
||||
FRxGainMode: Integer; // 0=manual,1=fast,2=slow,3=hybrid
|
||||
FRxGainDb: Integer; // ручной gain дБ (0..73)
|
||||
FRxMuteVisible: Boolean; // RX MUTE доступна (Pluto + QO-100)
|
||||
FRxMuteOn: Boolean; // self-monitor mute активен
|
||||
FOnRxGainMode: TWebCmdRxGainMode;
|
||||
FOnRxGain: TWebCmdRxGain;
|
||||
FOnRxMute: TWebCmdRxMute;
|
||||
|
||||
FWebClientActive: Boolean;
|
||||
FOnClientActiveChanged: TWebClientActiveEvent;
|
||||
|
||||
@@ -416,8 +432,14 @@ type
|
||||
// QO-100 beacon lock: зеркало статуса в state (зовётся из PushState хозяина).
|
||||
procedure SetBeaconStatus(AVisible, AOn: Boolean; const AText: string;
|
||||
ARefHz, ATrackHz: Double);
|
||||
// Pluto RF-AGC + QO-100 RX MUTE: зеркало в state (зовётся из PushState хозяина).
|
||||
procedure SetRxGainStatus(AVisible: Boolean; AMode, ADb: Integer);
|
||||
procedure SetRxMuteStatus(AVisible, AOn: Boolean);
|
||||
property OnBeacon: TWebCmdBeacon read FOnBeacon write FOnBeacon;
|
||||
property OnBeaconSeed: TWebCmdBeaconSeed read FOnBeaconSeed write FOnBeaconSeed;
|
||||
property OnRxGainMode: TWebCmdRxGainMode read FOnRxGainMode write FOnRxGainMode;
|
||||
property OnRxGain: TWebCmdRxGain read FOnRxGain write FOnRxGain;
|
||||
property OnRxMute: TWebCmdRxMute read FOnRxMute write FOnRxMute;
|
||||
property OnSpan: TWebCmdSpan read FOnSpan write FOnSpan;
|
||||
property OnVolume: TWebCmdVolume read FOnVolume write FOnVolume;
|
||||
property OnWfAGC: TWebCmdWfAGC read FOnWfAGC write FOnWfAGC;
|
||||
@@ -565,6 +587,11 @@ begin
|
||||
FBeaconText := '';
|
||||
FBeaconRefHz := 0;
|
||||
FBeaconTrackHz := 0;
|
||||
FRfAgcVisible := False;
|
||||
FRxGainMode := 2; // slow_attack по умолчанию (как контроллер)
|
||||
FRxGainDb := 40;
|
||||
FRxMuteVisible := False;
|
||||
FRxMuteOn := False;
|
||||
SetLength(FXvtrBands, 0);
|
||||
// Bootstrap-набор рейтов (до connect): хост перезапишет под бэкенд (HPSDR/Pluto).
|
||||
SetRatePresets([48000, 96000, 192000, 384000, 768000, 1536000]);
|
||||
@@ -604,6 +631,29 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TWebServer.SetRxGainStatus(AVisible: Boolean; AMode, ADb: Integer);
|
||||
begin
|
||||
FStateLock.Enter;
|
||||
try
|
||||
FRfAgcVisible := AVisible;
|
||||
FRxGainMode := AMode;
|
||||
FRxGainDb := ADb;
|
||||
finally
|
||||
FStateLock.Leave;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TWebServer.SetRxMuteStatus(AVisible, AOn: Boolean);
|
||||
begin
|
||||
FStateLock.Enter;
|
||||
try
|
||||
FRxMuteVisible := AVisible;
|
||||
FRxMuteOn := AOn;
|
||||
finally
|
||||
FStateLock.Leave;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TWebServer.SetDeviceList(const ADevices: TWebDeviceArray);
|
||||
var i: Integer;
|
||||
begin
|
||||
@@ -1496,6 +1546,24 @@ begin
|
||||
HzF := JsonGetFloat(Json, 'frac', -1);
|
||||
if (HzF >= 0) and Assigned(FOnBeaconSeed) then FOnBeaconSeed(HzF);
|
||||
end
|
||||
else if Cmd = 'set_rx_gain_mode' then
|
||||
begin
|
||||
Idx := JsonGetInt(Json, 'mode', FRxGainMode); // 0=man,1=fast,2=slow,3=hybrid
|
||||
FStateLock.Enter; FRxGainMode := Idx; FStateLock.Leave;
|
||||
if Assigned(FOnRxGainMode) then FOnRxGainMode(Idx);
|
||||
end
|
||||
else if Cmd = 'set_rx_gain' then
|
||||
begin
|
||||
DB := JsonGetInt(Json, 'db', FRxGainDb); // ручной gain 0..73 дБ
|
||||
FStateLock.Enter; FRxGainDb := DB; FStateLock.Leave;
|
||||
if Assigned(FOnRxGain) then FOnRxGain(DB);
|
||||
end
|
||||
else if Cmd = 'set_rx_mute' then
|
||||
begin
|
||||
On_ := JsonGetBool(Json, 'on', FRxMuteOn);
|
||||
FStateLock.Enter; FRxMuteOn := On_; FStateLock.Leave;
|
||||
if Assigned(FOnRxMute) then FOnRxMute(On_);
|
||||
end
|
||||
else if Cmd = 'freq_a' then
|
||||
begin
|
||||
HzF := JsonGetFloat(Json, 'hz', FFreq);
|
||||
@@ -1718,7 +1786,9 @@ begin
|
||||
'"fmstep_idx":%d,"devices":%s,"rate_presets":%s,"bands":%s,' +
|
||||
'"freq_min":%.0f,"freq_max":%.0f,' +
|
||||
'"beacon_visible":%s,"beacon_on":%s,"beacon_text":"%s",' +
|
||||
'"beacon_ref_hz":%.0f,"beacon_track_hz":%.0f}',
|
||||
'"beacon_ref_hz":%.0f,"beacon_track_hz":%.0f,' +
|
||||
'"rf_agc_visible":%s,"rx_gain_mode":%d,"rx_gain_db":%d,' +
|
||||
'"rx_mute_visible":%s,"rx_mute_on":%s}',
|
||||
[FFreq, FVfoB, FActiveVfo,
|
||||
FMode, MODE_N[FMode mod 8],
|
||||
FFilterIdx, FFilterBW,
|
||||
@@ -1751,7 +1821,10 @@ begin
|
||||
FFreqMin, FFreqMax,
|
||||
BoolToStr(FBeaconVisible, 'true', 'false'),
|
||||
BoolToStr(FBeaconOn, 'true', 'false'),
|
||||
JsonEscape(FBeaconText), FBeaconRefHz, FBeaconTrackHz
|
||||
JsonEscape(FBeaconText), FBeaconRefHz, FBeaconTrackHz,
|
||||
BoolToStr(FRfAgcVisible, 'true', 'false'), FRxGainMode, FRxGainDb,
|
||||
BoolToStr(FRxMuteVisible, 'true', 'false'),
|
||||
BoolToStr(FRxMuteOn, 'true', 'false')
|
||||
], FS);
|
||||
finally
|
||||
FStateLock.Leave;
|
||||
|
||||
Reference in New Issue
Block a user