mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +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:
@@ -84,6 +84,13 @@ var
|
||||
// ---- Утилиты ----
|
||||
iio_strerror: procedure(err: cint; dst: PAnsiChar; len: csize_t); cdecl;
|
||||
|
||||
// ---- libad9361 (опционально) ----
|
||||
// ad9361_set_bb_rate: настраивает BBPLL + ЗАГРУЖАЕТ FIR-таблицу под частоту.
|
||||
// Без него прямая запись sampling_frequency на холодную даёт мусор (битый FIR).
|
||||
// nil если libad9361 не загружена.
|
||||
ad9361_set_bb_rate: function(dev: Piio_device; rate: culong): cint; cdecl;
|
||||
ad9361_set_trx_fir_enable: function(dev: Piio_device; enable: cint): cint; cdecl;
|
||||
|
||||
// Загружает libiio (один раз). True — готово к использованию. Идемпотентно.
|
||||
function IIOLoad: Boolean;
|
||||
// True, если libiio загружена и символы разрешены.
|
||||
@@ -95,16 +102,20 @@ implementation
|
||||
|
||||
var
|
||||
GLib: TLibHandle = NilHandle;
|
||||
GLibAD: TLibHandle = NilHandle; // libad9361 (опционально)
|
||||
GLoaded: Boolean = False;
|
||||
|
||||
const
|
||||
{$IFDEF WINDOWS}
|
||||
IIO_LIBS: array[0..1] of string = ('libiio.dll', 'iio.dll');
|
||||
AD_LIBS: array[0..1] of string = ('libad9361.dll', 'ad9361.dll');
|
||||
{$ELSE}
|
||||
{$IFDEF DARWIN}
|
||||
IIO_LIBS: array[0..1] of string = ('libiio.dylib', 'libiio.1.dylib');
|
||||
AD_LIBS: array[0..1] of string = ('libad9361.dylib', 'libad9361.0.dylib');
|
||||
{$ELSE}
|
||||
IIO_LIBS: array[0..1] of string = ('libiio.so', 'libiio.so.0');
|
||||
AD_LIBS: array[0..1] of string = ('libad9361.so', 'libad9361.so.0');
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
|
||||
@@ -163,6 +174,21 @@ begin
|
||||
iio_buffer_step := Sym('iio_buffer_step');
|
||||
iio_buffer_end := Sym('iio_buffer_end');
|
||||
iio_strerror := Sym('iio_strerror');
|
||||
|
||||
// libad9361 — опционально (ad9361_set_bb_rate грузит FIR). Отсутствие не
|
||||
// фатально: ApplySampleRate откатится на прямую запись sampling_frequency.
|
||||
if GLibAD = NilHandle then
|
||||
for I := 0 to High(AD_LIBS) do
|
||||
begin
|
||||
GLibAD := LoadLibrary(AD_LIBS[I]);
|
||||
if GLibAD <> NilHandle then Break;
|
||||
end;
|
||||
if GLibAD <> NilHandle then
|
||||
begin
|
||||
ad9361_set_bb_rate := GetProcedureAddress(GLibAD, 'ad9361_set_bb_rate');
|
||||
ad9361_set_trx_fir_enable := GetProcedureAddress(GLibAD, 'ad9361_set_trx_fir_enable');
|
||||
end;
|
||||
|
||||
GLoaded := True;
|
||||
except
|
||||
on E: Exception do
|
||||
@@ -190,6 +216,11 @@ begin
|
||||
end;
|
||||
|
||||
finalization
|
||||
if GLibAD <> NilHandle then
|
||||
begin
|
||||
UnloadLibrary(GLibAD);
|
||||
GLibAD := NilHandle;
|
||||
end;
|
||||
if GLib <> NilHandle then
|
||||
begin
|
||||
UnloadLibrary(GLib);
|
||||
|
||||
+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 — вызываются из рабочих потоков
|
||||
// ===========================================================================
|
||||
|
||||
+28
-2
@@ -94,6 +94,7 @@ type
|
||||
Transmitting, PAEnabled, AlexEnabled: Boolean); override;
|
||||
procedure SendFullHP; override;
|
||||
procedure SendPTT(Active: Boolean); override;
|
||||
procedure SetRxGain(ModeIdx: Integer; GainDb: Integer); override;
|
||||
end;
|
||||
|
||||
// Стабильный 6-байтовый ключ (synthetic MAC) из serial/URI — для per-device
|
||||
@@ -446,12 +447,25 @@ begin
|
||||
if (FPhy = nil) or (Hz < PLUTO_MIN_SR) then Exit;
|
||||
WasStreaming := FStreaming;
|
||||
if WasStreaming then StopRX; // менять rate с открытым буфером нельзя
|
||||
|
||||
// Предпочтительно ad9361_set_bb_rate: настраивает BBPLL И загружает FIR-таблицу
|
||||
// децимации под частоту. Без этого на холодную (битый/дефолтный FIR) спектр —
|
||||
// широкая палка по центру, не реагирует на перестройку. Fallback — прямая
|
||||
// запись sampling_frequency (работает, если FIR уже корректен).
|
||||
if Assigned(ad9361_set_bb_rate) then
|
||||
ad9361_set_bb_rate(FPhy, culong(Hz))
|
||||
else
|
||||
begin
|
||||
Ch := iio_device_find_channel(FPhy, 'voltage0', 0);
|
||||
if Ch <> nil then
|
||||
begin
|
||||
iio_channel_attr_write_longlong(Ch, 'sampling_frequency', Hz);
|
||||
iio_channel_attr_write_longlong(Ch, 'rf_bandwidth', Hz);
|
||||
end;
|
||||
|
||||
// RF-полоса отдельно (set_bb_rate её не трогает).
|
||||
Ch := iio_device_find_channel(FPhy, 'voltage0', 0);
|
||||
if Ch <> nil then
|
||||
iio_channel_attr_write_longlong(Ch, 'rf_bandwidth', Hz);
|
||||
|
||||
if WasStreaming then StartRX;
|
||||
end;
|
||||
|
||||
@@ -552,4 +566,16 @@ begin
|
||||
// Реальный RX↔TX (вкл/выкл стримов) — фаза 4.
|
||||
end;
|
||||
|
||||
procedure TPlutoBackend.SetRxGain(ModeIdx: Integer; GainDb: Integer);
|
||||
begin
|
||||
case ModeIdx of
|
||||
1: FGainMode := 'fast_attack';
|
||||
2: FGainMode := 'slow_attack';
|
||||
3: FGainMode := 'hybrid';
|
||||
else FGainMode := 'manual';
|
||||
end;
|
||||
FGainDb := GainDb;
|
||||
if FConnected then ApplyGain;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
@@ -134,6 +134,9 @@ type
|
||||
procedure SendDUCSpecific(const Pkt: TDUCSpecificPacket); virtual;
|
||||
procedure SendHighPriority(const Pkt: THighPriorityPacket); virtual;
|
||||
procedure SetStepAtten(dB: Byte); virtual;
|
||||
// RX-усиление (Pluto/AD936x). ModeIdx: 0=manual, 1=fast_attack, 2=slow_attack,
|
||||
// 3=hybrid. GainDb применяется только в manual. HPSDR — no-op.
|
||||
procedure SetRxGain(ModeIdx: Integer; GainDb: Integer); virtual;
|
||||
procedure SetAlexConfig(const A: TAlexSettings); virtual;
|
||||
procedure SetXvtrMode(AEnable, ADisablePA: Boolean; ARxAnt: Byte); virtual;
|
||||
procedure SendDDCAudio(const LeftRight: array of SmallInt); virtual;
|
||||
@@ -204,6 +207,10 @@ procedure TRadioBackend.SetStepAtten(dB: Byte);
|
||||
begin
|
||||
end;
|
||||
|
||||
procedure TRadioBackend.SetRxGain(ModeIdx: Integer; GainDb: Integer);
|
||||
begin
|
||||
end;
|
||||
|
||||
procedure TRadioBackend.SetAlexConfig(const A: TAlexSettings);
|
||||
begin
|
||||
end;
|
||||
|
||||
@@ -58,6 +58,7 @@ type
|
||||
rfVfoA, rfVfoB, rfActiveVfo,
|
||||
rfMode, rfFilter, rfFilterBW,
|
||||
rfAGCMode, rfAGCTop,
|
||||
rfRxGain, // Pluto: hw-gain (auto/manual dB)
|
||||
rfVolume, rfMute, rfDrive, rfAtten,
|
||||
rfBand, rfXvtr, rfBandRestore, // rfBandRestore: явная смена диапазона (сброс Wf-avg в UI)
|
||||
rfCenterFreq, rfSpan, rfSampleRate,
|
||||
@@ -95,6 +96,8 @@ type
|
||||
ActiveVfo: Integer;
|
||||
Mode, Filter, FilterBW: Integer;
|
||||
AGCMode, AGCTop: Integer;
|
||||
RxGainMode: Integer;
|
||||
RxGainDb: Integer;
|
||||
Volume, Drive, Atten: Integer;
|
||||
Band, Xvtr: Integer;
|
||||
Muted, CTun, Duplex: Boolean;
|
||||
@@ -164,6 +167,8 @@ type
|
||||
FFilterBW: Integer;
|
||||
FAGCMode: Integer;
|
||||
FAGCTop: Integer;
|
||||
FRxGainMode: Integer; // Pluto hw-gain: 0=manual,1=fast,2=slow,3=hybrid
|
||||
FRxGainDb: Integer; // Pluto manual gain (дБ, 0..73)
|
||||
FCTun: Boolean;
|
||||
FCenterFreq: Double;
|
||||
FSpanHz: Double;
|
||||
@@ -395,6 +400,13 @@ type
|
||||
procedure SetAGCTop(DB: Integer);
|
||||
procedure AGCTopBy(Delta: Integer);
|
||||
|
||||
// RX hw-gain (Pluto): режим (0=manual,1=fast,2=slow,3=hybrid) / ручной дБ.
|
||||
// На HPSDR — no-op в бэкенде.
|
||||
procedure SetRxGainMode(M: Integer);
|
||||
procedure SetRxGain(Db: Integer);
|
||||
procedure RxGainBy(Delta: Integer);
|
||||
procedure ApplyRxGainToBackend; // FRxGain* → FNetwork.SetRxGain
|
||||
|
||||
// Громкость / mute / drive / аттенюатор
|
||||
procedure SetVolume(V: Integer);
|
||||
procedure VolumeBy(Delta: Integer);
|
||||
@@ -486,6 +498,7 @@ begin
|
||||
FVfoA := 14200000; FVfoB := 7100000; FActiveVfo := 0;
|
||||
FMode := 1; FFilter := 5; FFilterBW := 2700;
|
||||
FAGCMode := 1; FAGCTop := 90;
|
||||
FRxGainMode := 2; FRxGainDb := 40; // Pluto: slow_attack по умолчанию
|
||||
FVolume := 70; FDrivePercent := 50; FDriveLevel := 0; FAtten := 0;
|
||||
FCenterFreq := FVfoA; FSpanHz := 192000; FSampleRate := 192000;
|
||||
FCurrentBand := 5; FCurrentXvtr := -1;
|
||||
@@ -863,6 +876,7 @@ begin
|
||||
Result.SampleRate := FSampleRate; Result.ActiveVfo := FActiveVfo;
|
||||
Result.Mode := FMode; Result.Filter := FFilter; Result.FilterBW := FFilterBW;
|
||||
Result.AGCMode := FAGCMode; Result.AGCTop := FAGCTop;
|
||||
Result.RxGainMode := FRxGainMode; Result.RxGainDb := FRxGainDb;
|
||||
Result.Volume := FVolume; Result.Drive := FDrivePercent; Result.Atten := FAtten;
|
||||
Result.Band := FCurrentBand; Result.Xvtr := FCurrentXvtr;
|
||||
Result.Muted := FMuted; Result.CTun := FCTun; Result.Duplex := FDisplayDuplex;
|
||||
@@ -1121,6 +1135,8 @@ begin
|
||||
Result.LastBand := FCurrentBand;
|
||||
Result.LastXvtr := FCurrentXvtr;
|
||||
Result.SampleRate := FSampleRate;
|
||||
Result.RxGainMode := FRxGainMode;
|
||||
Result.RxGainDb := FRxGainDb;
|
||||
if FWDSPReady then
|
||||
begin
|
||||
Result.FFTSize := FDSPEngine.FFTSize;
|
||||
@@ -1633,6 +1649,33 @@ end;
|
||||
procedure TRadioController.AGCTopBy(Delta: Integer);
|
||||
begin SetAGCTop(FAGCTop + Delta); end;
|
||||
|
||||
procedure TRadioController.ApplyRxGainToBackend;
|
||||
begin
|
||||
if Assigned(FNetwork) and FNetwork.Connected then
|
||||
FNetwork.SetRxGain(FRxGainMode, FRxGainDb);
|
||||
end;
|
||||
|
||||
procedure TRadioController.SetRxGainMode(M: Integer);
|
||||
begin
|
||||
if M < 0 then M := 0 else if M > 3 then M := 3;
|
||||
FRxGainMode := M;
|
||||
ApplyRxGainToBackend;
|
||||
Changed(rfRxGain);
|
||||
end;
|
||||
|
||||
procedure TRadioController.SetRxGain(Db: Integer);
|
||||
begin
|
||||
if Db < 0 then Db := 0 else if Db > 73 then Db := 73;
|
||||
FRxGainDb := Db;
|
||||
// Ручная установка усиления подразумевает manual-режим (0).
|
||||
FRxGainMode := 0;
|
||||
ApplyRxGainToBackend;
|
||||
Changed(rfRxGain);
|
||||
end;
|
||||
|
||||
procedure TRadioController.RxGainBy(Delta: Integer);
|
||||
begin SetRxGain(FRxGainDb + Delta); end;
|
||||
|
||||
procedure TRadioController.SetVolume(V: Integer);
|
||||
begin
|
||||
if V < 0 then V := 0 else if V > 100 then V := 100;
|
||||
@@ -2284,6 +2327,8 @@ begin
|
||||
FNetwork.ConfigureDDCs(1, FSampleRate div 1000, 0, FDitherEnabled, FRandomEnabled);
|
||||
// Применяем сохранённое состояние динамика/отправки аудио (мьют byte 1400 bit1).
|
||||
FNetwork.SetSpeakerAudio(FSendAudioToRadio);
|
||||
// RX hw-gain в бэкенд (Pluto). HPSDR — no-op.
|
||||
ApplyRxGainToBackend;
|
||||
SendDUCSpecificFromSettings;
|
||||
// Применяем TX-цепь (фильтр, mic gain, EQ, leveler, ALC, comp, ...).
|
||||
ApplyTXSettingsToDSP;
|
||||
@@ -2374,6 +2419,8 @@ begin
|
||||
FSampleRate := 1536000;
|
||||
FSpanHz := FSampleRate;
|
||||
end;
|
||||
FRxGainMode := EnsureRange(FLoadedGlobal.RxGainMode, 0, 3);
|
||||
FRxGainDb := EnsureRange(FLoadedGlobal.RxGainDb, 0, 73);
|
||||
FNRMode := EnsureRange(FLoadedGlobal.NRMode, 0, 4);
|
||||
FNBMode := EnsureRange(FLoadedGlobal.NBMode, 0, 2);
|
||||
FSNB := FLoadedGlobal.SNBEnabled;
|
||||
|
||||
@@ -218,6 +218,8 @@ type
|
||||
LastBand: Integer;
|
||||
LastXvtr: Integer; // -1 = HF, 0..CFG_XVTR_COUNT-1 = активный трансвертер при выходе
|
||||
SampleRate: Integer; // глобальный — один для всех диапазонов
|
||||
RxGainMode: Integer; // Pluto: 0=manual,1=fast,2=slow,3=hybrid
|
||||
RxGainDb: Integer; // Pluto: manual gain дБ
|
||||
WindowLeft: Integer;
|
||||
WindowTop: Integer;
|
||||
WindowWidth: Integer;
|
||||
@@ -401,6 +403,7 @@ begin
|
||||
G.WfAGCEnabled := True;
|
||||
G.WfNFEnabled := False;
|
||||
G.SampleRate := 192000;
|
||||
G.RxGainMode := 2; G.RxGainDb := 40;
|
||||
G.PAMaxPower := 100.0;
|
||||
for i := 0 to CFG_BAND_COUNT-1 do G.PABandCal[i] := CFG_PA_BAND_CAL_DEFAULT[i];
|
||||
for i := 0 to CFG_XVTR_COUNT-1 do G.VHFBandCal[i] := CFG_VHF_CAL_DEFAULT;
|
||||
@@ -597,6 +600,8 @@ begin
|
||||
G.LastBand := JI(GObj,'last_band',5);
|
||||
G.LastXvtr := JI(GObj,'last_xvtr',-1);
|
||||
G.SampleRate := JI(GObj,'sample_rate',192000);
|
||||
G.RxGainMode := JI(GObj,'rx_gain_mode',2);
|
||||
G.RxGainDb := JI(GObj,'rx_gain_db',40);
|
||||
// Display settings
|
||||
G.FFTSize := JI(GObj,'fft_size',131072);
|
||||
G.WindowType := JI(GObj,'win_type',2);
|
||||
@@ -712,6 +717,8 @@ begin
|
||||
JW(O,'last_band',G.LastBand);
|
||||
JW(O,'last_xvtr',G.LastXvtr);
|
||||
JW(O,'sample_rate',G.SampleRate);
|
||||
JW(O,'rx_gain_mode',G.RxGainMode);
|
||||
JW(O,'rx_gain_db',G.RxGainDb);
|
||||
// Display settings
|
||||
JW(O,'fft_size',G.FFTSize);
|
||||
JW(O,'win_type',G.WindowType);
|
||||
|
||||
Reference in New Issue
Block a user