User:Johnburger/Demo/Dev/Key

From OSDev Wiki
Jump to navigation Jump to search

Programmers are often surprised to find out that the IBM keyboard doesn't send ASCII characters to the PC.

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"), and 1 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