From 9349b16a17d6395e301c719af14b4428fee73421 Mon Sep 17 00:00:00 2001 From: Devin Acker Date: Wed, 2 Apr 2025 10:22:45 -0400 Subject: [PATCH] Add a skeleton for an Oldsmobile Driver Information System (#13525) * New NOT_WORKING machine ---------- Oldsmobile Driver Information System (version 2.2 CH) [Devin Acker] --- src/devices/cpu/upd7810/upd7810.cpp | 13 ++ src/devices/cpu/upd7810/upd7810.h | 10 ++ src/devices/cpu/upd7810/upd7810_opcodes.cpp | 5 +- src/mame/mame.lst | 3 + src/mame/skeleton/omdisv22.cpp | 176 ++++++++++++++++++++ 5 files changed, 206 insertions(+), 1 deletion(-) create mode 100644 src/mame/skeleton/omdisv22.cpp diff --git a/src/devices/cpu/upd7810/upd7810.cpp b/src/devices/cpu/upd7810/upd7810.cpp index 0883dd3cc31..4f706c09a13 100644 --- a/src/devices/cpu/upd7810/upd7810.cpp +++ b/src/devices/cpu/upd7810/upd7810.cpp @@ -378,6 +378,7 @@ DEFINE_DEVICE_TYPE(UPD7810, upd7810_device, "upd7810", "NEC uPD7810") DEFINE_DEVICE_TYPE(UPD78C10, upd78c10_device, "upd78c10", "NEC uPD78C10") DEFINE_DEVICE_TYPE(UPD7811, upd7811_device, "upd7811", "NEC uPD7811") DEFINE_DEVICE_TYPE(UPD78C11, upd78c11_device, "upd78c11", "NEC uPD78C11") +DEFINE_DEVICE_TYPE(UPD78C14, upd78c14_device, "upd78c14", "NEC uPD78C14") DEFINE_DEVICE_TYPE(UPD7807, upd7807_device, "upd7807", "NEC uPD7807") DEFINE_DEVICE_TYPE(UPD7801, upd7801_device, "upd7801", "NEC uPD7801") DEFINE_DEVICE_TYPE(UPD78C05, upd78c05_device, "upd78c05", "NEC uPD78C05") @@ -408,6 +409,13 @@ void upd7810_device::upd_internal_4096_rom_256_ram_map(address_map &map) m_ram_view[0](0xff00, 0xffff).ram(); } +void upd7810_device::upd_internal_16k_rom_256_ram_map(address_map &map) +{ + map(0x0000, 0x3fff).rom(); + map(0xff00, 0xffff).view(m_ram_view); + m_ram_view[0](0xff00, 0xffff).ram(); +} + upd7810_device::upd7810_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal_map) : cpu_device(mconfig, type, tag, owner, clock) , m_to_func(*this) @@ -474,6 +482,11 @@ upd78c11_device::upd78c11_device(const machine_config &mconfig, const char *tag, { } +upd78c14_device::upd78c14_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : upd78c10_device(mconfig, UPD78C14, tag, owner, clock, address_map_constructor(FUNC(upd78c14_device::upd_internal_16k_rom_256_ram_map), this)) +{ +} + void upd7807_device::configure_ops() { m_opXX = s_opXX_7807; diff --git a/src/devices/cpu/upd7810/upd7810.h b/src/devices/cpu/upd7810/upd7810.h index 9e07c77043b..cdda6dd8077 100644 --- a/src/devices/cpu/upd7810/upd7810.h +++ b/src/devices/cpu/upd7810/upd7810.h @@ -90,6 +90,7 @@ protected: void upd_internal_256_ram_map(address_map &map) ATTR_COLD; void upd_internal_4096_rom_128_ram_map(address_map &map) ATTR_COLD; void upd_internal_4096_rom_256_ram_map(address_map &map) ATTR_COLD; + void upd_internal_16k_rom_256_ram_map(address_map &map) ATTR_COLD; // flags enum @@ -1384,6 +1385,14 @@ public: }; +class upd78c14_device : public upd78c10_device +{ +public: + // construction/destruction + upd78c14_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +}; + + class upd7807_device : public upd7810_device { public: @@ -1449,6 +1458,7 @@ DECLARE_DEVICE_TYPE(UPD7810, upd7810_device) DECLARE_DEVICE_TYPE(UPD78C10, upd78c10_device) DECLARE_DEVICE_TYPE(UPD7811, upd7811_device) DECLARE_DEVICE_TYPE(UPD78C11, upd78c11_device) +DECLARE_DEVICE_TYPE(UPD78C14, upd78c14_device) DECLARE_DEVICE_TYPE(UPD7807, upd7807_device) DECLARE_DEVICE_TYPE(UPD7801, upd7801_device) DECLARE_DEVICE_TYPE(UPD78C05, upd78c05_device) diff --git a/src/devices/cpu/upd7810/upd7810_opcodes.cpp b/src/devices/cpu/upd7810/upd7810_opcodes.cpp index 892db43bc33..f9580278be5 100644 --- a/src/devices/cpu/upd7810/upd7810_opcodes.cpp +++ b/src/devices/cpu/upd7810/upd7810_opcodes.cpp @@ -309,7 +309,10 @@ void upd7810_device::DIV_A() A = remainder; } else - EA = 0xffff; /* guess */ + { + A = EAL; + EA = 0xffff; + } } /* 48 3e: 0100 1000 0011 1110 */ diff --git a/src/mame/mame.lst b/src/mame/mame.lst index cdc18c95d3f..9179ea363a9 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -43050,6 +43050,9 @@ ngenb38 @source:skeleton/nordlead.cpp nordle2x +@source:skeleton/omdisv22.cpp +omdisv22 + @source:skeleton/onyx.cpp c5000 c8002 diff --git a/src/mame/skeleton/omdisv22.cpp b/src/mame/skeleton/omdisv22.cpp new file mode 100644 index 00000000000..c47b8883516 --- /dev/null +++ b/src/mame/skeleton/omdisv22.cpp @@ -0,0 +1,176 @@ +// license:BSD-3-Clause +// copyright-holders:Devin Acker +/* + Skeleton driver for the uPD78C14-based "Driver Information System" used by + the circa-1990 Oldsmobile 98 and other models. + + Press 6, then Test/Reset, then enter a distance of 8192 to show a debug display + with information about the current ADC readings. After that, press any button + to display the ROM version. + + TODO: + - identify/hook up the display hardware + - properly hook up or at least figure out other inputs (port B, SCK/RX, CI, most ADCs, etc) + The function at 09D5 handles reading the ADC values. +*/ + +#include "emu.h" + +#include "cpu/upd7810/upd7810.h" + +#include + +namespace { + +class omdisv22_state : public driver_device +{ +public: + omdisv22_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_inputs(*this, "IN%u", 0U) + { } + + void omdisv22(machine_config &config); + + void inputs_w(int state) { m_input_sel = state; } + ioport_value inputs_r(); + +protected: + virtual void machine_start() override ATTR_COLD; + virtual void machine_reset() override ATTR_COLD; + +private: + required_device m_maincpu; + required_ioport_array<3> m_inputs; + + void pd_w(u8 data) { m_pd = data; } + void pf_w(u8 data); + + ioport_value m_input_sel; + + u8 m_output_pos; + u8 m_output[18]; + + u8 m_pd, m_pf; +}; + +/**************************************************************************/ +static INPUT_PORTS_START(omdisv22) + PORT_START("PA") + PORT_BIT( 0x07, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_MEMBER(FUNC(omdisv22_state::inputs_w)) + PORT_BIT( 0x78, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(FUNC(omdisv22_state::inputs_r)) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + + PORT_START("AN5") + PORT_CONFNAME( 0xff, 0xff, "Default Units" ) + PORT_CONFSETTING( 0xff, "English") + PORT_CONFSETTING( 0x00, "Metric") + + PORT_START("IN0") + PORT_BIT( 0x1, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("0 / E/M") PORT_CODE(KEYCODE_0_PAD); + PORT_BIT( 0x2, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("1 / RANGE") PORT_CODE(KEYCODE_1_PAD); + PORT_BIT( 0x4, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("2 / ECON") PORT_CODE(KEYCODE_2_PAD); + PORT_BIT( 0x8, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("3 / GAGES") PORT_CODE(KEYCODE_3_PAD); + + PORT_START("IN1") + PORT_BIT( 0x1, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("4 / OIL") PORT_CODE(KEYCODE_4_PAD); + PORT_BIT( 0x2, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("5 / FUEL") PORT_CODE(KEYCODE_5_PAD); + PORT_BIT( 0x4, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("6 / DEST") PORT_CODE(KEYCODE_6_PAD); + PORT_BIT( 0x8, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("7 / ETA") PORT_CODE(KEYCODE_7_PAD); + + PORT_START("IN2") + PORT_BIT( 0x1, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("8 / E/T") PORT_CODE(KEYCODE_8_PAD); + PORT_BIT( 0x2, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("9 / SPEED") PORT_CODE(KEYCODE_9_PAD); + PORT_BIT( 0x4, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("RESET") PORT_CODE(KEYCODE_ENTER_PAD); + PORT_BIT( 0x8, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("DATE/TIME") PORT_CODE(KEYCODE_DEL_PAD); +INPUT_PORTS_END + +/**************************************************************************/ +void omdisv22_state::omdisv22(machine_config &config) +{ + UPD78C14(config, m_maincpu, 3'145'728); // 128*64*384, generates 1 Hz INTFT1 and 8192 Hz SCK + m_maincpu->pa_in_cb().set_ioport("PA"); + m_maincpu->pa_out_cb().set_ioport("PA"); + m_maincpu->pb_in_cb().set_constant(0xff); // bit 1 = display ready + m_maincpu->pc_in_cb().set_constant(0xff); + m_maincpu->pd_out_cb().set(FUNC(omdisv22_state::pd_w)); + m_maincpu->pf_out_cb().set(FUNC(omdisv22_state::pf_w)); + m_maincpu->an0_func().set_constant(0xff); // fuel level sensor? + m_maincpu->an1_func().set_constant(0xff); // unknown + m_maincpu->an2_func().set_constant(0xff); // unknown (only tested whether on/off) + m_maincpu->an3_func().set_constant(0xff); // reference/divisor for AN0 + m_maincpu->an4_func().set_constant(0xff); // affects scaling of AN0/AN3 (only tested whether on/off) + m_maincpu->an5_func().set_ioport("AN5"); + m_maincpu->an6_func().set_constant(0xff); // similar to AN4 +} + +/**************************************************************************/ +void omdisv22_state::machine_start() +{ + std::fill(std::begin(m_output), std::end(m_output), 0); + + save_item(NAME(m_input_sel)); + save_item(NAME(m_output_pos)); + save_item(NAME(m_output)); + save_item(NAME(m_pd)); + save_item(NAME(m_pf)); +} + +/**************************************************************************/ +void omdisv22_state::machine_reset() +{ + m_maincpu->set_input_line(UPD7810_INTF2, ASSERT_LINE); + + m_input_sel = 0x7; + + m_output_pos = 0; + m_pd = m_pf = 0xff; +} + +/**************************************************************************/ +ioport_value omdisv22_state::inputs_r() +{ + ioport_value val = 0xf; + + for (int i = 0; i < 3; i++) + if (!BIT(m_input_sel, i)) + val &= m_inputs[i]->read(); + + return val; +} + +/**************************************************************************/ +void omdisv22_state::pf_w(u8 data) +{ + // TODO: what kind of display is this, anyway? + if (BIT(m_pf, 5) && BIT(m_pf, 4) && !BIT(data, 4)) + { + if (m_pd == 0xf1) + { + m_output_pos = 0; + } + else if (m_pd == 0xf2) + { + m_output[m_output_pos] = 0; + logerror("%s\n", (const char*)m_output); + popmessage("%s", (const char*)m_output); + } + else if (m_output_pos < (sizeof(m_output) - 1)) + { + m_output[m_output_pos++] = 0x30 + (m_pd / 5); + } + } + + m_pf = data; +} + +/**************************************************************************/ +ROM_START( omdisv22 ) + ROM_REGION(0x4000, "maincpu", 0) // date code 9020, upper half of ROM is empty/unused + ROM_LOAD( "upd78c14g-443.bin", 0x0000, 0x4000, CRC(fab369b2) SHA1(7cbd5be32e475efd58db70c0a94b770c58fd9b8e) ) +ROM_END + +} // anonymous namespace + +SYST( 1990?, omdisv22, 0, 0, omdisv22, omdisv22, omdisv22_state, empty_init, "General Motors", "Oldsmobile Driver Information System (version 2.2 CH)", MACHINE_NO_SOUND_HW | MACHINE_NOT_WORKING )