diff options
Diffstat (limited to 'src/devices/bus/hp_ipc_io/82919.cpp')
-rw-r--r-- | src/devices/bus/hp_ipc_io/82919.cpp | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/src/devices/bus/hp_ipc_io/82919.cpp b/src/devices/bus/hp_ipc_io/82919.cpp new file mode 100644 index 00000000000..901350f5bdd --- /dev/null +++ b/src/devices/bus/hp_ipc_io/82919.cpp @@ -0,0 +1,251 @@ +// 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" + +// 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(); + } +} + +void hp82919_io_card_device::uart_irq(int state) +{ + m_uart_int = state; + update_irq(); +} + +void hp82919_io_card_device::uart_a_tx(int state) +{ + m_rs232_prim->write_txd(state); + if (m_loopback) { + m_uart->rx_b_w(state); + } +} + +void hp82919_io_card_device::uart_b_tx(int state) +{ + 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)); + } +} + +void hp82919_io_card_device::prim_rxd(int state) +{ + if (!m_loopback) { + m_uart->rx_a_w(state); + } +} + +void hp82919_io_card_device::prim_dcd(int state) +{ + if (!m_loopback) { + m_uart->ip3_w(state); + } +} + +void hp82919_io_card_device::prim_dsr(int state) +{ + if (!m_loopback) { + m_uart->ip1_w(state); + } +} + +void hp82919_io_card_device::prim_ri(int state) +{ + if (!m_loopback) { + m_uart->ip2_w(state); + } +} + +void hp82919_io_card_device::prim_cts(int state) +{ + if (!m_loopback) { + m_uart->ip0_w(state); + } +} + +void hp82919_io_card_device::sec_rxd(int state) +{ + if (!m_loopback) { + m_uart->rx_b_w(state); + } +} + +void hp82919_io_card_device::sec_dcd(int state) +{ + if (!m_loopback) { + m_uart->ip5_w(state); + } +} + +void hp82919_io_card_device::sec_cts(int state) +{ + 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") |