// license:BSD-3-Clause
// copyright-holders:Olivier Galibert

// Emulation of the MKS3 keyboard scanning PCB used in the psr340 and
// psr540 among others.

#include "emu.h"
#include "mks3.h"

DEFINE_DEVICE_TYPE(MKS3, mks3_device, "mks3", "Yamaha MKS3 piano keyboard scanner")

#define PORT_VELOCITY_START /**/
#define PORT_VELOCITY_END /**/

static INPUT_PORTS_START(piano)
	PORT_START("B1")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_C1
	PORT_BIT(0x3e, IP_ACTIVE_LOW, IPT_UNUSED)

	PORT_START("B2")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_CS1
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_D1
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_DS1
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_E1
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_F1
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_FS1

	PORT_START("B3")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_C2
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_B1
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_AS1
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_A1
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_GS1
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_G1

	PORT_START("B4")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_CS2
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_D2
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_DS2
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_E2
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_F2
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_FS2

	PORT_START("B5")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_C3
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_B2
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_AS2
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_A2
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_GS2
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_G2

	PORT_START("B6")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_CS3
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_D3
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_DS3
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_E3
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_F3
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_FS3

	PORT_START("B7")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_C4
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_B3
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_AS3
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_A3
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_GS3
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_G3

	PORT_START("B8")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_CS4
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_D4
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_DS4
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_E4
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_F4
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_FS4

	PORT_START("B9")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_C5
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_B4
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_AS4
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_A4
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_GS4
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_G4

	PORT_START("B10")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_CS5
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_D5
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_DS5
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_E5
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_F5
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_FS5

	PORT_START("B11")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_C6
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_B5
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_AS5
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_A5
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_GS5
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_START PORT_GM_G5

	PORT_START("A1")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_C1
	PORT_BIT(0x3e, IP_ACTIVE_LOW, IPT_UNUSED)

	PORT_START("A2")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_CS1
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_D1
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_DS1
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_E1
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_F1
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_FS1

	PORT_START("A3")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_C2
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_B1
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_AS1
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_A1
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_GS1
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_G1

	PORT_START("A4")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_CS2
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_D2
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_DS2
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_E2
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_F2
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_FS2

	PORT_START("A5")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_C3
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_B2
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_AS2
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_A2
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_GS2
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_G2

	PORT_START("A6")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_CS3
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_D3
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_DS3
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_E3
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_F3
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_FS3

	PORT_START("A7")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_C4
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_B3
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_AS3
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_A3
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_GS3
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_G3

	PORT_START("A8")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_CS4
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_D4
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_DS4
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_E4
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_F4
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_FS4

	PORT_START("A9")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_C5
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_B4
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_AS4
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_A4
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_GS4
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_G4

	PORT_START("A10")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_CS5
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_D5
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_DS5
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_E5
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_F5
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_FS5

	PORT_START("A11")
	PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_C6
	PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_B5
	PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_AS5
	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_A5
	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_GS5
	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_VELOCITY_END PORT_GM_G5
INPUT_PORTS_END

ROM_START( mks3 )
	ROM_REGION( 0x1000, "cpu", 0 )
	ROM_LOAD( "xr951a0.ic1", 0x0000, 0x1000, CRC(01c80e83) SHA1(fee3628ac49556a60a597ee6ea71fb48646c6229) )
ROM_END

mks3_device::mks3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
	device_t(mconfig, MKS3, tag, owner, clock),
	m_cpu(*this, "cpu"),
	m_port_a(*this, "A%d", 1U),
	m_port_b(*this, "B%d", 1U),
	m_write_da(*this),
	m_write_clk(*this)
{
}

ioport_constructor mks3_device::device_input_ports() const
{
	return INPUT_PORTS_NAME(piano);
}

tiny_rom_entry const *mks3_device::device_rom_region() const
{
	return ROM_NAME(mks3);
}

void mks3_device::device_start()
{
	save_item(NAME(m_ic));
	save_item(NAME(m_req));
	save_item(NAME(m_port_c));
	save_item(NAME(m_port_d));

	m_ic = 1;
	m_req = 1;
	m_port_c = 0xff;
	m_port_d = 0xff;
}

void mks3_device::pc_w(u8 data)
{
	m_port_c = data;
}

void mks3_device::pd_w(u8 data)
{
	m_port_d = data;
}

u8 mks3_device::pa_r()
{
	u8 res = 0x3f;
	for(int i=0; i != 3; i++)
		if(!BIT(m_port_d, i))
			res &= m_port_a[i]->read();
	for(int i=0; i != 8; i++)
		if(!BIT(m_port_c, i))
			res &= m_port_a[i+3]->read();
	return 0x80 | res;
}

u8 mks3_device::pb_r()
{
	u8 res = 0x3f;
	for(int i=0; i != 3; i++)
		if(!BIT(m_port_d, i))
			res &= m_port_b[i]->read();
	for(int i=0; i != 8; i++)
		if(!BIT(m_port_c, i))
			res &= m_port_b[i+3]->read();
	return res;
}

void mks3_device::device_reset()
{
}

void mks3_device::da_w(int state)
{
	m_write_da(state);
}

void mks3_device::clk_w(int state)
{
	m_write_clk(state);
}

void mks3_device::device_add_mconfig(machine_config &config)
{
	HD6305V0(config, m_cpu, 8_MHz_XTAL);
	m_cpu->write_sci_tx().set(FUNC(mks3_device::da_w));
	m_cpu->write_sci_clk().set(FUNC(mks3_device::clk_w));
	m_cpu->read_porta().set(FUNC(mks3_device::pa_r));
	m_cpu->read_portb().set(FUNC(mks3_device::pb_r));
	m_cpu->write_portc().set(FUNC(mks3_device::pc_w));
	m_cpu->write_portd().set(FUNC(mks3_device::pd_w));
}

void mks3_device::ic_w(int state)
{
	if(state == m_ic)
		return;

	m_ic = state;
	logerror("ic %d\n", m_ic);
	if(!m_ic)
		m_cpu->reset();
}

void mks3_device::req_w(int state)
{
	if(state == m_req)
		return;

	m_req = state;
	m_cpu->set_input_line(HD6305_INT_IRQ1, m_req);
	logerror("req %d\n", m_req);
}
