add Alex setup

This commit is contained in:
2026-05-14 18:52:50 +03:00
parent ec596bb0c8
commit aea9f02df8
4 changed files with 559 additions and 52 deletions
+104 -40
View File
@@ -19,7 +19,7 @@ uses
{$ELSE}
Sockets, BaseUnix,
{$ENDIF}
HPSDRProtocol, SyncObjs;
HPSDRProtocol, SyncObjs, Settings;
const
DUC_TX_QUEUE_SIZE = 256; // power of two, bounded latency on TX underrun/overrun
@@ -141,7 +141,8 @@ type
FIsTransmitting: Boolean;
FPAEnabled: Boolean;
FAlexEnabled: Boolean;
FStepAtten: Byte; // ADC0 step attenuator 0-31 dB
FAlexConfig: TAlexSettings; // per-band antenna + routing config
FStepAtten: Byte; // ADC0 step attenuator 0-31 dB
FSendLock: TCriticalSection; // защита concurrent UDP sends
@@ -192,6 +193,7 @@ type
procedure UpdateState(RXFreqHz, TXFreqHz: Double; DriveLevel: Byte;
Transmitting, PAEnabled, AlexEnabled: Boolean);
procedure SetStepAtten(dB: Byte);
procedure SetAlexConfig(const A: TAlexSettings);
procedure SendFullHP;
procedure SendDDCAudio(const LeftRight: array of SmallInt);
procedure SendDUCIQ(const IData, QData: array of Integer);
@@ -611,6 +613,7 @@ begin
FIsTransmitting := False;
FPAEnabled := True;
FAlexEnabled := True;
TSettingsManager.DefaultAlex(FAlexConfig);
FSendLock := TCriticalSection.Create;
FDUCIQLock := TCriticalSection.Create;
FDUCIQSem := RTLEventCreate;
@@ -1071,65 +1074,126 @@ end;
// Transmitting — режим передачи
// IsOrion2 — ANAN-7000/8000 (другие BPF)
// ---------------------------------------------------------------------------
// Преобразует частоту в индекс диапазона 0=160m..10=6m (Thetis-compatible).
function FreqToBandIndex(FreqHz: Double): Integer;
begin
if FreqHz >= 39850000 then Result := 10 // 6m
else if FreqHz >= 26465000 then Result := 9 // 10m
else if FreqHz >= 23170000 then Result := 8 // 12m
else if FreqHz >= 19584000 then Result := 7 // 15m
else if FreqHz >= 16209000 then Result := 6 // 17m
else if FreqHz >= 12075000 then Result := 5 // 20m
else if FreqHz >= 8700000 then Result := 4 // 30m
else if FreqHz >= 6202000 then Result := 3 // 40m
else if FreqHz >= 4665000 then Result := 2 // 60m
else if FreqHz >= 2750000 then Result := 1 // 80m
else Result := 0; // 160m
end;
// Строит 32-битное слово Alex0 для HP-пакета (байты 1432-1435).
// Протокол: openHPSDR Ethernet Protocol v4.3, Appendix D.
// Все биты active-high. Bit 27 = T/R relay (0=RX, 1=TX).
// Биты 24-26: ANT1/ANT2/ANT3. Биты 20-23,29-31: LPF. Биты 1-12: HPF/BPF.
// Биты 8-11: вторичный RX вход (XVTR/Ext1/Ext2/Bypass relay).
function CalcAlex0(RXFreqHz, TXFreqHz: Double;
Transmitting, IsOrion2: Boolean): LongWord;
Transmitting, IsOrion2: Boolean;
const Alex: TAlexSettings): LongWord;
var
txf: Double;
txf: Double;
BandIdx: Integer;
AntVal: Byte;
begin
Result := 0;
// TX relay при передаче
// Bit 27 ($08000000) = T/R relay для всех плат
// Bit 18 ($00040000) = TxRx Status для Orion MkII / Saturn / G2
// Bit 27 = T/R relay (0=RX, 1=TX).
// Bit 18 = TxRx Status для Orion MkII 5.2 / 7000DLE / Saturn / G2.
if Transmitting then
begin
Result := Result or $08000000; // ALEX_TX_RELAY bit27
Result := Result or $08000000; // bit 27: T/R relay
if IsOrion2 then
Result := Result or $00040000; // TxRx Status bit18 (ANAN-7/8000, Saturn)
Result := Result or $00040000; // bit 18: TxRx Status
end;
// RX HPF (для ANAN-100/200) или BPF (для ANAN-7000)
// HPF (ANAN-100/200) или BPF (ANAN-7000/8000/Saturn/G2) — по RX-частоте.
if IsOrion2 then
begin
// Band-pass filters ANAN-7000/8000
if RXFreqHz < 1500000 then Result := Result or $00001000 // BYPASS_BPF
else if RXFreqHz < 2100000 then Result := Result or $00000040 // 160 BPF
else if RXFreqHz < 5500000 then Result := Result or $00000020 // 80/60 BPF
else if RXFreqHz < 11000000 then Result := Result or $00000010 // 40/30 BPF
else if RXFreqHz < 22000000 then Result := Result or $00000002 // 20/15 BPF
else if RXFreqHz < 35600000 then Result := Result or $00000004 // 12/10 BPF
else Result := Result or $00000008; // 6m+preamp
// Band-pass filters — Orion MkII 5.2, ANAN-7000DLE, Saturn, ANAN-G2
if RXFreqHz < 1500000 then Result := Result or $00001000 // bit 12: HF Bypass
else if RXFreqHz < 2100000 then Result := Result or $00000040 // bit 6: 160m BPF
else if RXFreqHz < 5500000 then Result := Result or $00000020 // bit 5: 80/60m BPF
else if RXFreqHz < 11000000 then Result := Result or $00000010 // bit 4: 40/30m BPF
else if RXFreqHz < 22000000 then Result := Result or $00000002 // bit 1: 20/15m BPF
else if RXFreqHz < 35600000 then Result := Result or $00000004 // bit 2: 12/10m BPF
else Result := Result or $00000008; // bit 3: 6m + preamp
end
else
begin
// High-pass filters ANAN-100/200
if RXFreqHz < 1800000 then Result := Result or $00001000 // BYPASS_HPF
else if RXFreqHz < 6500000 then Result := Result or $00000040 // 1.5 MHz HPF
else if RXFreqHz < 9500000 then Result := Result or $00000020 // 6.5 MHz HPF
else if RXFreqHz < 13000000 then Result := Result or $00000010 // 9.5 MHz HPF
else if RXFreqHz < 20000000 then Result := Result or $00000002 // 13 MHz HPF
else if RXFreqHz < 50000000 then Result := Result or $00000004 // 20 MHz HPF
else Result := Result or $00000008; // 6m preamp
// High-pass filters — Atlas, Hermes, ANAN-10/10E/100/100B/100D/200D
if RXFreqHz < 1800000 then Result := Result or $00001000 // bit 12: HF Bypass
else if RXFreqHz < 6500000 then Result := Result or $00000040 // bit 6: 1.5 MHz HPF
else if RXFreqHz < 9500000 then Result := Result or $00000020 // bit 5: 6.5 MHz HPF
else if RXFreqHz < 13000000 then Result := Result or $00000010 // bit 4: 9.5 MHz HPF
else if RXFreqHz < 20000000 then Result := Result or $00000002 // bit 1: 13 MHz HPF
else if RXFreqHz < 50000000 then Result := Result or $00000004 // bit 2: 20 MHz HPF
else Result := Result or $00000008; // bit 3: 6m preamp
end;
// TX LPF — при RX через Ant1/2/3 сигнал идёт через TX LPF тоже
// (для pre-Orion2 без внешней антенны)
// TX LPF — по TX-частоте. В RX-режиме для не-Orion2 плат RX-сигнал идёт
// через TX LPF (общий сигнальный путь), поэтому используем RX-частоту.
if not Transmitting and not IsOrion2 then
txf := RXFreqHz // RX через Ant1: используем RX частоту для LPF
txf := RXFreqHz
else
txf := TXFreqHz;
if txf > 35600000 then Result := Result or $20000000 // 6m bypass LPF
else if txf > 24000000 then Result := Result or $40000000 // 12/10m LPF
else if txf > 16500000 then Result := Result or $80000000 // 17/15m LPF
else if txf > 8000000 then Result := Result or $00100000 // 30/20m LPF
else if txf > 5000000 then Result := Result or $00200000 // 60/40m LPF
else if txf > 2500000 then Result := Result or $00400000 // 80m LPF
else Result := Result or $00800000; // 160m LPF
if txf > 35600000 then Result := Result or $20000000 // bit 29: 6m bypass LPF
else if txf > 24000000 then Result := Result or $40000000 // bit 30: 12/10m LPF
else if txf > 16500000 then Result := Result or $80000000 // bit 31: 17/15m LPF
else if txf > 8000000 then Result := Result or $00100000 // bit 20: 30/20m LPF
else if txf > 5000000 then Result := Result or $00200000 // bit 21: 60/40m LPF
else if txf > 2500000 then Result := Result or $00400000 // bit 22: 80m LPF
else Result := Result or $00800000; // bit 23: 160m LPF
// TX antenna — ANT1 по умолчанию
if not Transmitting then
Result := Result or $01000000; // ALEX_TX_ANTENNA_1
// Биты 24-26: ANT 1/2/3. Выбор зависит от диапазона и режима TX/RX.
// Дефолт ANT1 — безопасен при любом состоянии.
BandIdx := FreqToBandIndex(RXFreqHz);
if Transmitting then
AntVal := Alex.TxAnt[BandIdx]
else
AntVal := Alex.RxAnt[BandIdx];
if AntVal < 1 then AntVal := 1;
case AntVal of
2: Result := Result or $02000000; // bit 25: ANT 2
3: Result := Result or $04000000; // bit 26: ANT 3
else Result := Result or $01000000; // bit 24: ANT 1 (дефолт)
end;
// Биты 8-11: вторичный RX вход (Bypass relay, Ext1, Ext2, XvtrDDC).
// В режиме TX управляется глобальными флагами; в RX — per-band конфигом.
if Transmitting then
begin
if Alex.RxBypassOnTx then
Result := Result or $00000800; // bit 11: Bypass relay
if Alex.Ext1OnTx then
Result := Result or $00000200 // bit 9: Ext1
or $00000800; // bit 11: Bypass relay
end
else
begin
case Alex.RxOnly[BandIdx] of
1: Result := Result or $00000200 // bit 9: Ext1
or $00000800; // bit 11: Bypass relay
2: Result := Result or $00000400 // bit 10: Ext2
or $00000800; // bit 11: Bypass relay
3: Result := Result or $00000100 // bit 8: XVTR DDC In
or $00000800; // bit 11: Bypass relay
end;
end;
end;
procedure THPSDRNetwork.SetAlexConfig(const A: TAlexSettings);
begin
FAlexConfig := A;
if FConnected then SendFullHP;
end;
procedure THPSDRNetwork.ConfigureDDCs(NumDDCs: Byte; SampleRate: Word;
@@ -1274,7 +1338,7 @@ begin
if FAlexEnabled then
begin
Alex0 := CalcAlex0(FCurrentRXFreq, FCurrentTXFreq,
FIsTransmitting, IsOrion2);
FIsTransmitting, IsOrion2, FAlexConfig);
Buf[1432] := (Alex0 shr 24) and $FF;
Buf[1433] := (Alex0 shr 16) and $FF;
Buf[1434] := (Alex0 shr 8) and $FF;