Arduino Micro as an emulated USB Keyboard for old legacy DOS systems.

I'm trying to remotely interface with some really old DOS boxes. I use a capture card to capture the display for remote viewing. I like to use a keyboard emulator to remotely control the old DOS boxes too.

For video, I have the following setup:
remote device ---> PC ----> capture card ---> DOS box

For controls, I have the following setup
remote device ---> PC ----> Arduino ---> DOS box

The PC is connected to the Arduino via a FTDI USB to tty cable. Keyboard commands are sent to the Arduino Serial1 as HEX. The Arduino then sends the key stroke via the USB port.

The thing is that my program works when I connect Arduino Micro as an emulated keyboard to modern OS like Windows and Ubuntu. The TX is always constantly lit because my loop always sends a key release when nothing happens. However, when I connect the Arduino Micro to the DOS box, the TX never lights up and the RX blinks a few times before stopping. I can't get any keyboard presses sent through.

#include <Keyboard.h>

int incomingByte = 0;   // for incoming serial data
int incomingByte1 = 0;   // for incoming serial data

void setup() {
  // make pin 2 an input and turn on the 
  // pullup resistor so it goes high unless
  // connected to ground:
  Serial.begin(9600);     // opens serial port, sets data rate to 9600 bps
  Serial1.begin(9600);     // opens serial port, sets data rate to 9600 bps  
  pinMode(2, INPUT_PULLUP);
  Keyboard.begin();
}

void loop() {
  if (digitalRead(2) == HIGH) {
    // do nothing until pin 2 goes low
    delay(2);
    Keyboard.releaseAll(); 
  }
  if (digitalRead(2) == LOW) {
    // new document:
    Keyboard.press('n');
    delay(2);
  }

//  if (Serial.available() > 0) {
        // read the incoming byte:
//        incomingByte = Serial.read();

        // say what you got:
//        Serial.print("I received: ");
//        Serial.println(incomingByte, DEC);
//        Serial1.print("I received: ");
//        Serial1.println(incomingByte, DEC);
//        delay(2);
  }
  if (Serial1.available() > 0) {
        // read the incoming byte:
        incomingByte1 = Serial1.read();

        // say what you got:
        Serial.print("I received: ");
        Serial.print(incomingByte1, DEC);        
        Serial1.print(incomingByte1, DEC);
        Keyboard.press(incomingByte1);
        delay(2);
        }
}

Does your old DOS box have an USB keyboard handler installed?

Perhaps your MS-DOS (PC-DOS?) box can be updated to run FreeDOS which is a modern DOS replacement that supports USB mouse and keyboard input. http://www.freedos.org/

These DOS boxes run on DOS 5.00. I've tried updating them to 6.22 but the old software wouldn't run correctly, so I'm stuck running DOS 5.00.

Anyways, I kind of got the keyboard working in DOS using BIOS keyboard from BootKeyboard. However, BootKeyboard requires enum inputs, which is extremely annoying. I had to build a giant switch statement for all possible keys.

Here comes my second issue. I'm running Arduino IDE 1.8.1 from the Windows Store on Windows 10. The same exact code without any changes would sometimes compile and sometimes not compile (collect2.exe: error: ld returned 5 exit status). It is driving me crazy.

#include "HID-Project.h"

const int pinLed = LED_BUILTIN;
const int pinButton = 2;
int incomingByte = 0;

void setup() {
  pinMode(pinLed, OUTPUT);
  pinMode(pinButton, INPUT_PULLUP);
  Serial1.begin(9600);
  // Sends a clean report to the host. This is important on any Arduino type.
  BootKeyboard.begin();
}


void loop() {
  // Light led if keyboard uses the boot protocol (normally while in bios)
  // Keep in mind that on a 16u2 and Arduino Micro HIGH and LOW for TX/RX Leds are inverted.
  if (BootKeyboard.getProtocol() == HID_BOOT_PROTOCOL)
    digitalWrite(pinLed, HIGH);
  else
    digitalWrite(pinLed, LOW);

  // Trigger caps lock manually via button
  if (!digitalRead(pinButton)) {
    BootKeyboard.write(KEY_A);
    
    // Simple debounce
    delay(300);
  }
  if (Serial1.available() > 0) {
    incomingByte = Serial1.read();

    switch (incomingByte){
      case 65:
        BootKeyboard.write(KEY_A);
        break;
      case 66:
        BootKeyboard.write(KEY_B);
        break;
      case 67:
        BootKeyboard.write(KEY_C);
        break;
      case 68:
        BootKeyboard.write(KEY_D);
        break;
      case 69:
        BootKeyboard.write(KEY_E);
        break;
      case 70:
        BootKeyboard.write(KEY_F);
        break;
      case 71:
        BootKeyboard.write(KEY_G);
        break;
      case 72:
        BootKeyboard.write(KEY_H);
        break;
      case 73:
        BootKeyboard.write(KEY_I);
        break;
      case 74:
        BootKeyboard.write(KEY_J);
        break;
      case 75:
        BootKeyboard.write(KEY_K);
        break;
      case 76:
        BootKeyboard.write(KEY_L);
        break;
      case 77:
        BootKeyboard.write(KEY_M);
        break;
      case 78:
        BootKeyboard.write(KEY_N);
        break;
      case 79:
        BootKeyboard.write(KEY_O);
        break;
      case 80:
        BootKeyboard.write(KEY_P);
        break;
      case 81:
        BootKeyboard.write(KEY_Q);
        break;
      case 82:
        BootKeyboard.write(KEY_R);
        break;
      case 83:
        BootKeyboard.write(KEY_S);
        break;
      case 84:
        BootKeyboard.write(KEY_T);
        break;
      case 85:
        BootKeyboard.write(KEY_U);
        break;
      case 86:
        BootKeyboard.write(KEY_V);
        break;
      case 87:
        BootKeyboard.write(KEY_W);
        break;
      case 88:
        BootKeyboard.write(KEY_X);
        break;
      case 89:
        BootKeyboard.write(KEY_Y);
        break;
      case 90:
        BootKeyboard.write(KEY_Z);
        break;
      case 97:
        BootKeyboard.write(KEY_A);
        break;
      case 98:
        BootKeyboard.write(KEY_B);
        break;
      case 99:
        BootKeyboard.write(KEY_C);
        break;
      case 100:
        BootKeyboard.write(KEY_D);
        break;
      case 101:
        BootKeyboard.write(KEY_E);
        break;
      case 102:
        BootKeyboard.write(KEY_F);
        break;
      case 103:
        BootKeyboard.write(KEY_G);
        break;
      case 104:
        BootKeyboard.write(KEY_H);
        break;
      case 105:
        BootKeyboard.write(KEY_I);
        break;
      case 106:
        BootKeyboard.write(KEY_J);
        break;
      case 107:
        BootKeyboard.write(KEY_K);
        break;
      case 108:
        BootKeyboard.write(KEY_L);
        break;
      case 109:
        BootKeyboard.write(KEY_M);
        break;
      case 110:
        BootKeyboard.write(KEY_N);
        break;
      case 111:
        BootKeyboard.write(KEY_O);
        break;
      case 112:
        BootKeyboard.write(KEY_P);
        break;
      case 113:
        BootKeyboard.write(KEY_Q);
        break;
      case 114:
        BootKeyboard.write(KEY_R);
        break;
      case 115:
        BootKeyboard.write(KEY_S);
        break;
      case 116:
        BootKeyboard.write(KEY_T);
        break;
      case 117:
        BootKeyboard.write(KEY_U);
        break;
      case 118:
        BootKeyboard.write(KEY_V);
        break;
      case 119:
        BootKeyboard.write(KEY_W);
        break;
      case 120:
        BootKeyboard.write(KEY_X);
        break;
      case 121:
        BootKeyboard.write(KEY_Y);
        break;
      case 122:
        BootKeyboard.write(KEY_Z);
        break;
      case 49:
        BootKeyboard.write(KEY_1);
        break;
      case 50:
        BootKeyboard.write(KEY_2);
        break;
      case 51:
        BootKeyboard.write(KEY_3);
        break;
      case 52:
        BootKeyboard.write(KEY_4);
        break;
      case 53:
        BootKeyboard.write(KEY_5);
        break;
      case 54:
        BootKeyboard.write(KEY_6);
        break;
      case 55:
        BootKeyboard.write(KEY_7);
        break;
      case 56:
        BootKeyboard.write(KEY_8);
        break;
      case 57:
        BootKeyboard.write(KEY_9);
        break;
      case 48:
        BootKeyboard.write(KEY_0);
        break;
      case 176:
        BootKeyboard.write(KEY_ENTER);
        break;
      case 177:
        BootKeyboard.write(KEY_ESC);
        break;
      case 178:
        BootKeyboard.write(KEY_BACKSPACE);
        break;
      case 179:
        BootKeyboard.write(KEY_TAB);
        break;
      case 32:
        BootKeyboard.write(KEY_SPACE);
        break;
      case 45:
        BootKeyboard.write(KEY_MINUS);
        break;
      case 61:
        BootKeyboard.write(KEY_EQUAL);
        break;
      case 91:
        BootKeyboard.write(KEY_LEFT_BRACE);
        break;
      case 93:
        BootKeyboard.write(KEY_RIGHT_BRACE);
        break;
      case 92:
        BootKeyboard.write(KEY_BACKSLASH);
        break;
      case 59:
        BootKeyboard.write(KEY_SEMICOLON);
        break;
      case 39:
        BootKeyboard.write(KEY_QUOTE);
        break;
      case 96:
        BootKeyboard.write(KEY_TILDE);
        break;
      case 44:
        BootKeyboard.write(KEY_COMMA);
        break;
      case 46:
        BootKeyboard.write(KEY_PERIOD);
        break;
      case 47:
        BootKeyboard.write(KEY_SLASH);
        break;
      case 193:
        BootKeyboard.write(KEY_CAPS_LOCK);
        break;
      case 194:
        BootKeyboard.write(KEY_F1);
        break;
      case 195:
        BootKeyboard.write(KEY_F2);
        break;
      case 196:
        BootKeyboard.write(KEY_F3);
        break;
      case 197:
        BootKeyboard.write(KEY_F4);
        break;
      case 198:
        BootKeyboard.write(KEY_F5);
        break;
      case 199:
        BootKeyboard.write(KEY_F6);
        break;
      case 200:
        BootKeyboard.write(KEY_F7);
        break;
      case 201:
        BootKeyboard.write(KEY_F8);
        break;
      case 202:
        BootKeyboard.write(KEY_F9);
        break;
      case 203:
        BootKeyboard.write(KEY_F10);
        break;
      case 204:
        BootKeyboard.write(KEY_F11);
        break;
      case 205:
        BootKeyboard.write(KEY_F12);
        break;
      default:
        incomingByte = 0;
      break;
    }
    delay(2);
  }
}

If your DOS box is old enough, you can use the old PS/2 keyboard interface, instead of USB.

The switch code can be simplified a lot. A const array can be used for the scan code conversion, no need for handling each key explicitly. Doesn't the library come with example code?

Do you have an example of emulating the PS2 keyboard?

I might go with PS2 emulation since these DOS systems are so old. However, last time I looked there weren't many examples.

You may get helpful information by searching for "PS/2 keyboard emulator arduino".

Ok, I decided to go with PS2 route for my keyboard emulator. The Bootkeyboard was causing odd key repeats in my DOS system.

I'm programming a PS2 keyboard emulator using ps2dev. For the most part the code works as intended if I put a large enough delay in the main "loop". However, if the delay is small, my serial connection tends to freeze (via realterm and serial monitor in Arduino IDE).

I'm basically using a network connected Ubuntu Box to control an offline DOS box. The Ubuntu box uses tkinter key events to send keys press via the serial port to the Arduino Micro. The Arduino Micro then sends the corresponding key press through the PS2 port to the DOS box

Ubuntu Box -- USB --> Arduino Micro -- PS2 --> DOS Box

This is how the PS2 cable is hooked up

  • Pin 2 - Data (Pin 1 on PS2)
  • Pin 3 - Clock (Pin 5 on PS2)
  • 5V - VCC (Pin 4 on PS2)
  • GND - GND (Pin 3 on PS2)

Here is my code (kind of long with big array initialization, will move to the txt file later to clean up code)

#include "ps2dev.h" // to emulate a PS/2 device

PS2dev keyboard(3,2); // PS2dev object (2:data, 3:clock)
int enabled = 0; // pseudo variable for state of "keyboard"
int inByte = 0;         // incoming serial byte
int presskey = 0;
byte KeyCode2Hex[256][2];

void ack() {
 //acknowledge commands
 while(keyboard.write(0xFA));
}

int keyboardcommand(int command) {
 unsigned char val;
 switch (command) {
 case 0xFF: //reset
   ack();
   //the while loop lets us wait for the host to be ready
   while(keyboard.write(0xAA)!=0);
   break;
 case 0xFE: //resend
   ack();
   break;
 case 0xF6: //set defaults
   //enter stream mode
   ack();
   break;
 case 0xF5: //disable data reporting
   //FM
   enabled = 0;
   ack();
   break;
 case 0xF4: //enable data reporting
   //FM
   enabled = 1;
   ack();
   break;
 case 0xF3: //set typematic rate
   ack();
   keyboard.read(&val); //do nothing with the rate
   ack();
   break;
 case 0xF2: //get device id
   ack();
   keyboard.write(0xAB);
   keyboard.write(0x83);
   break;
 case 0xF0: //set scan code set
   ack();
   keyboard.read(&val); //do nothing with the rate
   ack();
   break;
 case 0xEE: //echo
   //ack();
   keyboard.write(0xEE);
   break;
 case 0xED: //set/reset LEDs
   ack();
   keyboard.read(&val); //do nothing with the rate 
   ack();
   break;
 }
}

void setupKeyCode2Hex()
{
  // initialize everything to 0xE0 just because
  for (int i = 0; i < 256; i++)
  {
	for (int j = 0; j < 2; j++)
	{
	  KeyCode2Hex[i][j] = 0xE0;
	}
  }
  
  KeyCode2Hex[9][0] = 0x76;
  KeyCode2Hex[10][0] = 0x45;
  KeyCode2Hex[11][0] = 0x16;    
  KeyCode2Hex[12][0] = 0x1E;    
  KeyCode2Hex[13][0] = 0x26;    
  KeyCode2Hex[14][0] = 0x25;    
  KeyCode2Hex[15][0] = 0x2E;    
  KeyCode2Hex[16][0] = 0x36;    
  KeyCode2Hex[17][0] = 0x3D;    
  KeyCode2Hex[18][0] = 0x3E;
  KeyCode2Hex[19][0] = 0x46;  
  KeyCode2Hex[20][0] = 0x4E;  
  KeyCode2Hex[21][0] = 0x55;  
  KeyCode2Hex[22][0] = 0x66;  
  KeyCode2Hex[23][0] = 0x0D;  
  KeyCode2Hex[24][0] = 0x15;  
  KeyCode2Hex[25][0] = 0x1D;  
  KeyCode2Hex[26][0] = 0x24;  
  KeyCode2Hex[27][0] = 0x2D;  
  KeyCode2Hex[28][0] = 0x2C;  
  KeyCode2Hex[29][0] = 0x35;  
  KeyCode2Hex[30][0] = 0x3C;  
  KeyCode2Hex[31][0] = 0x43;  
  KeyCode2Hex[32][0] = 0x44;  
  KeyCode2Hex[33][0] = 0x4D;  
  KeyCode2Hex[34][0] = 0x54;  
  KeyCode2Hex[35][0] = 0x5B;  
  KeyCode2Hex[36][0] = 0x5A;  
  KeyCode2Hex[37][0] = 0x14;  
  KeyCode2Hex[38][0] = 0x1C;  
  KeyCode2Hex[39][0] = 0x1B;  
  KeyCode2Hex[40][0] = 0x23;  
  KeyCode2Hex[41][0] = 0x2B;  
  KeyCode2Hex[42][0] = 0x34;  
  KeyCode2Hex[43][0] = 0x33;  
  KeyCode2Hex[44][0] = 0x3B;  
  KeyCode2Hex[45][0] = 0x42;  
  KeyCode2Hex[46][0] = 0x4B;  
  KeyCode2Hex[47][0] = 0x4C;  
  KeyCode2Hex[48][0] = 0x52;  
  KeyCode2Hex[49][0] = 0x0E;  
  KeyCode2Hex[50][0] = 0x12;  
  KeyCode2Hex[51][0] = 0x5D;  
  KeyCode2Hex[52][0] = 0x1A;  
  KeyCode2Hex[53][0] = 0x22;  
  KeyCode2Hex[54][0] = 0x21;  
  KeyCode2Hex[55][0] = 0x2A;  
  KeyCode2Hex[56][0] = 0x32;  
  KeyCode2Hex[57][0] = 0x31;  
  KeyCode2Hex[58][0] = 0x3A;  
  KeyCode2Hex[59][0] = 0x41;  
  KeyCode2Hex[60][0] = 0x49;  
  KeyCode2Hex[61][0] = 0x4A;  
  KeyCode2Hex[62][0] = 0x59;  
  KeyCode2Hex[63][0] = 0x7C;  
  KeyCode2Hex[64][0] = 0x11;  
  KeyCode2Hex[65][0] = 0x29;  
  KeyCode2Hex[66][0] = 0x58;  
  KeyCode2Hex[67][0] = 0x05;  
  KeyCode2Hex[68][0] = 0x06;  
  KeyCode2Hex[69][0] = 0x04;  
  KeyCode2Hex[70][0] = 0x0C;  
  KeyCode2Hex[71][0] = 0x03;  
  KeyCode2Hex[72][0] = 0x0B;  
  KeyCode2Hex[73][0] = 0x83;  
  KeyCode2Hex[74][0] = 0x0A;  
  KeyCode2Hex[75][0] = 0x01;  
  KeyCode2Hex[76][0] = 0x09;  
  KeyCode2Hex[77][0] = 0x77;  
  KeyCode2Hex[78][0] = 0x7E;  
  KeyCode2Hex[79][0] = 0x6C;  
  KeyCode2Hex[80][0] = 0x75;  
  KeyCode2Hex[81][0] = 0x7D;  
  KeyCode2Hex[82][0] = 0x7B;  
  KeyCode2Hex[83][0] = 0x6B;  
  KeyCode2Hex[84][0] = 0x73;  
  KeyCode2Hex[85][0] = 0x74;  
  KeyCode2Hex[86][0] = 0x79;  
  KeyCode2Hex[87][0] = 0x69;  
  KeyCode2Hex[88][0] = 0x72;  
  KeyCode2Hex[89][0] = 0x7A;  
  KeyCode2Hex[90][0] = 0x70;  
  KeyCode2Hex[91][0] = 0x71;  
  KeyCode2Hex[95][0] = 0x78;  
  KeyCode2Hex[96][0] = 0x07;
  KeyCode2Hex[104][1] = 0x5A;
  KeyCode2Hex[105][1] = 0x14;
  KeyCode2Hex[106][1] = 0x4A;
  KeyCode2Hex[108][1] = 0x11;
  KeyCode2Hex[110][1] = 0x6C;
  KeyCode2Hex[111][1] = 0x75;
  KeyCode2Hex[112][1] = 0x7D;
  KeyCode2Hex[113][1] = 0x6B;
  KeyCode2Hex[114][1] = 0x74;
  KeyCode2Hex[115][1] = 0x69;
  KeyCode2Hex[116][1] = 0x72;
  KeyCode2Hex[117][1] = 0x7A;
  KeyCode2Hex[118][1] = 0x70;
  KeyCode2Hex[119][1] = 0x71;
  KeyCode2Hex[133][1] = 0x1F;
  KeyCode2Hex[134][1] = 0x27;
  KeyCode2Hex[135][1] = 0x2F;
}

void setup() {
  Serial.begin(9600);
  while (!Serial) {
	; // wait for serial port to connect. Needed for native USB port only
  }

  // prints title with ending line break
  Serial.println("ASCII Table ~ Character Map");

  // send the keyboard start up
  while(keyboard.write(0xAA)!=0);
  delay(10);

  setupKeyCode2Hex();
}

void ps2Delay()
{
  delay (10);
}

void ps2PressRelease(int code)
{
  if(KeyCode2Hex[code][0] == 0xE0) //extended keys?
  {
	keyboard.write(0xE0);
	ps2Delay();
	keyboard.write(KeyCode2Hex[code][1]);
	ps2Delay();  
	keyboard.write(0xE0);
	ps2Delay();
	keyboard.write(0xF0);
	ps2Delay();    
	keyboard.write(KeyCode2Hex[code][1]);
	ps2Delay();      
  }
  else
  {
	keyboard.write(KeyCode2Hex[code][0]);
	ps2Delay();  
	keyboard.write(0xF0);
	ps2Delay();    
	keyboard.write(KeyCode2Hex[code][0]);
	ps2Delay();      
  }
}

void loop() {
  unsigned char c;
  //if host device wants to send a command:
  if( (digitalRead(3)==LOW) || (digitalRead(2) == LOW)) {
	while(keyboard.read(&c)) ;
	keyboardcommand(c);
  }
  else{ //send keypresses accordingly using scancodes
	// secancodes: http://www.computer-engineering.org/ps2keyboard/scancodes2.html
	if (Serial.available() > 0) {
	  inByte = Serial.read();
	  Serial.println(inByte);    
	  ps2PressRelease(inByte);
	}
	/*
	keyboard.write(0x1C); // \
	keyboard.write(0xF0); //  |- send 'a'
	keyboard.write(0x1C); // /
	*/
	delay (20); // wait 1 second. Short delay causes freezing????
  }
}

Usually the code runs ok with delay greater than 300ms (still freezes though).

You should connect only one power source to the Arduino, not shorting 5V on USB and PS/2. If either voltage is used for connection detection, put it on an input pin.

I went ahead and unhooked the PS2 VCC since the board gets power from the USB connection anyways.

When the serial port does freeze. The TX status is stuck yellow according to the realterm.

Anyways, I completely commented out the following section

  if( (digitalRead(3)==LOW) || (digitalRead(2) == LOW)) {
	while(keyboard.read(&c)) ;
	keyboardcommand(c);
  }

Now everything seems to work even when I set that last delay to just 8ms. I'm trying to figure exactly what that bit code is there for in the first place.

Anyways, here is a bit more cleaned up code that works with 102 keys (missing pause and print keys just because I'm too lazy to deal with those specialized scan codes). It does have code I mention above omitted via setting startedFlag = 1 as a global variable.

#include "ps2dev.h" // to emulate a PS/2 device

PS2dev keyboard(3,2); // PS2dev object (2:data, 3:clock)
int enabled = 0; // pseudo variable for state of "keyboard"
int inByte = 0;         // incoming serial byte
int presskey = 0;
byte KeyCode2Hex[256][2];
int startedFlag = 0;

void ack() {
 //acknowledge commands
 while(keyboard.write(0xFA));
}

int keyboardcommand(int command) {
 unsigned char val;
 switch (command) {
 case 0xFF: //reset
   ack();
   //the while loop lets us wait for the host to be ready
   while(keyboard.write(0xAA)!=0);
   break;
 case 0xFE: //resend
   ack();
   break;
 case 0xF6: //set defaults
   //enter stream mode
   ack();
   break;
 case 0xF5: //disable data reporting
   //FM
   enabled = 0;
   ack();
   break;
 case 0xF4: //enable data reporting
   //FM
   enabled = 1;
   ack();
   break;
 case 0xF3: //set typematic rate
   ack();
   keyboard.read(&val); //do nothing with the rate
   ack();
   break;
 case 0xF2: //get device id
   ack();
   keyboard.write(0xAB);
   keyboard.write(0x83);
   break;
 case 0xF0: //set scan code set
   ack();
   keyboard.read(&val); //do nothing with the rate
   ack();
   break;
 case 0xEE: //echo
   //ack();
   keyboard.write(0xEE);
   break;
 case 0xED: //set/reset LEDs
   ack();
   keyboard.read(&val); //do nothing with the rate 
   ack();
   break;
 }
}

void setupKeyCode2Hex()
{
  // initialize everything to 0xE0 just because
  for (int i = 0; i < 256; i++)
  {
    for (int j = 0; j < 2; j++)
    {
      KeyCode2Hex[i][j] = 0xE0;
    }
  }
  
  KeyCode2Hex[9][0] = 0x76;
  KeyCode2Hex[10][0] = 0x45;
  KeyCode2Hex[11][0] = 0x16;    
  KeyCode2Hex[12][0] = 0x1E;    
  KeyCode2Hex[13][0] = 0x26;    
  KeyCode2Hex[14][0] = 0x25;    
  KeyCode2Hex[15][0] = 0x2E;    
  KeyCode2Hex[16][0] = 0x36;    
  KeyCode2Hex[17][0] = 0x3D;    
  KeyCode2Hex[18][0] = 0x3E;
  KeyCode2Hex[19][0] = 0x46;  
  KeyCode2Hex[20][0] = 0x4E;  
  KeyCode2Hex[21][0] = 0x55;  
  KeyCode2Hex[22][0] = 0x66;  
  KeyCode2Hex[23][0] = 0x0D;  
  KeyCode2Hex[24][0] = 0x15;  
  KeyCode2Hex[25][0] = 0x1D;  
  KeyCode2Hex[26][0] = 0x24;  
  KeyCode2Hex[27][0] = 0x2D;  
  KeyCode2Hex[28][0] = 0x2C;  
  KeyCode2Hex[29][0] = 0x35;  
  KeyCode2Hex[30][0] = 0x3C;  
  KeyCode2Hex[31][0] = 0x43;  
  KeyCode2Hex[32][0] = 0x44;  
  KeyCode2Hex[33][0] = 0x4D;  
  KeyCode2Hex[34][0] = 0x54;  
  KeyCode2Hex[35][0] = 0x5B;  
  KeyCode2Hex[36][0] = 0x5A;  
  KeyCode2Hex[37][0] = 0x14;  
  KeyCode2Hex[38][0] = 0x1C;  
  KeyCode2Hex[39][0] = 0x1B;  
  KeyCode2Hex[40][0] = 0x23;  
  KeyCode2Hex[41][0] = 0x2B;  
  KeyCode2Hex[42][0] = 0x34;  
  KeyCode2Hex[43][0] = 0x33;  
  KeyCode2Hex[44][0] = 0x3B;  
  KeyCode2Hex[45][0] = 0x42;  
  KeyCode2Hex[46][0] = 0x4B;  
  KeyCode2Hex[47][0] = 0x4C;  
  KeyCode2Hex[48][0] = 0x52;  
  KeyCode2Hex[49][0] = 0x0E;  
  KeyCode2Hex[50][0] = 0x12;  
  KeyCode2Hex[51][0] = 0x5D;  
  KeyCode2Hex[52][0] = 0x1A;  
  KeyCode2Hex[53][0] = 0x22;  
  KeyCode2Hex[54][0] = 0x21;  
  KeyCode2Hex[55][0] = 0x2A;  
  KeyCode2Hex[56][0] = 0x32;  
  KeyCode2Hex[57][0] = 0x31;  
  KeyCode2Hex[58][0] = 0x3A;  
  KeyCode2Hex[59][0] = 0x41;  
  KeyCode2Hex[60][0] = 0x49;  
  KeyCode2Hex[61][0] = 0x4A;  
  KeyCode2Hex[62][0] = 0x59;  
  KeyCode2Hex[63][0] = 0x7C;  
  KeyCode2Hex[64][0] = 0x11;  
  KeyCode2Hex[65][0] = 0x29;  
  KeyCode2Hex[66][0] = 0x58;  
  KeyCode2Hex[67][0] = 0x05;  
  KeyCode2Hex[68][0] = 0x06;  
  KeyCode2Hex[69][0] = 0x04;  
  KeyCode2Hex[70][0] = 0x0C;  
  KeyCode2Hex[71][0] = 0x03;  
  KeyCode2Hex[72][0] = 0x0B;  
  KeyCode2Hex[73][0] = 0x83;  
  KeyCode2Hex[74][0] = 0x0A;  
  KeyCode2Hex[75][0] = 0x01;  
  KeyCode2Hex[76][0] = 0x09;  
  KeyCode2Hex[77][0] = 0x77;  
  KeyCode2Hex[78][0] = 0x7E;  
  KeyCode2Hex[79][0] = 0x6C;  
  KeyCode2Hex[80][0] = 0x75;  
  KeyCode2Hex[81][0] = 0x7D;  
  KeyCode2Hex[82][0] = 0x7B;  
  KeyCode2Hex[83][0] = 0x6B;  
  KeyCode2Hex[84][0] = 0x73;  
  KeyCode2Hex[85][0] = 0x74;  
  KeyCode2Hex[86][0] = 0x79;  
  KeyCode2Hex[87][0] = 0x69;  
  KeyCode2Hex[88][0] = 0x72;  
  KeyCode2Hex[89][0] = 0x7A;  
  KeyCode2Hex[90][0] = 0x70;  
  KeyCode2Hex[91][0] = 0x71;  
  KeyCode2Hex[95][0] = 0x78;  
  KeyCode2Hex[96][0] = 0x07;
  KeyCode2Hex[104][1] = 0x5A;
  KeyCode2Hex[105][1] = 0x14;
  KeyCode2Hex[106][1] = 0x4A;
  KeyCode2Hex[108][1] = 0x11;
  KeyCode2Hex[110][1] = 0x6C;
  KeyCode2Hex[111][1] = 0x75;
  KeyCode2Hex[112][1] = 0x7D;
  KeyCode2Hex[113][1] = 0x6B;
  KeyCode2Hex[114][1] = 0x74;
  KeyCode2Hex[115][1] = 0x69;
  KeyCode2Hex[116][1] = 0x72;
  KeyCode2Hex[117][1] = 0x7A;
  KeyCode2Hex[118][1] = 0x70;
  KeyCode2Hex[119][1] = 0x71;
  KeyCode2Hex[133][1] = 0x1F;
  KeyCode2Hex[134][1] = 0x27;
  KeyCode2Hex[135][1] = 0x2F;
}

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // prints title with ending line break
  Serial.println("ASCII Table ~ Character Map");

  // send the keyboard start up
  while(keyboard.write(0xAA)!=0);
  delay(10);

  setupKeyCode2Hex();
}

void ps2Delay()
{
  delay (8);
}

void ps2Press(int code)
{
  if(KeyCode2Hex[code][0] == 0xE0) //extended keys?
  {
    keyboard.write(0xE0);
    ps2Delay();
    keyboard.write(KeyCode2Hex[code][1]);
    ps2Delay();     
  }
  else
  {
    keyboard.write(KeyCode2Hex[code][0]);
    ps2Delay();       
  }
}

void ps2Release(int code)
{
  if(KeyCode2Hex[code][0] == 0xE0) //extended keys?
  {
    keyboard.write(0xE0);
    ps2Delay();
    keyboard.write(0xF0);
    ps2Delay();    
    keyboard.write(KeyCode2Hex[code][1]);
    ps2Delay();      
  }
  else
  { 
    keyboard.write(0xF0);
    ps2Delay();    
    keyboard.write(KeyCode2Hex[code][0]);
    ps2Delay();      
  }
}

void ps2PressRelease(int code)
{
  ps2Press(code);
  ps2Release(code);
}

void loop() {
  unsigned char c;
  //if host device wants to send a command:
  if (startedFlag == 1)
  {  
    if( (digitalRead(3)==LOW) || (digitalRead(2) == LOW)) 
    {
      startedFlag = 1;
      while(keyboard.read(&c)) ;
      keyboardcommand(c);
    }
  }
  else{ //send keypresses accordingly using scancodes
    // secancodes: http://www.computer-engineering.org/ps2keyboard/scancodes2.html
    if (Serial.available() > 0) {
      inByte = Serial.read();
      //Serial.println(inByte);    
      if(inByte == 1) // key press
      {
        inByte = Serial.read();
        while (inByte == -1)
        {
          inByte = Serial.read();
        }
        ps2Press(inByte);
        //Serial.println("Press");          
      }
      else if (inByte == 2) // key release
      {   
        inByte = Serial.read();
        while (inByte == -1)
        {
          inByte = Serial.read();
        }
        ps2Release(inByte);        
        //Serial.println("Release");          
      }
    }
    /*
    keyboard.write(0x1C); // \
    keyboard.write(0xF0); //  |- send 'a'
    keyboard.write(0x1C); // /
    */
    //delay (10); // wait 1 second
  }
}