mirror of
https://github.com/flowenol/MacintoshKeyboardRemapper.git
synced 2024-11-21 16:31:00 +00:00
initial commit
This commit is contained in:
commit
a8eccba5db
97
Keyboard.ino
Normal file
97
Keyboard.ino
Normal 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
120
KeyboardRemapper.ino
Normal 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
158
Macintosh.ino
Normal 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
98
Mapping.ino
Normal 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
28
Reset.ino
Normal 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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user