Using an Arduino as a PS/2 Keyboard

All the research I've done has shown me a lot of people converting PS/2 to USB with Arduino, and even searching for anyone trying to make a PS/2 keyboard has given me the same results. It is an old interface so I can understand this, but even now a lot of gaming and lower-end motherboards come with PS/2 for wither the latency or legacy purposes.

I'd just like to know if it's even possible to do this or if there's a better way to do it without a microcontroller.

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

// Orange = 2
// Blue = 3
// Red = 5V (3 in)
// Black = GND (4 in)
// EXT Power, USB for COM only

PS2dev keyboard(3,2); // PS2dev object (2:data, 3:clock)
int enabled = 0; // pseudo variable for state of "keyboard"
boolean serialConnected = false;
int incomingByte = 0;

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

int kbdCmd(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 connectHost() {
  while (Serial.available() <= 0) {
    Serial.print('A');   // send a capital A
    delay(300);
  }
}

void setup() {
  pinMode(13, OUTPUT);
  //establish serial connection with host
  Serial.begin(9600);
  // establish ps/2 connection with target
  while(keyboard.write(0xAA)!=0){
    digitalWrite(13, HIGH);
    delay(500); 
    digitalWrite(13, LOW);
    delay(500);
  }
  delay(100);  
  
  connectHost();
  Serial.println("\nSerial Host Connected");
  Serial.flush();
}

void loop() {
  unsigned char c;
  if( (digitalRead(3)==LOW) || (digitalRead(2) == LOW)) {
    if(digitalRead(3)==LOW){
      Serial.println("pin 3  is LOW");
    } else {
      Serial.println("pin 2 is LOW");
    }
    while(keyboard.read(&c));
    kbdCmd(c);
    Serial.print("Target: 0x");
    Serial.println(c, HEX);
  }  
  else {//if host device wants to send a command:
    //echo ASCII code from terminal and write to ps/2
    if(Serial.available() > 0) {
      incomingByte = Serial.read();
      keyboard.write(incomingByte);      
      Serial.print("Host: 0x");
      Serial.print(incomingByte, HEX);
      Serial.print(" ");
      Serial.print(incomingByte);
      Serial.print(" ");
      Serial.println(incomingByte, BIN);
    }
  }
}

On this page at the very bottom there is a listing of a possible initialization sequence. Start by comparing this initialization to that one.
http://www.computer-engineering.org/ps2keyboard/

It can be used to act as a mouse or a keyboard.
http://playground.arduino.cc/ComponentLib/Ps2mouse

//KBD stuff
#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"
unsigned char c;  //char stores data recieved from computer for KBD

//Sonar stuff
const int numReadings = 5;   // set a variable for the number of readings to take
int index = 0;                // the index of the current reading
int total = 0;                // the total of all readings
int average = 0;              // the average
int oldAverage = 0;           // the old average
int echoPin = 6;              // the SRF05's echo pin
int trigPin = 7;              // the SRF05's init pin
unsigned long pulseTime = 0;  // variable for reading the pulse
unsigned long distance = 0;   // variable for storing distance

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 setup()
{
  // send the keyboard start up
  while(keyboard.write(0xAA)!=0);
  delay(10);
  // make the init pin an output:
  pinMode(trigPin, OUTPUT);
  // make the echo pin an input:
  pinMode(echoPin, INPUT);
  // initialize the serial port:
  Serial.begin(9600);
}

void loop()
{
  // loop for a number of readings on the SRF-05 to get an average to smooth the results. Much like all my other examples
  for (index = 0; index<=numReadings;index++)
  {
    digitalWrite(trigPin, HIGH);
    delay(1);
    digitalWrite(trigPin, LOW);
    pulseTime = pulseIn(echoPin, HIGH);
    distance = pulseTime/58;
    total = total + distance;
    delay(5);
  }
  // store the previous reading
  oldAverage = average;
  // store the current reading
  average = total/numReadings;
  // debug to check for spikes in the sensor etc..
  Serial.println(average);

  //if host device wants to send a command:
  if( (digitalRead(3)==LOW) || (digitalRead(2) == LOW))
  {
    while(keyboard.read(&c)) ;
    keyboardcommand(c);
  }
  else
  {
    // now the fun part...
    // if my distance is less than 5...
    if (average <=5)
    {
      int x = 0;
      if(x<=5)  //how many times to press tab
      {
        Serial.println("TAB+ALT");
        keyboard.write(0x11); //send ALT
        keyboard.write(0x0D); //then send Tab

        keyboard.write(0xF0);  //tab break
        keyboard.write(0x0D);  //...
        delay(700); // wait so doesnt tab too fast

        if(x<=5)
        {
          keyboard.write(0x0D); //send another Tab
          keyboard.write(0xF0);  //tab break
          keyboard.write(0x0D);  //...         
          delay(700);
        }
      }
      else //x is nolonger <=5 must be 6, set x to 0, and end all keys
      {
        x=0; //reset tab counter
        keyboard.write(0xF0);  //tab break
        keyboard.write(0x0D);  //...

        keyboard.write(0xF0);  //alt break
        keyboard.write(0x11);  //...

      }
      x++; //add 1 to tab counter
    }
    else // otherwise if my hand is higher
    {
      // check to see if my hand is in the registered space above the sensor
      if (average <=20 && average >=10 && oldAverage >=10)
      {
        // the below statement is our sensitive the readings are so if the current and previous readings are different with a tolerance of +/
        //we can look at the direction of movement
        if ((average != oldAverage) && (average+1 != oldAverage) && (average-1 != oldAverage))
        {
          // if the current reading is higher than the previous, then my hand is moving upwards
          if (average > oldAverage)
          {
            Serial.println("Sound up");
            keyboard.write(0xE0); //make volume +
            keyboard.write(0x32); //...
            keyboard.write(0xE0); //break
            keyboard.write(0xF0); //...
            keyboard.write(0x32); //...
            delay(150);  //wait so it doesnt change volume rapidly
          }
          else
          {
            // otherwise if it is below then my hand is moving downwards
            if (average < oldAverage && oldAverage <=20)
            {
              Serial.println("Sound down");
              keyboard.write(0xE0); //make volume -
              keyboard.write(0x21); //...
              keyboard.write(0xE0); //break
              keyboard.write(0xF0); //...
              keyboard.write(0x21); //...
              delay(150);
            }
          }
          // otherwise my hand must be stationary so check where it is.
        }
        else
        {
          // if my hand is stationary between 10 and 15 cms away from the sensor
          if (average >= 10 && average <=15)
          {
            Serial.println("Copy");
            keyboard.write(0x14); //make CNTRL
            keyboard.write(0x21); //make 'c'

            keyboard.write(0xF0); //break 'c' break
            keyboard.write(0x21); //...
            keyboard.write(0xF0); //break FO capital o) CNTRL break
            keyboard.write(0x14); //...
            delay(250);
          }
          else
          {
            // if my hand is a bit higher up...
            if (average >= 16 && average <=20)
            {
              Serial.println("Paste");
              keyboard.write(0x14); //make CNTRL
              keyboard.write(0x2A); //make 'v'

              keyboard.write(0xF0); //break 'v' break
              keyboard.write(0x2A); //...
              keyboard.write(0xF0); //break FO capital o) CNTRL break
              keyboard.write(0x14); //...
              delay(250);
            }
          }
        }
      }
    }
  }
  // clear our index and total for the next reading just in case
  if (index >= numReadings)
  {
    index = 0;
    total = 0;
  }
}

thnikk:
if there’s a better way to do it without a microcontroller.

If you want to do it without a microcontroller, you can do it with FPGA.

You can buy a PS2 to USB converter for a lot less (about 1/4 of the Uno) than the price of an Arduino! It takes both the keyboard and the mouse.

If you still want to DIY it the you need a Leonardo or the Yun.

Mark

holmes4: You can buy a PS2 to USB converter for a lot less (about 1/4 of the UNO) than the price of an Arduino! It takes both the keyboard and the mouse.

I have a funny suspicion that you understood the request backwards.

Mind you, that's not surprising!