hfmodemDocumentation

HF selcall (CCIR 493-4 land mobile, the UN open 6-digit selcall)

hfmodem.bateleur.selcall sends and receives the selective calling that HF land-mobile radios (Codan, Barrett, Q-MAC, Vertex and others) carry in the voice channel: a 4-digit selcall on the CCIR 493-4 pattern, and the UN's open 6-digit selcall. HFLINK's HFS and HFR amateur nets use it.

Sources

The waveform

PartWhere
FSK, 1700 Hz for 0 and 1870 Hz for 1, 100 bits a second, phase continuousfsk.modulate
Characters of ten bits: seven of information, least significant first, then the count of 0s among them, most significant firstcode.char_bits
A dot pattern (2 s for a radio sitting on the channel, 6 s or more for scanning ones), then phasing: six pairs of 125 and 109 down to 104fsk.modulate, code.air_chars
Each character in the DX position, and again four characters later in the RX positioncode.air_chars
Format 120, the called address in digit pairs (2 for four digits, 3 for six), category 100, the caller's address, the call's content, the end character three times (117: acknowledgment asked)code.encode

Which tone is which bit. M.493 gives the maritime service's higher tone to 0. The land-mobile diagrams label 1870 Hz as 1, and all three recordings agree: their known characters' 0 bits are at 1700 Hz. invert swaps them, and the receiver tries both, so an inverted sideband somewhere on the path costs nothing.

The 6-digit format character. The UN diagrams draw 126 in the format position of a 6-digit call. The capture printed with them sends 120, as the 4-digit calls do. We send 120 and accept either, and tell 4 digits from 6 by where the category character falls.

Calls

KindContent after the caller's addressHost command
SelcallnothingCALL <address>
All, group, sub-groupa selcall to X000, XX00, XXX0 (XXX000 ... in six digits); all zeros is every stationCALL 5600
Beaconformat 125 in place of 120BEACON <address>
Hang-up104 105HANGUP <address>
Telcall102, the number of digits, 8 characters of digits, a parity characterTELCALL <address> <number>
Pagecall116 and up to 32 characters of textPAGE <address> <text>
GPS position121, a status byte, the position in 8 characters, a parity characterGPS <address> <lat> <lon>
GPS request125 125GPSREQ <address>
Status request103 103STATUSREQ <address>
Emergency119, ending 119; with a position, 122 and the GPS contentEMERGENCY [address] [lat lon]
Acknowledgmentnothing, ending 122sent automatically if acknowledge is on

A position is latitude and longitude as degrees (three digits), minutes and thousandths of a minute, paired into characters; the status byte's low bits give the hemispheres. The capture's parity character is the exclusive-or of the status byte and the eight position characters (the legend says only the eight); we send the capture's and accept either.

Receive layouts

Transmit uses six DX/RX pairs of 125 against 109 through 104, followed by one format specifier. This is the land-mobile layout; it differs from the M.493 layout of six 125s against 111 through 106, then 105 and 104 under two format specifiers. The receiver now finds the first format specifier and accepts either layout, including the repeated format specifier.

The M.493 path is pinned by a synthetic symbol sequence and waveform. It is unverified against a foreign implementation. A foreign recording with the full phasing sequence, repeated format specifier, known caller and destination, and end characters would settle it. The three cited land-mobile recordings do not establish maritime M.493 interoperability.

The receiver caches tone windows across audio chunks and tries both tone polarities. It emits calls to its observer without keeping an unread history list. This implementation remains in bateleur.selcall; moving its FSK code into lanner is a separate change.

Measured

The earlier call-success table retained no measurement command, seeds or raw output. Its fading results used the old per-burst-normalized channel; those figures are withdrawn. The corrected-channel PHY harness does not measure selcall call-success rates.

A minute of noise alone makes no call. Calls survive a clock 2% out and 40 Hz of offset. All three published recordings decode: 3000 (all stations beginning 3) called by 3332, 3332 calling itself, and 1225 called by 1221, the last 40 Hz off with its clock 1% fast.

On a station

[protocols.selcall]
enabled     = true
host        = "selcall"
port        = 8340
addresses   = ["1234", "123456"]   # one of four digits and/or one of six
dots_s      = 6.0
acknowledge = false
emergency   = false
invert      = false

Host connections use the normal host opening. EMERGENCY is refused unless emergency = true is configured.

The lane listens on whatever channel the radio is on and never moves it. A network that scans for selcall uses the radio's own scanning or the ALE lane's. Every call heard is reported to the host port as a line:

CALL PAGE FROM 123456 TO 567890 MINE TEXT MEET AT THE BRIDGE
CALL GPS FROM 1234 TO 5678 POSITION -32.09520 115.80060

MINE marks a call to one of the station's addresses or a group it falls in. PARITY-BAD marks a telcall or GPS call whose parity disagreed, and INVERTED one read with the tones swapped.

Not verified, and not implemented