Add flat FM RAW transmit path

This commit is contained in:
2026-07-16 20:33:39 +03:00
parent cd816c54d6
commit 6197ed0aee
3 changed files with 86 additions and 21 deletions
+50 -4
View File
@@ -447,6 +447,7 @@ type
FTXWfAvgTimeMS: Double;
FMode: Integer;
FTXMode: Integer; // may differ from RX when a slice is TX source
FRawFMDeviation: Double;
FSMeter: Double;
FFilterLow: Integer;
@@ -486,6 +487,9 @@ type
procedure ApplyRXDMRToChan(Chan: Integer);
procedure ApplyRXRawToChan(Chan: Integer);
procedure ApplyWFMSettings;
// Mode-dependent TX overlay. FM RAW uses the flat WFM modulator and
// bypasses every speech processor without overwriting the saved TX setup.
procedure ApplyTXModeSettings(Mode: Integer);
// --- Мультислайсы ---
function FindSliceIdx(Id: Integer): Integer; // -1 если нет
function SliceInRate(Idx: Integer): Integer; // входной rate слайса (его пан)
@@ -1006,8 +1010,10 @@ end;
function TWDSPEngine.ModeToWDSPTX(Mode: Integer): Integer;
// txaMode расходится с rxaMode после DRM — отдельный маппинг только для WFM.
begin
if Mode = MODE_WFM then Result := WDSP_TX_WFM
else if Mode in [MODE_DMR, MODE_FMRAW] then Result := WDSP_FM
// The narrow FM modulator has mandatory speech pre-emphasis. FM RAW uses
// wfmmod even at NFM deviation because that path has an explicit flat mode.
if Mode in [MODE_WFM, MODE_FMRAW] then Result := WDSP_TX_WFM
else if Mode = MODE_DMR then Result := WDSP_FM
else Result := ModeToWDSP(Mode);
end;
@@ -1148,6 +1154,36 @@ begin
SetTXAWFMPreEmphTau (TXA_CHAN, WFM_TAU_DE_US);
end;
procedure TWDSPEngine.ApplyTXModeSettings(Mode: Integer);
begin
if not FInitialized then Exit;
if Mode = MODE_FMRAW then
begin
// Decoder/modem-grade FM input. A full-scale PCM peak produces the
// selected peak deviation. Keep only a broad linear-phase AF bandpass;
// APRS and other external modems must not see voice EQ, dynamics or emphasis.
SetTXAWFMDeviation (TXA_CHAN, FRawFMDeviation);
SetTXAWFMAFFreqs (TXA_CHAN, 20.0, 7000.0);
SetTXAWFMPreEmphRun (TXA_CHAN, 0);
SetTXABandpassFreqs (TXA_CHAN, 20.0, 7000.0);
SetTXABandpassRun (TXA_CHAN, 1);
SetTXAPanelGain1 (TXA_CHAN, 1.0);
SetTXACompressorRun (TXA_CHAN, 0);
SetTXALevelerSt (TXA_CHAN, 0);
SetTXAALCSt (TXA_CHAN, 0);
SetTXAPHROTRun (TXA_CHAN, 0);
SetTXAEQRun (TXA_CHAN, 0);
SetTXACTCSSRun (TXA_CHAN, 0);
end
else
begin
// Restore the user's normal voice/data chain after leaving FM RAW.
SetTXABandpassRun(TXA_CHAN, 1);
ApplyTXChainSettings;
if Mode = MODE_WFM then ApplyWFMSettings;
end;
end;
function TWDSPEngine.ClampToNyquist(Hz, Rate: Integer): Integer;
var Limit: Integer;
begin
@@ -1196,6 +1232,7 @@ begin
FInitialized := False;
FAnalyzerOpen := False;
FMode := MODE_USB;
FTXMode := MODE_USB;
FFilterLow := 100;
FFilterHigh := 2400;
FAGCMode := agcMedium;
@@ -1688,7 +1725,8 @@ begin
// изредка фазовый разрыв PostGen-тона (всплеск на водопаде + щелчок).
);
SetTXAMode(TXA_CHAN, ModeToWDSPTX(FMode));
FTXMode := FMode;
SetTXAMode(TXA_CHAN, ModeToWDSPTX(FTXMode));
SetTXAPanelRun(TXA_CHAN, 1);
// PatchPanel: 1=Q, 2=I. Mic подаётся в I (FTXIn[i*2]), Q=0 — выбираем I.
SetTXAPanelSelect(TXA_CHAN, 2);
@@ -2819,6 +2857,7 @@ end;
procedure TWDSPEngine.SetMode(Mode: Integer);
begin
FMode := Mode;
FTXMode := Mode;
if not FInitialized then Exit;
// Rate — до режима: setDSPSamplerate_rxa перестраивает всю цепь (в т.ч. wfmd),
// а SetRXAMode затем пересчитает bpsnba под уже актуальный dsp_rate.
@@ -2833,6 +2872,7 @@ begin
SetRXAWFMDeemphRun (RXA_CHAN, 0);
end
else if Mode = MODE_FMRAW then ApplyRXRawToChan(RXA_CHAN);
ApplyTXModeSettings(FTXMode);
// НЕ вызываем ApplyDefaultFilter — фильтр устанавливается явно из UI
end;
@@ -3081,6 +3121,7 @@ begin
FRawFMDeviation := EnsureRange(Deviation, 500.0, 10000.0);
if not FInitialized then Exit;
if FMode = MODE_FMRAW then SetRXAWFMDeviation(RXA_CHAN, FRawFMDeviation);
if FTXMode = MODE_FMRAW then SetTXAWFMDeviation(TXA_CHAN, FRawFMDeviation);
// One calibration value applies to every active FM RAW decoder output.
FSliceLock.Enter;
try
@@ -3127,13 +3168,18 @@ end;
procedure TWDSPEngine.SetTXMode(Mode: Integer);
begin
FTXMode := Mode;
if not FInitialized then Exit;
SetTXAMode(TXA_CHAN, ModeToWDSPTX(Mode));
SetTXAMode(TXA_CHAN, ModeToWDSPTX(FTXMode));
ApplyTXModeSettings(FTXMode);
end;
procedure TWDSPEngine.SetTXFilter(Low, High: Integer);
begin
if not FInitialized then Exit;
// In FM RAW this is an RF-channel-width update mirrored from the RX UI,
// not an audio passband request. The flat modem AF passband is fixed above.
if FTXMode = MODE_FMRAW then Exit;
SetTXABandpassFreqs(TXA_CHAN, Low, High);
end;