summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/devices/bus/mackbd/keyboard.cpp677
-rw-r--r--src/devices/bus/mackbd/keyboard.h21
-rw-r--r--src/devices/bus/mackbd/mackbd.cpp162
-rw-r--r--src/devices/bus/mackbd/mackbd.h91
-rw-r--r--src/devices/bus/mackbd/pluskbd.cpp311
-rw-r--r--src/devices/bus/mackbd/pluskbd.h17
-rw-r--r--src/devices/cpu/mcs48/mcs48.h4
-rw-r--r--src/emu/ioport.cpp2
-rw-r--r--src/emu/natkeyboard.cpp18
-rw-r--r--src/emu/natkeyboard.h4
-rw-r--r--src/mame/drivers/mac128.cpp17
-rw-r--r--src/mame/machine/mackbd.cpp287
-rw-r--r--src/mame/machine/mackbd.h58
13 files changed, 1309 insertions, 360 deletions
diff --git a/src/devices/bus/mackbd/keyboard.cpp b/src/devices/bus/mackbd/keyboard.cpp
new file mode 100644
index 00000000000..6a8faf140a3
--- /dev/null
+++ b/src/devices/bus/mackbd/keyboard.cpp
@@ -0,0 +1,677 @@
+// license: BSD-3-Clause
+// copyright-holders: Vas Crabb
+/***************************************************************************
+
+ Apple M0110/M0120 keyboard/keypad
+
+ These peripherals have a lot in common:
+ * Based on Intel or Philips mask-programmed 8021 microcontroller
+ * 100µH inductor as timing element (gives approximately 3MHz)
+ * Identical microcontroller programs
+ * Identical external watchdog circuits based on 74LS123
+ * Identical power-on/brownout reset circuits
+ * Identical host communication interface via P07 and P20
+ * Keys read with a mixture of matrix and dedicated inputs
+ * Neither has diodes to prevent ghosting
+
+ The program chooses keyboard or keypad mode based on whether P05
+ reads low with no outputs driven low.
+
+ The keyboard has dedicated inputs for the four modifiers (Shift,
+ Command, Option, and mechanically toggling Caps Lock - no Control
+ keys and no distinction between left/right Shift and Option). The
+ rest of the keys (52 for ANSI or 53 for ISO) are read via a
+ nine-by-six matrix.
+
+ The keypad has dedicated inputs for the digits and (rather
+ ineffciently) reads the other eight keys via a three-by-three
+ matrix.
+
+ +-----------+---------------+-------------------+
+ | Pin | Keyboard | Keypad |
+ +-----------+---------------+-------------------+
+ | P00 (4) | column read | row drive |
+ | P01 (5) | column read | row drive |
+ | P02 (6) | column read | row drive |
+ | P03 (7) | column read | 8 |
+ | P04 (8) | column read | 9 |
+ | P05 (9) | column read | sense |
+ | P06 (10) | Caps Lock | keyboard clock |
+ | P07 (11) | host clock | host clock |
+ +-----------+---------------+-------------------+
+ | P10 (18) | row drive | 0 |
+ | P11 (19) | row drive | 1 |
+ | P12 (20) | row drive | 2 |
+ | P13 (21) | row drive | 3 |
+ | P14 (22) | row drive | 4 |
+ | P15 (23) | row drive | 5 |
+ | P16 (24) | row drive | 6 |
+ | P17 (25) | row drive | 7 |
+ +-----------+---------------+-------------------+
+ | P20 (26) | host data | host data |
+ | P21 (27) | row drive* | keyboard data |
+ | P22 (1) | Shift | column read |
+ | P23 (2) | Command | column read |
+ +-----------+---------------+-------------------+
+ | T1 (13) | Option | column read |
+ +-----------+---------------+-------------------+
+ * falling edge starts/resets watchdog timer
+
+ +------+-----------------------------------------------------+
+ | ANSI | P21 P10 P11 P12 P13 P14 P15 P16 P17 |
+ +------+-----------------------------------------------------+
+ | P00 | A Z Q 1 = ] Rtn \ Tab |
+ | P01 | S X W 2 9 O L , Spc |
+ | P02 | D C E 3 7 U J / ` |
+ | P03 | F V R 4 - [ ' N Bsp |
+ | P04 | H Y 6 8 I K M Ent |
+ | P05 | G B T 5 0 P ; . |
+ +------+-----------------------------------------------------+
+
+ +------+-----------------------------------------------------+
+ | ISO | P21 P10 P11 P12 P13 P14 P15 P16 P17 |
+ +------+-----------------------------------------------------+
+ | P00 | A ` Q 1 = ] \ Rtn Tab |
+ | P01 | S Z W 2 9 O L M Ent |
+ | P02 | D X E 3 7 U J . § |
+ | P03 | F C R 4 - [ ' B Bsp |
+ | P04 | H / Y 6 8 I K N Spc |
+ | P05 | G V T 5 0 P ; , |
+ +------+-----------------------------------------------------+
+
+ +------+-----------------+
+ | Pad | P00 P01 P02 |
+ +------+-----------------+
+ | P22 | / Clr . |
+ | P23 | - , * |
+ | T1 | Ent + |
+ +------+-----------------+
+
+ Known part numbers:
+ * M0110 (U.S. - ANSI)
+ * M0110B (British - ISO)
+ * M0110F (French - ISO)
+
+ Also known to exist:
+ * Japanese - ANSI
+ * Italian - ISO
+ * M0110T
+
+ TODO:
+ * Determine whether P00 or P01 actually feeds the keypad watchdog
+ * Find more model numbers and implement more layouts
+ * Is the kana key on the Japanese version locking?
+
+***************************************************************************/
+
+#include "emu.h"
+#include "keyboard.h"
+
+#include "cpu/mcs48/mcs48.h"
+
+#define LOG_GENERAL (1U << 0)
+#define LOG_WATCHDOG (1U << 1)
+#define LOG_MATRIX (1U << 2)
+#define LOG_COMM (1U << 3)
+
+//#define VERBOSE (LOG_GENERAL | LOG_WATCHDOG | LOG_MATRIX | LOG_COMM)
+//#define LOG_OUTPUT_STREAM std::cerr
+#include "logmacro.h"
+
+#define LOGWATCHDOG(...) LOGMASKED(LOG_WATCHDOG, __VA_ARGS__)
+#define LOGMATRIX(...) LOGMASKED(LOG_MATRIX, __VA_ARGS__)
+#define LOGCOMM(...) LOGMASKED(LOG_COMM, __VA_ARGS__)
+
+
+namespace {
+
+ROM_START(keyboard)
+ ROM_REGION(0x0400, "mpu", 0)
+ ROM_LOAD("ip8021h_2173.bin", 0x000000, 0x000400, CRC(5fbd9a94) SHA1(32a3b58afb445a8675b12a4de3aec2fa00c99222))
+ROM_END
+
+
+template <unsigned Rows>
+class peripheral_base : public device_t, public device_mac_keyboard_interface
+{
+public:
+ CUSTOM_INPUT_MEMBER(columns_r)
+ {
+ ioport_value result(make_bitmask<ioport_value>(Rows));
+ for (unsigned i = 0U; Rows > i; ++i)
+ {
+ if (!BIT(m_row_drive, i))
+ result &= m_rows[i]->read();
+ }
+ LOGMATRIX("read matrix: row drive = %X, result = %X\n", m_row_drive, result);
+ return result ^ make_bitmask<ioport_value>(Rows);
+ }
+
+ CUSTOM_INPUT_MEMBER(host_data_r)
+ {
+ return m_host_data_in ^ 0x01;
+ }
+
+protected:
+ peripheral_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_mac_keyboard_interface(mconfig, *this)
+ , m_mpu{ *this, "mpu" }
+ , m_rows{ *this, "ROW%u", 0U }
+ {
+ }
+
+ virtual tiny_rom_entry const *device_rom_region() const override
+ {
+ return ROM_NAME(keyboard);
+ }
+
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ I8021(config, m_mpu, 3'000'000); // 100µH inductor gives approximately 3MHz
+ m_mpu->p0_out_cb().set(FUNC(peripheral_base::host_clock_w)).bit(7);
+ m_mpu->p2_out_cb().set(FUNC(peripheral_base::host_data_w)).bit(0);
+ }
+
+ virtual void device_start() override
+ {
+ m_watchdog_timeout = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(peripheral_base::watchdog_timeout), this));
+ m_watchdog_output = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(peripheral_base::watchdog_output), this));
+
+ m_row_drive = make_bitmask<u16>(Rows);
+ m_host_clock_out = 1U;
+ m_host_data_out = 1U;
+ m_host_data_in = 0x01U;
+ m_watchdog_in = 1U;
+
+ save_item(NAME(m_row_drive));
+ save_item(NAME(m_host_clock_out));
+ save_item(NAME(m_host_data_out));
+ save_item(NAME(m_host_data_in));
+ save_item(NAME(m_watchdog_in));
+ }
+
+ virtual DECLARE_WRITE_LINE_MEMBER(data_w) override
+ {
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(peripheral_base::update_host_data), this), state);
+ }
+
+ DECLARE_WRITE_LINE_MEMBER(watchdog_w)
+ {
+ if (bool(state) != bool(m_watchdog_in))
+ {
+ m_watchdog_in = state ? 1U : 0U;
+ if (!state)
+ {
+ // 74LS123 with Rt = 200kΩ and Cext = 1µF
+ // t = K * Rt * Cext * (1 + (0.7 / Rt)) = 0.28 * 200k * 1µ * (1 + (0.7 / 200k)) ≈ 56ms
+ m_watchdog_timeout->adjust(attotime::from_msec(56));
+ LOGWATCHDOG("%s: watchdog reset\n", machine().describe_context());
+ }
+ }
+ }
+
+ template <u16 Mask> void set_row_drive(u16 value)
+ {
+ m_row_drive = ((m_row_drive & ~Mask) | (value & Mask)) & make_bitmask<u16>(Rows);
+ }
+
+ required_device<i8021_device> m_mpu;
+
+private:
+ DECLARE_WRITE_LINE_MEMBER(host_clock_w)
+ {
+ if (bool(state) != bool(m_host_clock_out))
+ {
+ if (state)
+ LOGCOMM("%s: host clock out 0 -> 1 data=%u\n", machine().describe_context(), (m_host_data_out && m_host_data_in) ? 1U : 0U);
+ else
+ LOGCOMM("%s: host clock out 1 -> 0\n", machine().describe_context());
+ write_clock(m_host_clock_out = state ? 1U : 0U);
+ }
+ }
+
+ DECLARE_WRITE_LINE_MEMBER(host_data_w)
+ {
+ if (bool(state) != bool(m_host_data_out))
+ {
+ LOGCOMM("%s: host data out %u -> %u\n", machine().describe_context(), m_host_data_out, state ? 1U : 0U);
+ write_data(m_host_data_out = state ? 1U : 0U);
+ }
+ }
+
+ TIMER_CALLBACK_MEMBER(update_host_data)
+ {
+ if (bool(param) != bool(m_host_data_in))
+ {
+ LOGCOMM("host data in %u -> %u\n", m_host_data_in, param ? 1U : 0U);
+ m_host_data_in = param ? 0x01U : 0x00U;
+ }
+ }
+
+ TIMER_CALLBACK_MEMBER(watchdog_timeout)
+ {
+ // 74LS123 with Rt = 200kΩ and Cext = 100nF
+ // t = K * Rt * Cext * (1 + (0.7 / Rt)) = 0.28 * 200k * 100n * (1 + (0.7 / 200k)) ≈ 5.6ms
+ m_watchdog_output->adjust(attotime::from_usec(5600));
+ LOG("watchdog timeout\n");
+ m_mpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
+ }
+
+ TIMER_CALLBACK_MEMBER(watchdog_output)
+ {
+ LOGWATCHDOG("watchdog release\n");
+ m_mpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
+ }
+
+ required_ioport_array<Rows> m_rows;
+
+ emu_timer *m_watchdog_timeout = nullptr;
+ emu_timer *m_watchdog_output = nullptr;
+
+ u16 m_row_drive = make_bitmask<u16>(Rows); // current bit pattern driving rows (active low)
+ u8 m_host_clock_out = 1U; // clock line drive to host (idle high)
+ u8 m_host_data_out = 1U; // data line drive to host (idle high)
+ u8 m_host_data_in = 0x01U; // data line drive from host (idle high)
+ u8 m_watchdog_in = 1U; // watchdog start/reset (falling edge trigger)
+};
+
+
+class keyboard_base : public peripheral_base<9>
+{
+protected:
+ keyboard_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock)
+ : peripheral_base<9>(mconfig, type, tag, owner, clock)
+ {
+ }
+
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ peripheral_base<9>::device_add_mconfig(config);
+
+ m_mpu->p0_in_cb().set_ioport("P0");
+ m_mpu->p1_out_cb().set([this] (u8 data) { set_row_drive<0x01feU>(u16(data) << 1); });
+ m_mpu->p2_in_cb().set_ioport("P2");
+ m_mpu->p2_out_cb().append([this] (u8 data) { set_row_drive<0x0001U>((data >> 1) & 0x01U); });
+ m_mpu->p2_out_cb().append(FUNC(keyboard_base::watchdog_w)).bit(1);
+ m_mpu->t1_in_cb().set_ioport("T1");
+ }
+};
+
+
+class keypad_base : public peripheral_base<3>
+{
+public:
+ CUSTOM_INPUT_MEMBER(keyboard_clock_r)
+ {
+ return m_keyboard_clock_in ^ 0x01;
+ }
+
+ CUSTOM_INPUT_MEMBER(keyboard_data_r)
+ {
+ return m_keyboard_data_in ^ 0x01;
+ }
+
+protected:
+ keypad_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock)
+ : peripheral_base<3>(mconfig, type, tag, owner, clock)
+ , m_keyboard_port(*this, "kbd")
+ {
+ }
+
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ peripheral_base<3>::device_add_mconfig(config);
+
+ m_mpu->p0_in_cb().set_ioport("P0");
+ m_mpu->p0_out_cb().append(FUNC(keypad_base::set_row_drive<0x07U>));
+ m_mpu->p0_out_cb().append(FUNC(keypad_base::watchdog_w)).bit(1); // TODO: confirm whether P0 or P1 resets watchdog
+ m_mpu->p1_in_cb().set_ioport("P1");
+ m_mpu->p2_in_cb().set_ioport("P2");
+ m_mpu->p2_out_cb().append(FUNC(keypad_base::keyboard_data_out_w)).bit(1);
+ m_mpu->t1_in_cb().set([this] () { return int((~columns_r() >> 2) & 0x01U); });
+
+ MAC_KEYBOARD_PORT(config, m_keyboard_port, mac_keyboard_devices, "us");
+ m_keyboard_port->clock_cb().set(FUNC(keypad_base::keyboard_clock_in_w));
+ m_keyboard_port->data_cb().set(FUNC(keypad_base::keyboard_data_in_w));
+ }
+
+ virtual void device_start() override
+ {
+ peripheral_base<3>::device_start();
+
+ m_keyboard_data_out = 0x01U;
+ m_keyboard_clock_in = 0x01U;
+ m_keyboard_data_in = 0x01U;
+
+ save_item(NAME(m_keyboard_data_out));
+ save_item(NAME(m_keyboard_clock_in));
+ save_item(NAME(m_keyboard_data_in));
+ }
+
+private:
+ DECLARE_WRITE_LINE_MEMBER(keyboard_data_out_w)
+ {
+ if (bool(state) != bool(m_keyboard_data_out))
+ {
+ LOGCOMM("%s: keyboard data out %u -> %u\n", machine().describe_context(), m_keyboard_data_out, state ? 1U : 0U);
+ m_keyboard_port->data_w(m_keyboard_data_out = state ? 0x01U : 0x00U);
+ }
+ }
+
+ DECLARE_WRITE_LINE_MEMBER(keyboard_clock_in_w)
+ {
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(keypad_base::update_keyboard_clock), this), state);
+ }
+
+ DECLARE_WRITE_LINE_MEMBER(keyboard_data_in_w)
+ {
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(keypad_base::update_keyboard_data), this), state);
+ }
+
+ TIMER_CALLBACK_MEMBER(update_keyboard_clock)
+ {
+ m_keyboard_clock_in = param ? 0x01U : 0x00U;
+ }
+
+ TIMER_CALLBACK_MEMBER(update_keyboard_data)
+ {
+ m_keyboard_data_in = param ? 0x01U : 0x00U;
+ }
+
+ required_device<mac_keyboard_port_device> m_keyboard_port;
+
+ u8 m_keyboard_data_out = 0x01U; // data line drive to keyboard (idle high)
+ u8 m_keyboard_clock_in = 0x01U; // clock line driver from keyboard (idle high)
+ u8 m_keyboard_data_in = 0x01U; // data line drive from keyboard (idle high)
+};
+
+
+INPUT_PORTS_START(keyboard_us)
+ PORT_START("ROW0")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
+
+ PORT_START("ROW1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
+
+ PORT_START("ROW2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
+
+ PORT_START("ROW3")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
+
+ PORT_START("ROW4")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
+
+ PORT_START("ROW5")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
+
+ PORT_START("ROW6")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(0x0d) PORT_NAME("Return")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
+
+ PORT_START("ROW7")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|')
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
+
+ PORT_START("ROW8")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR(0x09) PORT_NAME("Tab")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(0x08) PORT_NAME("Backspace")
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RCONTROL) PORT_NAME("Enter")
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("P0")
+ PORT_BIT(0x3f, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_CUSTOM_MEMBER(keyboard_base, columns_r)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_NAME("Caps Lock") PORT_TOGGLE
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("P2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_CUSTOM_MEMBER(keyboard_base, host_data_r)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) PORT_NAME("Shift")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_NAME("Command")
+ PORT_BIT(0xf0, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("T1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LALT) PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_SHIFT_2) PORT_NAME("Option")
+INPUT_PORTS_END
+
+INPUT_PORTS_START(keyboard_gb)
+ PORT_INCLUDE(keyboard_us)
+
+ PORT_MODIFY("ROW1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('\\') PORT_CHAR('|')
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
+
+ PORT_MODIFY("ROW3")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR(0xa3) // £
+
+ PORT_MODIFY("ROW6")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('`') PORT_CHAR('~')
+
+ PORT_MODIFY("ROW7")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(0x0d) PORT_NAME("Return")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
+
+ PORT_MODIFY("ROW8")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RCONTROL) PORT_NAME("Enter")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR(0xa7) PORT_CHAR('#') // §
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+INPUT_PORTS_END
+
+INPUT_PORTS_START(keyboard_fr)
+ PORT_INCLUDE(keyboard_us)
+
+ PORT_MODIFY("ROW0")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('q') PORT_CHAR('Q')
+
+ PORT_MODIFY("ROW1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>')
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('w') PORT_CHAR('W')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('=') PORT_CHAR('+')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
+
+ PORT_MODIFY("ROW2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('a') PORT_CHAR('A')
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('z') PORT_CHAR('Z')
+
+ PORT_MODIFY("ROW3")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('&') PORT_CHAR('1')
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR(0xe9) PORT_CHAR('2') // é
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('"') PORT_CHAR('3')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('\'') PORT_CHAR('4')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR(0xa7) PORT_CHAR('6') // §
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('(') PORT_CHAR('5')
+
+ PORT_MODIFY("ROW4")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('-') PORT_CHAR('_')
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR(0xe7) PORT_CHAR('9') // ç
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR(0xe8) PORT_CHAR('7') // è
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR(')') PORT_CHAR(0xb0) // °
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('!') PORT_CHAR('8')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR(0xe0) PORT_CHAR('0') // à
+
+ PORT_MODIFY("ROW5")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('$') PORT_CHAR('*')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0x2c6) PORT_CHAR(0xa8) // ˆ ¨
+
+ PORT_MODIFY("ROW6")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('`') PORT_CHAR(0xa3) // £
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(0xf9) PORT_CHAR('%') // ù
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR('m') PORT_CHAR('M')
+
+ PORT_MODIFY("ROW7")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(0x0d) PORT_NAME("Return")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR(',') PORT_CHAR('?')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR(':') PORT_CHAR('/')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(';') PORT_CHAR('.')
+
+ PORT_MODIFY("ROW8")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RCONTROL) PORT_NAME("Enter")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('@') PORT_CHAR('#')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+INPUT_PORTS_END
+
+
+class m0110_device : public keyboard_base
+{
+public:
+ m0110_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : keyboard_base(mconfig, MACKBD_M0110, tag, owner, clock)
+ {
+ }
+
+protected:
+ virtual ioport_constructor device_input_ports() const override
+ {
+ return INPUT_PORTS_NAME(keyboard_us);
+ }
+};
+
+class m0110b_device : public keyboard_base
+{
+public:
+ m0110b_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : keyboard_base(mconfig, MACKBD_M0110B, tag, owner, clock)
+ {
+ }
+
+protected:
+ virtual ioport_constructor device_input_ports() const override
+ {
+ return INPUT_PORTS_NAME(keyboard_gb);
+ }
+};
+
+class m0110f_device : public keyboard_base
+{
+public:
+ m0110f_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : keyboard_base(mconfig, MACKBD_M0110F, tag, owner, clock)
+ {
+ }
+
+protected:
+ virtual ioport_constructor device_input_ports() const override
+ {
+ return INPUT_PORTS_NAME(keyboard_fr);
+ }
+};
+
+
+INPUT_PORTS_START(keypad)
+ PORT_START("ROW0")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD)) PORT_NAME("Keypad / (Up)")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_EQUALS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PORT_NAME("Keypad -")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) PORT_NAME("Keypad Enter")
+
+ PORT_START("ROW1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK)) PORT_NAME("Keypad Clear")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(COMMA_PAD)) PORT_NAME("Keypad , (Down)")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_SLASH_PAD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD)) PORT_NAME("Keypad + (Left)")
+
+ PORT_START("ROW2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) PORT_NAME("Keypad .")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR(UCHAR_MAMEKEY(ASTERISK)) PORT_NAME("Keypad * (Right)")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("P0")
+ PORT_BIT(0x07, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) PORT_NAME("Keypad 8")
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) PORT_NAME("Keypad 9")
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_CUSTOM)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_CUSTOM_MEMBER(keypad_base, keyboard_clock_r)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("P1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) PORT_NAME("Keypad 0")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) PORT_NAME("Keypad 1")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) PORT_NAME("Keypad 2")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) PORT_NAME("Keypad 3")
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) PORT_NAME("Keypad 4")
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) PORT_NAME("Keypad 5")
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) PORT_NAME("Keypad 6")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) PORT_NAME("Keypad 7")
+
+ PORT_START("P2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_CUSTOM_MEMBER(keypad_base, host_data_r)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_CUSTOM_MEMBER(keypad_base, keyboard_data_r)
+ PORT_BIT(0x0c, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_CUSTOM_MEMBER(keypad_base, columns_r)
+INPUT_PORTS_END
+
+
+class m0120_device : public keypad_base
+{
+public:
+ m0120_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : keypad_base(mconfig, MACKBD_M0120, tag, owner, clock)
+ {
+ }
+
+protected:
+ virtual ioport_constructor device_input_ports() const override
+ {
+ return INPUT_PORTS_NAME(keypad);
+ }
+};
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MACKBD_M0110, device_mac_keyboard_interface, m0110_device, "mackbd_m0110", "Macintosh Keyboard (U.S. - M0110)")
+DEFINE_DEVICE_TYPE_PRIVATE(MACKBD_M0110B, device_mac_keyboard_interface, m0110b_device, "mackbd_m0110b", "Macintosh Keyboard (British - M0110B)")
+DEFINE_DEVICE_TYPE_PRIVATE(MACKBD_M0110F, device_mac_keyboard_interface, m0110f_device, "mackbd_m0110f", "Macintosh Keyboard (French - M0110F)")
+
+DEFINE_DEVICE_TYPE_PRIVATE(MACKBD_M0120, device_mac_keyboard_interface, m0120_device, "mackbd_m0120", "Macintosh Numeric Keypad (M0120)")
diff --git a/src/devices/bus/mackbd/keyboard.h b/src/devices/bus/mackbd/keyboard.h
new file mode 100644
index 00000000000..6b051081835
--- /dev/null
+++ b/src/devices/bus/mackbd/keyboard.h
@@ -0,0 +1,21 @@
+// license: BSD-3-Clause
+// copyright-holders: Vas Crabb
+/***************************************************************************
+
+ Apple M0110/M0120 keyboard/keypad
+
+***************************************************************************/
+#ifndef MAME_BUS_MACKBD_KEYBOARD_H
+#define MAME_BUS_MACKBD_KEYBOARD_H
+
+#pragma once
+
+#include "mackbd.h"
+
+DECLARE_DEVICE_TYPE(MACKBD_M0110, device_mac_keyboard_interface)
+DECLARE_DEVICE_TYPE(MACKBD_M0110B, device_mac_keyboard_interface)
+DECLARE_DEVICE_TYPE(MACKBD_M0110F, device_mac_keyboard_interface)
+
+DECLARE_DEVICE_TYPE(MACKBD_M0120, device_mac_keyboard_interface)
+
+#endif // MAME_BUS_MACKBD_KEYBOARD_H
diff --git a/src/devices/bus/mackbd/mackbd.cpp b/src/devices/bus/mackbd/mackbd.cpp
new file mode 100644
index 00000000000..c51b9f255c9
--- /dev/null
+++ b/src/devices/bus/mackbd/mackbd.cpp
@@ -0,0 +1,162 @@
+// license: BSD-3-Clause
+// copyright-holders: Vas Crabb
+/***************************************************************************
+
+ Mac 128k/512k/Plus keyboard interface (pre-ADB)
+
+ Two-wire protocol designed to avoid the need for an accurate/stable
+ clock source in the keyboard. This is not a multi-drop bus. In
+ cases where peripherals are daisy-chained, the upstream peripheral
+ acts as a host for the downstream peripheral.
+
+ In the idle state, both signal lines are high, pulled up using
+ resistors. All transactions are initiated by the host, but the
+ timing is controlled entirely by the peripheral. The data signal
+ must be valid on the rising edge of the clock signal. The data is
+ not inverted.
+
+ Transaction steps (ignoring mandatory delays):
+ * Host pulls down data line to initiate transfer
+ * Peripheral reads one octet (eight bits) from host, MSB first:
+ - Peripheral pulls clock line low
+ - Host sets bit on data line
+ - Peripheral releases clock line
+ - Peripheral samples data line
+ - Repeat for remaining bits of octet
+ * Host releases data line
+ * Peripheral sends one octet (eight bits) to host, MSB first:
+ - Peripheral places bit on data line
+ - Peripheral pulls clock line low
+ - Peripheral releases clock line
+ - Host samples data line
+ - Repeat for remaining bits of octet
+ * Peripheral releases data line
+
+ The last bit (LSB) of the octet transferred from the host to the
+ peripheral is always zero. This allows the host to hold the data
+ line low until it's ready to receive the response from the
+ peripheral. The last bit of the octet transferred from the
+ peripheral to the host is always high.
+
+ Some transactions expect an immediate response while others allow
+ the peripheral to delay the response if it has no data to send
+ immediately. The host polls the peripheral continuously. If no
+ response is received in about 500ms, the host assumes the
+ peripheral has crashed/reset or has been unplugged, and will
+ attempt to re-establish communication.
+
+ Transactions:
+ * 0x10: Permission to send
+ Peripheral responds immediately with data if avaiblable. If no
+ data is available, peripheral waits for data and responds when it
+ becomes available. If no data is availabel after 250ms, the
+ peripheral responds with 0x7b to hand control back to the host.
+ * 0x14: Request to send
+ Peripheral responds immediately with data or 0x7b if no data is
+ available.
+ * 0x16: Reset and identify
+ Peripheral responds with identification code.
+ - 0x03: M0110 compact keyboard
+ - 0x0b: M0110A Mac Plus keyboard
+ - 0x11: M0120 numeric keypad
+ - 0x13: M0120 numeric keypad with M0110 compact keyboard
+ - 0x1b: M0120 numeric keypad with M0110A Mac Plus keyboard
+ - 0x27: Assimilation Process keypad with M0110 keyboard???
+ * 0x36: Perform self test
+ Peripheral responds with 0x7d (pass) or 0x77 (failure).
+
+ Additionally, if bit 5 of the octet sent to the peripheral is set
+ (0x40), the octet is passed on to a daisy-chained peripheral with
+ this bit cleared. The response from the daisy-chained peripheral is
+ passed back to the host. If the transaction to the daisy-chained
+ peripheral times out, the peripheral sends the response 0x77 to the
+ host.
+
+ TODO:
+ * Emulate Music Publisher music notation input pad
+ * Emulate Assimilation Process keypad (and trackball)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "mackbd.h"
+
+
+DEFINE_DEVICE_TYPE(MAC_KEYBOARD_PORT, mac_keyboard_port_device, "mackbd_port", "Macintosh 128k/512k/Plus Keyboard Port")
+
+
+//**************************************************************************
+// HOST PORT
+//**************************************************************************
+
+mac_keyboard_port_device::mac_keyboard_port_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MAC_KEYBOARD_PORT, tag, owner, clock)
+ , device_single_card_slot_interface<device_mac_keyboard_interface>(mconfig, *this)
+ , m_clock_cb{ *this }
+ , m_data_cb{ *this }
+ , m_peripheral{ nullptr }
+{
+}
+
+mac_keyboard_port_device::~mac_keyboard_port_device()
+{
+}
+
+WRITE_LINE_MEMBER(mac_keyboard_port_device::data_w)
+{
+ if (m_peripheral)
+ m_peripheral->data_w(state);
+}
+
+void mac_keyboard_port_device::device_resolve_objects()
+{
+ m_clock_cb.resolve_safe();
+ m_data_cb.resolve_safe();
+}
+
+void mac_keyboard_port_device::device_start()
+{
+ m_peripheral = dynamic_cast<device_mac_keyboard_interface *>(get_card_device());
+}
+
+
+//**************************************************************************
+// PERIPHERAL INTERFACE
+//**************************************************************************
+
+device_mac_keyboard_interface::device_mac_keyboard_interface(machine_config const &mconfig, device_t &device)
+ : device_interface(device, "mackbd")
+ , m_host{ dynamic_cast<mac_keyboard_port_device *>(device.owner()) }
+{
+}
+
+device_mac_keyboard_interface::~device_mac_keyboard_interface()
+{
+}
+
+void device_mac_keyboard_interface::interface_validity_check(validity_checker &valid) const
+{
+ device_t *const owner(device().owner());
+ if (owner && dynamic_cast<device_slot_interface *>(owner) && !dynamic_cast<mac_keyboard_port_device *>(owner))
+ osd_printf_error("Device %s (%s) is not a Macintosh keyboard port\n", owner->tag(), owner->name());
+}
+
+
+//**************************************************************************
+// SUPPORTED DEVICES
+//**************************************************************************
+
+#include "keyboard.h"
+#include "pluskbd.h"
+
+
+void mac_keyboard_devices(device_slot_interface &device)
+{
+ device.option_add("us", MACKBD_M0110);
+ device.option_add("gb", MACKBD_M0110B);
+ device.option_add("fr", MACKBD_M0110F);
+
+ device.option_add("pad", MACKBD_M0120);
+
+ device.option_add("plus", MACKBD_M0110A);
+}
diff --git a/src/devices/bus/mackbd/mackbd.h b/src/devices/bus/mackbd/mackbd.h
new file mode 100644
index 00000000000..29be2d6e4ea
--- /dev/null
+++ b/src/devices/bus/mackbd/mackbd.h
@@ -0,0 +1,91 @@
+// license: BSD-3-Clause
+// copyright-holders: Vas Crabb
+/***************************************************************************
+
+ Mac 128k/512k/Plus keyboard interface (pre-ADB)
+
+ 4p4c RJ11 connector (cables wired straight through):
+ 1: power/signal ground (black)
+ 2: clock (red, peripheral to host)
+ 3: data (green, bidirectional)
+ 4: +5V power (yellow, maximum 200mA for all peripherals)
+
+***************************************************************************/
+#ifndef MAME_BUS_MACKBD_MACKBD_H
+#define MAME_BUS_MACKBD_MACKBD_H
+
+#pragma once
+
+
+class device_mac_keyboard_interface;
+
+DECLARE_DEVICE_TYPE(MAC_KEYBOARD_PORT, mac_keyboard_port_device)
+
+void mac_keyboard_devices(device_slot_interface &device);
+
+
+//**************************************************************************
+// HOST PORT
+//**************************************************************************
+
+class mac_keyboard_port_device : public device_t, public device_single_card_slot_interface<device_mac_keyboard_interface>
+{
+public:
+ template <typename T>
+ mac_keyboard_port_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
+ : mac_keyboard_port_device(mconfig, tag, owner, 0U)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+ mac_keyboard_port_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0U);
+ virtual ~mac_keyboard_port_device() override;
+
+ auto clock_cb() { return m_clock_cb.bind(); }
+ auto data_cb() { return m_data_cb.bind(); }
+
+ DECLARE_WRITE_LINE_MEMBER(data_w);
+
+protected:
+ virtual void device_resolve_objects() override;
+ virtual void device_start() override;
+
+private:
+ devcb_write_line m_clock_cb;
+ devcb_write_line m_data_cb;
+
+ device_mac_keyboard_interface *m_peripheral;
+
+ friend class device_mac_keyboard_interface;
+};
+
+
+//**************************************************************************
+// PERIPHERAL INTERFACE
+//**************************************************************************
+
+class device_mac_keyboard_interface : public device_interface
+{
+public:
+ virtual ~device_mac_keyboard_interface() override;
+
+protected:
+ device_mac_keyboard_interface(machine_config const &mconfig, device_t &device);
+
+ virtual void interface_validity_check(validity_checker &valid) const override;
+
+ DECLARE_WRITE_LINE_MEMBER(write_clock) { if (m_host) m_host->m_clock_cb(state); }
+ DECLARE_WRITE_LINE_MEMBER(write_data) { if (m_host) m_host->m_data_cb(state); }
+
+ virtual DECLARE_WRITE_LINE_MEMBER(data_w) = 0;
+
+private:
+ mac_keyboard_port_device *const m_host;
+
+ friend class mac_keyboard_port_device;
+};
+
+
+#endif // MAME_BUS_MACKBD_MACKBD_H
diff --git a/src/devices/bus/mackbd/pluskbd.cpp b/src/devices/bus/mackbd/pluskbd.cpp
new file mode 100644
index 00000000000..e67735bfb56
--- /dev/null
+++ b/src/devices/bus/mackbd/pluskbd.cpp
@@ -0,0 +1,311 @@
+// license: BSD-3-Clause
+// copyright-holders: Vas Crabb
+/***************************************************************************
+
+ Apple M0110A keyboard with integrated keypad
+
+ This keyboard was only available in U.S./ANSI layout. International
+ markets continued to receive the M0110/M0120 keyboard/keypad.
+
+ Emulation based entirely on examining the MPU program and observing
+ behaviour. There may be additional hardware in the keyboard that is
+ not emulated (e.g. a watchdog timer).
+
+ +-----------+---------------+
+ | Pin | Keyboard |
+ +-----------+---------------+
+ | P10 (27) | row drive |
+ | P11 (28) | row drive |
+ | P12 (29) | row drive |
+ | P13 (30) | row drive |
+ | P14 (31) | row drive |
+ | P15 (32) | row drive |
+ | P16 (33) | row drive |
+ | P17 (34) | row drive |
+ +-----------+---------------+
+ | P20 (21) | row drive |
+ | P21 (22) | row drive |
+ | P22 (23) | Shift |
+ | P23 (24) | Caps Lock |
+ | P24 (35) | Option |
+ | P25 (36) | Command |
+ | P26 (37) | host clock |
+ | P27 (38) | host data |
+ +-----------+---------------+
+ | DB0 (12) | column read |
+ | DB1 (13) | column read |
+ | DB2 (14) | column read |
+ | DB3 (15) | column read |
+ | DB4 (16) | column read |
+ | DB5 (17) | column read |
+ | DB6 (18) | column read |
+ | DB6 (19) | column read |
+ +-----------+---------------+
+
+ +-----+-----------------------------------------------------------+
+ | | P10 P11 P12 P13 P14 P15 P16 P17 P20 P21 |
+ +-----+-----------------------------------------------------------+
+ | DB0 | \ Left Right Down KP0 KP. Ent |
+ | DB1 | KP* KP/ KP= Clear Bsp = - 0 Z |
+ | DB2 | KP8 KP9 KP- Up KP1 KP2 KP3 KP+ KP7 |
+ | DB3 | P [ ] ' Rtn KP4 KP5 KP6 Spc |
+ | DB4 | D F G H J K L ; A S |
+ | DB5 | W E R T Y U I O Tab Q |
+ | DB6 | 2 3 4 5 6 7 8 9 ` 1 |
+ | DB7 | V B N M , . / X C |
+ +-----+-----------------------------------------------------------+
+
+***************************************************************************/
+
+#include "emu.h"
+#include "pluskbd.h"
+
+#include "cpu/mcs48/mcs48.h"
+
+#define LOG_GENERAL (1U << 0)
+#define LOG_MATRIX (1U << 1)
+#define LOG_COMM (1U << 2)
+
+//#define VERBOSE (LOG_GENERAL | LOG_MATRIX | LOG_COMM)
+//#define LOG_OUTPUT_STREAM std::cerr
+#include "logmacro.h"
+
+#define LOGMATRIX(...) LOGMASKED(LOG_MATRIX, __VA_ARGS__)
+#define LOGCOMM(...) LOGMASKED(LOG_COMM, __VA_ARGS__)
+
+
+namespace {
+
+ROM_START(keyboard)
+ ROM_REGION(0x0400, "mpu", 0)
+ ROM_LOAD("341-0332-a.bin", 0x000000, 0x000400, CRC(6554f5b6) SHA1(a80404a122d74721cda13b285c412057c2c78bd7))
+ROM_END
+
+
+class m0110a_device : public device_t, public device_mac_keyboard_interface
+{
+public:
+ m0110a_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MACKBD_M0110A, tag, owner, clock)
+ , device_mac_keyboard_interface(mconfig, *this)
+ , m_mpu{ *this, "mpu" }
+ , m_rows{ *this, "ROW%u", 0U }
+ {
+ }
+
+ CUSTOM_INPUT_MEMBER(host_data_r)
+ {
+ return m_host_data_in ^ 0x01;
+ }
+
+protected:
+ virtual tiny_rom_entry const *device_rom_region() const override
+ {
+ return ROM_NAME(keyboard);
+ }
+
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ I8048(config, m_mpu, 6'000'000); // clock frequency unconfirmed
+ m_mpu->p1_out_cb().set(FUNC(m0110a_device::p1_w));
+ m_mpu->p2_in_cb().set_ioport("P2");
+ m_mpu->p2_out_cb().set(FUNC(m0110a_device::p2_w));
+ m_mpu->bus_in_cb().set(FUNC(m0110a_device::bus_r));
+ }
+
+ virtual void device_start() override
+ {
+ m_row_drive = 0x03ffU;
+ m_host_clock_out = 1U;
+ m_host_data_out = 1U;
+ m_host_data_in = 0x01U;
+
+ save_item(NAME(m_row_drive));
+ save_item(NAME(m_host_clock_out));
+ save_item(NAME(m_host_data_out));
+ save_item(NAME(m_host_data_in));
+ }
+
+ virtual DECLARE_WRITE_LINE_MEMBER(data_w) override
+ {
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(m0110a_device::update_host_data), this), state);
+ }
+
+private:
+ void p1_w(u8 data)
+ {
+ m_row_drive = (m_row_drive & 0x0300) | u16(data);
+ }
+
+ void p2_w(u8 data)
+ {
+ m_row_drive = (m_row_drive & 0x00ff) | (u16(data & 0x03) << 8);
+
+ if (BIT(data, 6) != m_host_clock_out)
+ {
+ if (BIT(data, 6))
+ LOGCOMM("%s: host clock out 0 -> 1 data=%u\n", machine().describe_context(), (m_host_data_out && m_host_data_in) ? 1U : 0U);
+ else
+ LOGCOMM("%s: host clock out 1 -> 0\n", machine().describe_context());
+ write_clock(m_host_clock_out = BIT(data, 6));
+ }
+
+ if (BIT(data, 7) != m_host_data_out)
+ {
+ LOGCOMM("%s: host data out %u -> %u\n", machine().describe_context(), m_host_data_out, BIT(data, 7));
+ write_data(m_host_data_out = BIT(data, 7));
+ }
+ }
+
+ u8 bus_r()
+ {
+ u8 result(0xffU);
+ for (unsigned i = 0U; m_rows.size() > i; ++i)
+ {
+ if (!BIT(m_row_drive, i))
+ result &= m_rows[i]->read();
+ }
+ LOGMATRIX("read matrix: row drive = %X, result = %X\n", m_row_drive, result);
+ return result;
+ }
+
+ TIMER_CALLBACK_MEMBER(update_host_data)
+ {
+ if (bool(param) != bool(m_host_data_in))
+ {
+ LOGCOMM("host data in %u -> %u\n", m_host_data_in, param ? 1U : 0U);
+ m_host_data_in = param ? 0x01U : 0x00U;
+ }
+ }
+
+ required_device<mcs48_cpu_device> m_mpu;
+ required_ioport_array<10> m_rows;
+
+ u16 m_row_drive = 0x03ffU; // current bit pattern driving rows (active low)
+ u8 m_host_clock_out = 1U; // clock line drive to host (idle high)
+ u8 m_host_data_out = 1U; // data line drive to host (idle high)
+ u8 m_host_data_in = 0x01U; // data line drive from host (idle high)
+};
+
+
+INPUT_PORTS_START(keyboard)
+ PORT_START("ROW0")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR(UCHAR_MAMEKEY(ASTERISK)) PORT_NAME("Keypad *")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) PORT_NAME("Keypad 8")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
+
+ PORT_START("ROW1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|')
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH_PAD) PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD)) PORT_NAME("Keypad /")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) PORT_NAME("Keypad 9")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
+
+ PORT_START("ROW2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS_PAD) PORT_CHAR(UCHAR_MAMEKEY(EQUALS_PAD)) PORT_NAME("Keypad =")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PORT_NAME("Keypad -")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
+
+ PORT_START("ROW3")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK)) PORT_NAME("Keypad Clear")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
+
+ PORT_START("ROW4")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(0x08) PORT_NAME("Backspace")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) PORT_NAME("Keypad 1")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(0x0d) PORT_NAME("Return")
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
+
+ PORT_START("ROW5")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) PORT_NAME("Keypad 0")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) PORT_NAME("Keypad 2")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) PORT_NAME("Keypad 4")
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
+
+ PORT_START("ROW6")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) PORT_NAME("Keypad .")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) PORT_NAME("Keypad 3")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) PORT_NAME("Keypad 5")
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
+
+ PORT_START("ROW7")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) PORT_NAME("Keypad Enter")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD)) PORT_NAME("Keypad +")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) PORT_NAME("Keypad 6")
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("ROW8")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR(0x09) PORT_NAME("Tab")
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
+
+ PORT_START("ROW9")
+ PORT_BIT(0x03, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) PORT_NAME("Keypad 7")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
+
+ PORT_START("P2")
+ PORT_BIT(0x43, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) PORT_NAME("Shift")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_NAME("Caps Lock") PORT_TOGGLE
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LALT) PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_SHIFT_2) PORT_NAME("Option")
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_NAME("Command")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_CUSTOM_MEMBER(m0110a_device, host_data_r)
+INPUT_PORTS_END
+
+
+ioport_constructor m0110a_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(keyboard);
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MACKBD_M0110A, device_mac_keyboard_interface, m0110a_device, "mackbd_m0110a", "Macintosh Plus Keyboard (U.S. - M0110A)")
diff --git a/src/devices/bus/mackbd/pluskbd.h b/src/devices/bus/mackbd/pluskbd.h
new file mode 100644
index 00000000000..cf84a8ed6ed
--- /dev/null
+++ b/src/devices/bus/mackbd/pluskbd.h
@@ -0,0 +1,17 @@
+// license: BSD-3-Clause
+// copyright-holders: Vas Crabb
+/***************************************************************************
+
+ Apple M0110A keyboard with integrated keypad
+
+***************************************************************************/
+#ifndef MAME_BUS_MACKBD_PLUSKBD_H
+#define MAME_BUS_MACKBD_PLUSKBD_H
+
+#pragma once
+
+#include "mackbd.h"
+
+DECLARE_DEVICE_TYPE(MACKBD_M0110A, device_mac_keyboard_interface)
+
+#endif // MAME_BUS_MACKBD_PLUSKBD_H
diff --git a/src/devices/cpu/mcs48/mcs48.h b/src/devices/cpu/mcs48/mcs48.h
index 572c09b6bec..ec43d71d34f 100644
--- a/src/devices/cpu/mcs48/mcs48.h
+++ b/src/devices/cpu/mcs48/mcs48.h
@@ -511,6 +511,10 @@ protected:
class i8021_device : public mcs48_cpu_device
{
public:
+ // configuration
+ auto p0_in_cb() { return bus_in_cb(); }
+ auto p0_out_cb() { return bus_out_cb(); }
+
// construction/destruction
i8021_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
diff --git a/src/emu/ioport.cpp b/src/emu/ioport.cpp
index 281563935c3..cd8f49fe0d6 100644
--- a/src/emu/ioport.cpp
+++ b/src/emu/ioport.cpp
@@ -1378,7 +1378,7 @@ ioport_field_live::ioport_field_live(ioport_field &field, analog_field *analog)
if (field.type_class() == INPUT_CLASS_KEYBOARD && field.specific_name() == nullptr)
{
// loop through each character on the field
- for (int which = 0; which < 4; which++)
+ for (int which = 0; which < (1 << (UCHAR_SHIFT_END - UCHAR_SHIFT_BEGIN + 1)); which++)
{
std::vector<char32_t> const codes = field.keyboard_codes(which);
if (codes.empty())
diff --git a/src/emu/natkeyboard.cpp b/src/emu/natkeyboard.cpp
index 110e0462b6d..53a95f46a4b 100644
--- a/src/emu/natkeyboard.cpp
+++ b/src/emu/natkeyboard.cpp
@@ -660,9 +660,9 @@ void natural_keyboard::build_codes(ioport_manager &manager)
newcode.field[fieldnum] = &field;
if (m_keycode_map.end() == found)
{
- keycode_map_list map_list;
- map_list.emplace_back(newcode);
- m_keycode_map.emplace(code, map_list);
+ keycode_map_entries entries;
+ entries.emplace_back(newcode);
+ m_keycode_map.emplace(code, std::move(entries));
}
else
found->second.emplace_back(newcode);
@@ -679,6 +679,15 @@ void natural_keyboard::build_codes(ioport_manager &manager)
}
}
}
+
+ // sort mapping entries by shift state
+ for (auto &mapping : m_keycode_map)
+ {
+ std::sort(
+ mapping.second.begin(),
+ mapping.second.end(),
+ [] (keycode_map_entry const &x, keycode_map_entry const &y) { return x.shift < y.shift; });
+ }
}
@@ -880,7 +889,8 @@ std::string natural_keyboard::unicode_to_string(char32_t ch) const
const natural_keyboard::keycode_map_entry *natural_keyboard::find_code(char32_t ch) const
{
keycode_map::const_iterator const found(m_keycode_map.find(ch));
- if (m_keycode_map.end() == found) return nullptr;
+ if (m_keycode_map.end() == found)
+ return nullptr;
for (keycode_map_entry const &entry : found->second)
{
if (entry.condition.eval())
diff --git a/src/emu/natkeyboard.h b/src/emu/natkeyboard.h
index d99e0cdf009..d411eb74173 100644
--- a/src/emu/natkeyboard.h
+++ b/src/emu/natkeyboard.h
@@ -76,8 +76,8 @@ private:
unsigned shift;
ioport_condition condition;
};
- typedef std::list<keycode_map_entry> keycode_map_list;
- typedef std::unordered_map<char32_t, keycode_map_list> keycode_map;
+ typedef std::vector<keycode_map_entry> keycode_map_entries;
+ typedef std::unordered_map<char32_t, keycode_map_entries> keycode_map;
// internal helpers
void build_codes(ioport_manager &manager);
diff --git a/src/mame/drivers/mac128.cpp b/src/mame/drivers/mac128.cpp
index 2f9afee825b..46afd8d8e44 100644
--- a/src/mame/drivers/mac128.cpp
+++ b/src/mame/drivers/mac128.cpp
@@ -80,15 +80,14 @@ c0 8 data bits, Rx disabled
#include "emu.h"
-#include "machine/mackbd.h"
#include "machine/macrtc.h"
+#include "bus/mackbd/mackbd.h"
#include "bus/macpds/hyperdrive.h"
#include "bus/scsi/scsicd.h"
#include "bus/scsi/scsi.h"
#include "bus/scsi/scsihd.h"
#include "cpu/m68000/m68000.h"
-#include "cpu/powerpc/ppc.h"
#include "machine/6522via.h"
#include "machine/applefdc.h"
#include "machine/ncr5380.h"
@@ -151,7 +150,7 @@ public:
m_ram(*this, RAM_TAG),
m_ncr5380(*this, "ncr5380"),
m_iwm(*this, "fdc"),
- m_mackbd(*this, "mackbd"),
+ m_mackbd(*this, "kbd"),
m_rtc(*this,"rtc"),
m_mouse0(*this, "MOUSE0"),
m_mouse1(*this, "MOUSE1"),
@@ -176,7 +175,7 @@ private:
required_device<ram_device> m_ram;
optional_device<ncr5380_device> m_ncr5380;
required_device<applefdc_base_device> m_iwm;
- required_device<mackbd_device> m_mackbd;
+ required_device<mac_keyboard_port_device> m_mackbd;
optional_device<rtc3430042_device> m_rtc;
required_ioport m_mouse0, m_mouse1, m_mouse2;
@@ -967,12 +966,12 @@ void mac128_state::mac512ke(machine_config &config)
m_via->readpb_handler().set(FUNC(mac128_state::mac_via_in_b));
m_via->writepa_handler().set(FUNC(mac128_state::mac_via_out_a));
m_via->writepb_handler().set(FUNC(mac128_state::mac_via_out_b));
- m_via->cb2_handler().set(m_mackbd, FUNC(mackbd_device::datain_w));
+ m_via->cb2_handler().set(m_mackbd, FUNC(mac_keyboard_port_device::data_w));
m_via->irq_handler().set(FUNC(mac128_state::mac_via_irq));
- MACKBD(config, m_mackbd, 0);
- m_mackbd->dataout_handler().set(m_via, FUNC(via6522_device::write_cb2));
- m_mackbd->clkout_handler().set(m_via, FUNC(via6522_device::write_cb1)).invert();
+ MAC_KEYBOARD_PORT(config, m_mackbd, mac_keyboard_devices, "pad");
+ m_mackbd->clock_cb().set(m_via, FUNC(via6522_device::write_cb1)).invert();
+ m_mackbd->data_cb().set(m_via, FUNC(via6522_device::write_cb2));
/* internal ram */
RAM(config, m_ram);
@@ -998,6 +997,8 @@ void mac128_state::macplus(machine_config &config)
mac512ke(config);
m_maincpu->set_addrmap(AS_PROGRAM, &mac128_state::macplus_map);
+ m_mackbd->set_default_option("plus");
+
scsi_port_device &scsibus(SCSI_PORT(config, "scsi"));
scsibus.set_slot_device(1, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_6));
scsibus.set_slot_device(2, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_5));
diff --git a/src/mame/machine/mackbd.cpp b/src/mame/machine/mackbd.cpp
deleted file mode 100644
index 4918cc8e875..00000000000
--- a/src/mame/machine/mackbd.cpp
+++ /dev/null
@@ -1,287 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:R. Belmont
-/*
- Apple Macintosh original/512/Plus keyboard
- Emulation by R. Belmont
-
- Port definitions from "IM Underground Volume 1"
- http://bitsavers.org/pdf/apple/mac/IM_Underground_Vol_1_1985.pdf
-
- Key matrix for keyboard:
-
- Cols 0 1 2 3 4 5 6 7 8 Rows
- G B T 5 0 P ; . n/a 0
- H n/a Y 6 8 I K M Enter 1
- F V R 4 - [ ' N Backsp 2
- D C E 3 7 U J / ` 3
- S X W 2 9 O L , Space 4
- A Z Q 1 = ] Ret \ Tab 5
-
- Port 0:
-
- x------- Clock, pulled up, driven by the 8021
- -x------ Caps Lock
- --x----- Row 5 readback (tied to Vcc for keypad)
- ---x---- Row 4 readback
- ----x--- Row 3 readback
- -----x-- Row 2 readback
- ------x- Row 1 readback
- -------x Row 0 readback
-
- Port 1:
-
- x------- Column 8 strobe
- -x------ Column 7 strobe
- --x----- Column 6 strobe
- ---x---- Column 5 strobe
- ----x--- Column 4 strobe
- -----x-- Column 3 strobe
- ------x- Column 2 strobe
- -------x Column 1 strobe
-
- Port 2:
- x--- Command/Apple
- -x-- Shift
- --x- Column 0 strobe
- ---x Data, pulled up, driven by both sides
-
- The T1 line is "Option".
-
- There is a later M0110 keyboard version which uses a GI PIC1657; we do not have a dump of that version.
-*/
-
-
-#include "emu.h"
-#include "mackbd.h"
-#include "cpu/mcs48/mcs48.h"
-
-//**************************************************************************
-// MACROS / CONSTANTS
-//**************************************************************************
-
-#define MACKBD_CPU_TAG "mackbd"
-
-//**************************************************************************
-// DEVICE DEFINITIONS
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(MACKBD, mackbd_device, "mackbd", "Macintosh Keyboard")
-
-ROM_START( mackbd )
- ROM_REGION(0x800, MACKBD_CPU_TAG, 0)
- // original Mac keyboard and optional external keypad
- ROM_LOAD( "ip8021h_2173.bin", 0x000000, 0x000400, CRC(5fbd9a94) SHA1(32a3b58afb445a8675b12a4de3aec2fa00c99222) )
- // Mac Plus all-in-one keyboard (not yet supported)
- ROM_LOAD( "341-0332-a.bin", 0x000400, 0x000400, CRC(6554f5b6) SHA1(a80404a122d74721cda13b285c412057c2c78bd7) )
-ROM_END
-
-
-static INPUT_PORTS_START( mackbd )
- PORT_START("COL0")
- PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
- PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
- PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
- PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
- PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
- PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
-
- PORT_START("COL1")
- PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
- PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_UNKNOWN)
- PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
- PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
- PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
- PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
-
- PORT_START("COL2")
- PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
- PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
- PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
- PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
- PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
- PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
-
- PORT_START("COL3")
- PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
- PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^')
- PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
- PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
- PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@')
- PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
-
- PORT_START("COL4")
- PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
- PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')
- PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_')
- PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')
- PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
- PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
-
- PORT_START("COL5")
- PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
- PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
- PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{')
- PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
- PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
- PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')
-
- PORT_START("COL6")
- PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
- PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
- PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"')
- PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
- PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
- PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR('\r') PORT_NAME("Return")
-
- PORT_START("COL7")
- PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
- PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
- PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
- PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
- PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
- PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|')
-
- PORT_START("COL8")
- PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_UNKNOWN)
- PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_UNKNOWN)
- PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
- PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~')
- PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
- PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR('\t')
-
- PORT_START("MODS")
- PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Caps Lock") PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE
- PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Option") PORT_CODE(KEYCODE_LALT) PORT_CHAR(UCHAR_SHIFT_2)
- PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
- PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Command") PORT_CODE(KEYCODE_LCONTROL)
-INPUT_PORTS_END
-
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
-
-void mackbd_device::device_add_mconfig(machine_config &config)
-{
- mcs48_cpu_device &cpu(I8021(config, m_maincpu, 3000000)); // "the approximate clock rate of the MPU is 3 MHz"
- cpu.bus_in_cb().set(FUNC(mackbd_device::p0_r));
- cpu.bus_out_cb().set(FUNC(mackbd_device::p0_w));
- cpu.p1_in_cb().set(FUNC(mackbd_device::p1_r));
- cpu.p1_out_cb().set(FUNC(mackbd_device::p1_w));
- cpu.p2_in_cb().set(FUNC(mackbd_device::p2_r));
- cpu.p2_out_cb().set(FUNC(mackbd_device::p2_w));
- cpu.t1_in_cb().set_ioport("MODS").bit(1); // option
-}
-
-const tiny_rom_entry *mackbd_device::device_rom_region() const
-{
- return ROM_NAME( mackbd );
-}
-
-ioport_constructor mackbd_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME( mackbd );
-}
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// mackbd_device - constructor
-//-------------------------------------------------
-
-mackbd_device::mackbd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, MACKBD, tag, owner, clock),
- m_maincpu(*this, MACKBD_CPU_TAG),
- m_col(*this, "COL%u", 0U),
- m_clkout_handler(*this),
- m_dataout_handler(*this)
-{
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void mackbd_device::device_start()
-{
- m_clkout_handler.resolve_safe();
- m_dataout_handler.resolve_safe();
- m_sync = timer_alloc(0);
-}
-
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void mackbd_device::device_reset()
-{
- p0 = p1 = p2 = 0xff;
- datain = true;
- m_clkout_handler(1);
- m_dataout_handler(1);
-}
-
-u8 mackbd_device::p0_r()
-{
- u8 ret = p0;
-
- for(int i=0; i<8; i++)
- if(!(p1 & (1<<i)))
- ret &= m_col[i+1]->read();
-
- if(!(p2 & 0x02))
- ret &= m_col[0]->read();
-
- // capslock
- if(!(ioport("MODS")->read() & 0x1))
- ret &= ~0x40;
-
- return ret;
-}
-
-void mackbd_device::p0_w(u8 data)
-{
- u8 delta = p0 ^ data;
- p0 = data;
-
- if(delta & 0x80)
- m_sync->adjust(attotime::zero);
-}
-
-void mackbd_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- m_clkout_handler(p0 & 0x80 ? ASSERT_LINE : CLEAR_LINE);
-}
-
-u8 mackbd_device::p1_r()
-{
- return p1;
-}
-
-void mackbd_device::p1_w(u8 data)
-{
- p1 = data;
-}
-
-u8 mackbd_device::p2_r()
-{
- // Keypad has bit 5 connected to GND, but this is the keyboard.
- u8 ret = p2;
- if(!datain)
- ret &= 0xfe;
- ret &= ioport("MODS")->read() | ~0x0c;
- return ret;
-}
-
-void mackbd_device::p2_w(u8 data)
-{
- p2 = data;
- m_dataout_handler(p2 & datain & 1);
-}
-
-void mackbd_device::datain_w(int state)
-{
- datain = state;
-}
diff --git a/src/mame/machine/mackbd.h b/src/mame/machine/mackbd.h
deleted file mode 100644
index 01cb62c68b2..00000000000
--- a/src/mame/machine/mackbd.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:R. Belmont
-#ifndef MAME_MACHINE_MACKBD_H
-#define MAME_MACHINE_MACKBD_H
-
-#pragma once
-
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> mackbd_device
-
-class mackbd_device : public device_t
-{
-public:
- // config helper
- auto clkout_handler() { return m_clkout_handler.bind(); }
- auto dataout_handler() { return m_dataout_handler.bind(); }
- void datain_w(int state);
-
- // construction/destruction
- mackbd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-
-private:
- required_device<cpu_device> m_maincpu;
- required_ioport_array<9> m_col;
- devcb_write_line m_clkout_handler;
- devcb_write_line m_dataout_handler;
- emu_timer *m_sync;
-
- u8 p0, p1, p2;
- bool datain;
-
- void scan_kbd_col(int col);
-
- u8 p0_r();
- void p0_w(u8 data);
- u8 p1_r();
- void p1_w(u8 data);
- u8 p2_r();
- void p2_w(u8 data);
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(MACKBD, mackbd_device)
-
-#endif // MAME_MACHINE_MACKBD_H