summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/bus/isa/pcmidi.cpp
blob: 45cc41ff4f46dc32f2b21dbc1bde4cef59c79930 (plain) (tree)





























                                                                            

                                                                             





































































                                                                                                                  

                                                                                    
















































































                                                                                            
                                           











































































                                                                                                                                 
// license:BSD-3-Clause
// copyright-holders:AJR
/***************************************************************************

    PC MIDI Card
    Copyright (C) 1989 Music Quest, Inc.
    FCC ID: IH9MQ9

    This is one of several Z8681-based MIDI cards by Music Quest. Its
    interface is more or less compatible with the Roland MPU401.

****************************************************************************

Music Quest PC MIDI CARD IH9MQ9 component list:

C1  : 2.2uf 50v electrolytic capacitor
C2  : 100nf tantalum capacitor
C3  : 100nf tantalum capacitor
C4  : 100nf tantalum capacitor
C5  : 100nf tantalum capacitor
C6  : 100nf tantalum capacitor
C7  : 100nf tantalum capacitor
C9  : 100nf tantalum capacitor

D1  : diode (IN4148 ?)
Y1  : 12,000 MHz crystal 2 pin

R1  : 15K ohm resistor +-5%
R2  : 390 ohm resistor +-5%

RP1 : 10K ohm Commoned (?) resistor network 2% SIP package (code used A103GA)
RP2 : 220 ohm Commoned (?) resistor network 2% SIP package (code used B221GA)



U1  : 74LS374N
U2  : Zilog Z8 ROMLESS MCU Z0868112PSC
U3  : 74LS139N
U4  : 74LS74AN
U5  : PAL-16L8-25N - read protected , unknown code
U6  : OTP firmware rom chip compatible with 27C512 eproms/eeproms , 64kbyte
U7  : HYUNDAI HY611ALP-10 or compatible 2K x8bits CMOS SRAM IC
U8  : 74LS125AN
U9  : 74LS374N
U10 : 74LS374N
U11 : SHARP PC900V or compatible photocoupler

***************************************************************************/

#include "emu.h"
#include "pcmidi.h"

//**************************************************************************
//  GLOBAL VARIABLES
//**************************************************************************

DEFINE_DEVICE_TYPE(ISA8_PCMIDI, isa8_pcmidi_device, "isa_pcmidi", "Music Quest PC MIDI Card (IHQMQ9)")


//**************************************************************************
//  DEVICE SETUP
//**************************************************************************

//-------------------------------------------------
//  isa8_pcmidi_device - constructor
//-------------------------------------------------

isa8_pcmidi_device::isa8_pcmidi_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
	: device_t(mconfig, ISA8_PCMIDI, tag, owner, clock)
	, device_isa8_card_interface(mconfig, *this)
	, m_mpu(*this, "mpu")
	, m_cmdlatch(*this, "cmdlatch")
	, m_statlatch(*this, "statlatch")
	, m_midiout(*this, "midiout")
	, m_config(*this, "CONFIG")
	, m_mpu_p3(0)
	, m_host_irq(false)
{
}


//-------------------------------------------------
//  device_start - device-specific startup
//-------------------------------------------------

void isa8_pcmidi_device::device_start()
{
	set_isa_device();

	save_item(NAME(m_mpu_p3));
	save_item(NAME(m_host_irq));
}


//-------------------------------------------------
//  device_reset - device-specific reset
//-------------------------------------------------

void isa8_pcmidi_device::device_reset()
{
	offs_t ioaddr = BIT(m_config->read(), 0) ? 0x300 : 0x330;
	m_isa->install_device(ioaddr, ioaddr + 1,
			read8sm_delegate(*this, FUNC(isa8_pcmidi_device::host_r)),
			write8sm_delegate(*this, FUNC(isa8_pcmidi_device::host_w)));

	set_host_irq(false);
}


//**************************************************************************
//  LATCHES AND IRQS
//**************************************************************************

//-------------------------------------------------
//  set_host_irq - update the host IRQ level
//-------------------------------------------------

void isa8_pcmidi_device::set_host_irq(bool state)
{
	if (m_host_irq != state)
	{
		m_host_irq = state;

		ioport_value config = m_config->read();
		if (!BIT(config, 1))
			m_isa->irq3_w(state);
		if (!BIT(config, 2))
			m_isa->irq5_w(state);
		if (!BIT(config, 3))
			m_isa->irq7_w(state);
		if (!BIT(config, 4))
			m_isa->irq2_w(state);
	}
}


//-------------------------------------------------
//  host_r - read from data or status port
//-------------------------------------------------

u8 isa8_pcmidi_device::host_r(offs_t offset)
{
	if (!machine().side_effects_disabled())
	{
		set_host_irq(false);
		m_mpu->set_input_line(INPUT_LINE_IRQ1, ASSERT_LINE);
	}
	return m_statlatch->read();
}


//-------------------------------------------------
//  host_w - write to data or command port
//-------------------------------------------------

void isa8_pcmidi_device::host_w(offs_t offset, u8 data)
{
	m_cmdlatch->write(data);

	// IRQs are latched and acknowledged internally
	m_mpu->pulse_input_line(offset ? INPUT_LINE_IRQ0 : INPUT_LINE_IRQ2, attotime::zero);
}


//-------------------------------------------------
//  status_w - mailbox write from local processor
//-------------------------------------------------

void isa8_pcmidi_device::status_w(u8 data)
{
	m_statlatch->write(data);
	if (!BIT(m_mpu_p3, 5))
	{
		set_host_irq(true);
		m_mpu->set_input_line(INPUT_LINE_IRQ1, CLEAR_LINE);
	}
}


//-------------------------------------------------
//  mpu_p3_w - write to output port
//-------------------------------------------------

void isa8_pcmidi_device::mpu_p3_w(u8 data)
{
	m_midiout->write_txd(BIT(data, 7));

	// P36 = error LED output?

	if (BIT(m_mpu_p3, 5) && !BIT(data, 5))
		set_host_irq(false);

	m_mpu_p3 = data;
}


//-------------------------------------------------
//  mpu_map - Z8681 address map
//-------------------------------------------------

void isa8_pcmidi_device::mpu_map(address_map &map)
{
	map(0x0000, 0x1fff).rom().region("microcode", 0);
	map(0x6000, 0x7fff).rom().mirror(0x8000).region("microcode", 0);
	map(0xa000, 0xa7ff).ram();
	map(0xc000, 0xc000).mirror(0xff).r(m_cmdlatch, FUNC(generic_latch_8_device::read)).w(FUNC(isa8_pcmidi_device::status_w));
}


//**************************************************************************
//  DEVICE CONFIGURATION
//**************************************************************************

static INPUT_PORTS_START(isa_pcmidi)
	PORT_START("CONFIG") // dual inline block of jumpers with idiosyncratic numbering
	PORT_DIPNAME(0x01, 0x00, "I/O Address (P)") PORT_DIPLOCATION("J1:1")
	PORT_DIPSETTING(0x01, "300")
	PORT_DIPSETTING(0x00, "330")
	PORT_DIPNAME(0x1e, 0x0e, "Interrupt") PORT_DIPLOCATION("J1:2,3,4,5")
	PORT_DIPSETTING(0x0e, "IRQ2")
	PORT_DIPSETTING(0x1c, "IRQ3")
	PORT_DIPSETTING(0x1a, "IRQ5")
	PORT_DIPSETTING(0x16, "IRQ7")
INPUT_PORTS_END

ioport_constructor isa8_pcmidi_device::device_input_ports() const
{
	return INPUT_PORTS_NAME(isa_pcmidi);
}


//-------------------------------------------------
//  device_add_mconfig - add device configuration
//-------------------------------------------------

void isa8_pcmidi_device::device_add_mconfig(machine_config &config)
{
	Z8681(config, m_mpu, 12_MHz_XTAL);
	m_mpu->set_addrmap(AS_PROGRAM, &isa8_pcmidi_device::mpu_map);
	m_mpu->p3_out_cb().set(FUNC(isa8_pcmidi_device::mpu_p3_w));

	GENERIC_LATCH_8(config, m_cmdlatch);
	GENERIC_LATCH_8(config, m_statlatch);

	MIDI_PORT(config, m_midiout, midiout_slot, "midiout");
	MIDI_PORT(config, "midiin", midiin_slot, "midiin").rxd_handler().set_inputline(m_mpu, INPUT_LINE_IRQ3).invert();
}


//**************************************************************************
//  ROM DEFINITION
//**************************************************************************

ROM_START(isa_pcmidi)
	ROM_REGION(0x10000, "microcode", 0)
	ROM_LOAD("ih9mq9_firmware_v010.bin", 0x00000, 0x10000, CRC(d4cab098) SHA1(9446c4939de557f839a74ca6fe7f41df46752e25))
ROM_END

const tiny_rom_entry *isa8_pcmidi_device::device_rom_region() const
{
	return ROM_NAME(isa_pcmidi);
}