summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/machine/cmi_mkbd.cpp
blob: 2128f88c5b18548df12e0b76d7885ae37571fed2 (plain) (tree)

























































                                                                                                                                
                                   

















































                                                                                                                                   
                                                      


















                                                                            
                                                      
 
















                                                               






                                                          
                           





                                    
                           





                                    
                           

                            

 
                                                                                        











                                                               
                                             














                                                  
                                                        
                 
                                                  




































                                                                 











                                                                    








                                                            
                                                                    
                                 
                                                                   






















































                                                                    

































































































































                                                                                                         


                                                                                                   


























































                                                                                                                
// license:BSD-3-Clause
// copyright-holders:Phil Bennett
/***************************************************************************

    Fairlight CMI Music Keyboard
    - CMI-10 Music Keyboard Controller
    - CMI-11 Keyboard Switch Module
    - CMI-12 Keyboard Display and Keypad Module
    - CMI-14 Slave Keyboard Interface

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

        The Master Keyboard
        -------------------

        The master keyboard has the following features:
            - A serial connector for communicating with the CMI mainframe
            - A connector for a slave keyboard
            - A connector for the alphanumeric keyboard
            - Connectors for pedal controls
            - Three slider-type analog controls
            - Two switch controls (one momentary, one toggle on/off)
            - Two lamp indicators for the switches with software-defined
              control
            - A 12-character LED alphanumeric display
            - A 16-switch keypad

        All communications with all peripherals and controls on the master
        keyboard is handled via the master keyboard's controller, and as
        such there is one single serial link to the "CMI mainframe" box
        itself.

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

#include "emu.h"
#include "cmi_mkbd.h"

#include "cpu/m6800/m6800.h"
#include "machine/clock.h"

DEFINE_DEVICE_TYPE(CMI_MUSIC_KEYBOARD, cmi_music_keyboard_device, "cmi_mkbd", "Fairlight CMI Music Keyboard")

cmi_music_keyboard_device::cmi_music_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
	: device_t(mconfig, CMI_MUSIC_KEYBOARD, tag, owner, clock)
	, m_cmi_txd(*this)
	, m_cmi_rts(*this)
	, m_kbd_txd(*this)
	, m_kbd_rts(*this)
	, m_cpu(*this, "kbdcpu")
	, m_acia_kbd(*this, "acia_kbd")
	, m_acia_cmi(*this, "acia_cmi")
	, m_cmi10_pia_u20(*this, "cmi10_pia_u20")
	, m_cmi10_pia_u21(*this, "cmi10_pia_u21")
	, m_dp1(*this, "dp1")
	, m_dp2(*this, "dp2")
	, m_dp3(*this, "dp3")
	, m_keypad_a_port(*this, "KEYPAD_A")
	, m_keypad_b_port(*this, "KEYPAD_B")
	, m_analog(*this, "ANALOG")
	, m_key_mux_ports{ { *this, "KEY_%u_0", 0 }, { *this, "KEY_%u_1", 0 }, { *this, "KEY_%u_2", 0 }, { *this, "KEY_%u_3", 0 } }
	, m_digit(*this, "digit%u", 0U)
{
}

void cmi_music_keyboard_device::device_resolve_objects()
{
	m_cmi_txd.resolve_safe();
	m_cmi_rts.resolve_safe();
	m_kbd_txd.resolve_safe();
	m_kbd_rts.resolve_safe();
	m_digit.resolve();
}

void cmi_music_keyboard_device::device_start()
{
	m_cmi10_scnd_timer = timer_alloc(TIMER_CMI10_SCND);

	m_cmi10_scnd_timer->adjust(attotime::from_hz(4000000 / 4 / 2048 / 2), 0, attotime::from_hz(4000000 / 4 / 2048 / 2));
	m_scnd = 0;
}

void cmi_music_keyboard_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
	switch (id)
	{
	case TIMER_CMI10_SCND:
		m_cmi10_pia_u20->ca1_w(m_scnd);
		m_scnd ^= 1;
		m_cmi10_pia_u21->ca1_w(m_scnd);
		break;
	}
}

/*
    PA0-7 = BKA0-7 (display)

    PB0 = DA1
    PB1 = DA0
    PB2 = CS2
    PB3 = CU2
    PB4 = CS1
    PB5 = CU1
    PB6 = CS0
    PB7 = CU0

    CB1 = /KPAD
    CB2 = /DWS
*/

void cmi_music_keyboard_device::cmi10_u20_a_w(u8 data)
{
	// low 7 bits connected to alphanumeric display data lines
	m_dp1->data_w(data & 0x7f);
	m_dp2->data_w(data & 0x7f);
	m_dp3->data_w(data & 0x7f);

	/*
	int bk = data;
	int bit = 0;

	if (BIT(bk, 3))
	    bit = BIT(input_port_read(device->machine, "KEYPAD_A"), bk & 7);
	else if (!BIT(bk, 4))
	    bit = BIT(input_port_read(device->machine, "KEYPAD_B"), bk & 7);

	pia6821_cb1_w(m_cmi10_pia_u20, 0, !bit);
	*/
}

void cmi_music_keyboard_device::cmi10_u20_b_w(u8 data)
{
}

READ_LINE_MEMBER( cmi_music_keyboard_device::cmi10_u20_cb1_r )
{
	int bk = m_cmi10_pia_u20->a_output();
	int bit = 0;

	if (BIT(bk, 3))
		bit = BIT(m_keypad_a_port->read(), bk & 7);
	else if (!BIT(bk, 4))
		bit = BIT(m_keypad_b_port->read(), bk & 7);

	return !bit;
}

WRITE_LINE_MEMBER( cmi_music_keyboard_device::cmi10_u20_cb2_w )
{
	uint8_t data = m_cmi10_pia_u20->a_output() & 0x7f;
	uint8_t b_port = m_cmi10_pia_u20->b_output();
	int addr = (BIT(b_port, 0) << 1) | BIT(b_port, 1);

	/* DP1 */
	m_dp1->ce_w(BIT(b_port, 6));
	m_dp1->cu_w(BIT(b_port, 7));
	m_dp1->wr_w(state);
	m_dp1->addr_w(addr);
	m_dp1->data_w(data);

	/* DP2 */
	m_dp2->ce_w(BIT(b_port, 4));
	m_dp2->cu_w(BIT(b_port, 5));
	m_dp2->wr_w(state);
	m_dp2->addr_w(addr);
	m_dp2->data_w(data);

	/* DP3 */
	m_dp3->ce_w(BIT(b_port, 2));
	m_dp3->cu_w(BIT(b_port, 3));
	m_dp3->wr_w(state);
	m_dp3->addr_w(addr);
	m_dp3->data_w(data);
}

template <unsigned N> void cmi_music_keyboard_device::update_dp(offs_t offset, u16 data)
{
	m_digit[(N << 2) | ((offset ^ 3) & 3)] = data;
}

/* Begin Conversion */
WRITE_LINE_MEMBER( cmi_music_keyboard_device::cmi10_u21_cb2_w )
{
	// if 0
//  state = state;
}


u8 cmi_music_keyboard_device::cmi10_u21_a_r()
{
#if 0
//  int thld = m_cmi10_pia_u21->ca2_output();
	int sel = m_cmi10_pia_u20->a_output();
	int key = sel & 7;
	int mux = (sel >> 3) & 3;
	u8 data = 0x38; // slave keyboard not used


	for (int module = 0; module < 3; ++module)
	{
//      char keyname[16];
		u8 keyval;
		int state = 1;

		if (module == 1 && mux == 2 && key == 3)
		{
			keyval = m_analog->read();

			/* Unpressed */
			if (keyval <= 0)
				state = 1;
			/* In flight */

	#if 0
			else if (keyval <= 80)
			{
				if (thld == 1)
					state = 0;
				else
					state = 1;
			}
			/* Fully depressed */
	#endif
			else
				state = 0;

		}

		data |= state << module;
	}

	return data;
#else
	int sel = m_cmi10_pia_u20->a_output();
	int key = sel & 7;
	int mux = (sel >> 3) & 3;
	u8 data = 0xf8; // slave keyboard not used

	for (int module = 0; module < 3; ++module)
	{
		u8 keyval = m_key_mux_ports[mux][module]->read();
		data |= BIT(keyval, key) << module;
	}

	/* Now do KD7 */
	{
		int bit = 0;

		if (BIT(sel, 3))
			bit = BIT(m_keypad_a_port->read(), sel & 7);
		else if (!BIT(sel, 4))
			bit = BIT(m_keypad_b_port->read(), sel & 7);

		data |= (bit && BIT(sel, 7)) << 7;
	}

	return data;
#endif
}

WRITE_LINE_MEMBER( cmi_music_keyboard_device::kbd_acia_int )
{
	m_kbd_acia_irq = state;

	if (m_kbd_acia_irq)
		m_cpu->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE);
	else if (!m_cmi_acia_irq)
		m_cpu->set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE);
}

WRITE_LINE_MEMBER( cmi_music_keyboard_device::cmi_acia_int )
{
	m_cmi_acia_irq = state;

	if (m_cmi_acia_irq)
		m_cpu->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE);
	else if (!m_kbd_acia_irq)
		m_cpu->set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE);
}

WRITE_LINE_MEMBER( cmi_music_keyboard_device::cmi_txd_w )
{
	m_cmi_txd(state);
}

WRITE_LINE_MEMBER( cmi_music_keyboard_device::cmi_rts_w )
{
	m_cmi_rts(state);
}

WRITE_LINE_MEMBER( cmi_music_keyboard_device::cmi_rxd_w )
{
	m_acia_cmi->write_rxd(state);
}

WRITE_LINE_MEMBER( cmi_music_keyboard_device::cmi_cts_w )
{
	m_acia_cmi->write_cts(state);
}

WRITE_LINE_MEMBER( cmi_music_keyboard_device::kbd_txd_w )
{
	m_kbd_txd(state);
}

WRITE_LINE_MEMBER( cmi_music_keyboard_device::kbd_rts_w )
{
	m_kbd_rts(state);
}

WRITE_LINE_MEMBER( cmi_music_keyboard_device::kbd_rxd_w )
{
	m_acia_kbd->write_rxd(state);
}

WRITE_LINE_MEMBER( cmi_music_keyboard_device::kbd_cts_w )
{
	m_acia_kbd->write_cts(state);
}

void cmi_music_keyboard_device::muskeys_map(address_map &map)
{
	map.unmap_value_high();
	map(0x0080, 0x0083).rw(m_cmi10_pia_u21, FUNC(pia6821_device::read), FUNC(pia6821_device::write));
	map(0x0090, 0x0093).rw(m_cmi10_pia_u20, FUNC(pia6821_device::read), FUNC(pia6821_device::write));
	map(0x00a0, 0x00a1).rw(m_acia_kbd, FUNC(acia6850_device::read), FUNC(acia6850_device::write));
	map(0x00b0, 0x00b1).rw(m_acia_cmi, FUNC(acia6850_device::read), FUNC(acia6850_device::write));
	map(0x4000, 0x47ff).ram();
	map(0xb000, 0xb400).rom();
	map(0xf000, 0xffff).rom();
}

static INPUT_PORTS_START(cmi_music_keyboard)
	/* Keypad */
	PORT_START("KEYPAD_A")
	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1_PAD)
	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2_PAD)
	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3_PAD)
	PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4_PAD)
	PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5_PAD)
	PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6_PAD)
	PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7_PAD)
	PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8_PAD)

	PORT_START("KEYPAD_B")
	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9_PAD)
	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0_PAD)
	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1_PAD)
	PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2_PAD)
	PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3_PAD)
	PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4_PAD)
	PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5_PAD)
	PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6_PAD)

	/* Master musical keyboard */
	PORT_START("KEY_0_0")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F0")
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F0 #")
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G0")
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G0 #")
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A1")
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A1 #")
	PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B1")
	PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C1")

	PORT_START("KEY_0_1")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C1 #")
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D1")
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D1 #")
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E1")
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F1")
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F1 #")
	PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G1")
	PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G1 #")

	PORT_START("KEY_0_2")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A2")
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A2 #")
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B2")
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C2")
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C2 #")
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D2")
	PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D2 #")
	PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E2")

	PORT_START("KEY_0_3")
	PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNUSED)

	PORT_START("KEY_1_0")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F2")
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F2 #")
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G2")
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G2 #")
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A3")
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A3 #")
	PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B3")
	PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C3")

	PORT_START("KEY_1_1")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C3 #")
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D3")
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D3 #")
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E3")
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F3")
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G3")
	PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G3 #")
	PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A4")

	PORT_START("KEY_1_2")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A4 #")
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B4")
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B4 #")
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C4")
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C4 #")
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D4")
	PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D4 #")
	PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E4")

	PORT_START("KEY_1_3")
	PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNUSED)

	PORT_START("KEY_2_0")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F4")
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F4 #")
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G4")
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G4 #")
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A5")
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A5 #")
	PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B5")
	PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C5")

	PORT_START("KEY_2_1")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C5 #")
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D5")
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D5 #")
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E5")
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F5")
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F5 #")
	PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G5")
	PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G5 #")

	PORT_START("KEY_2_2")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A6")
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A6 #")
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B6")
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C6")
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C6 #")
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D6")
	PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D6 #")
	PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E6")

	PORT_START("KEY_2_3")
	PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F6")

	PORT_START("ANALOG")
	PORT_BIT(0xff, 0x00, IPT_PEDAL) PORT_MINMAX(0, 128) PORT_SENSITIVITY(100) PORT_KEYDELTA(50)
INPUT_PORTS_END

ioport_constructor cmi_music_keyboard_device::device_input_ports() const
{
	return INPUT_PORTS_NAME(cmi_music_keyboard);
}

void cmi_music_keyboard_device::device_add_mconfig(machine_config &config)
{
	M6802(config, m_cpu, 4_MHz_XTAL);
	m_cpu->set_addrmap(AS_PROGRAM, &cmi_music_keyboard_device::muskeys_map);

	PIA6821(config, m_cmi10_pia_u20);
	m_cmi10_pia_u20->readcb1_handler().set(FUNC(cmi_music_keyboard_device::cmi10_u20_cb1_r));
	m_cmi10_pia_u20->writepa_handler().set(FUNC(cmi_music_keyboard_device::cmi10_u20_a_w));
	m_cmi10_pia_u20->writepb_handler().set(FUNC(cmi_music_keyboard_device::cmi10_u20_b_w));
	m_cmi10_pia_u20->cb2_handler().set(FUNC(cmi_music_keyboard_device::cmi10_u20_cb2_w));

	PIA6821(config, m_cmi10_pia_u21);
	m_cmi10_pia_u21->readpa_handler().set(FUNC(cmi_music_keyboard_device::cmi10_u21_a_r));
	m_cmi10_pia_u21->cb2_handler().set(FUNC(cmi_music_keyboard_device::cmi10_u21_cb2_w));

	clock_device &acia_clock(CLOCK(config, "acia_clock", 1.8432_MHz_XTAL / 12));
	acia_clock.signal_handler().set(m_acia_kbd, FUNC(acia6850_device::write_rxc));
	acia_clock.signal_handler().append(m_acia_kbd, FUNC(acia6850_device::write_txc));
	acia_clock.signal_handler().append(m_acia_cmi, FUNC(acia6850_device::write_rxc));
	acia_clock.signal_handler().append(m_acia_cmi, FUNC(acia6850_device::write_txc));

	ACIA6850(config, m_acia_cmi);
	m_acia_cmi->txd_handler().set(FUNC(cmi_music_keyboard_device::cmi_txd_w));
	m_acia_cmi->rts_handler().set(FUNC(cmi_music_keyboard_device::cmi_rts_w));
	m_acia_cmi->irq_handler().set(FUNC(cmi_music_keyboard_device::cmi_acia_int));

	ACIA6850(config, m_acia_kbd);
	m_acia_kbd->txd_handler().set(FUNC(cmi_music_keyboard_device::kbd_txd_w));
	m_acia_kbd->rts_handler().set(FUNC(cmi_music_keyboard_device::kbd_rts_w));
	m_acia_kbd->irq_handler().set(FUNC(cmi_music_keyboard_device::kbd_acia_int));

	/* alpha-numeric display */
	DL1416T(config, m_dp1, u32(0));
	m_dp1->update().set(FUNC(cmi_music_keyboard_device::update_dp<0>));
	DL1416T(config, m_dp2, u32(0));
	m_dp2->update().set(FUNC(cmi_music_keyboard_device::update_dp<1>));
	DL1416T(config, m_dp3, u32(0));
	m_dp3->update().set(FUNC(cmi_music_keyboard_device::update_dp<2>));
}

ROM_START( cmi_mkbd )
	// Both of these dumps have been trimmed to size from within a roughly 2x-bigger file.
	// The actual size is known based on the format apparently used by the dumping device.
	ROM_REGION( 0x10000, "kbdcpu", 0 )
	ROM_LOAD( "velkeysd.bin", 0xb000, 0x0400, CRC(9b636781) SHA1(be29a72a1d6d313dafe0b63951b5e3e18ddb9a21) )
	ROM_LOAD( "kbdioa.bin",   0xfc00, 0x0400, CRC(a5cbe218) SHA1(bc6784aaa5697c28eab126e20500139b8d0c1f50) )
ROM_END

const tiny_rom_entry *cmi_music_keyboard_device::device_rom_region() const
{
	return ROM_NAME(cmi_mkbd);
}