2016-11-24 12:54:25 +00:00
|
|
|
#include "PS2Keyboard.h"
|
|
|
|
|
2016-11-25 22:25:19 +00:00
|
|
|
//#define SERIAL_DEBUG
|
|
|
|
|
|
|
|
#define NUMPAD 0x0100
|
|
|
|
#define NUMPAD2 0x0200
|
|
|
|
|
|
|
|
#define PS2_DATA_PIN 3
|
|
|
|
#define PS2_CLOCK_PIN 2
|
2016-11-24 12:54:25 +00:00
|
|
|
|
|
|
|
#define MAC_DATA_PIN 5
|
|
|
|
#define MAC_CLOCK_PIN 6
|
|
|
|
|
|
|
|
#define NULL_TRANSITION 0x7b
|
2016-11-26 07:06:36 +00:00
|
|
|
#define CAPS_LOCK 0x73
|
2016-11-24 12:54:25 +00:00
|
|
|
|
|
|
|
PS2Keyboard keyboard;
|
2016-11-25 22:25:19 +00:00
|
|
|
unsigned int scanCodesTable[256];
|
|
|
|
unsigned int extScanCodesTable[256];
|
2016-11-24 12:54:25 +00:00
|
|
|
|
|
|
|
void setup() {
|
2016-11-25 22:25:19 +00:00
|
|
|
#ifdef SERIAL_DEBUG
|
|
|
|
Serial.begin(9600);
|
|
|
|
#endif
|
2016-11-24 12:54:25 +00:00
|
|
|
initScancodes();
|
2016-11-24 22:20:20 +00:00
|
|
|
|
2016-11-24 12:54:25 +00:00
|
|
|
keyboard.begin(PS2_DATA_PIN, PS2_CLOCK_PIN);
|
2016-11-24 22:20:20 +00:00
|
|
|
|
2016-11-24 12:54:25 +00:00
|
|
|
pinMode(LED_BUILTIN, OUTPUT);
|
|
|
|
pinMode(MAC_CLOCK_PIN, OUTPUT);
|
|
|
|
pinMode(MAC_DATA_PIN, INPUT_PULLUP);
|
2016-11-25 22:25:19 +00:00
|
|
|
|
2016-11-24 22:20:20 +00:00
|
|
|
waitForInitSignal();
|
2016-11-24 12:54:25 +00:00
|
|
|
delayMicroseconds(180);
|
|
|
|
}
|
|
|
|
|
2016-11-24 22:20:20 +00:00
|
|
|
void waitForInitSignal() {
|
|
|
|
unsigned long t = millis();
|
|
|
|
boolean led = false;
|
|
|
|
while (digitalRead(MAC_CLOCK_PIN) != LOW) {
|
|
|
|
if (millis() - t > 100) {
|
|
|
|
t = millis();
|
|
|
|
led = !led;
|
|
|
|
digitalWrite(LED_BUILTIN, led);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-24 12:54:25 +00:00
|
|
|
void loop() {
|
2016-11-25 22:25:19 +00:00
|
|
|
switch (readCmd()) {
|
2016-11-24 12:54:25 +00:00
|
|
|
case 0x10:
|
|
|
|
inquiry();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x14: // instant
|
2016-11-25 22:25:19 +00:00
|
|
|
sendKey(getKeyTransition());
|
2016-11-24 12:54:25 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x16: // model number
|
2016-11-25 22:25:19 +00:00
|
|
|
sendByte(0x0b);
|
2016-11-24 12:54:25 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x36: // test
|
|
|
|
sendByte(0x7d);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-26 16:19:44 +00:00
|
|
|
// reads the command, operates the diagnostic LED and switches pin mode back to OUTPUT
|
2016-11-25 22:25:19 +00:00
|
|
|
byte readCmd() {
|
|
|
|
digitalWrite(LED_BUILTIN, LOW);
|
|
|
|
pinMode(MAC_DATA_PIN, INPUT_PULLUP);
|
|
|
|
delayMicroseconds(20);
|
|
|
|
|
|
|
|
while (digitalRead(MAC_DATA_PIN) != LOW);
|
2016-11-26 07:06:36 +00:00
|
|
|
delayMicroseconds(400); // this is apparently required so we don't lose the first digit
|
2016-11-25 22:25:19 +00:00
|
|
|
byte cmd = readByte();
|
|
|
|
while (digitalRead(MAC_DATA_PIN) != HIGH);
|
|
|
|
|
|
|
|
digitalWrite(LED_BUILTIN, HIGH);
|
|
|
|
pinMode(MAC_DATA_PIN, OUTPUT);
|
|
|
|
delayMicroseconds(20);
|
|
|
|
return cmd;
|
|
|
|
}
|
|
|
|
|
2016-11-24 12:54:25 +00:00
|
|
|
void inquiry() {
|
|
|
|
unsigned long start = millis();
|
|
|
|
while ((millis() - start) < 250) {
|
2016-11-25 22:25:19 +00:00
|
|
|
int key = getKeyTransition();
|
2016-11-24 12:54:25 +00:00
|
|
|
if (key != NULL_TRANSITION) {
|
2016-11-25 22:25:19 +00:00
|
|
|
sendKey(key);
|
2016-11-24 12:54:25 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sendByte(NULL_TRANSITION);
|
|
|
|
}
|
|
|
|
|
2016-11-25 22:25:19 +00:00
|
|
|
void sendKey(unsigned int key) {
|
|
|
|
if (key & NUMPAD) {
|
|
|
|
sendByte(0x79); readCmd();
|
|
|
|
sendByte(key);
|
|
|
|
} else if (key & NUMPAD2) {
|
|
|
|
sendByte(0x71); readCmd();
|
|
|
|
sendByte(0x79); readCmd();
|
|
|
|
sendByte(key);
|
|
|
|
} else {
|
|
|
|
sendByte(key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-24 12:54:25 +00:00
|
|
|
byte readByte() {
|
|
|
|
byte b = 0;
|
|
|
|
for (byte i = 0; i < 8; i++) {
|
|
|
|
digitalWrite(MAC_CLOCK_PIN, LOW);
|
|
|
|
delayMicroseconds(180);
|
|
|
|
digitalWrite(MAC_CLOCK_PIN, HIGH);
|
2016-11-25 22:25:19 +00:00
|
|
|
delayMicroseconds(80);
|
2016-11-24 12:54:25 +00:00
|
|
|
b = (b << 1) | digitalRead(MAC_DATA_PIN);
|
2016-11-25 22:25:19 +00:00
|
|
|
delayMicroseconds(140);
|
2016-11-24 12:54:25 +00:00
|
|
|
}
|
2016-11-25 22:25:19 +00:00
|
|
|
#ifdef SERIAL_DEBUG
|
|
|
|
Serial.print(b, HEX);
|
|
|
|
Serial.print(" -> ");
|
|
|
|
#endif
|
2016-11-24 12:54:25 +00:00
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
|
|
|
void sendByte(byte b) {
|
2016-11-25 22:25:19 +00:00
|
|
|
#ifdef SERIAL_DEBUG
|
|
|
|
Serial.print(b, HEX);
|
|
|
|
Serial.println();
|
|
|
|
#endif
|
2016-11-24 12:54:25 +00:00
|
|
|
for (byte m = 128; m > 0; m >>= 1) {
|
2016-11-25 22:25:19 +00:00
|
|
|
digitalWrite(MAC_DATA_PIN, !(b & m) ? LOW : HIGH);
|
2016-11-24 12:54:25 +00:00
|
|
|
delayMicroseconds(40);
|
|
|
|
digitalWrite(MAC_CLOCK_PIN, LOW);
|
2016-11-25 22:25:19 +00:00
|
|
|
delayMicroseconds(120);
|
2016-11-24 12:54:25 +00:00
|
|
|
digitalWrite(MAC_CLOCK_PIN, HIGH);
|
2016-11-25 22:25:19 +00:00
|
|
|
delayMicroseconds(170);
|
2016-11-24 12:54:25 +00:00
|
|
|
}
|
2016-11-25 22:25:19 +00:00
|
|
|
digitalWrite(MAC_DATA_PIN, HIGH);
|
2016-11-24 12:54:25 +00:00
|
|
|
}
|
|
|
|
|
2016-11-25 22:25:19 +00:00
|
|
|
unsigned int getKeyTransition() {
|
2016-11-24 12:54:25 +00:00
|
|
|
byte c = keyboard.getScanCode();
|
|
|
|
if (c == 0) {
|
|
|
|
return NULL_TRANSITION;
|
|
|
|
} else if (c == 0xf0) {
|
2016-11-25 22:25:19 +00:00
|
|
|
return translate(waitForScanCode(), false, true);
|
2016-11-24 12:54:25 +00:00
|
|
|
} else if (c == 0xe0) {
|
|
|
|
return getExtendedTransition();
|
|
|
|
} else {
|
|
|
|
return translate(c, false, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-25 22:25:19 +00:00
|
|
|
unsigned int getExtendedTransition() {
|
|
|
|
byte c = waitForScanCode();
|
2016-11-24 12:54:25 +00:00
|
|
|
if (c == 0xf0) {
|
2016-11-25 22:25:19 +00:00
|
|
|
return translate(waitForScanCode(), true, true);
|
2016-11-24 12:54:25 +00:00
|
|
|
} else {
|
|
|
|
return translate(c, true, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-25 22:25:19 +00:00
|
|
|
unsigned int translate(byte scanCode, boolean extended, boolean released) {
|
|
|
|
unsigned int translated = extended ? extScanCodesTable[scanCode] : scanCodesTable[scanCode];
|
2016-11-24 12:54:25 +00:00
|
|
|
if (translated == NULL_TRANSITION) {
|
|
|
|
return NULL_TRANSITION;
|
|
|
|
} else if (released) {
|
2016-11-26 07:06:36 +00:00
|
|
|
if (translated == CAPS_LOCK) {
|
|
|
|
return handleCapsLockRelease();
|
|
|
|
} else {
|
|
|
|
return translated | 0x80;
|
|
|
|
}
|
2016-11-24 12:54:25 +00:00
|
|
|
} else {
|
|
|
|
return translated;
|
|
|
|
}
|
|
|
|
}
|
2016-11-25 22:25:19 +00:00
|
|
|
|
2016-11-26 16:19:44 +00:00
|
|
|
boolean capsLockPressed = false;
|
|
|
|
|
2016-11-26 07:06:36 +00:00
|
|
|
unsigned int handleCapsLockRelease() {
|
|
|
|
if (capsLockPressed) {
|
|
|
|
capsLockPressed = false;
|
|
|
|
return CAPS_LOCK | 0x80;
|
|
|
|
} else {
|
|
|
|
capsLockPressed = true;
|
|
|
|
return NULL_TRANSITION;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-25 22:25:19 +00:00
|
|
|
byte waitForScanCode() {
|
|
|
|
while (true) {
|
|
|
|
byte s = keyboard.getScanCode();
|
|
|
|
if (s) {
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|