From 9533352c6bd965e680f5f20285381d551d508228 Mon Sep 17 00:00:00 2001 From: Mark Garlanger Date: Fri, 24 Feb 2017 18:58:16 -0600 Subject: Fix Heath H19 keyboard (#2066) * Fix Heath H19 keyboard * Fix how enable/disable of 25th line is handled. * Updated to use internal ROM in MM5740. --- scripts/src/machine.lua | 12 + scripts/target/mame/mess.lua | 1 + src/devices/machine/mm5740.cpp | 173 +++++++++++++++ src/devices/machine/mm5740.h | 162 ++++++++++++++ src/mame/drivers/h19.cpp | 491 ++++++++++++++++++++++++++--------------- 5 files changed, 655 insertions(+), 184 deletions(-) create mode 100644 src/devices/machine/mm5740.cpp create mode 100644 src/devices/machine/mm5740.h diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index 8e33f586b68..5816349fa71 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -1236,6 +1236,18 @@ if (MACHINES["K056230"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/machine/mm5740.h,MACHINES["MM5740"] = true +--------------------------------------------------- + +if (MACHINES["MM5740"]~=null) then + files { + MAME_DIR .. "src/devices/machine/mm5740.cpp", + MAME_DIR .. "src/devices/machine/mm5740.h", + } +end + --------------------------------------------------- -- --@src/devices/machine/kb3600.h,MACHINES["KB3600"] = true diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 9d441207bdf..ba31c0bc232 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -471,6 +471,7 @@ MACHINES["MIOT6530"] = true MACHINES["MM58167"] = true MACHINES["MM58274C"] = true MACHINES["MM74C922"] = true +MACHINES["MM5740"] = true MACHINES["MOS6526"] = true MACHINES["MOS6529"] = true MACHINES["MOS6551"] = true diff --git a/src/devices/machine/mm5740.cpp b/src/devices/machine/mm5740.cpp new file mode 100644 index 00000000000..df8f5e43985 --- /dev/null +++ b/src/devices/machine/mm5740.cpp @@ -0,0 +1,173 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont, Mark Garlanger +/********************************************************************** + + National Semiconductor MM5740 Keyboard Encoder emulation + (Code originally based on kb3600.cpp) + +*********************************************************************/ + +#include "mm5740.h" + +#include + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +// devices +const device_type MM5740 = &device_creator; + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +ROM_START( mm5740 ) + ROM_REGION(0x1c2, "internal", 0) + ROM_LOAD("mm5740aac.ic1", 0x000, 0x1c2, CRC(aed404d3) SHA1(e7b9feba5f789f388d27820b5f3fa591d41b4ab1)) +ROM_END + +//------------------------------------------------- +// rom_region - device-specific ROM region +//------------------------------------------------- + +const tiny_rom_entry *mm5740_device::device_rom_region() const +{ + return ROM_NAME( mm5740 ); +} + + +//------------------------------------------------- +// mm5740_device - constructor +//------------------------------------------------- + +mm5740_device::mm5740_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, MM5740, "MM5740", tag, owner, clock, "mm5740", __FILE__), + m_read_x({*this, *this, *this, *this, *this, *this, *this, *this, *this}), + m_read_shift(*this), + m_read_control(*this), + m_write_data_ready(*this), + m_rom(*this, "internal") +{ + std::fill_n(m_x_mask, 9, 0); +} + +uint32_t mm5740_device::calc_effective_clock_key_debounce(uint32_t capacitance) +{ + // calculate key debounce based on capacitance in pF + uint32_t key_debounce_msec = capacitance / 125; + if (key_debounce_msec == 0) + { + key_debounce_msec = 1; + } + + return 1000 / key_debounce_msec; +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void mm5740_device::device_start() +{ + // resolve callbacks + for(int i = 0; i < 9; i++) + { + m_read_x[i].resolve_safe(0x3ff); + } + m_read_shift.resolve_safe(0); + m_read_control.resolve_safe(0); + m_write_data_ready.resolve_safe(); + + // allocate timers + m_scan_timer = timer_alloc(); + m_scan_timer->adjust(attotime::from_hz(clock()), 0, attotime::from_hz(clock())); + + // state saving + save_item(NAME(m_b)); + save_item(NAME(m_x_mask)); +} + + +//------------------------------------------------- +// device_start - device-specific reset +//------------------------------------------------- + +void mm5740_device::device_reset() +{ +} + +//------------------------------------------------- +// device_timer - handler timer events +//------------------------------------------------- + +void mm5740_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + int ako = 0; + + for (int x = 0; x < 9; x++) + { + uint16_t data = m_read_x[x]() ^ 0x3ff; + + if ((data ^ m_x_mask[x]) == 0) + { + // bail early if nothing has changed. + continue; + } + + for (int y = 0; y < 10; y++) + { + + if (BIT(data, y)) + { + uint8_t *rom = m_rom->base(); + uint16_t offset = x*10 + y; + // Common portion + uint16_t common = (uint16_t) rom[offset]; + + offset += (((m_read_shift() ? 1: 0) + (m_read_control() ? 2: 0)) + 1) * 90; + + // Unique portion based on shift/ctrl keys. + uint8_t uniq = rom[offset]; + + uint16_t b = (((common & 0x10) << 4) | ((uniq & 0x0f) << 4) | (common & 0x0f)) ^ 0x1ff; + + ako = 1; + + if (!BIT(m_x_mask[x], y)) + { + m_x_mask[x] |= (1 << y); + if (m_b != b) + { + m_b = b; + m_write_data_ready(ASSERT_LINE); + + return; + } + } + } + else // key released, unmark it from the "down" info + { + m_x_mask[x] &= ~(1 << y); + } + } + } + + if (!ako) + { + m_write_data_ready(CLEAR_LINE); + m_b = -1; + } +} + + +//------------------------------------------------- +// b_r - +//------------------------------------------------- + +uint16_t mm5740_device::b_r() +{ + m_write_data_ready(CLEAR_LINE); + return m_b; +} + diff --git a/src/devices/machine/mm5740.h b/src/devices/machine/mm5740.h new file mode 100644 index 00000000000..8687f4d6cc9 --- /dev/null +++ b/src/devices/machine/mm5740.h @@ -0,0 +1,162 @@ +// license:BSD-3-Clause +// copyright-holders: R. Belmont +/********************************************************************** + + MM5740 Keyboard Encoder emulation + +********************************************************************** + _____ _____ + B3 1 |* \_/ | 40 B4 + Vll 2 | | 39 B9 + Clock 3 | | 38 B2 + X9 4 | | 37 B1 + X8 5 | | 36 B8 + X7 6 | | 35 B7 + X6 7 | | 34 B6 + X5 8 | | 33 B5 + X4 9 | | 32 Vss + X3 10 | MM5740 | 31 Y9 + X2 11 | | 30 Y8 + X1 12 | | 29 Y7 + Data Strobe Output 13 | | 28 Y6 + Data Strobe Control 14 | | 27 Y5 + Output Enable 15 | | 26 Y4 + Repeat 16 | | 25 Y3 + Key Bounce Mask 17 | | 24 Y2 + Vgg 18 | | 23 Y1 + Control 19 | | 22 Y0 + Shift Lock I/O 20 |_____________| 21 Shift + +Name Pin No. Function +---------------------------------------------------------------------- + +X1-X9 4-12 Output - Drives the key switch matrix. + +Y1-Y10 22-31 Inputs - connect to the X drive lines with + the key switch matrix. + +B1-B9 1,33-40 Tri-stated data outputs. + +Data Strobe Output 13 Output to indicate key pressed. + +Data Strobe Control 14 Input to control data strobe output pulse width. + +Output Enable 15 Input to control the chip's TRI-STATE output + +Repeat 16 Each cycle of this signal will issue + a new data strobe for the pressed key. + +Key-Bounce Mask 17 Use capacitor on this chip to provide + key debouncing + +Shift 21 Shift key pressed + +Control 19 Control key pressed + +Shift Lock I/O 20 Togglable input to signify shift (NOT caps) lock. + +Clock 3 A TTL compatible clock signal + +Vss 32 +5.0V + +Vll 2 Ground + +Vgg 18 -12V + + +**********************************************************************/ + +/* TODO: + Support Key-bounce mask + Support Repeat function + Support shift lock + Support additional internal ROMs +*/ + +#pragma once + +#ifndef MAME_DEVICE_MACHINE_MM5740_H +#define MAME_DEVICE_MACHINE_MM5740_H + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_MM5740_MATRIX_X1(_cb) devcb = &mm5740_device::set_x_cb(*device, DEVCB_##_cb, 0); +#define MCFG_MM5740_MATRIX_X2(_cb) devcb = &mm5740_device::set_x_cb(*device, DEVCB_##_cb, 1); +#define MCFG_MM5740_MATRIX_X3(_cb) devcb = &mm5740_device::set_x_cb(*device, DEVCB_##_cb, 2); +#define MCFG_MM5740_MATRIX_X4(_cb) devcb = &mm5740_device::set_x_cb(*device, DEVCB_##_cb, 3); +#define MCFG_MM5740_MATRIX_X5(_cb) devcb = &mm5740_device::set_x_cb(*device, DEVCB_##_cb, 4); +#define MCFG_MM5740_MATRIX_X6(_cb) devcb = &mm5740_device::set_x_cb(*device, DEVCB_##_cb, 5); +#define MCFG_MM5740_MATRIX_X7(_cb) devcb = &mm5740_device::set_x_cb(*device, DEVCB_##_cb, 6); +#define MCFG_MM5740_MATRIX_X8(_cb) devcb = &mm5740_device::set_x_cb(*device, DEVCB_##_cb, 7); +#define MCFG_MM5740_MATRIX_X9(_cb) devcb = &mm5740_device::set_x_cb(*device, DEVCB_##_cb, 8); +#define MCFG_MM5740_SHIFT_CB(_cb) devcb = &mm5740_device::set_shift_cb(*device, DEVCB_##_cb); +#define MCFG_MM5740_CONTROL_CB(_cb) devcb = &mm5740_device::set_control_cb(*device, DEVCB_##_cb); +#define MCFG_MM5740_DATA_READY_CB(_cb) devcb = &mm5740_device::set_data_ready_cb(*device, DEVCB_##_cb); + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> mm5740_device + +class mm5740_device : public device_t +{ +public: + // construction/destruction + mm5740_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // public interface + uint16_t b_r(); + + template static devcb_base &set_x_cb(device_t &device, Object &&object, uint8_t i) + { + assert(i<9); return downcast(device).m_read_x[i].set_callback(std::forward(object)); + } + template static devcb_base &set_shift_cb(device_t &device, Object &&object) + { + return downcast(device).m_read_shift.set_callback(std::forward(object)); + } + template static devcb_base &set_control_cb(device_t &device, Object &&object) + { + return downcast(device).m_read_control.set_callback(std::forward(object)); + } + template static devcb_base &set_data_ready_cb(device_t &device, Object &&object) + { + return downcast(device).m_write_data_ready.set_callback(std::forward(object)); + } + static uint32_t calc_effective_clock_key_debounce(uint32_t capacitance); + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + + virtual const tiny_rom_entry *device_rom_region() const override; + +private: + devcb_read16 m_read_x[9]; + devcb_read_line m_read_shift, m_read_control; + devcb_write_line m_write_data_ready; + + required_memory_region m_rom; // Internal ROM + + int m_b; // output buffer + + int m_x_mask[9]; // mask of what keys are down + + // timers + emu_timer *m_scan_timer; // keyboard scan timer +}; + + +// device type definition +extern const device_type MM5740; + + + +#endif + diff --git a/src/mame/drivers/h19.cpp b/src/mame/drivers/h19.cpp index 1a3efd1a314..50d4781e4f2 100644 --- a/src/mame/drivers/h19.cpp +++ b/src/mame/drivers/h19.cpp @@ -2,35 +2,25 @@ // copyright-holders:Robbbert, Mark Garlanger /*************************************************************************** - Heathkit H19 + Heathkit H19 - 12/05/2009 Skeleton driver. + A smart terminal designed and manufactured by Heath Company. - The keyboard consists of a 9x10 matrix connected to a MM5740N - mask-programmed keyboard controller. The output of this passes - through a rom. The MM5740N may be custom-made, in which case it - will need to be procured and tested. There is a "default" array; - perhaps this is used. The presence of the rom would seem to - indicate that the default is being used. We won't know, of - course, until the device is emulated. + The keyboard consists of a 9x10 matrix connected to a MM5740AAC/N + mask-programmed keyboard controller. The output of this passes + through a rom. - Keyboard input can also come from the serial port (a 8250). - Either device will signal an interrupt to the CPU when a key - is pressed/sent. + Input can also come from the serial port (a 8250). + Either device will signal an interrupt to the CPU when a key + is pressed/data is received. - For the moment, the "ascii keyboard" device is used for the keyboard. + TODO: + - Finish connecting up the 8250 + - enable 8520 interrupts + - speed up emulation - TODO: - - Create device or HLE of MM5740N keyboard controller - - Make sure correct mask programming is used for it - - Use keyboard rom - - Finish connecting up the 8250 - - Verify beep lengths - - Verify ram size - - When the internal keyboard works, get rid of the "ascii_keyboard". - - Bios 1 (super19) has the videoram at D800. This is not emulated. - However, a keyclick can be heard, to assure you it does in fact work. + super19 version has the videoram at D800. This is not emulated. + However, a keyclick can be heard, to assure you it does in fact work. ****************************************************************************/ /*************************************************************************** @@ -48,17 +38,16 @@ Only address lines A5, A6, A7 are used by the U442 three-to-eight line decoder - 1. Keyboard encoder 0x80 - 2. Keyboard status 0xA0 - 3. CRT controller 0x60 - 4. Power-up configuration (primary) 0x00 - 5. Power-up configuration (secondary) 0x20 - 6. ACE (communications) 0x40 - 7. Bell enable 0xE0 - 8. Key click enable 0xC0 - - Decoder U442 is enabled only during an I/O read or write operation to elimnate the - possibility of false decoding on a refresh address coming from the Z80. +Address Description +---------------------------------------------------- + 0x00 Power-up configuration (primary - SW401) + 0x20 Power-up configuration (secondary - SW402) + 0x40 ACE (communications) + 0x60 CRT controller + 0x80 Keyboard encoder + 0xA0 Keyboard status + 0xC0 Key click enable + 0xE0 Bell enable ****************************************************************************/ @@ -67,21 +56,29 @@ #include "video/mc6845.h" #include "sound/beep.h" #include "machine/ins8250.h" -#include "machine/keyboard.h" +#include "machine/mm5740.h" // Standard H19 used a 2.048 MHz clock #define H19_CLOCK (XTAL_12_288MHz / 6) +#define MC6845_CLOCK (XTAL_12_288MHz /8) +#define INS8250_CLOCK (XTAL_12_288MHz /4) +// Capacitor value in pF +#define H19_KEY_DEBOUNCE_CAPACITOR 5000 +#define MM5740_CLOCK (mm5740_device::calc_effective_clock_key_debounce(H19_KEY_DEBOUNCE_CAPACITOR)) // Beep Frequency is 1 KHz #define H19_BEEP_FRQ (H19_CLOCK / 2048) +#define KBDC_TAG "mm5740" + class h19_state : public driver_device { public: enum { - TIMER_BEEP_OFF + TIMER_KEY_CLICK_OFF, + TIMER_BELL_OFF }; h19_state(const machine_config &mconfig, device_type type, const char *tag) @@ -93,13 +90,20 @@ public: , m_beep(*this, "beeper") , m_p_videoram(*this, "videoram") , m_p_chargen(*this, "chargen") + , m_mm5740(*this, KBDC_TAG) + , m_kbdrom(*this, "keyboard") + , m_kbspecial(*this, "MODIFIERS") { } - DECLARE_READ8_MEMBER(h19_80_r); - DECLARE_READ8_MEMBER(h19_a0_r); - DECLARE_WRITE8_MEMBER(h19_c0_w); - DECLARE_WRITE8_MEMBER(h19_kbd_put); + DECLARE_WRITE8_MEMBER(h19_keyclick_w); + DECLARE_WRITE8_MEMBER(h19_bell_w); + DECLARE_READ8_MEMBER(kbd_key_r); + DECLARE_READ8_MEMBER(kbd_flags_r); + DECLARE_READ_LINE_MEMBER(mm5740_shift_r); + DECLARE_READ_LINE_MEMBER(mm5740_control_r); + DECLARE_WRITE_LINE_MEMBER(mm5740_data_ready_w); + MC6845_UPDATE_ROW(crtc_update_row); private: @@ -113,182 +117,187 @@ private: required_device m_beep; required_shared_ptr m_p_videoram; required_region_ptr m_p_chargen; + required_device m_mm5740; + required_memory_region m_kbdrom; + required_ioport m_kbspecial; + + uint8_t m_transchar; + bool m_strobe; + uint16_t translate_mm5740_b(uint16_t b); + bool m_keyclickactive; + bool m_bellactive; }; - void h19_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { switch (id) { - case TIMER_BEEP_OFF: - m_beep->set_state(0); + case TIMER_KEY_CLICK_OFF: + m_keyclickactive = false; + break; + case TIMER_BELL_OFF: + m_bellactive = false; break; default: assert_always(false, "Unknown id in h19_state::device_timer"); } -} -READ8_MEMBER( h19_state::h19_80_r ) -{ -// keyboard data - uint8_t ret = m_term_data; - m_term_data = 0; - return ret; -} - -READ8_MEMBER( h19_state::h19_a0_r ) -{ -// keyboard status - m_maincpu->set_input_line(0, CLEAR_LINE); - return 0x7f; // says that a key is ready and no modifier keys are pressed + if (!m_keyclickactive && !m_bellactive) + { + m_beep->set_state(0); + } } -WRITE8_MEMBER( h19_state::h19_c0_w ) -{ -/* Beeper control - a 96L02 contains 2 oneshots, one for bell and one for keyclick. - - offset 00-1F = keyclick - offset 20-3F = terminal bell */ - uint8_t length = (offset & 0x20) ? 200 : 6; - m_beep->set_state(1); - timer_set(attotime::from_msec(length), TIMER_BEEP_OFF); -} static ADDRESS_MAP_START(h19_mem, AS_PROGRAM, 8, h19_state) ADDRESS_MAP_UNMAP_HIGH AM_RANGE(0x0000, 0x1fff) AM_ROM - AM_RANGE(0x2000, 0xf7ff) AM_RAM + AM_RANGE(0x4000, 0x4100) AM_RAM AM_RANGE(0xf800, 0xffff) AM_RAM AM_SHARE("videoram") ADDRESS_MAP_END static ADDRESS_MAP_START( h19_io, AS_IO, 8, h19_state) ADDRESS_MAP_UNMAP_HIGH ADDRESS_MAP_GLOBAL_MASK(0xff) - AM_RANGE(0x00, 0x1F) AM_READ_PORT("S401") - AM_RANGE(0x20, 0x3F) AM_READ_PORT("S402") + AM_RANGE(0x00, 0x1F) AM_READ_PORT("SW401") + AM_RANGE(0x20, 0x3F) AM_READ_PORT("SW402") AM_RANGE(0x40, 0x47) AM_MIRROR(0x18) AM_DEVREADWRITE("ins8250", ins8250_device, ins8250_r, ins8250_w ) AM_RANGE(0x60, 0x60) AM_DEVWRITE("crtc", mc6845_device, address_w) AM_RANGE(0x61, 0x61) AM_DEVREADWRITE("crtc", mc6845_device, register_r, register_w) - AM_RANGE(0x80, 0x9F) AM_READ(h19_80_r) - AM_RANGE(0xA0, 0xBF) AM_READ(h19_a0_r) - AM_RANGE(0xC0, 0xFF) AM_WRITE(h19_c0_w) + AM_RANGE(0x80, 0x9F) AM_READ(kbd_key_r) + AM_RANGE(0xA0, 0xBF) AM_READ(kbd_flags_r) + AM_RANGE(0xC0, 0xDF) AM_WRITE(h19_keyclick_w) + AM_RANGE(0xE0, 0xFF) AM_WRITE(h19_bell_w) ADDRESS_MAP_END /* Input ports */ static INPUT_PORTS_START( h19 ) -// Port codes are omitted to prevent collision with terminal keys PORT_START("MODIFIERS") - // bit 0 connects to B8 of MM5740 - purpose unknown + // bit 0 connects to B8 of MM5740 - low if either shift key is // bit 7 is low if a key is pressed - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CapsLock") - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Break") - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("OffLine") - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CTRL") - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("LeftShift") - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Repeat") - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Reset") - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("RightShift") + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CapsLock") PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Break") PORT_CODE(KEYCODE_PAUSE) + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("OffLine") PORT_CODE(KEYCODE_F12) PORT_TOGGLE + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("LeftShift") PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Repeat") PORT_CODE(KEYCODE_LALT) + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("RightShift") PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Reset") PORT_CODE(KEYCODE_F10) PORT_START("X1") - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("/") - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("X2") - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0-pad") - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Dot-pad") - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Enter-pad") + PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("/") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Unused") + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Unused") + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Unused") + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("k_X2") + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Unused") + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0-pad") PORT_CODE(KEYCODE_0_PAD) PORT_CHAR('0') + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Dot-pad") PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR('.') + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Enter-pad") PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(13) + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Unused") PORT_START("X2") - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(";") - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\'") - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("{") - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("1-pad") - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("2-pad") - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("3-pad") + PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(";") PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR('.') + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\'") PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('\"') + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("{") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('{') PORT_CHAR('}') + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Unused") + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Unused") + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("1-pad") PORT_CODE(KEYCODE_1_PAD) PORT_CHAR('1') + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("2-pad") PORT_CODE(KEYCODE_2_PAD) PORT_CHAR('2') + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("3-pad") PORT_CODE(KEYCODE_3_PAD) PORT_CHAR('3') + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Unused") PORT_START("X3") - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P") - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("[") - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\\") - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("LF") - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("DEL") - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("4-pad") - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("5-pad") - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("6-pad") + PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("[") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR(']') + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\\") PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|') + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("LF") PORT_CODE(KEYCODE_RWIN) + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("DEL") PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL)) + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Unused") + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("4-pad") PORT_CODE(KEYCODE_4_PAD) PORT_CHAR('4') + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("5-pad") PORT_CODE(KEYCODE_5_PAD) PORT_CHAR('5') + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("6-pad") PORT_CODE(KEYCODE_6_PAD) PORT_CHAR('6') + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Unused") PORT_START("X4") - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0") - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("-") - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("=") - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("AccentAcute") - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("BS") - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("X1") - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("7-pad") - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("8-pad") - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("9-pad") + PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("-") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_') + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("=") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+') + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("AccentAcute") PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~') + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("BS") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("k_X1") + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("7-pad") PORT_CODE(KEYCODE_7_PAD) PORT_CHAR('7') + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("8-pad") PORT_CODE(KEYCODE_8_PAD) PORT_CHAR('8') + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("9-pad") PORT_CODE(KEYCODE_9_PAD) PORT_CHAR('9') + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Unused") PORT_START("X5") - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F1") - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F2") - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F3") - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F4") - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F5") - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Erase") - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Blue") - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Red") - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Gray") + PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F1") PORT_CODE(KEYCODE_F1) + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F2") PORT_CODE(KEYCODE_F2) + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F3") PORT_CODE(KEYCODE_F3) + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F4") PORT_CODE(KEYCODE_F4) + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F5") PORT_CODE(KEYCODE_F5) + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Erase") PORT_CODE(KEYCODE_F6) + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Blue") PORT_CODE(KEYCODE_F7) + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Red") PORT_CODE(KEYCODE_F8) + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Gray") PORT_CODE(KEYCODE_F9) + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Unused") PORT_START("X6") - PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Space") - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z") - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("X") - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C") - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("V") - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B") - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("N") - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M") - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(",") - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(".") + PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(",") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(".") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') PORT_START("X7") - PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Scroll") - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A") - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("S") - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D") - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F") - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G") - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("H") - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("J") - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("K") - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L") + PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Scroll") PORT_CODE(KEYCODE_LWIN) + PORT_START("X8") - PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Tab") - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q") - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W") - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E") - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("R") - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("T") - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y") - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("U") - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("I") - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O") + PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Tab") PORT_CODE(KEYCODE_TAB) PORT_CHAR(9) + PORT_START("X9") - PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("1") - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("2") - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("3") - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("4") - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("5") - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("6") - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("7") - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("8") - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("9") - - PORT_START("S401") - PORT_DIPNAME( 0x0f, 0x03, "Baud Rate") + PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^') + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CODE(KEYCODE_ESC) PORT_CHAR(27) + + PORT_START("SW401") + PORT_DIPNAME( 0x0f, 0x0c, "Baud Rate") PORT_DIPSETTING( 0x01, "110") PORT_DIPSETTING( 0x02, "150") PORT_DIPSETTING( 0x03, "300") @@ -309,21 +318,21 @@ static INPUT_PORTS_START( h19 ) PORT_DIPNAME( 0x40, 0x00, "Parity Type") PORT_DIPSETTING( 0x00, DEF_STR(Normal)) PORT_DIPSETTING( 0x40, "Stick") - PORT_DIPNAME( 0x80, 0x00, "Duplex") + PORT_DIPNAME( 0x80, 0x80, "Duplex") PORT_DIPSETTING( 0x00, "Half") PORT_DIPSETTING( 0x80, "Full") - PORT_START("S402") // stored at 40C8 + PORT_START("SW402") // stored at 40C8 PORT_DIPNAME( 0x01, 0x00, "Cursor") PORT_DIPSETTING( 0x00, "Underline") PORT_DIPSETTING( 0x01, "Block") PORT_DIPNAME( 0x02, 0x00, "Keyclick") PORT_DIPSETTING( 0x02, DEF_STR(No)) PORT_DIPSETTING( 0x00, DEF_STR(Yes)) - PORT_DIPNAME( 0x04, 0x04, "Wrap at EOL") + PORT_DIPNAME( 0x04, 0x00, "Wrap at EOL") PORT_DIPSETTING( 0x00, DEF_STR(No)) PORT_DIPSETTING( 0x04, DEF_STR(Yes)) - PORT_DIPNAME( 0x08, 0x08, "Auto LF on CR") + PORT_DIPNAME( 0x08, 0x00, "Auto LF on CR") PORT_DIPSETTING( 0x00, DEF_STR(No)) PORT_DIPSETTING( 0x08, DEF_STR(Yes)) PORT_DIPNAME( 0x10, 0x00, "Auto CR on LF") @@ -340,11 +349,120 @@ static INPUT_PORTS_START( h19 ) PORT_DIPSETTING( 0x80, "60Hz") INPUT_PORTS_END +// Keyboard encoder masks +#define KB_ENCODER_KEY_VALUE_MASK 0x7F +#define KB_ENCODER_CONTROL_KEY_MASK 0x80 + +// Keyboard flag masks +#define KB_STATUS_SHIFT_KEYS_MASK 0x01 +#define KB_STATUS_CAPS_LOCK_MASK 0x02 +#define KB_STATUS_BREAK_KEY_MASK 0x04 +#define KB_STATUS_ONLINE_KEY_MASK 0x08 +#define KB_STATUS_REPEAT_KEYS_MASK 0x40 +#define KB_STATUS_KEYBOARD_STROBE_MASK 0x80 + void h19_state::machine_reset() { } + +WRITE8_MEMBER( h19_state::h19_keyclick_w ) +{ +/* Keyclick - 6 mSec */ + + m_beep->set_state(1); + m_keyclickactive = true; + timer_set(attotime::from_msec(6), TIMER_KEY_CLICK_OFF); +} + +WRITE8_MEMBER( h19_state::h19_bell_w ) +{ +/* Bell (^G) - 200 mSec */ + + m_beep->set_state(1); + m_bellactive = true; + timer_set(attotime::from_msec(200), TIMER_BELL_OFF); +} + + +/*************************************************************************** +MM5740 B Mapping to the ROM address + +B1 -> A0 A10 = 0 +B2 -> A1 A9 = 0 +B3 -> A2 A8 = B8 +B4 -> A3 A7 = B7 +B5 -> A4 A6 = B9 +B6 -> A5 A5 = B6 +B7 -> A7 A4 = B5 +B8 -> A8 A3 = B4 +B9 -> A6 A2 = B3 +ground -> A9 A1 = B2 +ground -> A10 A0 = B1 + +****************************************************************************/ +uint16_t h19_state::translate_mm5740_b(uint16_t b) +{ + return ((b & 0x100) >> 2) | ((b & 0x0c0) << 1) | (b & 0x03f); +} + +READ8_MEMBER(h19_state::kbd_key_r) +{ + m_maincpu->set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE); + m_strobe = false; + + // high bit is for control key pressed, this is handled in the ROM, no processing needed. + return m_transchar; +} + +READ8_MEMBER(h19_state::kbd_flags_r) +{ + uint8_t rv = 0; + uint16_t modifiers = m_kbspecial->read(); + + rv = modifiers & 0xff; + + // check both shifts + if (((modifiers & 0x020) == 0) || ((modifiers & 0x100) == 0)) + { + rv |= 0x1; + } + + // invert offline switch + rv ^= KB_STATUS_ONLINE_KEY_MASK; + + if (!m_strobe) + { + rv |= KB_STATUS_KEYBOARD_STROBE_MASK; + } + + return rv; +} + +READ_LINE_MEMBER(h19_state::mm5740_shift_r) +{ + return ((m_kbspecial->read() ^ 0x120) & 0x120) ? ASSERT_LINE : CLEAR_LINE; +} + +READ_LINE_MEMBER(h19_state::mm5740_control_r) +{ + return ((m_kbspecial->read() ^ 0x10) & 0x10) ? ASSERT_LINE: CLEAR_LINE; +} + +WRITE_LINE_MEMBER(h19_state::mm5740_data_ready_w) +{ + if (state == ASSERT_LINE) + { + uint8_t *decode = m_kbdrom->base(); + + m_transchar = decode[translate_mm5740_b(m_mm5740->b_r())]; + m_strobe = true; + m_maincpu->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE); + } +} + + MC6845_UPDATE_ROW( h19_state::crtc_update_row ) { const rgb_t *palette = m_palette->palette()->entry_list_raw(); @@ -399,40 +517,45 @@ static GFXDECODE_START( h19 ) GFXDECODE_ENTRY( "chargen", 0x0000, h19_charlayout, 0, 1 ) GFXDECODE_END -WRITE8_MEMBER( h19_state::h19_kbd_put ) -{ - m_term_data = data; - m_maincpu->set_input_line(0, HOLD_LINE); -} - static MACHINE_CONFIG_START( h19, h19_state ) /* basic machine hardware */ MCFG_CPU_ADD("maincpu",Z80, H19_CLOCK) // From schematics MCFG_CPU_PROGRAM_MAP(h19_mem) MCFG_CPU_IO_MAP(h19_io) - //MCFG_DEVICE_PERIODIC_INT_DRIVER(h19_state, irq0_line_hold, 50) // for testing, causes a keyboard scan /* video hardware */ MCFG_SCREEN_ADD_MONOCHROME("screen", RASTER, rgb_t::green()) - MCFG_SCREEN_REFRESH_RATE(60) + MCFG_SCREEN_REFRESH_RATE(60) // TODO- this is adjustable by dipswitch. MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */ MCFG_SCREEN_UPDATE_DEVICE("crtc", mc6845_device, screen_update) + MCFG_SCREEN_SIZE(640, 250) MCFG_SCREEN_VISIBLE_AREA(0, 640 - 1, 0, 250 - 1) MCFG_GFXDECODE_ADD("gfxdecode", "palette", h19) MCFG_PALETTE_ADD_MONOCHROME("palette") - MCFG_MC6845_ADD("crtc", MC6845, "screen", XTAL_12_288MHz / 8) // clk taken from schematics - MCFG_MC6845_SHOW_BORDER_AREA(false) - MCFG_MC6845_CHAR_WIDTH(8) /*?*/ + MCFG_MC6845_ADD("crtc", MC6845, "screen", MC6845_CLOCK) + MCFG_MC6845_SHOW_BORDER_AREA(true) + MCFG_MC6845_CHAR_WIDTH(8) MCFG_MC6845_UPDATE_ROW_CB(h19_state, crtc_update_row) MCFG_MC6845_OUT_VSYNC_CB(INPUTLINE("maincpu", INPUT_LINE_NMI)) // frame pulse - MCFG_DEVICE_ADD("ins8250", INS8250, XTAL_12_288MHz / 4) // 3.072mhz clock which gets divided down for the various baud rates + MCFG_DEVICE_ADD("ins8250", INS8250, INS8250_CLOCK) MCFG_INS8250_OUT_INT_CB(INPUTLINE("maincpu", 0)) // interrupt - MCFG_DEVICE_ADD("keyboard", GENERIC_KEYBOARD, 0) - MCFG_GENERIC_KEYBOARD_CB(WRITE8(h19_state, h19_kbd_put)) + MCFG_DEVICE_ADD(KBDC_TAG, MM5740, MM5740_CLOCK) + MCFG_MM5740_MATRIX_X1(IOPORT("X1")) + MCFG_MM5740_MATRIX_X2(IOPORT("X2")) + MCFG_MM5740_MATRIX_X3(IOPORT("X3")) + MCFG_MM5740_MATRIX_X4(IOPORT("X4")) + MCFG_MM5740_MATRIX_X5(IOPORT("X5")) + MCFG_MM5740_MATRIX_X6(IOPORT("X6")) + MCFG_MM5740_MATRIX_X7(IOPORT("X7")) + MCFG_MM5740_MATRIX_X8(IOPORT("X8")) + MCFG_MM5740_MATRIX_X9(IOPORT("X9")) + MCFG_MM5740_SHIFT_CB(READLINE(h19_state, mm5740_shift_r)) + MCFG_MM5740_CONTROL_CB(READLINE(h19_state, mm5740_control_r)) + MCFG_MM5740_DATA_READY_CB(WRITELINE(h19_state, mm5740_data_ready_w)) /* sound hardware */ MCFG_SPEAKER_STANDARD_MONO("mono") @@ -483,7 +606,7 @@ ROM_START( watz19 ) ROM_END /* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */ -COMP( 1979, h19, 0, 0, h19, h19, driver_device, 0, "Heath Inc", "Heathkit H-19", MACHINE_NOT_WORKING ) +COMP( 1979, h19, 0, 0, h19, h19, driver_device, 0, "Heath Inc", "Heathkit H-19", 0 ) /* TODO - verify the years for these third-party replacement ROMs. */ COMP( 1982, super19, h19, 0, h19, h19, driver_device, 0, "Heath Inc", "Heathkit H-19 w/ Super-19 ROM", MACHINE_NOT_WORKING ) COMP( 1982, watz19, h19, 0, h19, h19, driver_device, 0, "Heath Inc", "Heathkit H-19 w/ Watzman ROM", MACHINE_NOT_WORKING ) -- cgit v1.2.3