Field Guide · algorithm

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

11 data cols 5 parity row 7 · column parity rows 0–6: Hamming(16,11,4) col 10 of rows 2–6 → 5-bit mod-31 checksum
The 128 channel bits deinterleave into an 8×16 matrix: seven Hamming rows, an eighth column-parity row, and five checksum cells; the 72 LC bits are read from the data columns.

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:

  1. Deinterleave the 128 on-air bits into an 8-row × 16-column matrix with data[b] = onair[a], b += 16 wrapping b -= 127 when b > 127.
  2. 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: decodeEmb16114 corrects one bit error per row (by trial flip until the 5-bit syndrome clears) and detects two; any uncorrectable row fails the block.
  3. 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.
  4. 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

  1. Digital mobile radio — Wikipedia, on the DMR standard and its embedded link control. 

  2. Hamming code — Wikipedia, on the row component code of the embedded BPTC. 

See also