mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
fix(hpsdr): TX-антенна тонула в Alex1, OC-пины били через один, SO_EXCLUSIVEADDRUSE
Три дефекта, найденные сверкой с прошивкой (Anvelina_PROIII, board_type=5) и с Thetis. 1. CalcAlex1 жёстко ставил бит 24 (ANT1) с комментарием «ADC1 дефолт». Старшие 16 бит Alex1 — не фильтры ADC1, а TX-СЛОВО Alex: прошивка кладёт байты 1428-1429 в Alex_Tx_data и на PTT подменяет им верхнюю половину Alex-слова целиком (Orion.v:2346, Alex_Tx_data_ok = Alex_Tx_data[10:8] — те же ANT1/2/3). Захардкоженный ANT1 делал условие истинным и затирал антенну, посчитанную в CalcAlex0: оператор с TX на ANT2/ANT3 передавал в ANT1. Thetis делает ровно то, что теперь делаем мы — netInterface.c:489 чистит биты 24-26 и ставит _TXANT_1/2/3 из tx_ant. 2. Байт 1401 (Open Collector) уходил без сдвига. Бит 0 не разведён, пины сидят на битах 1..7 (Orion.v:913, USEROUT0..6 = Open_Collector[1..7]) — та же раскладка, что у C2[7:1] в протоколе 1. Каждый включённый пин срабатывал на соседнем выходе, седьмой не срабатывал никогда. CalcOCBits остаётся в логических координатах (бит i = пин i+1), сдвиг делает SendFullHP на границе с проводом. 3. SO_EXCLUSIVEADDRUSE = not 5 ($FFFFFFFA) вместо ~SO_REUSEADDR = not 4 ($FFFFFFFB) — как и написано в собственном комментарии. Опции с таким номером нет: setsockopt возвращал ошибку (её результат не проверяется), и порт оставался перехватываемым, ровно от чего строка и спасала. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+39
-7
@@ -32,7 +32,12 @@ const
|
||||
SOCK_INVALID = TSocket(INVALID_SOCKET);
|
||||
INADDR_ANY = 0;
|
||||
IPPROTO_UDP = 17;
|
||||
SO_EXCLUSIVEADDRUSE = LongInt(not 5); // = $FFFFFFFB — исключительное владение портом
|
||||
// Winsock: SO_EXCLUSIVEADDRUSE == ~SO_REUSEADDR == ~$0004 == $FFFFFFFB
|
||||
// (то же значение объявляет и сам WinSock2 — держим локально, как соседние
|
||||
// INADDR_ANY/IPPROTO_UDP). Стояло `not 5` = $FFFFFFFA — несуществующая
|
||||
// опция: setsockopt возвращал ошибку (её результат не проверяется), и порт
|
||||
// оставался перехватываемым, ровно от чего эта строка и должна была спасать.
|
||||
SO_EXCLUSIVEADDRUSE = LongInt(not 4); // = -5 = $FFFFFFFB
|
||||
|
||||
type
|
||||
TInetSockAddr = WinSock2.TSockAddrIn;
|
||||
@@ -1486,12 +1491,25 @@ end;
|
||||
// Bit 8 = ALEX1_ANAN7000_RX_GNDonTX: заземляет ADC1-вход во время TX
|
||||
// чтобы предотвратить перегрузку второго приёмника.
|
||||
// Остальные биты — те же LPF/BPF/ANT что и у ALEX0.
|
||||
//
|
||||
// ★СТАРШИЕ 16 БИТ ЭТОГО СЛОВА — НЕ «фильтры ADC1», А TX-СЛОВО ALEX.
|
||||
// Прошивка (Orion.v/High_Priority_CC.v) раскладывает байты так:
|
||||
// 1428-1429 -> Alex_Tx_data[15:0] (TX-фильтры + выбор TX-антенны)
|
||||
// 1430-1431 -> Alex_data[31:16] (RX1-фильтры — это НИЖНИЕ 16 бит Alex1)
|
||||
// и на передаче ПОДМЕНЯЕТ верхнюю половину Alex-слова:
|
||||
// Alex_Tx_data_ok = Alex_Tx_data[10:8] in {001,010,100} // ANT1/2/3
|
||||
// Alex_upper = (FPGA_PTT && Alex_Tx_data_ok) ? Alex_Tx_data : Alex_data[47:32]
|
||||
// Биты 24..26 здесь — те же ANT1/2/3, что и в ALEX0, поэтому захардкоженный
|
||||
// ANT1 делал Alex_Tx_data_ok=1 и на КАЖДОМ PTT затирал антенну, посчитанную
|
||||
// в CalcAlex0: оператор с TX на ANT2/ANT3 передавал в ANT1. Антенну берём
|
||||
// из той же таблицы и по той же частоте, что и CalcAlex0.
|
||||
function CalcAlex1(RXFreqHz, TXFreqHz: Double;
|
||||
Transmitting: Boolean;
|
||||
const Alex: TAlexSettings;
|
||||
XvtrDisablePA: Boolean = False): LongWord;
|
||||
var
|
||||
txf: Double;
|
||||
txf: Double;
|
||||
AntVal: Byte;
|
||||
begin
|
||||
Result := 0;
|
||||
|
||||
@@ -1517,7 +1535,15 @@ begin
|
||||
else if txf > 2500000 then Result := Result or $00400000 // bit 22: 80m LPF
|
||||
else Result := Result or $00800000; // bit 23: 160m LPF
|
||||
|
||||
Result := Result or $01000000; // bit 24: ANT1 (ADC1 дефолт)
|
||||
// Биты 24-26: ANT 1/2/3 TX-слова (см. шапку). Ровно та же величина, что
|
||||
// CalcAlex0 кладёт в TX-ветке, иначе прошивка на PTT её перебьёт.
|
||||
AntVal := Alex.TxAnt[FreqToBandIndex(TXFreqHz)];
|
||||
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;
|
||||
|
||||
// Bit 8: заземление ADC1-входа во время TX (галочка "Ground BPF2 on TX")
|
||||
if Transmitting and Alex.GndBpf2OnTx then
|
||||
@@ -1552,7 +1578,9 @@ begin
|
||||
if FConnected then SendFullHP;
|
||||
end;
|
||||
|
||||
// Строит 8-битное слово OC (byte 1401 HP-пакета, биты 0..6 = пины 1..7).
|
||||
// Строит ЛОГИЧЕСКУЮ маску OC-пинов: бит i = пин i+1 (i = 0..OC_PIN_COUNT-1) —
|
||||
// в тех же координатах, в которых маски лежат в настройках и рисуются в UI.
|
||||
// Сдвиг в проводное представление байта 1401 делает вызывающий (SendFullHP).
|
||||
// Портировано из Thetis (Penny.UpdateExtCtrl/adjustForTXAction), урезано:
|
||||
// без PA-override и split-pins VFO A/B (см. project_oc_control память).
|
||||
// RX: маска банда/слота как есть. TX: маска банда/слота, каждый включённый
|
||||
@@ -1969,10 +1997,14 @@ begin
|
||||
if not FSpeakerAudioEnabled then
|
||||
Buf[1400] := Buf[1400] or $02;
|
||||
|
||||
// OC Control — Open Collector outputs (byte 1401)
|
||||
// OC Control — Open Collector outputs (byte 1401).
|
||||
// ★СДВИГ НА БИТ ОБЯЗАТЕЛЕН. Бит 0 байта 1401 не разведён, пины сидят на
|
||||
// битах 1..7 (Orion.v: USEROUT0..6 = Open_Collector[1..7]) — та же раскладка,
|
||||
// что у C2[7:1] в протоколе 1. Без shl 1 каждый включённый пин срабатывал
|
||||
// на соседнем физическом выходе, а седьмой не срабатывал никогда.
|
||||
if FOCConfig.Enabled then
|
||||
Buf[1401] := CalcOCBits(FCurrentRXFreq, FCurrentTXFreq, FIsTransmitting,
|
||||
FTuning, FTwoTone, FXvtrSlot, FOCConfig);
|
||||
Buf[1401] := Byte(CalcOCBits(FCurrentRXFreq, FCurrentTXFreq, FIsTransmitting,
|
||||
FTuning, FTwoTone, FXvtrSlot, FOCConfig) shl 1);
|
||||
|
||||
// Step attenuators ADC0/ADC1 (bytes 1443/1442)
|
||||
// 0 dB = 0, max 31 dB
|
||||
|
||||
Reference in New Issue
Block a user