VAXStations: Improvements and bug fixes to keyboard and mouse devices

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.
This commit is contained in:
Matt Burke 2017-04-23 10:40:00 -07:00 committed by Mark Pizzolato
parent 168d0d9c47
commit c94edb6b2d
10 changed files with 594 additions and 315 deletions

View file

@ -1,6 +1,6 @@
/* vax_lk.c: DEC Keyboard (LK201) /* vax_lk.c: DEC Keyboard (LK201)
Copyright (c) 2011-2013, Matt Burke Copyright (c) 2013-2017, Matt Burke
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -26,12 +26,15 @@
lk LK201 keyboard lk LK201 keyboard
11-Jun-2013 MB First version 11-Jun-2013 MB First version
Related documents:
EK-104AA-TM-001 - VCB02 Technical Manual (chapter B.5)
*/ */
#if !defined(VAX_620) #if !defined(VAX_620)
#include "vax_defs.h" #include "vax_lk.h"
#include "sim_video.h"
/* States */ /* States */
@ -46,10 +49,21 @@
#define LK_MODE_NONE 2 #define LK_MODE_NONE 2
#define LK_MODE_DOWNUP 3 #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_modes[] = {"DOWN", "AUTODOWN", "NONE", "DOWNUP"};
static const char *lk_states[] = {"DOWN", "UP", "REPEAT"}; 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 */ /* Scan codes */
typedef struct { typedef struct {
@ -57,107 +71,102 @@ typedef struct {
uint8 code; uint8 code;
} LK_KEYDATA; } LK_KEYDATA;
LK_KEYDATA LK_KEY_UNKNOWN = { 0, 0 }; LK_KEYDATA LK_KEY_UNKNOWN = { 0, LK_UNKNOWN };
LK_KEYDATA LK_KEY_TR_0 = { 1, 0xEF }; LK_KEYDATA LK_KEY_TR_0 = { 1, LK_TR_0 };
LK_KEYDATA LK_KEY_TR_1 = { 1, 0xC0 }; LK_KEYDATA LK_KEY_TR_1 = { 1, LK_TR_1 };
LK_KEYDATA LK_KEY_TR_2 = { 1, 0xC5 }; LK_KEYDATA LK_KEY_TR_2 = { 1, LK_TR_2 };
LK_KEYDATA LK_KEY_TR_3 = { 1, 0xCB }; LK_KEYDATA LK_KEY_TR_3 = { 1, LK_TR_3 };
LK_KEYDATA LK_KEY_TR_4 = { 1, 0xD0 }; LK_KEYDATA LK_KEY_TR_4 = { 1, LK_TR_4 };
LK_KEYDATA LK_KEY_TR_5 = { 1, 0xD6 }; LK_KEYDATA LK_KEY_TR_5 = { 1, LK_TR_5 };
LK_KEYDATA LK_KEY_TR_6 = { 1, 0xDB }; LK_KEYDATA LK_KEY_TR_6 = { 1, LK_TR_6 };
LK_KEYDATA LK_KEY_TR_7 = { 1, 0xE0 }; LK_KEYDATA LK_KEY_TR_7 = { 1, LK_TR_7 };
LK_KEYDATA LK_KEY_TR_8 = { 1, 0xE5 }; LK_KEYDATA LK_KEY_TR_8 = { 1, LK_TR_8 };
LK_KEYDATA LK_KEY_TR_9 = { 1, 0xEA }; LK_KEYDATA LK_KEY_TR_9 = { 1, LK_TR_9 };
LK_KEYDATA LK_KEY_A = { 1, 0xC2 }; LK_KEYDATA LK_KEY_A = { 1, LK_A };
LK_KEYDATA LK_KEY_B = { 1, 0xD9 }; LK_KEYDATA LK_KEY_B = { 1, LK_B };
LK_KEYDATA LK_KEY_C = { 1, 0xCE }; LK_KEYDATA LK_KEY_C = { 1, LK_C };
LK_KEYDATA LK_KEY_D = { 1, 0xCD }; LK_KEYDATA LK_KEY_D = { 1, LK_D };
LK_KEYDATA LK_KEY_E = { 1, 0xCC }; LK_KEYDATA LK_KEY_E = { 1, LK_E };
LK_KEYDATA LK_KEY_F = { 1, 0xD2 }; LK_KEYDATA LK_KEY_F = { 1, LK_F };
LK_KEYDATA LK_KEY_G = { 1, 0xD8 }; LK_KEYDATA LK_KEY_G = { 1, LK_G };
LK_KEYDATA LK_KEY_H = { 1, 0xDD }; LK_KEYDATA LK_KEY_H = { 1, LK_H };
LK_KEYDATA LK_KEY_I = { 1, 0xE6 }; LK_KEYDATA LK_KEY_I = { 1, LK_I };
LK_KEYDATA LK_KEY_J = { 1, 0xE2 }; LK_KEYDATA LK_KEY_J = { 1, LK_J };
LK_KEYDATA LK_KEY_K = { 1, 0xE7 }; LK_KEYDATA LK_KEY_K = { 1, LK_K };
LK_KEYDATA LK_KEY_L = { 1, 0xEC }; LK_KEYDATA LK_KEY_L = { 1, LK_L };
LK_KEYDATA LK_KEY_M = { 1, 0xE3 }; LK_KEYDATA LK_KEY_M = { 1, LK_M };
LK_KEYDATA LK_KEY_N = { 1, 0xDE }; LK_KEYDATA LK_KEY_N = { 1, LK_N };
LK_KEYDATA LK_KEY_O = { 1, 0xEB }; LK_KEYDATA LK_KEY_O = { 1, LK_O };
LK_KEYDATA LK_KEY_P = { 1, 0xF0 }; LK_KEYDATA LK_KEY_P = { 1, LK_P };
LK_KEYDATA LK_KEY_Q = { 1, 0xC1 }; LK_KEYDATA LK_KEY_Q = { 1, LK_Q };
LK_KEYDATA LK_KEY_R = { 1, 0xD1 }; LK_KEYDATA LK_KEY_R = { 1, LK_R };
LK_KEYDATA LK_KEY_S = { 1, 0xC7 }; LK_KEYDATA LK_KEY_S = { 1, LK_S };
LK_KEYDATA LK_KEY_T = { 1, 0xD7 }; LK_KEYDATA LK_KEY_T = { 1, LK_T };
LK_KEYDATA LK_KEY_U = { 1, 0xE1 }; LK_KEYDATA LK_KEY_U = { 1, LK_U };
LK_KEYDATA LK_KEY_V = { 1, 0xD3 }; LK_KEYDATA LK_KEY_V = { 1, LK_V };
LK_KEYDATA LK_KEY_W = { 1, 0xC6 }; LK_KEYDATA LK_KEY_W = { 1, LK_W };
LK_KEYDATA LK_KEY_X = { 1, 0xC8 }; LK_KEYDATA LK_KEY_X = { 1, LK_X };
LK_KEYDATA LK_KEY_Y = { 1, 0xDC }; LK_KEYDATA LK_KEY_Y = { 1, LK_Y };
LK_KEYDATA LK_KEY_Z = { 1, 0xC3 }; LK_KEYDATA LK_KEY_Z = { 1, LK_Z };
LK_KEYDATA LK_KEY_SPACE = { 1, 0xD4 }; LK_KEYDATA LK_KEY_SPACE = { 1, LK_SPACE };
LK_KEYDATA LK_KEY_SEMICOLON = { 1, 0xF2 }; LK_KEYDATA LK_KEY_SEMICOLON = { 1, LK_SEMICOLON };
LK_KEYDATA LK_KEY_PLUS = { 1, 0xF5 }; LK_KEYDATA LK_KEY_PLUS = { 1, LK_PLUS };
LK_KEYDATA LK_KEY_COMMA = { 1, 0xE8 }; LK_KEYDATA LK_KEY_COMMA = { 1, LK_COMMA };
LK_KEYDATA LK_KEY_UBAR = { 1, 0xF9 }; LK_KEYDATA LK_KEY_UBAR = { 1, LK_UBAR };
LK_KEYDATA LK_KEY_PERIOD = { 1, 0xED }; LK_KEYDATA LK_KEY_PERIOD = { 1, LK_PERIOD };
LK_KEYDATA LK_KEY_QMARK = { 1, 0xF3 }; LK_KEYDATA LK_KEY_QMARK = { 1, LK_QMARK };
LK_KEYDATA LK_KEY_QUOTE = { 1, 0xFB }; LK_KEYDATA LK_KEY_QUOTE = { 1, LK_QUOTE };
LK_KEYDATA LK_KEY_LBRACE = { 1, 0xFA }; LK_KEYDATA LK_KEY_LBRACE = { 1, LK_LBRACE };
LK_KEYDATA LK_KEY_RBRACE = { 1, 0xF6 }; LK_KEYDATA LK_KEY_RBRACE = { 1, LK_RBRACE };
LK_KEYDATA LK_KEY_VBAR = { 1, 0xF7 }; LK_KEYDATA LK_KEY_VBAR = { 1, LK_VBAR };
LK_KEYDATA LK_KEY_TILDE = { 1, 0xBF }; LK_KEYDATA LK_KEY_TILDE = { 1, LK_TILDE };
LK_KEYDATA LK_KEY_KP_0 = { 2, 0x92 }; LK_KEYDATA LK_KEY_KP_0 = { 2, LK_KP_0 };
LK_KEYDATA LK_KEY_KP_1 = { 2, 0x96 }; LK_KEYDATA LK_KEY_KP_1 = { 2, LK_KP_1 };
LK_KEYDATA LK_KEY_KP_2 = { 2, 0x97 }; LK_KEYDATA LK_KEY_KP_2 = { 2, LK_KP_2 };
LK_KEYDATA LK_KEY_KP_3 = { 2, 0x98 }; LK_KEYDATA LK_KEY_KP_3 = { 2, LK_KP_3 };
LK_KEYDATA LK_KEY_KP_4 = { 2, 0x99 }; LK_KEYDATA LK_KEY_KP_4 = { 2, LK_KP_4 };
LK_KEYDATA LK_KEY_KP_5 = { 2, 0x9A }; LK_KEYDATA LK_KEY_KP_5 = { 2, LK_KP_5 };
LK_KEYDATA LK_KEY_KP_6 = { 2, 0x9B }; LK_KEYDATA LK_KEY_KP_6 = { 2, LK_KP_6 };
LK_KEYDATA LK_KEY_KP_7 = { 2, 0x9D }; LK_KEYDATA LK_KEY_KP_7 = { 2, LK_KP_7 };
LK_KEYDATA LK_KEY_KP_8 = { 2, 0x9E }; LK_KEYDATA LK_KEY_KP_8 = { 2, LK_KP_8 };
LK_KEYDATA LK_KEY_KP_9 = { 2, 0x9F }; LK_KEYDATA LK_KEY_KP_9 = { 2, LK_KP_9 };
LK_KEYDATA LK_KEY_KP_PF1 = { 2, 0xA1 }; LK_KEYDATA LK_KEY_KP_PF1 = { 2, LK_KP_PF1 };
LK_KEYDATA LK_KEY_KP_PF2 = { 2, 0xA2 }; LK_KEYDATA LK_KEY_KP_PF2 = { 2, LK_KP_PF2 };
LK_KEYDATA LK_KEY_KP_PF3 = { 2, 0xA3 }; LK_KEYDATA LK_KEY_KP_PF3 = { 2, LK_KP_PF3 };
LK_KEYDATA LK_KEY_KP_PF4 = { 2, 0xA4 }; LK_KEYDATA LK_KEY_KP_PF4 = { 2, LK_KP_PF4 };
LK_KEYDATA LK_KEY_KP_HYPHEN = { 2, 0xA0 }; LK_KEYDATA LK_KEY_KP_HYPHEN = { 2, LK_KP_HYPHEN };
LK_KEYDATA LK_KEY_KP_COMMA = { 2, 0x9C }; LK_KEYDATA LK_KEY_KP_COMMA = { 2, LK_KP_COMMA };
LK_KEYDATA LK_KEY_KP_PERIOD = { 2, 0x94 }; LK_KEYDATA LK_KEY_KP_PERIOD = { 2, LK_KP_PERIOD };
LK_KEYDATA LK_KEY_KP_ENTER = { 2, 0x95 }; LK_KEYDATA LK_KEY_KP_ENTER = { 2, LK_KP_ENTER };
LK_KEYDATA LK_KEY_DELETE = { 3, 0xBC }; LK_KEYDATA LK_KEY_DELETE = { 3, LK_DELETE };
LK_KEYDATA LK_KEY_TAB = { 3, 0xBE }; LK_KEYDATA LK_KEY_TAB = { 3, LK_TAB };
LK_KEYDATA LK_KEY_RETURN = { 4, 0xBD }; LK_KEYDATA LK_KEY_RETURN = { 4, LK_RETURN };
LK_KEYDATA LK_KEY_META = { 5, 0xB1 }; LK_KEYDATA LK_KEY_META = { 5, LK_META };
LK_KEYDATA LK_KEY_LOCK = { 5, 0xB0 }; LK_KEYDATA LK_KEY_LOCK = { 5, LK_LOCK };
LK_KEYDATA LK_KEY_SHIFT = { 6, 0xAE }; LK_KEYDATA LK_KEY_SHIFT = { 6, LK_SHIFT };
LK_KEYDATA LK_KEY_CTRL = { 6, 0xAF }; LK_KEYDATA LK_KEY_CTRL = { 6, LK_CTRL };
LK_KEYDATA LK_KEY_LEFT = { 7, 0xA7 }; LK_KEYDATA LK_KEY_LEFT = { 7, LK_LEFT };
LK_KEYDATA LK_KEY_RIGHT = { 7, 0xA8 }; LK_KEYDATA LK_KEY_RIGHT = { 7, LK_RIGHT };
LK_KEYDATA LK_KEY_UP = { 8, 0xAA }; LK_KEYDATA LK_KEY_UP = { 8, LK_UP };
LK_KEYDATA LK_KEY_DOWN = { 8, 0xA9 }; LK_KEYDATA LK_KEY_DOWN = { 8, LK_DOWN };
LK_KEYDATA LK_KEY_REMOVE = { 9, 0x8C }; LK_KEYDATA LK_KEY_REMOVE = { 9, LK_REMOVE };
LK_KEYDATA LK_KEY_NEXT_SCREEN= { 9, 0x8F }; LK_KEYDATA LK_KEY_NEXT_SCREEN= { 9, LK_NEXT_SCREEN };
LK_KEYDATA LK_KEY_PREV_SCREEN= { 9, 0x8E }; LK_KEYDATA LK_KEY_PREV_SCREEN= { 9, LK_PREV_SCREEN };
LK_KEYDATA LK_KEY_INSERT_HERE= { 9, 0x8B }; LK_KEYDATA LK_KEY_INSERT_HERE= { 9, LK_INSERT_HERE };
LK_KEYDATA LK_KEY_FIND = { 9, 0x8A }; LK_KEYDATA LK_KEY_FIND = { 9, LK_FIND };
LK_KEYDATA LK_KEY_SELECT = { 9, 0x8D }; LK_KEYDATA LK_KEY_SELECT = { 9, LK_SELECT };
LK_KEYDATA LK_KEY_F1 = { 10, 0x56 }; LK_KEYDATA LK_KEY_F1 = { 10, LK_F1 };
LK_KEYDATA LK_KEY_F2 = { 10, 0x57 }; LK_KEYDATA LK_KEY_F2 = { 10, LK_F2 };
LK_KEYDATA LK_KEY_F3 = { 10, 0x58 }; LK_KEYDATA LK_KEY_F3 = { 10, LK_F3 };
LK_KEYDATA LK_KEY_F4 = { 10, 0x59 }; LK_KEYDATA LK_KEY_F4 = { 10, LK_F4 };
LK_KEYDATA LK_KEY_F5 = { 10, 0x5A }; LK_KEYDATA LK_KEY_F5 = { 10, LK_F5 };
LK_KEYDATA LK_KEY_F6 = { 11, 0x64 }; LK_KEYDATA LK_KEY_F6 = { 11, LK_F6 };
LK_KEYDATA LK_KEY_F7 = { 11, 0x65 }; LK_KEYDATA LK_KEY_F7 = { 11, LK_F7 };
LK_KEYDATA LK_KEY_F8 = { 11, 0x66 }; LK_KEYDATA LK_KEY_F8 = { 11, LK_F8 };
LK_KEYDATA LK_KEY_F9 = { 11, 0x67 }; LK_KEYDATA LK_KEY_F9 = { 11, LK_F9 };
LK_KEYDATA LK_KEY_F10 = { 11, 0x68 }; LK_KEYDATA LK_KEY_F10 = { 11, LK_F10 };
LK_KEYDATA LK_KEY_F11 = { 12, 0x71 }; LK_KEYDATA LK_KEY_F11 = { 12, LK_F11 };
LK_KEYDATA LK_KEY_F12 = { 12, 0x72 }; LK_KEYDATA LK_KEY_F12 = { 12, LK_F12 };
#define LK_BUF_LEN 100
#define LK_SEND_CHAR(c) lk_sbuf[lk_stptr++] = c; \
if (lk_stptr == LK_BUF_LEN) lk_stptr = 0
/* Debugging Bitmaps */ /* Debugging Bitmaps */
@ -167,11 +176,8 @@ LK_KEYDATA LK_KEY_F12 = { 12, 0x72 };
t_bool lk_repeat = TRUE; /* autorepeat flag */ t_bool lk_repeat = TRUE; /* autorepeat flag */
t_bool lk_trpti = FALSE; /* temp repeat inhibit */ t_bool lk_trpti = FALSE; /* temp repeat inhibit */
int32 lk_keysdown = 0; /* no of keys held down */ int32 lk_keysdown = 0; /* no of keys held down */
uint8 lk_sbuf[LK_BUF_LEN]; /* send buffer */ LK_FIFO lk_sndf; /* send FIFO */
int32 lk_shptr = 0; /* send buf head ptr */ LK_FIFO lk_rcvf; /* receive FIFO */
int32 lk_stptr = 0; /* send buf tail ptr */
uint8 lk_rbuf[10]; /* receive buffer */
int32 lk_rbuf_p = 0; /* receive buffer ptr */
int32 lk_mode[16]; /* mode of each key group */ int32 lk_mode[16]; /* mode of each key group */
t_stat lk_wr (uint8 c); t_stat lk_wr (uint8 c);
@ -179,8 +185,10 @@ t_stat lk_rd (uint8 *c);
t_stat lk_reset (DEVICE *dptr); t_stat lk_reset (DEVICE *dptr);
void lk_reset_mode (void); void lk_reset_mode (void);
void lk_cmd (void); void lk_cmd (void);
void lk_poll (void);
const char *lk_description (DEVICE *dptr); 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 data structures
@ -224,10 +232,9 @@ t_stat lk_wr (uint8 c)
sim_debug (DBG_SERIAL, &lk_dev, "vax -> lk: %02X\n", c); sim_debug (DBG_SERIAL, &lk_dev, "vax -> lk: %02X\n", c);
if (c == 0) if (c == 0)
return SCPE_OK; return SCPE_OK;
lk_rbuf[lk_rbuf_p++] = c; if (lk_put_fifo (&lk_rcvf, c) != SCPE_OK) { /* too long? */
if (lk_rbuf_p == sizeof(lk_rbuf)) { /* too long? */ lk_clear_fifo (&lk_rcvf);
lk_rbuf_p = 0; LK_SEND_CHAR(LK_INERR); /* input error */
LK_SEND_CHAR(0xB6); /* input error */
return SCPE_OK; return SCPE_OK;
} }
if (c & 0x80) /* cmd terminator? */ if (c & 0x80) /* cmd terminator? */
@ -239,28 +246,57 @@ return SCPE_OK;
t_stat lk_rd (uint8 *c) t_stat lk_rd (uint8 *c)
{ {
if (lk_shptr == lk_stptr) t_stat r;
lk_poll ();
if (lk_shptr == lk_stptr) { r = lk_get_fifo (&lk_sndf, c);
*c = 0; if (r == SCPE_OK)
return SCPE_EOF;
}
else {
*c = lk_sbuf[lk_shptr++];
if (lk_shptr == LK_BUF_LEN)
lk_shptr = 0; /* ring buffer wrap */
sim_debug (DBG_SERIAL, &lk_dev, "lk -> vax: %02X (%s)\n", *c, sim_debug (DBG_SERIAL, &lk_dev, "lk -> vax: %02X (%s)\n", *c,
(lk_shptr != lk_stptr) ? "more" : "end"); (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; 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 () void lk_cmd ()
{ {
int32 i, group, mode; int32 i, group, mode;
uint8 data;
if (lk_rbuf[0] & 1) { /* peripheral command */ lk_get_fifo (&lk_rcvf, &data);
switch (lk_rbuf[0]) {
if (data & 1) { /* peripheral command */
switch (data) {
case 0x11: case 0x11:
sim_debug (DBG_CMD, &lk_dev, "LED on\n"); sim_debug (DBG_CMD, &lk_dev, "LED on\n");
@ -276,7 +312,7 @@ if (lk_rbuf[0] & 1) { /* peripheral command */
case 0x8B: case 0x8B:
sim_debug (DBG_CMD, &lk_dev, "resume keyboard transmission\n"); sim_debug (DBG_CMD, &lk_dev, "resume keyboard transmission\n");
lk_shptr = lk_stptr = 0; lk_clear_fifo (&lk_sndf);
break; break;
case 0x99: case 0x99:
@ -358,26 +394,26 @@ if (lk_rbuf[0] & 1) { /* peripheral command */
lk_reset_mode (); lk_reset_mode ();
lk_repeat = TRUE; lk_repeat = TRUE;
lk_trpti = FALSE; lk_trpti = FALSE;
LK_SEND_CHAR (0xBA); /* Mode change ACK */ LK_SEND_CHAR (LK_MODEACK); /* Mode change ACK */
break; break;
default: default:
sim_printf ("lk: unknown cmd %02X\n", lk_rbuf[0]); sim_printf ("lk: unknown cmd %02X\n", data);
break; break;
}
}
else {
group = (lk_rbuf[0] >> 3) & 0xF;
if (group < 15) {
mode = (lk_rbuf[0] >> 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 (0xBA); /* Mode change ACK */
} }
else }
sim_debug (DBG_CMD, &lk_dev, "set auto-repeat timing\n"); 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 */
} }
lk_rbuf_p = 0; 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_map_key (int key)
@ -762,62 +798,57 @@ lk_mode[14] = LK_MODE_AUTODOWN; /* 14 = function keys: f
t_stat lk_reset (DEVICE *dptr) t_stat lk_reset (DEVICE *dptr)
{ {
lk_rbuf_p = 0; lk_clear_fifo (&lk_sndf);
lk_clear_fifo (&lk_rcvf);
lk_keysdown = 0; lk_keysdown = 0;
lk_repeat = TRUE; lk_repeat = TRUE;
lk_trpti = FALSE; lk_trpti = FALSE;
lk_shptr = 0;
lk_stptr = 0;
lk_reset_mode (); lk_reset_mode ();
return SCPE_OK; return SCPE_OK;
} }
void lk_poll (void) void lk_event (SIM_KEY_EVENT *ev)
{ {
SIM_KEY_EVENT ev;
LK_KEYDATA lk_key; LK_KEYDATA lk_key;
int32 mode; int32 mode;
if (vid_poll_kb (&ev) != SCPE_OK) lk_key = lk_map_key (ev->key);
return;
lk_key = lk_map_key (ev.key);
mode = lk_mode[lk_key.group]; 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]); 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)) if (lk_trpti && (ev->state != SIM_KEYPRESS_REPEAT))
lk_trpti = FALSE; lk_trpti = FALSE;
switch (mode) { switch (mode) {
case LK_MODE_DOWN: case LK_MODE_DOWN:
if (ev.state == SIM_KEYPRESS_DOWN) { if (ev->state == SIM_KEYPRESS_DOWN) {
LK_SEND_CHAR (lk_key.code); LK_SEND_CHAR (lk_key.code);
} }
break; break;
case LK_MODE_AUTODOWN: case LK_MODE_AUTODOWN:
if (ev.state == SIM_KEYPRESS_DOWN) { if (ev->state == SIM_KEYPRESS_DOWN) {
LK_SEND_CHAR (lk_key.code); LK_SEND_CHAR (lk_key.code);
} }
else if ((ev.state == SIM_KEYPRESS_REPEAT) && lk_repeat && !lk_trpti) { else if ((ev->state == SIM_KEYPRESS_REPEAT) && lk_repeat && !lk_trpti) {
LK_SEND_CHAR (0xB4); LK_SEND_CHAR (LK_METRONOME);
} }
break; break;
case LK_MODE_DOWNUP: case LK_MODE_DOWNUP:
if (ev.state == SIM_KEYPRESS_DOWN) { if (ev->state == SIM_KEYPRESS_DOWN) {
lk_keysdown++; lk_keysdown++;
LK_SEND_CHAR (lk_key.code); LK_SEND_CHAR (lk_key.code);
} }
else { else if (ev->state == SIM_KEYPRESS_UP) {
lk_keysdown--; lk_keysdown--;
if (lk_keysdown > 0) { if (lk_keysdown > 0) {
LK_SEND_CHAR (lk_key.code); LK_SEND_CHAR (lk_key.code);
} }
else { else {
LK_SEND_CHAR (0xB3); /* LK_ALLUP */ LK_SEND_CHAR (LK_ALLUP);
} }
} }
break; break;

152
VAX/vax_lk.h Normal file
View file

@ -0,0 +1,152 @@
/* vax_lk.h: DEC Keyboard (LK201)
Copyright (c) 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
*/
#ifndef _VAX_LK_H_
#define _VAX_LK_H_
#include "vax_defs.h"
#include "sim_video.h"
/* standard key codes */
#define LK_UNKNOWN 0x00
#define LK_TR_0 0xEF
#define LK_TR_1 0xC0
#define LK_TR_2 0xC5
#define LK_TR_3 0xCB
#define LK_TR_4 0xD0
#define LK_TR_5 0xD6
#define LK_TR_6 0xDB
#define LK_TR_7 0xE0
#define LK_TR_8 0xE5
#define LK_TR_9 0xEA
#define LK_A 0xC2
#define LK_B 0xD9
#define LK_C 0xCE
#define LK_D 0xCD
#define LK_E 0xCC
#define LK_F 0xD2
#define LK_G 0xD8
#define LK_H 0xDD
#define LK_I 0xE6
#define LK_J 0xE2
#define LK_K 0xE7
#define LK_L 0xEC
#define LK_M 0xE3
#define LK_N 0xDE
#define LK_O 0xEB
#define LK_P 0xF0
#define LK_Q 0xC1
#define LK_R 0xD1
#define LK_S 0xC7
#define LK_T 0xD7
#define LK_U 0xE1
#define LK_V 0xD3
#define LK_W 0xC6
#define LK_X 0xC8
#define LK_Y 0xDC
#define LK_Z 0xC3
#define LK_SPACE 0xD4
#define LK_SEMICOLON 0xF2
#define LK_PLUS 0xF5
#define LK_COMMA 0xE8
#define LK_UBAR 0xF9
#define LK_PERIOD 0xED
#define LK_QMARK 0xF3
#define LK_QUOTE 0xFB
#define LK_LBRACE 0xFA
#define LK_RBRACE 0xF6
#define LK_VBAR 0xF7
#define LK_TILDE 0xBF
#define LK_KP_0 0x92
#define LK_KP_1 0x96
#define LK_KP_2 0x97
#define LK_KP_3 0x98
#define LK_KP_4 0x99
#define LK_KP_5 0x9A
#define LK_KP_6 0x9B
#define LK_KP_7 0x9D
#define LK_KP_8 0x9E
#define LK_KP_9 0x9F
#define LK_KP_PF1 0xA1
#define LK_KP_PF2 0xA2
#define LK_KP_PF3 0xA3
#define LK_KP_PF4 0xA4
#define LK_KP_HYPHEN 0xA0
#define LK_KP_COMMA 0x9C
#define LK_KP_PERIOD 0x94
#define LK_KP_ENTER 0x95
#define LK_DELETE 0xBC
#define LK_TAB 0xBE
#define LK_RETURN 0xBD
#define LK_META 0xB1
#define LK_LOCK 0xB0
#define LK_SHIFT 0xAE
#define LK_CTRL 0xAF
#define LK_LEFT 0xA7
#define LK_RIGHT 0xA8
#define LK_UP 0xAA
#define LK_DOWN 0xA9
#define LK_REMOVE 0x8C
#define LK_NEXT_SCREEN 0x8F
#define LK_PREV_SCREEN 0x8E
#define LK_INSERT_HERE 0x8B
#define LK_FIND 0x8A
#define LK_SELECT 0x8D
#define LK_F1 0x56
#define LK_F2 0x57
#define LK_F3 0x58
#define LK_F4 0x59
#define LK_F5 0x5A
#define LK_F6 0x64
#define LK_F7 0x65
#define LK_F8 0x66
#define LK_F9 0x67
#define LK_F10 0x68
#define LK_F11 0x71
#define LK_F12 0x72
/* special codes */
#define LK_ALLUP 0xB3 /* all up */
#define LK_METRONOME 0xB4 /* metronome code */
#define LK_OUTERR 0xB5 /* output error */
#define LK_INERR 0xB6 /* input error */
#define LK_LOCKACK 0xB7 /* kbd locked ack */
#define LK_TESTACK 0xB8 /* test mode ack */
#define LK_PREDOWN 0xB9 /* prefix to keys down */
#define LK_MODEACK 0xBA /* mode change ack */
/* interface functions */
t_stat lk_wr (uint8 c);
t_stat lk_rd (uint8 *c);
void lk_event (SIM_KEY_EVENT *ev);
#endif

View file

@ -29,6 +29,10 @@
06-Nov-2013 MB Increased the speed of v-sync interrupts, which 06-Nov-2013 MB Increased the speed of v-sync interrupts, which
was too slow for some O/S drivers. was too slow for some O/S drivers.
11-Jun-2013 MB First version 11-Jun-2013 MB First version
Related documents:
AZ-GLFAB-MN - VAXstation II Technical Manual, BA23 Enclosure (Appendix C)
*/ */
#if !defined(VAX_620) #if !defined(VAX_620)
@ -36,6 +40,8 @@
#include "vax_defs.h" #include "vax_defs.h"
#include "sim_video.h" #include "sim_video.h"
#include "vax_2681.h" #include "vax_2681.h"
#include "vax_lk.h"
#include "vax_vs.h"
/* CSR - control/status register */ /* CSR - control/status register */
@ -195,11 +201,6 @@ BITFIELD vc_ic_mode_bits[] = {
extern int32 tmxr_poll; /* calibrated delay */ extern int32 tmxr_poll; /* calibrated delay */
extern t_stat lk_wr (uint8 c);
extern t_stat lk_rd (uint8 *c);
extern t_stat vs_wr (uint8 c);
extern t_stat vs_rd (uint8 *c);
struct vc_int_t { struct vc_int_t {
uint32 ptr; uint32 ptr;
uint32 vec[8]; /* Interrupt vectors */ uint32 vec[8]; /* Interrupt vectors */
@ -875,6 +876,8 @@ return 0; /* no intr req */
t_stat vc_svc (UNIT *uptr) t_stat vc_svc (UNIT *uptr)
{ {
SIM_MOUSE_EVENT mev;
SIM_KEY_EVENT kev;
t_bool updated = FALSE; /* flag for refresh */ t_bool updated = FALSE; /* flag for refresh */
uint32 lines; uint32 lines;
uint32 ln, col, off; uint32 ln, col, off;
@ -914,31 +917,35 @@ vc_cur_v = CUR_V;
vc_cur_f = CUR_F; vc_cur_f = CUR_F;
vc_cur_new_data = FALSE; vc_cur_new_data = FALSE;
xpos = vc_mpos & 0xFF; /* get current mouse position */ if (vid_poll_kb (&kev) == SCPE_OK) /* poll keyboard */
ypos = (vc_mpos >> 8) & 0xFF; lk_event (&kev); /* push event */
dx = vid_mouse_xrel; /* get relative movement */ if (vid_poll_mouse (&mev) == SCPE_OK) { /* poll mouse */
dy = -vid_mouse_yrel; xpos = vc_mpos & 0xFF; /* get current mouse position */
if (dx > VC_MOVE_MAX) /* limit movement */ ypos = (vc_mpos >> 8) & 0xFF;
dx = VC_MOVE_MAX; dx = mev.x_rel; /* get relative movement */
else if (dx < -VC_MOVE_MAX) dy = -mev.y_rel;
dx = -VC_MOVE_MAX; if (dx > VC_MOVE_MAX) /* limit movement */
if (dy > VC_MOVE_MAX) dx = VC_MOVE_MAX;
dy = VC_MOVE_MAX; else if (dx < -VC_MOVE_MAX)
else if (dy < -VC_MOVE_MAX) dx = -VC_MOVE_MAX;
dy = -VC_MOVE_MAX; if (dy > VC_MOVE_MAX)
xpos += dx; /* add to counters */ dy = VC_MOVE_MAX;
ypos += dy; else if (dy < -VC_MOVE_MAX)
vc_mpos = ((ypos & 0xFF) << 8) | (xpos & 0xFF); /* update register */ dy = -VC_MOVE_MAX;
vid_mouse_xrel -= dx; /* reset counters for next poll */ xpos += dx; /* add to counters */
vid_mouse_yrel += dy; ypos += dy;
vc_mpos = ((ypos & 0xFF) << 8) | (xpos & 0xFF); /* update register */
vc_csr |= (CSR_MSA | CSR_MSB | CSR_MSC); /* reset button states */ vc_csr |= (CSR_MSA | CSR_MSB | CSR_MSC); /* reset button states */
if (vid_mouse_b3) /* set new button states */ if (mev.b3_state) /* set new button states */
vc_csr &= ~CSR_MSA; vc_csr &= ~CSR_MSA;
if (vid_mouse_b2) if (mev.b2_state)
vc_csr &= ~CSR_MSB; vc_csr &= ~CSR_MSB;
if (vid_mouse_b1) if (mev.b1_state)
vc_csr &= ~CSR_MSC; vc_csr &= ~CSR_MSC;
vs_event (&mev); /* push event */
}
lines = 0; lines = 0;
for (ln = 0; ln < VC_YSIZE; ln++) { for (ln = 0; ln < VC_YSIZE; ln++) {

View file

@ -1,6 +1,6 @@
/* vax_vs.c: DEC Mouse/Tablet (VSXXX) /* vax_vs.c: DEC Mouse/Tablet (VSXXX)
Copyright (c) 2011-2013, Matt Burke Copyright (c) 2013-2017, Matt Burke
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -27,58 +27,52 @@
09-Aug-2013 MB Added definitions for self test report 09-Aug-2013 MB Added definitions for self test report
11-Jun-2013 MB First version 11-Jun-2013 MB First version
Related documents:
EK-104AA-TM-001 - VCB02 Technical Manual (chapter C.6)
*/ */
#if !defined(VAX_620) #if !defined(VAX_620)
#include "vax_defs.h" #include "vax_vs.h"
#include "sim_video.h"
#define VSXXX_IDLE 0
#define VSXXX_RECV 1
#define VSXXX_SEND 2
#define VSXXX_TEST 3
#define VSXXX_PROMPT 0 #define VSXXX_PROMPT 0
#define VSXXX_INC 1 #define VSXXX_INC 1
#define VSXXX_REV 0 /* hardware revision */ #define VSXXX_REV 0 /* hardware revision */
/* Report bit definitions */
#define RPT_SYNC 0x80 /* synchronise */
#define RPT_TABP 0x40 /* tablet position */
#define RPT_TEST 0x20 /* self test */
#define RPT_TAB 0x4 /* tablet device */
#define RPT_MOU 0x2 /* mouse device */
#define RPT_V_MFR 4 /* manufacturer location ID */
#define RPT_REV 0xF /* revision number */
#define RPT_BC 0x7 /* button code */
#define RPT_EC 0x7F /* error code */
/* Debugging Bitmaps */ /* Debugging Bitmaps */
#define DBG_SERIAL 0x0001 /* serial port data */ #define DBG_SERIAL 0x0001 /* serial port data */
#define DBG_CMD 0x0002 /* commands */ #define DBG_CMD 0x0002 /* commands */
int32 vs_state = VSXXX_IDLE; #define VS_BUF_LEN 100
typedef struct {
int32 head;
int32 tail;
int32 count;
uint8 buf[VS_BUF_LEN];
} VS_FIFO;
int32 vs_mode = VSXXX_PROMPT; int32 vs_mode = VSXXX_PROMPT;
int32 vs_bptr = 0;
int32 vs_datalen = 0;
int32 vs_x = 0; /* X-axis motion */ int32 vs_x = 0; /* X-axis motion */
int32 vs_y = 0; /* Y-axis motion */ int32 vs_y = 0; /* Y-axis motion */
t_bool vs_l = 0; /* Left button state */ t_bool vs_l = FALSE; /* Left button state */
t_bool vs_m = 0; /* Middle button state */ t_bool vs_m = FALSE; /* Middle button state */
t_bool vs_r = 0; /* Right button state */ t_bool vs_r = FALSE; /* Right button state */
uint8 vs_buf[10]; VS_FIFO vs_sndf; /* send FIFO */
t_stat vs_wr (uint8 c); t_stat vs_wr (uint8 c);
t_stat vs_rd (uint8 *c); t_stat vs_rd (uint8 *c);
t_stat vs_reset (DEVICE *dptr); t_stat vs_reset (DEVICE *dptr);
void vs_cmd (int32 c); void vs_cmd (int32 c);
void vs_sendupd (void); void vs_sendupd (void);
void vs_poll (void);
const char *vs_description (DEVICE *dptr); const char *vs_description (DEVICE *dptr);
t_stat vs_put_fifo (VS_FIFO *fifo, uint8 data);
t_stat vs_get_fifo (VS_FIFO *fifo, uint8 *data);
void vs_clear_fifo (VS_FIFO *fifo);
/* VS data structures /* VS data structures
@ -119,126 +113,148 @@ DEVICE vs_dev = {
t_stat vs_wr (uint8 c) t_stat vs_wr (uint8 c)
{ {
if (vs_state != VSXXX_TEST) { vs_clear_fifo (&vs_sndf);
vs_bptr = 0; vs_cmd (c);
vs_state = VSXXX_IDLE;
vs_datalen = 0;
vs_cmd (c);
}
return SCPE_OK; return SCPE_OK;
} }
t_stat vs_rd (uint8 *c) t_stat vs_rd (uint8 *c)
{ {
if (vs_state == VSXXX_IDLE) t_stat r;
vs_poll ();
switch (vs_state) {
case VSXXX_IDLE: r = vs_get_fifo (&vs_sndf, c);
*c = 0; if (r == SCPE_OK)
return SCPE_EOF; sim_debug (DBG_SERIAL, &vs_dev, "mouse -> vax: 0x%02X\n", *c);
return r;
}
case VSXXX_SEND: t_stat vs_put_fifo (VS_FIFO *fifo, uint8 data)
case VSXXX_TEST: {
*c = vs_buf[vs_bptr++]; if (fifo->count < VS_BUF_LEN) {
sim_debug (DBG_SERIAL, &vs_dev, "mouse -> vax: 0x%02X\n", *c); fifo->buf[fifo->head++] = data;
if (vs_bptr == vs_datalen) { if (fifo->head == VS_BUF_LEN)
vs_state = VSXXX_IDLE; fifo->head = 0;
} fifo->count++;
return SCPE_OK; return SCPE_OK;
} }
return SCPE_EOF; else
return SCPE_EOF;
}
t_stat vs_get_fifo (VS_FIFO *fifo, uint8 *data)
{
if (fifo->count > 0) {
*data = fifo->buf[fifo->tail++];
if (fifo->tail == VS_BUF_LEN)
fifo->tail = 0;
fifo->count--;
return SCPE_OK;
}
else
return SCPE_EOF;
}
void vs_clear_fifo (VS_FIFO *fifo)
{
fifo->head = 0;
fifo->tail = 0;
fifo->count = 0;
} }
void vs_cmd (int32 c) void vs_cmd (int32 c)
{ {
uint8 data;
sim_debug (DBG_SERIAL, &vs_dev, "vax -> mouse: %c\n", c); sim_debug (DBG_SERIAL, &vs_dev, "vax -> mouse: %c\n", c);
switch (c) { switch (c) {
case 0x52: /* R */ case VS_INCR: /* R */
sim_debug (DBG_CMD, &vs_dev, "set mode incremental(%c)\n", c); sim_debug (DBG_CMD, &vs_dev, "set mode incremental(%c)\n", c);
vs_mode = VSXXX_INC; vs_mode = VSXXX_INC;
break; break;
case 0x44: /* D */ case VS_PROMPT: /* D */
sim_debug (DBG_CMD, &vs_dev, "set mode prompt(%c)\n", c); sim_debug (DBG_CMD, &vs_dev, "set mode prompt(%c)\n", c);
vs_mode = VSXXX_PROMPT; vs_mode = VSXXX_PROMPT;
break; break;
case 0x50: /* P */ case VS_POLL: /* P */
sim_debug (DBG_CMD, &vs_dev, "poll(%c)\n", c); sim_debug (DBG_CMD, &vs_dev, "poll(%c)\n", c);
vs_mode = VSXXX_PROMPT; vs_mode = VSXXX_PROMPT;
vs_sendupd (); vs_sendupd ();
break; break;
case 0x54: /* T */ case VS_TEST: /* T */
sim_debug (DBG_CMD, &vs_dev, "test(%c)\n", c); sim_debug (DBG_CMD, &vs_dev, "test(%c)\n", c);
vs_reset (&vs_dev); vs_reset (&vs_dev);
vs_state = VSXXX_TEST; /* send self test report */ data = RPT_TEST | RPT_SYNC | (VSXXX_REV & RPT_REV);
vs_buf[0] = RPT_TEST | RPT_SYNC | (VSXXX_REV & RPT_REV); vs_put_fifo (&vs_sndf, data);
vs_buf[1] = (1 << RPT_V_MFR) | RPT_MOU; /* device type, build location */ data = (1 << RPT_V_MFR) | RPT_MOU; /* device type, build location */
vs_buf[2] = 0; /* error code <6:0> (0 = OK) */ vs_put_fifo (&vs_sndf, data);
vs_buf[3] = 0; /* button code <2:0> (0 = OK) */ data = 0; /* error code <6:0> (0 = OK) */
vs_bptr = 0; vs_put_fifo (&vs_sndf, data);
vs_state = VSXXX_SEND; data = 0; /* button code <2:0> (0 = OK) */
vs_datalen = 4; vs_put_fifo (&vs_sndf, data);
break; break;
} }
} }
t_stat vs_reset (DEVICE *dptr) t_stat vs_reset (DEVICE *dptr)
{ {
vs_bptr = 0; vs_x = 0;
vs_state = VSXXX_IDLE; vs_y = 0;
vs_datalen = 0; vs_l = FALSE;
vs_m = FALSE;
vs_r = FALSE;
vs_clear_fifo (&vs_sndf);
vs_mode = VSXXX_PROMPT; vs_mode = VSXXX_PROMPT;
return SCPE_OK; return SCPE_OK;
} }
void vs_sendupd (void) void vs_sendupd (void)
{ {
vs_buf[0] = RPT_SYNC; uint8 b0, b1, b2;
vs_buf[0] |= (((vs_x > 0) ? 1 : 0) << 4); /* sign bits */
vs_buf[0] |= (((vs_y >= 0) ? 0 : 1) << 3); do {
vs_buf[0] |= (((vs_l) ? 1 : 0) << 2); /* button states */ if (vs_sndf.count == VS_BUF_LEN) /* fifo full? */
vs_buf[0] |= (((vs_m) ? 1 : 0) << 1); return;
vs_buf[0] |= ((vs_r) ? 1 : 0); b0 = RPT_SYNC;
vs_buf[1] = (abs(vs_x) > 0x3F) ? 0x3F : abs(vs_x); /* motion (limited to 63 pixels in any direction) */ b0 |= (((vs_x > 0) ? 1 : 0) << 4); /* sign bits */
if (vs_x > 0) b0 |= (((vs_y >= 0) ? 0 : 1) << 3);
vs_x -= vs_buf[1]; b0 |= (((vs_l) ? 1 : 0) << 2); /* button states */
else b0 |= (((vs_m) ? 1 : 0) << 1);
vs_x += vs_buf[1]; b0 |= ((vs_r) ? 1 : 0);
vs_buf[2] = (abs(vs_y) > 0x3F) ? 0x3F : abs(vs_y); vs_put_fifo (&vs_sndf, b0);
if (vs_y > 0) b1 = (abs(vs_x) > 0x3F) ? 0x3F : abs(vs_x); /* motion (limited to 63 pixels in any direction) */
vs_y -= vs_buf[2]; if (vs_x > 0)
else vs_x -= b1;
vs_y += vs_buf[2]; else
vs_bptr = 0; vs_x += b1;
vs_state = VSXXX_SEND; vs_put_fifo (&vs_sndf, b1);
vs_datalen = 3; b2 = (abs(vs_y) > 0x3F) ? 0x3F : abs(vs_y);
sim_debug (DBG_SERIAL, &vs_dev, "mouse motion queued for delivery: Motion:(%s%d,%s%d), Buttons:(%s,%s,%s) Remnant skipped:(%d,%d)\n", if (vs_y > 0)
(vs_buf[0]&0x10) ? "s" : "", vs_buf[1], (vs_buf[0]&0x08) ? "s" : "", vs_buf[2], (vs_buf[0]&0x04) ? "L" : "l", (vs_buf[0]&0x02) ? "M" : "m", (vs_buf[0]&0x01) ? "R" : "r", vs_x, vs_y); vs_y -= b2;
else
vs_y += b2;
vs_put_fifo (&vs_sndf, b2);
sim_debug (DBG_SERIAL, &vs_dev, "mouse motion queued for delivery: Motion:(%s%d,%s%d), Buttons:(%s,%s,%s) Remnant skipped:(%d,%d)\n",
(b0 & 0x10) ? "s" : "", b1, (b0 & 0x08) ? "s" : "", b2, (b0 & 0x04) ? "L" : "l", (b0 & 0x02) ? "M" : "m", (b0 & 0x01) ? "R" : "r", vs_x, vs_y);
} while ((vs_x != 0) && (vs_y != 0));
vs_x = vs_y = 0; vs_x = vs_y = 0;
} }
void vs_poll (void) void vs_event (SIM_MOUSE_EVENT *ev)
{ {
SIM_MOUSE_EVENT ev; if ((ev->x_rel == 0) && (ev->y_rel == 0) &&
(vs_l == ev->b1_state) && (vs_m == ev->b2_state) && (vs_r == ev->b3_state))
if (vid_poll_mouse (&ev) != SCPE_OK)
return; return;
if (vs_state == VSXXX_IDLE) { vs_x += ev->x_rel;
if ((ev.x_rel == 0) && (ev.y_rel == 0) && vs_y += ev->y_rel;
(vs_l == ev.b1_state) && (vs_m == ev.b2_state) && (vs_r == ev.b3_state)) vs_l = ev->b1_state;
return; vs_m = ev->b2_state;
vs_x = ev.x_rel; vs_r = ev->b3_state;
vs_y = ev.y_rel; if (vs_mode == VSXXX_INC)
vs_l = ev.b1_state; vs_sendupd ();
vs_m = ev.b2_state;
vs_r = ev.b3_state;
if (vs_mode == VSXXX_INC)
vs_sendupd ();
}
} }
const char *vs_description (DEVICE *dptr) const char *vs_description (DEVICE *dptr)

58
VAX/vax_vs.h Normal file
View file

@ -0,0 +1,58 @@
/* vax_vs.h: DEC Mouse/Tablet (VSXXX)
Copyright (c) 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.
vs VSXXX-nn pointing device
*/
#ifndef _VAX_VS_H_
#define _VAX_VS_H_
#include "vax_defs.h"
#include "sim_video.h"
/* command definitions */
#define VS_INCR 0x52 /* set mode incremental */
#define VS_PROMPT 0x44 /* set mode prompt */
#define VS_POLL 0x50 /* poll */
#define VS_TEST 0x54 /* test */
/* Report bit definitions */
#define RPT_SYNC 0x80 /* synchronise */
#define RPT_TABP 0x40 /* tablet position */
#define RPT_TEST 0x20 /* self test */
#define RPT_TAB 0x4 /* tablet device */
#define RPT_MOU 0x2 /* mouse device */
#define RPT_V_MFR 4 /* manufacturer location ID */
#define RPT_REV 0xF /* revision number */
#define RPT_BC 0x7 /* button code */
#define RPT_EC 0x7F /* error code */
t_stat vs_wr (uint8 c);
t_stat vs_rd (uint8 *c);
void vs_event (SIM_MOUSE_EVENT *ev);
#endif

View file

@ -640,10 +640,18 @@
RelativePath="..\VAX\vax_defs.h" RelativePath="..\VAX\vax_defs.h"
> >
</File> </File>
<File
RelativePath="..\VAX\vax_lk.h"
>
</File>
<File <File
RelativePath="..\VAX\vax_mmu.h" RelativePath="..\VAX\vax_mmu.h"
> >
</File> </File>
<File
RelativePath="..\VAX\vax_vs.h"
>
</File>
</Filter> </Filter>
<Filter <Filter
Name="Resource Files" Name="Resource Files"

View file

@ -640,10 +640,18 @@
RelativePath="..\VAX\vax_defs.h" RelativePath="..\VAX\vax_defs.h"
> >
</File> </File>
<File
RelativePath="..\VAX\vax_lk.h"
>
</File>
<File <File
RelativePath="..\VAX\vax_mmu.h" RelativePath="..\VAX\vax_mmu.h"
> >
</File> </File>
<File
RelativePath="..\VAX\vax_vs.h"
>
</File>
</Filter> </Filter>
<Filter <Filter
Name="Resource Files" Name="Resource Files"

View file

@ -636,10 +636,18 @@
RelativePath="..\VAX\vax_defs.h" RelativePath="..\VAX\vax_defs.h"
> >
</File> </File>
<File
RelativePath="..\VAX\vax_lk.h"
>
</File>
<File <File
RelativePath="..\VAX\vax_mmu.h" RelativePath="..\VAX\vax_mmu.h"
> >
</File> </File>
<File
RelativePath="..\VAX\vax_vs.h"
>
</File>
<File <File
RelativePath="..\VAX\vaxmod_defs.h" RelativePath="..\VAX\vaxmod_defs.h"
> >

View file

@ -31,8 +31,6 @@
#include "scp.h" #include "scp.h"
t_bool vid_active = FALSE; t_bool vid_active = FALSE;
int32 vid_mouse_xrel;
int32 vid_mouse_yrel;
int32 vid_cursor_x; int32 vid_cursor_x;
int32 vid_cursor_y; int32 vid_cursor_y;
t_bool vid_mouse_b1 = FALSE; t_bool vid_mouse_b1 = FALSE;
@ -523,8 +521,6 @@ if (!vid_active) {
vid_height = height; vid_height = height;
vid_mouse_captured = FALSE; vid_mouse_captured = FALSE;
vid_cursor_visible = (vid_flags & SIM_VID_INPUTCAPTURED); vid_cursor_visible = (vid_flags & SIM_VID_INPUTCAPTURED);
vid_mouse_xrel = 0;
vid_mouse_yrel = 0;
vid_key_events.head = 0; vid_key_events.head = 0;
vid_key_events.tail = 0; vid_key_events.tail = 0;
@ -717,6 +713,9 @@ void vid_set_cursor_position (int32 x, int32 y)
int32 x_delta = vid_cursor_x - x; int32 x_delta = vid_cursor_x - x;
int32 y_delta = vid_cursor_y - y; int32 y_delta = vid_cursor_y - y;
if (vid_flags & SIM_VID_INPUTCAPTURED)
return;
if ((x_delta) || (y_delta)) { if ((x_delta) || (y_delta)) {
sim_debug (SIM_VID_DBG_CURSOR, vid_dev, "vid_set_cursor_position(%d, %d) - Cursor position changed\n", x, y); sim_debug (SIM_VID_DBG_CURSOR, vid_dev, "vid_set_cursor_position(%d, %d) - Cursor position changed\n", x, y);
/* Any queued mouse motion events need to have their relative /* Any queued mouse motion events need to have their relative
@ -728,12 +727,8 @@ if ((x_delta) || (y_delta)) {
for (i=0; i<vid_mouse_events.count; i++) { for (i=0; i<vid_mouse_events.count; i++) {
ev = &vid_mouse_events.events[(vid_mouse_events.head + i)%MAX_EVENTS]; ev = &vid_mouse_events.events[(vid_mouse_events.head + i)%MAX_EVENTS];
sim_debug (SIM_VID_DBG_CURSOR, vid_dev, "Pending Mouse Motion Event Adjusted from: (%d, %d) to (%d, %d)\n", ev->x_rel, ev->y_rel, ev->x_rel + x_delta, ev->y_rel + y_delta); sim_debug (SIM_VID_DBG_CURSOR, vid_dev, "Pending Mouse Motion Event Adjusted from: (%d, %d) to (%d, %d)\n", ev->x_rel, ev->y_rel, ev->x_rel + x_delta, ev->y_rel + y_delta);
vid_mouse_xrel -= ev->x_rel; /* remove previously accumulated relative position */
vid_mouse_yrel -= ev->y_rel;
ev->x_rel += x_delta; ev->x_rel += x_delta;
ev->y_rel += y_delta; ev->y_rel += y_delta;
vid_mouse_xrel += ev->x_rel; /* update cumulative x & y rel */
vid_mouse_yrel += ev->y_rel;
} }
if (SDL_SemPost (vid_mouse_events.sem)) if (SDL_SemPost (vid_mouse_events.sem))
sim_printf ("%s: vid_set_cursor_position(): SDL_SemPost error: %s\n", vid_dev ? sim_dname(vid_dev) : "Video Device", SDL_GetError()); sim_printf ("%s: vid_set_cursor_position(): SDL_SemPost error: %s\n", vid_dev ? sim_dname(vid_dev) : "Video Device", SDL_GetError());
@ -1250,13 +1245,11 @@ if (SDL_SemWait (vid_mouse_events.sem) == 0) {
event->xrel = (event->x - vid_cursor_x); event->xrel = (event->x - vid_cursor_x);
event->yrel = (event->y - vid_cursor_y); event->yrel = (event->y - vid_cursor_y);
} }
vid_mouse_xrel += event->xrel; /* update cumulative x rel */
vid_mouse_yrel += event->yrel; /* update cumulative y rel */
vid_mouse_b1 = (event->state & SDL_BUTTON(SDL_BUTTON_LEFT)) ? TRUE : FALSE; vid_mouse_b1 = (event->state & SDL_BUTTON(SDL_BUTTON_LEFT)) ? TRUE : FALSE;
vid_mouse_b2 = (event->state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) ? TRUE : FALSE; vid_mouse_b2 = (event->state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) ? TRUE : FALSE;
vid_mouse_b3 = (event->state & SDL_BUTTON(SDL_BUTTON_RIGHT)) ? TRUE : FALSE; vid_mouse_b3 = (event->state & SDL_BUTTON(SDL_BUTTON_RIGHT)) ? TRUE : FALSE;
sim_debug (SIM_VID_DBG_MOUSE, vid_dev, "Mouse Move Event: pos:(%d,%d) rel:(%d,%d) buttons:(%d,%d,%d) - Count: %d vid_mouse_rel:(%d,%d), vid_cursor:(%d,%d)\n", sim_debug (SIM_VID_DBG_MOUSE, vid_dev, "Mouse Move Event: pos:(%d,%d) rel:(%d,%d) buttons:(%d,%d,%d) - Count: %d vid_cursor:(%d,%d)\n",
event->x, event->y, event->xrel, event->yrel, (event->state & SDL_BUTTON(SDL_BUTTON_LEFT)) ? 1 : 0, (event->state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) ? 1 : 0, (event->state & SDL_BUTTON(SDL_BUTTON_RIGHT)) ? 1 : 0, vid_mouse_events.count, vid_mouse_xrel, vid_mouse_yrel, vid_cursor_x, vid_cursor_y); event->x, event->y, event->xrel, event->yrel, (event->state & SDL_BUTTON(SDL_BUTTON_LEFT)) ? 1 : 0, (event->state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) ? 1 : 0, (event->state & SDL_BUTTON(SDL_BUTTON_RIGHT)) ? 1 : 0, vid_mouse_events.count, vid_cursor_x, vid_cursor_y);
if (vid_mouse_events.count < MAX_EVENTS) { if (vid_mouse_events.count < MAX_EVENTS) {
SIM_MOUSE_EVENT *tail = &vid_mouse_events.events[(vid_mouse_events.tail+MAX_EVENTS-1)%MAX_EVENTS]; SIM_MOUSE_EVENT *tail = &vid_mouse_events.events[(vid_mouse_events.tail+MAX_EVENTS-1)%MAX_EVENTS];
@ -1275,8 +1268,8 @@ if (SDL_SemWait (vid_mouse_events.sem) == 0) {
tail->y_rel += ev.y_rel; tail->y_rel += ev.y_rel;
tail->x_pos = ev.x_pos; tail->x_pos = ev.x_pos;
tail->y_pos = ev.y_pos; tail->y_pos = ev.y_pos;
sim_debug (SIM_VID_DBG_MOUSE, vid_dev, "Mouse Move Event: Coalesced into pending event: (%d,%d) vid_mouse_rel:(%d,%d)\n", sim_debug (SIM_VID_DBG_MOUSE, vid_dev, "Mouse Move Event: Coalesced into pending event: (%d,%d)\n",
tail->x_rel, tail->y_rel, vid_mouse_xrel, vid_mouse_yrel); tail->x_rel, tail->y_rel);
} }
else { /* Add a new event */ else { /* Add a new event */
vid_mouse_events.events[vid_mouse_events.tail++] = ev; vid_mouse_events.events[vid_mouse_events.tail++] = ev;
@ -1705,6 +1698,9 @@ while (vid_active) {
if (vid_flags & SIM_VID_INPUTCAPTURED) if (vid_flags & SIM_VID_INPUTCAPTURED)
SDL_WarpMouseInWindow (NULL, vid_width/2, vid_height/2); /* center position */ SDL_WarpMouseInWindow (NULL, vid_width/2, vid_height/2); /* center position */
break; break;
case SDL_WINDOWEVENT_EXPOSED:
vid_update ();
break;
} }
} }
break; break;

View file

@ -197,11 +197,6 @@ t_stat vid_screenshot (const char *filename);
extern t_bool vid_active; extern t_bool vid_active;
extern uint32 vid_mono_palette[2]; extern uint32 vid_mono_palette[2];
extern int32 vid_mouse_xrel; /* mouse cumulative x rel */
extern int32 vid_mouse_yrel; /* mouse cumulative y rel */
extern t_bool vid_mouse_b1; /* mouse button 1 state */
extern t_bool vid_mouse_b2; /* mouse button 2 state */
extern t_bool vid_mouse_b3; /* mouse button 3 state */
void vid_set_cursor_position (int32 x, int32 y); /* cursor position (set by calling code) */ void vid_set_cursor_position (int32 x, int32 y); /* cursor position (set by calling code) */
#define SIM_VID_DBG_MOUSE 0x01000000 #define SIM_VID_DBG_MOUSE 0x01000000