mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
fix: Pluto TX buffer scaled by sample-rate (SoapyPlutoSDR model)
Fixed 4096-pair TX buffer was too small for full-duplex above ~1 Msps
("not enough ... samples getting dropped" per SoapyPlutoSDR), causing
clicks/dropouts. Now sized as round(rate/60) rounded up to a power of 2,
clamped [4096..65536] (576k→16384, 1536k→32768). FIFO cushion (~4 buffers)
resizes to match in StartTX.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+30
-4
@@ -68,6 +68,7 @@ type
|
||||
FTxThread: TThread;
|
||||
FTxStreaming: Boolean;
|
||||
FTxRatio: Integer; // FSampleRate div 192000 (целочисленный апсемпл)
|
||||
FTxBufPairs: Integer; // размер TX-буфера в IQ-парах (по sample-rate, см. TxBufPairsForRate)
|
||||
FTxPrevI: LongInt; // последний 24-бит сэмпл (линейная интерполяция между вызовами)
|
||||
FTxPrevQ: LongInt;
|
||||
// FIFO int16-пар @ device-rate (кольцо): продюсер — SendDUCIQ, консьюмер — push-поток.
|
||||
@@ -140,7 +141,11 @@ const
|
||||
RX_BUF_SAMPLES = 8192; // IQ-пар за один refill (~5.3 мс @ 1.536 MS/s)
|
||||
PAIRS_PER_PKT = 238; // как DDC IQ HPSDR (238*6 = 1428 байт IQData)
|
||||
TX_SRC_RATE = 192000; // фиксированный TX-рейт WDSP (TX_SAMPLE_RATE)
|
||||
TX_BUF_PAIRS = 4096; // IQ-пар в одном TX-буфере push (~2.7 мс @ 1.536 MS/s)
|
||||
// Размер TX-буфера масштабируется от sample-rate (как SoapyPlutoSDR):
|
||||
// round(rate/60) → следующая степень 2. Фикс 4096 «недостаточно для full-duplex
|
||||
// выше 1 Msps — сэмплы дропаются» (комментарий драйвера). Минимум — TX_BUF_MIN.
|
||||
TX_BUF_MIN = 4096; // нижняя граница (~7 мс @ 576k)
|
||||
TX_BUF_MAX = 65536; // верхняя граница (защита от гигантских буферов)
|
||||
PLUTO_TX_OFF = -89.75; // макс. аттенюация AD9361 — TX практически выключен
|
||||
|
||||
type
|
||||
@@ -285,6 +290,21 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TxBufPairsForRate(Rate: Integer): Integer;
|
||||
// Размер TX-буфера в IQ-парах под device-rate (как SoapyPlutoSDR): round(rate/60)
|
||||
// округлённое вверх до степени 2, с клампом [TX_BUF_MIN..TX_BUF_MAX].
|
||||
// 576k→16384, 1536k→32768, 3072k→65536.
|
||||
var
|
||||
Target, P: Integer;
|
||||
begin
|
||||
Target := (Rate + 30) div 60; // round(rate/60)
|
||||
P := TX_BUF_MIN;
|
||||
while P < Target do P := P shl 1; // следующая степень 2 ≥ Target
|
||||
if P < TX_BUF_MIN then P := TX_BUF_MIN;
|
||||
if P > TX_BUF_MAX then P := TX_BUF_MAX;
|
||||
Result := P;
|
||||
end;
|
||||
|
||||
function PlutoSyntheticMAC(const S: string): TBytes;
|
||||
var
|
||||
H: QWord;
|
||||
@@ -323,8 +343,10 @@ begin
|
||||
FTxBuf := nil; FTxChI := nil; FTxChQ := nil; FTxThread := nil;
|
||||
FTxStreaming := False; FTxRatio := 8; FTxPrevI := 0; FTxPrevQ := 0;
|
||||
FTxAttDb := PLUTO_TX_OFF; // на старте TX выключен (макс. аттенюация)
|
||||
// FIFO на ~4 TX-буфера запаса под джиттер продюсера/консьюмера.
|
||||
FTxFifoCap := TX_BUF_PAIRS * 2 * 4;
|
||||
// FIFO на ~4 TX-буфера запаса под джиттер продюсера/консьюмера. Окончательный
|
||||
// размер выставляется в StartTX по фактическому device-rate (TxBufPairsForRate).
|
||||
FTxBufPairs := TxBufPairsForRate(FSampleRate);
|
||||
FTxFifoCap := FTxBufPairs * 2 * 4;
|
||||
SetLength(FTxFifo, FTxFifoCap);
|
||||
FTxFifoHead := 0; FTxFifoTail := 0; FTxFifoCount := 0;
|
||||
InitCriticalSection(FTxLock);
|
||||
@@ -645,10 +667,14 @@ begin
|
||||
FTxRatio := FSampleRate div TX_SRC_RATE;
|
||||
if FTxRatio < 1 then FTxRatio := 1;
|
||||
FTxPrevI := 0; FTxPrevQ := 0;
|
||||
// Размер push-буфера под текущий rate + FIFO на ~4 таких буфера запаса.
|
||||
FTxBufPairs := TxBufPairsForRate(FSampleRate);
|
||||
EnterCriticalSection(FTxLock);
|
||||
FTxFifoCap := FTxBufPairs * 2 * 4;
|
||||
if Length(FTxFifo) <> FTxFifoCap then SetLength(FTxFifo, FTxFifoCap);
|
||||
FTxFifoHead := 0; FTxFifoTail := 0; FTxFifoCount := 0;
|
||||
LeaveCriticalSection(FTxLock);
|
||||
FTxBuf := iio_device_create_buffer(FTxDev, TX_BUF_PAIRS, False);
|
||||
FTxBuf := iio_device_create_buffer(FTxDev, FTxBufPairs, False);
|
||||
if FTxBuf = nil then begin FLastError := 'TX create_buffer failed'; Exit; end;
|
||||
ApplyTxAtten; // стартуем с текущей аттенюации (по умолчанию OFF до PTT)
|
||||
FTxStreaming := True;
|
||||
|
||||
Reference in New Issue
Block a user