From 9a69be8fd315faa30caee833213a523f7bf25700 Mon Sep 17 00:00:00 2001 From: Mark Garlanger Date: Sun, 11 Jun 2023 09:57:13 -0500 Subject: heathkit/h89.cpp add support for z37 soft-sector controller (#11276) Machines promoted to WORKING --------------------------------- Heathkit H89 [Mark Garlanger] --- src/mame/heathkit/h89.cpp | 94 ++++++++++++----- src/mame/heathkit/intr_cntrl.cpp | 179 ++++++++++++++++++++++++++++++++ src/mame/heathkit/intr_cntrl.h | 75 ++++++++++++++ src/mame/heathkit/tlb.cpp | 2 +- src/mame/heathkit/z37_fdc.cpp | 216 +++++++++++++++++++++++++++++++++++++++ src/mame/heathkit/z37_fdc.h | 83 +++++++++++++++ 6 files changed, 620 insertions(+), 29 deletions(-) create mode 100644 src/mame/heathkit/intr_cntrl.cpp create mode 100644 src/mame/heathkit/intr_cntrl.h create mode 100644 src/mame/heathkit/z37_fdc.cpp create mode 100644 src/mame/heathkit/z37_fdc.h diff --git a/src/mame/heathkit/h89.cpp b/src/mame/heathkit/h89.cpp index 44cf2c76927..2a5e2ab81dd 100644 --- a/src/mame/heathkit/h89.cpp +++ b/src/mame/heathkit/h89.cpp @@ -44,6 +44,8 @@ #include "emu.h" #include "tlb.h" +#include "z37_fdc.h" +#include "intr_cntrl.h" #include "cpu/z80/z80.h" #include "machine/ins8250.h" @@ -64,26 +66,28 @@ public: , m_ram(*this, RAM_TAG) , m_floppy_ram(*this, "floppyram") , m_tlb(*this, "tlb") + , m_h37(*this, "h37") + , m_intr_cntrl(*this, "intr_cntrl") , m_console(*this, "console") , m_serial1(*this, "serial1") , m_serial2(*this, "serial2") , m_serial3(*this, "serial3") - , m_gpp(0) - , m_rom_enabled(true) - , m_timer_intr_enabled(true) - , m_floppy_ram_wp(true) { } void h89(machine_config &config); + private: + required_device m_maincpu; required_memory_region m_maincpu_region; memory_view m_mem_view; required_device m_ram; required_shared_ptr m_floppy_ram; required_device m_tlb; + required_device m_h37; + required_device m_intr_cntrl; required_device m_console; required_device m_serial1; required_device m_serial2; @@ -118,6 +122,7 @@ private: uint8_t raise_NMI_r(); void raise_NMI_w(uint8_t data); + void console_intr(uint8_t data); }; /* @@ -206,6 +211,7 @@ void h89_state::h89_io(address_map &map) // - H47 Dual 8" Drives - Requires MTR-89 or MTR-90 ROM // - H67 8" Hard disk + 8" Floppy Drives - Requires MTR-90 ROM // map(0x78, 0x7b) + map(0x78, 0x7b).rw(m_h37, FUNC(heath_z37_fdc_device::read), FUNC(heath_z37_fdc_device::write)); // Disk I/O #2 - 0174-0177 (0x7c-0x7f) // Options @@ -228,7 +234,7 @@ void h89_state::h89_io(address_map &map) map(0xf0, 0xf1).rw(FUNC(h89_state::raise_NMI_r),FUNC(h89_state::raise_NMI_w)); // General Purpose Port (GPP) - map(0xf2, 0xf2).w(FUNC(h89_state::port_f2_w)).portr("SW501"); + map(0xf2, 0xf2).w(FUNC(h89_state::port_f2_w)).portr("MTR90_SW501"); // port defined on the H8. On the H89, access to these addresses causes a NMI map(0xfa, 0xfb).rw(FUNC(h89_state::raise_NMI_r), FUNC(h89_state::raise_NMI_w)); @@ -238,7 +244,7 @@ void h89_state::h89_io(address_map &map) static INPUT_PORTS_START( h89 ) // Settings with the MTR-88 ROM (#444-40) -// PORT_START("SW501") +// PORT_START("MTR88_SW501") // PORT_DIPNAME( 0x1f, 0x00, "Unused" ) PORT_DIPLOCATION("S1:1,2,3,4,5") // PORT_DIPNAME( 0x20, 0x20, "Perform memory test at start" ) PORT_DIPLOCATION("S1:6") // PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) @@ -250,7 +256,7 @@ static INPUT_PORTS_START( h89 ) // PORT_DIPSETTING( 0xc0, "57600" ) // Settings with the MTR-89 ROM (#444-62) -// PORT_START("SW501") +// PORT_START("MTR89_SW501") // PORT_DIPNAME( 0x03, 0x00, "Disk I/O #2" ) PORT_DIPLOCATION("S1:1,2") // PORT_DIPSETTING( 0x00, "H-88-1" ) // PORT_DIPSETTING( 0x01, "H/Z-47" ) @@ -275,27 +281,27 @@ static INPUT_PORTS_START( h89 ) // PORT_DIPSETTING( 0x80, "Auto" ) // Settings with the MTR-90 ROM (#444-84 or 444-142) - PORT_START("SW501") - PORT_DIPNAME( 0x03, 0x00, "Disk I/O #2" ) PORT_DIPLOCATION("S1:1,2") + PORT_START("MTR90_SW501") + PORT_DIPNAME( 0x03, 0x00, "Disk I/O #2" ) PORT_DIPLOCATION("SW501:1,2") PORT_DIPSETTING( 0x00, "H-88-1 (Not yet implemented)" ) PORT_DIPSETTING( 0x01, "H/Z-47 (Not yet implemented)" ) PORT_DIPSETTING( 0x02, "Z-67 (Not yet implemented)" ) PORT_DIPSETTING( 0x03, "Undefined" ) - PORT_DIPNAME( 0x0c, 0x00, "Disk I/O #1" ) PORT_DIPLOCATION("S1:3,4") - PORT_DIPSETTING( 0x00, "H-89-37 (Not yet implemented)" ) + PORT_DIPNAME( 0x0c, 0x00, "Disk I/O #1" ) PORT_DIPLOCATION("SW501:3,4") + PORT_DIPSETTING( 0x00, "H-89-37" ) PORT_DIPSETTING( 0x04, "H/Z-47 (Not yet implemented)" ) PORT_DIPSETTING( 0x08, "Z-67 (Not yet implemented)" ) PORT_DIPSETTING( 0x0c, "Undefined" ) - PORT_DIPNAME( 0x10, 0x00, "Primary Boot from" ) PORT_DIPLOCATION("S1:5") + PORT_DIPNAME( 0x10, 0x00, "Primary Boot from" ) PORT_DIPLOCATION("SW501:5") PORT_DIPSETTING( 0x00, "Disk I/O #2" ) PORT_DIPSETTING( 0x10, "Disk I/O #1" ) - PORT_DIPNAME( 0x20, 0x20, "Perform memory test at start" ) PORT_DIPLOCATION("S1:6") + PORT_DIPNAME( 0x20, 0x20, "Perform memory test at start" ) PORT_DIPLOCATION("SW501:6") PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x40, 0x00, "Console Baud rate" ) PORT_DIPLOCATION("S1:7") + PORT_DIPNAME( 0x40, 0x00, "Console Baud rate" ) PORT_DIPLOCATION("SW501:7") PORT_DIPSETTING( 0x00, "9600" ) PORT_DIPSETTING( 0x40, "19200" ) - PORT_DIPNAME( 0x80, 0x00, "Boot mode" ) PORT_DIPLOCATION("S1:8") + PORT_DIPNAME( 0x80, 0x00, "Boot mode" ) PORT_DIPLOCATION("SW501:8") PORT_DIPSETTING( 0x00, DEF_STR( Normal ) ) PORT_DIPSETTING( 0x80, "Auto" ) INPUT_PORTS_END @@ -340,13 +346,22 @@ void h89_state::machine_start() m_mem_view[2].install_ram(0x0000, 0x1fff, m_ram_ptr + ram_size - 0x2000); } + m_rom_enabled = true; + m_timer_intr_enabled = true; + m_floppy_ram_wp = false; update_gpp(0); + update_mem_view(); } void h89_state::machine_reset() { + m_rom_enabled = true; + m_timer_intr_enabled = true; + m_floppy_ram_wp = false; + update_gpp(0); + update_mem_view(); } @@ -362,41 +377,53 @@ void h89_state::raise_NMI_w(uint8_t) m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::from_usec(2)); } +void h89_state::console_intr(uint8_t data) +{ + if (data == CLEAR_LINE) + { + m_intr_cntrl->lower_irq(3); + } + else + { + m_intr_cntrl->raise_irq(3); + } +} + TIMER_DEVICE_CALLBACK_MEMBER(h89_state::h89_irq_timer) { if (m_timer_intr_enabled) { - m_maincpu->set_input_line_and_vector(0, HOLD_LINE, 0xcf); + m_intr_cntrl->raise_irq(1); } } void h89_state::update_mem_view() { - if (m_rom_enabled) - { - m_mem_view.select(m_floppy_ram_wp ? 0 : 1); - } - else - { - m_mem_view.select(2); - } + m_mem_view.select(m_rom_enabled ? (m_floppy_ram_wp ? 0 : 1) : 2); } void h89_state::update_gpp(uint8_t gpp) { m_gpp = gpp; - m_rom_enabled = BIT(m_gpp, GPP_DISABLE_ROM_BIT) == 0; + bool new_rom_enabled = BIT(m_gpp, GPP_DISABLE_ROM_BIT) == 0; - update_mem_view(); + if (m_rom_enabled != new_rom_enabled) + { + m_rom_enabled = new_rom_enabled; - m_timer_intr_enabled = BIT(m_gpp, GPP_ENABLE_TIMER_INTERRUPT_BIT) == 1; + update_mem_view(); + } + + m_timer_intr_enabled = bool(BIT(m_gpp, GPP_ENABLE_TIMER_INTERRUPT_BIT)); } // General Purpose Port void h89_state::port_f2_w(uint8_t data) { update_gpp(data); + + m_intr_cntrl->lower_irq(1); } void h89_state::h89(machine_config & config) @@ -405,16 +432,27 @@ void h89_state::h89(machine_config & config) Z80(config, m_maincpu, H89_CLOCK); m_maincpu->set_addrmap(AS_PROGRAM, &h89_state::h89_mem); m_maincpu->set_addrmap(AS_IO, &h89_state::h89_io); + m_maincpu->set_irq_acknowledge_callback("intr_cntrl", FUNC(heath_intr_cntrl::irq_callback)); + + HEATH_Z37_INTR_CNTRL(config, m_intr_cntrl); + m_intr_cntrl->irq_line_cb().set_inputline(m_maincpu, INPUT_LINE_IRQ0); RAM(config, m_ram).set_default_size("64K").set_extra_options("16K,32K,48K").set_default_value(0x00); INS8250(config, m_console, INS8250_CLOCK); + m_console->out_int_callback().set(FUNC(h89_state::console_intr)); + HEATH_TLB(config, m_tlb); // Connect the console port on CPU board to serial port on TLB m_console->out_tx_callback().set(m_tlb, FUNC(heath_tlb_device::cb1_w)); m_tlb->serial_data_callback().set(m_console, FUNC(ins8250_uart_device::rx_w)); + HEATH_Z37_FDC(config, m_h37); + m_h37->drq_cb().set(m_intr_cntrl, FUNC(z37_intr_cntrl::set_drq)); + m_h37->irq_cb().set(m_intr_cntrl, FUNC(z37_intr_cntrl::set_intrq)); + m_h37->block_interrupt_cb().set(m_intr_cntrl, FUNC(z37_intr_cntrl::block_interrupts)); + // H-88-3 3-port serial board INS8250(config, m_serial1, INS8250_CLOCK); INS8250(config, m_serial2, INS8250_CLOCK); @@ -453,4 +491,4 @@ ROM_END // Driver // YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS -COMP( 1979, h89, 0, 0, h89, h89, h89_state, empty_init, "Heath Company", "Heathkit H89", MACHINE_NOT_WORKING) +COMP( 1979, h89, 0, 0, h89, h89, h89_state, empty_init, "Heath Company", "Heathkit H89", MACHINE_SUPPORTS_SAVE) diff --git a/src/mame/heathkit/intr_cntrl.cpp b/src/mame/heathkit/intr_cntrl.cpp new file mode 100644 index 00000000000..30a694c05cb --- /dev/null +++ b/src/mame/heathkit/intr_cntrl.cpp @@ -0,0 +1,179 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + Heathkit Interrupt controller for H89 + +****************************************************************************/ + +#include "emu.h" + +#include "intr_cntrl.h" + +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"); + +heath_intr_cntrl::heath_intr_cntrl(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : heath_intr_cntrl(mconfig, HEATH_INTR_CNTRL, tag, owner, clock) +{ +} + +heath_intr_cntrl::heath_intr_cntrl(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, type, tag, owner, 0) + , m_irq_line(*this) +{ +} + +void heath_intr_cntrl::device_start() +{ + save_item(NAME(m_intr_lines)); + + m_intr_lines = 0; +} + +void heath_intr_cntrl::device_resolve_objects() +{ + m_irq_line.resolve_safe(); +} + +void heath_intr_cntrl::update_intr_line() +{ + + m_irq_line(m_intr_lines == 0 ? CLEAR_LINE : ASSERT_LINE); +} + +void heath_intr_cntrl::raise_irq(uint8_t level) +{ + // only 0 to 7 is valid + level &= 0x7; + m_intr_lines |= 1 << level; + + update_intr_line(); +} + +void heath_intr_cntrl::lower_irq(uint8_t level) +{ + // only 0 to 7 is valid + level &= 0x7; + m_intr_lines &= ~(1 << level); + + update_intr_line(); +} + +uint8_t heath_intr_cntrl::get_instruction() +{ + + // determine top priority instruction + if (!m_intr_lines) + { + // should not occur. + // NO-OP ? + logerror("get instruct: bad m_intr_lines\n"); + + return 0x00; + } + + uint8_t level = 0; + uint8_t mask = 0x01; + + while (mask) + { + if (m_intr_lines & mask) + { + break; + } + level++; + mask <<= 1; + } + + if (level > 7) + { + logerror("bad level: %d\n", level); + } + + // return RST based on level + return 0xc7 | ((level & 0x7) << 3); +} + +IRQ_CALLBACK_MEMBER(heath_intr_cntrl::irq_callback) +{ + return get_instruction(); +} + +z37_intr_cntrl::z37_intr_cntrl(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : heath_intr_cntrl(mconfig, HEATH_Z37_INTR_CNTRL, tag, owner, clock) +{ + m_interrupts_blocked = false; + m_drq_raised = false; + m_fd_irq_raised = false; +} + +void z37_intr_cntrl::update_intr_line() +{ + + m_irq_line( + m_fd_irq_raised || + m_drq_raised || + (!m_interrupts_blocked && (m_intr_lines != 0)) ? ASSERT_LINE : CLEAR_LINE); +} + +uint8_t z37_intr_cntrl::get_instruction() +{ + + if (m_drq_raised) + { + // EI + return 0xfb; + } + + if (m_fd_irq_raised) + { + // RST 20H (Interrupt 4) + return 0xe7; + } + + + if (!m_interrupts_blocked) + { + return heath_intr_cntrl::get_instruction(); + } + + // shouldn't get here - NO-OP? + logerror("Warning: z37 intr get_instruction: fd: %d dr: %d ib: %d\n", m_fd_irq_raised, m_drq_raised, m_interrupts_blocked); + return 0x00; +} + +void z37_intr_cntrl::set_drq(uint8_t data) +{ + m_drq_raised = (data != CLEAR_LINE); + + update_intr_line(); +} + + +void z37_intr_cntrl::set_intrq(uint8_t data) +{ + m_fd_irq_raised = (data != CLEAR_LINE); + + update_intr_line(); +} + +void z37_intr_cntrl::device_start() +{ + heath_intr_cntrl::device_start(); + + save_item(NAME(m_interrupts_blocked)); + save_item(NAME(m_drq_raised)); + save_item(NAME(m_fd_irq_raised)); + + m_interrupts_blocked = false; + m_drq_raised = false; + m_fd_irq_raised = false; +} + +void z37_intr_cntrl::block_interrupts(uint8_t data) +{ + m_interrupts_blocked = (data != CLEAR_LINE); + + update_intr_line(); +} diff --git a/src/mame/heathkit/intr_cntrl.h b/src/mame/heathkit/intr_cntrl.h new file mode 100644 index 00000000000..d6da5c0b6d9 --- /dev/null +++ b/src/mame/heathkit/intr_cntrl.h @@ -0,0 +1,75 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + Heathkit Interrupt Controllers + + Interrupt controllers for the Heath H89. + +****************************************************************************/ + +#ifndef MAME_HEATHKIT_INTR_CNTRL_H +#define MAME_HEATHKIT_INTR_CNTRL_H + +#pragma once + +/** + * Heath H89 interrupt controller + * + */ +class heath_intr_cntrl : public device_t +{ +public: + heath_intr_cntrl(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + + virtual void raise_irq(uint8_t level); + virtual void lower_irq(uint8_t level); + + IRQ_CALLBACK_MEMBER(irq_callback); + + auto irq_line_cb() { return m_irq_line.bind(); } + +protected: + heath_intr_cntrl(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock = 0); + + virtual uint8_t get_instruction(); + virtual void update_intr_line(); + + virtual void device_start() override; + virtual void device_resolve_objects() override; + + devcb_write8 m_irq_line; + + uint8_t m_intr_lines; +}; + +/** + * Interrupt controller when the Z37 soft-sectored controller is installed. + * + */ +class z37_intr_cntrl : public heath_intr_cntrl +{ +public: + z37_intr_cntrl(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + + virtual void set_drq(uint8_t data); + virtual void set_intrq(uint8_t data); + virtual void block_interrupts(uint8_t data); + +protected: + + virtual uint8_t get_instruction() override; + virtual void update_intr_line() override; + + virtual void device_start() override; + +private: + bool m_interrupts_blocked; + bool m_drq_raised; + bool m_fd_irq_raised; +}; + +DECLARE_DEVICE_TYPE(HEATH_INTR_CNTRL, heath_intr_cntrl) +DECLARE_DEVICE_TYPE(HEATH_Z37_INTR_CNTRL, z37_intr_cntrl) + +#endif // MAME_HEATHKIT_H89_INTR_CNTRL_H diff --git a/src/mame/heathkit/tlb.cpp b/src/mame/heathkit/tlb.cpp index ee13efb3e8c..38a67c01353 100644 --- a/src/mame/heathkit/tlb.cpp +++ b/src/mame/heathkit/tlb.cpp @@ -744,7 +744,7 @@ void heath_tlb_device::device_add_mconfig(machine_config &config) // sound hardware SPEAKER(config, "mono").front_center(); - BEEP(config, m_beep, H19_BEEP_FRQ).add_route(ALL_OUTPUTS, "mono", 1.00); + BEEP(config, m_beep, H19_BEEP_FRQ).add_route(ALL_OUTPUTS, "mono", 0.05); } heath_super19_tlb_device::heath_super19_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : diff --git a/src/mame/heathkit/z37_fdc.cpp b/src/mame/heathkit/z37_fdc.cpp new file mode 100644 index 00000000000..5fccdc2d751 --- /dev/null +++ b/src/mame/heathkit/z37_fdc.cpp @@ -0,0 +1,216 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + Heathkit Z-37 Floppy controller + + This was an option for both the Heathkit H8 and H89 computer systems. + +****************************************************************************/ + +#include "emu.h" + +#include "z37_fdc.h" + +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(HEATH_Z37_FDC, heath_z37_fdc_device, "heath_z37_fdc", "Heath H/Z-37 Soft-sectored Controller"); + +heath_z37_fdc_device::heath_z37_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, HEATH_Z37_FDC, tag, owner, 0) + , m_fd_irq_cb(*this) + , m_drq_cb(*this) + , m_block_interrupt_cb(*this) + , m_fdc(*this, "z37_fdc") + , m_floppies(*this, "z37_fdc:%u", 0U) +{ +} + + +void heath_z37_fdc_device::ctrl_w(uint8_t val) +{ + m_control_reg = val; + + bool motor_on = bool(BIT(val, ctrl_MotorsOn_c)); + + m_intrq_allowed = bool(BIT(val, ctrl_EnableIntReq_c)); + m_drq_allowed = bool(BIT(val, ctrl_EnableDrqInt_c)); + m_fdc->dden_w(BIT(val, ctrl_SetMFMRecording_c) ? CLEAR_LINE : ASSERT_LINE); + + if (m_drq_allowed) + { + m_block_interrupt_cb(ASSERT_LINE); + } + else + { + m_block_interrupt_cb(CLEAR_LINE); + m_drq_cb(CLEAR_LINE); + } + + m_floppy = nullptr; + if (BIT(val, ctrl_Drive_0_c)) + { + m_floppy = m_floppies[0]->get_device(); + } + else if (BIT(val, ctrl_Drive_1_c)) + { + m_floppy = m_floppies[1]->get_device(); + } + else if (BIT(val, ctrl_Drive_2_c)) + { + m_floppy = m_floppies[2]->get_device(); + } + else if (BIT(val, ctrl_Drive_3_c)) + { + m_floppy = m_floppies[3]->get_device(); + } + + m_fdc->set_floppy(m_floppy); + + + for (uint8_t i = 0; i < 4; i++) + { + floppy_image_device *floppy = m_floppies[i]->get_device(); + if (floppy) + { + floppy->mon_w(!motor_on); + } + } +} + +uint8_t heath_z37_fdc_device::ctrl_r() +{ + return m_control_reg; +} + +void heath_z37_fdc_device::intf_w(uint8_t val) +{ + m_access_track_sector = bool(BIT(val, if_SelectSectorTrack_c)); +} + +uint8_t heath_z37_fdc_device::intf_r() +{ + return m_interface_reg; +} + +void heath_z37_fdc_device::stat_w(uint8_t val) +{ + m_access_track_sector ? m_fdc->sector_w(val) : m_fdc->cmd_w(val); +} + +uint8_t heath_z37_fdc_device::stat_r() +{ + return m_access_track_sector ? m_fdc->sector_r() : m_fdc->status_r(); +} + +void heath_z37_fdc_device::data_w(uint8_t val) +{ + m_access_track_sector ? m_fdc->track_w(val) : m_fdc->data_w(val); +} + +uint8_t heath_z37_fdc_device::data_r() +{ + return m_access_track_sector ? m_fdc->track_r() : m_fdc->data_r(); +} + +void heath_z37_fdc_device::write(offs_t reg, uint8_t val) +{ + switch (reg) + { + case 0: + ctrl_w(val); + break; + case 1: + intf_w(val); + break; + case 2: + stat_w(val); + break; + case 3: + data_w(val); + break; + } +} + +uint8_t heath_z37_fdc_device::read(offs_t reg) +{ + uint8_t value = 0xff; + switch (reg) + { + case 0: + value = ctrl_r(); + break; + case 1: + value = intf_r(); + break; + case 2: + value = stat_r(); + break; + case 3: + value = data_r(); + break; + } + + return value; +} + +void heath_z37_fdc_device::device_start() +{ + save_item(NAME(m_control_reg)); + save_item(NAME(m_interface_reg)); + save_item(NAME(m_intrq_allowed)); + save_item(NAME(m_drq_allowed)); + save_item(NAME(m_access_track_sector)); + + m_control_reg = 0; + m_interface_reg = 0; + + m_intrq_allowed = false; + m_drq_allowed = false; + m_access_track_sector = false; +} + +static void z37_floppies(device_slot_interface &device) +{ + // H-17-1 + device.option_add("ssdd", FLOPPY_525_SSDD); + // SS 96tpi + device.option_add("ssqd", FLOPPY_525_SSQD); + // DS 48tpi + device.option_add("dd", FLOPPY_525_DD); + // H-17-4 / H-17-5 -- DS 96tpi + device.option_add("qd", FLOPPY_525_QD); +} + +void heath_z37_fdc_device::device_add_mconfig(machine_config &config) +{ + FD1797(config, m_fdc, 16_MHz_XTAL / 16); + m_fdc->intrq_wr_callback().set(FUNC(heath_z37_fdc_device::set_irq)); + m_fdc->drq_wr_callback().set(FUNC(heath_z37_fdc_device::set_drq)); + + FLOPPY_CONNECTOR(config, m_floppies[0], z37_floppies, "qd", floppy_image_device::default_mfm_floppy_formats); + m_floppies[0]->enable_sound(true); + FLOPPY_CONNECTOR(config, m_floppies[1], z37_floppies, "qd", floppy_image_device::default_mfm_floppy_formats); + m_floppies[1]->enable_sound(true); + FLOPPY_CONNECTOR(config, m_floppies[2], z37_floppies, "qd", floppy_image_device::default_mfm_floppy_formats); + m_floppies[2]->enable_sound(true); + FLOPPY_CONNECTOR(config, m_floppies[3], z37_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats); + m_floppies[3]->enable_sound(true); +} + +void heath_z37_fdc_device::device_resolve_objects() +{ + m_fd_irq_cb.resolve_safe(); + m_drq_cb.resolve_safe(); + m_block_interrupt_cb.resolve_safe(); +} + +void heath_z37_fdc_device::set_irq(uint8_t data) +{ + m_fd_irq_cb(m_intrq_allowed ? data : CLEAR_LINE); +} + +void heath_z37_fdc_device::set_drq(uint8_t data) +{ + m_drq_cb(m_drq_allowed ? data : CLEAR_LINE); +} diff --git a/src/mame/heathkit/z37_fdc.h b/src/mame/heathkit/z37_fdc.h new file mode 100644 index 00000000000..dcd6a154938 --- /dev/null +++ b/src/mame/heathkit/z37_fdc.h @@ -0,0 +1,83 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + Heathkit Z-37 Floppy Disk Controller + +****************************************************************************/ + +#ifndef MAME_HEATHKIT_Z37_FDC_H +#define MAME_HEATHKIT_Z37_FDC_H + +#pragma once + +#include "imagedev/floppy.h" +#include "machine/wd_fdc.h" + + +class heath_z37_fdc_device : public device_t +{ +public: + heath_z37_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + + void write(offs_t reg, uint8_t val); + uint8_t read(offs_t reg); + auto irq_cb() { return m_fd_irq_cb.bind(); } + auto drq_cb() { return m_drq_cb.bind(); } + + auto block_interrupt_cb() { return m_block_interrupt_cb.bind(); } + +protected : virtual void device_start() override; + virtual void device_add_mconfig(machine_config &config) override; + virtual void device_resolve_objects() override; + + void ctrl_w(uint8_t val); + uint8_t ctrl_r(); + + void intf_w(uint8_t val); + uint8_t intf_r(); + + void stat_w(uint8_t val); + uint8_t stat_r(); + + void data_w(uint8_t val); + uint8_t data_r(); + + void set_irq(uint8_t data); + void set_drq(uint8_t data); + +private: + devcb_write_line m_fd_irq_cb; + devcb_write_line m_drq_cb; + devcb_write_line m_block_interrupt_cb; + + required_device m_fdc; + required_device_array m_floppies; + + u8 m_control_reg; + u8 m_interface_reg; + bool m_intrq_allowed; + bool m_drq_allowed; + bool m_access_track_sector; + + floppy_image_device *m_floppy; + + /// Bits set in cmd_ControlPort_c - DK.CON + static constexpr u8 ctrl_EnableIntReq_c = 0; + static constexpr u8 ctrl_EnableDrqInt_c = 1; + static constexpr u8 ctrl_SetMFMRecording_c = 2; + static constexpr u8 ctrl_MotorsOn_c = 3; + static constexpr u8 ctrl_Drive_0_c = 4; + static constexpr u8 ctrl_Drive_1_c = 5; + static constexpr u8 ctrl_Drive_2_c = 6; + static constexpr u8 ctrl_Drive_3_c = 7; + + /// Bits to set alternate registers on InterfaceControl_c - DK.INT + static constexpr uint8_t if_SelectSectorTrack_c = 0; + +}; + +DECLARE_DEVICE_TYPE(HEATH_Z37_FDC, heath_z37_fdc_device) + + +#endif // MAME_HEATHKIT_Z37_FDC_H -- cgit v1.2.3