Field Guide · algorithm

Also known as: MAC burst interleaver, Phase 2 block interleaver

The P25 Phase 2 MAC interleaver is the block interleaver that reorders a trellis-coded MAC burst before it goes on air.1 Its purpose is the classic one: a physical burst error on the channel — a fade, a click, an interfering hit — arrives as a contiguous run of corrupted dibits, and a run is exactly what the Viterbi trellis decoder handles worst. By permuting the burst at the transmitter and un-permuting it at the receiver, adjacent on-air errors are pulled apart so they land as isolated errors spread across the trellis decoder’s input, where the code can absorb them.2

write row-major → 01234 56789 read column-major → 0 5 1 6 2 7 3 8 4 9 burst hits 5,1 → originally-adjacent errors land half a burst apart at the trellis input
Writing row-major into a 2-row matrix and reading column-major interleaves the dibits; a burst that corrupts consecutive read-order positions un-maps to originally distant dibits, so the trellis sees isolated errors.

The permutation

GopherTrunk models the MAC interleaver as a 2-row block interleaver. The dibits are written into a 2 × N matrix in row-major order (fill row 0 left to right, then row 1), and read back out in column-major order (column 0’s two entries, then column 1’s, and so on). The read index for matrix position (row r, column c) is c·2 + r, and the de-interleaver applies the exact inverse — read column-major back into the row-major grid — so any originally-adjacent pair of dibits ends up half a burst apart. A slice whose length is not a multiple of the 2 rows is returned unchanged rather than being partially permuted, so a malformed input is a no-op instead of a corrupting operation. Because InterleaveMACBurst and DeinterleaveMACBurst are exact inverses, a synthetic fixture round-trips cleanly whether or not the modelled permutation matches the standard’s.

That inverse-pair property is what lets the code carry an explicit caveat: the exact permutation table is not in the repository’s spec PDFs. The 2-row model is the project’s working assumption — it delivers the burst-spreading the code exists to provide — and a spec correction is a single local change that both the encoder and decoder pick up together, with no downstream code needing to know.

Ordering in the FEC chain

Interleaving is undone before trellis decoding and after descrambling. The receiver’s Phase 2 chain is: descramble the raw channel dibits with the PN44 scrambler, then de-interleave, then run the trellis Viterbi decoder, then check the outer Reed-Solomon code. Placing the de-interleave between the descrambler and the trellis is precisely what turns a channel burst back into the isolated-error pattern the convolutional decoder was designed for.

The soft-decision path needs the same permutation applied to a parallel array. DeinterleaveMACBurstC de-interleaves a complex64 slice — the per-dibit differential soft sample — with the identical permutation as the hard dibits, keeping each soft reliability value aligned with its dibit through the interleaver so the soft Viterbi sees consistent inputs.

Relevance to SDR

internal/radio/framing/p25p2_interleave.go implements InterleaveMACBurst, DeinterleaveMACBurst, and the soft DeinterleaveMACBurstC. Getting the interleaver right is part of what lets a real Phase 2 MAC burst survive a channel hit and still decode to a valid opcode instead of being discarded — the same burst-resilience motive that recurs across digital radio. The spec is TIA-102.BBAC, with the exact table flagged as a working model pending a spec figure.

Sources

  1. Burst error-correcting code — Wikipedia, on why contiguous channel errors are the hard case and how interleaving disperses them. 

  2. Interleaving — Wikipedia, on the block-interleaving read/write permutation. 

See also