diff options
| author | 2025-06-16 20:46:19 +0100 | |
|---|---|---|
| committer | 2025-06-16 22:44:33 +0100 | |
| commit | b4e04ba8cff51beffe25fc02cc77bcabd8a947d2 (patch) | |
| tree | 277d996db4997524703758139a9fb07b4d10c68b | |
| parent | 50be01c6509cea62b8b254dafe506608d1cc24c6 (diff) | |
machine/ay34592.cpp: New AY-3-4592 keyboard encoder device.
| -rw-r--r-- | scripts/src/machine.lua | 12 | ||||
| -rw-r--r-- | src/devices/machine/ay34592.cpp | 236 | ||||
| -rw-r--r-- | src/devices/machine/ay34592.h | 81 |
3 files changed, 329 insertions, 0 deletions
diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index c48bee5e9c5..2f3fac2ae3b 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -907,6 +907,18 @@ end --------------------------------------------------- -- +--@src/devices/machine/ay34592.h,MACHINES["AY34592"] = true +--------------------------------------------------- + +if (MACHINES["AY34592"]~=null) then + files { + MAME_DIR .. "src/devices/machine/ay34592.cpp", + MAME_DIR .. "src/devices/machine/ay34592.h", + } +end + +--------------------------------------------------- +-- --@src/devices/machine/bankdev.h,MACHINES["BANKDEV"] = true --------------------------------------------------- diff --git a/src/devices/machine/ay34592.cpp b/src/devices/machine/ay34592.cpp new file mode 100644 index 00000000000..bc93e5d1fc6 --- /dev/null +++ b/src/devices/machine/ay34592.cpp @@ -0,0 +1,236 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************** + + AY-3-4592 Keyboard Encoder emulation + + TODO: + - verify keyboard rollover behaviour. + +**********************************************************************/ + +#include "emu.h" +#include "ay34592.h" + + +DEFINE_DEVICE_TYPE(AY34592, ay34592_device, "ay34592", "AY-3-4592 Keyboard Encoder") + +ay34592_device::ay34592_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, AY34592, tag, owner, clock) + , m_read_x(*this, 0xff) + , m_akd_cb(*this) + , m_sli_cb(*this) + , m_ali_cb(*this) + , m_x15_cb(*this) + , m_scan_timer(nullptr) +{ +} + + +uint16_t ay34592_device::output_code(int mode, int x, int y) +{ + static const uint16_t OUTPUT_CODE[4][14][8] = + { + // normal + { + // Y0 Y1 Y2 Y3 Y4 Y5 Y6 Y7 + { 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, 0x0ce }, // X0 + { 0x1e4, 0x0cd, 0x0cd, 0x188, 0x18e, 0x18c, 0x19e, 0x185 }, // X1 + { 0x17f, 0x0cb, 0x0cc, 0x18d, 0x19a, 0x19b, 0x187, 0x19c }, // X2 + { 0x17e, 0x17d, 0x0ca, 0x18b, 0x199, 0x198, 0x189, 0x19d }, // X3 + { 0x17c, 0x0c8, 0x0c9, 0x186, 0x197, 0x191, 0x0c9, 0x0df }, // X4 + { 0x17b, 0x0c7, 0x0c8, 0x18a, 0x195, 0x194, 0x192, 0x0d3 }, // X5 + { 0x17a, 0x0c6, 0x0c7, 0x196, 0x190, 0x194, 0x193, 0x192 }, // X6 + { 0x179, 0x0cf, 0x0c6, 0x178, 0x18f, 0x0c4, 0x193, 0x0d1 }, // X7 + { 0x0d2, 0x191, 0x18f, 0x1a4, 0x0d8, 0x0c4, 0x0d0, 0x177 }, // X8 + { 0x0c2, 0x0c5, 0x176, 0x1a3, 0x175, 0x1a4, 0x1f2, 0x1a2 }, // X9 + { 0x080, 0x174, 0x0d2, 0x173, 0x1f5, 0x1bf, 0x1a1, 0x1a0 }, // X10 + { 0x172, 0x1f6, 0x0d2, 0x171, 0x190, 0x1a4, 0x1f7, 0x160 }, // X11 + { 0x170, 0x0c8, 0x1f4, 0x16f, 0x0cb, 0x0d3, 0x0ce, 0x0cf }, // X12 + { 0x16e, 0x0c6, 0x0c7, 0x0ca, 0x0c9, 0x0cd, 0x0cc, 0x0d1 } // X13 + }, + + // shift + { + // Y0 Y1 Y2 Y3 Y4 Y5 Y6 Y7 + { 0x3ff, 0x3ff, 0x3ff, 0x3ff, 0x3ff, 0x3ff, 0x3ff, 0x0de }, // X0 + { 0x1e4, 0x18f, 0x0dd, 0x1a8, 0x1ae, 0x1ac, 0x1be, 0x1a5 }, // X1 + { 0x17f, 0x0db, 0x0dc, 0x1ad, 0x1ba, 0x1bb, 0x1a7, 0x1bc }, // X2 + { 0x17e, 0x17d, 0x0da, 0x1ab, 0x1b9, 0x1b8, 0x1a9, 0x1bd }, // X3 + { 0x17c, 0x0d9, 0x0d9, 0x1a6, 0x1b7, 0x1b1, 0x0c3, 0x0df }, // X4 + { 0x17b, 0x0d5, 0x0d8, 0x1aa, 0x1b5, 0x1b4, 0x1b2, 0x0c3 }, // X5 + { 0x17a, 0x0d7, 0x0d7, 0x1b6, 0x1b0, 0x1a4, 0x1b3, 0x1a2 }, // X6 + { 0x179, 0x0d6, 0x0d6, 0x178, 0x1af, 0x0c5, 0x1a3, 0x0c1 }, // X7 + { 0x1a0, 0x1a1, 0x1bf, 0x1a2, 0x0dd, 0x0d4, 0x0c0, 0x177 }, // X8 + { 0x0d4, 0x0d5, 0x176, 0x083, 0x175, 0x084, 0x1f2, 0x082 }, // X9 + { 0x080, 0x174, 0x1a0, 0x173, 0x1f5, 0x1a3, 0x081, 0x0c2 }, // X10 + { 0x172, 0x1f6, 0x0c2, 0x171, 0x1a0, 0x1a2, 0x1f7, 0x160 }, // X11 + { 0x170, 0x0c8, 0x1f4, 0x16f, 0x0cb, 0x0d3, 0x0ce, 0x0cf }, // X12 + { 0x16e, 0x0c6, 0x0c7, 0x0ca, 0x0c9, 0x0cd, 0x0cc, 0x0d1 } // X13 + }, + + // control + { + // Y0 Y1 Y2 Y3 Y4 Y5 Y6 Y7 + { 0x3ff, 0x3ff, 0x3ff, 0x3ff, 0x3ff, 0x3ff, 0x3ff, 0x0ce }, // X0 + { 0x1e4, 0x0cd, 0x0cd, 0x1e8, 0x1ee, 0x1ec, 0x1fe, 0x1e5 }, // X1 + { 0x17f, 0x0cb, 0x0cc, 0x1ed, 0x1fa, 0x1fb, 0x1e7, 0x1fc }, // X2 + { 0x17e, 0x17d, 0x0ca, 0x1eb, 0x1f9, 0x1f8, 0x1e9, 0x1fd }, // X3 + { 0x17c, 0x0c8, 0x0c9, 0x1e6, 0x1f7, 0x1f1, 0x0c9, 0x0df }, // X4 + { 0x17b, 0x0c7, 0x0c8, 0x1ea, 0x1f5, 0x1f4, 0x1f2, 0x0d3 }, // X5 + { 0x17a, 0x0c6, 0x0c7, 0x1f6, 0x1f0, 0x1f4, 0x1f3, 0x1f2 }, // X6 + { 0x179, 0x0cf, 0x0c6, 0x178, 0x1ef, 0x0c4, 0x1f3, 0x0d1 }, // X7 + { 0x0d2, 0x1f1, 0x1ef, 0x1e4, 0x0d8, 0x0c4, 0x0d0, 0x177 }, // X8 + { 0x0c2, 0x0c5, 0x176, 0x1e3, 0x175, 0x1e4, 0x1f2, 0x1e2 }, // X9 + { 0x080, 0x174, 0x1e0, 0x173, 0x1f5, 0x1ff, 0x1e1, 0x1a0 }, // X10 + { 0x172, 0x1f6, 0x0d2, 0x171, 0x1f0, 0x1a4, 0x1f7, 0x160 }, // X11 + { 0x170, 0x0c8, 0x1f4, 0x16f, 0x0cb, 0x0d3, 0x0ce, 0x0cf }, // X12 + { 0x16e, 0x0c6, 0x0c7, 0x0ca, 0x0c9, 0x0cd, 0x0cc, 0x0d1 } // X13 + }, + + // shift/control + { + // Y0 Y1 Y2 Y3 Y4 Y5 Y6 Y7 + { 0x3ff, 0x3ff, 0x3ff, 0x3ff, 0x3ff, 0x3ff, 0x3ff, 0x0de }, // X0 + { 0x1e4, 0x1ff, 0x0dd, 0x1e8, 0x1ee, 0x1ec, 0x1fe, 0x1e5 }, // X1 + { 0x17f, 0x0db, 0x0dc, 0x1ed, 0x1fa, 0x1fb, 0x1e7, 0x1fc }, // X2 + { 0x17e, 0x17d, 0x0da, 0x1eb, 0x1f9, 0x1f8, 0x1e9, 0x1fd }, // X3 + { 0x17c, 0x0d9, 0x0d9, 0x1e6, 0x1f7, 0x1f1, 0x0c3, 0x0df }, // X4 + { 0x17b, 0x0d5, 0x0d8, 0x1ea, 0x1f5, 0x1f4, 0x1f2, 0x0c3 }, // X5 + { 0x17a, 0x0d7, 0x0d7, 0x1f6, 0x1f0, 0x1e4, 0x1f3, 0x1e2 }, // X6 + { 0x179, 0x0d6, 0x0d6, 0x178, 0x1ef, 0x0c5, 0x1e3, 0x0c1 }, // X7 + { 0x1a0, 0x1e1, 0x1ff, 0x1e2, 0x0dd, 0x0d4, 0x0c0, 0x177 }, // X8 + { 0x0d4, 0x0d5, 0x176, 0x1e3, 0x175, 0x1e4, 0x1f2, 0x1e2 }, // X9 + { 0x080, 0x174, 0x1e0, 0x173, 0x1f5, 0x1ff, 0x1e1, 0x0c2 }, // X10 + { 0x172, 0x1f6, 0x0c2, 0x171, 0x1e0, 0x1a2, 0x1f7, 0x160 }, // X11 + { 0x170, 0x0c8, 0x1f4, 0x16f, 0x0cb, 0x0d3, 0x0ce, 0x0cf }, // X12 + { 0x16e, 0x0c6, 0x0c7, 0x0ca, 0x0c9, 0x0cd, 0x0cc, 0x0d1 } // X13 + } + }; + return OUTPUT_CODE[mode][x][y]; +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void ay34592_device::device_start() +{ + m_scan_timer = timer_alloc(FUNC(ay34592_device::scan_matrix), this); + + // register for state saving + save_item(NAME(m_matrix_addr)); + save_item(NAME(m_keydown_addr)); + save_item(NAME(m_key_latch)); + save_item(NAME(m_opcode)); + save_item(NAME(m_akd)); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void ay34592_device::device_reset() +{ + m_scan_timer->adjust(attotime::zero, 0, attotime::from_hz(clock())); + + m_matrix_addr = 0x00; + m_keydown_addr = 0x00; + m_key_latch = 0x00; + m_opcode = 0x00; + m_akd = 0; +} + + +TIMER_CALLBACK_MEMBER(ay34592_device::scan_matrix) +{ + int akd = m_akd; + + // 7 bit counter + m_matrix_addr--; + m_matrix_addr &= 0x7f; + + const int x = m_matrix_addr >> 3; + const int y = m_matrix_addr & 7; + + // scan rows X0 to X13 only + if (x < 14) + { + if (x == 0 && y < 7) // FFB = 1 + { + // Op-Code Function + // x x 0 0 0 Function key (with up/down codes) + // x x 0 0 1 Right Shift Key + // x x 0 1 0 Left Shift Key + // x x 0 1 1 Shift Lock Key or Discrete Key (output SLI) + // x x 1 0 0 Control Key + // x x 1 0 1 Alpha Lock Key or Discrete Key (output ALI) + // x 0 1 1 0 Error Reset Key or Discrete Key (output X15) + // x x 1 1 1 Discrete Key (output D10) + + if (!BIT(m_read_x[x](), y)) + m_opcode |= 1 << output_code(0, x, y); + else + m_opcode &= ~(1 << output_code(0, x, y)); + + m_sli_cb(BIT(m_opcode, 3)); // Shift Lock Indicator + m_ali_cb(BIT(m_opcode, 5)); // Alpha Lock Indicator + m_x15_cb(BIT(m_opcode, 6)); // X15 discrete output + } + else // FFB = 0 + { + if (!BIT(m_read_x[x](), y)) + { + if (m_matrix_addr == m_keydown_addr) + { + if ((m_opcode & 0x0e) && (m_opcode & 0x10)) + m_key_latch = output_code(3, x, y); // Shift/Control + else if (m_opcode & 0x10) + m_key_latch = output_code(2, x, y); // Control + else if (m_opcode & 0x0e) + m_key_latch = output_code(1, x, y); // Shift + else + m_key_latch = output_code(0, x, y); // Normal + + // set 'any key down' + akd = 1; + } + else + { + m_keydown_addr = m_matrix_addr; + } + } + } + } + + // reset 'any key down' if all keys released + bool keydown = false; + for (int x = 0; x < 14; x++) + { + uint8_t keymask = (x == 0) ? 0x80 : 0xff; + if ((m_read_x[x]() & keymask) != keymask) + { + keydown = true; + break; + } + } + if (!keydown) + { + // clear 'any key down' + akd = 0; + } + + // update AKD output (only if changed to avoid conflict with any external repeat circuit) + if (akd != m_akd) + { + m_akd_cb(akd); + m_akd = akd; + } +} + + +uint16_t ay34592_device::data_r() +{ + return m_key_latch; +} diff --git a/src/devices/machine/ay34592.h b/src/devices/machine/ay34592.h new file mode 100644 index 00000000000..c9757f2a42a --- /dev/null +++ b/src/devices/machine/ay34592.h @@ -0,0 +1,81 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************** + + AY-3-4592 Keyboard Encoder emulation + +********************************************************************** + _____ _____ + GND 1 |* \_/ | 40 Vcc + Data Output D1 2 | | 39 AKD + Data Output D2 3 | | 38 nMATIN + Data Output D3 4 | | 37 nPOR + Data Output D4 5 | | 36 Clock + Data Output D5 6 | | 35 nKPD + Data Output D6 7 | | 34 SLI + Data Output D7 8 | | 33 ALI + Data Output D8 9 | | 32 Matrix Output X6 + Data Output D9 10 | AY-3-4592 | 31 Matrix Output X7 + Data Output D10 11 | | 30 Matrix Output X5 + KBINH 12 | | 29 Matrix Output X14 + LO/RO 13 | | 28 Matrix Output X15 + Matrix Input YA 14 | | 27 Matrix Output X13 + Matrix Input YC 15 | | 26 Matrix Output X12 + Matrix Input YB 16 | | 25 Matrix Output X11 + Matrix Output X0 17 | | 24 Matrix Output X10 + Matrix Output X1 18 | | 23 Matrix Output X9 + Matrix Output X2 19 | | 22 Matrix Output X8 + Matrix Output X3 20 |_____________| 21 Matrix Output X4 + +**********************************************************************/ + +#ifndef MAME_MACHINE_AY34592_H +#define MAME_MACHINE_AY34592_H + +#pragma once + +class ay34592_device : public device_t +{ +public: + ay34592_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + template <unsigned N> auto x() { return m_read_x[N].bind(); } + + auto akd_cb() { return m_akd_cb.bind(); } + auto sli_cb() { return m_sli_cb.bind(); } + auto ali_cb() { return m_ali_cb.bind(); } + auto x15_cb() { return m_x15_cb.bind(); } + + // keyboard data + uint16_t data_r(); + +protected: + // device_t overrides + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + +private: + devcb_read16::array<14> m_read_x; + devcb_write_line m_akd_cb; + devcb_write_line m_sli_cb; + devcb_write_line m_ali_cb; + devcb_write_line m_x15_cb; + + emu_timer *m_scan_timer; + + TIMER_CALLBACK_MEMBER(scan_matrix); + + uint16_t output_code(int mode, int x, int y); + + // internal state + uint8_t m_matrix_addr; + uint8_t m_keydown_addr; + uint8_t m_opcode; + uint8_t m_akd; + uint16_t m_key_latch; +}; + + +DECLARE_DEVICE_TYPE(AY34592, ay34592_device) + +#endif // MAME_MACHINE_AY34592_H |
