
Notes on KEYBTST.BS2 program
============================

[From: cj@hth.com (Christer Johansson)

The KEYBTST.BS2 program is a simple program for Parallax BASIC Stamp II wich
is able to send scancodes to the AT keyboard port on a PC. However the program
does lack in features and was just a hack to get more understanding of the 
keyboard interface and to see if it was possible to use a BASIC Stamp II to do
this, and it was !

First of all since the BASIC Stamp II in this design can't receive any info-
rmation from the motherboard you have to boot your PC with your regular 
keyboard inserted and then switch. You also have to manually convert the scan 
hex code and calculate the parity bit for each character to use and below is
a simple example for character "a".

The scan code for "a" is 1C and the bit pattern is 00011100 to use that in
the program you must rotate it so the LSB bit is first: 

 MSB    LSB 
  |-DATA-|
  00011100

Rotated:

 LSB    MSB 
  |-DATA-|
  00111000

Then calculate and add the odd parity bit, and 1C contains 3 ones so the odd
parity bit should be a 0.

      Paritybit
          |
  001110000

Then to form the eleven bits you have to add one start bit (logic 0) and 
one stopbit (logic 1):

 Startbit
  |
  00011100001
            |
         Stopbit

The last thing you have to do is to invert all the bits and place them in
the char variable in the BASIC Stamp II program.

  00011100001

Inverted

  11100011110  

Example:

'     s--DATA--PS (s=startbit, DATA=LSB First, P=paritybit, S=stopbit)
char=%11100011110 '/a

I will eventually enhance the program to do all this automaticly but if some-
one does it before me please let me know so I could make it available to all
in our file library.

The following crude diagram attempts to illustrate the basic circuit:



          +--------------------+--------+---------------------o Kbd +5V   (Pin 5)
          |                    |        |
          |   0.1uF            /        /
          +----||---+          \ 2.2K   \ 2.2K
          |         |          /        /
          |        ---         |        |
          |        Gnd         +------------------------------o Kbd DATA  (Pin 2) 
          |                    |        |
          |                    |        +---------------------o Kbd CLOCK (Pin 1)
   +-------------+           e |        |
   |     Vdd     |    10K    |/ BC547   |                 +---o Kbd GND   (Pin 4)
   |          P0 |---/\/\/---|b (NPN)   |                 |
   |   BS2-IC    |           |\         |                ---
   |             |           c |        |                Gnd
   |             |            ---       |
   |             |            Gnd       |
   |             |           e _________/  
   |             |    10K    |/ BC547
   |          P1 |---/\/\/---|b (NPN)         +5V
   |             |           |\                o
   |             |           c |               |
   |             |            ---              /
   |             |            Gnd              \ 10K  
   |             |                             /       Button 0 
   |             |                             |      ---
   |          P2 |-----------------------------+------o o---+
   |          P3 |-                                         |
   |          P4 |-                                        ---
   |          P5 |-    (P3-P7 same as P2)                  Gnd
   |          P6 |-
   |          P7 |-
   |     Gnd     |
   +-------------+
          |
         ---
         Gnd


/Christer

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 * High Tech Horizon  -  Christer Johansson  -  E-mail: cj@hth.com * 
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 * Vi saljer Parallax, Inc. BASIC Stamp's produkter i Skandinavien * 
     >>  World Wide Web On-Line Catalog - http://www.hth.com  <<     
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

PS: Please read below to get more information about the keyboard protocol.

-=============================================================================-

How does the keyboard interface work?
=====================================

[From: jhallen@world.std.com (Joseph H Allen)] 
 
The IBM keyboard is connected to the computer through a serial interface 
similar to a COM port.  When you press a key, the keyboard sends a 
"scan-code" for that key to the computer.  When you release the key, the 
keyboard sends a release code to the computer.  If you hold down one key and 
press and release another key, the computer will receive the scan-code for 
the held key and a scan and release code for the other key.  Since the 
release code for the held key was not received, the computer knows that the 
held key was down while the other key was pressed.  In this way, the 
computer can handle the Shift, Alt and Ctrl keys (and any key could work 
like a shift key, since all keys work alike).  The ROM BIOS in the computer 
buffers the data from the keyboard, translates the scan-codes to ASCII and 
handles the operation of the shift and lock keys.  The keyboard itself also 
has a small buffer and there is hardware flow-control for preventing 
overruns.  All of this seems simple and quite elegant, but by the time we 
get to the AT keyboard the details of the implementation are so complicated 
as to ruin an otherwise ideal keyboard. 
 
The XT keyboard's interface almost captures the above elegance (indeed it is 
the only elegant thing about the XT, IMHO).  The interface uses a 5-pin DIN 
connector with these signal assignments: 
 
     1     CLK/CTS (open-collector) 
     2     RxD 
     3     RESET 
     4     GND 
     5     +5V 
 
When the keyboard has a byte to send to the computer, it shifts 9 bits out 
to the data line (RxD) with nine clock pulses on the CLK line.  The data 
format is 1 start bit, followed by 8 data bits.  The baud rate is roughly 
2000 bits per second and is not precisely defined.  Once a byte is 
completely transmitted, the computer holds the Clear-To-Send (CTS) line low 
to prevent the keyboard from sending any more bytes until the keyboard 
interrupt handler reads the current one.  Usually a simple 9-bit clearable 
TTL shift register is used to receive keyboard data.  The 9th bit of the 
shift register is used to drive an open-collector buffer connected to the 
CTS line.  When the start-bit gets all of the way through the shift 
register, it holds the CTS line low itself.  Once the CPU reads the 
assembled byte, it has only to clear the shift register to release the CTS 
line and allow another byte to be received.  Three TTL chips or a single PAL 
can implement an entire XT keyboard interface. 
 
The data bytes which the XT sends are also simple.  Codes 0-127 are the 
scan-codes.  Codes 128-255 are the release codes- they're the same as the 
scan codes, but with the high bit set.  The XT keyboard has only 84 keys, so 
not all of the scan-codes are used. 
 
The only problems with the XT keyboard are the lock-status lights 
(Caps-lock, Scroll-lock and Num-lock) and the key repeat mechanism.  The 
lock-status lights can get out of sync with the computer's idea of which 
lock keys are activated, but this only happens if someone resets the 
keyboard by unplugging it temporarily.  When you hold a key down long 
enough, the keyboard starts repeating the scan-code for that key.  The 
release code is still only transmitted once, when the key is released.  The 
problem here is that the delay to the start of the repeats and the repeat 
rate were made too slow.  Of course, the keyboard really doesn't have to 
handle repeat at all, since the computer knows when keys are pressed and 
released and has a timer itself.  Old XT keyboard TSRs allowed you to adjust 
the repeat delay and rate by duplicating the key repeat mechanism in the 
computer. 
 
Once IBM found that it had a nearly perfect keyboard it, of course, decided 
that it had to be almost completely redesigned for the AT.  The keyboard 
didn't have to be redesigned- there were enough extra scan-codes for the 
AT's 101 key keyboard and the repeat mechanism could simply have been moved 
to the BIOS.  But no, they had to redesign everything.  Sigh. 
 
The AT uses a 5-pin DIN and the PS/2 uses a smaller connector with the same 
signals: 
 
     1     CLK/CTS (open-collector) 
     2     RxD/TxD/RTS (open-collector) 
     3     Not connected or Reset 
     4     GND 
     5     +5V 
 
Now the interface is bi-directional.  When the computer wants to send a byte 
to the keyboard, it asserts RTS and releases CTS.  If you're lucky, the 
keyboard isn't deciding to transmit at the same time and it responds by 
giving 10 clock pulses (at about 10000 baud) on the CLK line.  The computer 
shifts a frame out on TxD on rising clock edges.  The frame format is now 1 
start bit, 8 data bits and 1 odd parity bit.  The keyboard takes RTS being 
held low as the first start bit, and the first data bit should be sent on 
TxD after the first clock edge is received.  Yes, now you need a full UART 
for the keyboard interface since you have to both transmit and receive and 
generate and check parity (but it's still not RS-232- that would have been 
too logical).  Why do you need parity checking on a three foot long keyboard 
cable?  Because collisions can occur since the lines are so overloaded with 
signals with different meanings and parity provides the means for detecting 
these collisions. 
 
The AT documentation says that pin 3 is "reserved", so the keyboard has to 
provide its own reset.  But on the original AT, pin 3 was still Reset and 
IBM's own keyboards at that time needed Reset (original AT keyboards won't 
work on some old clones because of this).  Don't ask me... I don't 
understand why they did this. 
 
The protocol on the keyboard interface is now much more complicated.  These 
bytes are defined: 
  
Commands 
 
  ED <byte>                 Set leds depending on byte 
                              bit 0 is Scroll lock 
                              bit 1 is Num lock 
                              bit 2 is Caps lock 
 
  EE                        Echo EE (for testing?) 
  F0 <mode>                 Select mode 1, 2 or 3 
  F2                        Send keyboard I.D. 
  F3 <byte>                 Set repeat delay and rate 
                              byte is: 0ddbbaaa 
                              delay is (dd+1)*250 msec 
                              rate is (8+aaa)*2^bb*4 msec 
 
  F4                        Clear buffer 
  F5                        Restore default settings and wait for enable 
  F6                        Restore default settings 
  FA	                    Acknowledge 
  FE                        Error- please retransmit 
  FF                        Reset keyboard 
 
Status returns 
 
  00                        Buffer overflow 
  AA                        Self-test passed 
  F0 <scan-code>            Release code 
  FA                        Acknowledge last command 
  FD                        Self-test failed 
  FC                        Self-test failed 
  FE                        Last command in error; re-send 
  E0 scan/release code      Extended keys in Mode 2 
 
The computer and keyboard must acknowledge each command and key code with 
either FA if there was no error, or FE if the last command/key-code should 
be re-sent.  There are three modes of operation for the keyboard, depending 
on which scan code assignments you want (these can often be set by a switch 
on the back of keyboard, except that if mode 1 is selected from the switch, 
the protocol is eliminated an the keyboard works exactly like an original XT 
keyboard- newer keyboards only support modes 1 and 3).  In mode 1, the 
keyboard gives XT scan-codes.  The keyboard handles the cursor keypad (which 
didn't exist on the XT) by simulating pressing or releasing a shift key 
(depending on whether shift or num-lock are pressed) and sending codes from 
the numeric keypad.  Mode 2 works like mode 1, except that when the keyboard 
does the weird stuff with the numeric keypad it prefixes everything with E0 
and the release codes are the scan-codes prefixed with F0.  In mode 3, each 
key gets a unique code and the release codes work as in mode 2: the release 
are the scan-codes prefixed by F0. 
 
When the AT keyboard is first reset it's supposed to send an AA if its 
self-test passed or FD or FC if it failed.  But before it does this, it 
sends a continual stream of AAs with the parity incorrect.  Once the 
computer sends an FE to indicate that there is a parity error, the keyboard 
stops sending bad AAs and sends a correct AA or an FD or FC.  This sounds 
like someone made a quick fix in the keyboard firmware for mis-matched reset 
timing (the keyboard always finishes resetting before the computer so the 
computer could miss the AA/FD/FC). 

-=============================================================================-

AT keyboard interface
=====================

[From: mschultz@wctc.net (Mark Schultz)]

The AT keyboard transmission protocol is clocked serial (with the keyboard as 
clock source or 'master'), 11 bits in length.  One start bit (logic 0), 8 
data bits (LSB first), one odd parity bit and a stop bit (logic 1).  The 
clock rate is approx. 10-20 KHz and can vary from keyboard to keyboard.  The 
keyboard data format resembles 8-odd-1 asynchronous transmission format.  
However, the bit rate from keyboard to keyboard can vary significantly so it 
is necessary to use a clocked serial interface (SPI in Motorola parlance) or 
a async (SCI) interface with a 1x receive clock input.  For MPUs that cannot 
accomodate this transmission protocol directly using a hardware subsystem 
(SPI or SCI) I have found it useful to tie the CLOCK input to a IRQ (external 
interrupt) line and read the data bits one-by-one on the falling edge of each 
clock pulse.

Both CLOCK and DATA lines are implemented on the keyboard end as 
open-collector outputs with pull-up resistors to +5V.  It is possible (and 
sometimes necessary) for the host system to actively pull these lines LOW.

Keyboard to system protocol:

The keyboard will transmit keystroke data to the host system as soon as a key 
is pressed (or released) if both the DATA and CLOCK lines are HIGH.  If the 
CLOCK line is LOW, the keyboard will buffer keystroke data until the CLOCK 
line goes HIGH again (the clock line acts as a -RTS signal).  If the DATA 
line is LOW, the keyboard prepares to accept a 11-bit control message from 
the host (see below).

If the CLOCK line is pulled LOW by the host while the keyboard is 
transmitting data (up to the 10th bit) for at least 60 uS, the keyboard will 
suspend transmission and prepare to receive a system message.  The keyboard 
will eventually re-transmit the data byte that was interrupted, unless the 
keyboard was successful in transmitting the 10th bit, in which case the 
keyboard considers the data byte as successfully sent.  It is generally a bad 
idea to interrupt keyboard transfers this way.

System to keyboard protocol:

AT-style keyboards are capable of accepting control messages from the system 
in addition to sending scan code information to the host.  In this way, the 
status LEDs may be controlled and the keyboard typematic parameters (repeat 
delay and rate) can be set.  Command transmission to the keyboard is 
initiated by bringing the keyboard CLOCK line LOW for at least 60 uS.  After 
the 60 uS delay, the DATA line should be brought LOW and the CLOCK line 
released (HIGH).  Make sure to bring the DATA line LOW before releasing 
the CLOCK line.  Some time later (up to 10 milliseconds) the keyboard will 
start to generate clock signals.  At each HIGH to LOW clock transition the 
keyboard will clock in a new bit.  The data stream from the system (on the 
DATA line) should conform to the serial protocol described above.

After the parity bit has been clocked out, the host should release (bring 
HIGH) the DATA line and wait for the keyboard to send another CLOCK pulse 
(this will be the 10th HIGH to LOW transition, not counting the initial H->L 
transition generated by the host).  The KEYBOARD will then bring the DATA 
line LOW sometime before the 11th HIGH to LOW transition of the CLOCK line to 
acknowledge reception of the command byte.

If the DATA line is not released (allowed to go HIGH) after the 10th CLOCK 
bit then the keyboard will continue to issue clock pulses until the DATA line 
is released.  In this event, the keyboard will (after some delay) pull the 
DATA line LOW and transmit a RESEND status byte (FEh).

Commands - Host to keyboard
(all numeric values are in HEX)

I will present these command bytes briefly here.  I will be happy to expand 
on their function and purpose if asked.  This started out as a simple reply 
to a question and has almost turned into a FAQ <g>.  Depending on demand, I 
just might expand this impromptu reply into a full-fledged FAQ.

F5 - Default Disable.  Resets keyboard, returns ACK and suspends
     scanning, waiting for another command.  Does not affect the
     indicator LEDs.
EE - Echo.  Responds with ECHO code (EE).
F4 - Enable.  Clears output buffer, enabled kbd, returns ACK.
F2 - Read ID.  Responds with ACK and two ID bytes (83,AB).  Resumes
     scanning even if previously disabled.
FE - Resend.  Retransmit last sent scan code.
FF - Reset.  Resets keyboard CPU, starts power-on test.  Responds with
     power-on-test byte.
F0 - Select scan code set.  Responds with ACK, then waits for host to
     send a byte (01,02 or 03) specifying the scan code set to use.
     If 00 is sent, keyboard responds with ACK followed by the scan code
     set in use.
F7 - 'Set all keys typematic'
F8 - 'Set all keys make/break'
F9 - 'Set all keys make'
FA - 'Set all keys typematic/make/break'
     I am not certain what these commands do.  I suspect they control the
     way the keyboard transmits scan codes.  All of the above commands
     respond with an ACK code.
F6 - Set default.  Responds as the 'Default Disable' command, but does
     not inhibit scanning.  Does not affect LED indicators.
FB - 'Set key type typematic'
FC - 'Set key type make/break'
FD - 'Set key type make'
     Again, I'm not sure what these do.  Unlike the 'set all' commands,
     these commands presumably act on single keys.  The keyboard sends
     the ACK code, then waits for keyboard scan code(s).  ACK is set
     after each scan code is received.  Keyboard remains in the 'set
     type' state until a new command is received.
ED - Set/reset status indicators.  This command allows you to control
     the status LEDs on the keyboard.  Keyboard responds with ACK and
     waits for a option byte, bitmapped as follows: b0-Scrollock,
     b1-Numlock, b2-Capslock, b3..7=0.  A '1' bit turns the indicator
     ON.
F3 - Set autorepeat rate/delay.  Responds with ACK, then waits for an
     option byte that specifies the autorepeat delay and rate,
     bitmapped as follows: b7-unused. b6..5-Repeat delay (00=250 mS,
     11=1000mS). b4..0-Repeat rate (00000=30x/sec, 11111=2x/sec).
     Keyboard responds with ACK after reception of the option byte.

Keyboard response codes:

FA - ACK (acknowledge), response to most commands.
AA - Poweron test successful.
EE - Echo.  Response to the ECHO command (EE).
00 or FF - Key detection error, also indicates buffer overflow.
FE - Resend.  Sent in response to the receipt of a invalid command code
     or code with a bad parity bit.

The keyboard can, of course, send key scan make/break codes as well as
numeric responses to certain commands as outlined above.

-=============================================================================-

Scan codes
==========

-----------------------------------------------------------------------------

           *** STANDARD 101-KEY KEYBOARD SCAN CODE SEQUENCES ***

                          ** Main Keyboard **
----------------------------------------------------------------------------
  Key         Make Code                       Break Code         Notes
----------------------------------------------------------------------------
  `              #0E                           #F0 #0E
  1              #16                           #F0 #16
  2              #1E                           #F0 #1E
  3              #26                           #F0 #26
  4              #25                           #F0 #25
  5              #2E                           #F0 #2E
  6              #36                           #F0 #36
  7              #3D                           #F0 #3D
  8              #3E                           #F0 #3E
  9              #46                           #F0 #46
  0              #45                           #F0 #45
  -              #4E                           #F0 #4E
  =              #55                           #F0 #55
  Backspace      #66                           #F0 #66

  Tab            #0D                           #F0 #0D
  Q              #15                           #F0 #15
  W              #1D                           #F0 #1D
  E              #24                           #F0 #24
  R              #2D                           #F0 #2D
  T              #2C                           #F0 #2C
  Y              #35                           #F0 #35
  U              #3C                           #F0 #3C
  I              #43                           #F0 #43
  O              #44                           #F0 #44
  P              #4D                           #F0 #4D
  [              #54                           #F0 #54
  ]              #5B                           #F0 #5B
  \              #5D                           #F0 #5D

  Caps Lock      #58                           #F0 #58
  A              #1C                           #F0 #1C
  S              #1B                           #F0 #1B
  D              #23                           #F0 #23
  F              #2B                           #F0 #2B
  G              #34                           #F0 #34
  H              #33                           #F0 #33
  J              #3B                           #F0 #3B
  K              #42                           #F0 #42
  L              #4B                           #F0 #4B
  ;              #4C                           #F0 #4C
  '              #52                           #F0 #52
  Enter          #5A                           #F0 #5A

  Left Shift     #12                           #F0 #12
  Z              #1A                           #F0 #1A
  X              #22                           #F0 #22
  C              #21                           #F0 #21
  V              #2A                           #F0 #2A
  B              #32                           #F0 #32
  N              #31                           #F0 #31
  M              #3A                           #F0 #3A
  ,              #41                           #F0 #41
  .              #49                           #F0 #49
  /              #4A                           #F0 #4A
  Right Shift    #59                           #F0 #59

  Left Ctrl      #14                           #F0 #14
  Left Alt       #11                           #F0 #11
  Space          #29                           #F0 #29
  Right Alt      #E0 #11                       #E0 #F0 #11
  Right Ctrl     #E0 #14                       #E0 #F0 #14
  ESC            #76                           #F0 #76
----------------------------------------------------------------------------


                          ** Function Keys **
----------------------------------------------------------------------------
  Key         Make Code                       Break Code        Notes
----------------------------------------------------------------------------
  F1             #05                           #F0 #05
  F2             #06                           #F0 #06
  F3             #04                           #F0 #04
  F4             #0C                           #F0 #0C
  F5             #03                           #F0 #03
  F6             #0B                           #F0 #0B
  F7             #83                           #F0 #83
  F8             #0A                           #F0 #0A
  F9             #01                           #F0 #01
  F10            #09                           #F0 #09
  F11            #78                           #F0 #78
  F12            #07                           #F0 #07
----------------------------------------------------------------------------


                            ** Numeric Pad **
----------------------------------------------------------------------------
  Key         Make Code                       Break Code         Notes
----------------------------------------------------------------------------
  NumLok         #77                           #F0 #77
  KP-            #7B                           #F0 #7B
  KP/            #E0 #4A                       #E0 #F0 #4A     Notes 1, 2
  KP.            #71                           #F0 #71
  KP*            #7C                           #F0 #7C
  KP+            #79                           #F0 #79
  KPEnter        #E0 #5A                       #E0 #F0 #5A

  KP0            #70                           #F0 #70
  KP1            #69                           #F0 #69
  KP2            #72                           #F0 #72
  KP3            #7A                           #F0 #7A
  KP4            #6B                           #F0 #6B
  KP5            #73                           #F0 #73
  KP6            #74                           #F0 #74
  KP7            #6C                           #F0 #6C
  KP8            #75                           #F0 #75
  KP9            #7D                           #F0 #7D
----------------------------------------------------------------------------


                           ** Auxiliary Pads **
----------------------------------------------------------------------------
  Key           Make Code                      Break Code        Notes
----------------------------------------------------------------------------
  Ins            #E0 #70                       #E0 #F0 #70    Notes 1, 2, 3
  Home           #E0 #6C                       #E0 #F0 #6C    Notes 1, 2, 3
  Pg Up          #E0 #7D                       #E0 #F0 #7D    Notes 1, 2, 3
  Del            #E0 #71                       #E0 #F0 #71    Notes 1, 2, 3
  End            #E0 #69                       #E0 #F0 #69    Notes 1, 2, 3
  Pg Dn          #E0 #7A                       #E0 #F0 #7A    Notes 1, 2, 3

  Up Arrow       #E0 #75                       #E0 #F0 #75    Notes 1, 2, 3
  Left Arrow     #E0 #6B                       #E0 #F0 #6B    Notes 1, 2, 3
  Right Arrow    #E0 #74                       #E0 #F0 #74    Notes 1, 2, 3
  Down Arrow     #E0 #72                       #E0 #F0 #72    Notes 1, 2, 3

  PrtSc          #E0 #12 #E0 #7C               #E0 #F0 #7C #E0 #F0 #12
  Ctl-PrtSc      #E0 #7C                       #E0 #F0 #7C
  Alt-PrtSc      #84                           #E0 #84
  ScrLk          #7E                           #F0 #7E
  Pause          #E1 #14 #77 #E1 #F0 #14 #77   None
  Ctrl-Break     #E0 #7E #E0 #F0 #7E           None

----------------------------------------------------------------------------


                                ** Notes **
----------------------------------------------------------------------------

  Note 1

     If Left Shift is Down:

        Make Sequence - #E0 #F0 #12 #** #**
       Break Sequence _ #** #** #** #E0 #12

  Note 2

    If Right Shift is Down:

        Make Sequence - #E0 #F0 #59 #** #**
       Break Sequence - #** #** #** #E0 #59

  Note 3

    If Num Lock is On:

        Make Sequence - #E0 #12 #** #**
       Break Sequence - #** #** #** #E0 #F0 #12

  The '#** #**' entry represents the Make Code and the '#** #** #**' entry
  represents the  Break Code specified for the character in the main chart
  and should be replaced with those sequences in actual use.

-----------------------------------------------------------------------------
