mirror of
https://github.com/alfishe/amiga-bootcamp.git
synced 2026-06-12 16:16:28 +00:00
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
179 lines
5.8 KiB
Markdown
179 lines
5.8 KiB
Markdown
[← 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 (0–127)
|
||
|
||
```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
|