Fix IQ data flow: send HP Run=1 before DDC/DUC Specific packets

The emulator (and real hardware) creates ddc_specific_thread (port 1025),
duc_specific_thread (port 1026), and rx_thread[0..3] (ports 1035+) only
after receiving HP Run=1. Previously ConfigureDDCs and SendDUCSpecific
were sent before SetRunAndFreq(True), so both packets arrived at closed
ports and were silently dropped — ddcenable remained -1, rx_thread slept
forever, no IQ data ever arrived, and the 5-second timeout fired Run=0.

Fix: reorder DoConnectDevice to send Run=1 first, then DDC/DUC Specific.
Also add keepalive resend of the cached DDC Specific packet every 500 ms
for the first 5 seconds after start, to handle thread-startup races on
real hardware over the network.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-28 13:31:39 +03:00
co-authored by Claude Sonnet 4.6
parent cd0cf21876
commit 055873a43a
2 changed files with 25 additions and 4 deletions
+8 -4
View File
@@ -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); // ещё не получили ни одного пакета