Also known as: dPMR FEC, dPMR channel coding
dPMR channel coding is the forward-error-correction that protects a dPMR CSBK or traffic payload as it crosses a noisy 4FSK channel.1 Per ETSI TS 102 658 §6, dPMR wraps its payload bits in a short-block cyclic code under a rate-¾ convolutional outer code, then interleaves the result across the burst so a fade turns into scattered single errors the decoder can repair.2 GopherTrunk currently parses dPMR at the layer above this stage — an honest, documented deferral covered below.
What the coding does
The three stages each answer a different failure mode. The short-block cyclic code adds a small number of parity bits so the receiver can detect — and for the shortest blocks, correct — a handful of bit errors, and it doubles as an integrity check like a CRC. The rate-¾ convolutional outer code spreads each input bit’s influence across several output bits, so a Viterbi-style decoder can reconstruct the original stream even where individual bits were lost; the ¾ rate keeps the overhead modest, appropriate for dPMR’s narrow 6.25 kHz channel where bandwidth is scarce. The interleaver then reorders the coded bits so that a burst error on the channel — a fade lasting several symbols — is spread out into isolated single-bit errors once de-interleaved, which is exactly the error pattern the cyclic and convolutional decoders handle best. Together they let a marginal dPMR signal deliver a correct CSBK where an uncoded block would be discarded.
The implementation gap
GopherTrunk is deliberate about what it has and has not built. Its dPMR package ships a clean structured surface — frame sync detection, CSBK parsing, the opcode enum, the band-plan resolver, and the trunking state machine — so the engine can consume grants end-to-end against fixtures. The CSBK parser, though, assumes the upstream caller has already corrected errors: it maps 80 clean bits into fields, and the FEC that would produce those 80 clean bits from an on-air burst is listed among the package’s honest deferrals. The source names the missing pieces explicitly: the interleaver plus the short-block-cyclic / rate-¾-convolutional FEC over the CSBK bits, the 4FSK demodulator and symbol-clock recovery for the 2400 sym/sec air interface, and voice-frame extraction into the AMBE+2 vocoder. Flagging these as named follow-ups — rather than silently shipping a half-built decoder — is a deliberate choice: the structured layer is testable now against pre-corrected fixtures, and the FEC slots in beneath it without changing the surface above.
Relevance to SDR
internal/radio/dpmr/dpmr.go documents this boundary in the package doc comment, and the
parsing in csbk.go operates on the post-FEC bit layer. For a live off-air dPMR control channel
the chain would be: 4FSK demod → FS3 sync → de-interleave → convolutional + cyclic decode →
80-bit CSBK → parse. Today GopherTrunk implements the sync-and-parse ends of that chain and
defers the demod-and-FEC middle, which is the correct order for a decoder built against captured
and replayed fixtures: the structured trunking logic is proven first, and the error-correction
that feeds it is added as a self-contained stage once conformance vectors are in hand.
Sources
-
dPMR — Wikipedia, on the ETSI dPMR standard and its physical layer. ↩
-
Convolutional code — Wikipedia, on the outer code family dPMR’s channel coding uses. ↩