AT Command Reference
The gateway's serial ports emulate a Hayes Smartmodem. A vintage computer drives them with the same AT commands it would send a real modem — except a “dial” opens a TCP connection instead of a phone call.
Each of the two serial ports, when in Modem (AT Command)
Mode, presents a Hayes-compatible command interface. Your retro
machine's terminal program talks to it exactly as if it were a
Smartmodem 2400 or compatible: type AT commands in
command mode, “dial” to open a connection,
exchange data in online mode, and use the
+++ escape to slip back to command mode without dropping the
link. There is no phone line — ATDT host:port is a
TcpStream::connect().
AT (or at — commands are case-insensitive) and ends with a carriage return.A/, which repeats the last command with no AT and no carriage return.OK, CONNECT, ERROR, etc. — in words (verbose) or as a digit (numeric), controlled by ATV.ATE0Q0V1); see Command Chaining.0 when omitted: ATH = ATH0, ATE = ATE0.AT&W persists them to egateway.conf and ATZ reloads that saved profile.ATDT ethernet-gateway loopback. Each port keeps its own
independent AT / S-register state and its own AT&W
profile (serial_a_* / serial_b_*). For the
hardware-setup and menu walkthrough, see the
Serial Modem section of the User Manual.
| Command | Effect |
|---|---|
AT | Attention / line check. Returns OK — the classic “is the modem there?” probe. |
A/ | Repeat the last command line. No AT prefix, no carriage return — the modem acts the instant it sees the slash. Handy for re-dialing. |
AT? | Print the built-in AT command help. |
ATZ | Reset to the stored profile (the last AT&W, read from egateway.conf). Drops any active connection. |
AT&F | Restore the gateway-friendly factory defaults. Does not overwrite the stored profile, but does drop any active connection. |
AT&W / AT&W0 | Save the current settings (echo, verbose, quiet, all 27 S-registers, X, &C, &D, &K, +PETSCII, and the four stored numbers) to egateway.conf. |
AT&V | Display the current configuration — a line of mode flags, a line of all S-registers, and a line of stored numbers. |
ATH / ATH0 | Hang up — close any active connection and return to command mode. |
ATA | Answer an incoming “call” (a ring from the Ring Emulator) immediately, before S0 rings elapse. |
ATO / ATO0 | Return to online (data) mode after a +++ escape, resuming the preserved connection. |
The ATIn family reports product and firmware strings — some terminal programs probe these to recognise the modem.
| Command | Response |
|---|---|
ATI / ATI0 | Hayes-compatible Ethernet Gateway Modem Emulator v0.6.2 |
ATI1 | 000 — ROM checksum (virtual) |
ATI2 | OK — ROM self-test |
ATI3 | Ethernet Gateway v0.6.2 (Hayes-compatible) |
ATI4 | Hayes-compatible virtual modem over TCP |
ATI5 | B00 — OEM / country code |
ATI6 | No link diagnostics available |
ATI7 | Product: ethernet-gateway (software emulator) |
| Command | Effect |
|---|---|
ATE0 / ATE1 | Command echo off / on. Default on. Turn it off (ATE0) for scripted init strings so you don't see your own typing echoed back. |
ATV0 / ATV1 | Result codes as numeric digits / verbose words. Default verbose. |
ATQ0 / ATQ1 | Result codes enabled / suppressed (quiet). Default enabled. ATQ1 silences all result codes — useful when a program is confused by them. |
In verbose mode the modem returns the word; in numeric mode (ATV0) the digit. Which codes can appear depends on the ATX level (below).
| Verbose | Numeric | Meaning |
|---|---|---|
OK | 0 | Command accepted. |
CONNECT | 1 | Connected (no speed reported — X0, or a non-standard rate). |
RING | 2 | An incoming call is ringing. |
NO CARRIER | 3 | Connection failed, ended, or was refused. |
ERROR | 4 | Command not understood or out of range. |
CONNECT <baud> | 5/10/12/16/28/87 | Connected, with speed (X1+). Codes: 1200=5, 2400=10, 9600=12, 19200=16, 38400=28, 115200=87, 300=1. |
NO DIALTONE | 6 | Only at X2 and above; otherwise folds into NO CARRIER. |
BUSY | 7 | Only at X3 and above; otherwise NO CARRIER. |
NO ANSWER | 8 | Only at X3 and above; otherwise NO CARRIER. |
| Command | Extended codes | CONNECT format |
|---|---|---|
ATX0 | Basic only; BUSY / NO DIALTONE / NO ANSWER all collapse to NO CARRIER | CONNECT (no baud) |
ATX1 | Basic + speed reporting | CONNECT <baud> |
ATX2 | Adds NO DIALTONE | CONNECT <baud> |
ATX3 | Adds BUSY / NO ANSWER | CONNECT <baud> |
ATX4 (default) | Full extended set | CONNECT <baud> |
| Command | Meaning |
|---|---|
AT&C0 | DCD (carrier-detect) always asserted. |
AT&C1 (Hayes default) | DCD reflects the connection state. |
AT&D0 (gateway default) | Ignore DTR entirely. |
AT&D1 | DTR drop → return to command mode. |
AT&D2 (Hayes default) | DTR drop → hang up. |
AT&D3 | DTR drop → hang up and reset. |
AT&K0 (gateway default) | No modem-layer flow control. |
AT&K1 | Auto-detect (accepted and stored; no wire-level effect). |
AT&K3 | Bidirectional RTS/CTS hardware flow control. |
AT&K4 | Bidirectional XON/XOFF software flow control. |
&D0 (not &D2) and &K0
(not &K3) because many C64 / CP/M clients don't wire DTR
or implement flow control — the Hayes defaults would cause spurious
disconnects. S7 is also lowered to 15 s. All are overridable
(AT&D2, AT&K3, ATS7=50) and
persist with AT&W.
&C,
&D, and &K are parsed, stored, persisted,
and shown by AT&V, but the emulator does not toggle the
real RS-232 DCD / DTR / DSR / RI pins. Actual wire flow control is set by
each port's serial_x_flowcontrol config key, not by
&K. If your terminal program insists on DCD before it will
talk, look for its “ignore carrier” / “force DTR”
option.
A gateway-specific vendor extension that makes ASCII BBSes readable on a PETSCII Commodore when you dial them directly over TCP.
| Command | Effect |
|---|---|
AT+PETSCII=0 (default) | Off — direct-TCP dials (ATDT host:port) are raw ASCII passthrough. |
AT+PETSCII=1 | On — translate between PETSCII and ASCII on direct-TCP dials. |
With AT+PETSCII=1, on a direct-TCP dial the emulator:
telehack.com reads in the right case.AT command line itself.ESC [ … cursor / colour codes) so they don't spray as garbage on a screen that can't render them.', smart double quotes to ", tilde / en- / em-dashes to -, the ellipsis to ...; other undisplayable high bytes are dropped or shown as ?.ATDT ethernet-gateway already detects PETSCII terminals through
the telnet menu and renders accordingly. It is set-only
(=0/=1), persists immediately (and re-saves with
AT&W), reloads on ATZ, resets to off on
AT&F, and is reported by AT&V as
+PETSCII:n. It lives in the ITU-T V.250 +
extended-command namespace (not AT&P, which means
pulse-dial ratio on real modems). Also editable from the telnet, web, and
GUI config surfaces.
A “dial” is a TCP connect. The dial string is a host:port, a stored slot, or a phone number mapped in dialup.conf.
| Command | Effect |
|---|---|
ATDT host:port | Tone-dial — open a TCP connection to host:port. The default for all TCP dials. |
ATDP host:port | Pulse-dial — identical to ATDT over TCP (there's no audible difference). |
ATD host:port | Generic dial (no T/P selector). |
ATDT ethernet-gateway | Built-in shortcut — “dial” this gateway's own main menu, so the serial device gets file transfer, browser, AI chat, etc. with no network detour. |
ATDT KERMIT | Drop straight into Kermit server mode (aliases: kermit, kermit-server, kermit server). Requires allow_atdt_kermit = true; off by default. See the Kermit Reference. |
ATDL | Redial the last number. |
ATDS / ATDSn | Dial the stored number in slot n (0–3; bare ATDS = slot 0). |
AT&Zn=s | Store phone number or host:port string s in slot n (0–3). Hostname case is preserved. Persisted with AT&W. |
Honoured only when the dial string looks like a phone number (digits + formatting). A hostname such as pine.example.com is dialled verbatim — modifiers are not stripped from it (except a trailing ;).
| Modifier | Effect |
|---|---|
, | Pause S8 seconds (default 2) per comma before continuing. |
W | Wait for dial tone — adds S6 seconds to the pre-delay. |
; | Return to command mode after connect instead of going online (applies to hostnames too). |
* # | DTMF digits — preserved in the dial target for dialup.conf lookup. |
P T @ ! | Pulse / tone / quiet-answer / hookflash selectors — accepted and ignored. |
dialup.conf (digits only — dashes, spaces, and
parens are ignored), which maps numbers to host:port targets.
The built-in entry 1001000 always reaches the local gateway
menu and can't be deleted. An unmapped number returns NO CARRIER.
S-registers hold numeric timing and behaviour parameters. Query with ATSn?, set with ATSn=v (0–255), list help with ATS?. AT&W saves all 27; ATZ restores them; AT&F resets to factory.
| Reg | Default | Meaning |
|---|---|---|
S0 | 5 | Auto-answer ring count (0 = don't auto-answer). |
S1 | 0 | Ring counter (read-only). |
S2 | 43 | Escape character (43 = +). Values > 127 disable the +++ escape. |
S3 | 13 | Carriage-return character. |
S4 | 10 | Line-feed character. |
S5 | 8 | Backspace character. |
S6 | 2 | Wait-for-dial-tone seconds (the W modifier). |
S7 | 15 | Wait-for-carrier seconds. Hayes default is 50; lowered here so failed TCP dials return fast. Capped internally at 60. |
S8 | 2 | Comma pause time (seconds). |
S9 | 6 | Carrier-detect response time (1/10 s). |
S10 | 14 | Carrier-loss disconnect time (1/10 s). |
S11 | 95 | DTMF tone duration (ms). |
S12 | 50 | Escape guard time (1/50 s; 50 = 1.0 s). 0 disables the escape. |
S13–S24 | 0 | Reserved placeholders — stored and persisted so legacy init strings don't error, but with no effect. |
S25 | 5 | DTR detect time (1/100 s). Reserved — no DTR pin. |
S26 | 1 | RTS-to-CTS delay (1/100 s). Reserved — no RTS/CTS pins. |
S3 = 8 would make backspace
terminate the line. The Hayes defaults (13 / 10 / 8) are safe; leave them
be.
How to get back to command mode without hanging up.
While online (passing data), typing +++ framed by a guard
time of silence on both sides drops you to command mode with the
connection still alive. From there, ATO resumes the data
session and ATH hangs up. This is the exact Hayes guard-time
behaviour:
S2 (default 43 = +).S12 / 50 seconds (default S12 = 50 → 1.0 s) of silence required both before the first + and after the third.S12 = 0, or S2 > 127, disables escape detection entirely.(online, exchanging data)
...wait ~1 second of silence...
+++
...wait ~1 second of silence...
OK now in command mode, link preserved
ATO resume the data session
-- or --
ATH hang up for good
S12 (e.g. ATS12=25 for a half-second guard) to
tighten the window, or enable the gateway byte-trace
(EGATEWAY_GATEWAY_DEBUG) to see exactly what broke it.
Multiple commands can ride on a single AT line, the way real
Hayes modems accept init strings. The emulator parses left-to-right,
applies each subcommand, and emits a single OK at the end
(or ERROR at the first failure — subcommands before the
failure still apply; those after do not run). Spaces between subcommands
are tolerated.
Some subcommands terminate the chain because they consume the rest of the line or leave command mode:
D… — any dial command goes online and consumes the rest of the line.A — answer; leaves command mode.O / O0 — return to online mode.&Zn=… — the stored-number value runs to end of line.
S-register set values stop at the first non-digit, so
ATS0=2E0 sets S0=2 then turns echo off —
no separator needed.
OK. Commands the
emulator has no hardware to implement — ATB,
ATC, ATL (speaker volume), ATM
(speaker), AT&B, AT&G,
AT&J, AT&S, AT&T,
AT&Y, and the like — are silently accepted with
OK so legacy init strings run to completion instead of
halting mid-setup with ERROR.
Common things you'll actually type. Lines without a result code shown assume verbose mode (the default).
AT OK
ATDT bbs.example.com:23
CONNECT 9600
(you're online — the BBS appears)
ATDT ethernet-gateway
CONNECT 9600
(the Ethernet Gateway main menu appears)
AT&Z0=bbs.example.com:23 OK
AT&W OK (persist it)
ATDS0 CONNECT 9600
ATE0Q0V1X4 OK
(echo off, result codes on, verbose, full extended codes)
+++ OK (still connected)
ATO CONNECT 9600 (back online)
...or...
ATH NO CARRIER (hung up)
ATS0=2 OK (auto-answer after 2 rings)
ATS7=50 OK (wait up to 50s for a slow connect)
ATS0? 002 (query: 3-digit decimal)
AT&W OK (persist)
AT+PETSCII=1 OK (translate ASCII ↔ PETSCII)
ATDT telehack.com:23
CONNECT 9600
(text now reads in the correct case on the C64)
ATDT bbs.example.com:23
NO CARRIER (busy — try again)
A/ (repeats the dial, no AT/Enter needed)
Deep-dive reference pages for every protocol and interface, plus the character-set tables and ANSI escape-sequence reference.
128-byte blocks; CRC-16 / checksum negotiation.
Block-0 metadata, batch, exact size truncation.
Streaming; ZDLE, CRC-32, autostart, resume.
Send-Init negotiation; F / A / D / Z / B transfer.
C1 dual checksum, two-phase, GOO/BAD/ACK.
Hayes command set, S-registers, +++ escape.
IAC negotiation, every option, the NVT data phase.
Server, gateway, host keys, TOFU, auth modes.
Hex tables for every encoding: ASCII, ANSI, PETSCII, ATASCII, Baudot/ITA2, ZX Spectrum, TRS-80.
Cursor, colour/SGR, erase, and screen-mode escape codes, with the raw hex bytes.