mirror of
https://github.com/holub/mame
synced 2025-04-20 15:32:45 +03:00
Replaced hacky Kaypro keyboard that bypassed the SIO with emulated
Kaypro 10 keyboard. [Vas Crabb, rfka01, TeamEurope] (nw) This exposes other issues in MAME. Some incredibly poorly-written code in the keyboard MCU depends on the fact that the T register is updated during S4 then copied to A during S4 when mov a,t is executed. If it doesn't see zero in this register when mov a,t is executed immediately before the timer interrupt is taken, it hangs. Really, the MCS-48 core needs to be re-written so it works at S-cycle level (if not clock cycle leve), but for now I've worked around this case in the least intrusive way possible. This also exposes issues in the Z80DART code. The keyboard communicates 0.8% slower than the nominal 300 Baud. This works perfectly in real life, but it causes occasional corrupted characters with MAME's implementation, particularly if you hold a key down and let it repeat. The Z80DART device needs to be fixed so it samples closer to the middle of the bit intervals and re-aquires on each start bit. Finally, I haven't hooked up the Kaypro's serial port Baud rate genrators, or exposed the serial ports as slots. I'll leave that for someone else to worry about.
This commit is contained in:
parent
f1dfb9d544
commit
30361572bd
@ -7,7 +7,13 @@
|
||||
reimplement as a push, not a pull
|
||||
- T0 output clock
|
||||
- get rid of i/o addressmap, use devcb for mcu pins
|
||||
- add CMOS devices, 1 new opcode(01 HALT)
|
||||
- add CMOS devices, 1 new opcode (01 HALT)
|
||||
- make timer update cleaner:
|
||||
timer is updated on S4 while I/O happens on S5
|
||||
due to very bad coding, Kaypro 10 keyboard depends on being able to see T=0 before interrupt is taken
|
||||
right now this is implemented with a hack in the mov_a_t handler
|
||||
in theory it should also be possible to see the timer flag before the interrupt is taken
|
||||
mov_t_a should also update the T register after it's incremented
|
||||
*/
|
||||
|
||||
/***************************************************************************
|
||||
@ -121,24 +127,6 @@
|
||||
MACROS
|
||||
***************************************************************************/
|
||||
|
||||
/* ROM is mapped to AS_PROGRAM */
|
||||
#define program_r(a) m_program->read_byte(a)
|
||||
|
||||
/* RAM is mapped to AS_DATA */
|
||||
#define ram_r(a) m_data->read_byte(a)
|
||||
#define ram_w(a,V) m_data->write_byte(a, V)
|
||||
|
||||
/* ports are mapped to AS_IO and callbacks */
|
||||
#define ext_r(a) m_io->read_byte(a)
|
||||
#define ext_w(a,V) m_io->write_byte(a, V)
|
||||
#define port_r(a) m_port_in_cb[a-1]()
|
||||
#define port_w(a,V) m_port_out_cb[a-1](V)
|
||||
#define test_r(a) m_test_in_cb[a]()
|
||||
#define test_w(a,V) m_test_out_cb[a](V)
|
||||
#define bus_r() m_bus_in_cb()
|
||||
#define bus_w(V) m_bus_out_cb(V)
|
||||
#define prog_w(V) m_prog_out_cb(V)
|
||||
|
||||
/* r0-r7 map to memory via the regptr */
|
||||
#define R0 m_regptr[0]
|
||||
#define R1 m_regptr[1]
|
||||
@ -151,24 +139,24 @@
|
||||
|
||||
|
||||
|
||||
DEFINE_DEVICE_TYPE(I8021, i8021_device, "i8021", "I8021")
|
||||
DEFINE_DEVICE_TYPE(I8022, i8022_device, "i8022", "I8022")
|
||||
DEFINE_DEVICE_TYPE(I8035, i8035_device, "i8035", "I8035")
|
||||
DEFINE_DEVICE_TYPE(I8048, i8048_device, "i8048", "I8048")
|
||||
DEFINE_DEVICE_TYPE(I8648, i8648_device, "i8648", "I8648")
|
||||
DEFINE_DEVICE_TYPE(I8748, i8748_device, "i8748", "I8748")
|
||||
DEFINE_DEVICE_TYPE(I8039, i8039_device, "i8039", "I8039")
|
||||
DEFINE_DEVICE_TYPE(I8049, i8049_device, "i8049", "I8049")
|
||||
DEFINE_DEVICE_TYPE(I8749, i8749_device, "i8749", "I8749")
|
||||
DEFINE_DEVICE_TYPE(I8040, i8040_device, "i8040", "I8040")
|
||||
DEFINE_DEVICE_TYPE(I8050, i8050_device, "i8050", "I8050")
|
||||
DEFINE_DEVICE_TYPE(I8041, i8041_device, "i8041", "I8041")
|
||||
DEFINE_DEVICE_TYPE(I8741, i8741_device, "i8741", "I8741")
|
||||
DEFINE_DEVICE_TYPE(I8042, i8042_device, "i8042", "I8042")
|
||||
DEFINE_DEVICE_TYPE(I8242, i8242_device, "i8242", "I8242")
|
||||
DEFINE_DEVICE_TYPE(I8742, i8742_device, "i8742", "I8742")
|
||||
DEFINE_DEVICE_TYPE(I8021, i8021_device, "i8021", "I8021")
|
||||
DEFINE_DEVICE_TYPE(I8022, i8022_device, "i8022", "I8022")
|
||||
DEFINE_DEVICE_TYPE(I8035, i8035_device, "i8035", "I8035")
|
||||
DEFINE_DEVICE_TYPE(I8048, i8048_device, "i8048", "I8048")
|
||||
DEFINE_DEVICE_TYPE(I8648, i8648_device, "i8648", "I8648")
|
||||
DEFINE_DEVICE_TYPE(I8748, i8748_device, "i8748", "I8748")
|
||||
DEFINE_DEVICE_TYPE(I8039, i8039_device, "i8039", "I8039")
|
||||
DEFINE_DEVICE_TYPE(I8049, i8049_device, "i8049", "I8049")
|
||||
DEFINE_DEVICE_TYPE(I8749, i8749_device, "i8749", "I8749")
|
||||
DEFINE_DEVICE_TYPE(I8040, i8040_device, "i8040", "I8040")
|
||||
DEFINE_DEVICE_TYPE(I8050, i8050_device, "i8050", "I8050")
|
||||
DEFINE_DEVICE_TYPE(I8041, i8041_device, "i8041", "I8041")
|
||||
DEFINE_DEVICE_TYPE(I8741, i8741_device, "i8741", "I8741")
|
||||
DEFINE_DEVICE_TYPE(I8042, i8042_device, "i8042", "I8042")
|
||||
DEFINE_DEVICE_TYPE(I8242, i8242_device, "i8242", "I8242")
|
||||
DEFINE_DEVICE_TYPE(I8742, i8742_device, "i8742", "I8742")
|
||||
DEFINE_DEVICE_TYPE(MB8884, mb8884_device, "mb8884", "MB8884")
|
||||
DEFINE_DEVICE_TYPE(N7751, n7751_device, "n7751", "N7751")
|
||||
DEFINE_DEVICE_TYPE(N7751, n7751_device, "n7751", "N7751")
|
||||
DEFINE_DEVICE_TYPE(M58715, m58715_device, "m58715", "M58715")
|
||||
|
||||
|
||||
@ -756,7 +744,7 @@ OPHANDLER( mov_a_r6 ) { m_a = R6; return 1; }
|
||||
OPHANDLER( mov_a_r7 ) { m_a = R7; return 1; }
|
||||
OPHANDLER( mov_a_xr0 ) { m_a = ram_r(R0); return 1; }
|
||||
OPHANDLER( mov_a_xr1 ) { m_a = ram_r(R1); return 1; }
|
||||
OPHANDLER( mov_a_t ) { m_a = m_timer; return 1; }
|
||||
OPHANDLER( mov_a_t ) { m_a = m_timer + ((m_timecount_enabled & TIMER_ENABLED) ? 1 : 0); return 1; }
|
||||
|
||||
OPHANDLER( mov_psw_a ) { m_psw = m_a; update_regptr(); return 1; }
|
||||
OPHANDLER( mov_sts_a ) { m_sts = (m_sts & 0x0f) | (m_a & 0xf0); return 1; }
|
||||
|
@ -242,6 +242,23 @@ protected:
|
||||
typedef int (mcs48_cpu_device::*mcs48_ophandler)();
|
||||
static const mcs48_ophandler s_opcode_table[256];
|
||||
|
||||
/* ROM is mapped to AS_PROGRAM */
|
||||
uint8_t program_r(offs_t a) { return m_program->read_byte(a); }
|
||||
|
||||
/* RAM is mapped to AS_DATA */
|
||||
uint8_t ram_r(offs_t a) { return m_data->read_byte(a); }
|
||||
void ram_w(offs_t a, uint8_t v) { m_data->write_byte(a, v); }
|
||||
|
||||
/* ports are mapped to AS_IO and callbacks */
|
||||
uint8_t ext_r(offs_t a) { return m_io->read_byte(a); }
|
||||
void ext_w(offs_t a, uint8_t v) { m_io->write_byte(a, v); }
|
||||
uint8_t port_r(offs_t a) { return m_port_in_cb[a - 1](); }
|
||||
void port_w(offs_t a, uint8_t v) { m_port_out_cb[a - 1](v); }
|
||||
int test_r(offs_t a) { return m_test_in_cb[a](); }
|
||||
uint8_t bus_r() { return m_bus_in_cb(); }
|
||||
void bus_w(uint8_t v) { m_bus_out_cb(v); }
|
||||
void prog_w(int v) { m_prog_out_cb(v); }
|
||||
|
||||
uint8_t opcode_fetch();
|
||||
uint8_t argument_fetch();
|
||||
void update_regptr();
|
||||
|
@ -43,13 +43,15 @@
|
||||
|
||||
#include "emu.h"
|
||||
#include "includes/kaypro.h"
|
||||
|
||||
#include "machine/kay_kbd.h"
|
||||
|
||||
#include "machine/clock.h"
|
||||
#include "formats/kaypro_dsk.h"
|
||||
#include "screen.h"
|
||||
#include "softlist.h"
|
||||
#include "speaker.h"
|
||||
|
||||
|
||||
READ8_MEMBER( kaypro_state::kaypro2x_87_r ) { return 0x7f; } /* to bypass unemulated HD controller */
|
||||
|
||||
/***********************************************************
|
||||
@ -68,7 +70,7 @@ static ADDRESS_MAP_START( kayproii_io, AS_IO, 8, kaypro_state )
|
||||
ADDRESS_MAP_GLOBAL_MASK(0xff)
|
||||
ADDRESS_MAP_UNMAP_HIGH
|
||||
AM_RANGE(0x00, 0x03) AM_DEVWRITE("brg", com8116_device, stt_w)
|
||||
AM_RANGE(0x04, 0x07) AM_READWRITE(kaypro_sio_r, kaypro_sio_w)
|
||||
AM_RANGE(0x04, 0x07) AM_DEVREADWRITE("z80sio", z80sio0_device, cd_ba_r, cd_ba_w)
|
||||
AM_RANGE(0x08, 0x0b) AM_DEVREADWRITE("z80pio_g", z80pio_device, read_alt, write_alt)
|
||||
AM_RANGE(0x0c, 0x0f) AM_DEVWRITE("brg", com8116_device, str_w)
|
||||
AM_RANGE(0x10, 0x13) AM_DEVREADWRITE("fdc", fd1793_device, read, write)
|
||||
@ -79,7 +81,7 @@ static ADDRESS_MAP_START( kaypro2x_io, AS_IO, 8, kaypro_state )
|
||||
ADDRESS_MAP_GLOBAL_MASK(0xff)
|
||||
ADDRESS_MAP_UNMAP_HIGH
|
||||
AM_RANGE(0x00, 0x03) AM_DEVWRITE("brg", com8116_device, str_w)
|
||||
AM_RANGE(0x04, 0x07) AM_READWRITE(kaypro_sio_r, kaypro_sio_w)
|
||||
AM_RANGE(0x04, 0x07) AM_DEVREADWRITE("z80sio", z80sio0_device, cd_ba_r, cd_ba_w)
|
||||
AM_RANGE(0x08, 0x0b) AM_DEVWRITE("brg", com8116_device, stt_w)
|
||||
AM_RANGE(0x0c, 0x0f) AM_DEVREADWRITE("z80sio_2x", z80sio0_device, ba_cd_r, ba_cd_w)
|
||||
AM_RANGE(0x10, 0x13) AM_DEVREADWRITE("fdc", fd1793_device, read, write)
|
||||
@ -105,6 +107,11 @@ static ADDRESS_MAP_START( kaypro2x_io, AS_IO, 8, kaypro_state )
|
||||
ADDRESS_MAP_END
|
||||
|
||||
|
||||
static INPUT_PORTS_START(kaypro)
|
||||
// everything comes from the keyboard device
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
/***************************************************************
|
||||
|
||||
F4 CHARACTER DISPLAYER
|
||||
@ -199,7 +206,6 @@ static MACHINE_CONFIG_START( kayproii )
|
||||
MCFG_CPU_ADD("maincpu", Z80, XTAL_20MHz / 8)
|
||||
MCFG_CPU_PROGRAM_MAP(kaypro_map)
|
||||
MCFG_CPU_IO_MAP(kayproii_io)
|
||||
MCFG_CPU_VBLANK_INT_DRIVER("screen", kaypro_state, kay_kbd_interrupt) /* this doesn't actually exist, it is to run the keyboard */
|
||||
MCFG_Z80_DAISY_CHAIN(kayproii_daisy_chain)
|
||||
|
||||
MCFG_MACHINE_START_OVERRIDE(kaypro_state, kayproii )
|
||||
@ -226,6 +232,12 @@ static MACHINE_CONFIG_START( kayproii )
|
||||
/* devices */
|
||||
MCFG_QUICKLOAD_ADD("quickload", kaypro_state, kaypro, "com,cpm", 3)
|
||||
|
||||
MCFG_DEVICE_ADD("kbd", KAYPRO_10_KEYBOARD, 0)
|
||||
MCFG_KAYPRO10KBD_RXD_CB(DEVWRITELINE("z80sio", z80sio0_device, rxb_w))
|
||||
|
||||
MCFG_CLOCK_ADD("kbdtxrxc", 4800)
|
||||
MCFG_CLOCK_SIGNAL_HANDLER(DEVWRITELINE("z80sio", z80sio0_device, rxtxcb_w))
|
||||
|
||||
MCFG_CENTRONICS_ADD("centronics", centronics_devices, "printer")
|
||||
MCFG_CENTRONICS_BUSY_HANDLER(WRITELINE(kaypro_state, write_centronics_busy))
|
||||
|
||||
@ -244,6 +256,7 @@ static MACHINE_CONFIG_START( kayproii )
|
||||
|
||||
MCFG_DEVICE_ADD("z80sio", Z80SIO0, XTAL_20MHz / 8)
|
||||
MCFG_Z80DART_OUT_INT_CB(INPUTLINE("maincpu", INPUT_LINE_IRQ0))
|
||||
MCFG_Z80DART_OUT_TXDB_CB(DEVWRITELINE("kbd", kaypro_10_keyboard_device, txd_w))
|
||||
|
||||
MCFG_FD1793_ADD("fdc", XTAL_20MHz / 20)
|
||||
MCFG_WD_FDC_INTRQ_CALLBACK(WRITELINE(kaypro_state, fdc_intrq_w))
|
||||
@ -269,7 +282,6 @@ static MACHINE_CONFIG_START( kaypro2x )
|
||||
MCFG_CPU_ADD("maincpu", Z80, XTAL_16MHz / 4)
|
||||
MCFG_CPU_PROGRAM_MAP(kaypro_map)
|
||||
MCFG_CPU_IO_MAP(kaypro2x_io)
|
||||
MCFG_CPU_VBLANK_INT_DRIVER("screen", kaypro_state, kay_kbd_interrupt)
|
||||
MCFG_Z80_DAISY_CHAIN(kaypro2x_daisy_chain)
|
||||
|
||||
MCFG_MACHINE_RESET_OVERRIDE(kaypro_state, kaypro )
|
||||
@ -300,6 +312,12 @@ static MACHINE_CONFIG_START( kaypro2x )
|
||||
|
||||
MCFG_QUICKLOAD_ADD("quickload", kaypro_state, kaypro, "com,cpm", 3)
|
||||
|
||||
MCFG_DEVICE_ADD("kbd", KAYPRO_10_KEYBOARD, 0)
|
||||
MCFG_KAYPRO10KBD_RXD_CB(DEVWRITELINE("z80sio", z80sio0_device, rxb_w))
|
||||
|
||||
MCFG_CLOCK_ADD("kbdtxrxc", 4800)
|
||||
MCFG_CLOCK_SIGNAL_HANDLER(DEVWRITELINE("z80sio", z80sio0_device, rxtxcb_w))
|
||||
|
||||
MCFG_CENTRONICS_ADD("centronics", centronics_devices, "printer")
|
||||
MCFG_CENTRONICS_BUSY_HANDLER(WRITELINE(kaypro_state, write_centronics_busy))
|
||||
|
||||
@ -307,6 +325,7 @@ static MACHINE_CONFIG_START( kaypro2x )
|
||||
|
||||
MCFG_DEVICE_ADD("z80sio", Z80SIO0, XTAL_16MHz / 4)
|
||||
MCFG_Z80DART_OUT_INT_CB(INPUTLINE("maincpu", INPUT_LINE_IRQ0))
|
||||
MCFG_Z80DART_OUT_TXDB_CB(DEVWRITELINE("kbd", kaypro_10_keyboard_device, txd_w))
|
||||
|
||||
MCFG_DEVICE_ADD("z80sio_2x", Z80SIO0, XTAL_16MHz / 4) /* extra sio for modem and printer */
|
||||
MCFG_Z80DART_OUT_INT_CB(INPUTLINE("maincpu", INPUT_LINE_IRQ0))
|
||||
@ -465,14 +484,14 @@ ROM_START(robie)
|
||||
ROM_LOAD("81-235.u9", 0x0000, 0x1000, CRC(5f72da5b) SHA1(8a597000cce1a7e184abfb7bebcb564c6bf24fb7) )
|
||||
ROM_END
|
||||
|
||||
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME */
|
||||
COMP( 1982, kayproii, 0, 0, kayproii, kay_kbd, kaypro_state, kaypro, "Non Linear Systems", "Kaypro II - 2/83" , 0 )
|
||||
COMP( 1983, kaypro4, kayproii, 0, kaypro4, kay_kbd, kaypro_state, kaypro, "Non Linear Systems", "Kaypro 4 - 4/83" , 0 ) // model 81-004
|
||||
COMP( 1983, kaypro4p88, kayproii, 0, kaypro4, kay_kbd, kaypro_state, kaypro, "Non Linear Systems", "Kaypro 4 plus88 - 4/83" , MACHINE_NOT_WORKING ) // model 81-004 with an added 8088 daughterboard and rom
|
||||
COMP( 198?, omni2, kayproii, 0, omni2, kay_kbd, kaypro_state, kaypro, "Non Linear Systems", "Omni II Logic Analyzer" , 0 )
|
||||
COMP( 198?, omni4, kaypro2x, 0, kaypro2x, kay_kbd, kaypro_state, kaypro, "Omni Logic Inc.", "Omni 4 Logic Analyzer" , MACHINE_NOT_WORKING )
|
||||
COMP( 1984, kaypro2x, 0, 0, kaypro2x, kay_kbd, kaypro_state, kaypro, "Non Linear Systems", "Kaypro 2x" , MACHINE_NOT_WORKING ) // model 81-025
|
||||
COMP( 1984, kaypro4a, kaypro2x, 0, kaypro2x, kay_kbd, kaypro_state, kaypro, "Non Linear Systems", "Kaypro 4 - 4/84" , MACHINE_NOT_WORKING ) // model 81-015
|
||||
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME */
|
||||
COMP( 1982, kayproii, 0, 0, kayproii, kaypro, kaypro_state, kaypro, "Non Linear Systems", "Kaypro II - 2/83" , 0 )
|
||||
COMP( 1983, kaypro4, kayproii, 0, kaypro4, kaypro, kaypro_state, kaypro, "Non Linear Systems", "Kaypro 4 - 4/83" , 0 ) // model 81-004
|
||||
COMP( 1983, kaypro4p88, kayproii, 0, kaypro4, kaypro, kaypro_state, kaypro, "Non Linear Systems", "Kaypro 4 plus88 - 4/83" , MACHINE_NOT_WORKING ) // model 81-004 with an added 8088 daughterboard and rom
|
||||
COMP( 198?, omni2, kayproii, 0, omni2, kaypro, kaypro_state, kaypro, "Non Linear Systems", "Omni II Logic Analyzer" , 0 )
|
||||
COMP( 198?, omni4, kaypro2x, 0, kaypro2x, kaypro, kaypro_state, kaypro, "Omni Logic Inc.", "Omni 4 Logic Analyzer" , MACHINE_NOT_WORKING )
|
||||
COMP( 1984, kaypro2x, 0, 0, kaypro2x, kaypro, kaypro_state, kaypro, "Non Linear Systems", "Kaypro 2x" , MACHINE_NOT_WORKING ) // model 81-025
|
||||
COMP( 1984, kaypro4a, kaypro2x, 0, kaypro2x, kaypro, kaypro_state, kaypro, "Non Linear Systems", "Kaypro 4 - 4/84" , MACHINE_NOT_WORKING ) // model 81-015
|
||||
// Kaypro 4/84 plus 88 goes here, model 81-015 with an added 8088 daughterboard and rom
|
||||
COMP( 1983, kaypro10, 0, 0, kaypro10, kay_kbd, kaypro_state, kaypro, "Non Linear Systems", "Kaypro 10" , MACHINE_NOT_WORKING ) // model 81-005
|
||||
COMP( 1984, robie, 0, 0, kaypro2x, kay_kbd, kaypro_state, kaypro, "Non Linear Systems", "Kaypro Robie" , MACHINE_NOT_WORKING ) // model 81-005
|
||||
COMP( 1983, kaypro10, 0, 0, kaypro10, kaypro, kaypro_state, kaypro, "Non Linear Systems", "Kaypro 10" , MACHINE_NOT_WORKING ) // model 81-005
|
||||
COMP( 1984, robie, 0, 0, kaypro2x, kaypro, kaypro_state, kaypro, "Non Linear Systems", "Kaypro Robie" , MACHINE_NOT_WORKING ) // model 81-005
|
||||
|
@ -16,8 +16,6 @@
|
||||
#include "video/mc6845.h"
|
||||
#include "machine/wd_fdc.h"
|
||||
|
||||
struct kay_kbd_t;
|
||||
|
||||
class kaypro_state : public driver_device
|
||||
{
|
||||
public:
|
||||
@ -63,19 +61,14 @@ public:
|
||||
DECLARE_MACHINE_RESET(kaypro);
|
||||
DECLARE_VIDEO_START(kaypro);
|
||||
DECLARE_PALETTE_INIT(kaypro);
|
||||
DECLARE_MACHINE_RESET(kay_kbd);
|
||||
DECLARE_DRIVER_INIT(kaypro);
|
||||
DECLARE_FLOPPY_FORMATS(kayproii_floppy_formats);
|
||||
DECLARE_FLOPPY_FORMATS(kaypro2x_floppy_formats);
|
||||
uint32_t screen_update_kayproii(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
uint32_t screen_update_kaypro2x(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
uint32_t screen_update_omni2(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
INTERRUPT_GEN_MEMBER(kay_kbd_interrupt);
|
||||
DECLARE_READ8_MEMBER(kaypro_sio_r);
|
||||
DECLARE_WRITE8_MEMBER(kaypro_sio_w);
|
||||
MC6845_UPDATE_ROW(kaypro2x_update_row);
|
||||
DECLARE_QUICKLOAD_LOAD_MEMBER(kaypro);
|
||||
TIMER_CALLBACK_MEMBER( kay_kbd_beepoff );
|
||||
|
||||
private:
|
||||
uint8_t m_mc6845_cursor[16];
|
||||
@ -83,12 +76,7 @@ private:
|
||||
uint8_t m_mc6845_ind;
|
||||
uint8_t m_framecnt;
|
||||
uint8_t *m_p_videoram;
|
||||
kay_kbd_t *m_kbd;
|
||||
int m_centronics_busy;
|
||||
void kay_kbd_in(uint8_t data );
|
||||
uint8_t kay_kbd_c_r();
|
||||
uint8_t kay_kbd_d_r();
|
||||
void kay_kbd_d_w( uint8_t data );
|
||||
bool m_is_motor_off;
|
||||
uint8_t m_fdc_rq;
|
||||
uint8_t m_system_port;
|
||||
|
@ -1,28 +1,16 @@
|
||||
// license:GPL-2.0+
|
||||
// copyright-holders:Juergen Buchmueller
|
||||
// copyright-holders:Vas Crabb
|
||||
/******************************************************************************
|
||||
*
|
||||
* kay_kbd.c
|
||||
* kay_kbd.cpp
|
||||
*
|
||||
* Kaypro II Serial Keyboard
|
||||
*
|
||||
* Most of this is copied from the old kaypro.c,
|
||||
* rather than re-inventing the wheel.
|
||||
*
|
||||
* Juergen Buchmueller, July 1998
|
||||
* Benjamin C. W. Sittler, July 1998 (new keyboard table)
|
||||
*
|
||||
* Converted to a serial device (as far as MESS will allow)
|
||||
* by Robbbert, April 2009.
|
||||
* Kaypro Serial Keyboards
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "machine/kay_kbd.h"
|
||||
|
||||
#include "sound/beep.h"
|
||||
#include "includes/kaypro.h"
|
||||
|
||||
|
||||
/*
|
||||
* The KAYPRO keyboard has roughly the following layout:
|
||||
@ -49,463 +37,365 @@
|
||||
* arrow graphics pointing in the appropriate directions. The F and J keys are specially shaped,
|
||||
* since they are the "home keys" for touch-typing. The CAPS LOCK key has a build-in red indicator
|
||||
* which is lit when CAPS LOCK is pressed once, and extinguished when the key is pressed again.
|
||||
*
|
||||
* Technical Notes
|
||||
* ---------------
|
||||
* The keyboard interfaces to the computer using a serial protocol. Modifier keys are handled
|
||||
* inside the keyboards, as is the CAPS LOCK key. The arrow keys and the numeric keypad send
|
||||
* non-ASCII codes which are not affected by the modifier keys. The remaining keys send the
|
||||
* appropriate ASCII values.
|
||||
*
|
||||
* The keyboard has a built-in buzzer which is activated briefly by a non-modifier keypress,
|
||||
* producing a "clicking" sound for user feedback. Additionally, this buzzer can be activated
|
||||
* for a longer period by sending a 0x04 byte to the keyboard. This is used by the ROM soft
|
||||
* terminal to alert the user in case of a BEL.
|
||||
*
|
||||
* 2008-05 FP:
|
||||
* Small note about natural keyboard support: currently,
|
||||
* - "Line Feed" is mapped to the 'End' key
|
||||
* - "Keypad ," is not mapped
|
||||
*/
|
||||
|
||||
struct kay_kbd_t
|
||||
{
|
||||
beep_device *beeper;
|
||||
uint8_t buff[16];
|
||||
uint8_t head;
|
||||
uint8_t tail;
|
||||
uint8_t beep_on;
|
||||
uint8_t control_status;
|
||||
uint8_t keyrows[10];
|
||||
int lastrow;
|
||||
int mask;
|
||||
int key;
|
||||
int repeat;
|
||||
int repeater;
|
||||
};
|
||||
|
||||
INPUT_PORTS_START( kay_kbd )
|
||||
PORT_START("ROW0")
|
||||
PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC))
|
||||
PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
|
||||
PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@')
|
||||
PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
|
||||
PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
|
||||
PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
|
||||
PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^')
|
||||
PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')
|
||||
/*
|
||||
Kaypro 10 keyboard
|
||||
|
||||
PORT_START("ROW1")
|
||||
PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')
|
||||
PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
|
||||
PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
|
||||
PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_')
|
||||
PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
|
||||
PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~')
|
||||
PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("BACK SPACE") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
|
||||
PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR('\t')
|
||||
This is a TTL-level asynchronous serial keyboard using mask-programmed
|
||||
MCS-48 MCU. Serial transmission and reception are handled in software
|
||||
using the onboard timer/counter interrupt. The frame format is 1 start
|
||||
bit, 8 data bits, no parity, and 1 stop bit.
|
||||
|
||||
PORT_START("ROW2")
|
||||
PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
|
||||
PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
|
||||
PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
|
||||
PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
|
||||
PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
|
||||
PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
|
||||
PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
|
||||
PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
|
||||
Active components:
|
||||
* Mitsubishi M5L8049-109P-6 (MCS-48 MCU with 2KiB mask ROM)
|
||||
* SN74154N (4-to-16 demultiplexer)
|
||||
* DM7406N (hex inverter with open collector outputs)
|
||||
* SN75451BP (dual high-speed, high-current line driver with AND inputs)
|
||||
* 6.000MHz crystal
|
||||
|
||||
PORT_START("ROW3")
|
||||
PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
|
||||
PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
|
||||
PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{')
|
||||
PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')
|
||||
PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("RETURN") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
|
||||
PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("DEL") PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL))
|
||||
PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2)
|
||||
PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK))
|
||||
D0-D3 select the key matrix row, only 0x0..0xE are used (0x0F ignored).
|
||||
|
||||
PORT_START("ROW4")
|
||||
PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
|
||||
PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
|
||||
PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
|
||||
PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
|
||||
PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
|
||||
PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
|
||||
PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
|
||||
PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
|
||||
D4 is the CAPS LOCK LED output.
|
||||
|
||||
PORT_START("ROW5")
|
||||
PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
|
||||
PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
|
||||
PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"')
|
||||
PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|')
|
||||
PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_MAMEKEY(LSHIFT))
|
||||
PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
|
||||
PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
|
||||
PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
|
||||
P1 is connected to the key matrix columns.
|
||||
|
||||
PORT_START("ROW6")
|
||||
PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
|
||||
PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
|
||||
PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
|
||||
PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
|
||||
PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
|
||||
PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
|
||||
PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
|
||||
PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_MAMEKEY(RSHIFT))
|
||||
P2.1, P2.2 and P2.3 are CTRL, CAPS LOCK, and SHIFT inputs.
|
||||
|
||||
PORT_START("ROW7")
|
||||
PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("LINE FEED") PORT_CODE(KEYCODE_END) PORT_CHAR(UCHAR_MAMEKEY(END))
|
||||
PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
|
||||
PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD))
|
||||
PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("Keypad ,") PORT_CODE(KEYCODE_PLUS_PAD)
|
||||
PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD))
|
||||
PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD))
|
||||
PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD))
|
||||
PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD))
|
||||
P2.6 drives the speaker (1.5625kHz tone generated using timer/counter).
|
||||
|
||||
PORT_START("ROW8")
|
||||
PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD))
|
||||
PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD))
|
||||
PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD))
|
||||
PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD))
|
||||
PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD))
|
||||
PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD))
|
||||
PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD))
|
||||
PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD))
|
||||
P2.7 is the serial data output to the host.
|
||||
|
||||
PORT_START("ROW9")
|
||||
PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("\xE2\x86\x91") PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
|
||||
PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("\xE2\x86\x93") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
|
||||
PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("\xE2\x86\x90") PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
|
||||
PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("\xE2\x86\x92") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
|
||||
PORT_BIT(0xf0, 0x00, IPT_UNUSED)
|
||||
T1 is the serial data input from the host.
|
||||
|
||||
The program appears to be able to support "typewriter shift" and
|
||||
"bitshift" layouts, and both ASCII and Kaypro control codes for the
|
||||
numeric keypad, depending on how the matrix is wired. All positions in
|
||||
the key matrix will produce characters, although it's not clear whether
|
||||
all of them are designed to serve a purpose - some may just be emergent
|
||||
behaviour from the decoding algorithm.
|
||||
|
||||
The serial rate is generated by reloading the T register with 0xfe and
|
||||
transfering a bit every 21 interrupts, giving a rate within 1% of the
|
||||
desired 300 Baud:
|
||||
6MHz / 15 / 32 / (0x100 - 0xfe) / 21 = 297.62 Baud
|
||||
|
||||
This scheme allows only 64 machine cycles between interrupts, and more
|
||||
than half of thse are consumed by the timer service routine itself.
|
||||
|
||||
The program ROM checksum routine is supposed to compute the sum of all
|
||||
program ROM bytes modulo 256 and the XOR of all program ROM bytes, but
|
||||
due to bugs it omits the first byte of each page (0x000, 0x100, 0x200,
|
||||
0x300, 0x400, 0x500, 0x600 and 0x700).
|
||||
|
||||
The serial command processing is quite lax in what it accepts:
|
||||
xxxx xxx1 ignored
|
||||
xxxx xx10 short beep
|
||||
xxxx x100 long beep
|
||||
xxx1 x000 answer back with 0xAA?
|
||||
|
||||
The Kaypro II was sold with a different keyboard using an 8751 (MCS-51)
|
||||
MCU, but we don't have a dump for it.
|
||||
*/
|
||||
#include "cpu/mcs48/mcs48.h"
|
||||
#include "speaker.h"
|
||||
|
||||
|
||||
DEFINE_DEVICE_TYPE(KAYPRO_10_KEYBOARD, kaypro_10_keyboard_device, "kaypro10kbd", "Kaypro 10 Keyboard")
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
ROM_START(kaypro_10_keyboard)
|
||||
ROM_REGION(0x0800, "mcu", 0)
|
||||
ROM_LOAD("m5l8049.bin", 0x0000, 0x0800, CRC(dc772f80) SHA1(aa7cd3f476466203294675d56098dff45952b9b0))
|
||||
ROM_END
|
||||
|
||||
INPUT_PORTS_START(kaypro_keyboard_typewriter)
|
||||
PORT_START("ROW.0")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) PORT_NAME("Pad 0")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) PORT_NAME("Pad 3")
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) PORT_NAME("Pad 6")
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) PORT_NAME("Pad 9")
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNKNOWN) // 0xf8
|
||||
|
||||
PORT_START("ROW.1")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNKNOWN) // 0xa5
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) PORT_NAME("Pad 2")
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) PORT_NAME("Pad 5")
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) PORT_NAME("Pad 8")
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNKNOWN) // 0xf7
|
||||
|
||||
PORT_START("ROW.2")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNKNOWN) // 0xa4
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^')
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) PORT_NAME("Pad 1")
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) PORT_NAME("Pad 4")
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) PORT_NAME("Pad 7")
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNKNOWN) // 0xf6
|
||||
|
||||
PORT_START("ROW.3")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RALT) PORT_CHAR(10) PORT_NAME("LINE FEED")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|')
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL)) PORT_NAME("DEL")
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNKNOWN) // 0xe0
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNKNOWN) // 0xf5
|
||||
|
||||
PORT_START("ROW.4")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNKNOWN) // 0xa3
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) PORT_NAME("RETURN")
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNKNOWN) // 0xd4
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) PORT_NAME("BACK SPACE")
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
|
||||
|
||||
PORT_START("ROW.5")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"')
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~')
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
|
||||
|
||||
PORT_START("ROW.6")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_')
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
|
||||
|
||||
PORT_START("ROW.7")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNKNOWN) // 0xa2
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{')
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
|
||||
|
||||
PORT_START("ROW.8")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNKNOWN) // 0xa1
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@')
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR(';')
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNKNOWN) // 0xf0
|
||||
|
||||
PORT_START("ROW.9")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNKNOWN) // 0xa0
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNKNOWN) // 0xb0
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR('\t')
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC))
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNKNOWN) // 0xfe
|
||||
|
||||
PORT_START("ROW.A")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) PORT_NAME("Pad .")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) PORT_NAME("Pad ENTER")
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_PLUS_PAD) PORT_NAME("Pad ,")
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PORT_NAME("Pad -")
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNKNOWN) // 0xf9
|
||||
|
||||
PORT_START("ROW.B")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) // 2 for ASCII keypad
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED) // 1 for ASCII keypad
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED) // 0 for "bitshift" layout or ASCII keypad
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED) // 7 for ASCII keypad
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) // 0 for "bitshift" layout or ASCII keypad
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED) // 9 for ASCII keypad
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) // 8 for ASCII keypad
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) // . for ASCII keypad
|
||||
|
||||
PORT_START("ROW.C")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) // 6 & for "bitshift" layout
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED) // 3 # for "bitshift" layout? identical to "typewriter shift" anyway
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED) // 2 " for "bitshift" layout
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED) // "typewriter shift" 2 @ duplicated here
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) // 6 for ASCII keypad
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED) // 5 for ASCII keypad
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) // 4 for ASCII keypad
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) // 3 for ASCII keypad
|
||||
|
||||
PORT_START("ROW.D")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) // ` @ for "bitshift" layout
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED) // - = for "bitshift" layout
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED) // : * for "bitshift" layout
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED) // ~ ^ for "bitshift" layout
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) // "typewriter shift" 6 ^ duplicated here
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED) // 9 ) for "bitshift" layout
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) // 8 ( for "bitshift" layout
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) // 7 ' for "bitshift" layout
|
||||
|
||||
PORT_START("ROW.E")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNKNOWN) // 0xe0
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNKNOWN) // 0x90
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNKNOWN) // 0xa0
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNKNOWN) // 0x00
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNKNOWN) // 0xe0
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNKNOWN) // 0xc0
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNKNOWN) // 0x54
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) // ; + for "bitshift" layout
|
||||
|
||||
PORT_START("ROW.F")
|
||||
PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNUSED) // not scanned
|
||||
|
||||
PORT_START("MOD")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_SHIFT_2) PORT_NAME("CTRL")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_NAME("CAPS LOCK")
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) PORT_NAME("SHIFT")
|
||||
INPUT_PORTS_END
|
||||
|
||||
static const uint8_t keyboard[8][10][8] = {
|
||||
{ /* normal */
|
||||
{ 27,'1','2','3','4','5','6','7'},
|
||||
{'8','9','0','-','=','`', 8, 9},
|
||||
{'q','w','e','r','t','y','u','i'},
|
||||
{'o','p','[',']', 13,127, 0, 0},
|
||||
{'a','s','d','f','g','h','j','k'},
|
||||
{'l',';', 39, 92, 0,'z','x','c'},
|
||||
{'v','b','n','m',',','.','/', 0},
|
||||
{ 10, 32, 228, 211, 195, 178, 177, 192},
|
||||
{ 193, 194, 208, 209, 210, 225, 226, 227},
|
||||
{ 241, 242, 243, 244, 0, 0, 0, 0},
|
||||
},
|
||||
{ /* Shift */
|
||||
{ 27,'!','@','#','$','%','^','&'},
|
||||
{'*','(',')','_','+','~', 8, 9},
|
||||
{'Q','W','E','R','T','Y','U','I'},
|
||||
{'O','P','{','}', 13,127, 0, 0},
|
||||
{'A','S','D','F','G','H','J','K'},
|
||||
{'L',':','"','|', 0,'Z','X','C'},
|
||||
{'V','B','N','M','<','>','?', 0},
|
||||
{ 10, 32, 228, 211, 195, 178, 177, 192},
|
||||
{ 193, 194, 208, 209, 210, 225, 226, 227},
|
||||
{ 241, 242, 243, 244, 0, 0, 0, 0},
|
||||
},
|
||||
{ /* Control */
|
||||
{ 27,'1','2','3','4','5','6','7'},
|
||||
{'8','9','0','-','=','`', 8, 9},
|
||||
{ 17, 23, 5, 18, 20, 25, 21, 9},
|
||||
{ 15, 16, 27, 29, 13,127, 0, 0},
|
||||
{ 1, 19, 4, 6, 7, 8, 10, 11},
|
||||
{ 12,';', 39, 28, 0, 26, 24, 3},
|
||||
{ 22, 2, 14, 13,',','.','/', 0},
|
||||
{ 10, 32, 228, 211, 195, 178, 177, 192},
|
||||
{ 193, 194, 208, 209, 210, 225, 226, 227},
|
||||
{ 241, 242, 243, 244, 0, 0, 0, 0},
|
||||
},
|
||||
{ /* Shift+Control */
|
||||
{ 27,'!', 0,'#','$','%', 30,'&'},
|
||||
{'*','(',')', 31,'+','~', 8, 9},
|
||||
{ 17, 23, 5, 18, 20, 25, 21, 9},
|
||||
{ 15, 16, 27, 29, 13,127, 0, 0},
|
||||
{ 1, 19, 4, 6, 7, 8, 10, 11},
|
||||
{ 12,':','"', 28, 0, 26, 24, 3},
|
||||
{ 22, 2, 14, 13,',','.','/', 0},
|
||||
{ 10, 32, 228, 211, 195, 178, 177, 192},
|
||||
{ 193, 194, 208, 209, 210, 225, 226, 227},
|
||||
{ 241, 242, 243, 244, 0, 0, 0, 0},
|
||||
},
|
||||
{ /* CapsLock */
|
||||
{ 27,'1','2','3','4','5','6','7'},
|
||||
{'8','9','0','-','=','`', 8, 9},
|
||||
{'Q','W','E','R','T','Y','U','I'},
|
||||
{'O','P','[',']', 13,127, 0, 0},
|
||||
{'A','S','D','F','G','H','J','K'},
|
||||
{'L',';', 39, 92, 0,'Z','X','C'},
|
||||
{'V','B','N','M',',','.','/', 0},
|
||||
{ 10, 32, 228, 211, 195, 178, 177, 192},
|
||||
{ 193, 194, 208, 209, 210, 225, 226, 227},
|
||||
{ 241, 242, 243, 244, 0, 0, 0, 0},
|
||||
},
|
||||
{ /* Shift+CapsLock */
|
||||
{ 27,'!','@','#','$','%','^','&'},
|
||||
{'*','(',')','_','+','~', 8, 9},
|
||||
{'Q','W','E','R','T','Y','U','I'},
|
||||
{'O','P','{','}', 13,127, 0, 0},
|
||||
{'A','S','D','F','G','H','J','K'},
|
||||
{'L',':','"','|', 0,'Z','X','C'},
|
||||
{'V','B','N','M','<','>','?', 0},
|
||||
{ 10, 32, 228, 211, 195, 178, 177, 192},
|
||||
{ 193, 194, 208, 209, 210, 225, 226, 227},
|
||||
{ 241, 242, 243, 244, 0, 0, 0, 0},
|
||||
},
|
||||
{ /* Control+CapsLock */
|
||||
{ 27,'1','2','3','4','5','6','7'},
|
||||
{'8','9','0','-','=','`', 8, 9},
|
||||
{ 17, 23, 5, 18, 20, 25, 21, 9},
|
||||
{ 15, 16, 27, 29, 13,127, 0, 0},
|
||||
{ 1, 19, 4, 6, 7, 8, 10, 11},
|
||||
{ 12,';', 39, 28, 0, 26, 24, 3},
|
||||
{ 22, 2, 14, 13,',','.','/', 0},
|
||||
{ 10, 32, 228, 211, 195, 178, 177, 192},
|
||||
{ 193, 194, 208, 209, 210, 225, 226, 227},
|
||||
{ 241, 242, 243, 244, 0, 0, 0, 0},
|
||||
},
|
||||
{ /* Shift+Control+CapsLock */
|
||||
{ 27,'!', 0,'#','$','%', 30,'&'},
|
||||
{'*','(',')', 31,'+','~', 8, 9},
|
||||
{ 17, 23, 5, 18, 20, 25, 21, 9},
|
||||
{ 15, 16, 27, 29, 13,127, 0, 0},
|
||||
{ 1, 19, 4, 6, 7, 8, 10, 11},
|
||||
{ 12,':','"', 28, 0, 26, 24, 3},
|
||||
{ 22, 2, 14, 13,',','.','/', 0},
|
||||
{ 10, 32, 228, 211, 195, 178, 177, 192},
|
||||
{ 193, 194, 208, 209, 210, 225, 226, 227},
|
||||
{ 241, 242, 243, 244, 0, 0, 0, 0},
|
||||
},
|
||||
};
|
||||
INPUT_PORTS_START(kaypro_keyboard_bitshift)
|
||||
PORT_INCLUDE(kaypro_keyboard_typewriter)
|
||||
|
||||
MACHINE_RESET_MEMBER(kaypro_state,kay_kbd)
|
||||
PORT_MODIFY("ROW.2")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED) // 6 ^ for "typewriter shift" layout
|
||||
|
||||
PORT_MODIFY("ROW.3")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED) // 7 & for "typewriter shift" layout
|
||||
|
||||
PORT_MODIFY("ROW.4")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED) // 8 * for "typewriter shift" layout
|
||||
|
||||
PORT_MODIFY("ROW.5")
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) // ' " for "typewriter shift" layout
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) // ` ~ for "typewriter shift" layout
|
||||
|
||||
PORT_MODIFY("ROW.6")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED) // 9 ) for "typewriter shift" layout
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) // - _ for "typewriter shift" layout
|
||||
|
||||
PORT_MODIFY("ROW.7")
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) // ; : for "typewriter shift" layout
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) // = + for "typewriter shift" layout
|
||||
|
||||
PORT_MODIFY("ROW.8")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED) // 2 @ for "typewriter shift" layout
|
||||
|
||||
PORT_MODIFY("ROW.C")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&')
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"')
|
||||
|
||||
PORT_MODIFY("ROW.D")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('`') PORT_CHAR('@')
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('=')
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(':') PORT_CHAR('*')
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('~') PORT_CHAR('^')
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')')
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(')
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('\'')
|
||||
|
||||
PORT_MODIFY("ROW.E")
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR('+')
|
||||
INPUT_PORTS_END
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
kaypro_10_keyboard_device::kaypro_10_keyboard_device(
|
||||
machine_config const &mconfig,
|
||||
char const *tag,
|
||||
device_t *owner,
|
||||
uint32_t clock)
|
||||
: device_t(mconfig, KAYPRO_10_KEYBOARD, tag, owner, clock)
|
||||
, m_bell(*this, "bell")
|
||||
, m_matrix(*this, "ROW.%X", 0)
|
||||
, m_modifiers(*this, "MOD")
|
||||
, m_rxd_cb(*this)
|
||||
, m_txd(1U)
|
||||
, m_bus(0U)
|
||||
{
|
||||
kay_kbd_t *kbd = m_kbd = auto_alloc_clear(machine(), <kay_kbd_t>());
|
||||
|
||||
/* disable CapsLock LED initially */
|
||||
output().set_led_value(1, 1);
|
||||
output().set_led_value(1, 0);
|
||||
kbd->beeper = machine().device<beep_device>("beeper");
|
||||
kbd->beep_on = 1;
|
||||
kbd->control_status = 0x14;
|
||||
kbd->beeper->set_state(0);
|
||||
kbd->head = kbd->tail = 0; /* init buffer */
|
||||
}
|
||||
|
||||
/******************************************************
|
||||
* vertical blank interrupt
|
||||
* used to scan keyboard; newly pressed keys
|
||||
* are stuffed into a keyboard buffer;
|
||||
* also drives keyboard LEDs and
|
||||
* and handles autorepeating keys
|
||||
******************************************************/
|
||||
INTERRUPT_GEN_MEMBER(kaypro_state::kay_kbd_interrupt)
|
||||
tiny_rom_entry const *kaypro_10_keyboard_device::device_rom_region() const
|
||||
{
|
||||
kay_kbd_t *kbd = m_kbd;
|
||||
int mod, row, col, chg, newval;
|
||||
uint8_t *keyrows = kbd->keyrows;
|
||||
|
||||
if( kbd->repeat )
|
||||
{
|
||||
if( !--kbd->repeat )
|
||||
kbd->repeater = 4;
|
||||
}
|
||||
else
|
||||
if( kbd->repeater )
|
||||
{
|
||||
kbd->repeat = kbd->repeater;
|
||||
}
|
||||
|
||||
row = 9;
|
||||
newval = machine().root_device().ioport("ROW9")->read();
|
||||
chg = keyrows[row] ^ newval;
|
||||
|
||||
if (!chg) { newval = machine().root_device().ioport("ROW8")->read(); chg = keyrows[--row] ^ newval; }
|
||||
if (!chg) { newval = machine().root_device().ioport("ROW7")->read(); chg = keyrows[--row] ^ newval; }
|
||||
if (!chg) { newval = machine().root_device().ioport("ROW6")->read(); chg = keyrows[--row] ^ newval; }
|
||||
if (!chg) { newval = machine().root_device().ioport("ROW5")->read(); chg = keyrows[--row] ^ newval; }
|
||||
if (!chg) { newval = machine().root_device().ioport("ROW4")->read(); chg = keyrows[--row] ^ newval; }
|
||||
if (!chg) { newval = machine().root_device().ioport("ROW3")->read(); chg = keyrows[--row] ^ newval; }
|
||||
if (!chg) { newval = machine().root_device().ioport("ROW2")->read(); chg = keyrows[--row] ^ newval; }
|
||||
if (!chg) { newval = machine().root_device().ioport("ROW1")->read(); chg = keyrows[--row] ^ newval; }
|
||||
if (!chg) { newval = machine().root_device().ioport("ROW0")->read(); chg = keyrows[--row] ^ newval; }
|
||||
if (!chg) --row;
|
||||
|
||||
if (row >= 0)
|
||||
{
|
||||
kbd->repeater = 0x00;
|
||||
kbd->mask = 0x00;
|
||||
kbd->key = 0x00;
|
||||
kbd->lastrow = row;
|
||||
/* CapsLock LED */
|
||||
if( row == 3 && chg == 0x80 )
|
||||
output().set_led_value(1, (kbd->keyrows[3] & 0x80) ? 0 : 1);
|
||||
|
||||
if (newval & chg) /* key(s) pressed ? */
|
||||
{
|
||||
mod = 0;
|
||||
|
||||
/* Shift modifier */
|
||||
if ( (keyrows[5] & 0x10) || (keyrows[6] & 0x80) )
|
||||
mod |= 1;
|
||||
|
||||
/* Control modifier */
|
||||
if (keyrows[3] & 0x40)
|
||||
mod |= 2;
|
||||
|
||||
/* CapsLock modifier */
|
||||
if (keyrows[3] & 0x80)
|
||||
mod |= 4;
|
||||
|
||||
/* find newval key */
|
||||
kbd->mask = 0x01;
|
||||
for (col = 0; col < 8; col ++)
|
||||
{
|
||||
if (chg & kbd->mask)
|
||||
{
|
||||
newval &= kbd->mask;
|
||||
kbd->key = keyboard[mod][row][col];
|
||||
break;
|
||||
}
|
||||
kbd->mask <<= 1;
|
||||
}
|
||||
if( kbd->key ) /* normal key */
|
||||
{
|
||||
kbd->repeater = 30;
|
||||
kay_kbd_in(kbd->key);
|
||||
}
|
||||
else
|
||||
if( (row == 0) && (chg == 0x04) ) /* Ctrl-@ (NUL) */
|
||||
kay_kbd_in(0);
|
||||
keyrows[row] |= newval;
|
||||
}
|
||||
else
|
||||
{
|
||||
kbd->keyrows[row] = newval;
|
||||
}
|
||||
kbd->repeat = kbd->repeater;
|
||||
}
|
||||
else if ( kbd->key && (keyrows[kbd->lastrow] & kbd->mask) && kbd->repeat == 0 )
|
||||
{
|
||||
kay_kbd_in(kbd->key);
|
||||
}
|
||||
return ROM_NAME(kaypro_10_keyboard);
|
||||
}
|
||||
|
||||
#if 0
|
||||
MACHINE_CONFIG_MEMBER(kaypro_10_keyboard_device::device_add_mconfig)
|
||||
MCFG_CPU_ADD("mcu", I8049, XTAL_6MHz)
|
||||
MCFG_MCS48_PORT_P1_IN_CB(READ8(kaypro_10_keyboard_device, p1_r))
|
||||
MCFG_MCS48_PORT_P2_IN_CB(READ8(kaypro_10_keyboard_device, p2_r))
|
||||
MCFG_MCS48_PORT_P2_OUT_CB(WRITE8(kaypro_10_keyboard_device, p2_w))
|
||||
MCFG_MCS48_PORT_T1_IN_CB(READLINE(kaypro_10_keyboard_device, t1_r))
|
||||
MCFG_MCS48_PORT_BUS_IN_CB(READ8(kaypro_10_keyboard_device, bus_r))
|
||||
MCFG_MCS48_PORT_BUS_OUT_CB(WRITE8(kaypro_10_keyboard_device, bus_w))
|
||||
|
||||
/******************************************************
|
||||
* kaypro_const_w (write console status ;)
|
||||
* bit
|
||||
* 0 flush keyboard buffer
|
||||
******************************************************/
|
||||
static WRITE8_HANDLER ( kaypro2_const_w )
|
||||
MCFG_SPEAKER_STANDARD_MONO("keyboard")
|
||||
MCFG_SOUND_ADD("bell", SPEAKER_SOUND, 0)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "keyboard", 0.25)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
ioport_constructor kaypro_10_keyboard_device::device_input_ports() const
|
||||
{
|
||||
if (data & 1)
|
||||
kbd->head = kbd->tail = 0;
|
||||
(void)INPUT_PORTS_NAME(kaypro_keyboard_bitshift);
|
||||
return INPUT_PORTS_NAME(kaypro_keyboard_typewriter);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/******************************************************
|
||||
* stuff character into the keyboard buffer
|
||||
* releases CPU if it was waiting for a key
|
||||
* sounds bell if buffer would overflow
|
||||
******************************************************/
|
||||
void kaypro_state::kay_kbd_in(uint8_t data )
|
||||
void kaypro_10_keyboard_device::device_start()
|
||||
{
|
||||
kay_kbd_t *kbd = m_kbd;
|
||||
uint8_t kbd_head_old;
|
||||
m_rxd_cb.resolve_safe();
|
||||
|
||||
kbd_head_old = kbd->head;
|
||||
kbd->buff[kbd->head] = data;
|
||||
kbd->head = (kbd->head + 1) % sizeof(kbd->buff);
|
||||
/* will the buffer overflow ? */
|
||||
if (kbd->head == kbd->tail)
|
||||
{
|
||||
kbd->head = kbd_head_old;
|
||||
kay_kbd_d_w(4);
|
||||
}
|
||||
else
|
||||
kay_kbd_d_w(1);
|
||||
save_item(NAME(m_txd));
|
||||
save_item(NAME(m_bus));
|
||||
}
|
||||
|
||||
|
||||
uint8_t kaypro_state::kay_kbd_c_r()
|
||||
READ8_MEMBER(kaypro_10_keyboard_device::p1_r)
|
||||
{
|
||||
/* d4 transmit buffer empty - 1=ok to send
|
||||
d2 appears to be receive buffer empty - 1=ok to receive
|
||||
d0 keyboard buffer empty - 1=key waiting to be used */
|
||||
|
||||
kay_kbd_t *kbd = m_kbd;
|
||||
uint8_t data = kbd->control_status;
|
||||
|
||||
if( kbd->head != kbd->tail )
|
||||
data++;
|
||||
|
||||
return data;
|
||||
return m_matrix[m_bus & 0x0f]->read();
|
||||
}
|
||||
|
||||
uint8_t kaypro_state::kay_kbd_d_r()
|
||||
READ8_MEMBER(kaypro_10_keyboard_device::p2_r)
|
||||
{
|
||||
/* return next key in buffer */
|
||||
|
||||
kay_kbd_t *kbd = m_kbd;
|
||||
uint8_t data = 0;
|
||||
|
||||
if (kbd->tail != kbd->head)
|
||||
{
|
||||
data = kbd->buff[kbd->tail];
|
||||
kbd->tail = (kbd->tail + 1) % sizeof(kbd->buff);
|
||||
}
|
||||
|
||||
return data;
|
||||
return m_modifiers->read() | 0xf8U;
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER( kaypro_state::kay_kbd_beepoff )
|
||||
WRITE8_MEMBER(kaypro_10_keyboard_device::p2_w)
|
||||
{
|
||||
kay_kbd_t *kbd = m_kbd;
|
||||
kbd->beeper->set_state(0);
|
||||
kbd->control_status |= 4;
|
||||
m_bell->level_w(BIT(data, 6));
|
||||
m_rxd_cb(BIT(data, 7));
|
||||
}
|
||||
|
||||
void kaypro_state::kay_kbd_d_w( uint8_t data )
|
||||
READ_LINE_MEMBER(kaypro_10_keyboard_device::t1_r)
|
||||
{
|
||||
/* Beeper control - lengths need verifying
|
||||
01 - keyclick
|
||||
02 - short beep
|
||||
04 - standard bell beep
|
||||
08 - mute
|
||||
16 - unmute */
|
||||
|
||||
kay_kbd_t *kbd = m_kbd;
|
||||
uint16_t length = 0;
|
||||
|
||||
if (data & 0x10)
|
||||
kbd->beep_on = 1;
|
||||
else
|
||||
if (data & 0x08)
|
||||
kbd->beep_on = 0;
|
||||
else
|
||||
if (kbd->beep_on)
|
||||
{
|
||||
if (data & 0x04)
|
||||
length = 400;
|
||||
else
|
||||
if (data & 0x02)
|
||||
length = 200;
|
||||
else
|
||||
if (data & 0x01)
|
||||
length = 4;
|
||||
|
||||
if (length)
|
||||
{
|
||||
kbd->control_status &= 0xfb;
|
||||
machine().scheduler().timer_set(attotime::from_msec(length), timer_expired_delegate(FUNC(kaypro_state::kay_kbd_beepoff),this));
|
||||
kbd->beeper->set_state(1);
|
||||
}
|
||||
}
|
||||
return m_txd ? 1 : 0;
|
||||
}
|
||||
|
||||
READ8_MEMBER(kaypro_10_keyboard_device::bus_r)
|
||||
{
|
||||
return m_bus;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(kaypro_10_keyboard_device::bus_w)
|
||||
{
|
||||
if (BIT(m_bus ^ data, 4))
|
||||
machine().output().set_value("led_caps_lock", BIT(data, 4));
|
||||
m_bus = data;
|
||||
}
|
||||
|
@ -1,4 +1,54 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Robbbert
|
||||
// copyright-holders:Vas Crabb
|
||||
#ifndef MAME_MACHINE_KAY_KBD_H
|
||||
#define MAME_MACHINE_KAY_KBD_H
|
||||
|
||||
INPUT_PORTS_EXTERN( kay_kbd );
|
||||
#pragma once
|
||||
|
||||
#include "sound/spkrdev.h"
|
||||
|
||||
|
||||
#define MCFG_KAYPRO10KBD_RXD_CB(cb) \
|
||||
devcb = &kaypro_10_keyboard_device::set_rxd_cb(*device, DEVCB_##cb);
|
||||
|
||||
|
||||
class kaypro_10_keyboard_device : public device_t
|
||||
{
|
||||
public:
|
||||
kaypro_10_keyboard_device(
|
||||
machine_config const &mconfig,
|
||||
char const *tag,
|
||||
device_t *owner,
|
||||
uint32_t clock);
|
||||
|
||||
template <class Object> static devcb_base &set_rxd_cb(device_t &device, Object &&cb)
|
||||
{ return downcast<kaypro_10_keyboard_device &>(device).m_rxd_cb.set_callback(std::forward<Object>(cb)); }
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(txd_w) { m_txd = state ? 1U : 0U; }
|
||||
|
||||
protected:
|
||||
virtual const tiny_rom_entry *device_rom_region() const override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
virtual ioport_constructor device_input_ports() const override;
|
||||
virtual void device_start() override;
|
||||
|
||||
DECLARE_READ8_MEMBER(p1_r);
|
||||
DECLARE_READ8_MEMBER(p2_r);
|
||||
DECLARE_WRITE8_MEMBER(p2_w);
|
||||
DECLARE_READ_LINE_MEMBER(t1_r);
|
||||
DECLARE_READ8_MEMBER(bus_r);
|
||||
DECLARE_WRITE8_MEMBER(bus_w);
|
||||
|
||||
private:
|
||||
required_device<speaker_sound_device> m_bell;
|
||||
required_ioport_array<16> m_matrix;
|
||||
required_ioport m_modifiers;
|
||||
devcb_write_line m_rxd_cb;
|
||||
|
||||
std::uint8_t m_txd;
|
||||
std::uint8_t m_bus;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(KAYPRO_10_KEYBOARD, kaypro_10_keyboard_device)
|
||||
|
||||
#endif // MAME_MACHINE_KAY_KBD_H
|
||||
|
@ -163,29 +163,9 @@ WRITE8_MEMBER( kaypro_state::kaypro2x_system_port_w )
|
||||
FFh 19200 */
|
||||
|
||||
|
||||
READ8_MEMBER(kaypro_state::kaypro_sio_r)
|
||||
{
|
||||
if (offset == 1)
|
||||
return kay_kbd_d_r();
|
||||
else
|
||||
if (offset == 3)
|
||||
return kay_kbd_c_r();
|
||||
else
|
||||
return m_sio->cd_ba_r(space, offset);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(kaypro_state::kaypro_sio_w)
|
||||
{
|
||||
if (offset == 1)
|
||||
kay_kbd_d_w(data);
|
||||
else
|
||||
m_sio->cd_ba_w(space, offset, data);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************************
|
||||
|
||||
Floppy DIsk
|
||||
Floppy Disk
|
||||
|
||||
If DRQ or IRQ is set, and cpu is halted, the NMI goes low.
|
||||
Since the HALT occurs last (and has no callback mechanism), we need to set
|
||||
@ -248,7 +228,6 @@ MACHINE_START_MEMBER( kaypro_state,kayproii )
|
||||
|
||||
MACHINE_RESET_MEMBER( kaypro_state,kaypro )
|
||||
{
|
||||
MACHINE_RESET_CALL_MEMBER(kay_kbd);
|
||||
membank("bankr0")->set_entry(1); // point at rom
|
||||
membank("bankw0")->set_entry(0); // always write to ram
|
||||
membank("bank3")->set_entry(1); // point at video ram
|
||||
|
Loading…
Reference in New Issue
Block a user