// license:BSD-3-Clause
// copyright-holders:Curt Coder
/**********************************************************************
Tandy 2000 keyboard emulation
*********************************************************************/
#include "emu.h"
#include "tandy2kb.h"
//**************************************************************************
// MACROS / CONSTANTS
//**************************************************************************
#define I8048_TAG "m1"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
DEFINE_DEVICE_TYPE(TANDY2K_KEYBOARD, tandy2k_keyboard_device, "tandy2kb", "Tandy 2000 Keyboard")
//-------------------------------------------------
// 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 tiny_rom_entry *tandy2k_keyboard_device::device_rom_region() const
{
return ROM_NAME( tandy2k_keyboard );
}
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
MACHINE_CONFIG_START(tandy2k_keyboard_device::device_add_mconfig)
MCFG_DEVICE_ADD(I8048_TAG, I8048, 1000000) // ?
MCFG_MCS48_PORT_P1_OUT_CB(WRITE8(*this, tandy2k_keyboard_device, kb_p1_w))
MCFG_MCS48_PORT_P2_OUT_CB(WRITE8(*this, tandy2k_keyboard_device, kb_p2_w))
MCFG_MCS48_PORT_BUS_IN_CB(READ8(*this, tandy2k_keyboard_device, kb_p1_r))
MCFG_DEVICE_DISABLE() // TODO
MACHINE_CONFIG_END
//-------------------------------------------------
// 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_t clock) :
device_t(mconfig, TANDY2K_KEYBOARD, tag, owner, clock),
m_maincpu(*this, I8048_TAG),
m_y(*this, "Y%u", 0),
m_led(*this, "led%u", 0U),
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()
{
m_led.resolve();
// 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_t data = 0xff;
for (int i = 0; i < 12; i++)
{
if (!BIT(m_keylatch, i)) data &= m_y[i]->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
m_led[LED_2] = BIT(~data, 4);
m_led[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);
}
}