home *** CD-ROM | disk | FTP | other *** search
/ The Unsorted BBS Collection / thegreatunsorted.tar / thegreatunsorted / programming / misc_programming / keyboard < prev    next >
Text File  |  1993-01-16  |  39KB  |  758 lines

  1.                       The Keyboard Interface Tutorial
  2.                              By: Inbar Raz
  3.  
  4. Preface:
  5.  
  6. The Keyboard on the IBM PC and compatible is connected to the PPI -
  7. Programmable Peripheral Interface, which generally takes care of Keyboard
  8. functions, equipment information and timer functions. The PPI is addressable
  9. via port reads and writes, to addresses 060h thru 063h.
  10.  
  11. There are several type of keyboards available. The main difference between the
  12. various types is the key count. Existing sizez are:
  13.  
  14. 83  Key (Original PC)
  15. 84  Key (XT and clones)
  16. 101 Key (Usually on AT's and up, called Enhanced Keyboard)
  17.  
  18. In addition to those standard types, there are numerous non-standard types,
  19. which varry from manufacturer to manufacturer. There are 102 Key keyboards,
  20. keyboards with two F-Key sets (upper and left), keyboards with weird
  21. hardly-used keys like 'Macro' and 'Turbo' (which DO have a scan code, though)
  22. etcetera.
  23.  
  24. The IBM AT and up provides a better way of negotiating the keyboard, by
  25. allowing the user to directly access and command the keyboard, as it will be
  26. demonstrated later.
  27.  
  28. Using assembly language, there are two major ways to handle the keyboard and
  29. keystrokes:
  30.  
  31. 1. Using DOS functions:
  32.  
  33.    DOS provides a useful set of functions to use in context with the keyboard.
  34.    This includes one-key-input and string input.
  35.  
  36. 2. Using BIOS interrupts:
  37.  
  38.    The IBM PC BIOS (Basic Input Output System) provides an interrupt to handle
  39.    the keyboard - Interrupt 016h (022d). These functions, titles KEYBOARD I/O,
  40.    are an efficient medium level way of using the keyboard
  41.  
  42.    In addition to the Interrupt 016h interface, there is the Keyboard
  43.    Interrupt, Interrupt 009h. As opposed to the other interrupt, Interrupt
  44.    009h is an IRQ - Interrupt Request, which means that it is never called by
  45.    software. Only hardware, when certain conditions are met, calls IRQ
  46.    interrupts. Naturally, the user is able to invoke them himself, but that is
  47.    not commonly done.
  48.  
  49. 3. Direct port access:
  50.  
  51.    It is possible to access the keyboard using direct port reads and writes.
  52.    As mentioned before, this is usually done by addressing the PPI. On AT's
  53.    and up, however, it is possible to directly access the keyboard itself.
  54.  
  55.  
  56. The BIOS also supplies a certain amount of information about the keyboard
  57. within it's BDA - BIOS Data Area, aka BDS - BIOS Data Segment - which is the
  58. segment that lies at paragraph 040h (0040h:XXXXh or 0000h:04XXh):
  59.  
  60. Address Size Contents
  61. ▀▀▀▀▀▀▀ ▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
  62. 0:0412    1  Errors in PCjr InfraRed keyboard link
  63.  
  64. 0:0417    2  Keyboard status bits. See Keyboard Flags
  65. 0:0419    1  Current (accumulating) value of Alt+numpad pseudo-key input.
  66.              Normally 0.  When [Alt] is released, value is stored in kbd buf.
  67. 0:041A    2  Address of keyboard buffer head (keystroke at that addr is next)
  68. 0:041C    2  Address of keyboard buffer tail
  69. 0:041E   32  Keyboard buffer.  BIOS stores keystrokes here (head and tail
  70.              point to addresses from 041Eh to 043Dh inclusive).
  71.  
  72. 0:0480    2  ▌AT▐  ≡PS/2≡ Keyboard buffer offset start address (usually 01Eh)
  73. 0:0482    2                                        end address (usually 03Eh)
  74.  
  75. 0:0496    1  ▌AT▐ Keyboard flag bit 4=1 (10h) if 101-key keyboard is attached
  76. 0:0497    1  ▌AT▐ Keyboard flag for LED 'key lock' display
  77.                   bits 0-2 are ScrollLock, NumLock, CapsLock respectively
  78.  
  79. ******************************************************************************
  80. ******************************************************************************
  81. ******************************************************************************
  82.  
  83. Using DOS functions:
  84. --------------------
  85.  
  86. DOS provides a set of 7 functions to handle the keyboard:
  87.  
  88. 01h Keyboard Input
  89. 06h Console I/O
  90. 07h No Echo Unfiltered Input
  91. 08h No Echo Filtered Input
  92. 0Ah Buffered Input
  93. 0Bh Input Status
  94. 0Ch Clear Keyboard Buffer & Input
  95.  
  96.  
  97.                           DOS Fn 01h: Keyboard Input
  98. ══════════════════════════════════════════════════════════════════════════════
  99. ┌─────────╥───────╥───────────────────────────────────────────────────────────
  100. │ Expects ║ AH    ║ 01h
  101. ├─────────╫───────╫───────────────────────────────────────────────────────────
  102. │ Returns ║ AL    ║ Character fetched from the Standard Input
  103. └─────────╨───────╨───────────────────────────────────────────────────────────
  104.  
  105. Description: Reads (waits for) a character from the Standard Input Device.
  106.              Echoes that character to the Standard Output Device.
  107.              If Ctrl-Break is detected, INT 23h is executed.
  108.  
  109. Notes:       Extended ASCII keystrokes (ie, F1-F12, PgUp, cursor, etc) will
  110.              require two calls to this function.  The first call will return
  111.              AL=0.  The second will return AL with the extended ASCII code.
  112.  
  113.  
  114.                           DOS Fn 02h: Display Output
  115. ══════════════════════════════════════════════════════════════════════════════
  116. ┌─────────╥───────╥───────────────────────────────────────────────────────────
  117. │ Expects ║ AH    ║ 02h
  118. └─────────╢ DL    ║ Character to send to the Standard Output
  119. ┌─────────╫───────╫───────────────────────────────────────────────────────────
  120. │ Returns ║ none  ║
  121. └─────────╨───────╨───────────────────────────────────────────────────────────
  122.  
  123. Description: Sends the character in DL to the Standard Output.
  124.  
  125.              Handles backspace (ASCII 8) by moving the cursor left and leaving
  126.              the cursor there.
  127.  
  128.              If Ctrl-Break is detected, INT 23h is executed.
  129.  
  130.  
  131.                            DOS Fn 06h: Console I/O
  132. ══════════════════════════════════════════════════════════════════════════════
  133. ┌─────────╥───────╥───────────────────────────────────────────────────────────
  134. │ Expects ║ AH    ║ 06h
  135. └─────────╢ DL    ║ 0 to 0FEh  Character to send to the Standard Output
  136.           ║       ║ 0FFh       Request for input from the Standard Input
  137. ┌─────────╫───────╫───────────────────────────────────────────────────────────
  138. │ Returns ║ ZF    ║ Clear (NZ) if character is ready ══╦═ on input requests
  139. └─────────╢ AL    ║ Character read, if ZF is clear ════╝   (when DL=0FFh)
  140.           ╙───────╨───────────────────────────────────────────────────────────
  141.  
  142. Description: If DL is 0FFh, this performs a "no wait" console input, returning
  143.              the Zero Flag (ZF) set (ZR) if there is no character ready.
  144.              If a character is ready, returns ZF cleared (NZ) with the
  145.              character that was read in AL.
  146.  
  147.              If DL is anything but 0FFh, DL is sent to the Standard Output.
  148.  
  149. Notes:       Does not check for Ctrl-Break.  Call twice for Extended ASCII.
  150.  
  151.  
  152.                  DOS Fn 07h: No Echo Unfiltered Console Input
  153. ══════════════════════════════════════════════════════════════════════════════
  154. ┌─────────╥───────╥───────────────────────────────────────────────────────────
  155. │ Expects ║ AH    ║ 07h
  156. ├─────────╫───────╫───────────────────────────────────────────────────────────
  157. │ Returns ║ AL    ║ Character fetched from the Standard Input
  158. └─────────╨───────╨───────────────────────────────────────────────────────────
  159.  
  160. Description: Reads (waits for) a character from the Standard Input Device,
  161.              returning that character in AL.
  162.  
  163.              Unfiltered: Does not detect Ctrl-Break, backspace, etc.
  164.  
  165. Notes:       Call twice for Extended ASCII character input.
  166.              Use Fn 0Bh to check status (if you don't want to wait for a key).
  167.  
  168.  
  169.                       DOS Fn 08h: No Echo Console Input
  170. ══════════════════════════════════════════════════════════════════════════════
  171. ┌─────────╥───────╥───────────────────────────────────────────────────────────
  172. │ Expects ║ AH    ║ 08h
  173. ├─────────╫───────╫───────────────────────────────────────────────────────────
  174. │ Returns ║ AL    ║ Character fetched from the Standard Input
  175. └─────────╨───────╨───────────────────────────────────────────────────────────
  176.  
  177. Description: Reads (waits for) a character from the Standard Input Device,
  178.              returning that character in AL.
  179.  
  180.              If Ctrl-Break is detected, INT 23h is executed.
  181.  
  182. Notes:       Call twice for Extended ASCII character input.
  183.  
  184.  
  185.                       DOS Fn 0Ah: Buffered String Input
  186. ══════════════════════════════════════════════════════════════════════════════
  187. ┌─────────╥───────╥───────────────────────────────────────────────────────────
  188. │ Expects ║ AH    ║ 0Ah
  189. └─────────╢ DS:DX ║ Address of an input buffer (see below)
  190. ┌─────────╫───────╫───────────────────────────────────────────────────────────
  191. │ Returns ║ none  ║ Buffer contains input terminated with CR (ASCII 13h)
  192. └─────────╨───────╨───────────────────────────────────────────────────────────
  193.  
  194. Description: On entry, the buffer at DS:DX must be set up as:
  195.              ┌───┬───┬───┬───┬───┬───┬─ ─ ─
  196.              │max│ ? │ ?   ?   ?   ?   ?     max is maximum acceptable input
  197.              └───┴───┴───┴───┴───┴───┴ ─  ─  (range: 1 to 254)
  198.              On exit, the buffer is filled:
  199.              ┌───┬───┬───┬───┬───┬───┬─ ─ ─
  200.              │max│len│ T   E   X   T   0Dh   len is actual length of input,
  201.              └───┴───┴───┴───┴───┴───┴ ─  ─  less the terminating CR (eg, 4).
  202.  
  203.              Characters are read from the Standard Input up to a CR (ASCII 13)
  204.              or up to the value of max-1.  If max-1 is reached, the console
  205.              bell rings (beeps) for each character until Enter (CR) is read.
  206.  
  207.              The second byte of the buffer is filled with the actual length of
  208.              the input, less the terminating CR.  The final character in the
  209.              buffer is always CR (which is not counted in the length byte).
  210.  
  211.              The characters in the buffer (including the len) before the call
  212.              are used as a "template" and the DOS editing keys are in effect:
  213.              [Esc] displays "\" and restarts the edit, [F3] displays to the
  214.              end of the template, [F5] displays "@" and stores the current
  215.              line as the template, etc.  Most Extended ASCII keystrokes are
  216.              ignored.
  217.  
  218.              If Ctrl-Break is detected, INT 23h is executed and the buffer is
  219.              left unchanged.
  220.  
  221.  
  222.                         DOS Fn 0Bh: Check Input Status
  223. ══════════════════════════════════════════════════════════════════════════════
  224. ┌─────────╥───────╥───────────────────────────────────────────────────────────
  225. │ Expects ║ AH    ║ 0Bh
  226. ├─────────╫───────╫───────────────────────────────────────────────────────────
  227. │ Returns ║ AL    ║ 0FFh if a character is available from the Standard Input
  228. └─────────╢       ║ 0    if no character is available
  229.           ╙───────╨───────────────────────────────────────────────────────────
  230.  
  231. Description: Checks the status of the Standard Input.
  232.  
  233.              If Ctrl-Break is detected, INT 23h is executed.
  234.  
  235. Notes:       Use before Fns 01h, 07h and 08h to avoid having DOS wait for a
  236.              key.
  237.  
  238.              This is a simple, non-destructive way to check for Ctrl-Break
  239.              during long calculations or other processing that does not
  240.              normally look for input.  It lets the user abort from such a
  241.              sequence.
  242.  
  243.  
  244.                           DOS Fn 0Ch: Clear & Input
  245. ══════════════════════════════════════════════════════════════════════════════
  246. ┌─────────╥───────╥───────────────────────────────────────────────────────────
  247. │ Expects ║ AH    ║ 0Ch
  248. └─────────╢ AL    ║ DOS input function number (01h, 06h, 07h, 08h, or 0Ah)
  249. ┌─────────╫───────╫───────────────────────────────────────────────────────────
  250. │ Returns ║ none  ║
  251. └─────────╨───────╨───────────────────────────────────────────────────────────
  252.  
  253. Description: Clears the Standard Input type-ahead buffer then invokes the DOS
  254.              input function specified by AL.  This forces the system to wait
  255.              for a character to be typed.
  256.  
  257.              These values are allowed for AL:  01h Keyboard Input
  258.                                                06h Console I/O
  259.                                                07h No Echo Unfiltered Input
  260.                                                08h No Echo Filtered Input
  261.                                                0Ah Buffered Input
  262.  
  263. ──────────────────────────────────────────────────────────────────────────────
  264.  
  265. In addition to these functions, it is also possible to read a selected amount
  266. of characters from the keyboard, using DOS's File Handle functions, as the
  267. Keyboard, aka Standard Input, has a pre-set handle of 0000h:
  268.  
  269.                     DOS Fn 3Fh: Read from keyboard via Handle
  270. ══════════════════════════════════════════════════════════════════════════════
  271. ┌─────────╥───────╥───────────────────────────────────────────────────────────
  272. │ Expects ║ AH    ║ 3Fh
  273. └─────────╢ BX    ║ 0000h - Handle for Standard Input (Keyboard)
  274.           ║ DS:DX ║ Address of buffer to receive data
  275.           ║ CX    ║ Number of bytes to read
  276. ┌─────────╫───────╫───────────────────────────────────────────────────────────
  277. │ Returns ║ AX    ║ Error code if CF is set to CY
  278. └─────────╢ AX    ║ Number of bytes actually read
  279.           ╙───────╨───────────────────────────────────────────────────────────
  280.  
  281. Description: CX bytes of data are read from the keyboard. The data is placed
  282.              into the caller's buffer pointed to by DS:DX.
  283.  
  284. Notes:       It is handy to use this function for reading default handles
  285.              such as the Standard I/O handles, instead of the buffered input
  286.              or character-by-character input functions.
  287.  
  288.              When you read from a device, AX returns the length of the line
  289.              up to and including the termination CR (ASCII 13h).
  290.  
  291. ******************************************************************************
  292. ******************************************************************************
  293. ******************************************************************************
  294.  
  295. Using BIOS Interrupts:
  296. ----------------------
  297.  
  298. As mentioned before, there are two ways to use interrupts to access the
  299. keyboard.
  300.  
  301. The first is Interrupt 016h - Keyboard I/O.
  302.  
  303.                           INT 16h: Keyboard Services
  304. ══════════════════════════════════════════════════════════════════════════════
  305.  This is the application-level interface to the keyboard.  Keystrokes are
  306.  actually processed asynchronously in the background.  As each keystroke is
  307.  received from the keyboard, it is processed by INT 09h and placed into a
  308.  circular queue.
  309.  
  310.  See AT Keyboard for ways to speed up the keyboard and other hardware info.
  311.  
  312. AH  Service
  313. ▀▀▀ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
  314. 00h Read (wait for) next keystroke
  315.     Output: AL = ASCII character  (if AL=0, AH is an Extended ASCII keystroke)
  316.             AH = Scan Code or Extended ASCII keystroke
  317.  
  318. 01h Check if a keystroke is ready (and preview it if so)
  319.     Output: ZF = ZR = 1 if no key is ready
  320.             ZF = NZ = 0 if a key is ready.
  321.                         AX is set as for SubFn 00h (but the keystroke has not
  322.                         been removed from the queue).
  323.  
  324. 02h Read the shift-key status.  Determine which shift keys are currently being
  325.      pressed and whether the keyboard is in NumLock state, etc.
  326.     Output: AL = shift key and 'lock' status as in Keyboard Flags
  327.  
  328. 03h Set keyboard typeamatic rate and delay. (11/15/85 BIOS)
  329.      Input: AL = 05h (eg, AX = 0305h)
  330.             BL = Typeamatic rate 0=30 rpts/sec, 1=26...1Fh=2. See AT Keyboard
  331.             BH = Delay (0=250ms, 1=500ms, 2=750ms, 3=1 second)
  332.     Output: (none)
  333.  
  334. 04h (reserved)
  335.  
  336. 05h Place a keystroke into the keyboard buffer. (11/15/85 BIOS)
  337.     Input:  CL = ASCII character.
  338.             CH = Scan Code  byte (or 0 if you don't care).
  339.     Output: AL = Status: 0=success; 1=buffer full
  340.  
  341. 06h-0Fh (reserved)
  342.  
  343. 10h Read (wait for) a keystroke; specific for 101-key 'board (11/15/85 BIOS)
  344.     Output: AL = ASCII character  (if AL=0, AH is an Extended ASCII keystroke)
  345.             AH = Scan Code or translated Extended ASCII keystroke
  346.  
  347. 11h Preview keystroke; same as 01, but for 101-key 'board (11/15/85 BIOS)
  348.     Output: ZF = ZR = 1 if no key is ready
  349.             ZF = NZ = 0 if a key is ready.
  350.             AX is set as for SubFn 10f but keystroke is still in the buffer.
  351.  
  352. 12h Read shift-key status; same as 02, but for 101-key 'board (11/15/85 BIOS)
  353.     Output: AL = shift key and 'lock' status.  See 101-key  Keyboard Flags
  354. ──────────────────────────────────────────────────────────────────────────────
  355.  
  356.  
  357. The second is Interrupt 009h - Keyboard Interrupt, IRQ 1
  358.  
  359.                          INT 09h: Keyboard Interrupt
  360. ══════════════════════════════════════════════════════════════════════════════
  361.  This hardware-generated interrupt (IRQ 1) is executed upon each press and
  362.  release of a key.  The ROM-BIOS code interprets the keystroke, storing values
  363.  into the keyboard buffer at 0:041Eh.  It also handles the special cases of the
  364.  PrtSc and SysReq keys, and tracks the status of the shift and case-lock keys.
  365.  
  366. See:  INT 16h .......... BIOS service to access the keys stored in the buffer
  367.                          and obtain status of the certain shift keys.
  368.       Scan Codes ....... a list of the values of each possible keystroke as
  369.                          it is received by INT 09h.
  370.       Extended ASCII ... for a summary of the values that BIOS stores into the
  371.                          the keyboard buffer after it translates a scan code.
  372.       Keyboard Flags ... for a summary of how to obtain, test for, and modify
  373.                          the bit-settings of shift and case-lock flags.
  374.  
  375.  TSRs (RAM-resident programs) that have a hot-key to trigger a popup usually
  376.  intercept INT 09h and test for a certain key with a sequence such as this:
  377.  
  378.          push    ax
  379.          in      al,60h             ; Read the key
  380.          cmp     al,POP_KEY         ; Is this the hot key?
  381.          je      do_pop             ; Yes, trigger the popup
  382.                                     ;  No, drop through to original driver
  383.          pop     ax
  384.          jmp     cs:[int9_vect]     ; Just hop out to original int handler
  385.  
  386. do_pop:  ;------ the following housekeeping is needed to satisfy the hdwr int
  387.  
  388.          in      al,61h             ; Get value of keyboard control lines
  389.          mov     ah,al              ;  Save it
  390.          or      al,80h             ; Set the "enable kbd" bit
  391.          out     61h,al             ;  And write it out the control port
  392.          xchg    ah,al              ; Fetch the original control port value
  393.          out     61h,al             ;  And write it back
  394.  
  395.          mov     al,20h             ; Send End-Of-Interrupt signal
  396.          out     20h,al             ;  to the 8259 Interrupt Controller
  397.  
  398.          ;------ other code handles other tests and finally the popup code
  399.  
  400. ******************************************************************************
  401. ******************************************************************************
  402. ******************************************************************************
  403.  
  404. Direct port access:
  405. -------------------
  406.  
  407. The keyboard is addressable in two manners.
  408.  
  409. The first, available on all IBM PCs of all types, is by addressing the PPI -
  410. Programmable Peripheral Interface.
  411.  
  412. Port  Description
  413. ▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
  414. 060h  ■PC/XT■  PPI port A.  Read keyboard scan code:
  415.  
  416.       IN   al,60h  ; Fetche most recent scan code.  See INT 09h and Scan Code
  417.  
  418.       ▌AT▐ keyboard data register.                     See AT Keyboard
  419.  
  420. 061h  ■PC/XT■ PPI (Programmable Peripheral Interface) port B.
  421.       ╓7┬6┬5┬4┬3┬2┬1┬0╖
  422.       ║ │ │ │ │ │0│ │ ║
  423.       ╙╥┴╥┴╥┴╥┴╥┴─┴╥┴╥╜ bit
  424.        ║ ║ ║ ║ ║   ║ ╚═ 0: Timer 2 gate (speaker)  ═╦═ OR 03h=speaker ON
  425.        ║ ║ ║ ║ ║   ╚═══ 1: Timer 2 data  ═══════════╝  AND 0FCh=speaker OFF
  426.        ║ ║ ║ ║ ╚═══════ 3: 1=Read high switches; 0=read low switches(see 62h)
  427.        ║ ║ ║ ╚═════════ 4: 0=Enable RAM parity checking; 1=disable
  428.        ║ ║ ╚═══════════ 5: 0=Enable I/O channel check
  429.        ║ ╚═════════════ 6: 0=Hold keyboard clock low
  430.        ╚═══════════════ 7: 0=Enable keyboard; 1=disable keyboard
  431.  
  432. ──────────────────────────────────────────────────────────────────────────────
  433.  
  434. The second, available only on IBM PC/ATs and up, is by directly commanding the
  435. keyboard itself. -= This is for the AT keyboard only. =-
  436.  
  437. Port  Description
  438. ▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
  439. 064h  ▌AT▐ keyboard command register.  This port communicates with the 8042
  440.       which runs an on-chip control program for the keyboard.  It accepts
  441.       command codes and data bytes.
  442.  
  443.  The keyboard of the ▌AT▐ (and its Intel 8042 microcomputer interface) is
  444.  programmable and a lot more interesting than the old-style PC keyboards.
  445.  Using the information below, you can set the key repeat speed and play
  446.  games with the "lock" key LED display.
  447.  
  448.  Note: This is not a comprehensive coverage of the details of keyboard and
  449.        8042 operation, but it should provide some food for thought.
  450.  
  451.  Port 60h is for writing data and is maintained for compatibility with
  452.  earlier models.  If the examples using port 64h don't work, try using 60h.
  453.  
  454.  Port 64h is for writing commands and data and for reading keyboard status.
  455.  Before sending a command to the keyboard, the BIOS tests its status
  456.  (IN al,64h) and makes sure a key isn't being pressed or the internal buffer
  457.  isn't full, etc.  There's a small risk if you just go ahead and send the
  458.  command:
  459.  
  460.        mov   al,cmd_code
  461.        out   64h,al
  462.  
  463.  For a two-part command such as setting the typeamatic rate, it's wise to
  464.  delay a little while between OUTs:
  465.  
  466.        mov   al,cmd_code
  467.        out   64h,al
  468.        mov   cx,2000h  ;arbitrary ≈ 10ms+
  469. delay: loop  delay
  470.        mov   al,data_value
  471.        out   64h,al
  472.  
  473. Cmd  Description
  474. ▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
  475. 0FFh Reset the keyboard and start internal diagnostics
  476. 0FEh Resend the last transmission
  477. 0FDh-0F7h (NOP)
  478. 0F6h Set keyboard to defaults and continue scanning
  479. 0F5h Set keyboard to defaults and disable keyboard scanning
  480. 0F4h Enable the keyboard. Kybd sends 'ACK', clears buffer, and starts scanning
  481.  
  482. 0F3h Set typeamatic rate and delay.  First send 0F3h, then send data byte:
  483.  
  484.      ╓7┬6┬5┬4┬3┬2┬1┬0╖
  485.      ║0│dly│rept rate║
  486.      ╙╥┴─┴─┴─┴─┴─┴─┴─╜
  487.       ║ ╚╦╝ ╚═══════╩═ bits 0-4 set the repeat rate (see below)
  488.       ║  ╚════════════ bits 5-6 set initial delay before first repeat:
  489.       ║                          00=250ms; 01=500ms; 10=750ms; 11=1000ms
  490.       ╚═══════════════ bit 7 is always 0
  491.                                                     Value Rate    Value Rate
  492.      This chart is a partial guide for the repeat    0  = 30.0    0Ah = 10.0
  493.      rate (bits 0-4).  You can interpolate for       1  = 26.7    0Dh =  9.2
  494.      values not shown, but let's face it, you're     2  = 24.0    10h =  7.5
  495.      only interested in the fastest rates.           4  = 20.0    14h =  5.0
  496.                                                      8  = 15.0    1Fh =  2.0
  497.  
  498.      The keyboard is initially set to begin repeating after 1/2-second and
  499.      repeat at a rate of 10 repeats per second.  This is much too slow.  A
  500.      data byte of 01h sets the delay to 1/4-second with 26 repeats per second.
  501.  
  502. 0F2h-0EFh (NOP)
  503. 0EEh Echo.  Diagnostics aid.  Simply sends 0EEh right back.
  504.  
  505. 0EDh Turn LED 'lock key' lights on or off. First send 0EDh, then send byte:
  506.  
  507.      ╓7┬6┬5┬4┬3┬2┬1┬0╖
  508.      ║ not used│c│n│s║
  509.      ╙─┴─┴─┴─┴─┴╥┴╥┴╥╜
  510.                 ║ ║ ╚═ ScrollLock light 01h=turn on
  511.                 ║ ╚═══ NumLock light    02h=turn on
  512.                 ╚═════ CapsLock light   04h=turn on
  513.  
  514.      The bit positions 0-3 correspond to bits 4-6 of the keyboard flags
  515.      variable in the BIOS Data area.  You should make an effort to keep the
  516.      flags in sync with the lights.  For instance, if you do a big favor for
  517.      the user and set his ten-key pad into NumLock mode (by setting bit 5 of
  518.      0:0417h) then be sure to turn on the corresponding LED (eg, bit 1).
  519.  
  520. ******************************************************************************
  521. ******************************************************************************
  522. ******************************************************************************
  523.  
  524.                            Additional Information
  525.                            ----------------------
  526.  
  527.                          Keyboard Shift Status Flags
  528. ══════════════════════════════════════════════════════════════════════════════
  529.  Two bytes at address 0:0417h and 0:0418h identify the status of the keyboard
  530.  shift keys and keyboard toggles.  INT 16h returns the first byte in AL.
  531.  
  532.  ╓─7┬─6┬─5┬─4┬─3┬─2┬─1┬─0╖     Perform INT 16h Fn 02h
  533.  ║I │C │N │S │a │c │sL│sR║     or fetch AL=byte at 0:0417h
  534.  ╙─╥┴─╥┴─╥┴─╥┴─╥┴─╥┴─╥┴─╥╜ bit
  535.    ║  ║  ║  ║  ║  ║  ║  ╚═ 0: Alpha-shift (right side) DOWN (AL & 01h)
  536.    ║  ║  ║  ║  ║  ║  ╚════ 1: Alpha-shift (left side) DOWN  (AL & 02h)
  537.    ║  ║  ║  ║  ║  ╚═══════ 2: Ctrl-shift (either side) DOWN (AL & 04h)
  538.    ║  ║  ║  ║  ╚══════════ 3: Alt-shift  (either side) DOWN (AL & 08h)
  539.    ║  ║  ║  ╚═════════════ 4: ScrollLock state              (AL & 10h)
  540.    ║  ║  ╚════════════════ 5: NumLock state                 (AL & 20h)
  541.    ║  ╚═══════════════════ 6: CapsLock state                (AL & 40h)
  542.    ╚══════════════════════ 7: Insert state                  (AL & 80h)
  543.  
  544.  ╓─7┬─6┬─5┬─4┬─3┬─2┬─1┬─0╖
  545.  ║i │c │n │s │  │sy│aL│cL║    fetch AL=byte at 0:0418h
  546.  ╙─╥┴─╥┴─╥┴─╥┴─╥┴─╥┴─╥┴─╥╜ bit
  547.    ║  ║  ║  ║  ║  ║  ║  ╚═ 0: Ctrl-shift (left side) DOWN (AL & 01h)
  548.    ║  ║  ║  ║  ║  ║  ╚════ 1: Alt-shift (left side) DOWN  (AL & 02h)
  549.    ║  ║  ║  ║  ║  ╚═══════ 2: SysReq DOWN                 (AL & 04h)
  550.    ║  ║  ║  ║  ╚══════════ 3: hold/pause state            (AL & 08h)
  551.    ║  ║  ║  ╚═════════════ 4: ScrollLock DOWN             (AL & 10h)
  552.    ║  ║  ╚════════════════ 5: NumLock DOWN                (AL & 20h)
  553.    ║  ╚═══════════════════ 6: CapsLock DOWN               (AL & 40h)
  554.    ╚══════════════════════ 7: Insert DOWN                 (AL & 80h)
  555.  
  556. Notes: Bits 0-2 of 0:0418h are defined only for the 101-key enhanced keyboard.
  557.  
  558.        The 101-key BIOS INT 16h Fn 12h returns AL as with Fn 02, but AH is
  559.        returned with the following bit-flag layout:
  560.  
  561.        ╓─7┬─6┬─5┬─4┬─3┬─2┬─1┬─0╖
  562.        ║sy│c │n │s │aR│cR│aL│cL║    Perform INT 16h Fn 12h (101-key BIOS only)
  563.        ╙─╥┴─╥┴─╥┴─╥┴─╥┴─╥┴─╥┴─╥╜ bit
  564.          ║  ║  ║  ║  ║  ║  ║  ╚═ 0: Ctrl-shift (left side) DOWN  (AH & 01h)
  565.          ║  ║  ║  ║  ║  ║  ╚════ 1: Alt-shift (left side) DOWN   (AH & 02h)
  566.          ║  ║  ║  ║  ║  ╚═══════ 2: Ctrl-shift (right side) DOWN (AH & 04h)
  567.          ║  ║  ║  ║  ╚══════════ 3: Alt-shift (right side) DOWN  (AH & 08h)
  568.          ║  ║  ║  ╚═════════════ 4: ScrollLock DOWN              (AH & 10h)
  569.          ║  ║  ╚════════════════ 5: NumLock DOWN                 (AH & 20h)
  570.          ║  ╚═══════════════════ 6: CapsLock DOWN                (AH & 40h)
  571.          ╚══════════════════════ 7: SysReq DOWN                  (AH & 80h)
  572.  
  573.        Some older programs change the values of NumLock and CapsLock state
  574.        bits (at 0:0417h) to force a known status.  This is unwise because
  575.        modern keyboards have indicator lights which will get out of sync with
  576.        the status. See AT Keyboard for more information on the lock-key LEDs.
  577.  
  578.        PCjr status bytes at 0:0488 are omitted for lack of interest.
  579.  
  580.  
  581.                              Keyboard Scan Codes
  582. ══════════════════════════════════════════════════════════════════════════════
  583.  When the keyboard forces a hardware interrupt, it passes a Scan Code to the
  584.  interrupt handler.  The handler converts this to an ASCII or Extended ASCII
  585.  value.  For compatibility across the various keyboards, it is wise to avoid
  586.  using scan codes and stick to the BIOS translation of a keystroke.
  587.  
  588. ┌─────────────────────────┐
  589. │ Original PC/XT Keyboard │ When a key is released, the keyboard sends the
  590. └─────────────────────────┘ same value, ORed with 80h (eg, [Ctrl] sends 1Dh
  591.  when pressed and 9Dh when released).
  592.  
  593. ────────────╥─────────────╥───────────────╥────────────────╥──────────────────
  594. Hex Dec Key ║Hex Dec Key  ║Hex Dec Key    ║Hex Dec Key     ║Hex Dec Key
  595. ────────────╫─────────────╫───────────────╫────────────────╫──────────────────
  596. 01   1  Esc ║12  18  E    ║23  35  H      ║34  52  . >     ║45  69  NumLock
  597. 02   2  1 ! ║13  19  R    ║24  36  J      ║35  53  / ?     ║46  70  ScrollLock
  598. 03   3  2 @ ║14  20  T    ║25  37  K      ║36  54  Shft(Rt)║47  71  Home [7]
  599. 04   4  3 # ║15  21  Y    ║26  38  L      ║37  55  * PrtSc ║48  72  Up   [8]
  600. 05   5  4 $ ║16  22  U    ║27  39  ; :    ║38  56  Alt     ║49  73  PgUp [9]
  601. 06   6  5 % ║17  23  I    ║28  40  " '    ║39  57  spacebar║4a  74  K -
  602. 07   7  6 ^ ║18  24  O    ║29  41  ` ~    ║3a  58  CapsLock║4b  75  Left [4]
  603. 08   8  7 & ║19  25  P    ║2a  42  Shft(L)║3b  59  F1      ║4c  76  Cntr [5]
  604. 09   9  8 * ║1a  26  [ {  ║2b  43  \ |    ║3c  60  F2      ║4d  77  Rght [6]
  605. 0a  10  9 ( ║1b  27  ] }  ║2c  44  Z      ║3d  61  F3      ║4e  78  K +
  606. 0b  11  0 ) ║1c  28  Enter║2d  45  X      ║3e  62  F4      ║4f  79  End  [1]
  607. 0c  12  - _ ║1d  29  Ctrl ║2e  46  C      ║3f  63  F5      ║50  80  Down [2]
  608. 0d  13  + = ║1e  30  A    ║2f  47  V      ║40  64  F6      ║51  81  PgDn [3]
  609. 0e  14  bksp║1f  31  S    ║30  48  B      ║41  65  F7      ║52  82  Ins  [0]
  610. 0f  15  Tab ║20  32  D    ║31  49  N      ║42  66  F8      ║53  83  Del  [.]
  611. 10  16  Q   ║21  33  F    ║32  50  M      ║43  67  F9      ║
  612. 11  17  W   ║22  34  G    ║33  51  , <    ║44  68  F10     ║
  613. ────────────╨─────────────╨───────────────╨────────────────╨──────────────────
  614.                   K indicates a key on the numeric keypad
  615.  
  616. ┌────────────────────┐
  617. │ 84-Key AT Keyboard │ The 84-key keyboard sends the same scan codes as the
  618. └────────────────────┘ 83-key (original PC) keyboard with the addition that
  619.  [SysReq] sends scan code 54h (84 decimal).
  620.  
  621.  However, the BIOS never lets an application program see this scan code.
  622.  Instead, it invokes INT 15h SubFn 85h on make or break of the SysReq key.
  623.  
  624.  The 'break' (release of a key) is handled differently.  Upon a break, the
  625.  keyboard sends a two-byte sequence:  0F0h, followed by the 'make' scan code.
  626.  See AT Keyboard Functions for information on programming this keyboard.
  627.  
  628. ┌──────────────────┐
  629. │ 101-Key Keyboard │ This keyboard has three separate mappings of the scan
  630. └──────────────────┘ codes, selected by communication through port 64h.  The
  631.  keyboard comes to life with scan code set 2 (which is wildly different from
  632.  the 84-key mapping.  However, the scan codes are translated by the hardware
  633.  keyboard interface before they are made available to programs that read the
  634.  keyboard.
  635.  
  636.  The result is that all of the scan codes identified in the above table are
  637.  valid when the 101-key 'board comes up naturally.  The following table
  638.  lists the additional scan-codes that are sent by the 101-key 'board.  Note
  639.  that all keys mentioned here refer to the keys that are unique to this
  640.  keyboard; eg, [Insert] is the dedicated insert key (not KeyPad Ins).
  641.  
  642.    ────────────────────────────────────────────╥───────────────────────────
  643.    Key                       Hex Sequence      ║ Key           Hex Sequence
  644.    ────────────────────────────────────────────╫───────────────────────────
  645.    F11 ..................... 57                ║ Home ........ E0 47
  646.    F12 ..................... 58                ║ Shift-Home .. E0 AA E0 47
  647.    Right-Alt ............... E0 38             ║ End ......... E0 4f
  648.    Right-Ctrl .............. E0 1D             ║ Shift-End ... E0 AA E0 4f
  649.    PrintScreen ............. E0 2A E0 37       ║ Up........... E0 48
  650.    Shft-PrintScreen (SysReq) E0 37             ║ Shift-Up .... E0 AA E0 48
  651.    Ctrl-PrintScreen (SysReq) E0 37             ║ Down ........ E0 50
  652.    Alt-PrintScreen ......... 54                ║ Shift-Down .. E0 AA E0 50
  653.    Pause ................... E1 1D 45 E1 9D C5 ║ PageUp ...... E0 49
  654.    Ctrl-Pause (Break) ...... E0 46 E0 C6       ║ Shft-PageUp . E0 AA E0 49
  655.    Insert .................. E0 53             ║ PageDown .... E0 51
  656.    Shift-Insert ............ E0 AA E0 52       ║ Shft-PageDown E0 AA E0 51
  657.    Delete .................. E0 53             ║ Right ....... E0 4D
  658.    Shift-Delete ............ E0 AA E0 53       ║ Shift-Right . E0 AA E0 4D
  659.    Left .................... E0 4B             ║ K Enter ..... E0 1C
  660.    Shift-Left .............. E0 AA E0 4B       ║ K / ......... E0 35
  661.                                                ║ Shift-K / ... E0 AA E0 35
  662.    ────────────────────────────────────────────╨───────────────────────────
  663.                    K indicates a key on the numeric keypad
  664.  
  665.  Note that in cases where a key is similar to another (pre-101) key, the
  666.  second scan code byte is the same as the original key.  Thus, some programs
  667.  that work at the scan-code level can get away with simply ignoring the E0h
  668.  prefix.
  669.  
  670.  
  671.                           Extended ASCII Keystrokes
  672. ══════════════════════════════════════════════════════════════════════════════
  673.  
  674.  When INT 16h Fn 00h returns AL=0, then AH will contain an extended ASCII
  675.  keystroke as listed in these tables.  When a DOS Character I/O function
  676.  returns a character of 00h, you should make a second call to obtain the
  677.  extended ASCII value.
  678.  
  679.   ╓─────────────╥───────────────────╥───────────────────╥──────────────────╖
  680.   ║ Key Hex Dec ║ Key       Hex Dec ║ Key       Hex Dec ║ Key      Hex Dec ║
  681.   ╟─────────────╫───────────────────╫───────────────────╫──────────────────╢
  682.   ║ F1   3B  59 ║ Shift-F1   54  84 ║ Ctrl-F1   5E   94 ║ Alt-F1   68  104 ║
  683.   ║ F2   3C  60 ║ Shift-F2   55  85 ║ Ctrl-F2   5F   95 ║ Alt-F2   69  105 ║
  684.   ║ F3   3D  61 ║ Shift-F3   56  86 ║ Ctrl-F3   60   96 ║ Alt-F3   6A  106 ║
  685.   ║ F4   3E  62 ║ Shift-F4   57  87 ║ Ctrl-F4   61   97 ║ Alt-F4   6B  107 ║
  686.   ║ F5   3F  63 ║ Shift-F5   58  88 ║ Ctrl-F5   62   98 ║ Alt-F5   6C  108 ║
  687.   ║ F6   40  64 ║ Shift-F6   59  89 ║ Ctrl-F6   63   99 ║ Alt-F6   6D  109 ║
  688.   ║ F7   41  65 ║ Shift-F7   5A  90 ║ Ctrl-F7   64  100 ║ Alt-F7   6E  110 ║
  689.   ║ F8   42  66 ║ Shift-F8   5B  91 ║ Ctrl-F8   65  101 ║ Alt-F8   6F  111 ║
  690.   ║ F9   43  67 ║ Shift-F9   5C  92 ║ Ctrl-F9   66  102 ║ Alt-F9   70  112 ║
  691.   ║ F10  44  68 ║ Shift-F10  5D  93 ║ Ctrl-F10  67  103 ║ Alt-F10  71  113 ║
  692.   ╙─────────────╨───────────────────╨───────────────────╨──────────────────╜
  693.   ╓───────────────╥────────────────╥───────────────────╥───────────────────╖
  694.   ║ Key   Hex  Dec║ Key   Hex  Dec ║ Key      Hex  Dec ║ Key      Hex  Dec ║
  695.   ╟───────────────╫────────────────╫───────────────────╫───────────────────╢
  696.   ║ Alt-A  1E  30 ║ Alt-P  19   25 ║ Alt-3     7A  122 ║ down      50   80 ║
  697.   ║ Alt-B  30  48 ║ Alt-Q  10   16 ║ Alt-4     7B  123 ║ left      4B   75 ║
  698.   ║ Alt-C  2E  46 ║ Alt-R  13   19 ║ Alt-5     7C  124 ║ right     4D   77 ║
  699.   ║ Alt-D  20  32 ║ Alt-S  1F   31 ║ Alt-6     7D  125 ║ up        48   72 ║
  700.   ║ Alt-E  12  18 ║ Alt-T  14   20 ║ Alt-7     7E  126 ║ End       4F   79 ║
  701.   ║ Alt-F  21  33 ║ Alt-U  16   22 ║ Alt-8     7F  127 ║ Home      47   71 ║
  702.   ║ Alt-G  22  34 ║ Alt-V  2F   47 ║ Alt-9     80  128 ║ PgDn      51   81 ║
  703.   ║ Alt-H  23  35 ║ Alt-W  11   17 ║ Alt--     82  130 ║ PgUp      49   73 ║
  704.   ║ Alt-I  17  23 ║ Alt-X  2D   45 ║ Alt-=     83  131 ║                   ║
  705.   ║ Alt-J  24  36 ║ Alt-Y  15   21 ║                   ║ ^left     73  115 ║
  706.   ║ Alt-K  25  37 ║ Alt-Z  2C   44 ║ NUL       03    3 ║ ^right    74  116 ║
  707.   ║ Alt-L  26  38 ║                ║ Shift-Tab 0F   15 ║ ^End      75  117 ║
  708.   ║ Alt-M  32  50 ║ Alt-0  81  129 ║ Ins       52   82 ║ ^Home     77  119 ║
  709.   ║ Alt-N  31  49 ║ Alt-1  78  120 ║ Del       53   83 ║ ^PgDn     76  118 ║
  710.   ║ Alt-O  18  24 ║ Alt-2  79  121 ║ ^PrtSc    72  114 ║ ^PgUp     84  132 ║
  711.   ╙───────────────╨────────────────╨───────────────────╨───────────────────╜
  712.               ╔═══════════════════════════════════════════════╗
  713.               ║ 101-key Keyboard Extensions Supported by BIOS ║
  714.     ╓─────────╨─────────╥───────────────────────╥─────────────╨──────────╖
  715.     ║ Key      Hex  Dec ║ Key           Hex Dec ║ Key           Hex  Dec ║
  716.     ╟───────────────────╫───────────────────────╫────────────────────────╢
  717.     ║ F11       85  133 ║ Alt-Bksp      0E   14 ║  Alt- K /      A4  164 ║
  718.     ║ F12       86  134 ║ Alt-Enter     1C   28 ║  Alt- K *      37   55 ║
  719.     ║ Shft-F11  87  135 ║ Alt-Esc       01    1 ║  Alt- K -      4A   74 ║
  720.     ║ Shft-F12  88  136 ║ Alt-Tab       A5  165 ║  Alt- K +      4E   78 ║
  721.     ║ Ctrl-F11  89  137 ║ Ctrl-Tab      94  148 ║  Alt- K Enter  A6  166 ║
  722.     ║ Ctrl-F12  8A  138 ║                       ║                        ║
  723.     ║ Alt-F11   8B  139 ║ Alt-up        98  152 ║ Ctrl- K /      95  149 ║
  724.     ║ Alt-F12   8C  140 ║ Alt-down      A0  160 ║ Ctrl- K *      96  150 ║
  725.     ║ Alt-[     1A   26 ║ Alt-left      9B  155 ║ Ctrl- K -      8E  142 ║
  726.     ║ Alt-]     1B   27 ║ Alt-right     9D  157 ║ Ctrl- K +      90  144 ║
  727.     ║ Alt-;     27   39 ║                       ║                        ║
  728.     ║ Alt-'     28   40 ║ Alt-Delete    A3  163 ║ Ctrl- K Up [8] 8D  141 ║
  729.     ║ Alt-`     29   41 ║ Alt-End       9F  159 ║ Ctrl- K Cn [5] 8F  143 ║
  730.     ║ Alt-\     2B   43 ║ Alt-Home      97  151 ║ Ctrl- K Dw [2] 91  145 ║
  731.     ║ Alt-,     33   51 ║ Alt-Insert    A2  162 ║ Ctrl- K Ins[0] 92  146 ║
  732.     ║ Alt-.     34   52 ║ Alt-PageUp    99  153 ║ Ctrl- K Del[.] 93  147 ║
  733.     ║ Alt-/     35   53 ║ Alt-PageDown  A1  161 ║                        ║
  734.     ╙───────────────────╨───────────────────────╨────────────────────────╜
  735.       K indicates a key on the numeric keypad (when not in NumLock mode)
  736.  
  737. ==============================================================================
  738.  
  739. For any ideas, requests, corrections ("There is always one more bug") or
  740. whatever, contant the author at:
  741.  
  742. Fido:
  743.  
  744. Inbar Raz, 2:401/100.1
  745. Inbar Raz, 2:403/100.42
  746.  
  747. Internet:
  748.  
  749. nyvirus@weizmann.weizmann.ac.il
  750. Inbar.Raz@p1.f100.n401.z2.fidonet.org
  751. Inbar.Raz@p42.f100.n403.z2.fidonet.org
  752.  
  753. Snailmail:
  754.  
  755. Inbar Raz
  756. 5 Hanegev Street
  757. Yavne 70600
  758.