diff options
Diffstat (limited to 'src/emu/machine')
-rw-r--r-- | src/emu/machine/mm74c922.c | 226 | ||||
-rw-r--r-- | src/emu/machine/mm74c922.h | 163 |
2 files changed, 389 insertions, 0 deletions
diff --git a/src/emu/machine/mm74c922.c b/src/emu/machine/mm74c922.c new file mode 100644 index 00000000000..61eea867700 --- /dev/null +++ b/src/emu/machine/mm74c922.c @@ -0,0 +1,226 @@ +/********************************************************************** + + MM74C922/MM74C923 16/20-Key Encoder emulation + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +**********************************************************************/ + +#include "mm74c922.h" +#include "machine/devhelpr.h" + + + +//************************************************************************** +// MACROS / CONSTANTS +//************************************************************************** + +#define LOG 1 + + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +const device_type MM74C922 = mm74c922_device_config::static_alloc_device_config; +const device_type MM74C923 = mm74c922_device_config::static_alloc_device_config; + + + +//************************************************************************** +// DEVICE CONFIGURATION +//************************************************************************** + +GENERIC_DEVICE_CONFIG_SETUP(mm74c922, "MM74C922") + + +//------------------------------------------------- +// device_config_complete - perform any +// operations now that the configuration is +// complete +//------------------------------------------------- + +void mm74c922_device_config::device_config_complete() +{ + // inherit a copy of the static data + const mm74c922_interface *intf = reinterpret_cast<const mm74c922_interface *>(static_config()); + if (intf != NULL) + *static_cast<mm74c922_interface *>(this) = *intf; + + // or initialize to defaults if none provided + else + { + memset(&m_out_da_func, 0, sizeof(m_out_da_func)); + memset(&m_in_x1_func, 0, sizeof(m_in_x1_func)); + memset(&m_in_x2_func, 0, sizeof(m_in_x2_func)); + memset(&m_in_x3_func, 0, sizeof(m_in_x3_func)); + memset(&m_in_x4_func, 0, sizeof(m_in_x4_func)); + memset(&m_in_x5_func, 0, sizeof(m_in_x5_func)); + } +} + + +//------------------------------------------------- +// static_set_config - configuration helper +//------------------------------------------------- + +void mm74c922_device_config::static_set_config(device_config *device, int max_y) +{ + mm74c922_device_config *mm74c922 = downcast<mm74c922_device_config *>(device); + + mm74c922->m_max_y = max_y; +} + + + +//************************************************************************** +// INLINE HELPERS +//************************************************************************** + +//------------------------------------------------- +// change_output_lines - +//------------------------------------------------- + +inline void mm74c922_device::change_output_lines() +{ + if (m_next_da != m_da) + { + m_da = m_next_da; + + if (LOG) logerror("MM74C922 '%s' Data Available: %u\n", tag(), m_da); + + devcb_call_write_line(&m_out_da_func, m_da); + } +} + + +//------------------------------------------------- +// clock_scan_counters - +//------------------------------------------------- + +inline void mm74c922_device::clock_scan_counters() +{ + if (!m_inhibit) + { + m_x++; + m_x &= 0x03; + } +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +inline void mm74c922_device::detect_keypress() +{ + if (m_inhibit) + { + UINT8 data = devcb_call_read8(&m_in_x_func[m_x], 0); + + if (BIT(data, m_y)) + { + // key released + m_inhibit = 0; + m_next_da = 0; + m_data = 0xff; // high-Z + + if (LOG) logerror("MM74C922 '%s' Key Released\n", tag()); + } + } + else + { + UINT8 data = devcb_call_read8(&m_in_x_func[m_x], 0); + + for (int y = 0; y < m_config.m_max_y; y++) + { + if (!BIT(data, y)) + { + // key depressed + m_inhibit = 1; + m_next_da = 1; + m_y = y; + + m_data = (y << 2) | m_x; + + if (LOG) logerror("MM74C922 '%s' Key Depressed: X %u Y %u = %02x\n", tag(), m_x, y, m_data); + return; + } + } + } +} + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// mm74c922_device - constructor +//------------------------------------------------- + +mm74c922_device::mm74c922_device(running_machine &_machine, const mm74c922_device_config &config) + : device_t(_machine, config), + m_x(0), + m_y(0), + m_next_da(0), + m_config(config) +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void mm74c922_device::device_start() +{ + // resolve callbacks + devcb_resolve_write_line(&m_out_da_func, &m_config.m_out_da_func, this); + devcb_resolve_read8(&m_in_x_func[0], &m_config.m_in_x1_func, this); + devcb_resolve_read8(&m_in_x_func[1], &m_config.m_in_x2_func, this); + devcb_resolve_read8(&m_in_x_func[2], &m_config.m_in_x3_func, this); + devcb_resolve_read8(&m_in_x_func[3], &m_config.m_in_x4_func, this); + devcb_resolve_read8(&m_in_x_func[4], &m_config.m_in_x5_func, this); + + // set initial values + change_output_lines(); + + // allocate timers + m_scan_timer = timer_alloc(); + m_scan_timer->adjust(attotime::zero, 0, attotime::from_hz(50)); + + // register for state saving + save_item(NAME(m_inhibit)); + save_item(NAME(m_x)); + save_item(NAME(m_y)); + save_item(NAME(m_data)); + save_item(NAME(m_da)); + save_item(NAME(m_next_da)); +} + + +//------------------------------------------------- +// device_timer - handler timer events +//------------------------------------------------- + +void mm74c922_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + change_output_lines(); + clock_scan_counters(); + detect_keypress(); +} + + +//------------------------------------------------- +// data_out_r - +//------------------------------------------------- + +UINT8 mm74c922_device::data_out_r() +{ + if (LOG) logerror("MM74C922 '%s' Data Read: %02x\n", tag(), m_data); + + return m_data; +} diff --git a/src/emu/machine/mm74c922.h b/src/emu/machine/mm74c922.h new file mode 100644 index 00000000000..94746d846a3 --- /dev/null +++ b/src/emu/machine/mm74c922.h @@ -0,0 +1,163 @@ +/********************************************************************** + + MM74C922/MM74C923 16/20-Key Encoder emulation + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +********************************************************************** + _____ _____ + ROW Y1 1 |* \_/ | 18 Vcc + ROW Y2 2 | | 17 DATA OUT A + ROW Y3 3 | | 16 DATA OUT B + ROW Y4 4 | | 15 DATA OUT C + OSCILLATOR 5 | MM74C922 | 14 DATA OUT D + KEYBOUNCE MASK 6 | | 13 _OUTPUT ENABLE + COLUMN X4 7 | | 12 DATA AVAILABLE + COLUMN X3 8 | | 11 COLUMN X1 + GND 9 |_____________| 10 COLUMN X2 + + _____ _____ + ROW Y1 1 |* \_/ | 20 Vcc + ROW Y2 2 | | 19 DATA OUT A + ROW Y3 3 | | 18 DATA OUT B + ROW Y4 4 | | 17 DATA OUT C + ROW Y5 5 | MM74C923 | 16 DATA OUT D + OSCILLATOR 6 | | 15 DATA OUT E + KEYBOUNCE MASK 7 | | 14 _OUTPUT ENABLE + COLUMN X4 8 | | 13 DATA AVAILABLE + COLUMN X3 9 | | 12 COLUMN X1 + GND 10 |_____________| 11 COLUMN X2 + +**********************************************************************/ + +#pragma once + +#ifndef __MM74C922__ +#define __MM74C922__ + +#include "emu.h" + + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_MM74C922_ADD(_tag, _config) \ + MCFG_DEVICE_ADD(_tag, MM74C922, 0) \ + MCFG_DEVICE_CONFIG(_config) \ + mm74c922_device_config::static_set_config(device, 4); + + +#define MCFG_MM74C923_ADD(_tag, _config) \ + MCFG_DEVICE_ADD(_tag, MM74C923, 0) \ + MCFG_DEVICE_CONFIG(_config) \ + mm74c922_device_config::static_set_config(device, 5); + + +#define MM74C922_INTERFACE(name) \ + const mm74c922_interface (name)= + + +#define MM74C923_INTERFACE(name) \ + const mm74c922_interface (name)= + + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> mm74c922_interface + +struct mm74c922_interface +{ + double m_cap_osc; + double m_cap_debounce; + + devcb_write_line m_out_da_func; + + devcb_read8 m_in_x1_func; + devcb_read8 m_in_x2_func; + devcb_read8 m_in_x3_func; + devcb_read8 m_in_x4_func; + devcb_read8 m_in_x5_func; +}; + + +// ======================> mm74c922_device_config + +class mm74c922_device_config : public device_config, + public mm74c922_interface +{ + friend class mm74c922_device; + + // construction/destruction + mm74c922_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock); + +public: + // allocators + static device_config *static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock); + virtual device_t *alloc_device(running_machine &machine) const; + + // inline configuration helpers + static void static_set_config(device_config *device, int max_y); + +protected: + // device_config overrides + virtual void device_config_complete(); + +private: + int m_max_y; +}; + + +// ======================> mm74c922_device + +class mm74c922_device : public device_t +{ + friend class mm74c922_device_config; + + // construction/destruction + mm74c922_device(running_machine &_machine, const mm74c922_device_config &_config); + +public: + UINT8 data_out_r(); + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); + +private: + inline void change_output_lines(); + inline void clock_scan_counters(); + inline void detect_keypress(); + + devcb_resolved_write_line m_out_da_func; + devcb_resolved_read8 m_in_x_func[5]; + + int m_inhibit; // scan counter clock inhibit + int m_x; // currently scanned column + int m_y; // latched row + + UINT8 m_data; // data latch + + int m_da; // data available flag + int m_next_da; // next value of data available flag + + // timers + emu_timer *m_scan_timer; // keyboard scan timer + + const mm74c922_device_config &m_config; +}; + + +// device type definition +extern const device_type MM74C922; +extern const device_type MM74C923; + + + +#endif |