summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/ti99/internal/genkbd.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/ti99/internal/genkbd.cpp')
-rw-r--r--src/devices/bus/ti99/internal/genkbd.cpp648
1 files changed, 648 insertions, 0 deletions
diff --git a/src/devices/bus/ti99/internal/genkbd.cpp b/src/devices/bus/ti99/internal/genkbd.cpp
new file mode 100644
index 00000000000..072ad1f6cb6
--- /dev/null
+++ b/src/devices/bus/ti99/internal/genkbd.cpp
@@ -0,0 +1,648 @@
+// license:BSD-3-Clause
+// copyright-holders:Michael Zapf
+/**********************************************************************
+
+ Geneve 9640 101-key XT/AT keyboard (High-level emulation)
+
+ Geneves may use any XT keyboard; some were delivered with a 101-key XT/AT
+ keyboard.
+
+ This is a high-level emulation in the sense that it is only emulated
+ from its behavior, not from its actual chipset. This will be done as
+ soon as we have a ROM dump.
+
+ Although the keyboard is switchable between XT and AT mode, we will
+ only emulate the XT mode here.
+
+ The code is copied from the previous implementation in genboard.cpp
+ and appropriately adapted to use the pc_kbd interface.
+
+ The XT keyboard interface is described in various places on the internet.
+ It does not comply with the PS2 protocol. The keyboard transmits 8-bit
+ scancodes serially with one (1) or two (0,1) start bits, LSB to MSB,
+ no parity and no stop bits. Each bit is read into the shift register
+ when the clock line is pulled low by the keyboard.
+
+ MZ, August 2019
+
+****************************************************************************/
+
+#include "emu.h"
+#include "genkbd.h"
+
+#define LOG_WARN (1U<<1)
+#define LOG_QUEUE (1U<<2)
+#define LOG_TRANSFER (1U<<3)
+#define LOG_LINES (1U<<4)
+
+#define VERBOSE ( LOG_GENERAL | LOG_WARN )
+
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(KBD_GENEVE_XT_101_HLE, geneve_xt_101_hle_keyboard_device, "kb_geneve_hle", "Geneve XT Keyboard 101 Keys (HLE)")
+
+INPUT_PORTS_START( geneve_xt_101_hle_keyboard )
+ PORT_START("KEY0") /* IN3 */
+ PORT_BIT(0x0001, 0x0000, IPT_UNUSED ) /* unused scancode 0 */
+ PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CODE(KEYCODE_ESC) /* Esc 01 81 */
+ PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("1 !") PORT_CODE(KEYCODE_1) /* 1 02 82 */
+ PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("2 @") PORT_CODE(KEYCODE_2) /* 2 03 83 */
+ PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("3 #") PORT_CODE(KEYCODE_3) /* 3 04 84 */
+ PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("4 $") PORT_CODE(KEYCODE_4) /* 4 05 85 */
+ PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("5 %") PORT_CODE(KEYCODE_5) /* 5 06 86 */
+ PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("6 ^") PORT_CODE(KEYCODE_6) /* 6 07 87 */
+ PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("7 &") PORT_CODE(KEYCODE_7) /* 7 08 88 */
+ PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("8 *") PORT_CODE(KEYCODE_8) /* 8 09 89 */
+ PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("9 (") PORT_CODE(KEYCODE_9) /* 9 0A 8A */
+ PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("0 )") PORT_CODE(KEYCODE_0) /* 0 0B 8B */
+ PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("- _") PORT_CODE(KEYCODE_MINUS) /* - 0C 8C */
+ PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("= +") PORT_CODE(KEYCODE_EQUALS) /* = 0D 8D */
+ PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Backspace") PORT_CODE(KEYCODE_BACKSPACE) /* Backspace 0E 8E */
+ PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Tab") PORT_CODE(KEYCODE_TAB) /* Tab 0F 8F */
+
+ PORT_START("KEY1") /* IN4 */
+ PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) /* Q 10 90 */
+ PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) /* W 11 91 */
+ PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) /* E 12 92 */
+ PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) /* R 13 93 */
+ PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) /* T 14 94 */
+ PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) /* Y 15 95 */
+ PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) /* U 16 96 */
+ PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) /* I 17 97 */
+ PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) /* O 18 98 */
+ PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) /* P 19 99 */
+ PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("[ {") PORT_CODE(KEYCODE_OPENBRACE) /* [ 1A 9A */
+ PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("] }") PORT_CODE(KEYCODE_CLOSEBRACE) /* ] 1B 9B */
+ PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Enter") PORT_CODE(KEYCODE_ENTER) /* Enter 1C 9C */
+ PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("L-Ctrl") PORT_CODE(KEYCODE_LCONTROL) /* LCtrl 1D 9D */
+ PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) /* A 1E 9E */
+ PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) /* S 1F 9F */
+
+ PORT_START("KEY2") /* IN5 */
+ PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) /* D 20 A0 */
+ PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) /* F 21 A1 */
+ PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) /* G 22 A2 */
+ PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) /* H 23 A3 */
+ PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) /* J 24 A4 */
+ PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) /* K 25 A5 */
+ PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) /* L 26 A6 */
+ PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("; :") PORT_CODE(KEYCODE_COLON) /* ; 27 A7 */
+ PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("' \"") PORT_CODE(KEYCODE_QUOTE) /* ' 28 A8 */
+ PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("` ~") PORT_CODE(KEYCODE_TILDE) /* ` 29 A9 */
+ PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("L-Shift") PORT_CODE(KEYCODE_LSHIFT) /* LShift 2A AA */
+ PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("\\ |") PORT_CODE(KEYCODE_BACKSLASH) /* \ 2B AB */
+ PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) /* Z 2C AC */
+ PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) /* X 2D AD */
+ PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) /* C 2E AE */
+ PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) /* V 2F AF */
+
+ PORT_START("KEY3") /* IN6 */
+ PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) /* B 30 B0 */
+ PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) /* N 31 B1 */
+ PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) /* M 32 B2 */
+ PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(", <") PORT_CODE(KEYCODE_COMMA) /* , 33 B3 */
+ PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(". >") PORT_CODE(KEYCODE_STOP) /* . 34 B4 */
+ PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("/ ?") PORT_CODE(KEYCODE_SLASH) /* / 35 B5 */
+ PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("R-Shift") PORT_CODE(KEYCODE_RSHIFT) /* RShift 36 B6 */
+ PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP * (PrtScr)") PORT_CODE(KEYCODE_ASTERISK ) /* KP * (PrtSc) 37 B7 */
+ PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Alt") PORT_CODE(KEYCODE_LALT) /* LAlt 38 B8 */
+ PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) /* Space 39 B9 */
+ PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Caps") PORT_CODE(KEYCODE_CAPSLOCK) /* Caps Lock 3A BA */
+ PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F1") PORT_CODE(KEYCODE_F1) /* F1 3B BB */
+ PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F2") PORT_CODE(KEYCODE_F2) /* F2 3C BC */
+ PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F3") PORT_CODE(KEYCODE_F3) /* F3 3D BD */
+ PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F4") PORT_CODE(KEYCODE_F4) /* F4 3E BE */
+ PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F5") PORT_CODE(KEYCODE_F5) /* F5 3F BF */
+
+ PORT_START("KEY4") /* IN7 */
+ PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F6") PORT_CODE(KEYCODE_F6) /* F6 40 C0 */
+ PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F7") PORT_CODE(KEYCODE_F7) /* F7 41 C1 */
+ PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F8") PORT_CODE(KEYCODE_F8) /* F8 42 C2 */
+ PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F9") PORT_CODE(KEYCODE_F9) /* F9 43 C3 */
+ PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F10") PORT_CODE(KEYCODE_F10) /* F10 44 C4 */
+ PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("NumLock") PORT_CODE(KEYCODE_NUMLOCK) /* Num Lock 45 C5 */
+ PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("ScrLock (F14)") PORT_CODE(KEYCODE_SCRLOCK) /* Scroll Lock 46 C6 */
+ PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 7 (Home)") PORT_CODE(KEYCODE_7_PAD) /* KP 7 (Home) 47 C7 */
+ PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 8 (Up)") PORT_CODE(KEYCODE_8_PAD) /* KP 8 (Up) 48 C8 */
+ PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 9 (PgUp)") PORT_CODE(KEYCODE_9_PAD) /* KP 9 (PgUp) 49 C9 */
+ PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP -") PORT_CODE(KEYCODE_MINUS_PAD) /* KP - 4A CA */
+ PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 4 (Left)") PORT_CODE(KEYCODE_4_PAD) /* KP 4 (Left) 4B CB */
+ PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 5") PORT_CODE(KEYCODE_5_PAD) /* KP 5 4C CC */
+ PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 6 (Right)") PORT_CODE(KEYCODE_6_PAD) /* KP 6 (Right)4D CD */
+ PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP +") PORT_CODE(KEYCODE_PLUS_PAD) /* KP + 4E CE */
+ PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 1 (End)") PORT_CODE(KEYCODE_1_PAD) /* KP 1 (End) 4F CF */
+
+ PORT_START("KEY5") /* IN8 */
+ PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 2 (Down)") PORT_CODE(KEYCODE_2_PAD) /* KP 2 (Down) 50 D0 */
+ PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 3 (PgDn)") PORT_CODE(KEYCODE_3_PAD) /* KP 3 (PgDn) 51 D1 */
+ PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 0 (Ins)") PORT_CODE(KEYCODE_0_PAD) /* KP 0 (Ins) 52 D2 */
+ PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP . (Del)") PORT_CODE(KEYCODE_DEL_PAD) /* KP . (Del) 53 D3 */
+ PORT_BIT ( 0x0030, 0x0000, IPT_UNUSED )
+ PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(84/102)\\") PORT_CODE(KEYCODE_BACKSLASH2) /* Backslash 2 56 D6 */
+ PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(101)F11") PORT_CODE(KEYCODE_F11) /* F11 57 D7 */
+ PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(101)F12") PORT_CODE(KEYCODE_F12) /* F12 58 D8 */
+ PORT_BIT ( 0xfe00, 0x0000, IPT_UNUSED )
+
+ PORT_START("KEY6") /* IN9 */
+ PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(101)KP Enter") PORT_CODE(KEYCODE_ENTER_PAD) /* KP Enter 60 e0 */
+ PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(101)R-Control") PORT_CODE(KEYCODE_RCONTROL) /* RCtrl 61 e1 */
+ PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(101)AltGr") PORT_CODE(KEYCODE_RALT) /* AltGr 64 e4 */
+
+ PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(101)KP /") PORT_CODE(KEYCODE_SLASH_PAD) /* KP Slash 62 e2 */
+
+ PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(101)Home") PORT_CODE(KEYCODE_HOME) /* Home 66 e6 */
+ PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(101)Cursor Up") PORT_CODE(KEYCODE_UP) /* Up 67 e7 */
+ PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(101)Page Up") PORT_CODE(KEYCODE_PGUP) /* Page Up 68 e8 */
+ PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(101)Cursor Left") PORT_CODE(KEYCODE_LEFT) /* Left 69 e9 */
+ PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(101)Cursor Right") PORT_CODE(KEYCODE_RIGHT) /* Right 6a ea */
+ PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(101)End") PORT_CODE(KEYCODE_END) /* End 6b eb */
+ PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(101)Cursor Down") PORT_CODE(KEYCODE_DOWN) /* Down 6c ec */
+ PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(101)Page Down") PORT_CODE(KEYCODE_PGDN) /* Page Down 6d ed */
+ PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(101)Insert") PORT_CODE(KEYCODE_INSERT) /* Insert 6e ee */
+ PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(101)Delete") PORT_CODE(KEYCODE_DEL) /* Delete 6f ef */
+
+ PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(101)PrtScr (F13)") PORT_CODE(KEYCODE_PRTSCR) /* Print Screen 63 e3 */
+ PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(101)Pause (F15)") PORT_CODE(KEYCODE_PAUSE) /* Pause 65 e5 */
+
+ PORT_START("KEY7") /* IN10 */
+ PORT_BIT ( 0xffff, 0x0000, IPT_UNUSED )
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor geneve_xt_101_hle_keyboard_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( geneve_xt_101_hle_keyboard );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// ibm_pc_xt_83_keyboard_device - constructor
+//-------------------------------------------------
+
+geneve_xt_101_hle_keyboard_device::geneve_xt_101_hle_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, KBD_GENEVE_XT_101_HLE, tag, owner, clock),
+ device_pc_kbd_interface(mconfig, *this),
+ m_keys(*this, "KEY%u", 0),
+ m_queue_length(0),
+ m_autorepeat_code(0),
+ m_autorepeat_timer(0),
+ m_fake_shift_state(false),
+ m_fake_unshift_state(false),
+ m_resetting(false),
+ m_clock_line(ASSERT_LINE),
+ m_data_line(ASSERT_LINE)
+{
+}
+
+/*
+ Called by the poll timer
+*/
+void geneve_xt_101_hle_keyboard_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ if (id==0)
+ {
+ poll();
+ send_key();
+ }
+ else
+ {
+ if (id==1)
+ {
+ // Send timer
+ if (m_shift_count==10)
+ {
+ // Done, all sent
+ m_pc_kbdc->clock_write_from_kb(1);
+ m_pc_kbdc->data_write_from_kb(1);
+ m_send_timer->reset();
+ m_shift_count = 0;
+
+ // Adjust the queue
+ m_queue_head = (m_queue_head + 1) % KEYQUEUESIZE;
+ m_queue_length--;
+ }
+ else
+ {
+ m_pc_kbdc->clock_write_from_kb(1);
+ m_pc_kbdc->data_write_from_kb(m_shift_reg&1);
+ m_pc_kbdc->clock_write_from_kb(0);
+ m_shift_reg>>=1;
+ m_shift_count++;
+ }
+ }
+ }
+}
+
+
+/*
+ Translations
+*/
+static const uint8_t MF1_CODE[0xe] =
+{
+ // Extended keys that are equivalent to non-extended keys
+ 0x1c, // KP Enter -> Return
+ 0x1d, // RCtrl -> LCtrl
+ 0x38, // AltGr -> LAlt
+
+ // Extended key that is equivalent to a non-extended key with shift off
+ 0x35, // KP / -> /
+
+ // Extended keys that are equivalent to non-extended keys with numlock off
+ 0x47, // Home -> KP 7 (Home)
+ 0x48, // Up -> KP 8 (Up)
+ 0x49, // Page up -> KP 9 (PgUp)
+ 0x4b, // Left -> KP 4 (Left)
+ 0x4d, // Right -> KP 6 (Right)
+ 0x4f, // End -> KP 1 (End)
+ 0x50, // Down -> KP 2 (Down)
+ 0x51, // Page dn -> KP 3 (PgDn)
+ 0x52, // Insert -> KP 0 (Ins)
+ 0x53 // Delete -> KP . (Del)
+};
+
+void geneve_xt_101_hle_keyboard_device::poll()
+{
+ uint32_t keystate;
+ uint32_t key_transitions;
+ uint32_t mask;
+ bool pressed = false;
+ int keycode = 0;
+
+ if (m_resetting) return;
+
+ // We're testing two 16-bit ports at once
+ // but only if we have enough space in the queue
+ for (int i=0; (i < 4) && (m_queue_length <= (KEYQUEUESIZE-MAXKEYMSGLENGTH)); i++)
+ {
+ // Get those two ports and calculate the difference
+ keystate = m_keys[2*i]->read() | (m_keys[2*i + 1]->read() << 16);
+ key_transitions = keystate ^ m_key_state_save[i];
+ if (key_transitions != 0)
+ {
+ mask = 0x00000001;
+ // Some key(s) has/have changed (pressed/released)
+ for (int j=0; (j < 32) && (m_queue_length <= (KEYQUEUESIZE-MAXKEYMSGLENGTH)); j++)
+ {
+ if ((key_transitions & mask)!=0)
+ {
+ // Found one changed key (i is a 32-key block)
+ keycode = (i<<5) | j;
+ pressed = (keystate & mask)!=0;
+
+ // Auto-repeat
+ if (pressed)
+ {
+ m_autorepeat_code = keycode;
+ m_autorepeat_timer = KEYAUTOREPEATDELAY+1;
+ m_key_state_save[i] |= mask;
+ }
+ else
+ {
+ m_autorepeat_code = 0;
+ m_key_state_save[i] &= ~mask;
+ }
+
+ // We are here because the set of pressed keys has changed
+ // In the case that we have a fake shift/unshift,
+ // we have to release it.
+
+ if (m_fake_shift_state)
+ {
+ /* Fake shift release */
+ post_in_key_queue(0xe0);
+ post_in_key_queue(0xaa);
+ m_fake_shift_state = false;
+ }
+ if (m_fake_unshift_state)
+ {
+ /* Fake shift press */
+ post_in_key_queue(0xe0);
+ post_in_key_queue(0x2a);
+ m_fake_unshift_state = false;
+ }
+
+ switch (keycode)
+ {
+ case 0x2a:
+ m_left_shift = pressed;
+ break;
+ case 0x36:
+ m_right_shift = pressed;
+ break;
+ case 0x1d:
+ m_left_ctrl = pressed;
+ break;
+ case 0x61:
+ m_right_ctrl = pressed;
+ break;
+ case 0x38:
+ m_left_alt = pressed;
+ break;
+ case 0x62:
+ m_altgr = pressed;
+ break;
+ case 0x45:
+ if (pressed) m_numlock = !m_numlock;
+ break;
+ default:
+ break;
+ }
+
+ // Extended keycodes
+ if ((keycode >= 0x60) && (keycode < 0x6e))
+ {
+ if ((keycode >= 0x63) && pressed)
+ {
+ // Handle shift state
+ if (keycode == 0x63) // Slash
+ {
+ if (m_left_shift || m_right_shift)
+ {
+ // Fake shift unpress
+ m_fake_unshift_state = true;
+ }
+ }
+ else
+ { // Key function with NumLock=0
+ if (m_numlock && (!m_left_shift) && (!m_right_shift))
+ {
+ // Fake shift press if numlock is active
+ m_fake_shift_state = true;
+ }
+ else
+ {
+ if ((!m_numlock) && (m_left_shift || m_right_shift))
+ {
+ // Fake shift unpress if shift is down
+ m_fake_unshift_state = true;
+ }
+ }
+ }
+
+ if (m_fake_shift_state)
+ {
+ post_in_key_queue(0xe0);
+ post_in_key_queue(0x2a);
+ }
+
+ if (m_fake_unshift_state)
+ {
+ post_in_key_queue(0xe0);
+ post_in_key_queue(0xaa);
+ }
+ }
+ keycode = MF1_CODE[keycode-0x60];
+ if (!pressed) keycode |= 0x80;
+ post_in_key_queue(0xe0);
+ post_in_key_queue(keycode);
+ }
+ else
+ {
+ if (keycode == 0x6e)
+ {
+ // Emulate Print Screen / System Request (F13) key
+ // this is a bit complex, as Alt+PrtScr -> SysRq
+ // Additionally, Ctrl+PrtScr involves no fake shift press
+ if (m_left_alt || m_altgr)
+ {
+ // SysRq
+ keycode = 0x54;
+ if (!pressed) keycode |= 0x80;
+ post_in_key_queue(keycode);
+ }
+ else
+ {
+ // Handle shift state
+ if (pressed && (!m_left_shift) && (!m_right_shift) && (!m_left_ctrl) && (!m_right_ctrl))
+ { // Fake shift press
+ post_in_key_queue(0xe0);
+ post_in_key_queue(0x2a);
+ m_fake_shift_state = true;
+ }
+
+ keycode = 0x37;
+ if (!pressed) keycode |= 0x80;
+ post_in_key_queue(0xe0);
+ post_in_key_queue(keycode);
+ }
+ }
+ else
+ {
+ if (keycode == 0x6f)
+ {
+ // Emulate pause (F15) key
+ // This is a bit complex, as Pause -> Ctrl+NumLock and
+ // Ctrl+Pause -> Ctrl+ScrLock.
+ // Furthermore, there is no repeat or release.
+ if (pressed)
+ {
+ if (m_left_ctrl || m_right_ctrl)
+ {
+ post_in_key_queue(0xe0);
+ post_in_key_queue(0x46);
+ post_in_key_queue(0xe0);
+ post_in_key_queue(0xc6);
+ }
+ else
+ {
+ post_in_key_queue(0xe1);
+ post_in_key_queue(0x1d);
+ post_in_key_queue(0x45);
+ post_in_key_queue(0xe1);
+ post_in_key_queue(0x9d);
+ post_in_key_queue(0xc5);
+ }
+ }
+ }
+ else
+ {
+ if (!pressed) keycode |= 0x80;
+ post_in_key_queue(keycode);
+ }
+ }
+ }
+
+ }
+ mask <<= 1;
+ }
+ }
+ }
+
+ // Implement auto repeat
+ if (m_autorepeat_code != 0)
+ {
+ m_autorepeat_timer--;
+ if ((m_autorepeat_timer == 0) && (m_queue_length <= (KEYQUEUESIZE-MAXKEYMSGLENGTH)))
+ {
+ // Extended code
+ if ((m_autorepeat_code >= 0x60) && (m_autorepeat_code < 0x6e))
+ {
+ post_in_key_queue(0xe0);
+ post_in_key_queue(MF1_CODE[m_autorepeat_code-0x60]);
+ }
+ else
+ {
+ if (m_autorepeat_code == 0x6e)
+ {
+ if (m_left_alt || m_altgr)
+ {
+ post_in_key_queue(0x54); // SysRq
+ }
+ else
+ {
+ post_in_key_queue(0xe0);
+ post_in_key_queue(0x37); // PrtScr
+ }
+ }
+ else
+ {
+ if (m_autorepeat_code != 0x6f) // Pause cannot do an auto-repeat
+ {
+ post_in_key_queue(m_autorepeat_code);
+ }
+ }
+ }
+ m_autorepeat_timer = KEYAUTOREPEATRATE;
+ }
+ }
+}
+
+void geneve_xt_101_hle_keyboard_device::send_key()
+{
+ if (m_clock_line == CLEAR_LINE)
+ {
+ m_reset_timer--;
+ if (m_reset_timer==0)
+ {
+ LOG("Reset triggered\n");
+ reset_line(0);
+ reset_line(1);
+ }
+ }
+ else
+ {
+ if (m_data_line==1)
+ {
+ // Dequeue a key
+ if (m_queue_length != 0)
+ {
+ LOGMASKED(LOG_TRANSFER, "Send keycode %02x\n", m_queue[m_queue_head]);
+ // Get the next key, add the two start bits to the right (0,1)
+ m_shift_reg = (m_queue[m_queue_head] << 2) | 0x02;
+ m_send_timer->adjust(attotime::from_usec(1), 0, attotime::from_hz(10000));
+ }
+ }
+ else
+ LOGMASKED(LOG_TRANSFER, "Transfer blocked by data=0 from host\n");
+ }
+}
+
+void geneve_xt_101_hle_keyboard_device::post_in_key_queue(int keycode)
+{
+ m_queue[(m_queue_head + m_queue_length) % KEYQUEUESIZE] = keycode;
+ m_queue_length++;
+
+ LOGMASKED(LOG_QUEUE, "Enqueue keycode %02x, queue length=%d\n", keycode, m_queue_length);
+}
+
+//-------------------------------------------------
+// clock_write -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( geneve_xt_101_hle_keyboard_device::clock_write )
+{
+ LOGMASKED(LOG_LINES, "Clock write: %d\n", state);
+ m_clock_line = (line_state)state;
+ if (m_clock_line == CLEAR_LINE)
+ {
+ if (m_reset_timer == -1)
+ m_reset_timer = 3; // 25 ms
+ }
+ else
+ m_reset_timer = -1;
+}
+
+
+//-------------------------------------------------
+// data_write -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( geneve_xt_101_hle_keyboard_device::data_write )
+{
+ LOGMASKED(LOG_LINES, "Data write: %d\n", state);
+ m_data_line = (line_state)state;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void geneve_xt_101_hle_keyboard_device::device_start()
+{
+ set_pc_kbdc_device();
+ m_poll_timer = timer_alloc(0);
+ m_send_timer = timer_alloc(1);
+
+ // state saving
+ save_item(NAME(m_queue_length));
+ save_item(NAME(m_queue_head));
+ save_pointer(NAME(m_key_state_save),4);
+ save_pointer(NAME(m_queue),KEYQUEUESIZE);
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void geneve_xt_101_hle_keyboard_device::device_reset()
+{
+ // Trigger our reset line
+ reset_line(0);
+ reset_line(1);
+ m_poll_timer->adjust(attotime::from_usec(1), 0, attotime::from_hz(120));
+}
+
+
+WRITE_LINE_MEMBER( geneve_xt_101_hle_keyboard_device::reset_line )
+{
+ m_resetting = (state==0);
+
+ if (m_resetting)
+ {
+ // Reset -> clear keyboard key queue
+ m_reset_timer = -1;
+ m_queue_length = 0;
+ m_queue_head = 0;
+ memset(m_key_state_save, 0, sizeof(m_key_state_save));
+
+ m_numlock = false;
+ m_left_shift = false;
+ m_right_shift = false;
+ m_left_ctrl = false;
+ m_right_ctrl = false;
+ m_left_alt = false;
+ m_altgr = false;
+
+ m_fake_shift_state = false;
+ m_fake_unshift_state = false;
+ m_autorepeat_code = 0;
+
+ m_shift_reg = 0;
+ m_shift_count = 0;
+
+ // Send the BAT (Basic assurance test) OK value (AA)
+ post_in_key_queue(0xaa);
+ }
+}
+