Add parallel port comms to arduino
This commit is contained in:
193
arduino/kbd/kbd.cc
Normal file
193
arduino/kbd/kbd.cc
Normal file
@@ -0,0 +1,193 @@
|
||||
// keyboard wiring diagram:
|
||||
// https://www.minuszerodegrees.net/5150/misc/5150_keyboard_reset.jpg
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
constexpr int kClockPin = PC6;
|
||||
constexpr int kDataPin = PC4;
|
||||
|
||||
constexpr int kBitDelayMicros = 100;
|
||||
constexpr int kCodeDelayMicros = 200;
|
||||
constexpr int kKeyDelayMicros = 100;
|
||||
|
||||
namespace {
|
||||
|
||||
void sendCode(int 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;
|
||||
|
||||
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 sendCtrlAltDel() {
|
||||
sendCode(0x1d); // ctrl
|
||||
sendCode(0x38); // alt
|
||||
sendCode(0x53); // del
|
||||
sendCode(0x53 | 0x80);
|
||||
sendCode(0x38 | 0x80);
|
||||
sendCode(0x1d | 0x80);
|
||||
}
|
||||
|
||||
void sendCtrlBreak() {
|
||||
sendCode(0x1d); // ctrl
|
||||
sendCode(0x46); // break
|
||||
sendCode(0x46 | 0x80);
|
||||
sendCode(0x1d | 0x80);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
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);
|
||||
|
||||
case 0:
|
||||
return sendCtrlAltDel();
|
||||
case 27:
|
||||
return sendCtrlBreak(); // escape
|
||||
}
|
||||
}
|
||||
|
||||
void setupKbd() {
|
||||
pinMode(kClockPin, INPUT);
|
||||
pinMode(kDataPin, INPUT);
|
||||
}
|
||||
|
||||
void checkKbdReset() {
|
||||
static State state = kReady;
|
||||
static int lastclocklow = 0;
|
||||
|
||||
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!");
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user