Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

The IBM PC/XT Keyboard Interface

The XT keyboard interface, as it will be referred to from now on, is one of the most frequently misunderstood systems on the IBM PC, confusing both emulator authors and retro-programmers alike. It is easy to write a program that uses the keyboard in a way that works fine on an AT (or in DosBox), but fails on a more accurate XT emulator or real XT system. This is due to some peculiarities of the XT interface, which will be explained here.

The Host Keyboard Interface

The low-level, host-facing interface to the keyboard is implemented via the 8255 PPI. The keyboard is controlled via two bits on Port B, 61h, and the scancodes themselves are read out of Port A, 60h. These particular ports became somewhat standard, and so are often implemented on systems which do not even have an 8255 at all.

PPI Port B Keyboard Control BitsKeyboard interface control signals on PPI Port B.PPI Port B Keyboard Control BitsKeyboard interface control signals on PPI Port B.61h76543210PB7PB6Other functions
BitsNameDescription
0:5Other functionsOther functions - see PPI section
6PB60: Pull keyboard clock line LOW
1: Allow keyboard to drive clock
7PB70: Normal operation
1: Clear KSR + Clear IRQ1
[5150 only: Present SW1 settings to port A]

The Hardware Keyboard Interface

PB6 is typically used to reset the keyboard. It is wired up to a driver that will connect the keyboard clock line to ground. The control pin of the driver is active-low, which is why setting PB6 to 0 will perform this function, and setting PB6 to 1 allows the keyboard to operate normally.

Here is a simplified schematic:

kbd_clock_schematic_01

See the Model F section for more specific details, but if the keyboard clock line is held low for 20ms the keyboard will perform a reset/self-test. The BIOS sometimes does this, but applications usually do not.

The keyboard interface is a typical two-wire serial connection with a clock and a data line. Both of these are pulled high, with either the PC or the keyboard able to drive the lines low. The PC drives the lines low with dedicated drivers; the keyboard takes advantage of the open-collector outputs of its 8048 microcontroller.

This scheme allows simple hardware flow control - when the PC has the clock or data line pulled low, the keyboard cannot send data. The keyboard’s microcontroller can detect when the PC has either line held low, and knows to wait as the PC must either be busy, or requesting a reset. Keys pressed while the data line is held low by the PC will be stored in the keyboard’s internal FIFO until they can be sent. If this FIFO is full, then any additional keystrokes will be lost.

Each scancode is sent as a series of 9 bits. A rising edge of the keyboard clock line triggers the PC to sample the data line, shifting the resulting bit into a 74LS322 shift register, U24. The first bit, called a start bit, is always 1. This is used to good effect - when the Qh output of U24 goes high, this triggers various circuitry that clamps down on the keyboard data line, pulling it low after an additional clock. At this point, the shift register contains the entire 8-bit scancode, which can then be read out of PPI Port A.

Bits are sent over the wire from least-significant (bit 0 of scancode) to most-significant. Here is a logic analyzer capture of the ‘G’ key being pressed (scancode 0x22):

Logic analyzer trace of the G key scancode 0x22

Keyboard scancode 0x22 timing trace (Click to zoom)

Here is a simplified schematic:

kbd_clock_schematic_02

Note that a complete scancode being received directly triggers IRQ1, and only writing 1 to PB7 will lower IRQ1 again.

Setting PB7 to 1 does several things:

  • It clears the contents of the keyboard shift register U24, making its Qh output low for at least the next 8 clocks.
  • It disables the parallel outputs of the keyboard shift register U24, making it impossible to read a scancode.
  • It resets the flip-flop controlling IRQ1 and the keyboard data line. This forces IRQ1 low, and allows the keyboard to drive the data line.

Therefore, to read the keyboard, software must set PB7 to 1 and then reset it back to 0 after each scancode is read.