Skip to content

Commit

Permalink
heath/h19.cpp Implement Shift-Reset functionality (mamedev#11330)
Browse files Browse the repository at this point in the history
  • Loading branch information
mgarlanger committed Jun 14, 2023
1 parent fdce6a4 commit 2c02460
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 39 deletions.
4 changes: 2 additions & 2 deletions src/mame/heathkit/h19.cpp
Expand Up @@ -5,7 +5,7 @@
Heathkit H19
A smart terminal designed and manufactured by Heath Company. This
is identical to the Zenith Data Systems Z-19.
is identical to the Zenith Data Systems Z-19.
****************************************************************************/

Expand Down Expand Up @@ -69,7 +69,7 @@ ROM_START( ultra19 )
ROM_END
} // anonymous namespace

// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
COMP( 1979, h19, 0, 0, h19, 0, h19_state, empty_init, "Heath Company", "Heathkit H-19", MACHINE_SUPPORTS_SAVE )
//Super-19 ROM - ATG Systems, Inc - Adv in Sextant Issue 4, Winter 1983. With the magazine lead-time, likely released late 1982.
COMP( 1982, super19, h19, 0, h19_superh19, 0, h19_state, empty_init, "Heath Company", "Heathkit H-19 w/ Super-19 ROM", MACHINE_SUPPORTS_SAVE )
Expand Down
19 changes: 18 additions & 1 deletion src/mame/heathkit/h89.cpp
Expand Up @@ -123,6 +123,7 @@ class h89_state : public driver_device
uint8_t raise_NMI_r();
void raise_NMI_w(uint8_t data);
void console_intr(uint8_t data);
void reset_line(uint8_t data);
};

/*
Expand Down Expand Up @@ -362,9 +363,15 @@ void h89_state::machine_reset()

update_gpp(0);
update_mem_view();
m_h37->reset();
m_intr_cntrl->reset();
m_console->reset();
m_serial1->reset();
m_serial2->reset();
m_serial3->reset();
m_maincpu->reset();
}


uint8_t h89_state::raise_NMI_r()
{
m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::from_usec(2));
Expand All @@ -389,6 +396,14 @@ void h89_state::console_intr(uint8_t data)
}
}

void h89_state::reset_line(uint8_t data)
{
if (data == ASSERT_LINE)
{
reset();
}
}

TIMER_DEVICE_CALLBACK_MEMBER(h89_state::h89_irq_timer)
{
if (m_timer_intr_enabled)
Expand Down Expand Up @@ -448,6 +463,8 @@ void h89_state::h89(machine_config & config)
m_console->out_tx_callback().set(m_tlb, FUNC(heath_tlb_device::cb1_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));

HEATH_Z37_FDC(config, m_h37);
m_h37->drq_cb().set(m_intr_cntrl, FUNC(z37_intr_cntrl::set_drq));
m_h37->irq_cb().set(m_intr_cntrl, FUNC(z37_intr_cntrl::set_intrq));
Expand Down
14 changes: 14 additions & 0 deletions src/mame/heathkit/intr_cntrl.cpp
Expand Up @@ -31,6 +31,11 @@ void heath_intr_cntrl::device_start()
m_intr_lines = 0;
}

void heath_intr_cntrl::device_reset()
{
m_intr_lines = 0;
}

void heath_intr_cntrl::device_resolve_objects()
{
m_irq_line.resolve_safe();
Expand Down Expand Up @@ -171,6 +176,15 @@ void z37_intr_cntrl::device_start()
m_fd_irq_raised = false;
}

void z37_intr_cntrl::device_reset()
{
heath_intr_cntrl::device_reset();

m_interrupts_blocked = false;
m_drq_raised = false;
m_fd_irq_raised = false;
}

void z37_intr_cntrl::block_interrupts(uint8_t data)
{
m_interrupts_blocked = (data != CLEAR_LINE);
Expand Down
3 changes: 3 additions & 0 deletions src/mame/heathkit/intr_cntrl.h
Expand Up @@ -36,6 +36,8 @@ class heath_intr_cntrl : public device_t
virtual void update_intr_line();

virtual void device_start() override;
virtual void device_reset() override;

virtual void device_resolve_objects() override;

devcb_write8 m_irq_line;
Expand All @@ -62,6 +64,7 @@ class z37_intr_cntrl : public heath_intr_cntrl
virtual void update_intr_line() override;

virtual void device_start() override;
virtual void device_reset() override;

private:
bool m_interrupts_blocked;
Expand Down
105 changes: 71 additions & 34 deletions src/mame/heathkit/tlb.cpp
Expand Up @@ -6,7 +6,7 @@
The board used in the H19 smart terminal designed and manufactured
by Heath Company. (and the identical Z19 sold by Zenith Data Systems)
This board is also used the Heath's H89 / H88, and ZDS's Z-89 and Z-90.
This board is also used the Heath's H89 / H88, and ZDS's Z-89 and Z-90.
The keyboard consists of a 9x10 matrix connected to a MM5740AAC/N
mask-programmed keyboard controller. The output of this passes
Expand All @@ -19,12 +19,14 @@
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
****************************************************************************/
/***************************************************************************
Memory Layout
The U435 three-to-eight line decoder uses A14 and A15 to generate three memory addresses:
The U435 three-to-eight line decoder uses A14 and A15 to generate
three memory addresses:
1. Program ROM 0x0000
2. Scratchpad RAM 0x4000
Expand All @@ -33,7 +35,8 @@
Port Layout
Only address lines A5, A6, A7 are used by the U442 three-to-eight line decoder
Only address lines A5, A6, A7 are used by the U442 three-to-eight
line decoder
Address Description
----------------------------------------------------
Expand Down Expand Up @@ -81,6 +84,7 @@ heath_tlb_device::heath_tlb_device(const machine_config &mconfig, device_type ty
device_t(mconfig, type, tag, owner, clock),
m_maincpu(*this, "maincpu"),
m_write_sd(*this),
m_reset(*this),
m_palette(*this, "palette"),
m_crtc(*this, "crtc"),
m_ace(*this, "ins8250"),
Expand Down Expand Up @@ -153,26 +157,40 @@ static constexpr uint8_t KB_STATUS_KEYBOARD_STROBE_MASK = 0x80;

void heath_tlb_device::device_resolve_objects()
{

m_write_sd.resolve_safe();
m_reset.resolve_safe();
}

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_reset_pending));

m_strobe = false;
m_keyclickactive = false;
m_bellactive = false;
m_reset_pending = 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);
}

void heath_tlb_device::device_reset()
{
m_strobe = false;
m_keyclickactive = false;
m_bellactive = false;
m_reset_pending = false;

m_crtc->reset();
m_ace->reset();
m_beep->reset();
m_mm5740->reset();
m_maincpu->reset();
}

void heath_tlb_device::key_click_w(uint8_t data)
{
Expand Down Expand Up @@ -212,22 +230,39 @@ uint16_t heath_tlb_device::translate_mm5740_b(uint16_t b)
return ((b & 0x100) >> 2) | ((b & 0x0c0) << 1) | (b & 0x03f);
}

void heath_tlb_device::check_for_reset()
{
ioport_value value = m_kbspecial->read();

if ((value & 0x300) == 0)
{
m_reset_pending = true;
}
else if (m_reset_pending)
{
m_reset_pending = false;
m_maincpu->reset();
m_reset(ASSERT_LINE);
}
}

uint8_t heath_tlb_device::kbd_key_r()
{
m_maincpu->set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE);
m_strobe = false;

// high bit is for control key pressed, this is handled in the ROM, no processing needed.
// high bit is for control key pressed, this is handled in the ROM,
// no processing needed.
return m_transchar;
}

uint8_t heath_tlb_device::kbd_flags_r()
{
uint16_t modifiers = m_kbspecial->read();
uint8_t rv = modifiers & 0x7f;
uint8_t rv = modifiers & 0x7e;

// check both shifts
if ((modifiers & 0x020) == 0 || (modifiers & 0x100) == 0)
if ((modifiers & 0x120) != 0x120)
{
rv |= KB_STATUS_SHIFT_KEYS_MASK;
}
Expand All @@ -242,16 +277,18 @@ uint8_t heath_tlb_device::kbd_flags_r()

int heath_tlb_device::mm5740_shift_r()
{
return ((m_kbspecial->read() ^ 0x120) & 0x120) ? ASSERT_LINE : CLEAR_LINE;
return ((m_kbspecial->read() & 0x120) != 0x120) ? ASSERT_LINE : CLEAR_LINE;
}

int heath_tlb_device::mm5740_control_r()
{
return ((m_kbspecial->read() ^ 0x10) & 0x10) ? ASSERT_LINE: CLEAR_LINE;
return (m_kbspecial->read() & 0x10) ? CLEAR_LINE : ASSERT_LINE;
}

void heath_tlb_device::mm5740_data_ready_w(int state)
{
check_for_reset();

if (state == ASSERT_LINE)
{
uint8_t *decode = m_kbdrom->base();
Expand Down Expand Up @@ -331,8 +368,8 @@ static INPUT_PORTS_START( tlb )
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)
// 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_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Reset") PORT_CODE(KEYCODE_F10)
PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("RightShift") PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_2)
PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Reset") PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10))

PORT_START("X1")
PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("/") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
Expand All @@ -350,7 +387,7 @@ static INPUT_PORTS_START( tlb )
PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("; :") PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\' \"") PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"')
PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("{ }") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('{') PORT_CHAR('}')
PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-1 IL") PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD))
Expand Down Expand Up @@ -383,15 +420,15 @@ static INPUT_PORTS_START( tlb )
PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_UNUSED)

PORT_START("X5")
PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F1") PORT_CODE(KEYCODE_F1)
PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F2") PORT_CODE(KEYCODE_F2)
PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F3") PORT_CODE(KEYCODE_F3)
PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F4") PORT_CODE(KEYCODE_F4)
PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F5") PORT_CODE(KEYCODE_F5)
PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Erase") PORT_CODE(KEYCODE_F6)
PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Blue") PORT_CODE(KEYCODE_F7)
PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Red") PORT_CODE(KEYCODE_F8)
PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Gray") PORT_CODE(KEYCODE_F9)
PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F1") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F2") PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F3") PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))
PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F4") PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))
PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F5") PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Erase") PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))
PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Blue") PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))
PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Red") PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))
PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Gray") PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9))
PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_UNUSED)

PORT_START("X6")
Expand Down Expand Up @@ -443,7 +480,7 @@ static INPUT_PORTS_START( tlb )
PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC))

PORT_START("SW401")
PORT_DIPNAME( 0x0f, 0x0c, "Baud Rate") PORT_DIPLOCATION("SW401:1,2,3,4")
PORT_DIPNAME( 0x0f, 0x0c, "Baud Rate") PORT_DIPLOCATION("SW401:1,2,3,4")
PORT_DIPSETTING( 0x01, "110")
PORT_DIPSETTING( 0x02, "150")
PORT_DIPSETTING( 0x03, "300")
Expand All @@ -470,28 +507,28 @@ static INPUT_PORTS_START( tlb )
PORT_DIPSETTING( 0x80, "Full")

PORT_START("SW402")
PORT_DIPNAME( 0x01, 0x00, "Cursor") PORT_DIPLOCATION("SW402:1")
PORT_DIPNAME( 0x01, 0x00, "Cursor") PORT_DIPLOCATION("SW402:1")
PORT_DIPSETTING( 0x00, "Underline")
PORT_DIPSETTING( 0x01, "Block")
PORT_DIPNAME( 0x02, 0x00, "Keyclick") PORT_DIPLOCATION("SW402:2")
PORT_DIPNAME( 0x02, 0x00, "Keyclick") PORT_DIPLOCATION("SW402:2")
PORT_DIPSETTING( 0x02, DEF_STR(No))
PORT_DIPSETTING( 0x00, DEF_STR(Yes))
PORT_DIPNAME( 0x04, 0x00, "Wrap at EOL") PORT_DIPLOCATION("SW402:3")
PORT_DIPNAME( 0x04, 0x00, "Wrap at EOL") PORT_DIPLOCATION("SW402:3")
PORT_DIPSETTING( 0x00, DEF_STR(No))
PORT_DIPSETTING( 0x04, DEF_STR(Yes))
PORT_DIPNAME( 0x08, 0x00, "Auto LF on CR") PORT_DIPLOCATION("SW402:4")
PORT_DIPNAME( 0x08, 0x00, "Auto LF on CR") PORT_DIPLOCATION("SW402:4")
PORT_DIPSETTING( 0x00, DEF_STR(No))
PORT_DIPSETTING( 0x08, DEF_STR(Yes))
PORT_DIPNAME( 0x10, 0x00, "Auto CR on LF") PORT_DIPLOCATION("SW402:5")
PORT_DIPNAME( 0x10, 0x00, "Auto CR on LF") PORT_DIPLOCATION("SW402:5")
PORT_DIPSETTING( 0x00, DEF_STR(No))
PORT_DIPSETTING( 0x10, DEF_STR(Yes))
PORT_DIPNAME( 0x20, 0x00, "Mode") PORT_DIPLOCATION("SW402:6")
PORT_DIPNAME( 0x20, 0x00, "Mode") PORT_DIPLOCATION("SW402:6")
PORT_DIPSETTING( 0x00, "Heath/VT52")
PORT_DIPSETTING( 0x20, "ANSI")
PORT_DIPNAME( 0x40, 0x00, "Keypad Shifted") PORT_DIPLOCATION("SW402:7")
PORT_DIPNAME( 0x40, 0x00, "Keypad Shifted") PORT_DIPLOCATION("SW402:7")
PORT_DIPSETTING( 0x00, DEF_STR(No))
PORT_DIPSETTING( 0x40, DEF_STR(Yes))
PORT_DIPNAME( 0x80, 0x00, "Refresh") PORT_DIPLOCATION("SW402:8")
PORT_DIPNAME( 0x80, 0x00, "Refresh") PORT_DIPLOCATION("SW402:8")
PORT_DIPSETTING( 0x00, "60Hz")
PORT_DIPSETTING( 0x80, "50Hz")
INPUT_PORTS_END
Expand Down Expand Up @@ -581,7 +618,7 @@ static INPUT_PORTS_START( ultra19 )
PORT_DIPSETTING( 0x20, "Invisible")
PORT_DIPSETTING( 0x40, "Fast Blink")
PORT_DIPSETTING( 0x60, "Slow Blink")
PORT_DIPNAME( 0x80, 0x00, "Interlace Scan Mode") PORT_DIPLOCATION("SW402:8")
PORT_DIPNAME( 0x80, 0x00, "Interlace Scan Mode") PORT_DIPLOCATION("SW402:8")
PORT_DIPSETTING( 0x00, "Off")
PORT_DIPSETTING( 0x80, "On")

Expand All @@ -591,7 +628,7 @@ static INPUT_PORTS_START( watz19 )
PORT_INCLUDE( tlb )

PORT_MODIFY("SW401")
PORT_DIPNAME( 0x0f, 0x0c, "Baud Rate") PORT_DIPLOCATION("SW401:1,2,3,4")
PORT_DIPNAME( 0x0f, 0x0c, "Baud Rate") PORT_DIPLOCATION("SW401:1,2,3,4")
PORT_DIPSETTING( 0x00, "75")
PORT_DIPSETTING( 0x01, "110")
PORT_DIPSETTING( 0x02, "150")
Expand All @@ -608,7 +645,7 @@ static INPUT_PORTS_START( watz19 )
PORT_DIPSETTING( 0x0d, "19200")
PORT_DIPSETTING( 0x0e, "38400")
PORT_DIPSETTING( 0x0f, "134.5")
PORT_DIPNAME( 0x40, 0x00, "Word Size") PORT_DIPLOCATION("SW401:7")
PORT_DIPNAME( 0x40, 0x00, "Word Size") PORT_DIPLOCATION("SW401:7")
PORT_DIPSETTING( 0x00, "8-bit Word")
PORT_DIPSETTING( 0x40, "7-bit Word")
PORT_DIPNAME( 0x80, 0x80, "Duplex") PORT_DIPLOCATION("SW401:8")
Expand Down

0 comments on commit 2c02460

Please sign in to comment.