diff options
| author | 2025-08-29 18:00:25 +0700 | |
|---|---|---|
| committer | 2025-08-29 18:00:25 +0700 | |
| commit | e34b80d4c6ff251e643fa9154a64f51208be5161 (patch) | |
| tree | 83bf4e2d0cd68188bd0d0047cd8c3fd112f00bb4 | |
| parent | bd4ace41e7a0a73821b4805eab562654d344e40f (diff) | |
ibm/rtpc.cpp: refactor keyboard, locator, speaker adapter
| -rw-r--r-- | src/devices/bus/isa/amgda.cpp | 2 | ||||
| -rw-r--r-- | src/mame/ibm/rtpc.cpp | 425 | ||||
| -rw-r--r-- | src/mame/ibm/rtpc_kls.cpp | 410 | ||||
| -rw-r--r-- | src/mame/ibm/rtpc_kls.h | 68 |
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 |
