Converter for Consul 262.5 terminal keyboard and VDX 52600 terminal.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

236 lines
5.0 KiB

  1. // Resources:
  2. // [Consul 262.4 Converter] https://deskthority.net/viewtopic.php?t=26908
  3. // [Consul 262.5 manual in CS] http://www.sapi.cz/prislusenstvi/c262-5.php#odkazp4
  4. #include <TimerOne.h>
  5. // pinout config
  6. const int pinData = 6;
  7. const int pinStatus = 7;
  8. const int clockPin = 5;
  9. const int dataPin = 3;
  10. const int outPin = 4;
  11. const int speakerPin = 6;
  12. // constant config
  13. const int slaveClockDivider = 16;
  14. const int timerDelay = 530 / slaveClockDivider;
  15. // variables
  16. volatile int slaveClockStep = 0;
  17. char m[255];
  18. volatile int data = 0;
  19. int test = 0;
  20. volatile int counter = 0;
  21. int numbits = 10;
  22. // MODS >>>
  23. // [1] send debug scancode information to serial port
  24. bool modConsoleLog = true;
  25. // [2] play speaker sounds of keys
  26. bool modKeySounds = true;
  27. // <<< MODS
  28. // ----------
  29. // KBD Output
  30. // ----------
  31. volatile long lastChange = 0;
  32. volatile int x = 0;
  33. volatile int dataWord = 0;
  34. volatile int dataState = 0;
  35. volatile int dataDelay = 0;
  36. volatile int packetDelay = 0;
  37. volatile int packetTail = 0;
  38. volatile bool nextKeyReady = false;
  39. volatile byte nextKey = 0;
  40. void typeKey(byte key) {
  41. nextKey = key;
  42. nextKeyReady = true;
  43. }
  44. void sendKey(byte key) {
  45. dataWord = key;
  46. dataState = 8;
  47. dataDelay = 0;
  48. packetDelay = 0;
  49. packetTail = 15;
  50. //Timer1.initialize(timerDelay);
  51. //Timer1.start();
  52. }
  53. void onHostStatusChange() {
  54. long timeNow = millis();
  55. long changeDiff = timeNow - lastChange;
  56. lastChange = timeNow;
  57. if (changeDiff >= 10 && nextKeyReady) {
  58. nextKeyReady = false;
  59. sendKey(nextKey);
  60. }
  61. }
  62. void onHostClockCycle(void)
  63. {
  64. int dataBit = HIGH;
  65. if (packetDelay > 0) {
  66. packetDelay--;
  67. } else if (dataDelay > 0) {
  68. dataDelay--;
  69. dataBit = LOW;
  70. } else if (dataState > 0) {
  71. int bitToSend = (dataWord >> (dataState - 1)) & 1;
  72. dataBit = !bitToSend ? LOW : HIGH;
  73. dataState--;
  74. } else if (packetTail > 0) {
  75. packetTail--;
  76. dataBit = LOW;
  77. } else {
  78. //Timer1.stop();
  79. }
  80. digitalWrite(pinData, dataBit);
  81. }
  82. // ---------
  83. // KBD Input
  84. // ---------
  85. const int receivingSteps = 16;
  86. volatile int clockStep = 0;
  87. volatile int receivingStep = 0;
  88. volatile int receivingData = 0;
  89. volatile int receivingBit = 0;
  90. void onSlaveClockInterrupt() {
  91. clockStep = (clockStep + 1) % 2;
  92. int clockValue = (clockStep % 2) ? HIGH : LOW;
  93. digitalWrite(clockPin, clockValue);
  94. int dataBit = digitalRead(dataPin);
  95. if (clockValue == LOW) {
  96. if (receivingData == 0 && dataBit == LOW) {
  97. receivingData = 1;
  98. receivingStep = 0;
  99. receivingBit = 0;
  100. test = 0;
  101. digitalWrite(outPin, HIGH);
  102. } else if (receivingData == 1) {
  103. receivingStep++;
  104. digitalWrite(outPin, HIGH);
  105. }
  106. if (receivingData == 1 && test == 0) {
  107. test = 1;
  108. receivingBit += dataBit == HIGH ? 1 : 0;
  109. if (receivingStep >= receivingSteps) {
  110. if (counter <= 8) {
  111. data = data >> 1;
  112. if (receivingBit > receivingSteps / 2) {
  113. bitSet(data, 7);
  114. }
  115. }
  116. counter++;
  117. receivingStep = 0;
  118. receivingBit = 0;
  119. digitalWrite(outPin, LOW);
  120. if (counter >= numbits) {
  121. receivingData = 0;
  122. }
  123. }
  124. }
  125. }
  126. if (clockValue == HIGH && test == 1) {
  127. test = 0;
  128. }
  129. }
  130. void setupKeyMapping() {
  131. }
  132. char translateKeyToChar(int key) {
  133. if (sizeof(m) <= key) {
  134. return 0;
  135. }
  136. return m[key];
  137. }
  138. void printChar(char keyChar) {
  139. Serial.print("'"); Serial.print(keyChar); Serial.print("' ("); Serial.print(int(keyChar)); Serial.println(")");
  140. }
  141. void processKbdByte(int data) {
  142. int key = data;
  143. if (modConsoleLog) {
  144. Serial.print("Key: <"); Serial.print(int(key)); Serial.print("> ");
  145. }
  146. char keyChar = translateKeyToChar(key);
  147. #ifdef KEYBOARD
  148. Keyboard.press(keyChar);
  149. delay(10);
  150. Keyboard.release(keyChar);
  151. #endif
  152. if (modConsoleLog) {
  153. Serial.print("Press: ");
  154. printChar(keyChar);
  155. }
  156. }
  157. // ----------------------
  158. // Input and Output Merge
  159. // ----------------------
  160. void onTimerInterrupt()
  161. {
  162. onSlaveClockInterrupt();
  163. slaveClockStep = (slaveClockStep + 1) % slaveClockDivider;
  164. if (slaveClockStep == 0) {
  165. onHostClockCycle();
  166. }
  167. }
  168. // ----
  169. // Main
  170. // ----
  171. void setup(void)
  172. {
  173. Serial.begin(9600);
  174. setupKeyMapping();
  175. pinMode(pinData, OUTPUT);
  176. pinMode(dataPin, INPUT);
  177. pinMode(outPin, OUTPUT);
  178. pinMode(clockPin, OUTPUT);
  179. pinMode(pinStatus, INPUT_PULLUP);
  180. digitalWrite(pinData, HIGH);
  181. digitalWrite(outPin, LOW);
  182. attachInterrupt(digitalPinToInterrupt(pinStatus), onHostStatusChange, CHANGE);
  183. Timer1.initialize(timerDelay);
  184. Timer1.attachInterrupt(onTimerInterrupt);
  185. //Timer1.stop();
  186. Serial.println("Keyboard ready");
  187. tone(speakerPin, 80, 50);
  188. }
  189. void loop(void)
  190. {
  191. // type key from serial
  192. if (!nextKeyReady && Serial.available() > 0) {
  193. long key = Serial.parseInt(SKIP_ALL);
  194. if (key != 0) {
  195. typeKey(key);
  196. }
  197. }
  198. // type key from keyboard
  199. if (counter >= numbits) {
  200. processKbdByte(data);
  201. if (modKeySounds) tone(speakerPin, 60 + int(data), 25);
  202. data = B0;
  203. counter = 0;
  204. }
  205. }