diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/devices/bus/mackbd/keyboard.cpp | 677 | ||||
-rw-r--r-- | src/devices/bus/mackbd/keyboard.h | 21 | ||||
-rw-r--r-- | src/devices/bus/mackbd/mackbd.cpp | 162 | ||||
-rw-r--r-- | src/devices/bus/mackbd/mackbd.h | 91 | ||||
-rw-r--r-- | src/devices/bus/mackbd/pluskbd.cpp | 311 | ||||
-rw-r--r-- | src/devices/bus/mackbd/pluskbd.h | 17 | ||||
-rw-r--r-- | src/devices/cpu/mcs48/mcs48.h | 4 | ||||
-rw-r--r-- | src/emu/ioport.cpp | 2 | ||||
-rw-r--r-- | src/emu/natkeyboard.cpp | 18 | ||||
-rw-r--r-- | src/emu/natkeyboard.h | 4 | ||||
-rw-r--r-- | src/mame/drivers/mac128.cpp | 17 | ||||
-rw-r--r-- | src/mame/machine/mackbd.cpp | 287 | ||||
-rw-r--r-- | src/mame/machine/mackbd.h | 58 |
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 |