mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 17:27:32 +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:
+14
-1
@@ -204,6 +204,13 @@ begin
|
||||
'<button id="anfBtn">ANF</button>' +
|
||||
'<button id="nrBtn">NR</button>' +
|
||||
'<button id="bcnBtn" title="QO-100 beacon lock" style="display:none">BCN</button>' +
|
||||
'<button id="rxMuteBtn" title="QO-100 RX self-monitor mute on TX" style="display:none">RX MUTE</button>' +
|
||||
// Pluto RF-AGC (hw gain): режим FAST/SLOW/HYB/MAN + ручной gain (активен в MAN). Виден только на Pluto.
|
||||
'<select id="rfagcSel" title="Pluto RF AGC mode" style="display:none">' +
|
||||
'<option value="1">RFagc-F</option><option value="2" selected>RFagc-S</option>' +
|
||||
'<option value="3">RFagc-H</option><option value="0">RFagc-M</option>' +
|
||||
'</select>' +
|
||||
'<div class="sl-g" id="rfgainG" style="display:none"><span class="sl-lb">GAIN</span><input type="range" id="rfgainSl" min="0" max="73" value="40"><span class="sl-val" id="rfgainVal">40dB</span></div>' +
|
||||
'<span class="sl-sep">|</span>' +
|
||||
'<button id="devBtn" title="Devices">DEV</button>' +
|
||||
'<button id="startStopBtn" class="on">START</button>' +
|
||||
@@ -290,6 +297,8 @@ begin
|
||||
'function updSnbBtn(){sw("snbBtn",!!cur.snb);}' +
|
||||
'function updAnfBtn(){sw("anfBtn",!!cur.anf);}' +
|
||||
'function updBcnBtn(){const b=q("bcnBtn");if(!b)return;b.style.display=cur.beacon_visible?"":"none";sw("bcnBtn",!!cur.beacon_on);}' +
|
||||
'function updRxMute(){const b=q("rxMuteBtn");if(!b)return;b.style.display=cur.rx_mute_visible?"":"none";sw("rxMuteBtn",!!cur.rx_mute_on);}' +
|
||||
'function updRfAgc(){const vis=!!cur.rf_agc_visible;const s=q("rfagcSel"),g=q("rfgainG");if(s)s.style.display=vis?"":"none";if(g)g.style.display=vis?"":"none";if(!vis)return;const m=cur.rx_gain_mode|0;if(s&&!isPending("rxgain"))s.value=String(m);const sl=q("rfgainSl"),l=q("rfgainVal");if(sl&&!sl.matches(":active")){sl.value=cur.rx_gain_db|0;sl.disabled=(m!==0);}if(l)l.textContent=(cur.rx_gain_db|0)+"dB";}' +
|
||||
|
||||
|
||||
'const MODE_N=["LSB","USB","DSB","CWL","CWU","FM","AM","SAM"];' +
|
||||
@@ -447,6 +456,9 @@ begin
|
||||
'q("nrBtn").onclick=function(){cur.nr_mode=((cur.nr_mode|0)+1)%5;cur.nr=cur.nr_mode!==0;updNrBtn();pend("nr");ws2({cmd:"set_nr_mode",mode:cur.nr_mode});};' +
|
||||
'q("nbBtn").onclick=function(){cur.nb_mode=((cur.nb_mode|0)+1)%3;cur.nb=cur.nb_mode!==0;updNbBtn();pend("nb");ws2({cmd:"set_nb_mode",mode:cur.nb_mode});};' +
|
||||
'q("bcnBtn").onclick=function(){cur.beacon_on=!cur.beacon_on;beaconArm=cur.beacon_on;updBcnBtn();pend("beacon");cmd("set_beacon",cur.beacon_on);};' +
|
||||
'q("rxMuteBtn").onclick=function(){cur.rx_mute_on=!cur.rx_mute_on;updRxMute();pend("rxmute");cmd("set_rx_mute",cur.rx_mute_on);};' +
|
||||
'q("rfagcSel").onchange=function(e){const m=+e.target.value;cur.rx_gain_mode=m;pend("rxgain");updRfAgc();ws2({cmd:"set_rx_gain_mode",mode:m});};' +
|
||||
'q("rfgainSl").oninput=function(e){const v=+e.target.value;cur.rx_gain_db=v;cur.rx_gain_mode=0;const l=q("rfgainVal");if(l)l.textContent=v+"dB";const s=q("rfagcSel");if(s)s.value="0";pend("rxgain");ws2({cmd:"set_rx_gain",db:v});};' +
|
||||
'q("snbBtn").onclick=function(){cur.snb=!cur.snb;updSnbBtn();pend("snb");cmd("set_snb",cur.snb);};' +
|
||||
'q("anfBtn").onclick=function(){cur.anf=!cur.anf;updAnfBtn();pend("anf");cmd("set_anf",cur.anf);};' +
|
||||
|
||||
@@ -681,7 +693,7 @@ begin
|
||||
'function isPending(field){return !!(pendingCmds[field]&&pendingCmds[field]>Date.now());}' +
|
||||
|
||||
// Маппинг: server JSON field → pend key
|
||||
'var PEND_MAP={vfo_a_hz:"freq",vfo_b_hz:"freq",nr:"nr",nr_mode:"nr",nb:"nb",nb_mode:"nb",snb:"snb",anf:"anf",running:"run",mode:"mode",agc_mode:"agc",transmitting:"mox",drive:"drive",attn_idx:"attn",tuning:"tun",filter_bw:"filter",mute:"mute",beacon_on:"beacon"};' +
|
||||
'var PEND_MAP={vfo_a_hz:"freq",vfo_b_hz:"freq",nr:"nr",nr_mode:"nr",nb:"nb",nb_mode:"nb",snb:"snb",anf:"anf",running:"run",mode:"mode",agc_mode:"agc",transmitting:"mox",drive:"drive",attn_idx:"attn",tuning:"tun",filter_bw:"filter",mute:"mute",beacon_on:"beacon",rx_mute_on:"rxmute",rx_gain_mode:"rxgain",rx_gain_db:"rxgain"};' +
|
||||
|
||||
'function applyState(msg){' +
|
||||
'Object.keys(msg).forEach(function(k){var pk=PEND_MAP[k];if(!pk||!isPending(pk))cur[k]=msg[k];});' +
|
||||
@@ -728,6 +740,7 @@ begin
|
||||
'if(!isPending("nr"))updNrBtn();if(!isPending("nb"))updNbBtn();' +
|
||||
'if(!isPending("snb"))updSnbBtn();if(!isPending("anf"))updAnfBtn();' +
|
||||
'if(!isPending("beacon"))updBcnBtn();' +
|
||||
'if(!isPending("rxmute"))updRxMute();updRfAgc();' +
|
||||
'if(!isPending("run"))updRunBtn(!!cur.running);' +
|
||||
'if(!isPending("mox"))updMoxBtn(!!cur.transmitting);' +
|
||||
'if(!isPending("tun"))updToneBtn(!!cur.tuning);' +
|
||||
|
||||
Reference in New Issue
Block a user