DMR Tier III trunking: plan

Status: plan, 2026-10-10. The only built part is a host-side prototype of the PDU coding (tests/host/tier3ProtoTest.c, section 7 WP T3-0). This page describes ETSI Tier III support in RadioFoundry: what it needs from each layer, what the radios can do, the IP position, the test strategy and the work packages.

The sources are public and free from etsi.org. Clause numbers below refer to these versions:

Short name Document Version
-1 ETSI TS 102 361-1, DMR air interface (AI) protocol V2.7.1 (2026-05)
-2 ETSI TS 102 361-2, DMR voice and generic services and facilities V2.5.1
-3 ETSI TS 102 361-3, DMR data protocol V1.3.1
-4 ETSI TS 102 361-4, DMR trunking protocol V1.12.1 (2023-07)
TR 398 ETSI TR 102 398, DMR general system design (informative background only) V1.5.1

RadioFoundry inputs: dmr-modem.md (the modem contract), modem-hrc6000.md, modem-hrc7000.md, gotchas.md, a board's hardware page, codeplug-native.md, docs/ux/principles.md, debuglink.md, tests/hil/README.md, docs/testing/dmr-bench.md.

Term Meaning
TS Trunked station: the infrastructure at a site (the glossary's TS is a timeslot)
payload channel A logical channel granted for a call
MVP The minimal viable subset of section 1.3
Contents
1, 2 Scope, protocol facts the implementation relies on
3 Mapping onto RadioFoundry
4, 5 Feasibility per board kind and risks, IP and legal
6 Test strategy
7, 8, 9 Phased implementation plan, open questions, references

1. Scope

1.1 What Tier III is

A Tier III site runs one or more duplex base stations. One TDMA logical channel is the TSCC. Its outbound is a continuous BS-sourced data channel with a CACH that carries CSBK, MBC and UDT signaling (-4 5.0). Idle radios listen to the TSCC. A radio asks for service with a random access request (C_RAND) in an inbound slot that the TSCC hasn't withdrawn. Random access follows a slotted Aloha discipline (-4 6.2). The TSCC answers with acknowledgements. For a call it sends a channel grant (PV_GRANT, TV_GRANT and others, -4 7.1.1.1.1) that names a payload channel (LPCN and timeslot). The parties retune and run a Tier II style call there (-2 procedures plus trunking maintenance PDUs). They return to the TSCC when the payload channel is cleared (P_CLEAR) or when they disconnect (P_MAINT). Registration, authentication, short data, status and polling all run on the TSCC. The protocol descends from MPT 1327.

1.2 MS features and the clauses they depend on

Phase: MVP (section 1.3), P2 (second phase, MS), P3 (later), no (not planned).

Item What the MS does -4 clauses Other parts Phase
TSCC framing receive a BS-sourced continuous outbound with CACH; send MS-sourced data bursts inbound 5.0, 5.2, 5.4.1, 5.4.2 -1 4.5, 4.6.1, 9.1.1 (sync), 9.3.8 (AT), 9.3.9 (TC) MVP
Channel timing aligned or offset inbound / outbound relationship (C_ALOHA Offset bit, grant Offset bit) 6.6.2.3.0, 7.1.1.1.4 -1 5.1.1, 5.1.4.1 MVP (the mode the target system uses), both in P2
CACH short LC C_SYS_Parms: 14 bits of C_SYScode, Reg, Common_Slot_Counter; P_SYS_Parms on payload channels 5.1, 7.1.2, B.2 -1 7.1.4, 9.1.7 P2 (MVP works from CSBKs alone, 1.3)
Hunting resume, commanded, short hunt list (up to 64 LPCNs), comprehensive hunt 6.3.0, 6.3.2.1, Annex D MVP: resume + commanded + short hunt; P2: comprehensive
Verification C_SYScode MODEL / NET / SITE list / PAR check, SYS_AREA vs denied list 6.3.2.2, 6.3.2.2.1.1-4, 6.3.2.2.2, 6.3.2.2.3 MVP
Confirmation signal quality thresholds (hunt vs idle), color code 6.3.2.3, 6.3.2.4, 6.2.1.3 MVP
Leaving a TSCC BER, NSYSerr syscode mismatches, T_Nosig, C_MOVE, registration refused / denied 6.3.3 MVP (C_MOVE in P2)
Random access Mask, Service_Function, withdrawn slots by the AT bit, NRand_Wait, Backoff, NRand_NR / NRand_NE retries, TRand_TC 6.1.3, 6.2.1.1.1-7, 6.2.1.2, 7.2.1-7.2.5, A.1, A.2 -1 4.5 (AT timing) MVP
Registration C_RAND Registration service, C_ACKD Reg_Accepted, C_NACKD Reg_Refused / Reg_Denied, C_WACKD, registration record 6.4.1-6.4.4.1.9, table 6.9 MVP
De-registration at power off / network change, T_Dereg 6.4.6 MVP
Mass re-registration C_BCAST MassReg with Reg_Window 6.4.5, 7.2.19.5 P2
Talkgroup attachment TRGT_ADR_CNTS = 01 / 10 in the registration C_RAND, appended UDT list 6.4.4.1.13 P2
Authentication C_AHOY challenge, RC4 response in C_ACKU / P_ACKU, optional PSN 6.4.4.1.5, 6.4.4.1.11, 6.4.8, 6.6.2.3.2.2 P2 (the algorithm is in the MVP prototype already)
Group call, calling C_RAND talkgroup voice, C_WACKD / C_QACKD / C_NACKD, TV_GRANT, TP_Timer 6.6.2.2.0-6.6.2.2.2, 6.6.2.2.5, 6.6.2.2.7, table 6.40 MVP
Group call, called TV_GRANT applicability (listen list, own source), late-entry grants 6.6.2.2.7, 6.6.2.4 MVP
Individual call PV_GRANT; called-party radio check C_AHOY answered C_ACKU MS_Accepted (OACSU) 6.6.2.2.6, 4.6.2.1.1 -2 5.2.2 (OACSU) MVP (OACSU); FOACSU (alerting, answer call service) P2
Payload channel move within the timing budget, PATCS call start, P_CLEAR, P_PROTECT, P_AHOY presence / selective clear, P_MAINT DISCON at the end, TV_Inactive / TV_Item / call timers, return to the TSCC 6.6.1.6, 6.6.2.3, 6.6.2.3.2.1-9, 7.1.1.3, 7.1.1.4 -2 5.2.2.1 (PATCS), -1 5.1.2 MVP (P_PROTECT DIS_PTT and P_AHOY in P2)
Late entry join a group call from a Late_Entry TV_GRANT, and from embedded LC on the payload channel 6.6.2.4 -1 7.1.3, dmr-modem.md 2.4 MVP
Emergency C_RAND with EMERG = 1 (ignores Service_Function and Mask < 24, NRand_NE retries), emergency grant bit 6.2.1.1.1, 6.2.1.1.2, 6.2.1.1.9, table 6.40 MVP for the request; emergency alarm by status P2
Status status delivery (emergency alarm = status 126, cancel = 124) and polling 6.6.6, 6.6.6.3 P2
UDT short data send / receive short messages on the TSCC (C_UDTHU / C_UDTHD + appended blocks, formats B.3) 6.5, 6.6.4, Annex B.3 -1 8.2.1.8, 8.2.2.5 P2
Packet data on payload PD_GRANT / TD_GRANT, -3 packet data on the payload channel 6.6.3 -3 P3 (the existing data service would carry it)
Absolute grants MBC grant with CG_AP (CdefParms, color code) 6.1.2, 7.1.1.1.2, 7.2.42, C.1.1.4 -1 7.4 (MBC) P2
Channel plan broadcast C_BCAST logical channel / frequency relationship 6.7.1.6, 7.2.19.6 P2
Adjacent sites, Vote Now C_BCAST adjacent site, vote now advice 6.7.1.3, 6.7.1.7 P3
Power save synchronized sleep to the Common_Slot_Counter 6.4.7 P3
TSCCAS, USBD polling second control slot, LIP location polling 6.1.1.3, 6.6.11 -1 8.2.3.1 P3
Stun / revive / kill 6.4.9, 6.4.10 P3, owner decision (kill is permanent)
Call diversion, DGNA, ALS, full duplex MS-MS, PSTN / PABX dialing, supplementary data, IP connection advice, preferential call notification 6.6.7, 6.6.8, 6.6.2.6, 6.6.9, 6.6.10, 6.4.11, 6.4.13, 6.6.2.5 no (re-evaluate on demand)
Asynchronous / unregulated TSCC (shared spectrum, BS activation) 5.3.3, 6.1.1.2 -2 5.1.1.1 (BS outbound activation) P3
Power control and de-key by reverse channel 6.4.14, 6.4.15 -1 5.1.5, 6.4 no (needs RC transmit / receive the drivers don't have)

1.3 The minimal viable subset

"Join an ETSI Tier III single-site system, register, receive and make group calls, receive and make OACSU private calls, send an emergency request, de-register at power off."

In the MVP the radio:

  1. Starts from a trunked "network" entry in the codeplug (section 3.7): MODEL, NET, optional SITE list, DMRLA, control category, short hunt list, channel plan, its own ID, its talkgroups.
  2. Hunts: last confirmed TSCC first (resume / commanded, kept in non-volatile storage as -4 6.3.1 allows), then the short hunt list. Samples each candidate: BS data sync and color code, then a CSBK carrying C_SYScode (C_ALOHA or a grant). The CACH short LC is not needed: every C_ALOHA carries the full 16-bit C_SYScode and the Reg bit.
  3. Verifies and confirms (6.3.2), then registers when Reg = 1 (6.4.3, 6.4.4.1), with random access per 6.2.
  4. Idles on the TSCC: decodes every outbound CSBK on the TSCC slot, follows Mask / Service_Function / NRand_Wait / Backoff from C_ALOHA, applies grants addressed to it or its talkgroups.
  5. On PTT sends a C_RAND (group or individual voice; emergency when the emergency key started it), waits for the grant (talk permit tone on the grant, a busy tone and message on C_NACKD with the reason in words, a "queued" message on C_QACKD / C_WACKD), moves to the payload channel, transmits with the existing call stack (headers, superframes, terminator, PATCS impolite), and on the end of the call sends N_Maint (4) P_MAINT DISCON when it is the caller of an individual call or the initiator of a group call (6.6.2.3.2.5), then resumes the TSCC.
  6. On the payload channel obeys P_CLEAR, the inactivity timer TV_Inactive, the item timer TV_Item and the call timer (6.6.2.3.2.6, 6.6.2.3.2.9).
  7. Answers a called-party radio check C_AHOY with C_ACKU(MS_Accepted) (OACSU, 6.6.2.2.6).
  8. Joins a group call already running from a Late_Entry TV_GRANT (6.6.2.4.1), and ignores Late_Entry grants for a call it left (same clause, last paragraph).
  9. De-registers at power off (6.4.6) within the existing power-off hold (gotcha 7.4).

Assumptions the MVP makes about the target system, to be confirmed with the owner (section 8):

  • Fixed or flexible channel plan programmed into the radio; no absolute (MBC) grants required. (qradiolink's dmrtc notes that absolute grants are only usable on some radios when they hunt in a flexible plan.)
  • Site timeslot synchronized (C_ALOHA Site Timeslot Synchronization = 1) preferred; unsynchronized supported with the 4-CACH resynchronization allowance of 6.6.1.6.2.2.
  • No authentication required, or authentication with a key the owner can program (the algorithm is ready, 2.9).
  • One timing mode (aligned or offset) on the target system; the other follows in P2.

Out of the MVP on purpose: UDT short data, status, mass re-registration, talkgroup attachment, FOACSU, packet data on payload, power save, TSCCAS, adjacent sites, C_MOVE, absolute grants, channel plan broadcasts.

1.4 Later phases: the trunked station side

Phase What Notes
P3a Host TSCC simulator (already needed for the MS tests, section 6.1): a TSCC and payload channel model in C on the host, driving the MS state machine through the simulated modem Becomes the reference for any TS work
P3b Single-carrier composite site on the hotspot: one duplex frequency pair, TS1 = TSCC, TS2 = payload channel (a non-dedicated / composite arrangement, -4 5.3.2), run by the PC side through the MMDVM protocol or by firmware on a duplex modem A two-frequency duplex BS needs a transmitter and a receiver running at once. None of the single-transceiver radios can do that. On the SDR bench's MMDVM_HS dual board it is possible today (section 6.2)
P3c Two-chip HR_C7000 radio: one chip transmits the TSCC / payload outbound continuously, the other receives the inbound; true duplex on one radio, a one-carrier site Depends on a port of such a radio; the C7000 has BS framing registers (LAYER2_BS_MODE, BS_CACH) never used by any working firmware
P3d Multi-carrier site, multi-site, network interconnect Out of scope for radio firmware; belongs to a PC or Linux controller. Mentioned only so nothing in P1/P2 blocks it

The TS side carries more IP risk than the MS side (section 5) and needs regulator-compliant duplex hardware. Plan it only after the MS works against a third-party TSCC.


2. Protocol facts the implementation relies on

Everything here is checked against the clauses cited. Bit layouts are in the prototype (tests/host/tier3ProtoTest.c), which packs and unpacks each PDU and checks the field sums (64 bits in octets 2-9 for every CSBK below).

2.1 Framing and slots

  • The TSCC outbound uses BS-sourced data sync; the inbound uses MS-sourced data sync (-4 5.0). Both logical channels of the carrier share the CACH (-1 4.5).
  • A power-save frame is 8 TDMA frames (480 ms): four short LCs, one per 120 ms (-4 5.0, 5.1.0).
  • On a TSCC the CACH carries C_SYS_Parms (SLCO 0010): MODEL (2), NET + SITE (12), Reg (1), Common_Slot_Counter (9, +1 per 120 ms, wraps at 511) (-4 5.1, 7.1.2.1). A payload carrier carries P_SYS_Parms (SLCO 0011) instead (7.1.2.2). Only the 14 MSBs of C_SYScode fit the CACH; PAR is in the CSBKs only (5.1.1).

2.2 C_SYScode (-4 6.3.2.2.1.1, table 6.5)

16 bits: MODEL (2) | NET | SITE | PAR (2). NET / SITE widths by model: tiny 9 / 3, small 7 / 5, large 4 / 8, huge 2 / 10. SYS_AREA (the registration record) is the DMRLA most significant bits of SITE (6.4.1.2), DMRLA 1-3 / 1-5 / 1-8 / 1-10 by model. PAR: 01 category A only, 10 category B only, 11 both, 00 reserved (6.3.2.2.1.4). Authorization: MODEL, then NET, then (if the radio holds a SITE list) SITE, then PAR against the radio's control category (6.3.2.2.2), then SYS_AREA against the denied registration list (6.3.2.2.3).

2.3 Random access (-4 6.2)

  • C_ALOHA (CSBKO 25) carries Mask (5), Service_Function (2), NRand_Wait (4), Reg (1), Backoff (4), C_SYScode (16), an MS address (24), and the flags TSCCAS, Site Timeslot Synchronization, Version (3), Offset, Active_Connection (7.1.1.1.4).
  • Mask: the PDU applies to us when its Mask LSBs of the address match ours (6.1.3). Mask 24 with ADRNULL forbids all random access. Emergency may ignore any Mask except 24 (6.2.1.1.1).
  • Service_Function: 00 all, 01 payload services + registration, 10 non-payload services + registration, 11 registration only (table 6.1). Emergency ignores it (6.2.1.1.2).
  • Withdrawn slots: an inbound slot is withdrawn when the AT bit of the CACH before it says busy. The CACH before outbound slot N gives the state of inbound slot N, one slot later, to leave time to decode and key up (-1 4.5, figure 4.8). The MS must have decoded that AT bit to use the slot; an AT bit not received counts as withdrawn (-4 6.2.1.1.6, note c). This is the hardest real-time requirement in the MVP (section 3.2).
  • After a C_RAND the response may come in the next TDMA frame or up to NWait frames later: NRand_Wait 0-13 = 0-13 frames, 14 = 15, 15 = 24 (table 6.2). Default before any C_ALOHA: NDefault_NW = 5 (A.2).
  • No response in NWait + 1 frames: pick the next slot uniformly in 1..Backoff frames; Backoff 1-15 = 1, 2, 3, 4, 5, 8, 11, 15, 20, 26, 33, 41, 50, 70, 100 frames (table 6.3). The first attempt may use the next slot (6.2.1.1.6).
  • Give up after NRand_NR = 6 attempts (NRand_NE = 10 for emergency) or TRand_TC (2-60 s) (6.2.1.1.7, A.1, A.2).
  • After a valid answer: stop sending, run TP_Timer (4-60 s, services that need a payload channel) or TNP_Timer (2-60 s, TSCC-only services), restarted by further acknowledgements (6.2.1.2).
  • A PDU that needs an answer from a given MS withdraws the slot one TDMA frame after its last block; the MS answers there (6.2.1.1.3). So C_AHOY answers (radio check, authentication) go out exactly one frame after the C_AHOY, without random access.

2.4 Registration (-4 6.4.3-6.4.6)

  • Reg = 0: no registration; free to call. Reg = 1 and no record for this SYS_AREA: register before sending anything but a registration request or an authentication answer (6.4.3).
  • C_RAND Service_Kind 1110 with Reg_Dereg = 1, target = 0x00 followed by C_SYScode (table 6.9). The TSCC drops a request whose C_SYScode doesn't match its own (6.4.4.1.0). Delete the old SYS_AREA record when sending.
  • Answers: C_ACKD Reg_Accepted (0110 0010) from REGI = record the SYS_AREA; C_NACKD Reg_Refused (0010 1010) = hunt again; C_NACKD Reg_Denied = add SYS_AREA to the denied list (at least 8 entries, FIFO, lifetime T_DENREG, discarded at power off) and hunt; C_WACKD = wait TNP_Timer; C_AHOY = authentication challenge (6.4.4.1.1-6.4.4.1.5, table 6.8).
  • The current registration record is retained at power off (table 6.8); the denied list is not.
  • De-registration: the same C_RAND with Reg_Dereg = 0, IP_Inform = 0, PS_RQ = 0; only answer C_ACKD Reg_Accepted; abandon after T_Dereg (0.2-2 s) (6.4.6, A.1).

2.5 Calls (-4 6.6.1-6.6.2)

  • Voice C_RAND: Service_Options = EMERG, privacy (0), SUPED_SV, BCAST_SV, reserved, PRIORITY (2; 0 when EMERG), then proxy, appended supplementary data (2), ALS, reserved, Service_Kind 0000 individual / 0001 talkgroup, target, source (table 6.40).
  • Valid answers to a single-part voice request: C_WACKD / C_QACKD / C_NACKD / C_ACKD(callback), a called-party radio check, a diversion UDT, the grant, a supplementary data C_AHOY (6.6.2.2.2). The MVP handles all but the last two (those need features it doesn't request).
  • Grants (CSBKO 48 PV_GRANT, 49 TV_GRANT, 50 BTV_GRANT): LPCN (12; 0 invalid, 4095 = absolute parameters in an appended MBC block), logical channel (0 = TS1), late entry (TV only), emergency, offset timing, target, source (7.1.1.1.1). Applicable when the source is us, or (private) the target is us, or (group) the target is one of our talkgroups (6.6.2.2.7).
  • Timing budget to the payload channel (6.6.1.6.2): site timeslot synchronized: be ready on the second occurrence of TS1, or the third of TS2, after decoding the grant, that is about 60-120 ms. Not synchronized: ready on the next assigned slot after synchronizing to the payload outbound, with at least 4 CACH (2 or 4, a recommended programmable value) of idle sent by the TS for that.
  • The payload channel starts with PATCS (-4 6.6.2.3.0; -2 5.2.2.1): the caller keys at once; for an individual call the radio check already happened on the TSCC.
  • Payload outbound may carry P_GRANT, P_CLEAR, P_PROTECT, P_AHOY, P_xACK, the call's voice, terminators, idle (6.6.1.6.2.0). The payload carrier's CACH never carries C_SYS_Parms (6.6.2.3.0).
  • End: caller of an individual call or initiator of a group call sends P_MAINT DISCON (N_Maint = 4 consecutively); a group recipient leaves silently; both go back to TSCC acquisition, starting with the TSCC they came from (6.6.2.3.2.5). P_CLEAR LPCN 0 means "the TSCC you were last confirmed on" (7.1.1.3.2).
  • Timers on the payload channel: TV_Inactive (0-20 s, no adequate signal), TV_Item (10-60 s, then terminator and PTT disabled until released), call timer tokens (A.1, tables A.2-A.5).
  • Trunking discipline (message / transmission / quasi-transmission trunking with TV_Hangtime) is the TS's choice; the MS just follows grants and clears (4.11, 6.6.2.3.0).

2.6 Late entry and emergency

  • Late entry: while a group call runs the TSCC may repeat TV_GRANT with Late_Entry = 1 at intervals (6.6.2.4.1). On the payload channel the existing embedded LC late entry still applies (dmr-modem.md 2.4).
  • Emergency: a C_RAND with EMERG = 1; the grant has its emergency bit; the TS uses T_EMERG_TIMER. Status 126 / 124 for alarm / cancel without a call (6.6.6.3). The Tier II emergency alarm CSBK of dmr-emergency.md is not a Tier III procedure; on a trunked network the emergency feature maps onto these.

2.7 Channel plans (Annex C)

  • Fixed plan: f_MS_Tx = f_base + (LPCN - 1) x separation; f_MS_Rx = f_MS_Tx -/+ duplex split (TXRX_SPLIT 0 = MS Tx high, 1 = MS Tx low); separation 5, 6.25, 10, 12.5, 15, 20, 25, 30 kHz; split 0-50 MHz in 2.5 kHz steps (C.1.1.2).
  • Flexible plan: a table of LPCN -> Tx, Rx, color code (C.1.1.3).
  • Absolute: CdefParms gives Tx and Rx as 10-bit MHz + 13-bit count of 125 Hz (C.1.1.4, 7.2.42); the CG_AP block also gives the color code (7.1.1.1.2).
  • Color code: 0000 by default, or per channel from the plan, or the TSCC's own outbound color code (6.2.1.3).

2.8 Defaults for the configurable timers

The standard gives ranges, not values. The MVP needs defaults the codeplug can override:

Timer / constant Range (A.1, A.2) RadioFoundry default Why
TRand_TC 2-60 s 10 s long enough for NRand_NR retries at Backoff 15
T_Nosig 1-15 s 5 s
TP_Timer / TNP_Timer 4-60 s / 2-60 s 20 s / 10 s
TV_Inactive 0-20 s 5 s
TV_Item 10-60 s the channel TOT, at most 60 s one meaning for the user
T_Dereg 0.2-2 s 1 s fits the power-off hold
T_DENREG 0 or 10-10 000 s 0 (inactive)
NSYSerr 1-3 3
Hunt threshold / idle threshold (6.3.2.3) manufacturer RSSI and burst CRC rate, both settable

2.9 Authentication (-4 6.4.8)

Response = bytes 257-259 of an RC4 keystream keyed with challenge (3 octets) followed by K (16 octets), optionally XORed with a 3-octet PSN. The prototype reproduces both ETSI test vectors (tables 6.15 and 6.16: K = 01..10, challenge 7A 17 C0 gives E8 CA 1D, with PSN 01 02 03 gives E9 C8 1E). The challenge comes in C_AHOY (Service_Kind 1110, challenge in the source field, 6.4.8.2); the answer is C_ACKU (CSBKO 33) with reason 0100 1000 and the response in the target field (6.4.8.3), or P_ACKU on a payload channel. K is a per-radio secret: it belongs in the settings store key slots like the privacy keys (codeplug-native.md 1), never in a codeplug file.


3. Mapping onto RadioFoundry

3.1 Layers

   UI (network / site / registration / call setup states)            core/ui           (later WP, not now)
        |
   radio core: channel vs trunked network, retune, PTT routing       core/radio        (small hooks)
        |
   trunk MS: hunt, verify, register, random access, grants, payload  core/dmr/trunk/   (new, CONFIG_DMR_TRUNK)
        |          \
        |           dmr_call (reused on the payload channel, and as the
        |           CSBK / data receive path on the TSCC)               core/dmr/call
        |
   hal_dmr_modem (+ AT bit, slot-exact single bursts, timing hold)   hal/              (contract additions)
   hal_radio     (+ split per-burst TX / RX, fast retune)            hal/
        |
   drivers / boards: HR_C6000 + AT1846S, HR_C7000 + FD6818

core/dmr/trunk/ (new, behind CONFIG_DMR_TRUNK, default n, a sub-feature of CONFIG_DMR):

File Role
t3_pdu.c/h pack / unpack of the CSBKs, MBC grants, C_SYS_Parms; reason / service kind tables. Starts from the prototype
t3_sys.c/h C_SYScode split, authorization, SYS_AREA, denied list, registration record
t3_access.c/h the random access engine: Aloha state, Mask / Service_Function, slot choice, withdrawn-slot check, NWait, Backoff, retries, timers
t3_hunt.c/h hunt lists and order (resume, commanded, short, comprehensive), per-candidate sampling, confirmation thresholds
t3_plan.c/h LPCN -> (Tx Hz, Rx Hz, CC) for fixed, flexible and absolute definitions
t3_ms.c/h the MS state machine: HUNT, VERIFY, CONFIRM, REGISTER, IDLE, SETUP (waiting for grant), PAYLOAD, RETURN, DEREG
t3_auth.c/h RC4 response (P2)

The trunk MS is modem neutral and board neutral like dmr_call: it sees hal_dmr_modem_t events through dmr_call (or directly while hunting), asks the radio core to retune, and never includes a board header.

How the pieces share the modem:

  • On the TSCC the trunk MS owns the transmit side. dmr_call stays configured RMO on the TSCC slot with its voice path idle; its data receive hook (dmr_call_set_data_rx) already delivers every CSBK / MBC / data burst with our color code. The trunk MS needs both slots on the carrier (a TSCC may be on either; a composite carrier has a payload slot next to it), so while hunting and idle the receiver runs every slot (gotcha 1.6) and the trunk MS filters by slot itself. A C_RAND or an AHOY answer goes out through a new single-burst request (3.2), not through dmr_call_data_tx (which does listen-before-talk and BS activation, both wrong on a TSCC).
  • On the payload channel dmr_call runs the call as today with a "trunked payload" profile: RMO framing, no BS activation, impolite access (PATCS), no reply window (the grant decides the target), its fade and terminator logic, plus hooks for the trunk MS to see P_CLEAR / P_PROTECT / P_AHOY (data receive hook) and to queue P_MAINT / P_ACKU after the terminator. A PTT pressed on the payload channel during message trunking keys straight away.
  • The radio core gets a third kind of "where am I": a trunked network (besides channel and VFO). It routes PTT to the trunk MS, applies its retune requests (the only component that calls hal_radio), and keeps Home's state.

3.2 dmr_modem HAL additions

The Tier II contract (dmr-modem.md 6) covers most of a payload channel. The TSCC needs:

# Capability Why Contract change
H1 AT bit per slot in DMR_EV_SLOT_TICK, with "valid" (decoded this slot) withdrawn-slot rule (2.3) dmr_event_t gains at (0 / 1 / unknown). The prose contract already lists "CACH AT (busy) if heard" for the slot tick; the struct doesn't carry it
H2 Slot-exact single burst with a last-moment veto: "send this burst in inbound slot N unless the CACH AT for slot N says busy (or wasn't decoded)", the decision taken by the driver in its slot interrupt the MS can't make that decision at task level in time (one slot = 30 ms; the HR_C6000 needs the set-up at the interrupt before) new tx_slot(slot_counter, burst, veto_on_at); result event DMR_EV_TX_SLOT_DONE (sent / vetoed / late)
H3 Inbound slot selection independent of the outbound slot heard, for aligned vs offset timing (-1 5.1.1 table 5.1: aligned logical channel 1 = inbound TS2 + outbound TS1) TSCC and payload channels may use either mode tx_begin(DMR_TIMING_ALIGNED, ts, ...) gets an explicit inbound TS; the driver maps it to its slot clock
H4 Timing hold across a retune: keep the slot clock running (passive timing free-runs) while the RF is retuned, and resynchronize without dropping to idle site timeslot synchronized grants (60-120 ms budget, 2.5) rx_restart gains a "keep timing" variant; or the board's retune keeps the modem untouched
H5 Both-slot receive with slot tags while locked to a BS outbound TSCC on either slot, composite carriers, TSCCAS exists (rx_lock_slot(0)); confirm the HR_C6000 driver reports ts from TC for every burst
H6 MBC delivery: header + continuation(s) grouped, CRC over the whole MBC checked absolute grants, C_BCAST channel plans (P2) the stack can group them itself from burst_rx; no driver change if every block is delivered
H7 Short LC (CACH) delivery, optional C_SYS_Parms for faster hunting, power save new event kind; the C6000 only flags "short LC received" (0x86 bit 2) and the C7000 has dll_shortlc_rx_interp; where the 28 bits are readable is unknown for both. The MVP does without it
H8 Per-burst RSSI / BER for confirmation thresholds 6.3.2.3 rssi_dbm exists; the C7000 has RECV_INFO_COUNT (sync / FSK errors); the C6000 path uses the AT1846S RSSI
H9 Reverse channel TX / RX power control, de-key (6.4.14) not planned

Everything else (CSBK and MBC TX / RX with chip-computed CRC, BS sync reception, slot tracking from TC, voice) is already in the contract and the two drivers.

3.3 hal_radio additions

# Capability Why
R1 Split frequencies per burst: TX on f_MS_Tx for our burst, back to f_MS_Rx right after it random access: listen to the TSCC outbound, send one inbound burst, hear the answer NWait + 1 frames later. Tier II RMO needs the same, but today an AT1846S board stays on the TX frequency between bursts (the per-burst switch only writes reg 0x30) and an FD6818 board sets the TX frequency once per transmission
R2 Fast retune from task level to a new (Rx, Tx) pair without the full rx() set-up (tones, bandwidth tables) hunting and payload moves; the AT1846S retune is three register writes (about 0.25 ms on I2C3, measured as the per-burst cost)
R3 A dwell measurement for hunting: RSSI after settling, sync seen or not, in a bounded time short and comprehensive hunts (Annex D)

Lock time after a jump is the unknown in all three: no AT1846S or FD6818 datasheet is available, and the only measured retunes are same-frequency (simplex) ones. It must be measured (section 6.3, WP T3-4) before the timing budget can be trusted.

Budget, site timeslot synchronized, worst case TS1 grant: grant decoded about 5 ms into its slot, ready by the second TS1 after it, so 60 ms minus margins for the move: the I2C writes (0.25 ms), PLL settling (unknown), the modem keeping its slot clock (H4), and the first payload burst being received in step. Even a 10 ms lock leaves room. The random access burst is tighter: RX on the outbound to read the AT bit, retune to Tx and key within about one slot, burst (27.5 ms), back to Rx for the next frame. That is the same per-burst switching Tier II RMO already needs, with the frequency changing each time.

3.4 HR_C6000

What helps:

  • RMO reception, TC slot tracking, BS sync detection, CSBK / MBC / data reception and CSBK transmission are all on air or host-tested (modem-hrc6000.md 5-6).
  • 0x52 bit 3 is the received AT bit (2); it is read at every system interrupt and at the timeslot interrupt.
  • The chip's polite access mode (0x20 / 0x21) refuses to send while "the channel is busy" and raises "send request rejected" (0x82 bit 7). On a BS outbound that may well be exactly the AT-busy rule; if so the chip does the H2 veto in hardware. Unverified: test it (WP T3-4).
  • CRC_MCU_Control lets the MCU supply CSBK CRCs (not needed: the chip computes the 0xA5A5 / 0xAAAA masks).

Known limits and risks:

  • Set-up deadline. The burst for slot N is set up in the timeslot interrupt before it ("writes at the start of the handler, the burst goes out in the following slot", 4.1). The AT bit for inbound slot N arrives in the CACH just before outbound slot N. Whether 0x52 already holds that CACH's AT when the timeslot interrupt for the set-up fires is unknown; if it holds the previous CACH, the veto is one slot stale. Measure: log 0x52 AT at each timeslot interrupt against a known AT pattern from the bench TSCC (WP T3-4).
  • CACH only refreshed in received slots (4.1, 5.3): once the receiver is locked to one slot it stops seeing the other slot's CACH, which carries the AT bit for our inbound slot in aligned timing. The TSCC must be received on both slots (H5), which also matches gotcha 1.6.
  • No RF RX interrupt on a board that routes only the RF TX interrupt: the PA drops at the next timeslot interrupt (gotcha 3.4). For a single random access burst followed by reception on another frequency, the switch back to Rx (and its retune) waits for that interrupt, about 1.3 ms into the next slot. Acceptable: the answer comes a frame later at the earliest.
  • Reports while transmitting are unreliable (7.8, gotcha 14.1). The MS sends single bursts on the TSCC, so this only matters if the TSCC answers in the slot right after ours; NRand_Wait 0 means "next TDMA frame", which is after our burst.
  • Boards with a synthesizer per band: relock per burst was already the open SFR risk (gotcha 14.6). The same applies to R1 here.
  • MK22 boards: flash nearly full (capabilities.md, gotcha 12.3): the MVP (estimate 12-20 KB) does not fit without dropping other features.

3.5 HR_C7000

What helps:

  • RX_TYPE_INFO gives the AT bit (bit 23), TC (bit 22), CACH LCSS, current RX slot and all CRC flags per burst (modem-hrc7000.md 2.7). RX_INFO bits 24-16 are a "trunking multiframe number", and the chip has layer-3 call control; neither has been used by any firmware we know of. Stay at layer 2: our stack owns the protocol, the chip frames bursts.
  • The chip computes CSBK / MBC CRCs with programmable masks (2.3). Fine for Tier III: every PDU we send has a correct CRC.
  • Separate TX and RX timeslot interrupts (vectors 62 / 63) and LAYER2_SLOT_PRE (processing-interrupt advance, 0x551010) give more room for the H2 decision than the C6000 has. How much is unknown (10.4).
  • dll_shortlc_rx_interp (SYS_INTERP bit 4) can be enabled in the interrupt mask: the chip decodes short LCs. Where it puts them is not documented.

Known limits and risks:

  • Tier III waits for Tier II repeater-mode transmit (BS activation, aligned TX) on this chip.
  • The board switches the FD6818 per burst but keeps the TX frequency for the whole transmission: R1 is new driver work. The FD6818 has no datasheet; lock time is unknown.
  • Flash: an HR_C7000 image must fit between 0x0300C000 and 0x03061000 with about 9-20 KB spare (gotcha 12.3). The MVP does not fit without trading features (capabilities.md: about 20 KB free); plan it on an AT1846S board first.

3.6 RF retuning per chip

Board kind RF Retune path Known cost Unknown
HR_C6000 with one AT1846S AT1846S, one for both bands I2C3 400 kHz, regs 0x30 (idle), 0x29, 0x2A, then 0x30 (TX / RX); done today from the modem ISR per burst 0.25 ms extra per burst (measured) PLL settling for a duplex split (5 MHz UHF, 0.6 MHz VHF); the 3 kHz TX offset trap when RX was on before TX (gotcha 3.5, bench finding 2026-10-10)
HR_C7000 with an FD6818 FD6818 bit-banged 3-wire, 2 x 16-bit frequency words at 1 us per bit under 0.1 ms of bus time settling; register meaning (no datasheet)
HR_C6000 with a synthesizer per band one synthesizer per band per-burst relock (gotcha 14.6)
HR_C5000 SKY72310 PLL not ported for DMR TX yet
Two-chip HR_C7000 radio (not ported) two transceivers (RDA1846 / FD6818 / AT1141) one per chip the port itself

3.7 Codeplug

Nothing in the open-firmware layout can hold a trunked network, so Tier III depends on the native codeplug (codeplug-native.md 3-4) or a stopgap record area. Proposed native records:

Record Fields Notes
network (1..8) name; MODEL; NET; SITE authorization list (0..8 entries); DMRLA; control category A / B; registration wanted; own ID (0 = radio's); auth key slot (0 = none; key in the settings store); PSN use; color code strategy (default 0 / per plan / TSCC's); timing mode hint; timer overrides (2.8) fixed during personalization in -4 terms
hunt list (per network, up to 64 LPCNs, -4 D.1.0 c) LPCNs, duplicates allowed for bias; Low_Comp_Ch / High_Comp_Ch; Comp_Flag
channel plan (per network) type fixed / flexible; fixed: f_base, separation code, TXRX_SPLIT, split; flexible: table of LPCN -> Tx Hz, Rx Hz, CC (size to decide, up to 4094 in the standard) the absolute and broadcast forms arrive over the air
talkgroups (per network) the network's listen list (existing listen list records can be reused), plus attachment flags (P2)
zone entry a zone may name a network instead of a channel: selecting it starts the trunk MS the UI sees "a channel kind"

Run-time state, in the settings store (not the codeplug, so a codeplug file stays shareable):

State Survives power off Source
last confirmed TSCC LPCN per network yes (commanded hunt) -4 6.3.1 allows it, D.1.0 b
registration record (SYS_AREA) per network yes table 6.8
denied registration list no table 6.8
hunt list additions from announcements yes table 6.4 (P2)

3.8 UI (design input for a later UI work package; core/ui is not edited by this plan)

Following docs/ux/principles.md:

  • P2 "you always know what PTT will do": Home on a trunked network shows the network name where the channel name goes, the site and registration state in the place row ("Site 3 · Registered", "Searching…", "Not allowed here"), and the talk target as today. TS / CC chips disappear: the system chooses them.
  • The status strip states: idle, "Searching", "Registering", RX (caller and TG as today), TX, and a new transient state "Requesting" between PTT and the grant. TX red only once the grant arrived and the radio keyed.
  • PTT: the talk-permit tone plays on the grant, not on the press; while waiting, Home says "Requesting TG 3100…". If PTT is released before the grant, the request is canceled where the standard allows (call cancel, P2) or the grant is ignored and the radio stays on the TSCC.
  • P9 messages, one per C_NACKD reason family: "TG 3100 is busy. The system queued your call." (C_QACKD), "Call refused: the system doesn't allow this service for your radio." (Perm_User_Refused), "No answer from 1234567: the radio is off or out of range." (MSaway_Refused), "This site doesn't accept your radio. Searching for another." (Reg_Denied). No reason codes alone.
  • P6: typing a TG or ID and pressing PTT works as on a channel: the C_RAND carries any target.
  • P7: the network entry is chosen like a channel; nothing a trunked operation does writes the codeplug.
  • Emergency stays hold-to-activate; on a network it sends the emergency C_RAND (and the status alarm in P2).
  • Diagnostics page: the trunk view section (3.10) rendered as text.

3.9 CPS

qdmr has no Tier III support (its device list and documentation are conventional only; nothing found in a search of its project pages). The open-firmware CPS shim can't carry trunked records. Options, owner decision (section 8):

  1. The native CPS protocol (cps-protocol.md 3) with record types for network, hunt list, channel plan; a small tools/ editor (JSON in, records out) until a GUI exists.
  2. Contribute a Tier III extension to qdmr's open-firmware driver later (qdmr is GPL: we contribute there, nothing comes back into RadioFoundry).
  3. Stopgap for bench work: a debug-link request that writes one network definition into the settings store.

A new view section trunk (core/debuglink/debuglink_view_trunk.c or appended to debuglink_view_ext.c), keys:

t3.built t3.state (off / hunt / verify / confirm / register / idle / setup / payload / return / dereg) t3.net t3.lpcn t3.ts t3.syscode t3.model t3.netid t3.site t3.par t3.reg_req t3.registered t3.sys_area t3.denied_n t3.aloha_mask t3.aloha_sf t3.nwait t3.backoff t3.site_sync t3.offset t3.version t3.ra_state t3.ra_attempts t3.ra_vetoed t3.ra_late t3.ra_sent t3.ra_answers t3.ra_timeouts t3.setup_target t3.setup_group t3.setup_result (granted / queued / refused: / timeout) t3.grant_lpcn t3.grant_ts t3.grant_ms (grant decoded to first in-step payload burst) t3.payload_rx_hz t3.payload_tx_hz t3.clears t3.maint_sent t3.inactive_timeouts counters: t3.rx_csbk t3.rx_aloha t3.rx_grants t3.rx_grants_ours t3.rx_bcast t3.rx_ahoy t3.at_busy t3.at_unknown t3.hunts t3.hunt_ms t3.retunes t3.retune_max_us.

Plus a debug-link radio request to select a network and one to force a hunt, so HIL tests need no keys.


4. Feasibility per board kind and risks

Board kind MVP feasibility Blocking work Notes
HR_C6000 + AT1846S Plausible. RAM is there; flash was (213 KB of 428 KB when planned) but the default image now leaves only a few KB free (docs/feature-matrix.md), so room has to be made (LTO, about 20 KB, or features off) R1 (split per burst), H1 / H2 measurements, Tier II RMO on air first has a bench radio; first target
HR_C7000 + FD6818 Plausible on the modem side (AT / TC per burst), blocked on flash and on repeater-mode TX on air R1 driver work, flash budget second
MK22 + HR_C6000 Modem as the AT1846S boards, but no flash flash only with features dropped
Synthesizer per band Doubtful until per-burst synthesizer relock is measured gotcha 14.6
HR_C5000 Not before its DMR TX works; HR_C5000 lacks the C6000's MCU CRC path (irrelevant here) DMR bring-up
Two-chip HR_C7000 MS as the HR_C7000 boards; the only candidate for a radio-hosted TS (two chips) the port P3c

Risks, highest first:

# Risk Effect Mitigation / test
K1 The AT bit for slot N isn't available in time for the C6000's set-up of slot N (3.4) random access either never fires (all slots look withdrawn) or fires blind into withdrawn slots and collides with solicited answers measure on the bench TSCC with a scripted AT pattern (WP T3-4); fallbacks: the chip's own polite access as the veto; or transmit only in slots following a C_ALOHA (Aloha PDUs never withdraw the next slot, 6.2.1.1.3 a), which needs no AT read at all
K2 PLL settling after a duplex jump longer than the RF TX interrupt lead first symbols of each inbound burst off frequency; the TSCC misses C_RAND SDR bench measurement of the burst ramp and frequency per burst (sdrmon.py), Tier II RMO first
K3 Inbound slot placement for aligned vs offset timing wrong every inbound burst in the wrong slot H3, checked against the bench TSCC and the SDR's slot phase report
K4 No reachable ETSI-conformant TSCC to test against (section 6.2) MVP can only be host-tested build the bench TSCC (WP T3-6); qradiolink's dmrtc as a black-box second opinion
K5 Real systems require authentication or vendor extensions (Capacity Max "open system" setting, Hytera options) registration refused owner to name a target system; dmrtc's compatibility notes show Motorola radios needing system settings on the TS side
K6 Timing budget to the payload channel missed (H4) late entry into our own call; first headers lost measure t3.grant_ms; site-synchronized and unsynchronized cases
K7 Codeplug: the native format isn't built no place for the network stopgap in the settings store (3.9 option 3) for bench work
K8 Power: hunting and idling keep the receiver on every slot idle current higher than on a channel; no power save in MVP P3 power save (6.4.7); measure idle current on the bench
K9 IP position (section 5) stay on ETSI procedures; legal review before release

Research notes, not legal advice.

  • The standard. TS 102 361-4 is a published ETSI technical specification, free to download and implement. ETSI's IPR policy means members declare patents they consider essential and offer licenses on FRAND terms; it does not mean the standard is royalty free. The ETSI IPR database (ipr.etsi.org) has not been searched for declarations against -4 yet: do this before any release and record the result next to this plan.
  • What this plan does to stay clear:
    • ETSI procedures only: no rest channel, no Capacity Plus / Linked Capacity Plus / Capacity Max signaling, no Hytera XPT, no vendor CSBKs (FID other than 0x00 is ignored by the trunk MS, as -4 6.6.1.6.2.0 allows).
    • BS activation (repeater wake) is only used where ETSI uses it (the unregulated TSCC, P3).
    • The TS side (P3) needs a separate legal review before it is built.
    • Nothing is taken from third-party trunking code (dmrtc, MMDVMHost forks, SDRTrunk, OP25); those tools may be used as black-box test equipment only.
  • Copyright: wire formats aren't protected; the risk is provenance. Everything here comes from the ETSI text.
  • Spectrum: transmitting on a licensed trunked system needs the system operator's permission; the bench TSCC needs a licensed duplex pair (amateur 70 cm repeater sub-band pairs, or the owner's business license).

6. Test strategy

6.1 Host simulation (no hardware)

  • PDU tests: tests/host/tier3ProtoTest.c today (72 checks: layouts, CRC, syscode, tables, channel plans, authentication vectors). It grows into t3PduTest when t3_pdu.c exists.
  • TSCC simulator (tests/host/sim/t3_tscc_sim.c, new): a slot-accurate model of one site on top of the existing simulated modem (tests/host/sim/dmr_sim_modem.c): a TSCC outbound (C_ALOHA with configurable Mask / SF / NRand_Wait / Backoff, AT bits per slot, solicited withdrawals), inbound collision model (two MS in one slot = both lost), registration answers, grants after a configurable delay, a payload channel (idle, P_CLEAR, P_AHOY), and RF retune latency. A virtual clock in slots.
  • MS scenarios (tests/host/t3MsTest.c): power-on hunt and register; Reg = 0; refused, denied, timeout paths; random access with Mask, SF 11, withdrawn slots, lost AT, backoff distribution (chi-square over many runs), NRand_NR exhaustion; group call out (grant, payload, P_MAINT x 4, return); group call in (grant to a listen list TG; grant to another TG ignored); late entry grant; left call not re-joined; individual call with radio check; P_CLEAR LPCN 0; TV_Inactive; emergency ignoring SF and Mask < 24; de-registration at power off within T_Dereg; C_SYScode change NSYSerr times; T_Nosig. Timing assertions in slots (the grant-to-payload budget of 6.6.1.6.2).
  • Radio core test additions: a zone entry naming a network; PTT routing; Home state strings.

6.2 The SDR bench as a Tier III site

What the bench has (docs/testing/dmr-bench.md 1): an MMDVM_HS dual board (two ADF7021s, duplex capable), an RTL-SDR, and the rfoundry_sdrbench package, which already runs a duplex repeater with BS sync and CACH short LC (tools/bench/bench_repeater.py).

Plan, WP T3-6: tools/bench/bench_tscc.py (MIT, ours), a single-carrier composite site on the dual board:

  • TS1 = TSCC: continuous C_ALOHA, C_SYS_Parms in the CACH, registration answers, grants; TS2 = the payload channel of the same carrier (LPCN = the TSCC's own channel, logical channel 2). No retune in the first tests: this isolates the protocol from the RF retune risk (K2).
  • Then a second payload channel needing a retune is impossible with one duplex board; for K2 / K6 the bench radio instead uses a channel plan whose payload LPCN maps to the same pair, and the retune is measured separately against bench_repeater.py on a second frequency pair (Tier II RMO).
  • Needs from the modem firmware: control over the CACH AT bit per slot and the short LC, continuous BS data bursts on TS1 while TS2 is idle or carrying voice. MMDVM's protocol has DMR_SHORTLC and a trunking flag / DMR_ALOHA in some firmware (mmdvm-protocol.md 2.10); whether MMDVM_HS honors the trunking flag and lets the host set AT per slot is unknown and is the first thing to check (owner question). If it doesn't, the fallback is an SDR transmitter (none on the bench today) or a two-chip HR_C7000 radio later.
  • The RTL-SDR with sdrmon.py checks every burst the radio sends: slot phase against the TSCC, sync family, data type, CSBK contents, carrier offset and ramps per burst (the retune measurement).

Black-box second opinions (used as instruments only, never read as code; GPL):

Tool License Use
qradiolink dmrtc (with MMDVMHost-SDR / MMDVM-SDR, a LimeSDR-class transmitter) GPL-3.0 an independent TSCC implementing registration, group and private calls, late entry, channel plans, authentication; its README lists Hytera and Motorola radios that registered on it. Needs an SDR transmitter the bench doesn't have
SDRTrunk GPL-3.0 decoding a TSCC and our inbound bursts; whether it follows ETSI Tier III (as opposed to Capacity Max) needs checking
DSD-FME mixed (ISC-style DSD core; check per file before any doubt) decoding CSBKs off air; Tier III support to be confirmed

A real commercial Tier III system (Hytera, Tait, Kenwood, Motorola Capacity Max in "open" mode) is the final interoperability test, if the owner has access to one.

6.3 HIL tests (tests/hil, opt-in)

Test Needs Pass
test_t3_retune.py --allow-rf --allow-service-stop, a duplex pair radio keys bursts alternating Rx / Tx frequencies (a debug-link test request); SDR: every burst within --max-foff, full length, in its slot; t3.retune_max_us under budget
test_t3_at_timing.py bench TSCC scripted AT pattern; the radio's t3.ra_vetoed / t3.ra_sent match the pattern exactly; no burst in a withdrawn slot on the SDR
test_t3_register.py bench TSCC t3.state=idle, t3.registered=1 within 5 s of selecting the network; one C_RAND heard (more with induced losses); de-registration heard at power off (opt-in --allow-reboot)
test_t3_group_call.py bench TSCC, codec PTT: C_RAND heard, grant sent, voice on TS2 with our ID and TG, 4 P_MAINT after the terminator, back on the TSCC (t3.state=idle)
test_t3_group_rx.py bench TSCC + bench modem as a second MS grant for a listen-list TG: the call is played; other TG: not moved
test_t3_late_entry.py bench TSCC late entry grant joins; a call the radio left isn't re-joined

7. Phased implementation plan

Work packages sized for one agent each. "Obs" = the debug-link keys it must add for its own HIL check.

Phase 1: MVP

WP Package Content Depends on Obs Tests
T3-0 prototype (done) PDU coding, tables, channel plans, auth vectors in tests/host/tier3ProtoTest.c host
T3-1 t3_pdu, t3_sys, t3_plan real encoders / decoders (CSBK set of 1.3, MBC grant + CG_AP, C_SYS_Parms), syscode authorization, SYS_AREA, denied list, channel plan lookup; CONFIG_DMR_TRUNK switch in config/features.mk and core/config.h T3-0 none (library) host: t3PduTest replaces the prototype
T3-2 host TSCC simulator tests/host/sim/t3_tscc_sim.c on the simulated modem, scenario scripting T3-1 host
T3-3 t3_access, t3_ms, t3_hunt the MS state machine and random access engine against the simulator; the trunk view section T3-1, T3-2, H1 / H2 in the sim modem t3.* (3.10) host: t3MsTest (6.1)
T3-4 modem + RF on an AT1846S board H1 (AT per tick), H2 (slot-exact burst with veto; try the C6000 polite access as the veto), H3 (inbound slot choice), H4 (timing hold), R1 / R2 (split per burst, fast retune) in drivers/modem/hrc6000, boards/<id>; debug-link test requests: alternate-frequency burst train, AT log dmr-modem.md contract update; coordinate with the HR_C6000 RX driver owner modem.at_*, rf.retune_*, per-burst AT log in the trace host: hrc6000DmrTest additions; HIL: test_t3_retune.py, test_t3_at_timing.py
T3-5 radio core + codeplug stopgap trunked network as a zone entry; PTT routing; retune requests; network definition in the settings store via a debug-link request (until the native codeplug); registration record persistence T3-3 core section: mode=trunk, network name host: radioCoreTest additions
T3-6 bench TSCC tools/bench/bench_tscc.py on the dual board: composite site TS1 TSCC / TS2 payload, scripted AT patterns, registration and grant logic, JSON log; docs/testing/dmr-bench.md cases owner answer on MMDVM_HS trunking support; a licensed duplex pair bench JSON log bench self-test with sdrmon.py
T3-7 MVP integration on air run 6.3 tests; fix; document results in this file and feature-matrix.md T3-3..T3-6 HIL
T3-8 UI Home / status strip / messages per 3.8 in core/ui with simulator screens and press budgets T3-5 ui.* uiFlowTest, gallery

T3-1, T3-2, T3-4 and T3-6 can run in parallel; T3-3 needs T3-1 and T3-2; T3-5 and T3-8 need T3-3; T3-7 needs all. Tier II RMO TX on air (BS activation, aligned TX, split frequencies) is a prerequisite for T3-4's on-air part and is worth doing first on its own: it retires K2 and K3 with an ordinary repeater.

Phase 2

WP Content Depends on
T3-9 native codeplug records (3.7) and the native CPS record types; tools/ editor codeplug-native.md 4 being built
T3-10 authentication (C_AHOY / C_ACKU / P_ACKU), key slot in the settings store, PSN T3-3
T3-11 UDT short data in / out, status delivery and polling, emergency alarm by status; bridge to the existing inbox T3-3, data service
T3-12 absolute grants (MBC + CG_AP), C_BCAST channel plan / adjacent sites / call timers, C_MOVE, mass re-registration, talkgroup attachment T3-3
T3-13 FOACSU (alerting, answer call service), call cancel, P_PROTECT DIS_PTT / EN_PTT, P_AHOY presence and selective clear T3-3
T3-14 both timing modes, unsynchronized sites, comprehensive hunt, CACH short LC (H7) where the chips allow T3-4
T3-15 HR_C7000 port of T3-4 (FD6818 split per burst, C7000 AT from RX_TYPE_INFO) repeater-mode TX on air on the chip, flash budget

Phase 3

Power save (6.4.7), TSCCAS / USBD LIP polling, packet data on payload channels, the TS side (1.4: host simulator as a reference, composite site on the hotspot or bench, two-chip HR_C7000 site), after a legal review of the TS side.


8. Open questions for the owner

  1. Target system. Is there a specific Tier III system to join (vendor, timing mode, fixed or flexible plan, authentication on or off, site synchronized)? The MVP's assumptions (1.3) should match it.
  2. Bench site. May we build bench_tscc.py on the SDR bench's MMDVM_HS dual board with rfoundry_sdrbench, and which licensed duplex pair should it use? Do you know whether the MMDVM_HS firmware on the bench honors the MMDVM trunking flag (CACH AT control, continuous TSCC), or should we plan an SDR transmitter for the bench?
  3. Third-party oracles. OK to run qradiolink's dmrtc (GPL-3.0) as black-box test equipment if an SDR transmitter becomes available, keeping it outside the repository?
  4. Order of work. Do Tier II repeater mode on air (BS activation, split frequencies, aligned TX) first, as the plan recommends?
  5. Codeplug. Build the native codeplug (T3-9) before Tier III, or use the settings-store stopgap for the MVP?
  6. CPS. Native CPS records plus a small tools/ editor, or work toward a qdmr contribution?
  7. Radios. Agree the HR_C6000 + AT1846S boards first, the HR_C7000 boards second, MK22, per-band synthesizer and HR_C5000 boards not planned for Tier III?
  8. Legal. Should the ETSI IPR database search for TS 102 361-4 declarations, and a check of whether shipping Tier III MS code needs a license, happen before any code lands, or before the first release?
  9. Stun / kill. Implement them at all (P3)? Kill permanently disables a radio by over-the-air command; for an open firmware the owner may prefer "stun only, kill treated as stun".
  10. TS side. Is a radio-hosted or hotspot-hosted trunked site (P3b / P3c) a goal, or only the MS?

9. References

  • ETSI TS 102 361-1 V2.7.1, -2 V2.5.1, -3 V1.3.1, -4 V1.12.1: https://www.etsi.org/deliver/etsi_ts/102300_102399/ (folders 10236101, 10236102, 10236103, 10236104).

  • ETSI TR 102 398 V1.5.1: https://www.etsi.org/deliver/etsi_tr/102300_102399/102398/

  • qradiolink dmrtc (GPL-3.0), README only (feature list and radio compatibility): https://github.com/qradiolink/dmrtc

  • SDRTrunk (GPL-3.0): https://github.com/DSheirer/sdrtrunk

  • DSD-FME: https://github.com/lwvmobile/dsd-fme

  • qdmr: https://dm3mat.darc.de/qdmr/

View the source of this page