HP IPC: support for I/O slots and 82919 serial card added (#7001)

* mc68681: tx/rx clocking from timer fixed, added partial support for
break signal

* hp_ipc: support for I/O slots added, 82919 serial I/O card added
This commit is contained in:
fulivi 2020-07-27 20:12:05 +02:00 committed by GitHub
parent b31859d6c5
commit 943fc34f39
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 668 additions and 35 deletions

View File

@ -4103,6 +4103,20 @@ if (BUSES["HP9845_IO"]~=null) then
}
end
---------------------------------------------------
--
--@src/devices/bus/hp_ipc_io/hp_ipc_io.h,BUSES["HP_IPC_IO"] = true
---------------------------------------------------
if (BUSES["HP_IPC_IO"]~=null) then
files {
MAME_DIR .. "src/devices/bus/hp_ipc_io/hp_ipc_io.cpp",
MAME_DIR .. "src/devices/bus/hp_ipc_io/hp_ipc_io.h",
MAME_DIR .. "src/devices/bus/hp_ipc_io/82919.cpp",
MAME_DIR .. "src/devices/bus/hp_ipc_io/829919.h",
}
end
---------------------------------------------------
--
--@src/devices/bus/compis/graphics.h,BUSES["COMPIS_GRAPHICS"] = true

View File

@ -860,6 +860,7 @@ BUSES["ISBX"] = true
BUSES["JAKKS_GAMEKEY"] = true
BUSES["HP80_IO"] = true
BUSES["HP9845_IO"] = true
BUSES["HP_IPC_IO"] = true
BUSES["KC"] = true
BUSES["LPCI"] = true
BUSES["M5"] = true

View File

@ -0,0 +1,252 @@
// license:BSD-3-Clause
// copyright-holders: F. Ulivi
/*********************************************************************
82919.cpp
82919 module (RS232 interface)
Main reference for this module is:
HP 82919-90009, feb 85, HP82919A Integral PC Serial Interface -
Component level service manual
*********************************************************************/
#include "emu.h"
#include "82919.h"
#include "coreutil.h"
// Debugging
#define VERBOSE 0
#include "logmacro.h"
// Bit manipulation
namespace {
template<typename T> constexpr T BIT_MASK(unsigned n)
{
return (T)1U << n;
}
template<typename T> void BIT_SET(T& w , unsigned n)
{
w |= BIT_MASK<T>(n);
}
}
hp82919_io_card_device::hp82919_io_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig , HP82919_IO_CARD , tag , owner , clock)
, device_hp_ipc_io_interface(mconfig, *this)
, m_rs232_prim(*this , "rs232_prim")
, m_rs232_sec(*this , "rs232_sec")
, m_uart(*this , "uart")
, m_loopback_en(*this, "loop")
{
}
hp82919_io_card_device::~hp82919_io_card_device()
{
}
uint8_t hp82919_io_card_device::read(offs_t addr)
{
uint8_t res = 0;
offs_t uart_addr = (addr ^ 0xc) & 0xf;
if (BIT(addr , 4)) {
res = m_uart->read(uart_addr);
} else {
// 2 is 82919 ID code
res = 2;
res |= (m_int_level << 4);
if (m_int_pending) {
BIT_SET(res , 6);
}
if (m_int_en) {
BIT_SET(res , 7);
}
m_uart->write(uart_addr , res);
}
LOG("RD %04x=%02x\n" , addr , res);
return res;
}
void hp82919_io_card_device::write(offs_t addr , uint8_t data)
{
LOG("WR %04x=%02x\n" , addr , data);
offs_t uart_addr = (addr ^ 0xc) & 0xf;
m_uart->write(uart_addr , data);
if (!BIT(addr , 4)) {
m_int_level = (data >> 4) & 3;
m_int_forced = BIT(data , 6);
m_int_en = BIT(data , 7);
update_irq();
}
}
WRITE_LINE_MEMBER(hp82919_io_card_device::uart_irq)
{
m_uart_int = state;
update_irq();
}
WRITE_LINE_MEMBER(hp82919_io_card_device::uart_a_tx)
{
m_rs232_prim->write_txd(state);
if (m_loopback) {
m_uart->rx_b_w(state);
}
}
WRITE_LINE_MEMBER(hp82919_io_card_device::uart_b_tx)
{
m_rs232_sec->write_txd(state);
if (m_loopback) {
m_uart->rx_a_w(state);
}
}
void hp82919_io_card_device::uart_output(uint8_t data)
{
m_rs232_prim->write_dtr(BIT(data , 0));
m_rs232_prim->write_rts(BIT(data , 1));
// b2 is TxClock
m_rs232_prim->write_spds(BIT(data , 3));
m_rs232_sec->write_rts(BIT(data , 4));
if (m_loopback) {
m_uart->ip0_w(BIT(data , 0));
m_uart->ip1_w(BIT(data , 1));
m_uart->ip2_w(BIT(data , 2));
m_uart->ip3_w(BIT(data , 3));
m_uart->ip4_w(BIT(data , 4));
m_uart->ip5_w(BIT(data , 4));
}
}
WRITE_LINE_MEMBER(hp82919_io_card_device::prim_rxd)
{
if (!m_loopback) {
m_uart->rx_a_w(state);
}
}
WRITE_LINE_MEMBER(hp82919_io_card_device::prim_dcd)
{
if (!m_loopback) {
m_uart->ip3_w(state);
}
}
WRITE_LINE_MEMBER(hp82919_io_card_device::prim_dsr)
{
if (!m_loopback) {
m_uart->ip1_w(state);
}
}
WRITE_LINE_MEMBER(hp82919_io_card_device::prim_ri)
{
if (!m_loopback) {
m_uart->ip2_w(state);
}
}
WRITE_LINE_MEMBER(hp82919_io_card_device::prim_cts)
{
if (!m_loopback) {
m_uart->ip0_w(state);
}
}
WRITE_LINE_MEMBER(hp82919_io_card_device::sec_rxd)
{
if (!m_loopback) {
m_uart->rx_b_w(state);
}
}
WRITE_LINE_MEMBER(hp82919_io_card_device::sec_dcd)
{
if (!m_loopback) {
m_uart->ip5_w(state);
}
}
WRITE_LINE_MEMBER(hp82919_io_card_device::sec_cts)
{
if (!m_loopback) {
m_uart->ip4_w(state);
}
}
void hp82919_io_card_device::install_read_write_handlers(address_space& space , uint32_t base_addr)
{
offs_t end_addr = base_addr + 0xffffU;
// Supervisor mode
space.install_readwrite_handler(base_addr, end_addr, read8sm_delegate(*this, FUNC(hp82919_io_card_device::read)), write8sm_delegate(*this, FUNC(hp82919_io_card_device::write)), 0x00ff);
// User mode
space.install_readwrite_handler(base_addr + USER_SPACE_OFFSET, end_addr + USER_SPACE_OFFSET, read8sm_delegate(*this, FUNC(hp82919_io_card_device::read)), write8sm_delegate(*this, FUNC(hp82919_io_card_device::write)), 0x00ff);
}
void hp82919_io_card_device::device_start()
{
}
void hp82919_io_card_device::device_reset()
{
m_loopback = m_loopback_en->read() != 0;
m_int_level = 0;
m_int_forced = false;
m_int_en = false;
m_uart_int = false;
m_irq = true;
update_irq();
}
void hp82919_io_card_device::device_add_mconfig(machine_config &config)
{
RS232_PORT(config, m_rs232_prim, default_rs232_devices, nullptr);
RS232_PORT(config, m_rs232_sec, default_rs232_devices, nullptr);
MC68681(config , m_uart , 3.6864_MHz_XTAL);
m_uart->irq_cb().set(FUNC(hp82919_io_card_device::uart_irq));
m_uart->a_tx_cb().set(FUNC(hp82919_io_card_device::uart_a_tx));
m_uart->b_tx_cb().set(FUNC(hp82919_io_card_device::uart_b_tx));
m_uart->outport_cb().set(FUNC(hp82919_io_card_device::uart_output));
m_rs232_prim->rxd_handler().set(FUNC(hp82919_io_card_device::prim_rxd));
m_rs232_prim->dcd_handler().set(FUNC(hp82919_io_card_device::prim_dcd));
m_rs232_prim->dsr_handler().set(FUNC(hp82919_io_card_device::prim_dsr));
m_rs232_prim->ri_handler().set(FUNC(hp82919_io_card_device::prim_ri));
m_rs232_prim->cts_handler().set(FUNC(hp82919_io_card_device::prim_cts));
m_rs232_sec->rxd_handler().set(FUNC(hp82919_io_card_device::sec_rxd));
m_rs232_sec->dcd_handler().set(FUNC(hp82919_io_card_device::sec_dcd));
m_rs232_sec->cts_handler().set(FUNC(hp82919_io_card_device::sec_cts));
}
static INPUT_PORTS_START(hp82919_port)
PORT_START("loop")
PORT_CONFNAME(1 , 0 , "Test loopback")
PORT_CONFSETTING(0 , DEF_STR(Off))
PORT_CONFSETTING(1 , DEF_STR(On))
INPUT_PORTS_END
ioport_constructor hp82919_io_card_device::device_input_ports() const
{
return INPUT_PORTS_NAME(hp82919_port);
}
void hp82919_io_card_device::update_irq()
{
m_int_pending = m_int_forced || m_uart_int;
bool irq = m_int_en && m_int_pending;
if (m_irq != irq) {
m_irq = irq;
LOG("IRQ %u=%d\n" , m_int_level , irq);
irq_w(m_int_level , irq);
}
}
// device type definition
DEFINE_DEVICE_TYPE(HP82919_IO_CARD, hp82919_io_card_device, "hp82919", "HP82919 card")

View File

@ -0,0 +1,73 @@
// license:BSD-3-Clause
// copyright-holders: F. Ulivi
/*********************************************************************
82919.h
82919 module (RS232 interface)
*********************************************************************/
#ifndef MAME_BUS_HP_IPC_IO_82919_H
#define MAME_BUS_HP_IPC_IO_82919_H
#pragma once
#include "hp_ipc_io.h"
#include "machine/mc68681.h"
#include "bus/rs232/rs232.h"
class hp82919_io_card_device : public device_t, public device_hp_ipc_io_interface
{
public:
// construction/destruction
hp82919_io_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~hp82919_io_card_device();
uint8_t read(offs_t addr);
void write(offs_t addr , uint8_t data);
DECLARE_WRITE_LINE_MEMBER(uart_irq);
DECLARE_WRITE_LINE_MEMBER(uart_a_tx);
DECLARE_WRITE_LINE_MEMBER(uart_b_tx);
void uart_output(uint8_t data);
DECLARE_WRITE_LINE_MEMBER(prim_rxd);
DECLARE_WRITE_LINE_MEMBER(prim_dcd);
DECLARE_WRITE_LINE_MEMBER(prim_dsr);
DECLARE_WRITE_LINE_MEMBER(prim_ri);
DECLARE_WRITE_LINE_MEMBER(prim_cts);
DECLARE_WRITE_LINE_MEMBER(sec_rxd);
DECLARE_WRITE_LINE_MEMBER(sec_dcd);
DECLARE_WRITE_LINE_MEMBER(sec_cts);
protected:
virtual void device_start() override;
virtual void device_reset() override;
// device-level overrides
virtual void device_add_mconfig(machine_config &config) override;
virtual ioport_constructor device_input_ports() const override;
virtual void install_read_write_handlers(address_space& space , uint32_t base_addr) override;
private:
required_device<rs232_port_device> m_rs232_prim;
required_device<rs232_port_device> m_rs232_sec;
required_device<mc68681_device> m_uart;
required_ioport m_loopback_en;
uint8_t m_int_level;
bool m_int_en;
bool m_int_forced;
bool m_int_pending;
bool m_uart_int;
bool m_irq;
bool m_loopback;
void update_irq();
};
// device type definition
DECLARE_DEVICE_TYPE(HP82919_IO_CARD, hp82919_io_card_device)
#endif // MAME_BUS_HP_IPC_IO_82919_H

View File

@ -0,0 +1,86 @@
// license:BSD-3-Clause
// copyright-holders: F. Ulivi
/*********************************************************************
hp_ipc_io.cpp
I/O bus of HP IPC system
*********************************************************************/
#include "emu.h"
#include "hp_ipc_io.h"
// Debugging
#define VERBOSE 0
#include "logmacro.h"
// device type definition
DEFINE_DEVICE_TYPE(HP_IPC_IO_SLOT, hp_ipc_io_slot_device, "hp ipc io slot", "HP IPC I/O Slot")
// +---------------------+
// |hp_ipc_io_slot_device|
// +---------------------+
hp_ipc_io_slot_device::hp_ipc_io_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, HP_IPC_IO_SLOT, tag, owner, clock),
device_single_card_slot_interface<device_hp_ipc_io_interface>(mconfig, *this),
m_irq_cb_func(*this),
m_slot_idx(0)
{
}
hp_ipc_io_slot_device::~hp_ipc_io_slot_device()
{
}
void hp_ipc_io_slot_device::device_start()
{
m_irq_cb_func.resolve_all_safe();
}
uint32_t hp_ipc_io_slot_device::get_slot_base_addr() const
{
return m_slot_idx ? 0x710000 : 0x700000;
}
void hp_ipc_io_slot_device::install_read_write_handlers(address_space& space)
{
device_hp_ipc_io_interface *card = get_card_device();
if (card != nullptr) {
card->install_read_write_handlers(space , get_slot_base_addr());
}
}
void hp_ipc_io_slot_device::irq_w(unsigned idx , bool state)
{
m_irq_cb_func[ 0 ](state && idx == 0);
m_irq_cb_func[ 1 ](state && idx == 1);
m_irq_cb_func[ 2 ](state && idx == 2);
m_irq_cb_func[ 3 ](state && idx == 3);
}
// +--------------------------+
// |device_hp_ipc_io_interface|
// +--------------------------+
device_hp_ipc_io_interface::device_hp_ipc_io_interface(const machine_config &mconfig, device_t &device) :
device_interface(device, "hp_ipcio")
{
}
device_hp_ipc_io_interface::~device_hp_ipc_io_interface()
{
}
void device_hp_ipc_io_interface::irq_w(unsigned idx , bool state)
{
hp_ipc_io_slot_device *slot = downcast<hp_ipc_io_slot_device *>(device().owner());
slot->irq_w(idx , state);
}
#include "82919.h"
void hp_ipc_io_slot_devices(device_slot_interface &device)
{
device.option_add("82919_serial" , HP82919_IO_CARD);
}

View File

@ -0,0 +1,82 @@
// license:BSD-3-Clause
// copyright-holders: F. Ulivi
/*********************************************************************
hp_ipc_io.h
I/O bus of HP IPC system
*********************************************************************/
#ifndef MAME_BUS_HP_IPC_IO_HP_IPC_IO_H
#define MAME_BUS_HP_IPC_IO_HP_IPC_IO_H
#pragma once
void hp_ipc_io_slot_devices(device_slot_interface &device);
class device_hp_ipc_io_interface;
class hp_ipc_io_slot_device : public device_t,
public device_single_card_slot_interface<device_hp_ipc_io_interface>
{
public:
// construction/destruction
hp_ipc_io_slot_device(machine_config const &mconfig, char const *tag, device_t *owner)
: hp_ipc_io_slot_device(mconfig, tag, owner, (uint32_t)0)
{
option_reset();
hp_ipc_io_slot_devices(*this);
set_default_option(nullptr);
set_fixed(false);
}
hp_ipc_io_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~hp_ipc_io_slot_device();
// Set A/B slot
void set_slot_idx(unsigned idx) { m_slot_idx = idx; }
// Callback setups
auto irq3_cb() { return m_irq_cb_func[ 0 ].bind(); }
auto irq4_cb() { return m_irq_cb_func[ 1 ].bind(); }
auto irq5_cb() { return m_irq_cb_func[ 2 ].bind(); }
auto irq6_cb() { return m_irq_cb_func[ 3 ].bind(); }
uint32_t get_slot_base_addr() const;
void install_read_write_handlers(address_space& space);
void irq_w(unsigned idx , bool state);
protected:
// device-level overrides
virtual void device_start() override;
private:
devcb_write_line::array<4> m_irq_cb_func;
// 0: slot A
// 1: slot B
unsigned m_slot_idx;
};
class device_hp_ipc_io_interface : public device_interface
{
public:
virtual ~device_hp_ipc_io_interface();
virtual void install_read_write_handlers(address_space& space , uint32_t base_addr) = 0;
static constexpr offs_t USER_SPACE_OFFSET = 0x1800000;
protected:
device_hp_ipc_io_interface(const machine_config &mconfig, device_t &device);
// card device handling
void irq_w(unsigned idx , bool state);
};
// device type definition
DECLARE_DEVICE_TYPE(HP_IPC_IO_SLOT, hp_ipc_io_slot_device)
#endif // MAME_BUS_HP_IPC_IO_HP_IPC_IO_H

View File

@ -439,28 +439,25 @@ TIMER_CALLBACK_MEMBER(duart_base_device::duart_timer_callback)
}
// timer driving any serial channels?
if (BIT(ACR, 7) == 1)
uint8_t csr = m_chanA->get_chan_CSR();
if ((csr & 0x0f) == 0x0d) // tx is timer driven
{
uint8_t csr = m_chanA->get_chan_CSR();
m_chanA->tx_16x_clock_w(half_period);
}
if ((csr & 0xf0) == 0xd0) // rx is timer driven
{
m_chanA->rx_16x_clock_w(half_period);
}
if ((csr & 0xf0) == 0xd0) // tx is timer driven
{
m_chanA->tx_clock_w(half_period);
}
if ((csr & 0x0f) == 0x0d) // rx is timer driven
{
m_chanA->rx_clock_w(half_period);
}
csr = m_chanB->get_chan_CSR();
if ((csr & 0xf0) == 0xd0) // tx is timer driven
{
m_chanB->tx_clock_w(half_period);
}
if ((csr & 0x0f) == 0x0d) // rx is timer driven
{
m_chanB->rx_clock_w(half_period);
}
csr = m_chanB->get_chan_CSR();
if ((csr & 0x0f) == 0x0d) // tx is timer driven
{
m_chanB->tx_16x_clock_w(half_period);
}
if ((csr & 0xf0) == 0xd0) // rx is timer driven
{
m_chanB->rx_16x_clock_w(half_period);
}
if (!half_period)
@ -1148,8 +1145,9 @@ duart_channel::duart_channel(const machine_config &mconfig, const char *tag, dev
, rx_enabled(0)
, rx_fifo_num(0)
, tx_enabled(0)
, m_tx_break(false)
{
std::fill_n(&rx_fifo[0], MC68681_RX_FIFO_SIZE, 0);
std::fill_n(&rx_fifo[0], MC68681_RX_FIFO_SIZE + 1, 0);
}
void duart_channel::device_start()
@ -1173,6 +1171,7 @@ void duart_channel::device_start()
save_item(NAME(tx_enabled));
save_item(NAME(tx_data));
save_item(NAME(tx_ready));
save_item(NAME(m_tx_break));
}
void duart_channel::device_reset()
@ -1186,6 +1185,7 @@ void duart_channel::device_reset()
tx_baud_rate = rx_baud_rate = 0;
CSR = 0;
m_tx_break = false;
}
// serial device virtual overrides
@ -1208,18 +1208,28 @@ void duart_channel::rcv_complete()
void duart_channel::rx_fifo_push(uint8_t data, uint8_t errors)
{
if (rx_fifo_num >= MC68681_RX_FIFO_SIZE)
if (rx_fifo_num == (MC68681_RX_FIFO_SIZE + 1))
{
logerror("68681: FIFO overflow\n");
SR |= STATUS_OVERRUN_ERROR;
return;
// In case of overrun the FIFO tail entry is overwritten
// Back rx_fifo_write_ptr up by one position
if (rx_fifo_write_ptr)
rx_fifo_write_ptr--;
else
rx_fifo_write_ptr = MC68681_RX_FIFO_SIZE;
}
rx_fifo[rx_fifo_write_ptr++] = data | (errors << 8);
if (rx_fifo_write_ptr == MC68681_RX_FIFO_SIZE)
if (rx_fifo_write_ptr > MC68681_RX_FIFO_SIZE)
rx_fifo_write_ptr = 0;
if (rx_fifo_num++ == 0)
if (rx_fifo_num <= MC68681_RX_FIFO_SIZE)
{
rx_fifo_num++;
}
if (rx_fifo_num == 1)
{
SR |= STATUS_RECEIVER_READY;
if (!(MR1 & MODE_BLOCK_ERROR))
@ -1238,9 +1248,9 @@ void duart_channel::tra_complete()
SR |= STATUS_TRANSMITTER_READY;
if (m_ch == 0)
m_uart->clear_ISR_bits(INT_TXRDYA);
m_uart->set_ISR_bits(INT_TXRDYA);
else
m_uart->clear_ISR_bits(INT_TXRDYB);
m_uart->set_ISR_bits(INT_TXRDYB);
// if local loopback is on, write the transmitted data as if a byte had been received
if ((MR2 & 0xc0) == 0x80)
@ -1363,13 +1373,17 @@ uint8_t duart_channel::read_rx_fifo()
}
rv = rx_fifo[rx_fifo_read_ptr++];
if (rx_fifo_read_ptr == MC68681_RX_FIFO_SIZE)
if (rx_fifo_read_ptr > MC68681_RX_FIFO_SIZE)
{
rx_fifo_read_ptr = 0;
}
rx_fifo_num--;
SR &= ~STATUS_FIFO_FULL;
if (rx_fifo_num == (MC68681_RX_FIFO_SIZE - 1))
{
SR &= ~STATUS_FIFO_FULL;
}
if (!(MR1 & MODE_BLOCK_ERROR))
SR &= ~(STATUS_RECEIVED_BREAK | STATUS_FRAMING_ERROR | STATUS_PARITY_ERROR);
if (rx_fifo_num == 0)
@ -1549,7 +1563,36 @@ void duart_channel::write_CR(uint8_t data)
else
m_uart->clear_ISR_bits(INT_DELTA_BREAK_B);
break;
/* TODO: case 6 and case 7 are start break and stop break respectively, which start or stop holding the TxDA or TxDB line low (space) after whatever data is in the buffer finishes transmitting (following the stop bit?), or after two bit-times if no data is being transmitted */
case 6: /* Start Tx break */
if (!m_tx_break)
{
m_tx_break = true;
if ((MR2 & 0xc0) == 0x80)
{
// Local loopback mode: set delta break in ISR, simulate break rx
if (m_ch == 0)
m_uart->set_ISR_bits(INT_DELTA_BREAK_A);
else
m_uart->set_ISR_bits(INT_DELTA_BREAK_B);
rx_fifo_push(0 , STATUS_RECEIVED_BREAK);
}
// TODO: Actually send break signal
}
break;
case 7: /* Stop tx break */
if (m_tx_break)
{
m_tx_break = false;
if ((MR2 & 0xc0) == 0x80)
{
// Local loopback mode: set delta break in ISR
if (m_ch == 0)
m_uart->set_ISR_bits(INT_DELTA_BREAK_A);
else
m_uart->set_ISR_bits(INT_DELTA_BREAK_B);
}
}
break;
default:
LOG("68681: Unhandled command (%x) in CR%d\n", (data >> 4) & 0x07, m_ch);
break;
@ -1623,3 +1666,43 @@ uint8_t duart_channel::get_chan_CSR()
{
return CSR;
}
void duart_channel::tx_16x_clock_w(bool state)
{
if (state)
{
m_tx_prescaler--;
if (m_tx_prescaler == 8)
{
tx_clock_w(true);
}
else if (m_tx_prescaler == 0)
{
m_tx_prescaler = 16;
tx_clock_w(false);
}
}
}
void duart_channel::rx_16x_clock_w(bool state)
{
if (!is_receive_register_synchronized())
{
// Skip over the start bit once synchonization is achieved
m_rx_prescaler = 32;
rx_clock_w(true);
}
else if (state)
{
m_rx_prescaler--;
if (m_rx_prescaler == 8)
{
rx_clock_w(false);
}
else if (m_rx_prescaler == 0)
{
m_rx_prescaler = 16;
rx_clock_w(true);
}
}
}

View File

@ -44,6 +44,9 @@ public:
void write_MR1(uint8_t data){ MR1 = data; }
void write_MR2(uint8_t data){ MR2 = data; }
void tx_16x_clock_w(bool state);
void rx_16x_clock_w(bool state);
private:
/* Registers */
uint8_t CR; /* Command register */
@ -58,7 +61,7 @@ private:
/* Receiver */
uint8_t rx_enabled;
uint16_t rx_fifo[MC68681_RX_FIFO_SIZE];
uint16_t rx_fifo[MC68681_RX_FIFO_SIZE + 1];
int rx_fifo_read_ptr;
int rx_fifo_write_ptr;
int rx_fifo_num;
@ -69,6 +72,10 @@ private:
uint8_t tx_enabled;
uint8_t tx_data;
uint8_t tx_ready;
bool m_tx_break;
/* Rx/Tx clocking */
uint8_t m_rx_prescaler , m_tx_prescaler;
duart_base_device *m_uart;

View File

@ -373,6 +373,8 @@ Software to look for
#include "speaker.h"
#include "sound/dac.h"
#include "sound/volt_reg.h"
#include "machine/input_merger.h"
#include "bus/hp_ipc_io/hp_ipc_io.h"
#include "emupal.h"
#include "screen.h"
@ -391,6 +393,12 @@ public:
, m_screen(*this, "screen")
, m_spkr(*this , "spkr")
, m_dac(*this , "dac")
, m_irq3_merger(*this , "merge_irq3")
, m_irq4_merger(*this , "merge_irq4")
, m_irq5_merger(*this , "merge_irq5")
, m_irq6_merger(*this , "merge_irq6")
, m_io_slot_a(*this , "slot_a")
, m_io_slot_b(*this , "slot_b")
{ }
void hp_ipc_base(machine_config &config);
@ -439,6 +447,12 @@ private:
required_device<screen_device> m_screen;
required_device<cop452_device> m_spkr;
required_device<dac_1bit_device> m_dac;
required_device<input_merger_any_high_device> m_irq3_merger;
required_device<input_merger_any_high_device> m_irq4_merger;
required_device<input_merger_any_high_device> m_irq5_merger;
required_device<input_merger_any_high_device> m_irq6_merger;
required_device<hp_ipc_io_slot_device> m_io_slot_a;
required_device<hp_ipc_io_slot_device> m_io_slot_b;
uint32_t m_mmu[4], m_lowest_ram_addr;
uint16_t *m_internal_ram;
@ -688,22 +702,22 @@ WRITE_LINE_MEMBER(hp_ipc_state::irq_2)
WRITE_LINE_MEMBER(hp_ipc_state::irq_3)
{
m_maincpu->set_input_line(M68K_IRQ_3, state);
m_irq3_merger->in_w<0>(state);
}
WRITE_LINE_MEMBER(hp_ipc_state::irq_4)
{
m_maincpu->set_input_line(M68K_IRQ_4, state);
m_irq4_merger->in_w<0>(state);
}
WRITE_LINE_MEMBER(hp_ipc_state::irq_5)
{
m_maincpu->set_input_line(M68K_IRQ_5, state);
m_irq5_merger->in_w<0>(state);
}
WRITE_LINE_MEMBER(hp_ipc_state::irq_6)
{
m_maincpu->set_input_line(M68K_IRQ_6, state);
m_irq6_merger->in_w<0>(state);
}
WRITE_LINE_MEMBER(hp_ipc_state::irq_7)
@ -720,6 +734,9 @@ void hp_ipc_state::machine_start()
m_lowest_ram_addr = 0x3c0000 - (m_ram->size() >> 1);
m_internal_ram = (uint16_t *)m_ram->pointer();
m_io_slot_a->install_read_write_handlers(m_bankdev->space());
m_io_slot_b->install_read_write_handlers(m_bankdev->space());
}
void hp_ipc_state::machine_reset()
@ -809,6 +826,24 @@ void hp_ipc_state::hp_ipc_base(machine_config &config)
vref.add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT);
m_spkr->oa_w().set(m_dac , FUNC(dac_1bit_device::write));
// IO slots
HP_IPC_IO_SLOT(config , m_io_slot_a).set_slot_idx(0);
HP_IPC_IO_SLOT(config , m_io_slot_b).set_slot_idx(1);
// IRQ3/4/5/6 mergers
INPUT_MERGER_ANY_HIGH(config , m_irq3_merger).output_handler().set_inputline(m_maincpu , M68K_IRQ_3);
INPUT_MERGER_ANY_HIGH(config , m_irq4_merger).output_handler().set_inputline(m_maincpu , M68K_IRQ_4);
INPUT_MERGER_ANY_HIGH(config , m_irq5_merger).output_handler().set_inputline(m_maincpu , M68K_IRQ_5);
INPUT_MERGER_ANY_HIGH(config , m_irq6_merger).output_handler().set_inputline(m_maincpu , M68K_IRQ_6);
m_io_slot_a->irq3_cb().set(m_irq3_merger , FUNC(input_merger_any_high_device::in_w<1>));
m_io_slot_a->irq4_cb().set(m_irq4_merger , FUNC(input_merger_any_high_device::in_w<1>));
m_io_slot_a->irq5_cb().set(m_irq5_merger , FUNC(input_merger_any_high_device::in_w<1>));
m_io_slot_a->irq6_cb().set(m_irq6_merger , FUNC(input_merger_any_high_device::in_w<1>));
m_io_slot_b->irq3_cb().set(m_irq3_merger , FUNC(input_merger_any_high_device::in_w<2>));
m_io_slot_b->irq4_cb().set(m_irq4_merger , FUNC(input_merger_any_high_device::in_w<2>));
m_io_slot_b->irq5_cb().set(m_irq5_merger , FUNC(input_merger_any_high_device::in_w<2>));
m_io_slot_b->irq6_cb().set(m_irq6_merger , FUNC(input_merger_any_high_device::in_w<2>));
RAM(config, RAM_TAG).set_default_size("512K").set_extra_options("768K,1M,1576K,2M,3M,4M,5M,6M,7M,7680K");
}