From c94edb6b2d21337def59b7e75c092f62381e5278 Mon Sep 17 00:00:00 2001 From: Matt Burke Date: Sun, 23 Apr 2017 10:40:00 -0700 Subject: [PATCH] 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. --- VAX/vax_lk.c | 361 +++++++++++++----------- VAX/vax_lk.h | 152 ++++++++++ VAX/vax_vc.c | 65 +++-- VAX/vax_vs.c | 220 ++++++++------- VAX/vax_vs.h | 58 ++++ Visual Studio Projects/MicroVAX1.vcproj | 8 + Visual Studio Projects/MicroVAX2.vcproj | 8 + Visual Studio Projects/VAX.vcproj | 8 + sim_video.c | 24 +- sim_video.h | 5 - 10 files changed, 594 insertions(+), 315 deletions(-) create mode 100644 VAX/vax_lk.h create mode 100644 VAX/vax_vs.h diff --git a/VAX/vax_lk.c b/VAX/vax_lk.c index 5757f80d..d824bac2 100644 --- a/VAX/vax_lk.c +++ b/VAX/vax_lk.c @@ -1,6 +1,6 @@ /* 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 copy of this software and associated documentation files (the "Software"), @@ -26,12 +26,15 @@ 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_defs.h" -#include "sim_video.h" +#include "vax_lk.h" /* States */ @@ -46,10 +49,21 @@ #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 { @@ -57,107 +71,102 @@ typedef struct { uint8 code; } LK_KEYDATA; -LK_KEYDATA LK_KEY_UNKNOWN = { 0, 0 }; -LK_KEYDATA LK_KEY_TR_0 = { 1, 0xEF }; -LK_KEYDATA LK_KEY_TR_1 = { 1, 0xC0 }; -LK_KEYDATA LK_KEY_TR_2 = { 1, 0xC5 }; -LK_KEYDATA LK_KEY_TR_3 = { 1, 0xCB }; -LK_KEYDATA LK_KEY_TR_4 = { 1, 0xD0 }; -LK_KEYDATA LK_KEY_TR_5 = { 1, 0xD6 }; -LK_KEYDATA LK_KEY_TR_6 = { 1, 0xDB }; -LK_KEYDATA LK_KEY_TR_7 = { 1, 0xE0 }; -LK_KEYDATA LK_KEY_TR_8 = { 1, 0xE5 }; -LK_KEYDATA LK_KEY_TR_9 = { 1, 0xEA }; -LK_KEYDATA LK_KEY_A = { 1, 0xC2 }; -LK_KEYDATA LK_KEY_B = { 1, 0xD9 }; -LK_KEYDATA LK_KEY_C = { 1, 0xCE }; -LK_KEYDATA LK_KEY_D = { 1, 0xCD }; -LK_KEYDATA LK_KEY_E = { 1, 0xCC }; -LK_KEYDATA LK_KEY_F = { 1, 0xD2 }; -LK_KEYDATA LK_KEY_G = { 1, 0xD8 }; -LK_KEYDATA LK_KEY_H = { 1, 0xDD }; -LK_KEYDATA LK_KEY_I = { 1, 0xE6 }; -LK_KEYDATA LK_KEY_J = { 1, 0xE2 }; -LK_KEYDATA LK_KEY_K = { 1, 0xE7 }; -LK_KEYDATA LK_KEY_L = { 1, 0xEC }; -LK_KEYDATA LK_KEY_M = { 1, 0xE3 }; -LK_KEYDATA LK_KEY_N = { 1, 0xDE }; -LK_KEYDATA LK_KEY_O = { 1, 0xEB }; -LK_KEYDATA LK_KEY_P = { 1, 0xF0 }; -LK_KEYDATA LK_KEY_Q = { 1, 0xC1 }; -LK_KEYDATA LK_KEY_R = { 1, 0xD1 }; -LK_KEYDATA LK_KEY_S = { 1, 0xC7 }; -LK_KEYDATA LK_KEY_T = { 1, 0xD7 }; -LK_KEYDATA LK_KEY_U = { 1, 0xE1 }; -LK_KEYDATA LK_KEY_V = { 1, 0xD3 }; -LK_KEYDATA LK_KEY_W = { 1, 0xC6 }; -LK_KEYDATA LK_KEY_X = { 1, 0xC8 }; -LK_KEYDATA LK_KEY_Y = { 1, 0xDC }; -LK_KEYDATA LK_KEY_Z = { 1, 0xC3 }; -LK_KEYDATA LK_KEY_SPACE = { 1, 0xD4 }; -LK_KEYDATA LK_KEY_SEMICOLON = { 1, 0xF2 }; -LK_KEYDATA LK_KEY_PLUS = { 1, 0xF5 }; -LK_KEYDATA LK_KEY_COMMA = { 1, 0xE8 }; -LK_KEYDATA LK_KEY_UBAR = { 1, 0xF9 }; -LK_KEYDATA LK_KEY_PERIOD = { 1, 0xED }; -LK_KEYDATA LK_KEY_QMARK = { 1, 0xF3 }; -LK_KEYDATA LK_KEY_QUOTE = { 1, 0xFB }; -LK_KEYDATA LK_KEY_LBRACE = { 1, 0xFA }; -LK_KEYDATA LK_KEY_RBRACE = { 1, 0xF6 }; -LK_KEYDATA LK_KEY_VBAR = { 1, 0xF7 }; -LK_KEYDATA LK_KEY_TILDE = { 1, 0xBF }; -LK_KEYDATA LK_KEY_KP_0 = { 2, 0x92 }; -LK_KEYDATA LK_KEY_KP_1 = { 2, 0x96 }; -LK_KEYDATA LK_KEY_KP_2 = { 2, 0x97 }; -LK_KEYDATA LK_KEY_KP_3 = { 2, 0x98 }; -LK_KEYDATA LK_KEY_KP_4 = { 2, 0x99 }; -LK_KEYDATA LK_KEY_KP_5 = { 2, 0x9A }; -LK_KEYDATA LK_KEY_KP_6 = { 2, 0x9B }; -LK_KEYDATA LK_KEY_KP_7 = { 2, 0x9D }; -LK_KEYDATA LK_KEY_KP_8 = { 2, 0x9E }; -LK_KEYDATA LK_KEY_KP_9 = { 2, 0x9F }; -LK_KEYDATA LK_KEY_KP_PF1 = { 2, 0xA1 }; -LK_KEYDATA LK_KEY_KP_PF2 = { 2, 0xA2 }; -LK_KEYDATA LK_KEY_KP_PF3 = { 2, 0xA3 }; -LK_KEYDATA LK_KEY_KP_PF4 = { 2, 0xA4 }; -LK_KEYDATA LK_KEY_KP_HYPHEN = { 2, 0xA0 }; -LK_KEYDATA LK_KEY_KP_COMMA = { 2, 0x9C }; -LK_KEYDATA LK_KEY_KP_PERIOD = { 2, 0x94 }; -LK_KEYDATA LK_KEY_KP_ENTER = { 2, 0x95 }; -LK_KEYDATA LK_KEY_DELETE = { 3, 0xBC }; -LK_KEYDATA LK_KEY_TAB = { 3, 0xBE }; -LK_KEYDATA LK_KEY_RETURN = { 4, 0xBD }; -LK_KEYDATA LK_KEY_META = { 5, 0xB1 }; -LK_KEYDATA LK_KEY_LOCK = { 5, 0xB0 }; -LK_KEYDATA LK_KEY_SHIFT = { 6, 0xAE }; -LK_KEYDATA LK_KEY_CTRL = { 6, 0xAF }; -LK_KEYDATA LK_KEY_LEFT = { 7, 0xA7 }; -LK_KEYDATA LK_KEY_RIGHT = { 7, 0xA8 }; -LK_KEYDATA LK_KEY_UP = { 8, 0xAA }; -LK_KEYDATA LK_KEY_DOWN = { 8, 0xA9 }; -LK_KEYDATA LK_KEY_REMOVE = { 9, 0x8C }; -LK_KEYDATA LK_KEY_NEXT_SCREEN= { 9, 0x8F }; -LK_KEYDATA LK_KEY_PREV_SCREEN= { 9, 0x8E }; -LK_KEYDATA LK_KEY_INSERT_HERE= { 9, 0x8B }; -LK_KEYDATA LK_KEY_FIND = { 9, 0x8A }; -LK_KEYDATA LK_KEY_SELECT = { 9, 0x8D }; -LK_KEYDATA LK_KEY_F1 = { 10, 0x56 }; -LK_KEYDATA LK_KEY_F2 = { 10, 0x57 }; -LK_KEYDATA LK_KEY_F3 = { 10, 0x58 }; -LK_KEYDATA LK_KEY_F4 = { 10, 0x59 }; -LK_KEYDATA LK_KEY_F5 = { 10, 0x5A }; -LK_KEYDATA LK_KEY_F6 = { 11, 0x64 }; -LK_KEYDATA LK_KEY_F7 = { 11, 0x65 }; -LK_KEYDATA LK_KEY_F8 = { 11, 0x66 }; -LK_KEYDATA LK_KEY_F9 = { 11, 0x67 }; -LK_KEYDATA LK_KEY_F10 = { 11, 0x68 }; -LK_KEYDATA LK_KEY_F11 = { 12, 0x71 }; -LK_KEYDATA LK_KEY_F12 = { 12, 0x72 }; - -#define LK_BUF_LEN 100 - -#define LK_SEND_CHAR(c) lk_sbuf[lk_stptr++] = c; \ - if (lk_stptr == LK_BUF_LEN) lk_stptr = 0 +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 */ @@ -167,11 +176,8 @@ LK_KEYDATA LK_KEY_F12 = { 12, 0x72 }; t_bool lk_repeat = TRUE; /* autorepeat flag */ t_bool lk_trpti = FALSE; /* temp repeat inhibit */ int32 lk_keysdown = 0; /* no of keys held down */ -uint8 lk_sbuf[LK_BUF_LEN]; /* send buffer */ -int32 lk_shptr = 0; /* send buf head ptr */ -int32 lk_stptr = 0; /* send buf tail ptr */ -uint8 lk_rbuf[10]; /* receive buffer */ -int32 lk_rbuf_p = 0; /* receive buffer ptr */ +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); @@ -179,8 +185,10 @@ t_stat lk_rd (uint8 *c); t_stat lk_reset (DEVICE *dptr); void lk_reset_mode (void); void lk_cmd (void); -void lk_poll (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 @@ -213,7 +221,7 @@ DEVICE lk_dev = { NULL, NULL, &lk_reset, NULL, NULL, NULL, NULL, DEV_DIS | DEV_DEBUG, 0, - lk_debug, NULL, NULL, NULL, NULL, NULL, + lk_debug, NULL, NULL, NULL, NULL, NULL, &lk_description }; @@ -224,10 +232,9 @@ t_stat lk_wr (uint8 c) sim_debug (DBG_SERIAL, &lk_dev, "vax -> lk: %02X\n", c); if (c == 0) return SCPE_OK; -lk_rbuf[lk_rbuf_p++] = c; -if (lk_rbuf_p == sizeof(lk_rbuf)) { /* too long? */ - lk_rbuf_p = 0; - LK_SEND_CHAR(0xB6); /* input error */ +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? */ @@ -239,28 +246,57 @@ return SCPE_OK; t_stat lk_rd (uint8 *c) { -if (lk_shptr == lk_stptr) - lk_poll (); -if (lk_shptr == lk_stptr) { - *c = 0; - return SCPE_EOF; - } -else { - *c = lk_sbuf[lk_shptr++]; - if (lk_shptr == LK_BUF_LEN) - lk_shptr = 0; /* ring buffer wrap */ +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_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; } +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; -if (lk_rbuf[0] & 1) { /* peripheral command */ - switch (lk_rbuf[0]) { +lk_get_fifo (&lk_rcvf, &data); + +if (data & 1) { /* peripheral command */ + switch (data) { case 0x11: sim_debug (DBG_CMD, &lk_dev, "LED on\n"); @@ -276,7 +312,7 @@ if (lk_rbuf[0] & 1) { /* peripheral command */ case 0x8B: sim_debug (DBG_CMD, &lk_dev, "resume keyboard transmission\n"); - lk_shptr = lk_stptr = 0; + lk_clear_fifo (&lk_sndf); break; case 0x99: @@ -358,26 +394,26 @@ if (lk_rbuf[0] & 1) { /* peripheral command */ lk_reset_mode (); lk_repeat = TRUE; lk_trpti = FALSE; - LK_SEND_CHAR (0xBA); /* Mode change ACK */ + LK_SEND_CHAR (LK_MODEACK); /* Mode change ACK */ break; default: - sim_printf ("lk: unknown cmd %02X\n", lk_rbuf[0]); + sim_printf ("lk: unknown cmd %02X\n", data); 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) @@ -609,7 +645,7 @@ switch (key) { case SIM_KEY_BACKSLASH: lk_key = LK_KEY_VBAR; break; - + case SIM_KEY_LEFT_BACKSLASH: case SIM_KEY_COMMA: lk_key = LK_KEY_COMMA; @@ -626,7 +662,7 @@ switch (key) { /* case SIM_KEY_PRINT: */ /* case SIM_KEY_PAUSE: */ /* case SIM_KEY_ESC: */ - + case SIM_KEY_BACKSPACE: lk_key = LK_KEY_DELETE; break; @@ -762,66 +798,61 @@ lk_mode[14] = LK_MODE_AUTODOWN; /* 14 = function keys: f t_stat lk_reset (DEVICE *dptr) { -lk_rbuf_p = 0; +lk_clear_fifo (&lk_sndf); +lk_clear_fifo (&lk_rcvf); lk_keysdown = 0; lk_repeat = TRUE; lk_trpti = FALSE; -lk_shptr = 0; -lk_stptr = 0; lk_reset_mode (); return SCPE_OK; } -void lk_poll (void) +void lk_event (SIM_KEY_EVENT *ev) { -SIM_KEY_EVENT ev; LK_KEYDATA lk_key; int32 mode; -if (vid_poll_kb (&ev) != SCPE_OK) - return; - -lk_key = lk_map_key (ev.key); +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]); +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; switch (mode) { case LK_MODE_DOWN: - if (ev.state == SIM_KEYPRESS_DOWN) { + if (ev->state == SIM_KEYPRESS_DOWN) { LK_SEND_CHAR (lk_key.code); } break; case LK_MODE_AUTODOWN: - if (ev.state == SIM_KEYPRESS_DOWN) { + 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 (0xB4); + 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) { + if (ev->state == SIM_KEYPRESS_DOWN) { lk_keysdown++; LK_SEND_CHAR (lk_key.code); } - else { + else if (ev->state == SIM_KEYPRESS_UP) { lk_keysdown--; if (lk_keysdown > 0) { LK_SEND_CHAR (lk_key.code); } else { - LK_SEND_CHAR (0xB3); /* LK_ALLUP */ + LK_SEND_CHAR (LK_ALLUP); } } break; - } + } } const char *lk_description (DEVICE *dptr) diff --git a/VAX/vax_lk.h b/VAX/vax_lk.h new file mode 100644 index 00000000..930622af --- /dev/null +++ b/VAX/vax_lk.h @@ -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 diff --git a/VAX/vax_vc.c b/VAX/vax_vc.c index 7c1956c5..5fcf3e97 100644 --- a/VAX/vax_vc.c +++ b/VAX/vax_vc.c @@ -29,6 +29,10 @@ 06-Nov-2013 MB Increased the speed of v-sync interrupts, which was too slow for some O/S drivers. 11-Jun-2013 MB First version + + Related documents: + + AZ-GLFAB-MN - VAXstation II Technical Manual, BA23 Enclosure (Appendix C) */ #if !defined(VAX_620) @@ -36,6 +40,8 @@ #include "vax_defs.h" #include "sim_video.h" #include "vax_2681.h" +#include "vax_lk.h" +#include "vax_vs.h" /* CSR - control/status register */ @@ -195,11 +201,6 @@ BITFIELD vc_ic_mode_bits[] = { 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 { uint32 ptr; uint32 vec[8]; /* Interrupt vectors */ @@ -875,6 +876,8 @@ return 0; /* no intr req */ t_stat vc_svc (UNIT *uptr) { +SIM_MOUSE_EVENT mev; +SIM_KEY_EVENT kev; t_bool updated = FALSE; /* flag for refresh */ uint32 lines; uint32 ln, col, off; @@ -914,31 +917,35 @@ vc_cur_v = CUR_V; vc_cur_f = CUR_F; vc_cur_new_data = FALSE; -xpos = vc_mpos & 0xFF; /* get current mouse position */ -ypos = (vc_mpos >> 8) & 0xFF; -dx = vid_mouse_xrel; /* get relative movement */ -dy = -vid_mouse_yrel; -if (dx > VC_MOVE_MAX) /* limit movement */ - dx = VC_MOVE_MAX; -else if (dx < -VC_MOVE_MAX) - dx = -VC_MOVE_MAX; -if (dy > VC_MOVE_MAX) - dy = VC_MOVE_MAX; -else if (dy < -VC_MOVE_MAX) - dy = -VC_MOVE_MAX; -xpos += dx; /* add to counters */ -ypos += dy; -vc_mpos = ((ypos & 0xFF) << 8) | (xpos & 0xFF); /* update register */ -vid_mouse_xrel -= dx; /* reset counters for next poll */ -vid_mouse_yrel += dy; +if (vid_poll_kb (&kev) == SCPE_OK) /* poll keyboard */ + lk_event (&kev); /* push event */ +if (vid_poll_mouse (&mev) == SCPE_OK) { /* poll mouse */ + xpos = vc_mpos & 0xFF; /* get current mouse position */ + ypos = (vc_mpos >> 8) & 0xFF; + dx = mev.x_rel; /* get relative movement */ + dy = -mev.y_rel; + if (dx > VC_MOVE_MAX) /* limit movement */ + dx = VC_MOVE_MAX; + else if (dx < -VC_MOVE_MAX) + dx = -VC_MOVE_MAX; + if (dy > VC_MOVE_MAX) + dy = VC_MOVE_MAX; + else if (dy < -VC_MOVE_MAX) + dy = -VC_MOVE_MAX; + xpos += dx; /* add to counters */ + ypos += dy; + vc_mpos = ((ypos & 0xFF) << 8) | (xpos & 0xFF); /* update register */ -vc_csr |= (CSR_MSA | CSR_MSB | CSR_MSC); /* reset button states */ -if (vid_mouse_b3) /* set new button states */ - vc_csr &= ~CSR_MSA; -if (vid_mouse_b2) - vc_csr &= ~CSR_MSB; -if (vid_mouse_b1) - vc_csr &= ~CSR_MSC; + vc_csr |= (CSR_MSA | CSR_MSB | CSR_MSC); /* reset button states */ + if (mev.b3_state) /* set new button states */ + vc_csr &= ~CSR_MSA; + if (mev.b2_state) + vc_csr &= ~CSR_MSB; + if (mev.b1_state) + vc_csr &= ~CSR_MSC; + + vs_event (&mev); /* push event */ + } lines = 0; for (ln = 0; ln < VC_YSIZE; ln++) { diff --git a/VAX/vax_vs.c b/VAX/vax_vs.c index 287751a7..5abb46a2 100644 --- a/VAX/vax_vs.c +++ b/VAX/vax_vs.c @@ -1,6 +1,6 @@ /* 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 copy of this software and associated documentation files (the "Software"), @@ -27,58 +27,52 @@ 09-Aug-2013 MB Added definitions for self test report 11-Jun-2013 MB First version + + Related documents: + + EK-104AA-TM-001 - VCB02 Technical Manual (chapter C.6) */ #if !defined(VAX_620) -#include "vax_defs.h" -#include "sim_video.h" - -#define VSXXX_IDLE 0 -#define VSXXX_RECV 1 -#define VSXXX_SEND 2 -#define VSXXX_TEST 3 +#include "vax_vs.h" #define VSXXX_PROMPT 0 #define VSXXX_INC 1 #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 */ #define DBG_SERIAL 0x0001 /* serial port data */ #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_bptr = 0; -int32 vs_datalen = 0; int32 vs_x = 0; /* X-axis motion */ int32 vs_y = 0; /* Y-axis motion */ -t_bool vs_l = 0; /* Left button state */ -t_bool vs_m = 0; /* Middle button state */ -t_bool vs_r = 0; /* Right button state */ -uint8 vs_buf[10]; +t_bool vs_l = FALSE; /* Left button state */ +t_bool vs_m = FALSE; /* Middle button state */ +t_bool vs_r = FALSE; /* Right button state */ +VS_FIFO vs_sndf; /* send FIFO */ t_stat vs_wr (uint8 c); t_stat vs_rd (uint8 *c); t_stat vs_reset (DEVICE *dptr); void vs_cmd (int32 c); void vs_sendupd (void); -void vs_poll (void); 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 @@ -112,133 +106,155 @@ DEVICE vs_dev = { NULL, NULL, &vs_reset, NULL, NULL, NULL, NULL, DEV_DIS | DEV_DEBUG, 0, - vs_debug, NULL, NULL, NULL, NULL, NULL, + vs_debug, NULL, NULL, NULL, NULL, NULL, &vs_description }; t_stat vs_wr (uint8 c) { -if (vs_state != VSXXX_TEST) { - vs_bptr = 0; - vs_state = VSXXX_IDLE; - vs_datalen = 0; - vs_cmd (c); - } +vs_clear_fifo (&vs_sndf); +vs_cmd (c); return SCPE_OK; } t_stat vs_rd (uint8 *c) { -if (vs_state == VSXXX_IDLE) - vs_poll (); -switch (vs_state) { +t_stat r; - case VSXXX_IDLE: - *c = 0; - return SCPE_EOF; +r = vs_get_fifo (&vs_sndf, c); +if (r == SCPE_OK) + sim_debug (DBG_SERIAL, &vs_dev, "mouse -> vax: 0x%02X\n", *c); +return r; +} - case VSXXX_SEND: - case VSXXX_TEST: - *c = vs_buf[vs_bptr++]; - sim_debug (DBG_SERIAL, &vs_dev, "mouse -> vax: 0x%02X\n", *c); - if (vs_bptr == vs_datalen) { - vs_state = VSXXX_IDLE; - } - return SCPE_OK; +t_stat vs_put_fifo (VS_FIFO *fifo, uint8 data) +{ +if (fifo->count < VS_BUF_LEN) { + fifo->buf[fifo->head++] = data; + if (fifo->head == VS_BUF_LEN) + fifo->head = 0; + fifo->count++; + 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) { +uint8 data; + sim_debug (DBG_SERIAL, &vs_dev, "vax -> mouse: %c\n", c); switch (c) { - case 0x52: /* R */ + case VS_INCR: /* R */ sim_debug (DBG_CMD, &vs_dev, "set mode incremental(%c)\n", c); vs_mode = VSXXX_INC; break; - case 0x44: /* D */ + case VS_PROMPT: /* D */ sim_debug (DBG_CMD, &vs_dev, "set mode prompt(%c)\n", c); vs_mode = VSXXX_PROMPT; break; - case 0x50: /* P */ + case VS_POLL: /* P */ sim_debug (DBG_CMD, &vs_dev, "poll(%c)\n", c); vs_mode = VSXXX_PROMPT; vs_sendupd (); break; - case 0x54: /* T */ + case VS_TEST: /* T */ sim_debug (DBG_CMD, &vs_dev, "test(%c)\n", c); vs_reset (&vs_dev); - vs_state = VSXXX_TEST; /* send self test report */ - vs_buf[0] = RPT_TEST | RPT_SYNC | (VSXXX_REV & RPT_REV); - vs_buf[1] = (1 << RPT_V_MFR) | RPT_MOU; /* device type, build location */ - vs_buf[2] = 0; /* error code <6:0> (0 = OK) */ - vs_buf[3] = 0; /* button code <2:0> (0 = OK) */ - vs_bptr = 0; - vs_state = VSXXX_SEND; - vs_datalen = 4; + data = RPT_TEST | RPT_SYNC | (VSXXX_REV & RPT_REV); + vs_put_fifo (&vs_sndf, data); + data = (1 << RPT_V_MFR) | RPT_MOU; /* device type, build location */ + vs_put_fifo (&vs_sndf, data); + data = 0; /* error code <6:0> (0 = OK) */ + vs_put_fifo (&vs_sndf, data); + data = 0; /* button code <2:0> (0 = OK) */ + vs_put_fifo (&vs_sndf, data); break; } } t_stat vs_reset (DEVICE *dptr) { -vs_bptr = 0; -vs_state = VSXXX_IDLE; -vs_datalen = 0; +vs_x = 0; +vs_y = 0; +vs_l = FALSE; +vs_m = FALSE; +vs_r = FALSE; +vs_clear_fifo (&vs_sndf); vs_mode = VSXXX_PROMPT; return SCPE_OK; } void vs_sendupd (void) { -vs_buf[0] = RPT_SYNC; -vs_buf[0] |= (((vs_x > 0) ? 1 : 0) << 4); /* sign bits */ -vs_buf[0] |= (((vs_y >= 0) ? 0 : 1) << 3); -vs_buf[0] |= (((vs_l) ? 1 : 0) << 2); /* button states */ -vs_buf[0] |= (((vs_m) ? 1 : 0) << 1); -vs_buf[0] |= ((vs_r) ? 1 : 0); -vs_buf[1] = (abs(vs_x) > 0x3F) ? 0x3F : abs(vs_x); /* motion (limited to 63 pixels in any direction) */ -if (vs_x > 0) - vs_x -= vs_buf[1]; -else - vs_x += vs_buf[1]; -vs_buf[2] = (abs(vs_y) > 0x3F) ? 0x3F : abs(vs_y); -if (vs_y > 0) - vs_y -= vs_buf[2]; -else - vs_y += vs_buf[2]; -vs_bptr = 0; -vs_state = VSXXX_SEND; -vs_datalen = 3; -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", - (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); +uint8 b0, b1, b2; + +do { + if (vs_sndf.count == VS_BUF_LEN) /* fifo full? */ + return; + b0 = RPT_SYNC; + b0 |= (((vs_x > 0) ? 1 : 0) << 4); /* sign bits */ + b0 |= (((vs_y >= 0) ? 0 : 1) << 3); + b0 |= (((vs_l) ? 1 : 0) << 2); /* button states */ + b0 |= (((vs_m) ? 1 : 0) << 1); + b0 |= ((vs_r) ? 1 : 0); + vs_put_fifo (&vs_sndf, b0); + b1 = (abs(vs_x) > 0x3F) ? 0x3F : abs(vs_x); /* motion (limited to 63 pixels in any direction) */ + if (vs_x > 0) + vs_x -= b1; + else + vs_x += b1; + vs_put_fifo (&vs_sndf, b1); + b2 = (abs(vs_y) > 0x3F) ? 0x3F : abs(vs_y); + if (vs_y > 0) + 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; } -void vs_poll (void) +void vs_event (SIM_MOUSE_EVENT *ev) { -SIM_MOUSE_EVENT ev; - -if (vid_poll_mouse (&ev) != SCPE_OK) +if ((ev->x_rel == 0) && (ev->y_rel == 0) && + (vs_l == ev->b1_state) && (vs_m == ev->b2_state) && (vs_r == ev->b3_state)) return; -if (vs_state == VSXXX_IDLE) { - if ((ev.x_rel == 0) && (ev.y_rel == 0) && - (vs_l == ev.b1_state) && (vs_m == ev.b2_state) && (vs_r == ev.b3_state)) - return; - vs_x = ev.x_rel; - vs_y = ev.y_rel; - vs_l = ev.b1_state; - vs_m = ev.b2_state; - vs_r = ev.b3_state; - if (vs_mode == VSXXX_INC) - vs_sendupd (); - } +vs_x += ev->x_rel; +vs_y += ev->y_rel; +vs_l = ev->b1_state; +vs_m = ev->b2_state; +vs_r = ev->b3_state; +if (vs_mode == VSXXX_INC) + vs_sendupd (); } const char *vs_description (DEVICE *dptr) diff --git a/VAX/vax_vs.h b/VAX/vax_vs.h new file mode 100644 index 00000000..a52263b4 --- /dev/null +++ b/VAX/vax_vs.h @@ -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 diff --git a/Visual Studio Projects/MicroVAX1.vcproj b/Visual Studio Projects/MicroVAX1.vcproj index e32311f4..e61852f7 100644 --- a/Visual Studio Projects/MicroVAX1.vcproj +++ b/Visual Studio Projects/MicroVAX1.vcproj @@ -640,10 +640,18 @@ RelativePath="..\VAX\vax_defs.h" > + + + + + + + + + + + + diff --git a/sim_video.c b/sim_video.c index 3dcd05ec..d55cbd3a 100644 --- a/sim_video.c +++ b/sim_video.c @@ -31,8 +31,6 @@ #include "scp.h" t_bool vid_active = FALSE; -int32 vid_mouse_xrel; -int32 vid_mouse_yrel; int32 vid_cursor_x; int32 vid_cursor_y; t_bool vid_mouse_b1 = FALSE; @@ -523,8 +521,6 @@ if (!vid_active) { vid_height = height; vid_mouse_captured = FALSE; vid_cursor_visible = (vid_flags & SIM_VID_INPUTCAPTURED); - vid_mouse_xrel = 0; - vid_mouse_yrel = 0; vid_key_events.head = 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 y_delta = vid_cursor_y - y; +if (vid_flags & SIM_VID_INPUTCAPTURED) + return; + 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); /* Any queued mouse motion events need to have their relative @@ -728,12 +727,8 @@ if ((x_delta) || (y_delta)) { for (i=0; ix_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->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)) 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->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_b2 = (event->state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) ? 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", - 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); + 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_cursor_x, vid_cursor_y); if (vid_mouse_events.count < 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->x_pos = ev.x_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", - tail->x_rel, tail->y_rel, vid_mouse_xrel, vid_mouse_yrel); + sim_debug (SIM_VID_DBG_MOUSE, vid_dev, "Mouse Move Event: Coalesced into pending event: (%d,%d)\n", + tail->x_rel, tail->y_rel); } else { /* Add a new event */ vid_mouse_events.events[vid_mouse_events.tail++] = ev; @@ -1705,6 +1698,9 @@ while (vid_active) { if (vid_flags & SIM_VID_INPUTCAPTURED) SDL_WarpMouseInWindow (NULL, vid_width/2, vid_height/2); /* center position */ break; + case SDL_WINDOWEVENT_EXPOSED: + vid_update (); + break; } } break; diff --git a/sim_video.h b/sim_video.h index b8ede979..384f1a43 100644 --- a/sim_video.h +++ b/sim_video.h @@ -197,11 +197,6 @@ t_stat vid_screenshot (const char *filename); extern t_bool vid_active; 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) */ #define SIM_VID_DBG_MOUSE 0x01000000