ncd88k: work in progress

* hook up serial eeprom
* initial work on interrupts
* add firmware version 2.6.0
This commit is contained in:
Patrick Mackinlay 2022-11-22 14:40:07 +07:00
parent a7622d4313
commit 5067b4996b

View File

@ -8,8 +8,20 @@
/*
* WIP notes
*
* 88k "base" (19c, 19g, 17cr, 19cp)
* - https://web-docs.gsi.de/~kraemer/COLLECTION/ftp.ncd.com/pub/ncd/Archive/NCD-Articles/NCD_X_Terminals/Memory_specs/NCD_88k_family_memory_specs
* There are two basic machines, NCD88k and Modular Color X (MCX). They share
* the same firmware and have very similar hardware, however the system memory
* maps differ. Marketing material for the MCX systems describes 3D and audio
* hardware as enhancements over the prior NCD88k, and the latter system board
* includes an additional custom ASIC. Various models of terminal differ only
* by the type of monitor supplied.
*
* 88k "base" (19c, 19g, 17cr, 17g, 19cp)
* - no on-board memory
* - J6 and J7 are code memory SIMM sockets (up to 64M)
* - J8, J9 and J10 are data memory SIMM sockets (up to 96M)
* - 19c shipped with 2M code memory (1991)
* - 17g 1280x1024 gray-scale (1992)
* - 17cr 1280x1024 color (1992)
*
* MCX
* - 2MB code and 4MB data memory on motherboard
@ -18,7 +30,25 @@
* or 8Mx32 SIMMs. Data memory can be added as 1Mx32, 2Mx32, 4Mx32,
* or 8Mx32 SIMMs.
* - 256Kx32 and 512Kx32 SIMMs are only supported as code memory
* - ports: ethernet (TP & AUI), monitor, aux, mouse, keyboard, audio in, audio out
* - 50kHz 16-bit sound
*
* Model Type, Colors/Grayscales Res. Mem. CPU/GCC List US$
* -------------------------------------------------------------------------------
* MCX-L base only, VGA color, 100dpi 1152x900 6.0 88100-20 2,295
* MCX14 14" color, 103dpi/70Hz 640x480,1024x768 6.0 88100-20 3,295
* MCX15 15" color, 100dpi/70Hz 640x480,1152x900 6.0 88100-20 3,495
* MCX17 17" color, 87dpi/75Hz 1024x768,1152x900 6.0 88100-20 4,295
* MCX-L19 19" color, 84dpi/72Hz 1152x900 6.0 88100-20 4,695
*
* Sources:
* - https://web-docs.gsi.de/~kraemer/COLLECTION/ftp.ncd.com/pub/ncd/Archive/NCD-Articles/NCD_X_Terminals/Memory_specs/NCD_88k_family_memory_specs
* - http://books.google.com/books?id=ujsEAAAAMBAJ&lpg=PA24&pg=PA24#v=onepage&q&f=false
*
* TODO:
* - ram control/sizing
* - keyboard and mouse
* - interrupts and mask
*/
#include "emu.h"
@ -26,6 +56,7 @@
#include "machine/mc68681.h"
#include "machine/am79c90.h"
#include "machine/eepromser.h"
#include "machine/pckeybrd.h"
#include "bus/rs232/rs232.h"
@ -33,6 +64,11 @@
#include "video/bt47x.h"
#include "screen.h"
#define VERBOSE (0)
#include "logmacro.h"
namespace {
class ncd88k_state : public driver_device
{
public:
@ -85,18 +121,18 @@ u32 ncd88k_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, con
void ncd88k_state::code_map(address_map &map)
{
map(0x00000000, 0x0001cfff).rom().region("program", 0);
map(0x04000000, 0x07ffffff).ram().share("coderam");
map(0x00000000, 0x0001cfff).rom().region("prom", 0);
map(0x04000000, 0x07ffffff).ram().share("cram");
}
void ncd88k_state::data_map(address_map &map)
{
map(0x00000000, 0x0001cfff).rom().region("program", 0);
map(0x00000000, 0x0001cfff).rom().region("prom", 0);
map(0x01000000, 0x0100003f).rw("duart", FUNC(scn2681_device::read), FUNC(scn2681_device::write)).umask32(0xff000000);
map(0x01400000, 0x0140001f).m(m_ramdac, FUNC(bt458_device::map)).umask32(0xff000000);
map(0x04000000, 0x07ffffff).ram().share("coderam");
map(0x08000000, 0x0d03ffff).ram().share("dataram");
map(0x04000000, 0x07ffffff).ram().share("cram");
map(0x08000000, 0x0d03ffff).ram().share("dram");
map(0x0e000000, 0x0e1fffff).ram().share("vram");
}
@ -120,7 +156,7 @@ void ncd88k_state::ncd19c(machine_config &config)
}
ROM_START(ncd19c)
ROM_REGION32_BE(0x20000, "program", ROMREGION_ERASE00)
ROM_REGION32_BE(0x20000, "prom", ROMREGION_ERASE00)
// These dumps have very strange lengths. The actual ROMs should be standard EEPROM types.
ROM_LOAD16_BYTE("ncd19c-e.rom", 0x0000, 0xb000, CRC(01e31b42) SHA1(28da6e4465415d00a739742ded7937a144129aad) BAD_DUMP)
ROM_LOAD16_BYTE("ncd19c-o.rom", 0x0001, 0xb000, CRC(dfd9be7c) SHA1(2e99a325b039f8c3bb89833cd1940e6737b64d79) BAD_DUMP)
@ -137,6 +173,8 @@ public:
, m_duart(*this, "duart")
, m_ramdac(*this, "ramdac")
, m_screen(*this, "screen")
, m_kbd(*this, "kbd")
, m_dram(*this, "dram")
, m_vram(*this, "vram")
{
}
@ -144,21 +182,39 @@ public:
void ncdmcx(machine_config &config);
private:
virtual void machine_reset() override;
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, rectangle const &cliprect);
void code_map(address_map &map);
void data_map(address_map &map);
template <unsigned N> void irq_w(int state);
required_device<cpu_device> m_cpu;
required_device<eeprom_serial_93cxx_device> m_eeprom;
required_device<am79c90_device> m_lance;
required_device<am7990_device> m_lance;
required_device<scn2681_device> m_duart;
required_device<bt477_device> m_ramdac;
required_device<screen_device> m_screen;
required_device<at_keyboard_device> m_kbd;
required_shared_ptr<u32> m_dram;
required_shared_ptr<u32> m_vram;
u8 m_int;
u8 m_msk;
};
void ncdmcx_state::machine_reset()
{
m_int = 0;
m_msk = 0;
m_duart->ip2_w(0);
}
u32 ncdmcx_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, rectangle const &cliprect)
{
u32 *pixel_pointer = m_vram;
@ -188,53 +244,151 @@ void ncdmcx_state::ncdmcx(machine_config &config)
m_cpu->set_addrmap(AS_PROGRAM, &ncdmcx_state::code_map);
m_cpu->set_addrmap(AS_DATA, &ncdmcx_state::data_map);
// CAT35C104P 256x16 or 512x8 4K-Bit SERIAL E2PROM
EEPROM_93C66_8BIT(config, m_eeprom);
EEPROM_93C66_16BIT(config, m_eeprom); // CAT35C104P
m_eeprom->default_value(0);
m_eeprom->do_callback().set(m_duart, FUNC(scn2681_device::ip2_w));
// ICD2061ASC-1
// 4100004
AM79C90(config, m_lance, 20_MHz_XTAL);
AM7990(config, m_lance, 20_MHz_XTAL / 2); // 4100004
m_lance->intr_out().set(FUNC(ncdmcx_state::irq_w<2>)).invert();
m_lance->dma_in().set([this](offs_t offset) { return util::big_endian_cast<const u16>(m_dram.target())[offset >> 1]; });
m_lance->dma_out().set([this](offs_t offset, u16 data, u16 mem_mask) { COMBINE_DATA(&util::big_endian_cast<u16>(m_dram.target())[offset >> 1]); });
SCN2681(config, m_duart, 3'686'400);
m_duart->irq_cb().set(FUNC(ncdmcx_state::irq_w<3>));
m_duart->outport_cb().set(
[this](u8 data)
{
m_eeprom->cs_write(BIT(data, 5));
m_eeprom->di_write(BIT(data, 4));
m_eeprom->clk_write(BIT(data, 6));
});
// ATT20C497-11
BT477(config, m_ramdac, 125'000'000);
BT477(config, m_ramdac, 125'000'000); // ATT20C497-11
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_raw(125'000'000, 1680, 0, 1280, 1063, 0, 1024); // 74.4 kHz horizontal, 70 Hz vertical
m_screen->set_screen_update(FUNC(ncdmcx_state::screen_update));
m_screen->screen_vblank().set(FUNC(ncdmcx_state::irq_w<4>));
AT_KEYB(config, m_kbd);
m_kbd->set_type(at_keyboard_device::KEYBOARD_TYPE::AT, 3);
m_kbd->keypress().set(FUNC(ncdmcx_state::irq_w<1>));
}
void ncdmcx_state::code_map(address_map &map)
{
map(0x00000000, 0x0003ffff).rom().region("program", 0);
map(0x00000000, 0x0003ffff).rom().region("prom", 0);
map(0x04000000, 0x07ffffff).ram().share("coderam");
map(0x04000000, 0x07ffffff).ram().share("cram"); // maximum 64M
}
void ncdmcx_state::data_map(address_map &map)
{
map(0x00000000, 0x0003ffff).rom().region("program", 0);
map(0x00000000, 0x0003ffff).rom().region("prom", 0);
map(0x00c00000, 0x00c00003).rw(m_lance, FUNC(am7990_device::regs_r), FUNC(am7990_device::regs_w)).mirror(0x000fff04);
map(0x01000000, 0x0100003f).rw(m_duart, FUNC(scn2681_device::read), FUNC(scn2681_device::write)).umask32(0xff000000);
map(0x01400000, 0x0140001f).m(m_ramdac, FUNC(bt477_device::map)).umask32(0xff000000);
// 014c0000.b - reset?
// bit 0 -> icd2061a clock
// bit 1 -> icd2016a data
map(0x01580000, 0x01580003).nopw();
map(0x04000000, 0x07ffffff).ram().share("coderam"); // maximum 64M
map(0x08000000, 0x0dffffff).ram().share("dataram"); // maximum 96M
map(0x01d80000, 0x01d80000).lrw8(
[this]()
{
return m_int;
}, "int_r",
[this](u8 data)
{
LOG("msk_w 0x%02x (%s)\n", data, machine().describe_context());
m_msk = data;
m_cpu->set_input_line(INPUT_LINE_IRQ0, bool(m_int & m_msk));
}, "msk_w");
// 0x64 -> ack or clear irq 4?
map(0x01d80001, 0x01d80001).lrw8(
[this]()
{
return 0;
}, "int?_r",
[this](u8 data)
{
LOG("ack_w 0x%02x int 0x%02x (%s)\n", data, m_int, machine().describe_context());
// 0x20?
// 0x65
// 0x60 - clr irq 0? (soft interrupt)
// 0x61 - set irq 0? (soft interrupt)
// 0x63 - clr irq 6?
// 0x64 - ack irq 4?
// 0x65 - 0x0400582c?
switch (data)
{
case 0x60: m_int &= ~0x01; break;
case 0x61: m_int |= 0x41; break;
//case 0x62: m_int &= ~0x40; break;
case 0x63: m_int &= ~0x40; break;
case 0x64: m_int &= ~0x10; break;
}
m_cpu->set_input_line(INPUT_LINE_IRQ0, bool(m_int & m_msk));
}, "ack_w");
map(0x01d80003, 0x01d80003).lr8(
[this]()
{
irq_w<1>(0);
// TODO: this might be keyboard rx?
return m_kbd->read();
}, "kbd_r");
map(0x02000000, 0x02ffffff).lw8(
[this](offs_t offset, u8 data)
{
LOG("dram_ctrl 0x%02x\n", offset >> 16);
}, "dram_ctrl_w");
map(0x03000000, 0x03ffffff).lw8(
[this](offs_t offset, u8 data)
{
LOG("cram_ctrl 0x%02x\n", offset >> 16);
}, "cram_ctrl_w");
map(0x04000000, 0x07ffffff).ram().share("cram"); // maximum 64M
map(0x08000000, 0x0dffffff).ram().share("dram"); // maximum 96M
map(0x0e000000, 0x0e3fffff).ram().share("vram");
}
template <unsigned N> void ncdmcx_state::irq_w(int state)
{
if (state)
m_int |= 1U << N;
else
m_int &= ~(1U << N);
m_cpu->set_input_line(INPUT_LINE_IRQ0, bool(m_int & m_msk));
}
ROM_START(ncdmcx)
ROM_REGION32_BE(0x40000, "program", 0)
ROM_LOAD16_BYTE("ncd88k_mcx_bm.u3", 0x0000, 0x20000, CRC(70305680) SHA1(b10b250fe319e823cff28ba7b449b0a40755f5a2))
ROM_LOAD16_BYTE("ncd88k_mcx_bm.u14", 0x0001, 0x20000, CRC(fc066464) SHA1(fa894de56b77bd4bc619040a2cf3a0d260914727))
ROM_REGION32_BE(0x40000, "prom", 0)
ROM_SYSTEM_BIOS(0, "v2.7.3", "v2.7.3")
ROMX_LOAD("ncd88k_mcx_bm__v2.7.3_b0e.u3", 0x0000, 0x20000, CRC(70305680) SHA1(b10b250fe319e823cff28ba7b449b0a40755f5a2), ROM_BIOS(0) | ROM_SKIP(1))
ROMX_LOAD("ncd88k_mcx_bm__v2.7.3_b0o.u14", 0x0001, 0x20000, CRC(fc066464) SHA1(fa894de56b77bd4bc619040a2cf3a0d260914727), ROM_BIOS(0) | ROM_SKIP(1))
ROM_SYSTEM_BIOS(1, "v2.6.0", "v2.6.0")
ROMX_LOAD("ncd88k_mcx_bm__v2.6.0_b0e.u3", 0x0000, 0x20000, CRC(99644196) SHA1(d5091fd4f096000de4970ae778112ff3c01ac340), ROM_BIOS(1) | ROM_SKIP(1))
ROMX_LOAD("ncd88k_mcx_bm__v2.6.0_b0o.u14", 0x0001, 0x20000, CRC(db2ed336) SHA1(8be4e08bf097d2b85be84da62b2a24c6e55661d9), ROM_BIOS(1) | ROM_SKIP(1))
ROM_END
COMP(1990, ncd19c, 0, 0, ncd19c, ncd19c, ncd88k_state, empty_init, "Network Computing Devices", "19c", MACHINE_IS_SKELETON)
COMP(1990, ncdmcx, 0, 0, ncdmcx, 0, ncdmcx_state, empty_init, "Network Computing Devices", "MCX", MACHINE_IS_SKELETON)
} // anonymous namespace
COMP(1991, ncd19c, 0, 0, ncd19c, ncd19c, ncd88k_state, empty_init, "Network Computing Devices", "19c", MACHINE_IS_SKELETON)
COMP(1993, ncdmcx, 0, 0, ncdmcx, 0, ncdmcx_state, empty_init, "Network Computing Devices", "MCX", MACHINE_IS_SKELETON)