Patrick Lidstone
Self-hosted

MT63 — native 64-carrier Walsh-spread DBPSK OFDM modem

The keyboard mode built like a broadcast system: every 6-bit character symbol is spread across all 64 OFDM carriers by a Walsh(64) codeword, differentially BPSK-keyed per carrier so no phase reference is needed, and block-interleaved in time — so neither a notch that kills carriers nor a burst that kills symbols can destroy a character.

Rafe project · app/radio/mt63.py, test_mt63.py · RX + TX · clean-room implementation of the MT63 (SP9VRC) architecture; exact fldigi wire-format interop (tone spacing per bandwidth, interleave geometry, secondary channel) is a named refinement


Abstract

MT63 (Pawel Jalocha SP9VRC's design, ubiquitous via fldigi and EmComm practice) takes the opposite bet from the narrowband keyboard modes: instead of concentrating each character's energy in one place and protecting it with a code, it smears every character over the whole channel and a long span of time, so that interference has to take out everything to take out anything. Three techniques do this, and Rafe's implementation captures all three in their standard form:

  1. OFDM with 64 carriers, differentially BPSK-modulated per carrier (each OFDM symbol's carrier phases are decoded against the previous symbol's — no carrier-phase tracking, the DAB trick at HF scale).
  2. Walsh(64) spreading across frequency: a 6-bit symbol selects one of the 64 orthogonal Walsh rows, and that ±1 row is the per-carrier bit pattern for the OFDM symbol. Decoding is a correlation against all 64 rows — a fast Walsh transform and an argmax, i.e. a soft-decision [64,6] block decode (see Olivia for the same code used tone-wise).
  3. Block interleaving across time (depth 8 symbols here), so a time-domain burst is dispersed over many characters.

This document pins the implementation exactly: the Walsh construction, the text↔︎symbol packing, the interleaver, the modulator's reference symbol and phase accumulation, and the correlation decoder — plus the deliberate, documented deltas from fldigi's wire format (§6).


1. The pieces and their constants

Parameter Value Code
Carriers 64 N_TONES = 64
Bits per symbol 6 (= one of 64 Walsh rows) BITS_PER_SYM = 6
Spreading code Walsh/Hadamard 64×64, ±1, Sylvester construction WALSH = _hadamard(64)
Per-carrier modulation DBPSK (phase increment 0 or π) phase += π·bits
OFDM symbol 64-point IFFT, norm="ortho", no cyclic prefix np.fft.ifft(...)
Interleaver block, 8 columns, write rows / read columns, zero-pad INTERLEAVE = 8
Reference symbol one leading OFDM symbol with all carriers at phase 0 ifft(ones(64))
Character set 8-bit ASCII packed into 6-bit symbols, MSB first text_to_symbols

The Walsh matrix is the standard Sylvester doubling \(H_{2n} = \begin{bmatrix}H_n & H_n\\ H_n & -H_n\end{bmatrix}\) from \(H_1=[1]\); row orthogonality (\(W W^{\top} = 64I\)) is asserted outright in the test suite. Row 0 is all +1 (symbol 0 = "no phase flips").

2. Transmit chain, step by step

modulate(text):

  1. Pack text — ASCII bytes → bitstream → 6-bit groups MSB-first → symbol values 0–63 (zero-padded to a whole symbol).
  2. Interleave — write the symbol sequence into an 8-column matrix by rows (zero-pad), read it out by columns.
  3. Reference symbol — emit one OFDM symbol with every carrier at phase 0 (IFFT of the all-ones spectrum). This anchors the differential chain, exactly like DAB's phase-reference symbol.
  4. Per symbol: look up WALSH[s]; map +1 → bit 0, −1 → bit 1; add π·bit to each carrier's running phase (the accumulation is what makes it differential); emit the 64-sample IFFT of \(e^{j\,\text{phase}}\).

Output is complex baseband at 64 samples per OFDM symbol; the sample rate (hence bandwidth and baud) is the caller's choice — see §6 for how the real mode names its variants.

3. Receive chain, step by step

demodulate(iq) / decode(iq):

  1. Reshape the input into consecutive 64-sample blocks and FFT each (norm="ortho"); the symbol count is inferred from the input length.
  2. For each symbol \(t \ge 1\): per-carrier differential phase \(\Delta\varphi = \arg\big(T_t \cdot \overline{T_{t-1}}\big)\); slice to a ±1 pattern by \(|\Delta\varphi| \le \pi/2 \Rightarrow +1\) (no flip), else −1.
  3. Walsh correlation: multiply the 64-long ±1 pattern against all 64 rows (one matrix–vector product = the fast Walsh transform's job) and take the argmax as the symbol. A perfect symbol scores 64; because the rows are orthogonal, a competing row scores 0 in the clean case, and the decision degrades gracefully — half the carriers must be wrong before a wrong row can win (maths guide §11.6).
  4. De-interleave the symbol stream, unpack 6-bit groups to bytes, strip trailing NULs.

4. Why it holds up under abuse

  • A frequency notch (multipath null, heterodyne) removes a few carriers: every Walsh correlation loses those chips equally, so every character loses a little margin and none is destroyed.
  • A time burst hits consecutive OFDM symbols: the depth-8 interleaver hands the damage to 8 different characters, each of which shrugs it off.
  • Phase drift / no tuning reference: DBPSK per carrier means only symbol-to-symbol phase changes matter; the reference symbol starts the chain and nothing else needs to be tracked.

The test suite quantifies it: exact text through complex AWGN at 0.3× and 0.6× signal power (and 0.4× on a longer message) with no equaliser and no explicit sync beyond block alignment.

5. Validation

Test Asserts
test_symbol_text_roundtrip ASCII ↔︎ 6-bit symbol packing is lossless
test_walsh_orthogonal \(WW^{\top} = 64I\) exactly
test_interleaver_bijective interleave/de-interleave identity (with padding)
test_modem_clean modulate → demodulate → identical text
test_modem_noise exact text at noise levels 0.3 and 0.6
test_modem_longer_text 78-char message at 0.4 noise

6. Deltas from the fldigi wire format (named refinements)

This implementation is the MT63 architecture — Walsh spreading × DBPSK OFDM × interleaving — as a complex-baseband modem. To interoperate with fldigi/original MT63 on the air, the remaining items are wire-format specifics, listed so nothing is silently claimed:

  • Audio placement and rates. Real MT63 variants are named by bandwidth: 500/1000/2000 Hz wide, 5/10/20 baud, 64 tones spaced baud/2 apart starting ~500 Hz into the passband. Here the modem is sample-rate-agnostic complex baseband; the passband mapping is the caller's.
  • Interleave geometry. The original uses a long bit-level diagonal interleaver (selectable 32 or 64 symbol "short/long" depths) spreading each character over seconds; here a symbol-level block interleaver of depth 8 captures the technique with lighter latency.
  • Character coding. The original spreads each 7-bit character over two Walsh halves with its own mapping and adds a low-rate secondary channel (idle CW ID); here characters are straight 8-bit ASCII packed into 6-bit symbols.
  • Sync. fldigi acquires symbol alignment from the signal itself; here block alignment is assumed (the reference symbol resolves phase, not timing).

The round-trip robustness above is therefore a property of the architecture, demonstrated natively; on-air fldigi interop is tracked in native-protocols.md as the refinement step.


Related: Olivia/Contestia (the same Walsh block code across MFSK tones), DAB (per-carrier DQPSK against a phase-reference symbol), HamDRM (full OFDM with pilots on the same HF channels), and the maths guide on OFDM and Walsh codes.