Ordo Artificum / CodeMonkey

CodeMonkey

CW Decoder, Keyer & Waterfall

Early Alpha

What is CodeMonkey?

CodeMonkey is a desktop application for Linux that decodes and transmits Morse code (CW) in real time. It listens to your radio through the sound card, displays a live scrolling waterfall of the received audio spectrum, and continuously decodes any CW signal you click on. When transmitting, it encodes plain text to Morse and keys your radio through a serial port line or a GPIO pin — with full Farnsworth timing for slow practice. If you have a Hamlib-compatible transceiver, CodeMonkey connects to it automatically and lets you retune to the center of any signal with a single click.

What it does

WebSocket API

CodeMonkey exposes a full WebSocket API on TCP port 2104 (configurable). Decoded characters, decoder status, radio frequency, PTT state, and transmission control are all available programmatically. The API uses plain JSON over WebSocket.

View WebSocket API documentation →

OTA Integration

CodeMonkey integrates with OTA, our SOTA/POTA spot hunter, via a built-in WebSocket bridge. OTA connects to CodeMonkey and delegates all radio control to it. When OTA selects a CW spot, it sends the frequency to CodeMonkey via the bridge; CodeMonkey automatically adjusts the VFO to place the incoming signal under the decoder tone marker. No manual offset calculation required.

Learn more about OTA →

Alpha notice

CodeMonkey is early alpha software. The decoder works and is used on the air, but the interface is still evolving and there are known rough edges. Alpha builds expire 30 days after their compile date — download a fresh build when yours expires.

Bug reports and feedback are welcome.

Download

Linux x86-64 only for now. All binaries are unsigned alpha builds.

Linux GUI
x86-64 • AppImage • Ubuntu 22.04+
Download AppImage
CW Decoder
x86-64 • CLI • codemonkey-decode
Download Binary
CW Encoder
x86-64 • CLI • codemonkey-encode
Download Binary

Installation

Linux GUI (AppImage)

  • 1.Download the AppImage and make it executable: chmod +x CodeMonkey-*.AppImage
  • 2.Run it: ./CodeMonkey-*.AppImage
  • 3.No installation required. Qt, Hamlib, and PortAudio are bundled inside the AppImage.
  • The AppImage also includes the codemonkey-decode and codemonkey-encode CLI tools.

CLI tools

  • 1.Download and make executable: chmod +x codemonkey-decode codemonkey-encode
  • 2.The CLI tools link against system libraries. Install: sudo apt-get install -y libportaudio2
  • Pipe audio data to codemonkey-decode, or pass text to codemonkey-encode to produce a WAV file.

How the decoder works

CodeMonkey’s decoder is built around a narrow-band I/Q demodulator and a probabilistic character matcher, inspired by the approach used in VE3NEA’s CW Skimmer. Rather than making hard threshold decisions at each step, it propagates confidence scores through the decoding pipeline so that ambiguous timing and noisy signals produce the most likely interpretation rather than garbage.

1. Resampling

Audio from the sound card (at any sample rate the system provides) is resampled to an internal rate of 8 000 Hz. The lower rate reduces CPU load for all downstream stages while comfortably covering the 0–4 kHz audio passband used on HF.

2. I/Q demodulation

The resampled audio is mixed with a cosine and a sine at the selected tone frequency to produce in-phase (I) and quadrature (Q) components. A low-pass Butterworth IIR filter (cutoff ≈ 200 Hz) is applied to both channels to isolate the baseband signal from adjacent QRM. The instantaneous signal strength (envelope) is computed as √(I² + Q²). This narrow, phase-coherent demodulation rejects adjacent signals and achieves a much cleaner envelope than simple rectification or energy detection.

3. Automatic gain control

An AGC stage normalizes the envelope to the 0–1 range using asymmetric time constants: fast attack (proportional to the estimated dit length) to track a suddenly stronger signal, and slow decay to avoid misreading the spaces between characters as signal loss. This makes the decoder insensitive to absolute signal level and allows it to follow fading without requiring manual gain adjustment.

4. Dual-threshold keying detection

A hysteresis comparator with upper threshold 0.60 and lower threshold 0.35 converts the normalized envelope to a binary key stream (mark / space). The gap between thresholds suppresses chatter at transitions caused by noise or signal flutter, producing a clean key-up / key-down event stream.

5. Adaptive timing analysis

The durations of successive marks and spaces form a bimodal histogram: one cluster for dits (and inter-element spaces), another for dahs (and inter-character/inter-word spaces). The decoder continuously fits this histogram to extract the current dit length in real time, tracking speed changes from approximately 5 WPM to 50 WPM without any manual adjustment. The PARIS standard (50 dit-equivalents per word) is used to convert dit length to words per minute.

6. Probabilistic character matching

Each mark or space is scored against the current timing model as a probability of being a dit, dah, inter-element space, inter-character space, or word space. These probabilities propagate through a Morse trie (binary decision tree, depth ≤ 6) to produce a weighted score for every candidate character at each branch. The highest-scoring leaf node wins. This approach — never making a hard timing decision early — is the core insight from CW Skimmer that lets it outperform threshold-only decoders on marginal signals and irregular fists.

7. Farnsworth timing (TX)

When sending, Farnsworth mode transmits each character at the full selected WPM but stretches inter-character and inter-word spaces so that the effective throughput matches a lower “Farnsworth WPM”. The spacing is computed from the PARIS formula: inter-character space = 3× a scaled unit, word space = 7×, where the unit is chosen so that the overall average matches the target Farnsworth rate. This is the standard method used by ARRL code courses for building copy speed.

Radio control & hardware keying

Hamlib rig control

CodeMonkey integrates with Hamlib, the universal amateur radio control library, which supports over 400 radio models from Icom, Kenwood, Yaesu, Elecraft, FlexRadio, and many others. Set your rig model, serial port, and baud rate in the Radio Setup dialog; CodeMonkey will connect automatically on startup and reconnect every 15 seconds if the link is lost.

Once connected, the frequency display in the status bar shows the current VFO frequency in real time. The Center button retunes the radio so that the decoded signal aligns with your TX tone frequency — one click to zero-beat any station you can hear.

Serial port keying (RTS / DTR)

CodeMonkey can key a CW interface wired to the RTS or DTR line of any serial port. Use the Hamlib-connected rig port (shared mode) or a separate USB-serial adapter for a standalone keyer interface. Both lines support polarity inversion for interfaces that require an active-low key signal. Keying is synchronized with audio output so both paths fire simultaneously.

GPIO keying (Raspberry Pi)

On Raspberry Pi and other Linux single-board computers, CodeMonkey can key a transistor or relay directly from a GPIO pin using the Linux /sys/class/gpio sysfs interface. Select any BCM pin number in the Keying Setup dialog (default: GPIO 17). Polarity inversion is supported for active-low circuits. No additional drivers or libraries are required.

Requirements

About Ordo Artificum

Ordo Artificum LLC is a small software company building amateur radio tools.