diff --git a/HPSDRNetwork.pas b/HPSDRNetwork.pas index ec5de6a..1197059 100644 --- a/HPSDRNetwork.pas +++ b/HPSDRNetwork.pas @@ -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