commit a8eccba5db582cd374add9ef53588ff001099e2c Author: flovenol Date: Sat Sep 28 00:15:00 2019 +0200 initial commit diff --git a/Keyboard.ino b/Keyboard.ino new file mode 100644 index 0000000..ee5acf4 --- /dev/null +++ b/Keyboard.ino @@ -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(); + } +} diff --git a/KeyboardRemapper.ino b/KeyboardRemapper.ino new file mode 100644 index 0000000..6856ec6 --- /dev/null +++ b/KeyboardRemapper.ino @@ -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; + } + +} diff --git a/Macintosh.ino b/Macintosh.ino new file mode 100644 index 0000000..a8b8bbc --- /dev/null +++ b/Macintosh.ino @@ -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); + } +} diff --git a/Mapping.ino b/Mapping.ino new file mode 100644 index 0000000..0b5442e --- /dev/null +++ b/Mapping.ino @@ -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; + } +} diff --git a/Reset.ino b/Reset.ino new file mode 100644 index 0000000..2acec78 --- /dev/null +++ b/Reset.ino @@ -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; +}