New working machines

--------------------
MDT 60 Video Display Terminal [Bitsavers, AJR]

z29: Add skeleton for undumped keyboard; try (and fail) to make this work with the MDT 60 keyboard instead

z22: Separate driver (nw)
This commit is contained in:
AJR 2020-04-29 11:12:52 -04:00
parent b403d9be2d
commit 9556e3a5bd
13 changed files with 1189 additions and 201 deletions

View File

@ -2198,6 +2198,23 @@ if (BUSES["WANGPC"]~=null) then
end
---------------------------------------------------
--
--@src/devices/bus/z29_kbd/keyboard.h,BUSES["Z29_KBD"] = true
---------------------------------------------------
if (BUSES["Z29_KBD"]~=null) then
files {
MAME_DIR .. "src/devices/bus/z29_kbd/keyboard.cpp",
MAME_DIR .. "src/devices/bus/z29_kbd/keyboard.h",
MAME_DIR .. "src/devices/bus/z29_kbd/he191_3425.cpp",
MAME_DIR .. "src/devices/bus/z29_kbd/he191_3425.h",
MAME_DIR .. "src/devices/bus/z29_kbd/md_kbd.cpp",
MAME_DIR .. "src/devices/bus/z29_kbd/md_kbd.h",
}
end
---------------------------------------------------
--
--@src/devices/bus/z88/z88.h,BUSES["Z88"] = true

View File

@ -918,6 +918,7 @@ BUSES["VTECH_MEMEXP"] = true
BUSES["WANGPC"] = true
BUSES["WSWAN"] = true
BUSES["X68K"] = true
BUSES["Z29_KBD"] = true
BUSES["Z88"] = true
BUSES["ZORRO"] = true
@ -4179,6 +4180,7 @@ createMESSProjects(_target, _subtarget, "zenith")
files {
MAME_DIR .. "src/mame/drivers/mdt60.cpp",
MAME_DIR .. "src/mame/drivers/z100.cpp",
MAME_DIR .. "src/mame/drivers/z22.cpp",
MAME_DIR .. "src/mame/drivers/z29.cpp",
}

View File

@ -0,0 +1,240 @@
// license:BSD-3-Clause
// copyright-holders:AJR
/***************************************************************************
Heath HE 191-3425 keyboard
This 91-key detached keyboard is standard issue for the H-29 (Z-29)
terminal. It is also specified for the MDT 60 in its schematics.
Since the 8021 MCU is not dumped, emulation is more or less a stub.
***************************************************************************/
#include "emu.h"
#include "he191_3425.h"
#include "cpu/mcs48/mcs48.h"
#include "machine/rescap.h"
#include "speaker.h"
DEFINE_DEVICE_TYPE(HE191_3425, he191_3425_device, "he191_3425", "Heath HE 191-3425 Keyboard")
he191_3425_device::he191_3425_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, HE191_3425, tag, owner, clock)
, device_z29_keyboard_interface(mconfig, *this)
, m_mcu(*this, "mcu")
, m_buzzer(*this, "buzzer")
, m_matrix(*this, {"B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "B11", "B13", "B14"})
, m_modifiers(*this, "MODIFIERS")
, m_leds(*this, "led%u", 1U)
, m_select(0)
, m_recv_data(true)
{
}
void he191_3425_device::device_resolve_objects()
{
m_leds.resolve();
}
void he191_3425_device::device_start()
{
m_leds[0] = 1; // L1: Power
save_item(NAME(m_select));
save_item(NAME(m_recv_data));
}
void he191_3425_device::receive_data(bool state)
{
machine().scheduler().synchronize(timer_expired_delegate(FUNC(he191_3425_device::receive_data_synced), this), state);
}
TIMER_CALLBACK_MEMBER(he191_3425_device::receive_data_synced)
{
m_recv_data = param;
}
u8 he191_3425_device::mcu_pa_r()
{
return m_select < 12 ? m_matrix[m_select]->read() : 0xff;
}
void he191_3425_device::mcu_pb_w(u8 data)
{
transmit_data(!BIT(data, 3));
m_leds[1] = !BIT(data, 4); // L2: Keyboard Lock
m_leds[2] = !BIT(data, 5); // L3: Off/Line
m_leds[3] = !BIT(data, 6); // L4: Caps Lock
m_buzzer->set_state(BIT(data, 7));
}
void he191_3425_device::mcu_pc_w(u8 data)
{
m_select = data & 0xf;
}
READ_LINE_MEMBER(he191_3425_device::mcu_t1_r)
{
return m_recv_data;
}
WRITE_LINE_MEMBER(he191_3425_device::shift_reset)
{
m_mcu->set_input_line(INPUT_LINE_RESET, (m_modifiers->read() & 0x06) != 0x00 ? CLEAR_LINE : ASSERT_LINE);
reset_from_keyboard((m_modifiers->read() & 0x06) != 0x00);
}
static INPUT_PORTS_START(he191_3425)
PORT_START("B1")
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(DEL_PAD)) PORT_CODE(KEYCODE_DEL_PAD)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) PORT_CODE(KEYCODE_0_PAD)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('`') PORT_CHAR('~') PORT_CODE(KEYCODE_BACKSLASH)
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_CHAR('o') PORT_CHAR('O') PORT_CODE(KEYCODE_O)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(';') PORT_CHAR(':') PORT_CODE(KEYCODE_COLON)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('/') PORT_CHAR('?') PORT_CODE(KEYCODE_SLASH)
PORT_START("B2")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 3 DL") PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) PORT_CODE(KEYCODE_3_PAD)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) PORT_CODE(KEYCODE_2_PAD)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 1 IL") PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) PORT_CODE(KEYCODE_1_PAD)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F9)) PORT_CODE(KEYCODE_F9)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('9') PORT_CHAR('(') PORT_CODE(KEYCODE_9)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('i') PORT_CHAR('I') PORT_CODE(KEYCODE_I)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('l') PORT_CHAR('L') PORT_CODE(KEYCODE_L)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('.') PORT_CHAR('>') PORT_CODE(KEYCODE_STOP)
PORT_START("B3")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) PORT_CODE(KEYCODE_6_PAD)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) PORT_CODE(KEYCODE_5_PAD)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) PORT_CODE(KEYCODE_4_PAD)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F8)) PORT_CODE(KEYCODE_F8)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('8') PORT_CHAR('*') PORT_CODE(KEYCODE_8)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('u') PORT_CHAR('U') PORT_CODE(KEYCODE_U)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('k') PORT_CHAR('K') PORT_CODE(KEYCODE_K)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(',') PORT_CHAR('<') PORT_CODE(KEYCODE_COMMA)
PORT_START("B4")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 9 DC") PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) PORT_CODE(KEYCODE_9_PAD)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) PORT_CODE(KEYCODE_8_PAD)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 7 IC") PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) PORT_CODE(KEYCODE_7_PAD)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F7)) PORT_CODE(KEYCODE_F7)
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_CHAR('y') PORT_CHAR('Y') PORT_CODE(KEYCODE_Y)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('j') PORT_CHAR('J') PORT_CODE(KEYCODE_J)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('m') PORT_CHAR('M') PORT_CODE(KEYCODE_M)
PORT_START("B5")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Help") PORT_CODE(KEYCODE_F10)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Line Feed") PORT_CHAR(0x0a) PORT_CODE(KEYCODE_RALT)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Space Bar") PORT_CHAR(' ') PORT_CODE(KEYCODE_SPACE)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F6)) PORT_CODE(KEYCODE_F6)
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_CHAR('t') PORT_CHAR('T') PORT_CODE(KEYCODE_T)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('h') PORT_CHAR('H') PORT_CODE(KEYCODE_H)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('n') PORT_CHAR('N') PORT_CODE(KEYCODE_N)
PORT_START("B6")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\\') PORT_CHAR('|') PORT_CODE(KEYCODE_RCONTROL) // to right of Return key
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") PORT_CHAR(0x0d) PORT_CODE(KEYCODE_ENTER)
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_CHAR(UCHAR_MAMEKEY(F5)) PORT_CODE(KEYCODE_F5)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('5') PORT_CHAR('%') PORT_CODE(KEYCODE_5)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('r') PORT_CHAR('R') PORT_CODE(KEYCODE_R)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('g') PORT_CHAR('G') PORT_CODE(KEYCODE_G)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('b') PORT_CHAR('B') PORT_CODE(KEYCODE_B)
PORT_START("B7")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(']') PORT_CHAR('}') PORT_CODE(KEYCODE_CLOSEBRACE)
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('p') PORT_CHAR('P') PORT_CODE(KEYCODE_P)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F4)) PORT_CODE(KEYCODE_F4)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('4') PORT_CHAR('$') PORT_CODE(KEYCODE_4)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('e') PORT_CHAR('E') PORT_CODE(KEYCODE_E)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('f') PORT_CHAR('F') PORT_CODE(KEYCODE_F)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('v') PORT_CHAR('V') PORT_CODE(KEYCODE_V)
PORT_START("B8")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Delete") PORT_CHAR(UCHAR_MAMEKEY(DEL)) PORT_CODE(KEYCODE_DEL) // to right of `/~ key
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(HOME)) PORT_CODE(KEYCODE_F11)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_CODE(KEYCODE_DOWN) // between +/= and Back Space keys
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F3)) PORT_CODE(KEYCODE_F3)
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_CHAR('w') PORT_CHAR('W') PORT_CODE(KEYCODE_W)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('d') PORT_CHAR('D') PORT_CODE(KEYCODE_D)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('c') PORT_CHAR('C') PORT_CODE(KEYCODE_C)
PORT_START("B9")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Back Space") PORT_CHAR(0x08) PORT_CODE(KEYCODE_BACKSPACE)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('=') PORT_CHAR('+') PORT_CODE(KEYCODE_EQUALS)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('-') PORT_CHAR('_') PORT_CODE(KEYCODE_MINUS)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F2)) PORT_CODE(KEYCODE_F2)
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_CHAR('q') PORT_CHAR('Q') PORT_CODE(KEYCODE_Q)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('s') PORT_CHAR('S') PORT_CODE(KEYCODE_S)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('x') PORT_CHAR('X') PORT_CODE(KEYCODE_X)
PORT_START("B11")
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(LEFT)) PORT_CODE(KEYCODE_LEFT) // to right of Home key
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_CODE(KEYCODE_F1)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('1') PORT_CHAR('!') PORT_CODE(KEYCODE_1)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Tab") PORT_CHAR('\t') PORT_CODE(KEYCODE_TAB)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('a') PORT_CHAR('A') PORT_CODE(KEYCODE_A)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('z') PORT_CHAR('Z') PORT_CODE(KEYCODE_Z)
PORT_START("B13")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(COMMA_PAD)) PORT_CODE(KEYCODE_PLUS_PAD)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PORT_CODE(KEYCODE_MINUS_PAD)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("No Scroll") PORT_CODE(KEYCODE_LALT)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Set Up") PORT_CODE(KEYCODE_ESC)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CHAR(0x1b) PORT_CODE(KEYCODE_TILDE)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Erase") PORT_CODE(KEYCODE_F12)
PORT_START("B14")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_CODE(KEYCODE_CAPSLOCK)
PORT_BIT(0xfe, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_START("MODIFIERS")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ctrl") PORT_CHAR(UCHAR_SHIFT_2) PORT_CODE(KEYCODE_LCONTROL)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Shift") PORT_CHAR(UCHAR_SHIFT_1) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_WRITE_LINE_MEMBER(he191_3425_device, shift_reset)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Break Reset") PORT_CODE(KEYCODE_PAUSE) PORT_WRITE_LINE_MEMBER(he191_3425_device, shift_reset) // to right of Back Space key
PORT_BIT(0xf8, IP_ACTIVE_LOW, IPT_UNUSED)
INPUT_PORTS_END
ioport_constructor he191_3425_device::device_input_ports() const
{
return INPUT_PORTS_NAME(he191_3425);
}
void he191_3425_device::device_add_mconfig(machine_config &config)
{
i8021_device &mcu(I8021(config, m_mcu, 3.579545_MHz_XTAL));
mcu.bus_in_cb().set(FUNC(he191_3425_device::mcu_pa_r));
mcu.p1_in_cb().set_ioport("MODIFIERS");
mcu.p1_out_cb().set(FUNC(he191_3425_device::mcu_pb_w));
mcu.p2_out_cb().set(FUNC(he191_3425_device::mcu_pc_w));
mcu.t1_in_cb().set(FUNC(he191_3425_device::mcu_t1_r));
SPEAKER(config, "speaker").front_center();
BEEP(config, m_buzzer, 1'000'000'000 / PERIOD_OF_555_ASTABLE_NSEC(RES_R(510), RES_R(510), CAP_U(1)));
m_buzzer->add_route(ALL_OUTPUTS, "speaker", 1.0);
}
ROM_START(he191_3425)
ROM_REGION(0x400, "mcu", ROMREGION_ERASE00)
ROM_LOAD("p8021h-2155_444-100.z1", 0x000, 0x400, NO_DUMP)
ROM_END
const tiny_rom_entry *he191_3425_device::device_rom_region() const
{
return ROM_NAME(he191_3425);
}

View File

@ -0,0 +1,58 @@
// license:BSD-3-Clause
// copyright-holders:AJR
#ifndef MAME_BUS_Z29_KBD_HE191_3425_H
#define MAME_BUS_Z29_KBD_HE191_3425_H
#pragma once
#include "bus/z29_kbd/keyboard.h"
#include "sound/beep.h"
class he191_3425_device : public device_t, public device_z29_keyboard_interface
{
public:
// device type constructor
he191_3425_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// miscellanous handlers
DECLARE_WRITE_LINE_MEMBER(shift_reset);
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;
// device_z29_keyboard_interface overrides
virtual void receive_data(bool state) override;
private:
// MCU port handlers
u8 mcu_pa_r();
void mcu_pb_w(u8 data);
void mcu_pc_w(u8 data);
DECLARE_READ_LINE_MEMBER(mcu_t1_r);
// misc. helpers
TIMER_CALLBACK_MEMBER(receive_data_synced);
// object finders
required_device<cpu_device> m_mcu;
required_device<beep_device> m_buzzer;
required_ioport_array<12> m_matrix;
required_ioport m_modifiers;
output_finder<4> m_leds;
// internal state
u8 m_select;
bool m_recv_data;
};
// device type declaration
DECLARE_DEVICE_TYPE(HE191_3425, he191_3425_device)
#endif // MAME_BUS_Z29_KBD_HE191_3425_H

View File

@ -0,0 +1,117 @@
// license:BSD-3-Clause
// copyright-holders:AJR
/***************************************************************************
Zenith Z-29 keyboard port
This supports the custom serial interface for the H-29/Z-29 and other
early Heath/Zenith terminals with detachable keyboards. (Keyboards for
later Zenith terminals such as the Z-49 use a standard asynchronous
serial protocol.)
All printable characters outside of the numeric keypad use standard
ASCII codes, as do Back Space, Line Feed, Return, Esc and Del. The
following codes are assigned to other keys:
80 Up
81 Down
82 Left
83 Right
84 Home
85 Erase
86 Help
87 No Scroll
88 Set Up
89 Break
8A Caps Lock
8B Tab
8C Space Bar
8F (Power On)
90 0 (Keypad)
91 1 (Keypad)
92 2 (Keypad)
93 3 (Keypad)
94 4 (Keypad)
95 5 (Keypad)
96 6 (Keypad)
97 7 (Keypad)
98 8 (Keypad)
99 9 (Keypad)
9A . (Keypad)
9B Enter (Keypad)
9C - (Keypad)
9D , (Keypad)
9F 80 F1
9F 81 F2
9F 82 F3
9F 83 F4
9F 84 F5
9F 85 F6
9F 86 F7
9F 87 F8
9F 88 F9
Bit 6 is set in these codes when pressed with Shift, and bit 5 when
pressed with Ctrl.
***************************************************************************/
#include "emu.h"
#include "keyboard.h"
#include "he191_3425.h"
#include "md_kbd.h"
//**************************************************************************
// Z-29 KEYBOARD PORT DEVICE
//**************************************************************************
DEFINE_DEVICE_TYPE(Z29_KEYBOARD, z29_keyboard_port_device, "z29_kbd", "Z-29 Keyboard Port")
z29_keyboard_port_device::z29_keyboard_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, Z29_KEYBOARD, tag, owner, clock)
, device_single_card_slot_interface<device_z29_keyboard_interface>(mconfig, *this)
, m_keyin_callback(*this)
, m_reset_callback(*this)
, m_kbd(nullptr)
{
}
void z29_keyboard_port_device::device_config_complete()
{
m_kbd = get_card_device();
}
void z29_keyboard_port_device::device_resolve_objects()
{
m_keyin_callback.resolve_safe();
m_reset_callback.resolve_safe();
}
void z29_keyboard_port_device::device_start()
{
}
//**************************************************************************
// Z-29 KEYBOARD INTERFACE
//**************************************************************************
device_z29_keyboard_interface::device_z29_keyboard_interface(const machine_config &mconfig, device_t &device)
: device_interface(device, "z29kbd")
, m_port(device, DEVICE_SELF_OWNER)
{
}
device_z29_keyboard_interface::~device_z29_keyboard_interface()
{
}
//**************************************************************************
// KEYBOARD OPTIONS
//**************************************************************************
void z29_keyboards(device_slot_interface &slot)
{
slot.option_add("heath", HE191_3425);
slot.option_add("md", MD_KEYBOARD);
}

View File

@ -0,0 +1,104 @@
// license:BSD-3-Clause
// copyright-holders:AJR
/***************************************************************************
Zenith Z-29 keyboard port
***************************************************************************/
#ifndef MAME_BUS_Z29_KBD_KEYBOARD_H
#define MAME_BUS_Z29_KBD_KEYBOARD_H
#pragma once
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// forward declaration
class device_z29_keyboard_interface;
// ======================> z29_keyboard_port_device
class z29_keyboard_port_device : public device_t, public device_single_card_slot_interface<device_z29_keyboard_interface>
{
friend class device_z29_keyboard_interface;
public:
// construction/destruction
z29_keyboard_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
template <typename T>
z29_keyboard_port_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt)
: z29_keyboard_port_device(mconfig, tag, owner, 0U)
{
option_reset();
opts(*this);
set_default_option(dflt);
set_fixed(false);
}
// callback configuration
auto keyin_callback() { return m_keyin_callback.bind(); }
auto reset_callback() { return m_reset_callback.bind(); }
// line handler
inline DECLARE_WRITE_LINE_MEMBER(keyout_w);
protected:
// device-level overrides
virtual void device_config_complete() override;
virtual void device_resolve_objects() override;
virtual void device_start() override;
// called from keyboard
void transmit_data(bool state) { m_keyin_callback(state); }
void reset_from_keyboard(bool state) { m_reset_callback(state); }
private:
// line callbacks
devcb_write_line m_keyin_callback;
devcb_write_line m_reset_callback;
// selected keyboard
device_z29_keyboard_interface *m_kbd;
};
// ======================> device_z29_keyboard_interface
class device_z29_keyboard_interface : public device_interface
{
friend class z29_keyboard_port_device;
protected:
// construction/destruction
device_z29_keyboard_interface(const machine_config &mconfig, device_t &device);
virtual ~device_z29_keyboard_interface();
void transmit_data(bool state) { m_port->transmit_data(state); }
void reset_from_keyboard(bool state) { m_port->reset_from_keyboard(state); }
virtual void receive_data(bool state) = 0;
private:
// parent port
required_device<z29_keyboard_port_device> m_port;
};
// device type definition
DECLARE_DEVICE_TYPE(Z29_KEYBOARD, z29_keyboard_port_device)
// standard options
extern void z29_keyboards(device_slot_interface &slot);
//**************************************************************************
// INLINE FUNCTIONS
//**************************************************************************
WRITE_LINE_MEMBER(z29_keyboard_port_device::keyout_w)
{
if (m_kbd != nullptr)
m_kbd->receive_data(state);
}
#endif // MAME_BUS_Z29_KBD_KEYBOARD_H

View File

@ -0,0 +1,277 @@
// license:BSD-3-Clause
// copyright-holders:AJR
/***************************************************************************
Micro-Decision keyboard
This 93-key keyboard was obtained with a Morrow MD3-P. The unit part
number is unknown, but "DEKU-0224-PHM-B" and "I/F PCB FOR 14515B" are
silkscreened on the component board.
Like the original Z-29 keyboard, it may also have been designed by
Heath/Zenith. It is missing the Erase, Set Up and Break keys (though
the first two are still recognized by the program), but has five
additional function keys instead.
Some clumsy coding suggests that the program was originally designed
for an 8048 operating in single-chip mode, with the 14515B and LS175
having being added to latch outputs also sent to the upper half of
Port 2.
***************************************************************************/
#include "emu.h"
#include "md_kbd.h"
#include "machine/rescap.h"
#include "speaker.h"
DEFINE_DEVICE_TYPE(MD_KEYBOARD, md_keyboard_device, "md_kbd", "Micro-Decision Keyboard")
md_keyboard_device::md_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, MD_KEYBOARD, tag, owner, clock)
, device_z29_keyboard_interface(mconfig, *this)
, m_mcu(*this, "mcu")
, m_buzzer(*this, "buzzer")
, m_matrix(*this, "S%u", 0U)
, m_leds(*this, "led%u", 1U)
, m_14515b_select(0)
, m_ls175_clock(true)
, m_recv_data(true)
{
}
void md_keyboard_device::device_resolve_objects()
{
m_leds.resolve();
}
void md_keyboard_device::device_start()
{
save_item(NAME(m_14515b_select));
save_item(NAME(m_ls175_clock));
save_item(NAME(m_recv_data));
}
void md_keyboard_device::device_reset()
{
ls175_w(0);
}
void md_keyboard_device::receive_data(bool state)
{
machine().scheduler().synchronize(timer_expired_delegate(FUNC(md_keyboard_device::receive_data_synced), this), state);
}
TIMER_CALLBACK_MEMBER(md_keyboard_device::receive_data_synced)
{
m_recv_data = param;
}
void md_keyboard_device::ls175_w(u8 data)
{
m_leds[0] = !BIT(data, 7); // Caps Lock
m_leds[1] = !BIT(data, 5); // Keyboard lock?
m_buzzer->set_state(BIT(data, 6));
}
u8 md_keyboard_device::mcu_p1_r()
{
return 0xc0 | m_matrix[m_14515b_select]->read();
}
void md_keyboard_device::mcu_p1_w(u8 data)
{
transmit_data(!BIT(data, 7));
if (!m_ls175_clock && BIT(data, 6))
ls175_w(m_mcu->p2_r());
m_ls175_clock = BIT(data, 6);
}
READ_LINE_MEMBER(md_keyboard_device::mcu_t1_r)
{
return m_recv_data;
}
void md_keyboard_device::mcu_movx_w(u8 data)
{
m_14515b_select = (data >> 4) & 0x0f;
}
void md_keyboard_device::prog_map(address_map &map)
{
map(0x000, 0xfff).rom().region("program", 0);
}
void md_keyboard_device::ext_map(address_map &map)
{
map(0x00, 0x00).mirror(0xff).w(FUNC(md_keyboard_device::mcu_movx_w));
}
static INPUT_PORTS_START(md_kbd)
PORT_START("S0")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('q') PORT_CHAR('Q') PORT_CODE(KEYCODE_Q)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('g') PORT_CHAR('G') PORT_CODE(KEYCODE_G)
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_CHAR(UCHAR_MAMEKEY(0_PAD)) PORT_CODE(KEYCODE_0_PAD)
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("Erase") // not actually on keyboard?
PORT_START("S1")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('w') PORT_CHAR('W') PORT_CODE(KEYCODE_W)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('b') PORT_CHAR('B') PORT_CODE(KEYCODE_B)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(']') PORT_CHAR('}') PORT_CODE(KEYCODE_CLOSEBRACE)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) PORT_CODE(KEYCODE_9_PAD)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('9') PORT_CHAR('(') PORT_CODE(KEYCODE_9)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Help") PORT_CODE(KEYCODE_F12)
PORT_START("S2")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('e') PORT_CHAR('E') PORT_CODE(KEYCODE_E)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('n') PORT_CHAR('N') PORT_CODE(KEYCODE_N)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('[') PORT_CHAR('{') PORT_CODE(KEYCODE_OPENBRACE)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) PORT_CODE(KEYCODE_8_PAD)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('8') PORT_CHAR('*') PORT_CODE(KEYCODE_8)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Home Clear") PORT_CHAR(UCHAR_MAMEKEY(HOME)) PORT_CODE(KEYCODE_F11)
PORT_START("S3")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('r') PORT_CHAR('R') PORT_CODE(KEYCODE_R)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('m') PORT_CHAR('M') PORT_CODE(KEYCODE_M)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('-') PORT_CHAR('_') PORT_CODE(KEYCODE_MINUS)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) PORT_CODE(KEYCODE_7_PAD)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('7') PORT_CHAR('&') PORT_CODE(KEYCODE_7)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_START("S4")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('f') PORT_CHAR('F') PORT_CODE(KEYCODE_F)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('l') PORT_CHAR('L') PORT_CODE(KEYCODE_L)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('=') PORT_CHAR('+') PORT_CODE(KEYCODE_EQUALS)
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('6') PORT_CHAR('^') PORT_CODE(KEYCODE_6)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("No Scroll") PORT_CODE(KEYCODE_ESC)
PORT_START("S5")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('d') PORT_CHAR('D') PORT_CODE(KEYCODE_D)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('k') PORT_CHAR('K') PORT_CODE(KEYCODE_K)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('`') PORT_CHAR('~') PORT_CODE(KEYCODE_BACKSLASH) // to right of +/=
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('5') PORT_CHAR('%') PORT_CODE(KEYCODE_5)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Caps Lock") PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_CODE(KEYCODE_CAPSLOCK)
PORT_START("S6")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('s') PORT_CHAR('S') PORT_CODE(KEYCODE_S)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('j') PORT_CHAR('J') PORT_CODE(KEYCODE_J)
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_CHAR(UCHAR_MAMEKEY(4_PAD)) PORT_CODE(KEYCODE_4_PAD)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('4') PORT_CHAR('$') PORT_CODE(KEYCODE_4)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Del") PORT_CHAR(UCHAR_MAMEKEY(DEL)) PORT_CODE(KEYCODE_DEL)
PORT_START("S7")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('a') PORT_CHAR('A') PORT_CODE(KEYCODE_A)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('h') PORT_CHAR('H') PORT_CODE(KEYCODE_H)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('p') PORT_CHAR('P') PORT_CODE(KEYCODE_P)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) PORT_CODE(KEYCODE_3_PAD)
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_CHAR(UCHAR_MAMEKEY(UP)) PORT_CODE(KEYCODE_UP)
PORT_START("S8")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('z') PORT_CHAR('Z') PORT_CODE(KEYCODE_Z)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('t') PORT_CHAR('T') PORT_CODE(KEYCODE_T)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('o') PORT_CHAR('O') PORT_CODE(KEYCODE_O)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) PORT_CODE(KEYCODE_2_PAD)
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_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_CODE(KEYCODE_DOWN)
PORT_START("S9")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('x') PORT_CHAR('X') PORT_CODE(KEYCODE_X)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('y') PORT_CHAR('Y') PORT_CODE(KEYCODE_Y)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\\') PORT_CHAR('|') PORT_CODE(KEYCODE_RCONTROL)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) PORT_CODE(KEYCODE_1_PAD)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('1') PORT_CHAR('!') PORT_CODE(KEYCODE_1)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_CODE(KEYCODE_RIGHT)
PORT_START("S10")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('c') PORT_CHAR('C') PORT_CODE(KEYCODE_C)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('u') PORT_CHAR('U') PORT_CODE(KEYCODE_U)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(',') PORT_CHAR('<') PORT_CODE(KEYCODE_COMMA)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(COMMA_PAD)) PORT_CODE(KEYCODE_PLUS_PAD)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CHAR(0x1b) PORT_CODE(KEYCODE_TILDE)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PORT_CODE(KEYCODE_LEFT)
PORT_START("S11")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('v') PORT_CHAR('V') PORT_CODE(KEYCODE_V)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('i') PORT_CHAR('I') PORT_CODE(KEYCODE_I)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('.') PORT_CHAR('>') PORT_CODE(KEYCODE_STOP)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) PORT_CODE(KEYCODE_DEL_PAD)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Tab") PORT_CHAR('\t') PORT_CODE(KEYCODE_TAB)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('/') PORT_CHAR('?') PORT_CODE(KEYCODE_SLASH)
PORT_START("S12")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(' ') PORT_CODE(KEYCODE_SPACE)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") PORT_CHAR(0x0d) PORT_CODE(KEYCODE_ENTER)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad Enter +") PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) PORT_CODE(KEYCODE_ENTER_PAD)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PORT_CODE(KEYCODE_MINUS_PAD)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Line Feed") PORT_CHAR(0x0a) PORT_CODE(KEYCODE_RALT)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Back Space") PORT_CHAR(0x08) PORT_CODE(KEYCODE_BACKSPACE)
PORT_START("S13")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_CODE(KEYCODE_F1)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F2)) PORT_CODE(KEYCODE_F2)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F3)) PORT_CODE(KEYCODE_F3)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F4)) PORT_CODE(KEYCODE_F4)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F5)) PORT_CODE(KEYCODE_F5)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F6)) PORT_CODE(KEYCODE_F6)
PORT_START("S14")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F7)) PORT_CODE(KEYCODE_F7)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F8)) PORT_CODE(KEYCODE_F8)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F9)) PORT_CODE(KEYCODE_F9)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F10)) PORT_CODE(KEYCODE_F10)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("FA") PORT_CHAR(UCHAR_MAMEKEY(F11))
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("FB") PORT_CHAR(UCHAR_MAMEKEY(F12))
PORT_START("S15")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
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("Setup") // not actually on keyboard?
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("FD") PORT_CHAR(UCHAR_MAMEKEY(F14))
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("FC") PORT_CHAR(UCHAR_MAMEKEY(F13))
PORT_START("MODIFIERS")
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ctrl") PORT_CHAR(UCHAR_SHIFT_2) PORT_CODE(KEYCODE_LCONTROL)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Shift") PORT_CHAR(UCHAR_SHIFT_1) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT)
INPUT_PORTS_END
ioport_constructor md_keyboard_device::device_input_ports() const
{
return INPUT_PORTS_NAME(md_kbd);
}
void md_keyboard_device::device_add_mconfig(machine_config &config)
{
// U4 is M5L8048-052P (internal ROM likely unused), but location is silkscreened "8035"
I8035(config, m_mcu, 3.579545_MHz_XTAL); // "CSA 3 58MT" resonator
m_mcu->set_addrmap(AS_PROGRAM, &md_keyboard_device::prog_map);
m_mcu->set_addrmap(AS_IO, &md_keyboard_device::ext_map);
m_mcu->p1_in_cb().set(FUNC(md_keyboard_device::mcu_p1_r));
m_mcu->p1_out_cb().set(FUNC(md_keyboard_device::mcu_p1_w));
m_mcu->p2_in_cb().set_ioport("MODIFIERS");
m_mcu->t1_in_cb().set(FUNC(md_keyboard_device::mcu_t1_r));
SPEAKER(config, "speaker").front_center();
BEEP(config, m_buzzer, 1'000'000'000 / PERIOD_OF_555_ASTABLE_NSEC(RES_R(510), RES_R(510), CAP_U(1)));
m_buzzer->add_route(ALL_OUTPUTS, "speaker", 1.0);
}
ROM_START(md_kbd)
ROM_REGION(0x1000, "program", 0)
ROM_LOAD("kb-rom_rev_3.4_27d4.u5", 0x0000, 0x1000, CRC(c34b606b) SHA1(20cf62fc31257b6c3e767152086f2604fead97bd)) // location marked "2716/2732"
ROM_END
const tiny_rom_entry *md_keyboard_device::device_rom_region() const
{
return ROM_NAME(md_kbd);
}

View File

@ -0,0 +1,61 @@
// license:BSD-3-Clause
// copyright-holders:AJR
#ifndef MAME_BUS_Z29_KBD_MD_KBD_H
#define MAME_BUS_Z29_KBD_MD_KBD_H
#pragma once
#include "keyboard.h"
#include "cpu/mcs48/mcs48.h"
#include "sound/beep.h"
class md_keyboard_device : public device_t, public device_z29_keyboard_interface
{
public:
// device type constructor
md_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
// device-level overrides
virtual void device_resolve_objects() override;
virtual void device_start() override;
virtual void device_reset() 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;
// device_z29_keyboard_interface overrides
virtual void receive_data(bool state) override;
private:
// MCU handlers
u8 mcu_p1_r();
void mcu_p1_w(u8 data);
DECLARE_READ_LINE_MEMBER(mcu_t1_r);
void mcu_movx_w(u8 data);
// misc. helpers
TIMER_CALLBACK_MEMBER(receive_data_synced);
void ls175_w(u8 data);
// address maps
void prog_map(address_map &map);
void ext_map(address_map &map);
// object finders
required_device<mcs48_cpu_device> m_mcu;
required_device<beep_device> m_buzzer;
required_ioport_array<16> m_matrix;
output_finder<2> m_leds;
// internal state
u8 m_14515b_select;
bool m_ls175_clock;
bool m_recv_data;
};
// device type declaration
DECLARE_DEVICE_TYPE(MD_KEYBOARD, md_keyboard_device)
#endif // MAME_BUS_Z29_KBD_MD_KBD_H

View File

@ -2,58 +2,41 @@
// copyright-holders:AJR
/**************************************************************************
Skeleton driver for MDT 60 and related Zenith terminals.
MDT 60 was designed by Zenith for use with Morrow's Micro-Decision
computers as a low-cost terminal with limited features. It appears
to be a stripped-down version of some previously designed terminal,
with the auxiliary port omitted from the Morrow version even though
the schematics published by Morrow include it. Morrow's schematics
also include the same keyboard used by the Z-29, though the actual
keyboard found with one unit was different.
the schematics published in its service manual include it. These
schematics also include the same keyboard used by the Z-29, though
the actual keyboard found with one unit was different.
**************************************************************************/
#include "emu.h"
#include "bus/rs232/rs232.h"
#include "bus/z29_kbd/keyboard.h"
#include "cpu/m6502/m6502.h"
#include "machine/eepromser.h"
#include "machine/i8251.h"
#include "machine/pit8253.h"
#include "video/mc6845.h"
#include "screen.h"
class mdt60_base_state : public driver_device
{
public:
mdt60_base_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_crtc(*this, "crtc")
, m_uart(*this, "uart%u", 0U)
, m_charram(*this, "charram")
{
}
protected:
MC6845_ON_UPDATE_ADDR_CHANGED(update_cb);
required_device<cpu_device> m_maincpu;
required_device<r6545_1_device> m_crtc;
optional_device_array<i8251_device, 2> m_uart;
required_shared_ptr<u8> m_charram;
};
class mdt60_state : public mdt60_base_state
class mdt60_state : public driver_device
{
public:
mdt60_state(const machine_config &mconfig, device_type type, const char *tag)
: mdt60_base_state(mconfig, type, tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_keyboard(*this, "keyboard")
, m_crtc(*this, "crtc")
, m_uart(*this, "uart%u", 0U)
, m_charram(*this, "charram")
, m_charrom(*this, "charrom")
, m_attrram(*this, "attrram")
, m_dip0(*this, "DIP0")
, m_baud_timer(nullptr)
, m_keyin(false)
, m_reverse(false)
, m_output_reg(0x3f)
, m_timer_output(false)
{
}
@ -65,6 +48,8 @@ protected:
private:
MC6845_UPDATE_ROW(update_row);
MC6845_ON_UPDATE_ADDR_CHANGED(update_cb);
TIMER_CALLBACK_MEMBER(baud_timer);
DECLARE_WRITE_LINE_MEMBER(keyin_w);
u8 dip0_r(offs_t offset);
@ -72,54 +57,30 @@ private:
void mem_map(address_map &map);
required_device<cpu_device> m_maincpu;
required_device<z29_keyboard_port_device> m_keyboard;
required_device<r6545_1_device> m_crtc;
optional_device_array<i8251_device, 2> m_uart;
required_shared_ptr<u8> m_charram;
required_region_ptr<u8> m_charrom;
required_shared_ptr<u8> m_attrram;
required_ioport m_dip0;
emu_timer *m_baud_timer;
bool m_keyin;
bool m_reverse;
};
class z22_state : public mdt60_base_state
{
public:
z22_state(const machine_config &mconfig, device_type type, const char *tag)
: mdt60_base_state(mconfig, type, tag)
, m_eeprom(*this, "eeprom")
, m_fontram(*this, "fontram")
, m_eeprom_clk(false)
{
}
void z22(machine_config &config);
protected:
virtual void machine_start() override;
private:
MC6845_UPDATE_ROW(update_row);
u8 status_r();
void control_w(u8 data);
DECLARE_WRITE_LINE_MEMBER(eeprom_clock_w);
void mem_map(address_map &map);
required_device<eeprom_serial_93cxx_device> m_eeprom;
required_shared_ptr<u8> m_fontram;
bool m_eeprom_clk;
u8 m_output_reg;
bool m_timer_output;
};
void mdt60_state::machine_start()
{
save_item(NAME(m_keyin));
save_item(NAME(m_reverse));
}
m_baud_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mdt60_state::baud_timer), this));
m_baud_timer->adjust(attotime::zero);
void z22_state::machine_start()
{
save_item(NAME(m_eeprom_clk));
save_item(NAME(m_keyin));
save_item(NAME(m_output_reg));
save_item(NAME(m_timer_output));
}
void mdt60_state::machine_reset()
@ -128,6 +89,23 @@ void mdt60_state::machine_reset()
}
TIMER_CALLBACK_MEMBER(mdt60_state::baud_timer)
{
m_timer_output = !m_timer_output;
// LS352 multiplexer has inverting outputs
m_uart[0]->write_rxc(!m_timer_output);
m_uart[0]->write_txc(!m_timer_output);
constexpr auto time_base = 16.5888_MHz_XTAL / 9;
if ((m_output_reg & 0x06) == 0x00)
m_baud_timer->adjust(attotime::from_ticks(m_timer_output ? 2 : 4, time_base));
else if ((m_output_reg & 0x06) == 0x06)
m_baud_timer->adjust(attotime::from_ticks(48, time_base));
else
m_baud_timer->adjust(attotime::from_ticks(3 * (m_output_reg & 0x06), time_base));
}
MC6845_UPDATE_ROW(mdt60_state::update_row)
{
u32 *pix = &bitmap.pix32(y);
@ -147,7 +125,7 @@ MC6845_UPDATE_ROW(mdt60_state::update_row)
rgb_t fg = BIT(adata, 1) ? rgb_t::white() : rgb_t(0xc0, 0xc0, 0xc0);
rgb_t bg = rgb_t::black();
if (m_reverse)
if (BIT(m_output_reg, 5))
std::swap(fg, bg);
for (int n = 8; n >= 0; n--)
@ -155,27 +133,7 @@ MC6845_UPDATE_ROW(mdt60_state::update_row)
}
}
MC6845_UPDATE_ROW(z22_state::update_row)
{
u32 *pix = &bitmap.pix32(y);
for (unsigned x = 0; x < x_count; x++)
{
u8 cdata = m_charram[(ma + x) & 0x7ff];
u16 dots = m_fontram[(cdata & 0x7f) << 4 | ra] << 1;
if (x == cursor_x)
dots = ~dots;
rgb_t fg = rgb_t::white();
rgb_t bg = rgb_t::black();
for (int n = 8; n >= 0; n--)
*pix++ = BIT(dots, n) ? fg : bg;
}
}
MC6845_ON_UPDATE_ADDR_CHANGED(mdt60_base_state::update_cb)
MC6845_ON_UPDATE_ADDR_CHANGED(mdt60_state::update_cb)
{
}
@ -190,9 +148,9 @@ u8 mdt60_state::dip0_r(offs_t offset)
{
u8 buffer = 0xff;
if (!BIT(offset, 0))
buffer &= m_dip0->read() | 0x80;
buffer &= m_dip0->read() >> 1 | 0x80;
if (!BIT(offset, 1))
buffer &= m_dip0->read() >> 7 | 0xfe;
buffer &= m_dip0->read() | 0xfe;
if (!m_keyin)
buffer &= 0x7f;
return buffer;
@ -200,29 +158,11 @@ u8 mdt60_state::dip0_r(offs_t offset)
void mdt60_state::reg_w(u8 data)
{
//m_keyboard->keyout_w(BIT(data, 0));
m_reverse = BIT(data, 5);
}
if (BIT(data, 0) != BIT(m_output_reg, 0))
m_keyboard->keyout_w(BIT(data, 0));
u8 z22_state::status_r()
{
u8 result = 0;
if (m_eeprom_clk)
result |= 0x02;
if (!m_eeprom->do_read())
result |= 0x01;
return result;
}
void z22_state::control_w(u8 data)
{
m_eeprom->di_write(!BIT(data, 7));
m_eeprom->cs_write(BIT(data, 6));
}
WRITE_LINE_MEMBER(z22_state::eeprom_clock_w)
{
m_eeprom_clk = state;
// Bits 12 & 34 select 1 of 4 baud rates for each UART; bit 5 selects inverse video
m_output_reg = data & 0x3f;
}
void mdt60_state::mem_map(address_map &map)
@ -240,23 +180,9 @@ void mdt60_state::mem_map(address_map &map)
map(0xe000, 0xefff).mirror(0x1000).rom().region("coderom", 0);
}
void z22_state::mem_map(address_map &map)
{
map(0x0000, 0x07ff).ram();
map(0x2000, 0x27ff).ram().share("charram");
map(0x4000, 0x4001).rw(m_uart[1], FUNC(i8251_device::read), FUNC(i8251_device::write));
map(0x6000, 0x67ff).ram().share("fontram");
map(0x8000, 0x8001).rw(m_uart[0], FUNC(i8251_device::read), FUNC(i8251_device::write));
map(0x8800, 0x8800).rw(m_crtc, FUNC(r6545_1_device::status_r), FUNC(r6545_1_device::address_w));
map(0x8801, 0x8801).rw(m_crtc, FUNC(r6545_1_device::register_r), FUNC(r6545_1_device::register_w));
map(0x9000, 0x9003).w("pit", FUNC(pit8254_device::write));
map(0xa000, 0xa000).rw(FUNC(z22_state::status_r), FUNC(z22_state::control_w));
map(0xc000, 0xffff).rom().region("program", 0);
}
static INPUT_PORTS_START(mdt60)
PORT_START("DIP0") // TODO: verify bit assignments
PORT_START("DIP0")
PORT_DIPNAME(0x03, 0x01, "Baud Rate") PORT_DIPLOCATION("SW1:1,2")
PORT_DIPSETTING(0x03, "300")
PORT_DIPSETTING(0x02, "1200")
@ -284,9 +210,6 @@ static INPUT_PORTS_START(mdt60)
PORT_BIT(0xff, 0xff, IPT_UNUSED) // SW2 is unpopulated
INPUT_PORTS_END
static INPUT_PORTS_START(z22)
INPUT_PORTS_END
// XTAL frequency is specified as 16.589 MHz on actual parts as well as in MDT 60 schematics.
// This has been assumed to be a lower-precision specification of the common 16.5888 MHz value.
@ -297,12 +220,15 @@ void mdt60_state::mdt60(machine_config &config)
I8251(config, m_uart[0], 16.5888_MHz_XTAL / 9); // TMP8251AP (U19)
m_uart[0]->rxrdy_handler().set_inputline(m_maincpu, m6512_device::NMI_LINE);
m_uart[0]->txd_handler().set("computer", FUNC(rs232_port_device::write_txd));
m_uart[0]->dtr_handler().set("computer", FUNC(rs232_port_device::write_dtr));
m_uart[0]->rts_handler().set("computer", FUNC(rs232_port_device::write_rts));
m_uart[0]->txd_handler().set("comm", FUNC(rs232_port_device::write_txd));
m_uart[0]->dtr_handler().set("comm", FUNC(rs232_port_device::write_dtr));
m_uart[0]->rts_handler().set("comm", FUNC(rs232_port_device::write_rts));
// UART 1 (at U28) is unpopulated and not used by code
Z29_KEYBOARD(config, m_keyboard, z29_keyboards, "md");
m_keyboard->keyin_callback().set(FUNC(mdt60_state::keyin_w)).invert();
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_color(rgb_t::amber());
screen.set_raw(16.5888_MHz_XTAL, 918, 0, 720, 301, 0, 288);
@ -314,54 +240,10 @@ void mdt60_state::mdt60(machine_config &config)
m_crtc->set_char_width(9);
m_crtc->set_update_row_callback(FUNC(mdt60_state::update_row));
m_crtc->set_on_update_addr_change_callback(FUNC(mdt60_state::update_cb));
// LPEN is tied to GND (code uses this to determine CRTC type)
rs232_port_device &computer(RS232_PORT(config, "computer", default_rs232_devices, nullptr));
computer.rxd_handler().set(m_uart[0], FUNC(i8251_device::write_rxd));
computer.dsr_handler().set(m_uart[0], FUNC(i8251_device::write_dsr));
computer.cts_handler().set(m_uart[0], FUNC(i8251_device::write_cts));
}
void z22_state::z22(machine_config &config)
{
M6512(config, m_maincpu, 16.5888_MHz_XTAL / 9); // R6512AP
m_maincpu->set_addrmap(AS_PROGRAM, &z22_state::mem_map);
I8251(config, m_uart[0], 16.5888_MHz_XTAL / 9); // NEC D8251AC (U33) + Intel P8251A (U35)
m_uart[0]->rxrdy_handler().set_inputline(m_maincpu, m6512_device::NMI_LINE);
m_uart[0]->txd_handler().set("comm", FUNC(rs232_port_device::write_txd));
m_uart[0]->dtr_handler().set("comm", FUNC(rs232_port_device::write_dtr));
m_uart[0]->rts_handler().set("comm", FUNC(rs232_port_device::write_rts));
I8251(config, m_uart[1], 16.5888_MHz_XTAL / 9);
EEPROM_93C06_16BIT(config, m_eeprom); // NMC9306 (U27)
pit8254_device &pit(PIT8254(config, "pit")); // Intel P8254
pit.set_clk<0>(16.5888_MHz_XTAL / 9);
pit.set_clk<1>(16.5888_MHz_XTAL / 9);
pit.set_clk<2>(16.5888_MHz_XTAL / 9);
pit.out_handler<0>().set(m_uart[1], FUNC(i8251_device::write_rxc));
pit.out_handler<0>().append(m_uart[1], FUNC(i8251_device::write_txc));
pit.out_handler<0>().append(m_eeprom, FUNC(eeprom_serial_93cxx_device::clk_write)); // weird synchronous clocking
pit.out_handler<0>().append(FUNC(z22_state::eeprom_clock_w));
pit.out_handler<1>().set(m_uart[0], FUNC(i8251_device::write_rxc));
pit.out_handler<2>().set(m_uart[0], FUNC(i8251_device::write_txc)); // or the other way around?
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_color(rgb_t::amber());
screen.set_raw(16.5888_MHz_XTAL, 873, 0, 720, 317, 0, 300);
screen.set_screen_update(m_crtc, FUNC(r6545_1_device::screen_update));
R6545_1(config, m_crtc, 16.5888_MHz_XTAL / 9); // R6545-1AP
m_crtc->set_screen("screen");
m_crtc->set_show_border_area(false);
m_crtc->set_char_width(9);
m_crtc->set_update_row_callback(FUNC(z22_state::update_row));
m_crtc->set_on_update_addr_change_callback(FUNC(z22_state::update_cb));
// TODO: onboard buzzer
rs232_port_device &comm(RS232_PORT(config, "comm", default_rs232_devices, nullptr));
rs232_port_device &comm(RS232_PORT(config, "comm", default_rs232_devices, "loopback"));
// Service Manual suggests shorting pins with a bent paper clip if no DB-25 loopback connector is available ;-)
comm.rxd_handler().set(m_uart[0], FUNC(i8251_device::write_rxd));
comm.dsr_handler().set(m_uart[0], FUNC(i8251_device::write_dsr));
comm.cts_handler().set(m_uart[0], FUNC(i8251_device::write_cts));
@ -370,17 +252,11 @@ void z22_state::z22(machine_config &config)
ROM_START(mdt60)
ROM_REGION(0x1000, "coderom", 0)
// "ROM REV. 1.7 -- Copyright (C) 1983 by Morrow Designs, Inc."
ROM_LOAD("vb-rom_1.7_bcfd.u9", 0x0000, 0x1000, CRC(3902f7b3) SHA1(ee0ce7f68efe20efe1ab8a44888e276f08fe2d07))
ROM_REGION(0x1000, "charrom", 0)
ROM_LOAD("char_gen_b207.u6", 0x0000, 0x1000, CRC(b19432da) SHA1(fa73641c08b778f19a17676a7f4074f69b7b55dd))
ROM_END
ROM_START(z22)
ROM_REGION(0x4000, "program", 0)
ROM_LOAD("u39.bin", 0x0000, 0x2000, CRC(2f62c1f8) SHA1(448581d987fee6b4303e481e78f46d3255baccbb)) // D2764A-3
ROM_LOAD("u38.bin", 0x2000, 0x2000, CRC(f0bfe9b5) SHA1(8807841b28549d0ddf30275fc6035a66093f8768)) // D2764A-3
ROM_END
SYST(1983, mdt60, 0, 0, mdt60, mdt60, mdt60_state, empty_init, "Morrow", "MDT 60 Video Display Terminal", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
SYST(1984, z22, 0, 0, z22, z22, z22_state, empty_init, "Zenith Data Systems", "Z-22 Terminal", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
SYST(1983, mdt60, 0, 0, mdt60, mdt60, mdt60_state, empty_init, "Morrow Designs", "MDT 60 Video Display Terminal", MACHINE_SUPPORTS_SAVE)

215
src/mame/drivers/z22.cpp Normal file
View File

@ -0,0 +1,215 @@
// license:BSD-3-Clause
// copyright-holders:AJR
/**************************************************************************
Skeleton driver for Zenith Z-22 terminal.
Despite featuring much of the same hardware as the MDT 60, with the
CPU, CRTC and UART types and even dot clock frequency being identical,
much else is different: a serial EEPROM replaces DIP switches, an 8254
generates baud rates, fonts are uploaded to RAM, and the serial
keyboard protocol is incompatible.
**************************************************************************/
#include "emu.h"
#include "bus/rs232/rs232.h"
#include "cpu/m6502/m6502.h"
#include "machine/eepromser.h"
#include "machine/i8251.h"
#include "machine/pit8253.h"
#include "video/mc6845.h"
#include "screen.h"
class z22_state : public driver_device
{
public:
z22_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_crtc(*this, "crtc")
, m_uart(*this, "uart%u", 0U)
, m_eeprom(*this, "eeprom")
, m_dispram(*this, "dispram")
, m_fontram(*this, "fontram")
, m_eeprom_clk(false)
{
}
void z22(machine_config &config);
protected:
virtual void machine_start() override;
virtual void machine_reset() override;
private:
MC6845_UPDATE_ROW(update_row);
MC6845_ON_UPDATE_ADDR_CHANGED(update_cb);
u8 irq_ack_r();
u8 status_r();
void control_w(u8 data);
DECLARE_WRITE_LINE_MEMBER(eeprom_clock_w);
void mem_map(address_map &map);
required_device<cpu_device> m_maincpu;
required_device<r6545_1_device> m_crtc;
optional_device_array<i8251_device, 2> m_uart;
required_device<eeprom_serial_93cxx_device> m_eeprom;
required_shared_ptr<u8> m_dispram;
required_shared_ptr<u8> m_fontram;
bool m_eeprom_clk;
};
void z22_state::machine_start()
{
save_item(NAME(m_eeprom_clk));
}
void z22_state::machine_reset()
{
control_w(0);
}
MC6845_UPDATE_ROW(z22_state::update_row)
{
u32 *pix = &bitmap.pix32(y);
for (unsigned x = 0; x < x_count; x++)
{
u8 cdata = m_dispram[(ma + x) & 0x7ff];
u16 dots = m_fontram[(cdata & 0x7f) << 4 | ra] << 1;
if (x == cursor_x)
dots = ~dots;
rgb_t fg = rgb_t::white();
rgb_t bg = rgb_t::black();
for (int n = 8; n >= 0; n--)
*pix++ = BIT(dots, n) ? fg : bg;
}
}
MC6845_ON_UPDATE_ADDR_CHANGED(z22_state::update_cb)
{
}
u8 z22_state::irq_ack_r()
{
if (!machine().side_effects_disabled())
m_maincpu->set_input_line(m6512_device::IRQ_LINE, CLEAR_LINE);
return 0xff;
}
u8 z22_state::status_r()
{
u8 result = 0;
if (!m_eeprom->do_read())
result |= 0x01;
if (m_eeprom_clk)
result |= 0x02;
// TODO: bit 7 = received keyboard data
return result;
}
void z22_state::control_w(u8 data)
{
m_eeprom->di_write(!BIT(data, 7));
m_eeprom->cs_write(BIT(data, 6));
//m_keyboard->keyout_w(BIT(data, 0));
}
WRITE_LINE_MEMBER(z22_state::eeprom_clock_w)
{
m_eeprom_clk = state;
if (state)
m_maincpu->set_input_line(m6512_device::IRQ_LINE, ASSERT_LINE);
}
void z22_state::mem_map(address_map &map)
{
map(0x0000, 0x07ff).ram();
map(0x2000, 0x27ff).ram().share("dispram");
map(0x4000, 0x4001).rw(m_uart[1], FUNC(i8251_device::read), FUNC(i8251_device::write));
map(0x6000, 0x67ff).ram().share("fontram");
map(0x8000, 0x8001).rw(m_uart[0], FUNC(i8251_device::read), FUNC(i8251_device::write));
map(0x8800, 0x8800).rw(m_crtc, FUNC(r6545_1_device::status_r), FUNC(r6545_1_device::address_w));
map(0x8801, 0x8801).rw(m_crtc, FUNC(r6545_1_device::register_r), FUNC(r6545_1_device::register_w));
map(0x9000, 0x9003).w("pit", FUNC(pit8254_device::write));
map(0x9800, 0x9800).r(FUNC(z22_state::irq_ack_r));
map(0xa000, 0xa000).rw(FUNC(z22_state::status_r), FUNC(z22_state::control_w));
map(0xc000, 0xffff).rom().region("program", 0);
}
static INPUT_PORTS_START(z22)
INPUT_PORTS_END
// XTAL frequency is specified as 16.589 MHz on actual parts. As with the MDT 60, this
// has been assumed to be a lower-precision specification of the common 16.5888 MHz value.
void z22_state::z22(machine_config &config)
{
M6512(config, m_maincpu, 16.5888_MHz_XTAL / 9); // R6512AP
m_maincpu->set_addrmap(AS_PROGRAM, &z22_state::mem_map);
I8251(config, m_uart[0], 16.5888_MHz_XTAL / 9); // NEC D8251AC (U33) + Intel P8251A (U35)
m_uart[0]->rxrdy_handler().set_inputline(m_maincpu, m6512_device::NMI_LINE);
m_uart[0]->txd_handler().set("comm", FUNC(rs232_port_device::write_txd));
m_uart[0]->dtr_handler().set("comm", FUNC(rs232_port_device::write_dtr));
m_uart[0]->rts_handler().set("comm", FUNC(rs232_port_device::write_rts));
I8251(config, m_uart[1], 16.5888_MHz_XTAL / 9);
m_uart[1]->txd_handler().set("printer", FUNC(rs232_port_device::write_txd));
EEPROM_93C06_16BIT(config, m_eeprom); // NMC9306 (U27)
pit8254_device &pit(PIT8254(config, "pit")); // Intel P8254
pit.set_clk<0>(16.5888_MHz_XTAL / 9);
pit.set_clk<1>(16.5888_MHz_XTAL / 9);
pit.set_clk<2>(16.5888_MHz_XTAL / 9);
pit.out_handler<0>().set(m_eeprom, FUNC(eeprom_serial_93cxx_device::clk_write)); // weird synchronous clocking
pit.out_handler<0>().append(FUNC(z22_state::eeprom_clock_w));
pit.out_handler<1>().set(m_uart[0], FUNC(i8251_device::write_rxc));
pit.out_handler<2>().set(m_uart[0], FUNC(i8251_device::write_txc)); // or the other way around?
pit.out_handler<2>().append(m_uart[1], FUNC(i8251_device::write_txc));
// TODO: Keyboard (asynchronous serial, like Z-49?)
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_color(rgb_t::amber());
screen.set_raw(16.5888_MHz_XTAL, 873, 0, 720, 317, 0, 300);
screen.set_screen_update(m_crtc, FUNC(r6545_1_device::screen_update));
R6545_1(config, m_crtc, 16.5888_MHz_XTAL / 9); // R6545-1AP
m_crtc->set_screen("screen");
m_crtc->set_show_border_area(false);
m_crtc->set_char_width(9);
m_crtc->set_update_row_callback(FUNC(z22_state::update_row));
m_crtc->set_on_update_addr_change_callback(FUNC(z22_state::update_cb));
// TODO: onboard buzzer
rs232_port_device &comm(RS232_PORT(config, "comm", default_rs232_devices, nullptr));
comm.rxd_handler().set(m_uart[0], FUNC(i8251_device::write_rxd));
comm.dsr_handler().set(m_uart[0], FUNC(i8251_device::write_dsr));
comm.cts_handler().set(m_uart[0], FUNC(i8251_device::write_cts));
rs232_port_device &printer(RS232_PORT(config, "printer", default_rs232_devices, nullptr));
printer.dsr_handler().set(m_uart[1], FUNC(i8251_device::write_dsr));
}
ROM_START(z22)
ROM_REGION(0x4000, "program", 0)
ROM_LOAD("u39.bin", 0x0000, 0x2000, CRC(2f62c1f8) SHA1(448581d987fee6b4303e481e78f46d3255baccbb)) // D2764A-3
ROM_LOAD("u38.bin", 0x2000, 0x2000, CRC(f0bfe9b5) SHA1(8807841b28549d0ddf30275fc6035a66093f8768)) // D2764A-3
ROM_END
SYST(1984, z22, 0, 0, z22, z22, z22_state, empty_init, "Zenith Data Systems", "Z-22 Terminal", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)

View File

@ -8,8 +8,8 @@
#include "emu.h"
//#include "bus/rs232/rs232.h"
#include "bus/z29_kbd/keyboard.h"
#include "cpu/mcs51/mcs51.h"
#include "cpu/mcs48/mcs48.h"
#include "machine/x2212.h"
#include "video/i8275.h"
#include "screen.h"
@ -20,11 +20,14 @@ public:
z29_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_keyboard(*this, "keyboard")
, m_crtc(*this, "crtc%u", 1U)
, m_nvram(*this, "nvram")
, m_charmem(*this, "charmem")
, m_attrmem(*this, "attrmem")
, m_chargen(*this, "chargen")
, m_dmatype(true)
, m_keyin(true)
{
}
@ -34,8 +37,10 @@ protected:
virtual void machine_start() override;
private:
DECLARE_WRITE_LINE_MEMBER(keyin_w);
u8 p1_r();
void p3_w(u8 data);
DECLARE_READ8_MEMBER(bs_24k_r);
u8 bs_24k_r(offs_t offset);
void crtc_w(offs_t offset, u8 data);
void latch_12k_w(u8 data);
@ -43,6 +48,7 @@ private:
void ext_map(address_map &map);
required_device<mcs51_cpu_device> m_maincpu;
required_device<z29_keyboard_port_device> m_keyboard;
required_device_array<i8276_device, 2> m_crtc;
required_device<x2210_device> m_nvram;
@ -51,11 +57,23 @@ private:
required_region_ptr<u8> m_chargen;
bool m_dmatype;
bool m_keyin;
};
void z29_state::machine_start()
{
save_item(NAME(m_dmatype));
save_item(NAME(m_keyin));
}
WRITE_LINE_MEMBER(z29_state::keyin_w)
{
m_keyin = state;
}
u8 z29_state::p1_r()
{
return m_keyin ? 0xfd : 0xff;
}
void z29_state::p3_w(u8 data)
@ -63,7 +81,7 @@ void z29_state::p3_w(u8 data)
m_dmatype = BIT(data, 4);
}
READ8_MEMBER(z29_state::bs_24k_r)
u8 z29_state::bs_24k_r(offs_t offset)
{
if (!machine().side_effects_disabled())
{
@ -122,11 +140,16 @@ void z29_state::z29(machine_config &config)
I8031(config, m_maincpu, 14.784_MHz_XTAL / 2); // Intel P8031AH
m_maincpu->set_addrmap(AS_PROGRAM, &z29_state::prg_map);
m_maincpu->set_addrmap(AS_IO, &z29_state::ext_map);
m_maincpu->port_in_cb<1>().set_constant(0xfd); // hack around keyboard not working
m_maincpu->port_in_cb<1>().set(FUNC(z29_state::p1_r));
m_maincpu->port_out_cb<1>().set(m_keyboard, FUNC(z29_keyboard_port_device::keyout_w)).bit(0).invert();
m_maincpu->port_out_cb<3>().set(FUNC(z29_state::p3_w));
X2210(config, m_nvram);
Z29_KEYBOARD(config, m_keyboard, z29_keyboards, /*"heath"*/ "md");
m_keyboard->keyin_callback().set(FUNC(z29_state::keyin_w));
m_keyboard->reset_callback().set_inputline(m_maincpu, INPUT_LINE_RESET).invert();
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_raw(14.784_MHz_XTAL, 880, 0, 640, 280, 0, 250);
screen.set_screen_update("crtc1", FUNC(i8276_device::screen_update));
@ -136,8 +159,6 @@ void z29_state::z29(machine_config &config)
m_crtc[0]->irq_wr_callback().set_inputline(m_maincpu, MCS51_INT1_LINE);
I8276(config, m_crtc[1], 14.784_MHz_XTAL / 8).set_character_width(8);
I8021(config, "kbdmcu", 3.579545_MHz_XTAL).set_disable();
}
@ -148,9 +169,6 @@ ROM_START(z29) // All EPROMs on 85-2835-1 terminal board are HN482732AG-30
ROM_REGION(0x1000, "chargen", 0)
ROM_LOAD("u429.bin", 0x0000, 0x1000, CRC(5e3bc5bf) SHA1(18d73e3d74a9768bee8b063ea45891f955558ae7))
ROM_REGION(0x400, "kbdmcu", 0)
ROM_LOAD("444-100.bin", 0x000, 0x400, NO_DUMP)
ROM_END

View File

@ -21873,7 +21873,6 @@ fl100 // (c) 198? Grundig
@source:mdt60.cpp
mdt60 //
z22 //
@source:meadows.cpp
bowl3d // [1978?]
@ -41792,6 +41791,9 @@ z1013k69 //
z1013k76 //
z1013s60 //
@source:z22.cpp
z22 //
@source:z29.cpp
z29 //

View File

@ -1075,6 +1075,7 @@ ymtx81z.cpp
ymvl70.cpp
z100.cpp
z1013.cpp
z22.cpp
z29.cpp
z80dev.cpp
z80ne.cpp