bus/heathzenith/h89: Add Z-89-11 Multi-Mode Interface Card option (#13105)

This commit is contained in:
Mark Garlanger 2024-12-27 21:00:29 -06:00 committed by GitHub
parent 926b6182b1
commit ee988cf9c6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 354 additions and 0 deletions

View File

@ -5787,6 +5787,8 @@ if (BUSES["H89BUS"]~=null) then
MAME_DIR .. "src/devices/bus/heathzenith/h89/sigmasoft_parallel_port.h",
MAME_DIR .. "src/devices/bus/heathzenith/h89/we_pullup.cpp",
MAME_DIR .. "src/devices/bus/heathzenith/h89/we_pullup.h",
MAME_DIR .. "src/devices/bus/heathzenith/h89/z_89_11.cpp",
MAME_DIR .. "src/devices/bus/heathzenith/h89/z_89_11.h",
MAME_DIR .. "src/devices/bus/heathzenith/h89/z37_fdc.cpp",
MAME_DIR .. "src/devices/bus/heathzenith/h89/z37_fdc.h",
}

View File

@ -16,6 +16,7 @@
#include "sigmasoft_parallel_port.h"
#include "sigmasoft_sound.h"
#include "we_pullup.h"
#include "z_89_11.h"
#include "z37_fdc.h"
void h89_left_cards(device_slot_interface &device)
@ -30,6 +31,8 @@ void h89_right_cards(device_slot_interface &device)
device.option_add("ha_88_3", H89BUS_HA_88_3);
device.option_add("h_88_5", H89BUS_H_88_5);
device.option_add("ss_snd", H89BUS_SIGMASOFT_SND);
device.option_add("z_89_11", H89BUS_Z_89_11);
device.option_add("z37fdc", H89BUS_Z37);
}

View File

@ -0,0 +1,330 @@
// license:BSD-3-Clause
// copyright-holders:Mark Garlanger
/***************************************************************************
Heath/Zenith Z-89-11 Multi-Mode Interface Card
****************************************************************************/
#include "emu.h"
#include "z_89_11.h"
#include "bus/rs232/rs232.h"
#include "machine/i8255.h"
#include "machine/ins8250.h"
#include "machine/scn_pci.h"
namespace {
class z_89_11_device : public device_t, public device_h89bus_right_card_interface
{
public:
z_89_11_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = XTAL(1'843'200).value());
virtual void write(u8 select_lines, u8 offset, u8 data) override;
virtual u8 read(u8 select_lines, u8 offset) override;
protected:
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual ioport_constructor device_input_ports() const override ATTR_COLD;
void lp_w(offs_t reg, u8 val);
u8 lp_r(offs_t reg);
void aux_w(offs_t reg, u8 val);
u8 aux_r(offs_t reg);
void modem_w(offs_t reg, u8 val);
u8 modem_r(offs_t reg);
void update_intr(u8 level);
void aux_int(int data);
required_device<i8255_device> m_lp;
required_device<ins8250_device> m_aux;
required_device<scn2661c_device> m_modem;
required_ioport m_cfg_lp;
required_ioport m_cfg_aux;
required_ioport m_cfg_modem;
bool m_lp_enabled;
bool m_aux_enabled;
bool m_modem_enabled;
u8 m_lp_int_idx;
u8 m_aux_int_idx;
u8 m_modem_int_idx;
int m_lp_intr;
int m_aux_intr;
int m_modem_intr;
};
z_89_11_device::z_89_11_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock):
device_t(mconfig, H89BUS_Z_89_11, tag, owner, clock),
device_h89bus_right_card_interface(mconfig, *this),
m_lp(*this, "lp"),
m_aux(*this, "aux"),
m_modem(*this, "modem"),
m_cfg_lp(*this, "CFG_LP"),
m_cfg_aux(*this, "CFG_AUX"),
m_cfg_modem(*this, "CFG_MODEM"),
m_lp_intr(0),
m_aux_intr(0),
m_modem_intr(0)
{
}
u8 z_89_11_device::read(u8 select_lines, u8 offset)
{
if ((select_lines & h89bus_device::H89_SER0) && (m_aux_enabled))
{
return aux_r(offset);
}
if ((select_lines & h89bus_device::H89_SER1) && (m_modem_enabled))
{
return modem_r(offset);
}
if ((select_lines & h89bus_device::H89_LP) && (m_lp_enabled))
{
return lp_r(offset);
}
return 0;
}
void z_89_11_device::write(u8 select_lines, u8 offset, u8 data)
{
if ((select_lines & h89bus_device::H89_SER0) && (m_aux_enabled))
{
aux_w(offset, data);
return;
}
if ((select_lines & h89bus_device::H89_SER1) && (m_modem_enabled))
{
modem_w(offset, data);
return;
}
if ((select_lines & h89bus_device::H89_LP) && (m_lp_enabled))
{
lp_w(offset, data);
return;
}
}
u8 z_89_11_device::lp_r(offs_t reg)
{
return m_lp->read(reg);
}
void z_89_11_device::lp_w(offs_t reg, u8 val)
{
m_lp->write(reg, val);
}
u8 z_89_11_device::aux_r(offs_t reg)
{
return m_aux->ins8250_r(reg);
}
void z_89_11_device::aux_w(offs_t reg, u8 val)
{
m_aux->ins8250_w(reg, val);
}
u8 z_89_11_device::modem_r(offs_t reg)
{
return m_modem->read(reg);
}
void z_89_11_device::modem_w(offs_t reg, u8 val)
{
m_modem->write(reg, val);
}
void z_89_11_device::update_intr(u8 level)
{
// check for interrupt disabled
if (level == 0)
{
return;
}
// Handle multiple ports set to the same interrupt. If any are set, interrupt should be triggered
int data = 0;
if (m_lp_enabled && (m_lp_int_idx == level))
{
data |= m_lp_intr;
}
if (m_aux_enabled && (m_aux_int_idx == level))
{
data |= m_aux_intr;
}
if (m_modem_enabled && (m_modem_int_idx == level))
{
data |= m_modem_intr;
}
switch(level)
{
case 1:
set_slot_int3(data);
break;
case 2:
set_slot_int4(data);
break;
case 3:
set_slot_int5(data);
break;
}
}
void z_89_11_device::aux_int(int data)
{
if (!m_aux_enabled)
{
return;
}
m_aux_intr = data;
update_intr(m_aux_int_idx);
}
void z_89_11_device::device_start()
{
save_item(NAME(m_lp_enabled));
save_item(NAME(m_lp_int_idx));
save_item(NAME(m_aux_enabled));
save_item(NAME(m_aux_int_idx));
save_item(NAME(m_modem_enabled));
save_item(NAME(m_modem_int_idx));
save_item(NAME(m_lp_intr));
save_item(NAME(m_aux_intr));
save_item(NAME(m_modem_intr));
}
void z_89_11_device::device_reset()
{
ioport_value const cfg_lp(m_cfg_lp->read());
ioport_value const cfg_aux(m_cfg_aux->read());
ioport_value const cfg_modem(m_cfg_modem->read());
m_lp_enabled = bool(BIT(cfg_lp, 0));
m_aux_enabled = bool(BIT(cfg_aux, 0));
m_modem_enabled = bool(BIT(cfg_modem, 0));
// LP Interrupt level
m_lp_int_idx = BIT(cfg_lp, 1, 2);
// AUX Interrupt level
m_aux_int_idx = BIT(cfg_aux, 1, 2);
// MODEM Interrupt level
m_modem_int_idx = BIT(cfg_modem, 1, 2);
}
void z_89_11_device::device_add_mconfig(machine_config &config)
{
// Parallel 0xD0-0xD7 (320 - 327 octal)
I8255(config, m_lp, m_clock);
// AUX DCE 0xE0-0xE7 (340 - 347 octal)
//
INS8250(config, m_aux, XTAL(1'843'200));
m_aux->out_tx_callback().set("dce2", FUNC(rs232_port_device::write_txd));
m_aux->out_dtr_callback().set("dce2", FUNC(rs232_port_device::write_dtr));
m_aux->out_rts_callback().set("dce2", FUNC(rs232_port_device::write_rts));
m_aux->out_int_callback().set(FUNC(z_89_11_device::aux_int));
rs232_port_device &dce2(RS232_PORT(config, "dce2", default_rs232_devices, "loopback"));
dce2.rxd_handler().set(m_aux, FUNC(ins8250_device::rx_w));
dce2.dcd_handler().set(m_aux, FUNC(ins8250_device::dcd_w));
dce2.dsr_handler().set(m_aux, FUNC(ins8250_device::dsr_w));
dce2.cts_handler().set(m_aux, FUNC(ins8250_device::cts_w));
dce2.ri_handler().set(m_aux, FUNC(ins8250_device::ri_w));
// Modem DTE 0xD7-0xDF (330 - 337 octal)
SCN2661C(config, m_modem, XTAL(5'068'800));
m_modem->txd_handler().set("dte", FUNC(rs232_port_device::write_txd));
m_modem->dtr_handler().set("dte", FUNC(rs232_port_device::write_dtr));
m_modem->rts_handler().set("dte", FUNC(rs232_port_device::write_rts));
rs232_port_device &dte(RS232_PORT(config, "dte", default_rs232_devices, "loopback"));
dte.rxd_handler().set(m_modem, FUNC(scn2661c_device::rxd_w));
dte.dcd_handler().set(m_modem, FUNC(scn2661c_device::dcd_w));
dte.dsr_handler().set(m_modem, FUNC(scn2661c_device::dsr_w));
dte.cts_handler().set(m_modem, FUNC(scn2661c_device::cts_w));
}
static INPUT_PORTS_START( z_89_11_device )
// INS8250
PORT_START("CFG_LP")
PORT_CONFNAME(0x01, 0x01, "LP - DCE (340 octal) Enabled" )
PORT_CONFSETTING( 0x00, DEF_STR( No ))
PORT_CONFSETTING( 0x01, DEF_STR( Yes ))
PORT_CONFNAME(0x06, 0x00, "LP - DCE (340 octal) Interrupt level")
PORT_CONFSETTING( 0x00, DEF_STR( None ))
PORT_CONFSETTING( 0x02, "3")
PORT_CONFSETTING( 0x04, "4")
PORT_CONFSETTING( 0x06, "5")
// 8255 chip
PORT_START("CFG_AUX")
PORT_CONFNAME(0x01, 0x01, "AUX - DCE (320 octal) Enabled" )
PORT_CONFSETTING( 0x00, DEF_STR( No ))
PORT_CONFSETTING( 0x01, DEF_STR( Yes ))
PORT_CONFNAME(0x06, 0x00, "AUX - DCE (320 octal) Interrupt level")
PORT_CONFSETTING( 0x00, DEF_STR( None ))
PORT_CONFSETTING( 0x02, "3")
PORT_CONFSETTING( 0x04, "4")
PORT_CONFSETTING( 0x06, "5")
// 2661
PORT_START("CFG_MODEM")
PORT_CONFNAME(0x01, 0x01, "MODEM - DTE (330 octal) Enabled" )
PORT_CONFSETTING( 0x00, DEF_STR( No ))
PORT_CONFSETTING( 0x01, DEF_STR( Yes ))
PORT_CONFNAME(0x06, 0x00, "MODEM - DTE (330 octal) Interrupt level")
PORT_CONFSETTING( 0x00, DEF_STR( None ))
PORT_CONFSETTING( 0x02, "3")
PORT_CONFSETTING( 0x04, "4")
PORT_CONFSETTING( 0x06, "5")
PORT_CONFNAME(0x08, 0x00, "Interrupt on Rx Ready Enabled")
PORT_CONFSETTING( 0x00, DEF_STR( No ))
PORT_CONFSETTING( 0x08, DEF_STR( Yes ))
PORT_CONFNAME(0x10, 0x00, "Interrupt on Tx Ready Enabled")
PORT_CONFSETTING( 0x00, DEF_STR( No ))
PORT_CONFSETTING( 0x10, DEF_STR( Yes ))
PORT_CONFNAME(0x20, 0x00, "Interrupt on Tx Empty Enabled")
PORT_CONFSETTING( 0x00, DEF_STR( No ))
PORT_CONFSETTING( 0x20, DEF_STR( Yes ))
INPUT_PORTS_END
ioport_constructor z_89_11_device::device_input_ports() const
{
return INPUT_PORTS_NAME(z_89_11_device);
}
}
DEFINE_DEVICE_TYPE_PRIVATE(H89BUS_Z_89_11, device_h89bus_right_card_interface, z_89_11_device, "z_89_11", "Heath/Zenith Z-89-11 Multi-Function I/O Card");

View File

@ -0,0 +1,19 @@
// license:BSD-3-Clause
// copyright-holders:Mark Garlanger
/***************************************************************************
Heath/Zenith Z-89-1 Multi-Function I/O card
****************************************************************************/
#ifndef MAME_BUS_HEATHZENITH_H89_Z_89_11_H
#define MAME_BUS_HEATHZENITH_H89_Z_89_11_H
#pragma once
#include "h89bus.h"
DECLARE_DEVICE_TYPE(H89BUS_Z_89_11, device_h89bus_right_card_interface)
#endif // MAME_BUS_HEATHZENITH_H89_Z_89_11_H