mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
hp64k: added support for HPIB bus. Extensive improvement of PHI emulation.
This commit is contained in:
parent
81a35fb46e
commit
01e86e4cec
@ -899,6 +899,7 @@ MACHINE_CONFIG_START(hp9895_device::device_add_mconfig)
|
||||
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))
|
||||
MCFG_PHI_SYS_CNTRL_READ_CB(GND)
|
||||
|
||||
MCFG_FLOPPY_DRIVE_ADD("floppy0" , hp9895_floppies , "8dsdd" , hp9895_floppy_formats)
|
||||
MCFG_SLOT_FIXED(true)
|
||||
|
@ -112,6 +112,7 @@ ieee488_device::ieee488_device(const machine_config &mconfig, const char *tag, d
|
||||
m_write_srq(*this),
|
||||
m_write_atn(*this),
|
||||
m_write_ren(*this),
|
||||
m_write_dio(*this),
|
||||
m_dio(0xff)
|
||||
{
|
||||
for (auto & elem : m_line)
|
||||
@ -136,6 +137,7 @@ void ieee488_device::device_start()
|
||||
m_write_srq.resolve_safe();
|
||||
m_write_atn.resolve_safe();
|
||||
m_write_ren.resolve_safe();
|
||||
m_write_dio.resolve_safe();
|
||||
}
|
||||
|
||||
|
||||
@ -320,11 +322,16 @@ int ieee488_device::get_signal(int signal)
|
||||
|
||||
void ieee488_device::set_data(device_t *device, uint8_t data)
|
||||
{
|
||||
bool changed = false;
|
||||
uint8_t old_state = get_data();
|
||||
|
||||
if (device == this)
|
||||
{
|
||||
if (LOG) logerror("%s IEEE488: '%s' DIO %02x\n", machine().describe_context(), tag(), data);
|
||||
|
||||
m_dio = data;
|
||||
if (m_dio != data) {
|
||||
m_dio = data;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -338,12 +345,22 @@ void ieee488_device::set_data(device_t *device, uint8_t data)
|
||||
{
|
||||
if (LOG) logerror("%s IEEE488: '%s' DIO %02x\n", machine().describe_context(), device->tag(), data);
|
||||
entry->m_dio = data;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
entry = entry->next();
|
||||
}
|
||||
}
|
||||
|
||||
if (!changed) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t new_state = get_data();
|
||||
if (old_state != new_state) {
|
||||
m_write_dio(new_state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -55,6 +55,12 @@
|
||||
#define MCFG_IEEE488_REN_CALLBACK(_write) \
|
||||
devcb = &downcast<ieee488_device *>(device)->set_ren_callback(DEVCB_##_write);
|
||||
|
||||
// This CB reports changes to the DIO lines on the bus (whose value comes from
|
||||
// ANDing the DIO lines of each device on the bus)
|
||||
// This CB is needed by those controllers that start a parallel poll and wait
|
||||
// for some condition to be set by devices on the DIO lines (e.g. PHI controller).
|
||||
#define MCFG_IEEE488_DIO_CALLBACK(_write) \
|
||||
devcb = &downcast<ieee488_device *>(device)->set_dio_callback(DEVCB_##_write);
|
||||
|
||||
#define MCFG_IEEE488_SLOT_ADD(_tag, _address, _slot_intf, _def_slot) \
|
||||
MCFG_DEVICE_ADD(_tag, IEEE488_SLOT, 0) \
|
||||
@ -99,6 +105,7 @@ public:
|
||||
template <class Object> devcb_base &set_srq_callback(Object &&cb) { return m_write_srq.set_callback(std::forward<Object>(cb)); }
|
||||
template <class Object> devcb_base &set_atn_callback(Object &&cb) { return m_write_atn.set_callback(std::forward<Object>(cb)); }
|
||||
template <class Object> devcb_base &set_ren_callback(Object &&cb) { return m_write_ren.set_callback(std::forward<Object>(cb)); }
|
||||
template <class Object> devcb_base &set_dio_callback(Object &&cb) { return m_write_dio.set_callback(std::forward<Object>(cb)); }
|
||||
|
||||
void add_device(ieee488_slot_device *slot, device_t *target);
|
||||
|
||||
@ -180,6 +187,7 @@ private:
|
||||
devcb_write_line m_write_srq;
|
||||
devcb_write_line m_write_atn;
|
||||
devcb_write_line m_write_ren;
|
||||
devcb_write8 m_write_dio;
|
||||
|
||||
void set_signal(device_t *device, int signal, int state);
|
||||
int get_signal(int signal);
|
||||
|
@ -31,15 +31,33 @@
|
||||
#include "phi.h"
|
||||
|
||||
// Debugging
|
||||
#define VERBOSE 1
|
||||
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
|
||||
#define VERBOSE_0 0
|
||||
#define LOG_0(x) do { if (VERBOSE_0) logerror x; } while (0)
|
||||
#include "logmacro.h"
|
||||
#define LOG_NOISY_MASK (LOG_GENERAL << 1)
|
||||
#define LOG_NOISY(...) LOGMASKED(LOG_NOISY_MASK, __VA_ARGS__)
|
||||
#define LOG_REG_MASK (LOG_NOISY_MASK << 1)
|
||||
#define LOG_REG(...) LOGMASKED(LOG_REG_MASK, __VA_ARGS__)
|
||||
#define LOG_INT_MASK (LOG_REG_MASK << 1)
|
||||
#define LOG_INT(...) LOGMASKED(LOG_INT_MASK, __VA_ARGS__)
|
||||
#undef VERBOSE
|
||||
#define VERBOSE LOG_GENERAL
|
||||
|
||||
// Macros to clear/set single bits
|
||||
#define BIT_MASK(n) (1U << (n))
|
||||
#define BIT_CLR(w , n) ((w) &= ~BIT_MASK(n))
|
||||
#define BIT_SET(w , n) ((w) |= BIT_MASK(n))
|
||||
// Bit manipulation
|
||||
namespace {
|
||||
template<typename T> constexpr T BIT_MASK(unsigned n)
|
||||
{
|
||||
return (T)1U << n;
|
||||
}
|
||||
|
||||
template<typename T> void BIT_CLR(T& w , unsigned n)
|
||||
{
|
||||
w &= ~BIT_MASK<T>(n);
|
||||
}
|
||||
|
||||
template<typename T> void BIT_SET(T& w , unsigned n)
|
||||
{
|
||||
w |= BIT_MASK<T>(n);
|
||||
}
|
||||
}
|
||||
|
||||
// Timers
|
||||
enum {
|
||||
@ -68,103 +86,102 @@ enum {
|
||||
};
|
||||
|
||||
// All valid bits in registers
|
||||
#define REG_ALL_MASK 0xc0ff
|
||||
constexpr uint16_t REG_ALL_MASK = 0xc0ff;
|
||||
|
||||
// D0 & D1 bits
|
||||
#define REG_D0D1_MASK 0xc000 // Mask of D0/D1 bits
|
||||
#define REG_D0D1_SHIFT 14 // Position of D0/D1 bits
|
||||
constexpr uint16_t REG_D0D1_MASK = 0xc000; // Mask of D0/D1 bits
|
||||
constexpr unsigned REG_D0D1_SHIFT = 14; // Position of D0/D1 bits
|
||||
|
||||
// D8-D15 bits
|
||||
#define REG_D08D15_MASK 0xff // Mask of D8:D15 bits
|
||||
constexpr uint16_t REG_D08D15_MASK = 0xff; // Mask of D8:D15 bits
|
||||
|
||||
// Bits in INT_COND & INT_MASK
|
||||
#define REG_INT_DEV_CLEAR_BIT 0 // Device clear
|
||||
#define REG_INT_FIFO_IDLE_BIT 1 // FIFO idle
|
||||
#define REG_INT_FIFO_AV_BIT 2 // FIFO bytes available
|
||||
#define REG_INT_FIFO_ROOM_BIT 3 // FIFO room available
|
||||
#define REG_INT_SRQ_BIT 4 // Service request
|
||||
#define REG_INT_PP_RESPONSE_BIT 5 // PP response
|
||||
#define REG_INT_PROC_ABORT_BIT 6 // Processor handshake abort
|
||||
#define REG_INT_STATUS_CH_BIT 7 // Status change
|
||||
#define REG_INT_PARITY_ERR_BIT 14 // Parity error
|
||||
#define REG_INT_PENDING_BIT 15 // Interrupt pending
|
||||
#define REG_INT_CLEARABLE_MASK 0x40c1 // Mask of clearable bits
|
||||
#define REG_INT_STATE_MASK 0x803e // Mask of "state" bits
|
||||
constexpr unsigned REG_INT_DEV_CLEAR_BIT = 0; // Device clear
|
||||
constexpr unsigned REG_INT_FIFO_IDLE_BIT = 1; // FIFO idle
|
||||
constexpr unsigned REG_INT_FIFO_AV_BIT = 2; // FIFO bytes available
|
||||
constexpr unsigned REG_INT_FIFO_ROOM_BIT = 3; // FIFO room available
|
||||
constexpr unsigned REG_INT_SRQ_BIT = 4; // Service request
|
||||
constexpr unsigned REG_INT_PP_RESPONSE_BIT = 5; // PP response
|
||||
constexpr unsigned REG_INT_PROC_ABORT_BIT = 6; // Processor handshake abort
|
||||
constexpr unsigned REG_INT_STATUS_CH_BIT = 7; // Status change
|
||||
constexpr unsigned REG_INT_PARITY_ERR_BIT = 14; // Parity error
|
||||
constexpr unsigned REG_INT_PENDING_BIT = 15; // Interrupt pending
|
||||
constexpr uint16_t REG_INT_CLEARABLE_MASK = 0x40c1; // Mask of clearable bits
|
||||
constexpr uint16_t REG_INT_STATE_MASK = 0x803e; // Mask of "state" bits
|
||||
|
||||
// Bits in inbound FIFO
|
||||
#define REG_IFIFO_NORMAL_MASK 0x0000 // Mask of D0/D1 bits for "normal" bytes
|
||||
#define REG_IFIFO_CNT_EXP_MASK 0x8000 // Mask for a byte that caused byte count to expire
|
||||
#define REG_IFIFO_LAST_MASK 0xc000 // Mask for last byte in a record
|
||||
#define REG_IFIFO_2_ADDR_MASK 0x4000 // Mask for secondary addresses
|
||||
#define REG_IFIFO_TALK_BIT 5 // Bit of "talk" flag
|
||||
constexpr uint16_t REG_IFIFO_NORMAL_MASK = 0x0000; // Mask of D0/D1 bits for "normal" bytes
|
||||
constexpr uint16_t REG_IFIFO_CNT_EXP_MASK = 0x8000; // Mask for a byte that caused byte count to expire
|
||||
constexpr uint16_t REG_IFIFO_LAST_MASK = 0xc000; // Mask for last byte in a record
|
||||
constexpr uint16_t REG_IFIFO_2_ADDR_MASK = 0x4000; // Mask for secondary addresses
|
||||
constexpr unsigned REG_IFIFO_TALK_BIT = 5; // Bit of "talk" flag
|
||||
|
||||
// Bits in outbound FIFO
|
||||
#define REG_OFIFO_SPECIAL_BIT 14 // Bit to discriminate between normal bytes and the rest
|
||||
#define REG_OFIFO_END_BIT 15 // Bit of EOI
|
||||
#define REG_OFIFO_IFCMD_MASK 0x4000 // Mask of interface commands
|
||||
#define REG_OFIFO_UNCNT_MASK 0xc000 // Mask of uncounted transfer enable
|
||||
#define REG_OFIFO_XFER_EN_MASK 0x0000 // Mask of byte transfer enable
|
||||
#define REG_OFIFO_LF_INH_BIT 15 // Bit of LF detection inhibit
|
||||
constexpr unsigned REG_OFIFO_SPECIAL_BIT = 14; // Bit to discriminate between normal bytes and the rest
|
||||
constexpr unsigned REG_OFIFO_END_BIT = 15; // Bit of EOI
|
||||
constexpr uint16_t REG_OFIFO_IFCMD_MASK = 0x4000; // Mask of interface commands
|
||||
constexpr uint16_t REG_OFIFO_UNCNT_MASK = 0xc000; // Mask of uncounted transfer enable
|
||||
constexpr unsigned REG_OFIFO_LF_INH_BIT = 15; // Bit of LF detection inhibit
|
||||
|
||||
// Bits in status register
|
||||
#define REG_STATUS_DATA_FREEZE_BIT 0 // Outbound data freeze
|
||||
#define REG_STATUS_LISTEN_BIT 1 // Addressed to listen
|
||||
#define REG_STATUS_TALK_BIT 2 // Addressed to talk or identify
|
||||
#define REG_STATUS_SYS_CTRL_BIT 3 // System controller
|
||||
#define REG_STATUS_CONTROLLER_BIT 4 // Current controller
|
||||
#define REG_STATUS_REMOTE_BIT 5 // Remote state
|
||||
#define REG_STATUS_D0D1_BIT 6 // D0/D1 bit access
|
||||
#define REG_STATUS_STATE_MASK 0x3e // Mask of "state" bits
|
||||
constexpr unsigned REG_STATUS_DATA_FREEZE_BIT = 0; // Outbound data freeze
|
||||
constexpr unsigned REG_STATUS_LISTEN_BIT = 1; // Addressed to listen
|
||||
constexpr unsigned REG_STATUS_TALK_BIT = 2; // Addressed to talk or identify
|
||||
constexpr unsigned REG_STATUS_SYS_CTRL_BIT = 3; // System controller
|
||||
constexpr unsigned REG_STATUS_CONTROLLER_BIT = 4; // Current controller
|
||||
constexpr unsigned REG_STATUS_REMOTE_BIT = 5; // Remote state
|
||||
constexpr unsigned REG_STATUS_D0D1_BIT = 6; // D0/D1 bit access
|
||||
constexpr uint16_t REG_STATUS_STATE_MASK = 0x3e; // Mask of "state" bits
|
||||
|
||||
// Bits in control register
|
||||
#define REG_CTRL_INIT_OFIFO_BIT 0 // Initialize outbound FIFO
|
||||
#define REG_CTRL_DMA_FIFO_BIT 1 // DMA FIFO selection
|
||||
#define REG_CTRL_SERVICE_REQ_BIT 2 // Request service
|
||||
#define REG_CTRL_PP_RESPONSE_BIT 3 // Respond to PP
|
||||
#define REG_CTRL_IFC_BIT 4 // IFC value
|
||||
#define REG_CTRL_REN_BIT 5 // REN value
|
||||
#define REG_CTRL_PAR_FREEZE_BIT 6 // Parity freeze
|
||||
#define REG_CTRL_8BIT_PROC_BIT 7 // 8-bit processor
|
||||
constexpr unsigned REG_CTRL_INIT_OFIFO_BIT = 0; // Initialize outbound FIFO
|
||||
constexpr unsigned REG_CTRL_DMA_FIFO_BIT = 1; // DMA FIFO selection
|
||||
constexpr unsigned REG_CTRL_SERVICE_REQ_BIT = 2; // Request service
|
||||
constexpr unsigned REG_CTRL_PP_RESPONSE_BIT = 3; // Respond to PP
|
||||
constexpr unsigned REG_CTRL_IFC_BIT = 4; // IFC value
|
||||
constexpr unsigned REG_CTRL_REN_BIT = 5; // REN value
|
||||
constexpr unsigned REG_CTRL_PAR_FREEZE_BIT = 6; // Parity freeze
|
||||
constexpr unsigned REG_CTRL_8BIT_PROC_BIT = 7; // 8-bit processor
|
||||
|
||||
// Bits in address register
|
||||
#define REG_ADDR_HPIB_ADDR_BIT 0 // HPIB address
|
||||
#define REG_ADDR_LA_BIT 5 // Listen always
|
||||
#define REG_ADDR_TA_BIT 6 // Talk always
|
||||
#define REG_ADDR_ONLINE_BIT 7 // Online
|
||||
constexpr unsigned REG_ADDR_HPIB_ADDR_BIT = 0; // HPIB address LSB
|
||||
constexpr unsigned REG_ADDR_LA_BIT = 5; // Listen always
|
||||
constexpr unsigned REG_ADDR_TA_BIT = 6; // Talk always
|
||||
constexpr unsigned REG_ADDR_ONLINE_BIT = 7; // Online
|
||||
|
||||
// Interface commands
|
||||
#define IFCMD_MASK 0x7f // Mask of interface commands
|
||||
#define IFCMD_DCL 0x14 // Device clear
|
||||
#define IFCMD_GET 0x08 // Group execute trigger
|
||||
#define IFCMD_GTL 0x01 // Go to local
|
||||
#define IFCMD_LLO 0x11 // Local lock-out
|
||||
#define IFCMD_AG_MASK 0x60 // Mask of bits identifying address group commands
|
||||
#define IFCMD_ADDR_MASK 0x1f // Mask of address in AG commands
|
||||
#define IFCMD_LAG_VALUE 0x20 // Value of LAG commands
|
||||
#define IFCMD_TAG_VALUE 0x40 // Value of TAG commands
|
||||
#define IFCMD_SCG_VALUE 0x60 // Value of SCG commands
|
||||
#define IFCMD_PPC 0x05 // Parallel poll configure
|
||||
#define IFCMD_PPX_MASK 0x70 // Mask of PPE/PPD commands
|
||||
#define IFCMD_PPE_VALUE 0x60 // Parallel poll enable
|
||||
#define IFCMD_PPE_S_BIT 3 // Position of "S" bit in PPE
|
||||
#define IFCMD_PPE_PPR_MASK 7 // Mask in PPE of PPR msg no.
|
||||
#define IFCMD_PPD_VALUE 0x70 // Parallel poll disable
|
||||
#define IFCMD_PPU 0x15 // Parallel poll unconfigure
|
||||
#define IFCMD_SDC 0x04 // Selected device clear
|
||||
#define IFCMD_SPD 0x19 // Serial poll disable
|
||||
#define IFCMD_SPE 0x18 // Serial poll enable
|
||||
#define IFCMD_TCT 0x09 // Take control
|
||||
#define IFCMD_UNL 0x3f // Unlisten
|
||||
#define IFCMD_UNT 0x5f // Untalk
|
||||
constexpr uint8_t IFCMD_MASK = 0x7f; // Mask of interface commands
|
||||
constexpr uint8_t IFCMD_DCL = 0x14; // Device clear
|
||||
constexpr uint8_t IFCMD_GET = 0x08; // Group execute trigger
|
||||
constexpr uint8_t IFCMD_GTL = 0x01; // Go to local
|
||||
constexpr uint8_t IFCMD_LLO = 0x11; // Local lock-out
|
||||
constexpr uint8_t IFCMD_AG_MASK = 0x60; // Mask of bits identifying address group commands
|
||||
constexpr uint8_t IFCMD_ADDR_MASK = 0x1f; // Mask of address in AG commands
|
||||
constexpr uint8_t IFCMD_LAG_VALUE = 0x20; // Value of LAG commands
|
||||
constexpr uint8_t IFCMD_TAG_VALUE = 0x40; // Value of TAG commands
|
||||
constexpr uint8_t IFCMD_SCG_VALUE = 0x60; // Value of SCG commands
|
||||
constexpr uint8_t IFCMD_PPC = 0x05; // Parallel poll configure
|
||||
constexpr uint8_t IFCMD_PPX_MASK = 0x70; // Mask of PPE/PPD commands
|
||||
constexpr uint8_t IFCMD_PPE_VALUE = 0x60; // Parallel poll enable
|
||||
constexpr unsigned IFCMD_PPE_S_BIT = 3; // Position of "S" bit in PPE
|
||||
constexpr uint8_t IFCMD_PPE_PPR_MASK = 7; // Mask in PPE of PPR msg no.
|
||||
constexpr uint8_t IFCMD_PPD_VALUE = 0x70; // Parallel poll disable
|
||||
constexpr uint8_t IFCMD_PPU = 0x15; // Parallel poll unconfigure
|
||||
constexpr uint8_t IFCMD_SDC = 0x04; // Selected device clear
|
||||
constexpr uint8_t IFCMD_SPD = 0x19; // Serial poll disable
|
||||
constexpr uint8_t IFCMD_SPE = 0x18; // Serial poll enable
|
||||
constexpr uint8_t IFCMD_TCT = 0x09; // Take control
|
||||
constexpr uint8_t IFCMD_UNL = 0x3f; // Unlisten
|
||||
constexpr uint8_t IFCMD_UNT = 0x5f; // Untalk
|
||||
|
||||
// Delays
|
||||
#define DELAY_T1 2000 // T1: 2 us
|
||||
#define DELAY_T7 500 // T7: 0.5 us
|
||||
#define DELAY_T9 1500 // T9: 1.5 us
|
||||
#define DELAY_T10 1500 // T10: 1.5 us
|
||||
constexpr unsigned DELAY_T1 = 2000; // T1: 2 us
|
||||
constexpr unsigned DELAY_T7 = 500; // T7: 0.5 us
|
||||
constexpr unsigned DELAY_T9 = 1500; // T9: 1.5 us
|
||||
constexpr unsigned DELAY_T10 = 1500; // T10: 1.5 us
|
||||
|
||||
// Controller address
|
||||
#define CONTROLLER_ADDR 0x1e // PHI always has this address when it's a controller
|
||||
constexpr uint8_t CONTROLLER_ADDR = 0x1e; // PHI always has this address when it's a system controller
|
||||
|
||||
// Device type definition
|
||||
DEFINE_DEVICE_TYPE(PHI, phi_device, "hp_phi", "HP Processor-to-HPIB Interface")
|
||||
@ -184,7 +201,8 @@ phi_device::phi_device(const machine_config &mconfig, device_type type, const ch
|
||||
devcb_write_line(*this),
|
||||
devcb_write_line(*this) },
|
||||
m_int_write_func(*this),
|
||||
m_dmarq_write_func(*this)
|
||||
m_dmarq_write_func(*this),
|
||||
m_sys_cntrl_read_func(*this)
|
||||
{
|
||||
}
|
||||
|
||||
@ -233,21 +251,25 @@ WRITE_LINE_MEMBER(phi_device::ren_w)
|
||||
set_ext_signal(PHI_488_REN , state);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(phi_device::bus_dio_w)
|
||||
{
|
||||
update_pp();
|
||||
}
|
||||
|
||||
void phi_device::set_ext_signal(phi_488_signal_t signal , int state)
|
||||
{
|
||||
state = !state;
|
||||
if (m_ext_signals[ signal ] != state) {
|
||||
m_ext_signals[ signal ] = state;
|
||||
LOG_0(("EXT EOI %d DAV %d NRFD %d NDAC %d IFC %d SRQ %d ATN %d REN %d\n" ,
|
||||
m_ext_signals[ PHI_488_EOI ] ,
|
||||
m_ext_signals[ PHI_488_DAV ] ,
|
||||
m_ext_signals[ PHI_488_NRFD ] ,
|
||||
m_ext_signals[ PHI_488_NDAC ] ,
|
||||
m_ext_signals[ PHI_488_IFC ] ,
|
||||
m_ext_signals[ PHI_488_SRQ ] ,
|
||||
m_ext_signals[ PHI_488_ATN ] ,
|
||||
m_ext_signals[ PHI_488_REN ]));
|
||||
LOG_NOISY("EXT EOI %d DAV %d NRFD %d NDAC %d IFC %d SRQ %d ATN %d REN %d\n" ,
|
||||
m_ext_signals[ PHI_488_EOI ] ,
|
||||
m_ext_signals[ PHI_488_DAV ] ,
|
||||
m_ext_signals[ PHI_488_NRFD ] ,
|
||||
m_ext_signals[ PHI_488_NDAC ] ,
|
||||
m_ext_signals[ PHI_488_IFC ] ,
|
||||
m_ext_signals[ PHI_488_SRQ ] ,
|
||||
m_ext_signals[ PHI_488_ATN ] ,
|
||||
m_ext_signals[ PHI_488_REN ]);
|
||||
update_fsm();
|
||||
}
|
||||
}
|
||||
@ -271,10 +293,13 @@ READ16_MEMBER(phi_device::reg16_r)
|
||||
break;
|
||||
|
||||
case REG_R_INBOUND_FIFO:
|
||||
// TODO: read from PP response
|
||||
if (m_fifo_in.empty()) {
|
||||
BIT_SET(m_reg_int_cond, REG_INT_PROC_ABORT_BIT);
|
||||
res = 0;
|
||||
if (m_c_state == PHI_C_CPPS) {
|
||||
res = get_pp_response();
|
||||
} else {
|
||||
BIT_SET(m_reg_int_cond, REG_INT_PROC_ABORT_BIT);
|
||||
res = 0;
|
||||
}
|
||||
} else {
|
||||
res = m_fifo_in.dequeue();
|
||||
}
|
||||
@ -303,7 +328,7 @@ READ16_MEMBER(phi_device::reg16_r)
|
||||
|
||||
default:
|
||||
res = 0;
|
||||
LOG(("Reading from unmapped address (%u)\n", offset));
|
||||
LOG("Reading from unmapped address (%u)\n", offset);
|
||||
break;
|
||||
};
|
||||
|
||||
@ -313,7 +338,7 @@ READ16_MEMBER(phi_device::reg16_r)
|
||||
((res & REG_D0D1_MASK) >> (REG_D0D1_SHIFT - REG_STATUS_D0D1_BIT));
|
||||
}
|
||||
|
||||
//LOG(("R %u=%04x\n" , offset , res));
|
||||
LOG_REG("R %u=%04x\n" , offset , res);
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -341,11 +366,12 @@ void phi_device::device_start()
|
||||
save_item(NAME(m_t_spms));
|
||||
save_item(NAME(m_l_state));
|
||||
save_item(NAME(m_sr_state));
|
||||
save_item(NAME(m_rl_rems));
|
||||
save_item(NAME(m_pp_state));
|
||||
save_item(NAME(m_pp_pacs));
|
||||
save_item(NAME(m_ppr_msg));
|
||||
save_item(NAME(m_s_sense));
|
||||
save_item(NAME(m_c_state));
|
||||
save_item(NAME(m_sa_state));
|
||||
save_item(NAME(m_be_counter));
|
||||
save_item(NAME(m_reg_status));
|
||||
save_item(NAME(m_reg_int_cond));
|
||||
@ -363,6 +389,7 @@ void phi_device::device_start()
|
||||
}
|
||||
m_int_write_func.resolve_safe();
|
||||
m_dmarq_write_func.resolve_safe();
|
||||
m_sys_cntrl_read_func.resolve_safe(0);
|
||||
|
||||
m_sh_dly_timer = timer_alloc(SH_DELAY_TMR_ID);
|
||||
m_c_dly_timer = timer_alloc(C_DELAY_TMR_ID);
|
||||
@ -391,6 +418,10 @@ void phi_device::device_reset()
|
||||
m_reg_address = 0;
|
||||
m_fifo_in.clear();
|
||||
m_fifo_out.clear();
|
||||
m_int_line = false;
|
||||
m_int_write_func(false);
|
||||
m_dmarq_line = false;
|
||||
m_dmarq_write_func(false);
|
||||
|
||||
pon_msg();
|
||||
update_488();
|
||||
@ -398,7 +429,7 @@ void phi_device::device_reset()
|
||||
|
||||
void phi_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
LOG_0(("tmr %d enabled %d\n" , id , timer.enabled()));
|
||||
LOG_NOISY("tmr %d enabled %d\n" , id , timer.enabled());
|
||||
update_fsm();
|
||||
}
|
||||
|
||||
@ -409,7 +440,7 @@ void phi_device::int_reg_w(offs_t offset , uint16_t data)
|
||||
data = (data & REG_D08D15_MASK) | ((m_reg_status << (REG_D0D1_SHIFT - REG_STATUS_D0D1_BIT)) & REG_D0D1_MASK);
|
||||
}
|
||||
|
||||
//LOG(("W %u=%04x\n" , offset , data));
|
||||
LOG_REG("W %u=%04x\n" , offset , data);
|
||||
|
||||
switch (offset) {
|
||||
case REG_W_INT_COND:
|
||||
@ -447,6 +478,11 @@ void phi_device::int_reg_w(offs_t offset , uint16_t data)
|
||||
m_reg_control = data & 0xfe;
|
||||
if (BIT(data , REG_CTRL_INIT_OFIFO_BIT)) {
|
||||
m_fifo_out.clear();
|
||||
if (m_c_state == PHI_C_CSBS) {
|
||||
// Take control asynchronously
|
||||
m_c_state = PHI_C_CSWS;
|
||||
m_c_dly_timer->adjust(attotime::from_nsec(DELAY_T7));
|
||||
}
|
||||
}
|
||||
if (m_loopback) {
|
||||
// TODO: better?
|
||||
@ -462,8 +498,7 @@ void phi_device::int_reg_w(offs_t offset , uint16_t data)
|
||||
bool prev_ol = BIT(m_reg_address , REG_ADDR_ONLINE_BIT);
|
||||
m_reg_address = data;
|
||||
bool current_ol = BIT(m_reg_address , REG_ADDR_ONLINE_BIT);
|
||||
// TODO: consider SYS CNTRL input, too
|
||||
m_sys_controller = !current_ol;
|
||||
m_sys_controller = !current_ol || m_sys_cntrl_read_func();
|
||||
m_loopback = !current_ol;
|
||||
if (!current_ol) {
|
||||
// IDENTIFY is enabled by PP_RESPONSE bit in control register
|
||||
@ -473,6 +508,7 @@ void phi_device::int_reg_w(offs_t offset , uint16_t data)
|
||||
pon_msg();
|
||||
m_id_enabled = BIT(m_reg_control , REG_CTRL_PP_RESPONSE_BIT);
|
||||
}
|
||||
configure_pp_response();
|
||||
if (prev_ol != current_ol) {
|
||||
update_488();
|
||||
}
|
||||
@ -493,7 +529,7 @@ void phi_device::int_reg_w(offs_t offset , uint16_t data)
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG(("Writing to unmapped address (%u)\n", offset));
|
||||
LOG("Writing to unmapped address (%u)\n", offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -510,7 +546,7 @@ uint8_t phi_device::get_dio(void)
|
||||
void phi_device::set_dio(uint8_t data)
|
||||
{
|
||||
if (data != m_dio) {
|
||||
LOG_0(("DIO=%02x\n" , data));
|
||||
LOG_NOISY("DIO=%02x\n" , data);
|
||||
m_dio = data;
|
||||
if (!m_loopback) {
|
||||
m_dio_write_func(~data);
|
||||
@ -531,15 +567,15 @@ void phi_device::set_signal(phi_488_signal_t signal , bool state)
|
||||
{
|
||||
if (state != m_signals[ signal ]) {
|
||||
m_signals[ signal ] = state;
|
||||
LOG_0(("INT EOI %d DAV %d NRFD %d NDAC %d IFC %d SRQ %d ATN %d REN %d\n" ,
|
||||
m_signals[ PHI_488_EOI ] ,
|
||||
m_signals[ PHI_488_DAV ] ,
|
||||
m_signals[ PHI_488_NRFD ] ,
|
||||
m_signals[ PHI_488_NDAC ] ,
|
||||
m_signals[ PHI_488_IFC ] ,
|
||||
m_signals[ PHI_488_SRQ ] ,
|
||||
m_signals[ PHI_488_ATN ] ,
|
||||
m_signals[ PHI_488_REN ]));
|
||||
LOG_NOISY("INT EOI %d DAV %d NRFD %d NDAC %d IFC %d SRQ %d ATN %d REN %d\n" ,
|
||||
m_signals[ PHI_488_EOI ] ,
|
||||
m_signals[ PHI_488_DAV ] ,
|
||||
m_signals[ PHI_488_NRFD ] ,
|
||||
m_signals[ PHI_488_NDAC ] ,
|
||||
m_signals[ PHI_488_IFC ] ,
|
||||
m_signals[ PHI_488_SRQ ] ,
|
||||
m_signals[ PHI_488_ATN ] ,
|
||||
m_signals[ PHI_488_REN ]);
|
||||
if (!m_loopback) {
|
||||
m_signal_wr_fns[ signal ](!state);
|
||||
}
|
||||
@ -554,18 +590,10 @@ void phi_device::pon_msg(void)
|
||||
m_t_spms = false;
|
||||
m_l_state = PHI_L_LIDS;
|
||||
m_sr_state = PHI_SR_NPRS;
|
||||
m_pp_pacs = false;
|
||||
uint8_t addr = my_address();
|
||||
if (addr <= 7) {
|
||||
// If address <= 7, PP is automatically enabled and configured for PPR = ~address
|
||||
m_ppr_msg = addr ^ 7;
|
||||
m_pp_state = PHI_PP_PPSS;
|
||||
} else {
|
||||
m_ppr_msg = 0;
|
||||
m_pp_state = PHI_PP_PPIS;
|
||||
}
|
||||
m_s_sense = true;
|
||||
m_rl_rems = false;
|
||||
m_pp_state = PHI_PP_PPIS;
|
||||
m_c_state = PHI_C_CIDS;
|
||||
m_sa_state = PHI_SA_NONE;
|
||||
m_be_counter = 0;
|
||||
m_nba_origin = NBA_NONE;
|
||||
}
|
||||
@ -597,26 +625,30 @@ void phi_device::update_fsm(void)
|
||||
set_signal(PHI_488_IFC , m_sys_controller && BIT(m_reg_control , REG_CTRL_IFC_BIT));
|
||||
set_signal(PHI_488_REN , m_sys_controller && BIT(m_reg_control , REG_CTRL_REN_BIT));
|
||||
|
||||
// TODO: improve (see SR FSM)
|
||||
// This is not entirely correct but it works for now (on HP64K, the only system
|
||||
// where it's relevant)
|
||||
set_signal(PHI_488_SRQ , BIT(m_reg_control , REG_CTRL_SERVICE_REQ_BIT));
|
||||
|
||||
bool changed = true;
|
||||
int prev_state;
|
||||
uint8_t new_byte = 0;
|
||||
bool new_eoi = false;
|
||||
bool prev_cic = controller_in_charge();
|
||||
// TODO: SR FSM
|
||||
// TODO: RL FSM
|
||||
// Loop until all changes settle
|
||||
while (changed) {
|
||||
LOG_0(("SH %d AH %d T %d SPMS %d L %d SR %d PP %d PACS %d PPR %u S %d C %d\n" ,
|
||||
m_sh_state , m_ah_state , m_t_state , m_t_spms , m_l_state , m_sr_state ,
|
||||
m_pp_state , m_pp_pacs , m_ppr_msg , m_s_sense , m_c_state));
|
||||
LOG_0(("O E/F=%d/%d I E/F=%d/%d\n" , m_fifo_out.empty() , m_fifo_out.full() , m_fifo_in.empty() , m_fifo_in.full()));
|
||||
LOG_NOISY("SH %d AH %d T %d SPMS %d L %d SR %d PP %d PPR %u S %d C %d SA %d\n" ,
|
||||
m_sh_state , m_ah_state , m_t_state , m_t_spms , m_l_state , m_sr_state ,
|
||||
m_pp_state , m_ppr_msg , m_s_sense , m_c_state , m_sa_state);
|
||||
LOG_NOISY("O E/F=%d/%d I E/F=%d/%d\n" , m_fifo_out.empty() , m_fifo_out.full() , m_fifo_in.empty() , m_fifo_in.full());
|
||||
changed = false;
|
||||
|
||||
// SH FSM
|
||||
prev_state = m_sh_state;
|
||||
bool sh_reset =
|
||||
(get_signal(PHI_488_ATN) && !(m_c_state == PHI_C_CACS || m_c_state == PHI_C_CTRS)) ||
|
||||
(!get_signal(PHI_488_ATN) && !(m_t_state == PHI_T_TACS || m_t_state == PHI_T_SPAS || m_t_state == PHI_T_ID3 || m_t_state == PHI_T_ID5));
|
||||
(!get_signal(PHI_488_ATN) && !(m_t_state == PHI_T_TACS || m_t_state == PHI_T_SPAS || m_t_state == PHI_T_ID2 || m_t_state == PHI_T_ID4));
|
||||
|
||||
if (sh_reset) {
|
||||
m_sh_state = PHI_SH_SIDS;
|
||||
@ -626,8 +658,8 @@ void phi_device::update_fsm(void)
|
||||
case PHI_SH_SIDS:
|
||||
if (m_t_state == PHI_T_TACS ||
|
||||
m_t_state == PHI_T_SPAS ||
|
||||
m_t_state == PHI_T_ID3 ||
|
||||
m_t_state == PHI_T_ID5 ||
|
||||
m_t_state == PHI_T_ID2 ||
|
||||
m_t_state == PHI_T_ID4 ||
|
||||
m_c_state == PHI_C_CACS) {
|
||||
m_sh_state = PHI_SH_SGNS;
|
||||
}
|
||||
@ -637,7 +669,7 @@ void phi_device::update_fsm(void)
|
||||
if ((m_nba_origin = nba_msg(new_byte , new_eoi)) != NBA_NONE) {
|
||||
m_sh_state = PHI_SH_SDYS;
|
||||
m_sh_dly_timer->adjust(attotime::from_nsec(DELAY_T1));
|
||||
LOG_0(("SH DLY enabled %d\n" , m_sh_dly_timer->enabled()));
|
||||
LOG_NOISY("SH DLY enabled %d\n" , m_sh_dly_timer->enabled());
|
||||
}
|
||||
break;
|
||||
|
||||
@ -649,7 +681,7 @@ void phi_device::update_fsm(void)
|
||||
|
||||
case PHI_SH_STRS:
|
||||
if (!get_signal(PHI_488_NDAC)) {
|
||||
LOG(("TX %02x/%d\n" , m_dio , m_signals[ PHI_488_EOI ]));
|
||||
LOG("%.6f TX %02x/%d\n" , machine().time().as_double() , m_dio , m_signals[ PHI_488_EOI ]);
|
||||
m_sh_state = PHI_SH_SGNS;
|
||||
clear_nba((nba_origin_t)m_nba_origin);
|
||||
}
|
||||
@ -779,33 +811,30 @@ void phi_device::update_fsm(void)
|
||||
break;
|
||||
|
||||
case PHI_T_ID1:
|
||||
break;
|
||||
|
||||
case PHI_T_ID2:
|
||||
if (!get_signal(PHI_488_ATN)) {
|
||||
m_t_state = PHI_T_ID3;
|
||||
}
|
||||
break;
|
||||
|
||||
case PHI_T_ID3:
|
||||
if (get_signal(PHI_488_ATN)) {
|
||||
m_t_state = PHI_T_ID2;
|
||||
}
|
||||
break;
|
||||
|
||||
case PHI_T_ID4:
|
||||
if (!get_signal(PHI_488_ATN)) {
|
||||
m_t_state = PHI_T_ID5;
|
||||
case PHI_T_ID2:
|
||||
if (get_signal(PHI_488_ATN)) {
|
||||
m_t_state = PHI_T_ID1;
|
||||
}
|
||||
break;
|
||||
|
||||
case PHI_T_ID5:
|
||||
if (get_signal(PHI_488_ATN)) {
|
||||
case PHI_T_ID3:
|
||||
if (!get_signal(PHI_488_ATN)) {
|
||||
m_t_state = PHI_T_ID4;
|
||||
}
|
||||
break;
|
||||
|
||||
case PHI_T_ID6:
|
||||
case PHI_T_ID4:
|
||||
if (get_signal(PHI_488_ATN)) {
|
||||
m_t_state = PHI_T_ID3;
|
||||
}
|
||||
break;
|
||||
|
||||
case PHI_T_ID5:
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -852,6 +881,13 @@ void phi_device::update_fsm(void)
|
||||
}
|
||||
// No direct L outputs
|
||||
|
||||
// RL FSM
|
||||
if (!get_signal(PHI_488_REN) && m_rl_rems) {
|
||||
m_rl_rems = false;
|
||||
changed = true;
|
||||
}
|
||||
// No direct RL outputs
|
||||
|
||||
// PP FSM
|
||||
prev_state = m_pp_state;
|
||||
switch (m_pp_state) {
|
||||
@ -879,8 +915,8 @@ void phi_device::update_fsm(void)
|
||||
}
|
||||
// PP outputs
|
||||
if (m_pp_state == PHI_PP_PPAS && m_s_sense == !!BIT(m_reg_control , REG_CTRL_PP_RESPONSE_BIT)) {
|
||||
LOG(("PP %u\n" , m_ppr_msg));
|
||||
dio_byte |= (1U << m_ppr_msg);
|
||||
LOG("%.6f PP %u\n" , machine().time().as_double() , m_ppr_msg);
|
||||
dio_byte |= BIT_MASK<uint8_t>(m_ppr_msg);
|
||||
}
|
||||
|
||||
// C FSM
|
||||
@ -918,19 +954,17 @@ void phi_device::update_fsm(void)
|
||||
m_be_counter = 0;
|
||||
} else if (rpp_msg()) {
|
||||
// Start parallel polling
|
||||
m_c_state = PHI_C_CPWS;
|
||||
m_c_state = PHI_C_CPPS;
|
||||
}
|
||||
// It's not clear what PHI does when it's controller-in-charge
|
||||
// and it's nothing to do. Here we park it in CACS.
|
||||
// There's no third case: rpp_msg() is true when m_fifo_out.empty() is true
|
||||
}
|
||||
break;
|
||||
|
||||
case PHI_C_CPWS:
|
||||
// TODO:
|
||||
break;
|
||||
|
||||
case PHI_C_CPPS:
|
||||
// TODO:
|
||||
if (!rpp_msg()) {
|
||||
m_c_state = PHI_C_CAWS;
|
||||
m_c_dly_timer->adjust(attotime::from_nsec(DELAY_T9));
|
||||
}
|
||||
break;
|
||||
|
||||
case PHI_C_CSBS:
|
||||
@ -950,7 +984,7 @@ void phi_device::update_fsm(void)
|
||||
|
||||
case PHI_C_CAWS:
|
||||
if (rpp_msg()) {
|
||||
m_c_state = PHI_C_CPWS;
|
||||
m_c_state = PHI_C_CPPS;
|
||||
m_c_dly_timer->reset();
|
||||
} else if (!m_c_dly_timer->enabled()) {
|
||||
m_c_state = PHI_C_CACS;
|
||||
@ -979,10 +1013,10 @@ void phi_device::update_fsm(void)
|
||||
changed = true;
|
||||
}
|
||||
// C outputs
|
||||
set_signal(PHI_488_ATN , m_c_state == PHI_C_CACS || m_c_state == PHI_C_CPWS ||
|
||||
set_signal(PHI_488_ATN , m_c_state == PHI_C_CACS ||
|
||||
m_c_state == PHI_C_CPPS || m_c_state == PHI_C_CSWS ||
|
||||
m_c_state == PHI_C_CAWS || m_c_state == PHI_C_CTRS);
|
||||
eoi_signal = eoi_signal || m_c_state == PHI_C_CPWS || m_c_state == PHI_C_CPPS;
|
||||
eoi_signal = eoi_signal || m_c_state == PHI_C_CPPS;
|
||||
set_signal(PHI_488_EOI , eoi_signal);
|
||||
set_dio(dio_byte);
|
||||
}
|
||||
@ -992,7 +1026,7 @@ void phi_device::update_fsm(void)
|
||||
if (m_l_state != PHI_L_LIDS) {
|
||||
BIT_SET(m_reg_status, REG_STATUS_LISTEN_BIT);
|
||||
}
|
||||
if (m_t_state != PHI_T_TIDS && m_t_state != PHI_T_ID1) {
|
||||
if (m_t_state != PHI_T_TIDS) {
|
||||
BIT_SET(m_reg_status, REG_STATUS_TALK_BIT);
|
||||
}
|
||||
if (m_sys_controller) {
|
||||
@ -1001,7 +1035,9 @@ void phi_device::update_fsm(void)
|
||||
if (controller_in_charge()) {
|
||||
BIT_SET(m_reg_status, REG_STATUS_CONTROLLER_BIT);
|
||||
}
|
||||
// TODO: REG_STATUS_REMOTE_BIT
|
||||
if (m_rl_rems) {
|
||||
BIT_SET(m_reg_status, REG_STATUS_REMOTE_BIT);
|
||||
}
|
||||
|
||||
// Update interrupting condition register and INT signal
|
||||
if (prev_cic != controller_in_charge()) {
|
||||
@ -1020,28 +1056,16 @@ void phi_device::update_fsm(void)
|
||||
if (controller_in_charge() && get_signal(PHI_488_SRQ)) {
|
||||
BIT_SET(m_reg_int_cond, REG_INT_SRQ_BIT);
|
||||
}
|
||||
// TODO: REG_INT_PP_RESPONSE_BIT
|
||||
bool int_pending = (m_reg_int_cond & m_reg_int_mask) != 0;
|
||||
bool int_line = false;
|
||||
if (int_pending) {
|
||||
BIT_SET(m_reg_int_cond, REG_INT_PENDING_BIT);
|
||||
if (BIT(m_reg_int_mask , REG_INT_PENDING_BIT)) {
|
||||
int_line = true;
|
||||
}
|
||||
}
|
||||
if (int_line != m_int_line) {
|
||||
m_int_line = int_line;
|
||||
m_int_write_func(m_int_line);
|
||||
}
|
||||
update_pp();
|
||||
update_interrupt();
|
||||
update_dmarq();
|
||||
|
||||
(void)m_dmarq_line; // TODO: update DMARQ
|
||||
m_no_recursion = false;
|
||||
}
|
||||
|
||||
phi_device::nba_origin_t phi_device::nba_msg(uint8_t& new_byte , bool& new_eoi) const
|
||||
{
|
||||
// TODO: consider CIC
|
||||
if (!m_fifo_out.empty()) {
|
||||
if (controller_in_charge() && m_c_state == PHI_C_CACS && !m_fifo_out.empty()) {
|
||||
uint16_t word = m_fifo_out.peek();
|
||||
if ((word & REG_D0D1_MASK) == REG_OFIFO_IFCMD_MASK) {
|
||||
// Controller sends an interface command
|
||||
@ -1071,21 +1095,22 @@ phi_device::nba_origin_t phi_device::nba_msg(uint8_t& new_byte , bool& new_eoi)
|
||||
|
||||
case PHI_T_SPAS:
|
||||
// Reply to serial poll: STB & RQS
|
||||
// TODO: check
|
||||
new_byte = m_sr_state == PHI_SR_NPRS ? 0x80 : 0x40;
|
||||
new_eoi = false;
|
||||
return NBA_FROM_SPAS;
|
||||
|
||||
case PHI_T_ID3:
|
||||
case PHI_T_ID2:
|
||||
// 1st byte of ID
|
||||
new_byte = (uint8_t)m_reg_1st_id;
|
||||
new_eoi = false;
|
||||
return NBA_FROM_ID3;
|
||||
return NBA_FROM_ID2;
|
||||
|
||||
case PHI_T_ID5:
|
||||
case PHI_T_ID4:
|
||||
// 2nd byte of ID
|
||||
new_byte = (uint8_t)m_reg_2nd_id;
|
||||
new_eoi = true;
|
||||
return NBA_FROM_ID5;
|
||||
return NBA_FROM_ID4;
|
||||
|
||||
default:
|
||||
break;
|
||||
@ -1101,12 +1126,12 @@ void phi_device::clear_nba(nba_origin_t origin)
|
||||
m_fifo_out.dequeue();
|
||||
break;
|
||||
|
||||
case NBA_FROM_ID3:
|
||||
m_t_state = PHI_T_ID4;
|
||||
case NBA_FROM_ID2:
|
||||
m_t_state = PHI_T_ID3;
|
||||
break;
|
||||
|
||||
case NBA_FROM_ID5:
|
||||
m_t_state = PHI_T_ID6;
|
||||
case NBA_FROM_ID4:
|
||||
m_t_state = PHI_T_ID5;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1116,20 +1141,23 @@ void phi_device::clear_nba(nba_origin_t origin)
|
||||
|
||||
bool phi_device::if_cmd_received(uint8_t byte)
|
||||
{
|
||||
LOG(("RX cmd: %02x\n" , byte));
|
||||
LOG("%.6f RX cmd: %02x\n" , machine().time().as_double() , byte);
|
||||
|
||||
bool accepted = true;
|
||||
|
||||
if ((byte & IFCMD_AG_MASK) != IFCMD_SCG_VALUE && byte != IFCMD_PPC) {
|
||||
// PACS -> PUCS when receiving a PCG command that is not PPC
|
||||
m_pp_pacs = false;
|
||||
if ((byte & IFCMD_AG_MASK) != IFCMD_SCG_VALUE) {
|
||||
// Any PCG clears sec. address recognition
|
||||
// Exceptions are intercepted below
|
||||
m_sa_state = PHI_SA_NONE;
|
||||
}
|
||||
|
||||
// TODO: IFC & non-reflection into controller
|
||||
switch (byte) {
|
||||
case IFCMD_GTL:
|
||||
// Go to local
|
||||
// TODO:
|
||||
if (m_l_state == PHI_L_LADS) {
|
||||
m_rl_rems = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case IFCMD_SDC:
|
||||
@ -1142,7 +1170,7 @@ bool phi_device::if_cmd_received(uint8_t byte)
|
||||
case IFCMD_PPC:
|
||||
// Parallel poll configure
|
||||
if (m_l_state == PHI_L_LADS) {
|
||||
m_pp_pacs = true;
|
||||
m_sa_state = PHI_SA_PACS;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1165,7 +1193,7 @@ bool phi_device::if_cmd_received(uint8_t byte)
|
||||
|
||||
case IFCMD_LLO:
|
||||
// Local lock-out
|
||||
// TODO:
|
||||
// Ignored
|
||||
break;
|
||||
|
||||
case IFCMD_DCL:
|
||||
@ -1194,19 +1222,20 @@ bool phi_device::if_cmd_received(uint8_t byte)
|
||||
|
||||
case IFCMD_UNL:
|
||||
// Unlisten
|
||||
if (m_l_state == PHI_L_LADS && !lon_msg()) {
|
||||
if (!lon_msg()) {
|
||||
m_l_state = PHI_L_LIDS;
|
||||
}
|
||||
break;
|
||||
|
||||
case IFCMD_UNT:
|
||||
// Untalk
|
||||
if (!ton_msg()) {
|
||||
if (m_id_enabled) {
|
||||
m_t_state = PHI_T_ID1;
|
||||
} else {
|
||||
m_t_state = PHI_T_TIDS;
|
||||
}
|
||||
if (ton_msg()) {
|
||||
m_t_state = PHI_T_TADS;
|
||||
} else {
|
||||
m_t_state = PHI_T_TIDS;
|
||||
}
|
||||
if (m_id_enabled) {
|
||||
m_sa_state = PHI_SA_UNT;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1218,51 +1247,65 @@ bool phi_device::if_cmd_received(uint8_t byte)
|
||||
|
||||
if (ag == IFCMD_LAG_VALUE) {
|
||||
// LAG
|
||||
if (!lon_msg() && m_l_state == PHI_L_LIDS && my_addr) {
|
||||
if (my_addr) {
|
||||
// MLA
|
||||
m_l_state = PHI_L_LADS;
|
||||
if (get_signal(PHI_488_REN)) {
|
||||
m_rl_rems = true;
|
||||
}
|
||||
m_sa_state = PHI_SA_LPAS;
|
||||
}
|
||||
} else if (ag == IFCMD_TAG_VALUE) {
|
||||
// TAG
|
||||
if (!ton_msg()) {
|
||||
if (my_addr) {
|
||||
// MTA
|
||||
m_t_state = PHI_T_TADS;
|
||||
} else {
|
||||
// OTA
|
||||
m_t_state = PHI_T_TIDS;
|
||||
}
|
||||
if (my_addr) {
|
||||
// MTA
|
||||
m_t_state = PHI_T_TADS;
|
||||
m_sa_state = PHI_SA_TPAS;
|
||||
} else if (!ton_msg()) {
|
||||
// OTA
|
||||
m_t_state = PHI_T_TIDS;
|
||||
}
|
||||
} else if (ag == IFCMD_SCG_VALUE) {
|
||||
// SCG
|
||||
if (m_pp_pacs) {
|
||||
switch (m_sa_state) {
|
||||
case PHI_SA_NONE:
|
||||
break;
|
||||
|
||||
case PHI_SA_PACS:
|
||||
if ((byte & IFCMD_PPX_MASK) == IFCMD_PPE_VALUE && m_pp_state == PHI_PP_PPIS) {
|
||||
// PPE
|
||||
m_s_sense = BIT(byte , IFCMD_PPE_S_BIT);
|
||||
m_ppr_msg = byte & IFCMD_PPE_PPR_MASK;
|
||||
LOG("PPE s=%d ppr=%u\n" , m_s_sense , m_ppr_msg);
|
||||
m_pp_state = PHI_PP_PPSS;
|
||||
} else if ((byte & IFCMD_PPX_MASK) == IFCMD_PPD_VALUE && m_pp_state == PHI_PP_PPSS) {
|
||||
// PPD
|
||||
m_pp_state = PHI_PP_PPIS;
|
||||
}
|
||||
} else {
|
||||
// command is a secondary address
|
||||
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) {
|
||||
// Unaddressed by OSA
|
||||
m_t_state = PHI_T_ID1;
|
||||
} else if (m_t_state == PHI_T_TADS || m_l_state == PHI_L_LADS) {
|
||||
if (m_fifo_in.full() || BIT(m_reg_int_cond , REG_INT_DEV_CLEAR_BIT)) {
|
||||
// No room for secondary address in FIFO, stall handshake
|
||||
accepted = false;
|
||||
} else {
|
||||
uint16_t word = REG_IFIFO_2_ADDR_MASK | address;
|
||||
if (m_t_state == PHI_T_TADS) {
|
||||
BIT_SET(word, REG_IFIFO_TALK_BIT);
|
||||
}
|
||||
rx_n_data_freeze(word);
|
||||
break;
|
||||
|
||||
case PHI_SA_TPAS:
|
||||
case PHI_SA_LPAS:
|
||||
// command is a secondary address after MTA or MLA
|
||||
if (m_fifo_in.full() || BIT(m_reg_int_cond , REG_INT_DEV_CLEAR_BIT)) {
|
||||
// No room for secondary address in FIFO, stall handshake
|
||||
accepted = false;
|
||||
} else {
|
||||
uint16_t word = REG_IFIFO_2_ADDR_MASK | address;
|
||||
if (m_sa_state == PHI_SA_TPAS) {
|
||||
BIT_SET(word, REG_IFIFO_TALK_BIT);
|
||||
}
|
||||
rx_n_data_freeze(word);
|
||||
}
|
||||
break;
|
||||
|
||||
case PHI_SA_UNT:
|
||||
if (my_addr) {
|
||||
// Start IDENTIFY sequence
|
||||
m_t_state = PHI_T_ID1;
|
||||
} else {
|
||||
// Unaddressed by OSA (== UNT)
|
||||
if_cmd_received(IFCMD_UNT);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1299,20 +1342,20 @@ bool phi_device::byte_received(uint8_t byte , bool eoi)
|
||||
}
|
||||
}
|
||||
|
||||
LOG(("RX word:%04x\n" , word));
|
||||
LOG("%.6f RX word:%04x\n" , machine().time().as_double() , word);
|
||||
|
||||
if (m_l_state == PHI_L_LACS) {
|
||||
if (m_fifo_in.full() || BIT(m_reg_int_cond , REG_INT_DEV_CLEAR_BIT)) {
|
||||
// No room for received byte, stall handshake
|
||||
LOG_0(("..stalled\n"));
|
||||
LOG_NOISY("..stalled\n");
|
||||
return false;
|
||||
} else {
|
||||
LOG_0(("..OK\n"));
|
||||
LOG_NOISY("..OK\n");
|
||||
rx_n_data_freeze(word);
|
||||
}
|
||||
}
|
||||
if (end_of_transfer) {
|
||||
LOG_0(("End of byte transfer enable\n"));
|
||||
LOG_NOISY("End of byte transfer enable\n");
|
||||
m_fifo_out.dequeue();
|
||||
m_be_counter = 0;
|
||||
} else {
|
||||
@ -1325,7 +1368,7 @@ bool phi_device::byte_received(uint8_t byte , bool eoi)
|
||||
void phi_device::rx_n_data_freeze(uint16_t word)
|
||||
{
|
||||
m_fifo_in.enqueue(word);
|
||||
if (m_sh_state != PHI_SH_STRS) {
|
||||
if (!controller_in_charge() && m_sh_state != PHI_SH_STRS) {
|
||||
// If PHI didn't send this byte to itself, set data freeze
|
||||
BIT_SET(m_reg_status, REG_STATUS_DATA_FREEZE_BIT);
|
||||
}
|
||||
@ -1364,22 +1407,84 @@ bool phi_device::tcs_msg(void) const
|
||||
bool new_eoi;
|
||||
|
||||
// When the CIC takes back control synchronously:
|
||||
// * Nothing in OFIFO
|
||||
// * Request to start parallel poll is pending
|
||||
// * Request to start parallel poll is pending (i.e. OFIFO is empty)
|
||||
// * There's an interface command to be sent at head of OFIFO
|
||||
return (m_c_state == PHI_C_CSBS || m_c_state == PHI_C_CSHS || m_c_state == PHI_C_CSWS) &&
|
||||
(m_fifo_out.empty() ||
|
||||
rpp_msg() ||
|
||||
(rpp_msg() ||
|
||||
nba_msg(new_byte , new_eoi) == NBA_CMD_FROM_OFIFO);
|
||||
}
|
||||
|
||||
bool phi_device::rpp_msg(void) const
|
||||
{
|
||||
// TODO:
|
||||
return false;
|
||||
return m_fifo_out.empty();
|
||||
}
|
||||
|
||||
uint8_t phi_device::get_pp_response()
|
||||
{
|
||||
return (get_dio() ^ m_reg_2nd_id) & m_reg_1st_id;
|
||||
}
|
||||
|
||||
bool phi_device::controller_in_charge(void) const
|
||||
{
|
||||
return m_c_state != PHI_C_CIDS;
|
||||
}
|
||||
|
||||
void phi_device::configure_pp_response()
|
||||
{
|
||||
uint8_t addr = (m_reg_address >> REG_ADDR_HPIB_ADDR_BIT) & 0x1f;
|
||||
if (addr <= 7) {
|
||||
// If address <= 7, PP is automatically enabled and configured for PPR = ~address
|
||||
m_ppr_msg = addr ^ 7;
|
||||
m_pp_state = PHI_PP_PPSS;
|
||||
} else {
|
||||
m_ppr_msg = 0;
|
||||
m_pp_state = PHI_PP_PPIS;
|
||||
}
|
||||
m_s_sense = true;
|
||||
}
|
||||
|
||||
void phi_device::update_pp()
|
||||
{
|
||||
if (m_c_state == PHI_C_CPPS) {
|
||||
if (m_fifo_in.empty() && get_pp_response()) {
|
||||
BIT_SET(m_reg_int_cond , REG_INT_PP_RESPONSE_BIT);
|
||||
} else {
|
||||
BIT_CLR(m_reg_int_cond , REG_INT_PP_RESPONSE_BIT);
|
||||
}
|
||||
update_interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
void phi_device::update_interrupt()
|
||||
{
|
||||
bool int_pending = (m_reg_int_cond & m_reg_int_mask) != 0;
|
||||
bool int_line = false;
|
||||
if (int_pending) {
|
||||
BIT_SET(m_reg_int_cond, REG_INT_PENDING_BIT);
|
||||
if (BIT(m_reg_int_mask , REG_INT_PENDING_BIT)) {
|
||||
int_line = true;
|
||||
}
|
||||
} else {
|
||||
BIT_CLR(m_reg_int_cond, REG_INT_PENDING_BIT);
|
||||
}
|
||||
if (int_line != m_int_line) {
|
||||
m_int_line = int_line;
|
||||
LOG_INT("INT %d\n" , m_int_line);
|
||||
m_int_write_func(m_int_line);
|
||||
}
|
||||
}
|
||||
|
||||
void phi_device::update_dmarq()
|
||||
{
|
||||
bool new_dmarq_line;
|
||||
if (BIT(m_reg_control , REG_CTRL_DMA_FIFO_BIT)) {
|
||||
new_dmarq_line = BIT(m_reg_int_cond , REG_INT_FIFO_ROOM_BIT);
|
||||
} else {
|
||||
new_dmarq_line = BIT(m_reg_int_cond , REG_INT_FIFO_AV_BIT);
|
||||
}
|
||||
if (new_dmarq_line != m_dmarq_line) {
|
||||
m_dmarq_line = new_dmarq_line;
|
||||
LOG_INT("DRQ %d\n" , m_dmarq_line);
|
||||
m_dmarq_write_func(m_dmarq_line);
|
||||
}
|
||||
}
|
||||
|
@ -49,6 +49,10 @@
|
||||
#define MCFG_PHI_DMARQ_WRITE_CB(_write) \
|
||||
downcast<phi_device &>(*device).set_dmarq_write_cb(DEVCB_##_write);
|
||||
|
||||
// Set read callback for SYS_CNTRL signal
|
||||
#define MCFG_PHI_SYS_CNTRL_READ_CB(_read) \
|
||||
downcast<phi_device &>(*device).set_sys_cntrl_read_cb(DEVCB_##_read);
|
||||
|
||||
class phi_device : public device_t
|
||||
{
|
||||
public:
|
||||
@ -68,11 +72,23 @@ public:
|
||||
PHI_488_SIGNAL_COUNT
|
||||
};
|
||||
|
||||
template<class Object> devcb_base& set_dio_read_cb(Object &&cb) { return m_dio_read_func.set_callback(std::forward<Object>(cb)); }
|
||||
template<class Object> devcb_base& set_dio_write_cb(Object &&cb) { return m_dio_write_func.set_callback(std::forward<Object>(cb)); }
|
||||
template<class Object> devcb_base& set_488_signal_write_cb(phi_488_signal_t signal , Object &&cb) { return m_signal_wr_fns[ signal ].set_callback(std::forward<Object>(cb)); }
|
||||
template<class Object> devcb_base& set_int_write_cb(Object &&cb) { return m_int_write_func.set_callback(std::forward<Object>(cb)); }
|
||||
template<class Object> devcb_base& set_dmarq_write_cb(Object &&cb) { return m_dmarq_write_func.set_callback(std::forward<Object>(cb)); }
|
||||
template <class Object> devcb_base& set_dio_read_cb(Object &&cb)
|
||||
{ return m_dio_read_func.set_callback(std::forward<Object>(cb)); }
|
||||
|
||||
template <class Object> devcb_base& set_dio_write_cb(Object &&cb)
|
||||
{ return m_dio_write_func.set_callback(std::forward<Object>(cb)); }
|
||||
|
||||
template <class Object> devcb_base& set_488_signal_write_cb(phi_488_signal_t signal , Object &&cb)
|
||||
{ return m_signal_wr_fns[ signal ].set_callback(std::forward<Object>(cb)); }
|
||||
|
||||
template <class Object> devcb_base& set_int_write_cb(Object &&cb)
|
||||
{ return m_int_write_func.set_callback(std::forward<Object>(cb)); }
|
||||
|
||||
template <class Object> devcb_base& set_dmarq_write_cb(Object &&cb)
|
||||
{ return m_dmarq_write_func.set_callback(std::forward<Object>(cb)); }
|
||||
|
||||
template <class Object> devcb_base &set_sys_cntrl_read_cb(Object &&cb)
|
||||
{ return m_sys_cntrl_read_func.set_callback(std::forward<Object>(cb)); }
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(eoi_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(dav_w);
|
||||
@ -83,6 +99,8 @@ public:
|
||||
DECLARE_WRITE_LINE_MEMBER(atn_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(ren_w);
|
||||
|
||||
DECLARE_WRITE8_MEMBER(bus_dio_w);
|
||||
|
||||
void set_ext_signal(phi_488_signal_t signal , int state);
|
||||
|
||||
// Register read/write
|
||||
@ -127,7 +145,7 @@ private:
|
||||
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;
|
||||
|
||||
devcb_read_line m_sys_cntrl_read_func;
|
||||
bool m_int_line;
|
||||
bool m_dmarq_line;
|
||||
|
||||
@ -172,12 +190,11 @@ private:
|
||||
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
|
||||
PHI_T_ID1, // Addressed by secondary address
|
||||
PHI_T_ID2, // Sending 1st byte
|
||||
PHI_T_ID3, // Waiting to send 2nd byte
|
||||
PHI_T_ID4, // Sending 2nd byte
|
||||
PHI_T_ID5 // 2nd byte sent, end of sequence
|
||||
};
|
||||
|
||||
int m_t_state;
|
||||
@ -201,6 +218,9 @@ private:
|
||||
|
||||
int m_sr_state;
|
||||
|
||||
// RL (Remote Local) states
|
||||
bool m_rl_rems; // false: LOCS, true: REMS
|
||||
|
||||
// PP (Parallel poll) states
|
||||
enum {
|
||||
PHI_PP_PPIS,
|
||||
@ -209,7 +229,6 @@ private:
|
||||
};
|
||||
|
||||
int m_pp_state;
|
||||
bool m_pp_pacs;
|
||||
uint8_t m_ppr_msg;
|
||||
bool m_s_sense;
|
||||
|
||||
@ -218,7 +237,6 @@ private:
|
||||
PHI_C_CIDS,
|
||||
PHI_C_CADS,
|
||||
PHI_C_CACS,
|
||||
PHI_C_CPWS,
|
||||
PHI_C_CPPS,
|
||||
PHI_C_CSBS,
|
||||
PHI_C_CSHS,
|
||||
@ -228,6 +246,18 @@ private:
|
||||
};
|
||||
|
||||
int m_c_state;
|
||||
|
||||
// Secondary address decoder states
|
||||
enum {
|
||||
PHI_SA_NONE,
|
||||
PHI_SA_PACS,
|
||||
PHI_SA_TPAS,
|
||||
PHI_SA_LPAS,
|
||||
PHI_SA_UNT
|
||||
};
|
||||
|
||||
int m_sa_state;
|
||||
|
||||
uint8_t m_be_counter;
|
||||
uint16_t m_reg_status;
|
||||
uint16_t m_reg_int_cond;
|
||||
@ -244,8 +274,8 @@ private:
|
||||
NBA_CMD_FROM_OFIFO,
|
||||
NBA_BYTE_FROM_OFIFO,
|
||||
NBA_FROM_SPAS,
|
||||
NBA_FROM_ID3,
|
||||
NBA_FROM_ID5
|
||||
NBA_FROM_ID2,
|
||||
NBA_FROM_ID4
|
||||
} nba_origin_t;
|
||||
|
||||
int m_nba_origin;
|
||||
@ -275,7 +305,12 @@ private:
|
||||
uint8_t my_address(void) const;
|
||||
bool tcs_msg(void) const;
|
||||
bool rpp_msg(void) const;
|
||||
uint8_t get_pp_response();
|
||||
bool controller_in_charge(void) const;
|
||||
void configure_pp_response();
|
||||
void update_pp();
|
||||
void update_interrupt();
|
||||
void update_dmarq();
|
||||
};
|
||||
|
||||
// device type definition
|
||||
|
@ -59,7 +59,7 @@
|
||||
// exponentially decaying envelope (a bell sound) whereas in the emulation it's inside a
|
||||
// simple rectangular envelope.
|
||||
//
|
||||
//*U20 HP "PHI" Custom HP-IB interface microcontroller
|
||||
// U20 HP "PHI" Custom HP-IB interface microcontroller
|
||||
// U28 i8251 RS232 UART
|
||||
//
|
||||
// **********
|
||||
@ -145,9 +145,6 @@
|
||||
// 1 Enable drive 0 motor (0)
|
||||
// 0 Enable drive 0 (0)
|
||||
//
|
||||
//
|
||||
// ICs that are not emulated yet are marked with "*"
|
||||
//
|
||||
|
||||
#include "emu.h"
|
||||
#include "bus/rs232/rs232.h"
|
||||
@ -162,6 +159,8 @@
|
||||
#include "video/i8275.h"
|
||||
#include "screen.h"
|
||||
#include "speaker.h"
|
||||
#include "machine/phi.h"
|
||||
#include "bus/ieee488/ieee488.h"
|
||||
|
||||
#define BIT_MASK(n) (1U << (n))
|
||||
|
||||
@ -228,6 +227,11 @@ public:
|
||||
DECLARE_WRITE_LINE_MEMBER(hp64k_rs232_dcd_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(hp64k_rs232_cts_w);
|
||||
|
||||
DECLARE_READ16_MEMBER(hp64k_phi_r);
|
||||
DECLARE_WRITE16_MEMBER(hp64k_phi_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(hp64k_phi_int_w);
|
||||
DECLARE_READ_LINE_MEMBER(hp64k_phi_sys_ctrl_r);
|
||||
|
||||
DECLARE_WRITE16_MEMBER(hp64k_beep_w);
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(hp64k_beeper_off);
|
||||
|
||||
@ -256,6 +260,7 @@ private:
|
||||
required_ioport m_s5_sw;
|
||||
required_device<i8251_device> m_uart;
|
||||
required_device<rs232_port_device> m_rs232;
|
||||
required_device<phi_device> m_phi;
|
||||
|
||||
// Character generator
|
||||
const uint8_t *m_chargen;
|
||||
@ -314,6 +319,9 @@ private:
|
||||
bool m_txd_state;
|
||||
bool m_dtr_state;
|
||||
bool m_rts_state;
|
||||
|
||||
// HPIB I/F
|
||||
uint8_t m_phi_reg;
|
||||
};
|
||||
|
||||
ADDRESS_MAP_START(hp64k_state::cpu_mem_map)
|
||||
@ -339,6 +347,9 @@ ADDRESS_MAP_START(hp64k_state::cpu_io_map)
|
||||
// PA = 6, IC = [0..3]
|
||||
// Read from USART
|
||||
AM_RANGE(HP_MAKE_IOADDR(6 , 0) , HP_MAKE_IOADDR(6 , 3)) AM_READ(hp64k_usart_r)
|
||||
// PA = 7, IC = 1
|
||||
// PHI
|
||||
AM_RANGE(HP_MAKE_IOADDR(7 , 1) , HP_MAKE_IOADDR(7 , 1)) AM_READWRITE(hp64k_phi_r , hp64k_phi_w)
|
||||
// PA = 7, IC = 2
|
||||
// Rear-panel switches and loopback relay control
|
||||
AM_RANGE(HP_MAKE_IOADDR(7 , 2) , HP_MAKE_IOADDR(7 , 2)) AM_READWRITE(hp64k_rear_sw_r , hp64k_loopback_w)
|
||||
@ -374,7 +385,8 @@ hp64k_state::hp64k_state(const machine_config &mconfig, device_type type, const
|
||||
m_baud_rate(*this , "baud_rate"),
|
||||
m_s5_sw(*this , "s5_sw"),
|
||||
m_uart(*this , "uart"),
|
||||
m_rs232(*this , "rs232")
|
||||
m_rs232(*this , "rs232"),
|
||||
m_phi(*this , "phi")
|
||||
{
|
||||
}
|
||||
|
||||
@ -418,7 +430,7 @@ void hp64k_state::machine_reset()
|
||||
m_txd_state = true;
|
||||
m_dtr_state = true;
|
||||
m_rts_state = true;
|
||||
|
||||
m_phi_reg = 0;
|
||||
}
|
||||
|
||||
uint8_t hp64k_state::hp64k_crtc_filter(uint8_t data)
|
||||
@ -1027,6 +1039,7 @@ WRITE_LINE_MEMBER(hp64k_state::hp64k_rts_w)
|
||||
|
||||
WRITE16_MEMBER(hp64k_state::hp64k_loopback_w)
|
||||
{
|
||||
m_phi_reg = (uint8_t)((data >> 8) & 7);
|
||||
m_loopback = BIT(data , 11);
|
||||
hp64k_update_loopback();
|
||||
}
|
||||
@ -1058,6 +1071,16 @@ WRITE_LINE_MEMBER(hp64k_state::hp64k_rs232_dcd_w)
|
||||
}
|
||||
}
|
||||
|
||||
READ16_MEMBER(hp64k_state::hp64k_phi_r)
|
||||
{
|
||||
return m_phi->reg16_r(space , m_phi_reg , mem_mask);
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(hp64k_state::hp64k_phi_w)
|
||||
{
|
||||
m_phi->reg16_w(space , m_phi_reg , data , mem_mask);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(hp64k_state::hp64k_rs232_cts_w)
|
||||
{
|
||||
if (!m_loopback) {
|
||||
@ -1065,6 +1088,22 @@ WRITE_LINE_MEMBER(hp64k_state::hp64k_rs232_cts_w)
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(hp64k_state::hp64k_phi_int_w)
|
||||
{
|
||||
if (state) {
|
||||
BIT_SET(m_irl_pending , 7);
|
||||
} else {
|
||||
BIT_CLR(m_irl_pending , 7);
|
||||
}
|
||||
|
||||
hp64k_update_irl();
|
||||
}
|
||||
|
||||
READ_LINE_MEMBER(hp64k_state::hp64k_phi_sys_ctrl_r)
|
||||
{
|
||||
return BIT(m_rear_panel_sw->read() , 6);
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(hp64k_state::hp64k_beep_w)
|
||||
{
|
||||
if (!BIT(offset , 0)) {
|
||||
@ -1254,6 +1293,9 @@ static INPUT_PORTS_START(hp64k)
|
||||
PORT_DIPNAME(0x0400 , 0x0400 , "E9-1 jumper")
|
||||
PORT_DIPSETTING(0x0000 , DEF_STR(Yes))
|
||||
PORT_DIPSETTING(0x0400 , DEF_STR(No))
|
||||
PORT_DIPNAME(0x0040 , 0x0000 , "System controller")
|
||||
PORT_DIPSETTING(0x0000 , DEF_STR(No))
|
||||
PORT_DIPSETTING(0x0040 , DEF_STR(Yes))
|
||||
PORT_DIPNAME(0x0018 , 0x0000 , "System source")
|
||||
PORT_DIPLOCATION("S1:!7,!6")
|
||||
PORT_DIPSETTING(0x0000 , "Sys bus")
|
||||
@ -1410,6 +1452,30 @@ MACHINE_CONFIG_START(hp64k_state::hp64k)
|
||||
MCFG_RS232_DCD_HANDLER(WRITELINE(hp64k_state , hp64k_rs232_dcd_w))
|
||||
MCFG_RS232_CTS_HANDLER(WRITELINE(hp64k_state , hp64k_rs232_cts_w))
|
||||
|
||||
MCFG_DEVICE_ADD("phi" , PHI , 0)
|
||||
MCFG_PHI_INT_WRITE_CB(WRITELINE(hp64k_state , hp64k_phi_int_w))
|
||||
MCFG_PHI_DMARQ_WRITE_CB(DEVWRITELINE("cpu" , hp_5061_3011_cpu_device , halt_w))
|
||||
MCFG_PHI_SYS_CNTRL_READ_CB(READLINE(hp64k_state , hp64k_phi_sys_ctrl_r))
|
||||
MCFG_PHI_DIO_READWRITE_CB(DEVREAD8(IEEE488_TAG , ieee488_device , dio_r) , DEVWRITE8(IEEE488_TAG , ieee488_device , dio_w))
|
||||
MCFG_PHI_EOI_WRITE_CB(DEVWRITELINE(IEEE488_TAG , ieee488_device , eoi_w))
|
||||
MCFG_PHI_DAV_WRITE_CB(DEVWRITELINE(IEEE488_TAG , ieee488_device , dav_w))
|
||||
MCFG_PHI_NRFD_WRITE_CB(DEVWRITELINE(IEEE488_TAG , ieee488_device , nrfd_w))
|
||||
MCFG_PHI_NDAC_WRITE_CB(DEVWRITELINE(IEEE488_TAG , ieee488_device , ndac_w))
|
||||
MCFG_PHI_IFC_WRITE_CB(DEVWRITELINE(IEEE488_TAG , ieee488_device , ifc_w))
|
||||
MCFG_PHI_SRQ_WRITE_CB(DEVWRITELINE(IEEE488_TAG , ieee488_device , srq_w))
|
||||
MCFG_PHI_ATN_WRITE_CB(DEVWRITELINE(IEEE488_TAG , ieee488_device , atn_w))
|
||||
MCFG_PHI_REN_WRITE_CB(DEVWRITELINE(IEEE488_TAG , ieee488_device , ren_w))
|
||||
MCFG_IEEE488_BUS_ADD()
|
||||
MCFG_IEEE488_EOI_CALLBACK(DEVWRITELINE("phi" , phi_device , eoi_w))
|
||||
MCFG_IEEE488_DAV_CALLBACK(DEVWRITELINE("phi" , phi_device , dav_w))
|
||||
MCFG_IEEE488_NRFD_CALLBACK(DEVWRITELINE("phi" , phi_device , nrfd_w))
|
||||
MCFG_IEEE488_NDAC_CALLBACK(DEVWRITELINE("phi" , phi_device , ndac_w))
|
||||
MCFG_IEEE488_IFC_CALLBACK(DEVWRITELINE("phi" , phi_device , ifc_w))
|
||||
MCFG_IEEE488_SRQ_CALLBACK(DEVWRITELINE("phi" , phi_device , srq_w))
|
||||
MCFG_IEEE488_ATN_CALLBACK(DEVWRITELINE("phi" , phi_device , atn_w))
|
||||
MCFG_IEEE488_REN_CALLBACK(DEVWRITELINE("phi" , phi_device , ren_w))
|
||||
MCFG_IEEE488_DIO_CALLBACK(DEVWRITE8("phi" , phi_device , bus_dio_w))
|
||||
// Feel so lonely here... waiting for the 488 remotizer ;)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
ROM_START(hp64k)
|
||||
|
Loading…
Reference in New Issue
Block a user