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.
This commit is contained in:
Mark Garlanger 2017-02-24 18:58:16 -06:00 committed by Vas Crabb
parent a0aa981a6e
commit 9533352c6b
5 changed files with 655 additions and 184 deletions

View File

@ -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

View File

@ -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

View File

@ -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 <algorithm>
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
// devices
const device_type MM5740 = &device_creator<mm5740_device>;
//**************************************************************************
// 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;
}

View File

@ -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<typename Object> static devcb_base &set_x_cb(device_t &device, Object &&object, uint8_t i)
{
assert(i<9); return downcast<mm5740_device &>(device).m_read_x[i].set_callback(std::forward<Object>(object));
}
template<typename Object> static devcb_base &set_shift_cb(device_t &device, Object &&object)
{
return downcast<mm5740_device &>(device).m_read_shift.set_callback(std::forward<Object>(object));
}
template<typename Object> static devcb_base &set_control_cb(device_t &device, Object &&object)
{
return downcast<mm5740_device &>(device).m_read_control.set_callback(std::forward<Object>(object));
}
template<typename Object> static devcb_base &set_data_ready_cb(device_t &device, Object &&object)
{
return downcast<mm5740_device &>(device).m_write_data_ready.set_callback(std::forward<Object>(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

View File

@ -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<beep_device> m_beep;
required_shared_ptr<uint8_t> m_p_videoram;
required_region_ptr<u8> m_p_chargen;
};
required_device<mm5740_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");
}
if (!m_keyclickactive && !m_bellactive)
{
m_beep->set_state(0);
}
}
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
}
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_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("S401")
PORT_DIPNAME( 0x0f, 0x03, "Baud Rate")
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 )