mirror of
https://github.com/holub/mame
synced 2025-04-21 07:52:35 +03:00
Enhance the sh704x. MU128 MSTO, needs interrupts now.
This commit is contained in:
parent
187945dbd0
commit
1dae50467e
@ -899,6 +899,14 @@ if CPUS["SH"] then
|
||||
MAME_DIR .. "src/devices/cpu/sh/sh7032.h",
|
||||
MAME_DIR .. "src/devices/cpu/sh/sh7042.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/sh/sh7042.h",
|
||||
MAME_DIR .. "src/devices/cpu/sh/sh_adc.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/sh/sh_adc.h",
|
||||
MAME_DIR .. "src/devices/cpu/sh/sh_cmt.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/sh/sh_cmt.h",
|
||||
MAME_DIR .. "src/devices/cpu/sh/sh_intc.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/sh/sh_intc.h",
|
||||
MAME_DIR .. "src/devices/cpu/sh/sh_port.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/sh/sh_port.h",
|
||||
MAME_DIR .. "src/devices/cpu/sh/sh7604_bus.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/sh/sh7604_bus.h",
|
||||
MAME_DIR .. "src/devices/cpu/sh/sh7604_sci.cpp",
|
||||
|
@ -31,8 +31,8 @@ void plg1x0_connector::midi_rx(int state)
|
||||
|
||||
void plg1x0_intf(device_slot_interface &device)
|
||||
{
|
||||
device.option_add("plg100-vl", PLG100_VL);
|
||||
device.option_add("plg150-ap", PLG150_AP);
|
||||
device.option_add("plg100vl", PLG100_VL);
|
||||
device.option_add("plg150ap", PLG150_AP);
|
||||
}
|
||||
|
||||
device_plg1x0_interface::device_plg1x0_interface(const machine_config &mconfig, device_t &device) :
|
||||
|
@ -19,7 +19,11 @@
|
||||
|
||||
class h8_adc_device : public device_t {
|
||||
public:
|
||||
template<typename T, typename U> void set_info(T &&cpu, U &&intc, int vect) { m_cpu.set_tag(std::forward<T>(cpu)), m_intc.set_tag(std::forward<U>(intc)); m_intc_vector = vect; }
|
||||
template<typename T, typename U> void set_info(T &&cpu, U &&intc, int vect) {
|
||||
m_cpu.set_tag(std::forward<T>(cpu));
|
||||
m_intc.set_tag(std::forward<U>(intc));
|
||||
m_intc_vector = vect;
|
||||
}
|
||||
|
||||
u8 addr8_r(offs_t offset);
|
||||
u16 addr16_r(offs_t offset);
|
||||
|
@ -21,13 +21,61 @@ sh7043_device::sh7043_device(const machine_config &mconfig, const char *tag, dev
|
||||
|
||||
sh7042_device::sh7042_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
|
||||
sh2_device(mconfig, type, tag, owner, clock, CPU_TYPE_SH2, address_map_constructor(FUNC(sh7042_device::map), this), 32, 0xffffffff),
|
||||
m_intc(*this, "intc"),
|
||||
m_adc(*this, "adc"),
|
||||
m_cmt(*this, "cmt"),
|
||||
m_porta(*this, "porta"),
|
||||
m_portb(*this, "portb"),
|
||||
m_portc(*this, "portc"),
|
||||
m_portd(*this, "portd"),
|
||||
m_porte(*this, "porte"),
|
||||
m_portf(*this, "portf"),
|
||||
m_read_adc(*this, 0),
|
||||
m_sci_tx(*this)
|
||||
m_sci_tx(*this),
|
||||
m_read_port16(*this, 0xffff),
|
||||
m_write_port16(*this),
|
||||
m_read_port32(*this, 0xffffffff),
|
||||
m_write_port32(*this)
|
||||
{
|
||||
m_port16_names = "bcef";
|
||||
m_port32_names = "ad";
|
||||
for(unsigned int i=0; i != m_read_adc.size(); i++)
|
||||
m_read_adc[i].bind().set([this, i]() { return adc_default(i); });
|
||||
for(unsigned int i=0; i != m_read_port16.size(); i++) {
|
||||
m_read_port16[i].bind().set([this, i]() { return port16_default_r(i); });
|
||||
m_write_port16[i].bind().set([this, i](u16 data) { port16_default_w(i, data); });
|
||||
}
|
||||
for(unsigned int i=0; i != m_read_port32.size(); i++) {
|
||||
m_read_port32[i].bind().set([this, i]() { return port32_default_r(i); });
|
||||
m_write_port32[i].bind().set([this, i](u32 data) { port32_default_w(i, data); });
|
||||
}
|
||||
}
|
||||
|
||||
u16 sh7042_device::port16_default_r(int port)
|
||||
{
|
||||
if(!machine().side_effects_disabled())
|
||||
logerror("read of un-hooked port %c\n", m_port16_names[port]);
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
void sh7042_device::port16_default_w(int port, u16 data)
|
||||
{
|
||||
logerror("write of un-hooked port %c %04x\n", m_port16_names[port], data);
|
||||
}
|
||||
|
||||
u32 sh7042_device::port32_default_r(int port)
|
||||
{
|
||||
if(!machine().side_effects_disabled())
|
||||
logerror("read of un-hooked port %c\n", m_port32_names[port]);
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
void sh7042_device::port32_default_w(int port, u32 data)
|
||||
{
|
||||
logerror("write of un-hooked port %c %04x\n", m_port32_names[port], data);
|
||||
}
|
||||
|
||||
|
||||
u16 sh7042_device::adc_default(int adc)
|
||||
{
|
||||
logerror("read of un-hooked adc %d\n", adc);
|
||||
@ -38,70 +86,214 @@ void sh7042_device::device_start()
|
||||
{
|
||||
sh2_device::device_start();
|
||||
|
||||
save_item(NAME(m_addr));
|
||||
save_item(NAME(m_adcsr));
|
||||
save_item(NAME(m_adcr));
|
||||
m_event_timer = timer_alloc(FUNC(sh7042_device::event_timer_tick), this);
|
||||
|
||||
save_item(NAME(m_pcf_ah));
|
||||
save_item(NAME(m_pcf_al));
|
||||
save_item(NAME(m_pcf_b));
|
||||
save_item(NAME(m_pcf_c));
|
||||
save_item(NAME(m_pcf_dh));
|
||||
save_item(NAME(m_pcf_dl));
|
||||
save_item(NAME(m_pcf_e));
|
||||
save_item(NAME(m_pcf_if));
|
||||
|
||||
m_pcf_ah = 0;
|
||||
m_pcf_al = 0;
|
||||
m_pcf_b = 0;
|
||||
m_pcf_c = 0;
|
||||
m_pcf_dh = 0;
|
||||
m_pcf_dl = 0;
|
||||
m_pcf_e = 0;
|
||||
m_pcf_if = 0;
|
||||
}
|
||||
|
||||
void sh7042_device::device_reset()
|
||||
{
|
||||
sh2_device::device_reset();
|
||||
|
||||
memset(m_addr, 0, sizeof(m_addr));
|
||||
m_adcsr = m_adcr = 0;
|
||||
}
|
||||
|
||||
|
||||
void sh7042_device::map(address_map &map)
|
||||
{
|
||||
map(0xffff83e0, 0xffff83e0).rw(FUNC(sh7042_device::adcsr_r), FUNC(sh7042_device::adcsr_w));
|
||||
map(0xffff83e1, 0xffff83e1).rw(FUNC(sh7042_device::adcr_r), FUNC(sh7042_device::adcr_w));
|
||||
map(0xffff83f0, 0xffff83ff).r(FUNC(sh7042_device::addr_r));
|
||||
map(0xffff8348, 0xffff8357).rw(m_intc, FUNC(sh_intc_device::ipr_r), FUNC(sh_intc_device::ipr_w));
|
||||
map(0xffff8358, 0xffff8359).rw(m_intc, FUNC(sh_intc_device::icr_r), FUNC(sh_intc_device::icr_w));
|
||||
map(0xffff835a, 0xffff835b).rw(m_intc, FUNC(sh_intc_device::isr_r), FUNC(sh_intc_device::isr_w));
|
||||
|
||||
map(0xffff8380, 0xffff8383).rw(m_porta, FUNC(sh_port32_device::dr_r), FUNC(sh_port32_device::dr_w));
|
||||
map(0xffff8384, 0xffff8387).rw(m_porta, FUNC(sh_port32_device::io_r), FUNC(sh_port32_device::io_w));
|
||||
map(0xffff8388, 0xffff8389).rw(FUNC(sh7042_device::pcf_ah_r), FUNC(sh7042_device::pcf_ah_w));
|
||||
map(0xffff838c, 0xffff838f).rw(FUNC(sh7042_device::pcf_al_r), FUNC(sh7042_device::pcf_al_w));
|
||||
map(0xffff8390, 0xffff8391).rw(m_portb, FUNC(sh_port16_device::dr_r), FUNC(sh_port16_device::dr_w));
|
||||
map(0xffff8392, 0xffff8393).rw(m_portc, FUNC(sh_port16_device::dr_r), FUNC(sh_port16_device::dr_w));
|
||||
map(0xffff8394, 0xffff8395).rw(m_portb, FUNC(sh_port16_device::io_r), FUNC(sh_port16_device::io_w));
|
||||
map(0xffff8396, 0xffff8397).rw(m_portc, FUNC(sh_port16_device::io_r), FUNC(sh_port16_device::io_w));
|
||||
map(0xffff8398, 0xffff839b).rw(FUNC(sh7042_device::pcf_b_r), FUNC(sh7042_device::pcf_b_w));
|
||||
map(0xffff839c, 0xffff839d).rw(FUNC(sh7042_device::pcf_c_r), FUNC(sh7042_device::pcf_c_w));
|
||||
map(0xffff83a0, 0xffff83a3).rw(m_portd, FUNC(sh_port32_device::dr_r), FUNC(sh_port32_device::dr_w));
|
||||
map(0xffff83a4, 0xffff83a7).rw(m_portd, FUNC(sh_port32_device::io_r), FUNC(sh_port32_device::io_w));
|
||||
map(0xffff83a8, 0xffff83ab).rw(FUNC(sh7042_device::pcf_dh_r), FUNC(sh7042_device::pcf_dh_w));
|
||||
map(0xffff83ac, 0xffff83ad).rw(FUNC(sh7042_device::pcf_dl_r), FUNC(sh7042_device::pcf_dl_w));
|
||||
map(0xffff83b0, 0xffff83b1).rw(m_porte, FUNC(sh_port16_device::dr_r), FUNC(sh_port16_device::dr_w));
|
||||
map(0xffff83b2, 0xffff83b3).r (m_portf, FUNC(sh_port16_device::dr_r));
|
||||
map(0xffff83b4, 0xffff83b5).rw(m_porte, FUNC(sh_port16_device::io_r), FUNC(sh_port16_device::io_w));
|
||||
map(0xffff83b8, 0xffff83bb).rw(FUNC(sh7042_device::pcf_e_r), FUNC(sh7042_device::pcf_e_w));
|
||||
map(0xffff83c8, 0xffff83c9).rw(FUNC(sh7042_device::pcf_if_r), FUNC(sh7042_device::pcf_if_w));
|
||||
|
||||
map(0xffff83d0, 0xffff83d1).rw(m_cmt, FUNC(sh_cmt_device::cmstr_r), FUNC(sh_cmt_device::cmstr_w));
|
||||
map(0xffff83d2, 0xffff83d3).rw(m_cmt, FUNC(sh_cmt_device::cmcsr0_r), FUNC(sh_cmt_device::cmcsr0_w));
|
||||
map(0xffff83d4, 0xffff83d5).rw(m_cmt, FUNC(sh_cmt_device::cmcnt0_r), FUNC(sh_cmt_device::cmcnt0_w));
|
||||
map(0xffff83d6, 0xffff83d7).rw(m_cmt, FUNC(sh_cmt_device::cmcor0_r), FUNC(sh_cmt_device::cmcor0_w));
|
||||
map(0xffff83d8, 0xffff83d9).rw(m_cmt, FUNC(sh_cmt_device::cmcsr1_r), FUNC(sh_cmt_device::cmcsr1_w));
|
||||
map(0xffff83da, 0xffff83db).rw(m_cmt, FUNC(sh_cmt_device::cmcnt1_r), FUNC(sh_cmt_device::cmcnt1_w));
|
||||
map(0xffff83dc, 0xffff83dd).rw(m_cmt, FUNC(sh_cmt_device::cmcor1_r), FUNC(sh_cmt_device::cmcor1_w));
|
||||
|
||||
map(0xffff83e0, 0xffff83e0).rw(m_adc, FUNC(sh_adc_device::adcsr_r), FUNC(sh_adc_device::adcsr_w));
|
||||
map(0xffff83e1, 0xffff83e1).rw(m_adc, FUNC(sh_adc_device::adcr_r), FUNC(sh_adc_device::adcr_w));
|
||||
map(0xffff83f0, 0xffff83ff).r(m_adc, FUNC(sh_adc_device::addr_r));
|
||||
|
||||
map(0xfffff000, 0xffffffff).ram();
|
||||
}
|
||||
|
||||
|
||||
// ADC section
|
||||
|
||||
u16 sh7042_device::addr_r(offs_t offset)
|
||||
void sh7042_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
logerror("addr16_r %d %03x\n", offset, m_addr[offset]);
|
||||
return m_addr[offset];
|
||||
}
|
||||
|
||||
u8 sh7042_device::adcsr_r()
|
||||
{
|
||||
logerror("adcsr_r %02x\n", m_adcsr);
|
||||
return m_adcsr;
|
||||
}
|
||||
|
||||
u8 sh7042_device::adcr_r()
|
||||
{
|
||||
logerror("adcr_r %02x\n", m_adcr);
|
||||
return m_adcr;
|
||||
}
|
||||
|
||||
void sh7042_device::adcsr_w(u8 data)
|
||||
{
|
||||
logerror("adcsr_w %02x\n", data);
|
||||
// u8 prev = m_adcsr;
|
||||
m_adcsr = (data & 0x7f) | (m_adcsr & data & CSR_ADF);
|
||||
}
|
||||
|
||||
void sh7042_device::adcr_w(u8 data)
|
||||
{
|
||||
static const char *const tg_modes[4] = { "soft", "mtu", "?", "external" };
|
||||
static const char *const buf_modes[4] = { "normal", "a->b", "a,b->c,d", "a->b->c->d" };
|
||||
logerror("adcr_w speed=%d trigger=%s mode=%s sampling=%s buffering=%s\n",
|
||||
BIT(data, 6) ? "high" : "low",
|
||||
tg_modes[(data >> 4) & 3],
|
||||
BIT(data, 3) ? "scan" : "single",
|
||||
BIT(data, 2) ? "simultaneous" : "normal",
|
||||
buf_modes[data & 3]);
|
||||
m_adcr = data;
|
||||
SH_INTC(config, m_intc, *this);
|
||||
SH_ADC(config, m_adc, *this, m_intc, 136);
|
||||
SH_CMT(config, m_cmt, *this, m_intc, 144, 148);
|
||||
SH_PORT32(config, m_porta, *this, 0, 0x00000000, 0xff000000);
|
||||
SH_PORT16(config, m_portb, *this, 0, 0x0000, 0xfc00);
|
||||
SH_PORT16(config, m_portc, *this, 1, 0x0000, 0x0000);
|
||||
SH_PORT32(config, m_portd, *this, 1, 0x0000, 0x0000);
|
||||
SH_PORT16(config, m_porte, *this, 2, 0x0000, 0x0000);
|
||||
SH_PORT16(config, m_portf, *this, 3, 0x0000, 0xff00);
|
||||
}
|
||||
|
||||
void sh7042_device::do_sci_w(int sci, int state)
|
||||
{
|
||||
logerror("sci %d %d\n", sci, state);
|
||||
}
|
||||
|
||||
void sh7042_device::internal_update()
|
||||
{
|
||||
internal_update(current_cycles());
|
||||
}
|
||||
|
||||
void sh7042_device::add_event(u64 &event_time, u64 new_event)
|
||||
{
|
||||
if(!new_event)
|
||||
return;
|
||||
if(!event_time || event_time > new_event)
|
||||
event_time = new_event;
|
||||
}
|
||||
|
||||
void sh7042_device::recompute_timer(u64 event_time)
|
||||
{
|
||||
if(!event_time) {
|
||||
m_event_timer->adjust(attotime::never);
|
||||
return;
|
||||
}
|
||||
|
||||
m_event_timer->adjust(attotime::from_ticks(2*event_time + 1, 2*clock()) - machine().time());
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(sh7042_device::event_timer_tick)
|
||||
{
|
||||
internal_update();
|
||||
}
|
||||
|
||||
void sh7042_device::internal_update(u64 current_time)
|
||||
{
|
||||
u64 event_time = 0;
|
||||
|
||||
add_event(event_time, m_adc->internal_update(current_time));
|
||||
add_event(event_time, m_cmt->internal_update(current_time));
|
||||
|
||||
recompute_timer(event_time);
|
||||
}
|
||||
|
||||
u16 sh7042_device::pcf_ah_r()
|
||||
{
|
||||
return m_pcf_ah;
|
||||
}
|
||||
|
||||
void sh7042_device::pcf_ah_w(offs_t, u16 data, u16 mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_pcf_ah);
|
||||
logerror("pcf ah = %04x\n", m_pcf_ah);
|
||||
}
|
||||
|
||||
u32 sh7042_device::pcf_al_r()
|
||||
{
|
||||
return m_pcf_al;
|
||||
}
|
||||
|
||||
void sh7042_device::pcf_al_w(offs_t, u32 data, u32 mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_pcf_al);
|
||||
logerror("pcf al = %08x\n", m_pcf_al);
|
||||
}
|
||||
|
||||
u32 sh7042_device::pcf_b_r()
|
||||
{
|
||||
return m_pcf_b;
|
||||
}
|
||||
|
||||
void sh7042_device::pcf_b_w(offs_t, u32 data, u32 mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_pcf_b);
|
||||
logerror("pcf b = %08x\n", m_pcf_b);
|
||||
}
|
||||
|
||||
u16 sh7042_device::pcf_c_r()
|
||||
{
|
||||
return m_pcf_c;
|
||||
}
|
||||
|
||||
void sh7042_device::pcf_c_w(offs_t, u16 data, u16 mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_pcf_c);
|
||||
logerror("pcf c = %04x\n", m_pcf_c);
|
||||
}
|
||||
|
||||
u32 sh7042_device::pcf_dh_r()
|
||||
{
|
||||
return m_pcf_dh;
|
||||
}
|
||||
|
||||
void sh7042_device::pcf_dh_w(offs_t, u32 data, u32 mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_pcf_dh);
|
||||
logerror("pcf dh = %08x\n", m_pcf_dh);
|
||||
}
|
||||
|
||||
u16 sh7042_device::pcf_dl_r()
|
||||
{
|
||||
return m_pcf_dl;
|
||||
}
|
||||
|
||||
void sh7042_device::pcf_dl_w(offs_t, u16 data, u16 mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_pcf_dl);
|
||||
logerror("pcf dl = %04x\n", m_pcf_dl);
|
||||
}
|
||||
|
||||
u32 sh7042_device::pcf_e_r()
|
||||
{
|
||||
return m_pcf_e;
|
||||
}
|
||||
|
||||
void sh7042_device::pcf_e_w(offs_t, u32 data, u32 mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_pcf_e);
|
||||
logerror("pcf e = %08x\n", m_pcf_e);
|
||||
}
|
||||
|
||||
u16 sh7042_device::pcf_if_r()
|
||||
{
|
||||
return m_pcf_if;
|
||||
}
|
||||
|
||||
void sh7042_device::pcf_if_w(offs_t, u16 data, u16 mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_pcf_if);
|
||||
logerror("pcf if = %04x\n", m_pcf_if);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Olivier Galibert
|
||||
|
||||
// SH7042, sh2 variant
|
||||
// SH704x, sh2 variant
|
||||
|
||||
#ifndef MAME_CPU_SH_SH7042_H
|
||||
#define MAME_CPU_SH_SH7042_H
|
||||
@ -9,6 +9,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "sh2.h"
|
||||
#include "sh_intc.h"
|
||||
#include "sh_adc.h"
|
||||
#include "sh_cmt.h"
|
||||
#include "sh_port.h"
|
||||
|
||||
class sh7042_device : public sh2_device
|
||||
{
|
||||
@ -19,8 +23,30 @@ public:
|
||||
template<int Sci> void sci_rx_w(int state) { do_sci_w(Sci, state); }
|
||||
template<int Sci> auto write_sci_tx() { return m_sci_tx[Sci].bind(); }
|
||||
|
||||
auto read_porta() { return m_read_port32 [0].bind(); }
|
||||
auto write_porta() { return m_write_port32[0].bind(); }
|
||||
auto read_portb() { return m_read_port16 [0].bind(); }
|
||||
auto write_portb() { return m_write_port16[0].bind(); }
|
||||
auto read_portc() { return m_read_port16 [1].bind(); }
|
||||
auto write_portc() { return m_write_port16[1].bind(); }
|
||||
auto read_portd() { return m_read_port32 [1].bind(); }
|
||||
auto write_portd() { return m_write_port32[1].bind(); }
|
||||
auto read_porte() { return m_read_port16 [2].bind(); }
|
||||
auto write_porte() { return m_write_port16[2].bind(); }
|
||||
auto read_portf() { return m_read_port16 [3].bind(); }
|
||||
|
||||
void internal_update();
|
||||
u16 do_read_adc(int port) { return m_read_adc[port](); }
|
||||
u16 do_read_port16(int port) { return m_read_port16[port](); }
|
||||
void do_write_port16(int port, u16 data, u16 ddr) { m_write_port16[port](0, data, ddr); }
|
||||
u32 do_read_port32(int port) { return m_read_port32[port](); }
|
||||
void do_write_port32(int port, u32 data, u32 ddr) { m_write_port32[port](0, data, ddr); }
|
||||
|
||||
u64 current_cycles() { return machine().time().as_ticks(clock()); }
|
||||
|
||||
protected:
|
||||
const char *m_port16_names;
|
||||
const char *m_port32_names;
|
||||
enum {
|
||||
CSR_ADF = 0x80,
|
||||
CSR_ADIE = 0x40,
|
||||
@ -42,25 +68,68 @@ protected:
|
||||
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
|
||||
private:
|
||||
required_device<sh_intc_device> m_intc;
|
||||
required_device<sh_adc_device> m_adc;
|
||||
required_device<sh_cmt_device> m_cmt;
|
||||
required_device<sh_port32_device> m_porta;
|
||||
required_device<sh_port16_device> m_portb;
|
||||
required_device<sh_port16_device> m_portc;
|
||||
required_device<sh_port32_device> m_portd;
|
||||
required_device<sh_port16_device> m_porte;
|
||||
required_device<sh_port16_device> m_portf;
|
||||
|
||||
devcb_read16::array<8> m_read_adc;
|
||||
devcb_write_line::array<2> m_sci_tx;
|
||||
devcb_read16::array<4> m_read_port16;
|
||||
devcb_write16::array<4> m_write_port16;
|
||||
devcb_read32::array<2> m_read_port32;
|
||||
devcb_write32::array<2> m_write_port32;
|
||||
|
||||
emu_timer *m_event_timer;
|
||||
|
||||
u16 m_pcf_ah;
|
||||
u32 m_pcf_al;
|
||||
u32 m_pcf_b;
|
||||
u16 m_pcf_c;
|
||||
u32 m_pcf_dh;
|
||||
u16 m_pcf_dl;
|
||||
u32 m_pcf_e;
|
||||
u16 m_pcf_if;
|
||||
|
||||
void map(address_map &map);
|
||||
|
||||
// ADC section
|
||||
uint16_t m_addr[8];
|
||||
uint8_t m_adcsr, m_adcr;
|
||||
|
||||
u16 adc_default(int adc);
|
||||
u16 addr_r(offs_t offset);
|
||||
u8 adcsr_r();
|
||||
u8 adcr_r();
|
||||
void adcsr_w(u8 data);
|
||||
void adcr_w(u8 data);
|
||||
u16 port16_default_r(int port);
|
||||
void port16_default_w(int port, u16 data);
|
||||
u32 port32_default_r(int port);
|
||||
void port32_default_w(int port, u32 data);
|
||||
|
||||
void add_event(u64 &event_time, u64 new_event);
|
||||
void recompute_timer(u64 event_time);
|
||||
TIMER_CALLBACK_MEMBER(event_timer_tick);
|
||||
void internal_update(u64 current_time);
|
||||
|
||||
void do_sci_w(int sci, int state);
|
||||
|
||||
u16 pcf_ah_r();
|
||||
void pcf_ah_w(offs_t, u16 data, u16 mem_mask);
|
||||
u32 pcf_al_r();
|
||||
void pcf_al_w(offs_t, u32 data, u32 mem_mask);
|
||||
u32 pcf_b_r();
|
||||
void pcf_b_w(offs_t, u32 data, u32 mem_mask);
|
||||
u16 pcf_c_r();
|
||||
void pcf_c_w(offs_t, u16 data, u16 mem_mask);
|
||||
u32 pcf_dh_r();
|
||||
void pcf_dh_w(offs_t, u32 data, u32 mem_mask);
|
||||
u16 pcf_dl_r();
|
||||
void pcf_dl_w(offs_t, u16 data, u16 mem_mask);
|
||||
u32 pcf_e_r();
|
||||
void pcf_e_w(offs_t, u32 data, u32 mem_mask);
|
||||
u16 pcf_if_r();
|
||||
void pcf_if_w(offs_t, u16 data, u16 mem_mask);
|
||||
};
|
||||
|
||||
class sh7043_device : public sh7042_device
|
||||
|
315
src/devices/cpu/sh/sh_adc.cpp
Normal file
315
src/devices/cpu/sh/sh_adc.cpp
Normal file
@ -0,0 +1,315 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Olivier Galibert
|
||||
|
||||
#include "emu.h"
|
||||
#include "sh_adc.h"
|
||||
#include "sh7042.h"
|
||||
#include "sh_intc.h"
|
||||
|
||||
// Verbosity level
|
||||
// 0 = no messages
|
||||
// 1 = everything
|
||||
static constexpr int V = 0;
|
||||
|
||||
DEFINE_DEVICE_TYPE(SH_ADC, sh_adc_device, "sh_adc", "SH2/704x ADC")
|
||||
|
||||
sh_adc_device::sh_adc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
|
||||
device_t(mconfig, SH_ADC, tag, owner, clock),
|
||||
m_cpu(*this, finder_base::DUMMY_TAG),
|
||||
m_intc(*this, finder_base::DUMMY_TAG),
|
||||
m_intc_vector(0), m_adcsr(0), m_adcr(0), m_register_mask(0), m_trigger(0), m_start_mode(0), m_start_channel(0),
|
||||
m_end_channel(0), m_start_count(0), m_mode(0), m_channel(0), m_count(0), m_analog_powered(false), m_adtrg(false), m_next_event(0)
|
||||
{
|
||||
m_suspend_on_interrupt = true;
|
||||
m_register_mask = 7;
|
||||
m_analog_power_control = false;
|
||||
}
|
||||
|
||||
u16 sh_adc_device::addr_r(offs_t offset)
|
||||
{
|
||||
if(V>=1) logerror("addr_r %d %03x\n", offset, m_addr[offset]);
|
||||
return m_addr[offset];
|
||||
}
|
||||
|
||||
u8 sh_adc_device::adcsr_r()
|
||||
{
|
||||
if(V>=1) logerror("adcsr_r %02x\n", m_adcsr);
|
||||
return m_adcsr;
|
||||
}
|
||||
|
||||
u8 sh_adc_device::adcr_r()
|
||||
{
|
||||
if(V>=1) logerror("adcr_r %02x\n", m_adcr);
|
||||
return m_adcr;
|
||||
}
|
||||
|
||||
void sh_adc_device::adcsr_w(u8 data)
|
||||
{
|
||||
if(V>=1) logerror("adcsr_w %02x\n", data);
|
||||
u8 prev = m_adcsr;
|
||||
m_adcsr = (data & 0x7f) | (m_adcsr & data & F_ADF);
|
||||
mode_update();
|
||||
if((prev & F_ADF) && !(m_adcsr & F_ADF)) {
|
||||
if(m_mode & HALTED) {
|
||||
m_mode &= ~HALTED;
|
||||
if(!(m_adcsr & F_ADST)) {
|
||||
sampling();
|
||||
conversion_wait(false, false);
|
||||
} else
|
||||
done();
|
||||
}
|
||||
}
|
||||
|
||||
if(!(prev & F_ADST) && (m_adcsr & F_ADST))
|
||||
start_conversion();
|
||||
}
|
||||
|
||||
void sh_adc_device::adcr_w(u8 data)
|
||||
{
|
||||
if(V>=1) logerror("adcr_w %02x\n", data);
|
||||
m_adcr = data;
|
||||
mode_update();
|
||||
}
|
||||
|
||||
void sh_adc_device::adtrg_w(int state)
|
||||
{
|
||||
if(state != m_adtrg) {
|
||||
m_adtrg = state;
|
||||
if(!m_adtrg && (m_trigger & T_EXT) && !(m_adcsr & F_ADST)) {
|
||||
m_adcsr |= F_ADST;
|
||||
start_conversion();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sh_adc_device::set_suspend(bool suspend)
|
||||
{
|
||||
}
|
||||
|
||||
void sh_adc_device::device_start()
|
||||
{
|
||||
save_item(NAME(m_addr));
|
||||
save_item(NAME(m_buf));
|
||||
save_item(NAME(m_adcsr));
|
||||
save_item(NAME(m_adcr));
|
||||
save_item(NAME(m_trigger));
|
||||
save_item(NAME(m_start_mode));
|
||||
save_item(NAME(m_start_channel));
|
||||
save_item(NAME(m_end_channel));
|
||||
save_item(NAME(m_start_count));
|
||||
save_item(NAME(m_suspend_on_interrupt));
|
||||
save_item(NAME(m_analog_power_control));
|
||||
save_item(NAME(m_mode));
|
||||
save_item(NAME(m_channel));
|
||||
save_item(NAME(m_count));
|
||||
save_item(NAME(m_analog_powered));
|
||||
save_item(NAME(m_next_event));
|
||||
save_item(NAME(m_adtrg));
|
||||
}
|
||||
|
||||
void sh_adc_device::device_reset()
|
||||
{
|
||||
memset(m_addr, 0, sizeof(m_addr));
|
||||
memset(m_buf, 0, sizeof(m_buf));
|
||||
m_adcsr = m_adcr = 0;
|
||||
m_trigger = T_SOFT;
|
||||
m_start_mode = IDLE;
|
||||
m_start_channel = m_end_channel = 0;
|
||||
m_start_count = 1;
|
||||
m_mode = IDLE;
|
||||
m_channel = 0;
|
||||
m_count = 0;
|
||||
m_next_event = 0;
|
||||
mode_update();
|
||||
m_analog_powered = !m_analog_power_control;
|
||||
m_adtrg = true;
|
||||
}
|
||||
|
||||
void sh_adc_device::done()
|
||||
{
|
||||
m_mode = IDLE;
|
||||
m_adcsr &= ~F_ADST;
|
||||
if(m_analog_power_control)
|
||||
m_analog_powered = false;
|
||||
}
|
||||
|
||||
u64 sh_adc_device::internal_update(u64 current_time)
|
||||
{
|
||||
if(m_next_event && m_next_event <= current_time) {
|
||||
m_next_event = 0;
|
||||
timeout(current_time);
|
||||
}
|
||||
return m_next_event;
|
||||
}
|
||||
|
||||
void sh_adc_device::conversion_wait(bool first, bool poweron, u64 current_time)
|
||||
{
|
||||
if(current_time)
|
||||
m_next_event = current_time + conversion_time(first, poweron);
|
||||
else {
|
||||
m_next_event = m_cpu->total_cycles() + conversion_time(first, poweron);
|
||||
m_cpu->internal_update();
|
||||
}
|
||||
}
|
||||
|
||||
void sh_adc_device::buffer_value(int port, int buffer)
|
||||
{
|
||||
m_buf[buffer] = m_cpu->do_read_adc(port);
|
||||
if(V>=1) logerror("adc buffer %d -> %d:%03x\n", port, buffer, m_buf[buffer]);
|
||||
}
|
||||
|
||||
void sh_adc_device::commit_value(int reg, int buffer)
|
||||
{
|
||||
reg &= m_register_mask;
|
||||
if(V>=1) logerror("adc commit %d -> %d:%03x\n", buffer, reg, m_buf[buffer]);
|
||||
m_addr[reg] = m_buf[buffer];
|
||||
}
|
||||
|
||||
void sh_adc_device::sampling()
|
||||
{
|
||||
if(m_mode & COUNTED)
|
||||
m_channel = get_channel_index(m_start_count - m_count);
|
||||
if(m_mode & DUAL) {
|
||||
buffer_value(m_channel, 0);
|
||||
buffer_value(m_channel+1, 1);
|
||||
} else
|
||||
buffer_value(m_channel);
|
||||
}
|
||||
|
||||
void sh_adc_device::start_conversion()
|
||||
{
|
||||
m_mode = m_start_mode;
|
||||
m_channel = m_start_channel;
|
||||
m_count = m_start_count;
|
||||
sampling();
|
||||
conversion_wait(true, !m_analog_powered);
|
||||
m_analog_powered = true;
|
||||
}
|
||||
|
||||
void sh_adc_device::timeout(u64 current_time)
|
||||
{
|
||||
if(m_mode & BUFFER) {
|
||||
do_buffering((m_mode & DUAL) && (m_channel & 1));
|
||||
if((m_mode & DUAL) && !(m_channel & 1)) {
|
||||
m_channel++;
|
||||
conversion_wait(false, false, current_time);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if(m_mode & DUAL) {
|
||||
if(m_channel & 1)
|
||||
commit_value(m_channel, 1);
|
||||
else {
|
||||
commit_value(m_channel, 0);
|
||||
m_channel++;
|
||||
conversion_wait(false, false, current_time);
|
||||
return;
|
||||
}
|
||||
} else
|
||||
commit_value(m_channel);
|
||||
}
|
||||
|
||||
if(m_mode & ROTATE) {
|
||||
if(m_channel != m_end_channel) {
|
||||
m_channel++;
|
||||
sampling();
|
||||
conversion_wait(false, false, current_time);
|
||||
return;
|
||||
}
|
||||
m_channel = m_start_channel;
|
||||
}
|
||||
|
||||
if(m_mode & COUNTED) {
|
||||
m_count--;
|
||||
if(m_count) {
|
||||
sampling();
|
||||
conversion_wait(false, false, current_time);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_adcsr |= F_ADF;
|
||||
if(m_adcsr & F_ADIE)
|
||||
m_intc->internal_interrupt(m_intc_vector);
|
||||
|
||||
if(m_mode & REPEAT) {
|
||||
if(m_suspend_on_interrupt && (m_adcsr & F_ADIE)) {
|
||||
m_mode |= HALTED;
|
||||
return;
|
||||
}
|
||||
m_channel = m_start_channel;
|
||||
m_count = m_start_count;
|
||||
sampling();
|
||||
conversion_wait(false, false, current_time);
|
||||
return;
|
||||
}
|
||||
|
||||
done();
|
||||
}
|
||||
|
||||
int sh_adc_device::conversion_time(bool first, bool poweron)
|
||||
{
|
||||
int tm = m_adcsr & 0x10 ? 44 : 24;
|
||||
if(first)
|
||||
tm += m_adcsr & 0x10 ? 20 : 10;
|
||||
if(poweron)
|
||||
tm += 200;
|
||||
return tm;
|
||||
}
|
||||
|
||||
void sh_adc_device::mode_update()
|
||||
{
|
||||
m_trigger = 1 << ((m_adcr >> 4) & 3);
|
||||
m_analog_power_control = !(m_adcr & 0x40);
|
||||
|
||||
m_mode = ACTIVE | (m_adcr & 0x08 ? REPEAT : 0);
|
||||
|
||||
if(m_adcsr & 0x03) {
|
||||
m_mode |= BUFFER;
|
||||
|
||||
}
|
||||
|
||||
if(m_adcsr & 0x08) {
|
||||
m_mode |= ROTATE;
|
||||
m_start_channel = 0;
|
||||
if(m_adcr & 0x04) {
|
||||
m_mode |= DUAL;
|
||||
m_end_channel = (m_adcsr & 6)+1;
|
||||
} else
|
||||
m_end_channel = m_adcsr & 7;
|
||||
} else
|
||||
m_start_channel = m_end_channel = m_adcsr & 7;
|
||||
|
||||
}
|
||||
|
||||
void sh_adc_device::do_buffering(int buffer)
|
||||
{
|
||||
if((m_mode & COUNTED) && m_channel >= 2) {
|
||||
commit_value(m_channel, buffer);
|
||||
return;
|
||||
}
|
||||
switch(m_adcsr & 3) {
|
||||
case 0:
|
||||
commit_value(m_channel, buffer);
|
||||
break;
|
||||
case 1:
|
||||
m_addr[1] = m_addr[0];
|
||||
commit_value(0, buffer);
|
||||
break;
|
||||
case 2:
|
||||
m_addr[2+buffer] = m_addr[buffer];
|
||||
commit_value(buffer, buffer);
|
||||
break;
|
||||
case 3:
|
||||
m_addr[3] = m_addr[2];
|
||||
m_addr[2] = m_addr[1];
|
||||
m_addr[1] = m_addr[0];
|
||||
commit_value(0, buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int sh_adc_device::get_channel_index(int count)
|
||||
{
|
||||
abort();
|
||||
}
|
100
src/devices/cpu/sh/sh_adc.h
Normal file
100
src/devices/cpu/sh/sh_adc.h
Normal file
@ -0,0 +1,100 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Olivier Galibert
|
||||
/***************************************************************************
|
||||
|
||||
sh_adc.h
|
||||
|
||||
SH Analog to Digital Converter subsystem
|
||||
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MAME_CPU_SH_SH_ADC_H
|
||||
#define MAME_CPU_SH_SH_ADC_H
|
||||
|
||||
#pragma once
|
||||
|
||||
class sh7042_device;
|
||||
class sh_intc_device;
|
||||
|
||||
class sh_adc_device : public device_t {
|
||||
public:
|
||||
sh_adc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
|
||||
|
||||
template<typename T, typename U> sh_adc_device(const machine_config &mconfig, const char *tag, device_t *owner,
|
||||
T &&cpu, U &&intc, int vect) :
|
||||
sh_adc_device(mconfig, tag, owner)
|
||||
{
|
||||
m_cpu.set_tag(std::forward<T>(cpu));
|
||||
m_intc.set_tag(std::forward<U>(intc));
|
||||
m_intc_vector = vect;
|
||||
}
|
||||
|
||||
u16 addr_r(offs_t offset);
|
||||
u8 adcsr_r();
|
||||
u8 adcr_r();
|
||||
void adcsr_w(u8 data);
|
||||
void adcr_w(u8 data);
|
||||
void adtrg_w(int state);
|
||||
|
||||
void set_suspend(bool suspend);
|
||||
u64 internal_update(u64 current_time);
|
||||
|
||||
protected:
|
||||
required_device<sh7042_device> m_cpu;
|
||||
required_device<sh_intc_device> m_intc;
|
||||
int m_intc_vector;
|
||||
|
||||
enum {
|
||||
T_SOFT = 1<<0,
|
||||
T_TPU = 1<<1,
|
||||
T_TIMER = 1<<2,
|
||||
T_EXT = 1<<3
|
||||
};
|
||||
|
||||
enum {
|
||||
F_ADF = 0x80,
|
||||
F_ADIE = 0x40,
|
||||
F_ADST = 0x20
|
||||
};
|
||||
|
||||
enum {
|
||||
IDLE = 0,
|
||||
ACTIVE = 1,
|
||||
HALTED = 2,
|
||||
REPEAT = 4,
|
||||
ROTATE = 8,
|
||||
DUAL = 16,
|
||||
BUFFER = 32,
|
||||
COUNTED = 64
|
||||
};
|
||||
|
||||
u16 m_addr[8], m_buf[2];
|
||||
u8 m_adcsr, m_adcr;
|
||||
int m_register_mask;
|
||||
int m_trigger, m_start_mode, m_start_channel, m_end_channel, m_start_count;
|
||||
bool m_suspend_on_interrupt, m_analog_power_control;
|
||||
int m_mode, m_channel, m_count;
|
||||
bool m_analog_powered, m_adtrg;
|
||||
u64 m_next_event;
|
||||
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
void sampling();
|
||||
void start_conversion();
|
||||
void conversion_wait(bool first, bool poweron, u64 current_time = 0);
|
||||
void buffer_value(int port, int buffer = 0);
|
||||
void commit_value(int reg, int buffer = 0);
|
||||
void timeout(u64 current_time);
|
||||
void done();
|
||||
|
||||
int conversion_time(bool first, bool poweron);
|
||||
void mode_update();
|
||||
void do_buffering(int buffer);
|
||||
int get_channel_index(int count);
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SH_ADC, sh_adc_device)
|
||||
|
||||
#endif // MAME_CPU_SH_SH_ADC_H
|
197
src/devices/cpu/sh/sh_cmt.cpp
Normal file
197
src/devices/cpu/sh/sh_cmt.cpp
Normal file
@ -0,0 +1,197 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Olivier Galibert
|
||||
/***************************************************************************
|
||||
|
||||
sh_cmt.h
|
||||
|
||||
SH Compare/Match timer subsystem
|
||||
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "sh7042.h"
|
||||
#include "sh_intc.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE(SH_CMT, sh_cmt_device, "sh_cmt", "SH2/704x CMT")
|
||||
|
||||
sh_cmt_device::sh_cmt_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
|
||||
device_t(mconfig, SH_CMT, tag, owner, clock),
|
||||
m_cpu(*this, finder_base::DUMMY_TAG),
|
||||
m_intc(*this, finder_base::DUMMY_TAG),
|
||||
m_intc_vector{0, 0},
|
||||
m_str(0),
|
||||
m_csr{ 0, 0 },
|
||||
m_cnt{ 0, 0 },
|
||||
m_cor{ 0xffff, 0xffff }
|
||||
{
|
||||
}
|
||||
|
||||
void sh_cmt_device::device_start()
|
||||
{
|
||||
}
|
||||
|
||||
void sh_cmt_device::device_reset()
|
||||
{
|
||||
}
|
||||
|
||||
u64 sh_cmt_device::internal_update(u64 current_time)
|
||||
{
|
||||
u64 next = 0;
|
||||
for(int i = 0; i != 2; i++) {
|
||||
if(m_next_event[i] && current_time >= m_next_event[i]) {
|
||||
m_csr[i] |= 0x80;
|
||||
if(BIT(m_csr[i], 6))
|
||||
m_intc->internal_interrupt(m_intc_vector[i]);
|
||||
cnt_update(i, current_time);
|
||||
}
|
||||
if(!next || (m_next_event[i] && m_next_event[i] < next))
|
||||
next = m_next_event[i];
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
|
||||
u16 sh_cmt_device::cmstr_r()
|
||||
{
|
||||
return m_str;
|
||||
}
|
||||
|
||||
u16 sh_cmt_device::cmcsr0_r()
|
||||
{
|
||||
return m_csr[0];
|
||||
}
|
||||
|
||||
u16 sh_cmt_device::cmcnt0_r()
|
||||
{
|
||||
cnt_update(0, m_cpu->current_cycles());
|
||||
return m_cnt[0];
|
||||
}
|
||||
|
||||
u16 sh_cmt_device::cmcor0_r()
|
||||
{
|
||||
return m_cor[0];
|
||||
}
|
||||
|
||||
u16 sh_cmt_device::cmcsr1_r()
|
||||
{
|
||||
return m_csr[1];
|
||||
}
|
||||
|
||||
u16 sh_cmt_device::cmcnt1_r()
|
||||
{
|
||||
cnt_update(1, m_cpu->current_cycles());
|
||||
return m_cnt[1];
|
||||
}
|
||||
|
||||
u16 sh_cmt_device::cmcor1_r()
|
||||
{
|
||||
return m_cor[1];
|
||||
}
|
||||
|
||||
void sh_cmt_device::cmcsr0_w(offs_t, u16 data, u16 mem_mask)
|
||||
{
|
||||
csr_w(0, data, mem_mask);
|
||||
}
|
||||
|
||||
void sh_cmt_device::cmcsr1_w(offs_t, u16 data, u16 mem_mask)
|
||||
{
|
||||
csr_w(1, data, mem_mask);
|
||||
}
|
||||
|
||||
void sh_cmt_device::cmcnt0_w(offs_t, u16 data, u16 mem_mask)
|
||||
{
|
||||
cnt_w(0, data, mem_mask);
|
||||
}
|
||||
|
||||
void sh_cmt_device::cmcnt1_w(offs_t, u16 data, u16 mem_mask)
|
||||
{
|
||||
cnt_w(1, data, mem_mask);
|
||||
}
|
||||
|
||||
void sh_cmt_device::cmcor0_w(offs_t, u16 data, u16 mem_mask)
|
||||
{
|
||||
cor_w(0, data, mem_mask);
|
||||
}
|
||||
|
||||
void sh_cmt_device::cmcor1_w(offs_t, u16 data, u16 mem_mask)
|
||||
{
|
||||
cor_w(1, data, mem_mask);
|
||||
}
|
||||
|
||||
void sh_cmt_device::cmstr_w(offs_t, u16 data, u16 mem_mask)
|
||||
{
|
||||
cnt_update(0, m_cpu->current_cycles());
|
||||
cnt_update(1, m_cpu->current_cycles());
|
||||
u16 old = m_str;
|
||||
COMBINE_DATA(&m_str);
|
||||
logerror("active %c %c\n", m_str & 1 ? '0' : '-', m_str & 2 ? '1' : '-');
|
||||
for(int i=0; i != 2; i++)
|
||||
if(!BIT(old, i) && BIT(m_str, i))
|
||||
clock_start(i);
|
||||
else if(!BIT(m_str, i))
|
||||
m_next_event[i] = 0;
|
||||
m_cpu->internal_update();
|
||||
}
|
||||
|
||||
void sh_cmt_device::csr_w(int reg, u16 data, u16 mem_mask)
|
||||
{
|
||||
cnt_update(reg, m_cpu->current_cycles());
|
||||
u16 old = m_csr[reg];
|
||||
COMBINE_DATA(&m_csr[reg]);
|
||||
if(!(old & 0x80))
|
||||
m_csr[reg] &= ~0x80;
|
||||
if((old ^ m_csr[reg]) & 0x7f)
|
||||
logerror("csr_w %d f=%d ie=%d div=%d\n", reg, BIT(m_csr[reg], 7), BIT(m_csr[reg], 6), 8 << (2*BIT(m_csr[reg], 0, 2)));
|
||||
}
|
||||
|
||||
void sh_cmt_device::cnt_w(int reg, u16 data, u16 mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_cnt[reg]);
|
||||
logerror("cnt_w %d, %04x\n", reg, m_cnt[reg]);
|
||||
if((m_str >> reg) & 1) {
|
||||
compute_next_event(reg);
|
||||
m_cpu->internal_update();
|
||||
}
|
||||
}
|
||||
|
||||
void sh_cmt_device::cor_w(int reg, u16 data, u16 mem_mask)
|
||||
{
|
||||
cnt_update(reg, m_cpu->current_cycles());
|
||||
COMBINE_DATA(&m_cor[reg]);
|
||||
logerror("cor_w %d, %04x\n", reg, m_cor[reg]);
|
||||
if((m_str >> reg) & 1) {
|
||||
compute_next_event(reg);
|
||||
m_cpu->internal_update();
|
||||
}
|
||||
}
|
||||
|
||||
void sh_cmt_device::clock_start(int clk)
|
||||
{
|
||||
logerror("start clock %d %dHz\n", clk, (m_cpu->clock() >> (3 + 2*BIT(m_csr[clk], 0, 2))) / (m_cor[clk] + 1));
|
||||
compute_next_event(clk);
|
||||
}
|
||||
|
||||
void sh_cmt_device::compute_next_event(int clk)
|
||||
{
|
||||
u64 step1 = 1 << (3 + 2*BIT(m_csr[clk], 0, 2));
|
||||
u64 time = m_cpu->current_cycles();
|
||||
if(time & (step1 - 1))
|
||||
time = (time | (step1 - 1)) + 1;
|
||||
s32 counts = m_cor[clk] + 1 - m_cnt[clk];
|
||||
if(counts < 0)
|
||||
counts += 0x10000;
|
||||
time += step1 * counts;
|
||||
m_next_event[clk] = time;
|
||||
}
|
||||
|
||||
void sh_cmt_device::cnt_update(int clk, u64 current_time)
|
||||
{
|
||||
if(!((m_str >> clk) & 1))
|
||||
return;
|
||||
u64 step = (m_cor[clk] + 1) << (3 + 2*BIT(m_csr[clk], 0, 2));
|
||||
while(current_time >= m_next_event[clk])
|
||||
m_next_event[clk] += step;
|
||||
u64 delta = m_next_event[clk] - current_time;
|
||||
m_cnt[clk] = m_cor[clk] - ((delta - 1) >> (3 + 2*BIT(m_csr[clk], 0, 2)));
|
||||
}
|
75
src/devices/cpu/sh/sh_cmt.h
Normal file
75
src/devices/cpu/sh/sh_cmt.h
Normal file
@ -0,0 +1,75 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Olivier Galibert
|
||||
/***************************************************************************
|
||||
|
||||
sh_cmt.h
|
||||
|
||||
SH Compare/Match timer subsystem
|
||||
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MAME_CPU_SH_SH_CMT_H
|
||||
#define MAME_CPU_SH_SH_CMT_H
|
||||
|
||||
#pragma once
|
||||
|
||||
class sh7042_device;
|
||||
class sh_intc_device;
|
||||
|
||||
class sh_cmt_device : public device_t {
|
||||
public:
|
||||
sh_cmt_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
|
||||
|
||||
template<typename T, typename U> sh_cmt_device(const machine_config &mconfig, const char *tag, device_t *owner,
|
||||
T &&cpu, U &&intc, int vect0, int vect1) :
|
||||
sh_cmt_device(mconfig, tag, owner)
|
||||
{
|
||||
m_cpu.set_tag(std::forward<T>(cpu));
|
||||
m_intc.set_tag(std::forward<U>(intc));
|
||||
m_intc_vector[0] = vect0;
|
||||
m_intc_vector[1] = vect1;
|
||||
}
|
||||
|
||||
u64 internal_update(u64 current_time);
|
||||
|
||||
u16 cmstr_r();
|
||||
void cmstr_w(offs_t, u16 data, u16 mem_mask);
|
||||
u16 cmcsr0_r();
|
||||
void cmcsr0_w(offs_t, u16 data, u16 mem_mask);
|
||||
u16 cmcnt0_r();
|
||||
void cmcnt0_w(offs_t, u16 data, u16 mem_mask);
|
||||
u16 cmcor0_r();
|
||||
void cmcor0_w(offs_t, u16 data, u16 mem_mask);
|
||||
u16 cmcsr1_r();
|
||||
void cmcsr1_w(offs_t, u16 data, u16 mem_mask);
|
||||
u16 cmcnt1_r();
|
||||
void cmcnt1_w(offs_t, u16 data, u16 mem_mask);
|
||||
u16 cmcor1_r();
|
||||
void cmcor1_w(offs_t, u16 data, u16 mem_mask);
|
||||
|
||||
protected:
|
||||
required_device<sh7042_device> m_cpu;
|
||||
required_device<sh_intc_device> m_intc;
|
||||
std::array<u64, 2> m_next_event;
|
||||
std::array<int, 2> m_intc_vector;
|
||||
u16 m_str;
|
||||
std::array<u16, 2> m_csr;
|
||||
std::array<u16, 2> m_cnt;
|
||||
std::array<u16, 2> m_cor;
|
||||
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
void csr_w(int reg, u16 data, u16 mem_mask);
|
||||
void cnt_w(int reg, u16 data, u16 mem_mask);
|
||||
void cor_w(int reg, u16 data, u16 mem_mask);
|
||||
|
||||
void clock_start(int clk);
|
||||
void compute_next_event(int clk);
|
||||
void cnt_update(int clk, u64 current_time);
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SH_CMT, sh_cmt_device)
|
||||
|
||||
#endif // MAME_CPU_SH_SH_CMT_H
|
75
src/devices/cpu/sh/sh_intc.cpp
Normal file
75
src/devices/cpu/sh/sh_intc.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Olivier Galibert
|
||||
/***************************************************************************
|
||||
|
||||
sh_intc.cpp
|
||||
|
||||
SH interrupt controllers family
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "sh_intc.h"
|
||||
|
||||
#include "sh7042.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE(SH_INTC, sh_intc_device, "sh_intc", "SH interrupt controller")
|
||||
|
||||
sh_intc_device::sh_intc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
|
||||
device_t(mconfig, SH_INTC, tag, owner, clock),
|
||||
m_cpu(*this, finder_base::DUMMY_TAG)
|
||||
{
|
||||
}
|
||||
|
||||
void sh_intc_device::device_start()
|
||||
{
|
||||
}
|
||||
|
||||
void sh_intc_device::device_reset()
|
||||
{
|
||||
}
|
||||
|
||||
int sh_intc_device::interrupt_taken(int vector)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sh_intc_device::internal_interrupt(int vector)
|
||||
{
|
||||
logerror("Internal interrupt %d\n", vector);
|
||||
}
|
||||
|
||||
void sh_intc_device::set_input(int inputnum, int state)
|
||||
{
|
||||
}
|
||||
|
||||
u16 sh_intc_device::icr_r()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sh_intc_device::icr_w(offs_t, u16 data, u16 mem_mask)
|
||||
{
|
||||
logerror("icr_w %04x @ %04x\n", data, mem_mask);
|
||||
}
|
||||
|
||||
u16 sh_intc_device::isr_r()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sh_intc_device::isr_w(offs_t, u16 data, u16 mem_mask)
|
||||
{
|
||||
logerror("isr_w %04x @ %04x\n", data, mem_mask);
|
||||
}
|
||||
|
||||
u16 sh_intc_device::ipr_r(offs_t offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sh_intc_device::ipr_w(offs_t offset, u16 data, u16 mem_mask)
|
||||
{
|
||||
logerror("ipr_w %x, %04x @ %04x\n", offset, data, mem_mask);
|
||||
}
|
||||
|
47
src/devices/cpu/sh/sh_intc.h
Normal file
47
src/devices/cpu/sh/sh_intc.h
Normal file
@ -0,0 +1,47 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Olivier Galibert
|
||||
/***************************************************************************
|
||||
|
||||
sh_intc.h
|
||||
|
||||
SH interrupt controllers family
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MAME_CPU_SH_SH_INTC_H
|
||||
#define MAME_CPU_SH_SH_INTC_H
|
||||
|
||||
#pragma once
|
||||
|
||||
class sh7042_device;
|
||||
|
||||
class sh_intc_device : public device_t {
|
||||
public:
|
||||
sh_intc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
|
||||
template<typename T> sh_intc_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&cpu) :
|
||||
sh_intc_device(mconfig, tag, owner)
|
||||
{
|
||||
m_cpu.set_tag(std::forward<T>(cpu));
|
||||
}
|
||||
|
||||
int interrupt_taken(int vector);
|
||||
void internal_interrupt(int vector);
|
||||
void set_input(int inputnum, int state);
|
||||
|
||||
u16 icr_r();
|
||||
void icr_w(offs_t, u16 data, u16 mem_mask);
|
||||
u16 isr_r();
|
||||
void isr_w(offs_t, u16 data, u16 mem_mask);
|
||||
u16 ipr_r(offs_t offset);
|
||||
void ipr_w(offs_t offset, u16 data, u16 mem_mask);
|
||||
|
||||
protected:
|
||||
required_device<sh7042_device> m_cpu;
|
||||
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SH_INTC, sh_intc_device)
|
||||
|
||||
#endif // MAME_CPU_SH_SH_INTC_H
|
109
src/devices/cpu/sh/sh_port.cpp
Normal file
109
src/devices/cpu/sh/sh_port.cpp
Normal file
@ -0,0 +1,109 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Olivier Galibert
|
||||
/***************************************************************************
|
||||
|
||||
sh_port.h
|
||||
|
||||
SH i/o ports
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "sh_intc.h"
|
||||
|
||||
#include "sh7042.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE(SH_PORT16, sh_port16_device, "sh_port16", "SH 16-bits port")
|
||||
DEFINE_DEVICE_TYPE(SH_PORT32, sh_port32_device, "sh_port32", "SH 32-bits port")
|
||||
|
||||
sh_port16_device::sh_port16_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
|
||||
device_t(mconfig, SH_PORT16, tag, owner, clock),
|
||||
m_cpu(*this, finder_base::DUMMY_TAG)
|
||||
{
|
||||
}
|
||||
|
||||
void sh_port16_device::device_start()
|
||||
{
|
||||
m_io = m_default_io;
|
||||
save_item(NAME(m_dr));
|
||||
save_item(NAME(m_io));
|
||||
}
|
||||
|
||||
void sh_port16_device::device_reset()
|
||||
{
|
||||
}
|
||||
|
||||
u16 sh_port16_device::dr_r()
|
||||
{
|
||||
if(~m_io & ~m_mask)
|
||||
return (m_dr & m_io) | (m_cpu->do_read_port16(m_index) & ~m_io);
|
||||
return m_dr;
|
||||
}
|
||||
|
||||
void sh_port16_device::dr_w(offs_t, u16 data, u16 mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_dr);
|
||||
m_dr &= ~m_mask;
|
||||
if(m_io)
|
||||
m_cpu->do_write_port16(m_index, m_dr & m_io, m_io);
|
||||
}
|
||||
|
||||
u16 sh_port16_device::io_r()
|
||||
{
|
||||
return m_io;
|
||||
}
|
||||
|
||||
void sh_port16_device::io_w(offs_t, u16 data, u16 mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_io);
|
||||
m_io &= ~m_mask;
|
||||
if(m_io)
|
||||
m_cpu->do_write_port16(m_index, m_dr & m_io, m_io);
|
||||
}
|
||||
|
||||
|
||||
sh_port32_device::sh_port32_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
|
||||
device_t(mconfig, SH_PORT32, tag, owner, clock),
|
||||
m_cpu(*this, finder_base::DUMMY_TAG)
|
||||
{
|
||||
}
|
||||
|
||||
void sh_port32_device::device_start()
|
||||
{
|
||||
m_io = m_default_io;
|
||||
save_item(NAME(m_dr));
|
||||
save_item(NAME(m_io));
|
||||
}
|
||||
|
||||
void sh_port32_device::device_reset()
|
||||
{
|
||||
}
|
||||
|
||||
u32 sh_port32_device::dr_r()
|
||||
{
|
||||
if(~m_io & ~m_mask)
|
||||
return (m_dr & m_io) | (m_cpu->do_read_port32(m_index) & ~m_io);
|
||||
return m_dr;
|
||||
}
|
||||
|
||||
void sh_port32_device::dr_w(offs_t, u32 data, u32 mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_dr);
|
||||
m_dr &= ~m_mask;
|
||||
if(m_io)
|
||||
m_cpu->do_write_port32(m_index, m_dr & m_io, m_io);
|
||||
}
|
||||
|
||||
u32 sh_port32_device::io_r()
|
||||
{
|
||||
return m_io;
|
||||
}
|
||||
|
||||
void sh_port32_device::io_w(offs_t, u32 data, u32 mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_io);
|
||||
m_io &= ~m_mask;
|
||||
if(m_io)
|
||||
m_cpu->do_write_port32(m_index, m_dr & m_io, m_io);
|
||||
}
|
||||
|
75
src/devices/cpu/sh/sh_port.h
Normal file
75
src/devices/cpu/sh/sh_port.h
Normal file
@ -0,0 +1,75 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Olivier Galibert
|
||||
/***************************************************************************
|
||||
|
||||
sh_port.h
|
||||
|
||||
SH i/o ports
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MAME_CPU_SH_SH_PORT_H
|
||||
#define MAME_CPU_SH_SH_PORT_H
|
||||
|
||||
#pragma once
|
||||
|
||||
class sh7042_device;
|
||||
|
||||
class sh_port16_device : public device_t {
|
||||
public:
|
||||
sh_port16_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
|
||||
template<typename T> sh_port16_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&cpu, int index, u16 default_io, u16 mask) :
|
||||
sh_port16_device(mconfig, tag, owner)
|
||||
{
|
||||
m_index = index;
|
||||
m_default_io = default_io;
|
||||
m_mask = mask;
|
||||
m_cpu.set_tag(std::forward<T>(cpu));
|
||||
}
|
||||
|
||||
u16 dr_r();
|
||||
void dr_w(offs_t, u16 data, u16 mem_mask);
|
||||
u16 io_r();
|
||||
void io_w(offs_t, u16 data, u16 mem_mask);
|
||||
|
||||
protected:
|
||||
required_device<sh7042_device> m_cpu;
|
||||
int m_index;
|
||||
u16 m_default_io, m_mask;
|
||||
u16 m_dr, m_io;
|
||||
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
};
|
||||
|
||||
class sh_port32_device : public device_t {
|
||||
public:
|
||||
sh_port32_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
|
||||
template<typename T> sh_port32_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&cpu, int index, u32 default_io, u32 mask) :
|
||||
sh_port32_device(mconfig, tag, owner)
|
||||
{
|
||||
m_index = index;
|
||||
m_default_io = default_io;
|
||||
m_mask = mask;
|
||||
m_cpu.set_tag(std::forward<T>(cpu));
|
||||
}
|
||||
|
||||
u32 dr_r();
|
||||
void dr_w(offs_t, u32 data, u32 mem_mask);
|
||||
u32 io_r();
|
||||
void io_w(offs_t, u32 data, u32 mem_mask);
|
||||
|
||||
protected:
|
||||
required_device<sh7042_device> m_cpu;
|
||||
int m_index;
|
||||
u32 m_default_io, m_mask;
|
||||
u32 m_dr, m_io;
|
||||
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SH_PORT16, sh_port16_device)
|
||||
DECLARE_DEVICE_TYPE(SH_PORT32, sh_port32_device)
|
||||
|
||||
#endif // MAME_CPU_SH_SH_PORT_H
|
@ -116,7 +116,6 @@ bool xavix_sound_device::is_voice_enabled(int voice)
|
||||
void xavix_sound_device::enable_voice(int voice, bool update_only)
|
||||
{
|
||||
m_stream->update();
|
||||
|
||||
int voicemembase = voice * 0x10;
|
||||
|
||||
uint16_t freq_mode = (m_readregs_cb(voicemembase + 0x1) << 8) | (m_readregs_cb(voicemembase + 0x0)); // sample rate maybe?
|
||||
|
@ -53,25 +53,76 @@ private:
|
||||
required_device<i8251_device> m_sci;
|
||||
required_shared_ptr<u32> m_ram;
|
||||
|
||||
u16 m_pe;
|
||||
|
||||
void map(address_map &map);
|
||||
void swp30_map(address_map &map);
|
||||
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
|
||||
u16 pe_r();
|
||||
void pe_w(u16 data);
|
||||
};
|
||||
|
||||
|
||||
void mu128_state::machine_start()
|
||||
{
|
||||
save_item(NAME(m_pe));
|
||||
m_pe = 0;
|
||||
}
|
||||
|
||||
void mu128_state::machine_reset()
|
||||
{
|
||||
}
|
||||
|
||||
void mu128_state::machine_reset()
|
||||
// Port E:
|
||||
// 0: lcd-r/w
|
||||
// 1: nc
|
||||
// 2: lcd-rs
|
||||
// 3: lcread (secondary functions on lcread edge)
|
||||
// 4: lcd-e
|
||||
// 5: 1mclk
|
||||
// 6: siclk
|
||||
// 7: sws
|
||||
// 8-a: db 0-2, lcdc a-c
|
||||
// b-c: db 3-4, mic/line
|
||||
// d: db 5, swp reset
|
||||
// e: db 6, sireset
|
||||
// f: db 7, breset
|
||||
|
||||
u16 mu128_state::pe_r()
|
||||
{
|
||||
if(BIT(m_pe, 4)) {
|
||||
if(BIT(m_pe, 0)) {
|
||||
if(BIT(m_pe, 2))
|
||||
return m_lcd->data_read() << 8;
|
||||
else
|
||||
return m_lcd->control_read() << 8;
|
||||
} else
|
||||
return 0x0000;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mu128_state::pe_w(u16 data)
|
||||
{
|
||||
u16 prev = m_pe;
|
||||
m_pe = data;
|
||||
if(BIT(m_pe, 4) && !BIT(prev, 4)) {
|
||||
if(!BIT(m_pe, 0)) {
|
||||
if(BIT(m_pe, 2))
|
||||
m_lcd->data_write(m_pe >> 8);
|
||||
else
|
||||
m_lcd->control_write(m_pe >> 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mu128_state::map(address_map &map)
|
||||
{
|
||||
map(0x000000, 0x1fffff).rom().region("maincpu", 0);
|
||||
map(0x200000, 0x21ffff).ram().share(m_ram);
|
||||
map(0x400000, 0x43ffff).ram().share(m_ram);
|
||||
map(0x800000, 0x801fff).m(m_swp30m, FUNC(swp30_device::map));
|
||||
map(0x802000, 0x803fff).m(m_swp30s, FUNC(swp30_device::map));
|
||||
map(0xc00000, 0xc00000).rw(m_sci, FUNC(i8251_device::data_r), FUNC(i8251_device::data_w)).mirror(0x3ffffe);
|
||||
@ -87,6 +138,8 @@ void mu128_state::mu128(machine_config &config)
|
||||
{
|
||||
SH7043(config, m_maincpu, 7_MHz_XTAL * 4);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &mu128_state::map);
|
||||
m_maincpu->read_porte().set(FUNC(mu128_state::pe_r));
|
||||
m_maincpu->write_porte().set(FUNC(mu128_state::pe_w));
|
||||
|
||||
NVRAM(config, m_nvram, nvram_device::DEFAULT_NONE);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user