/* vax_lk.c: DEC Keyboard (LK201) | |
Copyright (c) 2013-2017, Matt Burke | |
Permission is hereby granted, free of charge, to any person obtaining a | |
copy of this software and associated documentation files (the "Software"), | |
to deal in the Software without restriction, including without limitation | |
the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
and/or sell copies of the Software, and to permit persons to whom the | |
Software is furnished to do so, subject to the following conditions: | |
The above copyright notice and this permission notice shall be included in | |
all copies or substantial portions of the Software. | |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | |
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
Except as contained in this notice, the name of the author shall not be | |
used in advertising or otherwise to promote the sale, use or other dealings | |
in this Software without prior written authorization from the author. | |
lk LK201 keyboard | |
11-Jun-2013 MB First version | |
Related documents: | |
EK-104AA-TM-001 - VCB02 Technical Manual (chapter B.5) | |
*/ | |
#if !defined(VAX_620) | |
#include "vax_lk.h" | |
/* States */ | |
#define LK_IDLE 0 | |
#define LK_RECV 1 | |
#define LK_SEND 2 | |
/* Key group moding */ | |
#define LK_MODE_DOWN 0 | |
#define LK_MODE_AUTODOWN 1 | |
#define LK_MODE_NONE 2 | |
#define LK_MODE_DOWNUP 3 | |
#define LK_BUF_LEN 100 | |
#define LK_SEND_CHAR(c) lk_put_fifo (&lk_sndf, c) | |
static const char *lk_modes[] = {"DOWN", "AUTODOWN", "NONE", "DOWNUP"}; | |
static const char *lk_states[] = {"DOWN", "UP", "REPEAT"}; | |
typedef struct { | |
int32 head; | |
int32 tail; | |
int32 count; | |
uint8 buf[LK_BUF_LEN]; | |
} LK_FIFO; | |
/* Scan codes */ | |
typedef struct { | |
int8 group; | |
uint8 code; | |
} LK_KEYDATA; | |
LK_KEYDATA LK_KEY_UNKNOWN = { 0, LK_UNKNOWN }; | |
LK_KEYDATA LK_KEY_TR_0 = { 1, LK_TR_0 }; | |
LK_KEYDATA LK_KEY_TR_1 = { 1, LK_TR_1 }; | |
LK_KEYDATA LK_KEY_TR_2 = { 1, LK_TR_2 }; | |
LK_KEYDATA LK_KEY_TR_3 = { 1, LK_TR_3 }; | |
LK_KEYDATA LK_KEY_TR_4 = { 1, LK_TR_4 }; | |
LK_KEYDATA LK_KEY_TR_5 = { 1, LK_TR_5 }; | |
LK_KEYDATA LK_KEY_TR_6 = { 1, LK_TR_6 }; | |
LK_KEYDATA LK_KEY_TR_7 = { 1, LK_TR_7 }; | |
LK_KEYDATA LK_KEY_TR_8 = { 1, LK_TR_8 }; | |
LK_KEYDATA LK_KEY_TR_9 = { 1, LK_TR_9 }; | |
LK_KEYDATA LK_KEY_A = { 1, LK_A }; | |
LK_KEYDATA LK_KEY_B = { 1, LK_B }; | |
LK_KEYDATA LK_KEY_C = { 1, LK_C }; | |
LK_KEYDATA LK_KEY_D = { 1, LK_D }; | |
LK_KEYDATA LK_KEY_E = { 1, LK_E }; | |
LK_KEYDATA LK_KEY_F = { 1, LK_F }; | |
LK_KEYDATA LK_KEY_G = { 1, LK_G }; | |
LK_KEYDATA LK_KEY_H = { 1, LK_H }; | |
LK_KEYDATA LK_KEY_I = { 1, LK_I }; | |
LK_KEYDATA LK_KEY_J = { 1, LK_J }; | |
LK_KEYDATA LK_KEY_K = { 1, LK_K }; | |
LK_KEYDATA LK_KEY_L = { 1, LK_L }; | |
LK_KEYDATA LK_KEY_M = { 1, LK_M }; | |
LK_KEYDATA LK_KEY_N = { 1, LK_N }; | |
LK_KEYDATA LK_KEY_O = { 1, LK_O }; | |
LK_KEYDATA LK_KEY_P = { 1, LK_P }; | |
LK_KEYDATA LK_KEY_Q = { 1, LK_Q }; | |
LK_KEYDATA LK_KEY_R = { 1, LK_R }; | |
LK_KEYDATA LK_KEY_S = { 1, LK_S }; | |
LK_KEYDATA LK_KEY_T = { 1, LK_T }; | |
LK_KEYDATA LK_KEY_U = { 1, LK_U }; | |
LK_KEYDATA LK_KEY_V = { 1, LK_V }; | |
LK_KEYDATA LK_KEY_W = { 1, LK_W }; | |
LK_KEYDATA LK_KEY_X = { 1, LK_X }; | |
LK_KEYDATA LK_KEY_Y = { 1, LK_Y }; | |
LK_KEYDATA LK_KEY_Z = { 1, LK_Z }; | |
LK_KEYDATA LK_KEY_SPACE = { 1, LK_SPACE }; | |
LK_KEYDATA LK_KEY_SEMICOLON = { 1, LK_SEMICOLON }; | |
LK_KEYDATA LK_KEY_PLUS = { 1, LK_PLUS }; | |
LK_KEYDATA LK_KEY_COMMA = { 1, LK_COMMA }; | |
LK_KEYDATA LK_KEY_UBAR = { 1, LK_UBAR }; | |
LK_KEYDATA LK_KEY_PERIOD = { 1, LK_PERIOD }; | |
LK_KEYDATA LK_KEY_QMARK = { 1, LK_QMARK }; | |
LK_KEYDATA LK_KEY_QUOTE = { 1, LK_QUOTE }; | |
LK_KEYDATA LK_KEY_LBRACE = { 1, LK_LBRACE }; | |
LK_KEYDATA LK_KEY_RBRACE = { 1, LK_RBRACE }; | |
LK_KEYDATA LK_KEY_VBAR = { 1, LK_VBAR }; | |
LK_KEYDATA LK_KEY_TILDE = { 1, LK_TILDE }; | |
LK_KEYDATA LK_KEY_KP_0 = { 2, LK_KP_0 }; | |
LK_KEYDATA LK_KEY_KP_1 = { 2, LK_KP_1 }; | |
LK_KEYDATA LK_KEY_KP_2 = { 2, LK_KP_2 }; | |
LK_KEYDATA LK_KEY_KP_3 = { 2, LK_KP_3 }; | |
LK_KEYDATA LK_KEY_KP_4 = { 2, LK_KP_4 }; | |
LK_KEYDATA LK_KEY_KP_5 = { 2, LK_KP_5 }; | |
LK_KEYDATA LK_KEY_KP_6 = { 2, LK_KP_6 }; | |
LK_KEYDATA LK_KEY_KP_7 = { 2, LK_KP_7 }; | |
LK_KEYDATA LK_KEY_KP_8 = { 2, LK_KP_8 }; | |
LK_KEYDATA LK_KEY_KP_9 = { 2, LK_KP_9 }; | |
LK_KEYDATA LK_KEY_KP_PF1 = { 2, LK_KP_PF1 }; | |
LK_KEYDATA LK_KEY_KP_PF2 = { 2, LK_KP_PF2 }; | |
LK_KEYDATA LK_KEY_KP_PF3 = { 2, LK_KP_PF3 }; | |
LK_KEYDATA LK_KEY_KP_PF4 = { 2, LK_KP_PF4 }; | |
LK_KEYDATA LK_KEY_KP_HYPHEN = { 2, LK_KP_HYPHEN }; | |
LK_KEYDATA LK_KEY_KP_COMMA = { 2, LK_KP_COMMA }; | |
LK_KEYDATA LK_KEY_KP_PERIOD = { 2, LK_KP_PERIOD }; | |
LK_KEYDATA LK_KEY_KP_ENTER = { 2, LK_KP_ENTER }; | |
LK_KEYDATA LK_KEY_DELETE = { 3, LK_DELETE }; | |
LK_KEYDATA LK_KEY_TAB = { 3, LK_TAB }; | |
LK_KEYDATA LK_KEY_RETURN = { 4, LK_RETURN }; | |
LK_KEYDATA LK_KEY_META = { 5, LK_META }; | |
LK_KEYDATA LK_KEY_LOCK = { 5, LK_LOCK }; | |
LK_KEYDATA LK_KEY_SHIFT = { 6, LK_SHIFT }; | |
LK_KEYDATA LK_KEY_CTRL = { 6, LK_CTRL }; | |
LK_KEYDATA LK_KEY_LEFT = { 7, LK_LEFT }; | |
LK_KEYDATA LK_KEY_RIGHT = { 7, LK_RIGHT }; | |
LK_KEYDATA LK_KEY_UP = { 8, LK_UP }; | |
LK_KEYDATA LK_KEY_DOWN = { 8, LK_DOWN }; | |
LK_KEYDATA LK_KEY_REMOVE = { 9, LK_REMOVE }; | |
LK_KEYDATA LK_KEY_NEXT_SCREEN= { 9, LK_NEXT_SCREEN }; | |
LK_KEYDATA LK_KEY_PREV_SCREEN= { 9, LK_PREV_SCREEN }; | |
LK_KEYDATA LK_KEY_INSERT_HERE= { 9, LK_INSERT_HERE }; | |
LK_KEYDATA LK_KEY_FIND = { 9, LK_FIND }; | |
LK_KEYDATA LK_KEY_SELECT = { 9, LK_SELECT }; | |
LK_KEYDATA LK_KEY_F1 = { 10, LK_F1 }; | |
LK_KEYDATA LK_KEY_F2 = { 10, LK_F2 }; | |
LK_KEYDATA LK_KEY_F3 = { 10, LK_F3 }; | |
LK_KEYDATA LK_KEY_F4 = { 10, LK_F4 }; | |
LK_KEYDATA LK_KEY_F5 = { 10, LK_F5 }; | |
LK_KEYDATA LK_KEY_F6 = { 11, LK_F6 }; | |
LK_KEYDATA LK_KEY_F7 = { 11, LK_F7 }; | |
LK_KEYDATA LK_KEY_F8 = { 11, LK_F8 }; | |
LK_KEYDATA LK_KEY_F9 = { 11, LK_F9 }; | |
LK_KEYDATA LK_KEY_F10 = { 11, LK_F10 }; | |
LK_KEYDATA LK_KEY_F11 = { 12, LK_F11 }; | |
LK_KEYDATA LK_KEY_F12 = { 12, LK_F12 }; | |
/* Debugging Bitmaps */ | |
#define DBG_SERIAL 0x0001 /* serial port data */ | |
#define DBG_CMD 0x0002 /* commands */ | |
t_bool lk_repeat = TRUE; /* autorepeat flag */ | |
t_bool lk_trpti = FALSE; /* temp repeat inhibit */ | |
int32 lk_keysdown = 0; /* no of keys held down */ | |
LK_FIFO lk_sndf; /* send FIFO */ | |
LK_FIFO lk_rcvf; /* receive FIFO */ | |
int32 lk_mode[16]; /* mode of each key group */ | |
t_stat lk_wr (uint8 c); | |
t_stat lk_rd (uint8 *c); | |
t_stat lk_reset (DEVICE *dptr); | |
void lk_reset_mode (void); | |
void lk_cmd (void); | |
const char *lk_description (DEVICE *dptr); | |
t_stat lk_put_fifo (LK_FIFO *fifo, uint8 data); | |
t_stat lk_get_fifo (LK_FIFO *fifo, uint8 *data); | |
void lk_clear_fifo (LK_FIFO *fifo); | |
/* LK data structures | |
lk_dev LK device descriptor | |
lk_unit LK unit list | |
lk_reg LK register list | |
lk_mod LK modifier list | |
lk_debug LK debug list | |
*/ | |
DEBTAB lk_debug[] = { | |
{"SERIAL", DBG_SERIAL, "Serial port data"}, | |
{"CMD", DBG_CMD, "Commands"}, | |
{0} | |
}; | |
UNIT lk_unit = { UDATA (NULL, 0, 0) }; | |
REG lk_reg[] = { | |
{ NULL } | |
}; | |
MTAB lk_mod[] = { | |
{ 0 } | |
}; | |
DEVICE lk_dev = { | |
"LK", &lk_unit, lk_reg, lk_mod, | |
1, DEV_RDX, 20, 1, DEV_RDX, 8, | |
NULL, NULL, &lk_reset, | |
NULL, NULL, NULL, | |
NULL, DEV_DIS | DEV_DEBUG, 0, | |
lk_debug, NULL, NULL, NULL, NULL, NULL, | |
&lk_description | |
}; | |
/* Incoming data on serial line */ | |
t_stat lk_wr (uint8 c) | |
{ | |
sim_debug (DBG_SERIAL, &lk_dev, "vax -> lk: %02X\n", c); | |
if (c == 0) | |
return SCPE_OK; | |
if (lk_put_fifo (&lk_rcvf, c) != SCPE_OK) { /* too long? */ | |
lk_clear_fifo (&lk_rcvf); | |
LK_SEND_CHAR(LK_INERR); /* input error */ | |
return SCPE_OK; | |
} | |
if (c & 0x80) /* cmd terminator? */ | |
lk_cmd(); /* process cmd */ | |
return SCPE_OK; | |
} | |
/* Outgoing data on serial line */ | |
t_stat lk_rd (uint8 *c) | |
{ | |
t_stat r; | |
r = lk_get_fifo (&lk_sndf, c); | |
if (r == SCPE_OK) | |
sim_debug (DBG_SERIAL, &lk_dev, "lk -> vax: %02X (%s)\n", *c, | |
(lk_sndf.count > 0) ? "more" : "end"); | |
return r; | |
} | |
t_stat lk_put_fifo (LK_FIFO *fifo, uint8 data) | |
{ | |
if (fifo->count < LK_BUF_LEN) { | |
fifo->buf[fifo->head++] = data; | |
if (fifo->head == LK_BUF_LEN) | |
fifo->head = 0; | |
fifo->count++; | |
return SCPE_OK; | |
} | |
else | |
return SCPE_EOF; | |
} | |
t_stat lk_get_fifo (LK_FIFO *fifo, uint8 *data) | |
{ | |
if (fifo->count > 0) { | |
*data = fifo->buf[fifo->tail++]; | |
if (fifo->tail == LK_BUF_LEN) | |
fifo->tail = 0; | |
fifo->count--; | |
return SCPE_OK; | |
} | |
else | |
return SCPE_EOF; | |
} | |
void lk_clear_fifo (LK_FIFO *fifo) | |
{ | |
fifo->head = 0; | |
fifo->tail = 0; | |
fifo->count = 0; | |
} | |
void lk_cmd () | |
{ | |
int32 i, group, mode; | |
uint8 data; | |
lk_get_fifo (&lk_rcvf, &data); | |
if (data & 1) { /* peripheral command */ | |
switch (data) { | |
case 0x11: | |
sim_debug (DBG_CMD, &lk_dev, "LED on\n"); | |
break; | |
case 0x13: | |
sim_debug (DBG_CMD, &lk_dev, "LED off\n"); | |
break; | |
case 0x89: | |
sim_debug (DBG_CMD, &lk_dev, "inhibit keyboard transmission\n"); | |
break; | |
case 0x8B: | |
sim_debug (DBG_CMD, &lk_dev, "resume keyboard transmission\n"); | |
lk_clear_fifo (&lk_sndf); | |
break; | |
case 0x99: | |
sim_debug (DBG_CMD, &lk_dev, "disable keyclick\n"); | |
break; | |
case 0x1B: | |
sim_debug (DBG_CMD, &lk_dev, "enable keyclick, volume = \n"); | |
break; | |
case 0xB9: | |
sim_debug (DBG_CMD, &lk_dev, "disable ctrl keyclick\n"); | |
break; | |
case 0xBB: | |
sim_debug (DBG_CMD, &lk_dev, "enable ctrl keyclick\n"); | |
break; | |
case 0x9F: | |
sim_debug (DBG_CMD, &lk_dev, "sound keyclick\n"); | |
break; | |
case 0xA1: | |
sim_debug (DBG_CMD, &lk_dev, "disable bell\n"); | |
break; | |
case 0x23: | |
sim_debug (DBG_CMD, &lk_dev, "enable bell, volume = \n"); | |
break; | |
case 0xA7: | |
sim_debug (DBG_CMD, &lk_dev, "sound bell\n"); | |
vid_beep (); | |
break; | |
case 0xC1: | |
sim_debug (DBG_CMD, &lk_dev, "temporary auto-repeat inhibit\n"); | |
lk_trpti = TRUE; | |
break; | |
case 0xE3: | |
sim_debug (DBG_CMD, &lk_dev, "enable auto-repeat across keyboard\n"); | |
lk_repeat = TRUE; | |
break; | |
case 0xE1: | |
sim_debug (DBG_CMD, &lk_dev, "disable auto-repeat across keyboard\n"); | |
lk_repeat = FALSE; | |
break; | |
case 0xD9: | |
sim_debug (DBG_CMD, &lk_dev, "change all auto-repeat to down only\n"); | |
for (i = 0; i <= 15; i++) { | |
if (lk_mode[i] == LK_MODE_AUTODOWN) | |
lk_mode[i] = LK_MODE_DOWN; | |
} | |
break; | |
case 0xAB: | |
sim_debug (DBG_CMD, &lk_dev, "request keyboard ID\n"); | |
LK_SEND_CHAR (0x01); | |
LK_SEND_CHAR (0x00); | |
break; | |
case 0xFD: | |
sim_debug (DBG_CMD, &lk_dev, "jump to power-up\n"); | |
LK_SEND_CHAR (0x01); | |
LK_SEND_CHAR (0x00); | |
LK_SEND_CHAR (0x00); | |
LK_SEND_CHAR (0x00); | |
break; | |
case 0xCB: | |
sim_debug (DBG_CMD, &lk_dev, "jump to test mode\n"); | |
break; | |
case 0xD3: | |
sim_debug (DBG_CMD, &lk_dev, "reinstate defaults\n"); | |
lk_reset_mode (); | |
lk_repeat = TRUE; | |
lk_trpti = FALSE; | |
LK_SEND_CHAR (LK_MODEACK); /* Mode change ACK */ | |
break; | |
default: | |
sim_printf ("lk: unknown cmd %02X\n", data); | |
break; | |
} | |
} | |
else { | |
group = (data >> 3) & 0xF; | |
if (group < 15) { | |
mode = (data >> 1) & 0x3; | |
sim_debug (DBG_CMD, &lk_dev, "set group %d, mode = %s\n", group, lk_modes[mode]); | |
lk_mode[group] = mode; | |
LK_SEND_CHAR (LK_MODEACK); /* Mode change ACK */ | |
} | |
else | |
sim_debug (DBG_CMD, &lk_dev, "set auto-repeat timing\n"); | |
} | |
lk_clear_fifo (&lk_rcvf); | |
} | |
LK_KEYDATA lk_map_key (int key) | |
{ | |
LK_KEYDATA lk_key; | |
switch (key) { | |
case SIM_KEY_F1: | |
lk_key = LK_KEY_F1; | |
break; | |
case SIM_KEY_F2: | |
lk_key = LK_KEY_F2; | |
break; | |
case SIM_KEY_F3: | |
lk_key = LK_KEY_F3; | |
break; | |
case SIM_KEY_F4: | |
lk_key = LK_KEY_F4; | |
break; | |
case SIM_KEY_F5: | |
lk_key = LK_KEY_F5; | |
break; | |
case SIM_KEY_F6: | |
lk_key = LK_KEY_F6; | |
break; | |
case SIM_KEY_F7: | |
lk_key = LK_KEY_F7; | |
break; | |
case SIM_KEY_F8: | |
lk_key = LK_KEY_F8; | |
break; | |
case SIM_KEY_F9: | |
lk_key = LK_KEY_F9; | |
break; | |
case SIM_KEY_F10: | |
lk_key = LK_KEY_F10; | |
break; | |
case SIM_KEY_F11: | |
lk_key = LK_KEY_F11; | |
break; | |
case SIM_KEY_F12: | |
lk_key = LK_KEY_F12; | |
break; | |
case SIM_KEY_0: | |
lk_key = LK_KEY_TR_0; | |
break; | |
case SIM_KEY_1: | |
lk_key = LK_KEY_TR_1; | |
break; | |
case SIM_KEY_2: | |
lk_key = LK_KEY_TR_2; | |
break; | |
case SIM_KEY_3: | |
lk_key = LK_KEY_TR_3; | |
break; | |
case SIM_KEY_4: | |
lk_key = LK_KEY_TR_4; | |
break; | |
case SIM_KEY_5: | |
lk_key = LK_KEY_TR_5; | |
break; | |
case SIM_KEY_6: | |
lk_key = LK_KEY_TR_6; | |
break; | |
case SIM_KEY_7: | |
lk_key = LK_KEY_TR_7; | |
break; | |
case SIM_KEY_8: | |
lk_key = LK_KEY_TR_8; | |
break; | |
case SIM_KEY_9: | |
lk_key = LK_KEY_TR_9; | |
break; | |
case SIM_KEY_A: | |
lk_key = LK_KEY_A; | |
break; | |
case SIM_KEY_B: | |
lk_key = LK_KEY_B; | |
break; | |
case SIM_KEY_C: | |
lk_key = LK_KEY_C; | |
break; | |
case SIM_KEY_D: | |
lk_key = LK_KEY_D; | |
break; | |
case SIM_KEY_E: | |
lk_key = LK_KEY_E; | |
break; | |
case SIM_KEY_F: | |
lk_key = LK_KEY_F; | |
break; | |
case SIM_KEY_G: | |
lk_key = LK_KEY_G; | |
break; | |
case SIM_KEY_H: | |
lk_key = LK_KEY_H; | |
break; | |
case SIM_KEY_I: | |
lk_key = LK_KEY_I; | |
break; | |
case SIM_KEY_J: | |
lk_key = LK_KEY_J; | |
break; | |
case SIM_KEY_K: | |
lk_key = LK_KEY_K; | |
break; | |
case SIM_KEY_L: | |
lk_key = LK_KEY_L; | |
break; | |
case SIM_KEY_M: | |
lk_key = LK_KEY_M; | |
break; | |
case SIM_KEY_N: | |
lk_key = LK_KEY_N; | |
break; | |
case SIM_KEY_O: | |
lk_key = LK_KEY_O; | |
break; | |
case SIM_KEY_P: | |
lk_key = LK_KEY_P; | |
break; | |
case SIM_KEY_Q: | |
lk_key = LK_KEY_Q; | |
break; | |
case SIM_KEY_R: | |
lk_key = LK_KEY_R; | |
break; | |
case SIM_KEY_S: | |
lk_key = LK_KEY_S; | |
break; | |
case SIM_KEY_T: | |
lk_key = LK_KEY_T; | |
break; | |
case SIM_KEY_U: | |
lk_key = LK_KEY_U; | |
break; | |
case SIM_KEY_V: | |
lk_key = LK_KEY_V; | |
break; | |
case SIM_KEY_W: | |
lk_key = LK_KEY_W; | |
break; | |
case SIM_KEY_X: | |
lk_key = LK_KEY_X; | |
break; | |
case SIM_KEY_Y: | |
lk_key = LK_KEY_Y; | |
break; | |
case SIM_KEY_Z: | |
lk_key = LK_KEY_Z; | |
break; | |
case SIM_KEY_BACKQUOTE: | |
lk_key = LK_KEY_TILDE; | |
break; | |
case SIM_KEY_MINUS: | |
lk_key = LK_KEY_UBAR; | |
break; | |
case SIM_KEY_EQUALS: | |
lk_key = LK_KEY_PLUS; | |
break; | |
case SIM_KEY_LEFT_BRACKET: | |
lk_key = LK_KEY_LBRACE; | |
break; | |
case SIM_KEY_RIGHT_BRACKET: | |
lk_key = LK_KEY_RBRACE; | |
break; | |
case SIM_KEY_SEMICOLON: | |
lk_key = LK_KEY_SEMICOLON; | |
break; | |
case SIM_KEY_SINGLE_QUOTE: | |
lk_key = LK_KEY_QUOTE; | |
break; | |
case SIM_KEY_BACKSLASH: | |
lk_key = LK_KEY_VBAR; | |
break; | |
case SIM_KEY_LEFT_BACKSLASH: | |
case SIM_KEY_COMMA: | |
lk_key = LK_KEY_COMMA; | |
break; | |
case SIM_KEY_PERIOD: | |
lk_key = LK_KEY_PERIOD; | |
break; | |
case SIM_KEY_SLASH: | |
lk_key = LK_KEY_QMARK; | |
break; | |
/* case SIM_KEY_PRINT: */ | |
/* case SIM_KEY_PAUSE: */ | |
/* case SIM_KEY_ESC: */ | |
case SIM_KEY_BACKSPACE: | |
lk_key = LK_KEY_DELETE; | |
break; | |
case SIM_KEY_TAB: | |
lk_key = LK_KEY_TAB; | |
break; | |
case SIM_KEY_ENTER: | |
lk_key = LK_KEY_RETURN; | |
break; | |
case SIM_KEY_SPACE: | |
lk_key = LK_KEY_SPACE; | |
break; | |
case SIM_KEY_INSERT: | |
lk_key = LK_KEY_FIND; | |
break; | |
case SIM_KEY_DELETE: | |
lk_key = LK_KEY_SELECT; | |
break; | |
case SIM_KEY_HOME: | |
lk_key = LK_KEY_INSERT_HERE; | |
break; | |
case SIM_KEY_END: | |
lk_key = LK_KEY_PREV_SCREEN; | |
break; | |
case SIM_KEY_PAGE_UP: | |
lk_key = LK_KEY_REMOVE; | |
break; | |
case SIM_KEY_PAGE_DOWN: | |
lk_key = LK_KEY_NEXT_SCREEN; | |
break; | |
case SIM_KEY_UP: | |
lk_key = LK_KEY_UP; | |
break; | |
case SIM_KEY_DOWN: | |
lk_key = LK_KEY_DOWN; | |
break; | |
case SIM_KEY_LEFT: | |
lk_key = LK_KEY_LEFT; | |
break; | |
case SIM_KEY_RIGHT: | |
lk_key = LK_KEY_RIGHT; | |
break; | |
case SIM_KEY_CAPS_LOCK: | |
lk_key = LK_KEY_LOCK; | |
break; | |
case SIM_KEY_NUM_LOCK: | |
lk_key = LK_KEY_KP_PF1; | |
break; | |
case SIM_KEY_SCRL_LOCK: | |
case SIM_KEY_ALT_L: | |
case SIM_KEY_ALT_R: | |
lk_key = LK_KEY_META; | |
break; | |
case SIM_KEY_CTRL_L: | |
case SIM_KEY_CTRL_R: | |
lk_key = LK_KEY_CTRL; | |
break; | |
case SIM_KEY_SHIFT_L: | |
case SIM_KEY_SHIFT_R: | |
lk_key = LK_KEY_SHIFT; | |
break; | |
case SIM_KEY_WIN_L: | |
case SIM_KEY_WIN_R: | |
case SIM_KEY_MENU: | |
lk_key = LK_KEY_UNKNOWN; | |
break; | |
case SIM_KEY_KP_ADD: | |
case SIM_KEY_KP_SUBTRACT: | |
case SIM_KEY_KP_END: | |
case SIM_KEY_KP_DOWN: | |
case SIM_KEY_KP_PAGE_DOWN: | |
case SIM_KEY_KP_LEFT: | |
case SIM_KEY_KP_RIGHT: | |
case SIM_KEY_KP_HOME: | |
case SIM_KEY_KP_UP: | |
case SIM_KEY_KP_PAGE_UP: | |
case SIM_KEY_KP_INSERT: | |
case SIM_KEY_KP_DELETE: | |
case SIM_KEY_KP_5: | |
case SIM_KEY_KP_ENTER: | |
case SIM_KEY_KP_MULTIPLY: | |
case SIM_KEY_KP_DIVIDE: | |
case SIM_KEY_UNKNOWN: | |
lk_key = LK_KEY_UNKNOWN; | |
break; | |
default: | |
lk_key = LK_KEY_UNKNOWN; | |
break; | |
} | |
return lk_key; | |
} | |
void lk_reset_mode (void) | |
{ | |
lk_mode[1] = LK_MODE_AUTODOWN; /* 1 = 48 graphic keys, spacebar */ | |
lk_mode[2] = LK_MODE_AUTODOWN; /* 2 = numeric keypad */ | |
lk_mode[3] = LK_MODE_AUTODOWN; /* 3 = delete character */ | |
lk_mode[4] = LK_MODE_DOWN; /* 4 = return, tab */ | |
lk_mode[5] = LK_MODE_DOWN; /* 5 = lock, compose */ | |
lk_mode[6] = LK_MODE_DOWNUP; /* 6 = shift, ctrl */ | |
lk_mode[7] = LK_MODE_AUTODOWN; /* 7 = horizontal cursors */ | |
lk_mode[8] = LK_MODE_AUTODOWN; /* 8 = vertical cursors */ | |
lk_mode[9] = LK_MODE_DOWNUP; /* 9 = six basic editing keys */ | |
lk_mode[10] = LK_MODE_AUTODOWN; /* 10 = function keys: f1 - f5 */ | |
lk_mode[11] = LK_MODE_AUTODOWN; /* 11 = function keys: f6 - f10 */ | |
lk_mode[12] = LK_MODE_AUTODOWN; /* 12 = function keys: f11 - f14 */ | |
lk_mode[13] = LK_MODE_AUTODOWN; /* 13 = function keys: help, do */ | |
lk_mode[14] = LK_MODE_AUTODOWN; /* 14 = function keys: f17 - f20 */ | |
} | |
t_stat lk_reset (DEVICE *dptr) | |
{ | |
lk_clear_fifo (&lk_sndf); | |
lk_clear_fifo (&lk_rcvf); | |
lk_keysdown = 0; | |
lk_repeat = TRUE; | |
lk_trpti = FALSE; | |
lk_reset_mode (); | |
return SCPE_OK; | |
} | |
void lk_event (SIM_KEY_EVENT *ev) | |
{ | |
LK_KEYDATA lk_key; | |
int32 mode; | |
lk_key = lk_map_key (ev->key); | |
mode = lk_mode[lk_key.group]; | |
sim_debug (DBG_SERIAL, &lk_dev, "lk_poll() Event - Key: (group=%d, code=%02X), Mode: %s - auto-repeat inhibit: %s - state: %s\n", lk_key.group, lk_key.code, lk_modes[mode], lk_trpti ? "TRUE" : "FALSE", lk_states[ev->state]); | |
if (lk_trpti && (ev->state != SIM_KEYPRESS_REPEAT)) | |
lk_trpti = FALSE; | |
switch (mode) { | |
case LK_MODE_DOWN: | |
if (ev->state == SIM_KEYPRESS_DOWN) { | |
LK_SEND_CHAR (lk_key.code); | |
} | |
break; | |
case LK_MODE_AUTODOWN: | |
if (ev->state == SIM_KEYPRESS_DOWN) { | |
LK_SEND_CHAR (lk_key.code); | |
} | |
else if ((ev->state == SIM_KEYPRESS_REPEAT) && lk_repeat && !lk_trpti) { | |
LK_SEND_CHAR (LK_METRONOME); | |
} | |
break; | |
case LK_MODE_DOWNUP: | |
if (ev->state == SIM_KEYPRESS_DOWN) { | |
lk_keysdown++; | |
LK_SEND_CHAR (lk_key.code); | |
} | |
else if (ev->state == SIM_KEYPRESS_UP) { | |
lk_keysdown--; | |
if (lk_keysdown > 0) { | |
LK_SEND_CHAR (lk_key.code); | |
} | |
else { | |
LK_SEND_CHAR (LK_ALLUP); | |
} | |
} | |
break; | |
} | |
} | |
const char *lk_description (DEVICE *dptr) | |
{ | |
return " VCB01 - LK Keyboard interface"; | |
} | |
#else /* defined(VAX_620) */ | |
static const char *dummy_declaration = "Something to compile"; | |
#endif /* !defined(VAX_620) */ |