From a7be70a183ceee8ce3c79a6afec61ae7aef95fe1 Mon Sep 17 00:00:00 2001 From: AJR Date: Wed, 7 Sep 2022 09:14:06 -0400 Subject: Add preliminary M50734 emulation --- scripts/src/cpu.lua | 3 + src/devices/cpu/m6502/m50734.cpp | 158 +++++++++++++++++++++++++++++++++++++++ src/devices/cpu/m6502/m50734.h | 119 +++++++++++++++++++++++++++++ src/mame/kawai/kawai_r100.cpp | 43 +++++++++-- 4 files changed, 318 insertions(+), 5 deletions(-) create mode 100644 src/devices/cpu/m6502/m50734.cpp create mode 100644 src/devices/cpu/m6502/m50734.h diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index 8ca5f85418c..284e5757b60 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -1574,6 +1574,7 @@ end --@src/devices/cpu/m6502/n2a03.h,CPUS["M6502"] = true --@src/devices/cpu/m6502/m740.h,CPUS["M6502"] = true --@src/devices/cpu/m6502/m3745x.h,CPUS["M6502"] = true +--@src/devices/cpu/m6502/m50734.h,CPUS["M6502"] = true --@src/devices/cpu/m6502/m5074x.h,CPUS["M6502"] = true --@src/devices/cpu/m6502/m6502mtu.h,CPUS["M6502"] = true --@src/devices/cpu/m6502/st2xxx.h,CPUS["ST2XXX"] = true @@ -1629,6 +1630,8 @@ if CPUS["M6502"] then MAME_DIR .. "src/devices/cpu/m6502/m740.h", MAME_DIR .. "src/devices/cpu/m6502/m3745x.cpp", MAME_DIR .. "src/devices/cpu/m6502/m3745x.h", + MAME_DIR .. "src/devices/cpu/m6502/m50734.cpp", + MAME_DIR .. "src/devices/cpu/m6502/m50734.h", MAME_DIR .. "src/devices/cpu/m6502/m5074x.cpp", MAME_DIR .. "src/devices/cpu/m6502/m5074x.h", } diff --git a/src/devices/cpu/m6502/m50734.cpp b/src/devices/cpu/m6502/m50734.cpp new file mode 100644 index 00000000000..9b56903fba9 --- /dev/null +++ b/src/devices/cpu/m6502/m50734.cpp @@ -0,0 +1,158 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/********************************************************************** + + Mitsubishi M50734 emulation (preliminary) + + This microcontroller contains no internal memory, RAM or ROM. The + external bus allows P05 to be programmed as a strobe (DME) for a + separable "data" memory space. On-chip peripherals include an ADC, + UART, various general and special-purpose timers and a stepper + motor controller. + +**********************************************************************/ + +#include "emu.h" +#include "m50734.h" + +// device type definition +DEFINE_DEVICE_TYPE(M50734, m50734_device, "m50734", "Mitsubishi M50734") + +m50734_device::m50734_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : m740_device(mconfig, M50734, tag, owner, clock) + , m_data_config("data", ENDIANNESS_LITTLE, 8, 16, 0) + , m_port_in_cb(*this) + , m_port_out_cb(*this) + , m_port_latch{0, 0, 0, 0} + , m_port_3state{0, 0, 0, 0} +{ + program_config.m_internal_map = address_map_constructor(FUNC(m50734_device::internal_map), this); +} + +device_memory_interface::space_config_vector m50734_device::memory_space_config() const +{ + if (has_configured_map(AS_DATA)) + return space_config_vector { + std::make_pair(AS_PROGRAM, &program_config), + std::make_pair(AS_DATA, &m_data_config) + }; + else + return m740_device::memory_space_config(); +} + +void m50734_device::device_resolve_objects() +{ + for (int n = 0; n < 4; n++) + m_port_in_cb[n].resolve_safe(m_port_3state[n]); + m_port_in_cb[4].resolve_safe(0); + m_port_out_cb.resolve_all_safe(); +} + +void m50734_device::device_start() +{ + m740_device::device_start(); + + space(has_space(AS_DATA) ? AS_DATA : AS_PROGRAM).specific(m_data); + + save_item(NAME(m_port_latch)); + save_item(NAME(m_port_direction)); + save_item(NAME(m_p0_function)); + save_item(NAME(m_p2_p3_function)); +} + +void m50734_device::device_reset() +{ + std::fill(std::begin(m_port_direction), std::end(m_port_direction), 0x00); + for (int n = 0; n < 4; n++) + m_port_out_cb[n](m_port_3state[n]); + m_p0_function = 0x00; + m_p2_p3_function = 0x00; +} + +void m50734_device::read_dummy(u16 adr) +{ + // M50734 outputs RD and WR strobes rather than R/W, so dummy accesses should do nothing +} + +u8 m50734_device::read_data(u16 adr) +{ + if (BIT(m_p0_function, 5)) + return m_data.read_byte(adr); + else + return m740_device::read(adr); +} + +void m50734_device::write_data(u16 adr, u8 val) +{ + if (BIT(m_p0_function, 5)) + m_data.write_byte(adr, val); + else + m740_device::write(adr, val); +} + +template +u8 m50734_device::port_r(offs_t offset) +{ + if (BIT(offset, 0)) + return m_port_direction[N]; + else if (m_port_direction[0] == 0xff) + return m_port_latch[N]; + else + return (m_port_in_cb[N]() & ~m_port_direction[N]) | (m_port_latch[N] & m_port_direction[N]); +} + +template +void m50734_device::port_w(offs_t offset, u8 data) +{ + if (BIT(offset, 0)) + { + if (m_port_direction[N] != data) + { + logerror("Port P%d direction = $%02X\n", N, data); + m_port_direction[N] = data; + m_port_out_cb[N]((data & m_port_latch[N]) | (m_port_3state[N] & ~m_port_direction[N])); + } + } + else if (((std::exchange(m_port_latch[N], data) ^ data) & m_port_direction[N]) != 0) + m_port_out_cb[N]((data & m_port_direction[N]) | (m_port_3state[N] & ~m_port_direction[N])); +} + +u8 m50734_device::p4_r() +{ + // P4 has only 4 pins and no output drivers + return m_port_in_cb[4]() & 0x0f; +} + +u8 m50734_device::p0_function_r() +{ + return m_p0_function; +} + +void m50734_device::p0_function_w(u8 data) +{ + logerror("Port P0 function = $%02X\n", data); + m_p0_function = data; +} + +u8 m50734_device::p2_p3_function_r() +{ + return m_p2_p3_function; +} + +void m50734_device::p2_p3_function_w(u8 data) +{ + logerror("Port P2/P3 function = $%02X\n", data); + m_p2_p3_function = data & 0xc7; +} + +void m50734_device::internal_map(address_map &map) +{ + // TODO: timers, etc. + map(0x00eb, 0x00eb).r(FUNC(m50734_device::p4_r)); + map(0x00ed, 0x00ed).rw(FUNC(m50734_device::p2_p3_function_r), FUNC(m50734_device::p2_p3_function_w)); + map(0x00ee, 0x00ef).rw(FUNC(m50734_device::port_r<3>), FUNC(m50734_device::port_w<3>)); + map(0x00f0, 0x00f1).rw(FUNC(m50734_device::port_r<2>), FUNC(m50734_device::port_w<2>)); + map(0x00f3, 0x00f4).rw(FUNC(m50734_device::port_r<1>), FUNC(m50734_device::port_w<1>)); + map(0x00f5, 0x00f5).rw(FUNC(m50734_device::p0_function_r), FUNC(m50734_device::p0_function_w)); + map(0x00f6, 0x00f7).rw(FUNC(m50734_device::port_r<0>), FUNC(m50734_device::port_w<0>)); +} diff --git a/src/devices/cpu/m6502/m50734.h b/src/devices/cpu/m6502/m50734.h new file mode 100644 index 00000000000..4e71585e821 --- /dev/null +++ b/src/devices/cpu/m6502/m50734.h @@ -0,0 +1,119 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/********************************************************************** + + Mitsubishi M50734 + +********************************************************************** + _____ _____ + P04/STBout 1 |* \_/ | 64 Vcc + P05/_DME 2 | | 63 P03/BUSYout + P06/TxD 3 | | 62 P02/CNTR + P07/RxD 4 | | 61 P01/_INT2 + P10 5 | | 60 P00/_INT1 + P11 6 | | 59 WDout + P12 7 | | 58 A0/D0 + P13 8 | | 57 A1/D1 + P14 9 | | 56 A2/D2 + P15 10 | | 55 A3/D3 + P16 11 | | 54 A4/D4 + P17 12 | | 53 A5/D5 + P20/Ha 13 | | 52 A6/D6 + P21/Hb 14 | | 51 A7/D7 + P22/Hc 15 | M50734SP | 50 ALE + P23/Hd 16 | | 49 A8 + P24/Va 17 | | 48 A9 + P25/Vb 18 | | 47 A10 + P26/Vc 19 | | 46 A11 + P27/Vd 20 | | 45 A12 + P30/PWMout 21 | | 44 A13 + P31/Sclk 22 | | 43 A14 + P32/Sio 23 | | 42 A15 + P33 24 | | 41 SYNC + P34 25 | | 40 ΙΈ + P35 26 | | 39 _WR + P36 27 | | 38 _RD + P37 28 | | 37 Vref + _RESET 29 | | 36 P43/AN3 + Xin 30 | | 35 P42/AN2 + Xout 31 | | 34 P41/AN1 + Vss 32 |_____________| 33 P40/AN0 + +**********************************************************************/ + +#ifndef MAME_CPU_M6502_M50734_H +#define MAME_CPU_M6502_M50734_H + +#pragma once + +#include "m740.h" + +class m50734_device : public m740_device +{ +public: + //enum { + //}; + + m50734_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + // port callback configuration + auto p0_in_cb() { return m_port_in_cb[0].bind(); } + auto p0_out_cb() { return m_port_out_cb[0].bind(); } + auto p1_in_cb() { return m_port_in_cb[1].bind(); } + auto p1_out_cb() { return m_port_out_cb[1].bind(); } + auto p2_in_cb() { return m_port_in_cb[2].bind(); } + auto p2_out_cb() { return m_port_out_cb[2].bind(); } + auto p3_in_cb() { return m_port_in_cb[3].bind(); } + auto p3_out_cb() { return m_port_out_cb[3].bind(); } + auto p4_in_cb() { return m_port_in_cb[4].bind(); } + + // port three-state output configuration + void set_p0_3state(u8 value) { assert(!configured()); m_port_3state[0] = value; } + void set_p1_3state(u8 value) { assert(!configured()); m_port_3state[1] = value; } + void set_p2_3state(u8 value) { assert(!configured()); m_port_3state[2] = value; } + void set_p3_3state(u8 value) { assert(!configured()); m_port_3state[3] = value; } + +protected: + // device-level overrides + virtual void device_resolve_objects() override; + virtual void device_start() override; + virtual void device_reset() override; + + // device_execute_interface overrides + virtual u64 execute_clocks_to_cycles(u64 clocks) const noexcept override { return (clocks + 4 - 1) / 4; } + virtual u64 execute_cycles_to_clocks(u64 cycles) const noexcept override { return (cycles * 4); } + + // device_memory_interface overrides + space_config_vector memory_space_config() const override; + + // m740_device overrides + virtual void read_dummy(u16 adr) override; + virtual uint8_t read_data(u16 adr) override; + virtual void write_data(u16 adr, u8 val) override; + +private: + void internal_map(address_map &map); + template u8 port_r(offs_t offset); + template void port_w(offs_t offset, u8 data); + u8 p4_r(); + u8 p0_function_r(); + void p0_function_w(u8 data); + u8 p2_p3_function_r(); + void p2_p3_function_w(u8 data); + + const address_space_config m_data_config; + memory_access<16, 0, 0, ENDIANNESS_LITTLE>::specific m_data; + + devcb_read8::array<5> m_port_in_cb; + devcb_write8::array<4> m_port_out_cb; + + u8 m_port_latch[4]; + u8 m_port_direction[4]; + u8 m_port_3state[4]; + u8 m_p0_function; + u8 m_p2_p3_function; +}; + +DECLARE_DEVICE_TYPE(M50734, m50734_device) + +#endif // MAME_CPU_M6502_M50734_H diff --git a/src/mame/kawai/kawai_r100.cpp b/src/mame/kawai/kawai_r100.cpp index 0a09ced01f6..8d9b73f8869 100644 --- a/src/mame/kawai/kawai_r100.cpp +++ b/src/mame/kawai/kawai_r100.cpp @@ -7,7 +7,7 @@ ***************************************************************************/ #include "emu.h" -#include "cpu/m6502/m3745x.h" +#include "cpu/m6502/m50734.h" #include "machine/nvram.h" class kawai_r100_state : public driver_device @@ -22,13 +22,34 @@ public: void r100(machine_config &config); private: + void p0_w(u8 data); + void p1_w(u8 data); + void p2_w(u8 data); + void p3_w(u8 data); + void main_map(address_map &map); - //void data_map(address_map &map); + void data_map(address_map &map); - required_device m_maincpu; + required_device m_maincpu; }; +void kawai_r100_state::p0_w(u8 data) +{ +} + +void kawai_r100_state::p1_w(u8 data) +{ +} + +void kawai_r100_state::p2_w(u8 data) +{ +} + +void kawai_r100_state::p3_w(u8 data) +{ +} + void kawai_r100_state::main_map(address_map &map) { map(0x0000, 0x1fff).ram().share("nvram1"); @@ -36,15 +57,27 @@ void kawai_r100_state::main_map(address_map &map) map(0x4400, 0xffff).rom().region("program", 0x4400); } +void kawai_r100_state::data_map(address_map &map) +{ + // TODO: 0x0000-0x1fff and 0x2000-0x3fff mapped to cartridge slot +} + static INPUT_PORTS_START(r100) INPUT_PORTS_END void kawai_r100_state::r100(machine_config &config) { - M37450(config, m_maincpu, 16_MHz_XTAL / 2); // FIXME: M50734SP + M50734(config, m_maincpu, 16_MHz_XTAL / 2); // M50734SP m_maincpu->set_addrmap(AS_PROGRAM, &kawai_r100_state::main_map); - //m_maincpu->set_addrmap(AS_DATA, &kawai_r100_state::data_map); + m_maincpu->set_addrmap(AS_DATA, &kawai_r100_state::data_map); + m_maincpu->set_p0_3state(0x20); + m_maincpu->set_p3_3state(0x02); + m_maincpu->p0_out_cb().set(FUNC(kawai_r100_state::p0_w)); + m_maincpu->p1_out_cb().set(FUNC(kawai_r100_state::p1_w)); + m_maincpu->p2_out_cb().set(FUNC(kawai_r100_state::p2_w)); + m_maincpu->p3_out_cb().set(FUNC(kawai_r100_state::p3_w)); + m_maincpu->p4_in_cb().set_constant(0x0f); NVRAM(config, "nvram1", nvram_device::DEFAULT_ALL_0); // MB8464-15LL-SK + battery NVRAM(config, "nvram2", nvram_device::DEFAULT_ALL_0); // MB8464-15LL-SK + battery -- cgit v1.2.3