Also known as: embedded LC, embedded link control, BPTC(128,72)
The DMR embedded LC is the Full Link Control PDU a voice call carries inside its own signalling, protected by a variable-length BPTC(128,72) product code.1 A voice superframe cannot spare a whole burst for link control, so it spreads a 72-bit LC block across the 32-bit EMB fragments of bursts B, C, D and E; the receiver concatenates those four fragments into 128 channel bits and runs a BPTC-style two-dimensional decode to recover the 72 LC bits.2
The code
GopherTrunk implements the decode in internal/radio/framing/embedded_bptc.go, matching the
de-facto MMDVM reference verified against ETSI Annex B/C:
- Deinterleave the 128 on-air bits into an 8-row × 16-column matrix with
data[b] = onair[a],b += 16wrappingb -= 127whenb > 127. - Row Hamming. Rows 0–6 are each a shortened Hamming(16,11,4) codeword — data in columns
0–10, parity in columns 11–15. The code is SEC-DED:
decodeEmb16114corrects one bit error per row (by trial flip until the 5-bit syndrome clears) and detects two; any uncorrectable row fails the block. - Column parity. Row 7 holds even parity down each column, so every column of the full 8-row matrix must XOR to 0 — a second interleaving dimension that catches errors a row pass alone misses.
- 5-bit checksum. The 72 LC bits are read from rows 0–6 columns 0–10, except that column 10
of rows 2–6 carries the five bits of a checksum. That checksum is the sum of the nine LC octets
modulo 31 (
embFiveBit); it must match the recovered LC.
The 72 LC bits come out of extractEmbLC in the order the embLCRanges table defines — rows
0–6 columns 0–10, but only columns 0–9 for rows 2–6. DecodeEmbeddedLC returns the LC and a
corrected-bit count, or −1 if any row was uncorrectable, the column parity failed, or the
checksum did not verify.
Why three checks
The three integrity layers are complementary. The row Hamming codes locate and flip isolated bit
errors; the column parity crosses them so a burst that survives one row lands under a column that
can still catch it; and the mod-31 checksum is an independent end-to-end verifier that guards
against a Hamming pass mis-correcting into a valid-but-wrong codeword. Only when all three agree
does GopherTrunk treat the 72 bits as a genuine LC. ReassembleEmbeddedLC
(internal/radio/dmr/emb.go) then parses those bits as a Full LC — and because this whole block is
the integrity gate, the EMB’s own QR(16,7) FEC and the per-context
RS(12,9) parity can be deferred without admitting bad LCs.
Relevance to SDR
The embedded LC is what lets GopherTrunk label a DMR voice call it is already decoding. Burst A’s
sync word is BS-sourced and identical on both timeslots, so it cannot say which talkgroup a call
belongs to; the embedded LC’s destination and source addresses can, and its successful BPTC + CRC
decode is authoritative enough that the interleaved voice decoder locks its TDMA cadence the moment
one appears (see resolveAndSlice). Recovering it correctly from four fragments spread across four
bursts — deinterleave, two Hamming/parity dimensions, and the mod-31 check — is the difference
between reporting a talkgroup and a source radio versus hearing anonymous audio.
Sources
-
Digital mobile radio — Wikipedia, on the DMR standard and its embedded link control. ↩
-
Hamming code — Wikipedia, on the row component code of the embedded BPTC. ↩