diff options
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 |
commit | 4495c351139f13d46e087c448e3b2418491485e2 (patch) | |
tree | 7b26831d3a162de6105ed419a0def5f6d51b5156 | |
parent | ec4b8b2fa4db449ac7e2a683db953e93026c04cc (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.lua | 2 | ||||
-rw-r--r-- | src/devices/bus/pc_kbd/pc_kbdc.cpp | 19 | ||||
-rw-r--r-- | src/devices/bus/pc_kbd/pc_kbdc.h | 4 | ||||
-rw-r--r-- | src/devices/bus/ti99/internal/genboard.cpp | 809 | ||||
-rw-r--r-- | src/devices/bus/ti99/internal/genboard.h | 193 | ||||
-rw-r--r-- | src/devices/bus/ti99/internal/genkbd.cpp | 648 | ||||
-rw-r--r-- | src/devices/bus/ti99/internal/genkbd.h | 89 | ||||
-rw-r--r-- | src/mame/drivers/geneve.cpp | 103 |
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)); |