amiga-bootcamp/10_devices/keyboard.md
Ilia Sharin da9e7d3b63 Phase 1: enrich 07_dos and 10_devices (highest FPGA priority)
07_dos:
- file_io.md: 108→240+ lines — buffered I/O (FRead/FWrite/SetVBuf),
  access mode comparison, FileHandle struct with offsets, standard
  handles, Printf %ld warning, FileInfoBlock, practical patterns
  (copy file, get size, load to RAM), error code table
- filesystem.md: 91→270+ lines — full disk geometry (ADF/HDF),
  all 8 DOS\x filesystem IDs, root block byte-level layout, file
  header layout with reverse-order pointer quirk, OFS vs FFS data
  blocks with efficiency numbers, bitmap blocks, extension blocks,
  checksum algorithm, Python ADF reader
- locks_examine.md: 113→270+ lines — lock semantics diagram, FileLock
  struct with handler discovery, ExAll bulk scan, practical patterns
  (atomic write, path resolution, volume info), 4 antipatterns
  (leaked locks, exclusive too long, unchecked IoErr, DupLock),
  pattern matching

10_devices:
- audio.md: 73→240+ lines — hardware architecture diagram, channel
  registers with offsets, period/frequency table, priority allocation,
  double-buffering, audio interrupts, AM/PM modulation, direct HW
- timer.md: 80→230+ lines — CIA timer hardware, all 5 units with
  decision flowchart, non-blocking delays, signal-based waiting,
  time arithmetic, ReadEClock, periodic game loop pattern, pitfalls
- trackdisk.md: 82→210+ lines — MFM encoding, track format, disk
  geometry, read/write/motor, change notification, track caching,
  direct hardware access, FPGA timing implications
- keyboard.md: 58→220+ lines — CIA-A serial handshake protocol with
  sequence diagram, bit rotation quirk, complete key code map,
  key matrix bitmap, reset sequence, FPGA notes
2026-04-23 20:23:50 -04:00

179 lines
5.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[← Home](../README.md) · [Devices](README.md)
# keyboard.device — Keyboard Hardware and Raw Key Codes
## Overview
`keyboard.device` provides access to the Amiga keyboard via the CIA-A serial port handshake protocol. The keyboard controller (a dedicated 6500/1 or 68HC05 microcontroller inside the keyboard) transmits **raw key codes** as serial data through CIA-A. Understanding this protocol is essential for FPGA core implementation.
---
## Hardware Protocol
```mermaid
sequenceDiagram
participant KB as Keyboard MCU
participant CIA as CIA-A (SP/CNT pins)
participant CPU as 68000 (interrupt)
KB->>CIA: Serial data (8 bits, MSB first)
Note over CIA: CIA-A SP register latches byte
CIA->>CPU: CIA-A ICR bit 3 (SP interrupt)
CPU->>CIA: Read $BFEC01 (SP data register)
CPU->>CIA: Pulse KDAT line low for ~85µs
Note over CIA: Handshake acknowledges receipt
KB->>KB: Ready for next key
```
### CIA-A Registers Used
| Register | Address | Bit | Function |
|---|---|---|---|
| `CIASDR` | `$BFEC01` | 7:0 | Serial data register — receives raw key code |
| `CIACRA` | `$BFEE01` | 6 | SP direction: 0=input (keyboard), 1=output |
| `CIAICR` | `$BFED01` | 3 | SP interrupt flag — set when byte received |
### Raw Key Code Format
The keyboard sends an 8-bit value where:
- **Bit 7** = key state: 0 = **pressed**, 1 = **released**
- **Bits 6:0** = key code (0127)
```c
/* Decode a raw key event: */
UBYTE raw = ~(cia->ciaSDR); /* invert (active low) */
raw = (raw >> 1) | (raw << 7); /* rotate right 1 bit */
UBYTE keycode = raw & 0x7F;
BOOL keyup = raw & 0x80;
```
> **Bit rotation**: The keyboard transmits bits in a rotated format. The software must rotate the received byte right by 1 bit to get the actual key code. This is a hardware design quirk.
### Handshake Timing
After reading the key code, the CPU must acknowledge by pulsing the KDAT line:
```asm
; Acknowledge key reception:
OR.B #$40, $BFEE01 ; CIACRA — set SP to output
; Wait at least 85 µs
MOVE.B #0, $BFEC01 ; drive KDAT low
; (timer or loop delay ~85 µs)
AND.B #~$40, $BFEE01 ; CIACRA — set SP back to input
; Keyboard is now ready to send next key
```
> **FPGA note**: If the handshake acknowledgement is too fast (<75µs) or too slow (>200ms), the keyboard MCU will resend the key code or initiate a reset sequence.
---
## Raw Key Code Map
### Main Keys
| Code | Key | Code | Key | Code | Key |
|---|---|---|---|---|---|
| $00 | `` ` `` (backtick) | $01 | `1` | $02 | `2` |
| $03 | `3` | $04 | `4` | $05 | `5` |
| $06 | `6` | $07 | `7` | $08 | `8` |
| $09 | `9` | $0A | `0` | $0B | `-` |
| $0C | `=` | $0D | `\` | $10 | `Q` |
| $11 | `W` | $12 | `E` | $13 | `R` |
| $14 | `T` | $15 | `Y` | $16 | `U` |
| $17 | `I` | $18 | `O` | $19 | `P` |
| $1A | `[` | $1B | `]` | $20 | `A` |
| $21 | `S` | $22 | `D` | $23 | `F` |
| $24 | `G` | $25 | `H` | $26 | `J` |
| $27 | `K` | $28 | `L` | $29 | `;` |
| $2A | `'` | $31 | `Z` | $32 | `X` |
| $33 | `C` | $34 | `V` | $35 | `B` |
| $36 | `N` | $37 | `M` | $38 | `,` |
| $39 | `.` | $3A | `/` | $40 | `Space` |
| $41 | `Backspace` | $42 | `Tab` | $43 | `Numpad Enter` |
| $44 | `Return` | $45 | `Escape` | $46 | `Delete` |
### Modifier and Special Keys
| Code | Key | Code | Key |
|---|---|---|---|
| $60 | `Left Shift` | $61 | `Right Shift` |
| $62 | `Caps Lock` | $63 | `Ctrl` |
| $64 | `Left Alt` | $65 | `Right Alt` |
| $66 | `Left Amiga` | $67 | `Right Amiga` |
### Cursor and Function Keys
| Code | Key | Code | Key |
|---|---|---|---|
| $4C | `Cursor Up` | $4D | `Cursor Down` |
| $4E | `Cursor Right` | $4F | `Cursor Left` |
| $50$59 | `F1``F10` | $5F | `Help` |
### Special Codes
| Code | Meaning |
|---|---|
| $78 | **Reset warning** — Ctrl+Amiga+Amiga pressed (keyboard sends this before resetting) |
| $F9 | Last key code was bad (parity error) — resend |
| $FA | Keyboard buffer overflow |
| $FC | Keyboard self-test failed |
| $FD | Initiate power-up key stream |
| $FE | Terminate power-up key stream |
---
## Using keyboard.device (OS Level)
Most applications receive key events through Intuition IDCMP (see [idcmp.md](../09_intuition/idcmp.md)). Direct keyboard.device use is for system-level software:
```c
struct MsgPort *kbPort = CreateMsgPort();
struct IOStdReq *kbReq = (struct IOStdReq *)
CreateIORequest(kbPort, sizeof(struct IOStdReq));
OpenDevice("keyboard.device", 0, (struct IORequest *)kbReq, 0);
/* Read raw key events: */
struct InputEvent ie;
kbReq->io_Command = KBD_READMATRIX;
kbReq->io_Data = &keyMatrix; /* 16-byte key matrix bitmap */
kbReq->io_Length = 16;
DoIO((struct IORequest *)kbReq);
/* keyMatrix bit N = 1 if key code N is currently held down */
/* Reset keyboard (force self-test): */
kbReq->io_Command = KBD_RESETHANDLER;
DoIO((struct IORequest *)kbReq);
```
### Key Matrix
The `KBD_READMATRIX` command returns a 16-byte (128-bit) bitmap where each bit corresponds to a raw key code:
```c
UBYTE keyMatrix[16];
/* Bit test: is key $45 (Escape) pressed? */
BOOL escPressed = keyMatrix[0x45 / 8] & (1 << (0x45 % 8));
```
---
## Keyboard Reset Sequence
The Ctrl+Amiga+Amiga three-key combination triggers a hardware reset:
1. User presses Ctrl+Left Amiga+Right Amiga
2. Keyboard MCU detects the combo
3. Sends raw code `$78` (reset warning) — gives software ~10 seconds to clean up
4. Pulls KBRST line low → triggers 68000 reset via RESET pin
> **FPGA**: The core must implement this reset path. The `$78` warning code allows software (e.g., debuggers) to save state before reset.
---
## References
- NDK39: `devices/keyboard.h`, `devices/inputevent.h`
- HRM: *Amiga Hardware Reference Manual* — Keyboard chapter
- See also: [input.md](input.md) — input.device handler chain
- See also: [idcmp.md](../09_intuition/idcmp.md) — high-level key events via Intuition