diff options
author | Vas Crabb <vas@vastheman.com> | 2016-07-27 23:22:14 +1000 |
---|---|---|
committer | Vas Crabb <vas@vastheman.com> | 2016-07-27 23:22:14 +1000 |
commit | 334e948fdab587365b9224e56d909d25d7165d66 (patch) | |
tree | 55a52c7627e3db092e420a9477b01781460ab5be | |
parent | d061b1ddb3a8a744ec46351d0dca739c2aa10efc (diff) |
keyboard improvements: [Vas Crabb:
* Fix repeat delay/rate in x68000
* Make HLE Sun keyboard use common matrix keyboard routines
* Add linefeed key to generic keyboard (maps to ins by default)
-rw-r--r-- | src/devices/bus/sunkbd/hlekbd.cpp | 134 | ||||
-rw-r--r-- | src/devices/bus/sunkbd/hlekbd.h | 21 | ||||
-rw-r--r-- | src/devices/machine/keyboard.cpp | 16 | ||||
-rw-r--r-- | src/devices/machine/keyboard.h | 2 | ||||
-rw-r--r-- | src/devices/machine/keyboard.ipp | 14 | ||||
-rw-r--r-- | src/mame/machine/x68k_kbd.cpp | 8 |
6 files changed, 97 insertions, 98 deletions
diff --git a/src/devices/bus/sunkbd/hlekbd.cpp b/src/devices/bus/sunkbd/hlekbd.cpp index 54355cf376d..48491222bad 100644 --- a/src/devices/bus/sunkbd/hlekbd.cpp +++ b/src/devices/bus/sunkbd/hlekbd.cpp @@ -2,7 +2,7 @@ // copyright-holders:Vas Crabb #include "hlekbd.h" -#include <numeric> +#include "machine/keyboard.ipp" /* @@ -761,24 +761,18 @@ hle_device_base::hle_device_base( : device_t(mconfig, type, name, tag, owner, clock, shortname, source) , device_serial_interface(mconfig, *this) , device_sun_keyboard_port_interface(mconfig, *this) + , device_matrix_keyboard_interface(mconfig, *this, "ROW0", "ROW1", "ROW2", "ROW3", "ROW4", "ROW5", "ROW6", "ROW7") , m_dips(*this, "DIP") - , m_key_inputs{ - { *this, "ROW0" }, { *this, "ROW1" }, - { *this, "ROW2" }, { *this, "ROW3" }, - { *this, "ROW4" }, { *this, "ROW5" }, - { *this, "ROW6" }, { *this, "ROW7" } } - , m_scan_timer(nullptr) , m_click_timer(nullptr) , m_beeper(*this, "beeper") - , m_current_keys{ 0, 0, 0, 0, 0, 0, 0, 0 } - , m_next_row(0) , m_fifo{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } - , m_head(0) - , m_tail(0) - , m_empty(0) + , m_head(0U) + , m_tail(0U) + , m_empty(0U) + , m_make_count(0U) , m_rx_state(RX_IDLE) - , m_keyclick(0) - , m_beeper_state(0) + , m_keyclick(0U) + , m_beeper_state(0U) { } @@ -825,15 +819,13 @@ void hle_device_base::device_start() { device_serial_interface::register_save_state(machine().save(), this); - m_scan_timer = timer_alloc(SCAN_TIMER_ID); m_click_timer = timer_alloc(CLICK_TIMER_ID); - save_item(NAME(m_current_keys)); - save_item(NAME(m_next_row)); save_item(NAME(m_fifo)); save_item(NAME(m_head)); save_item(NAME(m_tail)); save_item(NAME(m_empty)); + save_item(NAME(m_make_count)); save_item(NAME(m_rx_state)); save_item(NAME(m_keyclick)); save_item(NAME(m_beeper_state)); @@ -849,11 +841,10 @@ void hle_device_base::device_start() void hle_device_base::device_reset() { // initialise state - std::fill(std::begin(m_current_keys), std::end(m_current_keys), UINT16(0x0000U)); - m_next_row = 0U; std::fill(std::begin(m_fifo), std::end(m_fifo), UINT8(0x00U)); m_head = m_tail = 0U; m_empty = 1U; + m_make_count = 0U; m_rx_state = RX_IDLE; m_keyclick = 0U; m_beeper_state = 0x00U; @@ -874,21 +865,18 @@ void hle_device_base::device_reset() machine().output().set_led_value(LED_CAPS, 0); machine().output().set_led_value(LED_KANA, 0); + // no beep + m_click_timer->reset(); + + // kick the base + reset_key_state(); + start_processing(attotime::from_hz(1'200)); + // send reset response send_byte(0xffU); send_byte(ident_byte()); - UINT16 const acc( - std::accumulate( - std::begin(m_key_inputs), - std::end(m_key_inputs), - UINT16(0), - [] (UINT16 a, auto const &b) { return a | b->read(); })); - if (!acc) + if (are_all_keys_up()) send_byte(0x7fU); - - // kick the scan timer - m_scan_timer->adjust(attotime::from_hz(1'200), 0, attotime::from_hz(1'200)); - m_click_timer->reset(); } @@ -901,16 +889,13 @@ void hle_device_base::device_timer(emu_timer &timer, device_timer_id id, int par { switch (id) { - case SCAN_TIMER_ID: - scan_row(); - break; - case CLICK_TIMER_ID: m_beeper_state &= ~UINT8(BEEPER_CLICK); m_beeper->set_state(m_beeper_state ? 1 : 0); break; default: + device_matrix_keyboard_interface::device_timer(timer, id, param, ptr); device_serial_interface::device_timer(timer, id, param, ptr); } } @@ -942,6 +927,8 @@ void hle_device_base::tra_complete() if (!m_empty) { transmit_register_setup(m_fifo[m_head]); + if (m_head == m_tail) + start_processing(attotime::from_hz(1'200)); m_head = (m_head + 1) & 0x0fU; m_empty = (m_head == m_tail) ? 1 : 0; } @@ -990,12 +977,12 @@ void hle_device_base::rcv_complete() break; case COMMAND_CLICK_ON: - m_keyclick = 1; + m_keyclick = 1U; m_rx_state = RX_IDLE; break; case COMMAND_CLICK_OFF: - m_keyclick = 0; + m_keyclick = 0U; m_click_timer->reset(); m_beeper_state &= ~UINT8(BEEPER_CLICK); m_beeper->set_state(m_beeper_state ? 1 : 0); @@ -1021,59 +1008,48 @@ void hle_device_base::rcv_complete() /*-------------------------------------------------- - hle_device_base::scan_row - scan the next row in the keyboard matrix and - send update to host + hle_device_base::key_make + handle a key being pressed --------------------------------------------------*/ -void hle_device_base::scan_row() +void hle_device_base::key_make(UINT8 row, UINT8 column) { - // ensure we aren't in a stupid state - assert(m_next_row < ARRAY_LENGTH(m_key_inputs)); - assert(m_next_row < ARRAY_LENGTH(m_current_keys)); - - // get last read state and new state of row - UINT16 const row(m_key_inputs[m_next_row]->read()); - UINT16 ¤t(m_current_keys[m_next_row]); - bool keydown(false), keyup(false); - - // while the buffer isn't full, look for changed keys in this row - for (UINT8 bit = 0; (bit < 16) && (m_empty || (m_head != m_tail)); ++bit) - { - UINT16 const mask(UINT16(1) << bit); - if ((row ^ current) & mask) - { - UINT8 const make_break((row & mask) ? 0x00U : 0x80U); - keydown = keydown || !bool(make_break); - keyup = keyup || bool(make_break); - current = (current & ~mask) | (row & mask); - send_byte(make_break | (m_next_row << 4) | bit); - } - } + // we should have stopped processing if we filled the FIFO + assert(m_empty || (m_head != m_tail)); - // if a key was pressed and keyclick is enabled, turn on the beeper - if (keydown && m_keyclick) + // send the make code, click if desired + send_byte((row << 4) | column); + if (m_keyclick) { m_beeper_state |= UINT8(BEEPER_CLICK); m_beeper->set_state(m_beeper_state ? 1 : 0); m_click_timer->reset(attotime::from_msec(5)); } - // if a key was released and no keys are down, send all keys up code - if (keyup) - { - UINT16 const acc( - std::accumulate( - std::begin(m_current_keys), - std::end(m_current_keys), - UINT16(0), - [] (UINT16 a, UINT16 b) { return a | b; })); - if (!acc) - send_byte(0x7fU); - } + // count keys + ++m_make_count; + assert(m_make_count); +} + + +/*-------------------------------------------------- + hle_device_base::key_break + handle a key being released +--------------------------------------------------*/ + +void hle_device_base::key_break(UINT8 row, UINT8 column) +{ + // we should have stopped processing if we filled the FIFO + assert(m_empty || (m_head != m_tail)); + assert(m_make_count); + + // send the break code, and the idle code if no other keysa are down + send_byte(0x80U | (row << 4) | column); + if (!--m_make_count) + send_byte(0x7fU); - // advance to the next row - m_next_row = (m_next_row + 1) & 0x07U; + // check our counting + assert(are_all_keys_up() == !bool(m_make_count)); } @@ -1097,6 +1073,8 @@ void hle_device_base::send_byte(UINT8 code) m_fifo[m_tail] = code; m_tail = (m_tail + 1) & 0x0fU; m_empty = 0; + if (m_head == m_tail) + stop_processing(); } else { diff --git a/src/devices/bus/sunkbd/hlekbd.h b/src/devices/bus/sunkbd/hlekbd.h index 545817783e5..2414b8391df 100644 --- a/src/devices/bus/sunkbd/hlekbd.h +++ b/src/devices/bus/sunkbd/hlekbd.h @@ -6,6 +6,7 @@ #pragma once #include "sunkbd.h" +#include "machine/keyboard.h" #include "sound/beep.h" @@ -18,7 +19,11 @@ extern device_type const SUN_TYPE5_JP_HLE_KEYBOARD; namespace bus { namespace sunkbd { -class hle_device_base : public device_t, public device_serial_interface, public device_sun_keyboard_port_interface +class hle_device_base + : public device_t + , public device_serial_interface + , public device_sun_keyboard_port_interface + , protected device_matrix_keyboard_interface<8U> { public: virtual machine_config_constructor device_mconfig_additions() const override; @@ -47,14 +52,17 @@ protected: virtual void tra_complete() override; virtual void rcv_complete() override; + // device_matrix_keyboard_interface overrides + virtual void key_make(UINT8 row, UINT8 column) override; + virtual void key_break(UINT8 row, UINT8 column) override; + required_ioport m_dips; - required_ioport m_key_inputs[8]; private: // device_serial_interface uses 10'000 range + // device_matrix_keyboard_interface uses 20'000 range enum { - SCAN_TIMER_ID = 20'000, - CLICK_TIMER_ID + CLICK_TIMER_ID = 30'000 }; // TODO: ensure these don't clash with diagnostic LEDs on host computer @@ -91,17 +99,14 @@ private: void scan_row(); void send_byte(UINT8 code); - emu_timer *m_scan_timer; emu_timer *m_click_timer; required_device<beep_device> m_beeper; - UINT16 m_current_keys[8]; - UINT8 m_next_row; - UINT8 m_fifo[16]; UINT8 m_head, m_tail; UINT8 m_empty; + UINT8 m_make_count; UINT8 m_rx_state; UINT8 m_keyclick; diff --git a/src/devices/machine/keyboard.cpp b/src/devices/machine/keyboard.cpp index fa03e41faa1..fb83c7da182 100644 --- a/src/devices/machine/keyboard.cpp +++ b/src/devices/machine/keyboard.cpp @@ -34,13 +34,13 @@ UINT8 const TRANSLATION_TABLE[][2][4][16] = { { // ANSI { '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0x08U, 0x7fU, 0x1bU }, { 0x09U, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\\', 0xffU, 0xffU }, - { 0xffU, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', 0x0dU, 0xffU, 0xffU, 0xffU }, + { 0xffU, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', 0x0dU, 0xffU, 0xffU, 0x0aU }, { 0xffU, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0xffU, 0xffU, 0xffU, ' ' } }, { // JIS { '\\', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '^', 0x08U, 0x7fU, 0x1bU }, { 0x09U, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '@', '[', ']', 0xffU, 0xffU }, - { 0xffU, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', ':', 0x0dU, 0xffU, 0xffU, 0xffU }, + { 0xffU, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', ':', 0x0dU, 0xffU, 0xffU, 0x0aU }, { 0xffU, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0xffU, 0xffU, 0xffU, ' ' } } }, @@ -48,13 +48,13 @@ UINT8 const TRANSLATION_TABLE[][2][4][16] = { { // ANSI shift { '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', 0x08U, 0x7fU, 0x1bU }, { 0x09U, 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '|', 0xffU, 0xffU }, - { 0xffU, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', 0x0dU, 0xffU, 0xffU, 0xffU }, + { 0xffU, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', 0x0dU, 0xffU, 0xffU, 0x0aU }, { 0xffU, '_', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 0xffU, 0xffU, 0xffU, ' ' } }, { // JIS shift { '|', '!', '"', '#', '$', '%', '&', '\'', '(', ')', 0xffU, '=', '~', 0x08U, 0x7fU, 0x1bU }, { 0x09U, 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '`', '{', '}', 0xffU, 0xffU }, - { 0xffU, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', '+', '*', 0x0dU, 0xffU, 0xffU, 0xffU }, + { 0xffU, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', '+', '*', 0x0dU, 0xffU, 0xffU, 0x0aU }, { 0xffU, '_', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 0xffU, 0xffU, 0xffU, ' ' } } }, @@ -62,13 +62,13 @@ UINT8 const TRANSLATION_TABLE[][2][4][16] = { { // ANSI ctrl { 0x00U, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 0x1fU, 0x1eU, 0x08U, 0x7fU, 0x1bU }, { 0x09U, 0x11U, 0x17U, 0x05U, 0x12U, 0x14U, 0x19U, 0x15U, 0x09U, 0x0fU, 0x10U, 0x1bU, 0x1dU, 0x1cU, 0xffU, 0xffU }, - { 0xffU, 0x01U, 0x13U, 0x04U, 0x06U, 0x07U, 0x08U, 0x0aU, 0x0bU, 0x0cU, ';', '\'', 0x0dU, 0xffU, 0xffU, 0xffU }, + { 0xffU, 0x01U, 0x13U, 0x04U, 0x06U, 0x07U, 0x08U, 0x0aU, 0x0bU, 0x0cU, ';', '\'', 0x0dU, 0xffU, 0xffU, 0x0aU }, { 0xffU, 0x1cU, 0x1aU, 0x18U, 0x03U, 0x16U, 0x02U, 0x0eU, 0x0dU, ',', '.', 0x1fU, 0xffU, 0xffU, 0xffU, 0x00U } }, { // JIS ctrl { 0x1cU, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 0x1fU, 0x1eU, 0x08U, 0x7fU, 0x1bU }, { 0x09U, 0x11U, 0x17U, 0x05U, 0x12U, 0x14U, 0x19U, 0x15U, 0x09U, 0x0fU, 0x10U, 0x00U, 0x1bU, 0x1dU, 0xffU, 0xffU }, - { 0xffU, 0x01U, 0x13U, 0x04U, 0x06U, 0x07U, 0x08U, 0x0aU, 0x0bU, 0x0cU, ';', ':', 0x0dU, 0xffU, 0xffU, 0xffU }, + { 0xffU, 0x01U, 0x13U, 0x04U, 0x06U, 0x07U, 0x08U, 0x0aU, 0x0bU, 0x0cU, ';', ':', 0x0dU, 0xffU, 0xffU, 0x0aU }, { 0xffU, 0x1cU, 0x1aU, 0x18U, 0x03U, 0x16U, 0x02U, 0x0eU, 0x0dU, ',', '.', 0x1fU, 0xffU, 0xffU, 0xffU, 0x00U } } } @@ -203,10 +203,10 @@ INPUT_PORTS_START( generic_keyboard ) PORT_BIT( 0x0400U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CONDITION("GENKBD_CFG", 0x01, EQUALS, 0x01) PORT_CHAR(';') PORT_CHAR('+') PORT_BIT( 0x0800U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CONDITION("GENKBD_CFG", 0x01, EQUALS, 0x00) PORT_CHAR('\'') PORT_CHAR('"') PORT_BIT( 0x0800U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CONDITION("GENKBD_CFG", 0x01, EQUALS, 0x01) PORT_CHAR(':') PORT_CHAR('*') - PORT_BIT( 0x1000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(0x0dU) + PORT_BIT( 0x1000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_ENTER) PORT_NAME("Return") PORT_CHAR(0x0dU) PORT_BIT( 0x2000U, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_BIT( 0x4000U, IP_ACTIVE_HIGH, IPT_UNUSED ) - PORT_BIT( 0x8000U, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x8000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_INS) PORT_NAME("Linefeed") PORT_CHAR(UCHAR_MAMEKEY(INS)) PORT_START("GENKBD_ROW3") PORT_BIT( 0x0001U, IP_ACTIVE_HIGH, IPT_UNUSED ) diff --git a/src/devices/machine/keyboard.h b/src/devices/machine/keyboard.h index 04972925815..343c8991bcb 100644 --- a/src/devices/machine/keyboard.h +++ b/src/devices/machine/keyboard.h @@ -61,6 +61,8 @@ protected: virtual void key_break(UINT8 row, UINT8 column); virtual void will_scan_row(UINT8 row); + bool are_all_keys_up(); + private: // device_serial_interface uses 10'000 range enum { diff --git a/src/devices/machine/keyboard.ipp b/src/devices/machine/keyboard.ipp index 966662b00a0..91c6992962e 100644 --- a/src/devices/machine/keyboard.ipp +++ b/src/devices/machine/keyboard.ipp @@ -7,6 +7,9 @@ #include "keyboard.h" +#include <numeric> + + template <UINT8 ROW_COUNT> template <typename... T> device_matrix_keyboard_interface<ROW_COUNT>::device_matrix_keyboard_interface(machine_config const &mconfig, device_t &device, T &&... tags) @@ -157,4 +160,15 @@ void device_matrix_keyboard_interface<ROW_COUNT>::will_scan_row(UINT8 row) { } + +template <UINT8 ROW_COUNT> +bool device_matrix_keyboard_interface<ROW_COUNT>::are_all_keys_up() +{ + return 0U == std::accumulate( + std::begin(m_key_rows), + std::end(m_key_rows), + ioport_value(0), + [] (ioport_value a, auto const &b) { return a | b->read(); }); +} + #endif // MAME_DEVICES_MACHINE_KEYBOARD_IPP diff --git a/src/mame/machine/x68k_kbd.cpp b/src/mame/machine/x68k_kbd.cpp index ae697d08f5f..cd39dde3403 100644 --- a/src/mame/machine/x68k_kbd.cpp +++ b/src/mame/machine/x68k_kbd.cpp @@ -74,14 +74,14 @@ void x68k_keyboard_device::received_byte(UINT8 data) if ((data & 0xf0) == 0x60) // Key delay time { - m_delay = data & 0x0f; - logerror("KB: Keypress delay time is now %ims\n", ((data & 0x0f) * 100) + 200); + m_delay = ((data & 0x0f) * 100) + 200; + logerror("KB: Keypress delay time is now %ims\n", m_delay); } if ((data & 0xf0) == 0x70) // Key repeat rate { - m_repeat = data & 0x0f; - logerror("KB: Keypress repeat rate is now %ims\n", (((data & 0x0f)^2) * 5) + 30); + m_repeat = (((data & 0x0f)^2) * 5) + 30; + logerror("KB: Keypress repeat rate is now %ims\n", m_repeat); } } |