diff options
-rw-r--r-- | scripts/src/cpu.lua | 8 | ||||
-rw-r--r-- | src/devices/bus/plg1x0/plg1x0.cpp | 4 | ||||
-rw-r--r-- | src/devices/cpu/h8/h8_adc.h | 6 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh7042.cpp | 264 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh7042.h | 91 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh_adc.cpp | 315 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh_adc.h | 100 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh_cmt.cpp | 197 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh_cmt.h | 75 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh_intc.cpp | 75 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh_intc.h | 47 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh_port.cpp | 109 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh_port.h | 75 | ||||
-rw-r--r-- | src/mame/tvgames/xavix_a.cpp | 1 | ||||
-rw-r--r-- | src/mame/yamaha/ymmu128.cpp | 59 |
15 files changed, 1372 insertions, 54 deletions
diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index 23f66cd7d5c..8fee43f4ab1 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -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", diff --git a/src/devices/bus/plg1x0/plg1x0.cpp b/src/devices/bus/plg1x0/plg1x0.cpp index 11f065b17c4..6abd5100209 100644 --- a/src/devices/bus/plg1x0/plg1x0.cpp +++ b/src/devices/bus/plg1x0/plg1x0.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) : diff --git a/src/devices/cpu/h8/h8_adc.h b/src/devices/cpu/h8/h8_adc.h index bb180703c64..8155f5bcd1d 100644 --- a/src/devices/cpu/h8/h8_adc.h +++ b/src/devices/cpu/h8/h8_adc.h @@ -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); diff --git a/src/devices/cpu/sh/sh7042.cpp b/src/devices/cpu/sh/sh7042.cpp index 35f559b47ce..7ef10f19ce1 100644 --- a/src/devices/cpu/sh/sh7042.cpp +++ b/src/devices/cpu/sh/sh7042.cpp @@ -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(); } +void sh7042_device::device_add_mconfig(machine_config &config) +{ + 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); +} -// ADC section +void sh7042_device::do_sci_w(int sci, int state) +{ + logerror("sci %d %d\n", sci, state); +} -u16 sh7042_device::addr_r(offs_t offset) +void sh7042_device::internal_update() { - logerror("addr16_r %d %03x\n", offset, m_addr[offset]); - return m_addr[offset]; + internal_update(current_cycles()); } -u8 sh7042_device::adcsr_r() +void sh7042_device::add_event(u64 &event_time, u64 new_event) { - logerror("adcsr_r %02x\n", m_adcsr); - return m_adcsr; + if(!new_event) + return; + if(!event_time || event_time > new_event) + event_time = new_event; } -u8 sh7042_device::adcr_r() +void sh7042_device::recompute_timer(u64 event_time) { - logerror("adcr_r %02x\n", m_adcr); - return m_adcr; + 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()); } -void sh7042_device::adcsr_w(u8 data) +TIMER_CALLBACK_MEMBER(sh7042_device::event_timer_tick) { - logerror("adcsr_w %02x\n", data); - // u8 prev = m_adcsr; - m_adcsr = (data & 0x7f) | (m_adcsr & data & CSR_ADF); + internal_update(); } -void sh7042_device::adcr_w(u8 data) +void sh7042_device::internal_update(u64 current_time) { - 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; + 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); } -void sh7042_device::do_sci_w(int sci, int state) +u16 sh7042_device::pcf_ah_r() { - logerror("sci %d %d\n", sci, state); + 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); } diff --git a/src/devices/cpu/sh/sh7042.h b/src/devices/cpu/sh/sh7042.h index dabcb7c272b..55795fd8282 100644 --- a/src/devices/cpu/sh/sh7042.h +++ b/src/devices/cpu/sh/sh7042.h @@ -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 diff --git a/src/devices/cpu/sh/sh_adc.cpp b/src/devices/cpu/sh/sh_adc.cpp new file mode 100644 index 00000000000..d9e1da01921 --- /dev/null +++ b/src/devices/cpu/sh/sh_adc.cpp @@ -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(); +} diff --git a/src/devices/cpu/sh/sh_adc.h b/src/devices/cpu/sh/sh_adc.h new file mode 100644 index 00000000000..9a48e3f804b --- /dev/null +++ b/src/devices/cpu/sh/sh_adc.h @@ -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 diff --git a/src/devices/cpu/sh/sh_cmt.cpp b/src/devices/cpu/sh/sh_cmt.cpp new file mode 100644 index 00000000000..1e659080e75 --- /dev/null +++ b/src/devices/cpu/sh/sh_cmt.cpp @@ -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))); +} diff --git a/src/devices/cpu/sh/sh_cmt.h b/src/devices/cpu/sh/sh_cmt.h new file mode 100644 index 00000000000..e365be37fb1 --- /dev/null +++ b/src/devices/cpu/sh/sh_cmt.h @@ -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 diff --git a/src/devices/cpu/sh/sh_intc.cpp b/src/devices/cpu/sh/sh_intc.cpp new file mode 100644 index 00000000000..d13f8f55853 --- /dev/null +++ b/src/devices/cpu/sh/sh_intc.cpp @@ -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); +} + diff --git a/src/devices/cpu/sh/sh_intc.h b/src/devices/cpu/sh/sh_intc.h new file mode 100644 index 00000000000..b93444d8e32 --- /dev/null +++ b/src/devices/cpu/sh/sh_intc.h @@ -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 diff --git a/src/devices/cpu/sh/sh_port.cpp b/src/devices/cpu/sh/sh_port.cpp new file mode 100644 index 00000000000..8bc962f65cd --- /dev/null +++ b/src/devices/cpu/sh/sh_port.cpp @@ -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); +} + diff --git a/src/devices/cpu/sh/sh_port.h b/src/devices/cpu/sh/sh_port.h new file mode 100644 index 00000000000..ec2a19228ee --- /dev/null +++ b/src/devices/cpu/sh/sh_port.h @@ -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 diff --git a/src/mame/tvgames/xavix_a.cpp b/src/mame/tvgames/xavix_a.cpp index 9470f8536de..ebddb577444 100644 --- a/src/mame/tvgames/xavix_a.cpp +++ b/src/mame/tvgames/xavix_a.cpp @@ -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? diff --git a/src/mame/yamaha/ymmu128.cpp b/src/mame/yamaha/ymmu128.cpp index b0a15fcfc92..8743612aadc 100644 --- a/src/mame/yamaha/ymmu128.cpp +++ b/src/mame/yamaha/ymmu128.cpp @@ -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() { } +// 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); |