Files
vt1200/reference/keyboard-mouse/PROTOCOL.md
T

18 KiB
Raw Blame History

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) and I - 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.txt lines ~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.md says the firmware writes 0xE1 to DUART2-A and expects a 10-byte reply. 0xE1 is 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, or 0xE1 is 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 in vt100net-lk201-keyboard.html; emulated identically by lk201emu (resetkb() sends 1,0,0,0) and expected by linux-lkkbd.c. [confirmed]
  • On a stuck key the reply becomes 01 00 3D <keycode> and the terminal re-issues FD. [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.c treats ≤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, send T; then S; then R (or D). [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", in src/mame/dec/lk201.h / src/mame/dec/lk201.cpp. It is a device_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 the FD self-test reply) comes from that ROM, not from C. It wires as m_lk201->tx_handler().../m_lk201->rx_w() (see src/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; no vsxxx*). We would need a small HLE model, but §4 gives the complete protocol, so this is low-risk.
  • Caveat / gap: MAME's lk201 wants the 6805 LK201 ROM 23-001s9-00.bin, which is not in the bitsavers zip we have (that is the 8051 23-004M2). Running MAME's device therefore needs that ROM sourced first; otherwise implement a HLE keyboard that answers FD with 01 00 00 00 (and optionally honours AB, 13/11, mode-set BA ACKs). 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