mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 19:45:09 +00:00
feat: Pluto TX path — attenuation-based power, full-duplex IQ stream
TX path for Pluto/AD936x (RX was already working): - PlutoBackend: continuous full-duplex TX stream (cf-ad9361-dds-core-lpc) with FIFO + push thread; SendDUCIQ upsamples WDSP 192k -> device rate (integer, linear interp), 24->16 bit, Q inverted; zeros on underrun. - Power via output attenuator (ADI-recommended): SetTxAtten writes hardwaregain on voltage0(out). Controller maps drive% -> dB (PlutoTxAttForDrive/ApplyPlutoTxAtten); -89.75 dB on RX (~off), ceiling PlutoTxMaxAttDb on 100% drive. - Configurable max-att (default -10 dB, ADI-linear) for external amp: persisted in global settings, UI spin on PA page, routed through controller SetPlutoTxMaxAtt (UI stays decoupled from logic). - RadioBackend: virtual SetTxAtten (no-op for HPSDR). - Update doc/PLUTO_INTEGRATION_PLAN.md: phases 3/4/5 + risks. Builds clean (headless + qt6 GUI). Not yet verified on hardware. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -35,6 +35,8 @@ type
|
||||
// PA: MaxPower в Вт, BandCal[0..10] — калибровка 38.8..100.0 на диапазон
|
||||
TOnPASettingsChange = procedure(MaxPower: Double;
|
||||
const BandCal: array of Double) of object;
|
||||
// Pluto TX: аттенюация выходного тракта на drive=100% (потолок), дБ<0
|
||||
TOnPlutoTxChange = procedure(MaxAttDb: Double) of object;
|
||||
// VHF (XVTR) PA calibration: 8 slots, 38.8..100.0
|
||||
TOnVHFCalChange = procedure(const VHFCal: array of Double) of object;
|
||||
// TX-настройки целиком (любая правка → один callback с актуальной структурой)
|
||||
@@ -132,6 +134,7 @@ type
|
||||
|
||||
// ---- PA Settings tab controls ----
|
||||
FEdMaxPower: TFlatSpinEdit;
|
||||
FEdPlutoTxMaxAtt: TFlatFloatSpinEdit; // Pluto TX att на drive=100%
|
||||
FEdBandCal: array[0..10] of TFlatFloatSpinEdit;
|
||||
FEdVHFCal: array[0..CFG_XVTR_COUNT-1] of TFlatFloatSpinEdit;
|
||||
FVHFCalLabels: array[0..CFG_XVTR_COUNT-1] of TLabel;
|
||||
@@ -265,6 +268,7 @@ type
|
||||
// ---- Callbacks ----
|
||||
FOnCATChange: TOnCATChange;
|
||||
FOnPAChange: TOnPASettingsChange;
|
||||
FOnPlutoTxChange: TOnPlutoTxChange;
|
||||
FOnVHFCalChange: TOnVHFCalChange;
|
||||
FOnADCChange: TOnADCChange;
|
||||
FOnWebSettingsChange: TOnWebSettingsChange;
|
||||
@@ -344,6 +348,7 @@ type
|
||||
procedure OnLightThemeChkChange(Sender: TObject);
|
||||
procedure OnFreqMhzDigitsCmbChange(Sender: TObject);
|
||||
procedure OnMaxPowerChange(Sender: TObject);
|
||||
procedure OnPlutoTxMaxAttChange(Sender: TObject);
|
||||
procedure OnBandCalChange(Sender: TObject);
|
||||
procedure OnVHFCalEdit(Sender: TObject);
|
||||
procedure OnCATSerialChange(Sender: TObject);
|
||||
@@ -386,6 +391,7 @@ type
|
||||
procedure LoadLightTheme(ALight: Boolean);
|
||||
procedure LoadFreqMhzDigits(Digits: Integer);
|
||||
procedure LoadPASettings(MaxPower: Double; const BandCal: array of Double);
|
||||
procedure LoadPlutoTxMaxAtt(MaxAttDb: Double);
|
||||
procedure LoadVHFCalSettings(const VHFCal: array of Double);
|
||||
procedure LoadCATSettings(
|
||||
const SerEnabled: array of Boolean;
|
||||
@@ -404,6 +410,7 @@ type
|
||||
property OnAlexChange: TOnAlexChange read FOnAlexChange write FOnAlexChange;
|
||||
property OnXvtrChange: TOnXvtrChange read FOnXvtrChange write FOnXvtrChange;
|
||||
property OnPAChange: TOnPASettingsChange read FOnPAChange write FOnPAChange;
|
||||
property OnPlutoTxChange: TOnPlutoTxChange read FOnPlutoTxChange write FOnPlutoTxChange;
|
||||
property OnVHFCalChange: TOnVHFCalChange read FOnVHFCalChange write FOnVHFCalChange;
|
||||
property OnDisplayChange: TOnDisplayParamChange read FOnDisplayChange write FOnDisplayChange;
|
||||
property OnWaterfallChange: TOnWaterfallParamChange read FOnWaterfallChange write FOnWaterfallChange;
|
||||
@@ -1662,6 +1669,29 @@ begin
|
||||
Spin.OnChange := OnMaxPowerChange;
|
||||
FEdMaxPower := Spin;
|
||||
|
||||
// Pluto TX max attenuation @ drive 100% (потолок под внешний усилитель), дБ<0
|
||||
Lbl := TLabel.Create(Self);
|
||||
Lbl.Parent := Grp;
|
||||
Lbl.Caption := 'Pluto TX att @100% (dB)';
|
||||
Lbl.SetBounds(GRP_PAD + 320, R1 + 6, 180, 18);
|
||||
Lbl.Font.Color := CLR_TEXTDIM;
|
||||
Lbl.Font.Name := UI_FONT;
|
||||
Lbl.Font.Size := 9;
|
||||
|
||||
FEdPlutoTxMaxAtt := TFlatFloatSpinEdit.Create(Self);
|
||||
FEdPlutoTxMaxAtt.Parent := Grp;
|
||||
FEdPlutoTxMaxAtt.SetBounds(GRP_PAD + 510, R1, ED_W, BTN_H + 2);
|
||||
FEdPlutoTxMaxAtt.Color := CLR_INPUT;
|
||||
FEdPlutoTxMaxAtt.Font.Color := CLR_INPUT_TEXT;
|
||||
FEdPlutoTxMaxAtt.Font.Name := UI_FONT;
|
||||
FEdPlutoTxMaxAtt.Font.Size := 9;
|
||||
FEdPlutoTxMaxAtt.DecimalPlaces := 2;
|
||||
FEdPlutoTxMaxAtt.MinValue := -50;
|
||||
FEdPlutoTxMaxAtt.MaxValue := 0;
|
||||
FEdPlutoTxMaxAtt.Increment := 0.25;
|
||||
FEdPlutoTxMaxAtt.Value := -10;
|
||||
FEdPlutoTxMaxAtt.OnChange := OnPlutoTxMaxAttChange;
|
||||
|
||||
// Calibration label
|
||||
Lbl := TLabel.Create(Self);
|
||||
Lbl.Parent := Grp;
|
||||
@@ -2486,6 +2516,16 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSettingsForm.LoadPlutoTxMaxAtt(MaxAttDb: Double);
|
||||
begin
|
||||
FLoading := True;
|
||||
try
|
||||
FEdPlutoTxMaxAtt.Value := EnsureRange(MaxAttDb, -50.0, 0.0);
|
||||
finally
|
||||
FLoading := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSettingsForm.OnMaxPowerChange(Sender: TObject);
|
||||
var
|
||||
BandCal: array[0..10] of Double;
|
||||
@@ -2498,6 +2538,12 @@ begin
|
||||
FOnPAChange(FEdMaxPower.Value, BandCal);
|
||||
end;
|
||||
|
||||
procedure TSettingsForm.OnPlutoTxMaxAttChange(Sender: TObject);
|
||||
begin
|
||||
if FLoading then Exit;
|
||||
if Assigned(FOnPlutoTxChange) then FOnPlutoTxChange(FEdPlutoTxMaxAtt.Value);
|
||||
end;
|
||||
|
||||
procedure TSettingsForm.OnBandCalChange(Sender: TObject);
|
||||
var
|
||||
BandCal: array[0..10] of Double;
|
||||
|
||||
Reference in New Issue
Block a user