mirror of
https://github.com/holub/mame
synced 2025-04-22 08:22:15 +03:00
Merge pull request #2749 from fulivi/hp80_dev04
HP85: support for I/O slots & HP-IB interface module
This commit is contained in:
commit
fb20279b92
@ -67,4 +67,17 @@
|
||||
</dataarea>
|
||||
</part>
|
||||
</software>
|
||||
<software name="mass">
|
||||
<description>Mass storage ROM</description>
|
||||
<year>1979</year>
|
||||
<publisher>Hewlett-Packard</publisher>
|
||||
<info name="serial" value="00085-15001"/>
|
||||
|
||||
<part name="rom" interface="hp80_rom">
|
||||
<feature name="sc" value="0xD0"/>
|
||||
<dataarea name="rom" size="0x2000">
|
||||
<rom name="rom320.bin" size="0x2000" crc="9c03582c" sha1="1cc9a5013739821cd1d7e2a52e8abbd29045e850" offset="0"/>
|
||||
</dataarea>
|
||||
</part>
|
||||
</software>
|
||||
</softwarelist>
|
||||
|
@ -3162,6 +3162,18 @@ if (BUSES["HP80_OPTROM"]~=null) then
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/bus/hp80_io/hp80_io.h,BUSES["HP80_IO"] = true
|
||||
---------------------------------------------------
|
||||
|
||||
if (BUSES["HP80_IO"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/bus/hp80_io/hp80_io.cpp",
|
||||
MAME_DIR .. "src/devices/bus/hp80_io/82937.cpp",
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/bus/hp9845_io/hp9845_io.h,BUSES["HP9845_IO"] = true
|
||||
|
@ -1036,6 +1036,18 @@ if (MACHINES["1MA6"]~=null) then
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/1mb5.h,MACHINES["1MB5"] = true
|
||||
---------------------------------------------------
|
||||
|
||||
if (MACHINES["1MB5"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/machine/1mb5.cpp",
|
||||
MAME_DIR .. "src/devices/machine/1mb5.h",
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/i2cmem.h,MACHINES["I2CMEM"] = true
|
||||
|
@ -418,6 +418,7 @@ MACHINES["HD63450"] = true
|
||||
MACHINES["HD64610"] = true
|
||||
MACHINES["HP_TACO"] = true
|
||||
MACHINES["1MA6"] = true
|
||||
MACHINES["1MB5"] = true
|
||||
MACHINES["I2CMEM"] = true
|
||||
MACHINES["I7220"] = true
|
||||
MACHINES["I80130"] = true
|
||||
@ -684,6 +685,7 @@ BUSES["ISA"] = true
|
||||
BUSES["ISBX"] = true
|
||||
BUSES["HP_OPTROM"] = true
|
||||
BUSES["HP80_OPTROM"] = true
|
||||
BUSES["HP80_IO"] = true
|
||||
BUSES["HP9845_IO"] = true
|
||||
BUSES["KC"] = true
|
||||
BUSES["LPCI"] = true
|
||||
|
354
src/devices/bus/hp80_io/82937.cpp
Normal file
354
src/devices/bus/hp80_io/82937.cpp
Normal file
@ -0,0 +1,354 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders: F. Ulivi
|
||||
/*********************************************************************
|
||||
|
||||
82937.cpp
|
||||
|
||||
82937 module (HPIB interface)
|
||||
|
||||
TODO: Implement Parallel Poll response
|
||||
|
||||
Thanks to Tim Nye & Everett Kaser for dumping the 8049 ROM
|
||||
|
||||
Main reference for this module is:
|
||||
HP 82937-90007, oct 80, HP82937A HP-IB Installation and theory
|
||||
of operation manual
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "82937.h"
|
||||
#include "coreutil.h"
|
||||
|
||||
// Debugging
|
||||
#define VERBOSE 0
|
||||
#include "logmacro.h"
|
||||
|
||||
// Bit manipulation
|
||||
namespace {
|
||||
static constexpr unsigned BIT_MASK(unsigned n)
|
||||
{
|
||||
return 1U << n;
|
||||
}
|
||||
|
||||
template<typename T> void BIT_SET(T& w , unsigned n)
|
||||
{
|
||||
w |= (T)BIT_MASK(n);
|
||||
}
|
||||
}
|
||||
|
||||
// Bits in U3 (m_latch)
|
||||
static constexpr unsigned LATCH_CA_BIT = 5; // Controller Active
|
||||
static constexpr unsigned LATCH_TA_BIT = 4; // Talker Active
|
||||
static constexpr unsigned LATCH_EN_IFC_INT_BIT = 3; // Enable IFC interrupt
|
||||
static constexpr unsigned LATCH_EN_REN_INT_BIT = 2; // Enable REN interrupt
|
||||
static constexpr unsigned LATCH_EN_ATN_INT_BIT = 1; // Enable ATN interrupt
|
||||
static constexpr unsigned LATCH_EN_NDAC_BIT = 0; // Enable NDAC
|
||||
|
||||
// Bits on P1 port of 8049
|
||||
static constexpr unsigned P1_IFC_BIT = 7;
|
||||
static constexpr unsigned P1_REN_BIT = 6;
|
||||
static constexpr unsigned P1_SRQ_BIT = 5;
|
||||
static constexpr unsigned P1_ATN_BIT = 4;
|
||||
static constexpr unsigned P1_EOI_BIT = 3;
|
||||
static constexpr unsigned P1_DAV_BIT = 2;
|
||||
static constexpr unsigned P1_NDAC_BIT = 1;
|
||||
static constexpr unsigned P1_NRFD_BIT = 0;
|
||||
|
||||
hp82937_io_card_device::hp82937_io_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: hp80_io_card_device(mconfig , HP82937_IO_CARD , tag , owner , clock),
|
||||
m_cpu(*this , "cpu"),
|
||||
m_translator(*this , "xlator"),
|
||||
m_sw1(*this , "sw1"),
|
||||
m_ieee488(*this , IEEE488_TAG)
|
||||
{
|
||||
}
|
||||
|
||||
hp82937_io_card_device::~hp82937_io_card_device()
|
||||
{
|
||||
}
|
||||
|
||||
void hp82937_io_card_device::install_read_write_handlers(address_space& space , uint16_t base_addr)
|
||||
{
|
||||
space.install_readwrite_handler(base_addr , base_addr + 1 , READ8_DEVICE_DELEGATE(m_translator , hp_1mb5_device , cpu_r) , WRITE8_DEVICE_DELEGATE(m_translator , hp_1mb5_device , cpu_w));
|
||||
}
|
||||
|
||||
void hp82937_io_card_device::inten()
|
||||
{
|
||||
m_translator->inten();
|
||||
}
|
||||
|
||||
void hp82937_io_card_device::clear_service()
|
||||
{
|
||||
m_translator->clear_service();
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(hp82937_io_card_device::reset_w)
|
||||
{
|
||||
m_cpu->set_input_line(INPUT_LINE_RESET , state);
|
||||
if (state) {
|
||||
// When reset is asserted, clear state
|
||||
device_reset();
|
||||
}
|
||||
}
|
||||
|
||||
READ_LINE_MEMBER(hp82937_io_card_device::t0_r)
|
||||
{
|
||||
return m_iatn;
|
||||
}
|
||||
|
||||
READ8_MEMBER(hp82937_io_card_device::p1_r)
|
||||
{
|
||||
uint8_t res = 0;
|
||||
|
||||
if (BIT(m_sw1->read() , 5)) {
|
||||
// System controller
|
||||
BIT_SET(res , P1_IFC_BIT);
|
||||
BIT_SET(res , P1_REN_BIT);
|
||||
} else {
|
||||
// Not system controller
|
||||
if (m_ieee488->ifc_r()) {
|
||||
BIT_SET(res , P1_IFC_BIT);
|
||||
}
|
||||
if (m_ieee488->ren_r()) {
|
||||
BIT_SET(res , P1_REN_BIT);
|
||||
}
|
||||
}
|
||||
if (!BIT(m_latch , LATCH_CA_BIT) || m_ieee488->srq_r()) {
|
||||
BIT_SET(res , P1_SRQ_BIT);
|
||||
}
|
||||
if (m_iatn) {
|
||||
BIT_SET(res , P1_ATN_BIT);
|
||||
}
|
||||
bool ndac = !BIT(m_latch , LATCH_EN_NDAC_BIT) || m_iatn;
|
||||
if (m_talker_out) {
|
||||
BIT_SET(res , P1_EOI_BIT);
|
||||
BIT_SET(res , P1_DAV_BIT);
|
||||
if (ndac && m_ieee488->ndac_r()) {
|
||||
BIT_SET(res , P1_NDAC_BIT);
|
||||
}
|
||||
if (m_ieee488->nrfd_r()) {
|
||||
BIT_SET(res , P1_NRFD_BIT);
|
||||
}
|
||||
} else {
|
||||
if (m_ieee488->eoi_r()) {
|
||||
BIT_SET(res , P1_EOI_BIT);
|
||||
}
|
||||
if (m_ieee488->dav_r()) {
|
||||
BIT_SET(res , P1_DAV_BIT);
|
||||
}
|
||||
if (ndac) {
|
||||
BIT_SET(res , P1_NDAC_BIT);
|
||||
}
|
||||
BIT_SET(res , P1_NRFD_BIT);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(hp82937_io_card_device::p1_w)
|
||||
{
|
||||
update_signals();
|
||||
update_data_out();
|
||||
}
|
||||
|
||||
READ8_MEMBER(hp82937_io_card_device::dio_r)
|
||||
{
|
||||
if (m_dio_out) {
|
||||
return 0xff;
|
||||
} else {
|
||||
return m_ieee488->dio_r();
|
||||
}
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(hp82937_io_card_device::dio_w)
|
||||
{
|
||||
update_data_out();
|
||||
}
|
||||
|
||||
READ8_MEMBER(hp82937_io_card_device::switch_r)
|
||||
{
|
||||
return m_sw1->read() | 0xc0;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(hp82937_io_card_device::latch_w)
|
||||
{
|
||||
LOG("latch=%02x\n" , data);
|
||||
m_latch = data;
|
||||
update_signals();
|
||||
update_data_out();
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(hp82937_io_card_device::ieee488_ctrl_w)
|
||||
{
|
||||
update_signals();
|
||||
update_data_out();
|
||||
}
|
||||
|
||||
static INPUT_PORTS_START(hp82937_port)
|
||||
MCFG_HP80_IO_SC(7)
|
||||
PORT_START("sw1")
|
||||
PORT_DIPNAME(0x1f , 0x15 , "HPIB address")
|
||||
PORT_DIPLOCATION("S1:7,6,5,4,3")
|
||||
PORT_DIPSETTING(0x00 , "0")
|
||||
PORT_DIPSETTING(0x01 , "1")
|
||||
PORT_DIPSETTING(0x02 , "2")
|
||||
PORT_DIPSETTING(0x03 , "3")
|
||||
PORT_DIPSETTING(0x04 , "4")
|
||||
PORT_DIPSETTING(0x05 , "5")
|
||||
PORT_DIPSETTING(0x06 , "6")
|
||||
PORT_DIPSETTING(0x07 , "7")
|
||||
PORT_DIPSETTING(0x08 , "8")
|
||||
PORT_DIPSETTING(0x09 , "9")
|
||||
PORT_DIPSETTING(0x0a , "10")
|
||||
PORT_DIPSETTING(0x0b , "11")
|
||||
PORT_DIPSETTING(0x0c , "12")
|
||||
PORT_DIPSETTING(0x0d , "13")
|
||||
PORT_DIPSETTING(0x0e , "14")
|
||||
PORT_DIPSETTING(0x0f , "15")
|
||||
PORT_DIPSETTING(0x10 , "16")
|
||||
PORT_DIPSETTING(0x11 , "17")
|
||||
PORT_DIPSETTING(0x12 , "18")
|
||||
PORT_DIPSETTING(0x13 , "19")
|
||||
PORT_DIPSETTING(0x14 , "20")
|
||||
PORT_DIPSETTING(0x15 , "21")
|
||||
PORT_DIPSETTING(0x16 , "22")
|
||||
PORT_DIPSETTING(0x17 , "23")
|
||||
PORT_DIPSETTING(0x18 , "24")
|
||||
PORT_DIPSETTING(0x19 , "25")
|
||||
PORT_DIPSETTING(0x1a , "26")
|
||||
PORT_DIPSETTING(0x1b , "27")
|
||||
PORT_DIPSETTING(0x1c , "28")
|
||||
PORT_DIPSETTING(0x1d , "29")
|
||||
PORT_DIPSETTING(0x1e , "30")
|
||||
PORT_DIPSETTING(0x1f , "31")
|
||||
PORT_DIPNAME(0x20 , 0x20 , "Sys. controller")
|
||||
PORT_DIPLOCATION("S1:2")
|
||||
PORT_DIPSETTING(0x00 , DEF_STR(Off))
|
||||
PORT_DIPSETTING(0x20 , DEF_STR(On))
|
||||
INPUT_PORTS_END
|
||||
|
||||
ioport_constructor hp82937_io_card_device::device_input_ports() const
|
||||
{
|
||||
return INPUT_PORTS_NAME(hp82937_port);
|
||||
}
|
||||
|
||||
void hp82937_io_card_device::device_start()
|
||||
{
|
||||
save_item(NAME(m_dio_out));
|
||||
save_item(NAME(m_talker_out));
|
||||
save_item(NAME(m_iatn));
|
||||
save_item(NAME(m_latch));
|
||||
}
|
||||
|
||||
void hp82937_io_card_device::device_reset()
|
||||
{
|
||||
hp80_io_card_device::device_reset();
|
||||
|
||||
m_latch = 0;
|
||||
m_updating = false;
|
||||
update_signals();
|
||||
update_data_out();
|
||||
}
|
||||
|
||||
void hp82937_io_card_device::update_data_out()
|
||||
{
|
||||
m_ieee488->dio_w(m_dio_out ? m_cpu->p2_r(machine().dummy_space() , 0) : 0xff);
|
||||
}
|
||||
|
||||
void hp82937_io_card_device::update_signals()
|
||||
{
|
||||
// Avoid recursive re-enter when writing to IEEE488 signals
|
||||
if (m_updating) {
|
||||
return;
|
||||
}
|
||||
m_updating = true;
|
||||
bool ctrl_active = BIT(m_latch , LATCH_CA_BIT);
|
||||
uint8_t p1 = m_cpu->p1_r(machine().dummy_space() , 0);
|
||||
m_iatn = BIT(p1 , P1_ATN_BIT);
|
||||
if (ctrl_active) {
|
||||
m_ieee488->atn_w(m_iatn);
|
||||
m_ieee488->srq_w(1);
|
||||
} else {
|
||||
m_ieee488->atn_w(1);
|
||||
m_iatn = m_iatn && m_ieee488->atn_r();
|
||||
m_ieee488->srq_w(BIT(p1 , P1_SRQ_BIT));
|
||||
}
|
||||
m_talker_out = (ctrl_active && !m_iatn) || (BIT(m_latch , LATCH_TA_BIT) && m_iatn);
|
||||
if (m_talker_out) {
|
||||
m_ieee488->nrfd_w(1);
|
||||
m_ieee488->dav_w(BIT(p1 , P1_DAV_BIT));
|
||||
m_ieee488->eoi_w(BIT(p1 , P1_EOI_BIT));
|
||||
m_ieee488->ndac_w(1);
|
||||
|
||||
} else {
|
||||
m_ieee488->nrfd_w(BIT(p1 , P1_NRFD_BIT));
|
||||
m_ieee488->dav_w(1);
|
||||
m_ieee488->eoi_w(1);
|
||||
bool ndac = BIT(p1 , P1_NDAC_BIT);
|
||||
if (BIT(m_latch , LATCH_EN_NDAC_BIT) && !m_iatn) {
|
||||
ndac = false;
|
||||
}
|
||||
m_ieee488->ndac_w(ndac);
|
||||
}
|
||||
bool iren = BIT(p1 , P1_REN_BIT);
|
||||
if (BIT(m_sw1->read() , 5)) {
|
||||
// System controller
|
||||
m_ieee488->ren_w(iren);
|
||||
m_ieee488->ifc_w(BIT(p1 , P1_IFC_BIT));
|
||||
} else {
|
||||
// Not system controller
|
||||
m_ieee488->ren_w(1);
|
||||
iren = iren && m_ieee488->ren_r();
|
||||
m_ieee488->ifc_w(1);
|
||||
}
|
||||
bool not_u8_1 = m_iatn || m_ieee488->eoi_r();
|
||||
m_dio_out = not_u8_1 && m_talker_out;
|
||||
bool irq = (BIT(m_latch , LATCH_EN_IFC_INT_BIT) && !m_ieee488->ifc_r()) ||
|
||||
(BIT(m_latch , LATCH_EN_REN_INT_BIT) && iren) ||
|
||||
(BIT(m_latch , LATCH_EN_ATN_INT_BIT) && !m_iatn);
|
||||
m_cpu->set_input_line(MCS48_INPUT_IRQ , irq);
|
||||
m_updating = false;
|
||||
}
|
||||
|
||||
ROM_START(hp82937)
|
||||
ROM_REGION(0x800 , "cpu" , 0)
|
||||
ROM_LOAD("1820-2437.bin" , 0 , 0x800 , CRC(687d1559) SHA1(44dfc8c3f431cd37a270b094f1db751214009214))
|
||||
ROM_END
|
||||
|
||||
static ADDRESS_MAP_START(cpu_io_map , AS_IO , 8 , hp82937_io_card_device)
|
||||
ADDRESS_MAP_UNMAP_HIGH
|
||||
AM_RANGE(0x00 , 0x01) AM_DEVREADWRITE("xlator" , hp_1mb5_device , uc_r , uc_w)
|
||||
AM_RANGE(0x03 , 0x03) AM_READWRITE(switch_r , latch_w)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
const tiny_rom_entry *hp82937_io_card_device::device_rom_region() const
|
||||
{
|
||||
return ROM_NAME(hp82937);
|
||||
}
|
||||
|
||||
MACHINE_CONFIG_MEMBER(hp82937_io_card_device::device_add_mconfig)
|
||||
MCFG_CPU_ADD("cpu" , I8049 , XTAL_11MHz)
|
||||
MCFG_CPU_IO_MAP(cpu_io_map)
|
||||
MCFG_MCS48_PORT_T0_IN_CB(READLINE(hp82937_io_card_device , t0_r))
|
||||
MCFG_MCS48_PORT_T1_IN_CB(DEVREADLINE("xlator" , hp_1mb5_device , int_r))
|
||||
MCFG_MCS48_PORT_P1_IN_CB(READ8(hp82937_io_card_device , p1_r))
|
||||
MCFG_MCS48_PORT_P1_OUT_CB(WRITE8(hp82937_io_card_device , p1_w))
|
||||
MCFG_MCS48_PORT_P2_IN_CB(READ8(hp82937_io_card_device , dio_r))
|
||||
MCFG_MCS48_PORT_P2_OUT_CB(WRITE8(hp82937_io_card_device , dio_w))
|
||||
|
||||
MCFG_DEVICE_ADD("xlator" , HP_1MB5 , 0)
|
||||
MCFG_1MB5_IRL_HANDLER(WRITELINE(hp82937_io_card_device , irl_w))
|
||||
MCFG_1MB5_HALT_HANDLER(WRITELINE(hp82937_io_card_device , halt_w))
|
||||
MCFG_1MB5_RESET_HANDLER(WRITELINE(hp82937_io_card_device , reset_w))
|
||||
|
||||
MCFG_IEEE488_SLOT_ADD("ieee_dev" , 0 , hp_ieee488_devices , nullptr)
|
||||
MCFG_IEEE488_BUS_ADD()
|
||||
MCFG_IEEE488_IFC_CALLBACK(WRITELINE(hp82937_io_card_device , ieee488_ctrl_w))
|
||||
MCFG_IEEE488_ATN_CALLBACK(WRITELINE(hp82937_io_card_device , ieee488_ctrl_w))
|
||||
MCFG_IEEE488_REN_CALLBACK(WRITELINE(hp82937_io_card_device , ieee488_ctrl_w))
|
||||
MCFG_IEEE488_EOI_CALLBACK(WRITELINE(hp82937_io_card_device , ieee488_ctrl_w))
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(HP82937_IO_CARD, hp82937_io_card_device, "hp82937", "HP82937 card")
|
71
src/devices/bus/hp80_io/82937.h
Normal file
71
src/devices/bus/hp80_io/82937.h
Normal file
@ -0,0 +1,71 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders: F. Ulivi
|
||||
/*********************************************************************
|
||||
|
||||
82937.h
|
||||
|
||||
82937 module (HPIB interface)
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef MAME_BUS_HP80_IO_82937_H
|
||||
#define MAME_BUS_HP80_IO_82937_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hp80_io.h"
|
||||
#include "cpu/mcs48/mcs48.h"
|
||||
#include "bus/ieee488/ieee488.h"
|
||||
#include "machine/1mb5.h"
|
||||
|
||||
class hp82937_io_card_device : public hp80_io_card_device
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
hp82937_io_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
virtual ~hp82937_io_card_device();
|
||||
|
||||
virtual void install_read_write_handlers(address_space& space , uint16_t base_addr) override;
|
||||
|
||||
virtual void inten() override;
|
||||
virtual void clear_service() override;
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(reset_w);
|
||||
DECLARE_READ_LINE_MEMBER(t0_r);
|
||||
DECLARE_READ8_MEMBER(p1_r);
|
||||
DECLARE_WRITE8_MEMBER(p1_w);
|
||||
DECLARE_READ8_MEMBER(dio_r);
|
||||
DECLARE_WRITE8_MEMBER(dio_w);
|
||||
DECLARE_READ8_MEMBER(switch_r);
|
||||
DECLARE_WRITE8_MEMBER(latch_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(ieee488_ctrl_w);
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// device-level overrides
|
||||
virtual ioport_constructor device_input_ports() const override;
|
||||
virtual const tiny_rom_entry *device_rom_region() const override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
|
||||
private:
|
||||
required_device<i8049_device> m_cpu;
|
||||
required_device<hp_1mb5_device> m_translator;
|
||||
required_ioport m_sw1;
|
||||
required_device<ieee488_device> m_ieee488;
|
||||
|
||||
bool m_dio_out; // U8-4
|
||||
bool m_talker_out; // U7-6
|
||||
bool m_iatn;
|
||||
uint8_t m_latch; // U3
|
||||
bool m_updating;
|
||||
|
||||
void update_data_out();
|
||||
void update_signals();
|
||||
};
|
||||
|
||||
// device type definition
|
||||
DECLARE_DEVICE_TYPE(HP82937_IO_CARD, hp82937_io_card_device)
|
||||
|
||||
#endif // MAME_BUS_HP80_IO_82937_H
|
150
src/devices/bus/hp80_io/hp80_io.cpp
Normal file
150
src/devices/bus/hp80_io/hp80_io.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders: F. Ulivi
|
||||
/*********************************************************************
|
||||
|
||||
hp80_io.cpp
|
||||
|
||||
I/O bus of HP80 systems
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "hp80_io.h"
|
||||
|
||||
// Debugging
|
||||
#define VERBOSE 0
|
||||
#include "logmacro.h"
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(HP80_IO_SLOT, hp80_io_slot_device, "hp80_io_slot", "HP80 I/O Slot")
|
||||
|
||||
// +-------------------+
|
||||
// |hp80_io_slot_device|
|
||||
// +-------------------+
|
||||
hp80_io_slot_device::hp80_io_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||
device_t(mconfig, HP80_IO_SLOT, tag, owner, clock),
|
||||
device_slot_interface(mconfig, *this),
|
||||
m_irl_cb_func(*this),
|
||||
m_halt_cb_func(*this),
|
||||
m_slot_no(0)
|
||||
{
|
||||
}
|
||||
|
||||
hp80_io_slot_device::~hp80_io_slot_device()
|
||||
{
|
||||
}
|
||||
|
||||
void hp80_io_slot_device::device_start()
|
||||
{
|
||||
m_irl_cb_func.resolve_safe();
|
||||
m_halt_cb_func.resolve_safe();
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(hp80_io_slot_device::irl_w)
|
||||
{
|
||||
LOG("irl_w slot %u=%d\n" , m_slot_no , state);
|
||||
m_irl_cb_func(m_slot_no , state , 0xff);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(hp80_io_slot_device::halt_w)
|
||||
{
|
||||
LOG("halt_w slot %u=%d\n" , m_slot_no , state);
|
||||
m_halt_cb_func(m_slot_no , state , 0xff);
|
||||
}
|
||||
|
||||
void hp80_io_slot_device::inten()
|
||||
{
|
||||
hp80_io_card_device *card = downcast<hp80_io_card_device*>(get_card_device());
|
||||
|
||||
if (card != nullptr) {
|
||||
card->inten();
|
||||
}
|
||||
}
|
||||
|
||||
void hp80_io_slot_device::clear_service()
|
||||
{
|
||||
hp80_io_card_device *card = downcast<hp80_io_card_device*>(get_card_device());
|
||||
|
||||
if (card != nullptr) {
|
||||
card->clear_service();
|
||||
}
|
||||
}
|
||||
|
||||
void hp80_io_slot_device::install_read_write_handlers(address_space& space)
|
||||
{
|
||||
hp80_io_card_device *card = downcast<hp80_io_card_device*>(get_card_device());
|
||||
|
||||
if (card != nullptr) {
|
||||
card->install_read_write_handlers(space , get_base_addr());
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t hp80_io_slot_device::get_sc() const
|
||||
{
|
||||
const hp80_io_card_device *card = downcast<hp80_io_card_device*>(get_card_device());
|
||||
|
||||
if (card != nullptr) {
|
||||
return card->get_sc();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t hp80_io_slot_device::get_base_addr() const
|
||||
{
|
||||
const hp80_io_card_device *card = downcast<hp80_io_card_device*>(get_card_device());
|
||||
|
||||
if (card != nullptr) {
|
||||
uint16_t addr = ((uint16_t)(card->get_sc() - HP80_IO_FIRST_SC) << 1) | 0xff50;
|
||||
return addr;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// +-------------------+
|
||||
// |hp80_io_card_device|
|
||||
// +-------------------+
|
||||
uint8_t hp80_io_card_device::get_sc() const
|
||||
{
|
||||
return m_select_code_port->read() + HP80_IO_FIRST_SC;
|
||||
}
|
||||
|
||||
void hp80_io_card_device::inten()
|
||||
{
|
||||
}
|
||||
|
||||
void hp80_io_card_device::clear_service()
|
||||
{
|
||||
}
|
||||
|
||||
hp80_io_card_device::hp80_io_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
|
||||
device_t(mconfig, type, tag, owner, clock),
|
||||
device_slot_card_interface(mconfig, *this),
|
||||
m_select_code_port(*this , "SC")
|
||||
{
|
||||
}
|
||||
|
||||
hp80_io_card_device::~hp80_io_card_device()
|
||||
{
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(hp80_io_card_device::irl_w)
|
||||
{
|
||||
LOG("irl_w card=%d\n" , state);
|
||||
hp80_io_slot_device *slot = downcast<hp80_io_slot_device *>(owner());
|
||||
slot->irl_w(state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(hp80_io_card_device::halt_w)
|
||||
{
|
||||
LOG("halt_w card=%d\n" , state);
|
||||
hp80_io_slot_device *slot = downcast<hp80_io_slot_device *>(owner());
|
||||
slot->halt_w(state);
|
||||
}
|
||||
|
||||
#include "82937.h"
|
||||
|
||||
SLOT_INTERFACE_START(hp80_io_slot_devices)
|
||||
SLOT_INTERFACE("82937_hpib" , HP82937_IO_CARD)
|
||||
SLOT_INTERFACE_END
|
107
src/devices/bus/hp80_io/hp80_io.h
Normal file
107
src/devices/bus/hp80_io/hp80_io.h
Normal file
@ -0,0 +1,107 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders: F. Ulivi
|
||||
/*********************************************************************
|
||||
|
||||
hp80_io.h
|
||||
|
||||
I/O bus of HP80 systems
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef MAME_BUS_HP80_IO_HP80_IO_H
|
||||
#define MAME_BUS_HP80_IO_HP80_IO_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#define MCFG_HP80_IO_SLOT_ADD(_tag , _idx) \
|
||||
MCFG_DEVICE_ADD(_tag, HP80_IO_SLOT, 0) \
|
||||
MCFG_DEVICE_SLOT_INTERFACE(hp80_io_slot_devices, nullptr, false) \
|
||||
hp80_io_slot_device::set_slot_no(*device , _idx);
|
||||
|
||||
#define MCFG_HP80_IO_IRL_CB(_devcb) \
|
||||
devcb = &hp80_io_slot_device::set_irl_cb_func(*device , DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_HP80_IO_HALT_CB(_devcb) \
|
||||
devcb = &hp80_io_slot_device::set_halt_cb_func(*device , DEVCB_##_devcb);
|
||||
|
||||
#define HP80_IO_FIRST_SC 3 // Lowest SC used by I/O cards
|
||||
|
||||
#define MCFG_HP80_IO_SC(_default_sc) \
|
||||
PORT_START("SC") \
|
||||
PORT_CONFNAME(0xf , (_default_sc) - HP80_IO_FIRST_SC , "Select Code") \
|
||||
PORT_CONFSETTING(0 , "3")\
|
||||
PORT_CONFSETTING(1 , "4")\
|
||||
PORT_CONFSETTING(2 , "5")\
|
||||
PORT_CONFSETTING(3 , "6")\
|
||||
PORT_CONFSETTING(4 , "7")\
|
||||
PORT_CONFSETTING(5 , "8")\
|
||||
PORT_CONFSETTING(6 , "9")\
|
||||
PORT_CONFSETTING(7 , "10")
|
||||
|
||||
class hp80_io_slot_device : public device_t,
|
||||
public device_slot_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
hp80_io_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
virtual ~hp80_io_slot_device();
|
||||
|
||||
// static configuration helpers
|
||||
static void set_slot_no(device_t &device, unsigned slot_no) { downcast<hp80_io_slot_device &>(device).m_slot_no = slot_no; }
|
||||
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
|
||||
// Callback setups
|
||||
template <class Object> static devcb_base &set_irl_cb_func(device_t &device, Object &&cb) { return downcast<hp80_io_slot_device &>(device).m_irl_cb_func.set_callback(std::forward<Object>(cb)); }
|
||||
template <class Object> static devcb_base &set_halt_cb_func(device_t &device, Object &&cb) { return downcast<hp80_io_slot_device &>(device).m_halt_cb_func.set_callback(std::forward<Object>(cb)); }
|
||||
|
||||
// SC getter
|
||||
uint8_t get_sc() const;
|
||||
|
||||
uint16_t get_base_addr() const;
|
||||
|
||||
void install_read_write_handlers(address_space& space);
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(irl_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(halt_w);
|
||||
|
||||
void inten();
|
||||
void clear_service();
|
||||
|
||||
private:
|
||||
devcb_write8 m_irl_cb_func;
|
||||
devcb_write8 m_halt_cb_func;
|
||||
unsigned m_slot_no;
|
||||
};
|
||||
|
||||
class hp80_io_card_device : public device_t,
|
||||
public device_slot_card_interface
|
||||
{
|
||||
public:
|
||||
// SC getter
|
||||
uint8_t get_sc() const;
|
||||
|
||||
virtual void install_read_write_handlers(address_space& space , uint16_t base_addr) = 0;
|
||||
|
||||
virtual void inten();
|
||||
virtual void clear_service();
|
||||
|
||||
protected:
|
||||
// construction/destruction
|
||||
hp80_io_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
|
||||
virtual ~hp80_io_card_device();
|
||||
|
||||
required_ioport m_select_code_port;
|
||||
|
||||
// card device handling
|
||||
DECLARE_WRITE_LINE_MEMBER(irl_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(halt_w);
|
||||
};
|
||||
|
||||
// device type definition
|
||||
DECLARE_DEVICE_TYPE(HP80_IO_SLOT, hp80_io_slot_device)
|
||||
|
||||
SLOT_INTERFACE_EXTERN(hp80_io_slot_devices);
|
||||
|
||||
#endif // MAME_BUS_HP80_IO_HP80_IO_H
|
@ -484,6 +484,10 @@ WRITE8_MEMBER(hp9895_device::phi_dio_w)
|
||||
WRITE_LINE_MEMBER(hp9895_device::phi_int_w)
|
||||
{
|
||||
m_cpu->set_input_line(INPUT_LINE_NMI , state);
|
||||
if (state) {
|
||||
// Ensure the event queue is emptied before executing any other instruction
|
||||
m_cpu->yield();
|
||||
}
|
||||
}
|
||||
|
||||
READ8_MEMBER(hp9895_device::phi_reg_r)
|
||||
|
295
src/devices/machine/1mb5.cpp
Normal file
295
src/devices/machine/1mb5.cpp
Normal file
@ -0,0 +1,295 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:F. Ulivi
|
||||
/*********************************************************************
|
||||
|
||||
1mb5.cpp
|
||||
|
||||
HP-8x I/O Translator chip (1MB5-0101)
|
||||
|
||||
Reference for this chip:
|
||||
HP, aug 79, 1MB5 Detailed specification - Translator chip
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "1mb5.h"
|
||||
|
||||
// Debugging
|
||||
#define VERBOSE 0
|
||||
#include "logmacro.h"
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(HP_1MB5, hp_1mb5_device, "hp_1mb5", "HP 1MB5")
|
||||
|
||||
// Bit manipulation
|
||||
namespace {
|
||||
static constexpr unsigned BIT_MASK(unsigned n)
|
||||
{
|
||||
return 1U << n;
|
||||
}
|
||||
|
||||
template<typename T> void BIT_CLR(T& w , unsigned n)
|
||||
{
|
||||
w &= ~(T)BIT_MASK(n);
|
||||
}
|
||||
|
||||
template<typename T> void BIT_SET(T& w , unsigned n)
|
||||
{
|
||||
w |= (T)BIT_MASK(n);
|
||||
}
|
||||
|
||||
template<typename T> void COPY_BIT(bool bit , T& w , unsigned n)
|
||||
{
|
||||
if (bit) {
|
||||
BIT_SET(w , n);
|
||||
} else {
|
||||
BIT_CLR(w , n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hp_1mb5_device::hp_1mb5_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig , HP_1MB5 , tag , owner , clock),
|
||||
m_irl_handler(*this),
|
||||
m_halt_handler(*this),
|
||||
m_reset_handler(*this),
|
||||
m_int_handler(*this)
|
||||
{
|
||||
}
|
||||
|
||||
READ8_MEMBER(hp_1mb5_device::cpu_r)
|
||||
{
|
||||
uint8_t res = 0;
|
||||
|
||||
switch (offset) {
|
||||
case 0:
|
||||
// Read SR
|
||||
res = m_sr & 0x7e;
|
||||
if (m_obf) {
|
||||
BIT_SET(res , 7);
|
||||
}
|
||||
if (m_ibf) {
|
||||
BIT_SET(res , 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Read IB
|
||||
res = m_ib;
|
||||
m_ibf = false;
|
||||
update_halt();
|
||||
break;
|
||||
}
|
||||
|
||||
//LOG("RD %u=%02x\n" , offset , res);
|
||||
return res;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(hp_1mb5_device::cpu_w)
|
||||
{
|
||||
//LOG("WR %u=%02x\n" , offset , data);
|
||||
bool need_resched = false;
|
||||
|
||||
switch (offset) {
|
||||
case 0:
|
||||
// Write CR
|
||||
m_cr = data;
|
||||
need_resched |= set_reset(BIT(m_cr , 7));
|
||||
need_resched |= set_int(!BIT(m_cr , 0));
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Write OB
|
||||
m_ob = data;
|
||||
m_obf = true;
|
||||
update_halt();
|
||||
break;
|
||||
}
|
||||
if (need_resched) {
|
||||
LOG("resched %s\n" , space.device().tag());
|
||||
space.device().execute().yield();
|
||||
}
|
||||
}
|
||||
|
||||
READ8_MEMBER(hp_1mb5_device::uc_r)
|
||||
{
|
||||
uint8_t res = 0;
|
||||
bool need_resched = false;
|
||||
|
||||
switch (offset) {
|
||||
case 0:
|
||||
// Read CR
|
||||
res = m_cr & 0x7e;
|
||||
if (m_obf) {
|
||||
BIT_SET(res , 7);
|
||||
}
|
||||
if (m_ibf) {
|
||||
BIT_SET(res , 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Read OB
|
||||
res = m_ob;
|
||||
m_obf = false;
|
||||
need_resched |= update_halt();
|
||||
break;
|
||||
}
|
||||
|
||||
if (need_resched) {
|
||||
LOG("resched %s\n" , space.device().tag());
|
||||
space.device().execute().spin();
|
||||
}
|
||||
//LOG("RDU %u=%02x\n" , offset , res);
|
||||
return res;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(hp_1mb5_device::uc_w)
|
||||
{
|
||||
//LOG("WRU %u=%02x SR=%02x\n" , offset , data , m_sr);
|
||||
bool need_resched = false;
|
||||
|
||||
switch (offset) {
|
||||
case 0:
|
||||
// Write SR
|
||||
if (!BIT(m_sr , 0) && BIT(data , 0)) {
|
||||
need_resched |= set_service(true);
|
||||
}
|
||||
m_sr = data;
|
||||
m_hlten = BIT(m_sr , 7);
|
||||
if (update_halt() && !m_halt) {
|
||||
need_resched = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Write IB
|
||||
m_ib = data;
|
||||
m_ibf = true;
|
||||
need_resched |= update_halt();
|
||||
break;
|
||||
}
|
||||
if (need_resched) {
|
||||
LOG("resched %s\n" , space.device().tag());
|
||||
space.device().execute().spin();
|
||||
}
|
||||
}
|
||||
|
||||
READ_LINE_MEMBER(hp_1mb5_device::irl_r)
|
||||
{
|
||||
return m_service;
|
||||
}
|
||||
|
||||
READ_LINE_MEMBER(hp_1mb5_device::halt_r)
|
||||
{
|
||||
return m_halt;
|
||||
}
|
||||
|
||||
READ_LINE_MEMBER(hp_1mb5_device::reset_r)
|
||||
{
|
||||
return m_reset;
|
||||
}
|
||||
|
||||
READ_LINE_MEMBER(hp_1mb5_device::int_r)
|
||||
{
|
||||
return m_cint;
|
||||
}
|
||||
|
||||
void hp_1mb5_device::inten()
|
||||
{
|
||||
// Enabling interrupts (i.e. writing to 0xff40) removes uC reset
|
||||
set_reset(false);
|
||||
}
|
||||
|
||||
void hp_1mb5_device::clear_service()
|
||||
{
|
||||
set_service(false);
|
||||
}
|
||||
|
||||
void hp_1mb5_device::device_start()
|
||||
{
|
||||
m_irl_handler.resolve_safe();
|
||||
m_halt_handler.resolve_safe();
|
||||
m_reset_handler.resolve_safe();
|
||||
m_int_handler.resolve_safe();
|
||||
|
||||
save_item(NAME(m_sr));
|
||||
save_item(NAME(m_cr));
|
||||
save_item(NAME(m_ib));
|
||||
save_item(NAME(m_ob));
|
||||
save_item(NAME(m_ibf));
|
||||
save_item(NAME(m_obf));
|
||||
save_item(NAME(m_hlten));
|
||||
save_item(NAME(m_service));
|
||||
save_item(NAME(m_cint));
|
||||
save_item(NAME(m_reset));
|
||||
save_item(NAME(m_halt));
|
||||
}
|
||||
|
||||
void hp_1mb5_device::device_reset()
|
||||
{
|
||||
m_sr = 0;
|
||||
m_cr = 0;
|
||||
m_ib = 0;
|
||||
m_ob = 0;
|
||||
m_ibf = false;
|
||||
m_obf = false;
|
||||
m_hlten = false;
|
||||
m_service = false;
|
||||
m_cint = true;
|
||||
m_reset = true;
|
||||
m_halt = false;
|
||||
|
||||
m_irl_handler(false);
|
||||
m_halt_handler(false);
|
||||
m_reset_handler(true);
|
||||
m_int_handler(true);
|
||||
}
|
||||
|
||||
bool hp_1mb5_device::set_service(bool new_service)
|
||||
{
|
||||
if (new_service != m_service) {
|
||||
m_service = new_service;
|
||||
//LOG("irl=%d\n" , m_service);
|
||||
m_irl_handler(m_service);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool hp_1mb5_device::update_halt()
|
||||
{
|
||||
bool new_halt = m_hlten && m_obf && !m_ibf;
|
||||
if (new_halt != m_halt) {
|
||||
//LOG("HALT=%d\n" , new_halt);
|
||||
m_halt = new_halt;
|
||||
m_halt_handler(m_halt);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool hp_1mb5_device::set_reset(bool new_reset)
|
||||
{
|
||||
if (new_reset != m_reset) {
|
||||
m_reset = new_reset;
|
||||
m_reset_handler(m_reset);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool hp_1mb5_device::set_int(bool new_int)
|
||||
{
|
||||
if (new_int != m_cint) {
|
||||
m_cint = new_int;
|
||||
LOG("cint=%d\n" , m_cint);
|
||||
m_int_handler(m_cint);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
95
src/devices/machine/1mb5.h
Normal file
95
src/devices/machine/1mb5.h
Normal file
@ -0,0 +1,95 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:F. Ulivi
|
||||
/*********************************************************************
|
||||
|
||||
1mb5.h
|
||||
|
||||
HP-8x I/O Translator chip (1MB5-0101)
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef MAME_MACHINE_1MB5_H
|
||||
#define MAME_MACHINE_1MB5_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#define MCFG_1MB5_IRL_HANDLER(_devcb) \
|
||||
devcb = &hp_1mb5_device::set_irl_handler(*device , DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_1MB5_HALT_HANDLER(_devcb) \
|
||||
devcb = &hp_1mb5_device::set_halt_handler(*device , DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_1MB5_RESET_HANDLER(_devcb) \
|
||||
devcb = &hp_1mb5_device::set_reset_handler(*device , DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_1MB5_INT_HANDLER(_devcb) \
|
||||
devcb = &hp_1mb5_device::set_int_handler(*device , DEVCB_##_devcb);
|
||||
|
||||
class hp_1mb5_device : public device_t
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
hp_1mb5_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
// static configuration helpers
|
||||
template <class Object> static devcb_base &set_irl_handler(device_t &device, Object &&cb) { return downcast<hp_1mb5_device &>(device).m_irl_handler.set_callback(std::forward<Object>(cb)); }
|
||||
template <class Object> static devcb_base &set_halt_handler(device_t &device, Object &&cb) { return downcast<hp_1mb5_device &>(device).m_halt_handler.set_callback(std::forward<Object>(cb)); }
|
||||
template <class Object> static devcb_base &set_reset_handler(device_t &device, Object &&cb) { return downcast<hp_1mb5_device &>(device).m_reset_handler.set_callback(std::forward<Object>(cb)); }
|
||||
template <class Object> static devcb_base &set_int_handler(device_t &device, Object &&cb) { return downcast<hp_1mb5_device &>(device).m_int_handler.set_callback(std::forward<Object>(cb)); }
|
||||
|
||||
// CPU access
|
||||
DECLARE_READ8_MEMBER(cpu_r);
|
||||
DECLARE_WRITE8_MEMBER(cpu_w);
|
||||
|
||||
// uC access
|
||||
DECLARE_READ8_MEMBER(uc_r);
|
||||
DECLARE_WRITE8_MEMBER(uc_w);
|
||||
|
||||
// Signals to CPU
|
||||
DECLARE_READ_LINE_MEMBER(irl_r);
|
||||
DECLARE_READ_LINE_MEMBER(halt_r);
|
||||
|
||||
// Signals to uC
|
||||
DECLARE_READ_LINE_MEMBER(reset_r);
|
||||
DECLARE_READ_LINE_MEMBER(int_r);
|
||||
|
||||
// Interrupt enable
|
||||
void inten();
|
||||
|
||||
// Interrupt clearing
|
||||
void clear_service();
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
private:
|
||||
devcb_write_line m_irl_handler;
|
||||
devcb_write_line m_halt_handler;
|
||||
devcb_write_line m_reset_handler;
|
||||
devcb_write_line m_int_handler;
|
||||
|
||||
// Registers
|
||||
uint8_t m_sr;
|
||||
uint8_t m_cr;
|
||||
uint8_t m_ib;
|
||||
uint8_t m_ob;
|
||||
bool m_ibf;
|
||||
bool m_obf;
|
||||
bool m_hlten;
|
||||
bool m_service;
|
||||
bool m_cint;
|
||||
bool m_reset;
|
||||
bool m_halt;
|
||||
|
||||
bool set_service(bool new_service);
|
||||
bool update_halt();
|
||||
bool set_reset(bool new_reset);
|
||||
bool set_int(bool new_int);
|
||||
};
|
||||
|
||||
// device type definition
|
||||
DECLARE_DEVICE_TYPE(HP_1MB5, hp_1mb5_device)
|
||||
|
||||
#endif /* MAME_MACHINE_1MB5_H */
|
@ -1246,7 +1246,7 @@ bool phi_device::if_cmd_received(uint8_t byte)
|
||||
}
|
||||
} else {
|
||||
// command is a secondary address
|
||||
if (m_t_state == PHI_T_ID1 && my_addr) {
|
||||
if (m_t_state == PHI_T_ID1 && (m_l_state == PHI_L_LADS) == !!lon_msg() && my_addr) {
|
||||
// Start IDENTIFY sequence
|
||||
m_t_state = PHI_T_ID2;
|
||||
} else if (m_t_state >= PHI_T_ID2 && m_t_state <= PHI_T_ID6 && !my_addr) {
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "bus/hp80_optroms/hp80_optrom.h"
|
||||
#include "softlist.h"
|
||||
#include "machine/bankdev.h"
|
||||
#include "bus/hp80_io/hp80_io.h"
|
||||
|
||||
// Debugging
|
||||
#define VERBOSE 1
|
||||
@ -72,7 +73,8 @@ static constexpr unsigned IRQ_KEYBOARD_BIT = 0;
|
||||
static constexpr unsigned IRQ_TIMER0_BIT = 1;
|
||||
static constexpr unsigned TIMER_COUNT = 4;
|
||||
static constexpr unsigned IRQ_IOP0_BIT = IRQ_TIMER0_BIT + TIMER_COUNT;
|
||||
static constexpr unsigned IOP_COUNT = 0;
|
||||
// Maximum count of I/O processors (the same thing as count of I/O slots)
|
||||
static constexpr unsigned IOP_COUNT = 4;
|
||||
static constexpr unsigned IRQ_BIT_COUNT = IRQ_IOP0_BIT + IOP_COUNT;
|
||||
static constexpr unsigned NO_IRQ = IRQ_BIT_COUNT;
|
||||
|
||||
@ -105,11 +107,17 @@ public:
|
||||
DECLARE_READ8_MEMBER(clkdat_r);
|
||||
DECLARE_WRITE8_MEMBER(clkdat_w);
|
||||
DECLARE_WRITE8_MEMBER(rselec_w);
|
||||
DECLARE_READ8_MEMBER(intrsc_r);
|
||||
DECLARE_WRITE8_MEMBER(intrsc_w);
|
||||
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(kb_scan);
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(vm_timer);
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(timer_update);
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(clk_busy_timer);
|
||||
|
||||
DECLARE_WRITE8_MEMBER(irl_w);
|
||||
DECLARE_WRITE8_MEMBER(halt_w);
|
||||
|
||||
protected:
|
||||
required_device<capricorn_cpu_device> m_cpu;
|
||||
required_device<screen_device> m_screen;
|
||||
@ -124,6 +132,7 @@ protected:
|
||||
required_ioport m_io_modkeys;
|
||||
required_device_array<hp80_optrom_slot_device , 6> m_rom_drawers;
|
||||
required_device<address_map_bank_device> m_rombank;
|
||||
required_device_array<hp80_io_slot_device , IOP_COUNT> m_io_slots;
|
||||
|
||||
// Character generator
|
||||
required_region_ptr<uint8_t> m_chargen;
|
||||
@ -137,11 +146,11 @@ protected:
|
||||
uint8_t m_crt_read_byte;
|
||||
uint8_t m_crt_write_byte;
|
||||
bool m_global_int_en;
|
||||
uint16_t m_int_req;
|
||||
uint16_t m_int_serv;
|
||||
unsigned m_top_pending;
|
||||
uint16_t m_int_acked;
|
||||
uint16_t m_int_en;
|
||||
uint8_t m_halt_lines;
|
||||
|
||||
// State of keyboard
|
||||
ioport_value m_kb_state[ 3 ];
|
||||
@ -192,6 +201,7 @@ hp85_state::hp85_state(const machine_config &mconfig, device_type type, const ch
|
||||
m_io_modkeys(*this, "MODKEYS"),
|
||||
m_rom_drawers(*this , "drawer%u" , 1),
|
||||
m_rombank(*this , "rombank"),
|
||||
m_io_slots(*this , "slot%u" , 1),
|
||||
m_chargen(*this , "chargen")
|
||||
{
|
||||
}
|
||||
@ -210,7 +220,6 @@ void hp85_state::machine_reset()
|
||||
m_crt_ctl = BIT_MASK(CRT_CTL_POWERDN_BIT) | BIT_MASK(CRT_CTL_WIPEOUT_BIT);
|
||||
m_crt_read_byte = 0;
|
||||
m_crt_write_byte = 0;
|
||||
m_int_req = 0;
|
||||
m_int_serv = 0;
|
||||
m_top_pending = NO_IRQ;
|
||||
m_int_acked = 0;
|
||||
@ -235,6 +244,8 @@ void hp85_state::machine_reset()
|
||||
m_timer_idx = 0;
|
||||
m_clk_busy = false;
|
||||
update_irl();
|
||||
m_halt_lines = 0;
|
||||
m_cpu->set_input_line(INPUT_LINE_HALT , CLEAR_LINE);
|
||||
|
||||
// Load optional ROMs (if any)
|
||||
// All entries in rombanks [01..FF] initially not present
|
||||
@ -245,6 +256,12 @@ void hp85_state::machine_reset()
|
||||
}
|
||||
// Clear RSELEC
|
||||
m_rombank->set_bank(0xff);
|
||||
|
||||
// Mount I/O slots in address space
|
||||
m_cpu->space(AS_PROGRAM).unmap_readwrite(0xff50 , 0xff5f);
|
||||
for (auto& io : m_io_slots) {
|
||||
io->install_read_write_handlers(m_cpu->space(AS_PROGRAM));
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t hp85_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
@ -307,13 +324,24 @@ static const uint8_t vector_table[] = {
|
||||
0x08, // Timer 0
|
||||
0x0a, // Timer 1
|
||||
0x0c, // Timer 2
|
||||
0x0e // Timer 3
|
||||
0x0e, // Timer 3
|
||||
0x10, // Slot 1
|
||||
0x10, // Slot 2
|
||||
0x10, // Slot 3
|
||||
0x10 // Slot 4
|
||||
};
|
||||
|
||||
IRQ_CALLBACK_MEMBER(hp85_state::irq_callback)
|
||||
{
|
||||
logerror("IRQ ACK %u\n" , m_top_pending);
|
||||
BIT_SET(m_int_acked , m_top_pending);
|
||||
if (m_top_pending > IRQ_IOP0_BIT && m_top_pending < IRQ_BIT_COUNT) {
|
||||
// Interrupts are disabled in all I/O translators of higher priority than
|
||||
// the one being serviced
|
||||
for (unsigned i = m_top_pending - 1; i >= IRQ_IOP0_BIT; i--) {
|
||||
irq_en_w(i , false);
|
||||
}
|
||||
}
|
||||
update_irl();
|
||||
return vector_table[ m_top_pending ];
|
||||
}
|
||||
@ -539,6 +567,30 @@ WRITE8_MEMBER(hp85_state::rselec_w)
|
||||
m_rombank->set_bank(data);
|
||||
}
|
||||
|
||||
READ8_MEMBER(hp85_state::intrsc_r)
|
||||
{
|
||||
if (m_top_pending >= IRQ_IOP0_BIT && m_top_pending < IRQ_BIT_COUNT && BIT(m_int_acked , m_top_pending)) {
|
||||
return (uint8_t)m_io_slots[ m_top_pending - IRQ_IOP0_BIT ]->get_base_addr();
|
||||
} else {
|
||||
// Probably..
|
||||
return 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(hp85_state::intrsc_w)
|
||||
{
|
||||
if (m_top_pending >= IRQ_IOP0_BIT && m_top_pending < IRQ_BIT_COUNT && BIT(m_int_acked , m_top_pending)) {
|
||||
// Clear interrupt request in the slot being serviced
|
||||
m_io_slots[ m_top_pending - IRQ_IOP0_BIT ]->clear_service();
|
||||
}
|
||||
for (auto& iop: m_io_slots) {
|
||||
iop->inten();
|
||||
}
|
||||
for (unsigned i = IRQ_IOP0_BIT; i < (IRQ_IOP0_BIT + IOP_COUNT); i++) {
|
||||
irq_en_w(i , true);
|
||||
}
|
||||
}
|
||||
|
||||
// Outer index: key position [0..79] = r * 8 + c
|
||||
// Inner index: SHIFT state (0 = no SHIFT, 1 = SHIFT)
|
||||
static const uint8_t keyboard_table[ 80 ][ 2 ] = {
|
||||
@ -790,6 +842,24 @@ TIMER_DEVICE_CALLBACK_MEMBER(hp85_state::clk_busy_timer)
|
||||
m_clk_busy = false;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(hp85_state::irl_w)
|
||||
{
|
||||
//LOG("irl_w %u=%u\n" , offset , data);
|
||||
irq_w(offset + IRQ_IOP0_BIT , data != 0);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(hp85_state::halt_w)
|
||||
{
|
||||
//LOG("halt_w %u=%u\n" , offset , data);
|
||||
bool prev_halt = m_halt_lines != 0;
|
||||
COPY_BIT(data != 0 , m_halt_lines , offset);
|
||||
bool new_halt = m_halt_lines != 0;
|
||||
if (prev_halt != new_halt) {
|
||||
LOG("halt=%d hl=%x\n" , new_halt , m_halt_lines);
|
||||
m_cpu->set_input_line(INPUT_LINE_HALT , new_halt);
|
||||
}
|
||||
}
|
||||
|
||||
attotime hp85_state::time_to_video_mem_availability() const
|
||||
{
|
||||
if (BIT(m_crt_ctl , CRT_CTL_WIPEOUT_BIT) || BIT(m_crt_ctl , CRT_CTL_POWERDN_BIT)) {
|
||||
@ -880,6 +950,7 @@ void hp85_state::video_mem_write()
|
||||
|
||||
void hp85_state::irq_w(unsigned n_irq , bool state)
|
||||
{
|
||||
//LOG("irq_w %u=%d GIE=%d SRV=%03x ACK=%03x IE=%03x\n" , n_irq , state , m_global_int_en , m_int_serv , m_int_acked , m_int_en);
|
||||
if (state && !BIT(m_int_serv , n_irq)) {
|
||||
// Set service request
|
||||
BIT_SET(m_int_serv , n_irq);
|
||||
@ -908,6 +979,7 @@ void hp85_state::update_int_bits()
|
||||
|
||||
void hp85_state::update_irl()
|
||||
{
|
||||
//LOG("irl GIE=%d top=%u ACK=%03x\n" , m_global_int_en , m_top_pending , m_int_acked);
|
||||
m_cpu->set_input_line(0 , m_global_int_en && m_top_pending < IRQ_BIT_COUNT && !BIT(m_int_acked , m_top_pending));
|
||||
}
|
||||
|
||||
@ -1024,6 +1096,7 @@ static ADDRESS_MAP_START(cpu_mem_map , AS_PROGRAM , 8 , hp85_state)
|
||||
AM_RANGE(0xff0a , 0xff0a) AM_READWRITE(clksts_r , clksts_w)
|
||||
AM_RANGE(0xff0b , 0xff0b) AM_READWRITE(clkdat_r , clkdat_w)
|
||||
AM_RANGE(0xff18 , 0xff18) AM_WRITE(rselec_w)
|
||||
AM_RANGE(0xff40 , 0xff40) AM_READWRITE(intrsc_r , intrsc_w)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static ADDRESS_MAP_START(rombank_mem_map , AS_PROGRAM , 8 , hp85_state)
|
||||
@ -1042,7 +1115,7 @@ static MACHINE_CONFIG_START(hp85)
|
||||
MCFG_ADDRESS_MAP_BANK_ENDIANNESS(ENDIANNESS_LITTLE)
|
||||
MCFG_ADDRESS_MAP_BANK_DATABUS_WIDTH(8)
|
||||
MCFG_ADDRESS_MAP_BANK_ADDRBUS_WIDTH(21)
|
||||
MCFG_ADDRESS_MAP_BANK_STRIDE(0x2000)
|
||||
MCFG_ADDRESS_MAP_BANK_STRIDE(HP80_OPTROM_SIZE)
|
||||
|
||||
MCFG_SCREEN_ADD("screen" , RASTER)
|
||||
MCFG_SCREEN_RAW_PARAMS(MASTER_CLOCK / 2 , 312 , 0 , 256 , 256 , 0 , 192)
|
||||
@ -1085,6 +1158,20 @@ static MACHINE_CONFIG_START(hp85)
|
||||
MCFG_DEVICE_ADD("drawer6", HP80_OPTROM_SLOT, 0)
|
||||
MCFG_DEVICE_SLOT_INTERFACE(hp80_optrom_slot_device, NULL, false)
|
||||
|
||||
// I/O slots
|
||||
MCFG_HP80_IO_SLOT_ADD("slot1" , 0)
|
||||
MCFG_HP80_IO_IRL_CB(WRITE8(hp85_state , irl_w))
|
||||
MCFG_HP80_IO_HALT_CB(WRITE8(hp85_state , halt_w))
|
||||
MCFG_HP80_IO_SLOT_ADD("slot2" , 1)
|
||||
MCFG_HP80_IO_IRL_CB(WRITE8(hp85_state , irl_w))
|
||||
MCFG_HP80_IO_HALT_CB(WRITE8(hp85_state , halt_w))
|
||||
MCFG_HP80_IO_SLOT_ADD("slot3" , 2)
|
||||
MCFG_HP80_IO_IRL_CB(WRITE8(hp85_state , irl_w))
|
||||
MCFG_HP80_IO_HALT_CB(WRITE8(hp85_state , halt_w))
|
||||
MCFG_HP80_IO_SLOT_ADD("slot4" , 3)
|
||||
MCFG_HP80_IO_IRL_CB(WRITE8(hp85_state , irl_w))
|
||||
MCFG_HP80_IO_HALT_CB(WRITE8(hp85_state , halt_w))
|
||||
|
||||
MCFG_SOFTWARE_LIST_ADD("optrom_list" , "hp85_rom")
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user