User:Johnburger/Demo/Dev/Key
Programmers are often surprised to find out that the IBM keyboard doesn't send ASCII characters to the PC.
Contents |
Key Codes
Instead, it sends byte-wide scan codes in a particular format:
- The high bit is
0
to indicate that the key has been pressed ("make"), and1
to indicate that it was released ("break"); - The remaining seven bits are simply a number that superficially resembles its location on the keyboard, with
01h
being the top left key and (around)50h
being the bottom right key. As keyboard layouts changed, these starting values became muddied: it was more important that a moved key kept its original scan code than that it held a rigorous positional value!
Shift Keys
This encoding has the effect of not caring about the current values of the <Shift> keys - the same letter or number key produces the same code regardless of whether <Shift> or <Caps Lock> is currently down. Indeed, these keys send their individual scan codes just like any other key on the keyboard. It is up to the system to keep track of what Shift/Ctrl/Alt/Lock keys are currently pressed, and to interpret the subsequent keypresses appropriately.
Extended Keys
The original IBM PC keyboard has 84 keys. Each was given its own scan code, so for example the Left and Right <Shift> keys each had their own value (2Ah
and 36h
respectively). When the 104-key Extended keyboard came out, they had duplicated some keys and added new ones - for example they added an extra <Ctrl> and <Alt> key on the right hand side, and provided dedicated arrow keys rather than overlaying the numeric keypad. Even later, completely new keys were added that had no equivalents, such as the <Windows> and <Menu> keys.
New Keys
These latter keys could be assigned brand new scan codes, since they didn't have to be backward compatible - if an old system didn't understand the scan code it could just ignore it. But the repeated keys caused backward compatibility issues that were resolved in an interesting way - but in a way that makes our job harder.
Multi-code Keys
The duplicated keys couldn't be given new scan codes, since existing software wouldn't understand the codes and that would cripple the new keys' functionality. But giving them the same code meant that new software couldn't distinguish between the original and the duplicate. So instead the designers made the new keys send a double scan code when they were pressed or released. The first byte was a special magic value of 0E0h: it looks like a break code (with the high bit set), but for an unknown key, so old software would ignore it. Then the normal scan code for the old key was sent. For example, the Left <Ctrl> key has a scan code of 1Dh
, so the new Right <Ctrl> key would send the double-byte sequence 0E0h 1Dh
(and 0E0h 9Dh
on release). Old code would only recognize the second byte, while new code could take advantage of the prefix byte to distinguish the duplicate keys.
One-key Keys
Some of the added keys were designed to be one-key replacements for functions that previously required two keystrokes to invoke: for example, on the original IBM to get the screen to dump to a printer required the user to press <Shift><PrScn>, and to Pause or Break the current program required <Ctrl><NumLock>. When the one-key replacements were added, they distinguished themselves with the magic value as well, but now they generated extended sequences by double-coding the <Shift> key too - Prt Sc generated 0E0h 2Ah 0E0h 37h
on press and 0E0h 0B7h 0E0h 0AAh
on release, which corresponded to the original key sequence.
Pause/Break
For some reason though, <Pause/Break> has its own magic value: 0E1h
. This value means that there will be two extended scan codes sent - 0E1h 1Dh 45h
and 0E1h 09Dh 0C5h
for make and break respectively. This magic value also seems to indicate that the codes won't be auto-repeated, unlike every other key on the keyboard.
Definitions
The following definitions are for the keyboard controller, but they also give scan codes for many of the special keys - not all of which are used by this Demonstrator. The system does display all keypresses though, so it should be easy to add new definitions for values as required.
Demo/Dev/Key.inc
; ; Dev/Key.inc ; ; These are the definitions for the Keyboard Dev.Key.Data EQU 060h Dev.Key.Ctrl EQU 064h Dev.Key.Make EQU 000h ; "Make" codes have high bit off Dev.Key.Break EQU 080h ; "Break" codes have high bit on Dev.Key.Ext1 EQU 0E0h ; This is the Extended Key prefix Dev.Key.Ext2 EQU 0E1h ; This one means TWO following ; Scan codes for various keys Dev.Key.Esc EQU 01h Dev.Key.Enter EQU 1Ch Dev.Key.Space EQU 39h Dev.Key.Pause EQU 45h Dev.Key.Home EQU 47h Dev.Key.Up EQU 48h Dev.Key.PgUp EQU 49h Dev.Key.Left EQU 4Bh Dev.Key.Right EQU 4Dh Dev.Key.End EQU 4Fh Dev.Key.Down EQU 50h Dev.Key.PgDn EQU 51h Dev.Key.Ins EQU 52h Dev.Key.Del EQU 53h Dev.Key.F1 EQU 3Bh Dev.Key.F2 EQU 3Ch Dev.Key.F3 EQU 3Dh Dev.Key.F4 EQU 3Eh Dev.Key.F5 EQU 3Fh Dev.Key.F6 EQU 40h Dev.Key.F7 EQU 41h Dev.Key.F8 EQU 42h Dev.Key.F9 EQU 43h Dev.Key.F10 EQU 44h Dev.Key.F11 EQU 57h Dev.Key.F12 EQU 58h Dev.Key.Window EQU 5Bh Dev.Key.Menu EQU 5Dh