Interfacing the AT Keyboard
-By Adam C


*NOTE:  IF YOU ARE NOT FAMILIAR WITH THE PS/2 PROTOCOL, I RECOMMEND YOU READ MY PS/2 PAGE BEFORE CONTINUING.

Table of Contents
Introduction

General Description

Scan Codes
Make Codes
Break Codes
Typematic Repeat
LEDs
More on Scan Codes
Scan Code Set 1
Scan Code Set 2
Scan Code Set 3
Commands (Host to Keyboard)
Commands (Keyboard to Host)
Other Sources


 



Introduction:

For many projects, wiring a few push-button switches to your microcontroller is enough for input.  However, projects can often be much more demanding and therefore require a more eloquent solution--that's where the keyboard comes in.  AT keyboards require very few to no external components, they're inexpensive (you can find free-after-rebate keyboards at most larger computer stores), and they require a relatively small amount of program space in your microcontroller.

So how can you identify an AT keyboard?  Well, if the keyboard has more than 83 keys,  its connector (on the computer end of the cable) is round, and it does not have an Apple logo on it, it's an AT keyboard.  If it has an Apple logo on it, it's an ADB (Apple Desktop Bus) keyboard;  if the connector that plugs into the computer is rectangular, it's a USB keyboard;  If it's not an ADB keyboard and it has 83 keys, it's probably an XT keyboard.  The AT, XT, ADB, and USB keyboards all operate very differently and the information in this document applies only to the AT keyboard.  I should also mention that AT keyboards are the most popular type of keyboard.  If your computer is running any version of windows, its most likely using an AT keyboard.

Although I'm sure you can apply this information to other areas, I wrote this page with keyboard-to-microcontroller interfacing and keyboard emulation in mind.  All examples are written in Microchip's MPASM for the PIC16F84 microcontroller.  Keep in mind that if you want to use a different microcontroller, MPASM consists of a very basic instruction set, so you should be able to port the code for use with other microcontrollers fairly easily (assuming you're familiar with MPASM.)

This page tells you exactly what the keyboard does (what information is sent when) but it does not tell you how that information is sent (what electrical signals need to be applied to communicate with the keyboard or computer.)  For information on this, I recommend you check out my PS/2 page which was written with keyboard and mouse interfacing in mind.  Many examples on this page assume you've already read the page on the PS/2 protocol.

I've tried to include a lot of examples to make major points.  However, if you're still confused after reading the examples or if you find any errors on this page, please send me an email and I'll try to clearify whatever it is you're having trouble understanding.
 



General Description:

AT keyboards consist of a large matrix of keys, all of which are monitored by an on-board processor.  The specific processor varies from keyboard-to-keyboard (common chips include the 8048, 8049, 6868 and the 6805) but they all basically do the same thing:  Monitor which key(s) is/are being pressed/released and send the appropriate data to the host.  This processor takes care of all the debouncing and buffers any data to its 16-byte buffer, if needed.  Your motherboard contains an 8042/compatible microcontroller that is in charge of decoding all of the data received from the keyboard and informing your computer of what's going on (via address 60h and IRQ1.)  All communication between the host and the keyboard uses the PS/2 protocol.  If you want information on this protocol (which you will need to know if you want to interface a keyboard,) check out my PS/2 page.
 



Scan Codes:

Your keyboard's processor spends most of its time scanning, or monitoring, the matrix of keys.  If it finds that any key is being pressed, released, or held down, the keyboard will send a packet of information known as a scan code to your computer.  There are two different types of scan codes:  make codes and break codes.  A make code is sent to your computer when a key is pressed or held down.  A break code is sent to your computer when a key is released.  Every key is assigned its own unique make code and break code so that the computer can determine exactly what happened to which key simply by looking at a single scan code sent from the keyboard.  The set of all make and break codes of every key comprises a scan code set. There are three standard scan code sets, numbered 1, 2, and 3.  Scan code set 2 is the default for all AT keyboards and all scan codes discussed in this document are from set two unless specified otherwise.  Most scan codes are 1-4 bytes wide and are usually written in hexadecimal.  I'll refer to a hex number by post-fixing it with an "h".  Also, when writing scan codes that are more than one byte wide, each byte is usually separated by a comma.  The comma has no meaning and is there only to make the number easier to read (similar to how we use commas to separate groups of three digits when writing decimal numbers.)

So how do you figure out what the make code and break code is for each key?  Unfortunately, there's no simple formula for doing this.  If you want to find a out which scan codes are assigned to a specific key, you'll have to look them up in a table.

<Click here for the tables of scan codes used by your keyboard>



Make Codes:

Whenever any key on a keyboard is pressed, that key's make code is sent to the computer.  Keep in mind that a make code only represents a key on a keyboard--it does not represent the character printed on that key.  This means that there is no relationship between a make code and a character.  It's up to your software to translate the scancodes to characters or commands.  If you want to associate a make code with a character, you'll have to implement a look-up table in your program.

Example:

Let's say you just pressed the "A" key on your keyboard.  How does the keyboard notify the computer that this has happened?  Answer:  It does this by sending the "A" key's make code to the computer.  From looking at my scan code tables, you'll see that the make code for the "A" key is 1Ch, so the keyboard sends 1Ch to the computer whenever you press the "A" key.


Although most make codes are only one-byte wide, there are a handfull of extended keys whose make codes are two or four bytes wide.  These make codes can be identified by the fact that the first byte is E0h.

Example:

The "A" key's make code is 1Ch, the "7" key's is 3Dh, and the "Delete" key's is E0,71h.  Which of these three keys is an extended key?  Answer:  The "Delete" key is an extended key.  The two clues for that answer are the make code for the "Delete" key is more than one byte wide and it begins with "E0" (only extended keys' scan codes begin with E0.)




Break Codes:

Just as a make code is sent to the computer whenever a key is pressed, a break code is sent to the computer whenever a key is released.  In addition to every key having its own unique make code, they all have their own unique break code.  Fortunately, however, you won't always have to use tables to figure out a key's break code--certain relationships do exist between make codes and break codes (I'll talk about these relationships later in this document.)

Whenever you press and release a key on your keyboard, that key's make code is sent to the computer, followed by that key's break code.

Example:

How would you emulate the press-and-release of the "A" key?  Answer:  First, you must make the computer think the "A" key has been pressed.  You do this by sending the make code for that key which, according to my scan code tables, is 1Ch.  After you've sent 1Ch to the computer, you need to tell the computer that the "A" key has been released.  This is done by sending the break code for the "A" key which turns out to be F0,1Ch.  So in order to make the letter "a" appear in your word processor, you need to send 1C,F0,1Ch to your computer's keyboard port.

This is how the computer distinguishes between lower-case and upper-case letters and primary and secondary charactors:  the computer takes a look at any make codes that occur between the time the make code and the break code for the "Shift" key are received.

Example:

What should you send to the computer's keyboard port to make the upper-case "A" appear on your screen?  Answer:  What you're trying to do is emulate the "A" key being pressed while the "Shift" key is held down which occurs in the following steps:
  1. The "Shift" key is pressed
  2. The "A" key is pressed
  3. The "A" key is released
  4. The "Shift" key is released

Since a key's make code is sent when that key is pressed, and its break code is sent when it's released, the following scan codes will be sent to the computer:

  1. The make code for the "Shift" key is sent to the computer
  2. The make code for the "A" key is sent to the computer
  3. The break code for the "A" key is sent to the computer
  4. The break code for the "Shift" key is sent to the computer

The make code for the left "Shift" key is 12h, the make code for the "A" key is 1Ch, the break code for the "A" key is F0,1Ch, and the break code for the left "Shift" key is F0,12h.  Putting all of these together, the following data should be sent to the computer:  12,1C,F0,1C,F0,12h.



Typematic Repeat:

If you press a key, its make code is sent to the computer.  When you press and hold down a key, that key becomes typematic, which means the keyboard will keep sending that key's make code until the key is released or another key is pressed.  To verify this, open a text editor and hold down the "A" key.  When you first press the key, the charater "a" immediately appears on your screen.  After a short delay, another "a" will appear followed by a whole stream of "a"s until you release the "A" key.  There are two important parameters here:  the typematic delay, which is the short delay between the first and second "a", and the typematic rate which is how many characters per second will appear on your screen after the typematic delay.  The typematic delay can range from 0.25 seconds to 1.00 second and the typematic rate can range from 2.0 cps (characters per second) to 30.0 cps.

One thing I should stress here is that the computer DOES NOT process the typematic rate or delay--it's all done within the keyboard itself.  To set the typematic rate, for example, you must issue a command to the keyboard specifying how many times per second it should transmit a key's make code if that key is being held down.  (I'll get to that command later in this document.)
 



LEDs:

Beleive it or not, your keyboard does not decide when the NUM LOCK, CAPS LOCK, and SCROLL LOCK light-emitting diodes are to be turned on/off.  Rather, it's up to your computer to tell your keyboard to turn on/off these LEDs.  So when you press the "Caps Lock" key, your keyboard just sends the make key for "Caps Lock" to the computer--it does not, at this time, turn on the Caps Lock LED.  In order to turn on the Caps Lock LED, your computer must send a command to your keyboard to turn it on.  In other words, the LEDs on your keyboard and their cooresponding keys are completely independent of each other.  Just because the "Caps Lock" key is pressed does not mean the CAPS LOCK LED will be lit--it depends on whether or not your computer wants to turn that LED on (and it usually does.)  One way to see if your computer is locked up or just slow is by pressing the "Caps Lock" key and seeing if the cooresponding LED changes state.  If it does, your computer is still able to operate on data; if it does not, your computer is locked up tighter than a drum.
 



More on Scan Codes:

There are many books and many sites on the internet that contain tables of scan codes.  Most of these tables, however, do not match.  This is because of where the authors gathered their data.  If you read the output of your computer's keyboard controller (via address 60h,) you will be reading scan codes that may have been modified by the BIOS. Therefor, what you read may not be what the keyboard is actually saying.  In order to interface the keyboard, we want the actual output of the keyboard so I connected an AT keyboard and a LCD display to a microcontroller and recorded the output when each key was pressed and released in scan code sets 1-3.  The result is the three scan code tables you'll find on this site.
 



Scan Code Set 1:

For compatibility with older IBM PS/2 computers, all AT keyboards are able to use scan code set 1 (these are the scan codes used by the XT keyboard.)  Most newer computers never use this set.  You set a keyboard to scan code set 1 by using the F0h (set scan code set) command (all examples in this section will assume that this command has been issued and the keyboard is set to scan code set 1.)  By default, all keys in scan code set 1 except "Pause/break" are set to typematic/make/break.  The "Pause/break" key has a make code only--it cannot be typematic and it does not have a break code.

The main reason you should use this scan code set instead of the default set 2 is that the make-break code relationships in set 1 are much more simple and this can be reflected in much shorter algorithms.

In set 1, there are two ways of finding a key's break code from its make code:

  1. (break code byte) = (make code byte--not including E0h) + 80h
  2. (break code byte) = (make code byte--not including E0h) OR 10000000b

Example:

The set 1 make code for the "A" key is 1Eh.  What is the set 1 break code for the "A" key?  Answer:  Using method 1, we can calculate the break code by adding 80h to the make code:  (break code) = 1Eh + 80h = 9Eh.  Alternatively, we could use method 2 by converting the make code to binary and setting the most significant bit (setting the most significant bit is the same as OR-ing it with 10000000b.)  So 1Eh = 00011110b and setting the most significant bit, we get 10011110b = 9Eh.

Example:

The set 1 make code for the "Insert" key is E0,52h.  What is that key's set 1 break code?  Answer:  Using method 1, we find the key's break code by adding 80h to every byte of its make code EXCEPT E0h. Doing this, we get:  (break code) = (E0h + 00h), (52h + 80h) = E0,D2h.  We could also use method two, but it's just a longer path to the same result.  Generally, we apply method two to finding out whether a scan code is a make code or a break code.

Example:

You're keyboard, which has been set to scan code set 1, has transmitted the scan code AEh.  From that scan code, determine if a key has been pressed or if it has been released.  Answer:  We'll apply method 2 to find this answer.  First, we convert AEh to binary:  AEh = 10101110b.  We then test the most significant bit;  if it's a 0, then we are looking at a make code otherwise, if the most significant bit is a 1, the byte is a break code.  In this case, the most significant bit is a 1, so this is a break code.

Using method two (testing MSb) can really save our microcontroller a lot of time and program space.  This is especially true for microcontrollers like the PIC which have bit test-skip instructions that can determine whether a scan code is make or break with just one instruction (btfss or btfsc.)  On the other hand, the btfss and btfsc instructions can only operate on general RAM registers--they cannot operate on the w register.  If we were to use method 1, we would require an extra step (we would have to subtract 80h, then test the carry bit in the status register,) but we wouldn't have to use any RAM--all operations could be done on w.



Scan Code Set 2:

Scan code set 2 is more messy than sets 1 and 3.  Unfortunately, it's the default scan code set, and if we want to emulate a keyboard, we have to use set 2 scan codes.  Also, if we want our microcontroller to read from a keyboard, we will require extra components and I/O pins to be able to tell the keyboard to change to a different scan code set.

To find a key's set 2 break code from its make code...

This means that for the majority of the keys, you simply insert an F0h before the key's make code to get its break code (and the algorithm for finding extended keys' break code isn't much more difficult.)

Example:

The set 2 make code for the "A" key is 1Ch.  What is that key's set 2 break code?  Answer:  Prefixing each byte (except any occurrances of E0h) with F0h, we get F0,1Ch for the break code.

Example:

The set 2 make code for the "Delete" key is E0,71h.  What is that key's break code?  Answer:  Again, we simply prefix each byte EXCEPT E0h with F0h.  Doing this, we get: E0,F0,71h.

Example:

The make code for the "Print Screen" key is E1,14,77,E1,F0,14,F0,77h. What is that key's break code?  Answer: remember, the "Print Screen" key does not have a set 2 break code.  However, its make code is quite interesting in that it can be broken up into E1,14,77h and E1,F0,14,F0,77h which looks somewhat like a make code immediately followed by a break code (except in this case, all keys except E1h--rather than E0h--are prefixed with F0h.



Scan Code Set 3:

I consider scan code set 3 easiest to work with because all keys are treated the same and the make-break code relationship is extremely simple.  Before I go on, though, I should mention that by default, only certain keys are make/break/typematic.  Most keys are only make (i.e, they only have a make code.)  To remedy this, you'll have to send the "set all keys typematic/make/break" command after changing to set 3.  Once you do this, all keys (including the Pause/Break key) will have make codes, break codes, and they can be typematic.

The relationship between set 3 make and break codes is very simple:

That is, simply prefix a make code with F0h to get the break code.

Example:

The set 3 make code for the "Space" key is 29h.  What is that key's set 3 break code?  Answer:  Simply prefix 29h with F0h...  So the break code is F0,29h.  This works for EVERY set 3 scan code.



Commands (Host to Keyboard):

<Sorry I'm not done with the description for every command...  Very soon, though... > Every once in a while, the computer needs to issue certain commands to the keyboard.  Click here for a short list of these commands, or read below for a more detailed descriptions:

ED  (Set/Reset LEDs)

This command controls the "Caps Lock," "Scroll Lock," and "Num Lock" LEDs.  To tell the keyboard which LEDs to turn on/off, send ED and wait for the keyboard to respond with FA (Acknowledge.)  Then send the (binary) number '00000XYZ' where the X bit is the state of the "Caps Lock" LED, Y is the state of the "Num Lock" LED, and Z is the state of the "Scroll Lock" LED (1 = ON; 0 = OFF.)  The keyboard will then respond (again) with FA, indicating it has successfully received the information.

As an example, suppose you want to tell the keyboard to turn on the "Caps Lock" LED and turn off the "Scroll Lock" and "Num Lock" LEDs:

If the keyboard responds with something other than FA, see Note 1.

Another important note is that the most significant five bits in the byte containing the LED status information (00000XYZ) MUST BE ZEROS.  If one or more of those most significant bits is a 1, the keyboard will respond with FE  and wait for you to send a byte in the form '00000XYZ'.  The keyboard will not accept any other input, or send any scancodes until it receives this byte in the proper form.

EE  (Echo)

If you send the echo command to the keyboard, it will respond with echo (EE.)  This is used to see if the keyboard is connected and working properly.  If the keyboard does not respond with EE, something's wrong.

Example:

If the keyboard does not respond at all, it's probably not connected, it doesn't have power, or it's broke.  If the keyboard responds with something other than EE, refer to Note 1.

F0 (Set Scan Code Set)

The keyboard controller has three different sets of scan codes built in and set 2 is the default.  If you want to change to a different scan code set, send F0 to the keyboard.  The keyboard will respond with FA (Acknowledge.)  You then send 01, 02, or 03 to the keyboard for scan code sets 1, 2, and 3, respectively.  The keyboard will again reply with FA.

Example:  Setting the keyboard to scan code set 1

You can also find out which scan code set is currently being used by the keyboard by sending 00 instead of 01, 02, or 03.  The keyboard will then respond with FA followed by 01, 02, or 03 indicating scan code sets 1, 2, and 3, respectively.

Example: Find out which scan code set the keyboard is currently using

F2 (Get ID)

The keyboard will respond to this command with FA followed by the ID number 83ABh.  This is used to identify the device connected to the host (if a keyboard is present, it will reply with ID 83ABh;  if a mouse is connected, it will respond with ID 00h.)  This command also enables the keyboard if it was previously disabled.



Commands (Keyboard to Host):

In addition to sending scan code for the keys on the keyboard, there are also a few special commands the keyboard can send to the host.  The protocol for sending these commands is exactly the same as sending normal scan codes.  Click here for an abbreviated list of these commands or read below for more detailed descriptions:

00h  (Error)

If the keyboard receives invalid data from the key matrix or the keyboard buffer overflows AND the keyboard is currently set to scan code set 1 or 2, it will send this command to the host.

83,ABh (Keyboard ID)

If the host sends the "Get ID" command, the keyboard will respond with this ID code.  Since devices other than keyboards (such as PS/2 mice) can be connected to the PS/2 port, the keyboard controller needs some way of figuring out what type of device is connected.  The ID 83,ABh is assigned to the keyboard.

AAh (Self-test passed)

When the keyboard is first powered up, it runs BAT (basic assurance test) to make sure everything is working correctly (when you turn on your computer, all of the LEDs on the keyboard will blink as part of this self-test.)  If everything is working correctly, it sends AAh to the host.  If the keyboard finds that it is not working correctly, it will return with FCh (Self-test failed.)

EEh (Echo)

When the host sends the "Echo" command to the keyboard, the keyboard will respond with EEh.

FAh (Acknowledge)

When the host sends a command to the keyboard, it will indicate that it received and recognizes the command by replying with FAh.

FCh (Self-test failed)
See "AAh (Self-test passed)"

FEh (resend)

If the keyboard receives a command it does not recognize, it will send FEh to the host.

FFh (Error)

This is similar to the "00h" command except "FFh" is sent if the keyboard is currently set to scan code set 3.
 
 

*Note 1:  If the keyboard responds with FE (the Resend command), this means either the keyboard does not recognize the command you sent or the parity bit was incorrect.  If you get this response, chances are your algorithm for sending data is somehow incorrect.  FA and FE are the only two responses you should get from the keyboard.  If you think you got something else, your algorithm is probably sending too many or too few bits to the keyboard.
 



Other Sources:

-Adam C

- Top of Page - Adam's micro-Resources -