radio-utils-cw-decoder 0.1.1

Streaming CW (Morse) decoder — no_std, no alloc
Documentation
  • Coverage
  • 100%
    10 out of 10 items documented0 out of 8 items with examples
  • Size
  • Source code size: 34.64 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 205.15 kB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 3s Average build duration of successful builds.
  • all releases: 3s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • SP5TLS/radio-utils
    2 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • kosciej

radio-utils-cw-decoder

Streaming CW (Morse code) decoder in Rust — no_std, no allocator, suitable for use inside an interrupt-priority task on bare-metal microcontrollers.

All state lives inline in [Decoder]: a packed u8 accumulator for the in-flight character and a 32-entry heapless::Deque of recently decoded ASCII bytes. The recent-history ring evicts oldest-first on overflow.

Features

  • Streaming, edge-driven: feed every key-line transition; the decoder updates in O(1) per edge.
  • Sender-WPM aware: dit / dah / inter-character / inter-word thresholds derive from the sender's WPM passed in on each call, so the same Decoder adapts as the sender changes speed.
  • Poll-flushed: a periodic [Decoder::poll] call drains the last character of a transmission once the inter-character silence threshold elapses — without it the trailing character would only appear when the next key-down arrives.
  • Idempotent during sustained silence: repeated polls while the key is up emit at most one character and at most one inter-word space.
  • No panics: invalid / overflowed in-flight characters are silently dropped; out-of-range gap measurements saturate.

Usage

use radio_utils_cw_decoder::Decoder;

let mut d = Decoder::new();
let wpm = 20;

// On every key-line edge:
d.on_transition(now_us, /* key_down = */ true,  wpm);
// … key held for a dit / dah …
d.on_transition(now_us, /* key_down = */ false, wpm);

// Periodically (e.g. from a UI tick) so the trailing character of a
// transmission flushes during silence:
d.poll(now_us, wpm);

// Read out the recent-history ring:
let mut buf = [0u8; 32];
let n = d.snapshot(&mut buf);
let decoded = &buf[..n]; // ASCII, oldest-first

The decoder is const fn new(), so it can be placed in a static and shared between an interrupt-priority writer and a low-priority reader through a blocking_mutex<CriticalSectionRawMutex, RefCell<Decoder>> without lazy initialisation.

Building

cargo build --release -p radio-utils-cw-decoder

no_std is the only mode — no Cargo features.

License

Dual MIT / Apache-2.0 — see LICENSE-MIT and LICENSE-APACHE.