mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
feat(cw): терминал телеграфа — набор с клавиатуры и декодер приёма
Окно (ПКМ по CWL/CWU, F9, кнопка в настройках CW): одна лента, где принятое декодером и СВОЯ передача идут вперемешку — своё акцентным цветом. Разделять их нельзя: в QSK они перемежаются посреди фразы. Под лентой строка набора. Печать уходит в эфир ПОСИМВОЛЬНО, а не по Enter: строка показывает ровно то, что ещё не передано (очередь генератора), знаки уходят из неё по мере отправки, Backspace стирает с хвоста очереди — то, что уже звучит, вернуть нельзя. Ctrl работает манипулятором (левый точка, правый тире; у кейера прошивки лепестков нет — там это прямой ключ через бит CWX), по умолчанию выключено, чтобы Ctrl+C не уводил в эфир. Отпускание ключа ловится и на потере фокуса: иначе уход из окна с зажатым Ctrl оставил бы несущую в эфире навсегда. CWDecoder.pas: аудио → текст. Отвод берётся до громкости и мьюта — там нет программного сайдтона, зато уже отработал узкий CW-фильтр, лучшего предетектора не найти. Гёрцель гребёнкой из пяти бинов вокруг pitch (заодно показывает расстройку) → огибающая → адаптивный порог с гистерезисом → длительности → адаптивная точка → обратная таблица Морзе. Длительности живут в шагах анализа, а не в показаниях часов: разбор идёт пачками с таймера, и привязка ко времени вызова ломала бы тайминг на любой загрузке. Вылезло на тестах и учтено: пик обязан клампиться не ниже пола шума (иначе на старте порог уходит НИЖЕ шума и первым «знаком» читается собственный шум); порог дребезга берётся от текущей точки, фиксированный либо пропускает щелчки на медленной передаче, либо ест посылки на быстрой; длина посылки меряется за вычетом подтверждения дребезга, иначе скорость занижалась на 15%; расстройка запоминается только на полной амплитуде посылки, иначе индикатор пляшет. Граница честная: при вдвое неверной подсказке скорости теряется первое слово — пока не услышана настоящая точка, длина элемента неизвестна. Лента расшифровки продублирована строкой под спектром (пан 0), эхо передачи и очередь набора появились у обоих отправителей — и у локального генератора, и у кейера прошивки. ★TFlatEdit получил публичный CaretPos: он вставляет знак сам в UTF8KeyPress и гасит клавишу, поэтому OnKeyPress контрола не вызывается вовсе — из-за этого набранное «исчезало», а в эфир не уходило. Ввод перенесён на уровень формы. Проверено оффлайн: 12/20/40 WPM, расстройка, шум, слабый сигнал, цифры и знаки; плюс сквозной прогон против шести станций CW-стенда в hpsdrsim. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -361,6 +361,10 @@ type
|
||||
KeyInvert: Boolean;
|
||||
KeyPowerDTR: Boolean;
|
||||
KeyPowerRTS: Boolean;
|
||||
// ---- Окно-терминал: набор с клавиатуры + декодер приёма ----------------
|
||||
Decoder: Boolean; // разбирать принимаемый телеграф в текст
|
||||
DecoderStrip: Boolean; // бегущая лента расшифровки под спектром
|
||||
KbdKey: Boolean; // Ctrl в окне терминала работает манипулятором
|
||||
end;
|
||||
|
||||
// ---- TX-профили (именованные снимки «как я звучу») ----------------------
|
||||
@@ -1821,6 +1825,9 @@ begin
|
||||
C.KeyInvert := False;
|
||||
C.KeyPowerDTR := True; // типовая распайка: ключ питается от DTR/RTS
|
||||
C.KeyPowerRTS := True;
|
||||
C.Decoder := True; // окно терминала без декодера бессмысленно
|
||||
C.DecoderStrip := False; // лента под спектром — по желанию
|
||||
C.KbdKey := False; // Ctrl-манипулятор включают осознанно
|
||||
// Заводские заготовки: типовой вызов, ответ и стандартные концовки.
|
||||
C.Messages[0] := 'CQ CQ DE ';
|
||||
C.Messages[1] := 'DE ';
|
||||
@@ -1867,6 +1874,9 @@ begin
|
||||
C.KeyInvert := JB(O,'key_invert', C.KeyInvert);
|
||||
C.KeyPowerDTR := JB(O,'key_power_dtr', C.KeyPowerDTR);
|
||||
C.KeyPowerRTS := JB(O,'key_power_rts', C.KeyPowerRTS);
|
||||
C.Decoder := JB(O,'decoder', C.Decoder);
|
||||
C.DecoderStrip := JB(O,'decoder_strip', C.DecoderStrip);
|
||||
C.KbdKey := JB(O,'kbd_key', C.KbdKey);
|
||||
for i := 0 to CW_MSG_COUNT - 1 do
|
||||
C.Messages[i] := Copy(JS(O, 'msg_' + IntToStr(i), C.Messages[i]), 1, 63);
|
||||
end;
|
||||
@@ -1900,6 +1910,9 @@ begin
|
||||
JW(O,'key_invert', C.KeyInvert);
|
||||
JW(O,'key_power_dtr', C.KeyPowerDTR);
|
||||
JW(O,'key_power_rts', C.KeyPowerRTS);
|
||||
JW(O,'decoder', C.Decoder);
|
||||
JW(O,'decoder_strip', C.DecoderStrip);
|
||||
JW(O,'kbd_key', C.KbdKey);
|
||||
for i := 0 to CW_MSG_COUNT - 1 do
|
||||
JWS(O, 'msg_' + IntToStr(i), C.Messages[i]);
|
||||
end;
|
||||
|
||||
Reference in New Issue
Block a user