mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
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:
@@ -103,6 +103,9 @@ type
|
||||
// сильно разное на 2м и на QO-100, поэтому режим и manual-гейн per-band.
|
||||
RxGainMode: Integer; // 0=manual,1=fast,2=slow,3=hybrid
|
||||
RxGainDb: Integer; // manual gain, дБ (0..73)
|
||||
// Шаговый аттенюатор ADC (openHPSDR) — на диапазон: на 40м ночью нужен,
|
||||
// на 10м нет. 0..31 дБ.
|
||||
AttenDB: Integer;
|
||||
end;
|
||||
|
||||
// Персист панадаптеров и слайсов (секция "pans" под MAC). Восстанавливается
|
||||
@@ -295,6 +298,7 @@ type
|
||||
// Аппаратный AGC AD936x на слот трансвертера (у QO-100 своё усиление тракта).
|
||||
LastRxGainMode: Integer; // 0=manual,1=fast,2=slow,3=hybrid
|
||||
LastRxGainDb: Integer; // manual gain, дБ
|
||||
LastAttenDB: Integer; // шаговый аттенюатор ADC слота, дБ (0..31)
|
||||
end;
|
||||
|
||||
TXvtrSettings = record
|
||||
@@ -558,6 +562,7 @@ begin
|
||||
B.SpanHz := 192000;
|
||||
B.RxGainMode := 2; // slow_attack (как глобальный дефолт Pluto)
|
||||
B.RxGainDb := 40;
|
||||
B.AttenDB := 0;
|
||||
B.FMSQOn := False;
|
||||
B.FMSQLevel := 30;
|
||||
B.CTCSSOn := False;
|
||||
@@ -944,6 +949,7 @@ begin
|
||||
Bands[i].FMRptOffsetHz := JD(BObj,'fmrpt_offset', Bands[i].FMRptOffsetHz);
|
||||
Bands[i].RxGainMode := EnsureRange(JI(BObj,'rx_gain_mode', Bands[i].RxGainMode), 0, 3);
|
||||
Bands[i].RxGainDb := EnsureRange(JI(BObj,'rx_gain_db', Bands[i].RxGainDb), 0, 73);
|
||||
Bands[i].AttenDB := EnsureRange(JI(BObj,'atten_db', Bands[i].AttenDB), 0, 31);
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -1060,6 +1066,7 @@ begin
|
||||
JW(O,'fmrpt_dir',B.FMRptDir); JW(O,'fmrpt_offset',B.FMRptOffsetHz);
|
||||
JW(O,'zoom_factor',B.ZoomFactor); JW(O,'pan_slider',B.PanSlider);
|
||||
JW(O,'rx_gain_mode',B.RxGainMode); JW(O,'rx_gain_db',B.RxGainDb);
|
||||
JW(O,'atten_db',B.AttenDB);
|
||||
end;
|
||||
|
||||
function TSettingsManager.LoadBand(const MAC: array of Byte; BandIdx: Integer;
|
||||
@@ -1091,6 +1098,7 @@ begin
|
||||
B.FMRptOffsetHz := JD(O,'fmrpt_offset', B.FMRptOffsetHz);
|
||||
B.RxGainMode := EnsureRange(JI(O,'rx_gain_mode', B.RxGainMode), 0, 3);
|
||||
B.RxGainDb := EnsureRange(JI(O,'rx_gain_db', B.RxGainDb), 0, 73);
|
||||
B.AttenDB := EnsureRange(JI(O,'atten_db', B.AttenDB), 0, 31);
|
||||
B.ZoomFactor := EnsureRange(JD(O,'zoom_factor', B.ZoomFactor), 0.0, 1.0);
|
||||
B.PanSlider := EnsureRange(JD(O,'pan_slider', B.PanSlider), 0.0, 1.0);
|
||||
end;
|
||||
@@ -1617,6 +1625,7 @@ begin
|
||||
X.Entries[i].LastPanSlider := 0.5;
|
||||
X.Entries[i].LastRxGainMode := 2; // slow_attack
|
||||
X.Entries[i].LastRxGainDb := 40;
|
||||
X.Entries[i].LastAttenDB := 0;
|
||||
end;
|
||||
// Шаблоны (пользователь должен сам Enable, чтобы трансверторы появились)
|
||||
X.Entries[0].ButtonText := '2m';
|
||||
@@ -1698,6 +1707,7 @@ begin
|
||||
X.Entries[i].LastPanSlider := EnsureRange(JD(EObj, 'last_pan_slider', X.Entries[i].LastPanSlider), 0.0, 1.0);
|
||||
X.Entries[i].LastRxGainMode := EnsureRange(JI(EObj, 'last_rx_gain_mode', X.Entries[i].LastRxGainMode), 0, 3);
|
||||
X.Entries[i].LastRxGainDb := EnsureRange(JI(EObj, 'last_rx_gain_db', X.Entries[i].LastRxGainDb), 0, 73);
|
||||
X.Entries[i].LastAttenDB := EnsureRange(JI(EObj, 'last_atten_db', X.Entries[i].LastAttenDB), 0, 31);
|
||||
// Валидация: Last freqs должны быть в [FreqBegin..FreqEnd]
|
||||
if (X.Entries[i].LastFreq < X.Entries[i].FreqBegin) or
|
||||
(X.Entries[i].LastFreq > X.Entries[i].FreqEnd) then
|
||||
@@ -1798,6 +1808,7 @@ begin
|
||||
JW(EObj, 'last_pan_slider', X.Entries[i].LastPanSlider);
|
||||
JW(EObj, 'last_rx_gain_mode', X.Entries[i].LastRxGainMode);
|
||||
JW(EObj, 'last_rx_gain_db', X.Entries[i].LastRxGainDb);
|
||||
JW(EObj, 'last_atten_db', X.Entries[i].LastAttenDB);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user