PS/2 Keyboard Interface
About
The class allows any IO pins to be used. Relies on default pull-up resistors having not been disabled.
Reads the Scan Code from a PS2 Keyboard and converts most characters into ASCII Code, a list of which to be attached.
Doesn't support host to keyboard commands i.e. - no CAPS LOCK Status LEDS
Most character keys have been covered and all non-character keys return the make code, with the exception of non-character keys with a scan code of more than one byte, which return the second byte and raise a flag to say that there are two bytes. Since the first byte is always 0xE0 the flag is E0flag
Pinout
Looking into end of the plug:
nc ---> o o <--- clk
+5V ---> o o <--- GND
||
nc ---> o || o <--- data
The Code
#include <mbed.h> Digital ps2clk(54); Digital ps2din(53); static const unsigned char ps2KeyMap[] = { // 0 1 2 3 4 5 6 7 8 9 A B C D E F ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '`', ' ', // 00-0F ' ', ' ', ' ', ' ', ' ', 'Q', '1', ' ', ' ', ' ', 'Z', 'S', 'A', 'W', '2', ' ', // 10-1F ' ', 'C', 'X', 'D', 'E', '4', '3', ' ', ' ', ' ', 'V', 'F', 'T', 'R', '5', ' ', // 20-2F ' ', 'N', 'B', 'H', 'G', 'Y', '6', ' ', ' ', ' ', 'M', 'J', 'U', '7', '8', ' ', // 30-3F ' ', ',', 'K', 'I', 'O', '0', '9', ' ', ' ', '.', '/', 'L', ';', 'P', '-', ' ', // 40-4F ' ', ' ','\'', ' ', '[', '=', ' ', ' ', ' ', ' ', ' ', ']', ' ','\\', ' ', ' ', // 50-5F ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // 60-6F ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // 70-7F ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // 80-8F ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // 90-9F ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // A0-AF ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // B0-BF ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // C0-CF ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // D0-DF ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // E0-EF ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // F0-FF }; unsigned char ps2GetKey(void) { unsigned int buf; int i; buf = 0; ps2clk = 0; ps2din.direction(0); ps2clk.direction(0); for(i=0;i<11;i++) { while(ps2clk); while(!ps2clk); buf = buf >> 1; buf |= ps2din ? 512 : 0; } ps2clk.direction(1); buf &= 0xFF; return (unsigned char)buf; } int main(void) { printf("\n\rPS2 Keyboard:"); while(1) { unsigned char c; skip_break: c = ps2GetKey(); if(c == 0xF0) { c = ps2GetKey(); goto skip_break; } printf("%c", ps2KeyMap[c]); } return 0; }
Extension
My task was to improve the PS2 Keyboard Interface by manipulating the data to produce a single ASCII character for every one typed on the keyboard. Also the CAPS LOCK key and the SHIFT key were to function as on a keyboard, so:
| EFFECT ON LETTERS | EFFECT ON OTHER SYMBOL | ||
| NO CAPS | NO SHIFT | LOWERCASE | BOTTOM SYMBOL |
| NO CAPS | SHIFT | UPPERCASE | TOP SYMBOL |
| CAPS | NO SHIFT | UPPERCASE | BOTTOM SYMBOL |
| CAPS | SHIFT | LOWERCASE | TOP SYMBOL |
My early versions of the code were developed in the main.cpp but later on I created a class PS2ASCII. The header file and CPP are downloadable from the SVN. In order for a PS2 Keyboard to fully function two other header files and CPPs are in the trunc file for download.
The Initial Concept
#include "mbed.h" #include "PS2Kbd.h" #include "MobileLCD.h" PS2Kbd kbd(28, 27); Serial pc (USBTX,USBRX); MobileLCD lcd(5, 6, 7, 8, 9); DigitalOut Led(LED1); bool caps = false; bool shift = false; static const unsigned char shift_on[] = { // 0 1 2 3 4 5 6 7 8 9 A B C D E F ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '`', ' ', // 00-0F ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // 10-1F ' ', 0x21, 0x22, '~', 0x24, 0x25, 0x26, '@', 0x28, 0x29, 0x30, 0x31, '<', '_', '>', '?', // 20-2F ')', '!', '\"', 0x9C, '$', '%', '^', '&', '*', '(', ' ', ':', ' ', '+', ' ', ' ', // 30-3F 0xAA, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', // 40-6F 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', ' ', ' ', // 50-7F ' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', // 60-4F 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', ' ', ' ', ' ', ' ', // 70-5F ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // 80-8F ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // 90-9F ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // A0-AF ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // B0-BF ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // C0-CF ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // D0-DF ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // E0-EF NULL, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', // F0-FF }; int main() { lcd.background(0x1E1CCD); //screen colour - some shade of blue lcd.cls(); while(1) { unsigned char keypress = kbd.rd(); //code in if(keypress == 0xE0) //is it a special E0 key? { keypress = kbd.rd(); //next byte in if(keypress == NULL) //is is a break code? { keypress = kbd.rd(); //if so chew it up and back to start continue; } lcd.printf("E0 "); //tell us that it is lcd.printf("%d ", keypress); continue; } if((keypress == 0x12) || (keypress == 0x59)) //SHIFT pressed? { shift = true; continue; } if(keypress == NULL) //gets rid of byte 1 of break code { keypress = kbd.rd(); //byte 2 of break code in switch (keypress) { case 0x12: shift = false; //if SHIFT released turn shift off continue; case 0x59: shift = false; continue; default: continue; } } switch (keypress) { case 0x1B: //the ESC key lcd.cls(); continue; case 0x5A: lcd.newline(); //the RETURN key continue; case 0x58: caps = !caps; //the CAPS LOCK key continue; default: break; } unsigned char last_keypress = keypress; if(shift == true) //if SHIFT is pressed take shifted character { last_keypress = shift_on[keypress]; } if((keypress >= 97)&&(keypress <= 127)) //is character a letter? { if((caps == true)&&(shift == false)) { last_keypress = shift_on[keypress]; //if caps is on shift the letter up } if((caps == true)&&(shift == true)) //if caps and shift are on shift the letter back down { last_keypress = shift_on[last_keypress]; } } lcd.printf("%c", last_keypress); wait(0.03); } }
This program looks at the character received in ASCII and according to the CAPS LOCK/SHIFT key table above, shifts each character up or down via the array at the top of the program. This program was intended for displaying a charcter on a MOD-NOKIA-6610 LCD Screen availiable from [ http://www.coolcomponents.co.uk/catalog/product_info.php?cPath=24&products_id=147 ]
The End Product
The main is a lot shorter with the new PS2ASCII class.
This Program is configured to print a character onto the Nokia LCD and if a function key is pressed of more than one byte the LCD displays E0 space scan code.
To Do
Convert to use a peripheral and fuse with mbedVGA code!
enjoy!
Daniel.

