mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 18:43:51 +00:00
Phase 5 (batch 24): move OnDDCIQ + seq telemetry into the controller
The DDC IQ receive handler (sequence-error tracking + feeding the active DDC into WDSP) moves verbatim into TRadioController.OnDDCIQ, along with the 12 RX/seq telemetry fields it owns (FRXPacketCount, FRXStartTime, FRXLastPktTime, FActiveDDC, FLastDDCSeq, FLastDDCIndex, FDDCLastSeq, FDDCSeqValid, FSeqErrorCount, FLastSeqErrorDDC, FLastSeqErrorDelta, FSeqOkStreak). FNetwork.OnDDCIQ is wired to the controller method; all MainForm readers (meter timer RX-running/stall detection, status-bar SEQ text, web seq text) and the START/STOP/connect resets now go through FController. Behaviour unchanged; backend-agnostic (a future Pluto backend synthesises the same TDDCIQPacket). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
3d2d76452c
commit
239ff54942
@@ -200,6 +200,20 @@ type
|
||||
FLastSMeter, FLastFwdW, FLastSWR, FLastSupplyV, FLastSupplyA: Double;
|
||||
FLastPLLLock: Boolean;
|
||||
|
||||
// ---- RX/seq телеметрия data-path (пишется из сетевого колбэка OnDDCIQ) ----
|
||||
FRXPacketCount: LongWord; // счётчик принятых IQ пакетов
|
||||
FRXStartTime: QWord; // GetTickCount64 момента START
|
||||
FRXLastPktTime: QWord; // GetTickCount64 последнего принятого пакета
|
||||
FActiveDDC: Integer; // DDC index для текущей платы (0 или 2)
|
||||
FLastDDCSeq: LongWord; // последний seq (из сетевого потока)
|
||||
FLastDDCIndex: Integer; // последний DDC index
|
||||
FDDCLastSeq: array[0..6] of LongWord;
|
||||
FDDCSeqValid: array[0..6] of Boolean;
|
||||
FSeqErrorCount: LongWord;
|
||||
FLastSeqErrorDDC: Integer;
|
||||
FLastSeqErrorDelta: Int64;
|
||||
FSeqOkStreak: Integer;
|
||||
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
|
||||
@@ -215,6 +229,7 @@ type
|
||||
// вызывающим (GUI или демон) после CreateEngines.
|
||||
procedure OnMicPacket(const Data: TMicDataPacket);
|
||||
function PullSoundCardMic(MaxN: Integer): Integer;
|
||||
procedure OnDDCIQ(DDCIndex: Integer; const Data: TDDCIQPacket);
|
||||
|
||||
// Маршалинг команды в поток контроллера (GUI: TThread.Synchronize).
|
||||
procedure Invoke(M: TThreadMethod);
|
||||
@@ -424,6 +439,66 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TRadioController.OnDDCIQ(DDCIndex: Integer; const Data: TDDCIQPacket);
|
||||
// Сетевой поток: трекинг seq + подача IQ активного DDC в WDSP. UI не трогаем —
|
||||
// статус рисует таймер по полям ниже. Backend-агностичен (Pluto синтезирует
|
||||
// тот же TDDCIQPacket).
|
||||
var
|
||||
SamplesPerFrame: Integer;
|
||||
Seq, ExpectedSeq: LongWord;
|
||||
Delta: Int64;
|
||||
begin
|
||||
Inc(FRXPacketCount);
|
||||
FRXLastPktTime := GetTickCount64;
|
||||
Seq := (LongWord(Data.Seq[0]) shl 24) or (LongWord(Data.Seq[1]) shl 16)
|
||||
or (LongWord(Data.Seq[2]) shl 8) or LongWord(Data.Seq[3]);
|
||||
|
||||
if (DDCIndex >= Low(FDDCLastSeq)) and (DDCIndex <= High(FDDCLastSeq)) then
|
||||
begin
|
||||
if Seq <> 0 then
|
||||
begin
|
||||
ExpectedSeq := FDDCLastSeq[DDCIndex] + 1;
|
||||
if FDDCSeqValid[DDCIndex] and (Seq <> ExpectedSeq) then
|
||||
begin
|
||||
Inc(FSeqErrorCount);
|
||||
FLastSeqErrorDDC := DDCIndex;
|
||||
Delta := Int64(Seq) - Int64(ExpectedSeq);
|
||||
FLastSeqErrorDelta := Delta;
|
||||
FSeqOkStreak := 0;
|
||||
end
|
||||
else if FDDCSeqValid[DDCIndex] then
|
||||
begin
|
||||
if FSeqErrorCount > 0 then
|
||||
begin
|
||||
Inc(FSeqOkStreak);
|
||||
if FSeqOkStreak >= 20 then
|
||||
begin
|
||||
FSeqErrorCount := 0;
|
||||
FLastSeqErrorDDC := -1;
|
||||
FLastSeqErrorDelta := 0;
|
||||
FSeqOkStreak := 0;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
FDDCLastSeq[DDCIndex] := Seq;
|
||||
FDDCSeqValid[DDCIndex] := True;
|
||||
end;
|
||||
|
||||
// Подаём IQ в DSP — только с активного DDC
|
||||
if (DDCIndex = FActiveDDC) and FWDSPReady then
|
||||
begin
|
||||
SamplesPerFrame := (Integer(Data.SamplesPerFrame[0]) shl 8) or
|
||||
Integer(Data.SamplesPerFrame[1]);
|
||||
if SamplesPerFrame <= 0 then SamplesPerFrame := 238; // fallback
|
||||
FDSPEngine.PushDDCPacket(Data.IQData, 0, SamplesPerFrame);
|
||||
end;
|
||||
|
||||
// Запоминаем последний seq — статус обновит таймер (без Synchronize в hot path)
|
||||
FLastDDCSeq := Seq;
|
||||
FLastDDCIndex := DDCIndex;
|
||||
end;
|
||||
|
||||
procedure TRadioController.OnMicPacket(const Data: TMicDataPacket);
|
||||
// HW mic-стрим уходит в WDSP только если выбран источник Radio; иначе сэмплы
|
||||
// игнорируются (mic берётся со звуковой карты).
|
||||
|
||||
Reference in New Issue
Block a user