decmate2, decmate3: Emulate HD-6120 CPU; add enough I/O to initialize various peripheral ICs and run tests on disk controller

This commit is contained in:
AJR 2021-05-19 18:27:34 -04:00
parent 2fa2ef8b0e
commit ab88bacf35
4 changed files with 2205 additions and 26 deletions

View File

@ -555,6 +555,8 @@ end
if CPUS["PDP8"] then if CPUS["PDP8"] then
files { files {
MAME_DIR .. "src/devices/cpu/pdp8/hd6120.cpp",
MAME_DIR .. "src/devices/cpu/pdp8/hd6120.h",
MAME_DIR .. "src/devices/cpu/pdp8/pdp8.cpp", MAME_DIR .. "src/devices/cpu/pdp8/pdp8.cpp",
MAME_DIR .. "src/devices/cpu/pdp8/pdp8.h", MAME_DIR .. "src/devices/cpu/pdp8/pdp8.h",
} }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,217 @@
// license:BSD-3-Clause
// copyright-holders:AJR
/***************************************************************************
Harris HD-6120 High-Speed CMOS 12 Bit Microprocessor
***********************************************************************
_____ _____
_OUT 1 |* \_/ | 40 VCC
DMAGNT 2 | | 39 _READ
_DMAREQ 3 | | 38 _WRITE
_SKIP 4 | | 37 _MEMSEL
RUN/_HLT 5 | | 36 _IOCLR
_RUN 6 | | 35 _LXDAR
_RESET 7 | | 34 _LXMAR
ACK 8 | | 33 _LXPAR
OSCIN 9 | | 32 _DATAF
OSCOUT 10 | HD-6120 | 31 _INTGNT
_IFETCH 11 | | 30 _INTREQ
DX0 12 | | 29 _CPREQ
DX1 13 | | 28 STRTUP
DX2 14 | | 27 EMA2
DX3 15 | | 26 C1/_C1
DX4 16 | | 25 C0/_C0
DX5 17 | | 24 DX11
DX6 18 | | 23 DX10
DX7 19 | | 22 DX9
VSS 20 |_____________| 21 DX8
***************************************************************************/
#ifndef MAME_CPU_PDP8_HD6120_H
#define MAME_CPU_PDP8_HD6120_H
#pragma once
class hd6120_device : public cpu_device
{
public:
static constexpr int AS_DEVCTL = AS_OPCODES + 1;
static constexpr offs_t INSTF = 0;
static constexpr offs_t IFETCH = 1;
static constexpr offs_t DATAF = 2;
enum {
HD6120_PC,
HD6120_AC, HD6120_MQ,
HD6120_SP1, HD6120_SP2,
HD6120_IF, HD6120_IB, HD6120_DF, HD6120_SF, HD6120_IIFF,
HD6120_FLAGS, HD6120_PNLFLGS, HD6120_PWRON
};
// input lines
enum {
INTREQ_LINE = 0,
CPREQ_LINE
//SKIP_LINE,
//DMAREQ_LINE
};
// device control flags
enum : u8 {
SKIP = 1 << 3,
C0 = 1 << 2,
C1 = 1 << 1
// C2 is ignored on HD-6120
};
// device type constructor
hd6120_device(const machine_config &config, const char *tag, device_t *owner, u32 clock);
// callback configuration
auto lxmar_callback() { return m_lxmar_callback.bind(); }
auto lxpar_callback() { return m_lxpar_callback.bind(); }
auto lxdar_callback() { return m_lxdar_callback.bind(); }
auto rsr_callback() { return m_rsr_callback.bind(); }
auto wsr_callback() { return m_wsr_callback.bind(); }
auto strtup_callback() { return m_strtup_callback.bind(); }
auto intgnt_callback() { return m_intgnt_callback.bind(); }
auto ioclr_callback() { return m_ioclr_callback.bind(); }
protected:
// device-level overrides
virtual void device_resolve_objects() override;
virtual void device_start() override;
virtual void device_reset() override;
// device_execute_interface overrides
virtual void execute_run() override;
virtual uint64_t execute_clocks_to_cycles(uint64_t clocks) const noexcept override { return (clocks + 2 - 1) / 2; }
virtual uint64_t execute_cycles_to_clocks(uint64_t cycles) const noexcept override { return (cycles * 2); }
virtual void execute_set_input(int linenum, int state) override;
// device_disasm_interface overrides
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
// device_memory_interface overrides
virtual space_config_vector memory_space_config() const override;
// device_state_interface overrides
virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
private:
enum class minor_state : u8 {
RESET_1, RESET_2, RESET_3, RESET_4, RESET_5,
IFETCH_1, IFETCH_2, IFETCH_3,
INDIR_1, INDIR_2, INDIR_3, INDIR_3A, INDIR_4, INDIR_5,
EXEC_1, EXEC_2, EXEC_3,
DEP_2, DEP_3,
AND_4,
TAD_4,
ISZ_4, ISZ_5, ISZ_6, ISZ_7, ISZ_8,
DCA_4,
JMS_4,
JMP_1,
OP1_1, OP1_2, OP1_3, OP1_4, OP1_5,
OP2_1, OP2_2, OP2_3, OP2_4,
OSR_2, OSR_3,
OP3_1, OP3_2, OP3_3,
IOT_1, IOT_2,
SKON_1, SKON_2, SKON_3,
IEN_1, IEN_2,
GTF_1, GTF_2, GTF_3, GTF_4, GTF_5,
RTF_1, RTF_2, RTF_3, RTF_4,
SRQ_1,
SGT_1,
CAF_1, CAF_2, CAF_3,
PRS_1, PRS_2, PRS_3, PRS_4,
PGO_1,
PEX_1, PEX_2,
CFIELD_1, CFIELD_2,
RFIELD_1, RFIELD_2,
RIB_1, RIB_2,
RMF_1, RMF_2, RMF_3, RMF_4,
PRQ_1,
WSR_1, WSR_2,
GCF_1, GCF_2, GCF_3, GCF_4,
SPD_1,
PPC_1, PPC_2, PPC_3, PPC_4, PPC_5, PPC_6,
PAC_1, PAC_2, PAC_3,
RTN_1, RTN_2, RTN_3, RTN_4,
POP_1, POP_2, POP_3, POP_4,
RSP_1, RSP_2,
LSP_1,
EXTIOT_1, EXTIOT_2, EXTIOT_3, EXTIOT_4, EXTIOT_4R, EXTIOT_5R, EXTIOT_5,
INTGNT_1,
CPINT_1, CPINT_2
};
u16 rotate_step(u16 data);
bool skip_test() const;
u16 dataf_map(u16 addr) const;
void next_instruction();
void transfer_pc(u16 addr);
void debug_set_pc(u16 addr);
void debug_update_pc(u16 addr);
// address spaces
address_space_config m_inst_config;
address_space_config m_data_config;
address_space_config m_io_config;
address_space_config m_devctl_config;
memory_access<16, 1, -1, ENDIANNESS_BIG>::cache m_icache;
memory_access<16, 1, -1, ENDIANNESS_BIG>::specific m_inst;
memory_access<16, 1, -1, ENDIANNESS_BIG>::specific m_data;
memory_access<9, 1, -1, ENDIANNESS_BIG>::specific m_io;
memory_access<9, 0, 0, ENDIANNESS_BIG>::specific m_devctl;
// callback objects
devcb_write16 m_lxmar_callback;
devcb_write16 m_lxpar_callback;
devcb_write16 m_lxdar_callback;
devcb_read16 m_rsr_callback;
devcb_write16 m_wsr_callback;
//devcb_read16 m_rtin_callback;
//devcb_write16 m_rtout_callback;
devcb_read_line m_strtup_callback;
devcb_write_line m_intgnt_callback;
//devcb_write_line m_dmagnt_callback;
devcb_write_line m_ioclr_callback;
// major registers
u16 m_pc;
u16 m_ac;
u16 m_mq;
u16 m_sp[2];
u16 m_temp;
u16 m_ir;
// field and flag registers
u8 m_if;
u8 m_ib;
u8 m_df;
u8 m_sf;
u8 m_flags;
u8 m_pnlflgs;
bool m_fz;
bool m_iiff;
bool m_pwron;
bool m_intgnt;
// misc. execution state
minor_state m_state;
u16 m_iaddr;
u16 m_oaddr;
s32 m_icount;
// input lines
bool m_intreq_input;
bool m_cpreq_input;
};
// device type declaration
DECLARE_DEVICE_TYPE(HD6120, hd6120_device)
#endif // MAME_CPU_PDP8_HD6120_H

View File

@ -2,7 +2,7 @@
// copyright-holders:AJR // copyright-holders:AJR
/**************************************************************************** /****************************************************************************
Skeleton driver for DECmate II & III business PCs. Preliminary driver for DECmate II & III business PCs.
The DECmate II & III are the last and in some ways least PDP-8-like The DECmate II & III are the last and in some ways least PDP-8-like
members of DEC's 12-bit computer line. Based on a Harris HD-6120 CMOS members of DEC's 12-bit computer line. Based on a Harris HD-6120 CMOS
@ -23,31 +23,34 @@
green or amber) VR201 monitor also physically resembles. (As with the green or amber) VR201 monitor also physically resembles. (As with the
DECmate's VT100 keyboard, the LK201 may have its PF1 key is painted gold DECmate's VT100 keyboard, the LK201 may have its PF1 key is painted gold
to highlight its importance to DECmate software.) DECmate II also differs to highlight its importance to DECmate software.) DECmate II also differs
from its CMOS-8 predecessors in using standard 8-bit EPROMs rather than from its CMOS-8 predecessors in using generic 8-bit EPROMs or mask ROMs
specialized 12-bit ROMs for its "control panel" program. rather than specialized 12-bit ROMs for its "control panel" program.
DECmate II had three different types of expansion options: the DECmate II had three different types of expansion options: the
aforementioned storage adapter, which also supported a 10 MB hard disk aforementioned storage adapter, which also supported a 10 MB hard disk
(RDC51-CA); a graphics board supporting monochrome or color graphics on interface (RDC51-CA) with its own 8051; a graphics board supporting
a second monitor; and an Auxiliary Processor Unit. The basic APU monochrome or color graphics on a second monitor; and an Auxiliary
(PC27X-AA or -AB) ran CP/M on a Z80 with 64K of its own RAM. The Processor Unit. The basic APU (PC27X-AA or -AB) ran CP/M on a Z80 with
upgraded XPU (PC27X-AH or PC27X-AJ) could also run MS-DOS 2.11 using an 64K of its own RAM. The upgraded XPU (PC27X-AH or PC27X-AJ) could also
additional 8086 CPU with 256K or 512K of RAM. run MS-DOS 2.11 using an additional 8086 CPU with 256K or 512K of RAM.
DECmate III (PC238) was a repackaging of the DECmate II in a smaller but DECmate III (PC238) was a repackaging of the DECmate II in a smaller but
taller box that provides space for only one internal RX33 floppy drive. taller box that provides space for only one internal RX50 floppy drive.
Much of the timing and support logic is compressed into two large PLCC Much of the timing and support logic is compressed into two large PLCC
gate arrays (DC381 and DC382), with a PLL and PAL16R8 to assist the FDC. gate arrays (DC381 and DC382), with a PLL and PAL16R8 to assist the FDC.
The DECmate III's own APU and graphics options share a single and unique (One consequence of this reduction is that the printer port is fixed to
expansion connector; the PC23X-CA graphics card supported RGB color the same baud rate as the keyboard.) The DECmate III's own APU and
output on a VR241 monitor. DEC also later released an enhanced version graphics options share a single and unique expansion connector; the
called DECmate III Plus (PC24P), which added a 20 MB RD31 hard disk. PC23X-CA graphics card supported RGB color output on a VR241 monitor.
DEC also later released an enhanced version called DECmate III Plus
(PC24P), which included a 20 MB RD31 hard disk underneath a half-height
RX33 floppy drive.
****************************************************************************/ ****************************************************************************/
#include "emu.h" #include "emu.h"
#include "bus/rs232/rs232.h" #include "bus/rs232/rs232.h"
#include "cpu/pdp8/pdp8.h" #include "cpu/pdp8/hd6120.h"
#include "cpu/mcs51/mcs51.h" #include "cpu/mcs51/mcs51.h"
#include "imagedev/floppy.h" #include "imagedev/floppy.h"
#include "machine/ay31015.h" #include "machine/ay31015.h"
@ -73,9 +76,24 @@ public:
, m_mpscc(*this, "mpscc") , m_mpscc(*this, "mpscc")
, m_brg(*this, "brg%u", 0U) , m_brg(*this, "brg%u", 0U)
, m_crtc(*this, "crtc") , m_crtc(*this, "crtc")
, m_ram(*this, "ram")
, m_cprom(*this, "cprom") , m_cprom(*this, "cprom")
, m_chargen(*this, "chargen") , m_chargen(*this, "chargen")
, m_cprom_iview(*this, "cpromi")
, m_cprom_dview(*this, "cpromd")
, m_cpsel(false)
, m_vint(false)
, m_cpromsel(false)
, m_eadd0(false)
, m_com_control_read(false)
, m_kbd_rflg(false)
, m_kbd_tflg(false)
, m_prt_rflg(false)
, m_prt_tflg(false)
, m_crtc_addr(0)
, m_rxdata(0) , m_rxdata(0)
, m_rx_control(0)
, m_rx_status(0)
{ {
} }
@ -86,9 +104,67 @@ public:
protected: protected:
virtual void machine_start() override; virtual void machine_start() override;
virtual void machine_reset() override;
private: private:
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
DECLARE_WRITE_LINE_MEMBER(vint_w);
void lxmar_w(offs_t offset, u16 data);
void lxpar_w(offs_t offset, u16 data);
void lxdar_w(offs_t offset, u16 data);
void wsr_w(u16 data);
u16 cprom_switch_r(offs_t offset);
DECLARE_WRITE_LINE_MEMBER(pc278_ioclr_w);
DECLARE_WRITE_LINE_MEMBER(pc238_ioclr_w);
DECLARE_WRITE_LINE_MEMBER(keyboard_dr_w);
DECLARE_WRITE_LINE_MEMBER(keyboard_dr_ff_w);
DECLARE_WRITE_LINE_MEMBER(keyboard_tbre_w);
DECLARE_WRITE_LINE_MEMBER(keyboard_tbre_ff_w);
DECLARE_WRITE_LINE_MEMBER(printer_dr_w);
DECLARE_WRITE_LINE_MEMBER(printer_dr_ff_w);
DECLARE_WRITE_LINE_MEMBER(printer_tbre_w);
DECLARE_WRITE_LINE_MEMBER(printer_tbre_ff_w);
u8 kbdrflg_devctl_r();
void kbdrflg_set_w(u16 data);
void kbdrflg_clear_w(u16 data);
u16 kbduart_r();
u8 kbdtflg_devctl_r();
void kbdtflg_set_w(u16 data);
void kbdtflg_clear_w(u16 data);
u8 prtrflg_devctl_r();
void prtrflg_set_w(u16 data);
void prtrflg_clear_w(u16 data);
u16 prtuart_r();
void prttflg_set_w(u16 data);
void prttflg_clear_w(u16 data);
u8 prttflg_devctl_r();
u8 apten_r();
u8 comreg_devctl_r();
u16 comreg_r();
void comreg_w(u16 data);
void cominit_w(u16 data);
u8 vint_devctl_r();
void lscreg_w(u16 data);
void wrcrtc_w(u16 data);
u16 rdcrtc_r();
void video_mod_w(u16 data);
void modem_w(u16 data);
void sel_w(u16 data);
void lcd_w(u16 data);
u16 xdr_r();
void xdr_w(u16 data);
u8 xdr_devctl_r();
u8 str_devctl_r();
u8 ser_devctl_r();
u8 sdn_devctl_r();
void intr_w(u16 data);
void rxinit_w(u16 data);
u8 rx_ldata_r(); u8 rx_ldata_r();
void rx_ldata_w(u8 data); void rx_ldata_w(u8 data);
@ -100,10 +176,14 @@ private:
void rx_sel_w(u8 data); void rx_sel_w(u8 data);
u8 rx_rdy_r(); u8 rx_rdy_r();
void mem_map(address_map &map); void inst_map(address_map &map);
void data_map(address_map &map);
void pc278_io_map(address_map &map);
void pc238_io_map(address_map &map);
void devctl_map(address_map &map);
void rx_map(address_map &map); void rx_map(address_map &map);
required_device<cpu_device> m_maincpu; required_device<hd6120_device> m_maincpu;
required_device<i8051_device> m_rxcpu; required_device<i8051_device> m_rxcpu;
required_device<fd1793_device> m_fdc; required_device<fd1793_device> m_fdc;
optional_device_array<floppy_connector, 4> m_floppy; optional_device_array<floppy_connector, 4> m_floppy;
@ -112,10 +192,27 @@ private:
required_device<upd7201_device> m_mpscc; required_device<upd7201_device> m_mpscc;
optional_device_array<com8116_device, 2> m_brg; optional_device_array<com8116_device, 2> m_brg;
required_device<crt9007_device> m_crtc; required_device<crt9007_device> m_crtc;
required_shared_ptr<u16> m_ram;
required_region_ptr<u16> m_cprom; required_region_ptr<u16> m_cprom;
required_region_ptr<u8> m_chargen; required_region_ptr<u8> m_chargen;
memory_view m_cprom_iview;
memory_view m_cprom_dview;
bool m_cpsel;
bool m_vint;
bool m_cpromsel;
bool m_eadd0;
bool m_com_control_read;
bool m_kbd_rflg;
bool m_kbd_tflg;
bool m_prt_rflg;
bool m_prt_tflg;
u8 m_crtc_addr;
u16 m_rxdata; // 74LS298, writable from both 6120 and 8051 u16 m_rxdata; // 74LS298, writable from both 6120 and 8051
u8 m_rx_control;
u8 m_rx_status;
}; };
void decmate2_state::init_pc278() void decmate2_state::init_pc278()
@ -168,7 +265,26 @@ void decmate2_state::machine_start()
m_mpscc->synca_w(1); m_mpscc->synca_w(1);
m_mpscc->syncb_w(1); m_mpscc->syncb_w(1);
save_item(NAME(m_cpsel));
save_item(NAME(m_vint));
save_item(NAME(m_cpromsel));
save_item(NAME(m_eadd0));
save_item(NAME(m_com_control_read));
save_item(NAME(m_kbd_rflg));
save_item(NAME(m_kbd_tflg));
save_item(NAME(m_prt_rflg));
save_item(NAME(m_prt_tflg));
save_item(NAME(m_crtc_addr));
save_item(NAME(m_rxdata)); save_item(NAME(m_rxdata));
save_item(NAME(m_rx_control));
save_item(NAME(m_rx_status));
}
void decmate2_state::machine_reset()
{
m_cprom_iview.select(0);
m_cprom_dview.select(0);
m_cpromsel = false;
} }
u32 decmate2_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) u32 decmate2_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
@ -177,6 +293,370 @@ u32 decmate2_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, c
return 0; return 0;
} }
WRITE_LINE_MEMBER(decmate2_state::vint_w)
{
// TODO: synchronize
m_vint = state;
}
void decmate2_state::lxmar_w(offs_t offset, u16 data)
{
if (offset == hd6120_device::IFETCH)
m_cpsel = false;
}
void decmate2_state::lxpar_w(offs_t offset, u16 data)
{
if (offset == hd6120_device::IFETCH)
m_cpsel = true;
}
void decmate2_state::lxdar_w(offs_t offset, u16 data)
{
m_eadd0 = BIT(data, 12); // latched from EMA2
}
void decmate2_state::wsr_w(u16 data)
{
if (m_cpsel)
{
if (BIT(data, 0) != m_cpromsel) // DX11
{
m_cprom_iview.select(1);
m_cpromsel = BIT(data, 0);
}
if (BIT(data, 11)) // DX0
m_cprom_dview.disable();
else
m_cprom_dview.select(0);
}
}
// This is not a precise implementation of the actual RAMDIS control circuit, but is close enough to work just as well
u16 decmate2_state::cprom_switch_r(offs_t offset)
{
if (m_cpromsel)
{
if (!machine().side_effects_disabled())
m_cprom_iview.disable();
return m_cprom[offset & 07777];
}
else
{
if (!machine().side_effects_disabled())
m_cprom_iview.select(0);
return m_ram[offset];
}
}
WRITE_LINE_MEMBER(decmate2_state::pc278_ioclr_w)
{
if (!state)
{
m_kbd_rflg = false;
m_kbd_tflg = false;
m_prt_rflg = false;
m_prt_tflg = false;
rxinit_w(0);
cominit_w(0);
}
}
WRITE_LINE_MEMBER(decmate2_state::pc238_ioclr_w)
{
if (!state)
{
rxinit_w(0);
cominit_w(0);
}
}
WRITE_LINE_MEMBER(decmate2_state::keyboard_dr_w)
{
m_kbd_rflg = state;
}
WRITE_LINE_MEMBER(decmate2_state::keyboard_dr_ff_w)
{
// TODO: edge trigger
if (state)
m_kbd_rflg = true;
}
WRITE_LINE_MEMBER(decmate2_state::keyboard_tbre_w)
{
m_kbd_tflg = state;
}
WRITE_LINE_MEMBER(decmate2_state::keyboard_tbre_ff_w)
{
// TODO: edge trigger
if (state)
m_kbd_tflg = true;
}
WRITE_LINE_MEMBER(decmate2_state::printer_dr_w)
{
m_prt_rflg = state;
}
WRITE_LINE_MEMBER(decmate2_state::printer_dr_ff_w)
{
// TODO: edge trigger
if (state)
m_prt_rflg = true;
}
WRITE_LINE_MEMBER(decmate2_state::printer_tbre_w)
{
m_prt_tflg = state;
}
WRITE_LINE_MEMBER(decmate2_state::printer_tbre_ff_w)
{
// TODO: edge trigger
if (state)
m_prt_tflg = true;
}
u8 decmate2_state::kbdrflg_devctl_r()
{
return m_kbd_rflg ? hd6120_device::SKIP : 0;
}
void decmate2_state::kbdrflg_set_w(u16 data)
{
m_kbd_rflg = true;
}
void decmate2_state::kbdrflg_clear_w(u16 data)
{
m_kbd_rflg = false;
}
u16 decmate2_state::kbduart_r()
{
return m_kbduart->receive();
}
u8 decmate2_state::kbdtflg_devctl_r()
{
return m_kbd_tflg ? hd6120_device::SKIP : 0;
}
void decmate2_state::kbdtflg_set_w(u16 data)
{
m_kbd_tflg = true;
}
void decmate2_state::kbdtflg_clear_w(u16 data)
{
m_kbd_tflg = false;
}
u8 decmate2_state::prtrflg_devctl_r()
{
return m_prt_rflg ? hd6120_device::SKIP : 0;
}
void decmate2_state::prtrflg_set_w(u16 data)
{
m_prt_rflg = true;
}
void decmate2_state::prtrflg_clear_w(u16 data)
{
m_prt_rflg = false;
}
u16 decmate2_state::prtuart_r()
{
return m_prtuart->receive();
}
u8 decmate2_state::prttflg_devctl_r()
{
return m_prt_tflg ? hd6120_device::SKIP : 0;
}
void decmate2_state::prttflg_set_w(u16 data)
{
m_prt_tflg = true;
}
void decmate2_state::prttflg_clear_w(u16 data)
{
m_prt_tflg = false;
}
u8 decmate2_state::apten_r()
{
// TODO: from pin 4 of printer connector J2
return 0;
}
u8 decmate2_state::comreg_devctl_r()
{
if (m_com_control_read)
return hd6120_device::C1;
else
return 0;
}
u16 decmate2_state::comreg_r()
{
if (m_eadd0)
return m_mpscc->cb_r();
else
return m_mpscc->ca_r();
}
void decmate2_state::comreg_w(u16 data)
{
if (!m_com_control_read)
{
if (m_eadd0)
m_mpscc->cb_w(data & 0377);
else
m_mpscc->ca_w(data & 0377);
}
m_com_control_read = BIT(data, 11);
}
void decmate2_state::cominit_w(u16 data)
{
m_mpscc->reset();
m_com_control_read = false;
}
u8 decmate2_state::vint_devctl_r()
{
return m_vint ? hd6120_device::SKIP : 0;
}
void decmate2_state::lscreg_w(u16 data)
{
m_crtc_addr = data & 077;
}
void decmate2_state::wrcrtc_w(u16 data)
{
m_crtc->write(m_crtc_addr, data & 0377);
}
u16 decmate2_state::rdcrtc_r()
{
return m_crtc->read(m_crtc_addr);
}
void decmate2_state::video_mod_w(u16 data)
{
logerror("%s: Loading %04o into video mod register (loopback %s)\n", machine().describe_context(), data, BIT(data, 4) ? "enabled" : "disabled");
}
void decmate2_state::modem_w(u16 data)
{
logerror("%s: Writing %04o to modem control register\n", machine().describe_context(), data);
}
void decmate2_state::sel_w(u16 data)
{
logerror("%s: RX drive pair %c selected\n", machine().describe_context(), BIT(data, 0) ? 'B' : 'A');
if (BIT(data, 0))
m_rx_status |= 0x80;
else
m_rx_status &= 0x7f;
}
void decmate2_state::lcd_w(u16 data)
{
logerror("%s: RX %d-bit command %d, drive %d\n", machine().describe_context(), BIT(data, 6) ? 8 : 12, BIT(data, 1, 3), BIT(data, 4));
m_rxdata = data;
m_rx_status &= 0xfc;
if (!BIT(data, 6))
m_rx_status |= 0x01;
m_rxcpu->set_input_line(MCS51_INT1_LINE, CLEAR_LINE);
}
u16 decmate2_state::xdr_r()
{
if (BIT(m_rx_status, 1))
{
if (!machine().side_effects_disabled())
logerror("%s: XDR received %04o from 8051\n", machine().describe_context(), m_rxdata);
return m_rxdata;
}
else
return 0;
}
void decmate2_state::xdr_w(u16 data)
{
if (!BIT(m_rx_status, 1))
{
logerror("%s: XDR transmit %04o to 8051\n", machine().describe_context(), data);
m_rxdata = data;
}
m_rxcpu->set_input_line(MCS51_INT1_LINE, CLEAR_LINE);
}
u8 decmate2_state::xdr_devctl_r()
{
if (BIT(m_rx_status, 1))
return hd6120_device::C1 | (BIT(m_rx_status, 0) ? hd6120_device::C0 : 0);
else
return 0;
}
u8 decmate2_state::str_devctl_r()
{
if (BIT(m_rx_control, 3))
{
if (!machine().side_effects_disabled())
m_rx_control &= 0x07;
return hd6120_device::SKIP;
}
else
return 0;
}
u8 decmate2_state::ser_devctl_r()
{
if (BIT(m_rx_control, 2))
{
if (!machine().side_effects_disabled())
m_rx_control &= 0x0b;
return hd6120_device::SKIP;
}
else
return 0;
}
u8 decmate2_state::sdn_devctl_r()
{
if (BIT(m_rx_control, 0))
{
if (!machine().side_effects_disabled())
m_rx_control &= 0x0e;
return hd6120_device::SKIP;
}
else
return 0;
}
void decmate2_state::intr_w(u16 data)
{
logerror("%s: RX interrupt enable %s\n", machine().describe_context(), BIT(data, 0) ? "set" : "cleared");
}
void decmate2_state::rxinit_w(u16 data)
{
m_rx_control = 0;
m_rx_status = (m_rx_status & 0x02) | 0x01;
m_rxcpu->set_input_line(MCS51_INT0_LINE, ASSERT_LINE);
}
u8 decmate2_state::rx_ldata_r() u8 decmate2_state::rx_ldata_r()
{ {
return m_rxdata & 0xff; return m_rxdata & 0xff;
@ -199,18 +679,20 @@ void decmate2_state::rx_hdata_w(u8 data)
void decmate2_state::rx_control_w(u8 data) void decmate2_state::rx_control_w(u8 data)
{ {
// TODO m_rx_control = data & 0x0d;
m_rx_status = (m_rx_status & 0xfd) | (data & 0x02);
m_rxcpu->set_input_line(MCS51_INT0_LINE, CLEAR_LINE);
m_rxcpu->set_input_line(MCS51_INT1_LINE, ASSERT_LINE);
} }
u8 decmate2_state::rx_status_r() u8 decmate2_state::rx_status_r()
{ {
// TODO return m_rx_status;
return 0;
} }
u8 decmate2_state::rx_intr_r() u8 decmate2_state::rx_intr_r()
{ {
return m_fdc->intrq_r() << 5; return m_fdc->intrq_r() << 5 | 0xdf;
} }
void decmate2_state::rx_sel_w(u8 data) void decmate2_state::rx_sel_w(u8 data)
@ -236,15 +718,25 @@ void decmate2_state::rx_sel_w(u8 data)
u8 decmate2_state::rx_rdy_r() u8 decmate2_state::rx_rdy_r()
{ {
return m_fdc->drq_r() << 6 /*| m_fdc->ready_r() << 7*/; return m_fdc->drq_r() << 6 | 1 /*m_fdc->ready_r()*/ << 7 | 0x3f;
} }
void decmate2_state::mem_map(address_map &map) void decmate2_state::inst_map(address_map &map)
{ {
map(00000, 07777).rom().region("cprom", 0); map(0000000, 0177777).ram().share("ram");
map(0000000, 0177777).view(m_cprom_iview);
m_cprom_iview[0](0000000, 0007777).mirror(0170000).rom().region("cprom", 0);
m_cprom_iview[1](0000000, 0177777).r(FUNC(decmate2_state::cprom_switch_r));
} }
// TODO: all I/O devices void decmate2_state::data_map(address_map &map)
{
map(0000000, 0177777).ram().share("ram");
map(0000000, 0177777).view(m_cprom_dview);
m_cprom_dview[0](0000000, 0007777).mirror(0170000).rom().region("cprom", 0);
}
// TODO: almost all I/O devices
// 03/04/07: Control panel interrupt // 03/04/07: Control panel interrupt
// 05: Keyboard input // 05: Keyboard input
// 06: Video interrupt // 06: Video interrupt
@ -259,6 +751,89 @@ void decmate2_state::mem_map(address_map &map)
// 36: Modem control and baud rate // 36: Modem control and baud rate
// 75: RX Simulator // 75: RX Simulator
void decmate2_state::pc278_io_map(address_map &map)
{
map(0050, 0050).w(FUNC(decmate2_state::kbdtflg_set_w));
map(0051, 0051).w(FUNC(decmate2_state::kbdtflg_clear_w));
map(0054, 0054).mirror(2).w(m_kbduart, FUNC(ay31015_device::transmit)).umask16(0377);
map(0061, 0061).nopw();
map(0110, 0110).w(FUNC(decmate2_state::kbdrflg_set_w));
map(0111, 0111).w(FUNC(decmate2_state::kbdrflg_clear_w));
map(0112, 0112).nopw();
map(0114, 0114).mirror(2).r(FUNC(decmate2_state::kbduart_r)).nopw();
map(0121, 0121).nopw();
map(0122, 0122).w(FUNC(decmate2_state::lscreg_w));
map(0124, 0124).w(FUNC(decmate2_state::wrcrtc_w));
map(0126, 0126).w(FUNC(decmate2_state::video_mod_w));
map(0127, 0127).r(FUNC(decmate2_state::rdcrtc_r)).nopw();
map(0320, 0320).w(FUNC(decmate2_state::prtrflg_set_w));
map(0321, 0321).w(FUNC(decmate2_state::prtrflg_clear_w));
map(0322, 0322).nopw();
map(0324, 0324).mirror(2).r(FUNC(decmate2_state::prtuart_r)).nopw();
map(0330, 0330).w(FUNC(decmate2_state::prttflg_set_w));
map(0331, 0331).w(FUNC(decmate2_state::prttflg_clear_w));
map(0334, 0334).mirror(2).w(m_prtuart, FUNC(ay31015_device::transmit)).umask16(0377);
map(0362, 0362).w(FUNC(decmate2_state::modem_w));
map(0366, 0366).rw(FUNC(decmate2_state::comreg_r), FUNC(decmate2_state::comreg_w));
map(0367, 0367).w(FUNC(decmate2_state::cominit_w));
map(0750, 0750).w(FUNC(decmate2_state::sel_w));
map(0751, 0751).w(FUNC(decmate2_state::lcd_w));
map(0752, 0752).rw(FUNC(decmate2_state::xdr_r), FUNC(decmate2_state::xdr_w));
map(0753, 0755).nopw();
map(0756, 0756).w(FUNC(decmate2_state::intr_w));
map(0757, 0757).w(FUNC(decmate2_state::rxinit_w));
}
void decmate2_state::pc238_io_map(address_map &map)
{
pc278_io_map(map);
map(0050, 0051).nopw();
map(0110, 0111).nopw();
map(0320, 0321).nopw();
map(0330, 0331).nopw();
}
void decmate2_state::devctl_map(address_map &map)
{
map(0050, 0050).lr8(NAME([]() { return 0; }));
map(0051, 0051).r(FUNC(decmate2_state::kbdtflg_devctl_r));
map(0054, 0054).lr8(NAME([]() { return 0; }));
map(0056, 0056).lr8(NAME([]() { return hd6120_device::C0; }));
map(0061, 0061).r(FUNC(decmate2_state::vint_devctl_r));
map(0110, 0110).lr8(NAME([]() { return 0; }));
map(0111, 0111).r(FUNC(decmate2_state::kbdrflg_devctl_r));
map(0112, 0112).lr8(NAME([]() { return hd6120_device::C0; }));
map(0114, 0114).lr8(NAME([]() { return hd6120_device::C1; }));
map(0116, 0116).lr8(NAME([]() { return hd6120_device::C0 | hd6120_device::C1; }));
map(0121, 0121).r(FUNC(decmate2_state::apten_r));
map(0122, 0126).lr8(NAME([]() { return 0; }));
map(0127, 0127).lr8(NAME([]() { return hd6120_device::C1; }));
map(0302, 0302).lr8(NAME([]() { return hd6120_device::C0; }));
map(0304, 0304).lr8(NAME([]() { return hd6120_device::C1; }));
map(0306, 0306).lr8(NAME([]() { return hd6120_device::C0 | hd6120_device::C1; }));
map(0314, 0314).lr8(NAME([]() { return 0; }));
map(0316, 0316).lr8(NAME([]() { return hd6120_device::C0; }));
map(0320, 0320).lr8(NAME([]() { return 0; }));
map(0321, 0321).r(FUNC(decmate2_state::prtrflg_devctl_r));
map(0322, 0322).lr8(NAME([]() { return hd6120_device::C0; }));
map(0324, 0324).lr8(NAME([]() { return hd6120_device::C1; }));
map(0326, 0326).lr8(NAME([]() { return hd6120_device::C0 | hd6120_device::C1; }));
map(0330, 0330).lr8(NAME([]() { return 0; }));
map(0331, 0331).r(FUNC(decmate2_state::prttflg_devctl_r));
map(0334, 0334).lr8(NAME([]() { return 0; }));
map(0336, 0336).lr8(NAME([]() { return hd6120_device::C0; }));
map(0362, 0363).lr8(NAME([]() { return 0; }));
map(0366, 0366).r(FUNC(decmate2_state::comreg_devctl_r));
map(0367, 0367).lr8(NAME([]() { return 0; }));
map(0750, 0750).lr8(NAME([]() { return 0; }));
map(0751, 0751).lr8(NAME([]() { return hd6120_device::C0; }));
map(0752, 0752).r(FUNC(decmate2_state::xdr_devctl_r));
map(0753, 0753).r(FUNC(decmate2_state::str_devctl_r));
map(0754, 0754).r(FUNC(decmate2_state::ser_devctl_r));
map(0755, 0755).r(FUNC(decmate2_state::sdn_devctl_r));
map(0756, 0757).lr8(NAME([]() { return 0; }));
}
void decmate2_state::rx_map(address_map &map) void decmate2_state::rx_map(address_map &map)
{ {
map.global_mask(0x7ff); map.global_mask(0x7ff);
@ -271,6 +846,11 @@ void decmate2_state::rx_map(address_map &map)
} }
static INPUT_PORTS_START(decmate2) static INPUT_PORTS_START(decmate2)
PORT_START("LAS")
PORT_BIT(00010, IP_ACTIVE_LOW, IPT_UNKNOWN) // APU present
PORT_BIT(00004, IP_ACTIVE_LOW, IPT_UNKNOWN) // storage adapter present
PORT_BIT(00002, IP_ACTIVE_LOW, IPT_UNKNOWN) // graphics controller present
PORT_BIT(07761, IP_ACTIVE_LOW, IPT_UNUSED)
INPUT_PORTS_END INPUT_PORTS_END
static void rx50_floppies(device_slot_interface &device) static void rx50_floppies(device_slot_interface &device)
@ -281,8 +861,19 @@ static void rx50_floppies(device_slot_interface &device)
// XTALs: 5.0688 MHz, 15.741 MHz, 22.896 MHz, 16.000 MHz // XTALs: 5.0688 MHz, 15.741 MHz, 22.896 MHz, 16.000 MHz
void decmate2_state::pc278(machine_config &config) void decmate2_state::pc278(machine_config &config)
{ {
PDP8(config, m_maincpu, 16_MHz_XTAL / 2); // FIXME: HD-6120 with dynamic divider HD6120(config, m_maincpu, 16_MHz_XTAL / 2);
m_maincpu->set_addrmap(AS_PROGRAM, &decmate2_state::mem_map); // TODO: CPU clock is throttled from 8 MHz to 4 MHz while accessing I/O devices or when CPROM is enabled
m_maincpu->set_addrmap(AS_PROGRAM, &decmate2_state::inst_map);
m_maincpu->set_addrmap(AS_DATA, &decmate2_state::data_map);
m_maincpu->set_addrmap(AS_IO, &decmate2_state::pc278_io_map);
m_maincpu->set_addrmap(hd6120_device::AS_DEVCTL, &decmate2_state::devctl_map);
m_maincpu->lxmar_callback().set(FUNC(decmate2_state::lxmar_w));
m_maincpu->lxpar_callback().set(FUNC(decmate2_state::lxpar_w));
m_maincpu->lxdar_callback().set(FUNC(decmate2_state::lxdar_w));
m_maincpu->rsr_callback().set_ioport("LAS");
m_maincpu->wsr_callback().set(FUNC(decmate2_state::wsr_w));
m_maincpu->ioclr_callback().set(FUNC(decmate2_state::pc278_ioclr_w));
m_maincpu->strtup_callback().set_constant(0);
I8051(config, m_rxcpu, 16_MHz_XTAL / 2); I8051(config, m_rxcpu, 16_MHz_XTAL / 2);
m_rxcpu->set_addrmap(AS_IO, &decmate2_state::rx_map); m_rxcpu->set_addrmap(AS_IO, &decmate2_state::rx_map);
@ -300,11 +891,15 @@ void decmate2_state::pc278(machine_config &config)
AY31015(config, m_kbduart); // 6402 AY31015(config, m_kbduart); // 6402
m_kbduart->write_so_callback().set("keyboard", FUNC(lk201_device::rx_w)); m_kbduart->write_so_callback().set("keyboard", FUNC(lk201_device::rx_w));
m_kbduart->write_dav_callback().set(FUNC(decmate2_state::keyboard_dr_ff_w));
m_kbduart->write_tbmt_callback().set(FUNC(decmate2_state::keyboard_tbre_ff_w));
m_kbduart->set_auto_rdav(true); m_kbduart->set_auto_rdav(true);
AY31015(config, m_prtuart); // 6402 AY31015(config, m_prtuart); // 6402
m_prtuart->write_so_callback().set("printer", FUNC(rs232_port_device::write_txd)); m_prtuart->write_so_callback().set("printer", FUNC(rs232_port_device::write_txd));
m_prtuart->write_fe_callback().set_nop(); // TODO: output on connector pin 9 m_prtuart->write_fe_callback().set_nop(); // TODO: output on connector pin 9
m_prtuart->write_dav_callback().set(FUNC(decmate2_state::printer_dr_ff_w));
m_prtuart->write_tbmt_callback().set(FUNC(decmate2_state::printer_tbre_ff_w));
m_prtuart->set_auto_rdav(true); m_prtuart->set_auto_rdav(true);
UPD7201(config, m_mpscc, 16_MHz_XTAL / 8); UPD7201(config, m_mpscc, 16_MHz_XTAL / 8);
@ -329,6 +924,7 @@ void decmate2_state::pc278(machine_config &config)
CRT9007(config, m_crtc, 15.741_MHz_XTAL / 10); CRT9007(config, m_crtc, 15.741_MHz_XTAL / 10);
m_crtc->set_character_width(10); // 9 in 132-column mode m_crtc->set_character_width(10); // 9 in 132-column mode
m_crtc->set_screen("screen"); m_crtc->set_screen("screen");
m_crtc->int_callback().set(FUNC(decmate2_state::vint_w));
LK201(config, "keyboard").tx_handler().set(m_kbduart, FUNC(ay31015_device::write_si)); LK201(config, "keyboard").tx_handler().set(m_kbduart, FUNC(ay31015_device::write_si));
@ -347,6 +943,14 @@ void decmate2_state::pc238(machine_config &config)
config.device_remove("fdc:b0"); config.device_remove("fdc:b0");
config.device_remove("fdc:b1"); config.device_remove("fdc:b1");
m_maincpu->set_addrmap(AS_IO, &decmate2_state::pc238_io_map);
m_maincpu->ioclr_callback().set(FUNC(decmate2_state::pc238_ioclr_w));
m_kbduart->write_dav_callback().set(FUNC(decmate2_state::keyboard_dr_w));
m_kbduart->write_tbmt_callback().set(FUNC(decmate2_state::keyboard_tbre_w));
m_prtuart->write_dav_callback().set(FUNC(decmate2_state::printer_dr_w));
m_prtuart->write_tbmt_callback().set(FUNC(decmate2_state::printer_tbre_w));
clock_device &pclk(CLOCK(config, "pclk", 16_MHz_XTAL / 208)); // Generated on pin 65 of DC382 clock_device &pclk(CLOCK(config, "pclk", 16_MHz_XTAL / 208)); // Generated on pin 65 of DC382
pclk.signal_handler().set(m_kbduart, FUNC(ay31015_device::write_rcp)); pclk.signal_handler().set(m_kbduart, FUNC(ay31015_device::write_rcp));
pclk.signal_handler().append(m_kbduart, FUNC(ay31015_device::write_tcp)); pclk.signal_handler().append(m_kbduart, FUNC(ay31015_device::write_tcp));