diff --git a/src/mame/heathkit/h19.cpp b/src/mame/heathkit/h19.cpp index 5aefbbb91b9..b1103180aae 100644 --- a/src/mame/heathkit/h19.cpp +++ b/src/mame/heathkit/h19.cpp @@ -21,627 +21,73 @@ - update SW401 & SW402 definitions for ULTRA ROM - add option for ULTRA ROMs second page of screen RAM -****************************************************************************/ -/*************************************************************************** - Memory Layout - The U435 three-to-eight line decoder uses A14 and A15 to generate three memory addresses: - - 1. Program ROM 0x0000 - - 2. Scratchpad RAM 0x4000 - - 3. Display Memory 0xF800 - - - Port Layout - - Only address lines A5, A6, A7 are used by the U442 three-to-eight line decoder - -Address Description ----------------------------------------------------- - 0x00 Power-up configuration (primary - SW401) - 0x20 Power-up configuration (secondary - SW402) - 0x40 ACE (communications) - 0x60 CRT controller - 0x80 Keyboard encoder - 0xA0 Keyboard status - 0xC0 Key click enable - 0xE0 Bell enable - ****************************************************************************/ #include "emu.h" -#include "cpu/z80/z80.h" -#include "machine/ins8250.h" -#include "machine/mm5740.h" -#include "sound/beep.h" -#include "video/mc6845.h" -#include "emupal.h" -#include "screen.h" -#include "speaker.h" +#include "tlb.h" namespace { -// Standard H19 used a 2.048 MHz clock -#define H19_CLOCK (XTAL(12'288'000) / 6) -#define MC6845_CLOCK (XTAL(12'288'000) /8) -#define INS8250_CLOCK (XTAL(12'288'000) /4) - -// Capacitor value in pF -#define H19_KEY_DEBOUNCE_CAPACITOR 5000 -#define MM5740_CLOCK (mm5740_device::calc_effective_clock_key_debounce(H19_KEY_DEBOUNCE_CAPACITOR)) - -// Beep Frequency is 1 KHz -#define H19_BEEP_FRQ (H19_CLOCK / 2048) - -#define KBDC_TAG "mm5740" - class h19_state : public driver_device { public: - h19_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag) - , m_palette(*this, "palette") - , m_maincpu(*this, "maincpu") - , m_crtc(*this, "crtc") - , m_ace(*this, "ins8250") - , m_beep(*this, "beeper") - , m_p_videoram(*this, "videoram") - , m_p_chargen(*this, "chargen") - , m_mm5740(*this, KBDC_TAG) - , m_kbdrom(*this, "keyboard") - , m_kbspecial(*this, "MODIFIERS") + h19_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_tlb(*this, "tlb") { } void h19(machine_config &config); + void h19_superh19(machine_config &config); + void h19_watzh19(machine_config &config); + void h19_ultrah19(machine_config &config); private: - virtual void machine_start() override; - void mem_map(address_map &map); - void io_map(address_map &map); + required_device m_tlb; - void key_click_w(uint8_t data); - void bell_w(uint8_t data); - uint8_t kbd_key_r(); - uint8_t kbd_flags_r(); - DECLARE_READ_LINE_MEMBER(mm5740_shift_r); - DECLARE_READ_LINE_MEMBER(mm5740_control_r); - DECLARE_WRITE_LINE_MEMBER(mm5740_data_ready_w); - - MC6845_UPDATE_ROW(crtc_update_row); - - TIMER_CALLBACK_MEMBER(key_click_off); - TIMER_CALLBACK_MEMBER(bell_off); - - emu_timer *m_key_click_timer = nullptr; - emu_timer *m_bell_timer = nullptr; - - required_device m_palette; - required_device m_maincpu; - required_device m_crtc; - required_device m_ace; - required_device m_beep; - required_shared_ptr m_p_videoram; - required_region_ptr m_p_chargen; - required_device m_mm5740; - required_memory_region m_kbdrom; - required_ioport m_kbspecial; - - uint8_t m_transchar; - bool m_strobe; - bool m_keyclickactive; - bool m_bellactive; - - uint16_t translate_mm5740_b(uint16_t b); }; -TIMER_CALLBACK_MEMBER(h19_state::key_click_off) -{ - m_keyclickactive = false; - - if (!m_keyclickactive && !m_bellactive) - m_beep->set_state(0); -} - -TIMER_CALLBACK_MEMBER(h19_state::bell_off) -{ - m_bellactive = false; - - if (!m_keyclickactive && !m_bellactive) - m_beep->set_state(0); -} - - - -void h19_state::mem_map(address_map &map) -{ - map.unmap_value_high(); - map(0x0000, 0x1fff).mirror(0x2000).rom(); - map(0x4000, 0x4100).mirror(0x3e00).ram(); - map(0xc000, 0xc7ff).mirror(0x3800).ram().share("videoram"); -} - -void h19_state::io_map(address_map &map) -{ - map.unmap_value_high(); - map.global_mask(0xff); - map(0x00, 0x00).mirror(0x1f).portr("SW401"); - map(0x20, 0x20).mirror(0x1f).portr("SW402"); - map(0x40, 0x47).mirror(0x18).rw(m_ace, FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w)); - map(0x60, 0x60).mirror(0x1E).w(m_crtc, FUNC(mc6845_device::address_w)); - map(0x61, 0x61).mirror(0x1E).rw(m_crtc, FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w)); - map(0x80, 0x80).mirror(0x1f).r(FUNC(h19_state::kbd_key_r)); - map(0xa0, 0xa0).mirror(0x1f).r(FUNC(h19_state::kbd_flags_r)); - map(0xc0, 0xc0).mirror(0x1f).w(FUNC(h19_state::key_click_w)); - map(0xe0, 0xe0).mirror(0x1f).w(FUNC(h19_state::bell_w)); -} - -/* Input ports */ -static INPUT_PORTS_START( h19 ) - - PORT_START("MODIFIERS") - // bit 0 connects to B8 of MM5740 - low if either shift key is - // bit 7 is low if a key is pressed - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CapsLock") PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Break") PORT_CODE(KEYCODE_PAUSE) - 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(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_START("X1") - PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("/") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Unused") - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Unused") - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Unused") - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("k_X2") - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Unused") - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0-pad") PORT_CODE(KEYCODE_0_PAD) PORT_CHAR('0') - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Dot-pad") PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR('.') - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Enter-pad") PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(13) - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Unused") - - PORT_START("X2") - 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(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Unused") - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Unused") - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("1-pad") PORT_CODE(KEYCODE_1_PAD) PORT_CHAR('1') - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("2-pad") PORT_CODE(KEYCODE_2_PAD) PORT_CHAR('2') - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("3-pad") PORT_CODE(KEYCODE_3_PAD) PORT_CHAR('3') - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Unused") - - PORT_START("X3") - PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("[") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR(']') - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\\") PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|') - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("LF") PORT_CODE(KEYCODE_RWIN) - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("DEL") PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL)) - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Unused") - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("4-pad") PORT_CODE(KEYCODE_4_PAD) PORT_CHAR('4') - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("5-pad") PORT_CODE(KEYCODE_5_PAD) PORT_CHAR('5') - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("6-pad") PORT_CODE(KEYCODE_6_PAD) PORT_CHAR('6') - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Unused") - - PORT_START("X4") - PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("-") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_') - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("=") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+') - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("AccentAcute") PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~') - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("BS") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("k_X1") - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("7-pad") PORT_CODE(KEYCODE_7_PAD) PORT_CHAR('7') - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("8-pad") PORT_CODE(KEYCODE_8_PAD) PORT_CHAR('8') - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("9-pad") PORT_CODE(KEYCODE_9_PAD) PORT_CHAR('9') - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("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(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Unused") - - PORT_START("X6") - PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(",") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(".") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') - - PORT_START("X7") - PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Scroll") PORT_CODE(KEYCODE_LWIN) - - PORT_START("X8") - PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Tab") PORT_CODE(KEYCODE_TAB) PORT_CHAR(9) - - PORT_START("X9") - PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') - PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') - PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') - PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') - PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') - PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^') - PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') - PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') - PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') - PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CODE(KEYCODE_ESC) PORT_CHAR(27) - - PORT_START("SW401") - PORT_DIPNAME( 0x0f, 0x0c, "Baud Rate") - PORT_DIPSETTING( 0x01, "110") - PORT_DIPSETTING( 0x02, "150") - PORT_DIPSETTING( 0x03, "300") - PORT_DIPSETTING( 0x04, "600") - PORT_DIPSETTING( 0x05, "1200") - PORT_DIPSETTING( 0x06, "1800") - PORT_DIPSETTING( 0x07, "2000") - PORT_DIPSETTING( 0x08, "2400") - PORT_DIPSETTING( 0x09, "3600") - PORT_DIPSETTING( 0x0a, "4800") - PORT_DIPSETTING( 0x0b, "7200") - PORT_DIPSETTING( 0x0c, "9600") - PORT_DIPSETTING( 0x0d, "19200") - PORT_DIPNAME( 0x30, 0x00, "Parity") - PORT_DIPSETTING( 0x00, DEF_STR(None)) - PORT_DIPSETTING( 0x10, "Odd") - PORT_DIPSETTING( 0x30, "Even") - PORT_DIPNAME( 0x40, 0x00, "Parity Type") - PORT_DIPSETTING( 0x00, DEF_STR(Normal)) - PORT_DIPSETTING( 0x40, "Stick") - PORT_DIPNAME( 0x80, 0x80, "Duplex") - PORT_DIPSETTING( 0x00, "Half") - PORT_DIPSETTING( 0x80, "Full") - - PORT_START("SW402") // stored at 40C8 - PORT_DIPNAME( 0x01, 0x00, "Cursor") - PORT_DIPSETTING( 0x00, "Underline") - PORT_DIPSETTING( 0x01, "Block") - PORT_DIPNAME( 0x02, 0x00, "Keyclick") - PORT_DIPSETTING( 0x02, DEF_STR(No)) - PORT_DIPSETTING( 0x00, DEF_STR(Yes)) - PORT_DIPNAME( 0x04, 0x00, "Wrap at EOL") - PORT_DIPSETTING( 0x00, DEF_STR(No)) - PORT_DIPSETTING( 0x04, DEF_STR(Yes)) - PORT_DIPNAME( 0x08, 0x00, "Auto LF on CR") - PORT_DIPSETTING( 0x00, DEF_STR(No)) - PORT_DIPSETTING( 0x08, DEF_STR(Yes)) - PORT_DIPNAME( 0x10, 0x00, "Auto CR on LF") - PORT_DIPSETTING( 0x00, DEF_STR(No)) - PORT_DIPSETTING( 0x10, DEF_STR(Yes)) - PORT_DIPNAME( 0x20, 0x00, "Mode") - PORT_DIPSETTING( 0x00, "VT52") - PORT_DIPSETTING( 0x20, "ANSI") - PORT_DIPNAME( 0x40, 0x00, "Keypad Shifted") - PORT_DIPSETTING( 0x00, DEF_STR(No)) - PORT_DIPSETTING( 0x40, DEF_STR(Yes)) - PORT_DIPNAME( 0x80, 0x00, "Refresh") - PORT_DIPSETTING( 0x00, "50Hz") - PORT_DIPSETTING( 0x80, "60Hz") -INPUT_PORTS_END - -// Keyboard encoder masks -#define KB_ENCODER_KEY_VALUE_MASK 0x7f -#define KB_ENCODER_CONTROL_KEY_MASK 0x80 - -// Keyboard flag masks -#define KB_STATUS_SHIFT_KEYS_MASK 0x01 -#define KB_STATUS_CAPS_LOCK_MASK 0x02 -#define KB_STATUS_BREAK_KEY_MASK 0x04 -#define KB_STATUS_ONLINE_KEY_MASK 0x08 -#define KB_STATUS_REPEAT_KEYS_MASK 0x40 -#define KB_STATUS_KEYBOARD_STROBE_MASK 0x80 - - -void h19_state::machine_start() -{ - save_item(NAME(m_transchar)); - save_item(NAME(m_strobe)); - save_item(NAME(m_keyclickactive)); - save_item(NAME(m_bellactive)); - - m_keyclickactive = false; - m_bellactive = false; - - m_key_click_timer = timer_alloc(FUNC(h19_state::key_click_off), this); - m_bell_timer = timer_alloc(FUNC(h19_state::bell_off), this); -} - - -void h19_state::key_click_w(uint8_t data) -{ -/* Keyclick - 6 mSec */ - - m_beep->set_state(1); - m_keyclickactive = true; - m_key_click_timer->adjust(attotime::from_msec(6)); -} - -void h19_state::bell_w(uint8_t data) -{ -/* Bell (^G) - 200 mSec */ - - m_beep->set_state(1); - m_bellactive = true; - m_bell_timer->adjust(attotime::from_msec(200)); -} - - -/*************************************************************************** -MM5740 B Mapping to the ROM address - -B1 -> A0 A10 = 0 -B2 -> A1 A9 = 0 -B3 -> A2 A8 = B8 -B4 -> A3 A7 = B7 -B5 -> A4 A6 = B9 -B6 -> A5 A5 = B6 -B7 -> A7 A4 = B5 -B8 -> A8 A3 = B4 -B9 -> A6 A2 = B3 -ground -> A9 A1 = B2 -ground -> A10 A0 = B1 - -****************************************************************************/ -uint16_t h19_state::translate_mm5740_b(uint16_t b) -{ - return ((b & 0x100) >> 2) | ((b & 0x0c0) << 1) | (b & 0x03f); -} - -uint8_t h19_state::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. - return m_transchar; -} - -uint8_t h19_state::kbd_flags_r() -{ - uint16_t modifiers = m_kbspecial->read(); - uint8_t rv = modifiers & 0x7f; - - // check both shifts - if ((modifiers & 0x020) == 0 || (modifiers & 0x100) == 0) - { - rv |= KB_STATUS_SHIFT_KEYS_MASK; - } - - // invert offline switch - rv ^= KB_STATUS_ONLINE_KEY_MASK; - - if (!m_strobe) - { - rv |= KB_STATUS_KEYBOARD_STROBE_MASK; - } - - return rv; -} - -READ_LINE_MEMBER(h19_state::mm5740_shift_r) -{ - return ((m_kbspecial->read() ^ 0x120) & 0x120) ? ASSERT_LINE : CLEAR_LINE; -} - -READ_LINE_MEMBER(h19_state::mm5740_control_r) -{ - return ((m_kbspecial->read() ^ 0x10) & 0x10) ? ASSERT_LINE: CLEAR_LINE; -} - -WRITE_LINE_MEMBER(h19_state::mm5740_data_ready_w) -{ - if (state == ASSERT_LINE) - { - uint8_t *decode = m_kbdrom->base(); - - m_transchar = decode[translate_mm5740_b(m_mm5740->b_r())]; - m_strobe = true; - m_maincpu->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE); - } -} - -MC6845_UPDATE_ROW( h19_state::crtc_update_row ) -{ - if (!de) - return; - - rgb_t const *const palette = m_palette->palette()->entry_list_raw(); - uint32_t *p = &bitmap.pix(y); - - for (uint16_t x = 0; x < x_count; x++) - { - uint8_t inv = (x == cursor_x) ? 0xff : 0; - - uint8_t chr = m_p_videoram[(ma + x) & 0x7ff]; - - if (chr & 0x80) - { - inv ^= 0xff; - chr &= 0x7f; - } - - /* get pattern of pixels for that character scanline */ - uint8_t const gfx = m_p_chargen[(chr<<4) | ra] ^ inv; - - /* Display a scanline of a character (8 pixels) */ - *p++ = palette[BIT(gfx, 7)]; - *p++ = palette[BIT(gfx, 6)]; - *p++ = palette[BIT(gfx, 5)]; - *p++ = palette[BIT(gfx, 4)]; - *p++ = palette[BIT(gfx, 3)]; - *p++ = palette[BIT(gfx, 2)]; - *p++ = palette[BIT(gfx, 1)]; - *p++ = palette[BIT(gfx, 0)]; - } -} - - -/* F4 Character Displayer */ -static const gfx_layout h19_charlayout = -{ - 8, 10, /* 8 x 10 characters */ - 128, /* 128 characters */ - 1, /* 1 bits per pixel */ - { 0 }, /* no bitplanes */ - /* x offsets */ - { 0, 1, 2, 3, 4, 5, 6, 7 }, - /* y offsets */ - { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8 }, - 8*16 /* every char takes 16 bytes */ -}; - -static GFXDECODE_START( gfx_h19 ) - GFXDECODE_ENTRY( "chargen", 0x0000, h19_charlayout, 0, 1 ) -GFXDECODE_END - void h19_state::h19(machine_config &config) { - /* basic machine hardware */ - Z80(config, m_maincpu, H19_CLOCK); // From schematics - m_maincpu->set_addrmap(AS_PROGRAM, &h19_state::mem_map); - m_maincpu->set_addrmap(AS_IO, &h19_state::io_map); + HEATH_TLB(config, m_tlb); +} - /* video hardware */ - // TODO: make configurable, Heath offered 3 different CRTs - White, Green, Amber. - screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER, rgb_t::green())); - screen.set_refresh_hz(60); // TODO- this is adjustable by dipswitch. - screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */ - screen.set_screen_update("crtc", FUNC(mc6845_device::screen_update)); - screen.set_size(640, 250); - screen.set_visarea(0, 640 - 1, 0, 250 - 1); +void h19_state::h19_superh19(machine_config &config) +{ + HEATH_SUPER19(config, m_tlb); +} - GFXDECODE(config, "gfxdecode", m_palette, gfx_h19); - PALETTE(config, "palette", palette_device::MONOCHROME); +void h19_state::h19_watzh19(machine_config &config) +{ + HEATH_WATZ(config, m_tlb); +} - MC6845(config, m_crtc, MC6845_CLOCK); - m_crtc->set_screen("screen"); - m_crtc->set_show_border_area(true); - m_crtc->set_char_width(8); - m_crtc->set_update_row_callback(FUNC(h19_state::crtc_update_row)); - m_crtc->out_vsync_callback().set_inputline(m_maincpu, INPUT_LINE_NMI); // frame pulse - - ins8250_device &uart(INS8250(config, "ins8250", INS8250_CLOCK)); - uart.out_int_callback().set_inputline("maincpu", INPUT_LINE_IRQ0); - - MM5740(config, m_mm5740, MM5740_CLOCK); - m_mm5740->x_cb<1>().set_ioport("X1"); - m_mm5740->x_cb<2>().set_ioport("X2"); - m_mm5740->x_cb<3>().set_ioport("X3"); - m_mm5740->x_cb<4>().set_ioport("X4"); - m_mm5740->x_cb<5>().set_ioport("X5"); - m_mm5740->x_cb<6>().set_ioport("X6"); - m_mm5740->x_cb<7>().set_ioport("X7"); - m_mm5740->x_cb<8>().set_ioport("X8"); - m_mm5740->x_cb<9>().set_ioport("X9"); - m_mm5740->shift_cb().set(FUNC(h19_state::mm5740_shift_r)); - m_mm5740->control_cb().set(FUNC(h19_state::mm5740_control_r)); - m_mm5740->data_ready_cb().set(FUNC(h19_state::mm5740_data_ready_w)); - - /* sound hardware */ - SPEAKER(config, "mono").front_center(); - BEEP(config, m_beep, H19_BEEP_FRQ).add_route(ALL_OUTPUTS, "mono", 1.00); +void h19_state::h19_ultrah19(machine_config &config) +{ + HEATH_ULTRA(config, m_tlb); } /* ROM definition */ ROM_START( h19 ) - ROM_REGION( 0x2000, "maincpu", ROMREGION_ERASEFF ) - // Original - ROM_LOAD( "2732_444-46_h19code.bin", 0x0000, 0x1000, CRC(f4447da0) SHA1(fb4093d5b763be21a9580a0defebed664b1f7a7b)) - - ROM_REGION( 0x0800, "chargen", 0 ) - // Original font dump - ROM_LOAD( "2716_444-29_h19font.bin", 0x0000, 0x0800, CRC(d595ac1d) SHA1(130fb4ea8754106340c318592eec2d8a0deaf3d0)) - - ROM_REGION( 0x1000, "keyboard", 0 ) - // Original dump - ROM_LOAD( "2716_444-37_h19keyb.bin", 0x0000, 0x0800, CRC(5c3e6972) SHA1(df49ce64ae48652346a91648c58178a34fb37d3c)) ROM_END ROM_START( super19 ) - // Super H19 ROM - ROM_REGION( 0x2000, "maincpu", ROMREGION_ERASEFF ) - ROM_LOAD( "2732_super19_h447.bin", 0x0000, 0x1000, CRC(6c51aaa6) SHA1(5e368b39fe2f1af44a905dc474663198ab630117)) - - ROM_REGION( 0x0800, "chargen", 0 ) - // Original font dump - ROM_LOAD( "2716_444-29_h19font.bin", 0x0000, 0x0800, CRC(d595ac1d) SHA1(130fb4ea8754106340c318592eec2d8a0deaf3d0)) - - ROM_REGION( 0x1000, "keyboard", 0 ) - // Original dump - ROM_LOAD( "2716_444-37_h19keyb.bin", 0x0000, 0x0800, CRC(5c3e6972) SHA1(df49ce64ae48652346a91648c58178a34fb37d3c)) ROM_END ROM_START( watz19 ) - // Watzman ROM - ROM_REGION( 0x2000, "maincpu", ROMREGION_ERASEFF ) - ROM_LOAD( "watzman.bin", 0x0000, 0x1000, CRC(8168b6dc) SHA1(bfaebb9d766edbe545d24bc2b6630be4f3aa0ce9)) - - ROM_REGION( 0x0800, "chargen", 0 ) - // Original font dump - ROM_LOAD( "2716_444-29_h19font.bin", 0x0000, 0x0800, CRC(d595ac1d) SHA1(130fb4ea8754106340c318592eec2d8a0deaf3d0)) - // Watzman keyboard - ROM_REGION( 0x1000, "keyboard", 0 ) - ROM_LOAD( "keybd.bin", 0x0000, 0x0800, CRC(58dc8217) SHA1(1b23705290bdf9fc6342065c6a528c04bff67b13)) ROM_END ROM_START( ultra19 ) - // ULTRA ROM - ROM_REGION( 0x2000, "maincpu", ROMREGION_ERASEFF ) - ROM_LOAD( "2532_h19_ultra_firmware.bin", 0x0000, 0x1000, CRC(8ad4cdb4) SHA1(d6e1fc37a1f52abfce5e9adb1819e0030bed1df3)) - - ROM_REGION( 0x0800, "chargen", 0 ) - // Original font dump - ROM_LOAD( "2716_444-29_h19font.bin", 0x0000, 0x0800, CRC(d595ac1d) SHA1(130fb4ea8754106340c318592eec2d8a0deaf3d0)) - // Watzman keyboard - ROM_REGION( 0x1000, "keyboard", 0 ) - ROM_LOAD( "2716_h19_ultra_keyboard.bin", 0x0000, 0x0800, CRC(76130c92) SHA1(ca39c602af48505139d2750a084b5f8f0e662ff7)) ROM_END - } // anonymous namespace - -// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS -COMP( 1979, h19, 0, 0, h19, h19, h19_state, empty_init, "Heath Company", "Heathkit H-19", MACHINE_SUPPORTS_SAVE ) +// 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, h19, h19_state, empty_init, "Heath Company", "Heathkit H-19 w/ Super-19 ROM", MACHINE_SUPPORTS_SAVE ) +COMP( 1982, super19, h19, 0, h19_superh19, 0, h19_state, empty_init, "Heath Company", "Heathkit H-19 w/ Super-19 ROM", MACHINE_SUPPORTS_SAVE ) // Watzman ROM - HUG p/n 885-1121, announced in REMark Issue 33, Oct. 1982 -COMP( 1982, watz19, h19, 0, h19, h19, h19_state, empty_init, "Heath Company", "Heathkit H-19 w/ Watzman ROM", MACHINE_SUPPORTS_SAVE ) +COMP( 1982, watz19, h19, 0, h19_watzh19, 0, h19_state, empty_init, "Heath Company", "Heathkit H-19 w/ Watzman ROM", MACHINE_SUPPORTS_SAVE ) // ULTRA ROM - Software Wizardry, Inc., (c) 1983 William G. Parrott, III -COMP( 1983, ultra19, h19, 0, h19, h19, h19_state, empty_init, "Heath Company", "Heathkit H-19 w/ ULTRA ROM", MACHINE_SUPPORTS_SAVE ) - +COMP( 1983, ultra19, h19, 0, h19_ultrah19, 0, h19_state, empty_init, "Heath Company", "Heathkit H-19 w/ ULTRA ROM", MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/heathkit/h89.cpp b/src/mame/heathkit/h89.cpp index 94cecac3d25..b64c622ad3e 100644 --- a/src/mame/heathkit/h89.cpp +++ b/src/mame/heathkit/h89.cpp @@ -2,40 +2,43 @@ // copyright-holders:Sandro Ronco, Mark Garlanger /*************************************************************************** - Heathkit H89 + Heathkit H89 - 12/05/2009 Skeleton driver. - - Monitor Commands: - B Boot - C Convert (number) - G Go (address) - I In (address) - O Out (address,data) - R Radix (H/O) - S Substitute (address) - T Test Memory - V View + Monitor Commands (for MTR-90): + B Boot + C Convert (number) + G Go (address) + I In (address) + O Out (address,data) + R Radix (H/O) + S Substitute (address) + T Test Memory + V View ****************************************************************************/ #include "emu.h" -#include "bus/rs232/rs232.h" + +#include "tlb.h" + #include "cpu/z80/z80.h" #include "machine/ins8250.h" #include "machine/timer.h" - namespace { -#define RS232_TAG "rs232" + +#define H89_CLOCK (XTAL(12'288'000) / 6) +#define INS8250_CLOCK (XTAL(1'843'200)) class h89_state : public driver_device { public: - h89_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag) - , m_maincpu(*this, "maincpu") + h89_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_maincpu(*this, "maincpu"), + m_tlb(*this, "tlb"), + m_console(*this, "console") { } @@ -43,6 +46,8 @@ public: private: required_device m_maincpu; + required_device m_tlb; + required_device m_console; void port_f2_w(uint8_t data); @@ -83,11 +88,9 @@ void h89_state::h89_io(address_map &map) // map(0xd0, 0xd7) 8250 UART DCE // map(0xd8, 0xdf) 8250 UART DTE - MODEM // map(0xe0, 0xe7) 8250 UART DCE - LP - map(0xe8, 0xef).rw("ins8250", FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w)); // 8250 UART console - this + map(0xe8, 0xef).rw(m_console, FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w)); // 8250 UART console - this // connects internally to a Terminal board - // that is also used in the H19. Ideally, - // the H19 code could be connected and ran - // as a separate thread. + // that is also used in the H19. // map(0xf0, 0xf1) // ports defined on the H8 - on the H89, access to these addresses causes a NMI map(0xf2, 0xf2).w(FUNC(h89_state::port_f2_w)).portr("SW501"); // map(0xf3, 0xf3) // ports defined on the H8 - on the H89, access to these addresses causes a NMI @@ -133,7 +136,7 @@ static INPUT_PORTS_START( h89 ) // PORT_DIPSETTING( 0x00, DEF_STR( Normal ) ) // PORT_DIPSETTING( 0x80, "Auto" ) - // Settings with the MTR-90 ROM (#444-84 or 444-142) + // Settings with the MTR-90 ROM (#444-84 or 444-142) PORT_START("SW501") PORT_DIPNAME( 0x03, 0x00, "Expansion 1" ) PORT_DIPLOCATION("S1:1,S1:2") PORT_DIPSETTING( 0x00, "H-88-1" ) @@ -167,7 +170,9 @@ void h89_state::machine_reset() TIMER_DEVICE_CALLBACK_MEMBER(h89_state::h89_irq_timer) { if (m_port_f2 & 0x02) + { m_maincpu->set_input_line_and_vector(0, HOLD_LINE, 0xcf); // Z80 + } } void h89_state::port_f2_w(uint8_t data) @@ -177,31 +182,22 @@ void h89_state::port_f2_w(uint8_t data) m_port_f2 = data; } -static DEVICE_INPUT_DEFAULTS_START( terminal ) - // TODO - baud rate should be controlled by SW501 setting - DEVICE_INPUT_DEFAULTS( "RS232_TXBAUD", 0xff, RS232_BAUD_9600 ) - DEVICE_INPUT_DEFAULTS( "RS232_RXBAUD", 0xff, RS232_BAUD_9600 ) - DEVICE_INPUT_DEFAULTS( "RS232_DATABITS", 0xff, RS232_DATABITS_8 ) - DEVICE_INPUT_DEFAULTS( "RS232_PARITY", 0xff, RS232_PARITY_NONE ) - DEVICE_INPUT_DEFAULTS( "RS232_STOPBITS", 0xff, RS232_STOPBITS_1 ) -DEVICE_INPUT_DEFAULTS_END - - void h89_state::h89(machine_config & config) { - /* basic machine hardware */ - Z80(config, m_maincpu, XTAL(12'288'000) / 6); + // basic machine hardware + Z80(config, m_maincpu, H89_CLOCK); m_maincpu->set_addrmap(AS_PROGRAM, &h89_state::h89_mem); m_maincpu->set_addrmap(AS_IO, &h89_state::h89_io); - ins8250_device &uart(INS8250(config, "ins8250", XTAL(1'843'200))); - uart.out_tx_callback().set(RS232_TAG, FUNC(rs232_port_device::write_txd)); + INS8250(config, m_console, INS8250_CLOCK); + HEATH_TLB(config, m_tlb); - rs232_port_device &rs232(RS232_PORT(config, RS232_TAG, default_rs232_devices, "terminal")); - rs232.rxd_handler().set("ins8250", FUNC(ins8250_uart_device::rx_w)); - rs232.set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(terminal)); + // 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_tlb->serial_data_callback().set(m_console, FUNC(ins8250_uart_device::rx_w)); - TIMER(config, "irq_timer", 0).configure_periodic(FUNC(h89_state::h89_irq_timer), attotime::from_hz(100)); + // H89 interrupt interval is 2mSec + TIMER(config, "irq_timer", 0).configure_periodic(FUNC(h89_state::h89_irq_timer), attotime::from_msec(2)); } /* ROM definition */ @@ -221,4 +217,4 @@ ROM_END /* Driver */ /* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */ -COMP( 1979, h89, 0, 0, h89, h89, h89_state, empty_init, "Heath Company", "Heathkit H89", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) +COMP( 1979, h89, 0, 0, h89, h89, h89_state, empty_init, "Heath Company", "Heathkit H89", MACHINE_NOT_WORKING) diff --git a/src/mame/heathkit/tlb.cpp b/src/mame/heathkit/tlb.cpp new file mode 100644 index 00000000000..d94f4b7d276 --- /dev/null +++ b/src/mame/heathkit/tlb.cpp @@ -0,0 +1,751 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + Heathkit Terminal Logic Board (TLB) + + The board used in the H19 smart terminal designed and manufactured + by Heath Company. (and identical Z19 sold by Zenith Data Systems) + + The keyboard consists of a 9x10 matrix connected to a MM5740AAC/N + mask-programmed keyboard controller. The output of this passes + through a rom. + + Input can also come from the serial port (a 8250). + Either device will signal an interrupt to the CPU when a key + is pressed/data is received. + + TODO: + - speed up emulation + - update SW401 baud rate options for Watz ROM + - update SW401 & SW402 definitions for Super-19 ROM + - update SW401 & SW402 definitions for ULTRA ROM + - add option for ULTRA ROMs second page of screen RAM + +****************************************************************************/ +/*************************************************************************** + Memory Layout + The U435 three-to-eight line decoder uses A14 and A15 to generate three memory addresses: + + 1. Program ROM 0x0000 + + 2. Scratchpad RAM 0x4000 + + 3. Display Memory 0xF800 + + + Port Layout + + Only address lines A5, A6, A7 are used by the U442 three-to-eight line decoder + +Address Description +---------------------------------------------------- + 0x00 Power-up configuration (primary - SW401) + 0x20 Power-up configuration (secondary - SW402) + 0x40 ACE (communications) + 0x60 CRT controller + 0x80 Keyboard encoder + 0xA0 Keyboard status + 0xC0 Key click enable + 0xE0 Bell enable + +****************************************************************************/ + +#include "emu.h" + +#include "tlb.h" + +// Standard H19 used a 2.048 MHz clock +#define H19_CLOCK (XTAL(12'288'000) / 6) +#define MC6845_CLOCK (XTAL(12'288'000) /8) +#define INS8250_CLOCK (XTAL(12'288'000) /4) + +// Capacitor value in pF +#define H19_KEY_DEBOUNCE_CAPACITOR 5000 +#define MM5740_CLOCK (mm5740_device::calc_effective_clock_key_debounce(H19_KEY_DEBOUNCE_CAPACITOR)) + +// Beep Frequency is 1 KHz +#define H19_BEEP_FRQ (H19_CLOCK / 2048) + +DEFINE_DEVICE_TYPE(HEATH_TLB, heath_tlb_device, "heath_tlb", "Heath Terminal Logic Board"); +DEFINE_DEVICE_TYPE(HEATH_SUPER19, heath_super19_tlb_device, "heath_super19_tlb", "Heath Terminal Logic Board w/Super19 ROM"); +DEFINE_DEVICE_TYPE(HEATH_WATZ, heath_watz_tlb_device, "heath_watz_tlb", "Heath Terminal Logic Board w/Watzman ROM"); +DEFINE_DEVICE_TYPE(HEATH_ULTRA, heath_ultra_tlb_device, "heath_ultra_tlb", "Heath Terminal Logic Board w/Ultra ROM"); + +heath_tlb_device::heath_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + heath_tlb_device(mconfig, HEATH_TLB, tag, owner, clock) +{ +} + +heath_tlb_device::heath_tlb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, type, tag, owner, clock), + m_write_sd(*this), + m_palette(*this, "palette"), + m_maincpu(*this, "maincpu"), + m_crtc(*this, "crtc"), + m_ace(*this, "ins8250"), + m_beep(*this, "beeper"), + m_p_videoram(*this, "videoram"), + m_p_chargen(*this, "chargen"), + m_mm5740(*this, "mm5740"), + m_kbdrom(*this, "keyboard"), + m_kbspecial(*this, "MODIFIERS") +{ +} + +void heath_tlb_device::checkBeepState() +{ + if (!m_keyclickactive && !m_bellactive) + { + m_beep->set_state(0); + } +} + +TIMER_CALLBACK_MEMBER(heath_tlb_device::key_click_off) +{ + m_keyclickactive = false; + + checkBeepState(); +} + +TIMER_CALLBACK_MEMBER(heath_tlb_device::bell_off) +{ + m_bellactive = false; + + checkBeepState(); +} + +void heath_tlb_device::mem_map(address_map &map) +{ + map.unmap_value_high(); + map(0x0000, 0x1fff).mirror(0x2000).rom(); + map(0x4000, 0x4100).mirror(0x3e00).ram(); + map(0xc000, 0xc7ff).mirror(0x3800).ram().share(m_p_videoram); +} + +void heath_tlb_device::io_map(address_map &map) +{ + map.unmap_value_high(); + map.global_mask(0xff); + map(0x00, 0x00).mirror(0x1f).portr("SW401"); + map(0x20, 0x20).mirror(0x1f).portr("SW402"); + map(0x40, 0x47).mirror(0x18).rw(m_ace, FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w)); + map(0x60, 0x60).mirror(0x1e).w(m_crtc, FUNC(mc6845_device::address_w)); + map(0x61, 0x61).mirror(0x1e).rw(m_crtc, FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w)); + map(0x80, 0x80).mirror(0x1f).r(FUNC(heath_tlb_device::kbd_key_r)); + map(0xa0, 0xa0).mirror(0x1f).r(FUNC(heath_tlb_device::kbd_flags_r)); + map(0xc0, 0xc0).mirror(0x1f).w(FUNC(heath_tlb_device::key_click_w)); + map(0xe0, 0xe0).mirror(0x1f).w(FUNC(heath_tlb_device::bell_w)); +} + + +// Keyboard encoder masks +static constexpr uint8_t KB_ENCODER_KEY_VALUE_MASK = 0x7f; +static constexpr uint8_t KB_ENCODER_CONTROL_KEY_MASK = 0x80; + +// Keyboard flag masks +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_REPEAT_KEYS_MASK = 0x40; +static constexpr uint8_t KB_STATUS_KEYBOARD_STROBE_MASK = 0x80; + +void heath_tlb_device::device_resolve_objects() +{ + + m_write_sd.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)); + + m_strobe = false; + m_keyclickactive = false; + m_bellactive = 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::key_click_w(uint8_t data) +{ + // Keyclick - 6 mSec + m_beep->set_state(1); + m_keyclickactive = true; + m_key_click_timer->adjust(attotime::from_msec(6)); +} + +void heath_tlb_device::bell_w(uint8_t data) +{ + // Bell (^G) - 200 mSec + m_beep->set_state(1); + m_bellactive = true; + m_bell_timer->adjust(attotime::from_msec(200)); +} + + +/*************************************************************************** +MM5740 B Mapping to the ROM address + +B1 -> A0 A10 = 0 +B2 -> A1 A9 = 0 +B3 -> A2 A8 = B8 +B4 -> A3 A7 = B7 +B5 -> A4 A6 = B9 +B6 -> A5 A5 = B6 +B7 -> A7 A4 = B5 +B8 -> A8 A3 = B4 +B9 -> A6 A2 = B3 +ground -> A9 A1 = B2 +ground -> A10 A0 = B1 + +****************************************************************************/ +uint16_t heath_tlb_device::translate_mm5740_b(uint16_t b) +{ + return ((b & 0x100) >> 2) | ((b & 0x0c0) << 1) | (b & 0x03f); +} + +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. + return m_transchar; +} + +uint8_t heath_tlb_device::kbd_flags_r() +{ + uint16_t modifiers = m_kbspecial->read(); + uint8_t rv = modifiers & 0x7f; + + // check both shifts + if ((modifiers & 0x020) == 0 || (modifiers & 0x100) == 0) + { + rv |= KB_STATUS_SHIFT_KEYS_MASK; + } + + if (!m_strobe) + { + rv |= KB_STATUS_KEYBOARD_STROBE_MASK; + } + + return rv; +} + +READ_LINE_MEMBER(heath_tlb_device::mm5740_shift_r) +{ + return ((m_kbspecial->read() ^ 0x120) & 0x120) ? ASSERT_LINE : CLEAR_LINE; +} + +READ_LINE_MEMBER(heath_tlb_device::mm5740_control_r) +{ + return ((m_kbspecial->read() ^ 0x10) & 0x10) ? ASSERT_LINE: CLEAR_LINE; +} + +WRITE_LINE_MEMBER(heath_tlb_device::mm5740_data_ready_w) +{ + if (state == ASSERT_LINE) + { + uint8_t *decode = m_kbdrom->base(); + + m_transchar = decode[translate_mm5740_b(m_mm5740->b_r())]; + m_strobe = true; + m_maincpu->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE); + } +} + +MC6845_UPDATE_ROW(heath_tlb_device::crtc_update_row) +{ + if (!de) + { + return; + } + + rgb_t const *const palette = m_palette->palette()->entry_list_raw(); + uint32_t *p = &bitmap.pix(y); + + for (uint16_t x = 0; x < x_count; x++) + { + uint8_t inv = (x == cursor_x) ? 0xff : 0; + + uint8_t chr = m_p_videoram[(ma + x) & 0x7ff]; + + if (chr & 0x80) + { + inv ^= 0xff; + chr &= 0x7f; + } + + // get pattern of pixels for that character scanline + uint8_t const gfx = m_p_chargen[(chr<<4) | ra] ^ inv; + + // Display a scanline of a character (8 pixels) + *p++ = palette[BIT(gfx, 7)]; + *p++ = palette[BIT(gfx, 6)]; + *p++ = palette[BIT(gfx, 5)]; + *p++ = palette[BIT(gfx, 4)]; + *p++ = palette[BIT(gfx, 3)]; + *p++ = palette[BIT(gfx, 2)]; + *p++ = palette[BIT(gfx, 1)]; + *p++ = palette[BIT(gfx, 0)]; + } +} + + +// F4 Character Displayer +static const gfx_layout h19_charlayout = +{ + 8, 10, // 8 x 10 characters + 128, // 128 characters + 1, // 1 bits per pixel + { 0 }, // no bitplanes + // x offsets + { 0, 1, 2, 3, 4, 5, 6, 7 }, + // y offsets + { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8 }, + 8*16 // every char takes 16 bytes +}; + +static GFXDECODE_START(gfx_h19) + GFXDECODE_ENTRY("chargen", 0x0000, h19_charlayout, 0, 1) +GFXDECODE_END + + +/* Input ports */ +static INPUT_PORTS_START( tlb ) + + PORT_START("MODIFIERS") + // bit 0 connects to B8 of MM5740 - low if either shift key is + // bit 7 is low if a key is pressed + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CapsLock") PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Break") PORT_CODE(KEYCODE_PAUSE) + 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(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_START("X1") + PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("/") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("k_X2") + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-0") PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-.") PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-Enter") PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("X2") + 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(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)) + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-2 Down") PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-3 DL") PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("X3") + PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("[ ]") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR(']') + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\\ |") PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|') + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Line Feed") PORT_CODE(KEYCODE_RWIN) + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("DEL") PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL)) + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-4 LEFT") PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-5 HOME") PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-6 RIGHT") PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("X4") + PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0 )") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("- _") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_') + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("= +") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+') + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("` ~") PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~') + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Back Space") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("k_X1") + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-7 IC") PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-8 UP") PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-9 DC") PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) + 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(0x200, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("X6") + PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(", <") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(". >") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') + + PORT_START("X7") + PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Scroll") PORT_CODE(KEYCODE_F11) + + PORT_START("X8") + PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Tab") PORT_CODE(KEYCODE_TAB) PORT_CHAR(9) + + PORT_START("X9") + PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("1 !") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') + PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("2 @") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') + PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("3 #") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') + PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("4 $") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') + PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("5 %") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') + PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("6 ^") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^') + PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("7 &") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') + PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("8 *") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') + PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("9 (") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') + PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CODE(KEYCODE_ESC) PORT_CHAR(27) + + PORT_START("SW401") + 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") + PORT_DIPSETTING( 0x04, "600") + PORT_DIPSETTING( 0x05, "1200") + PORT_DIPSETTING( 0x06, "1800") + PORT_DIPSETTING( 0x07, "2000") + PORT_DIPSETTING( 0x08, "2400") + PORT_DIPSETTING( 0x09, "3600") + PORT_DIPSETTING( 0x0a, "4800") + PORT_DIPSETTING( 0x0b, "7200") + PORT_DIPSETTING( 0x0c, "9600") + PORT_DIPSETTING( 0x0d, "19200") + PORT_DIPNAME( 0x30, 0x00, "Parity") PORT_DIPLOCATION("SW401:5,6") + PORT_DIPSETTING( 0x00, DEF_STR(None)) + PORT_DIPSETTING( 0x10, "Odd") + PORT_DIPSETTING( 0x20, "None") + PORT_DIPSETTING( 0x30, "Even") + PORT_DIPNAME( 0x40, 0x00, "Parity Type") PORT_DIPLOCATION("SW401:7") + PORT_DIPSETTING( 0x00, DEF_STR(Normal)) + PORT_DIPSETTING( 0x40, "Stick") + PORT_DIPNAME( 0x80, 0x80, "Duplex") PORT_DIPLOCATION("SW401:8") + PORT_DIPSETTING( 0x00, "Half") + PORT_DIPSETTING( 0x80, "Full") + + PORT_START("SW402") // stored at 40C8 + 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_DIPSETTING( 0x02, DEF_STR(No)) + PORT_DIPSETTING( 0x00, DEF_STR(Yes)) + 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_DIPSETTING( 0x00, DEF_STR(No)) + PORT_DIPSETTING( 0x08, DEF_STR(Yes)) + 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_DIPSETTING( 0x00, "Heath/VT52") + PORT_DIPSETTING( 0x20, "ANSI") + 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_DIPSETTING( 0x00, "50Hz") + PORT_DIPSETTING( 0x80, "60Hz") +INPUT_PORTS_END + + +static INPUT_PORTS_START( super19 ) + PORT_INCLUDE( tlb ) + + PORT_MODIFY("SW401") + PORT_DIPNAME( 0x0f, 0x0c, "Baud Rate") PORT_DIPLOCATION("SW401:1,2,3,4") + PORT_DIPSETTING( 0x0e, "38400") + PORT_DIPNAME( 0x30, 0x00, "Parity") PORT_DIPLOCATION("SW401:5,6") + PORT_DIPSETTING( 0x00, DEF_STR(None)) + PORT_DIPSETTING( 0x10, "Odd") + PORT_DIPSETTING( 0x20, "None") + PORT_DIPSETTING( 0x30, "Even") + PORT_DIPNAME( 0x40, 0x00, "Parity Type") PORT_DIPLOCATION("SW401:7") + PORT_DIPSETTING( 0x00, DEF_STR(Normal)) + PORT_DIPSETTING( 0x40, "Stick") + PORT_DIPNAME( 0x80, 0x80, "Duplex") PORT_DIPLOCATION("SW401:8") + PORT_DIPSETTING( 0x00, "Half") + PORT_DIPSETTING( 0x80, "Full") + + PORT_MODIFY("SW402") + PORT_DIPNAME( 0x02, 0x00, "Keyclick") PORT_DIPLOCATION("SW402:2") + PORT_DIPSETTING( 0x02, DEF_STR(No)) + PORT_DIPSETTING( 0x00, DEF_STR(Yes)) + PORT_DIPNAME( 0x80, 0x00, "DEC Keypad Codes") PORT_DIPLOCATION("SW402:8") + PORT_DIPSETTING( 0x00, "Off") + PORT_DIPSETTING( 0x80, "On") + +INPUT_PORTS_END + +static INPUT_PORTS_START( ultra19 ) + PORT_INCLUDE( tlb ) + + PORT_MODIFY("SW401") + PORT_DIPNAME( 0x07, 0x05, "Baud Rate") PORT_DIPLOCATION("SW401:1,2,3") + PORT_DIPSETTING( 0x00, "110") + PORT_DIPSETTING( 0x01, "300") + PORT_DIPSETTING( 0x02, "1200") + PORT_DIPSETTING( 0x03, "2400") + PORT_DIPSETTING( 0x04, "4800") + PORT_DIPSETTING( 0x05, "9600") + PORT_DIPSETTING( 0x06, "19200") + PORT_DIPSETTING( 0x07, "38400") + PORT_DIPNAME( 0x18, 0x00, "Parity") PORT_DIPLOCATION("SW401:4,5") + PORT_DIPSETTING( 0x00, DEF_STR(None)) + PORT_DIPSETTING( 0x10, "Odd") + PORT_DIPSETTING( 0x20, "None") + PORT_DIPSETTING( 0x30, "Even") + PORT_DIPNAME( 0x20, 0x00, "Data Size") PORT_DIPLOCATION("SW401:6") + PORT_DIPSETTING( 0x00, "8-bit") + PORT_DIPSETTING( 0x20, "7-bit") + PORT_DIPNAME( 0x40, 0x40, "Duplex") PORT_DIPLOCATION("SW401:7") + PORT_DIPSETTING( 0x00, "Half") + PORT_DIPSETTING( 0x40, "Full") + PORT_DIPNAME( 0x80, 0x80, "Software Handshaking") PORT_DIPLOCATION("SW401:8") + PORT_DIPSETTING( 0x00, "Enabled") + PORT_DIPSETTING( 0x80, "Disabled") + + PORT_MODIFY("SW402") + PORT_DIPNAME( 0x08, 0x00, "Keypad Shifted") PORT_DIPLOCATION("SW402:4") + PORT_DIPSETTING( 0x00, DEF_STR(No)) + PORT_DIPSETTING( 0x08, DEF_STR(Yes)) + PORT_DIPNAME( 0x10, 0x00, "Default Key Values") PORT_DIPLOCATION("SW402:5") + PORT_DIPSETTING( 0x00, "HDOS Values") + PORT_DIPSETTING( 0x10, "CP/M Values") + PORT_DIPNAME( 0x60, 0x60, "Cursor Blink") PORT_DIPLOCATION("SW402:6,7") + PORT_DIPSETTING( 0x00, "Steady") + 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_DIPSETTING( 0x00, "Off") + PORT_DIPSETTING( 0x80, "On") + +INPUT_PORTS_END + +static INPUT_PORTS_START( watz19 ) + PORT_INCLUDE( tlb ) + + PORT_MODIFY("SW402") + PORT_DIPNAME( 0x40, 0x00, "Word Size") PORT_DIPLOCATION("SW402:7") + PORT_DIPSETTING( 0x00, "8-bit") + PORT_DIPSETTING( 0x40, "7-bit") + +INPUT_PORTS_END + + +ROM_START( h19 ) + ROM_REGION( 0x2000, "maincpu", ROMREGION_ERASEFF ) + // Original + ROM_LOAD( "2732_444-46_h19code.bin", 0x0000, 0x1000, CRC(f4447da0) SHA1(fb4093d5b763be21a9580a0defebed664b1f7a7b)) + + ROM_REGION( 0x0800, "chargen", 0 ) + // Original font dump + ROM_LOAD( "2716_444-29_h19font.bin", 0x0000, 0x0800, CRC(d595ac1d) SHA1(130fb4ea8754106340c318592eec2d8a0deaf3d0)) + + ROM_REGION( 0x1000, "keyboard", 0 ) + // Original dump + ROM_LOAD( "2716_444-37_h19keyb.bin", 0x0000, 0x0800, CRC(5c3e6972) SHA1(df49ce64ae48652346a91648c58178a34fb37d3c)) +ROM_END + +ROM_START( super19 ) + // Super H19 ROM + ROM_REGION( 0x2000, "maincpu", ROMREGION_ERASEFF ) + ROM_LOAD( "2732_super19_h447.bin", 0x0000, 0x1000, CRC(6c51aaa6) SHA1(5e368b39fe2f1af44a905dc474663198ab630117)) + + ROM_REGION( 0x0800, "chargen", 0 ) + // Original font dump + ROM_LOAD( "2716_444-29_h19font.bin", 0x0000, 0x0800, CRC(d595ac1d) SHA1(130fb4ea8754106340c318592eec2d8a0deaf3d0)) + + ROM_REGION( 0x1000, "keyboard", 0 ) + // Original dump + ROM_LOAD( "2716_444-37_h19keyb.bin", 0x0000, 0x0800, CRC(5c3e6972) SHA1(df49ce64ae48652346a91648c58178a34fb37d3c)) +ROM_END + +ROM_START( watz19 ) + // Watzman ROM + ROM_REGION( 0x2000, "maincpu", ROMREGION_ERASEFF ) + ROM_LOAD( "watzman.bin", 0x0000, 0x1000, CRC(8168b6dc) SHA1(bfaebb9d766edbe545d24bc2b6630be4f3aa0ce9)) + + ROM_REGION( 0x0800, "chargen", 0 ) + // Original font dump + ROM_LOAD( "2716_444-29_h19font.bin", 0x0000, 0x0800, CRC(d595ac1d) SHA1(130fb4ea8754106340c318592eec2d8a0deaf3d0)) + // Watzman keyboard + ROM_REGION( 0x1000, "keyboard", 0 ) + ROM_LOAD( "keybd.bin", 0x0000, 0x0800, CRC(58dc8217) SHA1(1b23705290bdf9fc6342065c6a528c04bff67b13)) +ROM_END + +ROM_START( ultra19 ) + // ULTRA ROM + ROM_REGION( 0x2000, "maincpu", ROMREGION_ERASEFF ) + ROM_LOAD( "2532_h19_ultra_firmware.bin", 0x0000, 0x1000, CRC(8ad4cdb4) SHA1(d6e1fc37a1f52abfce5e9adb1819e0030bed1df3)) + + ROM_REGION( 0x0800, "chargen", 0 ) + // Original font dump + ROM_LOAD( "2716_444-29_h19font.bin", 0x0000, 0x0800, CRC(d595ac1d) SHA1(130fb4ea8754106340c318592eec2d8a0deaf3d0)) + // Watzman keyboard + ROM_REGION( 0x1000, "keyboard", 0 ) + ROM_LOAD( "2716_h19_ultra_keyboard.bin", 0x0000, 0x0800, CRC(76130c92) SHA1(ca39c602af48505139d2750a084b5f8f0e662ff7)) +ROM_END + + +ioport_constructor heath_tlb_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(tlb); +} + +const tiny_rom_entry *heath_tlb_device::device_rom_region() const +{ + return ROM_NAME(h19); +} + +void heath_tlb_device::serial_out_b(uint8_t data) +{ + m_write_sd(data); +} + +WRITE_LINE_MEMBER(heath_tlb_device::cb1_w) +{ + m_ace->rx_w(state); +} + +void heath_tlb_device::device_add_mconfig(machine_config &config) +{ + // basic machine hardware + Z80(config, m_maincpu, H19_CLOCK); // From schematics + m_maincpu->set_addrmap(AS_PROGRAM, &heath_tlb_device::mem_map); + m_maincpu->set_addrmap(AS_IO, &heath_tlb_device::io_map); + + // video hardware + // TODO: make configurable, Heath offered 2 different CRTs - White, Green + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER, rgb_t::green())); + screen.set_raw(MC6845_CLOCK * 45 / 2, 900, 260, 0, 640, 0, 250); + screen.set_screen_update("crtc", FUNC(mc6845_device::screen_update)); + + GFXDECODE(config, "gfxdecode", m_palette, gfx_h19); + PALETTE(config, "palette", palette_device::MONOCHROME); + + MC6845(config, m_crtc, MC6845_CLOCK); + m_crtc->set_screen("screen"); + 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 + + // serial port + INS8250(config, m_ace, INS8250_CLOCK); + m_ace->out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); + m_ace->out_tx_callback().set(FUNC(heath_tlb_device::serial_out_b)); + + // keyboard + MM5740(config, m_mm5740, MM5740_CLOCK); + m_mm5740->x_cb<1>().set_ioport("X1"); + m_mm5740->x_cb<2>().set_ioport("X2"); + m_mm5740->x_cb<3>().set_ioport("X3"); + m_mm5740->x_cb<4>().set_ioport("X4"); + m_mm5740->x_cb<5>().set_ioport("X5"); + m_mm5740->x_cb<6>().set_ioport("X6"); + m_mm5740->x_cb<7>().set_ioport("X7"); + m_mm5740->x_cb<8>().set_ioport("X8"); + m_mm5740->x_cb<9>().set_ioport("X9"); + m_mm5740->shift_cb().set(FUNC(heath_tlb_device::mm5740_shift_r)); + m_mm5740->control_cb().set(FUNC(heath_tlb_device::mm5740_control_r)); + m_mm5740->data_ready_cb().set(FUNC(heath_tlb_device::mm5740_data_ready_w)); + + // sound hardware + SPEAKER(config, "mono").front_center(); + BEEP(config, m_beep, H19_BEEP_FRQ).add_route(ALL_OUTPUTS, "mono", 1.00); +} + +heath_super19_tlb_device::heath_super19_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + heath_tlb_device(mconfig, HEATH_SUPER19, tag, owner, clock) +{ +} + +const tiny_rom_entry *heath_super19_tlb_device::device_rom_region() const +{ + return ROM_NAME(super19); +} + +ioport_constructor heath_super19_tlb_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(super19); +} + +heath_watz_tlb_device::heath_watz_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + heath_tlb_device(mconfig, HEATH_WATZ, tag, owner, clock) +{ +} + +const tiny_rom_entry *heath_watz_tlb_device::device_rom_region() const +{ + return ROM_NAME(watz19); +} + +ioport_constructor heath_watz_tlb_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(watz19); +} + +heath_ultra_tlb_device::heath_ultra_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + heath_tlb_device(mconfig, HEATH_ULTRA, tag, owner, clock) +{ +} + +const tiny_rom_entry *heath_ultra_tlb_device::device_rom_region() const +{ + return ROM_NAME(ultra19); +} + +ioport_constructor heath_ultra_tlb_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(ultra19); +} diff --git a/src/mame/heathkit/tlb.h b/src/mame/heathkit/tlb.h new file mode 100644 index 00000000000..49fe3720ed3 --- /dev/null +++ b/src/mame/heathkit/tlb.h @@ -0,0 +1,124 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + Heathkit Terminal Logic Board (TLB) + +****************************************************************************/ + +#ifndef MAME_HEATHKIT_TLB_H +#define MAME_HEATHKIT_TLB_H + +#pragma once + +#include "cpu/z80/z80.h" +#include "machine/ins8250.h" +#include "machine/mm5740.h" +#include "sound/beep.h" +#include "video/mc6845.h" +#include "emupal.h" +#include "screen.h" +#include "speaker.h" + +class heath_tlb_device : public device_t +{ +public: + heath_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + + // interface routines + auto serial_data_callback() { return m_write_sd.bind(); } + + DECLARE_WRITE_LINE_MEMBER(cb1_w); + +protected: + heath_tlb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock = 0); + + virtual ioport_constructor device_input_ports() const override; + virtual const tiny_rom_entry *device_rom_region() const override; + virtual void device_start() override; + virtual void device_add_mconfig(machine_config &config) override; + virtual void device_resolve_objects() override; + +private: + + void mem_map(address_map &map); + void io_map(address_map &map); + + void key_click_w(uint8_t data); + void bell_w(uint8_t data); + uint8_t kbd_key_r(); + uint8_t kbd_flags_r(); + uint16_t translate_mm5740_b(uint16_t b); + + void checkBeepState(); + + void serial_out_b(uint8_t data); + + DECLARE_READ_LINE_MEMBER(mm5740_shift_r); + DECLARE_READ_LINE_MEMBER(mm5740_control_r); + DECLARE_WRITE_LINE_MEMBER(mm5740_data_ready_w); + + MC6845_UPDATE_ROW(crtc_update_row); + + TIMER_CALLBACK_MEMBER(key_click_off); + TIMER_CALLBACK_MEMBER(bell_off); + + emu_timer *m_key_click_timer; + emu_timer *m_bell_timer; + + devcb_write_line m_write_sd; + + required_device m_palette; + required_device m_maincpu; + required_device m_crtc; + required_device m_ace; + required_device m_beep; + required_shared_ptr m_p_videoram; + required_region_ptr m_p_chargen; + required_device m_mm5740; + required_memory_region m_kbdrom; + required_ioport m_kbspecial; + + uint8_t m_transchar; + bool m_strobe; + bool m_keyclickactive; + bool m_bellactive; + +}; + +class heath_super19_tlb_device : public heath_tlb_device +{ +public: + heath_super19_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + +protected: + virtual const tiny_rom_entry *device_rom_region() const override; + virtual ioport_constructor device_input_ports() const override; +}; + +class heath_watz_tlb_device : public heath_tlb_device +{ +public: + heath_watz_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + +protected: + virtual const tiny_rom_entry *device_rom_region() const override; + virtual ioport_constructor device_input_ports() const override; +}; + +class heath_ultra_tlb_device : public heath_tlb_device +{ +public: + heath_ultra_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + +protected: + virtual const tiny_rom_entry *device_rom_region() const override; + virtual ioport_constructor device_input_ports() const override; +}; + +DECLARE_DEVICE_TYPE(HEATH_TLB, heath_tlb_device) +DECLARE_DEVICE_TYPE(HEATH_SUPER19, heath_super19_tlb_device) +DECLARE_DEVICE_TYPE(HEATH_WATZ, heath_watz_tlb_device) +DECLARE_DEVICE_TYPE(HEATH_ULTRA, heath_ultra_tlb_device) + +#endif // MAME_HEATHKIT_TLB_H