mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-26 04:47:35 +00:00
fix(cw): запрет передачи действует и на кейер прошивки (RX-only XVTR, DoNotTx)
Аудит трансвертерного режима против дефектов этой сессии нашёл ту же болезнь, что и всё остальное: защита жила только на пути через софтовый MOX. Бэнд с DoNotTx (Alex) и RX-only слот трансвертера проверялись тремя копиями кода — в SetMOX, SetTune и SetTwoTone. С кейером в прошивке ни одна из них не исполняется: на приёмном трансвертере замыкание ключа выходило в эфир, а там на выходе обычно вход конвертера, а не антенна. Три копии сведены в TXProhibited; CWTXActive её учитывает, поэтому байт 5 обнуляется и кейер разоружается там, где передавать нельзя. Передача текста гейтится тем же условием. Вооружение сделано самовосстанавливающимся: SyncCWKeyer идемпотентен (пара сравнений плюс ранний выход внутри SetCWKeyerArmed) и вызывается ещё и из разбора HP-статуса. Разоружить кейер может заход в RX-only слот, переход на запрещённый бэнд или правка Alex; перечислять такие точки поимённо — гарантия однажды пропустить очередную, на чём уже дважды обожглись за сегодня. Остальное в трансвертере проверено и чисто: сдвиг pitch переживает XvtrTranslateTX (включая split-LO QO-100), множитель мощности слота и VHF-калибровка уже входят в CalcDriveByte и потому уезжают в байт 345, OC-выходы идут за ключом через RadioKeyed, ActivateXvtr толкает верную частоту DUC. Инвертирующие трансвертеры не поддержаны нигде в проекте — это давнее общее ограничение, не регресс телеграфа. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+34
-19
@@ -609,6 +609,7 @@ type
|
|||||||
procedure SendDUCSpecificFromSettings; // DUC Specific (mic/keyer/atten) в сеть
|
procedure SendDUCSpecificFromSettings; // DUC Specific (mic/keyer/atten) в сеть
|
||||||
procedure ApplyTXSettingsToDSP; // TX-цепь (фильтр/gain/EQ/comp/...) → WDSP
|
procedure ApplyTXSettingsToDSP; // TX-цепь (фильтр/gain/EQ/comp/...) → WDSP
|
||||||
// ---- Телеграф ----------------------------------------------------------
|
// ---- Телеграф ----------------------------------------------------------
|
||||||
|
function TXProhibited: Boolean; // DoNotTx-бэнд / RX-only XVTR
|
||||||
function CWTXActive: Boolean; // передачей владеет FPGA-кейер
|
function CWTXActive: Boolean; // передачей владеет FPGA-кейер
|
||||||
function CWOptionsByte: Byte; // DUC Specific байт 5
|
function CWOptionsByte: Byte; // DUC Specific байт 5
|
||||||
procedure SyncCWKeyer; // байт 5 под текущий TX-режим
|
procedure SyncCWKeyer; // байт 5 под текущий TX-режим
|
||||||
@@ -1573,6 +1574,9 @@ begin
|
|||||||
Changed(rfADCOverload);
|
Changed(rfADCOverload);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// Вооружение кейера — под текущий контекст (бэнд/трансвертер/Alex могли
|
||||||
|
// поменяться мимо SetMode и SetTxSlice). Вызов идемпотентный, см. SyncCWKeyer.
|
||||||
|
SyncCWKeyer;
|
||||||
// ★Телеграф с кейером в прошивке: HPS_PTT здесь — ЭХО собственной манипуляции
|
// ★Телеграф с кейером в прошивке: HPS_PTT здесь — ЭХО собственной манипуляции
|
||||||
// (при break-in железо само поднимает T/R на каждую посылку), а не действие
|
// (при break-in железо само поднимает T/R на каждую посылку), а не действие
|
||||||
// оператора. Гонять по нему SetMOX нельзя: на каждой точке пересобирался бы
|
// оператора. Гонять по нему SetMOX нельзя: на каждой точке пересобирался бы
|
||||||
@@ -5097,12 +5101,25 @@ begin
|
|||||||
FDSPEngine.SetANF(FANF);
|
FDSPEngine.SetANF(FANF);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TRadioController.TXProhibited: Boolean;
|
||||||
|
// Единая точка запретов передачи: диапазон с DoNotTx (Alex) и RX-only слот
|
||||||
|
// трансвертера. Раньше эта пара была скопирована в SetMOX/SetTune/SetTwoTone —
|
||||||
|
// то есть жила ТОЛЬКО на пути через софтовый MOX. С кейером в прошивке этого
|
||||||
|
// пути нет вовсе, и на RX-only трансвертере ключ спокойно выходил в эфир.
|
||||||
|
begin
|
||||||
|
Result := (FDevConnected and (FCurrentXvtr < 0)
|
||||||
|
and FAlexSettings.DoNotTx[EnsureRange(TxBandIdx, 0, 10)])
|
||||||
|
or ((FCurrentXvtr >= 0) and (FCurrentXvtr < CFG_XVTR_COUNT)
|
||||||
|
and FXvtrSettings.Entries[FCurrentXvtr].RXOnly);
|
||||||
|
end;
|
||||||
|
|
||||||
function TRadioController.CWTXActive: Boolean;
|
function TRadioController.CWTXActive: Boolean;
|
||||||
// «Телеграфом управляет железо»: режим ИСТОЧНИКА передачи — CW и кейер в
|
// «Телеграфом управляет железо»: режим ИСТОЧНИКА передачи — CW и кейер в
|
||||||
// прошивке. В этом состоянии голосовой TXA не запускается вовсе (эталон
|
// прошивке. В этом состоянии голосовой TXA не запускается вовсе (эталон
|
||||||
// Thetis, console.cs:29570), а точки/тире формирует FPGA.
|
// Thetis, console.cs:29570), а точки/тире формирует FPGA.
|
||||||
begin
|
begin
|
||||||
Result := (ActiveTXMode in [MODE_CWL, MODE_CWU]) and FCWSettings.FWKeyer;
|
Result := (ActiveTXMode in [MODE_CWL, MODE_CWU]) and FCWSettings.FWKeyer
|
||||||
|
and (not TXProhibited); // где передавать нельзя — кейер разоружён
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TRadioController.CWOptionsByte: Byte;
|
function TRadioController.CWOptionsByte: Byte;
|
||||||
@@ -5509,13 +5526,8 @@ begin
|
|||||||
// DMR support is receive-only. This guard also covers CAT, web and hardware
|
// DMR support is receive-only. This guard also covers CAT, web and hardware
|
||||||
// PTT. FM RAW is a flat external-modem transmit path.
|
// PTT. FM RAW is a flat external-modem transmit path.
|
||||||
if On_ and (ActiveTXMode = MODE_DMR) then Exit;
|
if On_ and (ActiveTXMode = MODE_DMR) then Exit;
|
||||||
// Safety: блокируем TX на бэндах с DoNotTx (Alex) и на RX-only трансвертере.
|
// Safety: бэнды с DoNotTx (Alex) и RX-only трансвертер — см. TXProhibited.
|
||||||
if On_ and FDevConnected and (FCurrentXvtr < 0)
|
if On_ and TXProhibited then Exit;
|
||||||
and FAlexSettings.DoNotTx[EnsureRange(TxBandIdx, 0, 10)] then
|
|
||||||
Exit;
|
|
||||||
if On_ and (FCurrentXvtr >= 0) and (FCurrentXvtr < CFG_XVTR_COUNT)
|
|
||||||
and FXvtrSettings.Entries[FCurrentXvtr].RXOnly then
|
|
||||||
Exit;
|
|
||||||
WasTransmitting := FTransmitting;
|
WasTransmitting := FTransmitting;
|
||||||
// Снятие MOX руками обрывает программную передачу текста: оператор решил
|
// Снятие MOX руками обрывает программную передачу текста: оператор решил
|
||||||
// прекратить — ключ обязан отпуститься немедленно.
|
// прекратить — ключ обязан отпуститься немедленно.
|
||||||
@@ -5649,10 +5661,7 @@ begin
|
|||||||
if On_ and (ActiveTXMode in [MODE_DMR, MODE_FMRAW]) then Exit;
|
if On_ and (ActiveTXMode in [MODE_DMR, MODE_FMRAW]) then Exit;
|
||||||
// Safety: те же блокировки, что и в SetMOX — TUN это TX через WDSP PostGen-тон,
|
// Safety: те же блокировки, что и в SetMOX — TUN это TX через WDSP PostGen-тон,
|
||||||
// он тоже должен молчать на бэндах с DoNotTx и на RX-only XVTR.
|
// он тоже должен молчать на бэндах с DoNotTx и на RX-only XVTR.
|
||||||
if On_ and FDevConnected and (FCurrentXvtr < 0)
|
if On_ and TXProhibited then Exit;
|
||||||
and FAlexSettings.DoNotTx[EnsureRange(TxBandIdx, 0, 10)] then Exit;
|
|
||||||
if On_ and (FCurrentXvtr >= 0) and (FCurrentXvtr < CFG_XVTR_COUNT)
|
|
||||||
and FXvtrSettings.Entries[FCurrentXvtr].RXOnly then Exit;
|
|
||||||
if On_ and FTwoTone then SetTwoTone(False); // TUN поверх 2TON — гасим тона
|
if On_ and FTwoTone then SetTwoTone(False); // TUN поверх 2TON — гасим тона
|
||||||
if On_ then
|
if On_ then
|
||||||
begin
|
begin
|
||||||
@@ -5759,7 +5768,14 @@ procedure TRadioController.SyncCWKeyer;
|
|||||||
// TX-слайса обязана его перепослать: вне телеграфа он должен стать нулевым,
|
// TX-слайса обязана его перепослать: вне телеграфа он должен стать нулевым,
|
||||||
// иначе прошивка поднимет PTT на замыкание ключа посреди SSB.
|
// иначе прошивка поднимет PTT на замыкание ключа посреди SSB.
|
||||||
begin
|
begin
|
||||||
if not (ActiveTXMode in [MODE_CWL, MODE_CWU]) then CWXAbort;
|
// Дёшево и идемпотентно: пара сравнений плюс ранний выход внутри
|
||||||
|
// SetCWKeyerArmed. Поэтому зовётся не только на смене режима/источника, но и
|
||||||
|
// из разбора HP-статуса — вооружение кейера обязано быть САМОВОССТАНАВЛИВАЮЩИМСЯ.
|
||||||
|
// Разоружить его может что угодно: заход в RX-only слот трансвертера, переход
|
||||||
|
// на бэнд с DoNotTx, правка Alex. Перечислять такие точки поимённо — гарантия
|
||||||
|
// однажды пропустить очередную (ровно так уже вышло с DUC-частотой и мощностью).
|
||||||
|
if (not (ActiveTXMode in [MODE_CWL, MODE_CWU]))
|
||||||
|
and Assigned(FCWSender) and FCWSender.Busy then CWXAbort;
|
||||||
// Вооружённый кейер = железо может выйти в эфир само ⇒ бэкенд обязан класть
|
// Вооружённый кейер = железо может выйти в эфир само ⇒ бэкенд обязан класть
|
||||||
// уровень мощности в КАЖДЫЙ HP-кадр, а не только на передаче.
|
// уровень мощности в КАЖДЫЙ HP-кадр, а не только на передаче.
|
||||||
if Assigned(FNetwork) then FNetwork.SetCWKeyerArmed(CWTXActive);
|
if Assigned(FNetwork) then FNetwork.SetCWKeyerArmed(CWTXActive);
|
||||||
@@ -5785,8 +5801,10 @@ procedure TRadioController.CWXSend(const Text: string);
|
|||||||
// выключен — оператор держит MOX руками, как при ручном T/R.
|
// выключен — оператор держит MOX руками, как при ручном T/R.
|
||||||
begin
|
begin
|
||||||
if Text = '' then Exit;
|
if Text = '' then Exit;
|
||||||
if not (ActiveTXMode in [MODE_CWL, MODE_CWU]) then Exit;
|
// CWTXActive, а не просто режим: он же учитывает запрет передачи (RX-only
|
||||||
if not FCWSettings.FWKeyer then Exit;
|
// слот трансвертера, бэнд с DoNotTx) — там кейер разоружён, и дёргать бит
|
||||||
|
// CWX незачем.
|
||||||
|
if not CWTXActive then Exit;
|
||||||
if not Assigned(FCWSender) then
|
if not Assigned(FCWSender) then
|
||||||
FCWSender := TCWSender.Create(Self.CWXKeyEvent);
|
FCWSender := TCWSender.Create(Self.CWXKeyEvent);
|
||||||
FCWSender.SetSpeed(FCWSettings.Speed, FCWSettings.Weight);
|
FCWSender.SetSpeed(FCWSettings.Speed, FCWSettings.Weight);
|
||||||
@@ -6132,10 +6150,7 @@ begin
|
|||||||
if On_ and (ActiveTXMode in [MODE_DMR, MODE_FMRAW]) then Exit;
|
if On_ and (ActiveTXMode in [MODE_DMR, MODE_FMRAW]) then Exit;
|
||||||
if On_ and FTuning then Exit; // не поверх TUN-тона
|
if On_ and FTuning then Exit; // не поверх TUN-тона
|
||||||
// Safety: те же блокировки, что SetMOX/SetTune.
|
// Safety: те же блокировки, что SetMOX/SetTune.
|
||||||
if On_ and FDevConnected and (FCurrentXvtr < 0)
|
if On_ and TXProhibited then Exit;
|
||||||
and FAlexSettings.DoNotTx[EnsureRange(TxBandIdx, 0, 10)] then Exit;
|
|
||||||
if On_ and (FCurrentXvtr >= 0) and (FCurrentXvtr < CFG_XVTR_COUNT)
|
|
||||||
and FXvtrSettings.Entries[FCurrentXvtr].RXOnly then Exit;
|
|
||||||
if On_ then
|
if On_ then
|
||||||
begin
|
begin
|
||||||
// Генератор ДО запуска TX-тракта — первые блоки уже с тонами.
|
// Генератор ДО запуска TX-тракта — первые блоки уже с тонами.
|
||||||
|
|||||||
Reference in New Issue
Block a user