RailSpotting Receiver docs

ITC (220 MHz PTC)

ITC (Interoperable Train Control) is the 220 MHz radio network that carries positive train control (PTC) messages on North American freight railroads. A receiver with a dongle in the itc job decodes it: the base stations around it, and the wayside units at signals and switches reporting their state every few seconds.

ITC describes railroad operations: signal states show where trains are. What the receiver decodes stays on the receiver unless its owner turns ITC upload on, and RailSpotting never shows it publicly (see What is shared).

What is on the air

PTC is a safety system that can stop a train before it passes a red signal, overspeeds or enters work limits. Its radio link, ITC, connects four kinds of station:

Station What it sends
Base stations fixed towers that run the network: beacons naming themselves, the time, and slot control for everyone else on their channel
Wayside interface units (WIUs) boxes at signals, switches and detectors. Each reports the state of its devices every few seconds, whether or not anything changed
Locomotives the train’s PTC computer asking for wayside states and talking to the back office
Back office the railroad’s servers, reached through the bases

A receiver hears the bases and the wayside units best: they are fixed, and they transmit all the time. Locomotive traffic comes and goes with trains.

Channels

The radio layer

   
Modulation pi/4-DQPSK: each symbol is a phase change of +45, +135, -135 or -45 degrees, carrying 2 bits (Gray coded: 00, 01, 11, 10)
Rates 16,000 symbols/s (full rate, 32 kbit/s) on busy channels, 8,000 (half rate) on quiet ones
Access TDMA: stations take turns in time slots, so one burst on the air can hold several stations’ messages back to back
Start of a burst a short preamble, then a 64-bit unique word (f337eeb637660672) that marks where a frame begins

After the unique word, each frame has:

  1. A header, 24 bits sent as 48 with a convolutional code (constraint length 7, rate 1/2) for protection. It holds the frame’s length (9 bits), a mode (4 bits), the message type (8 bits) and a 3-bit check.
  2. The data, length bytes: the message, then a CRC-16 (CRC-16/ARC, low byte first). It is sent in blocks of a Reed-Solomon RS(16,12) code, which can repair up to 2 bad bytes in every 12, byte-interleaved across the blocks so a short burst of noise is spread over several.
  3. For message types above 5, a 4-byte trailer before the CRC, thought to be an authentication code.

A burst can hold several frames, so the decoder looks for the unique word again after each one.

Message types

Type Name From What the receiver reads
0x02 BEACON base base radio ID, position, local channel, neighbouring bases’ channels, how busy the channel is
0x05 CNTL base base radio ID and a sequence number (slot control, not yet understood)
0x06 TIME base the base’s UTC clock
0x33 WIU wayside unit the unit’s ID and its device states
0x34 WIU_REPLY wayside unit, relayed the same, sent in reply to a request; it can arrive a cycle late
others QSTAT, ACK, ACQ, T07, UNICAST various the sender and the raw bytes

Wayside status

A wayside unit’s ID is 10 hex digits: a 6-digit group shared by a railroad’s units in an area, then the unit’s own 4 digits. Units numbered one apart usually share a location, often the two directions at one signal.

Its message carries indicator bits. Read as 5-bit device codes (each field last bit first), they become one code per device:

Code Meaning
3 Clear
8 Approach
2 Medium Clear
6 Approach Medium
15 seen at control points; by observation a stop, held until the dispatcher clears the route
13 seen at intermediate (automatic) signals; by observation a stop that clears by itself as the train moves on

Codes 2, 3, 6 and 8 are named in public railroad material. The rest are set by each railroad’s device status table, so the receiver shows only those four by name. Switches (normal, reverse, out of correspondence) and detectors (on, off) report codes of their own.

A unit repeats its full status every few seconds, so almost every message is a repeat. On one receiver over 12 hours: about 35,000 messages an hour, of which about 43 were state changes. The receiver therefore tracks each unit and keeps only its changes:

How the receiver decodes it

All of this was worked out from recordings and implemented from scratch in the receiver (the railspotting-itc crate):

The details, with the evidence for each step, are in crates/itc/findings.md. The decoded messages’ JSON fields are in crates/itc/messages.md.

Setting up a dongle for ITC

Where to see it

What is shared

Credits