// license:BSD-3-Clause
// copyright-holders:Curt Coder
/**********************************************************************
Tandy 2000 keyboard emulation
*********************************************************************/
#include "tandy2kb.h"
//**************************************************************************
// MACROS / CONSTANTS
//**************************************************************************
#define I8048_TAG "m1"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
const device_type TANDY2K_KEYBOARD = &device_creator<tandy2k_keyboard_device>;
//-------------------------------------------------
// ROM( tandy2k_keyboard )
//-------------------------------------------------
ROM_START( tandy2k_keyboard )
ROM_REGION( 0x400, I8048_TAG, 0 )
ROM_LOAD( "keyboard.m1", 0x0000, 0x0400, NO_DUMP )
ROM_END
//-------------------------------------------------
// rom_region - device-specific ROM region
//-------------------------------------------------
const rom_entry *tandy2k_keyboard_device::device_rom_region() const
{
return ROM_NAME( tandy2k_keyboard );
}
//-------------------------------------------------
// ADDRESS_MAP( kb_io )
//-------------------------------------------------
static ADDRESS_MAP_START( tandy2k_keyboard_io, AS_IO, 8, tandy2k_keyboard_device )
AM_RANGE(MCS48_PORT_P1, MCS48_PORT_P1) AM_WRITE(kb_p1_w)
AM_RANGE(MCS48_PORT_P2, MCS48_PORT_P2) AM_WRITE(kb_p2_w)
AM_RANGE(MCS48_PORT_BUS, MCS48_PORT_BUS) AM_READ(kb_p1_r)
ADDRESS_MAP_END
//-------------------------------------------------
// MACHINE_DRIVER( tandy2k_keyboard )
//-------------------------------------------------
static MACHINE_CONFIG_FRAGMENT( tandy2k_keyboard )
MCFG_CPU_ADD(I8048_TAG, I8048, 1000000) // ?
MCFG_CPU_IO_MAP(tandy2k_keyboard_io)
MCFG_DEVICE_DISABLE() // TODO
MACHINE_CONFIG_END
//-------------------------------------------------
// machine_config_additions - device-specific
// machine configurations
//-------------------------------------------------
machine_config_constructor tandy2k_keyboard_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( tandy2k_keyboard );
}
//-------------------------------------------------
// INPUT_PORTS( tandy2k_keyboard )
//-------------------------------------------------
INPUT_PORTS_START( tandy2k_keyboard )
PORT_START("Y0")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_START("Y1")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_START("Y2")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_START("Y3")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_START("Y4")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_START("Y5")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_START("Y6")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_START("Y7")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_START("Y8")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_START("Y9")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_START("Y10")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_START("Y11")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD )
INPUT_PORTS_END
//-------------------------------------------------
// input_ports - device-specific input ports
//-------------------------------------------------
ioport_constructor tandy2k_keyboard_device::device_input_ports() const
{
return INPUT_PORTS_NAME( tandy2k_keyboard );
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// tandy2k_keyboard_device - constructor
//-------------------------------------------------
tandy2k_keyboard_device::tandy2k_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, TANDY2K_KEYBOARD, "Tandy 2000 Keyboard", tag, owner, clock, "tandy2kb", __FILE__),
m_maincpu(*this, I8048_TAG),
m_y0(*this, "Y0"),
m_y1(*this, "Y1"),
m_y2(*this, "Y2"),
m_y3(*this, "Y3"),
m_y4(*this, "Y4"),
m_y5(*this, "Y5"),
m_y6(*this, "Y6"),
m_y7(*this, "Y7"),
m_y8(*this, "Y8"),
m_y9(*this, "Y9"),
m_y10(*this, "Y10"),
m_y11(*this, "Y11"),
m_write_clock(*this),
m_write_data(*this),
m_keylatch(0xffff),
m_clock(0),
m_data(0)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void tandy2k_keyboard_device::device_start()
{
// resolve callbacks
m_write_clock.resolve_safe();
m_write_data.resolve_safe();
// state saving
save_item(NAME(m_keylatch));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void tandy2k_keyboard_device::device_reset()
{
}
//-------------------------------------------------
// power_w -
//-------------------------------------------------
WRITE_LINE_MEMBER( tandy2k_keyboard_device::power_w )
{
// TODO
}
//-------------------------------------------------
// reset_w -
//-------------------------------------------------
WRITE_LINE_MEMBER( tandy2k_keyboard_device::reset_w )
{
if (!state)
{
device_reset();
}
}
//-------------------------------------------------
// busy_w -
//-------------------------------------------------
WRITE_LINE_MEMBER( tandy2k_keyboard_device::busy_w )
{
m_maincpu->set_input_line(MCS48_INPUT_IRQ, state ? CLEAR_LINE : ASSERT_LINE);
}
//-------------------------------------------------
// data_r -
//-------------------------------------------------
READ_LINE_MEMBER( tandy2k_keyboard_device::data_r )
{
return m_data;
}
//-------------------------------------------------
// kb_p1_r -
//-------------------------------------------------
READ8_MEMBER( tandy2k_keyboard_device::kb_p1_r )
{
/*
bit description
0 X0
1 X1
2 X2
3 X3
4 X4
5 X5
6 X6
7 X7
*/
UINT8 data = 0xff;
if (!BIT(m_keylatch, 0)) data &= m_y0->read();
if (!BIT(m_keylatch, 1)) data &= m_y1->read();
if (!BIT(m_keylatch, 2)) data &= m_y2->read();
if (!BIT(m_keylatch, 3)) data &= m_y3->read();
if (!BIT(m_keylatch, 4)) data &= m_y4->read();
if (!BIT(m_keylatch, 5)) data &= m_y5->read();
if (!BIT(m_keylatch, 6)) data &= m_y6->read();
if (!BIT(m_keylatch, 7)) data &= m_y7->read();
if (!BIT(m_keylatch, 8)) data &= m_y8->read();
if (!BIT(m_keylatch, 9)) data &= m_y9->read();
if (!BIT(m_keylatch, 10)) data &= m_y10->read();
if (!BIT(m_keylatch, 11)) data &= m_y11->read();
return ~data;
}
//-------------------------------------------------
// kb_p1_w -
//-------------------------------------------------
WRITE8_MEMBER( tandy2k_keyboard_device::kb_p1_w )
{
/*
bit description
0 Y0
1 Y1
2 Y2
3 Y3
4 Y4
5 Y5
6 Y6
7 Y7
*/
// keyboard row
m_keylatch = (m_keylatch & 0xff00) | data;
}
//-------------------------------------------------
// kb_p2_w -
//-------------------------------------------------
WRITE8_MEMBER( tandy2k_keyboard_device::kb_p2_w )
{
/*
bit description
0 Y8
1 Y9
2 Y10
3 Y11
4 LED 2
5 LED 1
6 CLOCK
7 DATA
*/
// keyboard row
m_keylatch = ((data & 0x0f) << 8) | (m_keylatch & 0xff);
// led output
output_set_led_value(LED_2, !BIT(data, 4));
output_set_led_value(LED_1, !BIT(data, 5));
// keyboard clock
int clock = BIT(data, 6);
if (m_clock != clock)
{
m_clock = clock;
m_write_clock(m_clock);
}
// keyboard data
int kbddat = BIT(data, 7);
if (m_data != kbddat)
{
m_data = kbddat;
m_write_data(m_data);
}
}