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.

362 lines
7.2 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; // out, host data
  7. const int pinStatus = 7; // in, host status
  8. const int clockPin = 5; // out, kbd clock
  9. const int dataPin = 3; // in, kbd data
  10. const int outPin = 4; // out, kbd led
  11. // constant config
  12. const int slaveClockDivider = 8;
  13. const int timerDelay = 520 / slaveClockDivider;
  14. // variables
  15. volatile int slaveClockStep = 0;
  16. char m[255];
  17. volatile int data = 0;
  18. int test = 0;
  19. volatile int counter = 0;
  20. int numbits = 10;
  21. // MODS >>>
  22. // [1] send debug scancode information to serial port
  23. bool modConsoleLog = true;
  24. // <<< MODS
  25. // ----------
  26. // KBD Output
  27. // ----------
  28. volatile long lastChange = 0;
  29. volatile int x = 0;
  30. volatile int dataWord = 0;
  31. volatile int dataState = 0;
  32. volatile int dataDelay = 0;
  33. volatile int packetDelay = 0;
  34. volatile int packetTail = 0;
  35. volatile bool nextKeyReady = false;
  36. volatile byte nextKey = 0;
  37. void typeKey(byte key) {
  38. nextKey = key;
  39. nextKeyReady = true;
  40. //Serial.print("Typing key "); Serial.println((int) key);
  41. }
  42. void sendKey(byte key) {
  43. dataWord = key;
  44. dataState = 8;
  45. dataDelay = 0;
  46. packetDelay = 0;
  47. packetTail = 15;
  48. //Serial.print("Sending key "); Serial.println((int) key);
  49. }
  50. void onHostStatusChange() {
  51. long timeNow = millis();
  52. long changeDiff = timeNow - lastChange;
  53. lastChange = timeNow;
  54. if (changeDiff >= 10 && nextKeyReady) {
  55. nextKeyReady = false;
  56. sendKey(nextKey);
  57. Timer1.start(); // synchronize with the host
  58. slaveClockStep = 0;
  59. }
  60. }
  61. void onHostClockCycle(void)
  62. {
  63. int dataBit = HIGH;
  64. if (packetDelay > 0) {
  65. packetDelay--;
  66. } else if (dataDelay > 0) {
  67. dataDelay--;
  68. dataBit = LOW;
  69. } else if (dataState > 0) {
  70. int bitToSend = (dataWord >> (dataState - 1)) & 1;
  71. dataBit = !bitToSend ? LOW : HIGH;
  72. dataState--;
  73. } else if (packetTail > 0) {
  74. packetTail--;
  75. dataBit = LOW;
  76. } else {
  77. }
  78. digitalWrite(pinData, dataBit);
  79. }
  80. // ---------
  81. // KBD Input
  82. // ---------
  83. const int receivingSteps = 16;
  84. volatile int clockStep = 0;
  85. volatile int receivingStep = 0;
  86. volatile int receivingData = 0;
  87. volatile int receivingBit = 0;
  88. void onSlaveClockInterrupt() {
  89. clockStep = (clockStep + 1) % 2;
  90. int clockValue = (clockStep % 2) ? HIGH : LOW;
  91. digitalWrite(clockPin, clockValue);
  92. int dataBit = digitalRead(dataPin);
  93. if (clockValue == LOW) {
  94. if (receivingData == 0 && dataBit == LOW) {
  95. receivingData = 1;
  96. receivingStep = 0;
  97. receivingBit = 0;
  98. test = 0;
  99. } else if (receivingData == 1) {
  100. receivingStep++;
  101. }
  102. if (receivingData == 1 && test == 0) {
  103. test = 1;
  104. receivingBit += dataBit == HIGH ? 1 : 0;
  105. if (receivingStep >= receivingSteps) {
  106. if (counter <= 8) {
  107. data = data >> 1;
  108. if (receivingBit > receivingSteps / 2) {
  109. bitSet(data, 7);
  110. }
  111. }
  112. counter++;
  113. receivingStep = 0;
  114. receivingBit = 0;
  115. if (counter >= numbits) {
  116. receivingData = 0;
  117. }
  118. }
  119. }
  120. }
  121. if (clockValue == HIGH && test == 1) {
  122. test = 0;
  123. }
  124. }
  125. void setupKeyMapping() {
  126. m[0] = 0;
  127. m[223] = ' '; // Spacebar
  128. // top row special
  129. m[63] = 0x12; // ?? Setup
  130. m[62] = 'j'; // up
  131. m[61] = 'k'; // down
  132. m[59] = 'h'; // left
  133. m[60] = 'l'; // right
  134. // top numbers row
  135. m[228] = 0x1B; // ESC
  136. m[206] = '1';
  137. m[205] = '2';
  138. m[204] = '3';
  139. m[203] = '4';
  140. m[202] = '5';
  141. m[201] = '6';
  142. m[200] = '7';
  143. m[199] = '8';
  144. m[198] = '9';
  145. m[207] = '0';
  146. m[210] = '-';
  147. m[161] = '^';
  148. m[0] = ' '; // Empty cap
  149. m[247] = 0x08; // Backspace
  150. m[56] = 0x10; // Break
  151. // top letter row
  152. m[246] = '\t';
  153. m[142] = 'q';
  154. m[142+32] = 'Q';
  155. m[136] = 'w';
  156. m[136+32] = 'W';
  157. m[154] = 'e';
  158. m[154+32] = 'E';
  159. m[141] = 'r';
  160. m[141+32] = 'R';
  161. m[139] = 't';
  162. m[139+32] = 'T';
  163. m[134] = 'y';
  164. m[134+32] = 'Y';
  165. m[138] = 'u';
  166. m[138+32] = 'U';
  167. m[150] = 'i';
  168. m[150+32] = 'I';
  169. m[144] = 'o';
  170. m[144+32] = 'O';
  171. m[143] = 'p';
  172. m[143+32] = 'P';
  173. m[191] = '@';
  174. m[164] = '[';
  175. m[245] = 0x0A;
  176. m[128] = 0x7F;
  177. // middle letter row
  178. m[158] = 'a';
  179. m[158+32] = 'A';
  180. m[140] = 's';
  181. m[140+32] = 'S';
  182. m[153] = 'd'; // TODO
  183. m[153+32] = 'D'; // TODO
  184. m[153] = 'f';
  185. m[153+32] = 'F';
  186. m[152] = 'g';
  187. m[152+32] = 'G';
  188. m[151] = 'h';
  189. m[151+32] = 'H';
  190. m[149] = 'j';
  191. m[149+32] = 'J';
  192. m[148] = 'k';
  193. m[148+32] = 'K';
  194. m[147] = 'l';
  195. m[147+32] = 'L';
  196. m[196] = ';';
  197. m[196+32] = '+';
  198. m[197] = ':';
  199. m[197+32] = '*';
  200. m[162] = ']';
  201. m[162+32] = '}';
  202. m[242] = 0x0D;
  203. /*
  204. m[] = '';
  205. m[] = '';
  206. m[] = '';
  207. m[] = '';
  208. m[] = '';
  209. m[] = '';
  210. m[] = '';
  211. m[] = '';
  212. m[] = '';
  213. m[] = '';
  214. m[] = '';
  215. m[] = '';
  216. m[] = '';
  217. m[] = '';
  218. m[] = '';
  219. m[] = '';
  220. m[] = '';
  221. m[] = '';
  222. m[] = '';
  223. m[] = '';
  224. m[] = '';
  225. m[] = '';
  226. m[] = '';
  227. m[] = '';
  228. m[] = '';
  229. m[] = '';
  230. m[] = '';
  231. m[] = '';
  232. m[] = '';
  233. m[] = '';
  234. m[] = '';
  235. m[] = '';
  236. m[] = '';
  237. m[] = '';
  238. m[] = '';
  239. m[] = '';
  240. m[] = '';
  241. m[] = '';
  242. m[] = '';
  243. m[] = '';
  244. m[] = '';
  245. m[] = '';
  246. m[] = '';
  247. m[] = '';
  248. m[] = '';
  249. m[] = '';
  250. m[] = '';
  251. m[] = '';
  252. /**/
  253. }
  254. char translateKeyToChar(int key) {
  255. if (sizeof(m) <= key) {
  256. return 0;
  257. }
  258. return m[key];
  259. }
  260. void printChar(char keyChar) {
  261. Serial.print("'"); Serial.print(keyChar); Serial.print("' ("); Serial.print(int(keyChar)); Serial.println(")");
  262. }
  263. void processKbdByte(int data) {
  264. int key = data;
  265. char keyChar = translateKeyToChar(key);
  266. if (modConsoleLog) {
  267. Serial.print("Key: <"); Serial.print(int(key)); Serial.print("> ");
  268. Serial.print("Char: "); printChar(keyChar);
  269. }
  270. #ifdef KEYBOARD
  271. Keyboard.press(keyChar);
  272. delay(10);
  273. Keyboard.release(keyChar);
  274. #endif
  275. typeKey(keyChar);
  276. }
  277. // ----------------------
  278. // Input and Output Merge
  279. // ----------------------
  280. void onTimerInterrupt()
  281. {
  282. onSlaveClockInterrupt();
  283. if (slaveClockStep == 0) {
  284. onHostClockCycle();
  285. }
  286. slaveClockStep = (slaveClockStep + 1) % slaveClockDivider;
  287. }
  288. // ----
  289. // Main
  290. // ----
  291. void setup(void)
  292. {
  293. Serial.begin(9600);
  294. setupKeyMapping();
  295. pinMode(pinData, OUTPUT);
  296. pinMode(dataPin, INPUT);
  297. pinMode(outPin, OUTPUT);
  298. pinMode(clockPin, OUTPUT);
  299. pinMode(pinStatus, INPUT_PULLUP);
  300. digitalWrite(pinData, HIGH);
  301. digitalWrite(outPin, LOW);
  302. attachInterrupt(digitalPinToInterrupt(pinStatus), onHostStatusChange, CHANGE);
  303. Timer1.initialize(timerDelay);
  304. Timer1.attachInterrupt(onTimerInterrupt);
  305. Serial.println("Keyboard ready");
  306. }
  307. void loop(void)
  308. {
  309. // type key from serial
  310. if (!nextKeyReady && Serial.available() > 0) {
  311. long key = Serial.parseInt(SKIP_ALL);
  312. if (key != 0) {
  313. typeKey(key);
  314. }
  315. }
  316. /**/
  317. // type key from keyboard
  318. if (counter >= numbits) {
  319. processKbdByte(data);
  320. data = B0;
  321. counter = 0;
  322. }
  323. /**/
  324. /*/ auto-type test
  325. delay(500);
  326. typeKey('B');
  327. /**/
  328. }