feature(pluto): компенсация hardwaregain в уровнях + живое усиление в блоке RF AGC

На Pluto шкала dBm ничего не значила: усиление тракта 0..73 дБ входит в
показания напрямую, а в режимах AGC железо крутит его само, и картинка
«дышит» вместе с ним.

- RadioBackend: виртуальный RxGainNowDb (TELEMETRY_NONE = регулируемого
  усиления нет, как у openHPSDR с его аттенюатором).
- PlutoBackend: в MANUAL отдаёт FGainDb (точно, без опроса железа), в режимах
  AGC — hardwaregain из телеметрического потока (читается там же, где rssi,
  ~2 Гц, не блокируя UI).
- RadioController: AttenCalDB -> FrontEndCalDB, общее понятие «регулируемое
  усиление входа»: openHPSDR +FAtten (аттенюатор режет), AD936x -hardwaregain
  (усиление поднимает). Постоянная часть тракта (LNB, кабель, конвертер)
  остаётся за таблицами калибровки на диапазон/трансвертер.
- UI: в блоке RF AGC при режиме != MANUAL вместо надписи «AGC» — фактическое
  усиление («~38dB», тильда = измеренное), ползунок ездит сам. Видно, что
  цифра гуляет, а уровни на спектре стоят.

Ограничения: FAST AGC крутит усиление быстрее опроса (2 Гц), для стабильной
шкалы нужен MANUAL или SLOW; шумовая полка при смене усиления немного едет —
это физика (input-referred NF), компенсацию проверять по сигналу.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-21 11:50:28 +03:00
co-authored by Claude Opus 4.8
parent 6de8c00689
commit a95292d2c0
4 changed files with 84 additions and 16 deletions
+12 -2
View File
@@ -8004,10 +8004,20 @@ begin
for i := 0 to 3 do
if BtnPlutoGain[i] <> nil then
StyleButton(BtnPlutoGain[i], BtnPlutoGain[i].Tag = FController.FRxGainMode);
TrkRxGain.Position := FController.FRxGainDb;
TrkRxGain.Enabled := (FController.FRxGainMode = 0); // активен только в manual
if FController.FRxGainMode = 0 then
LblRxGain.Caption := Format('%ddB', [FController.FRxGainDb])
begin
TrkRxGain.Position := FController.FRxGainDb;
LblRxGain.Caption := Format('%ddB', [FController.FRxGainDb]);
end
else if FController.FLastPlutoGainDb > TELEMETRY_NONE then
begin
// AGC: показываем ФАКТИЧЕСКОЕ усиление железа (опрос ~2 Гц) — ползунок
// ездит сам, тильда отличает измеренное от заданного. На это же значение
// компенсируются уровни (FrontEndCalDB), поэтому шкала dBm стоит.
TrkRxGain.Position := EnsureRange(Round(FController.FLastPlutoGainDb), 0, 73);
LblRxGain.Caption := Format('~%ddB', [Round(FController.FLastPlutoGainDb)]);
end
else
LblRxGain.Caption := 'AGC';
finally