Whilst working on a new video device I ran into a few problems with the LKxxx keyboard and I noticed there are already some open issues against the keyboard and mouse devices. These changes should resolve #320 and may help with #272 (although I think that is an SDL issue). I've tested these changes with VWS, UWS and DECwindows with both captured and uncaptured input modes.
865 lines
23 KiB
C
865 lines
23 KiB
C
/* 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) */
|