diff --git a/HPSDRNetwork.pas b/HPSDRNetwork.pas index 7b5b4de..8fdb454 100644 --- a/HPSDRNetwork.pas +++ b/HPSDRNetwork.pas @@ -121,6 +121,11 @@ type FPortDUCIQ: Word; FDirectIP: string; // для unicast discovery + // Кэш DDC Specific — keepalive повторно шлёт первые 5 сек после старта + FCachedDDCSpec: TDDCSpecificPacket; + FCachedDDCValid: Boolean; + FResendCount: Integer; + // Текущее состояние для построения HP пакетов FCurrentRXFreq: Double; FCurrentTXFreq: Double; @@ -398,6 +403,15 @@ begin if not FNet.FConnected then Continue; // Отправляем полный HP с частотами и ALEX — как piHPSDR FNet.SendFullHP; + // Повторно отправляем DDC Specific первые 5 сек после Run=1 (каждые 500 мс). + // ddc_specific_thread на эмуляторе/железе стартует ПОСЛЕ получения Run=1, + // поэтому первый ConfigureDDCs может прийти раньше чем порт 1025 откроется. + if FNet.FRunning and FNet.FCachedDDCValid then + begin + Inc(FNet.FResendCount); + if (FNet.FResendCount <= 100) and (FNet.FResendCount mod 10 = 2) then + FNet.SendDDCSpecific(FNet.FCachedDDCSpec); + end; end; end; @@ -914,6 +928,9 @@ begin end; SendDDCSpecific(Pkt); + FCachedDDCSpec := Pkt; + FCachedDDCValid := True; + FResendCount := 0; end; procedure THPSDRNetwork.SendDUCSpecific(const Pkt: TDUCSpecificPacket); diff --git a/MainForm.pas b/MainForm.pas index 853543b..e9d3e5f 100644 --- a/MainForm.pas +++ b/MainForm.pas @@ -2827,8 +2827,6 @@ begin else FActiveDDC := 0; - FNetwork.ConfigureDDCs(1, FSampleRate div 1000, 0); - // Синхронизируем samplerate WDSP если нужно if FWDSPReady and (FDSPEngine.SampleRate <> FSampleRate) then begin @@ -2849,7 +2847,7 @@ begin end; FSpecView.AGCTop := FAGCTop; - // DUC specific + // DUC specific packet (строим здесь, отправляем после Run=1) FillChar(DUCPkt, SizeOf(DUCPkt), 0); DUCPkt.NumDACs := 1; DUCPkt.SidetoneLevel := 50; @@ -2860,14 +2858,20 @@ begin DUCPkt.DUC0RateHi := Hi(192); DUCPkt.DUC0RateLo := Lo(192); DUCPkt.DUC0Bits := 24; - FNetwork.SendDUCSpecific(DUCPkt); + // Сначала отправляем Run=1 — эмулятор/железо создают ddc_specific_thread + // (порт 1025) и rx_thread (порт 1035+) только после получения HP Run=1. + // DDC Specific и DUC Specific отправляем ПОСЛЕ, иначе порты ещё не открыты. FNetwork.UpdateState(FCenterFreq, FCenterFreq, FDriveLevel, False, True, True); FNetwork.SetRunAndFreq(True, FCenterFreq, FCenterFreq, FDriveLevel); FRunning := True; FRXStartTime := GetTickCount64; FRXLastPktTime := 0; + // DDC и DUC Specific — теперь потоки эмулятора слушают на своих портах + FNetwork.ConfigureDDCs(1, FSampleRate div 1000, 0); + FNetwork.SendDUCSpecific(DUCPkt); + // Принудительно обновляем AGC линии — гарантированно после всех SetAGC вызовов if FWDSPReady then FDSPEngine.UpdateAGCLines(FSpectrumWidth); // ещё не получили ни одного пакета