heathkit/h89.cpp: Add Magnolia Microsystems DD controller and h89-mms system (#12413)

This commit is contained in:
Mark Garlanger 2024-05-30 06:56:21 -05:00 committed by GitHub
parent 9d849dde70
commit d1846f21e7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 604 additions and 31 deletions

View File

@ -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<mms77316_fdc_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)

View File

@ -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,32 +188,13 @@ u8 z37_intr_cntrl::get_instruction()
return 0x00;
}
void z37_intr_cntrl::set_drq(int state)
{
m_drq_raised = bool(state);
update_intr_line();
}
void z37_intr_cntrl::set_irq(int state)
{
m_irq_raised = bool(state);
update_intr_line();
}
void z37_intr_cntrl::device_start()
{
heath_intr_cntrl::device_start();
ss_intr_cntrl::device_start();
save_item(NAME(m_intr_blocked));
save_item(NAME(m_drq_raised));
save_item(NAME(m_irq_raised));
m_intr_blocked = false;
m_drq_raised = false;
m_irq_raised = false;
}
void z37_intr_cntrl::block_interrupts(u8 data)
@ -186,6 +205,43 @@ void z37_intr_cntrl::block_interrupts(u8 data)
}
/**
* 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)
{
}
void mms_intr_cntrl::update_intr_line()
{
m_socket->raise_irq((m_irq_raised || m_drq_raised || (m_intr_lines != 0)) ? 1 : 0);
}
u8 mms_intr_cntrl::get_instruction()
{
if (m_irq_raised)
{
// RST 30H (Interrupt 6)
return 0xf7;
}
if (m_drq_raised)
{
// EI
return 0xfb;
}
return heath_intr_cntrl::get_instruction();
}
void mms_intr_cntrl::device_start()
{
ss_intr_cntrl::device_start();
}
/**
* Heath Interrupt socket
*

View File

@ -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,

View File

@ -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);
}

View File

@ -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<fd1797_device> m_fdc;
required_device_array<floppy_connector, 8> 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

View File

@ -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);
}

View File

@ -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