tek410x: Add keyboard [AJR, Bitsavers]

* tek440x: Hook up 410X keyboard to pass boot test
* mc68681: Wait until transmitter is actually empty to set TxEMT
This commit is contained in:
AJR 2021-05-31 22:13:44 -04:00
parent da24cd8d9b
commit 57d621860c
6 changed files with 751 additions and 52 deletions

View File

@ -3908,6 +3908,8 @@ files {
MAME_DIR .. "src/mame/drivers/tek440x.cpp", MAME_DIR .. "src/mame/drivers/tek440x.cpp",
MAME_DIR .. "src/mame/drivers/tekigw.cpp", MAME_DIR .. "src/mame/drivers/tekigw.cpp",
MAME_DIR .. "src/mame/drivers/tekxp33x.cpp", MAME_DIR .. "src/mame/drivers/tekxp33x.cpp",
MAME_DIR .. "src/mame/machine/tek410x_kbd.cpp",
MAME_DIR .. "src/mame/machine/tek410x_kbd.h",
} }
createMESSProjects(_target, _subtarget, "telenova") createMESSProjects(_target, _subtarget, "telenova")

View File

@ -1269,7 +1269,7 @@ void duart_channel::tra_complete()
{ {
//printf("%s ch %d Tx complete\n", tag(), m_ch); //printf("%s ch %d Tx complete\n", tag(), m_ch);
tx_ready = 1; tx_ready = 1;
SR |= STATUS_TRANSMITTER_READY; SR |= STATUS_TRANSMITTER_READY | STATUS_TRANSMITTER_EMPTY;
if (m_ch == 0) if (m_ch == 0)
m_uart->set_ISR_bits(INT_TXRDYA); m_uart->set_ISR_bits(INT_TXRDYA);
@ -1319,24 +1319,13 @@ void duart_channel::update_interrupts()
switch (MR2 & 0xc0) // what mode are we in? switch (MR2 & 0xc0) // what mode are we in?
{ {
case 0x00: // normal mode case 0x00: // normal mode
if (tx_enabled)
SR |= STATUS_TRANSMITTER_EMPTY;
else
SR &= ~STATUS_TRANSMITTER_EMPTY;
break; break;
case 0x40: // automatic echo mode case 0x40: // automatic echo mode
SR &= ~STATUS_TRANSMITTER_EMPTY;
SR &= ~STATUS_TRANSMITTER_READY; SR &= ~STATUS_TRANSMITTER_READY;
break; break;
case 0x80: // local loopback mode case 0x80: // local loopback mode
if (tx_enabled)
SR |= STATUS_TRANSMITTER_EMPTY;
else
SR &= ~STATUS_TRANSMITTER_EMPTY;
break; break;
case 0xc0: // remote loopback mode case 0xc0: // remote loopback mode
// write me, what the txrdy/txemt regs do for remote loopback mode is undocumented afaik, for now just clear both
SR &= ~STATUS_TRANSMITTER_EMPTY;
SR &= ~STATUS_TRANSMITTER_READY; SR &= ~STATUS_TRANSMITTER_READY;
break; break;
} }
@ -1571,7 +1560,8 @@ void duart_channel::write_CR(uint8_t data)
break; break;
case 3: /* Reset channel transmitter */ case 3: /* Reset channel transmitter */
tx_enabled = 0; tx_enabled = 0;
SR &= ~STATUS_TRANSMITTER_READY; tx_ready = 0;
SR &= ~(STATUS_TRANSMITTER_READY | STATUS_TRANSMITTER_EMPTY);
if (m_ch == 0) if (m_ch == 0)
m_uart->clear_ISR_bits(INT_TXRDYA); m_uart->clear_ISR_bits(INT_TXRDYA);
else else
@ -1636,7 +1626,7 @@ void duart_channel::write_CR(uint8_t data)
{ {
tx_enabled = 1; tx_enabled = 1;
tx_ready = 1; tx_ready = 1;
SR |= STATUS_TRANSMITTER_READY; SR |= STATUS_TRANSMITTER_READY | STATUS_TRANSMITTER_EMPTY;
if (m_ch == 0) if (m_ch == 0)
m_uart->set_ISR_bits(INT_TXRDYA); m_uart->set_ISR_bits(INT_TXRDYA);
else else
@ -1646,7 +1636,7 @@ void duart_channel::write_CR(uint8_t data)
{ {
tx_enabled = 0; tx_enabled = 0;
tx_ready = 0; tx_ready = 0;
SR &= ~STATUS_TRANSMITTER_READY; SR &= ~(STATUS_TRANSMITTER_READY | STATUS_TRANSMITTER_EMPTY);
if (m_ch == 0) if (m_ch == 0)
m_uart->clear_ISR_bits(INT_TXRDYA); m_uart->clear_ISR_bits(INT_TXRDYA);
else else
@ -1668,7 +1658,7 @@ void duart_channel::write_TX(uint8_t data)
//printf("%s ch %d Tx %c [%02x]\n", tag(), m_ch, isprint(data) ? data : ' ', data); //printf("%s ch %d Tx %c [%02x]\n", tag(), m_ch, isprint(data) ? data : ' ', data);
tx_ready = 0; tx_ready = 0;
SR &= ~STATUS_TRANSMITTER_READY; SR &= ~(STATUS_TRANSMITTER_READY | STATUS_TRANSMITTER_EMPTY);
if (m_ch == 0) if (m_ch == 0)
m_uart->clear_ISR_bits(INT_TXRDYA); m_uart->clear_ISR_bits(INT_TXRDYA);

View File

@ -1,5 +1,5 @@
// license:BSD-3-Clause // license:BSD-3-Clause
// copyright-holders:Curt Coder // copyright-holders:Curt Coder, AJR
/*************************************************************************** /***************************************************************************
Tektronix 4107A/4109A Tektronix 4107A/4109A
@ -8,19 +8,11 @@
****************************************************************************/ ****************************************************************************/
/*
TODO:
- everything
*/
#include "emu.h" #include "emu.h"
#include "cpu/i86/i186.h" #include "cpu/i86/i186.h"
#include "machine/i8255.h" #include "machine/i8255.h"
#include "machine/mc68681.h" #include "machine/mc68681.h"
#include "machine/tek410x_kbd.h"
#include "video/crt9007.h" #include "video/crt9007.h"
#include "emupal.h" #include "emupal.h"
#include "screen.h" #include "screen.h"
@ -31,7 +23,19 @@ class tek4107a_state : public driver_device
public: public:
tek4107a_state(const machine_config &mconfig, device_type type, const char *tag) tek4107a_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag) : driver_device(mconfig, type, tag)
, m_duart(*this, "duart%u", 0U)
, m_keyboard(*this, "keyboard")
, m_vpac(*this, "vpac") , m_vpac(*this, "vpac")
, m_ppi_pc(0)
, m_kb_rdata(true)
, m_kb_tdata(true)
, m_kb_rclamp(false)
, m_graphics_control(0)
, m_alpha_control(0)
, m_x_position(0)
, m_y_position(0)
, m_x_cursor(0)
, m_y_cursor(0)
{ } { }
void tek4109a(machine_config &config); void tek4109a(machine_config &config);
@ -46,10 +50,45 @@ private:
u8 vpac_r(offs_t offset); u8 vpac_r(offs_t offset);
u16 nmi_enable_r();
u16 nmi_disable_r();
u16 system_reset_r();
void ppi_pc_w(u8 data);
DECLARE_WRITE_LINE_MEMBER(kb_rdata_w);
DECLARE_WRITE_LINE_MEMBER(kb_tdata_w);
DECLARE_WRITE_LINE_MEMBER(kb_rclamp_w);
void xpos_w(u16 data);
void ypos_w(u16 data);
void xcur_w(u16 data);
void ycur_w(u16 data);
void tbwin_w(u16 data);
u16 gcntl_r();
void gcntl_w(u16 data);
u16 acntl_r();
void acntl_w(u16 data);
u16 test_r();
u8 font_r();
void tek4107a_io(address_map &map); void tek4107a_io(address_map &map);
void tek4107a_mem(address_map &map); void tek4107a_mem(address_map &map);
required_device_array<scn2681_device, 2> m_duart;
required_device<tek410x_keyboard_device> m_keyboard;
required_device<crt9007_device> m_vpac; required_device<crt9007_device> m_vpac;
u8 m_ppi_pc;
bool m_kb_rdata;
bool m_kb_tdata;
bool m_kb_rclamp;
u16 m_graphics_control;
u16 m_alpha_control;
u16 m_x_position;
u16 m_y_position;
u16 m_x_cursor;
u16 m_y_cursor;
}; };
u8 tek4107a_state::vpac_r(offs_t offset) u8 tek4107a_state::vpac_r(offs_t offset)
@ -57,22 +96,150 @@ u8 tek4107a_state::vpac_r(offs_t offset)
return m_vpac->read(offset + 0x20); return m_vpac->read(offset + 0x20);
} }
u16 tek4107a_state::nmi_enable_r()
{
// TODO
return 0;
}
u16 tek4107a_state::nmi_disable_r()
{
// TODO
return 0;
}
u16 tek4107a_state::system_reset_r()
{
// TODO
return 0;
}
void tek4107a_state::ppi_pc_w(u8 data)
{
if (!m_kb_rclamp && BIT(m_ppi_pc, 2) != BIT(data, 2))
m_keyboard->kdo_w(!BIT(data, 2) || m_kb_tdata);
m_ppi_pc = data;
}
WRITE_LINE_MEMBER(tek4107a_state::kb_rdata_w)
{
m_kb_rdata = state;
if (!m_kb_rclamp)
m_duart[0]->rx_a_w(state);
}
WRITE_LINE_MEMBER(tek4107a_state::kb_rclamp_w)
{
if (m_kb_rclamp != !state)
{
m_kb_rclamp = !state;
// Clamp RXDA to 1 and KBRDATA to 0 when DUART asserts RxRDYA
if (m_kb_tdata || !BIT(m_ppi_pc, 2))
m_keyboard->kdo_w(state);
m_duart[0]->rx_a_w(state ? m_kb_rdata : 1);
}
}
WRITE_LINE_MEMBER(tek4107a_state::kb_tdata_w)
{
if (m_kb_tdata != state)
{
m_kb_tdata = state;
m_duart[0]->ip4_w(!state);
if (BIT(m_ppi_pc, 2) && m_kb_rdata && !m_kb_rclamp)
m_keyboard->kdo_w(state);
}
}
void tek4107a_state::xpos_w(u16 data)
{
m_x_position = data & 0x03ff;
}
void tek4107a_state::ypos_w(u16 data)
{
m_y_position = data & 0x01ff;
}
void tek4107a_state::xcur_w(u16 data)
{
m_x_cursor = data & 0x03ff;
}
void tek4107a_state::ycur_w(u16 data)
{
m_y_cursor = data & 0x01ff;
}
void tek4107a_state::tbwin_w(u16 data)
{
// TODO
}
u16 tek4107a_state::gcntl_r()
{
return m_graphics_control;
}
void tek4107a_state::gcntl_w(u16 data)
{
m_graphics_control = data;
}
u16 tek4107a_state::acntl_r()
{
return m_alpha_control;
}
void tek4107a_state::acntl_w(u16 data)
{
m_alpha_control = data;
}
u16 tek4107a_state::test_r()
{
// TODO
return 0;
}
u8 tek4107a_state::font_r()
{
// TODO
return 0;
}
/* Memory Maps */ /* Memory Maps */
void tek4107a_state::tek4107a_mem(address_map &map) void tek4107a_state::tek4107a_mem(address_map &map)
{ {
map(0x00000, 0x7ffff).ram(); map(0x00000, 0x3ffff).ram();
map(0x40000, 0x7ffff).ram().share("gfxram");
map(0x80000, 0xbffff).rom().region("firmware", 0); map(0x80000, 0xbffff).rom().region("firmware", 0);
map(0xf0000, 0xfffff).rom().region("firmware", 0x30000); map(0xf0000, 0xfffff).rom().region("firmware", 0x30000);
} }
void tek4107a_state::tek4107a_io(address_map &map) void tek4107a_state::tek4107a_io(address_map &map)
{ {
map(0x0000, 0x001f).rw("duart0", FUNC(scn2681_device::read), FUNC(scn2681_device::write)).umask16(0x00ff); map(0x0000, 0x001f).rw(m_duart[0], FUNC(scn2681_device::read), FUNC(scn2681_device::write)).umask16(0x00ff);
map(0x0000, 0x001f).rw("duart1", FUNC(scn2681_device::read), FUNC(scn2681_device::write)).umask16(0xff00); map(0x0000, 0x001f).rw(m_duart[1], FUNC(scn2681_device::read), FUNC(scn2681_device::write)).umask16(0xff00);
map(0x0080, 0x00bf).r(FUNC(tek4107a_state::vpac_r)).w(m_vpac, FUNC(crt9007_device::write)).umask16(0x00ff); map(0x0080, 0x00bf).r(FUNC(tek4107a_state::vpac_r)).w(m_vpac, FUNC(crt9007_device::write)).umask16(0x00ff);
map(0x00ce, 0x00cf).ram(); map(0x00c0, 0x00c1).w(FUNC(tek4107a_state::xpos_w));
map(0x00c2, 0x00c3).w(FUNC(tek4107a_state::ypos_w));
map(0x00c4, 0x00c5).w(FUNC(tek4107a_state::xcur_w));
map(0x00c6, 0x00c7).w(FUNC(tek4107a_state::ycur_w));
map(0x00c8, 0x00c9).r(FUNC(tek4107a_state::test_r));
map(0x00ca, 0x00ca).r(FUNC(tek4107a_state::font_r));
map(0x00ca, 0x00cb).w(FUNC(tek4107a_state::tbwin_w));
map(0x00cc, 0x00cd).rw(FUNC(tek4107a_state::gcntl_r), FUNC(tek4107a_state::gcntl_w));
map(0x00ce, 0x00cf).rw(FUNC(tek4107a_state::acntl_r), FUNC(tek4107a_state::acntl_w));
map(0x0100, 0x0107).rw("ppi", FUNC(i8255_device::read), FUNC(i8255_device::write)).umask16(0xff00); map(0x0100, 0x0107).rw("ppi", FUNC(i8255_device::read), FUNC(i8255_device::write)).umask16(0xff00);
map(0x0200, 0x0201).r(FUNC(tek4107a_state::nmi_enable_r));
map(0x0280, 0x0281).r(FUNC(tek4107a_state::system_reset_r));
map(0x0300, 0x0301).r(FUNC(tek4107a_state::nmi_disable_r));
} }
/* Input Ports */ /* Input Ports */
@ -84,6 +251,12 @@ INPUT_PORTS_END
void tek4107a_state::video_start() void tek4107a_state::video_start()
{ {
save_item(NAME(m_graphics_control));
save_item(NAME(m_alpha_control));
save_item(NAME(m_x_position));
save_item(NAME(m_y_position));
save_item(NAME(m_x_cursor));
save_item(NAME(m_y_cursor));
} }
u32 tek4107a_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) u32 tek4107a_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
@ -110,6 +283,10 @@ GFXDECODE_END
void tek4107a_state::machine_start() void tek4107a_state::machine_start()
{ {
save_item(NAME(m_ppi_pc));
save_item(NAME(m_kb_rdata));
save_item(NAME(m_kb_tdata));
save_item(NAME(m_kb_rclamp));
} }
/* Machine Driver */ /* Machine Driver */
@ -117,25 +294,34 @@ void tek4107a_state::machine_start()
void tek4107a_state::tek4107a(machine_config &config) void tek4107a_state::tek4107a(machine_config &config)
{ {
/* basic machine hardware */ /* basic machine hardware */
i80186_cpu_device &maincpu(I80186(config, "maincpu", 21000000)); i80186_cpu_device &maincpu(I80186(config, "maincpu", 14.7456_MHz_XTAL));
maincpu.set_addrmap(AS_PROGRAM, &tek4107a_state::tek4107a_mem); maincpu.set_addrmap(AS_PROGRAM, &tek4107a_state::tek4107a_mem);
maincpu.set_addrmap(AS_IO, &tek4107a_state::tek4107a_io); maincpu.set_addrmap(AS_IO, &tek4107a_state::tek4107a_io);
SCN2681(config, m_duart[0], 14.7456_MHz_XTAL / 4);
m_duart[0]->irq_cb().set("maincpu", FUNC(i80186_cpu_device::int0_w));
m_duart[0]->outport_cb().set_inputline("maincpu", INPUT_LINE_NMI).bit(5).invert(); // RxRDYB
m_duart[0]->outport_cb().append(FUNC(tek4107a_state::kb_rclamp_w)).bit(4);
m_duart[0]->outport_cb().append(m_keyboard, FUNC(tek410x_keyboard_device::reset_w)).bit(3);
m_duart[0]->a_tx_cb().set(m_keyboard, FUNC(tek410x_keyboard_device::kdi_w));
SCN2681(config, m_duart[1], 14.7456_MHz_XTAL / 4);
m_duart[1]->irq_cb().set("maincpu", FUNC(i80186_cpu_device::int2_w));
i8255_device &ppi(I8255(config, "ppi"));
ppi.in_pb_callback().set_constant(0x30);
ppi.out_pc_callback().set(FUNC(tek4107a_state::ppi_pc_w));
TEK410X_KEYBOARD(config, m_keyboard);
m_keyboard->tdata_callback().set(FUNC(tek4107a_state::kb_tdata_w));
m_keyboard->rdata_callback().set(FUNC(tek4107a_state::kb_rdata_w));
/* video hardware */ /* video hardware */
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_raw(25200000, 800, 0, 640, 525, 0, 480); screen.set_raw(25.2_MHz_XTAL, 800, 0, 640, 525, 0, 480);
screen.set_screen_update(FUNC(tek4107a_state::screen_update)); screen.set_screen_update(FUNC(tek4107a_state::screen_update));
scn2681_device &duart0(SCN2681(config, "duart0", 3686400)); CRT9007(config, m_vpac, 25.2_MHz_XTAL / 8);
duart0.irq_cb().set("maincpu", FUNC(i80186_cpu_device::int0_w));
duart0.outport_cb().set_inputline("maincpu", INPUT_LINE_NMI).bit(5).invert(); // RxRDYB
scn2681_device &duart1(SCN2681(config, "duart1", 3686400));
duart1.irq_cb().set("maincpu", FUNC(i80186_cpu_device::int2_w));
I8255(config, "ppi").in_pb_callback().set_constant(0x30);
CRT9007(config, m_vpac, 25200000 / 8);
m_vpac->set_screen("screen"); m_vpac->set_screen("screen");
m_vpac->set_character_width(8); m_vpac->set_character_width(8);
m_vpac->int_callback().set("maincpu", FUNC(i80186_cpu_device::int1_w)); m_vpac->int_callback().set("maincpu", FUNC(i80186_cpu_device::int1_w));

View File

@ -1,5 +1,5 @@
// license:BSD-3-Clause // license:BSD-3-Clause
// copyright-holders:R. Belmont // copyright-holders:R. Belmont, AJR
/*************************************************************************** /***************************************************************************
Tektronix 440x "AI Workstations" Tektronix 440x "AI Workstations"
@ -45,12 +45,12 @@
#include "bus/rs232/rs232.h" #include "bus/rs232/rs232.h"
#include "cpu/m68000/m68000.h" #include "cpu/m68000/m68000.h"
#include "cpu/m6502/m6502.h" #include "cpu/m6502/m6502.h"
#include "cpu/mcs48/mcs48.h"
#include "machine/am9513.h" #include "machine/am9513.h"
#include "machine/bankdev.h" #include "machine/bankdev.h"
#include "machine/mos6551.h" // debug tty #include "machine/mos6551.h" // debug tty
#include "machine/mc146818.h" #include "machine/mc146818.h"
#include "machine/mc68681.h" #include "machine/mc68681.h"
#include "machine/tek410x_kbd.h"
#include "sound/sn76496.h" #include "sound/sn76496.h"
#include "emupal.h" #include "emupal.h"
#include "screen.h" #include "screen.h"
@ -65,10 +65,17 @@ public:
m_maincpu(*this, "maincpu"), m_maincpu(*this, "maincpu"),
m_fdccpu(*this, "fdccpu"), m_fdccpu(*this, "fdccpu"),
m_vm(*this, "vm"), m_vm(*this, "vm"),
m_duart(*this, "duart"),
m_keyboard(*this, "keyboard"),
m_snsnd(*this, "snsnd"), m_snsnd(*this, "snsnd"),
m_prom(*this, "maincpu"), m_prom(*this, "maincpu"),
m_mainram(*this, "mainram"), m_mainram(*this, "mainram"),
m_vram(*this, "vram") m_vram(*this, "vram"),
m_boot(false),
m_kb_rdata(true),
m_kb_tdata(true),
m_kb_rclamp(false),
m_kb_loop(false)
{ } { }
void tek4404(machine_config &config); void tek4404(machine_config &config);
@ -81,6 +88,11 @@ private:
u16 memory_r(offs_t offset, u16 mem_mask); u16 memory_r(offs_t offset, u16 mem_mask);
void memory_w(offs_t offset, u16 data, u16 mem_mask); void memory_w(offs_t offset, u16 data, u16 mem_mask);
void sound_w(u8 data); void sound_w(u8 data);
void diag_w(u8 data);
DECLARE_WRITE_LINE_MEMBER(kb_rdata_w);
DECLARE_WRITE_LINE_MEMBER(kb_tdata_w);
DECLARE_WRITE_LINE_MEMBER(kb_rclamp_w);
void logical_map(address_map &map); void logical_map(address_map &map);
void physical_map(address_map &map); void physical_map(address_map &map);
@ -89,12 +101,18 @@ private:
required_device<m68010_device> m_maincpu; required_device<m68010_device> m_maincpu;
required_device<m6502_device> m_fdccpu; required_device<m6502_device> m_fdccpu;
required_device<address_map_bank_device> m_vm; required_device<address_map_bank_device> m_vm;
required_device<mc68681_device> m_duart;
required_device<tek410x_keyboard_device> m_keyboard;
required_device<sn76496_device> m_snsnd; required_device<sn76496_device> m_snsnd;
required_region_ptr<u16> m_prom; required_region_ptr<u16> m_prom;
required_shared_ptr<u16> m_mainram; required_shared_ptr<u16> m_mainram;
required_shared_ptr<u16> m_vram; required_shared_ptr<u16> m_vram;
bool m_boot; bool m_boot;
bool m_kb_rdata;
bool m_kb_tdata;
bool m_kb_rclamp;
bool m_kb_loop;
}; };
/************************************* /*************************************
@ -106,6 +124,10 @@ private:
void tek440x_state::machine_start() void tek440x_state::machine_start()
{ {
save_item(NAME(m_boot)); save_item(NAME(m_boot));
save_item(NAME(m_kb_rdata));
save_item(NAME(m_kb_tdata));
save_item(NAME(m_kb_rclamp));
save_item(NAME(m_kb_loop));
} }
@ -119,6 +141,8 @@ void tek440x_state::machine_start()
void tek440x_state::machine_reset() void tek440x_state::machine_reset()
{ {
m_boot = true; m_boot = true;
diag_w(0);
m_keyboard->kdo_w(1);
} }
@ -178,6 +202,46 @@ void tek440x_state::sound_w(u8 data)
m_boot = false; m_boot = false;
} }
void tek440x_state::diag_w(u8 data)
{
if (!m_kb_rclamp && m_kb_loop != BIT(data, 7))
m_keyboard->kdo_w(!BIT(data, 7) || m_kb_tdata);
m_kb_loop = BIT(data, 7);
}
WRITE_LINE_MEMBER(tek440x_state::kb_rdata_w)
{
m_kb_rdata = state;
if (!m_kb_rclamp)
m_duart->rx_a_w(state);
}
WRITE_LINE_MEMBER(tek440x_state::kb_rclamp_w)
{
if (m_kb_rclamp != !state)
{
m_kb_rclamp = !state;
// Clamp RXDA to 1 and KBRDATA to 0 when DUART asserts RxRDYA
if (m_kb_tdata || !m_kb_loop)
m_keyboard->kdo_w(state);
m_duart->rx_a_w(state ? m_kb_rdata : 1);
}
}
WRITE_LINE_MEMBER(tek440x_state::kb_tdata_w)
{
if (m_kb_tdata != state)
{
m_kb_tdata = state;
m_duart->ip4_w(!state);
if (m_kb_loop && m_kb_rdata && !m_kb_rclamp)
m_keyboard->kdo_w(state);
}
}
void tek440x_state::logical_map(address_map &map) void tek440x_state::logical_map(address_map &map)
{ {
map(0x000000, 0x7fffff).rw(FUNC(tek440x_state::memory_r), FUNC(tek440x_state::memory_w)); map(0x000000, 0x7fffff).rw(FUNC(tek440x_state::memory_r), FUNC(tek440x_state::memory_w));
@ -195,9 +259,10 @@ void tek440x_state::physical_map(address_map &map)
map(0x788000, 0x788000).w(FUNC(tek440x_state::sound_w)); map(0x788000, 0x788000).w(FUNC(tek440x_state::sound_w));
// 78a000-78bfff: NS32081 FPU // 78a000-78bfff: NS32081 FPU
map(0x78c000, 0x78c007).rw("aica", FUNC(mos6551_device::read), FUNC(mos6551_device::write)).umask16(0xff00); map(0x78c000, 0x78c007).rw("aica", FUNC(mos6551_device::read), FUNC(mos6551_device::write)).umask16(0xff00);
map(0x7b0000, 0x7b0000).w(FUNC(tek440x_state::diag_w));
// 7b1000-7b2fff: diagnostic registers // 7b1000-7b2fff: diagnostic registers
// 7b2000-7b3fff: Centronics printer data // 7b2000-7b3fff: Centronics printer data
map(0x7b4000, 0x7b401f).rw("duart", FUNC(mc68681_device::read), FUNC(mc68681_device::write)).umask16(0xff00); map(0x7b4000, 0x7b401f).rw(m_duart, FUNC(mc68681_device::read), FUNC(mc68681_device::write)).umask16(0xff00);
// 7b6000-7b7fff: Mouse // 7b6000-7b7fff: Mouse
map(0x7b8000, 0x7b8003).mirror(0x100).rw("timer", FUNC(am9513_device::read16), FUNC(am9513_device::write16)); map(0x7b8000, 0x7b8003).mirror(0x100).rw("timer", FUNC(am9513_device::read16), FUNC(am9513_device::write16));
// 7ba000-7bbfff: MC146818 RTC // 7ba000-7bbfff: MC146818 RTC
@ -254,10 +319,15 @@ void tek440x_state::tek4404(machine_config &config)
aica.txd_handler().set("rs232", FUNC(rs232_port_device::write_txd)); aica.txd_handler().set("rs232", FUNC(rs232_port_device::write_txd));
aica.irq_handler().set_inputline(m_maincpu, M68K_IRQ_7); aica.irq_handler().set_inputline(m_maincpu, M68K_IRQ_7);
mc68681_device &duart(MC68681(config, "duart", 3.6864_MHz_XTAL)); MC68681(config, m_duart, 3.6864_MHz_XTAL);
duart.irq_cb().set_inputline(m_maincpu, M68K_IRQ_5); m_duart->irq_cb().set_inputline(m_maincpu, M68K_IRQ_5); // auto-vectored
m_duart->outport_cb().set(FUNC(tek440x_state::kb_rclamp_w)).bit(4);
m_duart->outport_cb().append(m_keyboard, FUNC(tek410x_keyboard_device::reset_w)).bit(3);
m_duart->a_tx_cb().set(m_keyboard, FUNC(tek410x_keyboard_device::kdi_w));
I8048(config, "kbdmcu", 4.608_MHz_XTAL).set_disable(); TEK410X_KEYBOARD(config, m_keyboard);
m_keyboard->tdata_callback().set(FUNC(tek440x_state::kb_tdata_w));
m_keyboard->rdata_callback().set(FUNC(tek440x_state::kb_rdata_w));
AM9513(config, "timer", 40_MHz_XTAL / 4 / 10); // from CPU E output AM9513(config, "timer", 40_MHz_XTAL / 4 / 10); // from CPU E output
@ -293,9 +363,6 @@ ROM_START( tek4404 )
ROM_REGION( 0x2000, "scsimfm", 0 ) ROM_REGION( 0x2000, "scsimfm", 0 )
ROM_LOAD( "scsi_mfm.bin", 0x000000, 0x002000, CRC(b4293435) SHA1(5e2b96c19c4f5c63a5afa2de504d29fe64a4c908) ) ROM_LOAD( "scsi_mfm.bin", 0x000000, 0x002000, CRC(b4293435) SHA1(5e2b96c19c4f5c63a5afa2de504d29fe64a4c908) )
ROM_REGION( 0x400, "kbdmcu", 0 )
ROM_LOAD( "keytronic_8x48.bin", 0x000, 0x400, NO_DUMP )
ROM_END ROM_END
/************************************* /*************************************

View File

@ -0,0 +1,385 @@
// license:BSD-3-Clause
// copyright-holders:AJR
/**********************************************************************
This emulates the standard serial keyboard used with Tektronix's
4105, 4106, 4107 and 4109 terminals, including the trademark
octagonal "joy disk". The 4404 keyboard is also compatible.
The hardware was designed by the Keytronic Corporation, and uses
their 20-pin key strobe driver (22-0950-003) and input receiver
(22-0908-003) ASICs.
The 8048/8748's DB pins are connected to drivers for up to 5 LEDs,
but only one of these LEDs (CR9, on the Caps Lock key) is actually
populated.
A different but apparently backward-compatible keyboard was used
with the CX4107 and CX4109, based on a 8051 CPU with space for an
external program ROM and adding an onboard speaker as well as many
extra keys and an IBM 3279-style layout.
Hexadecimal table of press codes (release codes are the same + 80):
00 Caps Lock
01 Left Shift
02 Right Shift
03 Ctrl
04 DEras/SEras
05 Break
06 Back Space
07 Tab
08 Line Feed
09 Return
0A Esc
0B Space Bar
0C " '
0D < ,
0E _ -
0F > .
10 ? /
11 ) 0
12 ! 1
13 @ 2
14 # 3
15 $ 4
16 % 5
17 ^ 6
18 & 7
19 * 8
1A ( 9
1B : ;
1C =
1D A
1E B
1F C
20 D
21 E
22 F
23 G
24 H
25 I
26 J
27 K
28 L
29 M
2A N
2B O
2C P
2D Q
2E R
2F S
30 T
31 U
32 V
33 W
34 X
35 Y
36 Z
37 { [
38 ` \
39 } ]
3A ~ |
3B Rub Out
3C Enter (keypad)
3D , (keypad)
3E - (keypad)
3F . (keypad)
40 0 (keypad)
41 1 (keypad)
42 2 (keypad)
43 3 (keypad)
44 4 (keypad)
45 5 (keypad)
46 6 (keypad)
47 7 (keypad)
48 8 (keypad)
49 9 (keypad)
4A F1
4B F2
4C F3
4D F4
4E F5
4F F6
50 F7
51 F8
52 GEras/Dialog
53 Cancel/Setup
54 DCopy/SCopy
55 Menu
56 Cursor Right (joystick)
57 Cursor Up (joystick)
58 Cursor Left (joystick)
59 Cursor Down (joystick)
Additional press codes for CX keyboard only:
5A Erase EOF
5B Dup/PA1
5C Reset/Dev Cncl
5D Field Mark/PA2/_
5E Attn Sys Req
5F Cursr Sel/Clear
60 < >
61 Cursr Blink/Alt Cursr
62 Ident
63 Down Arrow
64 Right Arrow/Right Double Arrow
65 Left Arrow/Left Double Arrow
66 Up Arrow
67 Insert/Alpha
68 Right Alt/Ctrl
The baud rate is 4800, with 8 data bits and no parity.
**********************************************************************/
#include "emu.h"
#include "tek410x_kbd.h"
// device type definition
DEFINE_DEVICE_TYPE(TEK410X_KEYBOARD, tek410x_keyboard_device, "tek410x_kbd", "Tektronix 410X Standard Keyboard (119-1592-01)")
tek410x_keyboard_device::tek410x_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, TEK410X_KEYBOARD, tag, owner, clock)
, m_mcu(*this, "mcu")
, m_key_matrix(*this, "X%u", 0U)
, m_config(*this, "CONFIG")
, m_tdata_callback(*this)
, m_rdata_callback(*this)
, m_select(0)
, m_p2_out(0)
, m_kdi(true)
, m_kdo(false)
{
}
void tek410x_keyboard_device::device_resolve_objects()
{
m_tdata_callback.resolve_safe();
m_rdata_callback.resolve_safe();
}
void tek410x_keyboard_device::device_start()
{
save_item(NAME(m_select));
save_item(NAME(m_p2_out));
save_item(NAME(m_kdi));
save_item(NAME(m_kdo));
}
WRITE_LINE_MEMBER(tek410x_keyboard_device::kdi_w)
{
m_kdi = state;
if (BIT(m_p2_out, 7))
{
m_mcu->set_input_line(MCS48_INPUT_IRQ, state ? CLEAR_LINE : ASSERT_LINE);
m_tdata_callback(state);
}
}
WRITE_LINE_MEMBER(tek410x_keyboard_device::kdo_w)
{
m_kdo = state;
if (BIT(m_p2_out, 5))
m_rdata_callback(state);
}
WRITE_LINE_MEMBER(tek410x_keyboard_device::reset_w)
{
m_mcu->set_input_line(INPUT_LINE_RESET, state ? CLEAR_LINE : ASSERT_LINE);
if (!state)
p2_w(0xff);
}
u8 tek410x_keyboard_device::p1_r()
{
if (m_select < 12)
return m_key_matrix[m_select]->read();
else
return 0xff;
}
u8 tek410x_keyboard_device::p2_r()
{
return 0xb0 | (m_kdo ? (m_p2_out & 0x20) << 1 : 0) | m_config->read();
}
void tek410x_keyboard_device::p2_w(u8 data)
{
if (!BIT(data, 4))
m_select = m_mcu->p1_r() & 0x0f;
if (m_kdi && BIT(data, 7) != BIT(m_p2_out, 7))
{
m_tdata_callback(BIT(data, 7));
m_mcu->set_input_line(MCS48_INPUT_IRQ, BIT(data, 7) ? CLEAR_LINE : ASSERT_LINE);
}
if (m_kdo && BIT(data, 5) != BIT(m_p2_out, 5))
m_rdata_callback(BIT(data, 5));
m_p2_out = data;
}
void tek410x_keyboard_device::ext_map(address_map &map)
{
map(0x00, 0xff).nopr();
}
static INPUT_PORTS_START(tek410x_keyboard)
PORT_START("X0")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) PORT_CODE(KEYCODE_ENTER_PAD)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(COMMA_PAD)) PORT_CODE(KEYCODE_PLUS_PAD)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) PORT_CODE(KEYCODE_3_PAD)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) PORT_CODE(KEYCODE_6_PAD)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PORT_CODE(KEYCODE_MINUS_PAD)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) PORT_CODE(KEYCODE_9_PAD)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) PORT_CODE(KEYCODE_DEL_PAD)
PORT_START("X1")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) PORT_CODE(KEYCODE_4_PAD)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) PORT_CODE(KEYCODE_2_PAD)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) PORT_CODE(KEYCODE_5_PAD)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) PORT_CODE(KEYCODE_7_PAD)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) PORT_CODE(KEYCODE_1_PAD)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) PORT_CODE(KEYCODE_8_PAD)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) PORT_CODE(KEYCODE_0_PAD)
PORT_START("X2")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Break") //PORT_CODE(KEYCODE_XXX)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Line Feed") PORT_CHAR(0x0a) //PORT_CODE(KEYCODE_XXX)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Rub Out") PORT_CODE(KEYCODE_BACKSPACE)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(']') PORT_CHAR('}') PORT_CODE(KEYCODE_BACKSLASH)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_START("X3")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Right Shift") PORT_CODE(KEYCODE_RSHIFT)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\\') PORT_CHAR('`') PORT_CODE(KEYCODE_OPENBRACE)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\'') PORT_CHAR('"') PORT_CODE(KEYCODE_QUOTE)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Back Space") PORT_CHAR(0x08) PORT_CODE(KEYCODE_CLOSEBRACE)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('-') PORT_CHAR('_') PORT_CODE(KEYCODE_MINUS)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") PORT_CHAR(0x0d) PORT_CODE(KEYCODE_ENTER)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('=') PORT_CHAR('+') PORT_CODE(KEYCODE_EQUALS)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Space Bar") PORT_CHAR(' ') PORT_CODE(KEYCODE_SPACE)
PORT_START("X4")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_CODE(KEYCODE_DOWN)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PORT_CODE(KEYCODE_LEFT)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F7)) PORT_CODE(KEYCODE_F11)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F2)) PORT_CODE(KEYCODE_F6)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F6)) PORT_CODE(KEYCODE_F10)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Setup Cancel") PORT_CODE(KEYCODE_F2)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F3)) PORT_CODE(KEYCODE_F7)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("SCopy DCopy") PORT_CODE(KEYCODE_F3)
PORT_START("X5")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_CODE(KEYCODE_RIGHT)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(UP)) PORT_CODE(KEYCODE_UP)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F8)) PORT_CODE(KEYCODE_F12)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_CODE(KEYCODE_F5)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F5)) PORT_CODE(KEYCODE_F9)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Dialog GEras") PORT_CODE(KEYCODE_F1)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F4)) PORT_CODE(KEYCODE_F8)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Menu") PORT_CODE(KEYCODE_F4)
PORT_START("X6")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("X") PORT_CHAR('x') PORT_CHAR('X') PORT_CODE(KEYCODE_X)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W") PORT_CHAR('w') PORT_CHAR('W') PORT_CODE(KEYCODE_W)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("S") PORT_CHAR('s') PORT_CHAR('S') PORT_CODE(KEYCODE_S)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q") PORT_CHAR('q') PORT_CHAR('Q') PORT_CODE(KEYCODE_Q)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('2') PORT_CHAR('@') PORT_CODE(KEYCODE_2)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A") PORT_CHAR('a') PORT_CHAR('A') PORT_CODE(KEYCODE_A)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('1') PORT_CHAR('!') PORT_CODE(KEYCODE_1)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z") PORT_CHAR('z') PORT_CHAR('Z') PORT_CODE(KEYCODE_Z)
PORT_START("X7")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Caps Lock") PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_CODE(KEYCODE_LCONTROL)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CHAR(0x1b) //PORT_CODE(KEYCODE_XXX)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Tab") PORT_CHAR(0x09) //PORT_CODE(KEYCODE_XXX)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('|') PORT_CHAR('~') PORT_CODE(KEYCODE_TAB)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("SEras DEras") //PORT_CODE(KEYCODE_XXX)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ctrl") PORT_CHAR(UCHAR_SHIFT_2) PORT_CODE(KEYCODE_CAPSLOCK)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('[') PORT_CHAR('{') PORT_CODE(KEYCODE_TILDE)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Left Shift") PORT_CHAR(UCHAR_SHIFT_1) PORT_CODE(KEYCODE_LSHIFT)
PORT_START("X8")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C") PORT_CHAR('c') PORT_CHAR('C') PORT_CODE(KEYCODE_C)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E") PORT_CHAR('e') PORT_CHAR('E') PORT_CODE(KEYCODE_E)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D") PORT_CHAR('d') PORT_CHAR('D') PORT_CODE(KEYCODE_D)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("R") PORT_CHAR('r') PORT_CHAR('R') PORT_CODE(KEYCODE_R)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('3') PORT_CHAR('#') PORT_CODE(KEYCODE_3)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F") PORT_CHAR('f') PORT_CHAR('F') PORT_CODE(KEYCODE_F)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('4') PORT_CHAR('$') PORT_CODE(KEYCODE_4)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("V") PORT_CHAR('v') PORT_CHAR('V') PORT_CODE(KEYCODE_V)
PORT_START("X9")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("N") PORT_CHAR('n') PORT_CHAR('N') PORT_CODE(KEYCODE_N)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y") PORT_CHAR('y') PORT_CHAR('Y') PORT_CODE(KEYCODE_Y)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("H") PORT_CHAR('h') PORT_CHAR('H') PORT_CODE(KEYCODE_H)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("T") PORT_CHAR('t') PORT_CHAR('T') PORT_CODE(KEYCODE_T)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('6') PORT_CHAR('^') PORT_CODE(KEYCODE_6)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G") PORT_CHAR('g') PORT_CHAR('G') PORT_CODE(KEYCODE_G)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('5') PORT_CHAR('%') PORT_CODE(KEYCODE_5)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B") PORT_CHAR('b') PORT_CHAR('B') PORT_CODE(KEYCODE_B)
PORT_START("X10")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M") PORT_CHAR('m') PORT_CHAR('M') PORT_CODE(KEYCODE_M)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("U") PORT_CHAR('u') PORT_CHAR('U') PORT_CODE(KEYCODE_U)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("J") PORT_CHAR('j') PORT_CHAR('J') PORT_CODE(KEYCODE_J)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("I") PORT_CHAR('i') PORT_CHAR('I') PORT_CODE(KEYCODE_I)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('7') PORT_CHAR('&') PORT_CODE(KEYCODE_7)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("K") PORT_CHAR('k') PORT_CHAR('K') PORT_CODE(KEYCODE_K)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('8') PORT_CHAR('*') PORT_CODE(KEYCODE_8)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(',') PORT_CHAR('>') PORT_CODE(KEYCODE_COMMA)
PORT_START("X11")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('/') PORT_CHAR('?') PORT_CODE(KEYCODE_SLASH)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P") PORT_CHAR('p') PORT_CHAR('P') PORT_CODE(KEYCODE_P)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(';') PORT_CHAR(':') PORT_CODE(KEYCODE_COLON)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O") PORT_CHAR('o') PORT_CHAR('O') PORT_CODE(KEYCODE_O)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('0') PORT_CHAR('(') PORT_CODE(KEYCODE_0)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L") PORT_CHAR('l') PORT_CHAR('L') PORT_CODE(KEYCODE_L)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('9') PORT_CHAR(')') PORT_CODE(KEYCODE_9)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('.') PORT_CHAR('>') PORT_CODE(KEYCODE_STOP)
PORT_START("CONFIG")
PORT_DIPNAME(0x0f, 0x00, "Keyboard Type") PORT_DIPLOCATION("E:1,2,3,4")
PORT_DIPSETTING(0x00, "North America")
PORT_DIPSETTING(0x08, "United Kingdom (4A)")
PORT_DIPSETTING(0x04, "French (4B)")
PORT_DIPSETTING(0x02, "Swedish (4C)")
PORT_DIPSETTING(0x06, "Danish/Norwegian (4F)")
PORT_DIPSETTING(0x07, "German (4G)")
PORT_DIPSETTING(0x0a, "Katakana (4K)")
INPUT_PORTS_END
ioport_constructor tek410x_keyboard_device::device_input_ports() const
{
return INPUT_PORTS_NAME(tek410x_keyboard);
}
void tek410x_keyboard_device::device_add_mconfig(machine_config &config)
{
I8748(config, m_mcu, 4.608_MHz_XTAL);
m_mcu->set_addrmap(AS_IO, &tek410x_keyboard_device::ext_map);
m_mcu->bus_out_cb().set_output("led0").bit(0);
m_mcu->p1_in_cb().set(FUNC(tek410x_keyboard_device::p1_r));
m_mcu->p2_in_cb().set(FUNC(tek410x_keyboard_device::p2_r));
m_mcu->p2_out_cb().set(FUNC(tek410x_keyboard_device::p2_w));
}
ROM_START(tek410x_kbd)
ROM_REGION(0x400, "mcu", 0)
ROM_LOAD("473_8748.bin", 0x000, 0x400, CRC(371553a8) SHA1(165ffc2c0775c1a3c2cc3ec86fb05adc8e8bb3eb))
ROM_END
const tiny_rom_entry *tek410x_keyboard_device::device_rom_region() const
{
return ROM_NAME(tek410x_kbd);
}

View File

@ -0,0 +1,69 @@
// license:BSD-3-Clause
// copyright-holders:AJR
#ifndef MAME_MACHINE_TEK410X_KEYBOARD_H
#define MAME_MACHINE_TEK410X_KEYBOARD_H
#pragma once
#include "cpu/mcs48/mcs48.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> tek410x_keyboard_device
class tek410x_keyboard_device : public device_t
{
public:
// device type constructor
tek410x_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
// callback configuration
auto tdata_callback() { return m_tdata_callback.bind(); }
auto rdata_callback() { return m_rdata_callback.bind(); }
// line inputs
DECLARE_WRITE_LINE_MEMBER(kdi_w);
DECLARE_WRITE_LINE_MEMBER(kdo_w);
DECLARE_WRITE_LINE_MEMBER(reset_w);
protected:
// device-level overrides
virtual void device_resolve_objects() override;
virtual void device_start() override;
virtual ioport_constructor device_input_ports() const override;
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
private:
// MCU handlers
u8 p1_r();
u8 p2_r();
void p2_w(u8 data);
// address maps
void ext_map(address_map &map);
// object finders
required_device<mcs48_cpu_device> m_mcu;
required_ioport_array<12> m_key_matrix;
required_ioport m_config;
// output callbacks
devcb_write_line m_tdata_callback;
devcb_write_line m_rdata_callback;
// internal state
u8 m_select;
u8 m_p2_out;
bool m_kdi;
bool m_kdo;
};
// device type declaration
DECLARE_DEVICE_TYPE(TEK410X_KEYBOARD, tek410x_keyboard_device)
#endif // MAME_MACHINE_TEK410X_KEYBOARD_H