Also known as: DMO, direct mode operation, TETRA direct mode
TETRA DMO (Direct Mode Operation) is TETRA’s infrastructure-less peer-to-peer mode: two radios talk directly with no base station or control channel between them.12 A transmitting station sends a Direct Mode Synchronisation Burst (DSB) to let the other radios acquire, then a train of Direct Mode Normal Bursts (DNB) carrying the call. Because there is no trunking layer, the trunked-mode ingestion path — hunt a control channel, follow grants — does not apply; a DMO receiver instead camps a direct-mode channel, detects the DSB, and follows the burst train.
A reused physical layer
The DMO air interface reuses the trunked-mode (TMO) physical layer wholesale: identical π/4-DQPSK at 18 ksym/s, 25 kHz channels, 255-symbol (14.167 ms) TDMA timeslots, the four-slot frame / 18-frame multiframe, the same normal and synchronisation training sequences, and the same 32-tap scrambler polynomial (colour code 0 for the SCH/S and SCH/H of a DSB, exactly as TMO scrambles its BSCH). So the receiver, sync-word correlation and channel-coding machinery are shared between the two modes — only the burst field layout differs, which is the one thing DMO needs to add.
The channel coding is likewise not a new code family: DMO’s SCH/S, SCH/H, SCH/F and TCH/S run the same per-channel chains as their TMO logical-channel counterparts, so the existing decoders handle them once the blocks are sliced, de-rotated and descrambled. The only DMO-specific coding rules are the colour-0 seed for the DSB signalling blocks and the field boundaries below.
The two burst kinds
| Burst | Layout (relative to training-sequence lead dibit L) |
|---|---|
| DSB (sync) | 40-dibit frequency correction · 60-dibit SCH/S (120 type-5 bits, BKN1) · 19-dibit sync training sequence · 108-dibit BKN2 (216 bits) |
| DNB (normal) | 108-dibit BKN1 (216 bits) · 11-dibit normal training sequence · 108-dibit BKN2 (216 bits) |
The DSB is the acquisition burst: its frequency-correction field lets a cold receiver lock, and its SCH/S (the 120-bit block ahead of the sync training sequence) carries the synchronisation PDU — the DM colour code and the master’s slot/frame numbering used to anchor the DNB traffic that follows. The SCH/S decodes exactly like a TMO BSCH (colour 0). The DNB is the payload burst: its two 216-bit blocks carry either TCH/S speech (decoded to the two 137-bit ACELP frames by the shared TCH/S chain) or SCH/F short-data signalling — a receiver tells them apart by which decode’s CRC passes. The block boundaries relative to the training-sequence lead dibit are not the same as TMO’s NDB, so DMO needs its own slicer.
Configuring a DMO system
A DMO channel is decoded by setting a system’s protocol: tetra-dmo (aliases dmo /
tetra_dmo) and pointing control_channels at the direct-mode frequency — the daemon camps
that frequency rather than hunting, locks on the first DSB, auto-recovers the DM colour code,
and records the DNB voice train. An optional tetra_colour_code overrides the auto-recovery
when the traffic colour is known.
trunking:
systems:
- name: DMO
protocol: tetra-dmo
control_channels: [438900000]
# tetra_colour_code: 3 # optional; 0/omitted = auto-recover the DM colour
Scope and honesty
GopherTrunk decodes DMO end to end in the daemon: newTETRADMOPipeline
(internal/scanner/ccdecoder/pipelines_dmo.go) locks on the DSB SCH/S, recovers the DM colour
code, and grants; a same-carrier voice chain (runTETRADMOVoiceChain,
internal/voice/composer/tetra_dmo_voice.go) decodes the DNB TCH/S speech — both hard- and
soft-decision (the same ~2× yield lever the TMO traffic path gets) — through the clean-room
ACELP vocoder to a recording. The DM call-control protocol that rides in SCH/S / SCH/F —
source and destination SSI, group, call type — is EN 300 396-3, a separate specification, and
is not yet decoded, so a DMO call is recorded without a talkgroup/party identity (it files
under group 0). And while the decode chain is validated offline (synthetic round-trips +
TestTETRADMOReplay on captures) and with a synthetic full-daemon lock test, it has not
yet been A/B’d against a real on-air DMO capture through the full daemon — the standing lesson
(#764/#771) is that synthetic round-trips can pass while on-air decode fails, so treat DMO
voice as functional-but-unverified-on-air until that A/B lands.
Relevance to SDR
internal/radio/tetra/dmo.go defines the DMBurstKind (DSB/DNB), the burst geometry, and the
ExtractDMBursts / ExtractDMBurstsSoft slicers that correlate the training sequences under
all four residual π/4-DQPSK rotations; dmo_stream.go wraps them in a bounded sliding-window
DMStreamExtractor for the live daemon.
A DNB detection on its own is not evidence of traffic, and treating it as such is a trap
worth understanding. The DNB training sequence is only 11 dibits and is matched at tolerance 2
under eight filters (two sequences × four rotations), so the number of sequences that match by
chance is Σ_{k≤2} C(11,k)·3^k = 529 out of 4^11, giving ≈1.0 × 10⁻³ per dibit position
across the eight — about 18 false DNBs per second at the 18 kdibit/s symbol rate. Since a
DMO channel is silent between transmissions, that is what the detector reports almost all of
the time. dmo_grid.go’s DMSlotGrid is the discriminator: a real transmission comes from one
radio on one clock, so every one of its bursts lands on the 255-dibit timeslot grid and all its
DNB leads share a single residue mod 255, whereas false alarms are uniform across all 255. The
residue is learned from the stream rather than derived from a hardcoded burst offset, so a
wrong constant cannot silently stop DMO from granting; the latch is dropped when the burst
train ends so the next transmission re-votes. The 19-dibit DSB detector needs no such gate —
its false-alarm rate is ~0.007/s and it must still pass the SCH/S CRC.
dmo_decode.go maps the sliced blocks onto the shared
decoders — DecodeDMSCHS (via the BSCH chain), DecodeDMSCHH (via SCH/HD), DecodeDMSCHF,
and DMBurstTCHSpeech / DMBurstTCHSpeechSoft (via the TCH/S chain) — de-rotating and
descrambling with the DM colour code (recovered by RecoverDMColourCode) before each decode.
Sources
-
Terrestrial Trunked Radio — Wikipedia, on the TETRA standard and its direct mode. ↩
-
Direct mode operation — Wikipedia, on infrastructure-less direct radio-to-radio operation. ↩