Field Guide · term

Also known as: SACCH, slow associated control channel

The NXDN Slow Associated Control Channel (SACCH) is the low-rate signalling channel that rides alongside every NXDN frame, carrying the per-frame housekeeping — the RAN, call state, and other control fields — underneath live traffic without stealing the frame’s payload.1 Each frame transmits a 60-bit SACCH block coded from just 32 information bits (26 payload bits plus a 6-bit CRC), so one frame alone is too small to hold a full control message; the receiver accumulates SACCH fragments across a superframe and reassembles the complete message.2

26 + CRC-6 = 32 bits +tail → 36 conv → 72 puncture drop 12 → 60 interleave 60 bits on air / frame fragment per frame reassembled message (superframe)
Each frame's SACCH codes a 32-bit block (26 payload + 6-bit CRC) into 60 on-air bits through tail-padding, half-rate convolution, puncturing, and interleaving; because one fragment is small, the receiver accumulates fragments across a superframe to rebuild the full control message.

The coding chain

The 32-bit information block is 26 payload bits followed by a 6-bit CRC computed over those 26 (NXDN’s CRC-6 uses the polynomial g(x) = x⁶ + x + 1). Four zero tail bits are appended so the encoder ends in state 0, giving 36 input bits. Those pass through a constraint-length-5, rate-½ convolutional code — generators g1 = 1+D³+D⁴ (octal 31) and g2 = 1+D+D²+D⁴ (octal 27), the same code the CAC uses — producing 72 channel bits. Twelve fixed positions are then punctured away (the drop list is evenly spaced, every sixth bit starting at position 5), leaving 60, and a 60-position interleaver permutes them so a burst on the channel scatters into isolated errors. The output is the 60 bits transmitted in the frame’s SACCH slot.

The receiver inverts this exactly: deinterleave, depuncture (inserting a zero-cost sentinel at the 12 dropped positions), Viterbi decode over 36 stages with the end-state constrained to 0, strip the 4 tail bits, and verify the CRC-6 over the recovered 26-bit payload. The decoder also returns the Viterbi path metric — zero means a clean decode — so the caller has a soft-quality read alongside the hard CRC pass/fail.

Fragment reassembly

A 26-bit payload cannot hold a whole control message, so NXDN treats the SACCH as a low-throughput pipe: successive frames each carry one fragment of a longer message, and the receiver stitches the fragments back together across a superframe before acting on the result. This is the deliberate trade the “slow” in Slow Associated Control Channel names — it accepts a superframe of latency in exchange for a steady signalling channel that runs continuously beneath voice or data without ever pre-empting the frame’s information field. A message is only trusted once every fragment has arrived and the reassembled block passes CRC.

Relevance to SDR

internal/radio/nxdn/sacch.go implements the chain end to end: EncodeSACCH builds a 60-bit block from 32 info bits, DecodeSACCH runs the deinterleave / depuncture / Viterbi / CRC-6 inverse and returns the decoded bits plus the path metric, and SACCHCRC6 / VerifySACCHCRC6 handle the 6-bit trailer. The interleave permutation and puncture list come from cross-referenced public NXDN decoders and are pinned in the source. Because the SACCH is where the RAN and call state live, decoding it reliably is what lets GopherTrunk tell one co-channel system from another and track call progress frame by frame — the CRC-6 pass is the gate that keeps a corrupted fragment from poisoning the reassembled message.

Sources

  1. NXDN — Wikipedia, on the NXDN standard and its associated control channels. 

  2. Convolutional code — Wikipedia, on the encoder and Viterbi decoding the SACCH uses. 

See also