summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Patrick Mackinlay <pmackinlay@hotmail.com>2025-08-29 18:00:25 +0700
committer Patrick Mackinlay <pmackinlay@hotmail.com>2025-08-29 18:00:25 +0700
commite34b80d4c6ff251e643fa9154a64f51208be5161 (patch)
tree83bf4e2d0cd68188bd0d0047cd8c3fd112f00bb4
parentbd4ace41e7a0a73821b4805eab562654d344e40f (diff)
ibm/rtpc.cpp: refactor keyboard, locator, speaker adapter
-rw-r--r--src/devices/bus/isa/amgda.cpp2
-rw-r--r--src/mame/ibm/rtpc.cpp425
-rw-r--r--src/mame/ibm/rtpc_kls.cpp410
-rw-r--r--src/mame/ibm/rtpc_kls.h68
4 files changed, 520 insertions, 385 deletions
diff --git a/src/devices/bus/isa/amgda.cpp b/src/devices/bus/isa/amgda.cpp
index d31173b7032..04ca7f37c92 100644
--- a/src/devices/bus/isa/amgda.cpp
+++ b/src/devices/bus/isa/amgda.cpp
@@ -170,7 +170,7 @@ void isa16_amgda_device::device_start()
m_isa->install_memory(0xd0'0000, 0xd1'ffff, *this, &isa16_amgda_device::mem_map);
// TODO: ISA bus shared interrupt 11 enable
- m_isa->space(isa16_device::AS_ISA_IO).install_write_tap(0x06f3, 0x06f3, "irq_arm", [this](offs_t offset, u8 &data, u8 mem_mask) { irq_w(0); });
+ //m_isa->space(isa16_device::AS_ISA_IO).install_write_tap(0x06f3, 0x06f3, "irq_arm", [this](offs_t offset, u8 &data, u8 mem_mask) { irq_w(0); });
}
void isa16_amgda_device::device_reset()
diff --git a/src/mame/ibm/rtpc.cpp b/src/mame/ibm/rtpc.cpp
index 6e9369a0d89..b587f90bb4c 100644
--- a/src/mame/ibm/rtpc.cpp
+++ b/src/mame/ibm/rtpc.cpp
@@ -13,7 +13,7 @@
* - finish refactoring iocc
* - additional machine variants
* - configurable RAM size
- * - kls locator
+ * - shared interrupts
*/
/*
* https://www-01.ibm.com/common/ssi/ShowDoc.wss?docURL=/common/ssi/rep_ca/6/897/ENUS186-006/index.html
@@ -37,6 +37,7 @@
* Advanced, 100ns 4MB (6151) external (6150) (presume ~40MHz crystal/4), 4MB/8MB memory boards
* Enhanced, 80ns, 16MB soldered, EAFPA standard, CMOS (49.400 MHz crystal/4 == 12.350MHz == 80.971ns)
*
+ * FPA is NS32081
* AFPA is M68881 @ 20MHz
* EAFPA is AD90221-2 ADSP-3210 (multiplier) + AD90222-2 ADSP-3221 (fp alu) + AD90220-2 ADSP-1401 (program sequencer)
*
@@ -77,18 +78,14 @@
#include "rosetta.h"
#include "rtpc_iocc.h"
-#include "rtpc_kbd.h"
-#include "rtpc_kbdc.h"
+#include "rtpc_kls.h"
// cpu and memory
#include "cpu/romp/romp.h"
-#include "cpu/mcs51/mcs51.h"
// various hardware
#include "imagedev/floppy.h"
#include "machine/am9517a.h"
-#include "machine/clock.h"
-#include "machine/i8255.h"
#include "machine/input_merger.h"
#include "machine/mc146818.h"
#include "machine/pic8259.h"
@@ -107,9 +104,7 @@
#include "rtpc.lh"
-#define LOG_KLS (1U << 1)
-
-//#define VERBOSE (LOG_GENERAL|LOG_KLS)
+#define VERBOSE (LOG_GENERAL)
#include "logmacro.h"
namespace {
@@ -120,18 +115,15 @@ public:
rtpc_state(machine_config const &mconfig, device_type type, char const *tag)
: driver_device(mconfig, type, tag)
, m_cpu(*this, "cpu")
- , m_mcu(*this, "mcu")
, m_mmu(*this, "mmu")
, m_iocc(*this, "iocc")
, m_dma(*this, "dma%u", 0U)
, m_pic(*this, "pic%u", 0U)
- , m_ppi(*this, "ppi")
+ , m_kls(*this, "kls")
, m_rtc(*this, "rtc")
, m_scc(*this, "scc")
, m_isa(*this, "isa")
, m_slot(*this, "isa%u", 1U)
- , m_kbdc(*this, "kbdc")
- , m_speaker(*this, "kbdc:kbd:speaker")
, m_ipl(*this, "ipl")
{
}
@@ -139,129 +131,49 @@ public:
void ibm6150(machine_config &config);
void ibm6151(machine_config &config);
- void init_common();
-
protected:
virtual void machine_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
void iocc_mem_map(address_map &map);
template <bool SCC> void iocc_pio_map(address_map &map) ATTR_COLD;
- void mcu_pgm_map(address_map &map) ATTR_COLD;
void common(machine_config &config);
- void kls_cmd_w(u16 data);
- void mcu_port1_w(u8 data);
- void mcu_port2_w(u8 data);
- void mcu_port3_w(u8 data);
- void ppi_portc_w(u8 data);
-
void crra_w(u8 data);
void crrb_w(u8 data);
void dia_w(u8 data);
- void speaker()
- {
- if (m_speaker)
- m_speaker->level_w((m_mcu_p2 & KLS_P27) ? 0 : m_mcu_p1 >> 6);
- }
-
// devices
required_device<romp_device> m_cpu;
- required_device<i8051_device> m_mcu;
required_device<rosetta_device> m_mmu;
required_device<rtpc_iocc_device> m_iocc;
required_device_array<am9517a_device, 2> m_dma;
required_device_array<pic8259_device, 2> m_pic;
- required_device<i8255_device> m_ppi;
+ required_device<rtpc_kls_device> m_kls;
required_device<mc146818_device> m_rtc;
optional_device<z80scc_device> m_scc;
required_device<isa16_device> m_isa;
optional_device_array<device_t, 8> m_slot;
- required_device<rtpc_kbdc_device> m_kbdc;
- optional_device<speaker_sound_device> m_speaker;
required_region_ptr<u32> m_ipl;
- u8 m_kls_cmd;
-
- u8 m_mcu_p0;
- enum kls_p1_mask : u8
- {
- KLS_P10 = 0x01, // cmd08 (i)
- KLS_P11 = 0x02, // cmd09 (i)
- KLS_P12 = 0x04, // cmd10 (i)
- KLS_P13 = 0x08, // cmd11 (i)
- KLS_P14 = 0x10, // cmd12 (i)
- KLS_P15 = 0x20, // keylock switch (i)
- KLS_P16 = 0x40, // speaker volume 0 (o)
- KLS_P17 = 0x80, // speaker volume 1 (o)
-
- KLS_CMD = 0x1f,
- KLS_P1O = 0xc0, // port 1 outputs
- };
- u8 m_mcu_p1;
- enum kls_p2_mask : u8
- {
- KLS_P20 = 0x01, // iid0 (o)
- KLS_P21 = 0x02, // iid1 (o)
- KLS_P22 = 0x04, // iid2 (o)
- KLS_P23 = 0x08, // i/o channel system reset, active low (o)
- KLS_P24 = 0x10, // ppi -stb (o)
- KLS_P25 = 0x20, // ppi ibf (i)
- KLS_P26 = 0x40, // ppi -ack (o)
- KLS_P27 = 0x80, // speaker frequency (o)
-
- KLS_IID = 0x07,
- KLS_P2O = 0xdf, // port 2 outputs
- };
- u8 m_mcu_p2;
- enum kls_p3_mask : u8
- {
- KLS_P30 = 0x01, // uart rx (i)
- KLS_P31 = 0x02, // uart tx (o)
- KLS_P32 = 0x04, // kbd clock/-int0 (i)
- KLS_P33 = 0x08, // ppi -obf/-int1 (i)
- KLS_P34 = 0x10, // 32kHz/t0 (i)
- KLS_P35 = 0x20, // kbd data (i)
- KLS_P36 = 0x40, // kbd data (o)
- KLS_P37 = 0x80, // kbd clock (o)
-
- KLS_P3O = 0xc2, // port 3 outputs
- };
- u8 m_mcu_p3;
-
- u8 m_ppi_pa;
- u8 m_ppi_pb;
- u8 m_ppi_pc;
-
- u8 m_ch8er = 0; // dma channel 8 enable register
- u8 m_crra = 0; // component reset register a
- u8 m_crrb = 0; // component reset register b
-
- u8 m_ext[2]{}; // external serial registers
+ u8 m_ch8er; // dma channel 8 enable register
+ u8 m_crra; // component reset register a
+ u8 m_crrb; // component reset register b
+ u8 m_ext[2]; // external serial registers
};
-static double const speaker_levels[4] = { 0.0, 1.0 / 3.0, 2.0 / 3.0, 1.0 };
-
void rtpc_state::machine_start()
{
- m_kls_cmd = 0;
-
- m_mcu_p0 = 0xff;
- m_mcu_p1 = 0xff & ~KLS_P15;
- m_mcu_p2 = 0xff;
- m_mcu_p3 = 0xff;
-
- m_ppi_pa = 0;
- m_ppi_pb = 0;
- m_ppi_pc = 0;
-
+ m_ch8er = 0;
m_crra = 0xff;
m_crrb = 0xff;
+
+ m_ext[0] = 0;
+ m_ext[1] = 0;
}
void rtpc_state::device_reset()
@@ -271,12 +183,6 @@ void rtpc_state::device_reset()
m_cpu->space(AS_PROGRAM).install_rom(0, mask, 0x00ff'ffff & ~mask, m_ipl);
}
-void rtpc_state::init_common()
-{
- if (m_speaker)
- m_speaker->set_levels(4, speaker_levels);
-}
-
void rtpc_state::iocc_mem_map(address_map &map)
{
map.unmap_value_high();
@@ -292,6 +198,10 @@ template <bool SCC> void rtpc_state::iocc_pio_map(address_map &map)
map(0x00'0110, 0x00'0113).noprw();
map(0x00'01e8, 0x00'01ef).noprw();
+ // interrupt level enables (shared interrupts)
+ map(0x00'02f0, 0x00'02f7).nopw(); // irq 0..7
+ map(0x00'06f0, 0x00'06f7).nopw(); // irq 8..15 (excluding 13)
+
if (SCC)
{
map(0x00'8000, 0x00'8003).rw(m_scc, FUNC(z80scc_device::dc_ab_r), FUNC(z80scc_device::dc_ab_w));
@@ -301,10 +211,10 @@ template <bool SCC> void rtpc_state::iocc_pio_map(address_map &map)
}
// delay 1µs per byte written
+ map(0x00'80e0, 0x00'80e3).nopr(); // TODO: does read also generate a delay?
map(0x00'80e0, 0x00'80e3).lw8([this](u8 data) { m_cpu->eat_cycles(m_cpu->clock() / 1000000 + 1); }, "io_delay");
- map(0x00'8400, 0x00'8401).w(FUNC(rtpc_state::kls_cmd_w)).flags(rtpc_iocc_device::PIO_W);
- map(0x00'8404, 0x00'8407).rw(m_ppi, FUNC(i8255_device::read), FUNC(i8255_device::write));
+ map(0x00'8400, 0x00'8407).m(m_kls, FUNC(rtpc_kls_device::map));
map(0x00'8800, 0x00'883f).rw(m_rtc, FUNC(mc146818_device::read_direct), FUNC(mc146818_device::write_direct));
map(0x00'8840, 0x00'884f).mirror(0x10).rw(m_dma[0], FUNC(am9517a_device::read), FUNC(am9517a_device::write));
@@ -328,182 +238,8 @@ template <bool SCC> void rtpc_state::iocc_pio_map(address_map &map)
// 8c82 diag dma mode?
// 8c84 diag dma exit?
map(0x00'8ce0, 0x00'8ce1).nopw(); // FIXME: hex display register?
-}
-
-void rtpc_state::mcu_pgm_map(address_map &map)
-{
- map(0x0000, 0x0fff).rom().region("mcu", 0);
- map(0xf800, 0xffff).lr8([this]() { m_cpu->pulse_input_line(INPUT_LINE_IRQ0, attotime::from_msec(1)); return 0; }, "sys_atn");
-}
-
-void rtpc_state::mcu_port1_w(u8 data)
-{
- LOGMASKED(LOG_KLS, "kls volume %d\n", data >> 6);
- m_mcu_p1 = (m_mcu_p1 & ~KLS_P1O) | (data & KLS_P1O);
-
- // speaker volume wraps to ppi port b.6 and b.5
- m_ppi_pb &= ~0x60;
- m_ppi_pb |= (data >> 1) & 0x60;
- speaker();
-}
-
-void rtpc_state::mcu_port2_w(u8 data)
-{
- if ((data ^ m_mcu_p2) & KLS_IID)
- {
- static const char *const mcu_code[] =
- {
- "informational", "received byte from keyboard", "received byte from uart", "returning byte requested by system",
- "block transfer ready", "unassigned", "self-test performed", "error condition"
- };
- LOGMASKED(LOG_KLS, "kls mcu iid %d: %s\n", data & 7, mcu_code[data & 7]);
- }
-
- if ((data ^ m_mcu_p2) & KLS_P23)
- LOGMASKED(LOG_KLS, "kls mcu system reset %d\n", BIT(data, 3));
-
- if ((data ^ m_mcu_p2) & KLS_P24)
- {
- if (!BIT(data, 4))
- {
- LOGMASKED(LOG_KLS, "kls mcu data out 0x%02x\n", m_mcu_p0);
- m_ppi_pa = m_mcu_p0;
- }
- m_ppi->pc4_w(BIT(data, 4));
- }
-
- if ((data ^ m_mcu_p2) & KLS_P26)
- {
-
- m_ppi->pc6_w(BIT(data, 6));
- if (!BIT(data, 6))
- {
- LOGMASKED(LOG_KLS, "kls mcu data in 0x%02x\n", m_ppi_pa);
- m_mcu_p0 = m_ppi_pa;
- }
- }
-
- m_mcu_p2 = (m_mcu_p2 & ~KLS_P2O) | (data & KLS_P2O);
-
- // speaker frequency wraps to ppi port b.7
- m_ppi_pb = (m_ppi_pb & ~0x80) | (~data & 0x80);
-
- // iid, ack, stb map to ppi port c
- m_ppi_pc = (m_ppi_pc & ~0x57) | (data & 0x57);
-
- speaker();
-}
-
-void rtpc_state::mcu_port3_w(u8 data)
-{
- // uart txd -> rxd wrap
- if (BIT(m_kls_cmd, 5))
- {
- if (BIT(data, 1))
- {
- m_ppi_pb |= 0x01;
- m_mcu_p3 |= KLS_P30;
- }
- else
- {
- m_ppi_pb &= ~0x01;
- m_mcu_p3 &= ~KLS_P30;
- }
- }
-
- m_kbdc->data_write_from_mb(BIT(data, 6));
- m_kbdc->clock_write_from_mb(BIT(data, 7));
-
- m_mcu_p3 = (m_mcu_p3 & ~KLS_P3O) | (data & KLS_P3O);
-}
-
-/*
- * bit i/o function
- * 0 i iid0
- * 1 i iid1
- * 2 i iid2
- * 3 o +irq
- * 4 i -stb
- * 5 o ibf
- * 6 i -ack
- * 7 o -obf
- */
-void rtpc_state::ppi_portc_w(u8 data)
-{
- LOGMASKED(LOG_KLS, "ppi_portc_w 0x%02x\n", data);
-
- // bit 3 (+irq) -> i/o channel
- if (BIT(m_ppi_pc ^ data, 3))
- {
- LOGMASKED(LOG_KLS, "kls host irq %d\n", BIT(data, 3));
- m_pic[0]->ir5_w(BIT(data, 3));
- }
-
- // bit 5 (+ibf) -> mcu p2.5
- if (BIT(m_ppi_pc ^ data, 5))
- {
- if (BIT(data, 5))
- m_mcu_p2 |= KLS_P25;
- else
- m_mcu_p2 &= ~KLS_P25;
- }
-
- // bit 7 (-obf) -> mcu p3.3 (-int1)
- if (BIT(m_ppi_pc ^ data, 7))
- {
- if (BIT(data, 7))
- m_mcu_p3 |= KLS_P33;
- else
- m_mcu_p3 &= ~KLS_P33;
-
- m_mcu->set_input_line(MCS51_INT1_LINE, !BIT(data, 7));
- }
-
- m_ppi_pc = (m_ppi_pc & ~0xa8) | (data & 0xa8);
-}
-
-void rtpc_state::kls_cmd_w(u16 data)
-{
- LOGMASKED(LOG_KLS, "kls command 0x%02x data 0x%02x (%s)\n", data >> 8, u8(data), machine().describe_context());
-
- // 00rc cccc dddd dddd
- m_kls_cmd = BIT(data, 8, 6);
-
- switch (m_kls_cmd & KLS_CMD)
- {
- case 0x0: // extended command
- switch (u8(data))
- {
- case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
- case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
- LOGMASKED(LOG_KLS, "clr mode bit %d\n", data & 0xf); break;
- case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
- case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
- LOGMASKED(LOG_KLS, "set mode bit %d\n", data & 0xf); break;
- default: LOGMASKED(LOG_KLS, "extended command 0x%02x\n", data); break;
- }
- break;
- case 0x1: LOGMASKED(LOG_KLS, "write keyboard 0x%02x\n", data); break;
- case 0x2: LOGMASKED(LOG_KLS, "write speaker 0x%02x\n", data); break;
- case 0x3: LOGMASKED(LOG_KLS, "write uart control 0x%02x\n", data); break;
- case 0x4: LOGMASKED(LOG_KLS, "write uart query 0x%02x\n", data); break;
- case 0x5: LOGMASKED(LOG_KLS, "set uart rate 0x%02x\n", data); break;
- case 0x6: LOGMASKED(LOG_KLS, "init uart 0x%02x\n", data); break;
- case 0x7: LOGMASKED(LOG_KLS, "set speaker duration 0x%02x\n", data); break;
- case 0x8: LOGMASKED(LOG_KLS, "set speaker freq-hi 0x%02x\n", data); break;
- case 0x9: LOGMASKED(LOG_KLS, "set speaker freq-lo 0x%02x\n", data); break;
- case 0xc: LOGMASKED(LOG_KLS, "diagnostic write 0x%02x\n", data); break;
- case 0xa: case 0xb: case 0xd: case 0xe: case 0xf:
- LOGMASKED(LOG_KLS, "unassigned\n");
- break;
- default:
- LOGMASKED(LOG_KLS, "write shared ram addr 0x%x data 0x%02x\n", m_kls_cmd & 0xf, data);
- break;
- }
-
- m_mcu_p1 = (m_mcu_p1 & ~KLS_CMD) | (m_kls_cmd & KLS_CMD);
- m_ppi->write(0, data);
+ map(0x01'1000, 0x01'20ff).noprw(); // silence something
}
void rtpc_state::crra_w(u8 data)
@@ -512,8 +248,13 @@ void rtpc_state::crra_w(u8 data)
// selectively reset i/o slots 1..8
for (unsigned i = 0; i < 8; i++)
+ {
if (BIT(data, i) && !BIT(m_crra, i) && m_slot[i].found())
+ {
+ LOG("reset slot %u\n", i);
m_slot[i]->reset();
+ }
+ }
m_crra = data;
}
@@ -537,7 +278,7 @@ void rtpc_state::crrb_w(u8 data)
// TODO: rs232 if
- m_mcu->set_input_line(INPUT_LINE_RESET, !BIT(data, 2));
+ m_kls->mcu_reset_w(!BIT(data, 2));
// TODO: dmac !ready
// TODO: arbitor
@@ -602,33 +343,6 @@ void rtpc_state::common(machine_config &config)
m_mmu->out_pchk().set(reqi2, FUNC(input_merger_device::in_w<0>));
m_mmu->out_mchk().set_inputline(m_cpu, INPUT_LINE_NMI);
- // keyboard, locator, speaker adapter
- // P8051AH 2075
- // 61X6310 8811
- // (c)IBM 1986
- // (c)INTEL '80
- I8051(config, m_mcu, 9.216_MHz_XTAL);
- m_mcu->set_addrmap(AS_PROGRAM, &rtpc_state::mcu_pgm_map);
- m_mcu->port_in_cb<0>().set([this]() { return m_mcu_p0; });
- m_mcu->port_out_cb<0>().set([this](u8 data) { m_mcu_p0 = data; });
- m_mcu->port_in_cb<1>().set([this]() { return m_mcu_p1; });
- m_mcu->port_out_cb<1>().set(FUNC(rtpc_state::mcu_port1_w));
- m_mcu->port_in_cb<2>().set([this]() { return m_mcu_p2; });
- m_mcu->port_out_cb<2>().set(FUNC(rtpc_state::mcu_port2_w));
- m_mcu->port_in_cb<3>().set([this]() { return m_mcu_p3; });
- m_mcu->port_out_cb<3>().set(FUNC(rtpc_state::mcu_port3_w));
-
- CLOCK(config, "mcu_t0", 32'768).signal_handler().set(
- [this](int state)
- {
- if (state)
- m_mcu_p3 |= KLS_P34;
- else
- m_mcu_p3 &= ~KLS_P34;
-
- m_mcu->set_input_line(MCS51_T0_LINE, state ? ASSERT_LINE : CLEAR_LINE);
- });
-
RTPC_IOCC(config, m_iocc, 0);
m_iocc->set_addrmap(0, &rtpc_state::iocc_mem_map);
m_iocc->out_int().set(reqi2, FUNC(input_merger_device::in_w<1>));
@@ -703,6 +417,9 @@ void rtpc_state::common(machine_config &config)
m_dma[1]->in_memr_callback().set(m_iocc, FUNC(rtpc_iocc_device::dma_w_r));
m_dma[1]->out_memw_callback().set(m_iocc, FUNC(rtpc_iocc_device::dma_w_w));
+
+ // TODO: system board irq 8, 13
+
// NEC
// D8259AC
PIC8259(config, m_pic[0]);
@@ -742,68 +459,17 @@ void rtpc_state::common(machine_config &config)
m_isa->irq5_callback().set(m_pic[1], FUNC(pic8259_device::ir5_w));
m_isa->irq15_callback().set(m_pic[1], FUNC(pic8259_device::ir6_w));
- // P8255A-5
- // L6430434
- // (C)INTEL '81
- I8255A(config, m_ppi);
- // port A: read/write 8051
- // port B: input
- // port C lower: input
- // port C upper: 8051 handshake
- // port C & 0x20 -> irq
- m_ppi->out_pa_callback().set([this](u8 data) { m_ppi_pa = data; });
- m_ppi->in_pa_callback().set([this]() { return m_ppi_pa; });
-
- // TODO: bits 4-1 "non-adapter system board signals"
- // TODO: bit 0 "uart rxd signal"
- m_ppi->in_pb_callback().set([this]() { return m_ppi_pb; });
-
- m_ppi->out_pc_callback().set(FUNC(rtpc_state::ppi_portc_w));
- m_ppi->in_pc_callback().set([this]() { return m_ppi_pc; });
-
- RTPC_KBDC(config, m_kbdc);
- m_kbdc->option_add("kbd", RTPC_KBD);
- m_kbdc->set_default_option("kbd");
- m_kbdc->out_data_cb().set(
- [this](int state)
- {
- if (state)
- m_mcu_p3 |= KLS_P35;
- else
- m_mcu_p3 &= ~KLS_P35;
- });
- m_kbdc->out_clock_cb().set(
- [this](int state)
- {
- if (state)
- m_mcu_p3 |= KLS_P32;
- else
- m_mcu_p3 &= ~KLS_P32;
-
- m_mcu->set_input_line(MCS51_INT0_LINE, state ? CLEAR_LINE : ASSERT_LINE);
- });
+ RTPC_KLS(config, m_kls);
+ m_kls->atn().set_inputline(m_cpu, INPUT_LINE_IRQ0);
+ m_kls->irq().set(m_pic[0], FUNC(pic8259_device::ir5_w));
// MC146818AP
// IL 0A46D8729
MC146818(config, m_rtc, 32.768_kHz_XTAL);
m_rtc->sqw().set(m_cpu, FUNC(romp_device::clk_w));
- m_rtc->sqw().append(
- [this](int state)
- {
- if (state)
- m_ppi_pb |= 0x08;
- else
- m_ppi_pb &= ~0x08;
- });
+ m_rtc->sqw().append(m_kls, FUNC(rtpc_kls_device::rtc_sqw_w));
m_rtc->irq().set_inputline(m_cpu, INPUT_LINE_IRQ1).invert();
- m_rtc->irq().append(
- [this](int state)
- {
- if (!state)
- m_ppi_pb |= 0x10;
- else
- m_ppi_pb &= ~0x10;
- });
+ m_rtc->irq().append(m_kls, FUNC(rtpc_kls_device::rtc_irq_w)).invert();
config.set_default_layout(layout_rtpc);
}
@@ -884,9 +550,6 @@ ROM_START(ibm6150)
ROMX_LOAD("79x3458.bin", 0x00001, 0x4000, CRC(7bd08ab6) SHA1(aabcfbb8fa1a5f8a08fb5cfd90ca6fe05258fde9), ROM_BIOS(0) | ROM_SKIP(3))
ROMX_LOAD("79x3460.bin", 0x00002, 0x4000, CRC(897586e0) SHA1(528772635903f27235ebba2622b03386b84e4e17), ROM_BIOS(0) | ROM_SKIP(3))
ROMX_LOAD("79x3462.bin", 0x00003, 0x4000, CRC(12aca906) SHA1(58f95b95768ef131d8d9d552506a9fe9c9c6077d), ROM_BIOS(0) | ROM_SKIP(3))
-
- ROM_REGION(0x1000, "mcu", 0)
- ROM_LOAD("61x6310_8051.bin", 0x0000, 0x1000, CRC(296c16c1) SHA1(83858109c39d5be37e49f24d1db4e2b15f38843e))
ROM_END
ROM_START(ibm6151)
@@ -896,12 +559,6 @@ ROM_START(ibm6151)
ROMX_LOAD("79x3458.bin", 0x00001, 0x4000, CRC(7bd08ab6) SHA1(aabcfbb8fa1a5f8a08fb5cfd90ca6fe05258fde9), ROM_BIOS(0) | ROM_SKIP(3))
ROMX_LOAD("79x3460.bin", 0x00002, 0x4000, CRC(897586e0) SHA1(528772635903f27235ebba2622b03386b84e4e17), ROM_BIOS(0) | ROM_SKIP(3))
ROMX_LOAD("79x3462.bin", 0x00003, 0x4000, CRC(12aca906) SHA1(58f95b95768ef131d8d9d552506a9fe9c9c6077d), ROM_BIOS(0) | ROM_SKIP(3))
-
- // Version: 073
- // Date: 85 289 (16 Oct 1985)
- // Checksum: 0xc8 0xe8
- ROM_REGION(0x1000, "mcu", 0)
- ROM_LOAD("61x6310_8051.bin", 0x0000, 0x1000, CRC(296c16c1) SHA1(83858109c39d5be37e49f24d1db4e2b15f38843e))
ROM_END
#define rom_rtpc010 rom_ibm6151
@@ -912,9 +569,9 @@ ROM_END
} // anonymous namespace
-/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
-COMP(1986, rtpc010, 0, 0, ibm6151, 0, rtpc_state, init_common, "International Business Machines", "IBM RT PC Model 010", MACHINE_NOT_WORKING)
-COMP(1986, rtpc015, 0, 0, ibm6151, 0, rtpc_state, init_common, "International Business Machines", "IBM RT PC Model 015", MACHINE_NOT_WORKING)
-COMP(1986, rtpc020, 0, 0, ibm6150, 0, rtpc_state, init_common, "International Business Machines", "IBM RT PC Model 020", MACHINE_NOT_WORKING)
-COMP(1986, rtpc025, 0, 0, ibm6150, 0, rtpc_state, init_common, "International Business Machines", "IBM RT PC Model 025", MACHINE_NOT_WORKING)
-COMP(1986, rtpca25, 0, 0, ibm6150, 0, rtpc_state, init_common, "International Business Machines", "IBM RT PC Model A25", MACHINE_NOT_WORKING)
+/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
+COMP(1986, rtpc010, 0, 0, ibm6151, 0, rtpc_state, empty_init, "International Business Machines", "IBM RT PC Model 010", MACHINE_NOT_WORKING)
+COMP(1986, rtpc015, 0, 0, ibm6151, 0, rtpc_state, empty_init, "International Business Machines", "IBM RT PC Model 015", MACHINE_NOT_WORKING)
+COMP(1986, rtpc020, 0, 0, ibm6150, 0, rtpc_state, empty_init, "International Business Machines", "IBM RT PC Model 020", MACHINE_NOT_WORKING)
+COMP(1986, rtpc025, 0, 0, ibm6150, 0, rtpc_state, empty_init, "International Business Machines", "IBM RT PC Model 025", MACHINE_NOT_WORKING)
+COMP(1986, rtpca25, 0, 0, ibm6150, 0, rtpc_state, empty_init, "International Business Machines", "IBM RT PC Model A25", MACHINE_NOT_WORKING)
diff --git a/src/mame/ibm/rtpc_kls.cpp b/src/mame/ibm/rtpc_kls.cpp
new file mode 100644
index 00000000000..c6ad6988513
--- /dev/null
+++ b/src/mame/ibm/rtpc_kls.cpp
@@ -0,0 +1,410 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+ * IBM RT PC keyboard, locator and speaker adapter (KLS) device.
+ */
+
+#include "emu.h"
+#include "rtpc_kls.h"
+
+#include "rtpc_kbd.h"
+
+//#define VERBOSE (LOG_GENERAL)
+#include "logmacro.h"
+
+enum kls_p1_mask : u8
+{
+ KLS_P10 = 0x01, // cmd08 (i)
+ KLS_P11 = 0x02, // cmd09 (i)
+ KLS_P12 = 0x04, // cmd10 (i)
+ KLS_P13 = 0x08, // cmd11 (i)
+ KLS_P14 = 0x10, // cmd12 (i)
+ KLS_P15 = 0x20, // keylock switch (i)
+ KLS_P16 = 0x40, // speaker volume 0 (o)
+ KLS_P17 = 0x80, // speaker volume 1 (o)
+
+ KLS_CMD = 0x1f,
+ KLS_P1O = 0xc0, // port 1 outputs
+};
+enum kls_p2_mask : u8
+{
+ KLS_P20 = 0x01, // iid0 (o)
+ KLS_P21 = 0x02, // iid1 (o)
+ KLS_P22 = 0x04, // iid2 (o)
+ KLS_P23 = 0x08, // i/o channel system reset, active low (o)
+ KLS_P24 = 0x10, // ppi -stb (o)
+ KLS_P25 = 0x20, // ppi ibf (i)
+ KLS_P26 = 0x40, // ppi -ack (o)
+ KLS_P27 = 0x80, // speaker frequency (o)
+
+ KLS_IID = 0x07,
+ KLS_P2O = 0xdf, // port 2 outputs
+};
+enum kls_p3_mask : u8
+{
+ KLS_P30 = 0x01, // uart rx (i)
+ KLS_P31 = 0x02, // uart tx (o)
+ KLS_P32 = 0x04, // kbd clock/-int0 (i)
+ KLS_P33 = 0x08, // ppi -obf/-int1 (i)
+ KLS_P34 = 0x10, // 32kHz/t0 (i)
+ KLS_P35 = 0x20, // kbd data (i)
+ KLS_P36 = 0x40, // kbd data (o)
+ KLS_P37 = 0x80, // kbd clock (o)
+
+ KLS_P3O = 0xc2, // port 3 outputs
+};
+
+DEFINE_DEVICE_TYPE(RTPC_KLS, rtpc_kls_device, "rtpc_kls", "IBM RT PC Keyboard, Locator, Speaker Adapter")
+
+rtpc_kls_device::rtpc_kls_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, RTPC_KLS, tag, owner, clock)
+ , m_mcu(*this, "mcu")
+ , m_ppi(*this, "ppi")
+ , m_kbdc(*this, "kbdc")
+ , m_locc(*this, "locc")
+ , m_rcv(*this, { "rcv_loop", "rcv_data" })
+ , m_speaker(*this, "kbdc:kbd:speaker")
+ , m_atn(*this)
+ , m_irq(*this)
+{
+}
+
+void rtpc_kls_device::map(address_map &map)
+{
+ map(0x0, 0x1).w(FUNC(rtpc_kls_device::cmd_w)).flags(1);
+ map(0x4, 0x7).rw(m_ppi, FUNC(i8255_device::read), FUNC(i8255_device::write));
+}
+
+void kbd_devices(device_slot_interface &device)
+{
+ device.option_add("keyboard", RTPC_KBD);
+}
+
+void loc_devices(device_slot_interface &device)
+{
+}
+
+void rtpc_kls_device::device_add_mconfig(machine_config &config)
+{
+ // keyboard, locator, speaker adapter
+ // P8051AH 2075
+ // 61X6310 8811
+ // (c)IBM 1986
+ // (c)INTEL '80
+ I8051(config, m_mcu, 9.216_MHz_XTAL);
+ m_mcu->set_addrmap(AS_PROGRAM, &rtpc_kls_device::mcu_map);
+ m_mcu->port_in_cb<0>().set([this]() { return m_mcu_p[0]; });
+ m_mcu->port_out_cb<0>().set([this](u8 data) { m_mcu_p[0] = data; });
+ m_mcu->port_in_cb<1>().set([this]() { return m_mcu_p[1]; });
+ m_mcu->port_out_cb<1>().set(FUNC(rtpc_kls_device::mcu_port1_w));
+ m_mcu->port_in_cb<2>().set([this]() { return m_mcu_p[2]; });
+ m_mcu->port_out_cb<2>().set(FUNC(rtpc_kls_device::mcu_port2_w));
+ m_mcu->port_in_cb<3>().set([this]() { return m_mcu_p[3]; });
+ m_mcu->port_out_cb<3>().set(FUNC(rtpc_kls_device::mcu_port3_w));
+
+ CLOCK(config, "t0", 32'768).signal_handler().set(
+ [this](int state)
+ {
+ if (state)
+ m_mcu_p[3] |= KLS_P34;
+ else
+ m_mcu_p[3] &= ~KLS_P34;
+
+ m_mcu->set_input_line(MCS51_T0_LINE, state ? ASSERT_LINE : CLEAR_LINE);
+ });
+
+ input_merger_any_high_device &rcv(INPUT_MERGER_ANY_HIGH(config, "rcv"));
+ rcv.output_handler().set(
+ [this](int state)
+ {
+ if (state)
+ {
+ m_mcu_p[3] |= KLS_P30;
+ m_ppi_p[1] |= 0x01;
+ }
+ else
+ {
+ m_mcu_p[3] &= ~KLS_P30;
+ m_ppi_p[1] &= ~0x01;
+ }
+ });
+ INPUT_MERGER_ALL_HIGH(config, m_rcv[0]).output_handler().set(rcv, FUNC(input_merger_any_high_device::in_w<0>));
+ INPUT_MERGER_ALL_HIGH(config, m_rcv[1]).output_handler().set(rcv, FUNC(input_merger_any_high_device::in_w<1>));
+
+ // P8255A-5
+ // L6430434
+ // (C)INTEL '81
+ I8255A(config, m_ppi);
+ // port A: read/write 8051
+ // port B: input
+ // port C lower: input
+ // port C upper: 8051 handshake
+ // port C & 0x20 -> irq
+ m_ppi->out_pa_callback().set([this](u8 data) { m_ppi_p[0] = data; });
+ m_ppi->in_pa_callback().set([this]() { return m_ppi_p[0]; });
+
+ // TODO: bits 4-1 "non-adapter system board signals"
+ m_ppi->in_pb_callback().set([this]() { return m_ppi_p[1]; });
+
+ m_ppi->out_pc_callback().set(FUNC(rtpc_kls_device::ppi_portc_w));
+ m_ppi->in_pc_callback().set([this]() { return m_ppi_p[2]; });
+
+ RTPC_KBDC(config, m_kbdc, kbd_devices, "keyboard");
+ m_kbdc->out_data_cb().set(
+ [this](int state)
+ {
+ if (state)
+ m_mcu_p[3] |= KLS_P35;
+ else
+ m_mcu_p[3] &= ~KLS_P35;
+ });
+ m_kbdc->out_clock_cb().set(
+ [this](int state)
+ {
+ if (state)
+ m_mcu_p[3] |= KLS_P32;
+ else
+ m_mcu_p[3] &= ~KLS_P32;
+
+ m_mcu->set_input_line(MCS51_INT0_LINE, state ? CLEAR_LINE : ASSERT_LINE);
+ });
+
+ RS232_PORT(config, m_locc, loc_devices, nullptr);
+ m_mcu->port_out_cb<3>().append(m_locc, FUNC(rs232_port_device::write_txd)).bit(1);
+ m_locc->rxd_handler().set(m_rcv[1], FUNC(input_merger_all_high_device::in_w<1>));
+}
+
+void rtpc_kls_device::device_start()
+{
+ constexpr double const speaker_levels[4] = { 0.0, 1.0 / 3.0, 2.0 / 3.0, 1.0 };
+
+ save_item(NAME(m_cmd));
+ save_item(NAME(m_mcu_p));
+ save_item(NAME(m_ppi_p));
+
+ m_cmd = 0;
+
+ m_mcu_p[0] = 0xff;
+ m_mcu_p[1] = 0xff & ~KLS_P15;
+ m_mcu_p[2] = 0xff;
+ m_mcu_p[3] = 0xff;
+
+ m_ppi_p[0] = 0;
+ m_ppi_p[1] = 0;
+ m_ppi_p[2] = 0;
+
+ if (m_speaker)
+ m_speaker->set_levels(4, speaker_levels);
+}
+
+void rtpc_kls_device::device_reset()
+{
+}
+
+void rtpc_kls_device::mcu_map(address_map &map)
+{
+ map(0x0000, 0x0fff).rom().region("mcu", 0);
+ map(0xf800, 0xffff).lr8([this]() { m_atn(1); m_atn(0); return 0; }, "sys_atn");
+}
+
+void rtpc_kls_device::mcu_port1_w(u8 data)
+{
+ LOG("volume %d\n", data >> 6);
+ m_mcu_p[1] = (m_mcu_p[1] & ~KLS_P1O) | (data & KLS_P1O);
+
+ // speaker volume wraps to ppi port b.6 and b.5
+ m_ppi_p[1] &= ~0x60;
+ m_ppi_p[1] |= (data >> 1) & 0x60;
+
+ speaker();
+}
+
+void rtpc_kls_device::mcu_port2_w(u8 data)
+{
+ if ((data ^ m_mcu_p[2]) & KLS_IID)
+ {
+ static const char *const mcu_code[] =
+ {
+ "informational", "received byte from keyboard", "received byte from uart", "returning byte requested by system",
+ "block transfer ready", "unassigned", "self-test performed", "error condition"
+ };
+ LOG("kls mcu iid %d: %s\n", data & 7, mcu_code[data & 7]);
+ }
+
+ if ((data ^ m_mcu_p[2]) & KLS_P23)
+ LOG("kls mcu system reset %d\n", BIT(data, 3));
+
+ if ((data ^ m_mcu_p[2]) & KLS_P24)
+ {
+ if (!BIT(data, 4))
+ {
+ LOG("kls mcu data out 0x%02x\n", m_mcu_p[0]);
+ m_ppi_p[0] = m_mcu_p[0];
+ }
+ m_ppi->pc4_w(BIT(data, 4));
+ }
+
+ if ((data ^ m_mcu_p[2]) & KLS_P26)
+ {
+
+ m_ppi->pc6_w(BIT(data, 6));
+ if (!BIT(data, 6))
+ {
+ LOG("kls mcu data in 0x%02x\n", m_ppi_p[0]);
+ m_mcu_p[0] = m_ppi_p[0];
+ }
+ }
+
+ m_mcu_p[2] = (m_mcu_p[2] & ~KLS_P2O) | (data & KLS_P2O);
+
+ // speaker frequency wraps to ppi port b.7
+ m_ppi_p[1] = (m_ppi_p[1] & ~0x80) | (~data & 0x80);
+
+ // iid, ack, stb map to ppi port c
+ m_ppi_p[2] = (m_ppi_p[2] & ~0x57) | (data & 0x57);
+
+ speaker();
+}
+
+void rtpc_kls_device::mcu_port3_w(u8 data)
+{
+ // uart txd -> rxd wrap
+ m_rcv[0]->in_w<1>(BIT(data, 1));
+
+ m_kbdc->data_write_from_mb(BIT(data, 6));
+ m_kbdc->clock_write_from_mb(BIT(data, 7));
+
+ m_mcu_p[3] = (m_mcu_p[3] & ~KLS_P3O) | (data & KLS_P3O);
+}
+
+/*
+ * bit i/o function
+ * 0 i iid0
+ * 1 i iid1
+ * 2 i iid2
+ * 3 o +irq
+ * 4 i -stb
+ * 5 o ibf
+ * 6 i -ack
+ * 7 o -obf
+ */
+void rtpc_kls_device::ppi_portc_w(u8 data)
+{
+ LOG("ppi_portc_w 0x%02x\n", data);
+
+ // bit 3 (+irq) -> i/o channel
+ if (BIT(m_ppi_p[2] ^ data, 3))
+ {
+ LOG("kls host irq %d\n", BIT(data, 3));
+ m_irq(BIT(data, 3));
+ }
+
+ // bit 5 (+ibf) -> mcu p2.5
+ if (BIT(m_ppi_p[2] ^ data, 5))
+ {
+ if (BIT(data, 5))
+ m_mcu_p[2] |= KLS_P25;
+ else
+ m_mcu_p[2] &= ~KLS_P25;
+ }
+
+ // bit 7 (-obf) -> mcu p3.3 (-int1)
+ if (BIT(m_ppi_p[2] ^ data, 7))
+ {
+ if (BIT(data, 7))
+ m_mcu_p[3] |= KLS_P33;
+ else
+ m_mcu_p[3] &= ~KLS_P33;
+
+ m_mcu->set_input_line(MCS51_INT1_LINE, !BIT(data, 7));
+ }
+
+ m_ppi_p[2] = (m_ppi_p[2] & ~0xa8) | (data & 0xa8);
+}
+
+void rtpc_kls_device::mcu_reset_w(int state)
+{
+ m_mcu->set_input_line(INPUT_LINE_RESET, state);
+}
+
+void rtpc_kls_device::rtc_sqw_w(int state)
+{
+ if (state)
+ m_ppi_p[1] |= 0x08;
+ else
+ m_ppi_p[1] &= ~0x08;
+}
+
+void rtpc_kls_device::rtc_irq_w(int state)
+{
+ if (state)
+ m_ppi_p[1] |= 0x10;
+ else
+ m_ppi_p[1] &= ~0x10;
+}
+
+void rtpc_kls_device::cmd_w(u16 data)
+{
+ LOG("command 0x%02x data 0x%02x (%s)\n", data >> 8, u8(data), machine().describe_context());
+
+ // 00rc cccc dddd dddd
+ m_cmd = BIT(data, 8, 6);
+
+ m_rcv[0]->in_w<0>(BIT(m_cmd, 5));
+ m_rcv[1]->in_w<0>(!BIT(m_cmd, 5));
+
+ switch (m_cmd & KLS_CMD)
+ {
+ case 0x0: // extended command
+ switch (u8(data))
+ {
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ LOG("clr mode bit %d\n", data & 0xf); break;
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ LOG("set mode bit %d\n", data & 0xf); break;
+ default: LOG("extended command 0x%02x\n", data); break;
+ }
+ break;
+ case 0x1: LOG("write keyboard 0x%02x\n", data); break;
+ case 0x2: LOG("write speaker 0x%02x\n", data); break;
+ case 0x3: LOG("write uart control 0x%02x\n", data); break;
+ case 0x4: LOG("write uart query 0x%02x\n", data); break;
+ case 0x5: LOG("set uart rate 0x%02x\n", data); break;
+ case 0x6: LOG("init uart 0x%02x\n", data); break;
+ case 0x7: LOG("set speaker duration 0x%02x\n", data); break;
+ case 0x8: LOG("set speaker freq-hi 0x%02x\n", data); break;
+ case 0x9: LOG("set speaker freq-lo 0x%02x\n", data); break;
+ case 0xc: LOG("diagnostic write 0x%02x\n", data); break;
+ case 0xa: case 0xb: case 0xd: case 0xe: case 0xf:
+ LOG("unassigned\n");
+ break;
+ default:
+ LOG("write shared ram addr 0x%x data 0x%02x\n", m_cmd & 0xf, data);
+ break;
+ }
+
+ m_mcu_p[1] = (m_mcu_p[1] & ~KLS_CMD) | (m_cmd & KLS_CMD);
+ m_ppi->write(0, data);
+}
+
+void rtpc_kls_device::speaker()
+{
+ if (m_speaker)
+ m_speaker->level_w((m_mcu_p[2] & KLS_P27) ? 0 : m_mcu_p[1] >> 6);
+}
+
+ROM_START(rtpc_kls)
+ // Version: 073
+ // Date: 85 289 (16 Oct 1985)
+ // Checksum: 0xc8 0xe8
+ ROM_REGION(0x1000, "mcu", 0)
+ ROM_LOAD("61x6310_8051.bin", 0x0000, 0x1000, CRC(296c16c1) SHA1(83858109c39d5be37e49f24d1db4e2b15f38843e))
+ROM_END
+
+tiny_rom_entry const *rtpc_kls_device::device_rom_region() const
+{
+ return ROM_NAME(rtpc_kls);
+}
diff --git a/src/mame/ibm/rtpc_kls.h b/src/mame/ibm/rtpc_kls.h
new file mode 100644
index 00000000000..834f0c0db1b
--- /dev/null
+++ b/src/mame/ibm/rtpc_kls.h
@@ -0,0 +1,68 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#ifndef MAME_IBM_RTPC_KLS_H
+#define MAME_IBM_RTPC_KLS_H
+
+#pragma once
+
+#include "rtpc_kbdc.h"
+
+#include "bus/rs232/rs232.h"
+#include "cpu/mcs51/mcs51.h"
+#include "machine/clock.h"
+#include "machine/i8255.h"
+#include "machine/input_merger.h"
+#include "sound/spkrdev.h"
+
+class rtpc_kls_device : public device_t
+{
+public:
+ rtpc_kls_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0);
+
+ // input/output lines
+ auto atn() { return m_atn.bind(); }
+ auto irq() { return m_irq.bind(); }
+ void mcu_reset_w(int state);
+ void rtc_sqw_w(int state);
+ void rtc_irq_w(int state);
+
+ // device address map
+ void map(address_map &map);
+
+protected:
+ virtual tiny_rom_entry const *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ void mcu_map(address_map &map) ATTR_COLD;
+
+ void cmd_w(u16 data);
+ void mcu_port1_w(u8 data);
+ void mcu_port2_w(u8 data);
+ void mcu_port3_w(u8 data);
+ void ppi_portc_w(u8 data);
+ void speaker();
+
+private:
+ required_device<i8051_device> m_mcu;
+ required_device<i8255_device> m_ppi;
+ required_device<rtpc_kbdc_device> m_kbdc;
+ required_device<rs232_port_device> m_locc;
+ required_device_array<input_merger_all_high_device, 2> m_rcv;
+
+ optional_device<speaker_sound_device> m_speaker;
+
+ devcb_write_line m_atn;
+ devcb_write_line m_irq;
+
+ u8 m_cmd;
+
+ u8 m_mcu_p[4];
+ u8 m_ppi_p[3];
+};
+
+DECLARE_DEVICE_TYPE(RTPC_KLS, rtpc_kls_device)
+
+#endif // MAME_IBM_RTPC_KLS_H