Motorola radios display an eight character alias carried in the P25 low
speed data, which they call Soft ID. Sending it lets a hotspot put the
caller's callsign on the screen of a receiving radio instead of a bare
numeric id.
The frame is opcode 0x02, length 0x08, eight space padded ASCII
characters and a two byte checksum, sent two bytes per LDU and repeated
for the length of the transmission. The checksum is validated by the
radio, which silently discards a frame carrying a wrong one.
Both checksum bytes are GF(256) lanes modulo x^8+x^4+x^3+x^2+1, with one
weight per character position. The weights and the value for an all
spaces string were measured off air from a Motorola APX transmitting its
own Soft ID, then verified against a sample held back from the fit.
The text comes from the existing callsign lookup, so an unknown id falls
back to its digits. Off by default, enabled with SoftId=1 in [P25].
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Several JSON message builders conditionally omit fields when their
values are empty or null:
- DMRSlot, P25Control, NXDNControl: source_info omitted when the
callsign/ID lookup returns an empty string
- DStarControl: reflector omitted in RF start messages and when
the reflector pointer is null in network start messages
- YSFControl: reflector omitted in RF start messages
Downstream consumers (such as Display-Driver) that access these
fields via nlohmann::json const operator[] crash with an assertion
failure when the key is absent.
Always emit these fields with an empty string default so that the
JSON schema is consistent regardless of lookup results or message
source.
CDStarControl::clock(),
CM17Control::clock(),
CNXDNControl::clock(),
CP25Control::clock(),
CYSFControl::clock():
- Leave ASAP when it's disabled.
CDMRSlot::enable(),
CDStarControl::enable(),
CM17Control::enable(),
CNXDNControl::enable(),
CP25Control::enable(),
CYSFControl::enable():
- Log a message when Controller get disabled while running, "<MODE>, RF user has timed out" or "<MODE>, network user has timed out", depending of the RF/Net state.
CMMDVMHost::run():
- After getting the modem data, don't handle it (read/write<Controler>, etc) if the given mode is not enabled.
MMDVMHost:
- Rename CMMDVMHost::processEnableCommand() to CMMDVMHost::enableModemMode().
- Add CMMDVMHost::enableMode() and CMMDVMHost::disableMode(), called now from CMMDVMHost::remoteControl(), which clarify the code.
- CMMDVMHost::remoteControl():
* Fix indentation,
* Simplify ENABLE_x/DISABLE_x cases code.
- CMMDVMHost::setMode():
* Enable pocsag network only if m_pocsagEnabled is true,
* Enable ax25 network only if m_ax25Enabled is true (not m_fmEnabled).