feat(cw): телеграф — FPGA-кейер, pitch, сайдтон, передача текста

CW не работал ни на приём, ни на передачу: фильтр стоял симметрично вокруг
нуля (тона не было), понятия pitch не существовало, MOX в CWL отправлял в
эфир голос 2.9 кГц (в WDSP TXA_CWL — ветка SSB), байт CW-опций DUC всегда
был нулевым, поэтому кейер, сайдтон и break-in в прошивке молчали.

Pitch сделан ОДНИМ сдвигом в движке. Кромки фильтра везде остаются
относительно VFO (у CW — симметрично нулю), а гетеродин и полосу двигают
три метода WDSPEngine: CWLOOffset / PushShift / PushPassband. Прямых
вызовов SetRXAShiftFreq и RXASetPassband в проекте больше нет. Так таблица
фильтров не перестраивается при смене pitch (в отличие от Thetis), полоска
на спектре и маркер VFO верны без правок в UI, а слайсы получают свой
сдвиг по своему режиму.

Правила эфира:
- голосовой TXA в CW не запускается вообще (гард по режиму), MOX = только
  PTT; несущую даёт кейер, бит CWX или тон TUN;
- байт 5 собирается из настроек и перепосылается на каждой смене режима и
  TX-слайса — вне CW он обязан быть нулевым, иначе прошивка поднимет PTT на
  замыкание ключа посреди SSB;
- TUN в CW: тон = pitch и встречный сдвиг DUC, несущая встаёт ровно на VFO;
- приёмник на передаче в CW не глушится, иначе умолкает программный
  сайдтон и эфир между посылками.

Программная передача текста (CWMorse): поток с абсолютными дедлайнами
дёргает бит CWX в High Priority, элементы рисует прошивка. Касание
манипулятора или снятие MOX обрывают передачу. Память сообщений — окно
CW Messages и F1..F8 в главном окне. Оживлены CAT KS/KY/ZZKM/ZZKS/ZZKY.

Настройки — вкладка Transmit, подвкладка Hardware, перед блоком FM/CTCSS.

Программный сайдтон точен для передачи текста и прямого ключа; при иамбике
таймингом владеет FPGA, поэтому там верен только аппаратный тон.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-10 12:20:56 +03:00
co-authored by Claude Opus 5
parent 0ec120c2d5
commit 53329e82e8
12 changed files with 1421 additions and 46 deletions
+8
View File
@@ -180,6 +180,10 @@ type
procedure SendDDCSpecific(const Pkt: TDDCSpecificPacket); virtual;
procedure SendDUCSpecific(const Pkt: TDUCSpecificPacket); virtual;
procedure SendHighPriority(const Pkt: THighPriorityPacket); virtual;
// Бит CWX (High Priority байт 5 bit0): «ключ нажат» для программной
// передачи телеграфа — несущую по нему формирует прошивка. Пакет уходит
// немедленно, каждый фронт (тайминги держит PC). Pluto — no-op.
procedure SetCWXKey(Down: Boolean); virtual;
procedure SetStepAtten(dB: Byte); virtual;
// RX-усиление (Pluto/AD936x). ModeIdx: 0=manual, 1=fast_attack, 2=slow_attack,
// 3=hybrid. GainDb применяется только в manual. HPSDR — no-op.
@@ -277,6 +281,10 @@ procedure TRadioBackend.SendHighPriority(const Pkt: THighPriorityPacket);
begin
end;
procedure TRadioBackend.SetCWXKey(Down: Boolean);
begin
end;
procedure TRadioBackend.SetStepAtten(dB: Byte);
begin
end;