mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
imds2: Split out emulation of I/O controller board as separate device
- Add and identify some extra IOC firmware revisions (v1.3 from Bitsavers) - More descriptive names for ROMs of latest IOC revision (from Bitsavers) imds: Remove skeleton driver; ROMs preserved as v1.4 of imds2ioc
This commit is contained in:
parent
d58c0abc64
commit
3c03e7de35
@ -2272,7 +2272,7 @@ files {
|
||||
createMESSProjects(_target, _subtarget, "intel")
|
||||
files {
|
||||
MAME_DIR .. "src/mame/drivers/basic52.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/imds.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/imds2.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/intellec4.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/ipc.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/ipds.cpp",
|
||||
@ -2289,8 +2289,8 @@ files {
|
||||
MAME_DIR .. "src/mame/drivers/sdk80.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/sdk85.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/sdk86.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/imds2.cpp",
|
||||
MAME_DIR .. "src/mame/includes/imds2.h",
|
||||
MAME_DIR .. "src/mame/machine/imds2ioc.cpp",
|
||||
MAME_DIR .. "src/mame/machine/imds2ioc.h",
|
||||
}
|
||||
|
||||
createMESSProjects(_target, _subtarget, "imp")
|
||||
|
@ -1,113 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Robbbert
|
||||
/***************************************************************************
|
||||
|
||||
Intel Intellec MDS
|
||||
|
||||
28/06/2011 Skeleton driver.
|
||||
|
||||
This is a prototyping machine, very complex and expensive.
|
||||
|
||||
It does all i/o via uarts, that is TTY, paper-tape puncher, CRT terminal.
|
||||
It also has proms which can be dynamically programmed to alter the machine
|
||||
architecture, so internal ports change meaning mid-stream. (e.g. port 80).
|
||||
|
||||
The code below is just a sample; it does not represent any aspect of the
|
||||
real hardware.
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "cpu/i8085/i8085.h"
|
||||
#include "machine/terminal.h"
|
||||
|
||||
|
||||
class imds_state : public driver_device
|
||||
{
|
||||
public:
|
||||
imds_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_terminal(*this, "terminal")
|
||||
{ }
|
||||
|
||||
void imds(machine_config &config);
|
||||
|
||||
private:
|
||||
DECLARE_READ8_MEMBER(term_r);
|
||||
DECLARE_READ8_MEMBER(term_status_r);
|
||||
void kbd_put(u8 data);
|
||||
uint8_t m_term_data;
|
||||
virtual void machine_reset() override;
|
||||
void imds_io(address_map &map);
|
||||
void imds_mem(address_map &map);
|
||||
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<generic_terminal_device> m_terminal;
|
||||
};
|
||||
|
||||
READ8_MEMBER( imds_state::term_status_r )
|
||||
{
|
||||
uint8_t ret = m_term_data;
|
||||
m_term_data = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
READ8_MEMBER( imds_state::term_r )
|
||||
{
|
||||
return (m_term_data) ? 0x21 : 0x20;
|
||||
}
|
||||
|
||||
void imds_state::imds_mem(address_map &map)
|
||||
{
|
||||
map.unmap_value_high();
|
||||
map(0x0000, 0x1fff).rom();
|
||||
map(0x2000, 0xffff).ram();
|
||||
}
|
||||
|
||||
void imds_state::imds_io(address_map &map)
|
||||
{
|
||||
map.unmap_value_high();
|
||||
map.global_mask(0xff);
|
||||
}
|
||||
|
||||
/* Input ports */
|
||||
static INPUT_PORTS_START( imds )
|
||||
INPUT_PORTS_END
|
||||
|
||||
void imds_state::kbd_put(u8 data)
|
||||
{
|
||||
m_term_data = data;
|
||||
}
|
||||
|
||||
void imds_state::machine_reset()
|
||||
{
|
||||
m_term_data = 0;
|
||||
}
|
||||
|
||||
MACHINE_CONFIG_START(imds_state::imds)
|
||||
/* basic machine hardware */
|
||||
MCFG_DEVICE_ADD("maincpu", I8080, 4_MHz_XTAL) // no idea of clock.
|
||||
MCFG_DEVICE_PROGRAM_MAP(imds_mem)
|
||||
MCFG_DEVICE_IO_MAP(imds_io)
|
||||
|
||||
// INS8250(config, "ins8250", 1843200);
|
||||
|
||||
/* video hardware */
|
||||
MCFG_DEVICE_ADD(m_terminal, GENERIC_TERMINAL, 0)
|
||||
MCFG_GENERIC_TERMINAL_KEYBOARD_CB(PUT(imds_state, kbd_put))
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
/* ROM definition */
|
||||
ROM_START( imds )
|
||||
ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF )
|
||||
ROM_LOAD( "a62_2716.bin", 0x0000, 0x0800, CRC(86a55b2f) SHA1(21033f7abb2c3e08028613e0c35ffecb703ff4f1))
|
||||
ROM_LOAD( "a51_2716.bin", 0x0800, 0x0800, CRC(ee55c448) SHA1(16c2f7e3b5baeb398adcc59603943910813e6a9b))
|
||||
ROM_LOAD( "a52_2716.bin", 0x1000, 0x0800, CRC(8db1b33e) SHA1(6fc5e438009636dd6d7185071b152b0491d3baeb))
|
||||
ROM_LOAD( "a53_2716.bin", 0x1800, 0x0800, CRC(01690f4f) SHA1(eadef30a3797f41e08d28e7691f8de44c0f3b8ea))
|
||||
ROM_END
|
||||
|
||||
/* Driver */
|
||||
|
||||
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
|
||||
COMP( 1983, imds, 0, 0, imds, imds, imds_state, empty_init, "Intel", "Intellec MDS", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
@ -60,15 +60,6 @@
|
||||
//
|
||||
// A3 8741 CPU @ 3.58 MHz
|
||||
//
|
||||
// NOTE:
|
||||
// Firmware running on PIO is NOT original because a dump is not available at the moment.
|
||||
// Emulator runs a version of PIO firmware that was specifically developed by me to implement
|
||||
// line printer output.
|
||||
//
|
||||
// TODO:
|
||||
// - Find a dump of the original PIO firmware
|
||||
// - Adjust speed of processors. Wait states are not accounted for yet.
|
||||
//
|
||||
// Huge thanks to Dave Mabry for dumping IOC firmware, KB firmware and character generator. This driver would not
|
||||
// exist without his dumps.
|
||||
// (https://web.archive.org/web/20080509062332/http://www.s100-manuals.com/intel/IOC_iMDX_511_Upgrade.zip)
|
||||
@ -88,9 +79,14 @@
|
||||
// the content of floppy disk.
|
||||
|
||||
#include "emu.h"
|
||||
#include "includes/imds2.h"
|
||||
#include "screen.h"
|
||||
#include "speaker.h"
|
||||
#include "machine/imds2ioc.h"
|
||||
|
||||
#include "cpu/i8085/i8085.h"
|
||||
#include "machine/74259.h"
|
||||
#include "machine/i8251.h"
|
||||
#include "machine/pit8253.h"
|
||||
#include "machine/pic8259.h"
|
||||
#include "bus/rs232/rs232.h"
|
||||
|
||||
// CPU oscillator of IPC board: 8 MHz
|
||||
#define IPC_XTAL_Y2 8_MHz_XTAL
|
||||
@ -98,17 +94,44 @@
|
||||
// Y1 oscillator of IPC board: 19.6608 MHz
|
||||
#define IPC_XTAL_Y1 19.6608_MHz_XTAL
|
||||
|
||||
// Main oscillator of IOC board: 22.032 MHz
|
||||
#define IOC_XTAL_Y2 22.032_MHz_XTAL
|
||||
class imds2_state : public driver_device
|
||||
{
|
||||
public:
|
||||
imds2_state(const machine_config &mconfig, device_type type, const char *tag);
|
||||
|
||||
// FDC oscillator of IOC board: 8 MHz
|
||||
#define IOC_XTAL_Y1 8_MHz_XTAL
|
||||
void imds2(machine_config &config);
|
||||
|
||||
// PIO oscillator: 6 MHz
|
||||
#define IOC_XTAL_Y3 6_MHz_XTAL
|
||||
private:
|
||||
DECLARE_READ8_MEMBER(ipc_mem_read);
|
||||
DECLARE_WRITE8_MEMBER(ipc_mem_write);
|
||||
DECLARE_WRITE8_MEMBER(ipc_control_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(ipc_intr_w);
|
||||
DECLARE_READ8_MEMBER(ipcsyspic_r);
|
||||
DECLARE_READ8_MEMBER(ipclocpic_r);
|
||||
DECLARE_WRITE8_MEMBER(ipcsyspic_w);
|
||||
DECLARE_WRITE8_MEMBER(ipclocpic_w);
|
||||
|
||||
// Frequency of beeper
|
||||
#define IOC_BEEP_FREQ 3300
|
||||
virtual void driver_start() override;
|
||||
|
||||
void ipc_io_map(address_map &map);
|
||||
void ipc_mem_map(address_map &map);
|
||||
|
||||
required_device<i8085a_cpu_device> m_ipccpu;
|
||||
required_device<pic8259_device> m_ipcsyspic;
|
||||
required_device<pic8259_device> m_ipclocpic;
|
||||
required_device<pit8253_device> m_ipctimer;
|
||||
required_device_array<i8251_device, 2> m_ipcusart;
|
||||
required_device<ls259_device> m_ipcctrl;
|
||||
required_device_array<rs232_port_device, 2> m_serial;
|
||||
required_device<imds2ioc_device> m_ioc;
|
||||
|
||||
std::vector<uint8_t> m_ipc_ram;
|
||||
|
||||
bool in_ipc_rom(offs_t offset) const;
|
||||
|
||||
// IPC ROM content
|
||||
required_region_ptr<uint8_t> m_ipc_rom;
|
||||
};
|
||||
|
||||
void imds2_state::ipc_mem_map(address_map &map)
|
||||
{
|
||||
@ -118,84 +141,35 @@ void imds2_state::ipc_mem_map(address_map &map)
|
||||
void imds2_state::ipc_io_map(address_map &map)
|
||||
{
|
||||
map.unmap_value_low();
|
||||
map(0xc0, 0xc0).rw(FUNC(imds2_state::imds2_ipc_dbbout_r), FUNC(imds2_state::imds2_ipc_dbbin_data_w));
|
||||
map(0xc1, 0xc1).rw(FUNC(imds2_state::imds2_ipc_status_r), FUNC(imds2_state::imds2_ipc_dbbin_cmd_w));
|
||||
map(0xc0, 0xc1).rw(m_ioc, FUNC(imds2ioc_device::dbb_master_r), FUNC(imds2ioc_device::dbb_master_w));
|
||||
map(0xf0, 0xf3).rw(m_ipctimer, FUNC(pit8253_device::read), FUNC(pit8253_device::write));
|
||||
map(0xf4, 0xf4).rw(m_ipcusart[0], FUNC(i8251_device::data_r), FUNC(i8251_device::data_w));
|
||||
map(0xf5, 0xf5).rw(m_ipcusart[0], FUNC(i8251_device::status_r), FUNC(i8251_device::control_w));
|
||||
map(0xf6, 0xf6).rw(m_ipcusart[1], FUNC(i8251_device::data_r), FUNC(i8251_device::data_w));
|
||||
map(0xf7, 0xf7).rw(m_ipcusart[1], FUNC(i8251_device::status_r), FUNC(i8251_device::control_w));
|
||||
map(0xf8, 0xf9).rw(m_iocpio, FUNC(i8041_device::upi41_master_r), FUNC(i8041_device::upi41_master_w));
|
||||
map(0xfa, 0xfb).rw(FUNC(imds2_state::imds2_ipclocpic_r), FUNC(imds2_state::imds2_ipclocpic_w));
|
||||
map(0xfc, 0xfd).rw(FUNC(imds2_state::imds2_ipcsyspic_r), FUNC(imds2_state::imds2_ipcsyspic_w));
|
||||
map(0xff, 0xff).w(FUNC(imds2_state::imds2_ipc_control_w));
|
||||
}
|
||||
|
||||
void imds2_state::ioc_mem_map(address_map &map)
|
||||
{
|
||||
map.unmap_value_high();
|
||||
map(0x0000, 0x1fff).rom();
|
||||
map(0x4000, 0x5fff).ram();
|
||||
}
|
||||
|
||||
void imds2_state::ioc_io_map(address_map &map)
|
||||
{
|
||||
map.unmap_value_high();
|
||||
map(0x00, 0x0f).w(FUNC(imds2_state::imds2_ioc_dbbout_w));
|
||||
map(0x20, 0x2f).w(FUNC(imds2_state::imds2_ioc_f0_w));
|
||||
map(0x30, 0x3f).w(FUNC(imds2_state::imds2_ioc_set_f1_w));
|
||||
map(0x40, 0x4f).w(FUNC(imds2_state::imds2_ioc_reset_f1_w));
|
||||
map(0x50, 0x5f).w(FUNC(imds2_state::imds2_start_timer_w));
|
||||
map(0x60, 0x6f).w(FUNC(imds2_state::imds2_miscout_w));
|
||||
map(0x80, 0x8f).r(FUNC(imds2_state::imds2_miscin_r));
|
||||
map(0x90, 0x9f).r(FUNC(imds2_state::imds2_kb_read));
|
||||
map(0xa0, 0xaf).r(FUNC(imds2_state::imds2_ioc_status_r));
|
||||
map(0xb0, 0xbf).r(FUNC(imds2_state::imds2_ioc_dbbin_r));
|
||||
map(0xc0, 0xcf).m(m_iocfdc, FUNC(i8271_device::map));
|
||||
map(0xd0, 0xdf).rw(m_ioccrtc, FUNC(i8275_device::read), FUNC(i8275_device::write));
|
||||
map(0xe0, 0xef).rw(m_ioctimer, FUNC(pit8253_device::read), FUNC(pit8253_device::write));
|
||||
// DMA controller range doesn't extend to 0xff because register 0xfd needs to be read as 0xff
|
||||
// This register is used by IOC firmware to detect DMA controller model (either 8237 or 8257)
|
||||
map(0xf0, 0xf8).rw(m_iocdma, FUNC(i8257_device::read), FUNC(i8257_device::write));
|
||||
map(0xf8, 0xf9).rw(m_ioc, FUNC(imds2ioc_device::pio_master_r), FUNC(imds2ioc_device::pio_master_w));
|
||||
map(0xfa, 0xfb).rw(FUNC(imds2_state::ipclocpic_r), FUNC(imds2_state::ipclocpic_w));
|
||||
map(0xfc, 0xfd).rw(FUNC(imds2_state::ipcsyspic_r), FUNC(imds2_state::ipcsyspic_w));
|
||||
map(0xff, 0xff).w(FUNC(imds2_state::ipc_control_w));
|
||||
}
|
||||
|
||||
imds2_state::imds2_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
driver_device(mconfig , type , tag),
|
||||
m_ipccpu(*this , "ipccpu"),
|
||||
m_ipcsyspic(*this , "ipcsyspic"),
|
||||
m_ipclocpic(*this , "ipclocpic"),
|
||||
m_ipctimer(*this , "ipctimer"),
|
||||
driver_device(mconfig, type, tag),
|
||||
m_ipccpu(*this, "ipccpu"),
|
||||
m_ipcsyspic(*this, "ipcsyspic"),
|
||||
m_ipclocpic(*this, "ipclocpic"),
|
||||
m_ipctimer(*this, "ipctimer"),
|
||||
m_ipcusart(*this, "ipcusart%u", 0U),
|
||||
m_ipcctrl(*this, "ipcctrl"),
|
||||
m_serial(*this, "serial%u", 0U),
|
||||
m_ioccpu(*this , "ioccpu"),
|
||||
m_iocdma(*this , "iocdma"),
|
||||
m_ioccrtc(*this , "ioccrtc"),
|
||||
m_iocbeep(*this , "iocbeep"),
|
||||
m_ioctimer(*this , "ioctimer"),
|
||||
m_iocfdc(*this , "iocfdc"),
|
||||
m_flop0(*this, "iocfdc:0"),
|
||||
m_iocpio(*this , "iocpio"),
|
||||
m_kbcpu(*this , "kbcpu"),
|
||||
m_palette(*this , "palette"),
|
||||
m_gfxdecode(*this, "gfxdecode"),
|
||||
m_centronics(*this , "centronics"),
|
||||
m_io_key0(*this , "KEY0"),
|
||||
m_io_key1(*this , "KEY1"),
|
||||
m_io_key2(*this , "KEY2"),
|
||||
m_io_key3(*this , "KEY3"),
|
||||
m_io_key4(*this , "KEY4"),
|
||||
m_io_key5(*this , "KEY5"),
|
||||
m_io_key6(*this , "KEY6"),
|
||||
m_io_key7(*this , "KEY7"),
|
||||
m_ioc_options(*this , "IOC_OPTS"),
|
||||
m_device_status_byte(0xff)
|
||||
m_ioc(*this, "ioc"),
|
||||
m_ipc_rom(*this, "ipcrom")
|
||||
{
|
||||
}
|
||||
|
||||
READ8_MEMBER(imds2_state::ipc_mem_read)
|
||||
{
|
||||
if (imds2_in_ipc_rom(offset)) {
|
||||
if (in_ipc_rom(offset)) {
|
||||
return m_ipc_rom[ (offset & 0x07ff) | ((offset & 0x1000) >> 1) ];
|
||||
} else {
|
||||
return m_ipc_ram[ offset ];
|
||||
@ -204,12 +178,12 @@ READ8_MEMBER(imds2_state::ipc_mem_read)
|
||||
|
||||
WRITE8_MEMBER(imds2_state::ipc_mem_write)
|
||||
{
|
||||
if (!imds2_in_ipc_rom(offset)) {
|
||||
if (!in_ipc_rom(offset)) {
|
||||
m_ipc_ram[ offset ] = data;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2_state::imds2_ipc_control_w)
|
||||
WRITE8_MEMBER(imds2_state::ipc_control_w)
|
||||
{
|
||||
// See A84, pg 28 of [1]
|
||||
// b3 is ~(bit to be written)
|
||||
@ -217,368 +191,38 @@ WRITE8_MEMBER(imds2_state::imds2_ipc_control_w)
|
||||
m_ipcctrl->write_bit(~data & 7, BIT(~data, 3));
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(imds2_state::imds2_ipc_intr)
|
||||
WRITE_LINE_MEMBER(imds2_state::ipc_intr_w)
|
||||
{
|
||||
m_ipccpu->set_input_line(I8085_INTR_LINE , (state != 0) && m_ipcctrl->q2_r());
|
||||
m_ipccpu->set_input_line(I8085_INTR_LINE, (state != 0) && m_ipcctrl->q2_r());
|
||||
}
|
||||
|
||||
READ8_MEMBER(imds2_state::imds2_ipcsyspic_r)
|
||||
READ8_MEMBER(imds2_state::ipcsyspic_r)
|
||||
{
|
||||
return m_ipcsyspic->read(space , offset == 0);
|
||||
return m_ipcsyspic->read(space, !BIT(offset, 0));
|
||||
}
|
||||
|
||||
READ8_MEMBER(imds2_state::imds2_ipclocpic_r)
|
||||
READ8_MEMBER(imds2_state::ipclocpic_r)
|
||||
{
|
||||
return m_ipclocpic->read(space , offset == 0);
|
||||
return m_ipclocpic->read(space, !BIT(offset, 0));
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2_state::imds2_ipcsyspic_w)
|
||||
WRITE8_MEMBER(imds2_state::ipcsyspic_w)
|
||||
{
|
||||
m_ipcsyspic->write(space , offset == 0 , data);
|
||||
m_ipcsyspic->write(space, !BIT(offset, 0), data);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2_state::imds2_ipclocpic_w)
|
||||
WRITE8_MEMBER(imds2_state::ipclocpic_w)
|
||||
{
|
||||
m_ipclocpic->write(space , offset == 0 , data);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2_state::imds2_miscout_w)
|
||||
{
|
||||
m_miscout = data;
|
||||
imds2_update_beeper();
|
||||
// Send INTR to IPC
|
||||
m_ipclocpic->ir6_w(BIT(m_miscout , 1));
|
||||
}
|
||||
|
||||
READ8_MEMBER(imds2_state::imds2_miscin_r)
|
||||
{
|
||||
uint8_t res = m_ioc_options->read();
|
||||
return res | ((m_beeper_timer == 0) << 2);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(imds2_state::imds2_beep_timer_w)
|
||||
{
|
||||
m_beeper_timer = state;
|
||||
imds2_update_beeper();
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2_state::imds2_start_timer_w)
|
||||
{
|
||||
// Trigger timer 2 of ioctimer
|
||||
m_ioctimer->write_gate2(0);
|
||||
m_ioctimer->write_gate2(1);
|
||||
}
|
||||
|
||||
READ8_MEMBER(imds2_state::imds2_kb_read)
|
||||
{
|
||||
return m_kbcpu->upi41_master_r(space , (offset & 2) >> 1);
|
||||
}
|
||||
|
||||
READ8_MEMBER(imds2_state::imds2_kb_port_p2_r)
|
||||
{
|
||||
if ((m_kb_p1 & 3) == 0) {
|
||||
// Row selected
|
||||
// Row number is encoded on bits P15..P12, they are "backwards" (P15 is LSB) and keyboard rows are encoded starting with value 2 on these bits (see A4, pg 56 of [1])
|
||||
unsigned row = (m_kb_p1 >> 2) & 0x0f;
|
||||
ioport_value data;
|
||||
|
||||
switch (row) {
|
||||
case 4:
|
||||
// Row 0
|
||||
data = m_io_key0->read();
|
||||
break;
|
||||
|
||||
case 12:
|
||||
// Row 1
|
||||
data = m_io_key1->read();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Row 2
|
||||
data = m_io_key2->read();
|
||||
break;
|
||||
|
||||
case 10:
|
||||
// Row 3
|
||||
data = m_io_key3->read();
|
||||
break;
|
||||
|
||||
case 6:
|
||||
// Row 4
|
||||
data = m_io_key4->read();
|
||||
break;
|
||||
|
||||
case 14:
|
||||
// Row 5
|
||||
data = m_io_key5->read();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Row 6
|
||||
data = m_io_key6->read();
|
||||
break;
|
||||
|
||||
case 9:
|
||||
// Row 7
|
||||
data = m_io_key7->read();
|
||||
break;
|
||||
|
||||
default:
|
||||
data = 0xff;
|
||||
break;
|
||||
}
|
||||
return data & 0xff;
|
||||
} else {
|
||||
// No row selected
|
||||
return 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2_state::imds2_kb_port_p1_w)
|
||||
{
|
||||
m_kb_p1 = data;
|
||||
}
|
||||
|
||||
READ_LINE_MEMBER(imds2_state::imds2_kb_port_t0_r)
|
||||
{
|
||||
// T0 tied low
|
||||
// It appears to be some kind of strapping option on kb hw
|
||||
return 0;
|
||||
}
|
||||
|
||||
READ_LINE_MEMBER(imds2_state::imds2_kb_port_t1_r)
|
||||
{
|
||||
// T1 tied low
|
||||
// It appears to be some kind of strapping option on kb hw
|
||||
return 0;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2_state::imds2_ioc_dbbout_w)
|
||||
{
|
||||
m_ioc_obf = ~data;
|
||||
// Set/reset OBF flag (b0)
|
||||
m_ipc_ioc_status = ((offset & 1) == 0) | (m_ipc_ioc_status & ~0x01);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2_state::imds2_ioc_f0_w)
|
||||
{
|
||||
// Set/reset F0 flag (b2)
|
||||
m_ipc_ioc_status = ((offset & 1) << 2) | (m_ipc_ioc_status & ~0x04);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2_state::imds2_ioc_set_f1_w)
|
||||
{
|
||||
// Set F1 flag (b3)
|
||||
m_ipc_ioc_status |= 0x08;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2_state::imds2_ioc_reset_f1_w)
|
||||
{
|
||||
// Reset F1 flag (b3)
|
||||
m_ipc_ioc_status &= ~0x08;
|
||||
}
|
||||
|
||||
READ8_MEMBER(imds2_state::imds2_ioc_status_r)
|
||||
{
|
||||
return ~m_ipc_ioc_status;
|
||||
}
|
||||
|
||||
READ8_MEMBER(imds2_state::imds2_ioc_dbbin_r)
|
||||
{
|
||||
// Reset IBF flag (b1)
|
||||
m_ipc_ioc_status &= ~0x02;
|
||||
return ~m_ioc_ibf;
|
||||
}
|
||||
|
||||
READ8_MEMBER(imds2_state::imds2_ipc_dbbout_r)
|
||||
{
|
||||
// Reset OBF flag (b0)
|
||||
m_ipc_ioc_status &= ~0x01;
|
||||
return m_ioc_obf;
|
||||
}
|
||||
|
||||
READ8_MEMBER(imds2_state::imds2_ipc_status_r)
|
||||
{
|
||||
return m_ipc_ioc_status;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2_state::imds2_ipc_dbbin_data_w)
|
||||
{
|
||||
// Set IBF flag (b1)
|
||||
m_ipc_ioc_status |= 0x02;
|
||||
// Reset F1 flag (b3)
|
||||
m_ipc_ioc_status &= ~0x08;
|
||||
m_ioc_ibf = data;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2_state::imds2_ipc_dbbin_cmd_w)
|
||||
{
|
||||
// Set IBF flag (b1)
|
||||
m_ipc_ioc_status |= 0x02;
|
||||
// Set F1 flag (b3)
|
||||
m_ipc_ioc_status |= 0x08;
|
||||
m_ioc_ibf = data;
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(imds2_state::imds2_hrq_w)
|
||||
{
|
||||
// Should be propagated to HOLD input of IOC CPU
|
||||
m_iocdma->hlda_w(state);
|
||||
}
|
||||
|
||||
READ8_MEMBER(imds2_state::imds2_ioc_mem_r)
|
||||
{
|
||||
address_space& prog_space = m_ioccpu->space(AS_PROGRAM);
|
||||
return prog_space.read_byte(offset);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2_state::imds2_ioc_mem_w)
|
||||
{
|
||||
address_space& prog_space = m_ioccpu->space(AS_PROGRAM);
|
||||
return prog_space.write_byte(offset , data);
|
||||
}
|
||||
|
||||
READ8_MEMBER(imds2_state::imds2_pio_port_p1_r)
|
||||
{
|
||||
// If STATUS ENABLE/ == 0 return inverted device status byte, else return 0xff
|
||||
// STATUS ENABLE/ == 0 when P23-P20 == 12 & P24 == 0 & P25 = 1 & P26 = 1
|
||||
if ((m_pio_port2 & 0x7f) == 0x6c) {
|
||||
return ~m_device_status_byte;
|
||||
} else {
|
||||
return 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2_state::imds2_pio_port_p1_w)
|
||||
{
|
||||
m_pio_port1 = data;
|
||||
imds2_update_printer();
|
||||
}
|
||||
|
||||
READ8_MEMBER(imds2_state::imds2_pio_port_p2_r)
|
||||
{
|
||||
return m_pio_port2;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2_state::imds2_pio_port_p2_w)
|
||||
{
|
||||
m_pio_port2 = data;
|
||||
imds2_update_printer();
|
||||
// Send INTR to IPC
|
||||
m_ipclocpic->ir5_w(BIT(data , 7));
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(imds2_state::imds2_pio_lpt_ack_w)
|
||||
{
|
||||
if (state) {
|
||||
m_device_status_byte |= 0x20;
|
||||
} else {
|
||||
m_device_status_byte &= ~0x20;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(imds2_state::imds2_pio_lpt_busy_w)
|
||||
{
|
||||
// Busy is active high in centronics_device whereas it's active low in MDS
|
||||
if (!state) {
|
||||
m_device_status_byte |= 0x10;
|
||||
} else {
|
||||
m_device_status_byte &= ~0x10;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(imds2_state::imds2_pio_lpt_select_w)
|
||||
{
|
||||
if (state) {
|
||||
m_device_status_byte |= 0x40;
|
||||
} else {
|
||||
m_device_status_byte &= ~0x40;
|
||||
}
|
||||
}
|
||||
|
||||
I8275_DRAW_CHARACTER_MEMBER(imds2_state::crtc_display_pixels)
|
||||
{
|
||||
unsigned i;
|
||||
const rgb_t *palette = m_palette->palette()->entry_list_raw();
|
||||
uint8_t chargen_byte = m_chargen[ (linecount & 7) | ((unsigned)charcode << 3) ];
|
||||
uint16_t pixels;
|
||||
|
||||
if (lten) {
|
||||
pixels = ~0;
|
||||
} else if (vsp != 0 || (linecount & 8) != 0) {
|
||||
pixels = 0; // VSP is gated with LC3
|
||||
} else {
|
||||
// See [2], pg 58 for the very peculiar way of generating character images
|
||||
// Here each half-pixel is translated into a full pixel
|
||||
uint16_t exp_pix_l;
|
||||
uint16_t exp_pix_r;
|
||||
|
||||
exp_pix_l = (uint16_t)chargen_byte;
|
||||
exp_pix_l = ((exp_pix_l & 0x80) << 5) |
|
||||
((exp_pix_l & 0x40) << 4) |
|
||||
((exp_pix_l & 0x20) << 3) |
|
||||
((exp_pix_l & 0x10) << 2) |
|
||||
((exp_pix_l & 0x08) << 1) |
|
||||
(exp_pix_l & 0x04);
|
||||
exp_pix_l |= (exp_pix_l << 1);
|
||||
exp_pix_r = exp_pix_l;
|
||||
|
||||
// Layout of exp_pix_l/r:
|
||||
// Bit # : F E D C B A 9 8 7 6 5 4 3 2 1 0
|
||||
// Bit of chargen_byte: 0 0 b7 b7 b6 b6 b5 b5 b4 b4 b3 b3 b2 b2 0 0
|
||||
if ((chargen_byte & 2) == 0) {
|
||||
exp_pix_l >>= 1;
|
||||
}
|
||||
exp_pix_l &= 0x3fc0;
|
||||
|
||||
if ((chargen_byte & 1) == 0) {
|
||||
exp_pix_r >>= 1;
|
||||
}
|
||||
exp_pix_r &= 0x003e;
|
||||
|
||||
pixels = exp_pix_l | exp_pix_r;
|
||||
}
|
||||
|
||||
if (rvv) {
|
||||
pixels = ~pixels;
|
||||
}
|
||||
|
||||
for (i = 0; i < 14; i++) {
|
||||
bitmap.pix32(y, x + i) = palette[ (pixels & (1U << (13 - i))) != 0 ];
|
||||
}
|
||||
m_ipclocpic->write(space, !BIT(offset, 0), data);
|
||||
}
|
||||
|
||||
void imds2_state::driver_start()
|
||||
{
|
||||
// Allocate 64k for IPC RAM
|
||||
m_ipc_ram.resize(0x10000);
|
||||
|
||||
memory_region *ipcrom = memregion("ipcrom");
|
||||
if (ipcrom == nullptr) {
|
||||
fatalerror("Unable to find IPC ROM region\n");
|
||||
} else {
|
||||
m_ipc_rom = ipcrom->base();
|
||||
}
|
||||
}
|
||||
|
||||
void imds2_state::machine_start()
|
||||
{
|
||||
m_iocfdc->set_ready_line_connected(true);
|
||||
}
|
||||
|
||||
void imds2_state::video_start()
|
||||
{
|
||||
m_chargen = memregion("gfx1")->base();
|
||||
}
|
||||
|
||||
void imds2_state::machine_reset()
|
||||
{
|
||||
m_ipc_ioc_status = 0x0f;
|
||||
|
||||
m_iocfdc->set_rate(500000); // The IMD images show a rate of 500kbps
|
||||
}
|
||||
|
||||
bool imds2_state::imds2_in_ipc_rom(offs_t offset) const
|
||||
bool imds2_state::in_ipc_rom(offs_t offset) const
|
||||
{
|
||||
offs_t masked_offset = offset & 0xf800;
|
||||
bool start_up = m_ipcctrl->q5_r();
|
||||
@ -602,312 +246,80 @@ bool imds2_state::imds2_in_ipc_rom(offs_t offset) const
|
||||
return false;
|
||||
}
|
||||
|
||||
void imds2_state::imds2_update_beeper(void)
|
||||
{
|
||||
m_iocbeep->set_state(m_beeper_timer == 0 && BIT(m_miscout , 0) == 0);
|
||||
}
|
||||
|
||||
void imds2_state::imds2_update_printer(void)
|
||||
{
|
||||
// Data to printer is ~P1 when STATUS ENABLE/==1, else 0xff (assuming pull-ups on printer)
|
||||
uint8_t printer_data;
|
||||
if ((m_pio_port2 & 0x7f) == 0x6c) {
|
||||
printer_data = 0xff;
|
||||
} else {
|
||||
printer_data = ~m_pio_port1;
|
||||
}
|
||||
m_centronics->write_data0(BIT(printer_data , 0));
|
||||
m_centronics->write_data1(BIT(printer_data , 1));
|
||||
m_centronics->write_data2(BIT(printer_data , 2));
|
||||
m_centronics->write_data3(BIT(printer_data , 3));
|
||||
m_centronics->write_data4(BIT(printer_data , 4));
|
||||
m_centronics->write_data5(BIT(printer_data , 5));
|
||||
m_centronics->write_data6(BIT(printer_data , 6));
|
||||
m_centronics->write_data7(BIT(printer_data , 7));
|
||||
|
||||
// LPT DATA STROBE/ == 0 when P23-P20 == 9 & P24 == 0
|
||||
m_centronics->write_strobe((m_pio_port2 & 0x1f) != 0x09);
|
||||
}
|
||||
|
||||
static INPUT_PORTS_START(imds2)
|
||||
// See [1], pg 56 for key matrix layout
|
||||
// See [1], pg 57 for keyboard layout
|
||||
PORT_START("KEY0")
|
||||
PORT_BIT(0x01 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR('\t') // OK
|
||||
PORT_BIT(0x02 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR('@') PORT_CHAR('`') // OK
|
||||
PORT_BIT(0x04 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') // OK
|
||||
PORT_BIT(0x08 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) // OK
|
||||
PORT_BIT(0x10 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') // OK
|
||||
PORT_BIT(0x20 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(':') PORT_CHAR('*') // OK
|
||||
PORT_BIT(0x40 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') // OK
|
||||
PORT_BIT(0x80 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') // OK
|
||||
|
||||
PORT_START("KEY1")
|
||||
PORT_BIT(0x01 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') // OK
|
||||
PORT_BIT(0x02 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') // OK
|
||||
PORT_BIT(0x04 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') // OK
|
||||
PORT_BIT(0x08 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') // OK
|
||||
PORT_BIT(0x10 , IP_ACTIVE_LOW , IPT_UNUSED)
|
||||
PORT_BIT(0x20 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') // OK
|
||||
PORT_BIT(0x40 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') // OK
|
||||
PORT_BIT(0x80 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') // OK
|
||||
|
||||
PORT_START("KEY2")
|
||||
PORT_BIT(0x01 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('~') // OK
|
||||
PORT_BIT(0x02 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{') // OK
|
||||
PORT_BIT(0x04 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') // OK
|
||||
PORT_BIT(0x08 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') // OK
|
||||
PORT_BIT(0x10 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') // OK
|
||||
PORT_BIT(0x20 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('=') // OK
|
||||
PORT_BIT(0x40 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') // OK
|
||||
PORT_BIT(0x80 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(';') PORT_CHAR('+') // OK
|
||||
|
||||
PORT_START("KEY3")
|
||||
PORT_BIT(0x01 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') // OK
|
||||
PORT_BIT(0x02 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') // OK
|
||||
PORT_BIT(0x04 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') // OK
|
||||
PORT_BIT(0x08 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') // OK
|
||||
PORT_BIT(0x10 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') // OK
|
||||
PORT_BIT(0x20 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') // OK
|
||||
PORT_BIT(0x40 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') // OK
|
||||
PORT_BIT(0x80 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') // OK
|
||||
|
||||
PORT_START("KEY4")
|
||||
PORT_BIT(0x01 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') // OK
|
||||
PORT_BIT(0x02 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') // OK
|
||||
PORT_BIT(0x04 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') // OK
|
||||
PORT_BIT(0x08 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') // OK
|
||||
PORT_BIT(0x10 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') // OK
|
||||
PORT_BIT(0x20 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') // OK
|
||||
PORT_BIT(0x40 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') // OK
|
||||
PORT_BIT(0x80 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') // OK
|
||||
|
||||
PORT_START("KEY5")
|
||||
PORT_BIT(0x01 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') // OK
|
||||
PORT_BIT(0x02 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') // OK
|
||||
PORT_BIT(0x04 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') // OK
|
||||
PORT_BIT(0x08 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') // OK
|
||||
PORT_BIT(0x10 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') // OK
|
||||
PORT_BIT(0x20 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') // OK
|
||||
PORT_BIT(0x40 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('\'') // OK
|
||||
PORT_BIT(0x80 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') // OK
|
||||
|
||||
PORT_START("KEY6")
|
||||
PORT_BIT(0x01 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) // BS
|
||||
PORT_BIT(0x02 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_HOME) PORT_CHAR(UCHAR_MAMEKEY(HOME)) // OK
|
||||
PORT_BIT(0x04 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('\\') PORT_CHAR('|') // OK
|
||||
PORT_BIT(0x08 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) // OK
|
||||
PORT_BIT(0x10 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2) // OK
|
||||
PORT_BIT(0x20 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) // OK
|
||||
PORT_BIT(0x40 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}') // OK
|
||||
PORT_BIT(0x80 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) // OK
|
||||
|
||||
PORT_START("KEY7")
|
||||
PORT_BIT(0x01 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC)) // OK
|
||||
PORT_BIT(0x02 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) // OK
|
||||
PORT_BIT(0x04 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('_') PORT_CHAR('^') // OK
|
||||
PORT_BIT(0x08 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) // OK
|
||||
PORT_BIT(0x10 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_LALT) PORT_CHAR(UCHAR_MAMEKEY(LALT)) // OK
|
||||
PORT_BIT(0x20 , IP_ACTIVE_LOW , IPT_KEYBOARD) PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK))
|
||||
PORT_BIT(0x40 , IP_ACTIVE_LOW , IPT_UNUSED)
|
||||
PORT_BIT(0x80 , IP_ACTIVE_LOW , IPT_UNUSED)
|
||||
|
||||
// Options on IOC: see [1], pg 40
|
||||
PORT_START("IOC_OPTS")
|
||||
PORT_DIPNAME(0x80 , 0x80 , "Keyboard present")
|
||||
PORT_DIPSETTING(0x80 , DEF_STR(Yes))
|
||||
PORT_DIPSETTING(0x00 , DEF_STR(No))
|
||||
PORT_DIPNAME(0x28 , 0x00 , "IOC mode")
|
||||
PORT_DIPSETTING(0x00 , "On line")
|
||||
PORT_DIPSETTING(0x08 , "Local")
|
||||
PORT_DIPSETTING(0x20 , "Diagnostic")
|
||||
PORT_DIPNAME(0x02 , 0x00 , "Floppy present")
|
||||
PORT_DIPSETTING(0x02 , DEF_STR(Yes))
|
||||
PORT_DIPSETTING(0x00 , DEF_STR(No))
|
||||
PORT_DIPNAME(0x01 , 0x01 , "CRT frame frequency")
|
||||
PORT_DIPSETTING(0x01 , "50 Hz")
|
||||
PORT_DIPSETTING(0x00 , "60 Hz")
|
||||
INPUT_PORTS_END
|
||||
|
||||
static GFXLAYOUT_RAW(imds2_charlayout , 8 , 8 , 8 , 64)
|
||||
|
||||
static GFXDECODE_START(gfx_imds2)
|
||||
GFXDECODE_ENTRY("gfx1" , 0x0000 , imds2_charlayout , 0 , 1)
|
||||
GFXDECODE_END
|
||||
|
||||
static void imds2_floppies(device_slot_interface &device)
|
||||
void imds2_state::imds2(machine_config &config)
|
||||
{
|
||||
device.option_add("8sssd", FLOPPY_8_SSSD);
|
||||
I8085A(config, m_ipccpu, IPC_XTAL_Y2); // CLK OUT = 4 MHz
|
||||
m_ipccpu->set_addrmap(AS_PROGRAM, &imds2_state::ipc_mem_map);
|
||||
m_ipccpu->set_addrmap(AS_IO, &imds2_state::ipc_io_map);
|
||||
m_ipccpu->set_irq_acknowledge_callback("ipcsyspic", FUNC(pic8259_device::inta_cb));
|
||||
//MCFG_QUANTUM_TIME(attotime::from_hz(100))
|
||||
|
||||
PIC8259(config, m_ipcsyspic, 0);
|
||||
m_ipcsyspic->out_int_callback().set(FUNC(imds2_state::ipc_intr_w));
|
||||
m_ipcsyspic->in_sp_callback().set_constant(1);
|
||||
|
||||
PIC8259(config, m_ipclocpic, 0);
|
||||
m_ipclocpic->out_int_callback().set(m_ipcsyspic, FUNC(pic8259_device::ir7_w));
|
||||
m_ipclocpic->in_sp_callback().set_constant(1);
|
||||
|
||||
PIT8253(config, m_ipctimer, 0);
|
||||
m_ipctimer->set_clk<0>(IPC_XTAL_Y1 / 16);
|
||||
m_ipctimer->set_clk<1>(IPC_XTAL_Y1 / 16);
|
||||
m_ipctimer->set_clk<2>(IPC_XTAL_Y1 / 16);
|
||||
m_ipctimer->out_handler<0>().set(m_ipcusart[0], FUNC(i8251_device::write_txc));
|
||||
m_ipctimer->out_handler<0>().append(m_ipcusart[0], FUNC(i8251_device::write_rxc));
|
||||
m_ipctimer->out_handler<1>().set(m_ipcusart[1], FUNC(i8251_device::write_txc));
|
||||
m_ipctimer->out_handler<1>().append(m_ipcusart[1], FUNC(i8251_device::write_rxc));
|
||||
m_ipctimer->out_handler<2>().set(m_ipclocpic, FUNC(pic8259_device::ir4_w));
|
||||
|
||||
I8251(config, m_ipcusart[0], IPC_XTAL_Y1 / 9);
|
||||
m_ipcusart[0]->rts_handler().set(m_ipcusart[0], FUNC(i8251_device::write_cts));
|
||||
m_ipcusart[0]->rxrdy_handler().set(m_ipclocpic, FUNC(pic8259_device::ir0_w));
|
||||
m_ipcusart[0]->txrdy_handler().set(m_ipclocpic, FUNC(pic8259_device::ir1_w));
|
||||
m_ipcusart[0]->txd_handler().set(m_serial[0], FUNC(rs232_port_device::write_txd));
|
||||
|
||||
I8251(config, m_ipcusart[1], IPC_XTAL_Y1 / 9);
|
||||
m_ipcusart[1]->rxrdy_handler().set(m_ipclocpic, FUNC(pic8259_device::ir2_w));
|
||||
m_ipcusart[1]->txrdy_handler().set(m_ipclocpic, FUNC(pic8259_device::ir3_w));
|
||||
m_ipcusart[1]->txd_handler().set(m_serial[1], FUNC(rs232_port_device::write_txd));
|
||||
m_ipcusart[1]->rts_handler().set(m_serial[1], FUNC(rs232_port_device::write_rts));
|
||||
m_ipcusart[1]->dtr_handler().set(m_serial[1], FUNC(rs232_port_device::write_dtr));
|
||||
|
||||
LS259(config, m_ipcctrl); // A84
|
||||
|
||||
RS232_PORT(config, m_serial[0], default_rs232_devices, nullptr);
|
||||
m_serial[0]->rxd_handler().set(m_ipcusart[0], FUNC(i8251_device::write_rxd));
|
||||
m_serial[0]->dsr_handler().set(m_ipcusart[0], FUNC(i8251_device::write_dsr));
|
||||
|
||||
RS232_PORT(config, m_serial[1], default_rs232_devices, nullptr);
|
||||
m_serial[1]->rxd_handler().set(m_ipcusart[1], FUNC(i8251_device::write_rxd));
|
||||
m_serial[1]->cts_handler().set(m_ipcusart[1], FUNC(i8251_device::write_cts));
|
||||
m_serial[1]->dsr_handler().set(m_ipcusart[1], FUNC(i8251_device::write_dsr));
|
||||
|
||||
IMDS2IOC(config, m_ioc);
|
||||
m_ioc->master_intr_cb().set(m_ipclocpic, FUNC(pic8259_device::ir6_w));
|
||||
m_ioc->parallel_int_cb().set(m_ipclocpic, FUNC(pic8259_device::ir5_w));
|
||||
}
|
||||
|
||||
MACHINE_CONFIG_START(imds2_state::imds2)
|
||||
MCFG_DEVICE_ADD("ipccpu", I8085A, IPC_XTAL_Y2) // CLK OUT = 4 MHz
|
||||
MCFG_DEVICE_PROGRAM_MAP(ipc_mem_map)
|
||||
MCFG_DEVICE_IO_MAP(ipc_io_map)
|
||||
MCFG_DEVICE_IRQ_ACKNOWLEDGE_DEVICE("ipcsyspic", pic8259_device, inta_cb)
|
||||
MCFG_QUANTUM_TIME(attotime::from_hz(100))
|
||||
|
||||
MCFG_DEVICE_ADD("ipcsyspic", PIC8259, 0)
|
||||
MCFG_PIC8259_OUT_INT_CB(WRITELINE(*this, imds2_state, imds2_ipc_intr))
|
||||
MCFG_PIC8259_IN_SP_CB(CONSTANT(1))
|
||||
|
||||
MCFG_DEVICE_ADD("ipclocpic", PIC8259, 0)
|
||||
MCFG_PIC8259_OUT_INT_CB(WRITELINE("ipcsyspic", pic8259_device, ir7_w))
|
||||
MCFG_PIC8259_IN_SP_CB(CONSTANT(1))
|
||||
|
||||
PIT8253(config, m_ipctimer, 0);
|
||||
m_ipctimer->set_clk<0>(IPC_XTAL_Y1 / 16);
|
||||
m_ipctimer->set_clk<1>(IPC_XTAL_Y1 / 16);
|
||||
m_ipctimer->set_clk<2>(IPC_XTAL_Y1 / 16);
|
||||
m_ipctimer->out_handler<0>().set(m_ipcusart[0], FUNC(i8251_device::write_txc));
|
||||
m_ipctimer->out_handler<0>().append(m_ipcusart[0], FUNC(i8251_device::write_rxc));
|
||||
m_ipctimer->out_handler<1>().set(m_ipcusart[1], FUNC(i8251_device::write_txc));
|
||||
m_ipctimer->out_handler<1>().append(m_ipcusart[1], FUNC(i8251_device::write_rxc));
|
||||
m_ipctimer->out_handler<2>().set("ipclocpic", FUNC(pic8259_device::ir4_w));
|
||||
|
||||
I8251(config, m_ipcusart[0], IPC_XTAL_Y1 / 9);
|
||||
m_ipcusart[0]->rts_handler().set(m_ipcusart[0], FUNC(i8251_device::write_cts));
|
||||
m_ipcusart[0]->rxrdy_handler().set("ipclocpic", FUNC(pic8259_device::ir0_w));
|
||||
m_ipcusart[0]->txrdy_handler().set("ipclocpic", FUNC(pic8259_device::ir1_w));
|
||||
m_ipcusart[0]->txd_handler().set(m_serial[0], FUNC(rs232_port_device::write_txd));
|
||||
|
||||
I8251(config, m_ipcusart[1], IPC_XTAL_Y1 / 9);
|
||||
m_ipcusart[1]->rxrdy_handler().set("ipclocpic", FUNC(pic8259_device::ir2_w));
|
||||
m_ipcusart[1]->txrdy_handler().set("ipclocpic", FUNC(pic8259_device::ir3_w));
|
||||
m_ipcusart[1]->txd_handler().set(m_serial[1], FUNC(rs232_port_device::write_txd));
|
||||
m_ipcusart[1]->rts_handler().set(m_serial[1], FUNC(rs232_port_device::write_rts));
|
||||
m_ipcusart[1]->dtr_handler().set(m_serial[1], FUNC(rs232_port_device::write_dtr));
|
||||
|
||||
LS259(config, m_ipcctrl); // A84
|
||||
|
||||
MCFG_DEVICE_ADD(m_serial[0], RS232_PORT, default_rs232_devices , nullptr)
|
||||
MCFG_RS232_RXD_HANDLER(WRITELINE(m_ipcusart[0], i8251_device , write_rxd))
|
||||
MCFG_RS232_DSR_HANDLER(WRITELINE(m_ipcusart[0], i8251_device , write_dsr))
|
||||
|
||||
MCFG_DEVICE_ADD(m_serial[1], RS232_PORT, default_rs232_devices , nullptr)
|
||||
MCFG_RS232_RXD_HANDLER(WRITELINE(m_ipcusart[1], i8251_device , write_rxd))
|
||||
MCFG_RS232_CTS_HANDLER(WRITELINE(m_ipcusart[1], i8251_device , write_cts))
|
||||
MCFG_RS232_DSR_HANDLER(WRITELINE(m_ipcusart[1], i8251_device , write_dsr))
|
||||
|
||||
MCFG_DEVICE_ADD("ioccpu" , I8080A , IOC_XTAL_Y2 / 18) // 2.448 MHz but running at 50% (due to wait states & DMA usage of bus)
|
||||
MCFG_DEVICE_PROGRAM_MAP(ioc_mem_map)
|
||||
MCFG_DEVICE_IO_MAP(ioc_io_map)
|
||||
MCFG_QUANTUM_TIME(attotime::from_hz(100))
|
||||
|
||||
// The IOC CRT hw is a bit complex, as the character clock (CCLK) to i8275
|
||||
// is varied according to the part of the video frame being scanned and according to
|
||||
// the 50/60 Hz option jumper (W8).
|
||||
// The basic clock (BCLK) runs at 22.032 MHz.
|
||||
// CCLK = BCLK / 14 when in the active region of video
|
||||
// CCLK = BCLK / 12 when in horizontal retrace (HRTC=1)
|
||||
// CCLK = BCLK / 10 when in horizontal retrace of "short scan lines" (50 Hz only)
|
||||
//
|
||||
// ***** 50 Hz timings *****
|
||||
// 80 chars/row, 26 chars/h. retrace, 11 scan lines/row, 25 active rows, 3 vertical retrace rows
|
||||
// Scan line: 80 chars * 14 BCLK + 26 chars * 12 BCLK = 1432 BCLK (64.996 usec)
|
||||
// Scan row: 11 * scan lines = 15752 BCLK (714.960 usec)
|
||||
// "Short" scan line: 80 chars * 14 BCLK + 26 chars * 10 BCLK = 1380 BCLK (62.636 usec)
|
||||
// Frame: 28 scan rows (8 scan lines of 27th row are short): 27 * scan row + 3 * scan line + 8 * short scan line: 440640 BCLK (20 msec)
|
||||
//
|
||||
// ***** 60 Hz timings *****
|
||||
// 80 chars/row, 20 chars/h. retrace, 10 scan lines/row, 25 active rows, 2 vertical retrace rows
|
||||
// Scan line: 80 chars * 14 BCLK + 20 chars * 12 BCLK = 1360 BCLK (61.728 usec)
|
||||
// Scan row: 10 * scan lines = 13600 BCLK (617.284 usec)
|
||||
// Frame: 27 scan rows : 367200 BCLK (16.667 msec)
|
||||
//
|
||||
// Clock here is semi-bogus: it gives the correct frame frequency at 50 Hz (with the incorrect
|
||||
// assumption that CCLK is fixed at BCLK / 14)
|
||||
MCFG_DEVICE_ADD("ioccrtc" , I8275 , 22853600 / 14)
|
||||
MCFG_I8275_CHARACTER_WIDTH(14)
|
||||
MCFG_I8275_DRAW_CHARACTER_CALLBACK_OWNER(imds2_state , crtc_display_pixels)
|
||||
MCFG_I8275_DRQ_CALLBACK(WRITELINE(m_iocdma , i8257_device , dreq2_w))
|
||||
MCFG_I8275_IRQ_CALLBACK(INPUTLINE("ioccpu" , I8085_INTR_LINE))
|
||||
MCFG_VIDEO_SET_SCREEN("screen")
|
||||
|
||||
MCFG_SCREEN_ADD("screen" , RASTER)
|
||||
MCFG_SCREEN_UPDATE_DEVICE("ioccrtc" , i8275_device , screen_update)
|
||||
MCFG_SCREEN_REFRESH_RATE(50)
|
||||
MCFG_DEVICE_ADD("gfxdecode" , GFXDECODE, "palette" , gfx_imds2)
|
||||
MCFG_PALETTE_ADD_MONOCHROME("palette")
|
||||
|
||||
SPEAKER(config, "mono").front_center();
|
||||
MCFG_DEVICE_ADD("iocbeep" , BEEP , IOC_BEEP_FREQ)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS , "mono" , 1.00)
|
||||
|
||||
I8257(config , m_iocdma , IOC_XTAL_Y2 / 9);
|
||||
m_iocdma->out_hrq_cb().set(FUNC(imds2_state::imds2_hrq_w));
|
||||
m_iocdma->in_memr_cb().set(FUNC(imds2_state::imds2_ioc_mem_r));
|
||||
m_iocdma->out_memw_cb().set(FUNC(imds2_state::imds2_ioc_mem_w));
|
||||
m_iocdma->in_ior_cb<1>().set("iocfdc" , FUNC(i8271_device::data_r));
|
||||
m_iocdma->out_iow_cb<1>().set("iocfdc" , FUNC(i8271_device::data_w));
|
||||
m_iocdma->out_iow_cb<2>().set("ioccrtc" , FUNC(i8275_device::dack_w));
|
||||
|
||||
MCFG_DEVICE_ADD("ioctimer" , PIT8253 , 0)
|
||||
MCFG_PIT8253_CLK0(IOC_XTAL_Y1 / 4)
|
||||
MCFG_PIT8253_OUT0_HANDLER(WRITELINE("ioctimer" , pit8253_device , write_clk2));
|
||||
MCFG_PIT8253_OUT2_HANDLER(WRITELINE(*this, imds2_state , imds2_beep_timer_w));
|
||||
|
||||
I8271(config, m_iocfdc, IOC_XTAL_Y1 / 2);
|
||||
m_iocfdc->drq_wr_callback().set(m_iocdma, FUNC(i8257_device::dreq1_w));
|
||||
MCFG_FLOPPY_DRIVE_ADD("iocfdc:0", imds2_floppies, "8sssd", floppy_image_device::default_floppy_formats)
|
||||
MCFG_SLOT_FIXED(true)
|
||||
|
||||
MCFG_DEVICE_ADD("iocpio" , I8041 , IOC_XTAL_Y3)
|
||||
MCFG_MCS48_PORT_P1_IN_CB(READ8(*this, imds2_state, imds2_pio_port_p1_r))
|
||||
MCFG_MCS48_PORT_P1_OUT_CB(WRITE8(*this, imds2_state, imds2_pio_port_p1_w))
|
||||
MCFG_MCS48_PORT_P2_IN_CB(READ8(*this, imds2_state, imds2_pio_port_p2_r))
|
||||
MCFG_MCS48_PORT_P2_OUT_CB(WRITE8(*this, imds2_state, imds2_pio_port_p2_w))
|
||||
MCFG_QUANTUM_TIME(attotime::from_hz(100))
|
||||
|
||||
MCFG_DEVICE_ADD("kbcpu", I8741, XTAL(3'579'545)) /* 3.579545 MHz */
|
||||
MCFG_MCS48_PORT_P1_OUT_CB(WRITE8(*this, imds2_state, imds2_kb_port_p1_w))
|
||||
MCFG_MCS48_PORT_P2_IN_CB(READ8(*this, imds2_state, imds2_kb_port_p2_r))
|
||||
MCFG_MCS48_PORT_T0_IN_CB(READLINE(*this, imds2_state, imds2_kb_port_t0_r))
|
||||
MCFG_MCS48_PORT_T1_IN_CB(READLINE(*this, imds2_state, imds2_kb_port_t1_r))
|
||||
MCFG_QUANTUM_TIME(attotime::from_hz(100))
|
||||
|
||||
MCFG_DEVICE_ADD(m_centronics, CENTRONICS, centronics_devices, "printer")
|
||||
MCFG_CENTRONICS_ACK_HANDLER(WRITELINE(*this, imds2_state , imds2_pio_lpt_ack_w))
|
||||
MCFG_CENTRONICS_BUSY_HANDLER(WRITELINE(*this, imds2_state , imds2_pio_lpt_busy_w))
|
||||
MCFG_CENTRONICS_PERROR_HANDLER(WRITELINE(*this, imds2_state , imds2_pio_lpt_select_w))
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
ROM_START(imds2)
|
||||
// ROM definition of IPC cpu (8085A)
|
||||
ROM_REGION(0x1000 , "ipcrom" , 0)
|
||||
ROM_DEFAULT_BIOS("mon13")
|
||||
// 1x2732 Copyright 1979
|
||||
ROM_SYSTEM_BIOS(0, "mon13", "Series II Monitor v1.3")
|
||||
ROMX_LOAD("ipc13_a82.bin" , 0x0000 , 0x1000 , CRC(0889394f) SHA1(b7525baf1884a7d67402dea4b5566016a9861ef2), ROM_BIOS(0))
|
||||
// 2x2716 Copyright 1978
|
||||
ROM_SYSTEM_BIOS(1, "mon12", "Series II Monitor v1.2")
|
||||
ROMX_LOAD("ipc12_a57.bin" , 0x0000 , 0x0800 , CRC(6496efaf) SHA1(1a9c0f1b19c1807803db3f1543f51349d7fd693a), ROM_BIOS(1))
|
||||
ROMX_LOAD("ipc12_a48.bin" , 0x0800 , 0x0800 , CRC(258dc9a6) SHA1(3fde993aee06d9af5093d7a2d9a8cbd71fed0951), ROM_BIOS(1))
|
||||
// 2x2716 Copyright 1977
|
||||
ROM_SYSTEM_BIOS(2, "mon11", "Series II Monitor v1.1")
|
||||
ROMX_LOAD("ipc11_a57.bin" , 0x0000 , 0x0800 , CRC(ffb7c036) SHA1(6f60cdfe20621c4b633c972adcb644a1c02eaa39), ROM_BIOS(2))
|
||||
ROMX_LOAD("ipc11_a48.bin" , 0x0800 , 0x0800 , CRC(3696ff28) SHA1(38b435e10a81629430275aec051fb0a55ec1f6fd), ROM_BIOS(2))
|
||||
|
||||
// ROM definition of IOC cpu (8080A)
|
||||
ROM_REGION(0x2000 , "ioccpu" , 0)
|
||||
ROM_LOAD("ioc_a50.bin" , 0x0000 , 0x0800 , CRC(d9f926a1) SHA1(bd9d0f7458acc2806120a6dbaab9c48be315b060))
|
||||
ROM_LOAD("ioc_a51.bin" , 0x0800 , 0x0800 , CRC(6aa2f86c) SHA1(d3a5314d86e3366545b4c97b29e323dfab383d5f))
|
||||
ROM_LOAD("ioc_a52.bin" , 0x1000 , 0x0800 , CRC(b88a38d5) SHA1(934716a1daec852f4d1f846510f42408df0c9584))
|
||||
ROM_LOAD("ioc_a53.bin" , 0x1800 , 0x0800 , CRC(c8df4bb9) SHA1(2dfb921e94ae7033a7182457b2f00657674d1b77))
|
||||
|
||||
// ROM definition of PIO controller (8041A)
|
||||
// For the time being a specially developed PIO firmware is used until a dump of the original PIO is
|
||||
// available.
|
||||
ROM_REGION(0x400 , "iocpio" , 0)
|
||||
ROM_LOAD("pio_a72.bin" , 0 , 0x400 , BAD_DUMP CRC(8c8e740b) SHA1(9b9333a9dc9585aa8f630721d13e551a5c87defc))
|
||||
|
||||
// ROM definition of keyboard controller (8741)
|
||||
ROM_REGION(0x400 , "kbcpu" , 0)
|
||||
ROM_LOAD("kbd511.bin" , 0 , 0x400 , CRC(ba7c4303) SHA1(19899af732d0ae1247bfc79979b1ee5f339ee5cf))
|
||||
// ROM definition of character generator (2708, A19 on IOC)
|
||||
ROM_REGION(0x400 , "gfx1" , 0)
|
||||
ROM_LOAD ("ioc_a19.bin" , 0x0000 , 0x0400 , CRC(47487d0f) SHA1(0ed98f9f06622949ee3cc2ffc572fb9702db0f81))
|
||||
// ROM definition of IPC cpu (8085A)
|
||||
ROM_REGION(0x1000, "ipcrom", 0)
|
||||
ROM_DEFAULT_BIOS("mon13")
|
||||
// 1x2732 Copyright 1979
|
||||
ROM_SYSTEM_BIOS(0, "mon13", "Series II Monitor v1.3")
|
||||
ROMX_LOAD("ipc13_a82.bin", 0x0000, 0x1000, CRC(0889394f) SHA1(b7525baf1884a7d67402dea4b5566016a9861ef2), ROM_BIOS(0))
|
||||
// 2x2716 Copyright 1978
|
||||
ROM_SYSTEM_BIOS(1, "mon12", "Series II Monitor v1.2")
|
||||
ROMX_LOAD("ipc12_a57.bin", 0x0000, 0x0800, CRC(6496efaf) SHA1(1a9c0f1b19c1807803db3f1543f51349d7fd693a), ROM_BIOS(1))
|
||||
ROMX_LOAD("ipc12_a48.bin", 0x0800, 0x0800, CRC(258dc9a6) SHA1(3fde993aee06d9af5093d7a2d9a8cbd71fed0951), ROM_BIOS(1))
|
||||
// 2x2716 Copyright 1977
|
||||
ROM_SYSTEM_BIOS(2, "mon11", "Series II Monitor v1.1")
|
||||
ROMX_LOAD("ipc11_a57.bin", 0x0000, 0x0800, CRC(ffb7c036) SHA1(6f60cdfe20621c4b633c972adcb644a1c02eaa39), ROM_BIOS(2))
|
||||
ROMX_LOAD("ipc11_a48.bin", 0x0800, 0x0800, CRC(3696ff28) SHA1(38b435e10a81629430275aec051fb0a55ec1f6fd), ROM_BIOS(2))
|
||||
ROM_END
|
||||
|
||||
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME */
|
||||
COMP( 1979, imds2, 0, 0, imds2, imds2, imds2_state, empty_init, "Intel", "Intellec MDS-II" , 0)
|
||||
COMP( 1979, imds2, 0, 0, imds2, imds2, imds2_state, empty_init, "Intel", "Intellec MDS-II", 0)
|
||||
|
@ -1,153 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:F. Ulivi
|
||||
// Driver for Intel Intellec MDS series-II
|
||||
|
||||
#ifndef MAME_INCLUDES_IMDS2_H
|
||||
#define MAME_INCLUDES_IMDS2_H
|
||||
|
||||
#include "cpu/i8085/i8085.h"
|
||||
#include "cpu/mcs48/mcs48.h"
|
||||
#include "machine/74259.h"
|
||||
#include "machine/i8257.h"
|
||||
#include "video/i8275.h"
|
||||
#include "sound/beep.h"
|
||||
#include "machine/pit8253.h"
|
||||
#include "machine/pic8259.h"
|
||||
#include "machine/i8271.h"
|
||||
#include "imagedev/flopdrv.h"
|
||||
#include "bus/centronics/ctronics.h"
|
||||
#include "machine/i8251.h"
|
||||
#include "bus/rs232/rs232.h"
|
||||
#include "emupal.h"
|
||||
|
||||
class imds2_state : public driver_device
|
||||
{
|
||||
public:
|
||||
imds2_state(const machine_config &mconfig, device_type type, const char *tag);
|
||||
|
||||
void imds2(machine_config &config);
|
||||
|
||||
private:
|
||||
DECLARE_READ8_MEMBER(ipc_mem_read);
|
||||
DECLARE_WRITE8_MEMBER(ipc_mem_write);
|
||||
DECLARE_WRITE8_MEMBER(imds2_ipc_control_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(imds2_ipc_intr);
|
||||
DECLARE_READ8_MEMBER(imds2_ipcsyspic_r);
|
||||
DECLARE_READ8_MEMBER(imds2_ipclocpic_r);
|
||||
DECLARE_WRITE8_MEMBER(imds2_ipcsyspic_w);
|
||||
DECLARE_WRITE8_MEMBER(imds2_ipclocpic_w);
|
||||
|
||||
DECLARE_WRITE8_MEMBER(imds2_miscout_w);
|
||||
DECLARE_READ8_MEMBER(imds2_miscin_r);
|
||||
DECLARE_WRITE_LINE_MEMBER(imds2_beep_timer_w);
|
||||
DECLARE_WRITE8_MEMBER(imds2_start_timer_w);
|
||||
DECLARE_READ8_MEMBER(imds2_kb_read);
|
||||
DECLARE_READ8_MEMBER(imds2_kb_port_p2_r);
|
||||
DECLARE_WRITE8_MEMBER(imds2_kb_port_p1_w);
|
||||
DECLARE_READ_LINE_MEMBER(imds2_kb_port_t0_r);
|
||||
DECLARE_READ_LINE_MEMBER(imds2_kb_port_t1_r);
|
||||
DECLARE_WRITE8_MEMBER(imds2_ioc_dbbout_w);
|
||||
DECLARE_WRITE8_MEMBER(imds2_ioc_f0_w);
|
||||
DECLARE_WRITE8_MEMBER(imds2_ioc_set_f1_w);
|
||||
DECLARE_WRITE8_MEMBER(imds2_ioc_reset_f1_w);
|
||||
DECLARE_READ8_MEMBER(imds2_ioc_status_r);
|
||||
DECLARE_READ8_MEMBER(imds2_ioc_dbbin_r);
|
||||
DECLARE_READ8_MEMBER(imds2_ipc_dbbout_r);
|
||||
DECLARE_READ8_MEMBER(imds2_ipc_status_r);
|
||||
DECLARE_WRITE8_MEMBER(imds2_ipc_dbbin_data_w);
|
||||
DECLARE_WRITE8_MEMBER(imds2_ipc_dbbin_cmd_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(imds2_hrq_w);
|
||||
|
||||
DECLARE_READ8_MEMBER(imds2_ioc_mem_r);
|
||||
DECLARE_WRITE8_MEMBER(imds2_ioc_mem_w);
|
||||
DECLARE_READ8_MEMBER(imds2_pio_port_p1_r);
|
||||
DECLARE_WRITE8_MEMBER(imds2_pio_port_p1_w);
|
||||
DECLARE_READ8_MEMBER(imds2_pio_port_p2_r);
|
||||
DECLARE_WRITE8_MEMBER(imds2_pio_port_p2_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(imds2_pio_lpt_ack_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(imds2_pio_lpt_busy_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(imds2_pio_lpt_select_w);
|
||||
|
||||
I8275_DRAW_CHARACTER_MEMBER(crtc_display_pixels);
|
||||
|
||||
virtual void driver_start() override;
|
||||
virtual void machine_start() override;
|
||||
virtual void video_start() override;
|
||||
virtual void machine_reset() override;
|
||||
|
||||
void ioc_io_map(address_map &map);
|
||||
void ioc_mem_map(address_map &map);
|
||||
void ipc_io_map(address_map &map);
|
||||
void ipc_mem_map(address_map &map);
|
||||
|
||||
required_device<i8085a_cpu_device> m_ipccpu;
|
||||
required_device<pic8259_device> m_ipcsyspic;
|
||||
required_device<pic8259_device> m_ipclocpic;
|
||||
required_device<pit8253_device> m_ipctimer;
|
||||
required_device_array<i8251_device, 2> m_ipcusart;
|
||||
required_device<ls259_device> m_ipcctrl;
|
||||
required_device_array<rs232_port_device, 2> m_serial;
|
||||
required_device<i8080a_cpu_device> m_ioccpu;
|
||||
required_device<i8257_device> m_iocdma;
|
||||
required_device<i8275_device> m_ioccrtc;
|
||||
required_device<beep_device> m_iocbeep;
|
||||
required_device<pit8253_device> m_ioctimer;
|
||||
required_device<i8271_device> m_iocfdc;
|
||||
required_device<floppy_connector> m_flop0;
|
||||
required_device<i8041_device> m_iocpio;
|
||||
required_device<i8741_device> m_kbcpu;
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<centronics_device> m_centronics;
|
||||
required_ioport m_io_key0;
|
||||
required_ioport m_io_key1;
|
||||
required_ioport m_io_key2;
|
||||
required_ioport m_io_key3;
|
||||
required_ioport m_io_key4;
|
||||
required_ioport m_io_key5;
|
||||
required_ioport m_io_key6;
|
||||
required_ioport m_io_key7;
|
||||
required_ioport m_ioc_options;
|
||||
|
||||
std::vector<uint8_t> m_ipc_ram;
|
||||
|
||||
bool imds2_in_ipc_rom(offs_t offset) const;
|
||||
|
||||
void imds2_update_beeper(void);
|
||||
void imds2_update_printer(void);
|
||||
|
||||
// IPC ROM content
|
||||
const uint8_t *m_ipc_rom;
|
||||
|
||||
// Character generator
|
||||
const uint8_t *m_chargen;
|
||||
|
||||
// MISCOUT state
|
||||
uint8_t m_miscout;
|
||||
|
||||
// Beeper timer line
|
||||
int m_beeper_timer;
|
||||
|
||||
// Keyboard state
|
||||
uint8_t m_kb_p1;
|
||||
|
||||
// IPC to IOC buffer
|
||||
uint8_t m_ioc_ibf;
|
||||
|
||||
// IOC to IPC buffer
|
||||
uint8_t m_ioc_obf;
|
||||
|
||||
// IPC/IOC status
|
||||
uint8_t m_ipc_ioc_status;
|
||||
|
||||
// PIO port 1
|
||||
uint8_t m_pio_port1;
|
||||
|
||||
// PIO port 2
|
||||
uint8_t m_pio_port2;
|
||||
|
||||
// PIO device status byte
|
||||
uint8_t m_device_status_byte;
|
||||
};
|
||||
|
||||
#endif // MAME_INCLUDES_IMDS2_H
|
690
src/mame/machine/imds2ioc.cpp
Normal file
690
src/mame/machine/imds2ioc.cpp
Normal file
@ -0,0 +1,690 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:F. Ulivi
|
||||
// I/O controller for Intel Intellec MDS series-II
|
||||
//
|
||||
// NOTE:
|
||||
// Firmware running on PIO is NOT original because a dump is not available at the moment.
|
||||
// Emulator runs a version of PIO firmware that was specifically developed by me to implement
|
||||
// line printer output.
|
||||
//
|
||||
// TODO:
|
||||
// - Find a dump of the original PIO firmware
|
||||
// - Adjust speed of processors. Wait states are not accounted for yet.
|
||||
|
||||
#include "emu.h"
|
||||
#include "machine/imds2ioc.h"
|
||||
#include "screen.h"
|
||||
#include "speaker.h"
|
||||
|
||||
// Main oscillator of IOC board: 22.032 MHz
|
||||
#define IOC_XTAL_Y2 22.032_MHz_XTAL
|
||||
|
||||
// FDC oscillator of IOC board: 8 MHz
|
||||
#define IOC_XTAL_Y1 8_MHz_XTAL
|
||||
|
||||
// PIO oscillator: 6 MHz
|
||||
#define IOC_XTAL_Y3 6_MHz_XTAL
|
||||
|
||||
// Frequency of beeper
|
||||
#define IOC_BEEP_FREQ 3300
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(IMDS2IOC, imds2ioc_device, "imds2ioc", "Intellec Series II Input/Output Controller")
|
||||
|
||||
void imds2ioc_device::mem_map(address_map &map)
|
||||
{
|
||||
map.unmap_value_high();
|
||||
map(0x0000, 0x1fff).rom();
|
||||
map(0x4000, 0x5fff).ram();
|
||||
}
|
||||
|
||||
void imds2ioc_device::io_map(address_map &map)
|
||||
{
|
||||
map.unmap_value_high();
|
||||
map(0x00, 0x0f).w(FUNC(imds2ioc_device::ioc_dbbout_w));
|
||||
map(0x20, 0x2f).w(FUNC(imds2ioc_device::ioc_f0_w));
|
||||
map(0x30, 0x3f).w(FUNC(imds2ioc_device::ioc_set_f1_w));
|
||||
map(0x40, 0x4f).w(FUNC(imds2ioc_device::ioc_reset_f1_w));
|
||||
map(0x50, 0x5f).w(FUNC(imds2ioc_device::start_timer_w));
|
||||
map(0x60, 0x6f).w(FUNC(imds2ioc_device::miscout_w));
|
||||
map(0x80, 0x8f).r(FUNC(imds2ioc_device::miscin_r));
|
||||
map(0x90, 0x9f).r(FUNC(imds2ioc_device::kb_read));
|
||||
map(0xa0, 0xaf).r(FUNC(imds2ioc_device::ioc_status_r));
|
||||
map(0xb0, 0xbf).r(FUNC(imds2ioc_device::ioc_dbbin_r));
|
||||
map(0xc0, 0xcf).m(m_iocfdc, FUNC(i8271_device::map));
|
||||
map(0xd0, 0xdf).rw(m_ioccrtc, FUNC(i8275_device::read), FUNC(i8275_device::write));
|
||||
map(0xe0, 0xef).rw(m_ioctimer, FUNC(pit8253_device::read), FUNC(pit8253_device::write));
|
||||
// DMA controller range doesn't extend to 0xff because register 0xfd needs to be read as 0xff
|
||||
// This register is used by IOC firmware to detect DMA controller model (either 8237 or 8257)
|
||||
map(0xf0, 0xf8).rw(m_iocdma, FUNC(i8257_device::read), FUNC(i8257_device::write));
|
||||
}
|
||||
|
||||
imds2ioc_device::imds2ioc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||
device_t(mconfig, IMDS2IOC, tag, owner, clock),
|
||||
m_ioccpu(*this, "ioccpu"),
|
||||
m_iocdma(*this, "iocdma"),
|
||||
m_ioccrtc(*this, "ioccrtc"),
|
||||
m_iocbeep(*this, "iocbeep"),
|
||||
m_ioctimer(*this, "ioctimer"),
|
||||
m_iocfdc(*this, "iocfdc"),
|
||||
m_flop0(*this, "iocfdc:0"),
|
||||
m_iocpio(*this, "iocpio"),
|
||||
m_kbcpu(*this, "kbcpu"),
|
||||
m_palette(*this, "palette"),
|
||||
m_gfxdecode(*this, "gfxdecode"),
|
||||
m_centronics(*this, "centronics"),
|
||||
m_io_key(*this, "KEY%u", 0U),
|
||||
m_ioc_options(*this, "IOC_OPTS"),
|
||||
m_master_intr_cb(*this),
|
||||
m_parallel_int_cb(*this),
|
||||
m_chargen(*this, "gfx1"),
|
||||
m_device_status_byte(0xff)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
WRITE8_MEMBER(imds2ioc_device::miscout_w)
|
||||
{
|
||||
m_miscout = data;
|
||||
update_beeper();
|
||||
// Send INTR to IPC
|
||||
m_master_intr_cb(BIT(m_miscout, 1));
|
||||
}
|
||||
|
||||
READ8_MEMBER(imds2ioc_device::miscin_r)
|
||||
{
|
||||
uint8_t res = m_ioc_options->read();
|
||||
return res | ((m_beeper_timer == 0) << 2);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(imds2ioc_device::beep_timer_w)
|
||||
{
|
||||
m_beeper_timer = state;
|
||||
update_beeper();
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2ioc_device::start_timer_w)
|
||||
{
|
||||
// Trigger timer 2 of ioctimer
|
||||
m_ioctimer->write_gate2(0);
|
||||
m_ioctimer->write_gate2(1);
|
||||
}
|
||||
|
||||
READ8_MEMBER(imds2ioc_device::kb_read)
|
||||
{
|
||||
return m_kbcpu->upi41_master_r(space, (offset & 2) >> 1);
|
||||
}
|
||||
|
||||
READ8_MEMBER(imds2ioc_device::kb_port_p2_r)
|
||||
{
|
||||
if ((m_kb_p1 & 3) == 0) {
|
||||
// Row selected
|
||||
// Row number is encoded on bits P15..P12, they are "backwards" (P15 is LSB) and keyboard rows are encoded starting with value 2 on these bits (see A4, pg 56 of schematic)
|
||||
unsigned row = (m_kb_p1 >> 2) & 0x0f;
|
||||
ioport_value data;
|
||||
|
||||
switch (row) {
|
||||
case 4:
|
||||
// Row 0
|
||||
data = m_io_key[0]->read();
|
||||
break;
|
||||
|
||||
case 12:
|
||||
// Row 1
|
||||
data = m_io_key[1]->read();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Row 2
|
||||
data = m_io_key[2]->read();
|
||||
break;
|
||||
|
||||
case 10:
|
||||
// Row 3
|
||||
data = m_io_key[3]->read();
|
||||
break;
|
||||
|
||||
case 6:
|
||||
// Row 4
|
||||
data = m_io_key[4]->read();
|
||||
break;
|
||||
|
||||
case 14:
|
||||
// Row 5
|
||||
data = m_io_key[5]->read();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Row 6
|
||||
data = m_io_key[6]->read();
|
||||
break;
|
||||
|
||||
case 9:
|
||||
// Row 7
|
||||
data = m_io_key[7]->read();
|
||||
break;
|
||||
|
||||
default:
|
||||
data = 0xff;
|
||||
break;
|
||||
}
|
||||
return data & 0xff;
|
||||
} else {
|
||||
// No row selected
|
||||
return 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2ioc_device::kb_port_p1_w)
|
||||
{
|
||||
m_kb_p1 = data;
|
||||
}
|
||||
|
||||
READ_LINE_MEMBER(imds2ioc_device::kb_port_t0_r)
|
||||
{
|
||||
// T0 tied low
|
||||
// It appears to be some kind of strapping option on kb hw
|
||||
return 0;
|
||||
}
|
||||
|
||||
READ_LINE_MEMBER(imds2ioc_device::kb_port_t1_r)
|
||||
{
|
||||
// T1 tied low
|
||||
// It appears to be some kind of strapping option on kb hw
|
||||
return 0;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2ioc_device::ioc_dbbout_w)
|
||||
{
|
||||
m_ioc_obf = ~data;
|
||||
// Set/reset OBF flag (b0)
|
||||
m_ipc_ioc_status = ((offset & 1) == 0) | (m_ipc_ioc_status & ~0x01);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2ioc_device::ioc_f0_w)
|
||||
{
|
||||
// Set/reset F0 flag (b2)
|
||||
m_ipc_ioc_status = ((offset & 1) << 2) | (m_ipc_ioc_status & ~0x04);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2ioc_device::ioc_set_f1_w)
|
||||
{
|
||||
// Set F1 flag (b3)
|
||||
m_ipc_ioc_status |= 0x08;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2ioc_device::ioc_reset_f1_w)
|
||||
{
|
||||
// Reset F1 flag (b3)
|
||||
m_ipc_ioc_status &= ~0x08;
|
||||
}
|
||||
|
||||
READ8_MEMBER(imds2ioc_device::ioc_status_r)
|
||||
{
|
||||
return ~m_ipc_ioc_status;
|
||||
}
|
||||
|
||||
READ8_MEMBER(imds2ioc_device::ioc_dbbin_r)
|
||||
{
|
||||
// Reset IBF flag (b1)
|
||||
if (!machine().side_effects_disabled())
|
||||
m_ipc_ioc_status &= ~0x02;
|
||||
return ~m_ioc_ibf;
|
||||
}
|
||||
|
||||
READ8_MEMBER(imds2ioc_device::dbb_master_r)
|
||||
{
|
||||
// Read status register
|
||||
if (BIT(offset, 0))
|
||||
return m_ipc_ioc_status;
|
||||
else
|
||||
{
|
||||
// Reset OBF flag (b0)
|
||||
if (!machine().side_effects_disabled())
|
||||
m_ipc_ioc_status &= ~0x01;
|
||||
|
||||
// Read output buffer
|
||||
return m_ioc_obf;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2ioc_device::dbb_master_w)
|
||||
{
|
||||
// Set IBF flag (b1)
|
||||
m_ipc_ioc_status |= 0x02;
|
||||
|
||||
// Command/Data = Master A0
|
||||
if (BIT(offset, 0))
|
||||
{
|
||||
// Set F1 flag (b3)
|
||||
m_ipc_ioc_status |= 0x08;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset F1 flag (b3)
|
||||
m_ipc_ioc_status &= ~0x08;
|
||||
}
|
||||
|
||||
// Set input buffer
|
||||
m_ioc_ibf = data;
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(imds2ioc_device::hrq_w)
|
||||
{
|
||||
// Should be propagated to HOLD input of IOC CPU
|
||||
m_iocdma->hlda_w(state);
|
||||
}
|
||||
|
||||
READ8_MEMBER(imds2ioc_device::ioc_mem_r)
|
||||
{
|
||||
address_space& prog_space = m_ioccpu->space(AS_PROGRAM);
|
||||
return prog_space.read_byte(offset);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2ioc_device::ioc_mem_w)
|
||||
{
|
||||
address_space& prog_space = m_ioccpu->space(AS_PROGRAM);
|
||||
return prog_space.write_byte(offset, data);
|
||||
}
|
||||
|
||||
READ8_MEMBER(imds2ioc_device::pio_port_p1_r)
|
||||
{
|
||||
// If STATUS ENABLE/ == 0 return inverted device status byte, else return 0xff
|
||||
// STATUS ENABLE/ == 0 when P23-P20 == 12 & P24 == 0 & P25 = 1 & P26 = 1
|
||||
if ((m_pio_port2 & 0x7f) == 0x6c) {
|
||||
return ~m_device_status_byte;
|
||||
} else {
|
||||
return 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2ioc_device::pio_port_p1_w)
|
||||
{
|
||||
m_pio_port1 = data;
|
||||
update_printer();
|
||||
}
|
||||
|
||||
READ8_MEMBER(imds2ioc_device::pio_port_p2_r)
|
||||
{
|
||||
return m_pio_port2;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2ioc_device::pio_port_p2_w)
|
||||
{
|
||||
m_pio_port2 = data;
|
||||
update_printer();
|
||||
// Send INTR to IPC
|
||||
m_parallel_int_cb(BIT(data, 7));
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(imds2ioc_device::pio_lpt_ack_w)
|
||||
{
|
||||
if (state) {
|
||||
m_device_status_byte |= 0x20;
|
||||
} else {
|
||||
m_device_status_byte &= ~0x20;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(imds2ioc_device::pio_lpt_busy_w)
|
||||
{
|
||||
// Busy is active high in centronics_device whereas it's active low in MDS
|
||||
if (!state) {
|
||||
m_device_status_byte |= 0x10;
|
||||
} else {
|
||||
m_device_status_byte &= ~0x10;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(imds2ioc_device::pio_lpt_select_w)
|
||||
{
|
||||
if (state) {
|
||||
m_device_status_byte |= 0x40;
|
||||
} else {
|
||||
m_device_status_byte &= ~0x40;
|
||||
}
|
||||
}
|
||||
|
||||
I8275_DRAW_CHARACTER_MEMBER(imds2ioc_device::crtc_display_pixels)
|
||||
{
|
||||
unsigned i;
|
||||
const rgb_t *palette = m_palette->palette()->entry_list_raw();
|
||||
uint8_t chargen_byte = m_chargen[ (linecount & 7) | ((unsigned)charcode << 3) ];
|
||||
uint16_t pixels;
|
||||
|
||||
if (lten) {
|
||||
pixels = ~0;
|
||||
} else if (vsp != 0 || (linecount & 8) != 0) {
|
||||
pixels = 0; // VSP is gated with LC3
|
||||
} else {
|
||||
// See hardware ref. manual, pg 58 for the very peculiar way of generating character images
|
||||
// Here each half-pixel is translated into a full pixel
|
||||
uint16_t exp_pix_l;
|
||||
uint16_t exp_pix_r;
|
||||
|
||||
exp_pix_l = (uint16_t)chargen_byte;
|
||||
exp_pix_l = ((exp_pix_l & 0x80) << 5) |
|
||||
((exp_pix_l & 0x40) << 4) |
|
||||
((exp_pix_l & 0x20) << 3) |
|
||||
((exp_pix_l & 0x10) << 2) |
|
||||
((exp_pix_l & 0x08) << 1) |
|
||||
(exp_pix_l & 0x04);
|
||||
exp_pix_l |= (exp_pix_l << 1);
|
||||
exp_pix_r = exp_pix_l;
|
||||
|
||||
// Layout of exp_pix_l/r:
|
||||
// Bit # : F E D C B A 9 8 7 6 5 4 3 2 1 0
|
||||
// Bit of chargen_byte: 0 0 b7 b7 b6 b6 b5 b5 b4 b4 b3 b3 b2 b2 0 0
|
||||
if ((chargen_byte & 2) == 0) {
|
||||
exp_pix_l >>= 1;
|
||||
}
|
||||
exp_pix_l &= 0x3fc0;
|
||||
|
||||
if ((chargen_byte & 1) == 0) {
|
||||
exp_pix_r >>= 1;
|
||||
}
|
||||
exp_pix_r &= 0x003e;
|
||||
|
||||
pixels = exp_pix_l | exp_pix_r;
|
||||
}
|
||||
|
||||
if (rvv) {
|
||||
pixels = ~pixels;
|
||||
}
|
||||
|
||||
for (i = 0; i < 14; i++) {
|
||||
bitmap.pix32(y, x + i) = palette[ (pixels & (1U << (13 - i))) != 0 ];
|
||||
}
|
||||
}
|
||||
|
||||
READ8_MEMBER(imds2ioc_device::pio_master_r)
|
||||
{
|
||||
return m_iocpio->upi41_master_r(space, offset);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(imds2ioc_device::pio_master_w)
|
||||
{
|
||||
m_iocpio->upi41_master_w(space, offset, data);
|
||||
}
|
||||
|
||||
void imds2ioc_device::device_resolve_objects()
|
||||
{
|
||||
m_master_intr_cb.resolve_safe();
|
||||
m_parallel_int_cb.resolve_safe();
|
||||
}
|
||||
|
||||
void imds2ioc_device::device_start()
|
||||
{
|
||||
m_iocfdc->set_ready_line_connected(true);
|
||||
}
|
||||
|
||||
void imds2ioc_device::device_reset()
|
||||
{
|
||||
m_ipc_ioc_status = 0x0f;
|
||||
|
||||
m_iocfdc->set_rate(500000); // The IMD images show a rate of 500kbps
|
||||
}
|
||||
|
||||
void imds2ioc_device::update_beeper()
|
||||
{
|
||||
m_iocbeep->set_state(m_beeper_timer == 0 && BIT(m_miscout, 0) == 0);
|
||||
}
|
||||
|
||||
void imds2ioc_device::update_printer()
|
||||
{
|
||||
// Data to printer is ~P1 when STATUS ENABLE/==1, else 0xff (assuming pull-ups on printer)
|
||||
uint8_t printer_data;
|
||||
if ((m_pio_port2 & 0x7f) == 0x6c) {
|
||||
printer_data = 0xff;
|
||||
} else {
|
||||
printer_data = ~m_pio_port1;
|
||||
}
|
||||
m_centronics->write_data0(BIT(printer_data, 0));
|
||||
m_centronics->write_data1(BIT(printer_data, 1));
|
||||
m_centronics->write_data2(BIT(printer_data, 2));
|
||||
m_centronics->write_data3(BIT(printer_data, 3));
|
||||
m_centronics->write_data4(BIT(printer_data, 4));
|
||||
m_centronics->write_data5(BIT(printer_data, 5));
|
||||
m_centronics->write_data6(BIT(printer_data, 6));
|
||||
m_centronics->write_data7(BIT(printer_data, 7));
|
||||
|
||||
// LPT DATA STROBE/ == 0 when P23-P20 == 9 & P24 == 0
|
||||
m_centronics->write_strobe((m_pio_port2 & 0x1f) != 0x09);
|
||||
}
|
||||
|
||||
static INPUT_PORTS_START(imds2ioc)
|
||||
// See schematic, pg 56 for key matrix layout
|
||||
// See schematic, pg 57 for keyboard layout
|
||||
PORT_START("KEY0")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR('\t') // OK
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR('@') PORT_CHAR('`') // OK
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') // OK
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) // OK
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') // OK
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(':') PORT_CHAR('*') // OK
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') // OK
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') // OK
|
||||
|
||||
PORT_START("KEY1")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') // OK
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') // OK
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') // OK
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') // OK
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') // OK
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') // OK
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') // OK
|
||||
|
||||
PORT_START("KEY2")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('~') // OK
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{') // OK
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') // OK
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') // OK
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') // OK
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('=') // OK
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') // OK
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(';') PORT_CHAR('+') // OK
|
||||
|
||||
PORT_START("KEY3")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') // OK
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') // OK
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') // OK
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') // OK
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') // OK
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') // OK
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') // OK
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') // OK
|
||||
|
||||
PORT_START("KEY4")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') // OK
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') // OK
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') // OK
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') // OK
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') // OK
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') // OK
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') // OK
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') // OK
|
||||
|
||||
PORT_START("KEY5")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') // OK
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') // OK
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') // OK
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') // OK
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') // OK
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') // OK
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('\'') // OK
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') // OK
|
||||
|
||||
PORT_START("KEY6")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) // BS
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_HOME) PORT_CHAR(UCHAR_MAMEKEY(HOME)) // OK
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('\\') PORT_CHAR('|') // OK
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) // OK
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2) // OK
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) // OK
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}') // OK
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) // OK
|
||||
|
||||
PORT_START("KEY7")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC)) // OK
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) // OK
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('_') PORT_CHAR('^') // OK
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) // OK
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LALT) PORT_CHAR(UCHAR_MAMEKEY(LALT)) // OK
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK))
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
|
||||
// Options on IOC: see schematic, pg 40
|
||||
PORT_START("IOC_OPTS")
|
||||
PORT_DIPNAME(0x80, 0x80, "Keyboard present")
|
||||
PORT_DIPSETTING(0x80, DEF_STR(Yes))
|
||||
PORT_DIPSETTING(0x00, DEF_STR(No))
|
||||
PORT_DIPNAME(0x28, 0x00, "IOC mode")
|
||||
PORT_DIPSETTING(0x00, "On line")
|
||||
PORT_DIPSETTING(0x08, "Local")
|
||||
PORT_DIPSETTING(0x20, "Diagnostic")
|
||||
PORT_DIPNAME(0x02, 0x00, "Floppy present")
|
||||
PORT_DIPSETTING(0x02, DEF_STR(Yes))
|
||||
PORT_DIPSETTING(0x00, DEF_STR(No))
|
||||
PORT_DIPNAME(0x01, 0x01, "CRT frame frequency")
|
||||
PORT_DIPSETTING(0x01, "50 Hz")
|
||||
PORT_DIPSETTING(0x00, "60 Hz")
|
||||
INPUT_PORTS_END
|
||||
|
||||
static GFXLAYOUT_RAW(imds2_charlayout, 8, 8, 8, 64)
|
||||
|
||||
static GFXDECODE_START(gfx_imds2)
|
||||
GFXDECODE_ENTRY("gfx1", 0x0000, imds2_charlayout, 0, 1)
|
||||
GFXDECODE_END
|
||||
|
||||
static void imds2_floppies(device_slot_interface &device)
|
||||
{
|
||||
device.option_add("8sssd", FLOPPY_8_SSSD);
|
||||
}
|
||||
|
||||
MACHINE_CONFIG_START(imds2ioc_device::device_add_mconfig)
|
||||
I8080A(config, m_ioccpu, IOC_XTAL_Y2 / 18); // 2.448 MHz but running at 50% (due to wait states & DMA usage of bus)
|
||||
m_ioccpu->set_addrmap(AS_PROGRAM, &imds2ioc_device::mem_map);
|
||||
m_ioccpu->set_addrmap(AS_IO, &imds2ioc_device::io_map);
|
||||
MCFG_QUANTUM_TIME(attotime::from_hz(100))
|
||||
|
||||
// The IOC CRT hw is a bit complex, as the character clock (CCLK) to i8275
|
||||
// is varied according to the part of the video frame being scanned and according to
|
||||
// the 50/60 Hz option jumper (W8).
|
||||
// The basic clock (BCLK) runs at 22.032 MHz.
|
||||
// CCLK = BCLK / 14 when in the active region of video
|
||||
// CCLK = BCLK / 12 when in horizontal retrace (HRTC=1)
|
||||
// CCLK = BCLK / 10 when in horizontal retrace of "short scan lines" (50 Hz only)
|
||||
//
|
||||
// ***** 50 Hz timings *****
|
||||
// 80 chars/row, 26 chars/h. retrace, 11 scan lines/row, 25 active rows, 3 vertical retrace rows
|
||||
// Scan line: 80 chars * 14 BCLK + 26 chars * 12 BCLK = 1432 BCLK (64.996 usec)
|
||||
// Scan row: 11 * scan lines = 15752 BCLK (714.960 usec)
|
||||
// "Short" scan line: 80 chars * 14 BCLK + 26 chars * 10 BCLK = 1380 BCLK (62.636 usec)
|
||||
// Frame: 28 scan rows (8 scan lines of 27th row are short): 27 * scan row + 3 * scan line + 8 * short scan line: 440640 BCLK (20 msec)
|
||||
//
|
||||
// ***** 60 Hz timings *****
|
||||
// 80 chars/row, 20 chars/h. retrace, 10 scan lines/row, 25 active rows, 2 vertical retrace rows
|
||||
// Scan line: 80 chars * 14 BCLK + 20 chars * 12 BCLK = 1360 BCLK (61.728 usec)
|
||||
// Scan row: 10 * scan lines = 13600 BCLK (617.284 usec)
|
||||
// Frame: 27 scan rows : 367200 BCLK (16.667 msec)
|
||||
//
|
||||
// Clock here is semi-bogus: it gives the correct frame frequency at 50 Hz (with the incorrect
|
||||
// assumption that CCLK is fixed at BCLK / 14)
|
||||
I8275(config, m_ioccrtc, 22853600 / 14);
|
||||
m_ioccrtc->set_character_width(14);
|
||||
m_ioccrtc->set_display_callback(FUNC(imds2ioc_device::crtc_display_pixels), this);
|
||||
m_ioccrtc->drq_wr_callback().set(m_iocdma, FUNC(i8257_device::dreq2_w));
|
||||
m_ioccrtc->irq_wr_callback().set_inputline(m_ioccpu, I8085_INTR_LINE);
|
||||
m_ioccrtc->set_screen("screen");
|
||||
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
||||
screen.set_screen_update("ioccrtc", FUNC(i8275_device::screen_update));
|
||||
screen.set_refresh_hz(50);
|
||||
GFXDECODE(config, "gfxdecode", "palette", gfx_imds2);
|
||||
MCFG_PALETTE_ADD_MONOCHROME("palette")
|
||||
|
||||
SPEAKER(config, "mono").front_center();
|
||||
BEEP(config, m_iocbeep, IOC_BEEP_FREQ).add_route(ALL_OUTPUTS, "mono", 1.00);
|
||||
|
||||
I8257(config, m_iocdma, IOC_XTAL_Y2 / 9);
|
||||
m_iocdma->out_hrq_cb().set(FUNC(imds2ioc_device::hrq_w));
|
||||
m_iocdma->in_memr_cb().set(FUNC(imds2ioc_device::ioc_mem_r));
|
||||
m_iocdma->out_memw_cb().set(FUNC(imds2ioc_device::ioc_mem_w));
|
||||
m_iocdma->in_ior_cb<1>().set("iocfdc", FUNC(i8271_device::data_r));
|
||||
m_iocdma->out_iow_cb<1>().set("iocfdc", FUNC(i8271_device::data_w));
|
||||
m_iocdma->out_iow_cb<2>().set(m_ioccrtc, FUNC(i8275_device::dack_w));
|
||||
|
||||
PIT8253(config, m_ioctimer, 0);
|
||||
m_ioctimer->set_clk<0>(IOC_XTAL_Y1 / 4);
|
||||
m_ioctimer->out_handler<0>().set(m_ioctimer, FUNC(pit8253_device::write_clk2));
|
||||
m_ioctimer->out_handler<2>().set(FUNC(imds2ioc_device::beep_timer_w));
|
||||
|
||||
I8271(config, m_iocfdc, IOC_XTAL_Y1 / 2);
|
||||
m_iocfdc->drq_wr_callback().set(m_iocdma, FUNC(i8257_device::dreq1_w));
|
||||
MCFG_FLOPPY_DRIVE_ADD("iocfdc:0", imds2_floppies, "8sssd", floppy_image_device::default_floppy_formats)
|
||||
MCFG_SLOT_FIXED(true)
|
||||
|
||||
I8041(config, m_iocpio, IOC_XTAL_Y3);
|
||||
m_iocpio->p1_in_cb().set(FUNC(imds2ioc_device::pio_port_p1_r));
|
||||
m_iocpio->p1_out_cb().set(FUNC(imds2ioc_device::pio_port_p1_w));
|
||||
m_iocpio->p2_in_cb().set(FUNC(imds2ioc_device::pio_port_p2_r));
|
||||
m_iocpio->p2_out_cb().set(FUNC(imds2ioc_device::pio_port_p2_w));
|
||||
|
||||
I8741(config, m_kbcpu, 3.579545_MHz_XTAL);
|
||||
m_kbcpu->p1_out_cb().set(FUNC(imds2ioc_device::kb_port_p1_w));
|
||||
m_kbcpu->p2_in_cb().set(FUNC(imds2ioc_device::kb_port_p2_r));
|
||||
m_kbcpu->t0_in_cb().set(FUNC(imds2ioc_device::kb_port_t0_r));
|
||||
m_kbcpu->t1_in_cb().set(FUNC(imds2ioc_device::kb_port_t1_r));
|
||||
|
||||
CENTRONICS(config, m_centronics, centronics_devices, "printer");
|
||||
m_centronics->ack_handler().set(FUNC(imds2ioc_device::pio_lpt_ack_w));
|
||||
m_centronics->busy_handler().set(FUNC(imds2ioc_device::pio_lpt_busy_w));
|
||||
m_centronics->perror_handler().set(FUNC(imds2ioc_device::pio_lpt_select_w));
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
ROM_START(imds2ioc)
|
||||
// ROM definition of IOC cpu (8080A)
|
||||
ROM_REGION(0x2000, "ioccpu", 0)
|
||||
ROM_DEFAULT_BIOS("v15")
|
||||
ROM_SYSTEM_BIOS(0, "v15", "Series II IOC Diagnostic v1.5") // "CORP INTEL corp.1981-83"
|
||||
ROMX_LOAD("ioc_a50_104692-001.bin", 0x0000, 0x0800, CRC(d9f926a1) SHA1(bd9d0f7458acc2806120a6dbaab9c48be315b060), ROM_BIOS(0))
|
||||
ROMX_LOAD("ioc_a51_104692-002.bin", 0x0800, 0x0800, CRC(6aa2f86c) SHA1(d3a5314d86e3366545b4c97b29e323dfab383d5f), ROM_BIOS(0))
|
||||
ROMX_LOAD("ioc_a52_104692-003.bin", 0x1000, 0x0800, CRC(b88a38d5) SHA1(934716a1daec852f4d1f846510f42408df0c9584), ROM_BIOS(0))
|
||||
ROMX_LOAD("ioc_a53_104692-004.bin", 0x1800, 0x0800, CRC(c8df4bb9) SHA1(2dfb921e94ae7033a7182457b2f00657674d1b77), ROM_BIOS(0))
|
||||
ROM_SYSTEM_BIOS(1, "v14", "Series II IOC Diagnostic v1.4") // "(C) Intel Corp. 1981,1982"
|
||||
ROMX_LOAD("a62_2716.bin", 0x0000, 0x0800, CRC(86a55b2f) SHA1(21033f7abb2c3e08028613e0c35ffecb703ff4f1), ROM_BIOS(1))
|
||||
ROMX_LOAD("a51_2716.bin", 0x0800, 0x0800, CRC(ee55c448) SHA1(16c2f7e3b5baeb398adcc59603943910813e6a9b), ROM_BIOS(1))
|
||||
ROMX_LOAD("a52_2716.bin", 0x1000, 0x0800, CRC(8db1b33e) SHA1(6fc5e438009636dd6d7185071b152b0491d3baeb), ROM_BIOS(1))
|
||||
ROMX_LOAD("a53_2716.bin", 0x1800, 0x0800, CRC(01690f4f) SHA1(eadef30a3797f41e08d28e7691f8de44c0f3b8ea), ROM_BIOS(1))
|
||||
ROM_SYSTEM_BIOS(2, "v13", "Series II IOC Diagnostic v1.3") // no copyright string; accompanying installation instructions © 1980 Intel Corporation
|
||||
ROMX_LOAD("104593-001.a50", 0x0000, 0x0800, CRC(801de7ad) SHA1(291b7db8a163b970e9082bdb637d7dee436c7a62), ROM_BIOS(2))
|
||||
ROMX_LOAD("104593-002.a51", 0x0800, 0x0800, CRC(6c8e21b6) SHA1(b3e63b2846a79866eb74ab354001996424ec22a0), ROM_BIOS(2))
|
||||
ROMX_LOAD("104593-003.a52", 0x1000, 0x0800, CRC(134c8115) SHA1(cd8c566344ee7a9cda78eea5fd2efdaca5a2e540), ROM_BIOS(2))
|
||||
ROMX_LOAD("104593-004.a53", 0x1800, 0x0800, CRC(04407e2a) SHA1(ecd65e4337d2bb7f5f6fdaae95696c9207ba57ee), ROM_BIOS(2))
|
||||
|
||||
// ROM definition of PIO controller (8041A)
|
||||
// For the time being a specially developed PIO firmware is used until a dump of the original PIO is
|
||||
// available.
|
||||
ROM_REGION(0x400, "iocpio", 0)
|
||||
ROM_LOAD("pio_a72.bin", 0, 0x400, BAD_DUMP CRC(8c8e740b) SHA1(9b9333a9dc9585aa8f630721d13e551a5c87defc))
|
||||
|
||||
// ROM definition of keyboard controller (8741)
|
||||
ROM_REGION(0x400, "kbcpu", 0)
|
||||
ROM_LOAD("kbd_a3_104675-001.bin", 0, 0x400, CRC(ba7c4303) SHA1(19899af732d0ae1247bfc79979b1ee5f339ee5cf))
|
||||
|
||||
// ROM definition of character generator (2708, A19 on IOC)
|
||||
ROM_REGION(0x400, "gfx1", 0)
|
||||
ROM_LOAD("ioc_a19_101539-001.bin", 0x0000, 0x0400, CRC(47487d0f) SHA1(0ed98f9f06622949ee3cc2ffc572fb9702db0f81))
|
||||
ROM_END
|
||||
|
||||
ioport_constructor imds2ioc_device::device_input_ports() const
|
||||
{
|
||||
return INPUT_PORTS_NAME(imds2ioc);
|
||||
}
|
||||
|
||||
const tiny_rom_entry *imds2ioc_device::device_rom_region() const
|
||||
{
|
||||
return ROM_NAME(imds2ioc);
|
||||
}
|
131
src/mame/machine/imds2ioc.h
Normal file
131
src/mame/machine/imds2ioc.h
Normal file
@ -0,0 +1,131 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:F. Ulivi
|
||||
|
||||
#ifndef MAME_MACHINE_IMDS2IOC_H
|
||||
#define MAME_MACHINE_IMDS2IOC_H
|
||||
|
||||
#include "cpu/i8085/i8085.h"
|
||||
#include "cpu/mcs48/mcs48.h"
|
||||
#include "machine/i8257.h"
|
||||
#include "video/i8275.h"
|
||||
#include "sound/beep.h"
|
||||
#include "machine/pit8253.h"
|
||||
#include "machine/i8271.h"
|
||||
#include "imagedev/flopdrv.h"
|
||||
#include "bus/centronics/ctronics.h"
|
||||
#include "emupal.h"
|
||||
|
||||
class imds2ioc_device : public device_t
|
||||
{
|
||||
public:
|
||||
imds2ioc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
|
||||
|
||||
auto master_intr_cb() { return m_master_intr_cb.bind(); }
|
||||
auto parallel_int_cb() { return m_parallel_int_cb.bind(); }
|
||||
|
||||
DECLARE_READ8_MEMBER(dbb_master_r);
|
||||
DECLARE_WRITE8_MEMBER(dbb_master_w);
|
||||
|
||||
DECLARE_READ8_MEMBER(pio_master_r);
|
||||
DECLARE_WRITE8_MEMBER(pio_master_w);
|
||||
|
||||
protected:
|
||||
virtual ioport_constructor device_input_ports() const override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
virtual const tiny_rom_entry *device_rom_region() const override;
|
||||
|
||||
virtual void device_resolve_objects() override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
private:
|
||||
DECLARE_WRITE8_MEMBER(miscout_w);
|
||||
DECLARE_READ8_MEMBER(miscin_r);
|
||||
DECLARE_WRITE_LINE_MEMBER(beep_timer_w);
|
||||
DECLARE_WRITE8_MEMBER(start_timer_w);
|
||||
|
||||
DECLARE_READ8_MEMBER(kb_read);
|
||||
DECLARE_READ8_MEMBER(kb_port_p2_r);
|
||||
DECLARE_WRITE8_MEMBER(kb_port_p1_w);
|
||||
DECLARE_READ_LINE_MEMBER(kb_port_t0_r);
|
||||
DECLARE_READ_LINE_MEMBER(kb_port_t1_r);
|
||||
|
||||
DECLARE_WRITE8_MEMBER(ioc_dbbout_w);
|
||||
DECLARE_WRITE8_MEMBER(ioc_f0_w);
|
||||
DECLARE_WRITE8_MEMBER(ioc_set_f1_w);
|
||||
DECLARE_WRITE8_MEMBER(ioc_reset_f1_w);
|
||||
DECLARE_READ8_MEMBER(ioc_status_r);
|
||||
DECLARE_READ8_MEMBER(ioc_dbbin_r);
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(hrq_w);
|
||||
DECLARE_READ8_MEMBER(ioc_mem_r);
|
||||
DECLARE_WRITE8_MEMBER(ioc_mem_w);
|
||||
|
||||
DECLARE_READ8_MEMBER(pio_port_p1_r);
|
||||
DECLARE_WRITE8_MEMBER(pio_port_p1_w);
|
||||
DECLARE_READ8_MEMBER(pio_port_p2_r);
|
||||
DECLARE_WRITE8_MEMBER(pio_port_p2_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(pio_lpt_ack_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(pio_lpt_busy_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(pio_lpt_select_w);
|
||||
|
||||
I8275_DRAW_CHARACTER_MEMBER(crtc_display_pixels);
|
||||
|
||||
void io_map(address_map &map);
|
||||
void mem_map(address_map &map);
|
||||
|
||||
void update_beeper();
|
||||
void update_printer();
|
||||
|
||||
required_device<i8080a_cpu_device> m_ioccpu;
|
||||
required_device<i8257_device> m_iocdma;
|
||||
required_device<i8275_device> m_ioccrtc;
|
||||
required_device<beep_device> m_iocbeep;
|
||||
required_device<pit8253_device> m_ioctimer;
|
||||
required_device<i8271_device> m_iocfdc;
|
||||
required_device<floppy_connector> m_flop0;
|
||||
required_device<i8041_device> m_iocpio;
|
||||
required_device<i8741_device> m_kbcpu;
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<centronics_device> m_centronics;
|
||||
required_ioport_array<8> m_io_key;
|
||||
required_ioport m_ioc_options;
|
||||
|
||||
devcb_write_line m_master_intr_cb;
|
||||
devcb_write_line m_parallel_int_cb;
|
||||
|
||||
// Character generator
|
||||
required_region_ptr<uint8_t> m_chargen;
|
||||
|
||||
// MISCOUT state
|
||||
uint8_t m_miscout;
|
||||
|
||||
// Beeper timer line
|
||||
int m_beeper_timer;
|
||||
|
||||
// Keyboard state
|
||||
uint8_t m_kb_p1;
|
||||
|
||||
// IPC to IOC buffer
|
||||
uint8_t m_ioc_ibf;
|
||||
|
||||
// IOC to IPC buffer
|
||||
uint8_t m_ioc_obf;
|
||||
|
||||
// IPC/IOC status
|
||||
uint8_t m_ipc_ioc_status;
|
||||
|
||||
// PIO port 1
|
||||
uint8_t m_pio_port1;
|
||||
|
||||
// PIO port 2
|
||||
uint8_t m_pio_port2;
|
||||
|
||||
// PIO device status byte
|
||||
uint8_t m_device_status_byte;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(IMDS2IOC, imds2ioc_device)
|
||||
|
||||
#endif // MAME_MACHINE_IMDS2IOC_H
|
@ -15504,9 +15504,6 @@ stellecu // (c) 1998
|
||||
farmer // TVG17 (c) 1985 Sun Electronics
|
||||
ikki // TVG17 (c) 1985 Sun Electronics (Japan)
|
||||
|
||||
@source:imds.cpp
|
||||
imds // intel
|
||||
|
||||
@source:imds2.cpp
|
||||
imds2 // Intellec MDS series-II
|
||||
|
||||
|
@ -308,7 +308,6 @@ icatel.cpp
|
||||
icebox.cpp
|
||||
ie15.cpp
|
||||
if800.cpp
|
||||
imds.cpp
|
||||
imds2.cpp
|
||||
imsai.cpp
|
||||
indiana.cpp
|
||||
|
Loading…
Reference in New Issue
Block a user