Real-Time Morse Code Transmission over IP Networks
Duration-Encoded CW (DECW) is a protocol for transmitting Morse code timing information over IP networks (UDP/TCP) intended prio for remote control. Unlike text-based approaches, DECW transmits raw key events with precise timing, preserving the operator's natural keying rhythm and "fist".
Each packet contains the duration of the event, not just state changes. This makes DECW robust against network jitter, as each event is self-contained and can be scheduled independently.
Status: π§ In development - Features and structure subject to change
Design Goal: Simple, cross-platform setup using Python - no complex dependencies or compilation required.
Each packet describes a state transition with the duration of the previous state:
[seq=5][UP][180ms] = "Key was DOWN for 180 milliseconds"
How it works:
- Manual keying: When key changes state, send packet with new state + previous state's duration
- Example: Press key β starts timer β release key (180ms later) β send
[UP][180ms] - Receiver: Play each state for its specified duration
Benefits:
- Self-contained packets (no dependency on previous packets)
- Jitter tolerant (duration preserved even if packet arrives late)
- Simpler receiver (just schedule event for X milliseconds)
- Better packet loss recovery (lost packet affects only one event)
The project includes multiple implementations optimized for different network conditions:
- UDP - Low latency, best for LAN
- UDP+Timestamps - Burst-resistant timing
- TCP - Reliable delivery, better for high jitter
- TCP+Timestamps - Burst-resistant timing
- WebSocket - Browser-based implementation
See the detailed README files in test_implementation/ and web_platform_tcp/ for specific implementations.
All terminal-based implementation files are in the test_implementation/ directory.
Linux (Fedora):
sudo dnf install -y python3-pyaudio python3-pyserial python3-numpy portaudio
sudo usermod -a -G dialout $USER # For serial port access, then log out/inLinux (Ubuntu/Debian):
sudo apt install -y python3-pyaudio python3-serial python3-numpy portaudio19-dev
sudo usermod -a -G dialout $USER # For serial port access, then log out/incd test_implementation/
# Start receiver
python3 cw_receiver.py
# Send automated text (in another terminal)
python3 cw_auto_sender.py localhost 20 "CQ CQ CQ DE SM5ABC"
# Interactive line-by-line sender
python3 cw_interactive_sender.py localhost 25
# Hardware key (USB serial adapter)
python3 cw_usb_key_sender.py localhost iambic-b 25 /dev/ttyUSB0For internet/WAN use, enable the jitter buffer to smooth network timing variations:
# Recommended for internet use
python3 cw_receiver.py --jitter-buffer 100
# For TCP timestamp version (WiFi-optimized)
python3 cw_receiver_tcp_ts.py --jitter-buffer 150Buffer sizing:
- LAN: 0ms (no buffer needed)
- Good Internet: 50-100ms
- Poor Internet/WiFi: 150-200ms
The test_implementation/ directory contains a complete Python reference implementation with:
- Multiple protocol variants (UDP, UDP+timestamps, TCP, TCP+timestamps)
- Automated senders (text-to-CW conversion)
- Interactive senders (line-by-line keying)
- Physical key support (USB serial adapters, iambic keyers)
- GPIO output (Raspberry Pi - drive transmitter relays)
- Detailed documentation (protocol specs, tuning guides)
See test_implementation/README.md for complete technical documentation.
The web_platform_tcp/ directory contains an experimental browser-based implementation:
- WebSocket-based (JSON event protocol)
- Multi-user rooms (practice with multiple operators)
- Real-time CW decoder (Morse to text)
- Web Audio API (sidetone generation)
- No installation required (works in any modern browser)
See web_platform_tcp/README.md for web platform details.
Here we have a coupleof options.
- USB HID interface
- USB HID (Vail adapter)
- Serial Interface
The USB_HID/ directory contains a production-ready hardware interface:
- Seeedstudio XIAO SAMD21 microcontroller
- USB HID Keyboard protocol (works on Linux/Windows/macOS) Quick Start:
# 1. Upload firmware (Arduino IDE)
cd USB_HID/xiao_samd21_hid_key/
# Open .ino file, select Seeeduino XIAO board, upload
# 2. Wire your paddles
# XIAO D2 β Dit paddle β GND
# XIAO D1 β Dah paddle β GND
# 3. Run sender
cd ../
python3 cw_xiao_hidraw_sender.py <receiver_ip> --wpm 25 --debug
# 4. Run receiver
cd ../test_implementation/
python3 cw_receiver_tcp_ts.py --jitter-buffer 150See USB_HID/README.md for complete setup guide, troubleshooting, and technical details.
See this - https://vailadapter.com/
Note Will require the same firmware as the HID interface.
Pin assignments:
DB-9 or USB-TTL adapter:
ββ Pin 8 (CTS) βββ Dit paddle (or straight key)
ββ Pin 6 (DSR) βββ Dah paddle
ββ Pin 5 (GND) βββ Common ground
For straight key: Connect key between CTS and GND
For iambic: Connect dit paddle to CTS, dah paddle to DSR
- Iambic-keyer
- Straight key mode
- Real-time sidetone
For driving physical transmitter keying circuits:
cd test_implementation/
# Basic usage (GPIO 17, active-high)
python3 cw_gpio_output.py
# Custom GPIO pin with buffer
python3 cw_gpio_output.py --pin 23 --buffer 150
Hardware connection: GPIO Pin β Relay/Transistor β Transmitter Key Input
See test_implementation/README.md for complete hardware setup details.
Note Serial interfaces can behave porly depending on supported sampling speed!
- TCP-TS Protocol Specification - TCP with timestamps for WiFi/burst-resistant timing
- Timestamp Protocol Example - Detailed timing trace examples
Complete technical documentation is in the implementation directories:
-
test_implementation/README.md - Python implementation guide
- Protocol specifications (packet format, timing)
- Protocol variants (UDP, TCP)
- Usage examples and command-line options
- Jitter buffer tuning and configuration
- Hardware setup (GPIO, USB serial)
- Network performance and testing
-
web_platform_tcp/README.md - Web platform guide
- WebSocket implementation
- Browser requirements
- Deployment instructions
- Multi-user room features
Currently implemented:
- β 3-byte UDP protocol
- β TCP variants (duration-based and timestamp-based)
- β Jitter buffer with word space detection
- β Hardware key support (USB serial)
- β USB HID paddle interface
- β Iambic keyer
- β Audio sidetone
- β GPIO output (Raspberry Pi)
- β Real-time CW decoder
- β Web platform (experimental)
Future possibilities:
- ESP32 HID variant (TinyUSB issues to resolve)
- Multi-operator relay server
- Additional error correction methods
Inspired by:
- Protocol concept: Wolfgang Buescher (DL4YHF)
- Iambic keyer reference: Steve Haynal (n1gp/iambic-keyer)
- USB HID inspired by the Vail-CW adapter project - https://github.com/Vail-CW
- Ideas and testing: Stu (KZ4LN)
- Testing: Fabian Kurz (DJ5CW/SO5CW)
Happy CW operating!
73 de SM0ONR