// 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 #include // pinout config const int pinData = 6; const int pinStatus = 7; const int clockPin = 5; const int dataPin = 3; const int outPin = 4; const int speakerPin = 6; // constant config const int slaveClockDivider = 16; const int timerDelay = 530 / slaveClockDivider; // variables volatile int slaveClockStep = 0; char m[255]; volatile int data = 0; int test = 0; volatile int counter = 0; int numbits = 10; // MODS >>> // [1] send debug scancode information to serial port bool modConsoleLog = true; // [2] play speaker sounds of keys bool modKeySounds = true; // <<< MODS // ---------- // KBD Output // ---------- volatile long lastChange = 0; 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; } void sendKey(byte key) { dataWord = key; dataState = 8; dataDelay = 0; packetDelay = 0; packetTail = 15; //Timer1.initialize(timerDelay); //Timer1.start(); } void onHostStatusChange() { long timeNow = millis(); long changeDiff = timeNow - lastChange; lastChange = timeNow; if (changeDiff >= 10 && nextKeyReady) { nextKeyReady = false; sendKey(nextKey); } } 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 { //Timer1.stop(); } 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; digitalWrite(outPin, HIGH); } else if (receivingData == 1) { receivingStep++; digitalWrite(outPin, HIGH); } 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; digitalWrite(outPin, LOW); if (counter >= numbits) { receivingData = 0; } } } } if (clockValue == HIGH && test == 1) { test = 0; } } void setupKeyMapping() { } 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; if (modConsoleLog) { Serial.print("Key: <"); Serial.print(int(key)); Serial.print("> "); } char keyChar = translateKeyToChar(key); #ifdef KEYBOARD Keyboard.press(keyChar); delay(10); Keyboard.release(keyChar); #endif if (modConsoleLog) { Serial.print("Press: "); printChar(keyChar); } } // ---------------------- // Input and Output Merge // ---------------------- void onTimerInterrupt() { onSlaveClockInterrupt(); slaveClockStep = (slaveClockStep + 1) % slaveClockDivider; if (slaveClockStep == 0) { onHostClockCycle(); } } // ---- // Main // ---- void setup(void) { Serial.begin(9600); setupKeyMapping(); pinMode(pinData, OUTPUT); pinMode(dataPin, INPUT); pinMode(outPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(pinStatus, INPUT_PULLUP); digitalWrite(pinData, HIGH); digitalWrite(outPin, LOW); attachInterrupt(digitalPinToInterrupt(pinStatus), onHostStatusChange, CHANGE); Timer1.initialize(timerDelay); Timer1.attachInterrupt(onTimerInterrupt); //Timer1.stop(); Serial.println("Keyboard ready"); tone(speakerPin, 80, 50); } 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); if (modKeySounds) tone(speakerPin, 60 + int(data), 25); data = B0; counter = 0; } }