// license:BSD-3-Clause // copyright-holders:Vas Crabb #ifndef MAME_MACHINE_KEYBOARD_IPP #define MAME_MACHINE_KEYBOARD_IPP #pragma once // Work around for MSVC warning that identifies some of these as unused #ifdef _MSC_VER #pragma warning ( disable : 4505 ) #endif #include "keyboard.h" #include template template device_matrix_keyboard_interface::device_matrix_keyboard_interface(machine_config const &mconfig, device_t &device, T &&... tags) : device_interface(device, "matrix_keyboard") , m_scan_timer(nullptr) , m_typematic_timer(nullptr) , m_key_rows{ { device, std::forward(tags) }... } , m_next_row(0U) , m_processing(0U) , m_typematic_row(0U) , m_typematic_column(0U) { } template void device_matrix_keyboard_interface::interface_pre_start() { if (!m_scan_timer) m_scan_timer = device().machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(device_matrix_keyboard_interface::scan_row), this)); if (!m_typematic_timer) m_typematic_timer = device().machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(device_matrix_keyboard_interface::typematic), this)); reset_key_state(); typematic_stop(); } template void device_matrix_keyboard_interface::interface_post_start() { device().save_item(NAME(m_key_states)); device().save_item(NAME(m_next_row)); device().save_item(NAME(m_processing)); device().save_item(NAME(m_typematic_row)); device().save_item(NAME(m_typematic_column)); } template void device_matrix_keyboard_interface::start_processing(const attotime &period) { m_processing = 1U; m_scan_timer->adjust(period, 0, period); } template void device_matrix_keyboard_interface::stop_processing() { m_scan_timer->reset(); m_processing = 0U; } template void device_matrix_keyboard_interface::reset_key_state() { std::fill(std::begin(m_key_states), std::end(m_key_states), ioport_value(0U)); m_next_row = 0U; } template void device_matrix_keyboard_interface::typematic_start(uint8_t row, uint8_t column, attotime const &delay, attotime const &interval) { m_typematic_row = row; m_typematic_column = column; m_typematic_timer->adjust(delay, 0, interval); } template void device_matrix_keyboard_interface::typematic_restart(attotime const &delay, attotime const &interval) { if ((m_typematic_row != uint8_t(~0U)) || (m_typematic_column != uint8_t(~0U))) m_typematic_timer->adjust(delay, 0, interval); } template void device_matrix_keyboard_interface::typematic_stop() { m_typematic_row = uint8_t(~0U); m_typematic_column = uint8_t(~0U); m_typematic_timer->reset(); } template TIMER_CALLBACK_MEMBER(device_matrix_keyboard_interface::scan_row) { assert(m_next_row < ARRAY_LENGTH(m_key_rows)); assert(m_next_row < ARRAY_LENGTH(m_key_states)); will_scan_row(m_next_row); ioport_value &state(m_key_states[m_next_row]); ioport_value const keys(m_key_rows[m_next_row]->read()); ioport_value const change(state ^ keys); ioport_value mask(1U); for (uint8_t column = 0U; m_processing && (state != keys); ++column, mask <<= 1) { if (change & mask) { state ^= mask; if (keys & mask) key_make(m_next_row, column); else key_break(m_next_row, column); } } m_next_row = (m_next_row + 1) % ARRAY_LENGTH(m_key_rows); if (m_next_row == 0) scan_complete(); } template TIMER_CALLBACK_MEMBER(device_matrix_keyboard_interface::typematic) { assert((m_typematic_row != uint8_t(~0U)) || (m_typematic_column != uint8_t(~0U))); key_repeat(m_typematic_row, m_typematic_column); } template void device_matrix_keyboard_interface::key_repeat(uint8_t row, uint8_t column) { } template void device_matrix_keyboard_interface::key_break(uint8_t row, uint8_t column) { if (typematic_is(row, column)) typematic_stop(); } template void device_matrix_keyboard_interface::will_scan_row(uint8_t row) { } template void device_matrix_keyboard_interface::scan_complete() { } template bool device_matrix_keyboard_interface::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_MACHINE_KEYBOARD_IPP