initial commit

This commit is contained in:
flovenol 2019-09-28 00:15:00 +02:00 committed by flowenol
commit a8eccba5db
5 changed files with 501 additions and 0 deletions

97
Keyboard.ino Normal file
View File

@ -0,0 +1,97 @@
void send_data_to_kbd(byte data, kbd_state next_state) {
if (!kbd_clock_detected) {
pinMode(DATA_KBD, OUTPUT);
digitalWrite(DATA_KBD, LOW);
kbd_clock_read = digitalRead(CLK_KBD);
if (kbd_clock_read == LOW) {
kbd_clock_detected = true;
kbd_clock_state=LOW;
} else {
check_kbd_clock_start();
return;
}
}
digitalWrite(DATA_KBD, data>>(7 - kbd_clock_count) & 1);
kbd_clock_read = digitalRead(CLK_KBD);
if (kbd_clock_read != kbd_clock_state) {
kbd_clock_transition_start = 0;
kbd_clock_state = kbd_clock_read;
if (kbd_clock_state == LOW) {
kbd_clock_count++;
}
if (kbd_clock_state == HIGH && kbd_clock_count == 7) {
digitalWrite(DATA_KBD, HIGH);
kbd_reset();
keyboard_state = next_state;
}
} else {
check_clock_transition();
}
}
void read_data_from_kbd(kbd_state next_state) {
if (!kbd_clock_detected) {
pinMode(DATA_KBD, INPUT);
kbd_clock_read = digitalRead(CLK_KBD);
if (kbd_clock_read == LOW) {
kbd_clock_detected = true;
kbd_clock_state=LOW;
} else {
check_kbd_clock_start();
return;
}
}
kbd_clock_read = digitalRead(CLK_KBD);
if (kbd_clock_read != kbd_clock_state) {
kbd_clock_transition_start = 0;
kbd_clock_state = kbd_clock_read;
if (kbd_clock_state == HIGH) {
if (digitalRead(DATA_KBD) == HIGH) {
kbd_data_read |= 1<<(7 - kbd_clock_count);
}
}
if (kbd_clock_state == LOW) {
kbd_clock_count++;
}
if (kbd_clock_state == HIGH && kbd_clock_count == 7) {
if (keyboard_state == READ_MODEL_NUMBER) {
model_number = kbd_data_read;
} else if (kbd_data_read != TEST_ACK && kbd_data_read != TEST_NAK) {
kbd_last_data_read_index = (kbd_last_data_read_index + 1) % 4;
kbd_last_data_read[kbd_last_data_read_index] = kbd_data_read;
}
/*if (kbd_data_read != NULL_TRANSITION && kbd_data_read != TEST_ACK) {
Serial.print("Data read: ");
Serial.println(kbd_data_read, BIN);
}*/
kbd_reset();
keyboard_state = next_state;
}
} else {
check_clock_transition();
}
}
void check_kbd_clock_start() {
if (kbd_clock_start == 0) {
kbd_clock_start = millis();
} else if (millis() - kbd_clock_start >= CLOCK_START_MSEC) {
//Serial.println("Failed to receive clock signal, resetting");
kbd_hard_reset();
}
}
void check_clock_transition() {
if (kbd_clock_transition_start == 0) {
kbd_clock_transition_start = micros();
} else if (micros() - kbd_clock_transition_start >= CLOCK_TRANSITION_USEC) {
//Serial.println("Failed to receive proper clock signal, resetting");
kbd_hard_reset();
}
}

120
KeyboardRemapper.ino Normal file
View File

@ -0,0 +1,120 @@
#define CLK_MAC 15
#define DATA_MAC 14
#define CLK_KBD 16
#define DATA_KBD 10
#define CLOCK_START_MSEC 500
#define CLOCK_TRANSITION_USEC 300
#define CLOCK_READ_LOW_USEC 180
#define CLOCK_READ_HIGH_USEC 200
#define CLOCK_WRITE_LOW_USEC 180
#define CLOCK_WRITE_HIGH_USEC 200
#define MAC_RESP_DELAY_MSEC 240
#define MAC_DETECT_READY_USEC 300
// command constants
const byte MODEL_NUMBER_CMD = 0x16;
const byte TEST_CMD = 0x36;
const byte INQUIRY_CMD = 0x10;
const byte INSTANT_CMD = 0x14;
// command response constants
const byte NULL_TRANSITION = 0x7B;
const byte TEST_ACK = 0x7D;
const byte TEST_NAK = 0x77;
const byte BAD_CMD = 0x00;
enum kbd_state {
REQUIRE_MODEL_NUMBER,
READ_MODEL_NUMBER,
REQUIRE_TEST,
READ_TEST,
REQUIRE_INQUIRY,
READ_INQUIRY,
DELAY_INQUIRY
};
enum mac_state {
DETECT_READY_FOR_CMD,
READ_CMD,
DETECT_READY_FOR_DATA,
WRITE_DATA
};
// keyboard state variables
kbd_state keyboard_state = REQUIRE_MODEL_NUMBER;
boolean kbd_clock_detected;
boolean kbd_clock_state;
boolean kbd_clock_read;
unsigned int kbd_clock_count;
unsigned long kbd_clock_start;
unsigned long kbd_clock_transition_start;
unsigned long kbd_delay_start;
byte kbd_data_read;
byte kbd_last_data_read[4];
short kbd_last_data_read_index = -1;
byte model_number;
// macintosh state variables
mac_state macintosh_state = DETECT_READY_FOR_CMD;
boolean mac_ready_detected;
unsigned long mac_delay_start;
boolean mac_clock_started;
boolean mac_clock_state;
unsigned int mac_clock_count;
unsigned long mac_clock_delay_start;
unsigned long mac_cmd_response_delay_start;
byte mac_data_read;
byte last_mac_cmd;
byte mac_data_write;
void setup() {
pinMode(CLK_MAC, OUTPUT);
digitalWrite(CLK_MAC, HIGH);
pinMode(CLK_KBD, INPUT);
kbd_hard_reset();
//Serial.begin(19200);
}
void loop() {
switch (keyboard_state) {
case REQUIRE_MODEL_NUMBER:
send_data_to_kbd(MODEL_NUMBER_CMD, READ_MODEL_NUMBER);
break;
case READ_MODEL_NUMBER:
read_data_from_kbd(REQUIRE_TEST);
break;
case REQUIRE_TEST:
send_data_to_kbd(TEST_CMD, READ_TEST);
break;
case READ_TEST:
read_data_from_kbd(REQUIRE_INQUIRY);
break;
case REQUIRE_INQUIRY:
send_data_to_kbd(INQUIRY_CMD, READ_INQUIRY);
break;
case READ_INQUIRY:
read_data_from_kbd(REQUIRE_INQUIRY);
break;
}
switch (macintosh_state) {
case DETECT_READY_FOR_CMD:
mac_detect_ready_to_send_cmd();
break;
case READ_CMD:
mac_read_data();
break;
case DETECT_READY_FOR_DATA:
mac_detect_ready_to_recv_data();
break;
case WRITE_DATA:
mac_write_data();
break;
}
}

158
Macintosh.ino Normal file
View File

@ -0,0 +1,158 @@
void mac_detect_ready_to_send_cmd() {
if (!mac_ready_detected) {
pinMode(DATA_MAC, INPUT);
if (digitalRead(DATA_MAC) == LOW) {
mac_ready_detected = true;
}
} else {
if (mac_delay_start == 0) {
mac_delay_start = micros();
}
if (micros() - mac_delay_start >= MAC_DETECT_READY_USEC) {
mac_reset();
macintosh_state = READ_CMD;
}
}
}
void mac_detect_ready_to_recv_data() {
if (mac_delay_start == 0) {
mac_delay_start = micros();
pinMode(DATA_MAC, INPUT);
}
if (micros() - mac_delay_start >= 400) {
if (digitalRead(DATA_MAC) == HIGH) {
macintosh_state = WRITE_DATA;
} else {
macintosh_state = DETECT_READY_FOR_CMD;
}
mac_reset();
}
}
void mac_read_data() {
if (!mac_clock_started) {
pinMode(DATA_MAC, INPUT);
mac_clock_state = LOW;
mac_clock_started = true;
}
if (mac_clock_state == LOW) {
if (mac_clock_delay_start == 0) {
digitalWrite(CLK_MAC, LOW);
mac_clock_delay_start = micros();
}
if (micros() - mac_clock_delay_start >= CLOCK_READ_LOW_USEC) {
mac_clock_state = HIGH;
mac_clock_delay_start = 0;
}
}
if (mac_clock_state == HIGH) {
if (mac_clock_delay_start == 0) {
digitalWrite(CLK_MAC, HIGH);
mac_clock_delay_start = micros();
if (digitalRead(DATA_MAC) == HIGH) {
mac_data_read |= 1<<(7 - mac_clock_count);
}
}
if (micros() - mac_clock_delay_start >= CLOCK_READ_HIGH_USEC) {
if (mac_clock_count < 7) {
mac_clock_state = LOW;
mac_clock_delay_start = 0;
mac_clock_count++;
} else {
last_mac_cmd = mac_data_read;
mac_reset();
macintosh_state = DETECT_READY_FOR_DATA;
}
}
}
}
void mac_write_data() {
if (!mac_clock_started) {
if (last_mac_cmd == INQUIRY_CMD && kbd_last_data_read_index == -1) {
if (mac_cmd_response_delay_start == 0) {
mac_cmd_response_delay_start = millis();
}
if (millis() - mac_cmd_response_delay_start >= MAC_RESP_DELAY_MSEC) {
goto WRITE_MAC;
} else {
return;
}
} else {
WRITE_MAC:
mac_data_write = mac_cmd_response_data();
if (mac_data_write == BAD_CMD) {
mac_reset();
macintosh_state = DETECT_READY_FOR_CMD;
return;
} else {
pinMode(DATA_MAC, OUTPUT);
mac_clock_state = LOW;
mac_clock_started = true;
}
}
}
if (mac_clock_state == LOW) {
if (mac_clock_delay_start == 0) {
digitalWrite(CLK_MAC, LOW);
mac_clock_delay_start = micros();
digitalWrite(DATA_MAC, mac_data_write>>(7 - mac_clock_count) & 1 > 0);
}
if (micros() - mac_clock_delay_start >= CLOCK_WRITE_LOW_USEC) {
mac_clock_state = HIGH;
mac_clock_delay_start = 0;
}
}
if (mac_clock_state == HIGH) {
if (mac_clock_delay_start == 0) {
digitalWrite(CLK_MAC, HIGH);
mac_clock_delay_start = micros();
}
if (micros() - mac_clock_delay_start >= CLOCK_WRITE_HIGH_USEC) {
if (mac_clock_count < 7) {
mac_clock_state = LOW;
mac_clock_delay_start = 0;
mac_clock_count++;
} else {
digitalWrite(DATA_MAC, HIGH);
mac_reset();
macintosh_state = DETECT_READY_FOR_CMD;
}
}
}
}
byte mac_cmd_response_data() {
switch (last_mac_cmd) {
case MODEL_NUMBER_CMD:
return model_number;
case TEST_CMD:
return TEST_ACK;
case INSTANT_CMD:
case INQUIRY_CMD:
if (kbd_last_data_read_index == -1) {
return NULL_TRANSITION;
}
byte inquiry_data = kbd_last_data_read[0];
kbd_last_data_read[0] = kbd_last_data_read[1];
kbd_last_data_read[1] = kbd_last_data_read[2];
kbd_last_data_read[2] = kbd_last_data_read[3];
kbd_last_data_read_index -= 1;
return remap(inquiry_data);
}
}

98
Mapping.ino Normal file
View File

@ -0,0 +1,98 @@
byte remap(byte kbd_data) {
switch (kbd_data) {
// Return
case 0xD5:
return 0xC9;
case 0x55:
return 0x49;
// backslash
case 0xC9:
return 0xD5;
case 0x49:
return 0x55;
// space
case 0xE9:
return 0xE3;
case 0x69:
return 0x63;
// Enter
case 0xE3:
return 0xE9;
case 0x63:
return 0x69;
// z
case 0xA1:
return 0x8D;
case 0x21:
return 0x0D;
// y
case 0x8F:
return 0xA1;
case 0x0F:
return 0x21;
// x
case 0x91:
return 0x8F;
case 0x11:
return 0x0F;
// c
case 0x93:
return 0x91;
case 0x13:
return 0x11;
// v
case 0x97:
return 0x93;
case 0x17:
return 0x13;
// b
case 0xDB:
return 0x97;
case 0x5B:
return 0x17;
// n
case 0xDD:
return 0xDB;
case 0x5D:
return 0x5B;
// m
case 0xD7:
return 0xDD;
case 0x57:
return 0x5D;
// .
case 0xD9:
return 0xDF;
case 0x59:
return 0x5F;
// /
case 0x95:
return 0xD9;
case 0x15:
return 0x59;
// ,
case 0xDF:
return 0xD7;
case 0x5F:
return 0x57;
default:
return kbd_data;
}
}

28
Reset.ino Normal file
View File

@ -0,0 +1,28 @@
void kbd_hard_reset() {
kbd_reset();
model_number = BAD_CMD;
kbd_last_data_read_index = -1;
keyboard_state = REQUIRE_MODEL_NUMBER;
}
void kbd_reset() {
kbd_clock_count = 0;
kbd_clock_detected = false;
kbd_clock_state = HIGH;
kbd_clock_start = 0;
kbd_clock_transition_start = 0;
kbd_delay_start = 0;
kbd_data_read = 0x00;
}
void mac_reset() {
mac_ready_detected = false;
mac_delay_start = 0;
mac_clock_state = HIGH;
mac_clock_started = false;
mac_clock_count = 0;
mac_clock_delay_start = 0;
mac_cmd_response_delay_start = 0;
mac_data_read = 0x00;
mac_data_write = 0x00;
}