Reference

Morse code table, timing formulas, settings, API endpoints, and project layout.

Morse Code Table

Letters

A
·−
B
−···
C
−·−·
D
−··
E
·
F
··−·
G
−−·
H
····
I
··
J
·−−−
K
−·−
L
·−··
M
−−
N
−·
O
−−−
P
·−−·
Q
−−·−
R
·−·
S
···
T
U
··−
V
···−
W
·−−
X
−··−
Y
−·−−
Z
−−··

Numbers

0
−−−−−
1
·−−−−
2
··−−−
3
···−−
4
····−
5
·····
6
−····
7
−−···
8
−−−··
9
−−−−·

Punctuation

.
·−·−·−
,
−−··−−
?
··−−··
'
·−−−−·
!
−·−·−−
/
−··−·
(
−·−−·
)
−·−−·−
&
·−···
:
−−−···
=
−···−
+
·−·−·
-
−····−
@
·−−·−·
_
··−−·−
"
·−··−·

Timing & WPM

All timing in Morse-Pi is derived from the dot unit, which is calculated from your WPM setting:

dot_unit = 1200ms / WPM
ElementDurationAt 20 WPM
Dot1 unit60 ms
Dash3 units180 ms
Inter-element gap1 unit60 ms
Letter gap3 units180 ms
Word gap7 units420 ms

Farnsworth timing

Farnsworth timing keeps character elements at full speed while stretching spacing, making copy practice easier for beginners.

In the UI, configure this in CONFIG → Farnsworth Timing (On/Off + Farnsworth Speed WPM).

Settings Reference

SettingTypeDefaultDescription
device_namestring"Morse Pi"Name shown to other devices on the network
wpm_targetint20Words per minute — all timing derives from this
pin_modestring"single"single = straight key, dual = iambic paddle
data_pinint17BCM pin for straight key input
dot_pinint22BCM pin for dot paddle (dual mode)
dash_pinint27BCM pin for dash paddle (dual mode)
speaker_pinint18BCM pin for speaker (pin 1)
speaker_pin2int|nullnullSecond speaker GPIO pin for push-pull drive. When set (and pigpio is available), the two pins are driven in anti-phase for louder audio.
output_typestring"speaker"speaker = PWM audio, led = on/off
ground_pinint|nullnullLegacy single ground output pin
grounded_pinslist[]Multiple GPIO pins driven LOW as grounds
dot_freqint700Dot tone frequency in Hz (100–4000)
dash_freqint500Dash tone frequency in Hz (100–4000)
volumefloat0.75PWM duty cycle (0.01–0.95)
themestring"dark"UI theme: dark or light
difficultystring"easy"Quiz difficulty: easy, medium, hard
farnsworth_wpmint20Spacing speed for Farnsworth timing. Set below wpm_target for extra spacing.
farnsworth_enabledboolfalseCompatibility flag accepted by /save_settings; effective mode is derived from farnsworth_wpm < wpm_target.
farnsworth_letter_multfloat2.0Legacy/internal compatibility field (not used by current UI controls).
farnsworth_word_multfloat2.0Legacy/internal compatibility field (not used by current UI controls).
kb_enabledboolfalseEnable USB HID keyboard output
kb_modestring"letters"letters = decoded chars, custom = mapped keys
kb_dot_keystring"z"Key sent for dot in custom mode
kb_dash_keystring"x"Key sent for dash in custom mode
radio_local_monitorbooltruePlay your own local keying audio while transmitting
radio_remote_monitorbooltruePlay incoming live key audio from peers
radio_receive_enabledbooltrueAllow/ignore incoming live key events from peers
ℹ Settings persistence
All settings are stored in /opt/morse-pi/morse-translator/settings.json regardless of which backend you're running. New settings added in updates are automatically merged with your existing file — you never lose your configuration.

API Routes

Morse-Pi exposes a REST-like API. The web UI uses these internally, but they can be called from scripts or other tools.

Core

RouteMethodDescription
/GETMain web UI
/networkGETDedicated radio control page
/radioGETLegacy alias for /network
/diagGETGPIO diagnostic page
/statusGETFull app state (polled by UI every 250ms)
/get_settingsGETCurrent settings
/save_settingsPOSTUpdate and persist settings
/set_modePOSTSwitch active mode
/clearPOSTClear all output buffers

Morse operations

RouteMethodDescription
/encodePOSTText → Morse code
/playPOSTPlay last encoded text as audio
/decode_submitPOSTSubmit decode quiz answer
/submit_testPOSTSubmit speed test for scoring
/key_pressPOSTSimulate straight key press/release
/key_press_dualPOSTSimulate dot/dash paddle press/release

Networking

RouteMethodDescription
/peersGETDevice identity + discovered peers
/send_to_peerPOSTSend message to another Pi
/receive_morsePOSTReceive incoming Morse from peer
/net_statusGETPeers + inbox + live receive fields + TX mode/mute config
/net_key_modePOSTEnable/disable keyed-message mode
/net_key_pressPOSTRecord local key press/release for keyed-message mode
/net_clear_morsePOSTClear keyed-message buffers
/net_send_morsePOSTSend buffered keyed Morse message to selected peer
/net_live_transmit_setPOSTToggle this device On Air / Off Air (Off Air blocks live TX/RX)
/net_live_configPOSTSet live TX mode (single/selected/all_on_air), selected peers, and muted peers
/net_live_transmit_symbolPOSTForward live dot/dash symbol events to a peer
/net_receive_live_symbolPOSTReceive live dot/dash symbol events from peer
/net_live_keyPOSTForward live key down/up events according to current TX mode
/net_receive_live_keyPOSTReceive live key down/up events from peer (filtered by Off Air / receive enabled / muted sender)

USB HID keyboard

RouteMethodDescription
/kb_statusGETHID keyboard status
/kb_enablePOSTEnable/disable keyboard mode
/kb_modePOSTSet letters or custom mode
/kb_set_keysPOSTSet custom dot/dash key mappings

Project Structure

Morse-Pi/
├── install.sh                  ← fresh installer — Python backend
├── install-rust.sh             ← fresh installer — Rust backend
├── transition-rust.sh          ← transition script: Python → Rust
├── update.sh                   ← updater — Python backend
├── update-rust.sh              ← updater — Rust backend (pull + rebuild)
├── packages.sh                 ← package updater (Python: upgrade apt + pip)
├── docs/                       ← documentation site (GitHub Pages)
│   ├── index.html              ← home / landing page
│   ├── getting-started.html    ← features, install, wiring, modes guide
│   ├── maintenance.html        ← updating, packages, services
│   ├── usb-hid.html            ← USB HID keyboard setup & usage
│   ├── reference.html          ← morse table, settings, API, structure
│   ├── troubleshooting.html    ← common issues & error solutions
│   └── style.css               ← shared stylesheet
├── morse-translator/           ← Python backend (Flask)
│   ├── app.py                  ← Flask app, GPIO, Morse timing, networking, HID
│   ├── settings.json           ← user settings (auto-created, preserved on update)
│   ├── stats.json              ← user statistics (auto-created, preserved on update)
│   ├── words.json              ← word list for quiz/speed modes
│   └── templates/
│       ├── index.html          ← single-page web UI
│       ├── radio.html          ← dedicated radio control page
│       └── diag.html           ← GPIO live diagnostic popup
└── morse-translator-rust/      ← Rust backend (native binary)
    ├── Cargo.toml              ← Rust package manifest & dependencies
    ├── templates/              ← source templates synced into runtime app dir by install/update scripts
    │   ├── index.html
    │   ├── radio.html
    │   └── diag.html
    └── src/
        ├── main.rs             ← HTTP server, routing, template engine
        ├── state.rs            ← settings, stats, app state, JSON serialization
        ├── morse.rs            ← Morse code translation, word lists, phrases
        ├── keyboard.rs         ← USB HID keyboard via /dev/hidg0
        ├── gpio.rs             ← GPIO via pigpiod_if2 C FFI
        ├── sound.rs            ← tones, iambic keyer, send/speed/net modes
        └── network.rs          ← UDP beacon peer discovery

# Created by installer on Raspberry Pi:
/etc/systemd/system/morse-pi.service       ← auto-start on boot
/etc/systemd/system/morse-pi-hid.service   ← USB HID gadget service
/usr/local/bin/morse-pi-hid-setup.sh       ← USB HID configuration script
/etc/udev/rules.d/99-morse-pi-hid.rules    ← udev rule for /dev/hidg0