Merge pull request #1926 from fulivi/hp9845_dev9

HP9895 dual-floppy drive (WIP)
This commit is contained in:
R. Belmont 2017-01-05 15:07:40 -05:00 committed by GitHub
commit 4cd61d1c72
10 changed files with 1993 additions and 0 deletions

View file

@ -761,6 +761,8 @@ if (BUSES["IEEE488"]~=null) then
MAME_DIR .. "src/devices/bus/ieee488/hardbox.h",
MAME_DIR .. "src/devices/bus/ieee488/shark.cpp",
MAME_DIR .. "src/devices/bus/ieee488/shark.h",
MAME_DIR .. "src/devices/bus/ieee488/hp9895.cpp",
MAME_DIR .. "src/devices/bus/ieee488/hp9895.h",
}
end

View file

@ -1928,6 +1928,18 @@ if (MACHINES["PCKEYBRD"]~=null) then
}
end
---------------------------------------------------
--
--@src/devices/machine/phi.h,MACHINES["PHI"] = true
---------------------------------------------------
if (MACHINES["PHI"]~=null) then
files {
MAME_DIR .. "src/devices/machine/phi.cpp",
MAME_DIR .. "src/devices/machine/phi.h",
}
end
---------------------------------------------------
--
--@src/devices/machine/pic8259.h,MACHINES["PIC8259"] = true

View file

@ -492,6 +492,7 @@ MACHINES["PCF8593"] = true
MACHINES["PCI"] = true
MACHINES["PCKEYBRD"] = true
MACHINES["PDC"] = true
MACHINES["PHI"] = true
MACHINES["PIC8259"] = true
MACHINES["PIT68230"] = true
MACHINES["PIT8253"] = true

View file

@ -132,6 +132,9 @@ READ16_MEMBER(hp98034_io_card::reg_r)
m_force_flg = true;
update_flg();
// PPU yields to let NP see FLG=0 immediately
// (horrible race conditions lurking...)
space.device().execute().yield();
LOG(("read R%u=%04x\n" , offset + 4 , res));
return res;
@ -152,6 +155,9 @@ WRITE16_MEMBER(hp98034_io_card::reg_w)
m_force_flg = true;
update_flg();
// PPU yields to let NP see FLG=0 immediately
// (horrible race conditions lurking...)
space.device().execute().yield();
LOG(("write R%u=%04x\n" , offset + 4 , data));
}
@ -356,6 +362,7 @@ static MACHINE_CONFIG_FRAGMENT(hp98034)
MCFG_HP_NANO_READ_DC_CB(READ8(hp98034_io_card , dc_r))
MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(hp98034_io_card , irq_callback)
MCFG_IEEE488_SLOT_ADD("ieee_dev" , 0 , hp_ieee488_devices , nullptr)
MCFG_IEEE488_BUS_ADD()
MCFG_IEEE488_IFC_CALLBACK(WRITELINE(hp98034_io_card , ieee488_ctrl_w))
MCFG_IEEE488_ATN_CALLBACK(WRITELINE(hp98034_io_card , ieee488_ctrl_w))

View file

@ -0,0 +1,208 @@
// license:BSD-3-Clause
// copyright-holders: F. Ulivi
/*********************************************************************
hp9895.cpp
HP9895 floppy disk drive
Reference manual:
HP 09895-90030, feb 81, 9895A Flexible Disc Memory Service Manual
*********************************************************************/
#include "hp9895.h"
// Debugging
#define VERBOSE 1
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
// device type definition
const device_type HP9895 = &device_creator<hp9895_device>;
hp9895_device::hp9895_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, HP9895, "HP9895", tag, owner, clock, "HP9895", __FILE__),
device_ieee488_interface(mconfig, *this),
m_cpu(*this , "cpu"),
m_phi(*this , "phi")
{
}
#if 0
ioport_constructor hp9895_device::device_input_ports() const
{
// TODO: inputs=HPIB address, "S" & "W" switches, "loop" pin
}
#endif
void hp9895_device::device_start()
{
}
void hp9895_device::device_reset()
{
m_cpu_irq = false;
}
void hp9895_device::ieee488_eoi(int state)
{
m_phi->eoi_w(state);
}
void hp9895_device::ieee488_dav(int state)
{
m_phi->dav_w(state);
}
void hp9895_device::ieee488_nrfd(int state)
{
m_phi->nrfd_w(state);
}
void hp9895_device::ieee488_ndac(int state)
{
m_phi->ndac_w(state);
}
void hp9895_device::ieee488_ifc(int state)
{
m_phi->ifc_w(state);
}
void hp9895_device::ieee488_srq(int state)
{
m_phi->srq_w(state);
}
void hp9895_device::ieee488_atn(int state)
{
m_phi->atn_w(state);
}
void hp9895_device::ieee488_ren(int state)
{
m_phi->ren_w(state);
}
WRITE_LINE_MEMBER(hp9895_device::phi_eoi_w)
{
m_bus->eoi_w(this , state);
}
WRITE_LINE_MEMBER(hp9895_device::phi_dav_w)
{
m_bus->dav_w(this , state);
}
WRITE_LINE_MEMBER(hp9895_device::phi_nrfd_w)
{
m_bus->nrfd_w(this , state);
}
WRITE_LINE_MEMBER(hp9895_device::phi_ndac_w)
{
m_bus->ndac_w(this , state);
}
WRITE_LINE_MEMBER(hp9895_device::phi_ifc_w)
{
m_bus->ifc_w(this , state);
}
WRITE_LINE_MEMBER(hp9895_device::phi_srq_w)
{
m_bus->srq_w(this , state);
}
WRITE_LINE_MEMBER(hp9895_device::phi_atn_w)
{
m_bus->atn_w(this , state);
}
WRITE_LINE_MEMBER(hp9895_device::phi_ren_w)
{
m_bus->ren_w(this , state);
}
READ8_MEMBER(hp9895_device::phi_dio_r)
{
return m_bus->dio_r();
}
WRITE8_MEMBER(hp9895_device::phi_dio_w)
{
m_bus->dio_w(this , data);
}
WRITE_LINE_MEMBER(hp9895_device::phi_int_w)
{
m_cpu->set_input_line(INPUT_LINE_NMI , state);
}
READ8_MEMBER(hp9895_device::phi_reg_r)
{
uint16_t reg = m_phi->reg16_r(space , offset , mem_mask);
// Reading D1=1 from a register sets the Z80 IRQ line
if (BIT(reg , 14) && !m_cpu_irq) {
m_cpu_irq = true;
m_cpu->set_input_line(INPUT_LINE_IRQ0 , ASSERT_LINE);
}
return (uint8_t)reg;
}
WRITE16_MEMBER(hp9895_device::z80_m1_w)
{
// Every M1 cycle of Z80 clears the IRQ line
if (m_cpu_irq) {
m_cpu_irq = false;
m_cpu->set_input_line(INPUT_LINE_IRQ0 , CLEAR_LINE);
}
}
ROM_START(hp9895)
ROM_REGION(0x2000 , "cpu" , 0)
ROM_LOAD("1818-1391a.bin" , 0 , 0x2000 , CRC(b50dbfb5) SHA1(96edf9af78be75fbad2a0245b8af43958ba32752))
ROM_END
static ADDRESS_MAP_START(z80_program_map , AS_PROGRAM , 8 , hp9895_device)
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x0000 , 0x1fff) AM_ROM AM_REGION("cpu" , 0)
AM_RANGE(0x6000 , 0x63ff) AM_RAM
ADDRESS_MAP_END
static ADDRESS_MAP_START(z80_io_map , AS_IO , 8 , hp9895_device)
ADDRESS_MAP_UNMAP_HIGH
ADDRESS_MAP_GLOBAL_MASK(0xff)
AM_RANGE(0x10 , 0x17) AM_DEVWRITE("phi" , phi_device , reg8_w) AM_READ(phi_reg_r)
// TODO: 60-67 range
ADDRESS_MAP_END
static MACHINE_CONFIG_FRAGMENT(hp9895)
MCFG_CPU_ADD("cpu" , Z80 , 4000000)
MCFG_CPU_PROGRAM_MAP(z80_program_map)
MCFG_CPU_IO_MAP(z80_io_map)
MCFG_Z80_SET_REFRESH_CALLBACK(WRITE16(hp9895_device , z80_m1_w))
MCFG_DEVICE_ADD("phi" , PHI , 0)
MCFG_PHI_EOI_WRITE_CB(WRITELINE(hp9895_device , phi_eoi_w))
MCFG_PHI_DAV_WRITE_CB(WRITELINE(hp9895_device , phi_dav_w))
MCFG_PHI_NRFD_WRITE_CB(WRITELINE(hp9895_device , phi_nrfd_w))
MCFG_PHI_NDAC_WRITE_CB(WRITELINE(hp9895_device , phi_ndac_w))
MCFG_PHI_IFC_WRITE_CB(WRITELINE(hp9895_device , phi_ifc_w))
MCFG_PHI_SRQ_WRITE_CB(WRITELINE(hp9895_device , phi_srq_w))
MCFG_PHI_ATN_WRITE_CB(WRITELINE(hp9895_device , phi_atn_w))
MCFG_PHI_REN_WRITE_CB(WRITELINE(hp9895_device , phi_ren_w))
MCFG_PHI_DIO_READWRITE_CB(READ8(hp9895_device , phi_dio_r) , WRITE8(hp9895_device , phi_dio_w))
MCFG_PHI_INT_WRITE_CB(WRITELINE(hp9895_device , phi_int_w))
MACHINE_CONFIG_END
const tiny_rom_entry *hp9895_device::device_rom_region() const
{
return ROM_NAME(hp9895);
}
machine_config_constructor hp9895_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME(hp9895);
}

View file

@ -0,0 +1,76 @@
// license:BSD-3-Clause
// copyright-holders: F. Ulivi
/*********************************************************************
hp9895.h
HP9895 floppy disk drive
*********************************************************************/
#pragma once
#ifndef _HP9895_H_
#define _HP9895_H_
#include "emu.h"
#include "ieee488.h"
#include "cpu/z80/z80.h"
#include "machine/phi.h"
class hp9895_device : public device_t,
public device_ieee488_interface
{
public:
// construction/destruction
hp9895_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
//virtual ioport_constructor device_input_ports() const override;
virtual void device_start() override;
virtual void device_reset() override;
virtual const tiny_rom_entry *device_rom_region() const override;
virtual machine_config_constructor device_mconfig_additions() const override;
// device_ieee488_interface overrides
virtual void ieee488_eoi(int state) override;
virtual void ieee488_dav(int state) override;
virtual void ieee488_nrfd(int state) override;
virtual void ieee488_ndac(int state) override;
virtual void ieee488_ifc(int state) override;
virtual void ieee488_srq(int state) override;
virtual void ieee488_atn(int state) override;
virtual void ieee488_ren(int state) override;
// PHI write CBs
DECLARE_WRITE_LINE_MEMBER(phi_eoi_w);
DECLARE_WRITE_LINE_MEMBER(phi_dav_w);
DECLARE_WRITE_LINE_MEMBER(phi_nrfd_w);
DECLARE_WRITE_LINE_MEMBER(phi_ndac_w);
DECLARE_WRITE_LINE_MEMBER(phi_ifc_w);
DECLARE_WRITE_LINE_MEMBER(phi_srq_w);
DECLARE_WRITE_LINE_MEMBER(phi_atn_w);
DECLARE_WRITE_LINE_MEMBER(phi_ren_w);
// PHI DIO r/w CBs
DECLARE_READ8_MEMBER(phi_dio_r);
DECLARE_WRITE8_MEMBER(phi_dio_w);
// PHI IRQ/Z80 NMI
DECLARE_WRITE_LINE_MEMBER(phi_int_w);
// PHI register read & Z80 IRQ
DECLARE_READ8_MEMBER(phi_reg_r);
DECLARE_WRITE16_MEMBER(z80_m1_w);
private:
required_device<z80_device> m_cpu;
required_device<phi_device> m_phi;
bool m_cpu_irq;
};
// device type definition
extern const device_type HP9895;
#endif /* _HP9895_H_ */

View file

@ -397,3 +397,14 @@ SLOT_INTERFACE_START( cbm_ieee488_devices )
SLOT_INTERFACE("shark", SHARK)
SLOT_INTERFACE("c4023", C4023)
SLOT_INTERFACE_END
//-------------------------------------------------
// SLOT_INTERFACE( hp_ieee488_devices )
//-------------------------------------------------
// slot devices
#include "hp9895.h"
SLOT_INTERFACE_START(hp_ieee488_devices)
SLOT_INTERFACE("hp9895", HP9895)
SLOT_INTERFACE_END

View file

@ -247,6 +247,7 @@ extern const device_type IEEE488_SLOT;
SLOT_INTERFACE_EXTERN( cbm_ieee488_devices );
SLOT_INTERFACE_EXTERN( hp_ieee488_devices );

1384
src/devices/machine/phi.cpp Normal file

File diff suppressed because it is too large Load diff

291
src/devices/machine/phi.h Normal file
View file

@ -0,0 +1,291 @@
// license:BSD-3-Clause
// copyright-holders:F. Ulivi
/*********************************************************************
phi.h
HP PHI (Processor-to-Hpib-Interface) (1AA6-6x04)
*********************************************************************/
#ifndef _PHI_H_
#define _PHI_H_
// Set read and write callbacks to access DIO bus on IEEE-488
#define MCFG_PHI_DIO_READWRITE_CB(_read , _write) \
phi_device::set_dio_read_cb(*device , DEVCB_##_read); \
phi_device::set_dio_write_cb(*device , DEVCB_##_write);
// Set write callbacks to access uniline signals on IEEE-488
#define MCFG_PHI_EOI_WRITE_CB(_write) \
phi_device::set_488_signal_write_cb(*device , phi_device::PHI_488_EOI , DEVCB_##_write);
#define MCFG_PHI_DAV_WRITE_CB(_write) \
phi_device::set_488_signal_write_cb(*device , phi_device::PHI_488_DAV , DEVCB_##_write);
#define MCFG_PHI_NRFD_WRITE_CB(_write) \
phi_device::set_488_signal_write_cb(*device , phi_device::PHI_488_NRFD , DEVCB_##_write);
#define MCFG_PHI_NDAC_WRITE_CB(_write) \
phi_device::set_488_signal_write_cb(*device , phi_device::PHI_488_NDAC , DEVCB_##_write);
#define MCFG_PHI_IFC_WRITE_CB(_write) \
phi_device::set_488_signal_write_cb(*device , phi_device::PHI_488_IFC , DEVCB_##_write);
#define MCFG_PHI_SRQ_WRITE_CB(_write) \
phi_device::set_488_signal_write_cb(*device , phi_device::PHI_488_SRQ , DEVCB_##_write);
#define MCFG_PHI_ATN_WRITE_CB(_write) \
phi_device::set_488_signal_write_cb(*device , phi_device::PHI_488_ATN , DEVCB_##_write);
#define MCFG_PHI_REN_WRITE_CB(_write) \
phi_device::set_488_signal_write_cb(*device , phi_device::PHI_488_REN , DEVCB_##_write);
// Set write callback for INT signal
#define MCFG_PHI_INT_WRITE_CB(_write) \
phi_device::set_int_write_cb(*device , DEVCB_##_write);
// Set write callback for DMARQ signal
#define MCFG_PHI_DMARQ_WRITE_CB(_write) \
phi_device::set_dmarq_write_cb(*device , DEVCB_##_write);
// Depth of inbound/outbound FIFOs
#define PHI_FIFO_SIZE 8
class phi_device : public device_t
{
public:
// construction/destruction
phi_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname);
phi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// See ieee488.h
typedef enum {
PHI_488_EOI,
PHI_488_DAV,
PHI_488_NRFD,
PHI_488_NDAC,
PHI_488_IFC,
PHI_488_SRQ,
PHI_488_ATN,
PHI_488_REN,
PHI_488_SIGNAL_COUNT
} phi_488_signal_t;
template<class _Object> static devcb_base& set_dio_read_cb(device_t &device , _Object object)
{ return downcast<phi_device&>(device).m_dio_read_func.set_callback(object); }
template<class _Object> static devcb_base& set_dio_write_cb(device_t &device , _Object object)
{ return downcast<phi_device&>(device).m_dio_write_func.set_callback(object); }
template<class _Object> static devcb_base& set_488_signal_write_cb(device_t &device , phi_488_signal_t signal , _Object object)
{ return downcast<phi_device&>(device).m_signal_wr_fns[ signal ].set_callback(object); }
template<class _Object> static devcb_base& set_int_write_cb(device_t &device , _Object object)
{ return downcast<phi_device&>(device).m_int_write_func.set_callback(object); }
template<class _Object> static devcb_base& set_dmarq_write_cb(device_t &device , _Object object)
{ return downcast<phi_device&>(device).m_dmarq_write_func.set_callback(object); }
DECLARE_WRITE_LINE_MEMBER(eoi_w);
DECLARE_WRITE_LINE_MEMBER(dav_w);
DECLARE_WRITE_LINE_MEMBER(nrfd_w);
DECLARE_WRITE_LINE_MEMBER(ndac_w);
DECLARE_WRITE_LINE_MEMBER(ifc_w);
DECLARE_WRITE_LINE_MEMBER(srq_w);
DECLARE_WRITE_LINE_MEMBER(atn_w);
DECLARE_WRITE_LINE_MEMBER(ren_w);
void set_ext_signal(phi_488_signal_t signal , int state);
// Register read/write
// Mapping of PHI register bits:
// Reg. bit PHI bit
// =================
// 15 0
// 14 1
// 13 =0=
// 12 =0=
// 11 =0=
// 10 =0=
// 9 =0=
// 8 =0=
// 7 8
// 6 9
// 5 10
// 4 11
// 3 12
// 2 13
// 1 14
// 0 15
DECLARE_WRITE16_MEMBER(reg16_w);
DECLARE_READ16_MEMBER(reg16_r);
DECLARE_WRITE8_MEMBER(reg8_w);
DECLARE_READ8_MEMBER(reg8_r);
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
private:
devcb_read8 m_dio_read_func;
devcb_write8 m_dio_write_func;
devcb_write_line m_signal_wr_fns[ PHI_488_SIGNAL_COUNT ];
devcb_write_line m_int_write_func;
devcb_write_line m_dmarq_write_func;
bool m_int_line;
bool m_dmarq_line;
// Internal copy of bus signals
// These signals have the "right" polarity (i.e. the opposite of bus signals, 1=L)
uint8_t m_dio;
bool m_signals[ PHI_488_SIGNAL_COUNT ];
bool m_ext_signals[ PHI_488_SIGNAL_COUNT ];
bool m_no_recursion;
bool m_sys_controller;
bool m_loopback;
bool m_id_enabled;
// SH (Source Handshake) states
enum {
PHI_SH_SIDS, // & SIWS
PHI_SH_SGNS, // & SWNS
PHI_SH_SDYS,
PHI_SH_STRS
};
int m_sh_state;
// AH (Acceptor Handshake) states
enum {
PHI_AH_AIDS,
PHI_AH_ANRS,
PHI_AH_ACRS,
PHI_AH_ACDS,
PHI_AH_ACDS_FROZEN, // Non-standard state: IF CMD rejected because of even parity
PHI_AH_AWNS
};
int m_ah_state;
// T (Talker) states
enum {
PHI_T_TIDS,
PHI_T_TADS,
PHI_T_SPAS,
PHI_T_TACS,
// The following are non-standard states for IDENTIFY sequencing
PHI_T_ID1, // Untalked
PHI_T_ID2, // Addressed by secondary address
PHI_T_ID3, // Sending 1st byte
PHI_T_ID4, // Waiting to send 2nd byte
PHI_T_ID5, // Sending 2nd byte
PHI_T_ID6 // 2nd byte sent, end of sequence
};
int m_t_state;
bool m_t_spms; // False: SPIS, true: SPMS
// L (Listener) states
enum {
PHI_L_LIDS,
PHI_L_LADS,
PHI_L_LACS
};
int m_l_state;
// SR (Service Request) states
enum {
PHI_SR_NPRS,
PHI_SR_SRQS,
PHI_SR_APRS
};
int m_sr_state;
// PP (Parallel poll) states
enum {
PHI_PP_PPIS,
PHI_PP_PPSS,
PHI_PP_PPAS
};
int m_pp_state;
bool m_pp_pacs;
uint8_t m_ppr_msg;
bool m_s_sense;
// C (Controller) states
enum {
PHI_C_CIDS,
PHI_C_CADS,
PHI_C_CACS,
PHI_C_CPWS,
PHI_C_CPPS,
PHI_C_CSBS,
PHI_C_CSHS,
PHI_C_CAWS,
PHI_C_CTRS,
PHI_C_CSWS
};
int m_c_state;
uint8_t m_be_counter;
uint16_t m_reg_status;
uint16_t m_reg_int_cond;
uint16_t m_reg_int_mask;
uint16_t m_reg_1st_id;
uint16_t m_reg_2nd_id;
uint16_t m_reg_control;
uint16_t m_reg_address;
util::fifo<uint16_t , PHI_FIFO_SIZE> m_fifo_in;
util::fifo<uint16_t , PHI_FIFO_SIZE> m_fifo_out;
typedef enum {
NBA_NONE,
NBA_CMD_FROM_OFIFO,
NBA_BYTE_FROM_OFIFO,
NBA_FROM_SPAS,
NBA_FROM_ID3,
NBA_FROM_ID5
} nba_origin_t;
int m_nba_origin;
// Timers
emu_timer *m_sh_dly_timer;
emu_timer *m_c_dly_timer;
void int_reg_w(offs_t offset , uint16_t data);
uint8_t get_dio(void);
void set_dio(uint8_t data);
bool get_signal(phi_488_signal_t signal);
void set_signal(phi_488_signal_t signal , bool state);
void pon_msg(void);
void update_488(void);
void update_fsm(void);
nba_origin_t nba_msg(uint8_t& new_byte , bool& new_eoi) const;
void clear_nba(nba_origin_t origin);
bool if_cmd_received(uint8_t byte);
bool byte_received(uint8_t byte , bool eoi);
bool ton_msg(void) const;
bool lon_msg(void) const;
bool odd_parity(uint8_t byte) const;
uint8_t my_address(void) const;
bool tcs_msg(void) const;
bool rpp_msg(void) const;
bool controller_in_charge(void) const;
};
// device type definition
extern const device_type PHI;
#endif /* _PHI_H_ */