Slotified Mac 128k/512k/512ke/Plus keyboard port.

Available keyboards are us (M0110, U.S.), gb (M0110B, British), fr
(M0110F, French), pad (M0120F, numeric keypad with passthrough port)
and plus (M0110A, U.S. with integrated numeric keypad).  The mac128k,
mac512k and mac512ke drivers default to the numeric keypad with the
U.S. keyboard connected to the passthrough port; the macplus driver
defaults to the U.S. keyboard with integrated numeric keypad.

Note that the numeric keypad may seem strange.  Four of the operators
work as cursor arrows if you don't hold shift.  There is a comma on one
of the keys, but by the time System 6 was released, Apple had decided
an equals sign was more useful, so that's what it will produces on
newer system versions.  The U.S. keyboard with integrated numeric
keypad emulates these aspects of the stand-alone keypad - pressing the
operator keys on the keypad sends fake shit key down/up events, and
using the arrow keys while holding shift will produces operator
characters rather than selecting text.

The ISO layout keyboards (M0110B and M0110F) produce different scan
codes to the ANSI keyboards (M0110 and M0110A) but they don't report a
different identification byte.  To use an ISO keyboard, you must open
the Keyboard control panel and change the layout to International (and
change it back to Domestic if you switch back to an ANSI keyboard).

This doesn't actually work at the moment due to issues with 6522 VIA
emulation, but it will work with macplus sys603 if applied on top of
revision 963a2c166d.
-----------------------------------------------------------------------
This commit is contained in:
Vas Crabb 2020-07-01 02:23:16 +10:00
parent 706c599f73
commit 802de3995d
15 changed files with 1326 additions and 362 deletions

View File

@ -3507,6 +3507,22 @@ if (BUSES["SCSI"]~=null) then
}
end
---------------------------------------------------
--
--@src/devices/bus/mackbd/mackbd.h,BUSES["MACKBD"] = true
---------------------------------------------------
if (BUSES["MACKBD"]~=null) then
files {
MAME_DIR .. "src/devices/bus/mackbd/keyboard.cpp",
MAME_DIR .. "src/devices/bus/mackbd/keyboard.h",
MAME_DIR .. "src/devices/bus/mackbd/mackbd.cpp",
MAME_DIR .. "src/devices/bus/mackbd/mackbd.h",
MAME_DIR .. "src/devices/bus/mackbd/pluskbd.cpp",
MAME_DIR .. "src/devices/bus/mackbd/pluskbd.h",
}
end
---------------------------------------------------
--
--@src/devices/bus/macpds/macpds.h,BUSES["MACPDS"] = true

View File

@ -856,6 +856,7 @@ BUSES["HP9845_IO"] = true
BUSES["KC"] = true
BUSES["LPCI"] = true
BUSES["M5"] = true
BUSES["MACKBD"] = true
BUSES["MACPDS"] = true
BUSES["MIDI"] = true
BUSES["MEGADRIVE"] = true
@ -1736,8 +1737,6 @@ files {
MAME_DIR .. "src/mame/machine/macadb.h",
MAME_DIR .. "src/mame/machine/macrtc.cpp",
MAME_DIR .. "src/mame/machine/macrtc.h",
MAME_DIR .. "src/mame/machine/mackbd.cpp",
MAME_DIR .. "src/mame/machine/mackbd.h",
MAME_DIR .. "src/mame/machine/swim.cpp",
MAME_DIR .. "src/mame/machine/swim.h",
MAME_DIR .. "src/mame/video/mac.cpp",

View File

@ -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)")

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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)")

View File

@ -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

View File

@ -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);

View File

@ -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())

View File

@ -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())

View File

@ -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);

View File

@ -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));

View File

@ -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;
}

View File

@ -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