geneve: Add PC KBD connector; allow for using XT keyboards in place of the currently high-level emulated XT/AT 101 keyboard.

This commit is contained in:
Michael Zapf 2019-09-17 17:41:19 +02:00
parent ec4b8b2fa4
commit 4495c35113
8 changed files with 1120 additions and 749 deletions

View File

@ -2941,6 +2941,8 @@ if (BUSES["TI99"]~=null) then
MAME_DIR .. "src/devices/bus/ti99/internal/evpcconn.h",
MAME_DIR .. "src/devices/bus/ti99/internal/genboard.cpp",
MAME_DIR .. "src/devices/bus/ti99/internal/genboard.h",
MAME_DIR .. "src/devices/bus/ti99/internal/genkbd.cpp",
MAME_DIR .. "src/devices/bus/ti99/internal/genkbd.h",
MAME_DIR .. "src/devices/bus/ti99/internal/ioport.cpp",
MAME_DIR .. "src/devices/bus/ti99/internal/ioport.h",
MAME_DIR .. "src/devices/bus/ti99/colorbus/busmouse.cpp",

View File

@ -16,6 +16,10 @@ The following basic program can be useful for identifying scancodes:
#include "emu.h"
#include "pc_kbdc.h"
#define LOG_SIGNALS (1U<<1)
#define VERBOSE ( LOG_GENERAL )
#include "logmacro.h"
//**************************************************************************
// GLOBAL VARIABLES
@ -109,7 +113,7 @@ void pc_kbdc_device::device_start()
}
void pc_kbdc_device::update_clock_state()
void pc_kbdc_device::update_clock_state(bool fromkb)
{
int new_clock_state = m_mb_clock_state & m_kb_clock_state;
@ -117,7 +121,7 @@ void pc_kbdc_device::update_clock_state()
{
// We first set our state to prevent possible endless loops
m_clock_state = new_clock_state;
LOGMASKED(LOG_SIGNALS, "%s Clock: %d\n", fromkb? "<-" : "->", m_clock_state);
// Send state to keyboard interface logic on mainboard
m_out_clock_cb(m_clock_state);
@ -128,7 +132,7 @@ void pc_kbdc_device::update_clock_state()
}
void pc_kbdc_device::update_data_state()
void pc_kbdc_device::update_data_state(bool fromkb)
{
int new_data_state = m_mb_data_state & m_kb_data_state;
@ -136,6 +140,7 @@ void pc_kbdc_device::update_data_state()
{
// We first set our state to prevent possible endless loops
m_data_state = new_data_state;
LOGMASKED(LOG_SIGNALS, "%s Data: %d\n", fromkb? "<-" : "->", m_data_state);
// Send state to keyboard interface logic on mainboard
m_out_data_cb(m_data_state);
@ -150,28 +155,28 @@ void pc_kbdc_device::update_data_state()
WRITE_LINE_MEMBER(pc_kbdc_device::clock_write_from_mb)
{
m_mb_clock_state = state;
update_clock_state();
update_clock_state(false);
}
WRITE_LINE_MEMBER(pc_kbdc_device::data_write_from_mb)
{
m_mb_data_state = state;
update_data_state();
update_data_state(false);
}
WRITE_LINE_MEMBER(pc_kbdc_device::clock_write_from_kb)
{
m_kb_clock_state = state;
update_clock_state();
update_clock_state(true);
}
WRITE_LINE_MEMBER(pc_kbdc_device::data_write_from_kb)
{
m_kb_data_state = state;
update_data_state();
update_data_state(true);
}

View File

@ -79,8 +79,8 @@ protected:
virtual void device_resolve_objects() override;
virtual void device_start() override;
void update_clock_state();
void update_data_state();
void update_clock_state(bool fromkb);
void update_data_state(bool fromkb);
devcb_write_line m_out_clock_cb;
devcb_write_line m_out_data_cb;

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,7 @@
#include "machine/mm58274c.h"
#include "machine/at29x.h"
#include "machine/ram.h"
#include "bus/pc_kbd/pc_kbdc.h"
enum
{
@ -37,12 +38,12 @@ enum
GENEVE_PFM512A
};
#define GENEVE_KEYBOARD_TAG "gkeyboard"
#define GENEVE_MAPPER_TAG "gmapper"
#define GENEVE_GATE_ARRAY_TAG "gatearray"
#define GENEVE_MOUSE_TAG "gmouse"
#define GENEVE_CLOCK_TAG "mm58274c"
#define GENEVE_PFM512_TAG "pfm512"
#define GENEVE_PFM512A_TAG "pfm512a"
#define GENEVE_KEYBOARD_CONN_TAG "keybconn"
#define GENEVE_SRAM_TAG "sram"
#define GENEVE_DRAM_TAG "dram"
@ -53,66 +54,10 @@ namespace bus { namespace ti99 { namespace internal {
/*****************************************************************************/
class geneve_keyboard_device : public device_t
class geneve_gate_array_device : public device_t
{
public:
geneve_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
DECLARE_WRITE_LINE_MEMBER( reset_line );
DECLARE_WRITE_LINE_MEMBER( send_scancodes );
DECLARE_WRITE_LINE_MEMBER( clock_control );
uint8_t get_recent_key();
auto int_cb() { return m_interrupt.bind(); }
protected:
void device_start() override;
void device_reset() override;
ioport_constructor device_input_ports() const override;
void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
devcb_write_line m_interrupt; // Keyboard interrupt to console
required_ioport_array<8> m_keys;
private:
static constexpr unsigned KEYQUEUESIZE = 256;
static constexpr unsigned MAXKEYMSGLENGTH = 10;
static constexpr unsigned KEYAUTOREPEATDELAY = 30;
static constexpr unsigned KEYAUTOREPEATRATE = 6;
void post_in_key_queue(int keycode);
void signal_when_key_available();
void poll();
bool m_key_reset;
int m_key_queue_length;
uint8_t m_key_queue[KEYQUEUESIZE];
int m_key_queue_head;
bool m_key_in_buffer;
uint32_t m_key_state_save[4];
bool m_key_numlock_state;
int m_key_ctrl_state;
int m_key_alt_state;
int m_key_real_shift_state;
bool m_key_fake_shift_state;
bool m_key_fake_unshift_state;
int m_key_autorepeat_key;
int m_key_autorepeat_timer;
bool m_keep_keybuf;
bool m_keyboard_clock;
emu_timer* m_timer;
};
/*****************************************************************************/
class geneve_mapper_device : public device_t
{
public:
geneve_mapper_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
geneve_gate_array_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
void set_geneve_mode(bool geneve);
void set_direct_mode(bool direct);
@ -130,44 +75,24 @@ public:
DECLARE_WRITE_LINE_MEMBER( clock_in );
DECLARE_WRITE_LINE_MEMBER( dbin_in );
// Keyboard support
DECLARE_WRITE_LINE_MEMBER( set_keyboard_clock );
DECLARE_WRITE_LINE_MEMBER( enable_shift_register );
DECLARE_WRITE_LINE_MEMBER( kbdclk );
DECLARE_WRITE_LINE_MEMBER( kbddata );
// PFM support
DECLARE_WRITE_LINE_MEMBER( pfm_select_lsb );
DECLARE_WRITE_LINE_MEMBER( pfm_select_msb );
DECLARE_WRITE_LINE_MEMBER( pfm_output_enable );
auto ready_cb() { return m_ready.bind(); }
auto kbdint_cb() { return m_keyint.bind(); }
protected:
geneve_mapper_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
void device_start() override;
virtual void device_reset() override;
geneve_gate_array_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
void common_reset();
// GROM simulation
bool m_gromwaddr_LSB;
bool m_gromraddr_LSB;
int m_grom_address;
uint8_t read_grom(offs_t offset);
void write_grom(offs_t offset, uint8_t data);
// wait states
void set_wait(int min);
void set_video_waitcount(int min);
bool m_video_waitstates;
bool m_extra_waitstates;
bool m_ready_asserted;
bool m_read_mode;
bool m_debug_no_ws;
bool m_geneve_mode;
bool m_direct_mode;
int m_cartridge_size;
bool m_cartridge_secondpage;
bool m_cartridge6_writable;
bool m_cartridge7_writable;
int m_map[8];
/*
Constants for mapper decoding. Naming scheme:
M=Mapper, L=Logical space; P=Physical space
@ -200,6 +125,39 @@ protected:
int wait; // Wait states
} decdata;
uint8_t* m_eprom;
int m_pbox_prefix;
int m_boot_rom;
private:
void device_start() override;
virtual void device_reset() override;
// GROM simulation
bool m_gromwaddr_LSB;
bool m_gromraddr_LSB;
int m_grom_address;
uint8_t read_grom(offs_t offset);
void write_grom(offs_t offset, uint8_t data);
// wait states
void set_wait(int min);
void set_video_waitcount(int min);
bool m_video_waitstates;
bool m_extra_waitstates;
bool m_ready_asserted;
bool m_read_mode;
bool m_debug_no_ws;
bool m_geneve_mode;
bool m_direct_mode;
int m_cartridge_size;
bool m_cartridge_secondpage;
bool m_cartridge6_writable;
bool m_cartridge7_writable;
int m_map[8];
// The result of decoding
decdata m_decoded;
@ -219,17 +177,6 @@ protected:
const char* description; // Good for logging
} logentry_t;
logentry_t m_logmap[7] =
{
{ 0xf100, 0x000e, 0x8800, 0x03fe, 0x0400, MLVIDEO, "video" },
{ 0xf110, 0x0007, 0x8000, 0x0007, 0x0000, MLMAPPER, "mapper" },
{ 0xf118, 0x0007, 0x8008, 0x0007, 0x0000, MLKEY, "keyboard" },
{ 0xf120, 0x000e, 0x8400, 0x03fe, 0x0000, MLSOUND, "sound" },
{ 0xf130, 0x000f, 0x8010, 0x000f, 0x0000, MLCLOCK, "clock" },
{ 0x0000, 0x0000, 0x9000, 0x03fe, 0x0400, MBOX, "speech (in P-Box)" },
{ 0x0000, 0x0000, 0x9800, 0x03fe, 0x0400, MLGROM, "GROM" },
};
// Static decoder entry for the physical space
// There are no differences between native mode and TI mode.
typedef struct
@ -241,13 +188,8 @@ protected:
const char* description; // Good for logging
} physentry_t;
physentry_t m_physmap[4] =
{
{ 0x000000, 0x07ffff, MPDRAM, 1, "DRAM" },
{ 0x080000, 0x07ffff, MPEXP, 1, "on-board expansion" },
{ 0x1e0000, 0x01ffff, MPEPROM, 0, "EPROM" },
{ 0x180000, 0x07ffff, MPSRAM, 0, "SRAM" }
};
static const geneve_gate_array_device::logentry_t s_logmap[];
static const geneve_gate_array_device::physentry_t s_physmap[];
void decode_logical(bool reading, decdata* dec);
void map_address(bool reading, decdata* dec);
@ -258,12 +200,9 @@ protected:
// PFM mod (0 = none, 1 = AT29C040, 2 = AT29C040A)
uint8_t boot_rom(offs_t offset);
void write_to_pfm(offs_t offset, uint8_t data);
int m_boot_rom;
int m_pfm_bank;
bool m_pfm_output_enable;
int m_pbox_prefix;
// SRAM access
int m_sram_mask;
int m_sram_val;
@ -271,29 +210,40 @@ protected:
// Ready line to the CPU
devcb_write_line m_ready;
// Keyboard interrupt
devcb_write_line m_keyint;
// Counter for the wait states.
int m_waitcount;
int m_video_waitcount;
// Keyboard support
uint16_t m_keyboard_shift_reg;
line_state m_keyboard_last_clock;
line_state m_keyboard_data_in;
bool m_shift_reg_enabled;
void shift_reg_changed();
// Devices
required_device<mm58274c_device> m_clock;
required_device<tms9995_device> m_cpu;
required_device<sn76496_base_device> m_sound;
required_device<v9938_device> m_video;
required_device<mm58274c_device> m_rtc;
required_device<ram_device> m_sram;
required_device<ram_device> m_dram;
required_device<bus::ti99::peb::peribox_device> m_peribox;
required_device<at29c040_device> m_pfm512;
required_device<at29c040a_device> m_pfm512a;
required_device<sn76496_base_device> m_sound;
required_device<bus::ti99::internal::geneve_keyboard_device> m_keyboard;
required_device<v9938_device> m_video;
required_device<bus::ti99::peb::peribox_device> m_peribox;
uint8_t* m_eprom;
required_device<ram_device> m_sram;
required_device<ram_device> m_dram;
required_device<pc_kbdc_device> m_keyb_conn;
};
class genmod_mapper_device : public geneve_mapper_device
class genmod_gate_array_device : public geneve_gate_array_device
{
public:
genmod_mapper_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
genmod_gate_array_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
void decode_mod(decdata* dec) override;
void device_reset() override;
DECLARE_INPUT_CHANGED_MEMBER( setgm_changed );
@ -306,8 +256,7 @@ private:
} } } // end namespace bus::ti99::internal
DECLARE_DEVICE_TYPE_NS(GENEVE_KEYBOARD, bus::ti99::internal, geneve_keyboard_device)
DECLARE_DEVICE_TYPE_NS(GENEVE_MAPPER, bus::ti99::internal, geneve_mapper_device)
DECLARE_DEVICE_TYPE_NS(GENMOD_MAPPER, bus::ti99::internal, genmod_mapper_device)
DECLARE_DEVICE_TYPE_NS(GENEVE_GATE_ARRAY, bus::ti99::internal, geneve_gate_array_device)
DECLARE_DEVICE_TYPE_NS(GENMOD_GATE_ARRAY, bus::ti99::internal, genmod_gate_array_device)
#endif // MAME_BUS_TI99_INTERNAL_GENBOARD_H

View File

@ -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);
}
}

View File

@ -0,0 +1,89 @@
// license:BSD-3-Clause
// copyright-holders:Michael Zapf
/**********************************************************************
Geneve 9640 101-key XT/AT keyboard (High-level emulation)
*********************************************************************/
#ifndef MAME_BUS_TI99_INTERNAL_GENKBD_H
#define MAME_BUS_TI99_INTERNAL_GENKBD_H
#pragma once
#include "bus/pc_kbd/pc_kbdc.h"
#define STR_KBD_GENEVE_XT_101_HLE "geneve_kb_101"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> geneve_xt_101_hle_keyboard_device
class geneve_xt_101_hle_keyboard_device : public device_t, public device_pc_kbd_interface
{
public:
// construction/destruction
geneve_xt_101_hle_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
DECLARE_WRITE_LINE_MEMBER( reset_line );
protected:
// device-level overrides
void device_start() override;
void device_reset() override;
ioport_constructor device_input_ports() const override;
// device_pc_kbd_interface overrides
DECLARE_WRITE_LINE_MEMBER( clock_write ) override;
DECLARE_WRITE_LINE_MEMBER( data_write ) override;
private:
emu_timer *m_poll_timer;
emu_timer *m_send_timer;
void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
static constexpr unsigned KEYQUEUESIZE = 256;
static constexpr unsigned MAXKEYMSGLENGTH = 10;
static constexpr unsigned KEYAUTOREPEATDELAY = 30;
static constexpr unsigned KEYAUTOREPEATRATE = 6;
void poll();
void send_key();
void post_in_key_queue(int key);
required_ioport_array<8> m_keys;
int m_queue_length;
int m_queue_head;
uint8_t m_queue[KEYQUEUESIZE];
uint32_t m_key_state_save[4];
int m_autorepeat_code;
int m_autorepeat_timer;
bool m_fake_shift_state;
bool m_fake_unshift_state;
bool m_left_shift;
bool m_right_shift;
bool m_left_ctrl;
bool m_right_ctrl;
bool m_left_alt;
bool m_altgr;
bool m_numlock;
bool m_resetting;
line_state m_clock_line;
line_state m_data_line;
int m_reset_timer;
int m_shift_reg;
int m_shift_count;
};
// device type definition
DECLARE_DEVICE_TYPE(KBD_GENEVE_XT_101_HLE, geneve_xt_101_hle_keyboard_device)
#endif // MAME_BUS_TI99_INTERNAL_GENKBD_H

View File

@ -190,23 +190,38 @@
#include "sound/sn76496.h"
#include "bus/ti99/internal/genboard.h"
#include "bus/ti99/internal/genkbd.h"
#include "bus/ti99/colorbus/colorbus.h"
#include "bus/ti99/joyport/joyport.h"
#include "bus/ti99/peb/peribox.h"
#include "bus/pc_kbd/keyboards.h"
#include "bus/pc_kbd/pc_kbdc.h"
#include "bus/pc_kbd/pcxt83.h"
#include "bus/pc_kbd/keytro.h"
#include "speaker.h"
#define LOG_WARN (1U<<1)
#define LOG_READY (1U<<2)
#define LOG_LINES (1U<<3)
#define LOG_CRU (1U<<4)
#define LOG_CRUKEY (1U<<5)
// Minimum log should be settings and warnings
#define VERBOSE ( LOG_GENERAL | LOG_WARN )
#include "logmacro.h"
void geneve_xt_keyboards(device_slot_interface &device)
{
device.option_add(STR_KBD_KEYTRONIC_PC3270, PC_KBD_KEYTRONIC_PC3270);
device.option_add(STR_KBD_IBM_PC_XT_83, PC_KBD_IBM_PC_XT_83);
device.option_add(STR_KBD_GENEVE_XT_101_HLE, KBD_GENEVE_XT_101_HLE);
}
class geneve_state : public driver_device
{
public:
@ -214,11 +229,11 @@ public:
: driver_device(mconfig, type, tag),
m_cpu(*this, "maincpu"),
m_tms9901(*this, TI_TMS9901_TAG),
m_keyboard(*this, GENEVE_KEYBOARD_TAG),
m_mapper(*this, GENEVE_MAPPER_TAG),
m_gatearray(*this, GENEVE_GATE_ARRAY_TAG),
m_peribox(*this, TI_PERIBOX_TAG),
m_joyport(*this, TI_JOYPORT_TAG),
m_colorbus(*this, COLORBUS_TAG),
m_kbdconn(*this, GENEVE_KEYBOARD_CONN_TAG),
m_left_button(0)
{
}
@ -240,9 +255,13 @@ private:
DECLARE_WRITE_LINE_MEMBER(VDP_reset);
DECLARE_WRITE_LINE_MEMBER(joystick_select);
DECLARE_WRITE_LINE_MEMBER(extbus_wait_states);
DECLARE_WRITE_LINE_MEMBER(keyboard_reset);
DECLARE_WRITE_LINE_MEMBER(video_wait_states);
DECLARE_WRITE_LINE_MEMBER(left_mouse_button);
DECLARE_WRITE_LINE_MEMBER(keyboard_clock_line);
DECLARE_WRITE_LINE_MEMBER(keyboard_data_line);
DECLARE_WRITE_LINE_MEMBER(clock_out);
void external_operation(offs_t offset, uint8_t data);
@ -253,16 +272,17 @@ private:
required_device<tms9995_device> m_cpu;
required_device<tms9901_device> m_tms9901;
required_device<bus::ti99::internal::geneve_keyboard_device> m_keyboard;
required_device<bus::ti99::internal::geneve_mapper_device> m_mapper;
required_device<bus::ti99::peb::peribox_device> m_peribox;
required_device<bus::ti99::joyport::joyport_device> m_joyport;
required_device<bus::ti99::internal::geneve_gate_array_device> m_gatearray;
required_device<bus::ti99::peb::peribox_device> m_peribox;
required_device<bus::ti99::joyport::joyport_device> m_joyport;
required_device<bus::ti99::colorbus::v9938_colorbus_device> m_colorbus;
required_device<pc_kbdc_device> m_kbdconn;
DECLARE_WRITE_LINE_MEMBER( inta );
DECLARE_WRITE_LINE_MEMBER( intb );
DECLARE_WRITE_LINE_MEMBER( ext_ready );
DECLARE_WRITE_LINE_MEMBER( mapper_ready );
DECLARE_WRITE_LINE_MEMBER( keyboard_int );
virtual void machine_start() override;
virtual void machine_reset() override;
@ -291,12 +311,12 @@ private:
void geneve_state::memmap(address_map &map)
{
map(0x0000, 0xffff).rw(GENEVE_MAPPER_TAG, FUNC(bus::ti99::internal::geneve_mapper_device::readm), FUNC(bus::ti99::internal::geneve_mapper_device::writem));
map(0x0000, 0xffff).rw(GENEVE_GATE_ARRAY_TAG, FUNC(bus::ti99::internal::geneve_gate_array_device::readm), FUNC(bus::ti99::internal::geneve_gate_array_device::writem));
}
void geneve_state::memmap_setaddress(address_map &map)
{
map(0x0000, 0xffff).w(GENEVE_MAPPER_TAG, FUNC(bus::ti99::internal::geneve_mapper_device::setaddress));
map(0x0000, 0xffff).w(GENEVE_GATE_ARRAY_TAG, FUNC(bus::ti99::internal::geneve_gate_array_device::setaddress));
}
/*
@ -316,7 +336,7 @@ void geneve_state::crumap(address_map &map)
static INPUT_PORTS_START(geneve_common)
PORT_START( "BOOTROM" )
PORT_CONFNAME( 0x03, GENEVE_EPROM, "Boot from" ) PORT_CHANGED_MEMBER(GENEVE_MAPPER_TAG, bus::ti99::internal::geneve_mapper_device, settings_changed, 3)
PORT_CONFNAME( 0x03, GENEVE_EPROM, "Boot from" ) PORT_CHANGED_MEMBER(GENEVE_GATE_ARRAY_TAG, bus::ti99::internal::geneve_gate_array_device, settings_changed, 3)
PORT_CONFSETTING( GENEVE_EPROM, "EPROM" )
PORT_CONFSETTING( GENEVE_PFM512, "PFM 512" )
PORT_CONFSETTING( GENEVE_PFM512A, "PFM 512A" )
@ -343,10 +363,10 @@ static INPUT_PORTS_START(genmod)
PORT_INCLUDE(geneve_common)
PORT_START( "GENMODDIPS" )
PORT_DIPNAME( GENEVE_GM_TURBO, 0x00, "Genmod Turbo mode") PORT_CHANGED_MEMBER(GENEVE_MAPPER_TAG, bus::ti99::internal::genmod_mapper_device, setgm_changed, 1)
PORT_DIPNAME( GENEVE_GM_TURBO, 0x00, "Genmod Turbo mode") PORT_CHANGED_MEMBER(GENEVE_GATE_ARRAY_TAG, bus::ti99::internal::genmod_gate_array_device, setgm_changed, 1)
PORT_CONFSETTING( 0x00, DEF_STR( Off ))
PORT_CONFSETTING( GENEVE_GM_TURBO, DEF_STR( On ))
PORT_DIPNAME( GENEVE_GM_TIM, GENEVE_GM_TIM, "Genmod TI mode") PORT_CHANGED_MEMBER(GENEVE_MAPPER_TAG, bus::ti99::internal::genmod_mapper_device, setgm_changed, 2)
PORT_DIPNAME( GENEVE_GM_TIM, GENEVE_GM_TIM, "Genmod TI mode") PORT_CHANGED_MEMBER(GENEVE_GATE_ARRAY_TAG, bus::ti99::internal::genmod_gate_array_device, setgm_changed, 2)
PORT_CONFSETTING( 0x00, DEF_STR( Off ))
PORT_CONFSETTING( GENEVE_GM_TIM, DEF_STR( On ))
@ -389,36 +409,36 @@ void geneve_state::cruwrite(offs_t offset, uint8_t data)
LOGMASKED(LOG_CRU, "Set capslock flag = %02x\n", data);
break;
case 8:
LOGMASKED(LOG_CRU, "Set keyboard clock flag = %02x\n", data);
m_keyboard->clock_control((data!=0)? ASSERT_LINE : CLEAR_LINE);
LOGMASKED(LOG_CRUKEY, "Set keyboard clock = %02x\n", data);
m_gatearray->set_keyboard_clock(data);
break;
case 9:
LOGMASKED(LOG_CRU, "Set keyboard scan flag = %02x\n", data);
m_keyboard->send_scancodes((data!=0)? ASSERT_LINE : CLEAR_LINE);
LOGMASKED(LOG_CRUKEY, "Enable keyboard shift reg = %02x\n", data);
m_gatearray->enable_shift_register(data);
break;
case 10:
LOGMASKED(LOG_CRU, "Geneve mode = %02x\n", data);
m_mapper->set_geneve_mode(data!=0);
m_gatearray->set_geneve_mode(data!=0);
break;
case 11:
LOGMASKED(LOG_CRU, "Direct mode = %02x\n", data);
m_mapper->set_direct_mode(data!=0);
m_gatearray->set_direct_mode(data!=0);
break;
case 12:
LOGMASKED(LOG_CRU, "Cartridge size 8K = %02x\n", data);
m_mapper->set_cartridge_size((data!=0)? 0x2000 : 0x4000);
m_gatearray->set_cartridge_size((data!=0)? 0x2000 : 0x4000);
break;
case 13:
LOGMASKED(LOG_CRU, "Cartridge writable 6000 = %02x\n", data);
m_mapper->set_cartridge_writable(0x6000, (data!=0));
m_gatearray->set_cartridge_writable(0x6000, (data!=0));
break;
case 14:
LOGMASKED(LOG_CRU, "Cartridge writable 7000 = %02x\n", data);
m_mapper->set_cartridge_writable(0x7000, (data!=0));
m_gatearray->set_cartridge_writable(0x7000, (data!=0));
break;
case 15:
LOGMASKED(LOG_CRU, "Extra wait states = %02x\n", data==0);
m_mapper->set_extra_waitstates(data==0); // let's use the inverse semantics
m_gatearray->set_extra_waitstates(data==0); // let's use the inverse semantics
break;
default:
LOGMASKED(LOG_WARN, "set CRU address %04x=%02x ignored\n", addroff, data);
@ -531,6 +551,7 @@ WRITE_LINE_MEMBER( geneve_state::joystick_select )
m_joyport->write_port((state==ASSERT_LINE)? 1:2);
}
/*
Write external mem cycles (0=long, 1=short)
*/
@ -546,10 +567,18 @@ WRITE_LINE_MEMBER( geneve_state::extbus_wait_states )
WRITE_LINE_MEMBER( geneve_state::video_wait_states )
{
LOGMASKED(LOG_LINES, "Video wait states set to %d\n", state);
m_mapper->set_video_waitstates(state==ASSERT_LINE);
m_gatearray->set_video_waitstates(state==ASSERT_LINE);
m_video_wait = (state!=0)? ASSERT_LINE : CLEAR_LINE;
}
/*
Keyboard reset (active low).
*/
WRITE_LINE_MEMBER( geneve_state::keyboard_reset )
{
LOGMASKED(LOG_CRUKEY, "Keyboard reset %d\n", state);
}
/*
Called by the 9901 core whenever the state of INTREQ and IC0-3 changes.
As with the TI-99/4A, the interrupt level is delivered as the offset,
@ -635,7 +664,7 @@ void geneve_state::external_operation(offs_t offset, uint8_t data)
WRITE_LINE_MEMBER( geneve_state::clock_out )
{
m_tms9901->phi_line(state);
m_mapper->clock_in(state);
m_gatearray->clock_in(state);
}
void geneve_state::init_geneve()
@ -679,9 +708,10 @@ void geneve_state::geneve(machine_config &config)
{
geneve_common(config);
// Mapper
GENEVE_MAPPER(config, m_mapper, 0);
m_mapper->ready_cb().set(FUNC(geneve_state::mapper_ready));
// Gate array
GENEVE_GATE_ARRAY(config, m_gatearray, 0);
m_gatearray->ready_cb().set(FUNC(geneve_state::mapper_ready));
m_gatearray->kbdint_cb().set(FUNC(geneve_state::keyboard_interrupt));
// Peripheral expansion box (Geneve composition)
TI99_PERIBOX_GEN(config, m_peribox, 0);
@ -695,8 +725,9 @@ void geneve_state::genmod(machine_config &config)
geneve_common(config);
// Mapper
GENMOD_MAPPER(config, m_mapper, 0);
m_mapper->ready_cb().set(FUNC(geneve_state::mapper_ready));
GENMOD_GATE_ARRAY(config, m_gatearray, 0);
m_gatearray->ready_cb().set(FUNC(geneve_state::mapper_ready));
m_gatearray->kbdint_cb().set(FUNC(geneve_state::keyboard_interrupt));
// Peripheral expansion box (Geneve composition with Genmod and plugged-in Memex)
TI99_PERIBOX_GENMOD(config, m_peribox, 0);
@ -737,12 +768,12 @@ void geneve_state::geneve_common(machine_config &config)
m_tms9901->p_out_cb(0).set(FUNC(geneve_state::peripheral_bus_reset));
m_tms9901->p_out_cb(1).set(FUNC(geneve_state::VDP_reset));
m_tms9901->p_out_cb(2).set(FUNC(geneve_state::joystick_select));
m_tms9901->p_out_cb(4).set(GENEVE_MAPPER_TAG, FUNC(bus::ti99::internal::geneve_mapper_device::pfm_select_lsb));
m_tms9901->p_out_cb(5).set(GENEVE_MAPPER_TAG, FUNC(bus::ti99::internal::geneve_mapper_device::pfm_output_enable));
m_tms9901->p_out_cb(6).set(GENEVE_KEYBOARD_TAG, FUNC(bus::ti99::internal::geneve_keyboard_device::reset_line));
m_tms9901->p_out_cb(4).set(GENEVE_GATE_ARRAY_TAG, FUNC(bus::ti99::internal::geneve_gate_array_device::pfm_select_lsb));
m_tms9901->p_out_cb(5).set(GENEVE_GATE_ARRAY_TAG, FUNC(bus::ti99::internal::geneve_gate_array_device::pfm_output_enable));
m_tms9901->p_out_cb(6).set(FUNC(geneve_state::keyboard_reset));
m_tms9901->p_out_cb(7).set(FUNC(geneve_state::extbus_wait_states));
m_tms9901->p_out_cb(9).set(FUNC(geneve_state::video_wait_states));
m_tms9901->p_out_cb(13).set(GENEVE_MAPPER_TAG, FUNC(bus::ti99::internal::geneve_mapper_device::pfm_select_msb));
m_tms9901->p_out_cb(13).set(GENEVE_GATE_ARRAY_TAG, FUNC(bus::ti99::internal::geneve_gate_array_device::pfm_select_msb));
m_tms9901->intreq_cb().set(FUNC(geneve_state::tms9901_interrupt));
// Clock
@ -754,8 +785,12 @@ void geneve_state::geneve_common(machine_config &config)
soundgen.ready_cb().set(FUNC(geneve_state::ext_ready));
soundgen.add_route(ALL_OUTPUTS, "sound_out", 0.75);
// User interface devices
GENEVE_KEYBOARD(config, m_keyboard, 0).int_cb().set(FUNC(geneve_state::keyboard_interrupt));
// User interface devices: PC-style keyboard, joystick port, mouse connector
PC_KBDC(config, m_kbdconn, 0);
PC_KBDC_SLOT(config, "kbd", geneve_xt_keyboards, STR_KBD_GENEVE_XT_101_HLE).set_pc_kbdc_slot(m_kbdconn);
m_kbdconn->out_clock_cb().set(GENEVE_GATE_ARRAY_TAG, FUNC(bus::ti99::internal::geneve_gate_array_device::kbdclk));
m_kbdconn->out_data_cb().set(GENEVE_GATE_ARRAY_TAG, FUNC(bus::ti99::internal::geneve_gate_array_device::kbddata));
TI99_JOYPORT(config, m_joyport, 0, ti99_joyport_options_plain, "twinjoy");
V9938_COLORBUS(config, m_colorbus, 0, ti99_colorbus_options, nullptr);
m_colorbus->extra_button_cb().set(FUNC(geneve_state::left_mouse_button));