heathkit/tlb.cpp: Added Imaginator I-100 terminal for Heath H19/H89. (#11735)

This commit is contained in:
Mark Garlanger 2023-11-17 11:49:28 -06:00 committed by GitHub
parent 1c9a2cc768
commit 31e73fea7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 348 additions and 13 deletions

View File

@ -36,6 +36,7 @@ static void tlb_options(device_slot_interface &device)
{
device.option_add("heath", HEATH_TLB);
device.option_add("gp19", HEATH_GP19);
device.option_add("imaginator", HEATH_IMAGINATOR);
device.option_add("super19", HEATH_SUPER19);
device.option_add("superset", HEATH_SUPERSET);
device.option_add("ultrarom", HEATH_ULTRA);

View File

@ -573,6 +573,7 @@ static void tlb_options(device_slot_interface &device)
{
device.option_add("heath", HEATH_TLB);
device.option_add("gp19", HEATH_GP19);
device.option_add("imaginator", HEATH_IMAGINATOR);
device.option_add("super19", HEATH_SUPER19);
device.option_add("superset", HEATH_SUPERSET);
device.option_add("ultrarom", HEATH_ULTRA);

View File

@ -21,14 +21,17 @@
- In 49/50 row mode, character descenders are cut off.
****************************************************************************/
/***************************************************************************
Memory Layout
The U435 three-to-eight line decoder uses A14 and A15 to generate
three memory addresses:
three memory address spaces:
1. Program ROM 0x0000
2. Scratchpad RAM 0x4000
3. Display Memory 0xF800
Address Description
----------------------------------------------------
0x0000 Program ROM
0x4000 Scratchpad RAM
0xF800 (0xC000) Display Memory
Port Layout
@ -86,12 +89,13 @@ static constexpr uint8_t KB_STATUS_KEYBOARD_STROBE_MASK = 0x80;
DEFINE_DEVICE_TYPE(HEATH_TLB_CONNECTOR, heath_tlb_connector, "heath_tlb_connector", "Heath Terminal Logic board connector abstraction")
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_SUPERSET, heath_superset_tlb_device, "heath_superset_tlb", "Heath Terminal Logic Board w/Superset ROM");
DEFINE_DEVICE_TYPE(HEATH_ULTRA, heath_ultra_tlb_device, "heath_ultra_tlb", "Heath Terminal Logic Board w/Ultra ROM");
DEFINE_DEVICE_TYPE(HEATH_WATZ, heath_watz_tlb_device, "heath_watz_tlb", "Heath Terminal Logic Board w/Watzman ROM");
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_SUPERSET, heath_superset_tlb_device, "heath_superset_tlb", "Heath Terminal Logic Board w/Superset ROM")
DEFINE_DEVICE_TYPE(HEATH_ULTRA, heath_ultra_tlb_device, "heath_ultra_tlb", "Heath Terminal Logic Board w/Ultra ROM")
DEFINE_DEVICE_TYPE(HEATH_WATZ, heath_watz_tlb_device, "heath_watz_tlb", "Heath Terminal Logic Board w/Watzman ROM")
DEFINE_DEVICE_TYPE(HEATH_GP19, heath_gp19_tlb_device, "heath_gp19_tlb", "Heath Terminal Logic Board plus Northwest Digital Systems GP-19")
DEFINE_DEVICE_TYPE(HEATH_IMAGINATOR, heath_imaginator_tlb_device, "heath_imaginator_tlb", "Heath Terminal Logic Board plus Cleveland Codonics Imaginator I-100")
@ -103,7 +107,7 @@ device_heath_tlb_card_interface::device_heath_tlb_card_interface(const machine_c
/**
* base Heath h19 functionality
* base Heath H19 functionality
*/
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)
@ -154,8 +158,14 @@ TIMER_CALLBACK_MEMBER(heath_tlb_device::bell_off)
void heath_tlb_device::mem_map(address_map &map)
{
map.unmap_value_high();
// H19 ROM
map(0x0000, 0x0fff).mirror(0x3000).rom();
// Scratchpad memory
map(0x4000, 0x40ff).mirror(0x3f00).ram();
// Video Memory
map(0xc000, 0xc7ff).mirror(0x3800).ram().share(m_p_videoram);
}
@ -232,7 +242,7 @@ void heath_tlb_device::device_reset()
}
// Set screen color
switch (BIT(cfg,2, 2))
switch (BIT(cfg, 2, 2))
{
case 0x01:
m_screen->set_color(rgb_t::white());
@ -939,6 +949,23 @@ ROM_START( gp19 )
ROM_LOAD( "2716_444-37_h19keyb.u445", 0x0000, 0x0800, CRC(5c3e6972) SHA1(df49ce64ae48652346a91648c58178a34fb37d3c))
ROM_END
ROM_START( imaginator )
// Program code
ROM_REGION( 0x4000, "maincpu", ROMREGION_ERASEFF )
// Original terminal code
ROM_LOAD( "2732_444-46_h19code.u437", 0x0000, 0x1000, CRC(f4447da0) SHA1(fb4093d5b763be21a9580a0defebed664b1f7a7b))
// Imaginator ROMs
ROM_LOAD( "2732_imaginator_gpc_rev_1.2_pn_9000_0002.u9a", 0x2000, 0x1000, CRC(507bb13f) SHA1(5b210f8d77e22fdf063f611eb5c29636cdb01250))
// Original font
ROM_REGION( 0x0800, "chargen", 0 )
ROM_LOAD( "2716_444-29_h19font.u420", 0x0000, 0x0800, CRC(d595ac1d) SHA1(130fb4ea8754106340c318592eec2d8a0deaf3d0))
// Original keyboard
ROM_REGION( 0x0800, "keyboard", 0 )
ROM_LOAD( "2716_444-37_h19keyb.u445", 0x0000, 0x0800, CRC(5c3e6972) SHA1(df49ce64ae48652346a91648c58178a34fb37d3c))
ROM_END
ioport_constructor heath_tlb_device::device_input_ports() const
{
@ -1390,6 +1417,261 @@ ioport_constructor heath_gp19_tlb_device::device_input_ports() const
}
/**
* Cleveland Codonics Imaginator-100 (I-100) add-in board
*
* Memory Range Description
* -----------------------------------------------------------------
* 0x0000-0x1fff Program ROM (Heath TLB board)
* 0x2000-0x3fff Graphics Command Processor(GCP) ROM (I-100)
* 0x4000-0x5fff Scratchpad RAM (Heath TLB board)
* 0x6000-0x7fff Graphics Scratchpad R/W RAM (I-100)
* 0x8000-0xbfff Graphics Display R/W RAM(I-100)
* 0xc000-0xdfff Optional Graphics Command Processor memory (I-100)
* 0xe000-0xffff Display Memory (Heath TLB board)
*
* New interrupt source
* - horizontal retrace interrupt
*
*/
heath_imaginator_tlb_device::heath_imaginator_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
heath_tlb_device(mconfig, HEATH_IMAGINATOR, tag, owner, clock),
m_mem_view(*this, "memmap"),
m_p_graphic_ram(*this, "graphicram")
{
}
void heath_imaginator_tlb_device::device_add_mconfig(machine_config &config)
{
heath_tlb_device::device_add_mconfig(config);
m_maincpu->set_addrmap(AS_PROGRAM, &heath_imaginator_tlb_device::mem_map);
m_maincpu->set_addrmap(AS_IO, &heath_imaginator_tlb_device::io_map);
m_maincpu->set_irq_acknowledge_callback(FUNC(heath_imaginator_tlb_device::irq_ack_cb));
m_crtc->out_hsync_callback().set(FUNC(heath_imaginator_tlb_device::crtc_hsync_w));
}
void heath_imaginator_tlb_device::device_start()
{
heath_tlb_device::device_start();
save_item(NAME(m_mem_map));
save_item(NAME(m_im2_val));
save_item(NAME(m_alphanumeric_mode_active));
save_item(NAME(m_graphics_mode_active));
save_item(NAME(m_allow_tlb_interrupts));
save_item(NAME(m_allow_imaginator_interrupts));
save_item(NAME(m_hsync_irq_raised));
m_maincpu->space(AS_PROGRAM).install_readwrite_tap(0x6000, 0x7fff, "mem_map_update",
[this](offs_t offset, u8 &data, u8 mem_mask) { if (!machine().side_effects_disabled()) { tap_6000h(); } },
[this](offs_t offset, u8 &data, u8 mem_mask) { if (!machine().side_effects_disabled()) { tap_6000h(); } });
m_maincpu->space(AS_PROGRAM).install_readwrite_tap(0x8000, 0xbfff, "irq_update",
[this](offs_t offset, u8 &data, u8 mem_mask) { if (!machine().side_effects_disabled()) { tap_8000h(); } },
[this](offs_t offset, u8 &data, u8 mem_mask) { if (!machine().side_effects_disabled()) { tap_8000h(); } });
}
void heath_imaginator_tlb_device::device_reset()
{
m_mem_map = 1;
m_mem_view.select(m_mem_map);
m_alphanumeric_mode_active = true;
m_graphics_mode_active = false;
m_hsync_irq_raised = false;
allow_tlb_intr();
}
/*
* Memory map for the I-100
*
* 0x0000-0x1fff Program ROM (Heath TLB board)
* 0x2000-0x3fff Graphics Command Processor(GCP) ROM (I-100)
* 0x4000-0x5fff Scratchpad RAM (Heath TLB board)
* 0x6000-0x7fff Graphics Scratchpad R/W RAM (I-100)
* 0x8000-0xbfff Graphics Display R/W RAM(I-100)
* 0xc000-0xdfff Optional Graphics Command Processor memory (I-100)
* 0xe000-0xffff Display Memory (Heath TLB board)
*/
void heath_imaginator_tlb_device::mem_map(address_map &map)
{
map.unmap_value_high();
map(0x0000, 0x1fff).view(m_mem_view);
// H19 standard ROM
m_mem_view[0](0x0000, 0x1fff).rom().region("maincpu", 0);
// GCP ROM mapped to 0x0000 on power-up/reset
m_mem_view[1](0x0000, 0x1fff).rom().region("maincpu", 0x2000);
// Normal spot of the GCP ROM
map(0x2000, 0x3fff).rom();
// TLB Scratchpad
map(0x4000, 0x40ff).mirror(0x1f00).ram();
// GCP Scratchpad
map(0x6000, 0x607f).mirror(0x1f80).ram();
// Graphics RAM
map(0x8000, 0xbfff).ram().share(m_p_graphic_ram);
// optional Graphics Command Processor (GCP)
// map(0xc000, 0xdfff);
// Alphanumeric RAM
map(0xe000, 0xe7ff).mirror(0x1800).ram().share(m_p_videoram);
}
void heath_imaginator_tlb_device::tap_6000h()
{
if (m_mem_map != 0)
{
m_mem_map = 0;
m_mem_view.select(m_mem_map);
}
}
void heath_imaginator_tlb_device::tap_8000h()
{
if (!m_allow_tlb_interrupts)
{
allow_tlb_intr();
set_irq_line();
}
}
void heath_imaginator_tlb_device::allow_tlb_intr()
{
m_allow_tlb_interrupts = true;
m_allow_imaginator_interrupts = false;
m_im2_val = 0x02;
}
void heath_imaginator_tlb_device::allow_hsync_intr()
{
m_allow_tlb_interrupts = false;
m_allow_imaginator_interrupts = true;
m_im2_val = 0x00;
}
/**
* An input/output request (IORQ) is sent to the TERMINAL LOGIC board only when
* both IORQ (pin 20 of U7) AND A4 are low.
*/
void heath_imaginator_tlb_device::io_map(address_map &map)
{
heath_tlb_device::io_map(map);
// interrupt routing
map(0x10, 0x10).select(0x08).mirror(0x07).w(FUNC(heath_imaginator_tlb_device::config_irq_w));
// display enabling (graphics or alphanumeric)
map(0x30, 0x30).select(0xc0).mirror(0x0f).w(FUNC(heath_imaginator_tlb_device::display_enable_w));
// Avoids writes to TLB when a4 is high on unused
map(0x50, 0x50).select(0x80).mirror(0x0f).w(FUNC(heath_imaginator_tlb_device::nop_w));
}
IRQ_CALLBACK_MEMBER(heath_imaginator_tlb_device::irq_ack_cb)
{
return m_im2_val;
}
void heath_imaginator_tlb_device::config_irq_w(offs_t reg, uint8_t val)
{
if (BIT(reg,3))
{
allow_tlb_intr();
}
else
{
allow_hsync_intr();
}
set_irq_line();
}
void heath_imaginator_tlb_device::display_enable_w(offs_t reg, uint8_t val)
{
m_alphanumeric_mode_active = bool(BIT(reg, 7));
m_graphics_mode_active = bool(BIT(reg, 6));
}
void heath_imaginator_tlb_device::nop_w(offs_t, uint8_t)
{
}
const tiny_rom_entry *heath_imaginator_tlb_device::device_rom_region() const
{
return ROM_NAME(imaginator);
}
MC6845_UPDATE_ROW(heath_imaginator_tlb_device::crtc_update_row)
{
rgb_t const *const palette = m_palette->palette()->entry_list_raw();
uint32_t *p = &bitmap.pix(y);
if (de)
{
for (int x = 0; x < x_count; x++)
{
uint8_t output = 0x00;
if (m_alphanumeric_mode_active)
{
uint8_t inv = (x == cursor_x) ? 0xff : 0;
uint8_t chr = m_p_videoram[(ma + x) & 0x7ff];
if (chr & 0x80)
{
inv ^= 0xff;
chr &= 0x7f;
}
output |= bitswap<8>(m_p_chargen[(chr << 4) | ra] ^ inv, 0, 1, 2, 3, 4, 5, 6, 7);
}
if (m_graphics_mode_active && (x > 7 ) && (x < 73))
{
output |= m_p_graphic_ram[((y * 64) + (x - 8)) & 0x3fff];
}
for (int b = 0; 8 > b; ++b)
{
*p++ = palette[BIT(output, b)];
}
}
}
else
{
std::fill_n(p, x_count * 8, palette[0]);
}
}
void heath_imaginator_tlb_device::crtc_hsync_w(int val)
{
m_hsync_irq_raised = bool(val);
set_irq_line();
}
void heath_imaginator_tlb_device::set_irq_line()
{
m_maincpu->set_input_line(INPUT_LINE_IRQ0,
(m_allow_imaginator_interrupts && m_hsync_irq_raised) ||
(m_allow_tlb_interrupts && (m_keyboard_irq_raised || m_serial_irq_raised || m_break_key_irq_raised)) ?
ASSERT_LINE : CLEAR_LINE);
}
heath_tlb_connector::heath_tlb_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, HEATH_TLB_CONNECTOR, tag, owner, clock),
device_single_card_slot_interface(mconfig, *this),

View File

@ -89,8 +89,8 @@ protected:
required_ioport m_config;
required_device<ins8250_device> m_ace;
private:
void set_irq_line();
//private:
virtual void set_irq_line();
void check_for_reset();
void key_click_w(uint8_t data);
@ -237,8 +237,59 @@ protected:
bool m_reverse_video;
};
/**
* Heath TLB plus Cleveland Codonics Imaginator-100
*/
class heath_imaginator_tlb_device : public heath_tlb_device
{
public:
heath_imaginator_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 void device_start() override;
virtual void device_reset() override;
virtual void device_add_mconfig(machine_config &config) override;
void mem_map(address_map &map);
void io_map(address_map &map);
virtual MC6845_UPDATE_ROW(crtc_update_row) override;
void crtc_hsync_w(int val);
IRQ_CALLBACK_MEMBER(irq_ack_cb);
void tap_6000h();
void tap_8000h();
void allow_tlb_intr();
void allow_hsync_intr();
void display_enable_w(offs_t reg, uint8_t val);
void config_irq_w(offs_t reg, uint8_t val);
void nop_w(offs_t reg, uint8_t val);
virtual void set_irq_line() override;
memory_view m_mem_view;
required_shared_ptr<uint8_t> m_p_graphic_ram;
uint8_t m_mem_map;
uint8_t m_im2_val;
bool m_alphanumeric_mode_active;
bool m_graphics_mode_active;
bool m_allow_tlb_interrupts;
bool m_allow_imaginator_interrupts;
bool m_hsync_irq_raised;
};
DECLARE_DEVICE_TYPE(HEATH_TLB, heath_tlb_device)
DECLARE_DEVICE_TYPE(HEATH_GP19, heath_gp19_tlb_device)
DECLARE_DEVICE_TYPE(HEATH_IMAGINATOR, heath_imaginator_tlb_device)
DECLARE_DEVICE_TYPE(HEATH_SUPER19, heath_super19_tlb_device)
DECLARE_DEVICE_TYPE(HEATH_SUPERSET, heath_superset_tlb_device)
DECLARE_DEVICE_TYPE(HEATH_WATZ, heath_watz_tlb_device)