summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Michael Zapf <github@mizapf.de>2019-09-17 17:41:19 +0200
committer Michael Zapf <github@mizapf.de>2019-09-17 17:47:14 +0200
commit4495c351139f13d46e087c448e3b2418491485e2 (patch)
tree7b26831d3a162de6105ed419a0def5f6d51b5156
parentec4b8b2fa4db449ac7e2a683db953e93026c04cc (diff)
geneve: Add PC KBD connector; allow for using XT keyboards in place of the currently high-level emulated XT/AT 101 keyboard.
-rw-r--r--scripts/src/bus.lua2
-rw-r--r--src/devices/bus/pc_kbd/pc_kbdc.cpp19
-rw-r--r--src/devices/bus/pc_kbd/pc_kbdc.h4
-rw-r--r--src/devices/bus/ti99/internal/genboard.cpp809
-rw-r--r--src/devices/bus/ti99/internal/genboard.h193
-rw-r--r--src/devices/bus/ti99/internal/genkbd.cpp648
-rw-r--r--src/devices/bus/ti99/internal/genkbd.h89
-rw-r--r--src/mame/drivers/geneve.cpp103
8 files changed, 1119 insertions, 748 deletions
diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua
index 60a2223cbf8..88d02bb592e 100644
--- a/scripts/src/bus.lua
+++ b/scripts/src/bus.lua
@@ -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",
diff --git a/src/devices/bus/pc_kbd/pc_kbdc.cpp b/src/devices/bus/pc_kbd/pc_kbdc.cpp
index 5e99056adbe..0b308b57f96 100644
--- a/src/devices/bus/pc_kbd/pc_kbdc.cpp
+++ b/src/devices/bus/pc_kbd/pc_kbdc.cpp
@@ -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);
}
diff --git a/src/devices/bus/pc_kbd/pc_kbdc.h b/src/devices/bus/pc_kbd/pc_kbdc.h
index ff1168c314c..34161c23c5a 100644
--- a/src/devices/bus/pc_kbd/pc_kbdc.h
+++ b/src/devices/bus/pc_kbd/pc_kbdc.h
@@ -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;
diff --git a/src/devices/bus/ti99/internal/genboard.cpp b/src/devices/bus/ti99/internal/genboard.cpp
index 91c5c8d127e..773aa0ef217 100644
--- a/src/devices/bus/ti99/internal/genboard.cpp
+++ b/src/devices/bus/ti99/internal/genboard.cpp
@@ -1,13 +1,52 @@
// license:LGPL-2.1+
// copyright-holders:Michael Zapf
/***************************************************************************
- Geneve 9640 mapper and more components
+ Geneve 9640 Gate Array and more components
- This file contains 2 classes:
- - mapper: main function of the Gate Array on the Geneve board. Maps logical
- memory accesses to a wider address space using map registers.
- - keyboard: an implementation of a XT-style keyboard. This should be dropped
- and replaced by a proper XT keyboard implementation.
+ This file contains the emulation of the gate array and of the PAL chip
+ that is used to control wait state generation.
+
+ Pins of the Gate Array:
+
+ in: AMC, AMB, AMA, A0..A15: Address bus
+ in: CLKOUT
+ in: IAQ/HOLDA
+ in?: NMI*
+ in?: RESET*
+
+ i/o: D0..D7: Data bus
+
+ out: KBDINT*: Keyboard interrupt
+ i/o: KBDCLK: Keyboard clock line
+ i/o: KBDDATA: Keyboard data line
+
+ out: SNDEN*: Sound chip select
+ out: RTCEN*: RTC chip select
+
+ out: RAS*
+ out: CAS* (2x for two banks)
+ out: DRA0..DRA8: Address bus for DRAM (1+18 bit = 512K)
+
+ out: PSIEN*: 9901 enable
+ out: CRUCLK*
+
+ out: CSW*: v9938 write
+ out: CSR*: v9938 read
+
+ out: RAMENX*: SRAM expansion
+ out: RAMEN*: SRAM
+ out: ROMEN*: EPROM
+ out: AB0, AB1, AB2: Mapped address bits
+ in: DBIN*
+ ? : ABUS* / HOLDA
+ out: DBIN
+ ? : HOLD*
+ ? : READY*
+ out: DBEN*: External data bus enable
+ in: MEMEN*
+ in: SNDRDY
+ out: WE* / CRUCLK
+ out: PhiCLK: System clock for 9901
Onboard SRAM configuration:
There is an adjustable SRAM configuration on board, representing the
@@ -221,6 +260,7 @@
#define LOG_VIDEOWS (1U<<9)
#define LOG_PFM (1U<<10)
#define LOG_DECODE (1U<<11)
+#define LOG_INVADDR (1U<<12)
// Minimum log should be settings and warnings
#define VERBOSE ( LOG_SETTING | LOG_WARN )
@@ -228,14 +268,15 @@
#include "genboard.h"
#include "logmacro.h"
-DEFINE_DEVICE_TYPE_NS(GENEVE_KEYBOARD, bus::ti99::internal, geneve_keyboard_device, "geneve_keyboard", "Geneve XT-style keyboard")
-DEFINE_DEVICE_TYPE_NS(GENEVE_MAPPER, bus::ti99::internal, geneve_mapper_device, "geneve_mapper", "Geneve Gate Array")
-DEFINE_DEVICE_TYPE_NS(GENMOD_MAPPER, bus::ti99::internal, genmod_mapper_device, "genmod_mapper", "Geneve Mod Gate Array")
+DEFINE_DEVICE_TYPE_NS(GENEVE_GATE_ARRAY, bus::ti99::internal, geneve_gate_array_device, "geneve_gate_array", "Geneve Gate Array")
+DEFINE_DEVICE_TYPE_NS(GENMOD_GATE_ARRAY, bus::ti99::internal, genmod_gate_array_device, "genmod_gate_array", "Geneve Mod Gate Array")
namespace bus { namespace ti99 { namespace internal {
-geneve_mapper_device::geneve_mapper_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, type, tag, owner, clock), m_gromwaddr_LSB(false),
+geneve_gate_array_device::geneve_gate_array_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock),
+ m_boot_rom(0),
+ m_gromwaddr_LSB(false),
m_gromraddr_LSB(false),
m_grom_address(0),
m_video_waitstates(false),
@@ -249,36 +290,40 @@ geneve_mapper_device::geneve_mapper_device(const machine_config &mconfig, device
m_cartridge_secondpage(false),
m_cartridge6_writable(false),
m_cartridge7_writable(false),
- m_boot_rom(0),
m_pfm_bank(0),
m_pfm_output_enable(false),
m_sram_mask(0),
m_sram_val(0),
m_ready(*this),
+ m_keyint(*this),
m_waitcount(0),
m_video_waitcount(0),
- m_clock(*owner, GENEVE_CLOCK_TAG),
+ m_keyboard_shift_reg(0),
+ m_keyboard_last_clock(CLEAR_LINE),
+ m_keyboard_data_in(CLEAR_LINE),
+ m_shift_reg_enabled(false),
m_cpu(*owner, "maincpu"),
- m_pfm512(*owner, GENEVE_PFM512_TAG),
- m_pfm512a(*owner, GENEVE_PFM512A_TAG),
m_sound(*owner, TI_SOUNDCHIP_TAG),
- m_keyboard(*owner, GENEVE_KEYBOARD_TAG),
m_video(*owner, TI_VDP_TAG),
- m_peribox(*owner, TI_PERIBOX_TAG),
+ m_rtc(*owner, GENEVE_CLOCK_TAG),
m_sram(*this, GENEVE_SRAM_PAR_TAG),
- m_dram(*this, GENEVE_DRAM_PAR_TAG)
+ m_dram(*this, GENEVE_DRAM_PAR_TAG),
+ m_peribox(*owner, TI_PERIBOX_TAG),
+ m_pfm512(*owner, GENEVE_PFM512_TAG),
+ m_pfm512a(*owner, GENEVE_PFM512A_TAG),
+ m_keyb_conn(*owner, GENEVE_KEYBOARD_CONN_TAG)
{
}
-geneve_mapper_device::geneve_mapper_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : geneve_mapper_device(mconfig, GENEVE_MAPPER, tag, owner, clock)
+geneve_gate_array_device::geneve_gate_array_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : geneve_gate_array_device(mconfig, GENEVE_GATE_ARRAY, tag, owner, clock)
{
m_eprom = nullptr;
m_pbox_prefix = 0x070000;
}
-genmod_mapper_device::genmod_mapper_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : geneve_mapper_device(mconfig, GENMOD_MAPPER, tag, owner, clock),
+genmod_gate_array_device::genmod_gate_array_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : geneve_gate_array_device(mconfig, GENMOD_GATE_ARRAY, tag, owner, clock),
m_gm_timode(false),
m_turbo(false)
{
@@ -286,13 +331,13 @@ genmod_mapper_device::genmod_mapper_device(const machine_config &mconfig, const
m_pbox_prefix = 0x170000;
}
-INPUT_CHANGED_MEMBER( geneve_mapper_device::settings_changed )
+INPUT_CHANGED_MEMBER( geneve_gate_array_device::settings_changed )
{
// Used when switching the boot ROMs during runtime, especially the PFM
m_boot_rom = newval;
}
-INPUT_CHANGED_MEMBER( genmod_mapper_device::setgm_changed )
+INPUT_CHANGED_MEMBER( genmod_gate_array_device::setgm_changed )
{
int number = int(param&0x03);
int value = newval;
@@ -329,7 +374,7 @@ INPUT_CHANGED_MEMBER( genmod_mapper_device::setgm_changed )
within the gate array. Unlike with real GROMs, no address wrapping occurs,
and the complete 64K space is available.
*/
-uint8_t geneve_mapper_device::read_grom(offs_t offset)
+uint8_t geneve_gate_array_device::read_grom(offs_t offset)
{
uint8_t reply;
if (offset & 0x0002)
@@ -364,7 +409,7 @@ uint8_t geneve_mapper_device::read_grom(offs_t offset)
Simulates GROM. The real Geneve does not use GROMs but simulates them
within the gate array.
*/
-void geneve_mapper_device::write_grom(offs_t offset, uint8_t data)
+void geneve_gate_array_device::write_grom(offs_t offset, uint8_t data)
{
if (offset & 0x0002)
{
@@ -393,7 +438,7 @@ void geneve_mapper_device::write_grom(offs_t offset, uint8_t data)
}
}
-void geneve_mapper_device::set_wait(int min)
+void geneve_gate_array_device::set_wait(int min)
{
if (m_extra_waitstates && min < 2) min = 2;
@@ -411,38 +456,38 @@ void geneve_mapper_device::set_wait(int min)
}
}
-void geneve_mapper_device::set_video_waitcount(int min)
+void geneve_gate_array_device::set_video_waitcount(int min)
{
if (m_debug_no_ws) return;
m_video_waitcount = min;
}
-void geneve_mapper_device::set_geneve_mode(bool geneve)
+void geneve_gate_array_device::set_geneve_mode(bool geneve)
{
LOGMASKED(LOG_SETTING, "Setting Geneve mode = %d\n", geneve);
m_geneve_mode = geneve;
}
-void geneve_mapper_device::set_direct_mode(bool direct)
+void geneve_gate_array_device::set_direct_mode(bool direct)
{
LOGMASKED(LOG_SETTING, "Setting direct mode = %d\n", direct);
m_direct_mode = direct;
}
-void geneve_mapper_device::set_cartridge_size(int size)
+void geneve_gate_array_device::set_cartridge_size(int size)
{
LOGMASKED(LOG_SETTING, "Setting cartridge size to %d\n", size);
m_cartridge_size = size;
}
-void geneve_mapper_device::set_cartridge_writable(int base, bool write)
+void geneve_gate_array_device::set_cartridge_writable(int base, bool write)
{
LOGMASKED(LOG_SETTING, "Cartridge %04x space writable = %d\n", base, write);
if (base==0x6000) m_cartridge6_writable = write;
else m_cartridge7_writable = write;
}
-void geneve_mapper_device::set_video_waitstates(bool wait)
+void geneve_gate_array_device::set_video_waitstates(bool wait)
{
// Tends to be called repeatedly
if (m_video_waitstates != wait)
@@ -452,12 +497,105 @@ void geneve_mapper_device::set_video_waitstates(bool wait)
m_video_waitstates = wait;
}
-void geneve_mapper_device::set_extra_waitstates(bool wait)
+void geneve_gate_array_device::set_extra_waitstates(bool wait)
{
LOGMASKED(LOG_SETTING, "Setting extra waitstates = %d\n", wait);
m_extra_waitstates = wait;
}
+/******************************************************************
+ Keyboard support
+ XT protocol:
+
+ Original XT: 0 1 bit0 bit1 bit2 bit3 bit4 bit5 bit6 bit7
+ Some clones: 1 bit0 bit1 bit2 bit3 bit4 bit5 bit6 bit7
+
+ bit0 = LSB, bit7 = MSB
+
+ For now we assume that the Geneve needs the original XT keyboard.
+
+ We can use the start 1 bit to control bit reception. When it reaches the
+ rightmost position, we suspend transfer and raise the interrupt.
+
+ With the flagging of the interrupt, the data line towards the keyboard
+ is held low until the interrupt is cleared. This is done by clearing the
+ shift register by setting the CRU address 1EF2 to 0.
+
+ Note that lowering the clock line to 0 for more than 20ms will trigger
+ a keyboard reset.
+
+******************************************************************/
+
+/*
+ Pull down or release the clock line.
+ Called by setting CRU bit 1EF0 to 0 or 1.
+*/
+WRITE_LINE_MEMBER( geneve_gate_array_device::set_keyboard_clock)
+{
+ m_keyb_conn->clock_write_from_mb(state);
+}
+
+/*
+ Enable the shift register. Setting to 0 will clear the register and
+ lock it. At the same time, the interrupt is cleared, and the data line
+ is released. If further scancodes are expected, the shift register should
+ immediately be enabled again.
+
+ Called by setting CRU bit 1EF2 to 0 or 1
+*/
+WRITE_LINE_MEMBER( geneve_gate_array_device::enable_shift_register)
+{
+ m_shift_reg_enabled = (state==ASSERT_LINE);
+
+ if (!m_shift_reg_enabled)
+ {
+ LOGMASKED(LOG_KEYBOARD, "Clear shift register, disable\n");
+ m_keyboard_shift_reg = 0;
+ shift_reg_changed();
+ }
+ else
+ LOGMASKED(LOG_KEYBOARD, "Enable shift register\n");
+}
+
+void geneve_gate_array_device::shift_reg_changed()
+{
+ // The level of the data line is the inverse of the rightmost bit of
+ // the shift register. This means that once the start bit reaches that
+ // position, it will pull down the data line and stop the transfer.
+ m_keyb_conn->data_write_from_mb(1 - (m_keyboard_shift_reg & 1));
+ m_keyint((m_keyboard_shift_reg & 1)? ASSERT_LINE : CLEAR_LINE);
+ if (m_keyboard_shift_reg & 1)
+ LOGMASKED(LOG_KEYBOARD, "Scan code complete; raise interrupt, hold down data line\n");
+ else
+ LOGMASKED(LOG_KEYBOARD, "Clear keyboard interrupt, release data line\n");
+}
+
+/*
+ Incoming keyboard strobe. When 0, push the current data line level into
+ the shift register at the leftmost position.
+*/
+WRITE_LINE_MEMBER( geneve_gate_array_device::kbdclk )
+{
+ LOGMASKED(LOG_KEYBOARD, "Keyboard clock: %d\n", state);
+ bool clock_falling_edge = (m_keyboard_last_clock == ASSERT_LINE && state == CLEAR_LINE);
+
+ if (m_shift_reg_enabled && clock_falling_edge)
+ {
+ m_keyboard_shift_reg = (m_keyboard_shift_reg>>1) | (m_keyboard_data_in? 0x100 : 0x00);
+ LOGMASKED(LOG_KEYBOARD, "Shift register = %02x\n", m_keyboard_shift_reg>>1);
+ shift_reg_changed();
+ }
+ m_keyboard_last_clock = (line_state)state;
+}
+
+/*
+ Latch the value of the incoming data line.
+*/
+WRITE_LINE_MEMBER( geneve_gate_array_device::kbddata )
+{
+ LOGMASKED(LOG_KEYBOARD, "Keyboard data: %d\n", state);
+ m_keyboard_data_in = (line_state)state;
+}
/************************************************************************
Called by the address map
@@ -468,7 +606,7 @@ void geneve_mapper_device::set_extra_waitstates(bool wait)
SETADDRESS method, and we re-use the values stored there to quickly
access the appropriate component.
*/
-uint8_t geneve_mapper_device::readm(offs_t offset)
+uint8_t geneve_gate_array_device::readm(offs_t offset)
{
uint8_t value = 0;
@@ -525,8 +663,8 @@ uint8_t geneve_mapper_device::readm(offs_t offset)
case MLKEY:
// key
- if (!machine().side_effects_disabled()) value = m_keyboard->get_recent_key();
- LOGMASKED(LOG_READ, "Read keyboard -> %02x\n", value);
+ value = m_keyboard_shift_reg>>1;
+ LOGMASKED(LOG_KEYBOARD, "Read keyboard -> %02x\n", value);
break;
case MLCLOCK:
@@ -538,7 +676,7 @@ uint8_t geneve_mapper_device::readm(offs_t offset)
// Needs more investigation. We might as well ignore this,
// as the high nibble is obviously undefined and takes some past
// value floating around.
- value = m_clock->read(dec->offset & 0x000f);
+ value = m_rtc->read(dec->offset & 0x000f);
if (m_geneve_mode) value |= 0xf0;
else value |= ((dec->offset & 0x000f)==0x000f)? 0x20 : 0x10;
LOGMASKED(LOG_READ, "Read clock %04x -> %02x\n", dec->offset, value);
@@ -582,7 +720,7 @@ uint8_t geneve_mapper_device::readm(offs_t offset)
}
else
{
- LOGMASKED(LOG_WARN, "Decoded as SRAM read, but no SRAM at %06x\n", dec->physaddr);
+ LOGMASKED(LOG_INVADDR, "Decoded as SRAM read, but no SRAM at %06x\n", dec->physaddr);
value = 0;
}
// Return in any case
@@ -605,7 +743,7 @@ uint8_t geneve_mapper_device::readm(offs_t offset)
return value;
}
-void geneve_mapper_device::writem(offs_t offset, uint8_t data)
+void geneve_gate_array_device::writem(offs_t offset, uint8_t data)
{
decdata *dec;
decdata debug;
@@ -666,7 +804,7 @@ void geneve_mapper_device::writem(offs_t offset, uint8_t data)
case MLCLOCK:
// clock
// ++++ ++++ ++++ ----
- m_clock->write(dec->offset & 0x000f, data);
+ m_rtc->write(dec->offset & 0x000f, data);
LOGMASKED(LOG_WRITE, "Write clock %04x <- %02x\n", offset, data);
break;
@@ -702,7 +840,7 @@ void geneve_mapper_device::writem(offs_t offset, uint8_t data)
// Ignore EPROM write (unless PFM)
if (m_boot_rom != GENEVE_EPROM) write_to_pfm(dec->physaddr, data);
else
- LOGMASKED(LOG_WARN, "Write EPROM %04x (%06x) <- %02x, ignored\n", offset, dec->physaddr, data);
+ LOGMASKED(LOG_INVADDR, "Write EPROM %04x (%06x) <- %02x, ignored\n", offset, dec->physaddr, data);
break;
case MPSRAM:
@@ -713,7 +851,7 @@ void geneve_mapper_device::writem(offs_t offset, uint8_t data)
}
else
{
- LOGMASKED(LOG_WARN, "Decoded as SRAM write, but no SRAM at %06x\n", dec->physaddr);
+ LOGMASKED(LOG_INVADDR, "Decoded as SRAM write, but no SRAM at %06x\n", dec->physaddr);
}
break;
@@ -730,7 +868,18 @@ void geneve_mapper_device::writem(offs_t offset, uint8_t data)
}
}
-void geneve_mapper_device::decode_logical(bool reading, geneve_mapper_device::decdata* dec)
+const geneve_gate_array_device::logentry_t geneve_gate_array_device::s_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" },
+};
+
+void geneve_gate_array_device::decode_logical(bool reading, geneve_gate_array_device::decdata* dec)
{
dec->function = MUNDEF;
dec->physaddr = m_pbox_prefix | dec->offset;
@@ -742,19 +891,19 @@ void geneve_mapper_device::decode_logical(bool reading, geneve_mapper_device::de
if (m_geneve_mode)
{
// Skip when genbase is 0
- if ((m_logmap[i].genbase != 0) && ((dec->offset & ~m_logmap[i].genmask) == m_logmap[i].genbase))
+ if ((s_logmap[i].genbase != 0) && ((dec->offset & ~s_logmap[i].genmask) == s_logmap[i].genbase))
break;
}
else
{
if (reading)
{
- if ((dec->offset & ~m_logmap[i].timask) == m_logmap[i].tibase)
+ if ((dec->offset & ~s_logmap[i].timask) == s_logmap[i].tibase)
break;
}
else
{
- if ((dec->offset & ~m_logmap[i].timask) == (m_logmap[i].tibase | m_logmap[i].writeoff))
+ if ((dec->offset & ~s_logmap[i].timask) == (s_logmap[i].tibase | s_logmap[i].writeoff))
break;
}
}
@@ -762,12 +911,12 @@ void geneve_mapper_device::decode_logical(bool reading, geneve_mapper_device::de
}
if (i != 7)
{
- LOGMASKED(LOG_DECODE, "Decoded as %s: %04x\n", m_logmap[i].description, dec->offset);
- dec->function = m_logmap[i].function;
+ LOGMASKED(LOG_DECODE, "Decoded as %s: %04x\n", s_logmap[i].description, dec->offset);
+ dec->function = s_logmap[i].function;
}
}
-void geneve_mapper_device::map_address(bool reading, geneve_mapper_device::decdata* dec)
+void geneve_gate_array_device::map_address(bool reading, geneve_gate_array_device::decdata* dec)
{
int logpage = (dec->offset & 0xe000) >> 13;
int physpage = 0;
@@ -812,22 +961,30 @@ void geneve_mapper_device::map_address(bool reading, geneve_mapper_device::decda
dec->physaddr = ((physpage << 13) | (dec->offset & 0x1fff)) & 0x1fffff;
}
-void geneve_mapper_device::decode_physical(geneve_mapper_device::decdata* dec)
+const geneve_gate_array_device::physentry_t geneve_gate_array_device::s_physmap[4] =
+{
+ { 0x000000, 0x07ffff, MPDRAM, 1, "DRAM" },
+ { 0x080000, 0x07ffff, MPEXP, 1, "on-board expansion" },
+ { 0x1e0000, 0x01ffff, MPEPROM, 0, "EPROM" },
+ { 0x180000, 0x07ffff, MPSRAM, 0, "SRAM" }
+};
+
+void geneve_gate_array_device::decode_physical(geneve_gate_array_device::decdata* dec)
{
dec->function = MUNDEF;
int i = 0;
while (i < 4)
{
- if ((dec->physaddr & ~m_physmap[i].mask) == m_physmap[i].base)
+ if ((dec->physaddr & ~s_physmap[i].mask) == s_physmap[i].base)
break;
i++;
}
if (i != 4)
{
- LOGMASKED(LOG_DECODE, "Decoded as %s: %06x\n", m_physmap[i].description, dec->physaddr);
- dec->function = m_physmap[i].function;
- dec->wait = m_physmap[i].wait;
+ LOGMASKED(LOG_DECODE, "Decoded as %s: %06x\n", s_physmap[i].description, dec->physaddr);
+ dec->function = s_physmap[i].function;
+ dec->wait = s_physmap[i].wait;
}
else
{
@@ -837,7 +994,7 @@ void geneve_mapper_device::decode_physical(geneve_mapper_device::decdata* dec)
}
}
-void genmod_mapper_device::decode_mod(geneve_mapper_device::decdata* dec)
+void genmod_gate_array_device::decode_mod(geneve_gate_array_device::decdata* dec)
{
// GenMod mode
// The TI Mode switch activates the DRAM on the board (1 WS)
@@ -854,7 +1011,7 @@ void genmod_mapper_device::decode_mod(geneve_mapper_device::decdata* dec)
/*
Boot ROM handling, from EPROM or PFM.
*/
-uint8_t geneve_mapper_device::boot_rom(offs_t offset)
+uint8_t geneve_gate_array_device::boot_rom(offs_t offset)
{
uint8_t value;
int pfmaddress = (offset & 0x01ffff) | (m_pfm_bank<<17);
@@ -881,7 +1038,7 @@ uint8_t geneve_mapper_device::boot_rom(offs_t offset)
return value;
}
-void geneve_mapper_device::write_to_pfm(offs_t offset, uint8_t data)
+void geneve_gate_array_device::write_to_pfm(offs_t offset, uint8_t data)
{
// Nota bene: The PFM must be write protected on startup, or the RESET
// of the 9995 will attempt to write the return vector into the flash EEPROM
@@ -907,7 +1064,7 @@ void geneve_mapper_device::write_to_pfm(offs_t offset, uint8_t data)
This decoding will later be used in the READ/WRITE member functions. Also,
we initiate wait state creation here.
*/
-void geneve_mapper_device::setaddress(offs_t address, uint8_t busctrl)
+void geneve_gate_array_device::setaddress(offs_t address, uint8_t busctrl)
{
LOGMASKED(LOG_DETAIL, "setaddress = %04x\n", address);
m_debug_no_ws = false;
@@ -944,7 +1101,7 @@ void geneve_mapper_device::setaddress(offs_t address, uint8_t busctrl)
affect the video access itself but become effective after the access; if
the code runs on the chip, these wait states are ignored.)
*/
-WRITE_LINE_MEMBER( geneve_mapper_device::clock_in )
+WRITE_LINE_MEMBER( geneve_gate_array_device::clock_in )
{
if (state==ASSERT_LINE)
{
@@ -1000,21 +1157,21 @@ WRITE_LINE_MEMBER( geneve_mapper_device::clock_in )
/*
PFM expansion: Setting the bank.
*/
-WRITE_LINE_MEMBER( geneve_mapper_device::pfm_select_lsb )
+WRITE_LINE_MEMBER( geneve_gate_array_device::pfm_select_lsb )
{
if (state==ASSERT_LINE) m_pfm_bank |= 1;
else m_pfm_bank &= 0xfe;
LOGMASKED(LOG_PFM, "Setting bank (l) = %d\n", m_pfm_bank);
}
-WRITE_LINE_MEMBER( geneve_mapper_device::pfm_select_msb )
+WRITE_LINE_MEMBER( geneve_gate_array_device::pfm_select_msb )
{
if (state==ASSERT_LINE) m_pfm_bank |= 2;
else m_pfm_bank &= 0xfd;
LOGMASKED(LOG_PFM, "Setting bank (u) = %d\n", m_pfm_bank);
}
-WRITE_LINE_MEMBER( geneve_mapper_device::pfm_output_enable )
+WRITE_LINE_MEMBER( geneve_gate_array_device::pfm_output_enable )
{
// Negative logic
m_pfm_output_enable = (state==CLEAR_LINE);
@@ -1025,9 +1182,10 @@ WRITE_LINE_MEMBER( geneve_mapper_device::pfm_output_enable )
// Common device lifecycle
//====================================================================
-void geneve_mapper_device::device_start()
+void geneve_gate_array_device::device_start()
{
- m_ready.resolve();
+ m_ready.resolve_safe();
+ m_keyint.resolve_safe();
m_geneve_mode = false;
m_direct_mode = true;
@@ -1060,7 +1218,7 @@ void geneve_mapper_device::device_start()
save_item(NAME(m_video_waitcount));
}
-void geneve_mapper_device::common_reset()
+void geneve_gate_array_device::common_reset()
{
m_extra_waitstates = false;
m_video_waitstates = true;
@@ -1092,7 +1250,7 @@ void geneve_mapper_device::common_reset()
LOGMASKED(LOG_SETTING, "Video RAM set to %d KiB\n", videoram / 1024);
}
-void geneve_mapper_device::device_reset()
+void geneve_gate_array_device::device_reset()
{
common_reset();
@@ -1121,7 +1279,7 @@ void geneve_mapper_device::device_reset()
}
}
-void genmod_mapper_device::device_reset()
+void genmod_gate_array_device::device_reset()
{
common_reset();
LOGMASKED(LOG_SETTING, "Using GenMod modification\n");
@@ -1129,521 +1287,6 @@ void genmod_mapper_device::device_reset()
m_gm_timode = ((machine().root_device().ioport("GENMODDIPS")->read() & GENEVE_GM_TIM)!=0);
}
-/****************************************************************************
- Keyboard support
-
- The XT keyboard interface is described in various places on the internet,
- like (http://www-2.cs.cmu.edu/afs/cs/usr/jmcm/www/info/key2.txt). It is a
- synchronous unidirectional serial interface: the data line is driven by the
- keyboard to send data to the CPU; the CTS/clock line has a pull up resistor
- and can be driven low by both keyboard and CPU. To send data to the CPU,
- the keyboard pulses the clock line low 9 times, and the Geneve samples all
- 8 bits of data (plus one start bit) on each falling edge of the clock.
- When the key code buffer is full, the Geneve gate array asserts the kbdint*
- line (connected to 9901 int8_t*). The Geneve gate array will hold the
- CTS/clock line low as long as the keyboard buffer is full or CRU bit @>F78
- is 0. Writing a 0 to >F79 will clear the Geneve keyboard buffer, and
- writing a 1 will resume normal operation: you need to write a 0 to >F78
- before clearing >F79, or the keyboard will be enabled to send data the gate
- array when >F79 is is set to 0, and any such incoming data from the
- keyboard will be cleared as soon as it is buffered by the gate array.
-
-****************************************************************************/
-
-static const uint8_t MF1_CODE[0xe] =
-{
- /* extended keys that are equivalent to non-extended keys */
- 0x1c, /* keypad enter */
- 0x1d, /* right control */
- 0x38, /* alt gr */
- // extra codes are 0x5b for Left Windows, 0x5c for Right Windows, 0x5d
- // for Menu, 0x5e for power, 0x5f for sleep, 0x63 for wake, but I doubt
- // any Geneve program would take advantage of these. */
-
- // extended key that is equivalent to a non-extended key
- // with shift off
- 0x35, /* pad slash */
-
- // extended keys that are equivalent to non-extended keys
- // with numlock off
- 0x47, /* home */
- 0x48, /* up */
- 0x49, /* page up */
- 0x4b, /* left */
- 0x4d, /* right */
- 0x4f, /* end */
- 0x50, /* down */
- 0x51, /* page down */
- 0x52, /* insert */
- 0x53 /* delete */
-};
-
-geneve_keyboard_device::geneve_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, GENEVE_KEYBOARD, tag, owner, clock),
- m_interrupt(*this),
- m_keys(*this, "KEY%u", 0),
- m_key_reset(false), m_key_queue_length(0), m_key_queue_head(0), m_key_in_buffer(false), m_key_numlock_state(false), m_key_ctrl_state(0), m_key_alt_state(0),
- m_key_real_shift_state(0), m_key_fake_shift_state(false), m_key_fake_unshift_state(false), m_key_autorepeat_key(0), m_key_autorepeat_timer(0), m_keep_keybuf(false),
- m_keyboard_clock(false), m_timer(nullptr)
-{
-}
-
-void geneve_keyboard_device::post_in_key_queue(int keycode)
-{
- m_key_queue[(m_key_queue_head + m_key_queue_length) % KEYQUEUESIZE] = keycode;
- m_key_queue_length++;
-
- LOGMASKED(LOG_KEYBOARD, "Posting keycode %02x\n", keycode);
-}
-
-void geneve_keyboard_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- poll();
-}
-
-void geneve_keyboard_device::poll()
-{
- uint32_t keystate;
- uint32_t key_transitions;
- int i, j;
- int keycode;
- int pressed;
- LOGMASKED(LOG_KEYBOARD, "Poll keyboard\n");
- if (m_key_reset) return;
-
- /* Poll keyboard */
- for (i = 0; (i < 4) && (m_key_queue_length <= (KEYQUEUESIZE-MAXKEYMSGLENGTH)); i++)
- {
- keystate = m_keys[2*i]->read() | (m_keys[2*i + 1]->read() << 16);
- key_transitions = keystate ^ m_key_state_save[i];
- if (key_transitions)
- {
- for (j = 0; (j < 32) && (m_key_queue_length <= (KEYQUEUESIZE-MAXKEYMSGLENGTH)); j++)
- {
- if ((key_transitions >> j) & 1)
- {
- keycode = (i << 5) | j;
- pressed = ((keystate >> j) & 1);
- if (pressed)
- m_key_state_save[i] |= (1 << j);
- else
- m_key_state_save[i] &= ~ (1 << j);
-
- /* Update auto-repeat */
- if (pressed)
- {
- m_key_autorepeat_key = keycode;
- m_key_autorepeat_timer = KEYAUTOREPEATDELAY+1;
- }
- else /*if (keycode == m_key_autorepeat_key)*/
- m_key_autorepeat_key = 0;
-
- // Release Fake Shift/Unshift if another key is pressed
- // We do so if a key is released, though it is actually
- // required only if it is a modifier key
- /*if (pressed)*/
- //{
- if (m_key_fake_shift_state)
- {
- /* Fake shift release */
- post_in_key_queue(0xe0);
- post_in_key_queue(0xaa);
- m_key_fake_shift_state = false;
- }
- if (m_key_fake_unshift_state)
- {
- /* Fake shift press */
- post_in_key_queue(0xe0);
- post_in_key_queue(0x2a);
- m_key_fake_unshift_state = false;
- }
- //}
-
- /* update shift and numlock state */
- if ((keycode == 0x2a) || (keycode == 0x36))
- m_key_real_shift_state = m_key_real_shift_state + (pressed ? +1 : -1);
- if ((keycode == 0x1d) || (keycode == 0x61))
- m_key_ctrl_state = m_key_ctrl_state + (pressed ? +1 : -1);
- if ((keycode == 0x38) || (keycode == 0x62))
- m_key_alt_state = m_key_alt_state + (pressed ? +1 : -1);
- if ((keycode == 0x45) && pressed)
- m_key_numlock_state = !m_key_numlock_state;
-
- if ((keycode >= 0x60) && (keycode < 0x6e))
- { /* simpler extended keys */
- /* these keys are emulated */
-
- if ((keycode >= 0x63) && pressed)
- {
- /* Handle shift state */
- if (keycode == 0x63)
- { /* non-shifted key */
- if (m_key_real_shift_state!=0)
- /* Fake shift unpress */
- m_key_fake_unshift_state = true;
- }
- else /*if (keycode >= 0x64)*/
- { /* non-numlock mode key */
- if (m_key_numlock_state & (m_key_real_shift_state==0))
- /* Fake shift press if numlock is active */
- m_key_fake_shift_state = true;
- else if ((!m_key_numlock_state) & (m_key_real_shift_state!=0))
- /* Fake shift unpress if shift is down */
- m_key_fake_unshift_state = true;
- }
-
- if (m_key_fake_shift_state)
- {
- post_in_key_queue(0xe0);
- post_in_key_queue(0x2a);
- }
-
- if (m_key_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_key_alt_state!=0)
- {
- /* SysRq */
- keycode = 0x54;
- if (!pressed) keycode |= 0x80;
- post_in_key_queue(keycode);
- }
- else
- {
- /* Handle shift state */
- if (pressed && (m_key_real_shift_state==0) && (m_key_ctrl_state==0))
- { /* Fake shift press */
- post_in_key_queue(0xe0);
- post_in_key_queue(0x2a);
- m_key_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_key_ctrl_state!=0)
- {
- 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);
- }
- signal_when_key_available();
- }
- }
- }
- }
-
- /* Handle auto-repeat */
- if ((m_key_queue_length <= (KEYQUEUESIZE-MAXKEYMSGLENGTH)) && (m_key_autorepeat_key!=0) && (--m_key_autorepeat_timer == 0))
- {
- if ((m_key_autorepeat_key >= 0x60) && (m_key_autorepeat_key < 0x6e))
- {
- post_in_key_queue(0xe0);
- post_in_key_queue(MF1_CODE[m_key_autorepeat_key-0x60]);
- }
- else if (m_key_autorepeat_key == 0x6e)
- {
- if (m_key_alt_state!=0)
- post_in_key_queue(0x54);
- else
- {
- post_in_key_queue(0xe0);
- post_in_key_queue(0x37);
- }
- }
- else if (m_key_autorepeat_key == 0x6f)
- ;
- else
- {
- post_in_key_queue(m_key_autorepeat_key);
- }
- signal_when_key_available();
- m_key_autorepeat_timer = KEYAUTOREPEATRATE;
- }
-}
-
-uint8_t geneve_keyboard_device::get_recent_key()
-{
- if (m_key_in_buffer) return m_key_queue[m_key_queue_head];
- else return 0;
-}
-
-void geneve_keyboard_device::signal_when_key_available()
-{
- // if keyboard reset is not asserted, and key clock is enabled, and key
- // buffer clear is disabled, and key queue is not empty. */
- if ((!m_key_reset) && (m_keyboard_clock) && (m_keep_keybuf) && (m_key_queue_length != 0))
- {
- LOGMASKED(LOG_KEYBOARD, "Key available\n");
- m_interrupt(ASSERT_LINE);
- m_key_in_buffer = true;
- }
-}
-
-WRITE_LINE_MEMBER( geneve_keyboard_device::clock_control )
-{
- bool rising_edge = (!m_keyboard_clock && (state==ASSERT_LINE));
- m_keyboard_clock = (state==ASSERT_LINE);
- LOGMASKED(LOG_KEYBOARD, "Keyboard clock_control state=%d\n", m_keyboard_clock);
- if (rising_edge)
- signal_when_key_available();
-}
-
-WRITE_LINE_MEMBER( geneve_keyboard_device::send_scancodes )
-{
- bool rising_edge = (!m_keep_keybuf && (state==ASSERT_LINE));
- bool falling_edge = (m_keep_keybuf && (state==CLEAR_LINE));
- m_keep_keybuf = (state==ASSERT_LINE);
-
- if (rising_edge) signal_when_key_available();
- else
- {
- if (falling_edge)
- {
- if (m_key_queue_length != 0)
- {
- m_key_queue_head = (m_key_queue_head + 1) % KEYQUEUESIZE;
- m_key_queue_length--;
- }
- /* clear keyboard interrupt */
- m_interrupt(CLEAR_LINE);
- m_key_in_buffer = false;
- }
- }
-}
-
-WRITE_LINE_MEMBER( geneve_keyboard_device::reset_line )
-{
- m_key_reset = !(state==ASSERT_LINE);
-
- if (m_key_reset)
- {
- /* reset -> clear keyboard key queue, but not geneve key buffer */
- m_key_queue_length = (m_key_in_buffer)? 1 : 0;
- m_key_queue_head = 0;
- memset(m_key_state_save, 0, sizeof(m_key_state_save));
- m_key_numlock_state = false;
- m_key_ctrl_state = 0;
- m_key_alt_state = 0;
- m_key_real_shift_state = 0;
- m_key_fake_shift_state = false;
- m_key_fake_unshift_state = false;
- m_key_autorepeat_key = 0;
- }
-}
-
-void geneve_keyboard_device::device_start()
-{
- m_timer = timer_alloc(0);
- m_interrupt.resolve();
-
- // State registration
- save_item(NAME(m_key_reset));
- save_item(NAME(m_key_queue_length));
- save_item(NAME(m_key_queue_head));
- save_item(NAME(m_key_in_buffer));
- save_item(NAME(m_key_numlock_state));
- save_item(NAME(m_key_ctrl_state));
- save_item(NAME(m_key_alt_state));
- save_item(NAME(m_key_real_shift_state));
- save_item(NAME(m_key_fake_shift_state));
- save_item(NAME(m_key_fake_unshift_state));
- save_item(NAME(m_key_autorepeat_key));
- save_item(NAME(m_key_autorepeat_timer));
- save_item(NAME(m_keep_keybuf));
- save_item(NAME(m_keyboard_clock));
- save_pointer(NAME(m_key_queue),KEYQUEUESIZE);
- save_pointer(NAME(m_key_state_save),4);
-}
-
-void geneve_keyboard_device::device_reset()
-{
- m_key_in_buffer = false;
- reset_line(CLEAR_LINE);
- m_key_queue_length = 0;
- m_key_reset = true;
- m_keyboard_clock = false;
- m_keep_keybuf = false;
- m_timer->adjust(attotime::from_usec(1), 0, attotime::from_hz(120));
-}
-
-INPUT_PORTS_START( genkeys )
- 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) /* Left Ctrl 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) /* Left Shift 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) /* Right Shift 36 B6 */
- PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP * (PrtScr)") PORT_CODE(KEYCODE_ASTERISK ) /* Keypad * (PrtSc) 37 B7 */
- PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Alt") PORT_CODE(KEYCODE_LALT) /* Left Alt 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 ) /* Keypad 7 (Home) 47 C7 */
- PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 8 (Up)") PORT_CODE(KEYCODE_8_PAD ) /* Keypad 8 (Up arrow) 48 C8 */
- PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 9 (PgUp)") PORT_CODE(KEYCODE_9_PAD ) /* Keypad 9 (PgUp) 49 C9 */
- PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP -") PORT_CODE(KEYCODE_MINUS_PAD) /* Keypad - 4A CA */
- PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 4 (Left)") PORT_CODE(KEYCODE_4_PAD ) /* Keypad 4 (Left arrow) 4B CB */
- PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 5") PORT_CODE(KEYCODE_5_PAD) /* Keypad 5 4C CC */
- PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 6 (Right)") PORT_CODE(KEYCODE_6_PAD ) /* Keypad 6 (Right arrow) 4D CD */
- PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP +") PORT_CODE(KEYCODE_PLUS_PAD) /* Keypad + 4E CE */
- PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 1 (End)") PORT_CODE(KEYCODE_1_PAD ) /* Keypad 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 ) /* Keypad 2 (Down arrow) 50 D0 */
- PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 3 (PgDn)") PORT_CODE(KEYCODE_3_PAD ) /* Keypad 3 (PgDn) 51 D1 */
- PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 0 (Ins)") PORT_CODE(KEYCODE_0_PAD ) /* Keypad 0 (Ins) 52 D2 */
- PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP . (Del)") PORT_CODE(KEYCODE_DEL_PAD ) /* Keypad . (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) /* PAD Enter 60 e0 */
- PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(101)R-Control") PORT_CODE(KEYCODE_RCONTROL) /* Right Control 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) /* PAD 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 )
-#if 0
- PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Print Screen") PORT_CODE(KEYCODE_PRTSCR) /* Print Screen alternate 77 f7 */
- PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Left Win") /* Left Win 7d fd */
- PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Right Win") /* Right Win 7e fe */
- PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Menu") /* Menu 7f ff */
-#endif
-INPUT_PORTS_END
-
-ioport_constructor geneve_keyboard_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME( genkeys );
-}
} } } // end namespace bus::ti99::internal
diff --git a/src/devices/bus/ti99/internal/genboard.h b/src/devices/bus/ti99/internal/genboard.h
index b0d6ba7bb1c..3e927ab70df 100644
--- a/src/devices/bus/ti99/internal/genboard.h
+++ b/src/devices/bus/ti99/internal/genboard.h
@@ -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
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);
+ }
+}
+
diff --git a/src/devices/bus/ti99/internal/genkbd.h b/src/devices/bus/ti99/internal/genkbd.h
new file mode 100644
index 00000000000..76ebb02ed40
--- /dev/null
+++ b/src/devices/bus/ti99/internal/genkbd.h
@@ -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
diff --git a/src/mame/drivers/geneve.cpp b/src/mame/drivers/geneve.cpp
index ddd8aacc807..c0f40b8769a 100644
--- a/src/mame/drivers/geneve.cpp
+++ b/src/mame/drivers/geneve.cpp
@@ -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,11 +567,19 @@ 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,
but again it is ignored. Anyway, the TMS9995 has only two external inputs
@@ -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));