Add arduino skecthes
This commit is contained in:
194
arduino/kbd/kbd.ino
Normal file
194
arduino/kbd/kbd.ino
Normal file
@@ -0,0 +1,194 @@
|
||||
// keyboard wiring diagram: https://www.minuszerodegrees.net/5150/misc/5150_keyboard_reset.jpg
|
||||
|
||||
constexpr int kClockPin = PC6;
|
||||
constexpr int kDataPin = PC4;
|
||||
|
||||
constexpr int kBitDelayMicros = 100;
|
||||
constexpr int kCodeDelayMicros = 200;
|
||||
constexpr int kKeyDelayMicros = 100;
|
||||
|
||||
void setup() {
|
||||
// put your setup code here, to run once:
|
||||
Serial.begin(115200);
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
|
||||
pinMode(kClockPin, INPUT);
|
||||
pinMode(kDataPin, INPUT);
|
||||
|
||||
Serial.println("kbd 0.1");
|
||||
}
|
||||
|
||||
// 0. reset
|
||||
// 0.0. clock line will be held low externally for 20 ms
|
||||
// when back up, keyboard needs to clock 0xAA as a response
|
||||
//
|
||||
// 1. operation
|
||||
// 1.0. just directly clock out scan codes of pressed keys
|
||||
|
||||
void sendCode(int code) {
|
||||
Serial.printf("sending code 0x%02x\n", code);
|
||||
// preconditions: clock and data pins are INPUT
|
||||
|
||||
while (digitalRead(kDataPin) == LOW || digitalRead(kClockPin) == LOW) {
|
||||
// wait. we're not allowed to send
|
||||
}
|
||||
|
||||
digitalWrite(kDataPin, LOW);
|
||||
digitalWrite(kClockPin, LOW);
|
||||
|
||||
pinMode(kClockPin, OUTPUT);
|
||||
delayMicroseconds(kBitDelayMicros);
|
||||
pinMode(kClockPin, INPUT);
|
||||
// delayMicroseconds(kDelayMicros);
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if ((code & (1 << i)) == 0) {
|
||||
// send a 0
|
||||
pinMode(kDataPin, OUTPUT);
|
||||
} // else do nothing, it's already a 1
|
||||
delayMicroseconds(kBitDelayMicros);
|
||||
|
||||
pinMode(kClockPin, OUTPUT);
|
||||
delayMicroseconds(kBitDelayMicros);
|
||||
pinMode(kDataPin, INPUT);
|
||||
pinMode(kClockPin, INPUT);
|
||||
}
|
||||
delayMicroseconds(kCodeDelayMicros);
|
||||
}
|
||||
|
||||
enum State {
|
||||
kReady,
|
||||
kMaybeReset,
|
||||
};
|
||||
|
||||
constexpr int kResetDelay = 19;
|
||||
|
||||
State state = State::kReady;
|
||||
int lastclocklow = 0;
|
||||
|
||||
constexpr int kLetterCodes[] = {
|
||||
0x1E, // 'a'
|
||||
0x30,
|
||||
0x2E,
|
||||
0x20,
|
||||
0x12,
|
||||
0x21,
|
||||
0x22,
|
||||
0x23,
|
||||
0x17,
|
||||
0x24,
|
||||
0x25,
|
||||
0x26,
|
||||
0x32,
|
||||
0x31,
|
||||
0x18,
|
||||
0x19,
|
||||
0x10,
|
||||
0x13,
|
||||
0x1F,
|
||||
0x14,
|
||||
0x16,
|
||||
0x2F,
|
||||
0x11,
|
||||
0x2D,
|
||||
0x15,
|
||||
0x2c,
|
||||
};
|
||||
|
||||
constexpr int kNumberCodes[] = {
|
||||
0x0B, // '0'
|
||||
0x02,
|
||||
0x03,
|
||||
0x04,
|
||||
0x05,
|
||||
0x06,
|
||||
0x07,
|
||||
0x08,
|
||||
0x09,
|
||||
0x0A,
|
||||
};
|
||||
|
||||
void sendNormalCode(int code) {
|
||||
sendCode(code);
|
||||
sendCode(code | 0x80);
|
||||
}
|
||||
|
||||
void sendShiftCode(int code) {
|
||||
sendCode(42); // left shift
|
||||
sendNormalCode(code);
|
||||
sendCode(42 | 0x80);
|
||||
}
|
||||
|
||||
void sendAsciiChar(int c) {
|
||||
if (c >= 'a' && c <= 'z') {
|
||||
return sendNormalCode(kLetterCodes[c - 'a']);
|
||||
} else if (c >= '0' && c <= '9') {
|
||||
return sendNormalCode(kNumberCodes[c - '0']);
|
||||
} else if (c >= 'A' && c <= 'Z') {
|
||||
return sendShiftCode(kLetterCodes[c - 'A']);
|
||||
}
|
||||
switch (c) {
|
||||
case '-': return sendNormalCode(12);
|
||||
case '=': return sendNormalCode(13);
|
||||
case '[': return sendNormalCode(26);
|
||||
case ']': return sendNormalCode(27);
|
||||
case ';': return sendNormalCode(39);
|
||||
case '\'': return sendNormalCode(40);
|
||||
case ',': return sendNormalCode(51);
|
||||
case '.': return sendNormalCode(52);
|
||||
case '/': return sendNormalCode(53);
|
||||
case ' ': return sendNormalCode(57);
|
||||
case '\n': return sendNormalCode(28);
|
||||
|
||||
case '!': return sendShiftCode(2);
|
||||
case '@': return sendShiftCode(3);
|
||||
case '#': return sendShiftCode(4);
|
||||
case '$': return sendShiftCode(5);
|
||||
case '%': return sendShiftCode(6);
|
||||
case '^': return sendShiftCode(7);
|
||||
case '&': return sendShiftCode(8);
|
||||
case '*': return sendShiftCode(9);
|
||||
case '(': return sendShiftCode(10);
|
||||
case ')': return sendShiftCode(11);
|
||||
case '_': return sendShiftCode(12);
|
||||
case '+': return sendShiftCode(13);
|
||||
|
||||
case '{': return sendShiftCode(26);
|
||||
case '}': return sendShiftCode(27);
|
||||
case ':': return sendShiftCode(39);
|
||||
case '"': return sendShiftCode(40);
|
||||
case '<': return sendShiftCode(51);
|
||||
case '>': return sendShiftCode(52);
|
||||
case '?': return sendShiftCode(53);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
static int led_counter = 0;
|
||||
static int led = HIGH;
|
||||
if (led_counter > 400000) {
|
||||
led_counter = 0;
|
||||
led = (led == HIGH) ? LOW : HIGH;
|
||||
digitalWrite(LED_BUILTIN, led);
|
||||
}
|
||||
led_counter += 1;
|
||||
|
||||
int clockp = digitalRead(kClockPin);
|
||||
if (state == State::kReady && clockp == LOW) {
|
||||
state = State::kMaybeReset;
|
||||
lastclocklow = millis();
|
||||
} else if (state == State::kMaybeReset) {
|
||||
if (clockp == HIGH && millis() - lastclocklow > kResetDelay) {
|
||||
delay(1);
|
||||
state = State::kReady;
|
||||
sendCode(0xaa);
|
||||
Serial.println("Reset!");
|
||||
}
|
||||
}
|
||||
|
||||
if (Serial.available() > 0) {
|
||||
int c = Serial.read();
|
||||
sendAsciiChar(c);
|
||||
//delayMicroseconds(kKeyDelayMicros);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user