LK201 Interface

LK201 Keyboard Interface

Overview

Electrical Interface

Communications from the Keyboard to the Computer

Communications from the Computer to the Keyboard

References

DISCLAIMER


Overview

Introduction and Purpose

This page is intended to detail the DEC LK201 keyboard interface. If anything on this page is unclear or incorrect, please contact me and I will do my best to clarify and/or correct the document.


Electrical Interface

Electrical Specifications

This section describes the electrical interface between the LK201 Keyboard and the computer. Some of these specifications came from publication EK-366AA-OG-002 "DECstation 5000, Model 200 Hardware Operator's Guide, April 1990". The rest of the items in this section were experimentally determined (like the pin outs).

The LK201 is powered from a 12 Volt supply generated by the computer. The keyboard and the computer communicate via a fairly standard serial interface. The key specifications are listed here:

  • Bidirectional asynchronous serial communication: 4800 baud, 8N1.
  • Serial interface levels: EIA RS 423 (ie signals swing +/- 5 Volts).
  • Power input: 4.2 Watts Max. 350 mA @ 11.8 Volts +/- 6%. (NOTE: This is the value quoted in the manual, but I measured 30 mA on a working LK201. Perhaps the 350 mA is the maximum the computer can supply?)

Connector Pinout

The pinout of the connector on the LK201 and on the computer in jpeg and postscript form are linked below.


    |----- data -< -------------------------------------------|
    |    |-------- >- Power -----------------------------|    |
    |    |    |------------- GND -------------------|    |    |
    |    |    |    |------------- <- data -----|    |    |    |
   -------------------                        -------------------
  | "    "    "    "  |                      | "    "    "    "  |
  | L    V    G    D  |                      | D    G    V    L  |
  | K    +    N    E  |                      | E    N    +    K  |
  | ->        D    C  |                      | C    D         -> |
  | D             ->  |                      | ->             D  |
  | E              L  |                      | L              E  |
  | C              K  |                      | K              C  |
   --               --                        --               --
     |             |                            |             |
      --         --                              --         --
        |       |                                  |       |
         -------                                    -------

     Looking into the                       Looking into the DECstation
     LK201 Connector                                 Connector
   (Socket on keyboard)                        (Socket on DECstation)


Communications from the Keyboard to the Computer

Overview

The next two sections will refer to the following table and/or diagram:

(I had a hard time getting a jpeg version which was legible so please bear with me on the postscript format for now.)

Keyboard Modes

The LK201 keyboard has its keys divided into 14 distinct groups. These groups are indicated on the LK201 Keycode and Keyboard Division Chart/Table. Each of the groups is separately programmed for its behaviour with respect to keycode generation. There are three operating modes to select from.

  • LK_DOWN mode: In this mode, the code indicated on the keycode chart is transmitted by the keyboard when the corresponding key is pressed. If held down, the key does not repeat and no further codes are generated.
  • LK_AUTODOWN mode: In this mode, the code indicated on the keycode chart is transmitted by the keyboard when the corresponding key is pressed. If held down the LK201 transmits the LK_REPEAT value, 0xB4,repeatedly at the key repeat rate. It is up to the computer to know what key is being repeated.
  • LK_UPDOWN mode: In this mode, the code indicated on the keycode chart is transmitted by the keyboard when the corresponding key is pressed. In addition, a code is generated when the key is released. The release code is determined by the following rule. If no other keys in LK_UPDOWN mode are pressed in addition to the one being released, the LK_ALLUP, 0xB3 is generated. If there is another key currently pressed which has been programmed for LK_UPDOWN mode, the code indicated on the keycode chart is used for the key release code. If held, the key does not repeat. LK_UPDOWN mode is used for keys such as SHIFT, and CONTROL. The computer recognizes that the SHIFT (or other "modifying" key) has been pressed and not released. In this manner, the computer knows to use the shifted character set. Once released, the computer sees the release code and switches back to the normal character set.

Communications from the Computer to the Keyboard

Overview

The LK201 accepts a handful of commands from the computer. These commands include programming the operational mode of each of the 14 groups of keys, control of the 4 LED's, control of the bell, and control of keyclicks.

Commands are send to the keyboard as either single byte commands or as a command byte followed by one data byte. Once again, the communication is 4800 baud serial.

LED Control

The 4 LED's on the LK201 are controlled by the computer. Either the command LK_LED_ENABLE or LK_LED_DISABLE is sent followed by 1 byte which indicates which of the 4 LED's are affected. The lower 4 bits of the data byte correspond to the 4 LED's. For example, to turn on the caps lock LED, the following two bytes would be sent:

LK_LED_ENABLE LED_LOCK

A sample code fragment which defines the LED control codes is shown here.

/* requires LED number data */ 
#define LK_LED_ENABLE   0x13            /* light LED        */ 
#define LK_LED_DISABLE  0x11            /* turn off LED     */ 

#define LED_WAIT        0x81            /* Wait LED         */ 
#define LED_COMP        0x82            /* Compose LED      */ 
#define LED_LOCK        0x84            /* Lock LED         */ 
#define LED_HOLD        0x88            /* Hold Screen LED  */ 
#define LED_ALL         0x8F            /* All LED's        */

Key Click Control

The LK201 accepts several commands relating to key clicks.

/* Requires volume data byte */
#define LK_CL_ENABLE    0x1B   /* keyclick enable.  Requires volume   */
                               /* byte.  This does not affect the     */
			       /* SHIFT key.  The CTRL key requires   */
                               /* LK_CL_ENABLE and LK_CCL_ENABLE to   */
			       /* have been sent before it clicks.    */
			       /* All other keys are only controlled  */    
			       /* by LK_CL_ENABLE.                    */
     
#define LK_CCL_ENABLE   0xBB   /* Enable keyclicks for the CTRL key.  */
                               /* The CTRL keyclick volume is set to  */
			       /* be the same as the rest of the keys */
			       /* LK_CCL_ENABLE sets a flag in the    */
			       /* keyboard with is logically AND'ed   */
			       /* with the LK_CL_ENABLE flag to enable*/
			       /* CTRL key keyclicks.                 */

#define LK_CL_DISABLE   0x99   /* keyclick disable                    */
#define LK_CCL_DISABLE  0xB9   /* CTRL key keyclick disable           */

#define LK_SOUND_CLICK  0x9F   /* causes the LK201 to sound a keyclick*/

/* max volume is 0, lowest is 0x7 */
#define LK_PARAM_VOLUME(v)              (0x80|((v)&0x7))

For example, to enable keyclicks at full volume, the following data would be sent to the keyboard:

LK_CL_ENABLE LK_PARAM_VOLUME(0x00)

Bell Control

The keyboard bell control commands work in the same manner as the keyclick commands. The keyboard never generates a bell sound on its own. A bell sound is always at the command of the computer.

/* requires bell volume data */ 
#define LK_BELL_ENABLE  0x23   /* enable the keyboard bell.  Requires */
                               /* volume data byte.                   */

#define LK_BELL_DISABLE 0xA1   /* disable the keyboard bell.          */

#define LK_RING_BELL    0xA7   /* ring the keyboard bell              */ 

/* max volume is 0, lowest is 0x7 */ 
#define LK_PARAM_VOLUME(v)              (0x80|((v)&0x7))

Key Control

The LK201 provides 3 different operating modes for the keys. In addition, the keyboard is divided into 14 different groups which are shown in the LK201 Keycode and Keyboard Division Chart (postscript 136k) and also in the LK201 Keycode and Keyboard Division Table (html). The three operating modes are discussed in 2. Communications from the Keyboard to the Computer.

Programming of the keyboard mode is accomplished via 1 byte per group of keys on the keyboard. The macro LK_CMD_MODE() is used to form the command. For example, to set division 2 (the numeric keypad) to LK_AUTODOWN mode, we would transmit:

LK_CMD_MODE(LK_AUTODOWN,2)

Upon successful receipt of the command, the LK201 responds with LK_MODECHG_ACK. The macros and constants used for key mode programming are listed below.

The details of the meaning of each bit in the mode command are listed below.

bit 7:      PARAM bit.
            1 = no parameter to follow
            0 = parameter will follow

bits 3-6:   keyboard division

bits 1-2:   mode  (00 = down, 01=autodown, 11=updown)

bit 0:      "type"  don't know what that means, but should be set to 0.

In the examples below, the PARAM bit is set to 1 meaning that no parameter will follow.

#define LK_UPDOWN           0x86 
#define LK_AUTODOWN         0x82 
#define LK_DOWN             0x80 

#define LK_CMD_MODE(m,div)  ((m)|((div)<<3)) 

#define LK_MODECHG_ACK      0xBA    /* sent by the keyboard to acknowledge a  */
                                    /* successful mode change.                */


#define LK_PFX_KEYDOWN      0xB9    /* indicates that the next byte is a key- */
                                    /* code for a key already down in a       */
                                    /* division that has been changed to      */
                                    /* LK_UPDOWN.  I think this means that if */
                                    /* for example, the 'a' key is in LK_DOWN */
                                    /* mode and the key is being held down and*/
                                    /* division 1 is switched to LK_UPDOWN    */
                                    /* mode, the keyboard will produce the    */
                                    /* byte LK_PFX_KEYDOWN followed by 0xC2   */
                                    /* (KEY_A).                               */

#define LK_CMD_RPT_TO_DOWN  0xD9    /* This command causes all divisions which */
                                    /* are programmed for LK_AUTODOWN mode to  */
                                    /* be switched to LK_DOWN mode.            */


#define LK_CMD_ENB_RPT      0xE3    /* enables auto repeat on the keys         */
                                    /* which are in LK_AUTODOWN mode           */

#define LK_CMD_DIS_RPT      0xE1    /* disables auto repeat on all keys, but   */
                                    /* does not change the mode that the       */
                                    /* divisions are programmed to.            */

#define LK_CMD_TMP_NORPT    0xD1    /* temporary auto repeat disable.  This    */
                                    /* command disables auto repeat for the key*/
                                    /* which is currently pressed down.  Auto  */
                                    /* repeat is re-enabled when another key is*/
                                    /* pressed.                                */


#define LK_INPUT_ERROR      0xB6    /* sent by the keyboard if it receives an  */
                                    /* invalid command.                        */

The LK201 contains 4 autorepeat registers. Each autorepeat register controls how quickly keys repeat and if repeating is enabled. The 4 autorepeat registers are independent. Each keyboard division can be associated with 1 of the 4 registers. To associate a keyboard division with a particular autorepeat register, use the same command as setting the key division mode except set the PARAM bit to 0 and send a second byte which controls which autorepeat register is selected. The format of the second byte is:

bit7:      1

bits 2-6:  0

bits 0-1:  number of the autorepeat register 00,01,10,11

For example, to set division 2 (the numeric keypad) to LK_AUTODOWN mode, and associate it with autorepeat register number 2, we would transmit: LK_CMD_MODE_AR(LK_AUTODOWN,2) 0x82 where the macro LK_CMD_MODE_AR is defined below.

#define LK_CMD_MODE_AR(m,div,arreg)  (0x7F & ((m)|((div)<<3)) )

Autorepeat Control

The autorepeat rate is programmed by a 3 byte command.

first byte:
bit7:      0  (means more bytes to come after this one)

bits 3-6:  1 (means we're calling the rate change command)

bits 1-2:  number of autorepeat register (00,01,10,11)

bit 0:     "type" set to 0

second byte:

bit7:      0  (more bytes to come after this one)

bits0-6:   time out value (how long to wait before beginning to autorepeat)
           this is in 5 ms increments.  allowed range is 5 ms-630 ms.  

note:  don't send 635ms, 0111 1111 is a reserved for internal use code.
note:  don't send 0ms,   0000 0000 is illegal.

third byte:

bit7:      1 (no more bytes after this one)

bits0-6:   autorepeat rate in number of generated key presses/second.
           lowest rate is 12 Hz.  

note:  125Hz  (1111 1101) must not be sent (its identical to the powerup
       command)

Power-Up and Self Test

This section details the self test features and the power up sequence of the keyboard. Upon power-up, the keyboard performs a self test in 70 ms or less. The results are sent to the computer. The power-up self test results consist of 4 bytes.

Byte 1:    Keyboard ID stored in the keyboard firmware.  On
           my LK201, this is 0x01.

Byte 2:    Keyboard ID read from hardware jumpers.  The documentation
           I have doesn't seem to quite match my keyboard (the docs say
           that the keyboard uses an 8051 microcontroller while mine
           uses a 68HC05C4).  Anyway, the docs and my keyboard both say
           the result is 0x00.

Byte 3:    Error code.  This byte indicates the result of the self test.
           Possible values are:

                               0x00    No Error
#define    LK_KDOWN_ERROR      0x3D    /* Key down on powerup error     */
#define    LK_POWER_ERROR      0x3E    /* Keyboard failure on pwrup tst */

Byte 4:    Keycode.  This byte contains the keycode of which key (if any)
           was pressed down on powerup.  If no keys were pressed, this
           byte is 0x00.

If the keyboard passes all power up tests with no error, the resulting sequence sent to the computer is:

0x01 0x00 0x00 0x00 

If the keyboard finds a key down on the first scan, it continues to look for an all up condition. When all keys are released, the keyboard transmits the correct 4 byte sequence (0x01 0x00 0x00 0x00).

Additional test commands are listed below.

#define LK_CMD_POWER_UP     0xFD    /* This command initiates the keyboard    */
                                    /* power up sequence.                     */ 

#define LK_CMD_REQ_ID       0xAB    /* This command requests the 2 byte       */
                                    /* keyboard ID.  The keyboard responds    */
                                    /* with the same Byte1 and Byte2 as in    */
                                    /* the power up self test.                */

#define LK_CMD_SET_DEFAULTS 0xD3    /* Restores the keyboard to its default   */
                                    /* state.  This command sets the:         */
                                    /* division mode settings,                */
                                    /* auto-repeat interval and timeout rate, */
                                    /* auto-repeat buffer selections,         */
                                    /* audio volume,                          */
                                    /* ctrl key keyclick setting,             */
                                    /* to their power up defaults.            */

#define LK_CMD_TEST_MODE    0xCB    /* causes the keyboard to enter the       */
                                    /* factory test mode.  This command       */
                                    /* should not be used.  If received, the  */
                                    /* keyboard responds with LK_TESTMODE_ACK */
                                    /* By sending a 0x80, the keyboard will   */
                                    /* leave factory test mode and jump to the*/
                                    /* power up sequence.                     */

#define LK_TESTMODE_ACK     0xB8    /* sent by the keyboard in response to    */
                                    /* the LK_CMD_TEST_MODE command.          */

The following are some additional keyboard control commands which didn't seem to fit anywhere else.

#define LK_CMD_INHIBIT      0xB9    /* This command suspends transmission     */
                                    /* the keyboard to the computer.  The     */
                                    /* keyboard responds with LK_KBDLOCK_ACK  */
                                    /* and turns on the LOCK LED.             */

#define LK_KDBLOCK_ACK      0xB7    /* send by the keyboard in response to    */
                                    /* the LK_CMD_INHIBIT command.            */

#define LK_CMD_RESUME       0x8B    /* Resumes normal keyboard operation after*/
                                    /* the LK_CMD_INHIBIT command.            */

#define LK_OUTPUT_ERROR     0xB5    /* If any keystrokes were lost while the  */
                                    /* keyboard was locked (LK_CMD_INHIBIT),  */
                                    /* then LK_OUTPUT_ERROR is generated by   */
                                    /* the keyboard when LK_CMD_RESUME is     */
                                    /* received.                              */

References

Sources of this Information

Much of this information came from NetBSD sources from mid-March, 1998. In particular, the files lk201.h and lk201.c from src/sys/arch/pmax/dev/ is the source of most of the code fragments on this page. Additional hints came from the X11R5 Xserver code for OpenBSD (I think the OpenBSD and NetBSD Xserver's are largely the same, at least with respect to the keyboard stuff). I also got some good hints and a few #define's from an unknown version of Mach from Carnegie Mellon. The files in the Mach source I looked at were also called lk201.h and lk201.c, but were not the same as the NetBSD files of the same names.

In addition to poking around the various pieces of code mentioned above, I hooked an LK201 up to the serial port on a NetBSD/mac68k machine and spent some time experimenting with the keyboard and the various control sequences. This is how I convinced myself of what the 14 keyboard divisions are. This test setup was invaluable for seeing exactly what the keyboard produces and how it reacts to known commands.

The text version of the keycodes and keyboard divisions was sent to me by Dave. My brother, Jeff, was also a big help in answering many C questions and pointing me towards the Mach code.

In addition, I got a copy rather late in the writing of this page of what could be considered the "real" document for all this stuff. "VCB02 Video Subsystem Technical Manual" DEC Educational Services, AZ-GLGAB-MN, February 1986 The appendix of this document cleaned out most of the remaining mysteries.


DISCLAIMER

No Fault

Any software and documentation here is provided "as is", no warranty, use at your own risk. Please do not hook up your LK201 and/or computer backwards and blame me!