mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-26 23:17:34 +00:00
fix(tx): чистый openHPSDR TX-тракт — задержка DUP, всплески TUN, фриз PTT-off
Диагностика временным TXLog (снят) вскрыла цепочку проблем TX-тракта: - Задержка ~200мс своего сигнала в DUP: за время приёма ринг PortAudio- микрофона наполнялся до упора (9600 сэмплов) и на старте TX бёрстом оседал стоячим запасом в DUC-очереди. Фикс: TAudioInput.Flush на RX→TX (заодно убрана передача в эфир аудио, записанного до нажатия PTT). - Всплески на TUN: (1) старт — радио начинало с пустого DUC-FIFO; (2) по ходу — пейсинг со строгой каденцией держал запас FIFO у нуля, джиттер 3-6мс давал underrun; (3) клип: голос из бэклога складывался с PostGen- тоном (стоит после ALC) поверх шкалы, а сам тон при mag=1.0 давал выброс Гиббса x1.18 на старте. Фиксы: pre-roll PrimeDUCIQ (THROTTLE + 3 блока подушки в очереди — sender метрит непрерывно, FIFO радио прижат 2000..2400), анти-старв доливка нулями до REANCHOR при просадке, TUN_TONE_MAG=0.83, мьют mic-входа TXA при активном тоне. - Огрызок TUN-тона в эфир на первом блоке следующего TX: стоп канала dmode=1 ждал фейд, который некому прокрутить (продюсер уже остановлен) — канал стопился по таймауту Sleep(1)x100 с недобранным сигналом в буферах. Это же было и «остаточным фризом ~106мс» GUI на отпускании PTT: чистый таймаут, фейд никогда не исполнялся. Фикс: dmode=0 + синхронный слив/продувка канала 4 нулевыми fexchange0 на стопе и старте (<1мс, штатные down-slew и flush). - Дисплей: ResetPixelBuffers(TX_DISP_ID) на старте TX — усредняющая история TX-анализатора показывала спектр тона прошлой сессии. - StopRunning при активном TUN не чистил DUC-очередь и не сбрасывал FTuning/тон — закрыто. Латентность тракта mic→радио теперь ~43мс (WDSP 11 + подушка 21 + FIFO 10.4). Проверено на эфире: q=0..30, fill/drops/underrun=0, clip=0, клоки радио/ПК без дрейфа (micRx 48000/с). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+36
-2
@@ -672,6 +672,14 @@ type
|
||||
|
||||
implementation
|
||||
|
||||
const
|
||||
// Амплитуда TUN-тона (WDSP PostGen). НЕ 1.0: на резком старте тона фильтры
|
||||
// TXA-тракта дают переходный выброс ~×1.18 (замерено: peak=1.176 при
|
||||
// mag=1.0) поверх полной шкалы → жёсткий кламп 24-бит → сплэттер на старте
|
||||
// TUN. 0.83×1.18≈0.98 — выброс остаётся в шкале. Мощность TUN задаёт drive
|
||||
// (TUNLevel), падение уровня IQ ~1.6дБ компенсируется калибровкой TUNLevel.
|
||||
TUN_TONE_MAG = 0.83;
|
||||
|
||||
constructor TRadioController.Create;
|
||||
begin
|
||||
inherited Create;
|
||||
@@ -2335,7 +2343,7 @@ begin
|
||||
begin
|
||||
FDSPEngine.SetMode(FMode);
|
||||
// Если TUN активен — пересчитываем знак частоты под новый режим
|
||||
if FTuning then FDSPEngine.SetTXTone(True, FTXSettings.TUNFreq, 1.0);
|
||||
if FTuning then FDSPEngine.SetTXTone(True, FTXSettings.TUNFreq, TUN_TONE_MAG);
|
||||
end;
|
||||
ApplyModeFilter;
|
||||
Changed(rfMode);
|
||||
@@ -3071,6 +3079,14 @@ begin
|
||||
FDriveLevel, True, True, True);
|
||||
FNetwork.SendFullHP; // 1й пакет: Alex bit27=1 (T/R relay), drive — без PTT
|
||||
FNetwork.SendPTT(True); // 2й пакет: PTT=1 после переключения реле
|
||||
// Pre-roll: THROTTLE (2000) + ТРИ WDSP-блока (3×2048) нулевых пар. Первая
|
||||
// часть улетает сразу и наполняет DUC-FIFO радио до порога THROTTLE (DAC
|
||||
// не стартует с пустого буфера), остаток ~3 блока (~32мс) ложится ПОДУШКОЙ
|
||||
// в очередь — дальше очередь на приходе каждого WDSP-блока непуста, sender
|
||||
// метрит непрерывно, и опоздание блока не роняет FIFO радио. Замеры: под
|
||||
// нагрузкой DUP и при быстром пере-PTT первый WDSP-блок опаздывает до
|
||||
// 25мс — двух блоков подушки не хватало (щелчок через ~0.5с после старта).
|
||||
FNetwork.PrimeDUCIQ(8144);
|
||||
end;
|
||||
if FWDSPReady and Assigned(FDSPEngine) then
|
||||
begin
|
||||
@@ -3093,6 +3109,14 @@ begin
|
||||
FWebMicActive := False;
|
||||
FDSPEngine.SetTXMicSource(DefaultMicSource);
|
||||
end;
|
||||
// Сброс бэклога sound-card микрофона на RX→TX: пока шёл приём, ринг
|
||||
// PortAudio наполнился до упора (~200мс). Без сброса весь этот «старый»
|
||||
// звук бёрстом уходит в тракт: стоячая задержка ~190мс в DUC-очереди
|
||||
// + в эфир передаётся аудио, записанное ДО нажатия PTT (на TUN оно
|
||||
// складывается с тоном поверх полной шкалы → клип-всплеск).
|
||||
if FTransmitting and (not WasTransmitting) and Assigned(FAudioIn)
|
||||
and FAudioIn.IsOpen then
|
||||
FAudioIn.Flush;
|
||||
// В non-DUP RX-IQ пакеты дропаются на входе DSP-потока во время TX, чтобы
|
||||
// TX leakage не накапливался в RXA pipeline / FFT-истории анализатора.
|
||||
FDSPEngine.KeepRXDuringTX := FDisplayDuplex;
|
||||
@@ -3139,7 +3163,7 @@ begin
|
||||
begin
|
||||
// Тон включаем ДО запуска TX-аудио, чтобы первые сэмплы уже шли с тоном.
|
||||
if FWDSPReady and Assigned(FDSPEngine) then
|
||||
FDSPEngine.SetTXTone(True, FTXSettings.TUNFreq, 1.0);
|
||||
FDSPEngine.SetTXTone(True, FTXSettings.TUNFreq, TUN_TONE_MAG);
|
||||
FTuning := True;
|
||||
FDriveLevel := CalcDriveByte; // CalcDriveByte увидит FTuning=True (TUN-уровень)
|
||||
ApplyWDSPDrive(FTXSettings.TUNLevel);
|
||||
@@ -3370,6 +3394,16 @@ begin
|
||||
FNetwork.SetRunAndFreq(False, XvtrTranslate(FCenterFreq), XvtrTranslate(FCenterFreq), 0);
|
||||
FRunning := False;
|
||||
FTransmitting := False;
|
||||
// Стоп при активном TX/TUN: хвост IQ в DUC-очереди не должен пережить
|
||||
// остановку (иначе при следующем старте уйдёт в эфир старый тон/голос),
|
||||
// а TUN-состояние (PostGen-тон) — вернуться в выключенное.
|
||||
FNetwork.ClearDUCIQQueue;
|
||||
if FTuning then
|
||||
begin
|
||||
FTuning := False;
|
||||
if FWDSPReady then FDSPEngine.SetTXTone(False, 0, 0);
|
||||
Changed(rfTuning); // UI: TUN-кнопка off
|
||||
end;
|
||||
if FWDSPReady then FDSPEngine.SetTXRun(False);
|
||||
Changed(rfTransmitting); // MOX-кнопка off
|
||||
end;
|
||||
|
||||
Reference in New Issue
Block a user