mirror of
https://github.com/holub/mame
synced 2025-04-19 07:00:31 +03:00

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
.
-----------------------------------------------------------------------
163 lines
5.9 KiB
C++
163 lines
5.9 KiB
C++
// 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);
|
|
}
|