|
- // Resources:
- // [Consul 262.4 Converter] https://deskthority.net/viewtopic.php?t=26908
- // [Consul 262.5 manual in CS] http://www.sapi.cz/prislusenstvi/c262-5.php#odkazp4
-
- #define KEYBOARD
-
- #ifdef KEYBOARD
- #include <Keyboard.h>
- #endif
-
- #include <TimerOne.h>
-
- // pinout config
- const int pinLedOffline = 10; // out
- const int pinLedOnline = 9; // out
- const int pinSpeaker = 8; // out
- const int pinData = 6; // out, host data
- const int pinStatus = 7; // in, host status
- const int clockPin = 5; // out, kbd clock
- const int dataPin = 3; // in, kbd data
- const int outPin = 4; // out, kbd led
-
- // constant config
- const int slaveClockDivider = 8;
- const int timerDelay = 520 / slaveClockDivider;
-
- // variables
- volatile int slaveClockStep = 0;
- char m[255];
- volatile int data = 0;
- int test = 0;
- volatile int counter = 0;
- int numbits = 10;
- volatile int typedKey = -1;
- bool hostOnline = false;
-
- // MODS >>>
- // [1] send debug scancode information to serial port
- bool modConsoleLog = true;
- // <<< MODS
-
- // ----------
- // KBD Output
- // ----------
- volatile long lastChange = -100000;
- volatile int x = 0;
- volatile int dataWord = 0;
- volatile int dataState = 0;
- volatile int dataDelay = 0;
- volatile int packetDelay = 0;
- volatile int packetTail = 0;
-
- volatile bool nextKeyReady = false;
- volatile byte nextKey = 0;
-
- void typeKey(byte key) {
- nextKey = key;
- nextKeyReady = true;
- //Serial.print("Typing key "); Serial.println((int) key);
- }
-
- void sendKey(byte key) {
- dataWord = key;
- dataState = 8;
- dataDelay = 0;
- packetDelay = 0;
- packetTail = 15;
- typedKey = key;
- //Serial.print("Sending key "); Serial.println((int) key);
- }
-
- void onHostStatusChange() {
- long timeNow = millis();
- long changeDiff = timeNow - lastChange;
- lastChange = timeNow;
- if (changeDiff >= 10 && nextKeyReady) {
- nextKeyReady = false;
- sendKey(nextKey);
- Timer1.start(); // synchronize with the host
- slaveClockStep = 0;
- }
- }
-
- void onHostClockCycle(void)
- {
- int dataBit = HIGH;
- if (packetDelay > 0) {
- packetDelay--;
- } else if (dataDelay > 0) {
- dataDelay--;
- dataBit = LOW;
- } else if (dataState > 0) {
- int bitToSend = (dataWord >> (dataState - 1)) & 1;
- dataBit = !bitToSend ? LOW : HIGH;
- dataState--;
- } else if (packetTail > 0) {
- packetTail--;
- dataBit = LOW;
- } else {
- }
- digitalWrite(pinData, dataBit);
- }
-
- // ---------
- // KBD Input
- // ---------
- const int receivingSteps = 16;
- volatile int clockStep = 0;
- volatile int receivingStep = 0;
- volatile int receivingData = 0;
- volatile int receivingBit = 0;
-
- void onSlaveClockInterrupt() {
- clockStep = (clockStep + 1) % 2;
- int clockValue = (clockStep % 2) ? HIGH : LOW;
- digitalWrite(clockPin, clockValue);
- int dataBit = digitalRead(dataPin);
- if (clockValue == LOW) {
- if (receivingData == 0 && dataBit == LOW) {
- receivingData = 1;
- receivingStep = 0;
- receivingBit = 0;
- test = 0;
- } else if (receivingData == 1) {
- receivingStep++;
- }
- if (receivingData == 1 && test == 0) {
- test = 1;
- receivingBit += dataBit == HIGH ? 1 : 0;
- if (receivingStep >= receivingSteps) {
- if (counter <= 8) {
- data = data >> 1;
- if (receivingBit > receivingSteps / 2) {
- bitSet(data, 7);
- }
- }
- counter++;
- receivingStep = 0;
- receivingBit = 0;
- if (counter >= numbits) {
- receivingData = 0;
- }
- }
- }
- }
- if (clockValue == HIGH && test == 1) {
- test = 0;
- }
- }
-
- void setupKeyMapping() {
- m[0] = 0;
- // top row special
- m[63] = 0x12; // ?? Setup
- m[62] = 'j'; // up
- m[61] = 'k'; // down
- m[59] = 'h'; // left
- m[60] = 'l'; // right
- // top numbers row
- m[228] = 0x1B; // ESC
- m[206] = '1';
- m[205] = '2';
- m[204] = '3';
- m[203] = '4';
- m[202] = '5';
- m[201] = '6';
- m[200] = '7';
- m[199] = '8';
- m[198] = '9';
- m[207] = '0';
- m[210] = '-';
- m[161] = '^';
- m[0] = ' '; // Empty cap
- m[247] = 0x08; // Backspace
- m[56] = 0x10; // Break
- // top letter row
- m[246] = '\t';
- m[142] = 'q';
- m[142+32] = 'Q';
- m[136] = 'w';
- m[136+32] = 'W';
- m[154] = 'e';
- m[154+32] = 'E';
- m[141] = 'r';
- m[141+32] = 'R';
- m[139] = 't';
- m[139+32] = 'T';
- m[134] = 'y';
- m[134+32] = 'Y';
- m[138] = 'u';
- m[138+32] = 'U';
- m[150] = 'i';
- m[150+32] = 'I';
- m[144] = 'o';
- m[144+32] = 'O';
- m[143] = 'p';
- m[143+32] = 'P';
- m[191] = '@';
- m[164] = '[';
- m[245] = 0x0A;
- m[128] = 0x7F;
- // middle letter row
- m[158] = 'a';
- m[158+32] = 'A';
- m[140] = 's';
- m[140+32] = 'S';
- m[155] = 'd';
- m[155+32] = 'D';
- m[153] = 'f';
- m[153+32] = 'F';
- m[152] = 'g';
- m[152+32] = 'G';
- m[151] = 'h';
- m[151+32] = 'H';
- m[149] = 'j';
- m[149+32] = 'J';
- m[148] = 'k';
- m[148+32] = 'K';
- m[147] = 'l';
- m[147+32] = 'L';
- m[196] = ';';
- m[196+32] = '+';
- m[197] = ':';
- m[197+32] = '*';
- m[162] = ']';
- m[162+32] = '}';
- m[242] = 0x0D;
- // bottom letter row
- m[58] = 0x11; // No Scroll
- m[133] = 'z';
- m[133+32] = 'Z';
- m[135] = 'x';
- m[135+32] = 'X';
- m[156] = 'c';
- m[156+32] = 'C';
- m[137] = 'v';
- m[137+32] = 'V';
- m[157] = 'b';
- m[157+32] = 'B';
- m[145] = 'n';
- m[145+32] = 'N';
- m[146] = 'm';
- m[146+32] = 'M';
- m[211] = ',';
- m[211+32] = '<';
- m[209] = '.';
- m[209+32] = '>';
- m[208] = '/';
- m[208+32] = '?';
- m[163] = '\\';
- m[163+32] = '|';
- m[78] = 'x'; // Blank cap
- m[77] = 'X'; // Blank cap + shift
- // spacebar
- m[223] = ' '; // Spacebar
- /*/ numpad
- m[] = '';
- m[+32] = '';
- m[] = '';
- m[+32] = '';
- m[] = '';
- m[+32] = '';
- m[] = '';
- m[+32] = '';
- m[] = '';
- m[+32] = '';
- /*
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- m[] = '';
- /**/
- //
- // 208 local ON
- // 209 leave local
- // 210 half/full duplex
- // 211 go home?
- // 212 print Ps junk
- // 213 mem protect
- // 214 disable NAT
- // 217 clear line?
- // 218 shows cursor
- // 219 hides cursor
- // 221 mem prot
- // 223 reset prompt
- // 241 random junk symbols
- // 243 random junk symbols
- // 244 stop junk
- // 248 hides cursor
- // 251 Hard copy
- // 250 Keyb. Inh.
- }
-
- char translateKeyToChar(int key) {
- if (sizeof(m) <= key) {
- return 0;
- }
- return m[key];
- }
-
- void printChar(char keyChar) {
- Serial.print("'"); Serial.print(keyChar); Serial.print("' ("); Serial.print(int(keyChar)); Serial.println(")");
- }
-
- void processKbdByte(int data) {
- int key = data;
- char keyChar = translateKeyToChar(key);
-
- if (modConsoleLog) {
- Serial.print("Key: <"); Serial.print(int(key)); Serial.print("> ");
- Serial.print("Char: "); printChar(keyChar);
- }
-
- #ifdef KEYBOARD
- if (!hostOnline) {
- Keyboard.press(keyChar);
- delay(10);
- Keyboard.release(keyChar);
- }
- #endif
-
- typeKey(keyChar);
- }
-
- // ----------------------
- // Input and Output Merge
- // ----------------------
- void onTimerInterrupt()
- {
- onSlaveClockInterrupt();
-
- if (slaveClockStep == 0) {
- onHostClockCycle();
- }
- slaveClockStep = (slaveClockStep + 1) % slaveClockDivider;
- }
-
- // --------------
- // User Interface
- // --------------
- void updateOnlineStatus()
- {
- long timeNow = millis();
- hostOnline = (lastChange > timeNow) || ((timeNow - lastChange) < 10000);
-
- digitalWrite(pinLedOffline, hostOnline ? LOW : HIGH);
- digitalWrite(pinLedOnline, hostOnline ? HIGH : LOW);
- }
-
- // ----
- // Main
- // ----
- void setup(void)
- {
- Serial.begin(9600);
-
- setupKeyMapping();
-
- pinMode(pinLedOffline, OUTPUT);
- pinMode(pinLedOnline, OUTPUT);
- pinMode(pinSpeaker, OUTPUT);
- pinMode(pinData, OUTPUT);
- pinMode(dataPin, INPUT);
- pinMode(outPin, OUTPUT);
- pinMode(clockPin, OUTPUT);
- pinMode(pinStatus, INPUT_PULLUP);
-
- digitalWrite(pinLedOffline, HIGH);
- digitalWrite(pinLedOnline, HIGH);
- digitalWrite(pinData, HIGH);
- digitalWrite(outPin, LOW);
-
- attachInterrupt(digitalPinToInterrupt(pinStatus), onHostStatusChange, CHANGE);
-
- Timer1.initialize(timerDelay);
- Timer1.attachInterrupt(onTimerInterrupt);
-
- delay(500);
- tone(pinSpeaker, 650, 200);
- digitalWrite(pinLedOffline, LOW);
- digitalWrite(pinLedOnline, HIGH);
- delay(200);
- tone(pinSpeaker, 500, 200);
- digitalWrite(pinLedOffline, HIGH);
- digitalWrite(pinLedOnline, LOW);
- delay(200);
- digitalWrite(pinLedOffline, LOW);
- digitalWrite(pinLedOnline, LOW);
- delay(500);
-
- updateOnlineStatus();
- tone(pinSpeaker, 440, 200);
- delay(200);
-
- Serial.println("Keyboard ready");
- }
-
- int qwe = 0;
- void loop(void)
- {
- // type key from serial
- if (!nextKeyReady && Serial.available() > 0) {
- long key = Serial.parseInt(SKIP_ALL);
- if (key != 0) {
- typeKey(key);
- }
- }
- /**/
-
- // type key from keyboard
- if (counter >= numbits) {
- processKbdByte(data);
- data = B0;
- counter = 0;
- }
- /**/
-
- /*/ auto-type test
- delay(2000);
- int k = 128 + qwe;
- typeKey(k);
- qwe = (qwe + 1) % 128;
- Serial.print("QWE "); Serial.println((int)k);
- if (qwe % 5 == 0) delay(2000);
- /**/
-
- updateOnlineStatus();
- if (nextKeyReady && !hostOnline) { // skip sending key without a host (used for USB)
- nextKeyReady = false;
- typedKey = nextKey;
- }
- if (!nextKeyReady && typedKey != -1) {
- tone(pinSpeaker, 200 + typedKey, 100);
- typedKey = -1;
- }
-
- delay(5);
- }
|