From d0f793242f02dd2d0ce84c60342022a28b1a3c13 Mon Sep 17 00:00:00 2001 From: Mark Garlanger Date: Tue, 4 Jul 2023 14:04:06 -0500 Subject: -machine/mm5740.cpp: Added repeat input. (#11352) -heathkit/tlb.cpp: Hooked up repeat key and fixed interrupt state calculation. --- src/devices/machine/mm5740.cpp | 69 +++++++++++++++++++++------------ src/devices/machine/mm5740.h | 42 +++++++++------------ src/mame/heathkit/h89.cpp | 2 +- src/mame/heathkit/tlb.cpp | 86 ++++++++++++++++++++++++++++-------------- src/mame/heathkit/tlb.h | 20 +++++++--- 5 files changed, 136 insertions(+), 83 deletions(-) diff --git a/src/devices/machine/mm5740.cpp b/src/devices/machine/mm5740.cpp index 46c72732fb4..9559594e2fc 100644 --- a/src/devices/machine/mm5740.cpp +++ b/src/devices/machine/mm5740.cpp @@ -43,7 +43,7 @@ const tiny_rom_entry *mm5740_device::device_rom_region() const // mm5740_device - constructor //------------------------------------------------- -mm5740_device::mm5740_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : +mm5740_device::mm5740_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : device_t(mconfig, MM5740, tag, owner, clock), m_read_x(*this, 0x3ff), m_read_shift(*this, 0), @@ -51,13 +51,12 @@ mm5740_device::mm5740_device(const machine_config &mconfig, const char *tag, dev m_write_data_ready(*this), m_rom(*this, "internal") { - std::fill(std::begin(m_x_mask), std::end(m_x_mask), 0); } -uint32_t mm5740_device::calc_effective_clock_key_debounce(uint32_t capacitance) +u32 mm5740_device::calc_effective_clock_key_debounce(u32 capacitance) { // calculate key debounce based on capacitance in pF - uint32_t key_debounce_msec = capacitance / 125; + u32 key_debounce_msec = capacitance / 125; if (key_debounce_msec == 0) { key_debounce_msec = 1; @@ -72,22 +71,21 @@ uint32_t mm5740_device::calc_effective_clock_key_debounce(uint32_t capacitance) void mm5740_device::device_start() { + std::fill(std::begin(m_x_mask), std::end(m_x_mask), 0); + m_b = -1; + m_repeat = false; + m_last_repeat = false; + // allocate timers m_scan_timer = timer_alloc(FUNC(mm5740_device::perform_scan), this); m_scan_timer->adjust(attotime::from_hz(clock()), 0, attotime::from_hz(clock())); // state saving save_item(NAME(m_b)); + save_item(NAME(m_offset)); save_item(NAME(m_x_mask)); -} - - -//------------------------------------------------- -// device_start - device-specific reset -//------------------------------------------------- - -void mm5740_device::device_reset() -{ + save_item(NAME(m_repeat)); + save_item(NAME(m_last_repeat)); } //------------------------------------------------- @@ -100,7 +98,12 @@ TIMER_CALLBACK_MEMBER(mm5740_device::perform_scan) for (int x = 0; x < 9; x++) { - uint16_t data = m_read_x[x]() ^ 0x3ff; + u16 data = m_read_x[x]() ^ 0x3ff; + + if (data) + { + ako = true; + } if ((data ^ m_x_mask[x]) == 0) { @@ -110,41 +113,55 @@ TIMER_CALLBACK_MEMBER(mm5740_device::perform_scan) for (int y = 0; y < 10; y++) { + u16 offset = x * 10 + y; + if (BIT(data, y)) { - uint8_t *rom = m_rom->base(); - uint16_t offset = x*10 + y; + u8 *rom = m_rom->base(); // Common portion - uint16_t common = (uint16_t) rom[offset]; + u16 common = (u16)rom[offset]; - offset += (((m_read_shift() ? 1: 0) + (m_read_control() ? 2: 0)) + 1) * 90; + u16 uniq_offset = offset + ((((m_read_shift() ? 1 : 0) + (m_read_control() ? 2 : 0)) + 1) * 90); // Unique portion based on shift/ctrl keys. - uint8_t uniq = rom[offset]; - - uint16_t b = (((common & 0x10) << 4) | ((uniq & 0x0f) << 4) | (common & 0x0f)) ^ 0x1ff; + u8 uniq = rom[uniq_offset]; - ako = true; + u16 b = (((common & 0x10) << 4) | ((uniq & 0x0f) << 4) | (common & 0x0f)) ^ 0x1ff; + // Check for a new keypress if (!BIT(m_x_mask[x], y)) { m_x_mask[x] |= (1 << y); if (m_b != b) { m_b = b; + m_offset = offset; m_write_data_ready(ASSERT_LINE); return; } } } - else // key released, unmark it from the "down" info + else { + // key released, unmark it from the "down" info m_x_mask[x] &= ~(1 << y); + if (m_offset == offset) + { + m_write_data_ready(CLEAR_LINE); + m_b = -1; + } } } } + if ((m_repeat) && (!m_last_repeat) && (m_b != -1)) + { + m_write_data_ready(ASSERT_LINE); + } + + m_last_repeat = m_repeat; + if (!ako) { m_write_data_ready(CLEAR_LINE); @@ -152,12 +169,16 @@ TIMER_CALLBACK_MEMBER(mm5740_device::perform_scan) } } +void mm5740_device::repeat_line_w(int state) +{ + m_repeat = (state == ASSERT_LINE); +} //------------------------------------------------- // b_r - //------------------------------------------------- -uint16_t mm5740_device::b_r() +u16 mm5740_device::b_r() { m_write_data_ready(CLEAR_LINE); return m_b; diff --git a/src/devices/machine/mm5740.h b/src/devices/machine/mm5740.h index c1e4eb81f70..7158009cdf3 100644 --- a/src/devices/machine/mm5740.h +++ b/src/devices/machine/mm5740.h @@ -1,10 +1,10 @@ // license:BSD-3-Clause -// copyright-holders: R. Belmont +// copyright-holders: R. Belmont, Mark Garlanger /********************************************************************** MM5740 Keyboard Encoder emulation -********************************************************************** + ********************************************************************** _____ _____ B3 1 |* \_/ | 40 B4 Vll 2 | | 39 B9 @@ -27,13 +27,14 @@ Control 19 | | 22 Y10 Shift Lock I/O 20 |_____________| 21 Shift + Name Pin No. Function ---------------------------------------------------------------------- X1-X9 4-12 Output - Drives the key switch matrix. Y1-Y10 22-31 Inputs - connect to the X drive lines with - the key switch matrix. + the key switch matrix. B1-B9 1,33-40 Tri-stated data outputs. @@ -44,10 +45,10 @@ Data Strobe Control 14 Input to control data strobe output pulse width Output Enable 15 Input to control the chip's TRI-STATE output Repeat 16 Each cycle of this signal will issue - a new data strobe for the pressed key. + a new data strobe for the pressed key. Key-Bounce Mask 17 Use capacitor on this chip to provide - key debouncing + key debouncing Shift 21 Shift key pressed @@ -63,12 +64,9 @@ Vll 2 Ground Vgg 18 -12V - **********************************************************************/ /* TODO: - Support Key-bounce mask - Support Repeat function Support shift lock Support additional internal ROMs */ @@ -78,33 +76,26 @@ Vgg 18 -12V #pragma once - -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** - -// ======================> mm5740_device - class mm5740_device : public device_t { public: - // construction/destruction - mm5740_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + mm5740_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); // public interface - uint16_t b_r(); + u16 b_r(); template auto x_cb() { return m_read_x[N - 1].bind(); } auto shift_cb() { return m_read_shift.bind(); } auto control_cb() { return m_read_control.bind(); } auto data_ready_cb() { return m_write_data_ready.bind(); } - static uint32_t calc_effective_clock_key_debounce(uint32_t capacitance); + void repeat_line_w(int state); + + static u32 calc_effective_clock_key_debounce(u32 capacitance); protected: // device-level overrides virtual void device_start() override; - virtual void device_reset() override; virtual const tiny_rom_entry *device_rom_region() const override; @@ -116,14 +107,17 @@ private: devcb_read_line m_read_control; devcb_write_line m_write_data_ready; - required_memory_region m_rom; // Internal ROM + required_memory_region m_rom; // Internal ROM - int m_b; // output buffer + s32 m_b; // output buffer + u16 m_offset; // last key pressed (without shift/ctrl modifiers) - int m_x_mask[9]; // mask of what keys are down + u16 m_x_mask[9]; // mask of what keys are down + bool m_repeat; // state of the 'repeat' input. + bool m_last_repeat; // state of the repeat input on the last scan. // timers - emu_timer *m_scan_timer; // keyboard scan timer + emu_timer *m_scan_timer; // keyboard scan timer }; diff --git a/src/mame/heathkit/h89.cpp b/src/mame/heathkit/h89.cpp index 94859793d8e..6174b1b26d5 100644 --- a/src/mame/heathkit/h89.cpp +++ b/src/mame/heathkit/h89.cpp @@ -454,7 +454,7 @@ void h89_state::h89(machine_config & config) HEATH_TLB(config, m_tlb); // Connect the console port on CPU board to serial port on TLB - m_console->out_tx_callback().set(m_tlb, FUNC(heath_tlb_device::cb1_w)); + m_console->out_tx_callback().set(m_tlb, FUNC(heath_tlb_device::serial_in_w)); m_tlb->serial_data_callback().set(m_console, FUNC(ins8250_uart_device::rx_w)); m_tlb->reset_cb().set(FUNC(h89_state::reset_line)); diff --git a/src/mame/heathkit/tlb.cpp b/src/mame/heathkit/tlb.cpp index 772c9ad3894..378f9f1996a 100644 --- a/src/mame/heathkit/tlb.cpp +++ b/src/mame/heathkit/tlb.cpp @@ -19,7 +19,6 @@ TODO: - determine why ULTRA ROM's self-diag (ESC |) fails for the ROM and scratchpad memory - - when pressing "REPEAT", the other pressed key should repeatedly trigger ****************************************************************************/ /*************************************************************************** @@ -42,12 +41,12 @@ ---------------------------------------------------- 0x00 Power-up configuration (primary - SW401) 0x20 Power-up configuration (secondary - SW402) - 0x40 ACE (communications) - 0x60 CRT controller - 0x80 Keyboard encoder + 0x40 INS8250 ACE (communications) + 0x60 MC6845 CRT controller + 0x80 MM5740 Keyboard encoder 0xA0 Keyboard status - 0xC0 Key click enable - 0xE0 Bell enable + 0xC0 Trigger key click + 0xE0 Trigger bell ****************************************************************************/ @@ -93,13 +92,14 @@ heath_tlb_device::heath_tlb_device(const machine_config &mconfig, device_type ty m_p_chargen(*this, "chargen"), m_mm5740(*this, "mm5740"), m_kbdrom(*this, "keyboard"), - m_kbspecial(*this, "MODIFIERS") + m_kbspecial(*this, "MODIFIERS"), + m_repeat_clock(*this, "repeatclock") { } -void heath_tlb_device::checkBeepState() +void heath_tlb_device::check_beep_state() { - if (!m_keyclickactive && !m_bellactive) + if (!m_key_click_active && !m_bell_active) { m_beep->set_state(0); } @@ -107,16 +107,16 @@ void heath_tlb_device::checkBeepState() TIMER_CALLBACK_MEMBER(heath_tlb_device::key_click_off) { - m_keyclickactive = false; + m_key_click_active = false; - checkBeepState(); + check_beep_state(); } TIMER_CALLBACK_MEMBER(heath_tlb_device::bell_off) { - m_bellactive = false; + m_bell_active = false; - checkBeepState(); + check_beep_state(); } void heath_tlb_device::mem_map(address_map &map) @@ -152,6 +152,7 @@ static constexpr uint8_t KB_STATUS_SHIFT_KEYS_MASK = 0x01; static constexpr uint8_t KB_STATUS_CAPS_LOCK_MASK = 0x02; static constexpr uint8_t KB_STATUS_BREAK_KEY_MASK = 0x04; static constexpr uint8_t KB_STATUS_ONLINE_KEY_MASK = 0x08; +static constexpr uint8_t KB_STATUS_CONTROL_KEY_MASK = 0x10; static constexpr uint8_t KB_STATUS_REPEAT_KEYS_MASK = 0x40; static constexpr uint8_t KB_STATUS_KEYBOARD_STROBE_MASK = 0x80; @@ -159,18 +160,22 @@ void heath_tlb_device::device_start() { save_item(NAME(m_transchar)); save_item(NAME(m_strobe)); - save_item(NAME(m_keyclickactive)); - save_item(NAME(m_bellactive)); + save_item(NAME(m_key_click_active)); + save_item(NAME(m_bell_active)); save_item(NAME(m_reset_pending)); save_item(NAME(m_right_shift)); save_item(NAME(m_reset_key)); + save_item(NAME(m_keyboard_irq_raised)); + save_item(NAME(m_serial_irq_raised)); m_strobe = false; - m_keyclickactive = false; - m_bellactive = false; + m_key_click_active = false; + m_bell_active = false; m_reset_pending = false; m_right_shift = false; m_reset_key = false; + m_keyboard_irq_raised = false; + m_serial_irq_raised = false; m_key_click_timer = timer_alloc(FUNC(heath_tlb_device::key_click_off), this); m_bell_timer = timer_alloc(FUNC(heath_tlb_device::bell_off), this); @@ -179,15 +184,15 @@ void heath_tlb_device::device_start() void heath_tlb_device::device_reset() { m_strobe = false; - m_keyclickactive = false; - m_bellactive = false; + m_key_click_active = false; + m_bell_active = false; } void heath_tlb_device::key_click_w(uint8_t data) { // Keyclick - 6 mSec m_beep->set_state(1); - m_keyclickactive = true; + m_key_click_active = true; m_key_click_timer->adjust(attotime::from_msec(6)); } @@ -195,7 +200,7 @@ void heath_tlb_device::bell_w(uint8_t data) { // Bell (^G) - 200 mSec m_beep->set_state(1); - m_bellactive = true; + m_bell_active = true; m_bell_timer->adjust(attotime::from_msec(200)); } @@ -223,7 +228,8 @@ uint16_t heath_tlb_device::translate_mm5740_b(uint16_t b) uint8_t heath_tlb_device::kbd_key_r() { - m_maincpu->set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE); + m_keyboard_irq_raised = false; + set_irq_line(); m_strobe = false; // high bit is for control key pressed, this is handled in the ROM, @@ -257,7 +263,7 @@ int heath_tlb_device::mm5740_shift_r() int heath_tlb_device::mm5740_control_r() { - return (m_kbspecial->read() & 0x10) ? CLEAR_LINE : ASSERT_LINE; + return (m_kbspecial->read() & KB_STATUS_CONTROL_KEY_MASK) ? CLEAR_LINE : ASSERT_LINE; } void heath_tlb_device::mm5740_data_ready_w(int state) @@ -268,10 +274,23 @@ void heath_tlb_device::mm5740_data_ready_w(int state) m_transchar = decode[translate_mm5740_b(m_mm5740->b_r())]; m_strobe = true; - m_maincpu->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE); + m_keyboard_irq_raised = true; + set_irq_line(); } } +void heath_tlb_device::serial_irq_w(int state) +{ + m_serial_irq_raised = state != CLEAR_LINE; + set_irq_line(); +} + +void heath_tlb_device::set_irq_line() +{ + m_maincpu->set_input_line(INPUT_LINE_IRQ0, + (m_keyboard_irq_raised || m_serial_irq_raised) ? ASSERT_LINE : CLEAR_LINE); +} + void heath_tlb_device::check_for_reset() { if (m_reset_key && m_right_shift) @@ -303,6 +322,12 @@ void heath_tlb_device::right_shift_w(int state) check_for_reset(); } +void heath_tlb_device::repeat_key_w(int state) +{ + // when repeat key pressed, set duty cycle to 0.5, else 0. + m_repeat_clock->set_duty_cycle(state == CLEAR_LINE ? 0.5 : 0); +} + MC6845_UPDATE_ROW(heath_tlb_device::crtc_update_row) { rgb_t const *const palette = m_palette->palette()->entry_list_raw(); @@ -384,7 +409,7 @@ static INPUT_PORTS_START( tlb ) PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("OffLine") PORT_CODE(KEYCODE_F12) PORT_TOGGLE PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("LeftShift") PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Repeat") PORT_CODE(KEYCODE_LALT) + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Repeat") PORT_CODE(KEYCODE_RALT) PORT_WRITE_LINE_MEMBER(heath_tlb_device, repeat_key_w) // bit 7 - 0x080 is low if a key is pressed PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("RightShift") PORT_CODE(KEYCODE_RSHIFT) PORT_WRITE_LINE_MEMBER(heath_tlb_device, right_shift_w) PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Reset") PORT_CODE(KEYCODE_F10) PORT_WRITE_LINE_MEMBER(heath_tlb_device, reset_key_w) @@ -749,7 +774,7 @@ void heath_tlb_device::serial_out_b(uint8_t data) m_write_sd(data); } -void heath_tlb_device::cb1_w(int state) +void heath_tlb_device::serial_in_w(int state) { m_ace->rx_w(state); } @@ -775,11 +800,12 @@ void heath_tlb_device::device_add_mconfig(machine_config &config) m_crtc->set_show_border_area(true); m_crtc->set_char_width(8); m_crtc->set_update_row_callback(FUNC(heath_tlb_device::crtc_update_row)); - m_crtc->out_vsync_callback().set_inputline(m_maincpu, INPUT_LINE_NMI); // frame pulse + // frame pulse + m_crtc->out_vsync_callback().set_inputline(m_maincpu, INPUT_LINE_NMI); // serial port INS8250(config, m_ace, INS8250_CLOCK); - m_ace->out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); + m_ace->out_int_callback().set(FUNC(heath_tlb_device::serial_irq_w)); m_ace->out_tx_callback().set(FUNC(heath_tlb_device::serial_out_b)); // keyboard @@ -800,6 +826,10 @@ void heath_tlb_device::device_add_mconfig(machine_config &config) // sound hardware SPEAKER(config, "mono").front_center(); BEEP(config, m_beep, H19_BEEP_FRQ).add_route(ALL_OUTPUTS, "mono", 0.05); + + CLOCK(config, m_repeat_clock, 40); + m_repeat_clock->set_duty_cycle(0); + m_repeat_clock->signal_handler().set(m_mm5740, FUNC(mm5740_device::repeat_line_w)); } heath_super19_tlb_device::heath_super19_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : diff --git a/src/mame/heathkit/tlb.h b/src/mame/heathkit/tlb.h index 220c73149b3..c8ce66714ff 100644 --- a/src/mame/heathkit/tlb.h +++ b/src/mame/heathkit/tlb.h @@ -12,6 +12,7 @@ #pragma once #include "cpu/z80/z80.h" +#include "machine/clock.h" #include "machine/ins8250.h" #include "machine/mm5740.h" #include "sound/beep.h" @@ -29,10 +30,12 @@ public: auto serial_data_callback() { return m_write_sd.bind(); } auto reset_cb() { return m_reset.bind(); } - void cb1_w(int state); + void serial_in_w(int state); void reset_key_w(int state); void right_shift_w(int state); + void repeat_key_w(int state); + void serial_irq_w(int state); protected: heath_tlb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock = 0); @@ -49,14 +52,16 @@ protected: required_device m_maincpu; private: + void set_irq_line(); + void check_for_reset(); + void key_click_w(uint8_t data); void bell_w(uint8_t data); - void check_for_reset(); uint8_t kbd_key_r(); uint8_t kbd_flags_r(); uint16_t translate_mm5740_b(uint16_t b); - void checkBeepState(); + void check_beep_state(); void serial_out_b(uint8_t data); @@ -80,18 +85,21 @@ private: required_device m_ace; required_device m_beep; required_shared_ptr m_p_videoram; - required_region_ptr m_p_chargen; + required_region_ptr m_p_chargen; required_device m_mm5740; required_memory_region m_kbdrom; required_ioport m_kbspecial; + required_device m_repeat_clock; uint8_t m_transchar; bool m_strobe; - bool m_keyclickactive; - bool m_bellactive; + bool m_key_click_active; + bool m_bell_active; bool m_reset_pending; bool m_right_shift; bool m_reset_key; + bool m_keyboard_irq_raised; + bool m_serial_irq_raised; }; class heath_super19_tlb_device : public heath_tlb_device -- cgit v1.2.3