From d1846f21e7795c657c21a4ccbfb0e0053d06ccff Mon Sep 17 00:00:00 2001 From: Mark Garlanger Date: Thu, 30 May 2024 06:56:21 -0500 Subject: heathkit/h89.cpp: Add Magnolia Microsystems DD controller and h89-mms system (#12413) --- src/mame/heathzenith/h89.cpp | 119 +++++++++++++- src/mame/heathzenith/intr_cntrl.cpp | 92 ++++++++--- src/mame/heathzenith/intr_cntrl.h | 47 +++++- src/mame/heathzenith/mms77316_fdc.cpp | 290 ++++++++++++++++++++++++++++++++++ src/mame/heathzenith/mms77316_fdc.h | 78 +++++++++ src/mame/heathzenith/z37_fdc.cpp | 2 +- src/mame/mame.lst | 1 + 7 files changed, 601 insertions(+), 28 deletions(-) create mode 100644 src/mame/heathzenith/mms77316_fdc.cpp create mode 100644 src/mame/heathzenith/mms77316_fdc.h diff --git a/src/mame/heathzenith/h89.cpp b/src/mame/heathzenith/h89.cpp index 65827b00adc..4fcb2a43d4f 100644 --- a/src/mame/heathzenith/h89.cpp +++ b/src/mame/heathzenith/h89.cpp @@ -45,6 +45,7 @@ #include "h_88_cass.h" #include "intr_cntrl.h" +#include "mms77316_fdc.h" #include "sigmasoft_parallel_port.h" #include "tlb.h" #include "z37_fdc.h" @@ -221,6 +222,44 @@ protected: }; +/** + * Heathkit H89 with MMS hardware + * - MMS 77316 - DD controller + * + * Functionality already implemented/Same as Heath options + * - MMS 77311 - 16k RAM + * - MMS 77312 - ORG-0 CP/M Mod + * + * Hardware currently planned to be implemented: + * - MMS 77318 - 128k RAM board + * - MMS 77319 - Video Output + * - MMS 77320 - SASI board + * - MMS 77322 - Network Controller + * + * Other hardware MMS offered + * - MMS 77314 - Remex H47 / IMI(Corvus) / 3 serial port + * - MMS 77315 - Cameo I/o + * - MMS 77317 - ACT/XCOMP I/O + * + */ +class h89_mms_state : public h89_base_state +{ +public: + h89_mms_state(const machine_config &mconfig, device_type type, const char *tag): + h89_base_state(mconfig, type, tag), + m_mms(*this, "mms_fdc") + { + } + + void h89_mms(machine_config &config); + +protected: + required_device m_mms; + + void h89_mms_io(address_map &map); +}; + + /* The H89 supported 16K, 32K, 48K, or 64K of RAM. The first 8K of address space is reserved for the monitor ROM, floppy ROM, and scratch pad RAM. For 16k-48K @@ -327,8 +366,8 @@ u8 h89_base_state::m1_r(offs_t offset) DCE Serial I/O | EO-E7 | 340-347 Console I/O | E8-EF | 350-357 NMI | F0-F1 | 360-361 - General purpose port | F2 | 362 - Cassette I/O(MTR-88) | F8-F9 | 370-371 + General purpose port | F2 | 362 + Cassette I/O(MTR-88 only)| F8-F9 | 370-371 NMI | FA-FB | 372-373 Disk I/O #1 - 0170-0173 (0x78-0x7b) @@ -393,6 +432,43 @@ void h89_sigmasoft_state::h89_sigmasoft_io(address_map &map) map(0x08,0x0f).rw(m_sigma_parallel, FUNC(sigmasoft_parallel_port::read), FUNC(sigmasoft_parallel_port::write)); } +/* + Memory Map for MMS 444-61C PROM + + PORT + Use | Hex | + ----------------------------+-------+ + Not specified, available | 0-37 | + MMS 77316 | 38-3F | + MMS Internal test fixtures | 40-47 | + MMS 77317 ACT/XCOMP I/O | 48-4F | + MMS 77315 CAMEO I/O | 50-56 | + Unused | 57 | + MMS 77314 Corvus I/O | 58-59 | + MMS 77314 REMEX I/O | 5A-5B | + MMS 77314,15,17 Conf Port | 5C | + Unused | 5D-77 | + Disk I/O #1 | 78-7B | + Disk I/O #2 | 7C-7F | + HDOS reserved | 80-CF | + DCE Serial I/O | D0-D7 | + DTE Serial I/O | D8-DF | + DCE Serial I/O | EO-E7 | + Console I/O | E8-EF | + NMI | F0-F1 | + General purpose port | F2 | + Unused | F8-F9 | + NMI | FA-FB | + Unused | FC-FF | + */ +void h89_mms_state::h89_mms_io(address_map &map) +{ + h89_base_state::h89_base_io(map); + + // Add MMS 77316 Double Density Controller + map(0x38,0x3f).rw(m_mms, FUNC(mms77316_fdc_device::read), FUNC(mms77316_fdc_device::write)); +} + // Input ports static INPUT_PORTS_START( h88 ) @@ -835,6 +911,7 @@ static void intr_ctrl_options(device_slot_interface &device) { device.option_add("original", HEATH_INTR_CNTRL); device.option_add("h37", HEATH_Z37_INTR_CNTRL); + device.option_add("mms", HEATH_MMS_INTR_CNTRL); } void h89_base_state::h89_base(machine_config &config) @@ -907,7 +984,7 @@ void h89_state::h89(machine_config &config) m_h37->block_interrupt_cb().set(m_intr_socket, FUNC(heath_intr_socket::block_interrupts)); } -void h89_sigmasoft_state::h89_sigmasoft(machine_config & config) +void h89_sigmasoft_state::h89_sigmasoft(machine_config &config) { h89(config); m_maincpu->set_addrmap(AS_IO, &h89_sigmasoft_state::h89_sigmasoft_io); @@ -925,6 +1002,19 @@ void h89_sigmasoft_state::h89_sigmasoft(machine_config & config) m_sigma_parallel->ctrl_cb().set(m_tlbc, FUNC(heath_tlb_connector::sigma_ctrl_w)); } +void h89_mms_state::h89_mms(machine_config &config) +{ + h89_base(config); + m_maincpu->set_addrmap(AS_IO, &h89_mms_state::h89_mms_io); + + m_intr_socket->set_default_option("mms"); + m_intr_socket->set_fixed(true); + + MMS77316_FDC(config, m_mms); + m_mms->drq_cb().set(m_intr_socket, FUNC(heath_intr_socket::set_drq)); + m_mms->irq_cb().set(m_intr_socket, FUNC(heath_intr_socket::set_irq)); +} + ROM_START( h88 ) ROM_REGION( 0x2000, "maincpu", ROMREGION_ERASEFF ) @@ -996,6 +1086,28 @@ ROM_START( h89_sigmasoft ) ROMX_LOAD("2716_mtrhex.u518", 0x0000, 0x0800, CRC(842a306a) SHA1(ddbc2b8bb127464af9eda8e7c56e6be7c8b43a16), ROM_BIOS(7)) ROM_END +ROM_START( h89_mms ) + ROM_REGION( 0x2000, "maincpu", ROMREGION_ERASEFF ) + ROM_DEFAULT_BIOS("mms84b") + + ROM_LOAD( "2716_444-19_h17.u520", 0x1800, 0x0800, CRC(26e80ae3) SHA1(0c0ee95d7cb1a760f924769e10c0db1678f2435c)) + + ROM_SYSTEM_BIOS(0, "mms84b", "MMS 444-84B") + ROMX_LOAD("2732_444_84b_mms.u518", 0x0000, 0x1000, CRC(7e75d6f4) SHA1(baf34e036388d1a191197e31f8a93209f04fc58b), ROM_BIOS(0)) + + ROM_SYSTEM_BIOS(1, "kmr-100", "Kres KMR-100 V3.a.02") + ROMX_LOAD("2732_kmr100_v3_a_02.u518", 0x0000, 0x1000, CRC(fd491592) SHA1(3d5803f95c38b237b07cd230353cd9ddc9858c13), ROM_BIOS(1)) + + ROM_SYSTEM_BIOS(2, "mtrhex_4k", "Ultimeth 4k ROM") + ROMX_LOAD("2732_mtrhex_4k.u518", 0x0000, 0x1000, CRC(e26b29a9) SHA1(ba13d6c9deef682a9a8262bc910d46b577929a13), ROM_BIOS(2)) + + ROM_SYSTEM_BIOS(3, "mms84a", "MMS 444-84A (Superseded by MMS 444-84B)") + ROMX_LOAD("2732_444_84a_mms.u518", 0x0000, 0x1000, CRC(0e541a7e) SHA1(b1deb620fc89c1068e2e663e14be69d1f337a4b9), ROM_BIOS(3)) + + ROM_SYSTEM_BIOS(4, "mtrhex", "Ultimeth 2k ROM") + ROMX_LOAD("2716_mtrhex.u518", 0x0000, 0x0800, CRC(842a306a) SHA1(ddbc2b8bb127464af9eda8e7c56e6be7c8b43a16), ROM_BIOS(4)) +ROM_END + ROM_START( z90 ) ROM_REGION( 0x2000, "maincpu", ROMREGION_ERASEFF ) ROM_DEFAULT_BIOS("mtr90") @@ -1027,5 +1139,6 @@ ROM_END // year name parent compat machine input class init company fullname flags COMP( 1979, h88, h89, 0, h88, h88, h88_state, empty_init, "Heath Company", "H-88", MACHINE_SUPPORTS_SAVE) COMP( 1979, h89, 0, 0, h89, h89, h89_state, empty_init, "Heath Company", "H-89", MACHINE_SUPPORTS_SAVE) +COMP( 1981, h89_mms, h89, 0, h89_mms, h89, h89_mms_state, empty_init, "Heath Company", "H-89 with MMS Equipment", MACHINE_SUPPORTS_SAVE) COMP( 1981, z90, h89, 0, h89, h89, h89_state, empty_init, "Zenith Data Systems", "Z-90", MACHINE_SUPPORTS_SAVE) COMP( 1984, h89_sigmasoft, h89, 0, h89_sigmasoft, h89, h89_sigmasoft_state, empty_init, "Heath Company", "H-89 with SigmaSoft IGC", MACHINE_SUPPORTS_SAVE) diff --git a/src/mame/heathzenith/intr_cntrl.cpp b/src/mame/heathzenith/intr_cntrl.cpp index 2ebb46701da..961d2662bb1 100644 --- a/src/mame/heathzenith/intr_cntrl.cpp +++ b/src/mame/heathzenith/intr_cntrl.cpp @@ -12,6 +12,7 @@ DEFINE_DEVICE_TYPE(HEATH_INTR_CNTRL, heath_intr_cntrl, "heath_intr_cntrl", "Heath H/Z-89 Interrupt Controller"); DEFINE_DEVICE_TYPE(HEATH_Z37_INTR_CNTRL, z37_intr_cntrl, "heath_z37_intr_cntrl", "Heath H/Z-89 with Z-37 Interrupt Controller"); +DEFINE_DEVICE_TYPE(HEATH_MMS_INTR_CNTRL, mms_intr_cntrl, "heath_mms_intr_cntrl", "Heath H/Z-89 with MMS Interrupt Controller"); DEFINE_DEVICE_TYPE(HEATH_INTR_SOCKET, heath_intr_socket, "heath_intr_socket", "Heath Interrupt Socket"); @@ -107,6 +108,43 @@ u8 heath_intr_cntrl::get_instruction() return 0xc7 | ((level & 0x7) << 3); } + +/** + * Base interrupt controller for soft-sectored controller. + * + */ +ss_intr_cntrl::ss_intr_cntrl(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock): + heath_intr_cntrl(mconfig, type, tag, owner, clock) +{ +} + +void ss_intr_cntrl::set_drq(int state) +{ + m_drq_raised = bool(state); + + update_intr_line(); +} + + +void ss_intr_cntrl::set_irq(int state) +{ + m_irq_raised = bool(state); + + update_intr_line(); +} + +void ss_intr_cntrl::device_start() +{ + heath_intr_cntrl::device_start(); + + save_item(NAME(m_drq_raised)); + save_item(NAME(m_irq_raised)); + + m_drq_raised = false; + m_irq_raised = false; +} + + /** * Interrupt controller for the Z37 soft-sectored controller. * @@ -114,7 +152,7 @@ u8 heath_intr_cntrl::get_instruction() * interrupts while it is waiting for Z37 events. */ z37_intr_cntrl::z37_intr_cntrl(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock): - heath_intr_cntrl(mconfig, HEATH_Z37_INTR_CNTRL, tag, owner, clock) + ss_intr_cntrl(mconfig, HEATH_Z37_INTR_CNTRL, tag, owner, clock) { } @@ -150,39 +188,57 @@ u8 z37_intr_cntrl::get_instruction() return 0x00; } -void z37_intr_cntrl::set_drq(int state) +void z37_intr_cntrl::device_start() { - m_drq_raised = bool(state); + ss_intr_cntrl::device_start(); + + save_item(NAME(m_intr_blocked)); + + m_intr_blocked = false; +} + +void z37_intr_cntrl::block_interrupts(u8 data) +{ + m_intr_blocked = bool(data); update_intr_line(); } -void z37_intr_cntrl::set_irq(int state) +/** + * Interrupt controller for the mms 77316 soft-sectored controller. + * + */ +mms_intr_cntrl::mms_intr_cntrl(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock): + ss_intr_cntrl(mconfig, HEATH_MMS_INTR_CNTRL, tag, owner, clock) { - m_irq_raised = bool(state); +} - update_intr_line(); +void mms_intr_cntrl::update_intr_line() +{ + m_socket->raise_irq((m_irq_raised || m_drq_raised || (m_intr_lines != 0)) ? 1 : 0); } -void z37_intr_cntrl::device_start() +u8 mms_intr_cntrl::get_instruction() { - heath_intr_cntrl::device_start(); + if (m_irq_raised) + { + // RST 30H (Interrupt 6) + return 0xf7; + } - save_item(NAME(m_intr_blocked)); - save_item(NAME(m_drq_raised)); - save_item(NAME(m_irq_raised)); + if (m_drq_raised) + { + // EI + return 0xfb; + } - m_intr_blocked = false; - m_drq_raised = false; - m_irq_raised = false; + return heath_intr_cntrl::get_instruction(); } -void z37_intr_cntrl::block_interrupts(u8 data) +void mms_intr_cntrl::device_start() { - m_intr_blocked = bool(data); - - update_intr_line(); + ss_intr_cntrl::device_start(); } diff --git a/src/mame/heathzenith/intr_cntrl.h b/src/mame/heathzenith/intr_cntrl.h index b5fc10cbf82..b35efe6ea9e 100644 --- a/src/mame/heathzenith/intr_cntrl.h +++ b/src/mame/heathzenith/intr_cntrl.h @@ -58,17 +58,36 @@ protected: u8 m_intr_lines; }; + +/** + * Base interrupt controller for multiple soft-sectored controllers. + * + */ +class ss_intr_cntrl : public heath_intr_cntrl +{ +public: + virtual void set_drq(int state) override; + virtual void set_irq(int state) override; + +protected: + ss_intr_cntrl(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock = 0); + + virtual void device_start() override; + + bool m_drq_raised; + bool m_irq_raised; +}; + + /** * Interrupt controller when the Z37 soft-sectored controller is installed. * */ -class z37_intr_cntrl : public heath_intr_cntrl +class z37_intr_cntrl : public ss_intr_cntrl { public: z37_intr_cntrl(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); - virtual void set_drq(int state) override; - virtual void set_irq(int state) override; virtual void block_interrupts(u8 data) override; protected: @@ -77,14 +96,30 @@ protected: virtual void device_start() override; -private: bool m_intr_blocked; - bool m_drq_raised; - bool m_irq_raised; }; + +/** + * Interrupt controller when the mms soft-sectored controller is installed. + * + */ +class mms_intr_cntrl : public ss_intr_cntrl +{ +public: + mms_intr_cntrl(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + +protected: + virtual u8 get_instruction() override; + virtual void update_intr_line() override; + + virtual void device_start() override; +}; + + DECLARE_DEVICE_TYPE(HEATH_INTR_CNTRL, heath_intr_cntrl) DECLARE_DEVICE_TYPE(HEATH_Z37_INTR_CNTRL, z37_intr_cntrl) +DECLARE_DEVICE_TYPE(HEATH_MMS_INTR_CNTRL, mms_intr_cntrl); class heath_intr_socket : public device_t, diff --git a/src/mame/heathzenith/mms77316_fdc.cpp b/src/mame/heathzenith/mms77316_fdc.cpp new file mode 100644 index 00000000000..c46e791ab6b --- /dev/null +++ b/src/mame/heathzenith/mms77316_fdc.cpp @@ -0,0 +1,290 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + Magnolia Microsystems 77316 soft-sectored floppy controller + + +****************************************************************************/ + +#include "emu.h" + +#include "mms77316_fdc.h" + +#define LOG_REG (1U << 1) // Shows register setup +#define LOG_LINES (1U << 2) // Show control lines +#define LOG_DRIVE (1U << 3) // Show drive select +#define LOG_FUNC (1U << 4) // Function calls +#define LOG_ERR (1U << 5) // log errors +#define LOG_BURST (1U << 6) // burst mode + +#define VERBOSE (0) + +#include "logmacro.h" + +#define LOGREG(...) LOGMASKED(LOG_REG, __VA_ARGS__) +#define LOGLINES(...) LOGMASKED(LOG_LINES, __VA_ARGS__) +#define LOGDRIVE(...) LOGMASKED(LOG_DRIVE, __VA_ARGS__) +#define LOGFUNC(...) LOGMASKED(LOG_FUNC, __VA_ARGS__) +#define LOGERR(...) LOGMASKED(LOG_ERR, __VA_ARGS__) +#define LOGBURST(...) LOGMASKED(LOG_BURST, __VA_ARGS__) + +#ifdef _MSC_VER +#define FUNCNAME __func__ +#else +#define FUNCNAME __PRETTY_FUNCTION__ +#endif + +DEFINE_DEVICE_TYPE(MMS77316_FDC, mms77316_fdc_device, "mms77316_fdc", "Magnolia MicroSystems 77316 Soft-sectored Controller"); + +mms77316_fdc_device::mms77316_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock): + device_t(mconfig, MMS77316_FDC, tag, owner, 0), + m_irq_cb(*this), + m_drq_cb(*this), + m_fdc(*this, "mms_fdc"), + m_floppies(*this, "mms_fdc:%u", 0U) +{ +} + +void mms77316_fdc_device::ctrl_w(u8 val) +{ + u8 floppy_drive = BIT(val, 0, 3); + u8 five_in_drv = bool(BIT(val, ctrl_525DriveSel_c)); + + m_drq_count = 0; + m_irq_allowed = bool(BIT(val, ctrl_EnableIntReq_c)); + m_drq_allowed = m_irq_allowed && bool(BIT(val, ctrl_EnableDrqInt_c)); + + m_fdc->dden_w(BIT(val, ctrl_SetMFMRecording_c)); + + if (m_irq_allowed) + { + m_irq_cb(m_irq); + m_drq_cb(m_drq); + } + else + { + m_irq_cb(CLEAR_LINE); + m_drq_cb(CLEAR_LINE); + } + + LOGREG("%s: floppydrive: %d\n", FUNCNAME, floppy_drive); + + m_fdc->set_floppy(m_floppies[floppy_drive]->get_device()); + + LOGREG("%s: intrq allowed: %d, drq allowed: %d\n", FUNCNAME, m_irq_allowed, m_drq_allowed); + + m_fdc->set_clock(five_in_drv ? FIVE_IN_CLOCK : EIGHT_IN_CLOCK); + + for (int i = 4; i < 8; i++) + { + auto elem = m_floppies[i]; + if (elem) + { + floppy_image_device *floppy = elem->get_device(); + if (floppy) + { + // turn on all installed 5" floppies + floppy->mon_w(!five_in_drv); + } + } + } +} + +void mms77316_fdc_device::data_w(u8 val) +{ + if (burstMode()) + { + // TODO add wait states in burst mode, currently blocked on Z80 properly supporting wait states + LOGBURST("%s: burst_mode: %d\n", FUNCNAME, val); + } + + m_fdc->data_w(val); +} + +void mms77316_fdc_device::write(offs_t reg, u8 val) +{ + LOGFUNC("%s: reg: %d val: 0x%02x\n", FUNCNAME, reg, val); + + switch (reg) + { + case 0: + ctrl_w(val); + break; + case 1: + case 2: + case 3: + LOGFUNC("%s: Unexpected port write reg: %d val: 0x%02x\n", FUNCNAME, reg, val); + break; + case 4: + m_fdc->cmd_w(val); + break; + case 5: + m_fdc->track_w(val); + break; + case 6: + m_fdc->sector_w(val); + break; + case 7: + data_w(val); + break; + } +} + +u8 mms77316_fdc_device::data_r() +{ + if (burstMode()) + { + // TODO add wait states in burst mode, currently blocked on Z80 properly supporting wait states + LOGBURST("%s: burst_mode\n", FUNCNAME); + } + + return m_fdc->data_r(); +} + +u8 mms77316_fdc_device::read(offs_t reg) +{ + // default return for the h89 + u8 value = 0xff; + + switch (reg) + { + case 0: + case 1: + case 2: + case 3: + // read not supported on these addresses + LOGERR("%s: Unexpected port read reg: %d\n", FUNCNAME, reg); + break; + case 4: + value = m_fdc->status_r(); + break; + case 5: + value = m_fdc->track_r(); + break; + case 6: + value = m_fdc->sector_r(); + break; + case 7: + value = data_r(); + break; + } + + LOGFUNC("%s: reg: %d val: 0x%02x\n", FUNCNAME, reg, value); + + return value; +} + +void mms77316_fdc_device::device_start() +{ + save_item(NAME(m_irq_allowed)); + save_item(NAME(m_drq_allowed)); + save_item(NAME(m_irq)); + save_item(NAME(m_drq)); + save_item(NAME(m_drq_count)); +} + +void mms77316_fdc_device::device_reset() +{ + m_irq_allowed = false; + m_drq_allowed = false; + m_irq = false; + m_drq_count = 0; + + m_irq_cb(0); + m_drq_cb(0); + for (int i = 0; i < 4; i++) + { + auto elem = m_floppies[i]; + if (elem) + { + floppy_image_device *floppy = elem->get_device(); + if (floppy) + { + // turn on motor of all installed 8" floppies + floppy->mon_w(0); + } + } + } +} + +static void mms_5_in_floppies(device_slot_interface &device) +{ + // H-17-1 -- SS 48tpi + device.option_add("5_ssdd", FLOPPY_525_SSDD); + // SS 96tpi + device.option_add("5_ssqd", FLOPPY_525_SSQD); + // DS 48tpi + device.option_add("5_dd", FLOPPY_525_DD); + // H-17-4 / H-17-5 -- DS 96tpi + device.option_add("5_qd", FLOPPY_525_QD); +} + +static void mms_8_in_floppies(device_slot_interface &device) +{ + // 8" DSDD + device.option_add("8_sssd", FLOPPY_8_SSSD); + // 8" SSDD + device.option_add("8_dssd", FLOPPY_8_DSSD); + // 8" DSDD + device.option_add("8_ssdd", FLOPPY_8_SSDD); + // 8" SSDD + device.option_add("8_dsdd", FLOPPY_8_DSDD); +} + +void mms77316_fdc_device::device_add_mconfig(machine_config &config) +{ + FD1797(config, m_fdc, EIGHT_IN_CLOCK); + m_fdc->intrq_wr_callback().set(FUNC(mms77316_fdc_device::set_irq)); + m_fdc->drq_wr_callback().set(FUNC(mms77316_fdc_device::set_drq)); + + // 8" Floppy drives + FLOPPY_CONNECTOR(config, m_floppies[0], mms_8_in_floppies, "8_dsdd", floppy_image_device::default_mfm_floppy_formats); + m_floppies[0]->enable_sound(true); + FLOPPY_CONNECTOR(config, m_floppies[1], mms_8_in_floppies, "8_dsdd", floppy_image_device::default_mfm_floppy_formats); + m_floppies[1]->enable_sound(true); + FLOPPY_CONNECTOR(config, m_floppies[2], mms_8_in_floppies, "8_dsdd", floppy_image_device::default_mfm_floppy_formats); + m_floppies[2]->enable_sound(true); + FLOPPY_CONNECTOR(config, m_floppies[3], mms_8_in_floppies, "8_dsdd", floppy_image_device::default_mfm_floppy_formats); + m_floppies[3]->enable_sound(true); + + // 5" Floppy drives + FLOPPY_CONNECTOR(config, m_floppies[4], mms_5_in_floppies, "5_qd", floppy_image_device::default_mfm_floppy_formats); + m_floppies[4]->enable_sound(true); + FLOPPY_CONNECTOR(config, m_floppies[5], mms_5_in_floppies, "5_qd", floppy_image_device::default_mfm_floppy_formats); + m_floppies[5]->enable_sound(true); + FLOPPY_CONNECTOR(config, m_floppies[6], mms_5_in_floppies, "5_qd", floppy_image_device::default_mfm_floppy_formats); + m_floppies[6]->enable_sound(true); + FLOPPY_CONNECTOR(config, m_floppies[7], mms_5_in_floppies, "5_qd", floppy_image_device::default_mfm_floppy_formats); + m_floppies[7]->enable_sound(true); +} + +void mms77316_fdc_device::set_irq(int state) +{ + LOGLINES("set irq, allowed: %d state: %d\n", m_irq_allowed, state); + + if (state) + { + m_drq_count = 0; + } + + m_irq = state; + + m_irq_cb(m_irq_allowed ? m_irq : CLEAR_LINE); +} + +void mms77316_fdc_device::set_drq(int state) +{ + bool drq_allowed = false; + + LOGLINES("set drq, allowed: %d state: %d\n", m_drq_allowed, state); + m_drq = state; + + if (m_drq) + { + // even if drq bit is not set, trigger if the first one after an IRQ. + drq_allowed = m_drq_allowed || (m_drq_count++ == 0); + } + + m_drq_cb(drq_allowed ? m_drq : CLEAR_LINE); +} diff --git a/src/mame/heathzenith/mms77316_fdc.h b/src/mame/heathzenith/mms77316_fdc.h new file mode 100644 index 00000000000..7a43fe8f90c --- /dev/null +++ b/src/mame/heathzenith/mms77316_fdc.h @@ -0,0 +1,78 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + Magnolia Microsystems 77316 soft-sectored floppy controller + +****************************************************************************/ + +#ifndef MAME_HEATHKIT_MMS77316_FDC_H +#define MAME_HEATHKIT_MMS77316_FDC_H + +#pragma once + +#include "imagedev/floppy.h" +#include "machine/wd_fdc.h" + + +class mms77316_fdc_device : public device_t +{ +public: + + mms77316_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + + void write(offs_t reg, u8 val); + u8 read(offs_t reg); + + auto irq_cb() { return m_irq_cb.bind(); } + auto drq_cb() { return m_drq_cb.bind(); } + +protected: + + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_add_mconfig(machine_config &config) override; + + void ctrl_w(u8 val); + void data_w(u8 val); + u8 data_r(); + + void set_irq(int state); + void set_drq(int state); + + // Burst mode was required for a 2 MHz Z80 to handle 8" DD data rates. + // The typical irq/drq was too slow, this utilizes wait states to read the + // WD1797 data port once the drq line is high. + inline bool burstMode() { return !m_drq_allowed; } + +private: + + devcb_write_line m_irq_cb; + devcb_write_line m_drq_cb; + + required_device m_fdc; + required_device_array m_floppies; + + bool m_irq_allowed; + bool m_drq_allowed; + + bool m_irq; + bool m_drq; + u32 m_drq_count; + + /// Bits set in cmd_ControlPort_c + static constexpr u8 ctrl_525DriveSel_c = 2; + static constexpr u8 ctrl_EnableIntReq_c = 3; + static constexpr u8 ctrl_EnableDrqInt_c = 5; + static constexpr u8 ctrl_SetMFMRecording_c = 6; + + static constexpr XTAL MASTER_CLOCK = XTAL(8'000'000); + static constexpr XTAL FIVE_IN_CLOCK = MASTER_CLOCK / 8; + static constexpr XTAL EIGHT_IN_CLOCK = MASTER_CLOCK / 4; + +}; + +DECLARE_DEVICE_TYPE(MMS77316_FDC, mms77316_fdc_device) + + +#endif // MAME_HEATHKIT_MMS77316_FDC_H diff --git a/src/mame/heathzenith/z37_fdc.cpp b/src/mame/heathzenith/z37_fdc.cpp index 669bd5b8722..e4d68c0c667 100644 --- a/src/mame/heathzenith/z37_fdc.cpp +++ b/src/mame/heathzenith/z37_fdc.cpp @@ -229,7 +229,7 @@ void heath_z37_fdc_device::set_irq(int state) void heath_z37_fdc_device::set_drq(int state) { - LOGLINES("set drq, allowed: %d state: %d\n", m_irq_allowed, state); + LOGLINES("set drq, allowed: %d state: %d\n", m_drq_allowed, state); m_drq_cb(m_drq_allowed ? state : CLEAR_LINE); } diff --git a/src/mame/mame.lst b/src/mame/mame.lst index b644e1f2dbf..fb4bc378c56 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -19435,6 +19435,7 @@ h19 // Heath H19 @source:heathzenith/h89.cpp h89 // Heath H89 (WH89) h88 // Heath H88 (with cassette tape) +h89_mms // Heath H89 with Magnolia MicroSystems(MMS) hardware h89_sigmasoft // H89 with the SigmaSoft IGC card z90 // Zenith Z-90 -- cgit v1.2.3