A correctness-first WSPR reference encoder/decoder with explicit ambiguity handling.
cmake -S . -B build
cmake --build build
./build/wspr-encode K1ABC FN20 30
./build/wspr-decode --quiet 330020021022111022120121133220000232032322002012130033030021303020033032301010232030110201323012223220221021021112330211212021312202030320112222222330323322013222
./build/wspr-correlate --quiet 330220021020113022100321133020200230032120022210130233030001301022033232321210012232130003103030203220001221023112330233230223312202030122132020202132103322031020 332002201020111022320121311022222212032302022230130033230021301202031232301032230032310221303032221222201023223312130031030203132200010100132000220330303120213202This project is a clean, testable WSPR reference implementation focused on correctness, transparency, and reproducibility.
It supports:
- Type 1 messages
- Type 2 messages, including prefix and suffix forms
- Type 3 messages with hashed callsign and 6-character locator
- Type 2 and Type 3 correlation
- Human-readable, quiet, and JSON CLI output modes
- Regression coverage for known ambiguity in the Type 2 overlap region
- A reusable, installable C++ library API
wspr-encodewspr-decodewspr-correlatewspr_ref_lib- Regression suite
- API example
./build/wspr-encode K1ABC FN20 30
./build/wspr-encode --quiet K1ABC FN20 30
./build/wspr-encode --symbols-only K1ABC FN20 30
./build/wspr-encode --json K1ABC FN20 30Default output:
Type: TYPE1
Callsign: K1ABC
Locator: FN20
Power: 30 dBm
Symbols: 330020021022111022120121133220000232032322002012130033030021303020033032301010232030110201323012223220221021021112330211212021312202030320112222222330323322013222
JSON output:
{
"type": "TYPE1",
"callsign": "K1ABC",
"locator": "FN20",
"power_dbm": 30,
"symbols": "330020021022111022120121133220000232032322002012130033030021303020033032301010232030110201323012223220221021021112330211212021312202030320112222222330323322013222"
}./build/wspr-decode <symbols>
./build/wspr-decode --quiet <symbols>
./build/wspr-decode --json <symbols>Quiet output examples:
TYPE1 K1ABC FN20 30
TYPE2 <hashed> /09 30 ALT /Z
TYPE3 <hashed> 6521 FN20AB 30
JSON fields:
{
"type": "TYPE2",
"callsign": "<hashed>",
"power_dbm": 30,
"is_partial": true,
"has_hash": false,
"has_ambiguity": true,
"extra": "/09",
"alternate_extra": "/Z"
}When no message type unpacks successfully, --json emits:
{
"type": "UNKNOWN",
"error": "No message type unpack succeeded."
}./build/wspr-correlate <symbols1> <symbols2>
./build/wspr-correlate --quiet <type2> <type3>
./build/wspr-correlate --json <type2> <type3>Quiet output examples:
CORRELATED TYPE2 <hashed>/12 6521 FN20AB 30
CORRELATED TYPE2 <hashed>/09 6521 FN20AB 30 ALT /Z
UNCORRELATED1 TYPE2 <hashed> /12 30
UNCORRELATED2 TYPE3 <hashed> 6521 FN20AB 30
Correlated JSON output:
{
"type": "TYPE2",
"callsign": "<hashed>/12",
"power_dbm": 30,
"is_partial": true,
"has_hash": true,
"has_ambiguity": false,
"locator": "FN20AB",
"hash": 6521,
"status": "CORRELATED"
}Uncorrelated JSON output contains:
{
"status": "UNCORRELATED",
"message1": {
"type": "TYPE2"
},
"message2": {
"type": "TYPE3"
}
}Overlap region:
/Z ⇄ /09
/Q ⇄ /00
Policy:
- Deterministic primary decode
- Alternate preserved
- No silent loss
./tests/run_major_regressions.shOverlap cases are observational, not failures.
auto encoded = wspr::encode_message("K1ABC", "FN20", 30);cmake -S . -B build
cmake --build build
cmake --install build --prefix ./installThis installs the library, all public-facing headers under include/wspr/, and
the exported CMake package files under lib/cmake/wspr_ref/.
find_package(wspr_ref CONFIG REQUIRED)
target_link_libraries(my_app PRIVATE wspr::wspr_ref_lib)If installed under a custom prefix, point CMake at it:
cmake -S examples/consumer -B build-consumer -DCMAKE_PREFIX_PATH="$PWD/install"
cmake --build build-consumer
./build-consumer/consumerMinimal consumer:
#include "wspr/wspr_ref_api.hpp"
#include <iostream>
#include <string>
int main()
{
const auto encoded = wspr::encode_message("K1ABC", "FN20", 30);
if (!encoded.ok)
return 1;
wspr::WsprDecodedMessage decoded;
std::string error;
if (!wspr::decode_symbols(encoded.symbols, decoded, error))
return 1;
std::cout << decoded.callsign << "\n";
return 0;
}- Core features complete
- Ambiguity handling complete
- Library export complete
- External consumption verified
MIT License