mirror of
https://git.k-space.ee/arti/vt1200.git
synced 2026-10-31 12:05:05 +02:00
Distils public docs into reference/keyboard-mouse/PROTOCOL.md for the level-1 Keyboard (27) / Mouse (26) device tests: - keyboard: 4800 8N1 RS-423, self-test via FD -> 01 00 00 00 (errors 3D/3E) - mouse: 4800 8O1 RS-232, self-test via 'T' -> 4-byte report (errors 3D/3E, >=0x20 fatal) - separate ports: DUART2 A=keyboard, B=mouse (NOT daisy-chained) MAME already has an LK201 device (src/mame/dec/lk201.cpp/.h) but no DEC mouse.
270 lines
17 KiB
Markdown
270 lines
17 KiB
Markdown
# 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.
|
||
|
||
---
|
||
|
||
## 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 |
|