rx2 support work

This commit is contained in:
2026-05-27 11:29:39 +03:00
parent 047c9b0997
commit c2ca52511c
4 changed files with 1290 additions and 258 deletions
+268 -230
View File
@@ -229,6 +229,11 @@ type
// не меняется.
FPostTXMuteUntil: QWord;
FActiveDisplayID: Integer; // RX_DISP_ID или TX_DISP_ID
FRXChan: Integer;
FTXChan: Integer;
FRXDispID: Integer;
FTXDispID: Integer;
FTXEnabled: Boolean;
FTXMicSource: TTXMicSource;
FOnPullMic: TPullMicSamplesFunc;
@@ -323,7 +328,12 @@ type
public
constructor Create(SampleRate: Integer = 192000;
AudioRate: Integer = 48000;
BufSize: Integer = DSP_BUFSIZE);
BufSize: Integer = DSP_BUFSIZE;
RXChan: Integer = RXA_CHAN;
TXChan: Integer = TXA_CHAN;
RXDispID: Integer = RX_DISP_ID;
TXDispID: Integer = TX_DISP_ID;
EnableTX: Boolean = True);
destructor Destroy; override;
// Открыть DSP каналы
@@ -479,7 +489,7 @@ type
implementation
// ===========================================================================
// TX DSP поток — читает mic ring buffer, вызывает fexchange0(TXA_CHAN),
// TX DSP поток — читает mic ring buffer, вызывает fexchange0(FTXChan),
// сигнализирует о готовых IQ данных через FOnTXIQ callback.
// Аналог tx_thread в piHPSDR/transmitter.c
// ===========================================================================
@@ -715,11 +725,17 @@ end;
// Constructor / Destructor
// ---------------------------------------------------------------------------
constructor TWDSPEngine.Create(SampleRate, AudioRate, BufSize: Integer);
constructor TWDSPEngine.Create(SampleRate, AudioRate, BufSize, RXChan, TXChan,
RXDispID, TXDispID: Integer; EnableTX: Boolean);
begin
inherited Create;
FSampleRate := SampleRate;
FAudioRate := AudioRate;
FRXChan := RXChan;
FTXChan := TXChan;
FRXDispID := RXDispID;
FTXDispID := TXDispID;
FTXEnabled := EnableTX;
// BufSize = dsp_size @ AudioRate (внутренний DSP буфер, piHPSDR buffer_size = 1024)
// FBufSize = in_size @ SampleRate = BufSize * (SampleRate/AudioRate)
// piHPSDR: in_size = buffer_size * sample_rate/48000 = 1024*4 = 4096 @ 192kHz
@@ -784,7 +800,7 @@ begin
FTXActive := False;
FKeepRXDuringTX := False;
FPostTXMuteUntil := 0;
FActiveDisplayID := RX_DISP_ID;
FActiveDisplayID := FRXDispID;
FTXMicSource := txmsRadio;
FOnPullMic := nil;
FTXThread := nil;
@@ -865,19 +881,22 @@ begin
if FAnalyzerOpen then Exit;
Success := -1;
XCreateAnalyzer(RX_DISP_ID, @Success, 262144, 1, 1, nil);
XCreateAnalyzer(FRXDispID, @Success, 262144, 1, 1, nil);
if Success <> 0 then
begin
FLastError := Format('XCreateAnalyzer(RX) failed: %d', [Success]);
Exit;
end;
// Отдельный analyzer для TX-спектра/водопада. Ошибку логируем в LastError,
// но не считаем фатальной — RX без TX-display продолжает работать.
Success := -1;
XCreateAnalyzer(TX_DISP_ID, @Success, 262144, 1, 1, nil);
if Success <> 0 then
FLastError := Format('XCreateAnalyzer(TX) failed: %d', [Success]);
if FTXEnabled then
begin
// Отдельный analyzer для TX-спектра/водопада. Ошибку логируем в LastError,
// но не считаем фатальной — RX без TX-display продолжает работать.
Success := -1;
XCreateAnalyzer(FTXDispID, @Success, 262144, 1, 1, nil);
if Success <> 0 then
FLastError := Format('XCreateAnalyzer(TX) failed: %d', [Success]);
end;
FFlp[0] := 0;
ApplyAnalyzerSettings;
@@ -888,7 +907,7 @@ begin
end;
procedure TWDSPEngine.ApplyRXAnalyzerSettings;
// Применяет FFFTSize / FWindowType / FSpec* / FWf* к RX_DISP_ID.
// Применяет FFFTSize / FWindowType / FSpec* / FWf* к FRXDispID.
var
AnalyzerFFT, AvgCount, WfAvgCount, MaxW, Overlap, DisplayPixels: Integer;
Backmult, WfBackmult: Double;
@@ -905,24 +924,24 @@ begin
AverageTimeToParams(FSpecAvgMode, FSpecAvgTimeMS, AvgCount, Backmult);
AverageTimeToParams(FWfAvgMode, FWfAvgTimeMS, WfAvgCount, WfBackmult);
SetAnalyzer(RX_DISP_ID, 2, 1, 1, @FFlp[0], AnalyzerFFT, DISPLAY_BLOCK_SIZE,
SetAnalyzer(FRXDispID, 2, 1, 1, @FFlp[0], AnalyzerFFT, DISPLAY_BLOCK_SIZE,
FWindowType, 14.0, Overlap, 0, 0.0, 0.0, DisplayPixels,
1, 0, 0.0, 0.0, MaxW);
SetDisplayDetectorMode(RX_DISP_ID, 0, FSpecDetector);
SetDisplayAverageMode (RX_DISP_ID, 0, FSpecAvgMode);
SetDisplayNumAverage (RX_DISP_ID, 0, AvgCount);
SetDisplayAvBackmult (RX_DISP_ID, 0, Backmult);
SetDisplayNormOneHz (RX_DISP_ID, 0, UsePanNormOneHz(FSpecDetector));
SetDisplayDetectorMode(RX_DISP_ID, 1, FWfDetector);
SetDisplayAverageMode (RX_DISP_ID, 1, FWfAvgMode);
SetDisplayNumAverage (RX_DISP_ID, 1, WfAvgCount);
SetDisplayAvBackmult (RX_DISP_ID, 1, WfBackmult);
SetDisplayNormOneHz (RX_DISP_ID, 1, 0);
SetDisplaySampleRate (RX_DISP_ID, FSampleRate);
SetDisplayDetectorMode(FRXDispID, 0, FSpecDetector);
SetDisplayAverageMode (FRXDispID, 0, FSpecAvgMode);
SetDisplayNumAverage (FRXDispID, 0, AvgCount);
SetDisplayAvBackmult (FRXDispID, 0, Backmult);
SetDisplayNormOneHz (FRXDispID, 0, UsePanNormOneHz(FSpecDetector));
SetDisplayDetectorMode(FRXDispID, 1, FWfDetector);
SetDisplayAverageMode (FRXDispID, 1, FWfAvgMode);
SetDisplayNumAverage (FRXDispID, 1, WfAvgCount);
SetDisplayAvBackmult (FRXDispID, 1, WfBackmult);
SetDisplayNormOneHz (FRXDispID, 1, 0);
SetDisplaySampleRate (FRXDispID, FSampleRate);
end;
procedure TWDSPEngine.ApplyTXAnalyzerSettings;
// Применяет FTXFFTSize / FTXWindowType / FTXSpec* / FTXWf* к TX_DISP_ID.
// Применяет FTXFFTSize / FTXWindowType / FTXSpec* / FTXWf* к FTXDispID.
// FFT/Window/Det/Avg отдельные от RX — TX-спектр обычно нужен мельче по FFT
// (TX-полоса узкая) и с другим усреднением (быстрее реагировать на голос).
var
@@ -931,6 +950,7 @@ var
EffectiveFPS: Double;
const KEEP_TIME_SEC = 0.10;
begin
if not FTXEnabled then Exit;
AnalyzerFFT := NormalizeFFTSize(FTXFFTSize);
FTXDispPos := 0;
MaxW := AnalyzerFFT + Round(Min(KEEP_TIME_SEC * FTXSampleRate,
@@ -941,27 +961,28 @@ begin
AverageTimeToParams(FTXSpecAvgMode, FTXSpecAvgTimeMS, AvgCount, Backmult);
AverageTimeToParams(FTXWfAvgMode, FTXWfAvgTimeMS, WfAvgCount, WfBackmult);
SetAnalyzer(TX_DISP_ID, 2, 1, 1, @FFlp[0], AnalyzerFFT, DISPLAY_BLOCK_SIZE,
SetAnalyzer(FTXDispID, 2, 1, 1, @FFlp[0], AnalyzerFFT, DISPLAY_BLOCK_SIZE,
FTXWindowType, 14.0, Overlap, 0, 0.0, 0.0, DisplayPixels,
1, 0, 0.0, 0.0, MaxW);
SetDisplayDetectorMode(TX_DISP_ID, 0, FTXSpecDetector);
SetDisplayAverageMode (TX_DISP_ID, 0, FTXSpecAvgMode);
SetDisplayNumAverage (TX_DISP_ID, 0, AvgCount);
SetDisplayAvBackmult (TX_DISP_ID, 0, Backmult);
SetDisplayNormOneHz (TX_DISP_ID, 0, UsePanNormOneHz(FTXSpecDetector));
SetDisplayDetectorMode(TX_DISP_ID, 1, FTXWfDetector);
SetDisplayAverageMode (TX_DISP_ID, 1, FTXWfAvgMode);
SetDisplayNumAverage (TX_DISP_ID, 1, WfAvgCount);
SetDisplayAvBackmult (TX_DISP_ID, 1, WfBackmult);
SetDisplayNormOneHz (TX_DISP_ID, 1, 0);
SetDisplaySampleRate (TX_DISP_ID, FTXSampleRate);
SetDisplayDetectorMode(FTXDispID, 0, FTXSpecDetector);
SetDisplayAverageMode (FTXDispID, 0, FTXSpecAvgMode);
SetDisplayNumAverage (FTXDispID, 0, AvgCount);
SetDisplayAvBackmult (FTXDispID, 0, Backmult);
SetDisplayNormOneHz (FTXDispID, 0, UsePanNormOneHz(FTXSpecDetector));
SetDisplayDetectorMode(FTXDispID, 1, FTXWfDetector);
SetDisplayAverageMode (FTXDispID, 1, FTXWfAvgMode);
SetDisplayNumAverage (FTXDispID, 1, WfAvgCount);
SetDisplayAvBackmult (FTXDispID, 1, WfBackmult);
SetDisplayNormOneHz (FTXDispID, 1, 0);
SetDisplaySampleRate (FTXDispID, FTXSampleRate);
end;
procedure TWDSPEngine.ApplyAnalyzerSettings;
// Совместимый вход: применяет настройки и к RX, и к TX analyzer'у.
begin
ApplyRXAnalyzerSettings;
ApplyTXAnalyzerSettings;
if FTXEnabled then
ApplyTXAnalyzerSettings;
end;
procedure TWDSPEngine.CloseAnalyzer;
@@ -973,8 +994,9 @@ begin
FDisplayThread.WaitFor;
FreeAndNil(FDisplayThread);
end;
DestroyAnalyzer(RX_DISP_ID);
DestroyAnalyzer(TX_DISP_ID);
DestroyAnalyzer(FRXDispID);
if FTXEnabled then
DestroyAnalyzer(FTXDispID);
FAnalyzerOpen := False;
end;
@@ -1011,7 +1033,7 @@ begin
end;
OpenChannel(
RXA_CHAN,
FRXChan,
FBufSize,
FAudioBufSize,
FSampleRate,
@@ -1023,45 +1045,49 @@ begin
0
);
create_anbEXT(RXA_CHAN, 1, FBufSize, FSampleRate, 0.0001, 0.0001, 0.0001, 0.05, 20);
create_nobEXT(RXA_CHAN, 1, 0, FBufSize, FSampleRate, 0.0001, 0.0001, 0.0001, 0.05, 20);
create_anbEXT(FRXChan, 1, FBufSize, FSampleRate, 0.0001, 0.0001, 0.0001, 0.05, 20);
create_nobEXT(FRXChan, 1, 0, FBufSize, FSampleRate, 0.0001, 0.0001, 0.0001, 0.05, 20);
SetRXABandpassWindow(RXA_CHAN, 1);
SetRXAMode(RXA_CHAN, ModeToWDSP(FMode));
SetRXAShiftRun(RXA_CHAN, 1);
SetRXAShiftFreq(RXA_CHAN, 0.0);
RXASetPassband(RXA_CHAN, FFilterLow, FFilterHigh);
SetRXABandpassWindow(FRXChan, 1);
SetRXAMode(FRXChan, ModeToWDSP(FMode));
SetRXAShiftRun(FRXChan, 1);
SetRXAShiftFreq(FRXChan, 0.0);
RXASetPassband(FRXChan, FFilterLow, FFilterHigh);
SetAGC(FAGCMode, 50.0);
SetRXAPanelGain1(RXA_CHAN, FVolume);
SetRXAPanelSelect(RXA_CHAN, 3);
SetRXAPanelRun(RXA_CHAN, 1);
SetChannelState(RXA_CHAN, 1, 0);
SetRXAPanelGain1(FRXChan, FVolume);
SetRXAPanelSelect(FRXChan, 3);
SetRXAPanelRun(FRXChan, 1);
SetChannelState(FRXChan, 1, 0);
// TXA: mic @ FAudioRate → IQ @ FTXSampleRate (фиксированный DUC rate, не зависит от RX).
// out_size = FAudioBufSize * FTXSampleRate/FAudioRate = FTXOutBufSize (4096 @ 192k tx).
// FTXOut уже имеет размер FTXOutBufSize*2.
OpenChannel(
TXA_CHAN,
FAudioBufSize,
FAudioBufSize,
FAudioRate,
FAudioRate,
FTXSampleRate,
1,
0,
0.010, 0.010, 0.010, 0.010,
0
);
if FTXEnabled then
begin
// TXA: mic @ FAudioRate → IQ @ FTXSampleRate (фиксированный DUC rate, не зависит от RX).
// out_size = FAudioBufSize * FTXSampleRate/FAudioRate = FTXOutBufSize (4096 @ 192k tx).
// FTXOut уже имеет размер FTXOutBufSize*2.
OpenChannel(
FTXChan,
FAudioBufSize,
FAudioBufSize,
FAudioRate,
FAudioRate,
FTXSampleRate,
1,
0,
0.010, 0.010, 0.010, 0.010,
0
);
SetTXAMode(TXA_CHAN, ModeToWDSP(FMode));
SetTXAPanelRun(TXA_CHAN, 1);
// PatchPanel: 1=Q, 2=I. Mic подаётся в I (FTXIn[i*2]), Q=0 — выбираем I.
SetTXAPanelSelect(TXA_CHAN, 2);
SetTXAMode(FTXChan, ModeToWDSP(FMode));
SetTXAPanelRun(FTXChan, 1);
// PatchPanel: 1=Q, 2=I. Mic подаётся в I (FTXIn[i*2]), Q=0 — выбираем I.
SetTXAPanelSelect(FTXChan, 2);
end;
FInitialized := True;
// Прокидываем все TX-параметры из FTX*-полей: фильтр, mic gain, EQ,
// Leveler, ALC, Compressor, Phase Rotator, AM Carrier, FM, CTCSS.
ApplyTXChainSettings;
if FTXEnabled then
ApplyTXChainSettings;
ApplyNoiseFilterState;
Result := True;
@@ -1094,10 +1120,11 @@ begin
end;
CloseAnalyzer;
destroy_anbEXT(RXA_CHAN);
destroy_nobEXT(RXA_CHAN);
CloseChannel(RXA_CHAN);
CloseChannel(TXA_CHAN);
destroy_anbEXT(FRXChan);
destroy_nobEXT(FRXChan);
CloseChannel(FRXChan);
if FTXEnabled then
CloseChannel(FTXChan);
FInitialized := False;
end;
@@ -1179,7 +1206,7 @@ procedure TWDSPEngine.PushIQItemToDSP(const Item: TIQQueueItem);
// Вызывается из DSP потока — декодирует IQ и накапливает до FBufSize.
// В non-DUP TX (FTXActive and not FKeepRXDuringTX) полностью пропускаем
// IQ-пакет: не кормим RX-анализатор и не накапливаем для fexchange0.
// Иначе TX leakage из DDC оседает в RXA pipeline / RX_DISP_ID FFT-истории
// Иначе TX leakage из DDC оседает в RXA pipeline / FRXDispID FFT-истории
// и звучит/виден на водопаде первые секунды после возврата на RX.
var
i, Pos: Integer;
@@ -1231,7 +1258,7 @@ begin
if FDispPos >= DISPLAY_BLOCK_SIZE then
begin
Spectrum0(1, RX_DISP_ID, 0, 0, @FDispBuf[0]);
Spectrum0(1, FRXDispID, 0, 0, @FDispBuf[0]);
FDispPos := 0;
end;
end;
@@ -1246,7 +1273,7 @@ begin
if FTXDispPos >= DISPLAY_BLOCK_SIZE then
begin
Spectrum0(1, TX_DISP_ID, 0, 0, @FTXDispBuf[0]);
Spectrum0(1, FTXDispID, 0, 0, @FTXDispBuf[0]);
FTXDispPos := 0;
end;
end;
@@ -1270,12 +1297,12 @@ begin
// DSP обработка
Err := 0;
fexchange0(RXA_CHAN, @FRXIn[0], @FRXOut[0], @Err);
fexchange0(FRXChan, @FRXIn[0], @FRXOut[0], @Err);
// S-meter: читаем ОДИН раз в DSP-колбэке и кешируем в FSMeter.
// GetRXAMeter сбрасывает аккумулятор после вызова, поэтому второй
// вызов вернёт 0/-∞ — отсюда "падение до нуля". Только здесь!
FSMeter := GetRXAMeter(RXA_CHAN, RXA_S_AV);
FSMeter := GetRXAMeter(FRXChan, RXA_S_AV);
// Аудио колбэк — FAudioBufSize сэмплов @ FAudioRate (после децимации 4:1).
// При TX RX-аудио глушим (как в Thetis/piHPSDR при не-duplex MOX),
@@ -1309,8 +1336,9 @@ procedure TWDSPEngine.SetMode(Mode: Integer);
begin
FMode := Mode;
if not FInitialized then Exit;
SetRXAMode(RXA_CHAN, ModeToWDSP(Mode));
SetTXAMode(TXA_CHAN, ModeToWDSP(Mode));
SetRXAMode(FRXChan, ModeToWDSP(Mode));
if FTXEnabled then
SetTXAMode(FTXChan, ModeToWDSP(Mode));
// НЕ вызываем ApplyDefaultFilter — фильтр устанавливается явно из UI
end;
@@ -1320,7 +1348,7 @@ begin
FFilterHigh := High;
if not FInitialized then Exit;
// RXASetPassband — правильный unified API, пересчитывает фильтр целиком
RXASetPassband(RXA_CHAN, Low, High);
RXASetPassband(FRXChan, Low, High);
end;
procedure TWDSPEngine.SetAGC(Mode: TWDSPAGCMode; FixedGain: Double);
@@ -1329,40 +1357,40 @@ begin
if not FInitialized then Exit;
// Точно по piHPSDR receiver.c: set_agc()
SetRXAAGCMode(RXA_CHAN, Ord(Mode));
SetRXAAGCSlope(RXA_CHAN, FAGCSlope);
SetRXAAGCTop(RXA_CHAN, FAGCTop);
SetRXAAGCMode(FRXChan, Ord(Mode));
SetRXAAGCSlope(FRXChan, FAGCSlope);
SetRXAAGCTop(FRXChan, FAGCTop);
case Mode of
agcOff:
SetRXAAGCFixed(RXA_CHAN, FixedGain);
SetRXAAGCFixed(FRXChan, FixedGain);
agcLong: begin
SetRXAAGCAttack(RXA_CHAN, 2);
SetRXAAGCHang(RXA_CHAN, 2000);
SetRXAAGCDecay(RXA_CHAN, 2000);
SetRXAAGCHangThreshold(RXA_CHAN, FAGCHangThreshold);
SetRXAAGCAttack(FRXChan, 2);
SetRXAAGCHang(FRXChan, 2000);
SetRXAAGCDecay(FRXChan, 2000);
SetRXAAGCHangThreshold(FRXChan, FAGCHangThreshold);
end;
agcSlow: begin
SetRXAAGCAttack(RXA_CHAN, 2);
SetRXAAGCHang(RXA_CHAN, 1000);
SetRXAAGCDecay(RXA_CHAN, 500);
SetRXAAGCHangThreshold(RXA_CHAN, FAGCHangThreshold);
SetRXAAGCAttack(FRXChan, 2);
SetRXAAGCHang(FRXChan, 1000);
SetRXAAGCDecay(FRXChan, 500);
SetRXAAGCHangThreshold(FRXChan, FAGCHangThreshold);
end;
agcMedium: begin
SetRXAAGCAttack(RXA_CHAN, 2);
SetRXAAGCHang(RXA_CHAN, 0);
SetRXAAGCDecay(RXA_CHAN, 250);
SetRXAAGCHangThreshold(RXA_CHAN, 100);
SetRXAAGCAttack(FRXChan, 2);
SetRXAAGCHang(FRXChan, 0);
SetRXAAGCDecay(FRXChan, 250);
SetRXAAGCHangThreshold(FRXChan, 100);
end;
agcFast: begin
SetRXAAGCAttack(RXA_CHAN, 2);
SetRXAAGCHang(RXA_CHAN, 0);
SetRXAAGCDecay(RXA_CHAN, 50);
SetRXAAGCHangThreshold(RXA_CHAN, 100);
SetRXAAGCAttack(FRXChan, 2);
SetRXAAGCHang(FRXChan, 0);
SetRXAAGCDecay(FRXChan, 50);
SetRXAAGCHangThreshold(FRXChan, 100);
end;
end;
@@ -1374,14 +1402,14 @@ procedure TWDSPEngine.SetShift(ShiftHz: Double);
begin
FShiftHz := ShiftHz;
if not FInitialized then Exit;
SetRXAShiftFreq(RXA_CHAN, ShiftHz);
SetRXAShiftFreq(FRXChan, ShiftHz);
end;
procedure TWDSPEngine.SetAGCTop(TopDBm: Double);
begin
FAGCTop := TopDBm;
if not FInitialized then Exit;
SetRXAAGCTop(RXA_CHAN, TopDBm);
SetRXAAGCTop(FRXChan, TopDBm);
UpdateAGCLines(FLastSpectrumW);
end;
@@ -1389,14 +1417,14 @@ procedure TWDSPEngine.SetAGCSlope(Slope: Integer);
begin
FAGCSlope := Slope;
if not FInitialized then Exit;
SetRXAAGCSlope(RXA_CHAN, Slope);
SetRXAAGCSlope(FRXChan, Slope);
end;
procedure TWDSPEngine.SetAGCHangThreshold(Threshold: Integer);
begin
FAGCHangThreshold := Threshold;
if not FInitialized then Exit;
SetRXAAGCHangThreshold(RXA_CHAN, Threshold);
SetRXAAGCHangThreshold(FRXChan, Threshold);
UpdateAGCLines(FLastSpectrumW);
end;
@@ -1413,8 +1441,8 @@ procedure TWDSPEngine.UpdateAGCLines(SpectrumW: Integer);
begin
if not FInitialized then Exit;
if SpectrumW <= 0 then Exit; // окно ещё не показано — не читаем
GetRXAAGCHangLevel(RXA_CHAN, @FAGCHangLevel);
GetRXAAGCThresh(RXA_CHAN, @FAGCThresh,
GetRXAAGCHangLevel(FRXChan, @FAGCHangLevel);
GetRXAAGCThresh(FRXChan, @FAGCThresh,
SpectrumW, // реальная ширина дисплея в пикселях
FSampleRate);
end;
@@ -1423,65 +1451,65 @@ procedure TWDSPEngine.ApplyNRState;
begin
if not FInitialized then Exit;
SetRXAANRVals(RXA_CHAN, 64, 16, 16e-4, 10e-7);
SetRXAANRPosition(RXA_CHAN, FILTER_NR_AGC_POSITION);
SetRXAANRRun(RXA_CHAN, Ord(FNRMode = NR_MODE_1));
SetRXAANRVals(FRXChan, 64, 16, 16e-4, 10e-7);
SetRXAANRPosition(FRXChan, FILTER_NR_AGC_POSITION);
SetRXAANRRun(FRXChan, Ord(FNRMode = NR_MODE_1));
SetRXAEMNRPosition(RXA_CHAN, FILTER_NR_AGC_POSITION);
SetRXAEMNRgainMethod(RXA_CHAN, FILTER_NR2_GAIN_METHOD);
SetRXAEMNRnpeMethod(RXA_CHAN, FILTER_NR2_NPE_METHOD);
SetRXAEMNRtrainZetaThresh(RXA_CHAN, FILTER_NR2_TRAINED_THRESHOLD);
SetRXAEMNRtrainT2(RXA_CHAN, FILTER_NR2_TRAINED_T2);
SetRXAEMNRpost2Taper(RXA_CHAN, FILTER_NR2_POST_TAPER);
SetRXAEMNRpost2Nlevel(RXA_CHAN, FILTER_NR2_POST_NLEVEL);
SetRXAEMNRpost2Factor(RXA_CHAN, FILTER_NR2_POST_FACTOR);
SetRXAEMNRpost2Rate(RXA_CHAN, FILTER_NR2_POST_RATE);
SetRXAEMNRaeRun(RXA_CHAN, 1);
SetRXAEMNRpost2Run(RXA_CHAN, FILTER_NR2_POST_RUN);
SetRXAEMNRRun(RXA_CHAN, Ord(FNRMode = NR_MODE_2));
SetRXAEMNRPosition(FRXChan, FILTER_NR_AGC_POSITION);
SetRXAEMNRgainMethod(FRXChan, FILTER_NR2_GAIN_METHOD);
SetRXAEMNRnpeMethod(FRXChan, FILTER_NR2_NPE_METHOD);
SetRXAEMNRtrainZetaThresh(FRXChan, FILTER_NR2_TRAINED_THRESHOLD);
SetRXAEMNRtrainT2(FRXChan, FILTER_NR2_TRAINED_T2);
SetRXAEMNRpost2Taper(FRXChan, FILTER_NR2_POST_TAPER);
SetRXAEMNRpost2Nlevel(FRXChan, FILTER_NR2_POST_NLEVEL);
SetRXAEMNRpost2Factor(FRXChan, FILTER_NR2_POST_FACTOR);
SetRXAEMNRpost2Rate(FRXChan, FILTER_NR2_POST_RATE);
SetRXAEMNRaeRun(FRXChan, 1);
SetRXAEMNRpost2Run(FRXChan, FILTER_NR2_POST_RUN);
SetRXAEMNRRun(FRXChan, Ord(FNRMode = NR_MODE_2));
SetRXARNNRPosition(RXA_CHAN, FILTER_NR_AGC_POSITION);
SetRXARNNRRun(RXA_CHAN, Ord(FNRMode = NR_MODE_3));
SetRXARNNRPosition(FRXChan, FILTER_NR_AGC_POSITION);
SetRXARNNRRun(FRXChan, Ord(FNRMode = NR_MODE_3));
SetRXASBNRreductionAmount(RXA_CHAN, FILTER_NR4_REDUCTION_AMOUNT);
SetRXASBNRsmoothingFactor(RXA_CHAN, FILTER_NR4_SMOOTHING_FACTOR);
SetRXASBNRwhiteningFactor(RXA_CHAN, FILTER_NR4_WHITENING_FACTOR);
SetRXASBNRnoiseRescale(RXA_CHAN, FILTER_NR4_NOISE_RESCALE);
SetRXASBNRpostFilterThreshold(RXA_CHAN, FILTER_NR4_POST_THRESHOLD);
SetRXASBNRnoiseScalingType(RXA_CHAN, FILTER_NR4_NOISE_SCALING_TYPE);
SetRXASBNRPosition(RXA_CHAN, FILTER_NR_AGC_POSITION);
SetRXASBNRRun(RXA_CHAN, Ord(FNRMode = NR_MODE_4));
SetRXASBNRreductionAmount(FRXChan, FILTER_NR4_REDUCTION_AMOUNT);
SetRXASBNRsmoothingFactor(FRXChan, FILTER_NR4_SMOOTHING_FACTOR);
SetRXASBNRwhiteningFactor(FRXChan, FILTER_NR4_WHITENING_FACTOR);
SetRXASBNRnoiseRescale(FRXChan, FILTER_NR4_NOISE_RESCALE);
SetRXASBNRpostFilterThreshold(FRXChan, FILTER_NR4_POST_THRESHOLD);
SetRXASBNRnoiseScalingType(FRXChan, FILTER_NR4_NOISE_SCALING_TYPE);
SetRXASBNRPosition(FRXChan, FILTER_NR_AGC_POSITION);
SetRXASBNRRun(FRXChan, Ord(FNRMode = NR_MODE_4));
end;
procedure TWDSPEngine.ApplyNBState;
begin
if not FInitialized then Exit;
SetEXTANBTau(RXA_CHAN, FILTER_NB_TAU);
SetEXTANBHangtime(RXA_CHAN, FILTER_NB_HANGTIME);
SetEXTANBAdvtime(RXA_CHAN, FILTER_NB_ADVTIME);
SetEXTANBThreshold(RXA_CHAN, FILTER_NB_THRESHOLD);
SetEXTANBRun(RXA_CHAN, Ord(FNBMode = NB_MODE_1));
SetEXTANBTau(FRXChan, FILTER_NB_TAU);
SetEXTANBHangtime(FRXChan, FILTER_NB_HANGTIME);
SetEXTANBAdvtime(FRXChan, FILTER_NB_ADVTIME);
SetEXTANBThreshold(FRXChan, FILTER_NB_THRESHOLD);
SetEXTANBRun(FRXChan, Ord(FNBMode = NB_MODE_1));
SetEXTNOBMode(RXA_CHAN, FILTER_NB2_MODE);
SetEXTNOBTau(RXA_CHAN, FILTER_NB_TAU);
SetEXTNOBHangtime(RXA_CHAN, FILTER_NB_HANGTIME);
SetEXTNOBAdvtime(RXA_CHAN, FILTER_NB_ADVTIME);
SetEXTNOBThreshold(RXA_CHAN, FILTER_NB_THRESHOLD);
SetEXTNOBRun(RXA_CHAN, Ord(FNBMode = NB_MODE_2));
SetEXTNOBMode(FRXChan, FILTER_NB2_MODE);
SetEXTNOBTau(FRXChan, FILTER_NB_TAU);
SetEXTNOBHangtime(FRXChan, FILTER_NB_HANGTIME);
SetEXTNOBAdvtime(FRXChan, FILTER_NB_ADVTIME);
SetEXTNOBThreshold(FRXChan, FILTER_NB_THRESHOLD);
SetEXTNOBRun(FRXChan, Ord(FNBMode = NB_MODE_2));
end;
procedure TWDSPEngine.ApplySNBState;
begin
if not FInitialized then Exit;
SetRXASNBARun(RXA_CHAN, Ord(FSNBEnabled));
SetRXASNBARun(FRXChan, Ord(FSNBEnabled));
end;
procedure TWDSPEngine.ApplyANFState;
begin
if not FInitialized then Exit;
SetRXAANFPosition(RXA_CHAN, FILTER_NR_AGC_POSITION);
SetRXAANFRun(RXA_CHAN, Ord(FANFEnabled));
SetRXAANFPosition(FRXChan, FILTER_NR_AGC_POSITION);
SetRXAANFRun(FRXChan, Ord(FANFEnabled));
end;
procedure TWDSPEngine.ApplyNoiseFilterState;
@@ -1535,7 +1563,7 @@ end;
procedure TWDSPEngine.SetRXFMDeviation(Deviation: Double);
begin
if not FInitialized then Exit;
SetRXAFMDeviation(RXA_CHAN, Deviation);
SetRXAFMDeviation(FRXChan, Deviation);
end;
procedure TWDSPEngine.SetFMSquelch(Enable: Boolean; Level: Integer);
@@ -1545,25 +1573,25 @@ begin
if Enable then
begin
Threshold := Level / 200.0; // 0..100 → 0.0..0.5
SetRXAFMSQThreshold(RXA_CHAN, Threshold);
SetRXAFMSQRun(RXA_CHAN, 1);
SetRXAFMSQThreshold(FRXChan, Threshold);
SetRXAFMSQRun(FRXChan, 1);
end
else
SetRXAFMSQRun(RXA_CHAN, 0);
SetRXAFMSQRun(FRXChan, 0);
end;
procedure TWDSPEngine.SetVolume(Vol: Double);
begin
FVolume := Max(0.0, Min(1.0, Vol));
if not FInitialized then Exit;
SetRXAPanelGain1(RXA_CHAN, FVolume);
SetRXAPanelGain1(FRXChan, FVolume);
end;
procedure TWDSPEngine.SetMute(Mute: Boolean);
begin
FMuted := Mute;
if not FInitialized then Exit;
SetRXAPanelRun(RXA_CHAN, Ord(not Mute));
SetRXAPanelRun(FRXChan, Ord(not Mute));
end;
// ---------------------------------------------------------------------------
@@ -1572,43 +1600,53 @@ end;
procedure TWDSPEngine.SetTXMode(Mode: Integer);
begin
if not FTXEnabled then Exit;
if not FInitialized then Exit;
SetTXAMode(TXA_CHAN, ModeToWDSP(Mode));
SetTXAMode(FTXChan, ModeToWDSP(Mode));
end;
procedure TWDSPEngine.SetTXFilter(Low, High: Integer);
begin
if not FTXEnabled then Exit;
if not FInitialized then Exit;
SetTXABandpassFreqs(TXA_CHAN, Low, High);
SetTXABandpassFreqs(FTXChan, Low, High);
end;
procedure TWDSPEngine.SetDriveLevel(Level: Double);
begin
if not FTXEnabled then Exit;
if not FInitialized then Exit;
SetTXAALCMaxGain(TXA_CHAN, Max(0.0, Min(1.0, Level)));
SetTXAALCMaxGain(FTXChan, Max(0.0, Min(1.0, Level)));
end;
procedure TWDSPEngine.SetMicGain(GainDB: Double);
begin
FTXMicGainDB := GainDB;
if not FTXEnabled then Exit;
if not FInitialized then Exit;
SetTXAPanelGain1(TXA_CHAN, Power(10.0, GainDB / 20.0));
SetTXAPanelGain1(FTXChan, Power(10.0, GainDB / 20.0));
end;
procedure TWDSPEngine.SetTXRun(Run: Boolean);
begin
if not FTXEnabled then
begin
FTXActive := False;
FActiveDisplayID := FRXDispID;
Exit;
end;
FTXActive := Run;
FDispPos := 0;
FTXDispPos := 0;
if Run then
FActiveDisplayID := TX_DISP_ID
FActiveDisplayID := FTXDispID
else
FActiveDisplayID := RX_DISP_ID;
FActiveDisplayID := FRXDispID;
if Run then
begin
if FInitialized then
SetChannelState(TXA_CHAN, 1, 0); // run, no delay
SetChannelState(FTXChan, 1, 0); // run, no delay
// Сброс mic ring buffer и запуск TX потока
FTXMicHead := 0;
FTXMicTail := 0;
@@ -1619,7 +1657,7 @@ begin
end;
end else begin
if FInitialized then
SetChannelState(TXA_CHAN, 0, 1); // stop, with slew
SetChannelState(FTXChan, 0, 1); // stop, with slew
// Останавливаем TX поток
if Assigned(FTXThread) then
begin
@@ -1647,12 +1685,12 @@ begin
SignedFreq := -Abs(FreqHz)
else
SignedFreq := Abs(FreqHz);
SetTXAPostGenMode(TXA_CHAN, 0); // 0 = tone
SetTXAPostGenToneFreq(TXA_CHAN, SignedFreq);
SetTXAPostGenToneMag(TXA_CHAN, Max(0.0, Min(1.0, Mag)));
SetTXAPostGenRun(TXA_CHAN, 1);
SetTXAPostGenMode(FTXChan, 0); // 0 = tone
SetTXAPostGenToneFreq(FTXChan, SignedFreq);
SetTXAPostGenToneMag(FTXChan, Max(0.0, Min(1.0, Mag)));
SetTXAPostGenRun(FTXChan, 1);
end else
SetTXAPostGenRun(TXA_CHAN, 0);
SetTXAPostGenRun(FTXChan, 0);
end;
procedure TWDSPEngine.SetDisplaySourceTX(UseTX: Boolean);
@@ -1664,9 +1702,9 @@ begin
FDispPos := 0;
FTXDispPos := 0;
if UseTX then
FActiveDisplayID := TX_DISP_ID
FActiveDisplayID := FTXDispID
else
FActiveDisplayID := RX_DISP_ID;
FActiveDisplayID := FRXDispID;
end;
procedure TWDSPEngine.ProcessTXBlock;
@@ -1702,9 +1740,9 @@ begin
end;
Err := 0;
fexchange0(TXA_CHAN, @FTXIn[0], @FTXOut[0], @Err);
fexchange0(FTXChan, @FTXIn[0], @FTXOut[0], @Err);
// TX сигнал → отдельный TX-analyzer (TX_DISP_ID).
// TX сигнал → отдельный TX-analyzer (FTXDispID).
// Подаём чанками по DISPLAY_BLOCK_SIZE — analyzer ожидает именно такой
// размер блока (см. SetAnalyzer). Если подавать FTXOut целиком
// (FTXOutBufSize пар), analyzer прочитает только первые DISPLAY_BLOCK_SIZE
@@ -1795,35 +1833,35 @@ begin
// Bandpass
if (FTXFilterLow > 0) and (FTXFilterHigh > FTXFilterLow) then
SetTXABandpassFreqs(TXA_CHAN, FTXFilterLow, FTXFilterHigh);
SetTXABandpassFreqs(FTXChan, FTXFilterLow, FTXFilterHigh);
if FTXFilterWindow >= 0 then
SetTXABandpassWindow(TXA_CHAN, FTXFilterWindow);
SetTXABandpassWindow(FTXChan, FTXFilterWindow);
if FTXFilterNC > 0 then
TXASetNC(TXA_CHAN, FTXFilterNC);
TXASetNC(FTXChan, FTXFilterNC);
if FTXFilterMP >= 0 then
TXASetMP(TXA_CHAN, FTXFilterMP);
TXASetMP(FTXChan, FTXFilterMP);
// Mic gain (panel gain1)
SetTXAPanelGain1(TXA_CHAN, Power(10.0, FTXMicGainDB / 20.0));
SetTXAPanelGain1(FTXChan, Power(10.0, FTXMicGainDB / 20.0));
// Compressor
SetTXACompressorRun(TXA_CHAN, Ord(FTXCompressorOn));
SetTXACompressorGain(TXA_CHAN, FTXCompressorGain);
SetTXACompressorRun(FTXChan, Ord(FTXCompressorOn));
SetTXACompressorGain(FTXChan, FTXCompressorGain);
// Leveler
SetTXALevelerSt(TXA_CHAN, Ord(FTXLevelerOn));
SetTXALevelerTop(TXA_CHAN, FTXLevelerTop);
SetTXALevelerDecay(TXA_CHAN, FTXLevelerDecay);
SetTXALevelerSt(FTXChan, Ord(FTXLevelerOn));
SetTXALevelerTop(FTXChan, FTXLevelerTop);
SetTXALevelerDecay(FTXChan, FTXLevelerDecay);
// ALC
SetTXAALCSt(TXA_CHAN, Ord(FTXALCOn));
SetTXAALCMaxGain(TXA_CHAN, FTXALCMaxGain);
SetTXAALCDecay(TXA_CHAN, FTXALCDecay);
SetTXAALCSt(FTXChan, Ord(FTXALCOn));
SetTXAALCMaxGain(FTXChan, FTXALCMaxGain);
SetTXAALCDecay(FTXChan, FTXALCDecay);
// Phase Rotator
SetTXAPHROTRun(TXA_CHAN, Ord(FTXPhaseRotOn));
SetTXAPHROTNstages(TXA_CHAN, FTXPhaseRotStages);
SetTXAPHROTCorner(TXA_CHAN, FTXPhaseRotFreq);
SetTXAPHROTRun(FTXChan, Ord(FTXPhaseRotOn));
SetTXAPHROTNstages(FTXChan, FTXPhaseRotStages);
SetTXAPHROTCorner(FTXChan, FTXPhaseRotFreq);
// EQ TX (10-band: [0]=preamp, [1..10]=bands)
for i := 0 to 10 do
@@ -1832,21 +1870,21 @@ begin
Freqs[i] := FTXEQFreqs[i];
Qs[i] := 0.707; // умолчание Q
end;
SetTXAEQProfile(TXA_CHAN, FTXEQNumBands, @Freqs[0], @Gains[0]);
SetTXAEQRun(TXA_CHAN, Ord(FTXEQOn));
SetTXAEQProfile(FTXChan, FTXEQNumBands, @Freqs[0], @Gains[0]);
SetTXAEQRun(FTXChan, Ord(FTXEQOn));
// AM
SetTXAAMCarrierLevel(TXA_CHAN, FTXAMCarrier);
SetTXAAMCarrierLevel(FTXChan, FTXAMCarrier);
// FM
SetTXAFMDeviation(TXA_CHAN, FTXFMDeviation);
SetTXAFMDeviation(FTXChan, FTXFMDeviation);
if (FTXFMLowCut < FTXFMHighCut) then
SetTXAFMAFFilter(TXA_CHAN, FTXFMLowCut, FTXFMHighCut);
SetTXAFMEmphPosition(TXA_CHAN, FTXFMEmphPos);
SetTXAFMAFFilter(FTXChan, FTXFMLowCut, FTXFMHighCut);
SetTXAFMEmphPosition(FTXChan, FTXFMEmphPos);
// CTCSS
SetTXACTCSSFreq(TXA_CHAN, FTXCTCSSFreq);
SetTXACTCSSRun(TXA_CHAN, Ord(FTXCTCSSOn));
SetTXACTCSSFreq(FTXChan, FTXCTCSSFreq);
SetTXACTCSSRun(FTXChan, Ord(FTXCTCSSOn));
end;
procedure TWDSPEngine.SetTXFilterFull(Low, High, NC, MP, Window: Integer);
@@ -1859,10 +1897,10 @@ begin
FFilterLow := Low;
FFilterHigh := High;
if not FInitialized then Exit;
SetTXABandpassFreqs(TXA_CHAN, Low, High);
SetTXABandpassWindow(TXA_CHAN, Window);
if NC > 0 then TXASetNC(TXA_CHAN, NC);
if MP >= 0 then TXASetMP(TXA_CHAN, MP);
SetTXABandpassFreqs(FTXChan, Low, High);
SetTXABandpassWindow(FTXChan, Window);
if NC > 0 then TXASetNC(FTXChan, NC);
if MP >= 0 then TXASetMP(FTXChan, MP);
end;
procedure TWDSPEngine.SetTXCompressor(Enable: Boolean; GainDB: Double);
@@ -1870,8 +1908,8 @@ begin
FTXCompressorOn := Enable;
FTXCompressorGain := GainDB;
if not FInitialized then Exit;
SetTXACompressorGain(TXA_CHAN, GainDB);
SetTXACompressorRun(TXA_CHAN, Ord(Enable));
SetTXACompressorGain(FTXChan, GainDB);
SetTXACompressorRun(FTXChan, Ord(Enable));
end;
procedure TWDSPEngine.SetTXLeveler(Enable: Boolean; TopDB: Double; DecayMS: Integer);
@@ -1880,9 +1918,9 @@ begin
FTXLevelerTop := TopDB;
FTXLevelerDecay := DecayMS;
if not FInitialized then Exit;
SetTXALevelerTop(TXA_CHAN, TopDB);
SetTXALevelerDecay(TXA_CHAN, DecayMS);
SetTXALevelerSt(TXA_CHAN, Ord(Enable));
SetTXALevelerTop(FTXChan, TopDB);
SetTXALevelerDecay(FTXChan, DecayMS);
SetTXALevelerSt(FTXChan, Ord(Enable));
end;
procedure TWDSPEngine.SetTXALC(Enable: Boolean; MaxGainDB: Double; DecayMS: Integer);
@@ -1891,9 +1929,9 @@ begin
FTXALCMaxGain := MaxGainDB;
FTXALCDecay := DecayMS;
if not FInitialized then Exit;
SetTXAALCMaxGain(TXA_CHAN, MaxGainDB);
SetTXAALCDecay(TXA_CHAN, DecayMS);
SetTXAALCSt(TXA_CHAN, Ord(Enable));
SetTXAALCMaxGain(FTXChan, MaxGainDB);
SetTXAALCDecay(FTXChan, DecayMS);
SetTXAALCSt(FTXChan, Ord(Enable));
end;
procedure TWDSPEngine.SetTXPhaseRot(Enable: Boolean; Stages: Integer; FreqHz: Double);
@@ -1902,9 +1940,9 @@ begin
FTXPhaseRotStages := Stages;
FTXPhaseRotFreq := FreqHz;
if not FInitialized then Exit;
SetTXAPHROTNstages(TXA_CHAN, Stages);
SetTXAPHROTCorner(TXA_CHAN, FreqHz);
SetTXAPHROTRun(TXA_CHAN, Ord(Enable));
SetTXAPHROTNstages(FTXChan, Stages);
SetTXAPHROTCorner(FTXChan, FreqHz);
SetTXAPHROTRun(FTXChan, Ord(Enable));
end;
procedure TWDSPEngine.SetTXEQ(Enable: Boolean; NumBands: Integer;
@@ -1924,15 +1962,15 @@ begin
F[i] := Freqs[i];
end;
if not FInitialized then Exit;
SetTXAEQProfile(TXA_CHAN, NumBands, @F[0], @G[0]);
SetTXAEQRun(TXA_CHAN, Ord(Enable));
SetTXAEQProfile(FTXChan, NumBands, @F[0], @G[0]);
SetTXAEQRun(FTXChan, Ord(Enable));
end;
procedure TWDSPEngine.SetTXAMCarrierLevel(Level: Double);
begin
FTXAMCarrier := Level;
if not FInitialized then Exit;
WDSP.SetTXAAMCarrierLevel(TXA_CHAN, Level);
WDSP.SetTXAAMCarrierLevel(FTXChan, Level);
end;
procedure TWDSPEngine.SetTXFMParams(Deviation: Double; LowCut, HighCut, EmphPos: Integer);
@@ -1942,10 +1980,10 @@ begin
FTXFMHighCut := HighCut;
FTXFMEmphPos := EmphPos;
if not FInitialized then Exit;
SetTXAFMDeviation(TXA_CHAN, Deviation);
SetTXAFMDeviation(FTXChan, Deviation);
if LowCut < HighCut then
SetTXAFMAFFilter(TXA_CHAN, LowCut, HighCut);
SetTXAFMEmphPosition(TXA_CHAN, EmphPos);
SetTXAFMAFFilter(FTXChan, LowCut, HighCut);
SetTXAFMEmphPosition(FTXChan, EmphPos);
end;
procedure TWDSPEngine.SetTXCTCSS(Enable: Boolean; FreqHz: Double);
@@ -1953,8 +1991,8 @@ begin
FTXCTCSSOn := Enable;
FTXCTCSSFreq := FreqHz;
if not FInitialized then Exit;
SetTXACTCSSFreq(TXA_CHAN, FreqHz);
SetTXACTCSSRun(TXA_CHAN, Ord(Enable));
SetTXACTCSSFreq(FTXChan, FreqHz);
SetTXACTCSSRun(FTXChan, Ord(Enable));
end;
function TWDSPEngine.TXMicRingAvail: Integer;
@@ -2016,7 +2054,7 @@ var
begin
if not FInitialized or not FAnalyzerOpen then Exit;
N := EnsureRange(FDisplayPixelCount, 1, SPECTRUM_PIXELS);
DispID := FActiveDisplayID; // RX_DISP_ID или TX_DISP_ID, зависит от FTXActive
DispID := FActiveDisplayID; // FRXDispID или FTXDispID, зависит от FTXActive
Flag := 0;
GetPixels(DispID, 0, @PixBuf[0], @Flag);
@@ -2176,11 +2214,11 @@ begin
FSpecAvgTimeMS := AvgTimeMS;
if not FAnalyzerOpen then Exit;
AverageTimeToParams(FSpecAvgMode, FSpecAvgTimeMS, AvgCount, Backmult);
SetDisplayDetectorMode(RX_DISP_ID, 0, FSpecDetector);
SetDisplayAverageMode(RX_DISP_ID, 0, FSpecAvgMode);
SetDisplayNumAverage(RX_DISP_ID, 0, AvgCount);
SetDisplayAvBackmult(RX_DISP_ID, 0, Backmult);
SetDisplayNormOneHz(RX_DISP_ID, 0, UsePanNormOneHz(FSpecDetector));
SetDisplayDetectorMode(FRXDispID, 0, FSpecDetector);
SetDisplayAverageMode(FRXDispID, 0, FSpecAvgMode);
SetDisplayNumAverage(FRXDispID, 0, AvgCount);
SetDisplayAvBackmult(FRXDispID, 0, Backmult);
SetDisplayNormOneHz(FRXDispID, 0, UsePanNormOneHz(FSpecDetector));
end;
procedure TWDSPEngine.SetWaterfallDisplay(Detector, AvgMode: Integer;
@@ -2200,11 +2238,11 @@ begin
FWfAvgTimeMS := AvgTimeMS;
if not FAnalyzerOpen then Exit;
AverageTimeToParams(FWfAvgMode, FWfAvgTimeMS, AvgCount, Backmult);
SetDisplayDetectorMode(RX_DISP_ID, 1, FWfDetector);
SetDisplayAverageMode(RX_DISP_ID, 1, FWfAvgMode);
SetDisplayNumAverage(RX_DISP_ID, 1, AvgCount);
SetDisplayAvBackmult(RX_DISP_ID, 1, Backmult);
SetDisplayNormOneHz(RX_DISP_ID, 1, 0);
SetDisplayDetectorMode(FRXDispID, 1, FWfDetector);
SetDisplayAverageMode(FRXDispID, 1, FWfAvgMode);
SetDisplayNumAverage(FRXDispID, 1, AvgCount);
SetDisplayAvBackmult(FRXDispID, 1, Backmult);
SetDisplayNormOneHz(FRXDispID, 1, 0);
end;
end.