#include #define PS2_KC_BKSP 0x08 #define PS2_KC_UP 0x81 #define PS2_KC_DOWN 0x82 #define PS2_KC_LEFT 0x83 #define PS2_KC_RIGHT 0x84 #define PS2_KC_PGDN 0x85 #define PS2_KC_PGUP 0x86 #define PS2_KC_END 0x87 #define PS2_KC_HOME 0x88 #define PS2_KC_INS 0x89 #define PS2_KC_DEL 0x8A #define PS2_KC_ESC 0x8B #define PS2_KC_CLON 0x8C // caps_lock on #define PS2_KC_CLOFF 0x8D // caps_lock off /* * Pin 4 is the ps2 data pin, pin 3 is the clock pin */ PS2 kbd(3, 4); bool ps2Keyboard_release = false; bool ps2Keyboard_extend = false; bool cmd_ack_byte_ok = false; bool ps2Keyboard_shift = false; bool ps2Keyboard_alt = false; bool ps2Keyboard_caps_lock = false; bool ps2Keyboard_ctrl = false; byte ps2Keyboard_CharBuffer = 0; byte code; // val : bit_2=caps_lock, bit_1=num_lock, bit_0=scroll_lock void kbd_set_lights(byte val) { kbd.write(0xED); kbd.read(); // pull out the ack byte kbd.write(val); // now send the data } byte lookupCode() { byte result = ps2Keyboard_CharBuffer; // Use a switch for the code to character conversion. // This is fast and actually only uses 4 bytes per simple line switch (result) { case 0x1C: result = 'a'; break; case 0x32: result = 'b'; break; case 0x21: result = 'c'; break; case 0x23: result = 'd'; break; case 0x24: result = 'e'; break; case 0x2B: result = 'f'; break; case 0x34: result = 'g'; break; case 0x33: result = 'h'; break; case 0x43: result = 'i'; break; case 0x3B: result = 'j'; break; case 0x42: result = 'k'; break; case 0x4B: result = 'l'; break; case 0x3A: result = 'm'; break; case 0x31: result = 'n'; break; case 0x44: result = 'o'; break; case 0x4D: result = 'p'; break; case 0x15: result = 'q'; break; case 0x2D: result = 'r'; break; case 0x1B: result = 's'; break; case 0x2C: result = 't'; break; case 0x3C: result = 'u'; break; case 0x2A: result = 'v'; break; case 0x1D: result = 'w'; break; case 0x22: result = 'x'; break; case 0x35: result = 'y'; break; case 0x1A: result = 'z'; break; // note that caps lock only used on a-z case 0x41: result = ps2Keyboard_shift? '<' : ','; break; case 0x49: result = ps2Keyboard_shift? '>' : '.'; break; case 0x4A: result = ps2Keyboard_shift? '?' : '/'; break; case 0x54: result = ps2Keyboard_shift? '{' : '['; break; case 0x5B: result = ps2Keyboard_shift? '}' : ']'; break; case 0x4E: result = ps2Keyboard_shift? '_' : '-'; break; case 0x55: result = ps2Keyboard_shift? '+' : '='; break; case 0x29: result = ' '; break; case 0x45: result = ps2Keyboard_shift? ')' : '0'; break; case 0x16: result = ps2Keyboard_shift? '!' : '1'; break; case 0x1E: result = ps2Keyboard_shift? '@' : '2'; break; case 0x26: result = ps2Keyboard_shift? '£' : '3'; break; case 0x25: result = ps2Keyboard_shift? '$' : '4'; break; case 0x2E: result = ps2Keyboard_shift? '%' : '5'; break; case 0x36: result = ps2Keyboard_shift? '^' : '6'; break; case 0x3D: result = ps2Keyboard_shift? '&' : '7'; break; case 0x3E: result = ps2Keyboard_shift? '*' : '8'; break; case 0x46: result = ps2Keyboard_shift? '(' : '9'; break; case 0x0D: result = '\t'; break; case 0x5A: result = '\n'; break; case 0x66: result = PS2_KC_BKSP; break; case 0x69: result = ps2Keyboard_extend? PS2_KC_END : '1'; break; case 0x6B: result = ps2Keyboard_extend? PS2_KC_LEFT : '4'; break; case 0x6C: result = ps2Keyboard_extend? PS2_KC_HOME : '7'; break; case 0x70: result = ps2Keyboard_extend? PS2_KC_INS : '0'; break; case 0x71: result = ps2Keyboard_extend? PS2_KC_DEL : '.'; break; case 0x72: result = ps2Keyboard_extend? PS2_KC_DOWN : '2'; break; case 0x73: result = '5'; break; case 0x74: result = ps2Keyboard_extend? PS2_KC_RIGHT : '6'; break; case 0x75: result = ps2Keyboard_extend? PS2_KC_UP : '8'; break; case 0x76: result = PS2_KC_ESC; break; case 0x79: result = '+'; break; case 0x7A: result = ps2Keyboard_extend? PS2_KC_PGDN : '3'; break; case 0x7B: result = '-'; break; case 0x7C: result = '*'; break; case 0x7D: result = ps2Keyboard_extend? PS2_KC_PGUP : '9'; break; // Reset the shift counter for unexpected values, to get back into sync // This allows for hot plugging a keyboard in and out default: delay(500); // but wait a bit in case part way through a shift ps2Keyboard_shift = false; ps2Keyboard_ctrl = false; ps2Keyboard_alt = false; ps2Keyboard_extend = false; ps2Keyboard_release = false; ps2Keyboard_caps_lock = false; } // end switch(result) // shift a-z chars here (less code than in the switch statement) if (((result>='a') && (result<='z')) && ((ps2Keyboard_shift && !ps2Keyboard_caps_lock) || (!ps2Keyboard_shift && ps2Keyboard_caps_lock))) { result = result + ('A'-'a'); } // done with the character ps2Keyboard_CharBuffer = 0; return(result); } void kbd_init() { char ack; kbd.write(0xff); // send reset code ack = kbd.read(); // byte, kbd does self test ack = kbd.read(); // another ack when self test is done } void setup() { Serial.begin(19200); //19200 bps used by iphone connector kbd_init(); } /* * get a keycode from the kbd and report it back to the * host via the serial line. */ void loop() { /* read a keycode */ code = kbd.read(); if( !code ) return; // ignore null bytes /* convert from scan code */ switch (code) { case 0xF0: { // key release char ps2Keyboard_release = true; ps2Keyboard_extend = false; break; } case 0xFA: { // command acknowlegde byte cmd_ack_byte_ok = true; break; } case 0xE0: { // extended char set ps2Keyboard_extend = true; break; } case 0x12: // left shift case 0x59: { // right shift ps2Keyboard_shift = ps2Keyboard_release? false : true; ps2Keyboard_release = false; break; } case 0x11: { // alt key (right alt is extended 0x11) ps2Keyboard_alt = ps2Keyboard_release? false : true; ps2Keyboard_release = false; break; } case 0x14: { // ctrl key (right ctrl is extended 0x14) ps2Keyboard_ctrl = ps2Keyboard_release? false : true; ps2Keyboard_release = false; break; } case 0x58: { // caps lock key if (!ps2Keyboard_release) { ps2Keyboard_caps_lock = ps2Keyboard_caps_lock? false : true; // allow caps lock code through to enable light on and off if (ps2Keyboard_caps_lock) kbd_set_lights(4); else kbd_set_lights(0); } else { ps2Keyboard_release = false; } break; } default: { // not a control key if (ps2Keyboard_release) { // ignore releases ps2Keyboard_release = false; } else { // real keys get sent out ps2Keyboard_CharBuffer = code; Serial.println(lookupCode(), BYTE); } } } }