mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
rx2 support work
This commit is contained in:
+67
-12
@@ -151,6 +151,8 @@ type
|
|||||||
// Текущее состояние для построения HP пакетов
|
// Текущее состояние для построения HP пакетов
|
||||||
FCurrentRXFreq: Double;
|
FCurrentRXFreq: Double;
|
||||||
FCurrentTXFreq: Double;
|
FCurrentTXFreq: Double;
|
||||||
|
FDDCFreq: array[0..MAX_DDCS - 1] of Double;
|
||||||
|
FDDCEnabled: array[0..MAX_DDCS - 1] of Boolean;
|
||||||
FCurrentDrive: Byte;
|
FCurrentDrive: Byte;
|
||||||
FIsTransmitting: Boolean;
|
FIsTransmitting: Boolean;
|
||||||
FPTTActive: Boolean; // фактический PTT в HP-пакете (отдельно от Alex T/R)
|
FPTTActive: Boolean; // фактический PTT в HP-пакете (отдельно от Alex T/R)
|
||||||
@@ -216,12 +218,18 @@ type
|
|||||||
procedure SendDDCSpecific(const Pkt: TDDCSpecificPacket);
|
procedure SendDDCSpecific(const Pkt: TDDCSpecificPacket);
|
||||||
procedure ConfigureDDCs(NumDDCs: Byte; SampleRate: Word; ADCSource: Byte = 0;
|
procedure ConfigureDDCs(NumDDCs: Byte; SampleRate: Word; ADCSource: Byte = 0;
|
||||||
DitherEnabled: Boolean = True; RandomEnabled: Boolean = True);
|
DitherEnabled: Boolean = True; RandomEnabled: Boolean = True);
|
||||||
|
procedure ConfigureDDCReceivers(ReceiverCount: Byte; SampleRate: Word;
|
||||||
|
RX1ADCSource: Byte = 0; RX2ADCSource: Byte = 0;
|
||||||
|
DitherEnabled: Boolean = True;
|
||||||
|
RandomEnabled: Boolean = True;
|
||||||
|
RX2SampleRate: Word = 0);
|
||||||
procedure SendDUCSpecific(const Pkt: TDUCSpecificPacket);
|
procedure SendDUCSpecific(const Pkt: TDUCSpecificPacket);
|
||||||
procedure SendHighPriority(const Pkt: THighPriorityPacket);
|
procedure SendHighPriority(const Pkt: THighPriorityPacket);
|
||||||
procedure SetRunAndFreq(Run: Boolean; DDC0FreqHz, DUCFreqHz: Double;
|
procedure SetRunAndFreq(Run: Boolean; DDC0FreqHz, DUCFreqHz: Double;
|
||||||
DriveLevel: Byte = 100);
|
DriveLevel: Byte = 100);
|
||||||
procedure UpdateState(RXFreqHz, TXFreqHz: Double; DriveLevel: Byte;
|
procedure UpdateState(RXFreqHz, TXFreqHz: Double; DriveLevel: Byte;
|
||||||
Transmitting, PAEnabled, AlexEnabled: Boolean);
|
Transmitting, PAEnabled, AlexEnabled: Boolean);
|
||||||
|
procedure SetDDCFrequency(DDCIndex: Integer; FreqHz: Double);
|
||||||
procedure SetStepAtten(dB: Byte);
|
procedure SetStepAtten(dB: Byte);
|
||||||
procedure SetAlexConfig(const A: TAlexSettings);
|
procedure SetAlexConfig(const A: TAlexSettings);
|
||||||
// Включение/настройка XVTR-режима. Все параметры применяются мгновенно
|
// Включение/настройка XVTR-режима. Все параметры применяются мгновенно
|
||||||
@@ -608,6 +616,8 @@ begin
|
|||||||
FWBSeqValid := False;
|
FWBSeqValid := False;
|
||||||
FCurrentRXFreq := 7100000;
|
FCurrentRXFreq := 7100000;
|
||||||
FCurrentTXFreq := 7100000;
|
FCurrentTXFreq := 7100000;
|
||||||
|
FillChar(FDDCEnabled, SizeOf(FDDCEnabled), 0);
|
||||||
|
FDDCFreq[0] := FCurrentRXFreq;
|
||||||
FCurrentDrive := 0;
|
FCurrentDrive := 0;
|
||||||
FIsTransmitting := False;
|
FIsTransmitting := False;
|
||||||
FPAEnabled := True;
|
FPAEnabled := True;
|
||||||
@@ -1376,15 +1386,29 @@ end;
|
|||||||
procedure THPSDRNetwork.ConfigureDDCs(NumDDCs: Byte; SampleRate: Word;
|
procedure THPSDRNetwork.ConfigureDDCs(NumDDCs: Byte; SampleRate: Word;
|
||||||
ADCSource: Byte;
|
ADCSource: Byte;
|
||||||
DitherEnabled: Boolean; RandomEnabled: Boolean);
|
DitherEnabled: Boolean; RandomEnabled: Boolean);
|
||||||
|
begin
|
||||||
|
ConfigureDDCReceivers(NumDDCs, SampleRate, ADCSource, ADCSource,
|
||||||
|
DitherEnabled, RandomEnabled);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure THPSDRNetwork.ConfigureDDCReceivers(ReceiverCount: Byte; SampleRate: Word;
|
||||||
|
RX1ADCSource: Byte; RX2ADCSource: Byte;
|
||||||
|
DitherEnabled: Boolean; RandomEnabled: Boolean;
|
||||||
|
RX2SampleRate: Word);
|
||||||
var
|
var
|
||||||
Pkt: TDDCSpecificPacket;
|
Pkt: TDDCSpecificPacket;
|
||||||
i, ddc: Integer;
|
i, ddc: Integer;
|
||||||
DDCBase: Integer;
|
DDCBase: Integer;
|
||||||
|
ADCSource: Byte;
|
||||||
|
DDCRate: Word;
|
||||||
begin
|
begin
|
||||||
FillChar(Pkt, SizeOf(Pkt), 0);
|
FillChar(Pkt, SizeOf(Pkt), 0);
|
||||||
|
|
||||||
// ANAN-7000/8000/Saturn имеют 2 ADC
|
if ReceiverCount < 1 then ReceiverCount := 1;
|
||||||
if FDevice.BoardType in [4, 5, 10] then // ORION=4, ORION2=5, SATURN=10
|
if ReceiverCount > 2 then ReceiverCount := 2;
|
||||||
|
|
||||||
|
// ANAN-100D/200D/7000/8000/Saturn имеют второй ADC/RX front-end.
|
||||||
|
if FDevice.BoardType in [3, 4, 5, 10] then
|
||||||
Pkt.NumADCs := 2
|
Pkt.NumADCs := 2
|
||||||
else
|
else
|
||||||
Pkt.NumADCs := 1;
|
Pkt.NumADCs := 1;
|
||||||
@@ -1402,9 +1426,17 @@ begin
|
|||||||
else
|
else
|
||||||
DDCBase := 0;
|
DDCBase := 0;
|
||||||
|
|
||||||
for i := 0 to NumDDCs - 1 do
|
FillChar(FDDCEnabled, SizeOf(FDDCEnabled), 0);
|
||||||
|
for i := 0 to ReceiverCount - 1 do
|
||||||
begin
|
begin
|
||||||
ddc := DDCBase + i;
|
ddc := DDCBase + i;
|
||||||
|
ADCSource := RX1ADCSource;
|
||||||
|
if i = 1 then ADCSource := RX2ADCSource;
|
||||||
|
if ADCSource >= Pkt.NumADCs then ADCSource := 0;
|
||||||
|
DDCRate := SampleRate;
|
||||||
|
if (i = 1) and (RX2SampleRate > 0) then DDCRate := RX2SampleRate;
|
||||||
|
|
||||||
|
FDDCEnabled[ddc] := True;
|
||||||
// Enable bit для DDC ddc
|
// Enable bit для DDC ddc
|
||||||
Pkt.DDCEnable[ddc div 8] := Pkt.DDCEnable[ddc div 8] or Byte(1 shl (ddc mod 8));
|
Pkt.DDCEnable[ddc div 8] := Pkt.DDCEnable[ddc div 8] or Byte(1 shl (ddc mod 8));
|
||||||
// Config: 6 байт на DDC начиная с offset 17 в пакете → в массиве DDCConfig
|
// Config: 6 байт на DDC начиная с offset 17 в пакете → в массиве DDCConfig
|
||||||
@@ -1412,8 +1444,8 @@ begin
|
|||||||
// DDCConfig[ddc*6 + 1..2] = sample rate / 1000 (ksps)
|
// DDCConfig[ddc*6 + 1..2] = sample rate / 1000 (ksps)
|
||||||
// DDCConfig[ddc*6 + 5] = bits per sample
|
// DDCConfig[ddc*6 + 5] = bits per sample
|
||||||
Pkt.DDCConfig[ddc * 6] := ADCSource;
|
Pkt.DDCConfig[ddc * 6] := ADCSource;
|
||||||
Pkt.DDCConfig[ddc * 6 + 1] := (SampleRate shr 8) and $FF;
|
Pkt.DDCConfig[ddc * 6 + 1] := (DDCRate shr 8) and $FF;
|
||||||
Pkt.DDCConfig[ddc * 6 + 2] := SampleRate and $FF;
|
Pkt.DDCConfig[ddc * 6 + 2] := DDCRate and $FF;
|
||||||
Pkt.DDCConfig[ddc * 6 + 3] := 0;
|
Pkt.DDCConfig[ddc * 6 + 3] := 0;
|
||||||
Pkt.DDCConfig[ddc * 6 + 4] := 0;
|
Pkt.DDCConfig[ddc * 6 + 4] := 0;
|
||||||
Pkt.DDCConfig[ddc * 6 + 5] := 24; // 24 bits per sample
|
Pkt.DDCConfig[ddc * 6 + 5] := 24; // 24 bits per sample
|
||||||
@@ -1451,6 +1483,8 @@ procedure THPSDRNetwork.UpdateState(RXFreqHz, TXFreqHz: Double;
|
|||||||
Transmitting, PAEnabled, AlexEnabled: Boolean);
|
Transmitting, PAEnabled, AlexEnabled: Boolean);
|
||||||
begin
|
begin
|
||||||
FCurrentRXFreq := RXFreqHz;
|
FCurrentRXFreq := RXFreqHz;
|
||||||
|
FDDCFreq[0] := RXFreqHz;
|
||||||
|
FDDCFreq[2] := RXFreqHz;
|
||||||
FCurrentTXFreq := TXFreqHz;
|
FCurrentTXFreq := TXFreqHz;
|
||||||
FCurrentDrive := DriveLevel;
|
FCurrentDrive := DriveLevel;
|
||||||
FIsTransmitting := Transmitting;
|
FIsTransmitting := Transmitting;
|
||||||
@@ -1458,6 +1492,15 @@ begin
|
|||||||
FAlexEnabled := AlexEnabled;
|
FAlexEnabled := AlexEnabled;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure THPSDRNetwork.SetDDCFrequency(DDCIndex: Integer; FreqHz: Double);
|
||||||
|
begin
|
||||||
|
if (DDCIndex < Low(FDDCFreq)) or (DDCIndex > High(FDDCFreq)) then Exit;
|
||||||
|
FDDCFreq[DDCIndex] := FreqHz;
|
||||||
|
if (DDCIndex = 0) or (DDCIndex = 2) then
|
||||||
|
FCurrentRXFreq := FreqHz;
|
||||||
|
if FConnected then SendFullHP;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure THPSDRNetwork.SetStepAtten(dB: Byte);
|
procedure THPSDRNetwork.SetStepAtten(dB: Byte);
|
||||||
begin
|
begin
|
||||||
if dB > 31 then dB := 31;
|
if dB > 31 then dB := 31;
|
||||||
@@ -1473,6 +1516,9 @@ var
|
|||||||
Alex1: LongWord;
|
Alex1: LongWord;
|
||||||
IsOrion2: Boolean;
|
IsOrion2: Boolean;
|
||||||
DDCBase: Integer; // 0 для HERMES, 2 для ORION/ORION2/ANGELIA
|
DDCBase: Integer; // 0 для HERMES, 2 для ORION/ORION2/ANGELIA
|
||||||
|
DDCIdx: Integer;
|
||||||
|
DDCF: Double;
|
||||||
|
RX2Freq: Double;
|
||||||
begin
|
begin
|
||||||
if not FConnected then Exit;
|
if not FConnected then Exit;
|
||||||
|
|
||||||
@@ -1504,12 +1550,19 @@ begin
|
|||||||
else
|
else
|
||||||
DDCBase := 0;
|
DDCBase := 0;
|
||||||
|
|
||||||
// DDC RX frequency (bytes 9 + DDC*4)
|
// DDC RX frequencies (bytes 9 + DDC*4)
|
||||||
Ph := FreqToPhaseWord(FCurrentRXFreq);
|
if FDDCFreq[DDCBase] <= 0 then FDDCFreq[DDCBase] := FCurrentRXFreq;
|
||||||
Buf[9 + DDCBase*4] := (Ph shr 24) and $FF;
|
for DDCIdx := 0 to MAX_DDCS - 1 do
|
||||||
Buf[10 + DDCBase*4] := (Ph shr 16) and $FF;
|
if FDDCEnabled[DDCIdx] or (DDCIdx = DDCBase) then
|
||||||
Buf[11 + DDCBase*4] := (Ph shr 8) and $FF;
|
begin
|
||||||
Buf[12 + DDCBase*4] := Ph and $FF;
|
DDCF := FDDCFreq[DDCIdx];
|
||||||
|
if DDCF <= 0 then DDCF := FCurrentRXFreq;
|
||||||
|
Ph := FreqToPhaseWord(DDCF);
|
||||||
|
Buf[9 + DDCIdx*4] := (Ph shr 24) and $FF;
|
||||||
|
Buf[10 + DDCIdx*4] := (Ph shr 16) and $FF;
|
||||||
|
Buf[11 + DDCIdx*4] := (Ph shr 8) and $FF;
|
||||||
|
Buf[12 + DDCIdx*4] := Ph and $FF;
|
||||||
|
end;
|
||||||
|
|
||||||
// DUC TX frequency (bytes 329-332)
|
// DUC TX frequency (bytes 329-332)
|
||||||
Ph := FreqToPhaseWord(FCurrentTXFreq);
|
Ph := FreqToPhaseWord(FCurrentTXFreq);
|
||||||
@@ -1537,7 +1590,9 @@ begin
|
|||||||
// ALEX1 filter bits (bytes 1428-1431) — только Orion2/Saturn
|
// ALEX1 filter bits (bytes 1428-1431) — только Orion2/Saturn
|
||||||
if IsOrion2 then
|
if IsOrion2 then
|
||||||
begin
|
begin
|
||||||
Alex1 := CalcAlex1(FCurrentRXFreq, FCurrentTXFreq,
|
RX2Freq := FDDCFreq[DDCBase + 1];
|
||||||
|
if RX2Freq <= 0 then RX2Freq := FCurrentRXFreq;
|
||||||
|
Alex1 := CalcAlex1(RX2Freq, FCurrentTXFreq,
|
||||||
FIsTransmitting, FAlexConfig,
|
FIsTransmitting, FAlexConfig,
|
||||||
FXvtrDisablePA);
|
FXvtrDisablePA);
|
||||||
Buf[1428] := (Alex1 shr 24) and $FF;
|
Buf[1428] := (Alex1 shr 24) and $FF;
|
||||||
|
|||||||
+947
-15
File diff suppressed because it is too large
Load Diff
@@ -26,6 +26,7 @@ type
|
|||||||
FOnSpanSelect: TSpanSelectEvent;
|
FOnSpanSelect: TSpanSelectEvent;
|
||||||
FOnHidePanel: THidePanelEvent;
|
FOnHidePanel: THidePanelEvent;
|
||||||
FOnInvalidate: TNotifyEvent;
|
FOnInvalidate: TNotifyEvent;
|
||||||
|
FFirstButtonCaption: string;
|
||||||
FLeft: Integer;
|
FLeft: Integer;
|
||||||
FTop: Integer;
|
FTop: Integer;
|
||||||
FWidth: Integer;
|
FWidth: Integer;
|
||||||
@@ -54,6 +55,7 @@ type
|
|||||||
property Width: Integer read FWidth;
|
property Width: Integer read FWidth;
|
||||||
property Height: Integer read FHeight;
|
property Height: Integer read FHeight;
|
||||||
property HotIdx: Integer read FHotIdx;
|
property HotIdx: Integer read FHotIdx;
|
||||||
|
property FirstButtonCaption: string read FFirstButtonCaption write FFirstButtonCaption;
|
||||||
property OnSpanSelect: TSpanSelectEvent read FOnSpanSelect write FOnSpanSelect;
|
property OnSpanSelect: TSpanSelectEvent read FOnSpanSelect write FOnSpanSelect;
|
||||||
property OnHidePanel: THidePanelEvent read FOnHidePanel write FOnHidePanel;
|
property OnHidePanel: THidePanelEvent read FOnHidePanel write FOnHidePanel;
|
||||||
property OnInvalidate: TNotifyEvent read FOnInvalidate write FOnInvalidate;
|
property OnInvalidate: TNotifyEvent read FOnInvalidate write FOnInvalidate;
|
||||||
@@ -200,7 +202,12 @@ begin
|
|||||||
C.Brush.Style := bsClear;
|
C.Brush.Style := bsClear;
|
||||||
C.Rectangle(HR);
|
C.Rectangle(HR);
|
||||||
C.Font.Size := 8;
|
C.Font.Size := 8;
|
||||||
if FPanelHidden then Cap := '>' else Cap := '<';
|
if FFirstButtonCaption <> '' then
|
||||||
|
Cap := FFirstButtonCaption
|
||||||
|
else if FPanelHidden then
|
||||||
|
Cap := '>'
|
||||||
|
else
|
||||||
|
Cap := '<';
|
||||||
TW := C.TextWidth(Cap);
|
TW := C.TextWidth(Cap);
|
||||||
C.Font.Color := CLR_TEXT;
|
C.Font.Color := CLR_TEXT;
|
||||||
C.Brush.Style := bsClear;
|
C.Brush.Style := bsClear;
|
||||||
|
|||||||
+268
-230
@@ -229,6 +229,11 @@ type
|
|||||||
// не меняется.
|
// не меняется.
|
||||||
FPostTXMuteUntil: QWord;
|
FPostTXMuteUntil: QWord;
|
||||||
FActiveDisplayID: Integer; // RX_DISP_ID или TX_DISP_ID
|
FActiveDisplayID: Integer; // RX_DISP_ID или TX_DISP_ID
|
||||||
|
FRXChan: Integer;
|
||||||
|
FTXChan: Integer;
|
||||||
|
FRXDispID: Integer;
|
||||||
|
FTXDispID: Integer;
|
||||||
|
FTXEnabled: Boolean;
|
||||||
FTXMicSource: TTXMicSource;
|
FTXMicSource: TTXMicSource;
|
||||||
FOnPullMic: TPullMicSamplesFunc;
|
FOnPullMic: TPullMicSamplesFunc;
|
||||||
|
|
||||||
@@ -323,7 +328,12 @@ type
|
|||||||
public
|
public
|
||||||
constructor Create(SampleRate: Integer = 192000;
|
constructor Create(SampleRate: Integer = 192000;
|
||||||
AudioRate: Integer = 48000;
|
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;
|
destructor Destroy; override;
|
||||||
|
|
||||||
// Открыть DSP каналы
|
// Открыть DSP каналы
|
||||||
@@ -479,7 +489,7 @@ type
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
// TX DSP поток — читает mic ring buffer, вызывает fexchange0(TXA_CHAN),
|
// TX DSP поток — читает mic ring buffer, вызывает fexchange0(FTXChan),
|
||||||
// сигнализирует о готовых IQ данных через FOnTXIQ callback.
|
// сигнализирует о готовых IQ данных через FOnTXIQ callback.
|
||||||
// Аналог tx_thread в piHPSDR/transmitter.c
|
// Аналог tx_thread в piHPSDR/transmitter.c
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
@@ -715,11 +725,17 @@ end;
|
|||||||
// Constructor / Destructor
|
// Constructor / Destructor
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
constructor TWDSPEngine.Create(SampleRate, AudioRate, BufSize: Integer);
|
constructor TWDSPEngine.Create(SampleRate, AudioRate, BufSize, RXChan, TXChan,
|
||||||
|
RXDispID, TXDispID: Integer; EnableTX: Boolean);
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
FSampleRate := SampleRate;
|
FSampleRate := SampleRate;
|
||||||
FAudioRate := AudioRate;
|
FAudioRate := AudioRate;
|
||||||
|
FRXChan := RXChan;
|
||||||
|
FTXChan := TXChan;
|
||||||
|
FRXDispID := RXDispID;
|
||||||
|
FTXDispID := TXDispID;
|
||||||
|
FTXEnabled := EnableTX;
|
||||||
// BufSize = dsp_size @ AudioRate (внутренний DSP буфер, piHPSDR buffer_size = 1024)
|
// BufSize = dsp_size @ AudioRate (внутренний DSP буфер, piHPSDR buffer_size = 1024)
|
||||||
// FBufSize = in_size @ SampleRate = BufSize * (SampleRate/AudioRate)
|
// FBufSize = in_size @ SampleRate = BufSize * (SampleRate/AudioRate)
|
||||||
// piHPSDR: in_size = buffer_size * sample_rate/48000 = 1024*4 = 4096 @ 192kHz
|
// piHPSDR: in_size = buffer_size * sample_rate/48000 = 1024*4 = 4096 @ 192kHz
|
||||||
@@ -784,7 +800,7 @@ begin
|
|||||||
FTXActive := False;
|
FTXActive := False;
|
||||||
FKeepRXDuringTX := False;
|
FKeepRXDuringTX := False;
|
||||||
FPostTXMuteUntil := 0;
|
FPostTXMuteUntil := 0;
|
||||||
FActiveDisplayID := RX_DISP_ID;
|
FActiveDisplayID := FRXDispID;
|
||||||
FTXMicSource := txmsRadio;
|
FTXMicSource := txmsRadio;
|
||||||
FOnPullMic := nil;
|
FOnPullMic := nil;
|
||||||
FTXThread := nil;
|
FTXThread := nil;
|
||||||
@@ -865,19 +881,22 @@ begin
|
|||||||
if FAnalyzerOpen then Exit;
|
if FAnalyzerOpen then Exit;
|
||||||
|
|
||||||
Success := -1;
|
Success := -1;
|
||||||
XCreateAnalyzer(RX_DISP_ID, @Success, 262144, 1, 1, nil);
|
XCreateAnalyzer(FRXDispID, @Success, 262144, 1, 1, nil);
|
||||||
if Success <> 0 then
|
if Success <> 0 then
|
||||||
begin
|
begin
|
||||||
FLastError := Format('XCreateAnalyzer(RX) failed: %d', [Success]);
|
FLastError := Format('XCreateAnalyzer(RX) failed: %d', [Success]);
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Отдельный analyzer для TX-спектра/водопада. Ошибку логируем в LastError,
|
if FTXEnabled then
|
||||||
// но не считаем фатальной — RX без TX-display продолжает работать.
|
begin
|
||||||
Success := -1;
|
// Отдельный analyzer для TX-спектра/водопада. Ошибку логируем в LastError,
|
||||||
XCreateAnalyzer(TX_DISP_ID, @Success, 262144, 1, 1, nil);
|
// но не считаем фатальной — RX без TX-display продолжает работать.
|
||||||
if Success <> 0 then
|
Success := -1;
|
||||||
FLastError := Format('XCreateAnalyzer(TX) failed: %d', [Success]);
|
XCreateAnalyzer(FTXDispID, @Success, 262144, 1, 1, nil);
|
||||||
|
if Success <> 0 then
|
||||||
|
FLastError := Format('XCreateAnalyzer(TX) failed: %d', [Success]);
|
||||||
|
end;
|
||||||
|
|
||||||
FFlp[0] := 0;
|
FFlp[0] := 0;
|
||||||
ApplyAnalyzerSettings;
|
ApplyAnalyzerSettings;
|
||||||
@@ -888,7 +907,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.ApplyRXAnalyzerSettings;
|
procedure TWDSPEngine.ApplyRXAnalyzerSettings;
|
||||||
// Применяет FFFTSize / FWindowType / FSpec* / FWf* к RX_DISP_ID.
|
// Применяет FFFTSize / FWindowType / FSpec* / FWf* к FRXDispID.
|
||||||
var
|
var
|
||||||
AnalyzerFFT, AvgCount, WfAvgCount, MaxW, Overlap, DisplayPixels: Integer;
|
AnalyzerFFT, AvgCount, WfAvgCount, MaxW, Overlap, DisplayPixels: Integer;
|
||||||
Backmult, WfBackmult: Double;
|
Backmult, WfBackmult: Double;
|
||||||
@@ -905,24 +924,24 @@ begin
|
|||||||
AverageTimeToParams(FSpecAvgMode, FSpecAvgTimeMS, AvgCount, Backmult);
|
AverageTimeToParams(FSpecAvgMode, FSpecAvgTimeMS, AvgCount, Backmult);
|
||||||
AverageTimeToParams(FWfAvgMode, FWfAvgTimeMS, WfAvgCount, WfBackmult);
|
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,
|
FWindowType, 14.0, Overlap, 0, 0.0, 0.0, DisplayPixels,
|
||||||
1, 0, 0.0, 0.0, MaxW);
|
1, 0, 0.0, 0.0, MaxW);
|
||||||
SetDisplayDetectorMode(RX_DISP_ID, 0, FSpecDetector);
|
SetDisplayDetectorMode(FRXDispID, 0, FSpecDetector);
|
||||||
SetDisplayAverageMode (RX_DISP_ID, 0, FSpecAvgMode);
|
SetDisplayAverageMode (FRXDispID, 0, FSpecAvgMode);
|
||||||
SetDisplayNumAverage (RX_DISP_ID, 0, AvgCount);
|
SetDisplayNumAverage (FRXDispID, 0, AvgCount);
|
||||||
SetDisplayAvBackmult (RX_DISP_ID, 0, Backmult);
|
SetDisplayAvBackmult (FRXDispID, 0, Backmult);
|
||||||
SetDisplayNormOneHz (RX_DISP_ID, 0, UsePanNormOneHz(FSpecDetector));
|
SetDisplayNormOneHz (FRXDispID, 0, UsePanNormOneHz(FSpecDetector));
|
||||||
SetDisplayDetectorMode(RX_DISP_ID, 1, FWfDetector);
|
SetDisplayDetectorMode(FRXDispID, 1, FWfDetector);
|
||||||
SetDisplayAverageMode (RX_DISP_ID, 1, FWfAvgMode);
|
SetDisplayAverageMode (FRXDispID, 1, FWfAvgMode);
|
||||||
SetDisplayNumAverage (RX_DISP_ID, 1, WfAvgCount);
|
SetDisplayNumAverage (FRXDispID, 1, WfAvgCount);
|
||||||
SetDisplayAvBackmult (RX_DISP_ID, 1, WfBackmult);
|
SetDisplayAvBackmult (FRXDispID, 1, WfBackmult);
|
||||||
SetDisplayNormOneHz (RX_DISP_ID, 1, 0);
|
SetDisplayNormOneHz (FRXDispID, 1, 0);
|
||||||
SetDisplaySampleRate (RX_DISP_ID, FSampleRate);
|
SetDisplaySampleRate (FRXDispID, FSampleRate);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.ApplyTXAnalyzerSettings;
|
procedure TWDSPEngine.ApplyTXAnalyzerSettings;
|
||||||
// Применяет FTXFFTSize / FTXWindowType / FTXSpec* / FTXWf* к TX_DISP_ID.
|
// Применяет FTXFFTSize / FTXWindowType / FTXSpec* / FTXWf* к FTXDispID.
|
||||||
// FFT/Window/Det/Avg отдельные от RX — TX-спектр обычно нужен мельче по FFT
|
// FFT/Window/Det/Avg отдельные от RX — TX-спектр обычно нужен мельче по FFT
|
||||||
// (TX-полоса узкая) и с другим усреднением (быстрее реагировать на голос).
|
// (TX-полоса узкая) и с другим усреднением (быстрее реагировать на голос).
|
||||||
var
|
var
|
||||||
@@ -931,6 +950,7 @@ var
|
|||||||
EffectiveFPS: Double;
|
EffectiveFPS: Double;
|
||||||
const KEEP_TIME_SEC = 0.10;
|
const KEEP_TIME_SEC = 0.10;
|
||||||
begin
|
begin
|
||||||
|
if not FTXEnabled then Exit;
|
||||||
AnalyzerFFT := NormalizeFFTSize(FTXFFTSize);
|
AnalyzerFFT := NormalizeFFTSize(FTXFFTSize);
|
||||||
FTXDispPos := 0;
|
FTXDispPos := 0;
|
||||||
MaxW := AnalyzerFFT + Round(Min(KEEP_TIME_SEC * FTXSampleRate,
|
MaxW := AnalyzerFFT + Round(Min(KEEP_TIME_SEC * FTXSampleRate,
|
||||||
@@ -941,27 +961,28 @@ begin
|
|||||||
AverageTimeToParams(FTXSpecAvgMode, FTXSpecAvgTimeMS, AvgCount, Backmult);
|
AverageTimeToParams(FTXSpecAvgMode, FTXSpecAvgTimeMS, AvgCount, Backmult);
|
||||||
AverageTimeToParams(FTXWfAvgMode, FTXWfAvgTimeMS, WfAvgCount, WfBackmult);
|
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,
|
FTXWindowType, 14.0, Overlap, 0, 0.0, 0.0, DisplayPixels,
|
||||||
1, 0, 0.0, 0.0, MaxW);
|
1, 0, 0.0, 0.0, MaxW);
|
||||||
SetDisplayDetectorMode(TX_DISP_ID, 0, FTXSpecDetector);
|
SetDisplayDetectorMode(FTXDispID, 0, FTXSpecDetector);
|
||||||
SetDisplayAverageMode (TX_DISP_ID, 0, FTXSpecAvgMode);
|
SetDisplayAverageMode (FTXDispID, 0, FTXSpecAvgMode);
|
||||||
SetDisplayNumAverage (TX_DISP_ID, 0, AvgCount);
|
SetDisplayNumAverage (FTXDispID, 0, AvgCount);
|
||||||
SetDisplayAvBackmult (TX_DISP_ID, 0, Backmult);
|
SetDisplayAvBackmult (FTXDispID, 0, Backmult);
|
||||||
SetDisplayNormOneHz (TX_DISP_ID, 0, UsePanNormOneHz(FTXSpecDetector));
|
SetDisplayNormOneHz (FTXDispID, 0, UsePanNormOneHz(FTXSpecDetector));
|
||||||
SetDisplayDetectorMode(TX_DISP_ID, 1, FTXWfDetector);
|
SetDisplayDetectorMode(FTXDispID, 1, FTXWfDetector);
|
||||||
SetDisplayAverageMode (TX_DISP_ID, 1, FTXWfAvgMode);
|
SetDisplayAverageMode (FTXDispID, 1, FTXWfAvgMode);
|
||||||
SetDisplayNumAverage (TX_DISP_ID, 1, WfAvgCount);
|
SetDisplayNumAverage (FTXDispID, 1, WfAvgCount);
|
||||||
SetDisplayAvBackmult (TX_DISP_ID, 1, WfBackmult);
|
SetDisplayAvBackmult (FTXDispID, 1, WfBackmult);
|
||||||
SetDisplayNormOneHz (TX_DISP_ID, 1, 0);
|
SetDisplayNormOneHz (FTXDispID, 1, 0);
|
||||||
SetDisplaySampleRate (TX_DISP_ID, FTXSampleRate);
|
SetDisplaySampleRate (FTXDispID, FTXSampleRate);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.ApplyAnalyzerSettings;
|
procedure TWDSPEngine.ApplyAnalyzerSettings;
|
||||||
// Совместимый вход: применяет настройки и к RX, и к TX analyzer'у.
|
// Совместимый вход: применяет настройки и к RX, и к TX analyzer'у.
|
||||||
begin
|
begin
|
||||||
ApplyRXAnalyzerSettings;
|
ApplyRXAnalyzerSettings;
|
||||||
ApplyTXAnalyzerSettings;
|
if FTXEnabled then
|
||||||
|
ApplyTXAnalyzerSettings;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.CloseAnalyzer;
|
procedure TWDSPEngine.CloseAnalyzer;
|
||||||
@@ -973,8 +994,9 @@ begin
|
|||||||
FDisplayThread.WaitFor;
|
FDisplayThread.WaitFor;
|
||||||
FreeAndNil(FDisplayThread);
|
FreeAndNil(FDisplayThread);
|
||||||
end;
|
end;
|
||||||
DestroyAnalyzer(RX_DISP_ID);
|
DestroyAnalyzer(FRXDispID);
|
||||||
DestroyAnalyzer(TX_DISP_ID);
|
if FTXEnabled then
|
||||||
|
DestroyAnalyzer(FTXDispID);
|
||||||
FAnalyzerOpen := False;
|
FAnalyzerOpen := False;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -1011,7 +1033,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
OpenChannel(
|
OpenChannel(
|
||||||
RXA_CHAN,
|
FRXChan,
|
||||||
FBufSize,
|
FBufSize,
|
||||||
FAudioBufSize,
|
FAudioBufSize,
|
||||||
FSampleRate,
|
FSampleRate,
|
||||||
@@ -1023,45 +1045,49 @@ begin
|
|||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
create_anbEXT(RXA_CHAN, 1, 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(RXA_CHAN, 1, 0, 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);
|
SetRXABandpassWindow(FRXChan, 1);
|
||||||
SetRXAMode(RXA_CHAN, ModeToWDSP(FMode));
|
SetRXAMode(FRXChan, ModeToWDSP(FMode));
|
||||||
SetRXAShiftRun(RXA_CHAN, 1);
|
SetRXAShiftRun(FRXChan, 1);
|
||||||
SetRXAShiftFreq(RXA_CHAN, 0.0);
|
SetRXAShiftFreq(FRXChan, 0.0);
|
||||||
RXASetPassband(RXA_CHAN, FFilterLow, FFilterHigh);
|
RXASetPassband(FRXChan, FFilterLow, FFilterHigh);
|
||||||
SetAGC(FAGCMode, 50.0);
|
SetAGC(FAGCMode, 50.0);
|
||||||
SetRXAPanelGain1(RXA_CHAN, FVolume);
|
SetRXAPanelGain1(FRXChan, FVolume);
|
||||||
SetRXAPanelSelect(RXA_CHAN, 3);
|
SetRXAPanelSelect(FRXChan, 3);
|
||||||
SetRXAPanelRun(RXA_CHAN, 1);
|
SetRXAPanelRun(FRXChan, 1);
|
||||||
SetChannelState(RXA_CHAN, 1, 0);
|
SetChannelState(FRXChan, 1, 0);
|
||||||
|
|
||||||
// TXA: mic @ FAudioRate → IQ @ FTXSampleRate (фиксированный DUC rate, не зависит от RX).
|
if FTXEnabled then
|
||||||
// out_size = FAudioBufSize * FTXSampleRate/FAudioRate = FTXOutBufSize (4096 @ 192k tx).
|
begin
|
||||||
// FTXOut уже имеет размер FTXOutBufSize*2.
|
// TXA: mic @ FAudioRate → IQ @ FTXSampleRate (фиксированный DUC rate, не зависит от RX).
|
||||||
OpenChannel(
|
// out_size = FAudioBufSize * FTXSampleRate/FAudioRate = FTXOutBufSize (4096 @ 192k tx).
|
||||||
TXA_CHAN,
|
// FTXOut уже имеет размер FTXOutBufSize*2.
|
||||||
FAudioBufSize,
|
OpenChannel(
|
||||||
FAudioBufSize,
|
FTXChan,
|
||||||
FAudioRate,
|
FAudioBufSize,
|
||||||
FAudioRate,
|
FAudioBufSize,
|
||||||
FTXSampleRate,
|
FAudioRate,
|
||||||
1,
|
FAudioRate,
|
||||||
0,
|
FTXSampleRate,
|
||||||
0.010, 0.010, 0.010, 0.010,
|
1,
|
||||||
0
|
0,
|
||||||
);
|
0.010, 0.010, 0.010, 0.010,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
SetTXAMode(TXA_CHAN, ModeToWDSP(FMode));
|
SetTXAMode(FTXChan, ModeToWDSP(FMode));
|
||||||
SetTXAPanelRun(TXA_CHAN, 1);
|
SetTXAPanelRun(FTXChan, 1);
|
||||||
// PatchPanel: 1=Q, 2=I. Mic подаётся в I (FTXIn[i*2]), Q=0 — выбираем I.
|
// PatchPanel: 1=Q, 2=I. Mic подаётся в I (FTXIn[i*2]), Q=0 — выбираем I.
|
||||||
SetTXAPanelSelect(TXA_CHAN, 2);
|
SetTXAPanelSelect(FTXChan, 2);
|
||||||
|
end;
|
||||||
|
|
||||||
FInitialized := True;
|
FInitialized := True;
|
||||||
// Прокидываем все TX-параметры из FTX*-полей: фильтр, mic gain, EQ,
|
// Прокидываем все TX-параметры из FTX*-полей: фильтр, mic gain, EQ,
|
||||||
// Leveler, ALC, Compressor, Phase Rotator, AM Carrier, FM, CTCSS.
|
// Leveler, ALC, Compressor, Phase Rotator, AM Carrier, FM, CTCSS.
|
||||||
ApplyTXChainSettings;
|
if FTXEnabled then
|
||||||
|
ApplyTXChainSettings;
|
||||||
ApplyNoiseFilterState;
|
ApplyNoiseFilterState;
|
||||||
Result := True;
|
Result := True;
|
||||||
|
|
||||||
@@ -1094,10 +1120,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
CloseAnalyzer;
|
CloseAnalyzer;
|
||||||
destroy_anbEXT(RXA_CHAN);
|
destroy_anbEXT(FRXChan);
|
||||||
destroy_nobEXT(RXA_CHAN);
|
destroy_nobEXT(FRXChan);
|
||||||
CloseChannel(RXA_CHAN);
|
CloseChannel(FRXChan);
|
||||||
CloseChannel(TXA_CHAN);
|
if FTXEnabled then
|
||||||
|
CloseChannel(FTXChan);
|
||||||
FInitialized := False;
|
FInitialized := False;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -1179,7 +1206,7 @@ procedure TWDSPEngine.PushIQItemToDSP(const Item: TIQQueueItem);
|
|||||||
// Вызывается из DSP потока — декодирует IQ и накапливает до FBufSize.
|
// Вызывается из DSP потока — декодирует IQ и накапливает до FBufSize.
|
||||||
// В non-DUP TX (FTXActive and not FKeepRXDuringTX) полностью пропускаем
|
// В non-DUP TX (FTXActive and not FKeepRXDuringTX) полностью пропускаем
|
||||||
// IQ-пакет: не кормим RX-анализатор и не накапливаем для fexchange0.
|
// IQ-пакет: не кормим RX-анализатор и не накапливаем для fexchange0.
|
||||||
// Иначе TX leakage из DDC оседает в RXA pipeline / RX_DISP_ID FFT-истории
|
// Иначе TX leakage из DDC оседает в RXA pipeline / FRXDispID FFT-истории
|
||||||
// и звучит/виден на водопаде первые секунды после возврата на RX.
|
// и звучит/виден на водопаде первые секунды после возврата на RX.
|
||||||
var
|
var
|
||||||
i, Pos: Integer;
|
i, Pos: Integer;
|
||||||
@@ -1231,7 +1258,7 @@ begin
|
|||||||
|
|
||||||
if FDispPos >= DISPLAY_BLOCK_SIZE then
|
if FDispPos >= DISPLAY_BLOCK_SIZE then
|
||||||
begin
|
begin
|
||||||
Spectrum0(1, RX_DISP_ID, 0, 0, @FDispBuf[0]);
|
Spectrum0(1, FRXDispID, 0, 0, @FDispBuf[0]);
|
||||||
FDispPos := 0;
|
FDispPos := 0;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@@ -1246,7 +1273,7 @@ begin
|
|||||||
|
|
||||||
if FTXDispPos >= DISPLAY_BLOCK_SIZE then
|
if FTXDispPos >= DISPLAY_BLOCK_SIZE then
|
||||||
begin
|
begin
|
||||||
Spectrum0(1, TX_DISP_ID, 0, 0, @FTXDispBuf[0]);
|
Spectrum0(1, FTXDispID, 0, 0, @FTXDispBuf[0]);
|
||||||
FTXDispPos := 0;
|
FTXDispPos := 0;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@@ -1270,12 +1297,12 @@ begin
|
|||||||
|
|
||||||
// DSP обработка
|
// DSP обработка
|
||||||
Err := 0;
|
Err := 0;
|
||||||
fexchange0(RXA_CHAN, @FRXIn[0], @FRXOut[0], @Err);
|
fexchange0(FRXChan, @FRXIn[0], @FRXOut[0], @Err);
|
||||||
|
|
||||||
// S-meter: читаем ОДИН раз в DSP-колбэке и кешируем в FSMeter.
|
// S-meter: читаем ОДИН раз в DSP-колбэке и кешируем в FSMeter.
|
||||||
// GetRXAMeter сбрасывает аккумулятор после вызова, поэтому второй
|
// GetRXAMeter сбрасывает аккумулятор после вызова, поэтому второй
|
||||||
// вызов вернёт 0/-∞ — отсюда "падение до нуля". Только здесь!
|
// вызов вернёт 0/-∞ — отсюда "падение до нуля". Только здесь!
|
||||||
FSMeter := GetRXAMeter(RXA_CHAN, RXA_S_AV);
|
FSMeter := GetRXAMeter(FRXChan, RXA_S_AV);
|
||||||
|
|
||||||
// Аудио колбэк — FAudioBufSize сэмплов @ FAudioRate (после децимации 4:1).
|
// Аудио колбэк — FAudioBufSize сэмплов @ FAudioRate (после децимации 4:1).
|
||||||
// При TX RX-аудио глушим (как в Thetis/piHPSDR при не-duplex MOX),
|
// При TX RX-аудио глушим (как в Thetis/piHPSDR при не-duplex MOX),
|
||||||
@@ -1309,8 +1336,9 @@ procedure TWDSPEngine.SetMode(Mode: Integer);
|
|||||||
begin
|
begin
|
||||||
FMode := Mode;
|
FMode := Mode;
|
||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
SetRXAMode(RXA_CHAN, ModeToWDSP(Mode));
|
SetRXAMode(FRXChan, ModeToWDSP(Mode));
|
||||||
SetTXAMode(TXA_CHAN, ModeToWDSP(Mode));
|
if FTXEnabled then
|
||||||
|
SetTXAMode(FTXChan, ModeToWDSP(Mode));
|
||||||
// НЕ вызываем ApplyDefaultFilter — фильтр устанавливается явно из UI
|
// НЕ вызываем ApplyDefaultFilter — фильтр устанавливается явно из UI
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -1320,7 +1348,7 @@ begin
|
|||||||
FFilterHigh := High;
|
FFilterHigh := High;
|
||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
// RXASetPassband — правильный unified API, пересчитывает фильтр целиком
|
// RXASetPassband — правильный unified API, пересчитывает фильтр целиком
|
||||||
RXASetPassband(RXA_CHAN, Low, High);
|
RXASetPassband(FRXChan, Low, High);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.SetAGC(Mode: TWDSPAGCMode; FixedGain: Double);
|
procedure TWDSPEngine.SetAGC(Mode: TWDSPAGCMode; FixedGain: Double);
|
||||||
@@ -1329,40 +1357,40 @@ begin
|
|||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
|
|
||||||
// Точно по piHPSDR receiver.c: set_agc()
|
// Точно по piHPSDR receiver.c: set_agc()
|
||||||
SetRXAAGCMode(RXA_CHAN, Ord(Mode));
|
SetRXAAGCMode(FRXChan, Ord(Mode));
|
||||||
SetRXAAGCSlope(RXA_CHAN, FAGCSlope);
|
SetRXAAGCSlope(FRXChan, FAGCSlope);
|
||||||
SetRXAAGCTop(RXA_CHAN, FAGCTop);
|
SetRXAAGCTop(FRXChan, FAGCTop);
|
||||||
|
|
||||||
case Mode of
|
case Mode of
|
||||||
agcOff:
|
agcOff:
|
||||||
SetRXAAGCFixed(RXA_CHAN, FixedGain);
|
SetRXAAGCFixed(FRXChan, FixedGain);
|
||||||
|
|
||||||
agcLong: begin
|
agcLong: begin
|
||||||
SetRXAAGCAttack(RXA_CHAN, 2);
|
SetRXAAGCAttack(FRXChan, 2);
|
||||||
SetRXAAGCHang(RXA_CHAN, 2000);
|
SetRXAAGCHang(FRXChan, 2000);
|
||||||
SetRXAAGCDecay(RXA_CHAN, 2000);
|
SetRXAAGCDecay(FRXChan, 2000);
|
||||||
SetRXAAGCHangThreshold(RXA_CHAN, FAGCHangThreshold);
|
SetRXAAGCHangThreshold(FRXChan, FAGCHangThreshold);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
agcSlow: begin
|
agcSlow: begin
|
||||||
SetRXAAGCAttack(RXA_CHAN, 2);
|
SetRXAAGCAttack(FRXChan, 2);
|
||||||
SetRXAAGCHang(RXA_CHAN, 1000);
|
SetRXAAGCHang(FRXChan, 1000);
|
||||||
SetRXAAGCDecay(RXA_CHAN, 500);
|
SetRXAAGCDecay(FRXChan, 500);
|
||||||
SetRXAAGCHangThreshold(RXA_CHAN, FAGCHangThreshold);
|
SetRXAAGCHangThreshold(FRXChan, FAGCHangThreshold);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
agcMedium: begin
|
agcMedium: begin
|
||||||
SetRXAAGCAttack(RXA_CHAN, 2);
|
SetRXAAGCAttack(FRXChan, 2);
|
||||||
SetRXAAGCHang(RXA_CHAN, 0);
|
SetRXAAGCHang(FRXChan, 0);
|
||||||
SetRXAAGCDecay(RXA_CHAN, 250);
|
SetRXAAGCDecay(FRXChan, 250);
|
||||||
SetRXAAGCHangThreshold(RXA_CHAN, 100);
|
SetRXAAGCHangThreshold(FRXChan, 100);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
agcFast: begin
|
agcFast: begin
|
||||||
SetRXAAGCAttack(RXA_CHAN, 2);
|
SetRXAAGCAttack(FRXChan, 2);
|
||||||
SetRXAAGCHang(RXA_CHAN, 0);
|
SetRXAAGCHang(FRXChan, 0);
|
||||||
SetRXAAGCDecay(RXA_CHAN, 50);
|
SetRXAAGCDecay(FRXChan, 50);
|
||||||
SetRXAAGCHangThreshold(RXA_CHAN, 100);
|
SetRXAAGCHangThreshold(FRXChan, 100);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -1374,14 +1402,14 @@ procedure TWDSPEngine.SetShift(ShiftHz: Double);
|
|||||||
begin
|
begin
|
||||||
FShiftHz := ShiftHz;
|
FShiftHz := ShiftHz;
|
||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
SetRXAShiftFreq(RXA_CHAN, ShiftHz);
|
SetRXAShiftFreq(FRXChan, ShiftHz);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.SetAGCTop(TopDBm: Double);
|
procedure TWDSPEngine.SetAGCTop(TopDBm: Double);
|
||||||
begin
|
begin
|
||||||
FAGCTop := TopDBm;
|
FAGCTop := TopDBm;
|
||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
SetRXAAGCTop(RXA_CHAN, TopDBm);
|
SetRXAAGCTop(FRXChan, TopDBm);
|
||||||
UpdateAGCLines(FLastSpectrumW);
|
UpdateAGCLines(FLastSpectrumW);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -1389,14 +1417,14 @@ procedure TWDSPEngine.SetAGCSlope(Slope: Integer);
|
|||||||
begin
|
begin
|
||||||
FAGCSlope := Slope;
|
FAGCSlope := Slope;
|
||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
SetRXAAGCSlope(RXA_CHAN, Slope);
|
SetRXAAGCSlope(FRXChan, Slope);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.SetAGCHangThreshold(Threshold: Integer);
|
procedure TWDSPEngine.SetAGCHangThreshold(Threshold: Integer);
|
||||||
begin
|
begin
|
||||||
FAGCHangThreshold := Threshold;
|
FAGCHangThreshold := Threshold;
|
||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
SetRXAAGCHangThreshold(RXA_CHAN, Threshold);
|
SetRXAAGCHangThreshold(FRXChan, Threshold);
|
||||||
UpdateAGCLines(FLastSpectrumW);
|
UpdateAGCLines(FLastSpectrumW);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -1413,8 +1441,8 @@ procedure TWDSPEngine.UpdateAGCLines(SpectrumW: Integer);
|
|||||||
begin
|
begin
|
||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
if SpectrumW <= 0 then Exit; // окно ещё не показано — не читаем
|
if SpectrumW <= 0 then Exit; // окно ещё не показано — не читаем
|
||||||
GetRXAAGCHangLevel(RXA_CHAN, @FAGCHangLevel);
|
GetRXAAGCHangLevel(FRXChan, @FAGCHangLevel);
|
||||||
GetRXAAGCThresh(RXA_CHAN, @FAGCThresh,
|
GetRXAAGCThresh(FRXChan, @FAGCThresh,
|
||||||
SpectrumW, // реальная ширина дисплея в пикселях
|
SpectrumW, // реальная ширина дисплея в пикселях
|
||||||
FSampleRate);
|
FSampleRate);
|
||||||
end;
|
end;
|
||||||
@@ -1423,65 +1451,65 @@ procedure TWDSPEngine.ApplyNRState;
|
|||||||
begin
|
begin
|
||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
|
|
||||||
SetRXAANRVals(RXA_CHAN, 64, 16, 16e-4, 10e-7);
|
SetRXAANRVals(FRXChan, 64, 16, 16e-4, 10e-7);
|
||||||
SetRXAANRPosition(RXA_CHAN, FILTER_NR_AGC_POSITION);
|
SetRXAANRPosition(FRXChan, FILTER_NR_AGC_POSITION);
|
||||||
SetRXAANRRun(RXA_CHAN, Ord(FNRMode = NR_MODE_1));
|
SetRXAANRRun(FRXChan, Ord(FNRMode = NR_MODE_1));
|
||||||
|
|
||||||
SetRXAEMNRPosition(RXA_CHAN, FILTER_NR_AGC_POSITION);
|
SetRXAEMNRPosition(FRXChan, FILTER_NR_AGC_POSITION);
|
||||||
SetRXAEMNRgainMethod(RXA_CHAN, FILTER_NR2_GAIN_METHOD);
|
SetRXAEMNRgainMethod(FRXChan, FILTER_NR2_GAIN_METHOD);
|
||||||
SetRXAEMNRnpeMethod(RXA_CHAN, FILTER_NR2_NPE_METHOD);
|
SetRXAEMNRnpeMethod(FRXChan, FILTER_NR2_NPE_METHOD);
|
||||||
SetRXAEMNRtrainZetaThresh(RXA_CHAN, FILTER_NR2_TRAINED_THRESHOLD);
|
SetRXAEMNRtrainZetaThresh(FRXChan, FILTER_NR2_TRAINED_THRESHOLD);
|
||||||
SetRXAEMNRtrainT2(RXA_CHAN, FILTER_NR2_TRAINED_T2);
|
SetRXAEMNRtrainT2(FRXChan, FILTER_NR2_TRAINED_T2);
|
||||||
SetRXAEMNRpost2Taper(RXA_CHAN, FILTER_NR2_POST_TAPER);
|
SetRXAEMNRpost2Taper(FRXChan, FILTER_NR2_POST_TAPER);
|
||||||
SetRXAEMNRpost2Nlevel(RXA_CHAN, FILTER_NR2_POST_NLEVEL);
|
SetRXAEMNRpost2Nlevel(FRXChan, FILTER_NR2_POST_NLEVEL);
|
||||||
SetRXAEMNRpost2Factor(RXA_CHAN, FILTER_NR2_POST_FACTOR);
|
SetRXAEMNRpost2Factor(FRXChan, FILTER_NR2_POST_FACTOR);
|
||||||
SetRXAEMNRpost2Rate(RXA_CHAN, FILTER_NR2_POST_RATE);
|
SetRXAEMNRpost2Rate(FRXChan, FILTER_NR2_POST_RATE);
|
||||||
SetRXAEMNRaeRun(RXA_CHAN, 1);
|
SetRXAEMNRaeRun(FRXChan, 1);
|
||||||
SetRXAEMNRpost2Run(RXA_CHAN, FILTER_NR2_POST_RUN);
|
SetRXAEMNRpost2Run(FRXChan, FILTER_NR2_POST_RUN);
|
||||||
SetRXAEMNRRun(RXA_CHAN, Ord(FNRMode = NR_MODE_2));
|
SetRXAEMNRRun(FRXChan, Ord(FNRMode = NR_MODE_2));
|
||||||
|
|
||||||
SetRXARNNRPosition(RXA_CHAN, FILTER_NR_AGC_POSITION);
|
SetRXARNNRPosition(FRXChan, FILTER_NR_AGC_POSITION);
|
||||||
SetRXARNNRRun(RXA_CHAN, Ord(FNRMode = NR_MODE_3));
|
SetRXARNNRRun(FRXChan, Ord(FNRMode = NR_MODE_3));
|
||||||
|
|
||||||
SetRXASBNRreductionAmount(RXA_CHAN, FILTER_NR4_REDUCTION_AMOUNT);
|
SetRXASBNRreductionAmount(FRXChan, FILTER_NR4_REDUCTION_AMOUNT);
|
||||||
SetRXASBNRsmoothingFactor(RXA_CHAN, FILTER_NR4_SMOOTHING_FACTOR);
|
SetRXASBNRsmoothingFactor(FRXChan, FILTER_NR4_SMOOTHING_FACTOR);
|
||||||
SetRXASBNRwhiteningFactor(RXA_CHAN, FILTER_NR4_WHITENING_FACTOR);
|
SetRXASBNRwhiteningFactor(FRXChan, FILTER_NR4_WHITENING_FACTOR);
|
||||||
SetRXASBNRnoiseRescale(RXA_CHAN, FILTER_NR4_NOISE_RESCALE);
|
SetRXASBNRnoiseRescale(FRXChan, FILTER_NR4_NOISE_RESCALE);
|
||||||
SetRXASBNRpostFilterThreshold(RXA_CHAN, FILTER_NR4_POST_THRESHOLD);
|
SetRXASBNRpostFilterThreshold(FRXChan, FILTER_NR4_POST_THRESHOLD);
|
||||||
SetRXASBNRnoiseScalingType(RXA_CHAN, FILTER_NR4_NOISE_SCALING_TYPE);
|
SetRXASBNRnoiseScalingType(FRXChan, FILTER_NR4_NOISE_SCALING_TYPE);
|
||||||
SetRXASBNRPosition(RXA_CHAN, FILTER_NR_AGC_POSITION);
|
SetRXASBNRPosition(FRXChan, FILTER_NR_AGC_POSITION);
|
||||||
SetRXASBNRRun(RXA_CHAN, Ord(FNRMode = NR_MODE_4));
|
SetRXASBNRRun(FRXChan, Ord(FNRMode = NR_MODE_4));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.ApplyNBState;
|
procedure TWDSPEngine.ApplyNBState;
|
||||||
begin
|
begin
|
||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
|
|
||||||
SetEXTANBTau(RXA_CHAN, FILTER_NB_TAU);
|
SetEXTANBTau(FRXChan, FILTER_NB_TAU);
|
||||||
SetEXTANBHangtime(RXA_CHAN, FILTER_NB_HANGTIME);
|
SetEXTANBHangtime(FRXChan, FILTER_NB_HANGTIME);
|
||||||
SetEXTANBAdvtime(RXA_CHAN, FILTER_NB_ADVTIME);
|
SetEXTANBAdvtime(FRXChan, FILTER_NB_ADVTIME);
|
||||||
SetEXTANBThreshold(RXA_CHAN, FILTER_NB_THRESHOLD);
|
SetEXTANBThreshold(FRXChan, FILTER_NB_THRESHOLD);
|
||||||
SetEXTANBRun(RXA_CHAN, Ord(FNBMode = NB_MODE_1));
|
SetEXTANBRun(FRXChan, Ord(FNBMode = NB_MODE_1));
|
||||||
|
|
||||||
SetEXTNOBMode(RXA_CHAN, FILTER_NB2_MODE);
|
SetEXTNOBMode(FRXChan, FILTER_NB2_MODE);
|
||||||
SetEXTNOBTau(RXA_CHAN, FILTER_NB_TAU);
|
SetEXTNOBTau(FRXChan, FILTER_NB_TAU);
|
||||||
SetEXTNOBHangtime(RXA_CHAN, FILTER_NB_HANGTIME);
|
SetEXTNOBHangtime(FRXChan, FILTER_NB_HANGTIME);
|
||||||
SetEXTNOBAdvtime(RXA_CHAN, FILTER_NB_ADVTIME);
|
SetEXTNOBAdvtime(FRXChan, FILTER_NB_ADVTIME);
|
||||||
SetEXTNOBThreshold(RXA_CHAN, FILTER_NB_THRESHOLD);
|
SetEXTNOBThreshold(FRXChan, FILTER_NB_THRESHOLD);
|
||||||
SetEXTNOBRun(RXA_CHAN, Ord(FNBMode = NB_MODE_2));
|
SetEXTNOBRun(FRXChan, Ord(FNBMode = NB_MODE_2));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.ApplySNBState;
|
procedure TWDSPEngine.ApplySNBState;
|
||||||
begin
|
begin
|
||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
SetRXASNBARun(RXA_CHAN, Ord(FSNBEnabled));
|
SetRXASNBARun(FRXChan, Ord(FSNBEnabled));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.ApplyANFState;
|
procedure TWDSPEngine.ApplyANFState;
|
||||||
begin
|
begin
|
||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
SetRXAANFPosition(RXA_CHAN, FILTER_NR_AGC_POSITION);
|
SetRXAANFPosition(FRXChan, FILTER_NR_AGC_POSITION);
|
||||||
SetRXAANFRun(RXA_CHAN, Ord(FANFEnabled));
|
SetRXAANFRun(FRXChan, Ord(FANFEnabled));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.ApplyNoiseFilterState;
|
procedure TWDSPEngine.ApplyNoiseFilterState;
|
||||||
@@ -1535,7 +1563,7 @@ end;
|
|||||||
procedure TWDSPEngine.SetRXFMDeviation(Deviation: Double);
|
procedure TWDSPEngine.SetRXFMDeviation(Deviation: Double);
|
||||||
begin
|
begin
|
||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
SetRXAFMDeviation(RXA_CHAN, Deviation);
|
SetRXAFMDeviation(FRXChan, Deviation);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.SetFMSquelch(Enable: Boolean; Level: Integer);
|
procedure TWDSPEngine.SetFMSquelch(Enable: Boolean; Level: Integer);
|
||||||
@@ -1545,25 +1573,25 @@ begin
|
|||||||
if Enable then
|
if Enable then
|
||||||
begin
|
begin
|
||||||
Threshold := Level / 200.0; // 0..100 → 0.0..0.5
|
Threshold := Level / 200.0; // 0..100 → 0.0..0.5
|
||||||
SetRXAFMSQThreshold(RXA_CHAN, Threshold);
|
SetRXAFMSQThreshold(FRXChan, Threshold);
|
||||||
SetRXAFMSQRun(RXA_CHAN, 1);
|
SetRXAFMSQRun(FRXChan, 1);
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
SetRXAFMSQRun(RXA_CHAN, 0);
|
SetRXAFMSQRun(FRXChan, 0);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.SetVolume(Vol: Double);
|
procedure TWDSPEngine.SetVolume(Vol: Double);
|
||||||
begin
|
begin
|
||||||
FVolume := Max(0.0, Min(1.0, Vol));
|
FVolume := Max(0.0, Min(1.0, Vol));
|
||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
SetRXAPanelGain1(RXA_CHAN, FVolume);
|
SetRXAPanelGain1(FRXChan, FVolume);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.SetMute(Mute: Boolean);
|
procedure TWDSPEngine.SetMute(Mute: Boolean);
|
||||||
begin
|
begin
|
||||||
FMuted := Mute;
|
FMuted := Mute;
|
||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
SetRXAPanelRun(RXA_CHAN, Ord(not Mute));
|
SetRXAPanelRun(FRXChan, Ord(not Mute));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -1572,43 +1600,53 @@ end;
|
|||||||
|
|
||||||
procedure TWDSPEngine.SetTXMode(Mode: Integer);
|
procedure TWDSPEngine.SetTXMode(Mode: Integer);
|
||||||
begin
|
begin
|
||||||
|
if not FTXEnabled then Exit;
|
||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
SetTXAMode(TXA_CHAN, ModeToWDSP(Mode));
|
SetTXAMode(FTXChan, ModeToWDSP(Mode));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.SetTXFilter(Low, High: Integer);
|
procedure TWDSPEngine.SetTXFilter(Low, High: Integer);
|
||||||
begin
|
begin
|
||||||
|
if not FTXEnabled then Exit;
|
||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
SetTXABandpassFreqs(TXA_CHAN, Low, High);
|
SetTXABandpassFreqs(FTXChan, Low, High);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.SetDriveLevel(Level: Double);
|
procedure TWDSPEngine.SetDriveLevel(Level: Double);
|
||||||
begin
|
begin
|
||||||
|
if not FTXEnabled then Exit;
|
||||||
if not FInitialized 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;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.SetMicGain(GainDB: Double);
|
procedure TWDSPEngine.SetMicGain(GainDB: Double);
|
||||||
begin
|
begin
|
||||||
FTXMicGainDB := GainDB;
|
FTXMicGainDB := GainDB;
|
||||||
|
if not FTXEnabled then Exit;
|
||||||
if not FInitialized 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;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.SetTXRun(Run: Boolean);
|
procedure TWDSPEngine.SetTXRun(Run: Boolean);
|
||||||
begin
|
begin
|
||||||
|
if not FTXEnabled then
|
||||||
|
begin
|
||||||
|
FTXActive := False;
|
||||||
|
FActiveDisplayID := FRXDispID;
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
FTXActive := Run;
|
FTXActive := Run;
|
||||||
FDispPos := 0;
|
FDispPos := 0;
|
||||||
FTXDispPos := 0;
|
FTXDispPos := 0;
|
||||||
if Run then
|
if Run then
|
||||||
FActiveDisplayID := TX_DISP_ID
|
FActiveDisplayID := FTXDispID
|
||||||
else
|
else
|
||||||
FActiveDisplayID := RX_DISP_ID;
|
FActiveDisplayID := FRXDispID;
|
||||||
|
|
||||||
if Run then
|
if Run then
|
||||||
begin
|
begin
|
||||||
if FInitialized then
|
if FInitialized then
|
||||||
SetChannelState(TXA_CHAN, 1, 0); // run, no delay
|
SetChannelState(FTXChan, 1, 0); // run, no delay
|
||||||
// Сброс mic ring buffer и запуск TX потока
|
// Сброс mic ring buffer и запуск TX потока
|
||||||
FTXMicHead := 0;
|
FTXMicHead := 0;
|
||||||
FTXMicTail := 0;
|
FTXMicTail := 0;
|
||||||
@@ -1619,7 +1657,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end else begin
|
end else begin
|
||||||
if FInitialized then
|
if FInitialized then
|
||||||
SetChannelState(TXA_CHAN, 0, 1); // stop, with slew
|
SetChannelState(FTXChan, 0, 1); // stop, with slew
|
||||||
// Останавливаем TX поток
|
// Останавливаем TX поток
|
||||||
if Assigned(FTXThread) then
|
if Assigned(FTXThread) then
|
||||||
begin
|
begin
|
||||||
@@ -1647,12 +1685,12 @@ begin
|
|||||||
SignedFreq := -Abs(FreqHz)
|
SignedFreq := -Abs(FreqHz)
|
||||||
else
|
else
|
||||||
SignedFreq := Abs(FreqHz);
|
SignedFreq := Abs(FreqHz);
|
||||||
SetTXAPostGenMode(TXA_CHAN, 0); // 0 = tone
|
SetTXAPostGenMode(FTXChan, 0); // 0 = tone
|
||||||
SetTXAPostGenToneFreq(TXA_CHAN, SignedFreq);
|
SetTXAPostGenToneFreq(FTXChan, SignedFreq);
|
||||||
SetTXAPostGenToneMag(TXA_CHAN, Max(0.0, Min(1.0, Mag)));
|
SetTXAPostGenToneMag(FTXChan, Max(0.0, Min(1.0, Mag)));
|
||||||
SetTXAPostGenRun(TXA_CHAN, 1);
|
SetTXAPostGenRun(FTXChan, 1);
|
||||||
end else
|
end else
|
||||||
SetTXAPostGenRun(TXA_CHAN, 0);
|
SetTXAPostGenRun(FTXChan, 0);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.SetDisplaySourceTX(UseTX: Boolean);
|
procedure TWDSPEngine.SetDisplaySourceTX(UseTX: Boolean);
|
||||||
@@ -1664,9 +1702,9 @@ begin
|
|||||||
FDispPos := 0;
|
FDispPos := 0;
|
||||||
FTXDispPos := 0;
|
FTXDispPos := 0;
|
||||||
if UseTX then
|
if UseTX then
|
||||||
FActiveDisplayID := TX_DISP_ID
|
FActiveDisplayID := FTXDispID
|
||||||
else
|
else
|
||||||
FActiveDisplayID := RX_DISP_ID;
|
FActiveDisplayID := FRXDispID;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.ProcessTXBlock;
|
procedure TWDSPEngine.ProcessTXBlock;
|
||||||
@@ -1702,9 +1740,9 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
Err := 0;
|
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 ожидает именно такой
|
// Подаём чанками по DISPLAY_BLOCK_SIZE — analyzer ожидает именно такой
|
||||||
// размер блока (см. SetAnalyzer). Если подавать FTXOut целиком
|
// размер блока (см. SetAnalyzer). Если подавать FTXOut целиком
|
||||||
// (FTXOutBufSize пар), analyzer прочитает только первые DISPLAY_BLOCK_SIZE
|
// (FTXOutBufSize пар), analyzer прочитает только первые DISPLAY_BLOCK_SIZE
|
||||||
@@ -1795,35 +1833,35 @@ begin
|
|||||||
|
|
||||||
// Bandpass
|
// Bandpass
|
||||||
if (FTXFilterLow > 0) and (FTXFilterHigh > FTXFilterLow) then
|
if (FTXFilterLow > 0) and (FTXFilterHigh > FTXFilterLow) then
|
||||||
SetTXABandpassFreqs(TXA_CHAN, FTXFilterLow, FTXFilterHigh);
|
SetTXABandpassFreqs(FTXChan, FTXFilterLow, FTXFilterHigh);
|
||||||
if FTXFilterWindow >= 0 then
|
if FTXFilterWindow >= 0 then
|
||||||
SetTXABandpassWindow(TXA_CHAN, FTXFilterWindow);
|
SetTXABandpassWindow(FTXChan, FTXFilterWindow);
|
||||||
if FTXFilterNC > 0 then
|
if FTXFilterNC > 0 then
|
||||||
TXASetNC(TXA_CHAN, FTXFilterNC);
|
TXASetNC(FTXChan, FTXFilterNC);
|
||||||
if FTXFilterMP >= 0 then
|
if FTXFilterMP >= 0 then
|
||||||
TXASetMP(TXA_CHAN, FTXFilterMP);
|
TXASetMP(FTXChan, FTXFilterMP);
|
||||||
|
|
||||||
// Mic gain (panel gain1)
|
// Mic gain (panel gain1)
|
||||||
SetTXAPanelGain1(TXA_CHAN, Power(10.0, FTXMicGainDB / 20.0));
|
SetTXAPanelGain1(FTXChan, Power(10.0, FTXMicGainDB / 20.0));
|
||||||
|
|
||||||
// Compressor
|
// Compressor
|
||||||
SetTXACompressorRun(TXA_CHAN, Ord(FTXCompressorOn));
|
SetTXACompressorRun(FTXChan, Ord(FTXCompressorOn));
|
||||||
SetTXACompressorGain(TXA_CHAN, FTXCompressorGain);
|
SetTXACompressorGain(FTXChan, FTXCompressorGain);
|
||||||
|
|
||||||
// Leveler
|
// Leveler
|
||||||
SetTXALevelerSt(TXA_CHAN, Ord(FTXLevelerOn));
|
SetTXALevelerSt(FTXChan, Ord(FTXLevelerOn));
|
||||||
SetTXALevelerTop(TXA_CHAN, FTXLevelerTop);
|
SetTXALevelerTop(FTXChan, FTXLevelerTop);
|
||||||
SetTXALevelerDecay(TXA_CHAN, FTXLevelerDecay);
|
SetTXALevelerDecay(FTXChan, FTXLevelerDecay);
|
||||||
|
|
||||||
// ALC
|
// ALC
|
||||||
SetTXAALCSt(TXA_CHAN, Ord(FTXALCOn));
|
SetTXAALCSt(FTXChan, Ord(FTXALCOn));
|
||||||
SetTXAALCMaxGain(TXA_CHAN, FTXALCMaxGain);
|
SetTXAALCMaxGain(FTXChan, FTXALCMaxGain);
|
||||||
SetTXAALCDecay(TXA_CHAN, FTXALCDecay);
|
SetTXAALCDecay(FTXChan, FTXALCDecay);
|
||||||
|
|
||||||
// Phase Rotator
|
// Phase Rotator
|
||||||
SetTXAPHROTRun(TXA_CHAN, Ord(FTXPhaseRotOn));
|
SetTXAPHROTRun(FTXChan, Ord(FTXPhaseRotOn));
|
||||||
SetTXAPHROTNstages(TXA_CHAN, FTXPhaseRotStages);
|
SetTXAPHROTNstages(FTXChan, FTXPhaseRotStages);
|
||||||
SetTXAPHROTCorner(TXA_CHAN, FTXPhaseRotFreq);
|
SetTXAPHROTCorner(FTXChan, FTXPhaseRotFreq);
|
||||||
|
|
||||||
// EQ TX (10-band: [0]=preamp, [1..10]=bands)
|
// EQ TX (10-band: [0]=preamp, [1..10]=bands)
|
||||||
for i := 0 to 10 do
|
for i := 0 to 10 do
|
||||||
@@ -1832,21 +1870,21 @@ begin
|
|||||||
Freqs[i] := FTXEQFreqs[i];
|
Freqs[i] := FTXEQFreqs[i];
|
||||||
Qs[i] := 0.707; // умолчание Q
|
Qs[i] := 0.707; // умолчание Q
|
||||||
end;
|
end;
|
||||||
SetTXAEQProfile(TXA_CHAN, FTXEQNumBands, @Freqs[0], @Gains[0]);
|
SetTXAEQProfile(FTXChan, FTXEQNumBands, @Freqs[0], @Gains[0]);
|
||||||
SetTXAEQRun(TXA_CHAN, Ord(FTXEQOn));
|
SetTXAEQRun(FTXChan, Ord(FTXEQOn));
|
||||||
|
|
||||||
// AM
|
// AM
|
||||||
SetTXAAMCarrierLevel(TXA_CHAN, FTXAMCarrier);
|
SetTXAAMCarrierLevel(FTXChan, FTXAMCarrier);
|
||||||
|
|
||||||
// FM
|
// FM
|
||||||
SetTXAFMDeviation(TXA_CHAN, FTXFMDeviation);
|
SetTXAFMDeviation(FTXChan, FTXFMDeviation);
|
||||||
if (FTXFMLowCut < FTXFMHighCut) then
|
if (FTXFMLowCut < FTXFMHighCut) then
|
||||||
SetTXAFMAFFilter(TXA_CHAN, FTXFMLowCut, FTXFMHighCut);
|
SetTXAFMAFFilter(FTXChan, FTXFMLowCut, FTXFMHighCut);
|
||||||
SetTXAFMEmphPosition(TXA_CHAN, FTXFMEmphPos);
|
SetTXAFMEmphPosition(FTXChan, FTXFMEmphPos);
|
||||||
|
|
||||||
// CTCSS
|
// CTCSS
|
||||||
SetTXACTCSSFreq(TXA_CHAN, FTXCTCSSFreq);
|
SetTXACTCSSFreq(FTXChan, FTXCTCSSFreq);
|
||||||
SetTXACTCSSRun(TXA_CHAN, Ord(FTXCTCSSOn));
|
SetTXACTCSSRun(FTXChan, Ord(FTXCTCSSOn));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.SetTXFilterFull(Low, High, NC, MP, Window: Integer);
|
procedure TWDSPEngine.SetTXFilterFull(Low, High, NC, MP, Window: Integer);
|
||||||
@@ -1859,10 +1897,10 @@ begin
|
|||||||
FFilterLow := Low;
|
FFilterLow := Low;
|
||||||
FFilterHigh := High;
|
FFilterHigh := High;
|
||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
SetTXABandpassFreqs(TXA_CHAN, Low, High);
|
SetTXABandpassFreqs(FTXChan, Low, High);
|
||||||
SetTXABandpassWindow(TXA_CHAN, Window);
|
SetTXABandpassWindow(FTXChan, Window);
|
||||||
if NC > 0 then TXASetNC(TXA_CHAN, NC);
|
if NC > 0 then TXASetNC(FTXChan, NC);
|
||||||
if MP >= 0 then TXASetMP(TXA_CHAN, MP);
|
if MP >= 0 then TXASetMP(FTXChan, MP);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.SetTXCompressor(Enable: Boolean; GainDB: Double);
|
procedure TWDSPEngine.SetTXCompressor(Enable: Boolean; GainDB: Double);
|
||||||
@@ -1870,8 +1908,8 @@ begin
|
|||||||
FTXCompressorOn := Enable;
|
FTXCompressorOn := Enable;
|
||||||
FTXCompressorGain := GainDB;
|
FTXCompressorGain := GainDB;
|
||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
SetTXACompressorGain(TXA_CHAN, GainDB);
|
SetTXACompressorGain(FTXChan, GainDB);
|
||||||
SetTXACompressorRun(TXA_CHAN, Ord(Enable));
|
SetTXACompressorRun(FTXChan, Ord(Enable));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.SetTXLeveler(Enable: Boolean; TopDB: Double; DecayMS: Integer);
|
procedure TWDSPEngine.SetTXLeveler(Enable: Boolean; TopDB: Double; DecayMS: Integer);
|
||||||
@@ -1880,9 +1918,9 @@ begin
|
|||||||
FTXLevelerTop := TopDB;
|
FTXLevelerTop := TopDB;
|
||||||
FTXLevelerDecay := DecayMS;
|
FTXLevelerDecay := DecayMS;
|
||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
SetTXALevelerTop(TXA_CHAN, TopDB);
|
SetTXALevelerTop(FTXChan, TopDB);
|
||||||
SetTXALevelerDecay(TXA_CHAN, DecayMS);
|
SetTXALevelerDecay(FTXChan, DecayMS);
|
||||||
SetTXALevelerSt(TXA_CHAN, Ord(Enable));
|
SetTXALevelerSt(FTXChan, Ord(Enable));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.SetTXALC(Enable: Boolean; MaxGainDB: Double; DecayMS: Integer);
|
procedure TWDSPEngine.SetTXALC(Enable: Boolean; MaxGainDB: Double; DecayMS: Integer);
|
||||||
@@ -1891,9 +1929,9 @@ begin
|
|||||||
FTXALCMaxGain := MaxGainDB;
|
FTXALCMaxGain := MaxGainDB;
|
||||||
FTXALCDecay := DecayMS;
|
FTXALCDecay := DecayMS;
|
||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
SetTXAALCMaxGain(TXA_CHAN, MaxGainDB);
|
SetTXAALCMaxGain(FTXChan, MaxGainDB);
|
||||||
SetTXAALCDecay(TXA_CHAN, DecayMS);
|
SetTXAALCDecay(FTXChan, DecayMS);
|
||||||
SetTXAALCSt(TXA_CHAN, Ord(Enable));
|
SetTXAALCSt(FTXChan, Ord(Enable));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.SetTXPhaseRot(Enable: Boolean; Stages: Integer; FreqHz: Double);
|
procedure TWDSPEngine.SetTXPhaseRot(Enable: Boolean; Stages: Integer; FreqHz: Double);
|
||||||
@@ -1902,9 +1940,9 @@ begin
|
|||||||
FTXPhaseRotStages := Stages;
|
FTXPhaseRotStages := Stages;
|
||||||
FTXPhaseRotFreq := FreqHz;
|
FTXPhaseRotFreq := FreqHz;
|
||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
SetTXAPHROTNstages(TXA_CHAN, Stages);
|
SetTXAPHROTNstages(FTXChan, Stages);
|
||||||
SetTXAPHROTCorner(TXA_CHAN, FreqHz);
|
SetTXAPHROTCorner(FTXChan, FreqHz);
|
||||||
SetTXAPHROTRun(TXA_CHAN, Ord(Enable));
|
SetTXAPHROTRun(FTXChan, Ord(Enable));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.SetTXEQ(Enable: Boolean; NumBands: Integer;
|
procedure TWDSPEngine.SetTXEQ(Enable: Boolean; NumBands: Integer;
|
||||||
@@ -1924,15 +1962,15 @@ begin
|
|||||||
F[i] := Freqs[i];
|
F[i] := Freqs[i];
|
||||||
end;
|
end;
|
||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
SetTXAEQProfile(TXA_CHAN, NumBands, @F[0], @G[0]);
|
SetTXAEQProfile(FTXChan, NumBands, @F[0], @G[0]);
|
||||||
SetTXAEQRun(TXA_CHAN, Ord(Enable));
|
SetTXAEQRun(FTXChan, Ord(Enable));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.SetTXAMCarrierLevel(Level: Double);
|
procedure TWDSPEngine.SetTXAMCarrierLevel(Level: Double);
|
||||||
begin
|
begin
|
||||||
FTXAMCarrier := Level;
|
FTXAMCarrier := Level;
|
||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
WDSP.SetTXAAMCarrierLevel(TXA_CHAN, Level);
|
WDSP.SetTXAAMCarrierLevel(FTXChan, Level);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.SetTXFMParams(Deviation: Double; LowCut, HighCut, EmphPos: Integer);
|
procedure TWDSPEngine.SetTXFMParams(Deviation: Double; LowCut, HighCut, EmphPos: Integer);
|
||||||
@@ -1942,10 +1980,10 @@ begin
|
|||||||
FTXFMHighCut := HighCut;
|
FTXFMHighCut := HighCut;
|
||||||
FTXFMEmphPos := EmphPos;
|
FTXFMEmphPos := EmphPos;
|
||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
SetTXAFMDeviation(TXA_CHAN, Deviation);
|
SetTXAFMDeviation(FTXChan, Deviation);
|
||||||
if LowCut < HighCut then
|
if LowCut < HighCut then
|
||||||
SetTXAFMAFFilter(TXA_CHAN, LowCut, HighCut);
|
SetTXAFMAFFilter(FTXChan, LowCut, HighCut);
|
||||||
SetTXAFMEmphPosition(TXA_CHAN, EmphPos);
|
SetTXAFMEmphPosition(FTXChan, EmphPos);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.SetTXCTCSS(Enable: Boolean; FreqHz: Double);
|
procedure TWDSPEngine.SetTXCTCSS(Enable: Boolean; FreqHz: Double);
|
||||||
@@ -1953,8 +1991,8 @@ begin
|
|||||||
FTXCTCSSOn := Enable;
|
FTXCTCSSOn := Enable;
|
||||||
FTXCTCSSFreq := FreqHz;
|
FTXCTCSSFreq := FreqHz;
|
||||||
if not FInitialized then Exit;
|
if not FInitialized then Exit;
|
||||||
SetTXACTCSSFreq(TXA_CHAN, FreqHz);
|
SetTXACTCSSFreq(FTXChan, FreqHz);
|
||||||
SetTXACTCSSRun(TXA_CHAN, Ord(Enable));
|
SetTXACTCSSRun(FTXChan, Ord(Enable));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TWDSPEngine.TXMicRingAvail: Integer;
|
function TWDSPEngine.TXMicRingAvail: Integer;
|
||||||
@@ -2016,7 +2054,7 @@ var
|
|||||||
begin
|
begin
|
||||||
if not FInitialized or not FAnalyzerOpen then Exit;
|
if not FInitialized or not FAnalyzerOpen then Exit;
|
||||||
N := EnsureRange(FDisplayPixelCount, 1, SPECTRUM_PIXELS);
|
N := EnsureRange(FDisplayPixelCount, 1, SPECTRUM_PIXELS);
|
||||||
DispID := FActiveDisplayID; // RX_DISP_ID или TX_DISP_ID, зависит от FTXActive
|
DispID := FActiveDisplayID; // FRXDispID или FTXDispID, зависит от FTXActive
|
||||||
|
|
||||||
Flag := 0;
|
Flag := 0;
|
||||||
GetPixels(DispID, 0, @PixBuf[0], @Flag);
|
GetPixels(DispID, 0, @PixBuf[0], @Flag);
|
||||||
@@ -2176,11 +2214,11 @@ begin
|
|||||||
FSpecAvgTimeMS := AvgTimeMS;
|
FSpecAvgTimeMS := AvgTimeMS;
|
||||||
if not FAnalyzerOpen then Exit;
|
if not FAnalyzerOpen then Exit;
|
||||||
AverageTimeToParams(FSpecAvgMode, FSpecAvgTimeMS, AvgCount, Backmult);
|
AverageTimeToParams(FSpecAvgMode, FSpecAvgTimeMS, AvgCount, Backmult);
|
||||||
SetDisplayDetectorMode(RX_DISP_ID, 0, FSpecDetector);
|
SetDisplayDetectorMode(FRXDispID, 0, FSpecDetector);
|
||||||
SetDisplayAverageMode(RX_DISP_ID, 0, FSpecAvgMode);
|
SetDisplayAverageMode(FRXDispID, 0, FSpecAvgMode);
|
||||||
SetDisplayNumAverage(RX_DISP_ID, 0, AvgCount);
|
SetDisplayNumAverage(FRXDispID, 0, AvgCount);
|
||||||
SetDisplayAvBackmult(RX_DISP_ID, 0, Backmult);
|
SetDisplayAvBackmult(FRXDispID, 0, Backmult);
|
||||||
SetDisplayNormOneHz(RX_DISP_ID, 0, UsePanNormOneHz(FSpecDetector));
|
SetDisplayNormOneHz(FRXDispID, 0, UsePanNormOneHz(FSpecDetector));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.SetWaterfallDisplay(Detector, AvgMode: Integer;
|
procedure TWDSPEngine.SetWaterfallDisplay(Detector, AvgMode: Integer;
|
||||||
@@ -2200,11 +2238,11 @@ begin
|
|||||||
FWfAvgTimeMS := AvgTimeMS;
|
FWfAvgTimeMS := AvgTimeMS;
|
||||||
if not FAnalyzerOpen then Exit;
|
if not FAnalyzerOpen then Exit;
|
||||||
AverageTimeToParams(FWfAvgMode, FWfAvgTimeMS, AvgCount, Backmult);
|
AverageTimeToParams(FWfAvgMode, FWfAvgTimeMS, AvgCount, Backmult);
|
||||||
SetDisplayDetectorMode(RX_DISP_ID, 1, FWfDetector);
|
SetDisplayDetectorMode(FRXDispID, 1, FWfDetector);
|
||||||
SetDisplayAverageMode(RX_DISP_ID, 1, FWfAvgMode);
|
SetDisplayAverageMode(FRXDispID, 1, FWfAvgMode);
|
||||||
SetDisplayNumAverage(RX_DISP_ID, 1, AvgCount);
|
SetDisplayNumAverage(FRXDispID, 1, AvgCount);
|
||||||
SetDisplayAvBackmult(RX_DISP_ID, 1, Backmult);
|
SetDisplayAvBackmult(FRXDispID, 1, Backmult);
|
||||||
SetDisplayNormOneHz(RX_DISP_ID, 1, 0);
|
SetDisplayNormOneHz(FRXDispID, 1, 0);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|||||||
Reference in New Issue
Block a user