heathkit/h_88_cass.cpp, heathkit/h89.cpp: Added H-88-5 Cassette interface and the H88 as clone of H89. (#11898)

New working clones
---------------
Heath Company Heathkit H88
This commit is contained in:
Mark Garlanger 2024-01-07 09:49:30 -06:00 committed by GitHub
parent a693f1e7e3
commit 46dbcf7f79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 426 additions and 101 deletions

View File

@ -43,9 +43,10 @@
#include "emu.h" #include "emu.h"
#include "h_88_cass.h"
#include "intr_cntrl.h"
#include "tlb.h" #include "tlb.h"
#include "z37_fdc.h" #include "z37_fdc.h"
#include "intr_cntrl.h"
#include "cpu/z80/z80.h" #include "cpu/z80/z80.h"
#include "machine/ins8250.h" #include "machine/ins8250.h"
@ -64,10 +65,13 @@
namespace { namespace {
class h89_state : public driver_device /**
* Base Heathkit H89 functionality
*/
class h89_base_state : public driver_device
{ {
public: protected:
h89_state(const machine_config &mconfig, device_type type, const char *tag): h89_base_state(const machine_config &mconfig, device_type type, const char *tag):
driver_device(mconfig, type, tag), driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"), m_maincpu(*this, "maincpu"),
m_maincpu_region(*this, "maincpu"), m_maincpu_region(*this, "maincpu"),
@ -75,7 +79,6 @@ public:
m_ram(*this, RAM_TAG), m_ram(*this, RAM_TAG),
m_floppy_ram(*this, "floppyram"), m_floppy_ram(*this, "floppyram"),
m_tlbc(*this, "tlbc"), m_tlbc(*this, "tlbc"),
m_h37(*this, "h37"),
m_intr_socket(*this, "intr_socket"), m_intr_socket(*this, "intr_socket"),
m_console(*this, "console"), m_console(*this, "console"),
m_serial1(*this, "serial1"), m_serial1(*this, "serial1"),
@ -85,10 +88,7 @@ public:
{ {
} }
void h89(machine_config &config); void h89_base(machine_config &config);
private:
required_device<z80_device> m_maincpu; required_device<z80_device> m_maincpu;
required_memory_region m_maincpu_region; required_memory_region m_maincpu_region;
@ -96,7 +96,6 @@ private:
required_device<ram_device> m_ram; required_device<ram_device> m_ram;
required_shared_ptr<uint8_t> m_floppy_ram; required_shared_ptr<uint8_t> m_floppy_ram;
required_device<heath_tlb_connector> m_tlbc; 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<heath_intr_socket> m_intr_socket;
required_device<ins8250_device> m_console; required_device<ins8250_device> m_console;
required_device<ins8250_device> m_serial1; required_device<ins8250_device> m_serial1;
@ -142,7 +141,8 @@ private:
void h89_mem(address_map &map); void h89_mem(address_map &map);
void map_fetch(address_map &map); void map_fetch(address_map &map);
uint8_t m1_r(offs_t offset); 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(); uint8_t raise_NMI_r();
void raise_NMI_w(uint8_t data); void raise_NMI_w(uint8_t data);
@ -151,6 +151,52 @@ private:
void reset_single_step_state(); 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 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 is reserved for the monitor ROM, floppy ROM, and scratch pad RAM. For 16k-48K
@ -187,7 +233,7 @@ private:
------------- 0k ------------- 0k ------------- 0k ------------- 0k
*/ */
void h89_state::h89_mem(address_map &map) void h89_base_state::h89_mem(address_map &map)
{ {
map.unmap_value_high(); 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(); 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); uint8_t data = m_program.read_byte(offset);
@ -248,7 +294,6 @@ uint8_t h89_state::m1_r(offs_t offset)
Use | Hex | Octal Use | Hex | Octal
--------------------------+-------+--------- --------------------------+-------+---------
Not specified, available | 0-77 | 0-167 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 #1 | 78-7B | 170-173
Disk I/O #2 | 7C-7F | 174-177 Disk I/O #2 | 7C-7F | 174-177
Not specified, reserved | 80-CF | 200-317 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 Console I/O | E8-EF | 350-357
NMI | F0-F1 | 360-361 NMI | F0-F1 | 360-361
General purpose port | F2 | 362 General purpose port | F2 | 362
Cassette I/O(MTR-88) | F8-F9 | 370-371
NMI | FA-FB | 372-373 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.unmap_value_high();
map.global_mask(0xff); map.global_mask(0xff);
// Disk I/O #1 - 0170-0173 (0x78-0x7b) // Disk I/O #1 - 0170-0173 (0x78-0x7b)
// Options // Options
// - Cassette I/O (only uses 0x78 - 0x79) - Requires MTR-88 ROM
// - H37 5-1/4" Soft-sectored Controller - Requires MTR-90 ROM // - H37 5-1/4" Soft-sectored Controller - Requires MTR-90 ROM
// - H47 Dual 8" Drives - Requires MTR-89 or 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 // - 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) // Disk I/O #2 - 0174-0177 (0x7c-0x7f)
// Options // 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)); 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 // 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) // 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 // 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 // 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 ) static INPUT_PORTS_START( h89 )
PORT_START("SW501") PORT_START("SW501")
@ -354,53 +443,42 @@ static INPUT_PORTS_START( h89 )
PORT_DIPSETTING( 0x00, DEF_STR( Normal ) ) PORT_DIPSETTING( 0x00, DEF_STR( Normal ) )
PORT_DIPSETTING( 0x80, "Auto" ) 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) // 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( 0x00, "H-88-1" )
PORT_DIPSETTING( 0x01, "H/Z-47" ) PORT_DIPSETTING( 0x01, "H/Z-47" )
PORT_DIPSETTING( 0x02, "Undefined" ) PORT_DIPSETTING( 0x02, "Undefined" )
PORT_DIPSETTING( 0x03, "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( 0x00, "Unused" )
PORT_DIPSETTING( 0x04, "H/Z-47" ) PORT_DIPSETTING( 0x04, "H/Z-47" )
PORT_DIPSETTING( 0x08, "Undefined" ) PORT_DIPSETTING( 0x08, "Undefined" )
PORT_DIPSETTING( 0x0c, "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( 0x00, "Disk I/O #2" )
PORT_DIPSETTING( 0x10, "Disk I/O #1" ) 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( 0x20, DEF_STR( No ) )
PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) 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( 0x00, "9600" )
PORT_DIPSETTING( 0x40, "19200" ) 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( 0x00, DEF_STR( Normal ) )
PORT_DIPSETTING( 0x80, "Auto" ) PORT_DIPSETTING( 0x80, "Auto" )
// MMS 444-84B (and possibly 444-84A) // 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( 0x00, "H-88-1" )
PORT_DIPSETTING( 0x01, "H/Z-47 (Not yet implemented)" ) PORT_DIPSETTING( 0x01, "H/Z-47 (Not yet implemented)" )
PORT_DIPSETTING( 0x02, "MMS 77320 SASI or Z-67 (Not yet implemented)" ) PORT_DIPSETTING( 0x02, "MMS 77320 SASI or Z-67 (Not yet implemented)" )
PORT_DIPSETTING( 0x03, "MMS 77422 Network Controller" ) 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( 0x00, "H-89-37" )
PORT_DIPSETTING( 0x04, "H/Z-47 (Not yet implemented)" ) PORT_DIPSETTING( 0x04, "H/Z-47 (Not yet implemented)" )
PORT_DIPSETTING( 0x08, "MMS 77320 SASI or Z-67 (Not yet implemented)" ) PORT_DIPSETTING( 0x08, "MMS 77320 SASI or Z-67 (Not yet implemented)" )
PORT_DIPSETTING( 0x0c, "MMS 77422 Network Controller" ) 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( 0x00, "MMS 77316 Dbl Den 5\"" )
PORT_DIPSETTING( 0x10, "MMS 77316 Dbl Den 8\"" ) PORT_DIPSETTING( 0x10, "MMS 77316 Dbl Den 8\"" )
PORT_DIPSETTING( 0x20, "Disk Device at 0x7C" ) 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( 0x50, "reserved for future use" )
PORT_DIPSETTING( 0x60, "MMS Network (77422)" ) PORT_DIPSETTING( 0x60, "MMS Network (77422)" )
PORT_DIPSETTING( 0x70, "Use MMS I/O board Config Port" ) 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( 0x00, DEF_STR( Normal ) )
PORT_DIPSETTING( 0x80, "Auto" ) PORT_DIPSETTING( 0x80, "Auto" )
// Kres KMR-100 // 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( 0x00, "H-17 hard-sectored 5\" floppy units 0-2" )
PORT_DIPSETTING( 0x01, "H-37 soft-sectored 5\" floppy units 0-3" ) PORT_DIPSETTING( 0x01, "H-37 soft-sectored 5\" floppy units 0-3" )
PORT_DIPSETTING( 0x02, "Corvus hard disk/Magnolia interface, partitions 0-8" ) 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( 0x0d, "Reserved" )
PORT_DIPSETTING( 0x0e, "Reserved" ) PORT_DIPSETTING( 0x0e, "Reserved" )
PORT_DIPSETTING( 0x0f, "Magnolia 128K pseudo disk, banks 0-1" ) 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( 0x00, DEF_STR( Yes ) )
PORT_DIPSETTING( 0x10, DEF_STR( No ) ) 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( 0x20, DEF_STR( No ) )
PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) 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( 0x00, DEF_STR( No ) )
PORT_DIPSETTING( 0x40, DEF_STR( Yes ) ) 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( 0x00, DEF_STR( Normal ) )
PORT_DIPSETTING( 0x80, "Auto" ) PORT_DIPSETTING( 0x80, "Auto" )
// Ultimeth MTRHEX-4k // Ultimeth MTRHEX-4k
// (values based on testing and comparison with the Kres KMR-100 ROM which was also written by Ultimeth) // (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( 0x00, "H-17 hard-sectored 5\" floppy" )
PORT_DIPSETTING( 0x01, "H-37 soft-sectored 5\" floppy" ) PORT_DIPSETTING( 0x01, "H-37 soft-sectored 5\" floppy" )
PORT_DIPSETTING( 0x02, "? Corvus hard disk/Magnolia interface" ) PORT_DIPSETTING( 0x02, "? Corvus hard disk/Magnolia interface" )
@ -463,16 +541,16 @@ static INPUT_PORTS_START( h89 )
PORT_DIPSETTING( 0x0d, "? Reserved" ) PORT_DIPSETTING( 0x0d, "? Reserved" )
PORT_DIPSETTING( 0x0e, "? Reserved" ) PORT_DIPSETTING( 0x0e, "? Reserved" )
PORT_DIPSETTING( 0x0f, "? Magnolia 128K pseudo disk" ) 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( 0x00, "? Yes" )
PORT_DIPSETTING( 0x10, "? No" ) 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( 0x20, DEF_STR( No ) )
PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) 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( 0x00, "? No" )
PORT_DIPSETTING( 0x40, "? Yes" ) 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( 0x00, DEF_STR( Normal ) )
PORT_DIPSETTING( 0x80, "Auto" ) PORT_DIPSETTING( 0x80, "Auto" )
@ -485,16 +563,15 @@ static INPUT_PORTS_START( h89 )
PORT_CONFNAME(0x3c, 0x04, "Switch SW501 Definitions") PORT_CONFNAME(0x3c, 0x04, "Switch SW501 Definitions")
PORT_CONFSETTING(0x00, "Generic" ) PORT_CONFSETTING(0x00, "Generic" )
PORT_CONFSETTING(0x04, "Heath MTR-90") PORT_CONFSETTING(0x04, "Heath MTR-90")
PORT_CONFSETTING(0x08, "Heath MTR-88") PORT_CONFSETTING(0x08, "Heath MTR-89")
PORT_CONFSETTING(0x0c, "Heath MTR-89") PORT_CONFSETTING(0x0c, "MMS 444-84B/444-84A")
PORT_CONFSETTING(0x10, "MMS 444-84B/444-84A") PORT_CONFSETTING(0x10, "Kres KMR-100")
PORT_CONFSETTING(0x14, "Kres KMR-100") PORT_CONFSETTING(0x14, "Ultimeth MTRHEX-4k")
PORT_CONFSETTING(0x18, "Ultimeth MTRHEX-4k")
INPUT_PORTS_END INPUT_PORTS_END
void h89_state::machine_start() void h89_base_state::machine_start()
{ {
save_item(NAME(m_gpp)); save_item(NAME(m_gpp));
save_item(NAME(m_rom_enabled)); save_item(NAME(m_rom_enabled));
@ -541,8 +618,7 @@ void h89_state::machine_start()
} }
} }
void h89_base_state::machine_reset()
void h89_state::machine_reset()
{ {
m_rom_enabled = true; m_rom_enabled = true;
m_timer_intr_enabled = true; m_timer_intr_enabled = true;
@ -577,24 +653,24 @@ void h89_state::machine_reset()
update_mem_view(); 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)); m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::from_usec(2));
return 0x00; 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)); 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); 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)) if (bool(data))
{ {
@ -603,7 +679,7 @@ void h89_state::reset_line(int data)
m_maincpu->set_input_line(INPUT_LINE_RESET, 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) 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); 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"); LOGSS("reset_single_step_state\n");
m_555a_latch = false; 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 // 6 Latched bit I/O 0 on I/O exp connector
// 7 Latched bit I/O 1 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; uint8_t changed_gpp = gpp ^ m_gpp;
@ -672,7 +748,7 @@ void h89_state::update_gpp(uint8_t gpp)
} }
// General Purpose Port // 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); update_gpp(data);
@ -696,22 +772,21 @@ static void intr_ctrl_options(device_slot_interface &device)
device.option_add("h37", HEATH_Z37_INTR_CNTRL); 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 // basic machine hardware
Z80(config, m_maincpu, H89_CLOCK); Z80(config, m_maincpu, H89_CLOCK);
m_maincpu->set_m1_map(&h89_state::map_fetch); m_maincpu->set_m1_map(&h89_base_state::map_fetch);
m_maincpu->set_memory_map(&h89_state::h89_mem); m_maincpu->set_memory_map(&h89_base_state::h89_mem);
m_maincpu->set_io_map(&h89_state::h89_io);
m_maincpu->set_irq_acknowledge_callback("intr_socket", FUNC(heath_intr_socket::irq_callback)); 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); 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); 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"); 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->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->dtr_callback().set(m_console, FUNC(ins8250_uart_device::dsr_w));
m_tlbc->reset_cb().set(FUNC(h89_state::reset_line)); m_tlbc->reset_cb().set(FUNC(h89_base_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));
// H-88-3 3-port serial board // H-88-3 3-port serial board
INS8250(config, m_serial1, INS8250_CLOCK); INS8250(config, m_serial1, INS8250_CLOCK);
@ -736,9 +806,46 @@ void h89_state::h89(machine_config & config)
INS8250(config, m_serial3, INS8250_CLOCK); INS8250(config, m_serial3, INS8250_CLOCK);
// H89 interrupt interval is 2mSec // 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 definition
ROM_START( h89 ) ROM_START( h89 )
ROM_REGION( 0x2000, "maincpu", ROMREGION_ERASEFF ) ROM_REGION( 0x2000, "maincpu", ROMREGION_ERASEFF )
@ -749,26 +856,23 @@ ROM_START( h89 )
ROM_SYSTEM_BIOS(0, "mtr90", "MTR-90 (444-142)") 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)) 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)") ROM_SYSTEM_BIOS(1, "mtr89", "MTR-89 (444-62)")
ROMX_LOAD("2716_444-40_mtr88.u518", 0x0000, 0x0800, CRC(093afb79) SHA1(bcc1569ad9da7babf0a4199cab96d8cd59b2dd78), ROM_BIOS(1)) ROMX_LOAD("2716_444-62_mtr89.u518", 0x0000, 0x0800, CRC(8f507972) SHA1(ac6c6c1344ee4e09fb60d53c85c9b761217fe9dc), ROM_BIOS(1))
ROM_SYSTEM_BIOS(2, "mtr89", "MTR-89 (444-62)") ROM_SYSTEM_BIOS(2, "mms84b", "MMS 444-84B")
ROMX_LOAD("2716_444-62_mtr89.u518", 0x0000, 0x0800, CRC(8f507972) SHA1(ac6c6c1344ee4e09fb60d53c85c9b761217fe9dc), ROM_BIOS(2)) ROMX_LOAD("2732_444_84b_mms.u518", 0x0000, 0x1000, CRC(7e75d6f4) SHA1(baf34e036388d1a191197e31f8a93209f04fc58b), ROM_BIOS(2))
ROM_SYSTEM_BIOS(3, "mms84b", "MMS 444-84B") ROM_SYSTEM_BIOS(3, "kmr-100", "Kres KMR-100 V3.a.02")
ROMX_LOAD("2732_444_84b_mms.u518", 0x0000, 0x1000, CRC(7e75d6f4) SHA1(baf34e036388d1a191197e31f8a93209f04fc58b), ROM_BIOS(3)) ROMX_LOAD("2732_kmr100_v3_a_02.u518", 0x0000, 0x1000, CRC(fd491592) SHA1(3d5803f95c38b237b07cd230353cd9ddc9858c13), ROM_BIOS(3))
ROM_SYSTEM_BIOS(4, "kmr-100", "Kres KMR-100 V3.a.02") ROM_SYSTEM_BIOS(4, "mtrhex_4k", "Ultimeth ROM")
ROMX_LOAD("2732_kmr100_v3_a_02.u518", 0x0000, 0x1000, CRC(fd491592) SHA1(3d5803f95c38b237b07cd230353cd9ddc9858c13), ROM_BIOS(4)) ROMX_LOAD("2732_mtrhex_4k.u518", 0x0000, 0x1000, CRC(e26b29a9) SHA1(ba13d6c9deef682a9a8262bc910d46b577929a13), ROM_BIOS(4))
ROM_SYSTEM_BIOS(5, "mtrhex_4k", "Ultimeth ROM") ROM_SYSTEM_BIOS(5, "mtr90-84", "Heath's MTR-90 (444-84 - Superseded by 444-142)")
ROMX_LOAD("2732_mtrhex_4k.u518", 0x0000, 0x1000, CRC(e26b29a9) SHA1(ba13d6c9deef682a9a8262bc910d46b577929a13), ROM_BIOS(5)) ROMX_LOAD("2732_444-84_mtr90.u518", 0x0000, 0x1000, CRC(f10fca03) SHA1(c4a978153af0f2dfcc9ba05be4c1033d33fee30b), ROM_BIOS(5))
ROM_SYSTEM_BIOS(6, "mtr90-84", "Heath's MTR-90 (444-84 - Superseded by 444-142)") ROM_SYSTEM_BIOS(6, "mms84a", "MMS 444-84A (Superseded by MMS 444-84B)")
ROMX_LOAD("2732_444-84_mtr90.u518", 0x0000, 0x1000, CRC(f10fca03) SHA1(c4a978153af0f2dfcc9ba05be4c1033d33fee30b), ROM_BIOS(6)) ROMX_LOAD("2732_444_84a_mms.u518", 0x0000, 0x1000, CRC(0e541a7e) SHA1(b1deb620fc89c1068e2e663e14be69d1f337a4b9), ROM_BIOS(6))
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_END ROM_END
} // anonymous namespace } // anonymous namespace
@ -777,4 +881,5 @@ ROM_END
// Driver // Driver
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS // 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) COMP( 1979, h89, 0, 0, h89, h89, h89_state, empty_init, "Heath Company", "Heathkit H89", MACHINE_SUPPORTS_SAVE)

View File

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

View File

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

View File

@ -19230,7 +19230,8 @@ h8 //
h19 // Heath H19 (Zenith Z-19) h19 // Heath H19 (Zenith Z-19)
@source:heathkit/h89.cpp @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 @source:hec2hrp/hec2hrp.cpp
hec2hr // hec2hr //