From 3e26ee8cfb580d3e7e53ecca422cc989e3ba4b7f Mon Sep 17 00:00:00 2001 From: shattered Date: Fri, 3 Dec 2021 03:43:19 +0000 Subject: [PATCH] dl11: DEC DL11-type serial line unit (#8894) --- scripts/src/machine.lua | 10 ++ scripts/target/mame/mess.lua | 1 + src/devices/machine/dl11.cpp | 288 +++++++++++++++++++++++++++++++++++ src/devices/machine/dl11.h | 103 +++++++++++++ src/mame/drivers/pdp11.cpp | 80 +++------- 5 files changed, 421 insertions(+), 61 deletions(-) create mode 100644 src/devices/machine/dl11.cpp create mode 100644 src/devices/machine/dl11.h diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index cfb5d1d3c58..358a7f7581f 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -1127,6 +1127,16 @@ if (MACHINES["CXD1095"]~=null) then } end +--@src/devices/machine/dl11.h,MACHINES["DL11"] = true +--------------------------------------------------- + +if (MACHINES["DL11"]~=null) then + files { + MAME_DIR .. "src/devices/machine/dl11.cpp", + MAME_DIR .. "src/devices/machine/dl11.h", + } +end + --@src/devices/machine/ds1204.h,MACHINES["DS1204"] = true --------------------------------------------------- diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 879a7db68e9..d5af35a4216 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -509,6 +509,7 @@ MACHINES["CS4031"] = true MACHINES["CS8221"] = true MACHINES["CS8900A"] = true MACHINES["CXD1095"] = true +MACHINES["DL11"] = true MACHINES["DP8390"] = true MACHINES["DP83932C"] = true MACHINES["DP8573"] = true diff --git a/src/devices/machine/dl11.cpp b/src/devices/machine/dl11.cpp new file mode 100644 index 00000000000..cdaaf7d90a9 --- /dev/null +++ b/src/devices/machine/dl11.cpp @@ -0,0 +1,288 @@ +// license:BSD-3-Clause +// copyright-holders:Sergey Svishchev +/*************************************************************************** + + DEC DL11-type SLU (serial line unit). + + Frame format is not software-configurable; hardcoded to 8N1 for now. + + http://www.ibiblio.org/pub/academic/computer-science/history/pdp-11/hardware/micronotes/numerical/micronote33.txt + +***************************************************************************/ + +#include "emu.h" +#include "machine/dl11.h" + + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +// device type definition +DEFINE_DEVICE_TYPE(DL11, dl11_device, "dl11", "DEC DL11-type SLU") + + +//************************************************************************** +// MACROS / CONSTANTS +//************************************************************************** + +enum +{ + DLRCSR = 0, + DLRBUF, + DLTCSR, + DLTBUF +}; + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// dl11_device - constructor +//------------------------------------------------- + +dl11_device::dl11_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, DL11, tag, owner, clock) + , device_serial_interface(mconfig, *this) + , device_z80daisy_interface(mconfig, *this) + , m_write_txd(*this) + , m_write_rxrdy(*this) + , m_write_txrdy(*this) + , m_rxc(0) + , m_txc(0) + , m_rxvec(0) + , m_txvec(0) +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void dl11_device::device_start() +{ + // resolve callbacks + m_write_txd.resolve_safe(); + m_write_rxrdy.resolve_safe(); + m_write_txrdy.resolve_safe(); + + // save state + save_item(NAME(m_rcsr)); + save_item(NAME(m_rbuf)); + save_item(NAME(m_tcsr)); + save_item(NAME(m_tbuf)); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void dl11_device::device_reset() +{ + set_data_frame(1, 8, PARITY_NONE, STOP_BITS_1); + + // create the timers + if (m_rxc > 0) + set_rcv_rate(m_rxc); + + if (m_txc > 0) + set_tra_rate(m_txc); + + m_rcsr = m_rbuf = m_tbuf = 0; + m_tcsr = CSR_DONE; + m_rxrdy = m_txrdy = CLEAR_LINE; + + m_write_txd(1); + m_write_rxrdy(m_rxrdy); + m_write_txrdy(m_txrdy); +} + +int dl11_device::z80daisy_irq_state() +{ + if (m_rxrdy == ASSERT_LINE || m_txrdy == ASSERT_LINE) + return Z80_DAISY_INT; + else + return 0; +} + +int dl11_device::z80daisy_irq_ack() +{ + int vec = -1; + + if (m_rxrdy == ASSERT_LINE) + { + m_rxrdy = CLEAR_LINE; + vec = m_rxvec; + } + else if (m_txrdy == ASSERT_LINE) + { + m_txrdy = CLEAR_LINE; + vec = m_txvec; + } + + return vec; +} + +void dl11_device::z80daisy_irq_reti() +{ +} + + +//------------------------------------------------- +// tra_callback - +//------------------------------------------------- + +void dl11_device::tra_callback() +{ + if (m_tcsr & DLTCSR_XBRK) + { + m_write_txd(0); + } + else if (!is_transmit_register_empty()) + { + m_write_txd(transmit_register_get_data_bit()); + } +} + + +//------------------------------------------------- +// tra_complete - +//------------------------------------------------- + +void dl11_device::tra_complete() +{ + m_tcsr |= CSR_DONE; + raise_virq(m_write_txrdy, m_tcsr, CSR_IE, m_txrdy); +} + + +//------------------------------------------------- +// rcv_complete - +//------------------------------------------------- + +void dl11_device::rcv_complete() +{ + receive_register_extract(); + if (is_receive_framing_error()) + { + m_rbuf = DLRBUF_ERR | DLRBUF_RBRK; + } + else + { + m_rbuf = get_received_char(); + } + if (is_receive_parity_error()) + { + m_rbuf |= DLRBUF_ERR | DLRBUF_PERR; + } + if (m_rcsr & CSR_DONE) + { + m_rbuf |= DLRBUF_ERR | DLRBUF_OVR; + } + else + { + m_rcsr |= CSR_DONE; + } + raise_virq(m_write_rxrdy, m_rcsr, CSR_IE, m_rxrdy); +} + + +//------------------------------------------------- +// read - register read +//------------------------------------------------- + +uint16_t dl11_device::read(offs_t offset) +{ + uint16_t data = 0; + + switch (offset & 3) + { + case DLRCSR: + data = m_rcsr & DLRCSR_RD; + break; + + case DLRBUF: + data = m_rbuf; + m_rcsr &= ~CSR_DONE; + clear_virq(m_write_rxrdy, m_rcsr, CSR_IE, m_rxrdy); + break; + + case DLTCSR: + data = m_tcsr & DLTCSR_RD; + break; + + case DLTBUF: + data = m_tbuf; + break; + } + + return data; +} + + +//------------------------------------------------- +// write - register write +//------------------------------------------------- + +void dl11_device::write(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + switch (offset & 3) + { + case DLRCSR: + if ((data & CSR_IE) == 0) + { + clear_virq(m_write_rxrdy, 1, 1, m_rxrdy); + } + else if ((m_rcsr & (CSR_DONE + CSR_IE)) == CSR_DONE) + { + raise_virq(m_write_rxrdy, 1, 1, m_rxrdy); + } + m_rcsr = ((m_rcsr & ~DLRCSR_WR) | (data & DLRCSR_WR)); + break; + + case DLRBUF: + break; + + case DLTCSR: + if ((data & CSR_IE) == 0) + { + clear_virq(m_write_txrdy, 1, 1, m_txrdy); + } + else if ((m_tcsr & (CSR_DONE + CSR_IE)) == CSR_DONE) + { + raise_virq(m_write_txrdy, 1, 1, m_txrdy); + } + m_tcsr = ((m_tcsr & ~DLTCSR_WR) | (data & DLTCSR_WR)); + break; + + case DLTBUF: + m_tbuf = data; + m_tcsr &= ~CSR_DONE; + clear_virq(m_write_txrdy, m_tcsr, CSR_IE, m_txrdy); + transmit_register_setup(data & 0xff); + break; + } +} + + +//------------------------------------------------- +// rxrdy_r - receiver ready +//------------------------------------------------- + +READ_LINE_MEMBER(dl11_device::rxrdy_r) +{ + return ((m_rcsr & (CSR_DONE | CSR_IE)) == (CSR_DONE | CSR_IE)) ? ASSERT_LINE : CLEAR_LINE; +} + + +//------------------------------------------------- +// txrdy_r - transmitter empty +//------------------------------------------------- + +READ_LINE_MEMBER(dl11_device::txrdy_r) +{ + return ((m_tcsr & (CSR_DONE | CSR_IE)) == (CSR_DONE | CSR_IE)) ? ASSERT_LINE : CLEAR_LINE; +} diff --git a/src/devices/machine/dl11.h b/src/devices/machine/dl11.h new file mode 100644 index 00000000000..82c0f5227ac --- /dev/null +++ b/src/devices/machine/dl11.h @@ -0,0 +1,103 @@ +// license:BSD-3-Clause +// copyright-holders:Sergey Svishchev +/*************************************************************************** + + DEC DL11-type SLU (serial line unit) + +***************************************************************************/ + +#ifndef MAME_MACHINE_DL11_H +#define MAME_MACHINE_DL11_H + +#pragma once + +#include "machine/z80daisy.h" +#include "machine/pdp11.h" +#include "diserial.h" + + +/* registers */ + +#define DLRCSR_RD (CSR_DONE|CSR_IE) +#define DLRCSR_WR (CSR_IE) + +#define DLRBUF_ERR 0100000 +#define DLRBUF_OVR 0040000 +#define DLRBUF_RBRK 0020000 +#define DLRBUF_PERR 0020000 + +#define DLTCSR_XBRK 0000001 +#define DLTCSR_RD (CSR_DONE|CSR_IE|DLTCSR_XBRK) +#define DLTCSR_WR (CSR_IE|DLTCSR_XBRK) + + +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ + +// ======================> dl11_device + +class dl11_device : public device_t, + public device_serial_interface, + public device_z80daisy_interface +{ +public: + // construction/destruction + dl11_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + void set_rxc(int clock) { m_rxc = clock; } + void set_txc(int clock) { m_txc = clock; } + void set_rxvec(int vec) { m_rxvec = vec; } + void set_txvec(int vec) { m_txvec = vec; } + + auto txd_wr_callback() { return m_write_txd.bind(); } + auto txrdy_wr_callback() { return m_write_txrdy.bind(); } + auto rxrdy_wr_callback() { return m_write_rxrdy.bind(); } + + uint16_t read(offs_t offset); + void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + + DECLARE_READ_LINE_MEMBER( rxrdy_r ); + DECLARE_READ_LINE_MEMBER( txrdy_r ); + + DECLARE_WRITE_LINE_MEMBER( rx_w ) { device_serial_interface::rx_w(state); } + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + // device_serial_interface overrides + virtual void tra_callback() override; + virtual void tra_complete() override; + virtual void rcv_complete() override; + + // device_z80daisy_interface overrides + virtual int z80daisy_irq_state() override; + virtual int z80daisy_irq_ack() override; + virtual void z80daisy_irq_reti() override; + +private: + devcb_write_line m_write_txd; + devcb_write_line m_write_rxrdy; + devcb_write_line m_write_txrdy; + + line_state m_rxrdy; + line_state m_txrdy; + + int m_rxc; + int m_txc; + int m_rxvec; + int m_txvec; + + uint16_t m_rcsr; + uint16_t m_rbuf; + uint16_t m_tcsr; + uint16_t m_tbuf; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(DL11, dl11_device) + +#endif diff --git a/src/mame/drivers/pdp11.cpp b/src/mame/drivers/pdp11.cpp index a2c30cb5268..54198082944 100644 --- a/src/mame/drivers/pdp11.cpp +++ b/src/mame/drivers/pdp11.cpp @@ -90,9 +90,10 @@ #include "emu.h" #include "bus/qbus/qbus.h" +#include "bus/rs232/rs232.h" #include "cpu/t11/t11.h" #include "cpu/i86/i186.h" -#include "machine/terminal.h" +#include "machine/dl11.h" #include "machine/rx01.h" @@ -104,7 +105,8 @@ public: pdp11_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag) , m_maincpu(*this, "maincpu") - , m_terminal(*this, "terminal") + , m_dl11(*this, "dl11") + , m_rs232(*this, "rs232") , m_qbus(*this, "qbus") { } @@ -119,13 +121,9 @@ protected: private: required_device m_maincpu; - required_device m_terminal; + required_device m_dl11; + required_device m_rs232; required_device m_qbus; - uint16_t teletype_ctrl_r(offs_t offset); - void teletype_ctrl_w(offs_t offset, uint16_t data); - void kbd_put(u8 data); - uint8_t m_teletype_data; - uint16_t m_teletype_status; DECLARE_MACHINE_RESET(pdp11ub2); DECLARE_MACHINE_RESET(pdp11qb); void load9312prom(uint8_t *desc, uint8_t *src, int size); @@ -134,50 +132,12 @@ private: void sms1000_mem_188(address_map &map); }; -uint16_t pdp11_state::teletype_ctrl_r(offs_t offset) -{ - uint16_t res = 0; - - switch(offset) - { - /* - keyboard - ---- x--- ---- ---- busy bit - ---- ---- x--- ---- ready bit (set on character receive, clear on buffer read) - ---- ---- -x-- ---- irq enable - ---- ---- ---- ---x reader enable (?) - */ - case 0: res = m_teletype_status; break; // reader status register (tks) - case 1: m_teletype_status &= ~0x80; res = m_teletype_data; break;// reader buffer register (tkb) - /* - printer - ---- ---- x--- ---- ready bit - ---- ---- -x-- ---- irq enable - ---- ---- ---- -x-- maintenance - */ - case 2: res = 0x80; break; // punch status register (tps) - case 3: res = 0; break; // punch buffer register (tpb) - } - - return res; -} - -void pdp11_state::teletype_ctrl_w(offs_t offset, uint16_t data) -{ - switch(offset) - { - case 3: - m_terminal->write(data); - break; - } -} - void pdp11_state::pdp11_mem(address_map &map) { map.unmap_value_high(); map(0x0000, 0xdfff).ram(); // RAM map(0xea00, 0xfeff).rom(); - map(0xff70, 0xff77).rw(FUNC(pdp11_state::teletype_ctrl_r), FUNC(pdp11_state::teletype_ctrl_w)); + map(0xff70, 0xff77).rw(m_dl11, FUNC(dl11_device::read), FUNC(dl11_device::write)); map(0xfe78, 0xfe7b).w("rx01", FUNC(rx01_device::write)); } @@ -288,11 +248,6 @@ INPUT_PORTS_END void pdp11_state::machine_start() { - m_teletype_data = 0; - m_teletype_status = 0; - - save_item(NAME(m_teletype_data)); - save_item(NAME(m_teletype_status)); } void pdp11_state::machine_reset() @@ -376,12 +331,6 @@ MACHINE_RESET_MEMBER(pdp11_state,pdp11qb) } -void pdp11_state::kbd_put(u8 data) -{ - m_teletype_data = data; - m_teletype_status |= 0x80; -} - void pdp11_state::pdp11(machine_config &config) { /* basic machine hardware */ @@ -389,9 +338,18 @@ void pdp11_state::pdp11(machine_config &config) m_maincpu->set_initial_mode(6 << 13); m_maincpu->set_addrmap(AS_PROGRAM, &pdp11_state::pdp11_mem); - /* video hardware */ - GENERIC_TERMINAL(config, m_terminal, 0); - m_terminal->set_keyboard_callback(FUNC(pdp11_state::kbd_put)); + DL11(config, m_dl11, XTAL(4'608'000)); + m_dl11->set_rxc(9600); + m_dl11->set_txc(9600); + m_dl11->set_rxvec(060); + m_dl11->set_txvec(064); + m_dl11->txd_wr_callback().set(m_rs232, FUNC(rs232_port_device::write_txd)); +// future +// m_dl11->txrdy_wr_callback().set_inputline(m_maincpu, T11_IRQ0); +// m_dl11->rxrdy_wr_callback().set_inputline(m_maincpu, T11_IRQ0); + + RS232_PORT(config, m_rs232, default_rs232_devices, "terminal"); + m_rs232->rxd_handler().set(m_dl11, FUNC(dl11_device::rx_w)); RX01(config, "rx01", 0); QBUS(config, m_qbus, 0);