fix: Pluto TX drive mapping — power-linear + full digital level

TUN produced no tone: TUNLevel default 10% mapped via the old dB-linear
attenuation curve (−89.75..ceiling) to −81.8 dB → effectively off. Now
power-linear: dB = ceiling + 20*log10(pct/100), so 10%→−30, 50%→−16,
100%→ceiling — usable across the whole slider.

Also keep WDSP digital level at full-scale for Pluto (ApplyWDSPDrive):
power is set once via hardware attenuation, not by scaling the WDSP path.
HPSDR unchanged (drive byte still drives the radio PA).

Note: at a given slider position Pluto TX is now much hotter than before
(50%: −49.9→−16 dB). Ceiling stays PlutoTxMaxAttDb (default −10 dB).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-19 21:20:57 +03:00
co-authored by Claude Opus 4.8
parent be684545c8
commit 09c9109491
+18 -7
View File
@@ -463,6 +463,7 @@ type
function PlutoTxAttForDrive: Double; // дБ<0 под текущий FDrivePercent
procedure ApplyPlutoTxAtten; // ставит att по FTransmitting/FTuning
procedure SetPlutoTxMaxAtt(Db: Double); // потолок на drive=100% (внешний усилитель)
procedure ApplyWDSPDrive(Pct: Integer); // цифровой drive WDSP: Pluto=1.0 (мощность — атт), HPSDR=Pct/100
// Диапазоны / трансвертеры / спан
procedure SetBand(Idx: Integer);
@@ -2104,7 +2105,7 @@ begin
if V < 0 then V := 0 else if V > 100 then V := 100;
FDrivePercent := V;
FDriveLevel := CalcDriveByte;
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetDriveLevel(FDrivePercent / 100.0);
ApplyWDSPDrive(FDrivePercent);
ApplyPlutoTxAtten; // Pluto: drive живьём меняет TX-аттенюацию во время передачи
PushNetworkState; // протолкнуть новый drive в радио (если подключено+Running)
Changed(rfDrive);
@@ -2122,8 +2123,10 @@ begin
// На тюне (TUN) уровень берём из TX-настроек (TUNLevel), иначе из drive%.
if FTuning then Pct := FTXSettings.TUNLevel else Pct := FDrivePercent;
if Pct < 0 then Pct := 0 else if Pct > 100 then Pct := 100;
// dB-линейно: 0% → TX_OFF, 100% → FPlutoTxMaxAttDb (потолок под внешний тракт).
Result := TX_OFF + (Pct / 100.0) * (FPlutoTxMaxAttDb - TX_OFF);
if Pct <= 0 then begin Result := TX_OFF; Exit; end; // 0% → TX практически выкл
// power-linear: мощность ∝ drive%. dB = потолок + 20·log10(pct/100); 100% → потолок,
// 50% → 6 дБ, 10% → −20 дБ. (Раньше dB-линейно от −89.75 — низкие % улетали в −80 дБ.)
Result := FPlutoTxMaxAttDb + 20.0 * Log10(Pct / 100.0);
if Result > FPlutoTxMaxAttDb then Result := FPlutoTxMaxAttDb;
if Result < TX_OFF then Result := TX_OFF;
end;
@@ -2146,6 +2149,16 @@ begin
SaveGlobalSettings; // персист потолка (per-device)
end;
procedure TRadioController.ApplyWDSPDrive(Pct: Integer);
// На Pluto мощность задаётся ОДИН раз — железной аттенюацией (PlutoTxAttForDrive),
// поэтому цифровой уровень WDSP держим на максимуме (1.0), а не режем по drive%.
// HPSDR — как раньше, Pct/100 (реальная мощность там — drive-байт в радио).
begin
if not (FWDSPReady and Assigned(FDSPEngine)) then Exit;
if IsPluto then FDSPEngine.SetDriveLevel(1.0)
else FDSPEngine.SetDriveLevel(EnsureRange(Pct, 0, 100) / 100.0);
end;
procedure TRadioController.SetAtten(Idx: Integer);
begin
if Idx < 0 then Idx := 0 else if Idx > 2 then Idx := 2;
@@ -2603,8 +2616,7 @@ begin
FDSPEngine.SetTXTone(True, FTXSettings.TUNFreq, 1.0);
FTuning := True;
FDriveLevel := CalcDriveByte; // CalcDriveByte увидит FTuning=True (TUN-уровень)
if FWDSPReady and Assigned(FDSPEngine) then
FDSPEngine.SetDriveLevel(FTXSettings.TUNLevel / 100.0);
ApplyWDSPDrive(FTXSettings.TUNLevel);
if not FTransmitting then SetMOX(True); // PTT + run TXA-канал
end
else
@@ -2614,8 +2626,7 @@ begin
FDSPEngine.SetTXTone(False, 0, 0);
FTuning := False;
FDriveLevel := CalcDriveByte; // вернуть обычный drive%
if FWDSPReady and Assigned(FDSPEngine) then
FDSPEngine.SetDriveLevel(FDrivePercent / 100.0);
ApplyWDSPDrive(FDrivePercent);
if Assigned(FNetwork) and FNetwork.Connected and FNetwork.Running then
begin
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslateTX(ActiveTXFreqHz),