mirror of
https://github.com/holub/mame
synced 2025-04-20 23:42:22 +03:00
Add preliminary M50734 emulation
This commit is contained in:
parent
b008567de0
commit
a7be70a183
@ -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",
|
||||
}
|
||||
|
158
src/devices/cpu/m6502/m50734.cpp
Normal file
158
src/devices/cpu/m6502/m50734.cpp
Normal file
@ -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 <int N>
|
||||
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 <int N>
|
||||
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>));
|
||||
}
|
119
src/devices/cpu/m6502/m50734.h
Normal file
119
src/devices/cpu/m6502/m50734.h
Normal file
@ -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 <int N> u8 port_r(offs_t offset);
|
||||
template <int N> 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
|
@ -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 main_map(address_map &map);
|
||||
//void data_map(address_map &map);
|
||||
void p0_w(u8 data);
|
||||
void p1_w(u8 data);
|
||||
void p2_w(u8 data);
|
||||
void p3_w(u8 data);
|
||||
|
||||
required_device<m740_device> m_maincpu;
|
||||
void main_map(address_map &map);
|
||||
void data_map(address_map &map);
|
||||
|
||||
required_device<m50734_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
|
||||
|
Loading…
Reference in New Issue
Block a user