feat: ESM (Enter Sends Message) for CW keyers, N1MM-style

With ESM enabled (Settings → CW Keyer), the keyer active and mode CW, Enter in
the entry strip fires a macro by QSO stage instead of logging:
- callsign field empty            → F1 (CQ)
- callsign entered (in call field) → F2 (report), then focus jumps to RST-sent
- Enter in RST-sent / RST-rcvd     → F3 (TU), which logs via its own <LOGQSO>

Works for every keyer engine (WinKeyer / serial DTR-RTS / Flex CWX / Icom CI-V)
since it routes through the shared macro sender. Enter in other fields still logs
normally, and ESM off keeps the classic Enter-to-log behaviour.

Backend: new `esm` flag on WinkeyerSettings (winkeyer.esm). Frontend: esmHandleEnter
state machine keyed off data-esm markers on the call/RST blocks, a Settings
checkbox + hint, and i18n EN/FR.
This commit is contained in:
2026-07-25 12:38:09 +02:00
parent e5ff30823d
commit 370fde42f7
6 changed files with 58 additions and 6 deletions
+4
View File
@@ -143,6 +143,8 @@ const en: Dict = {
// CW Keyer settings panel
'wk.enable': 'Enable CW keyer (shows the keyer panel)', 'wk.engine': 'Keyer engine',
'wk.escClears': 'ESC clears the callsign too (otherwise ESC only stops transmission)',
'wk.esm': 'ESM — Enter Sends Message (CW)',
'wk.esmHint': 'In CW with the keyer on, Enter fires a macro by QSO stage instead of logging: empty callsign → F1 (CQ); callsign entered → F2 (report) and focus jumps to RST; Enter in RST → F3 (TU), which logs if the macro contains <LOGQSO>.',
'wk.engWinkeyer': 'WinKeyer (K1EL, serial)', 'wk.engSerial': 'Serial port (DTR=CW / RTS=PTT)', 'wk.engIcom': 'Icom CI-V (rig keyer)', 'wk.engFlex': 'FlexRadio (CWX)', 'wk.engTci': 'TCI (coming soon)',
'wk.icomNote': "Icom CI-V keys CW through the rig's own keyer over the existing CAT connection (command 0x17) — it reuses the CAT COM port set in Settings → CAT, so there's nothing else to wire up here. Put the rig in CW mode. Weight, ratio, sidetone, paddle mode… are configured on the radio; only the speed is set from here (the rig's KEY SPEED).",
'wk.flexNote': "FlexRadio keys CW through the radio's CWX keyer over the existing SmartSDR CAT connection — no WinKeyer or SmartCAT needed. It reuses the connection set in Settings → CAT, so there's nothing else to wire up here. Put a slice in CW mode. Only the speed is set from here; weight, sidetone and break-in are configured on the radio (break-in must be on for CW to actually transmit).",
@@ -517,6 +519,8 @@ const fr: Dict = {
// Panneau Manipulateur CW
'wk.enable': 'Activer le manipulateur CW (affiche le panneau)', 'wk.engine': 'Moteur du manipulateur',
'wk.escClears': "ÉCHAP efface aussi l'indicatif (sinon ÉCHAP arrête seulement la transmission)",
'wk.esm': 'ESM — Entrée envoie le message (CW)',
'wk.esmHint': "En CW avec le keyer actif, Entrée envoie un macro selon l'étape du QSO au lieu de loguer : indicatif vide → F1 (CQ) ; indicatif saisi → F2 (report) et le focus passe au RST ; Entrée dans le RST → F3 (TU), qui logue si le macro contient <LOGQSO>.",
'wk.engWinkeyer': 'WinKeyer (K1EL, série)', 'wk.engSerial': 'Port série (DTR=CW / RTS=PTT)', 'wk.engIcom': 'Icom CI-V (keyer de la radio)', 'wk.engFlex': 'FlexRadio (CWX)', 'wk.engTci': 'TCI (bientôt)',
'wk.icomNote': "L'Icom CI-V manipule la CW via le keyer interne de la radio sur la connexion CAT existante (commande 0x17) — il réutilise le port COM CAT défini dans Réglages → CAT, rien d'autre à câbler ici. Mets la radio en mode CW. Poids, ratio, sidetone, mode paddle… se règlent sur la radio ; seule la vitesse est définie ici (KEY SPEED de la radio).",
'wk.flexNote': "FlexRadio manipule la CW via le keyer CWX de la radio sur la connexion SmartSDR CAT existante — pas besoin de WinKeyer ni de SmartCAT. Il réutilise la connexion définie dans Réglages → CAT, rien d'autre à câbler ici. Mets une slice en mode CW. Seule la vitesse est définie ici ; poids, sidetone et break-in se règlent sur la radio (le break-in doit être activé pour que la CW parte vraiment).",