summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--src/mame/heathkit/h89.cpp305
-rw-r--r--src/mame/heathkit/h_88_cass.cpp166
-rw-r--r--src/mame/heathkit/h_88_cass.h53
-rw-r--r--src/mame/mame.lst3
4 files changed, 426 insertions, 101 deletions
diff --git a/src/mame/heathkit/h89.cpp b/src/mame/heathkit/h89.cpp
index bb50d44b5c6..826927a87a4 100644
--- a/src/mame/heathkit/h89.cpp
+++ b/src/mame/heathkit/h89.cpp
@@ -43,9 +43,10 @@
#include "emu.h"
+#include "h_88_cass.h"
+#include "intr_cntrl.h"
#include "tlb.h"
#include "z37_fdc.h"
-#include "intr_cntrl.h"
#include "cpu/z80/z80.h"
#include "machine/ins8250.h"
@@ -64,10 +65,13 @@
namespace {
-class h89_state : public driver_device
+/**
+ * Base Heathkit H89 functionality
+ */
+class h89_base_state : public driver_device
{
-public:
- h89_state(const machine_config &mconfig, device_type type, const char *tag):
+protected:
+ h89_base_state(const machine_config &mconfig, device_type type, const char *tag):
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_maincpu_region(*this, "maincpu"),
@@ -75,7 +79,6 @@ public:
m_ram(*this, RAM_TAG),
m_floppy_ram(*this, "floppyram"),
m_tlbc(*this, "tlbc"),
- m_h37(*this, "h37"),
m_intr_socket(*this, "intr_socket"),
m_console(*this, "console"),
m_serial1(*this, "serial1"),
@@ -85,10 +88,7 @@ public:
{
}
- void h89(machine_config &config);
-
-
-private:
+ void h89_base(machine_config &config);
required_device<z80_device> m_maincpu;
required_memory_region m_maincpu_region;
@@ -96,7 +96,6 @@ private:
required_device<ram_device> m_ram;
required_shared_ptr<uint8_t> m_floppy_ram;
required_device<heath_tlb_connector> m_tlbc;
- required_device<heath_z37_fdc_device> m_h37;
required_device<heath_intr_socket> m_intr_socket;
required_device<ins8250_device> m_console;
required_device<ins8250_device> m_serial1;
@@ -142,7 +141,8 @@ private:
void h89_mem(address_map &map);
void map_fetch(address_map &map);
uint8_t m1_r(offs_t offset);
- void h89_io(address_map &map);
+
+ void h89_base_io(address_map &map);
uint8_t raise_NMI_r();
void raise_NMI_w(uint8_t data);
@@ -151,6 +151,52 @@ private:
void reset_single_step_state();
};
+/**
+ * Heathkit H88
+ * - BIOS MTR-88
+ * - H-88-5 Cassette Interface Board
+ *
+ */
+class h88_state : public h89_base_state
+{
+public:
+ h88_state(const machine_config &mconfig, device_type type, const char *tag):
+ h89_base_state(mconfig, type, tag),
+ m_cassette(*this, "h_88_5")
+ {
+ }
+
+ void h88(machine_config &config);
+
+protected:
+ required_device<heath_h_88_cass_device> m_cassette;
+
+ void h88_io(address_map &map);
+};
+
+
+/**
+ * Heathkit H89
+ * - Z-89-37 Soft-sectored Floppy Controller
+ *
+ */
+class h89_state : public h89_base_state
+{
+public:
+ h89_state(const machine_config &mconfig, device_type type, const char *tag):
+ h89_base_state(mconfig, type, tag),
+ m_h37(*this, "h37")
+ {
+ }
+
+ void h89(machine_config &config);
+
+protected:
+ required_device<heath_z37_fdc_device> m_h37;
+
+ void h89_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
@@ -187,7 +233,7 @@ private:
------------- 0k ------------- 0k
*/
-void h89_state::h89_mem(address_map &map)
+void h89_base_state::h89_mem(address_map &map)
{
map.unmap_value_high();
@@ -208,12 +254,12 @@ void h89_state::h89_mem(address_map &map)
m_mem_view[1](0x1800, 0x1fff).rom().region("maincpu", 0x1800).unmapw();
}
-void h89_state::map_fetch(address_map &map)
+void h89_base_state::map_fetch(address_map &map)
{
- map(0x0000, 0xffff).r(FUNC(h89_state::m1_r));
+ map(0x0000, 0xffff).r(FUNC(h89_base_state::m1_r));
}
-uint8_t h89_state::m1_r(offs_t offset)
+uint8_t h89_base_state::m1_r(offs_t offset)
{
uint8_t data = m_program.read_byte(offset);
@@ -248,7 +294,6 @@ uint8_t h89_state::m1_r(offs_t offset)
Use | Hex | Octal
--------------------------+-------+---------
Not specified, available | 0-77 | 0-167
- Cassette I/O (if used) | 78-79 | 170-171
Disk I/O #1 | 78-7B | 170-173
Disk I/O #2 | 7C-7F | 174-177
Not specified, reserved | 80-CF | 200-317
@@ -258,20 +303,20 @@ uint8_t h89_state::m1_r(offs_t offset)
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
NMI | FA-FB | 372-373
*/
-void h89_state::h89_io(address_map &map)
+void h89_base_state::h89_base_io(address_map &map)
{
map.unmap_value_high();
map.global_mask(0xff);
// Disk I/O #1 - 0170-0173 (0x78-0x7b)
// Options
- // - Cassette I/O (only uses 0x78 - 0x79) - Requires MTR-88 ROM
// - H37 5-1/4" Soft-sectored Controller - Requires MTR-90 ROM
// - 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).rw(m_h37, FUNC(heath_z37_fdc_device::read), FUNC(heath_z37_fdc_device::write));
+ // map(0x78, 0x7b)
// Disk I/O #2 - 0174-0177 (0x7c-0x7f)
// Options
@@ -291,16 +336,60 @@ void h89_state::h89_io(address_map &map)
map(0xe8, 0xef).rw(m_console, FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w));
// ports defined on the H8. On the H89, access to these addresses causes a NMI
- map(0xf0, 0xf1).rw(FUNC(h89_state::raise_NMI_r),FUNC(h89_state::raise_NMI_w));
+ map(0xf0, 0xf1).rw(FUNC(h89_base_state::raise_NMI_r),FUNC(h89_base_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_base_state::port_f2_w)).portr("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));
+ map(0xfa, 0xfb).rw(FUNC(h89_base_state::raise_NMI_r), FUNC(h89_base_state::raise_NMI_w));
+}
+
+void h88_state::h88_io(address_map &map)
+{
+ h89_base_state::h89_base_io(map);
+
+ // Cassette I/O (uses 0xf8 - 0xf9) - Requires MTR-88 ROM
+ map(0xf8, 0xf9).rw(m_cassette, FUNC(heath_h_88_cass_device::read), FUNC(heath_h_88_cass_device::write));
}
+void h89_state::h89_io(address_map &map)
+{
+ h89_base_state::h89_base_io(map);
+
+ // H37 5-1/4" Soft-sectored Controller - Requires MTR-90 ROM
+ map(0x78, 0x7b).rw(m_h37, FUNC(heath_z37_fdc_device::read), FUNC(heath_z37_fdc_device::write));
+}
+
+
// Input ports
+static INPUT_PORTS_START( h88 )
+
+ PORT_START("SW501")
+ // MTR-88 (444-40)
+ PORT_DIPUNUSED_DIPLOC(0x01, 0x00, "SW501:1")
+ PORT_DIPUNUSED_DIPLOC(0x02, 0x00, "SW501:2")
+ PORT_DIPUNUSED_DIPLOC(0x04, 0x00, "SW501:3")
+ PORT_DIPUNUSED_DIPLOC(0x08, 0x00, "SW501:4")
+ PORT_DIPUNUSED_DIPLOC(0x10, 0x00, "SW501:5")
+ PORT_DIPNAME( 0x20, 0x20, "Perform memory test at start" ) PORT_DIPLOCATION("SW501:6")
+ PORT_DIPSETTING( 0x20, DEF_STR( No ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( Yes ) )
+ PORT_DIPNAME( 0xc0, 0x00, "Console Baud rate" ) PORT_DIPLOCATION("SW501:7,8")
+ PORT_DIPSETTING( 0x00, "9600" )
+ PORT_DIPSETTING( 0x40, "19200" )
+ PORT_DIPSETTING( 0x80, "38400" )
+ PORT_DIPSETTING( 0xc0, "57600" )
+
+ PORT_START("CONFIG")
+ PORT_CONFNAME(0x03, 0x00, "CPU Clock Speed Upgrade")
+ PORT_CONFSETTING(0x00, DEF_STR( None ) )
+ PORT_CONFSETTING(0x01, "2 / 4 MHz")
+ PORT_CONFSETTING(0x02, "2 / 6 MHz")
+
+INPUT_PORTS_END
+
+
static INPUT_PORTS_START( h89 )
PORT_START("SW501")
@@ -354,53 +443,42 @@ static INPUT_PORTS_START( h89 )
PORT_DIPSETTING( 0x00, DEF_STR( Normal ) )
PORT_DIPSETTING( 0x80, "Auto" )
- // MTR-88 (444-40)
- PORT_DIPNAME( 0x1f, 0x00, "Unused" ) PORT_DIPLOCATION("SW501:1,2,3,4,5") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x08)
- PORT_DIPNAME( 0x20, 0x20, "Perform memory test at start" ) PORT_DIPLOCATION("SW501:6") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x08)
- PORT_DIPSETTING( 0x20, DEF_STR( No ) )
- PORT_DIPSETTING( 0x00, DEF_STR( Yes ) )
- PORT_DIPNAME( 0xc0, 0x00, "Console Baud rate" ) PORT_DIPLOCATION("SW501:7,8") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x08)
- PORT_DIPSETTING( 0x00, "9600" )
- PORT_DIPSETTING( 0x40, "19200" )
- PORT_DIPSETTING( 0x80, "38400" )
- PORT_DIPSETTING( 0xc0, "57600" )
-
// MTR-89 (444-62)
- PORT_DIPNAME( 0x03, 0x00, "Disk I/O #2" ) PORT_DIPLOCATION("SW501:1,2") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x0c)
+ PORT_DIPNAME( 0x03, 0x00, "Disk I/O #2" ) PORT_DIPLOCATION("SW501:1,2") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x08)
PORT_DIPSETTING( 0x00, "H-88-1" )
PORT_DIPSETTING( 0x01, "H/Z-47" )
PORT_DIPSETTING( 0x02, "Undefined" )
PORT_DIPSETTING( 0x03, "Undefined" )
- PORT_DIPNAME( 0x0c, 0x00, "Disk I/O #1" ) PORT_DIPLOCATION("SW501:3,4") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x0c)
+ PORT_DIPNAME( 0x0c, 0x00, "Disk I/O #1" ) PORT_DIPLOCATION("SW501:3,4") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x08)
PORT_DIPSETTING( 0x00, "Unused" )
PORT_DIPSETTING( 0x04, "H/Z-47" )
PORT_DIPSETTING( 0x08, "Undefined" )
PORT_DIPSETTING( 0x0c, "Undefined" )
- PORT_DIPNAME( 0x10, 0x00, "Primary Boot from" ) PORT_DIPLOCATION("SW501:5") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x0c)
+ PORT_DIPNAME( 0x10, 0x00, "Primary Boot from" ) PORT_DIPLOCATION("SW501:5") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x08)
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("SW501:6") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x0c)
+ PORT_DIPNAME( 0x20, 0x20, "Perform memory test at start" ) PORT_DIPLOCATION("SW501:6") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x08)
PORT_DIPSETTING( 0x20, DEF_STR( No ) )
PORT_DIPSETTING( 0x00, DEF_STR( Yes ) )
- PORT_DIPNAME( 0x40, 0x00, "Console Baud rate" ) PORT_DIPLOCATION("SW501:7") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x0c)
+ PORT_DIPNAME( 0x40, 0x00, "Console Baud rate" ) PORT_DIPLOCATION("SW501:7") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x08)
PORT_DIPSETTING( 0x00, "9600" )
PORT_DIPSETTING( 0x40, "19200" )
- PORT_DIPNAME( 0x80, 0x00, "Boot mode" ) PORT_DIPLOCATION("SW501:8") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x0c)
+ PORT_DIPNAME( 0x80, 0x00, "Boot mode" ) PORT_DIPLOCATION("SW501:8") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x08)
PORT_DIPSETTING( 0x00, DEF_STR( Normal ) )
PORT_DIPSETTING( 0x80, "Auto" )
// MMS 444-84B (and possibly 444-84A)
- PORT_DIPNAME( 0x03, 0x00, "Disk I/O #2" ) PORT_DIPLOCATION("SW501:1,2") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x10)
+ PORT_DIPNAME( 0x03, 0x00, "Disk I/O #2" ) PORT_DIPLOCATION("SW501:1,2") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x0c)
PORT_DIPSETTING( 0x00, "H-88-1" )
PORT_DIPSETTING( 0x01, "H/Z-47 (Not yet implemented)" )
PORT_DIPSETTING( 0x02, "MMS 77320 SASI or Z-67 (Not yet implemented)" )
PORT_DIPSETTING( 0x03, "MMS 77422 Network Controller" )
- PORT_DIPNAME( 0x0c, 0x00, "Disk I/O #1" ) PORT_DIPLOCATION("SW501:3,4") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x10)
+ PORT_DIPNAME( 0x0c, 0x00, "Disk I/O #1" ) PORT_DIPLOCATION("SW501:3,4") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x0c)
PORT_DIPSETTING( 0x00, "H-89-37" )
PORT_DIPSETTING( 0x04, "H/Z-47 (Not yet implemented)" )
PORT_DIPSETTING( 0x08, "MMS 77320 SASI or Z-67 (Not yet implemented)" )
PORT_DIPSETTING( 0x0c, "MMS 77422 Network Controller" )
- PORT_DIPNAME( 0x70, 0x00, "Default Boot Device" ) PORT_DIPLOCATION("SW501:5,6,7") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x10)
+ PORT_DIPNAME( 0x70, 0x00, "Default Boot Device" ) PORT_DIPLOCATION("SW501:5,6,7") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x0c)
PORT_DIPSETTING( 0x00, "MMS 77316 Dbl Den 5\"" )
PORT_DIPSETTING( 0x10, "MMS 77316 Dbl Den 8\"" )
PORT_DIPSETTING( 0x20, "Disk Device at 0x7C" )
@@ -409,12 +487,12 @@ static INPUT_PORTS_START( h89 )
PORT_DIPSETTING( 0x50, "reserved for future use" )
PORT_DIPSETTING( 0x60, "MMS Network (77422)" )
PORT_DIPSETTING( 0x70, "Use MMS I/O board Config Port" )
- PORT_DIPNAME( 0x80, 0x00, "Boot mode" ) PORT_DIPLOCATION("SW501:8") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x10)
+ PORT_DIPNAME( 0x80, 0x00, "Boot mode" ) PORT_DIPLOCATION("SW501:8") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x0c)
PORT_DIPSETTING( 0x00, DEF_STR( Normal ) )
PORT_DIPSETTING( 0x80, "Auto" )
// Kres KMR-100
- PORT_DIPNAME( 0x0f, 0x00, "Default Boot Device" ) PORT_DIPLOCATION("SW501:1,2,3,4") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x14)
+ PORT_DIPNAME( 0x0f, 0x00, "Default Boot Device" ) PORT_DIPLOCATION("SW501:1,2,3,4") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x10)
PORT_DIPSETTING( 0x00, "H-17 hard-sectored 5\" floppy units 0-2" )
PORT_DIPSETTING( 0x01, "H-37 soft-sectored 5\" floppy units 0-3" )
PORT_DIPSETTING( 0x02, "Corvus hard disk/Magnolia interface, partitions 0-8" )
@@ -431,22 +509,22 @@ static INPUT_PORTS_START( h89 )
PORT_DIPSETTING( 0x0d, "Reserved" )
PORT_DIPSETTING( 0x0e, "Reserved" )
PORT_DIPSETTING( 0x0f, "Magnolia 128K pseudo disk, banks 0-1" )
- PORT_DIPNAME( 0x10, 0x00, "Map ROM into RAM on boot" ) PORT_DIPLOCATION("SW501:5") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x14)
+ PORT_DIPNAME( 0x10, 0x00, "Map ROM into RAM on boot" ) PORT_DIPLOCATION("SW501:5") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x10)
PORT_DIPSETTING( 0x00, DEF_STR( Yes ) )
PORT_DIPSETTING( 0x10, DEF_STR( No ) )
- PORT_DIPNAME( 0x20, 0x20, "Perform memory test at start" ) PORT_DIPLOCATION("SW501:6") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x14)
+ PORT_DIPNAME( 0x20, 0x20, "Perform memory test at start" ) PORT_DIPLOCATION("SW501:6") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x10)
PORT_DIPSETTING( 0x20, DEF_STR( No ) )
PORT_DIPSETTING( 0x00, DEF_STR( Yes ) )
- PORT_DIPNAME( 0x40, 0x00, "Have a LLL controller installed" ) PORT_DIPLOCATION("SW501:7") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x14)
+ PORT_DIPNAME( 0x40, 0x00, "Have a LLL controller installed" ) PORT_DIPLOCATION("SW501:7") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x10)
PORT_DIPSETTING( 0x00, DEF_STR( No ) )
PORT_DIPSETTING( 0x40, DEF_STR( Yes ) )
- PORT_DIPNAME( 0x80, 0x00, "Boot mode" ) PORT_DIPLOCATION("SW501:8") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x14)
+ PORT_DIPNAME( 0x80, 0x00, "Boot mode" ) PORT_DIPLOCATION("SW501:8") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x10)
PORT_DIPSETTING( 0x00, DEF_STR( Normal ) )
PORT_DIPSETTING( 0x80, "Auto" )
// Ultimeth MTRHEX-4k
// (values based on testing and comparison with the Kres KMR-100 ROM which was also written by Ultimeth)
- PORT_DIPNAME( 0x0f, 0x00, "Default Boot Device" ) PORT_DIPLOCATION("SW501:1,2,3,4") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x18)
+ PORT_DIPNAME( 0x0f, 0x00, "Default Boot Device" ) PORT_DIPLOCATION("SW501:1,2,3,4") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x14)
PORT_DIPSETTING( 0x00, "H-17 hard-sectored 5\" floppy" )
PORT_DIPSETTING( 0x01, "H-37 soft-sectored 5\" floppy" )
PORT_DIPSETTING( 0x02, "? Corvus hard disk/Magnolia interface" )
@@ -463,16 +541,16 @@ static INPUT_PORTS_START( h89 )
PORT_DIPSETTING( 0x0d, "? Reserved" )
PORT_DIPSETTING( 0x0e, "? Reserved" )
PORT_DIPSETTING( 0x0f, "? Magnolia 128K pseudo disk" )
- PORT_DIPNAME( 0x10, 0x00, "? Map ROM into RAM on boot" ) PORT_DIPLOCATION("SW501:5") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x18)
+ PORT_DIPNAME( 0x10, 0x00, "? Map ROM into RAM on boot" ) PORT_DIPLOCATION("SW501:5") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x14)
PORT_DIPSETTING( 0x00, "? Yes" )
PORT_DIPSETTING( 0x10, "? No" )
- PORT_DIPNAME( 0x20, 0x20, "Perform memory test at start" ) PORT_DIPLOCATION("SW501:6") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x18)
+ PORT_DIPNAME( 0x20, 0x20, "Perform memory test at start" ) PORT_DIPLOCATION("SW501:6") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x14)
PORT_DIPSETTING( 0x20, DEF_STR( No ) )
PORT_DIPSETTING( 0x00, DEF_STR( Yes ) )
- PORT_DIPNAME( 0x40, 0x00, "? Have a LLL controller installed" ) PORT_DIPLOCATION("SW501:7") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x18)
+ PORT_DIPNAME( 0x40, 0x00, "? Have a LLL controller installed" ) PORT_DIPLOCATION("SW501:7") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x14)
PORT_DIPSETTING( 0x00, "? No" )
PORT_DIPSETTING( 0x40, "? Yes" )
- PORT_DIPNAME( 0x80, 0x00, "Boot mode" ) PORT_DIPLOCATION("SW501:8") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x18)
+ PORT_DIPNAME( 0x80, 0x00, "Boot mode" ) PORT_DIPLOCATION("SW501:8") PORT_CONDITION("CONFIG", 0x3c, EQUALS, 0x14)
PORT_DIPSETTING( 0x00, DEF_STR( Normal ) )
PORT_DIPSETTING( 0x80, "Auto" )
@@ -485,16 +563,15 @@ static INPUT_PORTS_START( h89 )
PORT_CONFNAME(0x3c, 0x04, "Switch SW501 Definitions")
PORT_CONFSETTING(0x00, "Generic" )
PORT_CONFSETTING(0x04, "Heath MTR-90")
- PORT_CONFSETTING(0x08, "Heath MTR-88")
- PORT_CONFSETTING(0x0c, "Heath MTR-89")
- PORT_CONFSETTING(0x10, "MMS 444-84B/444-84A")
- PORT_CONFSETTING(0x14, "Kres KMR-100")
- PORT_CONFSETTING(0x18, "Ultimeth MTRHEX-4k")
+ PORT_CONFSETTING(0x08, "Heath MTR-89")
+ PORT_CONFSETTING(0x0c, "MMS 444-84B/444-84A")
+ PORT_CONFSETTING(0x10, "Kres KMR-100")
+ PORT_CONFSETTING(0x14, "Ultimeth MTRHEX-4k")
INPUT_PORTS_END
-void h89_state::machine_start()
+void h89_base_state::machine_start()
{
save_item(NAME(m_gpp));
save_item(NAME(m_rom_enabled));
@@ -541,8 +618,7 @@ void h89_state::machine_start()
}
}
-
-void h89_state::machine_reset()
+void h89_base_state::machine_reset()
{
m_rom_enabled = true;
m_timer_intr_enabled = true;
@@ -577,24 +653,24 @@ void h89_state::machine_reset()
update_mem_view();
}
-uint8_t h89_state::raise_NMI_r()
+uint8_t h89_base_state::raise_NMI_r()
{
m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::from_usec(2));
return 0x00;
}
-void h89_state::raise_NMI_w(uint8_t)
+void h89_base_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)
+void h89_base_state::console_intr(uint8_t data)
{
m_intr_socket->set_irq_level(3, data);
}
-void h89_state::reset_line(int data)
+void h89_base_state::reset_line(int data)
{
if (bool(data))
{
@@ -603,7 +679,7 @@ void h89_state::reset_line(int data)
m_maincpu->set_input_line(INPUT_LINE_RESET, data);
}
-TIMER_DEVICE_CALLBACK_MEMBER(h89_state::h89_irq_timer)
+TIMER_DEVICE_CALLBACK_MEMBER(h89_base_state::h89_irq_timer)
{
if (m_timer_intr_enabled)
{
@@ -611,12 +687,12 @@ TIMER_DEVICE_CALLBACK_MEMBER(h89_state::h89_irq_timer)
}
}
-void h89_state::update_mem_view()
+void h89_base_state::update_mem_view()
{
m_mem_view.select(m_rom_enabled ? (m_floppy_ram_wp ? 0 : 1) : 2);
}
-void h89_state::reset_single_step_state()
+void h89_base_state::reset_single_step_state()
{
LOGSS("reset_single_step_state\n");
m_555a_latch = false;
@@ -638,7 +714,7 @@ void h89_state::reset_single_step_state()
// 6 Latched bit I/O 0 on I/O exp connector
// 7 Latched bit I/O 1 on I/O exp connector
//
-void h89_state::update_gpp(uint8_t gpp)
+void h89_base_state::update_gpp(uint8_t gpp)
{
uint8_t changed_gpp = gpp ^ m_gpp;
@@ -672,7 +748,7 @@ void h89_state::update_gpp(uint8_t gpp)
}
// General Purpose Port
-void h89_state::port_f2_w(uint8_t data)
+void h89_base_state::port_f2_w(uint8_t data)
{
update_gpp(data);
@@ -696,22 +772,21 @@ static void intr_ctrl_options(device_slot_interface &device)
device.option_add("h37", HEATH_Z37_INTR_CNTRL);
}
-void h89_state::h89(machine_config & config)
+void h89_base_state::h89_base(machine_config &config)
{
// basic machine hardware
Z80(config, m_maincpu, H89_CLOCK);
- m_maincpu->set_m1_map(&h89_state::map_fetch);
- m_maincpu->set_memory_map(&h89_state::h89_mem);
- m_maincpu->set_io_map(&h89_state::h89_io);
+ m_maincpu->set_m1_map(&h89_base_state::map_fetch);
+ m_maincpu->set_memory_map(&h89_base_state::h89_mem);
m_maincpu->set_irq_acknowledge_callback("intr_socket", FUNC(heath_intr_socket::irq_callback));
- HEATH_INTR_SOCKET(config, m_intr_socket, intr_ctrl_options, "h37", true);
- m_intr_socket->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);
+ HEATH_INTR_SOCKET(config, m_intr_socket, intr_ctrl_options, nullptr);
+ m_intr_socket->irq_line_cb().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
+
INS8250(config, m_console, INS8250_CLOCK);
- m_console->out_int_callback().set(FUNC(h89_state::console_intr));
+ m_console->out_int_callback().set(FUNC(h89_base_state::console_intr));
HEATH_TLB_CONNECTOR(config, m_tlbc, tlb_options, "heath");
@@ -723,12 +798,7 @@ void h89_state::h89(machine_config & config)
m_tlbc->rts_callback().set(m_console, FUNC(ins8250_uart_device::cts_w));
m_tlbc->dtr_callback().set(m_console, FUNC(ins8250_uart_device::dsr_w));
- m_tlbc->reset_cb().set(FUNC(h89_state::reset_line));
-
- HEATH_Z37_FDC(config, m_h37);
- m_h37->drq_cb().set(m_intr_socket, FUNC(heath_intr_socket::set_drq));
- m_h37->irq_cb().set(m_intr_socket, FUNC(heath_intr_socket::set_irq));
- m_h37->block_interrupt_cb().set(m_intr_socket, FUNC(heath_intr_socket::block_interrupts));
+ m_tlbc->reset_cb().set(FUNC(h89_base_state::reset_line));
// H-88-3 3-port serial board
INS8250(config, m_serial1, INS8250_CLOCK);
@@ -736,9 +806,46 @@ void h89_state::h89(machine_config & config)
INS8250(config, m_serial3, INS8250_CLOCK);
// H89 interrupt interval is 2mSec
- TIMER(config, "irq_timer", 0).configure_periodic(FUNC(h89_state::h89_irq_timer), attotime::from_msec(2));
+ TIMER(config, "irq_timer", 0).configure_periodic(FUNC(h89_base_state::h89_irq_timer), attotime::from_msec(2));
+}
+
+void h88_state::h88(machine_config &config)
+{
+ h89_base_state::h89_base(config);
+ m_maincpu->set_io_map(&h88_state::h88_io);
+
+ m_intr_socket->set_default_option("original");
+ m_intr_socket->set_fixed(true);
+
+ // H-88-5 Cassette interface board
+ HEATH_H88_CASS(config, m_cassette, H89_CLOCK);
}
+void h89_state::h89(machine_config &config)
+{
+ h89_base_state::h89_base(config);
+ m_maincpu->set_io_map(&h89_state::h89_io);
+
+ m_intr_socket->set_default_option("h37");
+ m_intr_socket->set_fixed(true);
+
+ // Z-89-37 Soft-sectored controller
+ HEATH_Z37_FDC(config, m_h37);
+ m_h37->drq_cb().set(m_intr_socket, FUNC(heath_intr_socket::set_drq));
+ m_h37->irq_cb().set(m_intr_socket, FUNC(heath_intr_socket::set_irq));
+ m_h37->block_interrupt_cb().set(m_intr_socket, FUNC(heath_intr_socket::block_interrupts));
+}
+
+
+// ROM definition
+ROM_START( h88 )
+ ROM_REGION( 0x2000, "maincpu", ROMREGION_ERASEFF )
+
+ ROM_LOAD( "2716_444-19_h17.u520", 0x1800, 0x0800, CRC(26e80ae3) SHA1(0c0ee95d7cb1a760f924769e10c0db1678f2435c))
+
+ ROM_LOAD("2716_444-40_mtr88.u518", 0x0000, 0x0800, CRC(093afb79) SHA1(bcc1569ad9da7babf0a4199cab96d8cd59b2dd78))
+ROM_END
+
// ROM definition
ROM_START( h89 )
ROM_REGION( 0x2000, "maincpu", ROMREGION_ERASEFF )
@@ -749,26 +856,23 @@ ROM_START( h89 )
ROM_SYSTEM_BIOS(0, "mtr90", "MTR-90 (444-142)")
ROMX_LOAD("2732_444-142_mtr90.u518", 0x0000, 0x1000, CRC(c4ff47c5) SHA1(d6f3d71ff270a663003ec18a3ed1fa49f627123a), ROM_BIOS(0))
- ROM_SYSTEM_BIOS(1, "mtr88", "MTR-88 (444-40)")
- ROMX_LOAD("2716_444-40_mtr88.u518", 0x0000, 0x0800, CRC(093afb79) SHA1(bcc1569ad9da7babf0a4199cab96d8cd59b2dd78), ROM_BIOS(1))
-
- ROM_SYSTEM_BIOS(2, "mtr89", "MTR-89 (444-62)")
- ROMX_LOAD("2716_444-62_mtr89.u518", 0x0000, 0x0800, CRC(8f507972) SHA1(ac6c6c1344ee4e09fb60d53c85c9b761217fe9dc), ROM_BIOS(2))
+ ROM_SYSTEM_BIOS(1, "mtr89", "MTR-89 (444-62)")
+ ROMX_LOAD("2716_444-62_mtr89.u518", 0x0000, 0x0800, CRC(8f507972) SHA1(ac6c6c1344ee4e09fb60d53c85c9b761217fe9dc), ROM_BIOS(1))
- ROM_SYSTEM_BIOS(3, "mms84b", "MMS 444-84B")
- ROMX_LOAD("2732_444_84b_mms.u518", 0x0000, 0x1000, CRC(7e75d6f4) SHA1(baf34e036388d1a191197e31f8a93209f04fc58b), ROM_BIOS(3))
+ ROM_SYSTEM_BIOS(2, "mms84b", "MMS 444-84B")
+ ROMX_LOAD("2732_444_84b_mms.u518", 0x0000, 0x1000, CRC(7e75d6f4) SHA1(baf34e036388d1a191197e31f8a93209f04fc58b), ROM_BIOS(2))
- ROM_SYSTEM_BIOS(4, "kmr-100", "Kres KMR-100 V3.a.02")
- ROMX_LOAD("2732_kmr100_v3_a_02.u518", 0x0000, 0x1000, CRC(fd491592) SHA1(3d5803f95c38b237b07cd230353cd9ddc9858c13), ROM_BIOS(4))
+ ROM_SYSTEM_BIOS(3, "kmr-100", "Kres KMR-100 V3.a.02")
+ ROMX_LOAD("2732_kmr100_v3_a_02.u518", 0x0000, 0x1000, CRC(fd491592) SHA1(3d5803f95c38b237b07cd230353cd9ddc9858c13), ROM_BIOS(3))
- ROM_SYSTEM_BIOS(5, "mtrhex_4k", "Ultimeth ROM")
- ROMX_LOAD("2732_mtrhex_4k.u518", 0x0000, 0x1000, CRC(e26b29a9) SHA1(ba13d6c9deef682a9a8262bc910d46b577929a13), ROM_BIOS(5))
+ ROM_SYSTEM_BIOS(4, "mtrhex_4k", "Ultimeth ROM")
+ ROMX_LOAD("2732_mtrhex_4k.u518", 0x0000, 0x1000, CRC(e26b29a9) SHA1(ba13d6c9deef682a9a8262bc910d46b577929a13), ROM_BIOS(4))
- ROM_SYSTEM_BIOS(6, "mtr90-84", "Heath's MTR-90 (444-84 - Superseded by 444-142)")
- ROMX_LOAD("2732_444-84_mtr90.u518", 0x0000, 0x1000, CRC(f10fca03) SHA1(c4a978153af0f2dfcc9ba05be4c1033d33fee30b), ROM_BIOS(6))
+ ROM_SYSTEM_BIOS(5, "mtr90-84", "Heath's MTR-90 (444-84 - Superseded by 444-142)")
+ ROMX_LOAD("2732_444-84_mtr90.u518", 0x0000, 0x1000, CRC(f10fca03) SHA1(c4a978153af0f2dfcc9ba05be4c1033d33fee30b), ROM_BIOS(5))
- ROM_SYSTEM_BIOS(7, "mms84a", "MMS 444-84A (Superseded by MMS 444-84B)")
- ROMX_LOAD("2732_444_84a_mms.u518", 0x0000, 0x1000, CRC(0e541a7e) SHA1(b1deb620fc89c1068e2e663e14be69d1f337a4b9), ROM_BIOS(7))
+ ROM_SYSTEM_BIOS(6, "mms84a", "MMS 444-84A (Superseded by MMS 444-84B)")
+ ROMX_LOAD("2732_444_84a_mms.u518", 0x0000, 0x1000, CRC(0e541a7e) SHA1(b1deb620fc89c1068e2e663e14be69d1f337a4b9), ROM_BIOS(6))
ROM_END
} // anonymous namespace
@@ -777,4 +881,5 @@ ROM_END
// Driver
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
+COMP( 1979, h88, h89, 0, h88, h88, h88_state, empty_init, "Heath Company", "Heathkit H88", MACHINE_SUPPORTS_SAVE)
COMP( 1979, h89, 0, 0, h89, h89, h89_state, empty_init, "Heath Company", "Heathkit H89", MACHINE_SUPPORTS_SAVE)
diff --git a/src/mame/heathkit/h_88_cass.cpp b/src/mame/heathkit/h_88_cass.cpp
new file mode 100644
index 00000000000..5f09426f964
--- /dev/null
+++ b/src/mame/heathkit/h_88_cass.cpp
@@ -0,0 +1,166 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger
+/***************************************************************************
+
+ Heathkit H-88-5 Cassette Interface Card
+
+ Came standard on the H88 computer and was on option for other H89 class
+ systems.
+
+****************************************************************************/
+
+#include "emu.h"
+
+#include "h_88_cass.h"
+
+#include "machine/clock.h"
+
+#include "speaker.h"
+
+#define LOG_REG (1U << 1)
+#define LOG_LINES (1U << 2)
+#define LOG_CASS (1U << 3)
+#define LOG_FUNC (1U << 4)
+//#define VERBOSE (0xff)
+
+#include "logmacro.h"
+
+#define LOGREG(...) LOGMASKED(LOG_REG, __VA_ARGS__)
+#define LOGLINES(...) LOGMASKED(LOG_LINES, __VA_ARGS__)
+#define LOGCASS(...) LOGMASKED(LOG_CASS, __VA_ARGS__)
+#define LOGFUNC(...) LOGMASKED(LOG_FUNC, __VA_ARGS__)
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
+
+DEFINE_DEVICE_TYPE(HEATH_H88_CASS, heath_h_88_cass_device, "heath_h_88_cass_device", "Heath H-88-5 Cassette Interface");
+
+heath_h_88_cass_device::heath_h_88_cass_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock):
+ device_t(mconfig, HEATH_H88_CASS, tag, owner, 0),
+ m_uart(*this, "uart"),
+ m_cass_player(*this, "cassette_player"),
+ m_cass_recorder(*this, "cassette_recorder")
+{
+}
+
+void heath_h_88_cass_device::write(offs_t reg, u8 val)
+{
+ LOGREG("%s: reg: %d val: 0x%02x\n", FUNCNAME, reg, val);
+
+ m_uart->write(reg, val);
+}
+
+u8 heath_h_88_cass_device::read(offs_t reg)
+{
+ u8 val = m_uart->read(reg);
+
+ LOGREG("%s: reg: %d val: 0x%02x\n", FUNCNAME, reg, val);
+
+ return val;
+}
+
+TIMER_DEVICE_CALLBACK_MEMBER(heath_h_88_cass_device::kansas_w)
+{
+ m_cass_data[3]++;
+
+ if (m_cassbit != m_cassold)
+ {
+ LOGCASS("%s: m_cassbit changed : %d\n", FUNCNAME, m_cassbit);
+ m_cass_data[3] = 0;
+ m_cassold = m_cassbit;
+ }
+
+ LOGCASS("%s: m_cassbit: %d\n", FUNCNAME, m_cassbit);
+ // 2400Hz -> 0
+ // 1200Hz -> 1
+ const int bit_pos = m_cassbit ? 0 : 1;
+
+ m_cass_recorder->output(BIT(m_cass_data[3], bit_pos) ? -1.0 : +1.0);
+}
+
+TIMER_DEVICE_CALLBACK_MEMBER(heath_h_88_cass_device::kansas_r)
+{
+ // cassette - turn 1200/2400Hz to a bit
+ m_cass_data[1]++;
+ u8 cass_ws = (m_cass_player->input() > +0.03) ? 1 : 0;
+
+ LOGCASS("%s: cass_ws: %d\n", FUNCNAME, cass_ws);
+
+ if (cass_ws != m_cass_data[0])
+ {
+ LOGCASS("%s: cass_ws has changed value\n", FUNCNAME);
+ m_cass_data[0] = cass_ws;
+ m_uart->write_rxd((m_cass_data[1] < 12) ? 1 : 0);
+ m_cass_data[1] = 0;
+ }
+}
+
+void heath_h_88_cass_device::uart_rts(u8 data)
+{
+ LOGLINES("%s: data: %d\n", FUNCNAME, data);
+
+ m_cass_player->change_state(bool(data) ? CASSETTE_STOPPED : CASSETTE_PLAY, CASSETTE_MASK_UISTATE);
+}
+
+void heath_h_88_cass_device::uart_tx_empty(u8 data)
+{
+ LOGLINES("%s: data: %d\n", FUNCNAME, data);
+
+ m_cass_recorder->change_state(bool(data) ? CASSETTE_STOPPED : CASSETTE_RECORD, CASSETTE_MASK_UISTATE);
+}
+
+void heath_h_88_cass_device::device_start()
+{
+ save_item(NAME(m_cass_data));
+ save_item(NAME(m_cassbit));
+ save_item(NAME(m_cassold));
+}
+
+void heath_h_88_cass_device::device_reset()
+{
+ LOGFUNC("%s\n", FUNCNAME);
+
+ // cassette
+ m_cassbit = 1;
+ m_cassold = 0;
+ m_cass_data[0] = 0;
+ m_cass_data[1] = 0;
+ m_cass_data[2] = 0;
+ m_cass_data[3] = 0;
+
+ m_uart->write_cts(0);
+ m_uart->write_dsr(0);
+ m_uart->write_rxd(0);
+}
+
+void heath_h_88_cass_device::device_add_mconfig(machine_config &config)
+{
+ I8251(config, m_uart, 0);
+ m_uart->txd_handler().set([this] (bool state) { m_cassbit = state; });
+ m_uart->rts_handler().set(FUNC(heath_h_88_cass_device::uart_rts));
+ m_uart->txempty_handler().set(FUNC(heath_h_88_cass_device::uart_tx_empty));
+
+ clock_device &cassette_clock(CLOCK(config, "cassette_clock", 4800));
+ cassette_clock.signal_handler().set(m_uart, FUNC(i8251_device::write_txc));
+ cassette_clock.signal_handler().append(m_uart, FUNC(i8251_device::write_rxc));
+
+ SPEAKER(config, "mono").front_right();
+
+ CASSETTE(config, m_cass_player);
+ m_cass_player->set_formats(h8_cassette_formats);
+ m_cass_player->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED);
+ m_cass_player->add_route(ALL_OUTPUTS, "mono", 0.15);
+ m_cass_player->set_interface("h89_cass_player");
+
+ CASSETTE(config, m_cass_recorder);
+ m_cass_recorder->set_formats(h8_cassette_formats);
+ m_cass_recorder->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED);
+ m_cass_recorder->add_route(ALL_OUTPUTS, "mono", 0.15);
+ m_cass_recorder->set_interface("h89_cass_recorder");
+
+ TIMER(config, "kansas_w").configure_periodic(FUNC(heath_h_88_cass_device::kansas_w), attotime::from_hz(4800));
+ TIMER(config, "kansas_r").configure_periodic(FUNC(heath_h_88_cass_device::kansas_r), attotime::from_hz(40000));
+}
diff --git a/src/mame/heathkit/h_88_cass.h b/src/mame/heathkit/h_88_cass.h
new file mode 100644
index 00000000000..8656ee6bbf4
--- /dev/null
+++ b/src/mame/heathkit/h_88_cass.h
@@ -0,0 +1,53 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger
+/***************************************************************************
+
+ Heathkit H-88-5 Cassette Interface card
+
+****************************************************************************/
+
+#ifndef MAME_HEATHKIT_H_88_CASS_H
+#define MAME_HEATHKIT_H_88_CASS_H
+
+#pragma once
+
+#include "imagedev/cassette.h"
+#include "machine/i8251.h"
+#include "machine/timer.h"
+
+#include "formats/h8_cas.h"
+
+
+class heath_h_88_cass_device : public device_t
+{
+public:
+ heath_h_88_cass_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);
+
+protected:
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ void uart_rts(u8 data);
+ void uart_tx_empty(u8 data);
+
+ TIMER_DEVICE_CALLBACK_MEMBER(kansas_r);
+ TIMER_DEVICE_CALLBACK_MEMBER(kansas_w);
+
+ required_device<i8251_device> m_uart;
+ required_device<cassette_image_device> m_cass_player;
+ required_device<cassette_image_device> m_cass_recorder;
+
+ u8 m_cass_data[4];
+ bool m_cassbit;
+ bool m_cassold;
+};
+
+DECLARE_DEVICE_TYPE(HEATH_H88_CASS, heath_h_88_cass_device)
+
+
+#endif // MAME_HEATHKIT_H_88_CASS_H
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index 4394718fd1f..8d261119eb0 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -19230,7 +19230,8 @@ h8 //
h19 // Heath H19 (Zenith Z-19)
@source:heathkit/h89.cpp
-h89 // Heath H89 (H88, Zenith Z-89, Z-90)
+h89 // Heath H89 (WH89, Zenith Z-89, Z-90)
+h88 // Heath H88 (with cassette tape)
@source:hec2hrp/hec2hrp.cpp
hec2hr //