feature(rx): плавный аттенюатор 0..31 дБ в UI, память на диапазон, компенсация уровней

Аттенюатор был только в web и только тремя ступенями (0/-10/-20), а его дБ
никуда не возвращались — при ATT 20 дБ S-метр и спектр уезжали на 20 дБ, и
свежая калибровка уровней была верна лишь при ATT=0.

- RadioController: SetAtten(Db) 0..31 (как умеет железо) вместо индекса *10.
  AttenCalDB входит в SMeterCalFor и DispCalFor — стрелка, спектр, водопад и
  паны компенсируются, шкала dBm остаётся абсолютной (как Thetis/piHPSDR).
  У AD936x аттенюатора нет, там поправка 0 (усиление тракта — hardwaregain).
- Память на диапазон/слот трансвертера по образцу RxGainMode/RxGainDb:
  TBandSettings.AttenDB (band 'atten_db') и TXvtrEntry.LastAttenDB
  ('last_atten_db'); восстановление и отправка в железо — в ApplyBandDSP,
  сбор — в MakeBandSettings/SaveCurrentBand, вход в слот — через B.AttenDB.
  SetAtten сразу кладёт значение в кэш диапазона/слота (JSON пишется общим
  сохранением, а не на каждый шаг ползунка — как у drive).
- MainForm: ряд «ATT [ползунок] NNdB» в RX-блоке левой панели, отступы как у
  VOL; на Pluto ряд скрыт и RX-блок ужимается (LayoutLeftPanel двигает
  панели ниже). Внешние изменения приходят по rfAtten.
- Web: select → ползунок 0..31 с цифрой, attn_idx -> attn_db, cmd attn {db:}.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-21 11:41:21 +03:00
co-authored by Claude Opus 4.8
parent 366d4c9821
commit 6de8c00689
5 changed files with 127 additions and 22 deletions
+9 -9
View File
@@ -296,7 +296,7 @@ type
FDriveLevel: Integer;
FOnFreqA: TWebCmdFreqA;
FOnAttn: TWebCmdAttn;
FAttnIdx: Integer;
FAttnDB: Integer; // шаговый аттенюатор ADC, дБ (0..31)
FOnTun: TWebCmdTun;
FOnFMStep: TWebCmdFMStep;
FTuning: Boolean;
@@ -406,7 +406,7 @@ type
CenterHz: Double; FilterIdx: Integer;
VfoB: Double; ActiveVfo: Integer;
Transmitting: Boolean; DriveLevel: Integer;
AttnIdx: Integer; Tuning: Boolean; Duplex: Boolean;
AttnDB: Integer; Tuning: Boolean; Duplex: Boolean;
FwdW, SWRV, PAMaxPower: Double;
const StatusText, BoardText, IPText, SupplyText, PLLText,
RXText, TXText, SeqText: string);
@@ -1572,10 +1572,10 @@ begin
end
else if Cmd = 'attn' then
begin
Idx := JsonGetInt(Json, 'idx', FAttnIdx);
Idx := JsonGetInt(Json, 'db', FAttnDB);
if Idx < 0 then Idx := 0;
if Idx > 2 then Idx := 2;
FStateLock.Enter; FAttnIdx := Idx; FStateLock.Leave;
if Idx > 31 then Idx := 31;
FStateLock.Enter; FAttnDB := Idx; FStateLock.Leave;
if Assigned(FOnAttn) then FOnAttn(Idx);
end
else if Cmd = 'fm_step' then
@@ -1778,7 +1778,7 @@ begin
'"wf_agc":%s,"wf_nf":%s,"band_idx":%d,"smeter_dbm":%.1f,' +
'"running":%s,"mute":%s,"ctun":%s,' +
'"nr_mode":%d,"nr":%s,"nb_mode":%d,"nb":%s,"snb":%s,"anf":%s,"connected":%s,' +
'"transmitting":%s,"drive":%d,"attn_idx":%d,"tuning":%s,"dup":%s,' +
'"transmitting":%s,"drive":%d,"attn_db":%d,"tuning":%s,"dup":%s,' +
'"fwd_w":%.1f,"swr":%.2f,"pa_max_power":%.0f,' +
'"status_text":"%s","board_text":"%s","ip_text":"%s","supply_text":"%s",' +
'"pll_text":"%s","rx_text":"%s","tx_text":"%s","seq_text":"%s",' +
@@ -1809,7 +1809,7 @@ begin
BoolToStr(FConnected, 'true', 'false'),
BoolToStr(FTransmitting, 'true', 'false'),
FDriveLevel,
FAttnIdx,
FAttnDB,
BoolToStr(FTuning, 'true', 'false'),
BoolToStr(FDuplex, 'true', 'false'),
FFwdW, FSWR, FPAMaxPower,
@@ -1889,7 +1889,7 @@ procedure TWebServer.PushSpectrum(
CenterHz: Double; FilterIdx: Integer;
VfoB: Double; ActiveVfo: Integer;
Transmitting: Boolean; DriveLevel: Integer;
AttnIdx: Integer; Tuning: Boolean; Duplex: Boolean;
AttnDB: Integer; Tuning: Boolean; Duplex: Boolean;
FwdW, SWRV, PAMaxPower: Double;
const StatusText, BoardText, IPText, SupplyText, PLLText,
RXText, TXText, SeqText: string);
@@ -1926,7 +1926,7 @@ begin
FActiveVfo := ActiveVfo;
FTransmitting := Transmitting;
FDriveLevel := DriveLevel;
FAttnIdx := AttnIdx;
FAttnDB := AttnDB;
FTuning := Tuning;
FDuplex := Duplex;
FFwdW := FwdW;