Mercury exposes a VARA-compatible TCP TNC interface for client applications. Two TCP ports are used:
| Port | Default | Purpose |
|---|---|---|
| Control port | 8300 | Text commands and asynchronous status lines |
| Data port | 8301 | Raw application data (binary payload) |
| Broadcast port | 8100 | KISS-framed broadcast frames (separate) |
The control and data ports are base_port and base_port + 1 respectively;
override with -p <base_port>. The broadcast port is independent; override
with -b <port>.
All control commands and responses are CR-terminated ASCII (\r).
Commands are sent on the control port.
Set the local station callsign and optional secondary callsigns.
MYCALL <callsign> [<secondary1> <secondary2> ...]\r
Response: OK\r on success, WRONG\r on error. After OK, an
asynchronous REGISTERED <callsign>\r notification confirms the callsign is
recognised (VARA compatibility).
The first token is the primary callsign (up to 15 characters), used as the
source address for outgoing CALL and ACCEPT frames. Any additional
space-separated tokens are registered as secondary callsigns — Mercury will
accept incoming CALL frames addressed to any of them, up to a maximum of
CALLSIGN_MAX_SECONDARY (currently 4) secondary callsigns.
Sending a new MYCALL command replaces the primary callsign and clears all
previously registered secondary callsigns.
Must be set before LISTEN ON or CONNECT.
Examples:
MYCALL VK2XYZ\r
MYCALL VK2XYZ VK2XYZ-1 VK2XYZ-2\r
Enable or disable listening for incoming ARQ connections.
LISTEN ON\r
LISTEN OFF\r
LISTEN CQ\r
Response: OK\r on success, WRONG\r on error.
When enabled, Mercury enters the LISTENING state and will accept incoming CALL frames addressed to the local callsign (or any callsign if PUBLIC is ON).
LISTEN CQ is treated as LISTEN ON (VarAC compatibility).
Accept calls addressed to any callsign (promiscuous mode).
PUBLIC ON\r
PUBLIC OFF\r
Response: OK\r on success, WRONG\r on error.
Default is OFF. When ON, Mercury accepts incoming CALL frames regardless of the destination callsign.
Set the maximum ARQ bandwidth.
BW2300\r
BW500\r
BW2750\r
Response: OK\r on success, WRONG\r on error.
- BW2300 — Full bandwidth. Allows gear-shifting up to DATAC1 (510 bytes/frame).
- BW500 — Narrow bandwidth. Restricts the maximum payload mode to DATAC3/DATAC4.
- BW2750 — Tactical mode token accepted for VARA compatibility. Mercury
currently uses the same payload-mode ceiling as BW2300, but preserves
2750as a negotiated/reporting token.
During connection setup, Mercury advertises the local BW token in CALL and
returns the negotiated token in ACCEPT. If either side is BW500, the session
stays at 500 on both ends. If both sides are wide, the session keeps the lower
wide token (2300 or 2750) and CONNECTED ... BW reports that negotiated value.
No-op for VARA client compatibility.
COMPRESSION ON\r
COMPRESSION OFF\r
Response: OK\r (always).
Mercury does not use compression; this command exists so VARA-compatible clients (e.g., Pat, VarAC) can connect without errors.
Enable chat-optimized mode (VARA compatibility).
CHAT ON\r
CHAT OFF\r
Response: OK\r on success, WRONG\r on error.
CHAT ON implicitly enables LISTEN ON, placing Mercury in the LISTENING
state. This matches VARA behavior where chat applications (VarAC, VARA Chat)
expect the modem to be ready for incoming connections after CHAT ON.
CHAT OFF is acknowledged but has no effect — Mercury does not currently
differentiate chat and file-transfer timing.
No-op for VARA client compatibility.
P2P\r
Response: OK\r (always).
Initiate an ARQ connection to a remote station.
CONNECT <mycall> <theircall>\r
Response: OK\r if the command was accepted, WRONG\r on error.
Mercury will transmit CALL frames on DATAC13, advertising the local BW token,
and wait for an ACCEPT carrying the negotiated session BW.
On success, the asynchronous response
CONNECTED <sourcecall> <destcall> <bandwidth>\r is sent on the control port,
preserving the same call order as the original CONNECT command on both peers.
Example:
CONNECT AAAA BBBB\r
Transmit a compact DATAC13 CQ frame.
CQFRAME <sourcecall> <bandwidth>\r
<bandwidth> must be one of 500, 2300, or 2750.
Response: OK\r if the command was accepted, WRONG\r on error.
For VARA compatibility, Mercury also emits PENDING\r when the CQ frame
starts transmitting and CANCELPENDING\r once that CQ transmission is done.
Terminate the current ARQ session.
DISCONNECT\r
Response: OK\r if the command was accepted, WRONG\r on error.
Mercury sends DISCONNECT frames to the peer. Once complete, the
asynchronous response DISCONNECTED\r is sent on the control port.
Dirty disconnect — immediately flush all buffers and terminate the session without air-side teardown. The remote peer will time out.
ABORT\r
Response: OK\r if the command was accepted, WRONG\r on error.
Unlike DISCONNECT, ABORT does not send any over-the-air DISCONNECT
frames and clears all pending TX data immediately.
Query the modem identification string.
VERSION\r
Response: A VARA-compatible version string on the control port.
This command exists for VARA-compatible clients (e.g., VarAC) that check the modem version at startup.
No-op for VARA client compatibility.
IGNOREKISSDCD\r
Response: OK\r (always).
Query the number of bytes pending in the ARQ transmit buffer.
BUFFER\r
Response: BUFFER <bytes>\r on the control port.
Query the last measured signal-to-noise ratio.
SN\r
Response: SN <value>\r (e.g., SN 8.2\r) on the control port.
Query the current throughput estimate.
BITRATE\r
Response: BITRATE (<speed_level>) <bps> BPS\r on the control port.
Override the amount of retries Mercury will try to connect or retry a transmission before giving up. Setting to 0 should revert to the defined values in datalink_arq/arq_protocol.h.
RETRIES 10\r
Override the interval in whole seconds between successive CALL/ACCEPT frame retries during connection setup. This has no effect on other control frame timing (keepalive, disconnect, turn request) or on data frame retry timing once a session is established.
Send 0 to restore the compiled default (7 seconds). The minimum
enforced value is 4 seconds; values below 4 are clamped to 4 to avoid
firing a retry before a valid ACCEPT can return over the air.
CALLINT 5\r
CALLINT 0\r
Response: OK\r on success, WRONG\r on error.
Key the transmitter and hold a steady 1000 Hz tone, so an antenna tuner can find a match — and so an operator has a known reference to set drive against. Same syntax as VARA HF / VARA SAT.
TUNE -15\r key TX, tone at -15 dBFS
TUNE ?\r report the current drive level
TUNE OFF\r stop the tone and unkey
The level is absolute dBFS at the sound card, in the range -60 to 0.
It deliberately does not pass through the modulator TX gain (tx_gain):
TUNE -15 means −15 dBFS, not −15 dBFS scaled by whatever the modulator gain
happens to be — otherwise it would be useless as a reference for setting that
very gain.
Re-issuing TUNE <level> while a carrier is already running changes the level
and restarts the safety timer, which is what adjusting drive on a live tuner
requires.
The carrier always stops by itself after 60 seconds. A tuning carrier is the one transmission with no protocol underneath it, so nothing else bounds it: a host that crashes, forgets
TUNE OFF, or simply drops the control socket would otherwise leave the radio keyed — cooking the finals and jamming the channel. Do not rely on the timer for normal operation; sendTUNE OFFwhen the tuner is done.
TUNE is refused (WRONG\r) when:
- the level is outside
-60 .. 0dBFS, or is not a number; - an ARQ link is currently connected, or a burst is in flight — a tuning carrier and a data burst must never key the radio at the same time.
While the carrier is up, ARQ transmissions are suppressed; TUNE OFF (or the
timer) restores normal operation. The usual PTT ON\r / PTT OFF\r
asynchronous lines bracket the carrier exactly as they do a data burst.
Response: OK\r on success, WRONG\r on error.
TUNE ? replies TUNE <level>\r (for example TUNE -15\r).
These are sent on the control port without a preceding command.
| Response | Meaning |
|---|---|
PENDING\r |
Incoming connect request or outgoing CQ TX started |
CANCELPENDING\r |
Pending incoming connect cancelled or outgoing CQ TX completed |
CONNECTED <sourcecall> <destcall> <bandwidth>\r |
ARQ session established |
CQFRAME <sourcecall> <bandwidth>\r |
Compact CQ frame decoded |
DISCONNECTED\r |
ARQ session ended |
PTT ON\r |
Radio transmitter keyed |
PTT OFF\r |
Radio transmitter unkeyed |
BUFFER <bytes>\r |
TX buffer level update (periodic) |
SN <value>\r |
SNR update |
BUSY ON\r |
Channel became occupied (busy detector) |
BUSY OFF\r |
Channel became clear (busy detector) |
BITRATE (<level>) <bps> BPS\r |
Throughput update |
IAMALIVE\r |
Heartbeat (sent periodically while idle) |
REGISTERED <callsign>\r |
Callsign registration confirmed (after MYCALL) |
Sent when Mercury detects an incoming ARQ connect request addressed to the local station. This is an early warning so VARA-compatible host applications can suspend scanning or other idle activity while the link setup is in progress.
Mercury also sends PENDING\r when an outgoing CQFRAME actually begins
transmitting so VARA clients can treat CQ send as an in-progress operation.
Sent when a previously pending incoming connect request does not complete and Mercury returns to the idle/listening state.
Mercury also sends CANCELPENDING\r when an outgoing CQFRAME transmission
finishes, which matches the lifecycle expected by VARA clients such as varim.
Sent when a session is successfully established (either outgoing CONNECT
or incoming CALL accepted). The <bandwidth> value is the negotiated session
BW token from the CALL / ACCEPT exchange (500, 2300, or 2750).
If either peer is BW500, both sides report 500. If both peers stay wide,
Mercury reports the lower of the two wide tokens, preserving 2750 only when
both sides advertised it. <sourcecall> is always the station that initiated
the session, and <destcall> is always the station that was called.
Sent when Mercury decodes a compact DATAC13 CQ frame on the air.
<sourcecall> is the transmitting station and <bandwidth> is the BW token
advertised inside that CQ frame (500, 2300, or 2750).
Emitted by the optional channel-busy (occupancy) detector when it observes the
HF channel transition between clear and occupied, using VARA's exact wording so
existing VARA-compatible hosts (VarAC, BPQ32, Winlink) act on them unchanged.
Edge-triggered: BUSY ON\r on clear→busy, BUSY OFF\r on busy→clear.
The detector is enabled by default and can be turned off via the [channel]
section of mercury.ini (busy_detect = false); its sensitivity/timing knobs
(busy_threshold_db, busy_hysteresis_db, busy_on_debounce_ms,
busy_hang_ms) typically need on-air tuning per band/noise environment. When
disabled, these notifications are never sent. See mercury.ini.example.
BUSY ON is the earliest notification a host can act on: it follows the carrier
by roughly the debounce time (~0.3 s by default), whereas PENDING cannot be
sent until a whole connect request has decoded — 3.74 s in the DATAC16 control
mode. A host that scans channels needs the former to hold its dwell long enough
to receive the latter.
Sent when the session ends, either by local DISCONNECT, remote DISCONNECT, or timeout.
Sent periodically during data transfer. The value reflects the number of
application bytes still queued for transmission. When it reaches 0, all
data has been acknowledged by the peer.
Sent periodically on the control port as a keepalive to detect broken TCP connections.
Sent when a callsign is set via MYCALL, confirming the callsign is
licensed (VARA compatibility). Arrives after the OK\r response to
MYCALL. Also sent on client reconnect if a callsign is already set.
REGISTERED is per call sign, so MYCALL emits one line for the primary
and one for each secondary it accepted, in the order given:
MYCALL AAAA BBBB CCCC\r
OK\r
REGISTERED AAAA\r
REGISTERED BBBB\r
REGISTERED CCCC\r
Secondaries beyond the four Mercury can hold are dropped, and dropped ones are not acknowledged — the host would otherwise address a callsign this station never answers.
The data port (base_port + 1, default 8301) carries raw application
payload. Bytes written to the data port are queued for ARQ transmission;
bytes received from the remote station are delivered on the data port.
No framing is needed — Mercury handles segmentation internally. The data port only carries payload when a session is CONNECTED.
The broadcast port (default 8100) is independent of ARQ and uses KISS framing. One-way broadcast frames are sent/received as fixed-size KISS-encoded packets matching the modem's payload size.
Three client framings are accepted, distinguished by the KISS command byte:
0x00(standard KISS data / VARA "AX.25 standard") and0x01(VARA "AX.25 7-char callsign", used by VarAC): Mercury injects its 1-byte broadcast header plus a 2-byte payload-length prefix, zero-pads to the modem frame size, and records which of the two framings the sender used in a header extension bit (BCAST_EXT_KISS_STD). The receiving side delivers exactly the original payload with the sender's command byte — so VarAC↔VarAC traffic stays0x01and standard-KISS clients (e.g. Reticulum, see RETICULUM.md) get0x00.0x02(CMD_DATA, used by hermes-broadcast): the frame is passed raw — the client supplies its own broadcast header, and receivers with aCMD_DATAclient get the full unmodified frame back.
Payloads larger than the modem frame (minus 3 bytes of header+length)
are truncated (0x00/0x01) or discarded (0x02) — the broadcast plane
does not fragment.
Client Mercury
| |
|--- (TCP connect to 8300) ---->|
|--- (TCP connect to 8301) ---->|
| |
|--- MYCALL AAAA\r ------------>|
|<-- OK\r ----------------------|
|<-- REGISTERED AAAA\r ---------|
| |
|--- LISTEN ON\r -------------->|
|<-- OK\r ----------------------|
| |
|--- BW2300\r ------------------>|
|<-- OK\r ----------------------|
| |
|--- CONNECT AAAA BBBB\r ------>|
|<-- OK\r ----------------------|
| | (RF: CALL/ACCEPT exchange)
|<-- CONNECTED AAAA BBBB 2300\r |
| |
|--- (write data to 8301) ----->| (RF: DATA frames)
|<-- BUFFER 2404\r -------------|
|<-- PTT ON\r ------------------|
|<-- PTT OFF\r ------------------|
|<-- BUFFER 0\r ----------------|
| |
|<-- (read data from 8301) -----| (received from remote)
| |
|--- DISCONNECT\r -------------->|
|<-- OK\r ----------------------|
|<-- DISCONNECTED\r ------------|
- ARQ Protocol & Architecture — Wire protocol, FSM, gear-shifting, tuning guide.
- Mercury README — Build instructions, CLI usage, project links.