Enhance the sh704x. MU128 MSTO, needs interrupts now.

This commit is contained in:
Olivier Galibert 2024-03-03 18:00:16 +01:00
parent 187945dbd0
commit 1dae50467e
15 changed files with 1383 additions and 65 deletions

View File

@ -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",

View File

@ -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) :

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View 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
View 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

View 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)));
}

View 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

View 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);
}

View 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

View 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);
}

View 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

View File

@ -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?

View File

@ -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);