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
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
-
Burst error-correcting code — Wikipedia, on why contiguous channel errors are the hard case and how interleaving disperses them. ↩
-
Interleaving — Wikipedia, on the block-interleaving read/write permutation. ↩