Field Guide · algorithm

Also known as: IMBE deinterleaver, IMBE 4400 interleaver, §7.5 interleaver

The IMBE interleaver is the final channel-coding step (TIA-102.BABA §7.5) applied to a P25 Phase 1 voice subframe: a fixed permutation that reorders all 144 channel bits so the bits of any one FEC codeword end up scattered across the whole burst rather than sitting adjacent.1 Its purpose is the classic interleaving trick — a fade or noise burst that would wipe out a run of consecutive bits instead knocks out a single bit from each of several Golay and Hamming codewords, where the per-vector FEC can correct it.

one codeword's bits on-air burst (interleaved)
The interleaver scatters each codeword's adjacent bits across the 144-bit burst, so a contiguous burst error strikes only one bit per codeword — recoverable by the per-vector FEC.

How it works

The permutation is a bijection of the integers 0–143: imbeDeinterleave[v] gives the on-air bit index that supplies vector-order bit v. GopherTrunk derives it from DSD’s published P25 Phase 1 schedule — the iW/iX/iY/iZ tables that map each on-air voice dibit’s two bits into the imbe_fr[row][col] vector array — remapped onto this package’s u_0u_7 vector layout. A slice of the resulting table shows the scatter:

var imbeDeinterleave = [144]int{
    132, 127, 120, 115, 108, 103, 96, 91, 84, 79, 72, 67,
    60, 55, 48, 43, 36, 31, 24, 19, 12, 7, 0, 126,
    // … 120 further entries, one per channel bit …
}

Consecutive vector-order positions map to widely separated on-air positions (132, 127, 120, 115, …), which is exactly the spread that turns an on-air burst into isolated single-bit hits. The DSD schedule expresses the same permutation over the 72 on-air voice dibits: each dibit’s two bits are placed into imbe_fr[iW[j]][iX[j]] and imbe_fr[iY[j]][iZ[j]], and mapping those row/column coordinates onto this package’s u_0u_7 layout reproduces the table above exactly. Because the table is a pure permutation, Deinterleave and Interleave are the same mapping applied in opposite directions — no separate inverse table is stored, so the two can never drift apart.

The bijection guard

A permutation table is only correct if it is a genuine bijection — every output index used exactly once. A table that mapped two vector bits to the same on-air bit (or left a bit unassigned) would silently corrupt every voice frame while still looking plausible. GopherTrunk refuses to ship such a table: an init() guard walks the array at package load, panics if any entry is out of range, and panics if any on-air index is claimed twice. Failing loudly at startup is preferable to shipping a subtly-wrong codec that mis-decodes only on real signals. A companion test, TestInterleavePermutationIsBijection, pins the same property in CI.

The receive order lesson

Interleaving is undone first in the receive chain, and the order is not negotiable: deinterleave → descramble → per-vector FEC decode. The descrambler’s u_0 seed is only valid once the bits are back in vector order, so deinterleaving must precede it. Omitting the deinterleave step entirely was GopherTrunk issue #489: the per-vector FEC then decoded interleaved garbage and the decoder reported roughly 100% uncorrectable LDUs on real signals, even though every synthetic round-trip test passed — a self-consistent bug, because the encode side had made the same omission. Reinstating the DSD-sourced permutation, verified against mbelib/DSD-faithful reference vectors, made a real P25 voice subframe decode bit-for-bit.

Relevance to SDR

Every P25 Phase 1 LDU carries nine 144-bit IMBE subframes, and each one enters GopherTrunk’s decoder through this permutation. The interleaver contributes no error correction of its own — it only rearranges the burst structure so the Golay and Hamming stages can do their work — but its correctness is a precondition for everything downstream. A wrong permutation, or the wrong receive order, presents the FEC with scrambled input and the call never decodes, which is precisely the failure #489 recorded.

Sources

  1. Burst error-correcting code — Wikipedia, on interleaving as a means of spreading burst errors across independent codewords. 

See also