mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
Phase 5 (batch 26): move OnTXIQ + DUC queue into the controller
The TX IQ handler (batch WDSP TXA output into 240-sample DUC packets, 24-bit clamp, FNetwork.SendDUCIQ) moves into TRadioController.OnTXIQ, along with the FDUCPendingI/Q/Count queue fields. The DUC-queue reset on a TX-state change moves from the rfTransmitting render into SetMOX itself (the render does not run headless). Both DSP-callback wiring sites (FormCreate and RecreateDSPEngine) now point at FController.OnTXIQ. Backend-agnostic: a Pluto backend converts 24-bit->int16 in SendDUCIQ. Pre-existing gap noted: RecreateDSPEngine never re-wires OnPullMicSamples, so sound-card mic is lost after a sample-rate change (unchanged here). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
c1da506f73
commit
3a387e06ce
@@ -215,6 +215,10 @@ type
|
||||
FLastSeqErrorDelta: Int64;
|
||||
FSeqOkStreak: Integer;
|
||||
FADCOverloadActive: Boolean; // ADC overload (рендерится по rfADCOverload)
|
||||
// ---- TX DUC-очередь (накопление IQ от WDSP в пакеты по 240, OnTXIQ) ----
|
||||
FDUCPendingI: array[0..239] of Integer;
|
||||
FDUCPendingQ: array[0..239] of Integer;
|
||||
FDUCPendingCount: Integer;
|
||||
// Pending-значения декода HP-статуса (сетевой поток → ApplyHPStatus через
|
||||
// Invoke; Synchronize блокирующий и последовательный, гонок нет).
|
||||
FHPpFwdW, FHPpSWR, FHPpSupplyV, FHPpSupplyA: Double;
|
||||
@@ -239,6 +243,7 @@ type
|
||||
procedure OnDDCIQ(DDCIndex: Integer; const Data: TDDCIQPacket);
|
||||
procedure OnHPStatus(const Status: THighPriorityStatus);
|
||||
procedure ApplyHPStatus; // маршалится из OnHPStatus (сглаживание/overload/HWPTT)
|
||||
procedure OnTXIQ(const Buf: array of Double; Count: Integer);
|
||||
|
||||
// Маршалинг команды в поток контроллера (GUI: TThread.Synchronize).
|
||||
procedure Invoke(M: TThreadMethod);
|
||||
@@ -508,6 +513,36 @@ begin
|
||||
FLastDDCIndex := DDCIndex;
|
||||
end;
|
||||
|
||||
procedure TRadioController.OnTXIQ(const Buf: array of Double; Count: Integer);
|
||||
// WDSP TXA отдаёт IQ-пары @ TX rate. Копим хвост между вызовами и шлём только
|
||||
// полные DUC-пакеты по 240 (зануление хвоста давало 47 Гц гул). Клампим в
|
||||
// 24-bit, чтобы пики компрессора/EQ (чуть >1.0) не оборачивались через wrap.
|
||||
// Backend-агностично: Pluto-backend в SendDUCIQ переведёт 24-bit→int16.
|
||||
function ScaleIQ24(V: Double): Integer;
|
||||
var S: Double;
|
||||
begin
|
||||
S := V * 8388607.0;
|
||||
if S > 8388607.0 then Result := 8388607
|
||||
else if S < -8388608.0 then Result := -8388608
|
||||
else Result := Round(S);
|
||||
end;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
if not (Assigned(FNetwork) and FNetwork.Connected) then Exit;
|
||||
for i := 0 to Count - 1 do
|
||||
begin
|
||||
FDUCPendingI[FDUCPendingCount] := ScaleIQ24(Buf[i * 2]);
|
||||
FDUCPendingQ[FDUCPendingCount] := ScaleIQ24(Buf[i * 2 + 1]);
|
||||
Inc(FDUCPendingCount);
|
||||
if FDUCPendingCount >= 240 then
|
||||
begin
|
||||
FNetwork.SendDUCIQ(FDUCPendingI, FDUCPendingQ);
|
||||
FDUCPendingCount := 0;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TRadioController.OnHPStatus(const Status: THighPriorityStatus);
|
||||
// Сетевой поток: декод HP-статуса (board-specific supply/power/SWR) → pending →
|
||||
// маршалинг в ApplyHPStatus (сглаживание + overload + HWPTT уже на потоке UI/ядра).
|
||||
@@ -1597,6 +1632,7 @@ begin
|
||||
WasTransmitting := FTransmitting;
|
||||
FTransmitting := On_;
|
||||
if On_ then FDriveLevel := CalcDriveByte;
|
||||
FDUCPendingCount := 0; // сброс TX DUC-очереди на смене TX-состояния
|
||||
// Сетевая PTT-последовательность TX-on: сначала реле (Alex bit27=1, drive) без
|
||||
// PTT, затем PTT=1 — переключаем реле раньше передачи.
|
||||
if FTransmitting and Assigned(FNetwork) and FNetwork.Connected and FNetwork.Running then
|
||||
|
||||
Reference in New Issue
Block a user