mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-26 04:47:35 +00:00
feat: Pluto RX hw-gain control + AD9361 cold-init (FIR via libad9361)
- RX hw-gain (Pluto/AD936x): backend SetRxGain(ModeIdx, GainDb) — gain_control_mode (manual/fast_attack/slow_attack/hybrid) + hardwaregain. Controller FRxGainMode/ FRxGainDb, commands SetRxGainMode/SetRxGain/RxGainBy, rfRxGain event, snapshot, applied in StartRunning. Persisted per-device (rx_gain_mode/rx_gain_db). HPSDR unaffected (backend no-op). - UI: separate "RF AGC" panel below the (unchanged) WDSP AGC block, shown only for Pluto — FAST/SLOW/HYB/MAN mode buttons + manual GAIN slider. LayoutLeftPanel reflows lower panels via RelayoutBelowBands; no layout shift on HPSDR. - Cold-init fix: direct sampling_frequency write doesn't load the AD9361 FIR decimation filter, so a cold-booted Pluto showed a wide centre spike that didn't track tuning (worked only after SDR Console pre-initialised it). Add optional libad9361 binding (dynamic) and call ad9361_set_bb_rate() in ApplySampleRate, which configures BBPLL + loads the FIR; falls back to direct write if absent. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+107
@@ -259,6 +259,11 @@ type
|
||||
BtnAGCMode: array[0..4] of TFlatButton; // FAST MED SLOW LONG OFF
|
||||
LblAGCTop: TLabel; // показывает значение уровня
|
||||
TrkAGC: TFlatSlider;
|
||||
// RX hw-gain (Pluto) — ОТДЕЛЬНЫЙ блок под AGC (WDSP). Виден только для Pluto.
|
||||
PanelPlutoAGC: TPanel;
|
||||
BtnPlutoGain: array[0..3] of TFlatButton; // FAST/SLOW/HYB/MAN (Tag=режим)
|
||||
TrkRxGain: TFlatSlider; // manual gain 0..73 dB
|
||||
LblRxGain: TLabel; // значение усиления
|
||||
TrkVolume: TFlatSlider;
|
||||
BtnNR: TFlatButton;
|
||||
BtnNB: TFlatButton;
|
||||
@@ -328,6 +333,9 @@ type
|
||||
function ResolveDevice(const IP: string): THPSDRDevice;
|
||||
procedure RelabelBands; // подписи band-кнопок под план бэкенда
|
||||
procedure ApplyBackendCapsToUI; // sample-rate пресеты + гейтинг полей по Caps
|
||||
procedure UpdateRxGainUI; // рендер RX hw-gain (Pluto)
|
||||
procedure LayoutLeftPanel(Pluto: Boolean); // показать/скрыть Pluto-блок + reflow
|
||||
procedure BtnPlutoGainClick(Sender: TObject);
|
||||
procedure DoConnectDevice(const Dev: THPSDRDevice);
|
||||
// Старт с уже выбранным устройством (preload rate + WDSP open + connect).
|
||||
// Переиспользуется десктоп-диалогом и web-оверлеем — без модального диалога.
|
||||
@@ -487,6 +495,8 @@ type
|
||||
procedure OnTXSettingsChange(const T: TTXSettings);
|
||||
procedure BtnAGCModeClick(Sender: TObject);
|
||||
procedure TrkAGCChange(Sender: TObject);
|
||||
procedure TrkRxGainChange(Sender: TObject);
|
||||
// (BtnPlutoGainClick объявлен выше)
|
||||
procedure MeterTimerTick(Sender: TObject);
|
||||
procedure SpectrumTimerTick(Sender: TObject);
|
||||
procedure RightPanelResize(Sender: TObject);
|
||||
@@ -1225,6 +1235,8 @@ begin
|
||||
for i := 0 to 4 do StyleButton(BtnAGCMode[i], i = FController.FAGCMode);
|
||||
rfVolume:
|
||||
TrkVolume.Position := FController.FVolume;
|
||||
rfRxGain:
|
||||
UpdateRxGainUI;
|
||||
rfDrive:
|
||||
begin
|
||||
TrkDrive.Position := FController.FDrivePercent; // слайдер ← drive%
|
||||
@@ -1397,6 +1409,7 @@ const
|
||||
BTN_H = 26;
|
||||
BTN_SM = 24;
|
||||
LEFT_W = 232;
|
||||
PLUTO_AGC_H = 64; // высота отдельного Pluto RF-AGC блока (под AGC)
|
||||
TOP_VFO_W = 244;
|
||||
TOP_VFO_FREQ_H = 47;
|
||||
var
|
||||
@@ -1759,6 +1772,47 @@ begin
|
||||
|
||||
Inc(Y, 74);
|
||||
|
||||
// --- Pluto RF AGC/gain — отдельный блок ПОД блоком AGC (WDSP). Виден только
|
||||
// когда подключён Pluto-бэкенд; раскладку панелей ниже сдвигает LayoutLeftPanel.
|
||||
PanelPlutoAGC := TPanel.Create(Self);
|
||||
PanelPlutoAGC.Parent := PanelLeft;
|
||||
PanelPlutoAGC.SetBounds(0, Y, LEFT_W, PLUTO_AGC_H);
|
||||
PanelPlutoAGC.BevelOuter := bvNone;
|
||||
PanelPlutoAGC.Visible := False;
|
||||
MakeLbl(PanelPlutoAGC, 'RF AGC', 4, 2);
|
||||
// Режимы AD936x: FAST/SLOW/HYB/MAN. Tag = индекс режима (1/2/3/0).
|
||||
BtnPlutoGain[0] := MakeBtn(PanelPlutoAGC, 'FAST',
|
||||
LeftPanelButtonLeft(LEFT_W, 4, 0), 16, LeftPanelButtonWidth(LEFT_W, 4, 0),
|
||||
BTN_SM, BtnPlutoGainClick);
|
||||
BtnPlutoGain[0].Tag := 1;
|
||||
BtnPlutoGain[1] := MakeBtn(PanelPlutoAGC, 'SLOW',
|
||||
LeftPanelButtonLeft(LEFT_W, 4, 1), 16, LeftPanelButtonWidth(LEFT_W, 4, 1),
|
||||
BTN_SM, BtnPlutoGainClick);
|
||||
BtnPlutoGain[1].Tag := 2;
|
||||
BtnPlutoGain[2] := MakeBtn(PanelPlutoAGC, 'HYB',
|
||||
LeftPanelButtonLeft(LEFT_W, 4, 2), 16, LeftPanelButtonWidth(LEFT_W, 4, 2),
|
||||
BTN_SM, BtnPlutoGainClick);
|
||||
BtnPlutoGain[2].Tag := 3;
|
||||
BtnPlutoGain[3] := MakeBtn(PanelPlutoAGC, 'MAN',
|
||||
LeftPanelButtonLeft(LEFT_W, 4, 3), 16, LeftPanelButtonWidth(LEFT_W, 4, 3),
|
||||
BTN_SM, BtnPlutoGainClick);
|
||||
BtnPlutoGain[3].Tag := 0;
|
||||
// Manual gain slider.
|
||||
MakeLbl(PanelPlutoAGC, 'GAIN', 4, 44);
|
||||
TrkRxGain := TFlatSlider.Create(Self);
|
||||
TrkRxGain.Parent := PanelPlutoAGC; TrkRxGain.Left := 56; TrkRxGain.Top := 40;
|
||||
TrkRxGain.Width := LEFT_W - 96; TrkRxGain.Height := 16;
|
||||
TrkRxGain.Min := 0; TrkRxGain.Max := 73; // AD936x hardwaregain dB
|
||||
TrkRxGain.Position := FController.FRxGainDb;
|
||||
TrkRxGain.OnChange := TrkRxGainChange;
|
||||
LblRxGain := TLabel.Create(Self);
|
||||
LblRxGain.Parent := PanelPlutoAGC;
|
||||
LblRxGain.Left := LEFT_W - 38; LblRxGain.Top := 44;
|
||||
LblRxGain.Caption := Format('%ddB', [FController.FRxGainDb]);
|
||||
LblRxGain.Font.Color := CLR_TEXT; LblRxGain.Font.Name := 'Courier New';
|
||||
LblRxGain.Font.Size := 7;
|
||||
// НЕ Inc(Y): панель скрыта и наложена на позицию Bands; LayoutLeftPanel сдвинет.
|
||||
|
||||
// Band selector. Высота резервирует 2 дополнительных ряда под XVTR-кнопки
|
||||
// (создаются динамически в RebuildXvtrButtons). В каждом ряду до 6 кнопок,
|
||||
// итого до 12 XVTR-кнопок (наш CFG_XVTR_COUNT = 8 умещается с запасом).
|
||||
@@ -3540,6 +3594,10 @@ begin
|
||||
FSampleRateOverlay.SetRatePresetsDefault; // HPSDR 48k..1536k
|
||||
FSampleRateOverlay.SetCurrentRate(FController.FSampleRate);
|
||||
end;
|
||||
|
||||
// Отдельный Pluto RF-AGC блок под AGC: показываем и сдвигаем панели ниже.
|
||||
LayoutLeftPanel(Caps.HasHWGain);
|
||||
if Caps.HasHWGain then UpdateRxGainUI;
|
||||
end;
|
||||
|
||||
procedure TMainForm.DoConnectDevice(const Dev: THPSDRDevice);
|
||||
@@ -5252,6 +5310,55 @@ begin
|
||||
FController.SetAGCTop(TrkAGC.Position);
|
||||
end;
|
||||
|
||||
procedure TMainForm.TrkRxGainChange(Sender: TObject);
|
||||
begin
|
||||
if FSyncingFromController then Exit;
|
||||
FController.SetRxGain(TrkRxGain.Position); // переводит в manual
|
||||
end;
|
||||
|
||||
procedure TMainForm.BtnPlutoGainClick(Sender: TObject);
|
||||
begin
|
||||
if FSyncingFromController then Exit;
|
||||
FController.SetRxGainMode((Sender as TFlatButton).Tag); // Tag = индекс режима
|
||||
end;
|
||||
|
||||
procedure TMainForm.UpdateRxGainUI;
|
||||
// Рендер Pluto RF-AGC блока: подсветка режима + слайдер/значение manual gain.
|
||||
var i: Integer;
|
||||
begin
|
||||
if PanelPlutoAGC = nil then Exit;
|
||||
FSyncingFromController := True;
|
||||
try
|
||||
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])
|
||||
else
|
||||
LblRxGain.Caption := 'AGC';
|
||||
finally
|
||||
FSyncingFromController := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.LayoutLeftPanel(Pluto: Boolean);
|
||||
// Показывает/скрывает Pluto RF-AGC блок под AGC и сдвигает панели ниже
|
||||
// (Bands и далее через RelayoutBelowBands).
|
||||
var baseTop: Integer;
|
||||
begin
|
||||
if (PanelPlutoAGC = nil) or (PanelAGC = nil) or (PanelBands = nil) then Exit;
|
||||
baseTop := PanelAGC.Top + PanelAGC.Height + 4;
|
||||
PanelPlutoAGC.Top := baseTop;
|
||||
PanelPlutoAGC.Visible := Pluto;
|
||||
if Pluto then
|
||||
PanelBands.Top := baseTop + PanelPlutoAGC.Height + 2
|
||||
else
|
||||
PanelBands.Top := baseTop;
|
||||
RelayoutBelowBands;
|
||||
end;
|
||||
|
||||
// ===========================================================================
|
||||
// DSP/Audio callbacks — вызываются из рабочих потоков
|
||||
// ===========================================================================
|
||||
|
||||
Reference in New Issue
Block a user