/* SOURCE: http://www.netbsd.org/docs/Hardware/Machines/DEC/lk201.html */ /* SOURCE: https://lkml.org/lkml/2004/3/16/160 */ /* https://vt100.net/docs/vt100-ug/chapter3.html */ /**********************************************************************/ /* requires LED number data */ #define LK_LED_ENABLE 0x13 /* light LED */ #define LK_LED_DISABLE 0x11 /* turn off LED */ #define LED_WAIT 0x81 /* Wait LED */ #define LED_COMP 0x82 /* Compose LED */ #define LED_LOCK 0x84 /* Lock LED */ #define LED_HOLD 0x88 /* Hold Screen LED */ #define LED_ALL 0x8F /* All LED's */ /**********************************************************************/ /* Requires volume data byte */ #define LK_CL_ENABLE 0x1B /* keyclick enable. Requires volume */ /* byte. This does not affect the */ /* SHIFT key. The CTRL key requires */ /* LK_CL_ENABLE and LK_CCL_ENABLE to */ /* have been sent before it clicks. */ /* All other keys are only controlled */ /* by LK_CL_ENABLE. */ #define LK_CCL_ENABLE 0xBB /* Enable keyclicks for the CTRL key. */ /* The CTRL keyclick volume is set to */ /* be the same as the rest of the keys */ /* LK_CCL_ENABLE sets a flag in the */ /* keyboard with is logically AND'ed */ /* with the LK_CL_ENABLE flag to enable*/ /* CTRL key keyclicks. */ #define LK_CL_DISABLE 0x99 /* keyclick disable */ #define LK_CCL_DISABLE 0xB9 /* CTRL key keyclick disable */ #define LK_SOUND_CLICK 0x9F /* causes the LK201 to sound a keyclick*/ /* max volume is 0, lowest is 0x7 */ #define LK_PARAM_VOLUME(v) (0x80|((v)&0x7)) /**********************************************************************/ /* requires bell volume data */ #define LK_BELL_ENABLE 0x23 /* enable the keyboard bell. Requires */ /* volume data byte. */ #define LK_BELL_DISABLE 0xA1 /* disable the keyboard bell. */ #define LK_RING_BELL 0xA7 /* ring the keyboard bell */ /* max volume is 0, lowest is 0x7 */ #define LK_PARAM_VOLUME(v) (0x80|((v)&0x7)) /**********************************************************************/ #define LK_UPDOWN 0x86 #define LK_AUTODOWN 0x82 #define LK_DOWN 0x80 #define LK_CMD_MODE(m,div) ((m)|((div)<<3)) #define LK_MODECHG_ACK 0xBA /* sent by the keyboard to acknowledge a */ /* successful mode change. */ #define LK_PFX_KEYDOWN 0xB9 /* indicates that the next byte is a key- */ /* code for a key already down in a */ /* division that has been changed to */ /* LK_UPDOWN. I think this means that if */ /* for example, the 'a' key is in LK_DOWN */ /* mode and the key is being held down and*/ /* division 1 is switched to LK_UPDOWN */ /* mode, the keyboard will produce the */ /* byte LK_PFX_KEYDOWN followed by 0xC2 */ /* (KEY_A). */ #define LK_CMD_RPT_TO_DOWN 0xD9 /* This command causes all divisions which */ /* are programmed for LK_AUTODOWN mode to */ /* be switched to LK_DOWN mode. */ #define LK_CMD_ENB_RPT 0xE3 /* enables auto repeat on the keys */ /* which are in LK_AUTODOWN mode */ #define LK_CMD_DIS_RPT 0xE1 /* disables auto repeat on all keys, but */ /* does not change the mode that the */ /* divisions are programmed to. */ #define LK_CMD_TMP_NORPT 0xD1 /* temporary auto repeat disable. This */ /* command disables auto repeat for the key*/ /* which is currently pressed down. Auto */ /* repeat is re-enabled when another key is*/ /* pressed. */ #define LK_OUTPUT_ERROR 0xb5 #define LK_INPUT_ERROR 0xB6 /* sent by the keyboard if it receives an */ /* invalid command. */ #define LK_NO_ERROR 0x00 /* No Error */ #define LK_KDOWN_ERROR 0x3D /* Key down on powerup error */ #define LK_POWER_ERROR 0x3E /* Keyboard failure on pwrup tst */ #define LK_ALLUP 0xB3 #define LK_ALL_KEYS_UP 0xb3 #define LK_METRONOME 0xb4 /**********************************************************************/ bool mod_shift = false; bool mod_ctrl = false; #define KB_CHAR_SHIFT(key_base, key_shift) ((mod_shift) ? (key_shift) : (key_base)) #define KB_CHAR_CTRL(key_base, key_ctrl) ((mod_ctrl) ? (key_ctrl) : (key_base)) #define KB_CHAR(key_base, key_shift) c = KB_CHAR_SHIFT(key_base, key_shift); #define KB_CHARC(key_base, key_shift, key_ctrl) c = KB_CHAR_CTRL(KB_CHAR_SHIFT(key_base, key_shift), key_ctrl); void keyboard_handle_key(int key) { int c = -1; switch (key) { /* Key Division 191-255 */ case 191: KB_CHAR('`', '~'); break; // (xbf): KEY_TILDE case 192: KB_CHAR('1', '!'); break; // (xc0): KEY_TR_1 case 193: KB_CHAR('q', 'Q'); break; // (xc1): KEY_Q case 194: KB_CHARC('a', 'A', '\x01'); break; // (xc2): KEY_A case 195: KB_CHAR('z', 'Z'); break; // (xc3): KEY_Z case 197: KB_CHAR('2', '@'); break; // (xc5): KEY_TR_2 case 198: KB_CHAR('w', 'W'); break; // (xc6): KEY_W case 199: KB_CHAR('s', 'S'); break; // (xc7): KEY_S case 200: KB_CHAR('x', 'X'); break; // (xc8): KEY_X case 201: KB_CHAR('<', '>'); break; // (xc9): KEY_LANGLE_RANGLE case 203: KB_CHAR('3', '#'); break; // (xcb): KEY_TR_3 case 204: KB_CHARC('e', 'E', '\x05'); break; // (xcc): KEY_E case 205: KB_CHARC('d', 'D', '\x04'); break; // (xcd): KEY_D case 206: KB_CHARC('c', 'C', '\x03'); break; // (xce): KEY_C case 208: KB_CHAR('4', '$'); break; // (xd0): KEY_TR_4 case 209: KB_CHAR('r', 'R'); break; // (xd1): KEY_R case 210: KB_CHARC('f', 'F', '\x06'); break; // (xd2): KEY_F case 211: KB_CHAR('v', 'V'); break; // (xd3): KEY_V case 212: KB_CHAR(' ', ' '); break; // (xd4): KEY_SPACE case 214: KB_CHAR('5', '%'); break; // (xd6): KEY_TR_5 case 215: KB_CHAR('t', 'T'); break; // (xd7): KEY_T case 216: KB_CHARC('g', 'G', '\x07'); break; // (xd8): KEY_G case 217: KB_CHARC('b', 'B', '\x02'); break; // (xd9): KEY_B case 219: KB_CHAR('6', '^'); break; // (xdb): KEY_TR_6 case 220: KB_CHAR('y', 'Y'); break; // (xdc): KEY_Y case 221: KB_CHARC('h', 'H', '\x08'); break; // (xdd): KEY_H case 222: KB_CHAR('n', 'N'); break; // (xde): KEY_N case 224: KB_CHAR('7', '&'); break; // (xe0): KEY_TR_7 case 225: KB_CHAR('u', 'U'); break; // (xe1): KEY_U case 226: KB_CHARC('j', 'J', '\x0A'); break; // (xe2): KEY_J case 227: KB_CHAR('m', 'M'); break; // (xe3): KEY_M case 229: KB_CHAR('8', '*'); break; // (xe5): KEY_TR_8 case 230: KB_CHARC('i', 'I', '\x09'); break; // (xe6): KEY_I case 231: KB_CHARC('k', 'K', '\x0B'); break; // (xe7): KEY_K case 232: KB_CHAR(',', '<'); break; // (xe8): KEY_COMMA case 234: KB_CHAR('9', '('); break; // (xea): KEY_TR_9 case 235: KB_CHAR('o', 'O'); break; // (xeb): KEY_O case 236: KB_CHARC('l', 'L', '\x0C'); break; // (xec): KEY_L case 237: KB_CHAR('.', '>'); break; // (xed): KEY_PERIOD case 239: KB_CHAR('0', ')'); break; // (xef): KEY_TR_0 case 240: KB_CHAR('p', 'P'); break; // (xf0): KEY_P case 242: KB_CHAR(';', ':'); break; // (xf2): KEY_SEMICOLON case 243: KB_CHAR('/', '?'); break; // (xf3): KEY_QMARK case 245: KB_CHAR('=', '+'); break; // (xf5): KEY_PLUS case 246: KB_CHAR(']', '}'); break; // (xf6): KEY_RBRACE case 247: KB_CHAR('\\', '|'); break; // (xf7): KEY_VBAR case 249: KB_CHAR('-', '_'); break; // (xf9): KEY_UBAR case 250: KB_CHAR('[', '{'); break; // (xfa): KEY_LBRACE case 251: KB_CHAR('\'', '"'); break; // (xfb): KEY_QUOTE /* Key Division 2: 145 - 165 */ /*146 (x92): KEY_KP_0 148 (x94): KEY_KP_PERIOD 149 (x95): KEY_KP_ENTER 150 (x96): KEY_KP_1 151 (x97): KEY_KP_2 152 (x98): KEY_KP_3 153 (x99): KEY_KP_4 154 (x9a): KEY_KP_5 155 (x9b): KEY_KP_6 156 (x9c): KEY_KP_COMMA 157 (x9d): KEY_KP_7 158 (x9e): KEY_KP_8 159 (x9f): KEY_KP_9 160 (xa0): KEY_KP_HYPHEN 161 (xa1): KEY_KP_PF1 162 (xa2): KEY_KP_PF2 163 (xa3): KEY_KP_PF3 164 (xa4): KEY_KP_PF4*/ /* Key Division 3: 188 - 188 */ case 188: c = 0177; Serial.print(""); break; // (xbc): KEY_DELETE /* Key Division 4: 189 - 190 */ case 189: c = '\n'; break; // (xbd): KEY_RETURN case 190: c = '\t'; break; // (xbe): KEY_TAB /* Key Division 5: (176 - 178) */ /*176 (xb0): KEY_LOCK 177 (xb1): KEY_META*/ /* Key Division 6: (173 - 175) */ case 174: mod_shift = !mod_shift; Serial.print(""); break; // (xae): KEY_SHIFT case 175: mod_ctrl = !mod_ctrl; Serial.print(""); break; // (xaf): KEY_CTRL*/ /* Key Division 7: (166 - 168) */ case 167: SerialTty.print("\033[D"); Serial.print("LEFT "); break; // (xa7): KEY_LEFT case 168: SerialTty.print("\033[C"); Serial.print("RIGHT "); break; // (xa8): KEY_RIGHT /* Key Division 8: (169 - 172) */ case 169: SerialTty.print("\033[B"); Serial.print("DOWN "); break; // (xa9): KEY_DOWN case 170: SerialTty.print("\033[A"); Serial.print("UP "); break; // (xaa): KEY_UP case 171: break; // (xab): KEY_R_SHIFT case 100: Serial.print(" "); SerialKbd.print((char)LK_BELL_ENABLE); SerialKbd.print((char)LK_PARAM_VOLUME(0x7)); break; case 101: Serial.print(" "); SerialKbd.print((char)LK_BELL_DISABLE); break; case 102: break; // F8 case 103: Serial.print(" "); SerialKbd.print((char)LK_LED_ENABLE); SerialKbd.print((char)LED_WAIT); break; case 104: Serial.print(" "); SerialKbd.print((char)LK_LED_DISABLE); SerialKbd.print((char)LED_WAIT); break; case 86: SerialTty.print("\x1B"); Serial.print(" "); break; case LK_INPUT_ERROR: Serial.print(" "); break; case LK_ALLUP: mod_shift = false; mod_ctrl = false; Serial.print(""); break; default: Serial.print(key); Serial.print(' '); } if (c != -1) { Serial.print((char) c); SerialTty.print((char) c); } }