home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Unsorted BBS Collection
/
thegreatunsorted.tar
/
thegreatunsorted
/
programming
/
misc_programming
/
keyboard
< prev
next >
Wrap
Text File
|
1993-01-16
|
39KB
|
758 lines
The Keyboard Interface Tutorial
By: Inbar Raz
Preface:
The Keyboard on the IBM PC and compatible is connected to the PPI -
Programmable Peripheral Interface, which generally takes care of Keyboard
functions, equipment information and timer functions. The PPI is addressable
via port reads and writes, to addresses 060h thru 063h.
There are several type of keyboards available. The main difference between the
various types is the key count. Existing sizez are:
83 Key (Original PC)
84 Key (XT and clones)
101 Key (Usually on AT's and up, called Enhanced Keyboard)
In addition to those standard types, there are numerous non-standard types,
which varry from manufacturer to manufacturer. There are 102 Key keyboards,
keyboards with two F-Key sets (upper and left), keyboards with weird
hardly-used keys like 'Macro' and 'Turbo' (which DO have a scan code, though)
etcetera.
The IBM AT and up provides a better way of negotiating the keyboard, by
allowing the user to directly access and command the keyboard, as it will be
demonstrated later.
Using assembly language, there are two major ways to handle the keyboard and
keystrokes:
1. Using DOS functions:
DOS provides a useful set of functions to use in context with the keyboard.
This includes one-key-input and string input.
2. Using BIOS interrupts:
The IBM PC BIOS (Basic Input Output System) provides an interrupt to handle
the keyboard - Interrupt 016h (022d). These functions, titles KEYBOARD I/O,
are an efficient medium level way of using the keyboard
In addition to the Interrupt 016h interface, there is the Keyboard
Interrupt, Interrupt 009h. As opposed to the other interrupt, Interrupt
009h is an IRQ - Interrupt Request, which means that it is never called by
software. Only hardware, when certain conditions are met, calls IRQ
interrupts. Naturally, the user is able to invoke them himself, but that is
not commonly done.
3. Direct port access:
It is possible to access the keyboard using direct port reads and writes.
As mentioned before, this is usually done by addressing the PPI. On AT's
and up, however, it is possible to directly access the keyboard itself.
The BIOS also supplies a certain amount of information about the keyboard
within it's BDA - BIOS Data Area, aka BDS - BIOS Data Segment - which is the
segment that lies at paragraph 040h (0040h:XXXXh or 0000h:04XXh):
Address Size Contents
▀▀▀▀▀▀▀ ▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
0:0412 1 Errors in PCjr InfraRed keyboard link
0:0417 2 Keyboard status bits. See Keyboard Flags
0:0419 1 Current (accumulating) value of Alt+numpad pseudo-key input.
Normally 0. When [Alt] is released, value is stored in kbd buf.
0:041A 2 Address of keyboard buffer head (keystroke at that addr is next)
0:041C 2 Address of keyboard buffer tail
0:041E 32 Keyboard buffer. BIOS stores keystrokes here (head and tail
point to addresses from 041Eh to 043Dh inclusive).
0:0480 2 ▌AT▐ ≡PS/2≡ Keyboard buffer offset start address (usually 01Eh)
0:0482 2 end address (usually 03Eh)
0:0496 1 ▌AT▐ Keyboard flag bit 4=1 (10h) if 101-key keyboard is attached
0:0497 1 ▌AT▐ Keyboard flag for LED 'key lock' display
bits 0-2 are ScrollLock, NumLock, CapsLock respectively
******************************************************************************
******************************************************************************
******************************************************************************
Using DOS functions:
--------------------
DOS provides a set of 7 functions to handle the keyboard:
01h Keyboard Input
06h Console I/O
07h No Echo Unfiltered Input
08h No Echo Filtered Input
0Ah Buffered Input
0Bh Input Status
0Ch Clear Keyboard Buffer & Input
DOS Fn 01h: Keyboard Input
══════════════════════════════════════════════════════════════════════════════
┌─────────╥───────╥───────────────────────────────────────────────────────────
│ Expects ║ AH ║ 01h
├─────────╫───────╫───────────────────────────────────────────────────────────
│ Returns ║ AL ║ Character fetched from the Standard Input
└─────────╨───────╨───────────────────────────────────────────────────────────
Description: Reads (waits for) a character from the Standard Input Device.
Echoes that character to the Standard Output Device.
If Ctrl-Break is detected, INT 23h is executed.
Notes: Extended ASCII keystrokes (ie, F1-F12, PgUp, cursor, etc) will
require two calls to this function. The first call will return
AL=0. The second will return AL with the extended ASCII code.
DOS Fn 02h: Display Output
══════════════════════════════════════════════════════════════════════════════
┌─────────╥───────╥───────────────────────────────────────────────────────────
│ Expects ║ AH ║ 02h
└─────────╢ DL ║ Character to send to the Standard Output
┌─────────╫───────╫───────────────────────────────────────────────────────────
│ Returns ║ none ║
└─────────╨───────╨───────────────────────────────────────────────────────────
Description: Sends the character in DL to the Standard Output.
Handles backspace (ASCII 8) by moving the cursor left and leaving
the cursor there.
If Ctrl-Break is detected, INT 23h is executed.
DOS Fn 06h: Console I/O
══════════════════════════════════════════════════════════════════════════════
┌─────────╥───────╥───────────────────────────────────────────────────────────
│ Expects ║ AH ║ 06h
└─────────╢ DL ║ 0 to 0FEh Character to send to the Standard Output
║ ║ 0FFh Request for input from the Standard Input
┌─────────╫───────╫───────────────────────────────────────────────────────────
│ Returns ║ ZF ║ Clear (NZ) if character is ready ══╦═ on input requests
└─────────╢ AL ║ Character read, if ZF is clear ════╝ (when DL=0FFh)
╙───────╨───────────────────────────────────────────────────────────
Description: If DL is 0FFh, this performs a "no wait" console input, returning
the Zero Flag (ZF) set (ZR) if there is no character ready.
If a character is ready, returns ZF cleared (NZ) with the
character that was read in AL.
If DL is anything but 0FFh, DL is sent to the Standard Output.
Notes: Does not check for Ctrl-Break. Call twice for Extended ASCII.
DOS Fn 07h: No Echo Unfiltered Console Input
══════════════════════════════════════════════════════════════════════════════
┌─────────╥───────╥───────────────────────────────────────────────────────────
│ Expects ║ AH ║ 07h
├─────────╫───────╫───────────────────────────────────────────────────────────
│ Returns ║ AL ║ Character fetched from the Standard Input
└─────────╨───────╨───────────────────────────────────────────────────────────
Description: Reads (waits for) a character from the Standard Input Device,
returning that character in AL.
Unfiltered: Does not detect Ctrl-Break, backspace, etc.
Notes: Call twice for Extended ASCII character input.
Use Fn 0Bh to check status (if you don't want to wait for a key).
DOS Fn 08h: No Echo Console Input
══════════════════════════════════════════════════════════════════════════════
┌─────────╥───────╥───────────────────────────────────────────────────────────
│ Expects ║ AH ║ 08h
├─────────╫───────╫───────────────────────────────────────────────────────────
│ Returns ║ AL ║ Character fetched from the Standard Input
└─────────╨───────╨───────────────────────────────────────────────────────────
Description: Reads (waits for) a character from the Standard Input Device,
returning that character in AL.
If Ctrl-Break is detected, INT 23h is executed.
Notes: Call twice for Extended ASCII character input.
DOS Fn 0Ah: Buffered String Input
══════════════════════════════════════════════════════════════════════════════
┌─────────╥───────╥───────────────────────────────────────────────────────────
│ Expects ║ AH ║ 0Ah
└─────────╢ DS:DX ║ Address of an input buffer (see below)
┌─────────╫───────╫───────────────────────────────────────────────────────────
│ Returns ║ none ║ Buffer contains input terminated with CR (ASCII 13h)
└─────────╨───────╨───────────────────────────────────────────────────────────
Description: On entry, the buffer at DS:DX must be set up as:
┌───┬───┬───┬───┬───┬───┬─ ─ ─
│max│ ? │ ? ? ? ? ? max is maximum acceptable input
└───┴───┴───┴───┴───┴───┴ ─ ─ (range: 1 to 254)
On exit, the buffer is filled:
┌───┬───┬───┬───┬───┬───┬─ ─ ─
│max│len│ T E X T 0Dh len is actual length of input,
└───┴───┴───┴───┴───┴───┴ ─ ─ less the terminating CR (eg, 4).
Characters are read from the Standard Input up to a CR (ASCII 13)
or up to the value of max-1. If max-1 is reached, the console
bell rings (beeps) for each character until Enter (CR) is read.
The second byte of the buffer is filled with the actual length of
the input, less the terminating CR. The final character in the
buffer is always CR (which is not counted in the length byte).
The characters in the buffer (including the len) before the call
are used as a "template" and the DOS editing keys are in effect:
[Esc] displays "\" and restarts the edit, [F3] displays to the
end of the template, [F5] displays "@" and stores the current
line as the template, etc. Most Extended ASCII keystrokes are
ignored.
If Ctrl-Break is detected, INT 23h is executed and the buffer is
left unchanged.
DOS Fn 0Bh: Check Input Status
══════════════════════════════════════════════════════════════════════════════
┌─────────╥───────╥───────────────────────────────────────────────────────────
│ Expects ║ AH ║ 0Bh
├─────────╫───────╫───────────────────────────────────────────────────────────
│ Returns ║ AL ║ 0FFh if a character is available from the Standard Input
└─────────╢ ║ 0 if no character is available
╙───────╨───────────────────────────────────────────────────────────
Description: Checks the status of the Standard Input.
If Ctrl-Break is detected, INT 23h is executed.
Notes: Use before Fns 01h, 07h and 08h to avoid having DOS wait for a
key.
This is a simple, non-destructive way to check for Ctrl-Break
during long calculations or other processing that does not
normally look for input. It lets the user abort from such a
sequence.
DOS Fn 0Ch: Clear & Input
══════════════════════════════════════════════════════════════════════════════
┌─────────╥───────╥───────────────────────────────────────────────────────────
│ Expects ║ AH ║ 0Ch
└─────────╢ AL ║ DOS input function number (01h, 06h, 07h, 08h, or 0Ah)
┌─────────╫───────╫───────────────────────────────────────────────────────────
│ Returns ║ none ║
└─────────╨───────╨───────────────────────────────────────────────────────────
Description: Clears the Standard Input type-ahead buffer then invokes the DOS
input function specified by AL. This forces the system to wait
for a character to be typed.
These values are allowed for AL: 01h Keyboard Input
06h Console I/O
07h No Echo Unfiltered Input
08h No Echo Filtered Input
0Ah Buffered Input
──────────────────────────────────────────────────────────────────────────────
In addition to these functions, it is also possible to read a selected amount
of characters from the keyboard, using DOS's File Handle functions, as the
Keyboard, aka Standard Input, has a pre-set handle of 0000h:
DOS Fn 3Fh: Read from keyboard via Handle
══════════════════════════════════════════════════════════════════════════════
┌─────────╥───────╥───────────────────────────────────────────────────────────
│ Expects ║ AH ║ 3Fh
└─────────╢ BX ║ 0000h - Handle for Standard Input (Keyboard)
║ DS:DX ║ Address of buffer to receive data
║ CX ║ Number of bytes to read
┌─────────╫───────╫───────────────────────────────────────────────────────────
│ Returns ║ AX ║ Error code if CF is set to CY
└─────────╢ AX ║ Number of bytes actually read
╙───────╨───────────────────────────────────────────────────────────
Description: CX bytes of data are read from the keyboard. The data is placed
into the caller's buffer pointed to by DS:DX.
Notes: It is handy to use this function for reading default handles
such as the Standard I/O handles, instead of the buffered input
or character-by-character input functions.
When you read from a device, AX returns the length of the line
up to and including the termination CR (ASCII 13h).
******************************************************************************
******************************************************************************
******************************************************************************
Using BIOS Interrupts:
----------------------
As mentioned before, there are two ways to use interrupts to access the
keyboard.
The first is Interrupt 016h - Keyboard I/O.
INT 16h: Keyboard Services
══════════════════════════════════════════════════════════════════════════════
This is the application-level interface to the keyboard. Keystrokes are
actually processed asynchronously in the background. As each keystroke is
received from the keyboard, it is processed by INT 09h and placed into a
circular queue.
See AT Keyboard for ways to speed up the keyboard and other hardware info.
AH Service
▀▀▀ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
00h Read (wait for) next keystroke
Output: AL = ASCII character (if AL=0, AH is an Extended ASCII keystroke)
AH = Scan Code or Extended ASCII keystroke
01h Check if a keystroke is ready (and preview it if so)
Output: ZF = ZR = 1 if no key is ready
ZF = NZ = 0 if a key is ready.
AX is set as for SubFn 00h (but the keystroke has not
been removed from the queue).
02h Read the shift-key status. Determine which shift keys are currently being
pressed and whether the keyboard is in NumLock state, etc.
Output: AL = shift key and 'lock' status as in Keyboard Flags
03h Set keyboard typeamatic rate and delay. (11/15/85 BIOS)
Input: AL = 05h (eg, AX = 0305h)
BL = Typeamatic rate 0=30 rpts/sec, 1=26...1Fh=2. See AT Keyboard
BH = Delay (0=250ms, 1=500ms, 2=750ms, 3=1 second)
Output: (none)
04h (reserved)
05h Place a keystroke into the keyboard buffer. (11/15/85 BIOS)
Input: CL = ASCII character.
CH = Scan Code byte (or 0 if you don't care).
Output: AL = Status: 0=success; 1=buffer full
06h-0Fh (reserved)
10h Read (wait for) a keystroke; specific for 101-key 'board (11/15/85 BIOS)
Output: AL = ASCII character (if AL=0, AH is an Extended ASCII keystroke)
AH = Scan Code or translated Extended ASCII keystroke
11h Preview keystroke; same as 01, but for 101-key 'board (11/15/85 BIOS)
Output: ZF = ZR = 1 if no key is ready
ZF = NZ = 0 if a key is ready.
AX is set as for SubFn 10f but keystroke is still in the buffer.
12h Read shift-key status; same as 02, but for 101-key 'board (11/15/85 BIOS)
Output: AL = shift key and 'lock' status. See 101-key Keyboard Flags
──────────────────────────────────────────────────────────────────────────────
The second is Interrupt 009h - Keyboard Interrupt, IRQ 1
INT 09h: Keyboard Interrupt
══════════════════════════════════════════════════════════════════════════════
This hardware-generated interrupt (IRQ 1) is executed upon each press and
release of a key. The ROM-BIOS code interprets the keystroke, storing values
into the keyboard buffer at 0:041Eh. It also handles the special cases of the
PrtSc and SysReq keys, and tracks the status of the shift and case-lock keys.
See: INT 16h .......... BIOS service to access the keys stored in the buffer
and obtain status of the certain shift keys.
Scan Codes ....... a list of the values of each possible keystroke as
it is received by INT 09h.
Extended ASCII ... for a summary of the values that BIOS stores into the
the keyboard buffer after it translates a scan code.
Keyboard Flags ... for a summary of how to obtain, test for, and modify
the bit-settings of shift and case-lock flags.
TSRs (RAM-resident programs) that have a hot-key to trigger a popup usually
intercept INT 09h and test for a certain key with a sequence such as this:
push ax
in al,60h ; Read the key
cmp al,POP_KEY ; Is this the hot key?
je do_pop ; Yes, trigger the popup
; No, drop through to original driver
pop ax
jmp cs:[int9_vect] ; Just hop out to original int handler
do_pop: ;------ the following housekeeping is needed to satisfy the hdwr int
in al,61h ; Get value of keyboard control lines
mov ah,al ; Save it
or al,80h ; Set the "enable kbd" bit
out 61h,al ; And write it out the control port
xchg ah,al ; Fetch the original control port value
out 61h,al ; And write it back
mov al,20h ; Send End-Of-Interrupt signal
out 20h,al ; to the 8259 Interrupt Controller
;------ other code handles other tests and finally the popup code
******************************************************************************
******************************************************************************
******************************************************************************
Direct port access:
-------------------
The keyboard is addressable in two manners.
The first, available on all IBM PCs of all types, is by addressing the PPI -
Programmable Peripheral Interface.
Port Description
▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
060h ■PC/XT■ PPI port A. Read keyboard scan code:
IN al,60h ; Fetche most recent scan code. See INT 09h and Scan Code
▌AT▐ keyboard data register. See AT Keyboard
061h ■PC/XT■ PPI (Programmable Peripheral Interface) port B.
╓7┬6┬5┬4┬3┬2┬1┬0╖
║ │ │ │ │ │0│ │ ║
╙╥┴╥┴╥┴╥┴╥┴─┴╥┴╥╜ bit
║ ║ ║ ║ ║ ║ ╚═ 0: Timer 2 gate (speaker) ═╦═ OR 03h=speaker ON
║ ║ ║ ║ ║ ╚═══ 1: Timer 2 data ═══════════╝ AND 0FCh=speaker OFF
║ ║ ║ ║ ╚═══════ 3: 1=Read high switches; 0=read low switches(see 62h)
║ ║ ║ ╚═════════ 4: 0=Enable RAM parity checking; 1=disable
║ ║ ╚═══════════ 5: 0=Enable I/O channel check
║ ╚═════════════ 6: 0=Hold keyboard clock low
╚═══════════════ 7: 0=Enable keyboard; 1=disable keyboard
──────────────────────────────────────────────────────────────────────────────
The second, available only on IBM PC/ATs and up, is by directly commanding the
keyboard itself. -= This is for the AT keyboard only. =-
Port Description
▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
064h ▌AT▐ keyboard command register. This port communicates with the 8042
which runs an on-chip control program for the keyboard. It accepts
command codes and data bytes.
The keyboard of the ▌AT▐ (and its Intel 8042 microcomputer interface) is
programmable and a lot more interesting than the old-style PC keyboards.
Using the information below, you can set the key repeat speed and play
games with the "lock" key LED display.
Note: This is not a comprehensive coverage of the details of keyboard and
8042 operation, but it should provide some food for thought.
Port 60h is for writing data and is maintained for compatibility with
earlier models. If the examples using port 64h don't work, try using 60h.
Port 64h is for writing commands and data and for reading keyboard status.
Before sending a command to the keyboard, the BIOS tests its status
(IN al,64h) and makes sure a key isn't being pressed or the internal buffer
isn't full, etc. There's a small risk if you just go ahead and send the
command:
mov al,cmd_code
out 64h,al
For a two-part command such as setting the typeamatic rate, it's wise to
delay a little while between OUTs:
mov al,cmd_code
out 64h,al
mov cx,2000h ;arbitrary ≈ 10ms+
delay: loop delay
mov al,data_value
out 64h,al
Cmd Description
▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
0FFh Reset the keyboard and start internal diagnostics
0FEh Resend the last transmission
0FDh-0F7h (NOP)
0F6h Set keyboard to defaults and continue scanning
0F5h Set keyboard to defaults and disable keyboard scanning
0F4h Enable the keyboard. Kybd sends 'ACK', clears buffer, and starts scanning
0F3h Set typeamatic rate and delay. First send 0F3h, then send data byte:
╓7┬6┬5┬4┬3┬2┬1┬0╖
║0│dly│rept rate║
╙╥┴─┴─┴─┴─┴─┴─┴─╜
║ ╚╦╝ ╚═══════╩═ bits 0-4 set the repeat rate (see below)
║ ╚════════════ bits 5-6 set initial delay before first repeat:
║ 00=250ms; 01=500ms; 10=750ms; 11=1000ms
╚═══════════════ bit 7 is always 0
Value Rate Value Rate
This chart is a partial guide for the repeat 0 = 30.0 0Ah = 10.0
rate (bits 0-4). You can interpolate for 1 = 26.7 0Dh = 9.2
values not shown, but let's face it, you're 2 = 24.0 10h = 7.5
only interested in the fastest rates. 4 = 20.0 14h = 5.0
8 = 15.0 1Fh = 2.0
The keyboard is initially set to begin repeating after 1/2-second and
repeat at a rate of 10 repeats per second. This is much too slow. A
data byte of 01h sets the delay to 1/4-second with 26 repeats per second.
0F2h-0EFh (NOP)
0EEh Echo. Diagnostics aid. Simply sends 0EEh right back.
0EDh Turn LED 'lock key' lights on or off. First send 0EDh, then send byte:
╓7┬6┬5┬4┬3┬2┬1┬0╖
║ not used│c│n│s║
╙─┴─┴─┴─┴─┴╥┴╥┴╥╜
║ ║ ╚═ ScrollLock light 01h=turn on
║ ╚═══ NumLock light 02h=turn on
╚═════ CapsLock light 04h=turn on
The bit positions 0-3 correspond to bits 4-6 of the keyboard flags
variable in the BIOS Data area. You should make an effort to keep the
flags in sync with the lights. For instance, if you do a big favor for
the user and set his ten-key pad into NumLock mode (by setting bit 5 of
0:0417h) then be sure to turn on the corresponding LED (eg, bit 1).
******************************************************************************
******************************************************************************
******************************************************************************
Additional Information
----------------------
Keyboard Shift Status Flags
══════════════════════════════════════════════════════════════════════════════
Two bytes at address 0:0417h and 0:0418h identify the status of the keyboard
shift keys and keyboard toggles. INT 16h returns the first byte in AL.
╓─7┬─6┬─5┬─4┬─3┬─2┬─1┬─0╖ Perform INT 16h Fn 02h
║I │C │N │S │a │c │sL│sR║ or fetch AL=byte at 0:0417h
╙─╥┴─╥┴─╥┴─╥┴─╥┴─╥┴─╥┴─╥╜ bit
║ ║ ║ ║ ║ ║ ║ ╚═ 0: Alpha-shift (right side) DOWN (AL & 01h)
║ ║ ║ ║ ║ ║ ╚════ 1: Alpha-shift (left side) DOWN (AL & 02h)
║ ║ ║ ║ ║ ╚═══════ 2: Ctrl-shift (either side) DOWN (AL & 04h)
║ ║ ║ ║ ╚══════════ 3: Alt-shift (either side) DOWN (AL & 08h)
║ ║ ║ ╚═════════════ 4: ScrollLock state (AL & 10h)
║ ║ ╚════════════════ 5: NumLock state (AL & 20h)
║ ╚═══════════════════ 6: CapsLock state (AL & 40h)
╚══════════════════════ 7: Insert state (AL & 80h)
╓─7┬─6┬─5┬─4┬─3┬─2┬─1┬─0╖
║i │c │n │s │ │sy│aL│cL║ fetch AL=byte at 0:0418h
╙─╥┴─╥┴─╥┴─╥┴─╥┴─╥┴─╥┴─╥╜ bit
║ ║ ║ ║ ║ ║ ║ ╚═ 0: Ctrl-shift (left side) DOWN (AL & 01h)
║ ║ ║ ║ ║ ║ ╚════ 1: Alt-shift (left side) DOWN (AL & 02h)
║ ║ ║ ║ ║ ╚═══════ 2: SysReq DOWN (AL & 04h)
║ ║ ║ ║ ╚══════════ 3: hold/pause state (AL & 08h)
║ ║ ║ ╚═════════════ 4: ScrollLock DOWN (AL & 10h)
║ ║ ╚════════════════ 5: NumLock DOWN (AL & 20h)
║ ╚═══════════════════ 6: CapsLock DOWN (AL & 40h)
╚══════════════════════ 7: Insert DOWN (AL & 80h)
Notes: Bits 0-2 of 0:0418h are defined only for the 101-key enhanced keyboard.
The 101-key BIOS INT 16h Fn 12h returns AL as with Fn 02, but AH is
returned with the following bit-flag layout:
╓─7┬─6┬─5┬─4┬─3┬─2┬─1┬─0╖
║sy│c │n │s │aR│cR│aL│cL║ Perform INT 16h Fn 12h (101-key BIOS only)
╙─╥┴─╥┴─╥┴─╥┴─╥┴─╥┴─╥┴─╥╜ bit
║ ║ ║ ║ ║ ║ ║ ╚═ 0: Ctrl-shift (left side) DOWN (AH & 01h)
║ ║ ║ ║ ║ ║ ╚════ 1: Alt-shift (left side) DOWN (AH & 02h)
║ ║ ║ ║ ║ ╚═══════ 2: Ctrl-shift (right side) DOWN (AH & 04h)
║ ║ ║ ║ ╚══════════ 3: Alt-shift (right side) DOWN (AH & 08h)
║ ║ ║ ╚═════════════ 4: ScrollLock DOWN (AH & 10h)
║ ║ ╚════════════════ 5: NumLock DOWN (AH & 20h)
║ ╚═══════════════════ 6: CapsLock DOWN (AH & 40h)
╚══════════════════════ 7: SysReq DOWN (AH & 80h)
Some older programs change the values of NumLock and CapsLock state
bits (at 0:0417h) to force a known status. This is unwise because
modern keyboards have indicator lights which will get out of sync with
the status. See AT Keyboard for more information on the lock-key LEDs.
PCjr status bytes at 0:0488 are omitted for lack of interest.
Keyboard Scan Codes
══════════════════════════════════════════════════════════════════════════════
When the keyboard forces a hardware interrupt, it passes a Scan Code to the
interrupt handler. The handler converts this to an ASCII or Extended ASCII
value. For compatibility across the various keyboards, it is wise to avoid
using scan codes and stick to the BIOS translation of a keystroke.
┌─────────────────────────┐
│ Original PC/XT Keyboard │ When a key is released, the keyboard sends the
└─────────────────────────┘ same value, ORed with 80h (eg, [Ctrl] sends 1Dh
when pressed and 9Dh when released).
────────────╥─────────────╥───────────────╥────────────────╥──────────────────
Hex Dec Key ║Hex Dec Key ║Hex Dec Key ║Hex Dec Key ║Hex Dec Key
────────────╫─────────────╫───────────────╫────────────────╫──────────────────
01 1 Esc ║12 18 E ║23 35 H ║34 52 . > ║45 69 NumLock
02 2 1 ! ║13 19 R ║24 36 J ║35 53 / ? ║46 70 ScrollLock
03 3 2 @ ║14 20 T ║25 37 K ║36 54 Shft(Rt)║47 71 Home [7]
04 4 3 # ║15 21 Y ║26 38 L ║37 55 * PrtSc ║48 72 Up [8]
05 5 4 $ ║16 22 U ║27 39 ; : ║38 56 Alt ║49 73 PgUp [9]
06 6 5 % ║17 23 I ║28 40 " ' ║39 57 spacebar║4a 74 K -
07 7 6 ^ ║18 24 O ║29 41 ` ~ ║3a 58 CapsLock║4b 75 Left [4]
08 8 7 & ║19 25 P ║2a 42 Shft(L)║3b 59 F1 ║4c 76 Cntr [5]
09 9 8 * ║1a 26 [ { ║2b 43 \ | ║3c 60 F2 ║4d 77 Rght [6]
0a 10 9 ( ║1b 27 ] } ║2c 44 Z ║3d 61 F3 ║4e 78 K +
0b 11 0 ) ║1c 28 Enter║2d 45 X ║3e 62 F4 ║4f 79 End [1]
0c 12 - _ ║1d 29 Ctrl ║2e 46 C ║3f 63 F5 ║50 80 Down [2]
0d 13 + = ║1e 30 A ║2f 47 V ║40 64 F6 ║51 81 PgDn [3]
0e 14 bksp║1f 31 S ║30 48 B ║41 65 F7 ║52 82 Ins [0]
0f 15 Tab ║20 32 D ║31 49 N ║42 66 F8 ║53 83 Del [.]
10 16 Q ║21 33 F ║32 50 M ║43 67 F9 ║
11 17 W ║22 34 G ║33 51 , < ║44 68 F10 ║
────────────╨─────────────╨───────────────╨────────────────╨──────────────────
K indicates a key on the numeric keypad
┌────────────────────┐
│ 84-Key AT Keyboard │ The 84-key keyboard sends the same scan codes as the
└────────────────────┘ 83-key (original PC) keyboard with the addition that
[SysReq] sends scan code 54h (84 decimal).
However, the BIOS never lets an application program see this scan code.
Instead, it invokes INT 15h SubFn 85h on make or break of the SysReq key.
The 'break' (release of a key) is handled differently. Upon a break, the
keyboard sends a two-byte sequence: 0F0h, followed by the 'make' scan code.
See AT Keyboard Functions for information on programming this keyboard.
┌──────────────────┐
│ 101-Key Keyboard │ This keyboard has three separate mappings of the scan
└──────────────────┘ codes, selected by communication through port 64h. The
keyboard comes to life with scan code set 2 (which is wildly different from
the 84-key mapping. However, the scan codes are translated by the hardware
keyboard interface before they are made available to programs that read the
keyboard.
The result is that all of the scan codes identified in the above table are
valid when the 101-key 'board comes up naturally. The following table
lists the additional scan-codes that are sent by the 101-key 'board. Note
that all keys mentioned here refer to the keys that are unique to this
keyboard; eg, [Insert] is the dedicated insert key (not KeyPad Ins).
────────────────────────────────────────────╥───────────────────────────
Key Hex Sequence ║ Key Hex Sequence
────────────────────────────────────────────╫───────────────────────────
F11 ..................... 57 ║ Home ........ E0 47
F12 ..................... 58 ║ Shift-Home .. E0 AA E0 47
Right-Alt ............... E0 38 ║ End ......... E0 4f
Right-Ctrl .............. E0 1D ║ Shift-End ... E0 AA E0 4f
PrintScreen ............. E0 2A E0 37 ║ Up........... E0 48
Shft-PrintScreen (SysReq) E0 37 ║ Shift-Up .... E0 AA E0 48
Ctrl-PrintScreen (SysReq) E0 37 ║ Down ........ E0 50
Alt-PrintScreen ......... 54 ║ Shift-Down .. E0 AA E0 50
Pause ................... E1 1D 45 E1 9D C5 ║ PageUp ...... E0 49
Ctrl-Pause (Break) ...... E0 46 E0 C6 ║ Shft-PageUp . E0 AA E0 49
Insert .................. E0 53 ║ PageDown .... E0 51
Shift-Insert ............ E0 AA E0 52 ║ Shft-PageDown E0 AA E0 51
Delete .................. E0 53 ║ Right ....... E0 4D
Shift-Delete ............ E0 AA E0 53 ║ Shift-Right . E0 AA E0 4D
Left .................... E0 4B ║ K Enter ..... E0 1C
Shift-Left .............. E0 AA E0 4B ║ K / ......... E0 35
║ Shift-K / ... E0 AA E0 35
────────────────────────────────────────────╨───────────────────────────
K indicates a key on the numeric keypad
Note that in cases where a key is similar to another (pre-101) key, the
second scan code byte is the same as the original key. Thus, some programs
that work at the scan-code level can get away with simply ignoring the E0h
prefix.
Extended ASCII Keystrokes
══════════════════════════════════════════════════════════════════════════════
When INT 16h Fn 00h returns AL=0, then AH will contain an extended ASCII
keystroke as listed in these tables. When a DOS Character I/O function
returns a character of 00h, you should make a second call to obtain the
extended ASCII value.
╓─────────────╥───────────────────╥───────────────────╥──────────────────╖
║ Key Hex Dec ║ Key Hex Dec ║ Key Hex Dec ║ Key Hex Dec ║
╟─────────────╫───────────────────╫───────────────────╫──────────────────╢
║ F1 3B 59 ║ Shift-F1 54 84 ║ Ctrl-F1 5E 94 ║ Alt-F1 68 104 ║
║ F2 3C 60 ║ Shift-F2 55 85 ║ Ctrl-F2 5F 95 ║ Alt-F2 69 105 ║
║ F3 3D 61 ║ Shift-F3 56 86 ║ Ctrl-F3 60 96 ║ Alt-F3 6A 106 ║
║ F4 3E 62 ║ Shift-F4 57 87 ║ Ctrl-F4 61 97 ║ Alt-F4 6B 107 ║
║ F5 3F 63 ║ Shift-F5 58 88 ║ Ctrl-F5 62 98 ║ Alt-F5 6C 108 ║
║ F6 40 64 ║ Shift-F6 59 89 ║ Ctrl-F6 63 99 ║ Alt-F6 6D 109 ║
║ F7 41 65 ║ Shift-F7 5A 90 ║ Ctrl-F7 64 100 ║ Alt-F7 6E 110 ║
║ F8 42 66 ║ Shift-F8 5B 91 ║ Ctrl-F8 65 101 ║ Alt-F8 6F 111 ║
║ F9 43 67 ║ Shift-F9 5C 92 ║ Ctrl-F9 66 102 ║ Alt-F9 70 112 ║
║ F10 44 68 ║ Shift-F10 5D 93 ║ Ctrl-F10 67 103 ║ Alt-F10 71 113 ║
╙─────────────╨───────────────────╨───────────────────╨──────────────────╜
╓───────────────╥────────────────╥───────────────────╥───────────────────╖
║ Key Hex Dec║ Key Hex Dec ║ Key Hex Dec ║ Key Hex Dec ║
╟───────────────╫────────────────╫───────────────────╫───────────────────╢
║ Alt-A 1E 30 ║ Alt-P 19 25 ║ Alt-3 7A 122 ║ down 50 80 ║
║ Alt-B 30 48 ║ Alt-Q 10 16 ║ Alt-4 7B 123 ║ left 4B 75 ║
║ Alt-C 2E 46 ║ Alt-R 13 19 ║ Alt-5 7C 124 ║ right 4D 77 ║
║ Alt-D 20 32 ║ Alt-S 1F 31 ║ Alt-6 7D 125 ║ up 48 72 ║
║ Alt-E 12 18 ║ Alt-T 14 20 ║ Alt-7 7E 126 ║ End 4F 79 ║
║ Alt-F 21 33 ║ Alt-U 16 22 ║ Alt-8 7F 127 ║ Home 47 71 ║
║ Alt-G 22 34 ║ Alt-V 2F 47 ║ Alt-9 80 128 ║ PgDn 51 81 ║
║ Alt-H 23 35 ║ Alt-W 11 17 ║ Alt-- 82 130 ║ PgUp 49 73 ║
║ Alt-I 17 23 ║ Alt-X 2D 45 ║ Alt-= 83 131 ║ ║
║ Alt-J 24 36 ║ Alt-Y 15 21 ║ ║ ^left 73 115 ║
║ Alt-K 25 37 ║ Alt-Z 2C 44 ║ NUL 03 3 ║ ^right 74 116 ║
║ Alt-L 26 38 ║ ║ Shift-Tab 0F 15 ║ ^End 75 117 ║
║ Alt-M 32 50 ║ Alt-0 81 129 ║ Ins 52 82 ║ ^Home 77 119 ║
║ Alt-N 31 49 ║ Alt-1 78 120 ║ Del 53 83 ║ ^PgDn 76 118 ║
║ Alt-O 18 24 ║ Alt-2 79 121 ║ ^PrtSc 72 114 ║ ^PgUp 84 132 ║
╙───────────────╨────────────────╨───────────────────╨───────────────────╜
╔═══════════════════════════════════════════════╗
║ 101-key Keyboard Extensions Supported by BIOS ║
╓─────────╨─────────╥───────────────────────╥─────────────╨──────────╖
║ Key Hex Dec ║ Key Hex Dec ║ Key Hex Dec ║
╟───────────────────╫───────────────────────╫────────────────────────╢
║ F11 85 133 ║ Alt-Bksp 0E 14 ║ Alt- K / A4 164 ║
║ F12 86 134 ║ Alt-Enter 1C 28 ║ Alt- K * 37 55 ║
║ Shft-F11 87 135 ║ Alt-Esc 01 1 ║ Alt- K - 4A 74 ║
║ Shft-F12 88 136 ║ Alt-Tab A5 165 ║ Alt- K + 4E 78 ║
║ Ctrl-F11 89 137 ║ Ctrl-Tab 94 148 ║ Alt- K Enter A6 166 ║
║ Ctrl-F12 8A 138 ║ ║ ║
║ Alt-F11 8B 139 ║ Alt-up 98 152 ║ Ctrl- K / 95 149 ║
║ Alt-F12 8C 140 ║ Alt-down A0 160 ║ Ctrl- K * 96 150 ║
║ Alt-[ 1A 26 ║ Alt-left 9B 155 ║ Ctrl- K - 8E 142 ║
║ Alt-] 1B 27 ║ Alt-right 9D 157 ║ Ctrl- K + 90 144 ║
║ Alt-; 27 39 ║ ║ ║
║ Alt-' 28 40 ║ Alt-Delete A3 163 ║ Ctrl- K Up [8] 8D 141 ║
║ Alt-` 29 41 ║ Alt-End 9F 159 ║ Ctrl- K Cn [5] 8F 143 ║
║ Alt-\ 2B 43 ║ Alt-Home 97 151 ║ Ctrl- K Dw [2] 91 145 ║
║ Alt-, 33 51 ║ Alt-Insert A2 162 ║ Ctrl- K Ins[0] 92 146 ║
║ Alt-. 34 52 ║ Alt-PageUp 99 153 ║ Ctrl- K Del[.] 93 147 ║
║ Alt-/ 35 53 ║ Alt-PageDown A1 161 ║ ║
╙───────────────────╨───────────────────────╨────────────────────────╜
K indicates a key on the numeric keypad (when not in NumLock mode)
==============================================================================
For any ideas, requests, corrections ("There is always one more bug") or
whatever, contant the author at:
Fido:
Inbar Raz, 2:401/100.1
Inbar Raz, 2:403/100.42
Internet:
nyvirus@weizmann.weizmann.ac.il
Inbar.Raz@p1.f100.n401.z2.fidonet.org
Inbar.Raz@p42.f100.n403.z2.fidonet.org
Snailmail:
Inbar Raz
5 Hanegev Street
Yavne 70600