mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
fix(tci): передача с слайса — маркер TX_CHRONO под номером клиента, фронт rfTransmitting
Живой прогон с MSHV на втором слайсе (openHPSDR): приём в порядке, эфир по trx:1,true,tci поднимается, а звук от клиента не доходит. Два независимых дефекта, оба видны только на приёмнике > 0 — на rx0 передача работала, потому стенд их и не ловил. 1. Маркеры TX_CHRONO уходили с receiver = 0 жёстко. MSHV шлёт TX-аудио ТОЛЬКО в ответ на маркер и фильтрует все входящие бинарные блоки по номеру приёмника первой же строкой обработчика (network.cpp: `if (pStream->receiver != tci_trx) return;`, ветка TxChrono там же и собирает блок). У клиента на слайсе tci_trx = 1, так что маркеры отбрасывались целиком. Теперь вместе с клиентом-модулятором запоминается номер приёмника из его же TRX (FTxRx), и маркеры идут под ним. 2. Changed(rfTransmitting) из SetTxSlice стирал TCIMicRequested. Контроллер шлёт это поле и просто как «перерисуй TX-бейджи», а адаптер понимал любой такой сигнал при FTransmitting = false как «передача кончилась». Приходил он посередине нашей же команды: SyncSetTRX ставит просьбу → RequestSliceTx → SetTxSlice → Changed → просьба стёрта → SetMOX выбирает микрофон уже без неё. В эфир шёл микрофон оператора (тишина), а TX-аудио клиента отбрасывалось — TCIMicActive не поднят. Теперь ловится фронт «было → стало» (FLastTxOn), а не всякое уведомление. Стенд test/tci: 217 проверок (было 214), все зелёные. Новое — часть E, слайс как приёмник 1: по trx:1,true,tci модуляция из TCI взята, маркеры TX_CHRONO идут и названы номером 1. Негативный контроль разделён: каждая правка краснит свою проверку. Проверено на железе: MSHV на втором слайсе передаёт. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+35
-1
@@ -1566,7 +1566,7 @@ var
|
||||
Op: Byte;
|
||||
Pay: TBytes;
|
||||
H: TTCIStreamHeader;
|
||||
AudioBlocks, IQBlocks, BadHdr: Integer;
|
||||
AudioBlocks, IQBlocks, BadHdr, BadRx: Integer;
|
||||
SliceId: Integer;
|
||||
SV: TSliceView;
|
||||
S: string;
|
||||
@@ -1758,6 +1758,40 @@ begin
|
||||
Inc(n);
|
||||
end;
|
||||
Check('аудио слайса идёт под номером 1', n > 0, IntToStr(n));
|
||||
|
||||
// ── ★TX со слайса: маркер обязан нести НОМЕР ЭТОГО приёмника ─────────
|
||||
// MSHV шлёт TX-аудио только в ответ на маркер TX_CHRONO и отбрасывает
|
||||
// ЛЮБОЙ входящий блок с чужим receiver (network.cpp:231 — `if
|
||||
// (pStream->receiver != tci_trx) return;`, ветка TxChrono — network.cpp:288
|
||||
// и далее). С жёстким нулём в заголовке клиент, сидящий на втором слайсе
|
||||
// (tci_trx = 1), поднимал эфир и молчал: маркеры до него не доходили, а
|
||||
// без них он не отправляет ни одного блока. Ровно это и наблюдалось на
|
||||
// живом железе с MSHV.
|
||||
Ctrl.FWDSPReady := True;
|
||||
Ctrl.SetSliceSlotAutoTx(Ctrl.SliceSlotOf(SliceId), True);
|
||||
C.SendText('trx:1,true,tci;');
|
||||
C.WaitText('trx:', 1500);
|
||||
Check('TX слайса: модуляция из TCI взята', Ctrl.TCIMicActive);
|
||||
C.Pump(400);
|
||||
n := 0;
|
||||
BadRx := 0;
|
||||
while C.NextFrame(Op, Pay) do
|
||||
if (Op = $02) and (Length(Pay) >= SizeOf(H)) then
|
||||
begin
|
||||
Move(Pay[0], H, SizeOf(H));
|
||||
if H.StreamType = LongWord(Ord(tstTXChrono)) then
|
||||
begin
|
||||
Inc(n);
|
||||
if H.Receiver <> 1 then Inc(BadRx);
|
||||
end;
|
||||
end;
|
||||
Check('TX слайса: маркеры TX_CHRONO идут', n > 0, IntToStr(n));
|
||||
Check('TX слайса: маркер назван номером приёмника (MSHV фильтрует)',
|
||||
(n > 0) and (BadRx = 0), IntToStr(BadRx));
|
||||
C.SendText('trx:1,false;');
|
||||
C.WaitText('trx:', 1000);
|
||||
Ctrl.SetSliceSlotAutoTx(Ctrl.SliceSlotOf(SliceId), False);
|
||||
|
||||
C.SendText('audio_stop:1;');
|
||||
C.Pump(200);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user