18 KiB
VT1200 keyboard & mouse serial protocol — distilled specification
Everything here is attributed to a source in SOURCES.md, and each fact is tagged
[confirmed], [probable] or [unknown].
0. Bottom line
There is no VT1200-specific protocol document. What exists is documentation for the
LK201 keyboard (and its successor the LK401) and for the VSXXX-AA/-GA mouse /
VSXXX-AB tablet. The evidence that these are the VT1200's parts — and therefore that
their protocols apply — is strong and is laid out in §1. The two facts the level-1
Keyboard/Mouse tests need (the self-test command and its reply) are covered by public
sources: it is FD → 01 00 00 00 for the keyboard and T → a 4-byte report for the mouse.
See §3.5 and §4.4.
Status of the question in the brief: closest-part-only. The VT1200's own manuals never describe the wire protocol.
1. Which parts the VT1200 uses — the evidence
| Fact | Value | Confidence | Source |
|---|---|---|---|
| Keyboard family | LK400 series; LK401-XX standard, LK402-XX word-processing |
[confirmed] | EK-V1000-SV-002_service-guide.txt §1.1.3 |
| Keyboard, ROM side | Terminal firmware source file is named LK401.C; ROM strings "The keyboard ROM reported a fault at power-up", "A key was held down during power-up" |
[confirmed] | ../rom-strings.txt (offsets 0x0E4AB9, 0x0E4B2A, 0x0E4B58) |
| Keyboard, model designation | LK401 Keyboard appears as a heading in the VT1200 user guide |
[confirmed] | ../../docs/EK-V1200-UG-001_installing-VT1200.txt (TOC §"The Keyboard") |
| LK401 electrical/firmware relation to LK201 | "not intended to be a direct replacement for the LK201, but is electrically and firmware functionally compatible" | [confirmed] | vt100net-lk401.txt line 239 |
| LK401 host protocol = LK201 protocol | LK401 spec says the terminal→keyboard protocol "can be found in the LK400 Keyboard Firmware Requirements"; lkkbd.c and elkay implement one driver for both, and lkkbd.c enables extra LK401 keys with one added command |
[probable] | vt100net-lk401.txt line 678; linux-lkkbd.c lines 39–46; elkay/docs/protocol.md |
| Mouse / tablet | 3-button pointing device; service guide calls the device test "mouse or tablet"; a VSXXX-AB tablet is the optional alternative |
[confirmed] device type / [probable] exact model VSXXX-AA |
EK-V1000-SV-002_service-guide.txt; vcb02-az-glgab-mn-feb86-text.txt App. C/D |
So: keyboard = LK401, which speaks the LK201 serial protocol; mouse = VSXXX-AA (hockey-puck), with the VSXXX-AB tablet as the alternate the firmware also supports.
2. Topology — separate ports, NOT daisy-chained
This is the one place the VT1200 differs from the common LK201/VSXXX picture (where the mouse hangs off the keyboard).
- The terminal ROM's own test list names two separate DUART2 channels:
H - DUART2, CHANNEL A (KEYBOARD)andI - DUART2, CHANNEL B (MOUSE). [confirmed] (../rom-strings.txt, offsets 0x179795 / nearby;../level1-test-sequence.md). - The service guide tells the technician to "Disconnect the keyboard, mouse, or printer from the rear of the system box"; the VT1200 user guide says "The keyboard cable connects to the system box" and "The mouse connects to the system box". [confirmed]
- The service guide provides a separate mouse-port loopback connector (12-25628-01) and a distinct Mouse Port Test (19) vs Keyboard Port Test (18). [confirmed]
- The VCB02 (the architectural ancestor, same Q-bus/DUART design) likewise keeps the keyboard
on DUART channel A and the pointing device on channel B, with "the other port …
for any other serial device, probably a mouse or a tablet". [confirmed]
(
vcb02-az-glgab-mn-feb86-text.txtlines ~9635, and the DUART reset-default table.)
Conclusion [confirmed]: on the VT1200 the keyboard is on DUART2-A and the mouse is on DUART2-B, as two independent serial links. The mouse is NOT daisy-chained through the keyboard. This matches the already-wired MAME SCN2681 at both DUART windows.
3. Keyboard (LK401, LK201 protocol)
3.1 Wire parameters
| Parameter | Value | Confidence | Source |
|---|---|---|---|
| Baud | 4800 | [confirmed] | netbsd-lk201-interface.html; vt100net-lk401.txt §3.5.4 "4800 baud only"; MAME lk201.cpp set_rate(4800) |
| Data bits | 8 | [confirmed] | LK401 §3.5.5 "start bit, 8 data bits, stop bit"; vt100net-lk401.txt |
| Parity | none | [confirmed] | LK401 §3.5.5 has no parity element (8N1); netbsd-lk201-interface.html ("8N1"); MAME set_data_frame(1, 8, PARITY_NONE, STOP_BITS_1) |
| Stop bits | 1 | [confirmed] | as above |
| Levels | EIA RS-423, ±5 V, powered from +12 V | [confirmed] | netbsd-lk201-interface.html; elkay/docs/protocol.md |
| Connector | 4P4C modular: 1=host TX→kbd, 2=GND, 3=+12 V, 4=kbd→host RX | [probable] (pin order differs between write-ups; verify at the cable) | linux-lkkbd.c header; elkay/docs/protocol.md |
3.2 Framing / command encoding
Host→keyboard: a command is one or more bytes. Bit 7 of the last byte of every command is
set (the "PARAMS" flag); bit 7 of a non-final byte is clear, and byte bit 0 is the
"TYPE" flag (0 = transmission command, 1 = peripheral command). [confirmed]
(vcb02-az-glgab-mn-feb86-text.txt §B.5.5.1–B.5.5.2.) Keyboard→host: single bytes.
3.3 Host → keyboard command set (VCB02 Table B-7, cross-checked against drivers)
| Bytes | Meaning | Conf. | Source |
|---|---|---|---|
FD |
Jump to Power-Up / Reinitiate Keyboard — keyboard runs its self-test and sends the 4-byte power-up sequence (§3.5) | [confirmed] | VCB02 B.5.5.3 "The jump to power-up command is FD (hexadecimal)"; linux-lkkbd.c LK_CMD_POWERCYCLE_RESET 0xfd; vt100net-lk201-keyboard.html trace |
AB |
Request keyboard ID — returns the 2-byte ID, does not jump to power-up | [confirmed] | VCB02 Table B-7; linux-lkkbd.c; netbsd-lk201-interface.html |
D3 |
Reinstate defaults | [confirmed] | VCB02 Table B-7; linux-lkkbd.c |
CB |
Jump to test mode (factory) → replies B8 |
[confirmed] | VCB02 Table B-7; netbsd-lk201-interface.html |
13 p / 11 p |
LEDs on / off; p bitmask: 01 Wait, 02 Compose, 04 Lock, 08 Hold Screen (parameter high bit set, e.g. 8F = all) |
[confirmed] | VCB02 Table B-7 + Fig. B-11; netbsd-lk201-interface.html |
99 |
Disable keyclick | [confirmed] | VCB02 Table B-7 |
1B v |
Enable keyclick, volume v (0x80|0–7, 0 = loudest) |
[confirmed] | VCB02 Table B-7 + Fig. B-13 |
B9 |
Disable Ctrl-key click | [confirmed] | VCB02 Table B-7 |
BB v |
Enable Ctrl-key click | [confirmed] | VCB02 Table B-7 |
9F |
Sound a keyclick | [confirmed] | VCB02 Table B-7 |
A1 |
Disable bell | [confirmed] | VCB02 Table B-7 |
23 v |
Enable bell, volume | [confirmed] | VCB02 Table B-7 |
A7 |
Sound bell | [confirmed] | VCB02 Table B-7 |
D1 |
Temporary auto-repeat inhibit | [confirmed] | VCB02 Table B-7 |
E3 / E1 |
Enable / disable auto-repeat across keyboard | [confirmed] | VCB02 Table B-7 |
D9 |
Change all auto-repeat to down-only | [confirmed] | VCB02 Table B-7 |
8B |
Resume keyboard transmission | [confirmed] | VCB02 Table B-7 |
89 (VCB02 OCR) / B9 (NetBSD) |
Inhibit keyboard transmission | [unknown] — the two sources disagree (89 vs B9); treat as unresolved |
VCB02 Table B-7; netbsd-lk201-interface.html |
0x86 | d<<3 |
Set division d (1–14) to a mode: low bits 00 down, 10 auto-down, 11 down/up |
[confirmed] | VCB02 B.5.5.4; netbsd-lk201-interface.html; elkay/docs/protocol.md |
E9 |
LK401 mode: enables the extra keys (LAlt, RAlt, RCompose, RShift). LK401-only. | [confirmed] | linux-lkkbd.c LK_CMD_ENABLE_LK401; elkay/docs/protocol.md |
⚠ The level-0 I/O data-path anomaly recorded in
../level1-test-sequence.mdsays the firmware writes0xE1to DUART2-A and expects a 10-byte reply.0xE1is documented as "disable auto-repeat across keyboard", which has no reply in any source here. So either that level-0 write is not what it looks like, or0xE1is a transcription error. [unknown] — flag it for the ROM/Ghidra side; it is not the keyboard self-test.
3.4 Keyboard → host special codes (single bytes)
B3 All-Up (last down/up key released) · B4 Metronome/auto-repeat tick · B5 Output Error
(buffer overflow) · B6 Input Error (bad command) · B7 KBD-locked ACK · B8 Test-mode ACK ·
B9 Prefix-to-keys-down · BA Mode-change ACK · 7F reserved. [confirmed]
(VCB02 Table B-4; netbsd-lk201-interface.html; linux-lkkbd.c.) Ordinary keycodes are
single bytes > 0x40; every key has one unique code, no shift/ctrl variants. [confirmed]
Full keycode table: netbsd-lk201-keycodes.html (14 divisions).
3.5 Power-up / self-test — what the level-1 Keyboard Test (error 27) exercises
On power-up, or on receiving FD, the keyboard runs a self-test in ≤70 ms and sends a
4-byte result. [confirmed] (VCB02 §B.5.4.3; NetBSD; LK401 §3.3.4.6; and the captured
VT320 trace in vt100net-lk201-keyboard.html.)
| Byte | Meaning | Value |
|---|---|---|
| 1 | Keyboard ID — firmware | 01 (lkkbd.c also accepts 02 = LK401 from the AB reply) |
| 2 | Keyboard ID — hardware | 00 |
| 3 | Error code | 00 = OK · 3D = key held down at power-up · 3E = ROM/RAM self-test failure |
| 4 | Keycode of the key held down, else 00 |
e.g. AE in the stuck-shift trace |
- Healthy reply:
01 00 00 00. Captured live on a VT320/LK201 invt100net-lk201-keyboard.html; emulated identically bylk201emu(resetkb()sends1,0,0,0) and expected bylinux-lkkbd.c. [confirmed] - On a stuck key the reply becomes
01 00 3D <keycode>and the terminal re-issuesFD. [confirmed] (vt100net-lk201-keyboard.html.) - "If the self-test fails and the error is fatal, the keyboard is unable to transmit." [confirmed] (VCB02 §B.5.4.3.)
⇒ Implement the device-test model to: on receiving FD, reply 01 00 00 00. The
terminal's own display of the error code (message "Keyboard Error - 27") comes from its
interpretation of byte 3; "any error code" from the device is what the service guide means by
"display any error code".
3.6 Wire parameters under test — does the terminal's test override them?
No source shows the Keyboard/Mouse tests changing baud/parity. The self-test is a normal
command on the already-configured port. [probable] — the VCB02 DUART reset-default table
sets channel A to "8 data, parity Off, 4800" and channel B to "8 data, parity Odd, 4800"
(vcb02-az-glgab-mn-feb86-text.txt §5.5.2.5, Table 5-9). Treat 4800/8N1 (kbd) and 4800/8O1
(mouse) as the port defaults; the VT1200's SCN2681 should be programmed the same way. [probable]
4. Mouse / tablet (VSXXX-AA / VSXXX-AB)
4.1 Wire parameters
| Parameter | Value | Confidence | Source |
|---|---|---|---|
| Baud | 4800 | [confirmed] | VCB02 §C.4; linux-vsxxxaa.c |
| Data bits | 8 | [confirmed] | VCB02 §C.6.1 |
| Parity | ODD | [confirmed] | VCB02 §C.6.1; allpinouts-dec-7pin.html; linux-vsxxxaa.c ("4800, 8o1") |
| Stop bits | 1 | [confirmed] | VCB02 §C.6.1 |
| Levels | RS-232-compatible (mark < −6 V, space > +4.6 V) | [confirmed] | VCB02 §C.5 |
| Connector | 7-pin micro-DIN: 1 GND, 2 TxD(mouse out), 3 RxD(into mouse), 4 −12 V, 5 +5 V, 6 n/c, 7 device-present→pin1 | [confirmed] | VCB02 Table C-1; vaxarchive-vsxxx.html |
| Duplex | half-duplex; a host byte during a mouse transmission aborts it | [confirmed] | VCB02 §C.6.1 |
4.2 Host → mouse commands (printable ASCII)
R (0x52) incremental stream mode · D (0x44) prompt mode (power-up default) · P (0x50)
request position (also enters prompt mode) · T (0x54) self-test & identify ·
S (0x53) select report format · Z (0x5A) reserved. Invalid commands are ignored.
[confirmed] (VCB02 Table C-2; linux-vsxxxaa.c; vaxarchive-vsxxx.html.)
4.3 Mouse → host position report (3 bytes, incremental mode)
bit 7 6 5 4 3 2 1 0
1 0 0 SX SY L M R byte 1 (header 100)
0 X6 X5 X4 X3 X2 X1 X0 byte 2
0 Y6 Y5 Y4 Y3 Y2 Y1 Y0 byte 3
SX/SY sign (1 = positive), L/M/R buttons (1 = depressed), X/Y in resolution units since
last report. [confirmed] (VCB02 Fig. C-4; linux-vsxxxaa.c; vaxarchive-vsxxx.html.)
4.4 Power-up / self-test — what the level-1 Mouse Test (error 26) exercises
On power-up, or on receiving T, the device sends a 4-byte self-test report, starting
bits 101 (0xA0). [confirmed] (VCB02 §C.6.5 and Fig. C-5; linux-vsxxxaa.c; captured in
vaxarchive-vsxxx.html.)
byte 1: 1 0 1 0 R3 R2 R1 R0 revision
byte 2: 0 M2 M1 M0 D3 D2 D1 D0 M = manufacturer loc.; device code D: 0010 = mouse, 0100 = tablet
byte 3: 0 E6 E5 E4 E3 E2 E1 E0 error code
byte 4: 0 0 0 0 0 L M R button state, or the failed button if byte 3 = 3D
- Byte-3 error codes:
00= OK;3E= ROM/RAM checksum error;3D= button error; codes ≥ 0x20 are fatal, < 0x20 non-fatal. [confirmed] (VCB02 §C.6.5;vsxxxaa.ctreats ≤0x1f as "no serious error".) - Self-test leaves the device in the reset/power-up state; data sent during self-test is ignored. Self-test completes within 500 ms (power-up within 1 s). [confirmed] (VCB02 §C.6.4/§C.6.7.)
- Recommended host init (VCB02 §C.7.1): configure port for
4800 8O1; read the power-up self-test report; if none within 1 s, sendT; thenS; thenR(orD). [confirmed]
⇒ Implement the device-test model to: on receiving T, reply a well-formed self-test
report (e.g. header 0xA0|rev, device byte 0x02, error 00, buttons 00). This is
exactly "firmware requests that the mouse do its self-test and display any error code".
4.5 Tablet (VSXXX-AB) — for completeness
Same connector, same serial parameters, same command set plus extras; power-up self-test differs
only in device code (0100) and a 5-byte absolute-position report (header 110/0xC0).
[confirmed] (VCB02 App. D, §C.7.4; linux-vsxxxaa.c ABS branch.) Not needed for the level-1
mouse test unless a tablet is what's attached.
Coordinate range: the absolute position spans 0..2199 over the active area
(VCB02 App. D.1). [confirmed]
How the terminal chooses — there is no separate command and no setup record. The device
code in the T reply is the whole discriminator, and the host then frames 3-byte relative
reports for a mouse (0010) or 5-byte absolute ones for a tablet (0100). [confirmed]
against the running OS in the harness: it sends T, reads A0 04 00 00 from a tablet, and then
reads RHRB in groups of 5 — groups of 3 with a mouse.
5. How a device failure is reported back (both devices)
The terminal displays an error code it derived from the device's self-test reply: keyboard
error byte 3 (3E/3D), mouse error byte 3 (3E/3D, or ≥0x20 fatal). The service guide's
troubleshooting table then says, for error 27, "Replace the keyboard"; for error 26,
"run the Mouse Port Test with external loopback … otherwise replace the mouse". [confirmed]
(EK-V1000-SV-002_service-guide.txt Table 3-1.)
6. MAME relevance (drop-in candidates)
- Keyboard: MAME already has a DEC LK201 device.
DECLARE_DEVICE_TYPE(LK201, lk201_device), device name"lk201", "DEC LK201 Keyboard", insrc/mame/dec/lk201.h/src/mame/dec/lk201.cpp. It is adevice_t + device_serial_interface, i.e. it expects a DUART-style serial channel — it would attach to the same SCN2681 channel A we already wired. It models the 68HC05 keyboard MCU and executes the real keyboard firmware ROM (23-001s9-00.bin), so the protocol behaviour (including theFDself-test reply) comes from that ROM, not from C. It wires asm_lk201->tx_handler().../m_lk201->rx_w()(seesrc/mame/dec/vt240.cpp, which places it behind an i8251). It does NOT model the mouse. - Mouse: no DEC mouse device exists in MAME (checked
src/mame/dec/and the tree; novsxxx*). We would need a small HLE model, but §4 gives the complete protocol, so this is low-risk. - Caveat / gap: MAME's
lk201wants the 6805 LK201 ROM23-001s9-00.bin, which is not in the bitsavers zip we have (that is the 805123-004M2). Running MAME's device therefore needs that ROM sourced first; otherwise implement a HLE keyboard that answersFDwith01 00 00 00(and optionally honoursAB,13/11, mode-setBAACKs). For merely passing level-1 tests 26/27, an HLE keyboard + HLE mouse driven off DUART2-A/B is the smallest sufficient model and needs no ROMs at all.
7. Confidence summary
| Item | Status |
|---|---|
| VT1200 uses LK401 keyboard / VSXXX-AA mouse | confirmed (service guide + ROM) |
| Keyboard LK401 speaks LK201 protocol | probable (LK401 spec: "firmware functionally compatible"; shared drivers) |
| Keyboard wire: 4800 8N1, RS-423 | confirmed |
Keyboard self-test command FD → 01 00 00 00 (+ 3D/3E errors) |
confirmed |
| Mouse wire: 4800 8O1, RS-232, 7-pin DIN | confirmed |
Mouse self-test command T → 4-byte report (3D/3E, ≥0x20 fatal) |
confirmed |
| Separate ports (DUART2-A kbd, DUART2-B mouse); no daisy chain | confirmed |
| Exact LK401 firmware protocol (LK400 Firmware Requirements) | unknown — document not public |
0xE1+10-byte level-0 anomaly |
unknown — not explained by any source here |
Inhibit-transmission opcode (89 vs B9) |
unknown — sources disagree |
| 4P4C keyboard pin order | probable — verify at cable |