From 141f2364cc5896717ff5f81e49c65b1fd12d7cad Mon Sep 17 00:00:00 2001 From: AJR Date: Sun, 10 Dec 2017 09:06:41 -0500 Subject: [PATCH] New generic ripple counter device --- scripts/src/machine.lua | 12 ++ scripts/target/mame/arcade.lua | 1 + scripts/target/mame/mess.lua | 1 + src/devices/bus/ss50/mpc.cpp | 42 ++--- src/devices/machine/ripple_counter.cpp | 202 +++++++++++++++++++++++++ src/devices/machine/ripple_counter.h | 92 +++++++++++ src/mame/drivers/mermaid.cpp | 52 ++++--- src/mame/includes/mermaid.h | 8 +- 8 files changed, 350 insertions(+), 60 deletions(-) create mode 100644 src/devices/machine/ripple_counter.cpp create mode 100644 src/devices/machine/ripple_counter.h diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index d254c010116..38017680f93 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -2196,6 +2196,18 @@ if (MACHINES["RF5C296"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/machine/ripple_counter.h,MACHINES["RIPPLE_COUNTER"] = true +--------------------------------------------------- + +if (MACHINES["RIPPLE_COUNTER"]~=null) then + files { + MAME_DIR .. "src/devices/machine/ripple_counter.cpp", + MAME_DIR .. "src/devices/machine/ripple_counter.h", + } +end + --------------------------------------------------- -- --@src/devices/machine/roc10937.h,MACHINES["ROC10937"] = true diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index 7d0902de2bd..1aa8b9d94b9 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -535,6 +535,7 @@ MACHINES["RA17XX"] = true --MACHINES["R64H156"] = true MACHINES["RF5C296"] = true --MACHINES["RIOT6532"] = true +MACHINES["RIPPLE_COUNTER"] = true MACHINES["ROC10937"] = true MACHINES["RP5C01"] = true MACHINES["RP5C15"] = true diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index ea2ee8ef9ec..03a80c4a6f0 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -524,6 +524,7 @@ MACHINES["PROM82S129"] = true MACHINES["R64H156"] = true MACHINES["RF5C296"] = true MACHINES["RIOT6532"] = true +MACHINES["RIPPLE_COUNTER"] = true MACHINES["ROC10937"] = true MACHINES["RP5C01"] = true MACHINES["RP5C15"] = true diff --git a/src/devices/bus/ss50/mpc.cpp b/src/devices/bus/ss50/mpc.cpp index 7f587d6bb62..8a1ac577a5e 100644 --- a/src/devices/bus/ss50/mpc.cpp +++ b/src/devices/bus/ss50/mpc.cpp @@ -13,6 +13,7 @@ #include "bus/rs232/rs232.h" #include "machine/6821pia.h" #include "machine/input_merger.h" +#include "machine/ripple_counter.h" //************************************************************************** // TYPE DEFINITIONS @@ -29,10 +30,8 @@ public: ss50_card_interface(mconfig, *this), m_pia(*this, "pia"), m_loopback(*this, "loopback"), + m_counter(*this, "counter"), m_baud_jumper(*this, "BAUD"), - m_cd4024ae_count(0), - m_cd4024ae_clock(false), - m_cd4024ae_reset(true), m_count_select(false) { } @@ -53,17 +52,13 @@ private: DECLARE_WRITE_LINE_MEMBER(serial_input_w); DECLARE_WRITE_LINE_MEMBER(reader_control_w); DECLARE_READ_LINE_MEMBER(count_r); - DECLARE_WRITE_LINE_MEMBER(count_reset_w); DECLARE_WRITE_LINE_MEMBER(count_select_w); - DECLARE_WRITE_LINE_MEMBER(clock_input_w); required_device m_pia; required_device m_loopback; + required_device m_counter; required_ioport m_baud_jumper; - u8 m_cd4024ae_count; - bool m_cd4024ae_clock; - bool m_cd4024ae_reset; bool m_count_select; }; @@ -113,7 +108,7 @@ MACHINE_CONFIG_MEMBER(ss50_mpc_device::device_add_mconfig) MCFG_PIA_READPB_HANDLER(IOPORT("STOP")) MCFG_DEVCB_BIT(6) MCFG_DEVCB_CHAIN_INPUT(READLINE(ss50_mpc_device, count_r)) MCFG_DEVCB_BIT(7) MCFG_PIA_WRITEPB_HANDLER(WRITELINE(ss50_mpc_device, count_select_w)) MCFG_DEVCB_BIT(2) - MCFG_DEVCB_CHAIN_OUTPUT(WRITELINE(ss50_mpc_device, count_reset_w)) MCFG_DEVCB_BIT(0) + MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE("counter", ripple_counter_device, reset_w)) MCFG_DEVCB_BIT(0) //MCFG_PIA_IRQA_HANDLER(WRITELINE(ss50_mpc_device, pia_irq_w)) //MCFG_PIA_IRQB_HANDLER(WRITELINE(ss50_mpc_device, pia_irq_w)) @@ -126,6 +121,9 @@ MACHINE_CONFIG_MEMBER(ss50_mpc_device::device_add_mconfig) MCFG_INPUT_MERGER_ANY_HIGH("loopback") MCFG_INPUT_MERGER_OUTPUT_HANDLER(DEVWRITELINE("outgate", input_merger_device, in_w<1>)) + + MCFG_DEVICE_ADD("counter", RIPPLE_COUNTER, 0) // CD4024AE (IC3) + MCFG_RIPPLE_COUNTER_STAGES(7) // only Q5 (÷32) and Q4 (÷16) are actually used MACHINE_CONFIG_END @@ -135,9 +133,6 @@ MACHINE_CONFIG_END void ss50_mpc_device::device_start() { - save_item(NAME(m_cd4024ae_count)); - save_item(NAME(m_cd4024ae_clock)); - save_item(NAME(m_cd4024ae_reset)); save_item(NAME(m_count_select)); } @@ -155,14 +150,7 @@ WRITE_LINE_MEMBER(ss50_mpc_device::reader_control_w) READ_LINE_MEMBER(ss50_mpc_device::count_r) { - return BIT(m_cd4024ae_count, m_count_select ? 4 : 3); -} - -WRITE_LINE_MEMBER(ss50_mpc_device::count_reset_w) -{ - m_cd4024ae_reset = bool(state); - if (state) - m_cd4024ae_count = 0; + return BIT(m_counter->count(), m_count_select ? 4 : 3); } WRITE_LINE_MEMBER(ss50_mpc_device::count_select_w) @@ -170,16 +158,6 @@ WRITE_LINE_MEMBER(ss50_mpc_device::count_select_w) m_count_select = bool(state); } -WRITE_LINE_MEMBER(ss50_mpc_device::clock_input_w) -{ - if (m_cd4024ae_clock != bool(state)) - { - m_cd4024ae_clock = bool(state); - if (!state && !m_cd4024ae_reset) - m_cd4024ae_count++; - } -} - //------------------------------------------------- // register_read - read from a port register @@ -202,13 +180,13 @@ WRITE8_MEMBER(ss50_mpc_device::register_write) WRITE_LINE_MEMBER(ss50_mpc_device::f110_w) { if (m_baud_jumper->read()) - clock_input_w(state); + m_counter->clock_w(state); } WRITE_LINE_MEMBER(ss50_mpc_device::f300_w) { if (!m_baud_jumper->read()) - clock_input_w(state); + m_counter->clock_w(state); } diff --git a/src/devices/machine/ripple_counter.cpp b/src/devices/machine/ripple_counter.cpp new file mode 100644 index 00000000000..ae38d342d68 --- /dev/null +++ b/src/devices/machine/ripple_counter.cpp @@ -0,0 +1,202 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/********************************************************************** + + Generic binary ripple counter emulation + + This device emulates basic ripple counter logic ICs with falling- + edge clocks and a synchronous reset inputs such as CD4040 and + 74LS393. + + The optional 8-bit ROM interface is intended to help stream ROM + data to sound chips that lack memory interfaces of their own + (e.g. MSM5205, TMS5110). + +**********************************************************************/ + +#include "emu.h" +#include "machine/ripple_counter.h" + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +// device type definition +DEFINE_DEVICE_TYPE(RIPPLE_COUNTER, ripple_counter_device, "ripple_counter", "Generic ripple counter") + + +//************************************************************************** +// RIPPLE COUNTER DEVICE +//************************************************************************** + +//------------------------------------------------- +// ripple_counter_device - constructor +//------------------------------------------------- + +ripple_counter_device::ripple_counter_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, RIPPLE_COUNTER, tag, owner, clock), + device_rom_interface(mconfig, *this, 0, ENDIANNESS_LITTLE, 8), + m_count_out_cb(*this), + m_rom_out_cb(*this), + m_count_timer(nullptr), + m_count_mask(0), + m_count(1), + m_clk(false), + m_reset(false) +{ +} + + +//------------------------------------------------- +// static_set_stages - configure the number of +// stages used to count +//------------------------------------------------- + +void ripple_counter_device::static_set_stages(device_t &device, u8 stages) +{ + auto &dev = downcast(device); + dev.m_count_mask = (1U << stages) - 1; + dev.set_rom_addr_width(stages); +} + + +//------------------------------------------------- +// memory_space_config - return a description of +// any address spaces owned by this device +//------------------------------------------------- + +device_memory_interface::space_config_vector ripple_counter_device::memory_space_config() const +{ + if (m_rom_out_cb.isnull()) + return space_config_vector(); + else + return device_rom_interface::memory_space_config(); +} + + +//------------------------------------------------- +// device_validity_check - validate a device after +// the configuration has been constructed +//------------------------------------------------- + +void ripple_counter_device::device_validity_check(validity_checker &valid) const +{ + if (m_count_mask == 0) + osd_printf_error("No counting stages configured\n"); +} + + +//------------------------------------------------- +// device_resolve_objects - resolve objects that +// may be needed for other devices to set +// initial conditions at start time +//------------------------------------------------- + +void ripple_counter_device::device_resolve_objects() +{ + // resolve callbacks + m_count_out_cb.resolve_safe(); + m_rom_out_cb.resolve(); +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void ripple_counter_device::device_start() +{ + // initialize timers + m_count_timer = timer_alloc(TIMER_COUNT); + + // register internal state + save_item(NAME(m_count)); + save_item(NAME(m_clk)); + save_item(NAME(m_reset)); +} + + +//------------------------------------------------- +// device_clock_changed - called when the +// device clock is altered in any way +//------------------------------------------------- + +void ripple_counter_device::device_clock_changed() +{ + attotime freq = m_reset ? attotime::never : clocks_to_attotime(1); + m_count_timer->adjust(freq, 0, freq); +} + + +//------------------------------------------------- +// rom_bank_updated - called when the ROM bank +// is changed +//------------------------------------------------- + +void ripple_counter_device::rom_bank_updated() +{ + m_rom_out_cb(read_byte(m_count)); +} + + +//------------------------------------------------- +// set_count - update the count and associated +// outputs +//------------------------------------------------- + +void ripple_counter_device::set_count(u32 count) +{ + m_count = count; + m_count_out_cb(count); + if (!m_rom_out_cb.isnull()) + m_rom_out_cb(read_byte(count)); +} + + +//------------------------------------------------- +// clock_w - handle falling-edge clock input +//------------------------------------------------- + +WRITE_LINE_MEMBER(ripple_counter_device::clock_w) +{ + if (m_clk != bool(state)) + { + m_clk = bool(state); + if (!state && !m_reset) + set_count((m_count + 1) & m_count_mask); + } +} + + +//------------------------------------------------- +// reset_w - handle active-high reset input +//------------------------------------------------- + +WRITE_LINE_MEMBER(ripple_counter_device::reset_w) +{ + if (m_reset != bool(state)) + { + m_reset = bool(state); + if (state && m_count != 0) + set_count(0); + + // stop or start the count timer as required + notify_clock_changed(); + } +} + + +//------------------------------------------------- +// device_timer - called whenever a device timer +// fires +//------------------------------------------------- + +void ripple_counter_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + switch (id) + { + case TIMER_COUNT: + set_count((m_count + 1) & m_count_mask); + break; + } +} diff --git a/src/devices/machine/ripple_counter.h b/src/devices/machine/ripple_counter.h new file mode 100644 index 00000000000..f9e997f3348 --- /dev/null +++ b/src/devices/machine/ripple_counter.h @@ -0,0 +1,92 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/********************************************************************** + + Generic binary ripple counter emulation + +**********************************************************************/ + +#ifndef MAME_MACHINE_RIPPLE_COUNTER_H +#define MAME_MACHINE_RIPPLE_COUNTER_H + +#pragma once + +//************************************************************************** +// CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_RIPPLE_COUNTER_STAGES(_stages) \ + ripple_counter_device::static_set_stages(*device, _stages); + +// output callbacks +#define MCFG_RIPPLE_COUNTER_COUNT_OUT_CB(_devcb) \ + devcb = &ripple_counter_device::static_set_count_out_cb(*device, DEVCB_##_devcb); +#define MCFG_RIPPLE_COUNTER_ROM_OUT_CB(_devcb) \ + devcb = &ripple_counter_device::static_set_rom_out_cb(*device, DEVCB_##_devcb); + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> ripple_counter_device + +class ripple_counter_device : public device_t, public device_rom_interface +{ +public: + // construction/destruction + ripple_counter_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + // static configuration + static void static_set_stages(device_t &device, u8 stages); + template static devcb_base &static_set_count_out_cb(device_t &device, Object &&cb) + { return downcast(device).m_count_out_cb.set_callback(std::forward(cb)); } + template static devcb_base &static_set_rom_out_cb(device_t &device, Object &&cb) + { return downcast(device).m_rom_out_cb.set_callback(std::forward(cb)); } + + // control line handlers + DECLARE_WRITE_LINE_MEMBER(clock_w); + DECLARE_WRITE_LINE_MEMBER(reset_w); + + // getters + u32 count() const { return m_count; } + +protected: + // device-level overrides + virtual void device_validity_check(validity_checker &valid) const override; + virtual void device_resolve_objects() override; + virtual void device_start() override; + virtual void device_clock_changed() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + + // device_rom_interface overrides + virtual space_config_vector memory_space_config() const override; + virtual void rom_bank_updated() override; + +private: + // internal helpers + void set_count(u32 count); + + // device callbacks + devcb_write32 m_count_out_cb; + devcb_write8 m_rom_out_cb; + + // device timers + enum + { + TIMER_COUNT + }; + emu_timer *m_count_timer; + + // configuration parameters + u32 m_count_mask; + + // running state + u32 m_count; + bool m_clk; + bool m_reset; +}; + +// device type definition +DECLARE_DEVICE_TYPE(RIPPLE_COUNTER, ripple_counter_device) + +#endif // MAME_MACHINE_RIPPLE_COUNTER_H diff --git a/src/mame/drivers/mermaid.cpp b/src/mame/drivers/mermaid.cpp index 2ab899f4d38..eaf4c46fc59 100644 --- a/src/mame/drivers/mermaid.cpp +++ b/src/mame/drivers/mermaid.cpp @@ -180,21 +180,22 @@ ADDRESS_MAP_END WRITE_LINE_MEMBER(mermaid_state::rougien_sample_rom_lo_w) { m_adpcm_rom_sel = state | (m_adpcm_rom_sel & 2); + m_adpcm_counter->set_rom_bank(m_adpcm_rom_sel); } WRITE_LINE_MEMBER(mermaid_state::rougien_sample_rom_hi_w) { m_adpcm_rom_sel = (state <<1) | (m_adpcm_rom_sel & 1); + m_adpcm_counter->set_rom_bank(m_adpcm_rom_sel); } WRITE_LINE_MEMBER(mermaid_state::rougien_sample_playback_w) { if (state) { - m_adpcm_pos = m_adpcm_rom_sel*0x1000; - m_adpcm_end = m_adpcm_pos+0x1000; m_adpcm_idle = 0; m_adpcm->reset_w(0); + m_adpcm_counter->reset_w(0); } } @@ -366,13 +367,10 @@ void mermaid_state::machine_start() save_item(NAME(m_rougien_gfxbank2)); save_item(NAME(m_ay8910_enable)); - save_item(NAME(m_adpcm_pos)); - save_item(NAME(m_adpcm_end)); save_item(NAME(m_adpcm_idle)); save_item(NAME(m_adpcm_data)); save_item(NAME(m_adpcm_trigger)); save_item(NAME(m_adpcm_rom_sel)); - save_item(NAME(m_adpcm_play_reg)); } void mermaid_state::machine_reset() @@ -387,33 +385,32 @@ void mermaid_state::machine_reset() m_adpcm_idle = 1; m_adpcm_rom_sel = 0; - m_adpcm_play_reg = 0; + m_adpcm->reset_w(1); + m_adpcm_counter->reset_w(1); + m_adpcm_trigger = 0; + m_adpcm_data = 0; } /* Similar to Jantotsu, apparently the HW has three ports that controls what kind of sample should be played. Every sample size is 0x1000. */ +WRITE8_MEMBER(mermaid_state::adpcm_data_w) +{ + m_adpcm_data = data; + m_adpcm->data_w(m_adpcm_trigger ? (data & 0x0f) : (data & 0xf0) >> 4); +} + WRITE_LINE_MEMBER(mermaid_state::rougien_adpcm_int) { -// popmessage("%08x",m_adpcm_pos); + if (!state) + return; - if (m_adpcm_pos >= m_adpcm_end || m_adpcm_idle) + m_adpcm_trigger ^= 1; + m_adpcm->data_w(m_adpcm_trigger ? (m_adpcm_data & 0x0f) : (m_adpcm_data & 0xf0) >> 4); + m_adpcm_counter->clock_w(m_adpcm_trigger); + if (m_adpcm_trigger == 0 && m_adpcm_counter->count() == 0) { - //m_adpcm_idle = 1; + m_adpcm_idle = 1; m_adpcm->reset_w(1); - m_adpcm_trigger = 0; - } - else - { - uint8_t *ROM = memregion("adpcm")->base(); - - m_adpcm_data = ((m_adpcm_trigger ? (ROM[m_adpcm_pos] & 0x0f) : (ROM[m_adpcm_pos] & 0xf0) >> 4)); - m_adpcm->data_w(m_adpcm_data & 0xf); - m_adpcm_trigger ^= 1; - if (m_adpcm_trigger == 0) - { - m_adpcm_pos++; - //if ((ROM[m_adpcm_pos] & 0xff) == 0x70) - // m_adpcm_idle = 1; - } + m_adpcm_counter->reset_w(1); } } @@ -483,9 +480,14 @@ static MACHINE_CONFIG_DERIVED( rougien, mermaid ) MCFG_PALETTE_INIT_OWNER(mermaid_state,rougien) MCFG_SOUND_ADD("adpcm", MSM5205, 384000) - MCFG_MSM5205_VCLK_CB(WRITELINE(mermaid_state, rougien_adpcm_int)) /* interrupt function */ + MCFG_MSM5205_VCK_CALLBACK(WRITELINE(mermaid_state, rougien_adpcm_int)) MCFG_MSM5205_PRESCALER_SELECTOR(S96_4B) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00) + + MCFG_DEVICE_ADD("adpcm_counter", RIPPLE_COUNTER, 0) + MCFG_DEVICE_ROM("adpcm") + MCFG_RIPPLE_COUNTER_STAGES(12) + MCFG_RIPPLE_COUNTER_ROM_OUT_CB(WRITE8(mermaid_state, adpcm_data_w)) MACHINE_CONFIG_END /* ROMs */ diff --git a/src/mame/includes/mermaid.h b/src/mame/includes/mermaid.h index 6c7e5451aed..62b78871823 100644 --- a/src/mame/includes/mermaid.h +++ b/src/mame/includes/mermaid.h @@ -5,6 +5,8 @@ Mermaid *************************************************************************/ + +#include "machine/ripple_counter.h" #include "sound/msm5205.h" #include "sound/ay8910.h" #include "screen.h" @@ -22,6 +24,7 @@ public: m_colorram(*this, "colorram"), m_maincpu(*this, "maincpu"), m_adpcm(*this, "adpcm"), + m_adpcm_counter(*this, "adpcm_counter"), m_ay8910(*this, "ay%u", 1), m_gfxdecode(*this, "gfxdecode"), m_screen(*this, "screen"), @@ -51,18 +54,16 @@ public: int m_rougien_gfxbank2; /* sound-related */ - uint32_t m_adpcm_pos; - uint32_t m_adpcm_end; uint8_t m_adpcm_idle; int m_adpcm_data; uint8_t m_adpcm_trigger; uint8_t m_adpcm_rom_sel; - uint8_t m_adpcm_play_reg; bool m_ay8910_enable[2]; /* devices */ required_device m_maincpu; optional_device m_adpcm; + optional_device m_adpcm_counter; required_device_array m_ay8910; required_device m_gfxdecode; required_device m_screen; @@ -77,6 +78,7 @@ public: DECLARE_WRITE_LINE_MEMBER(rougien_sample_rom_lo_w); DECLARE_WRITE_LINE_MEMBER(rougien_sample_rom_hi_w); DECLARE_WRITE_LINE_MEMBER(rougien_sample_playback_w); + DECLARE_WRITE8_MEMBER(adpcm_data_w); DECLARE_WRITE8_MEMBER(mermaid_videoram2_w); DECLARE_WRITE8_MEMBER(mermaid_videoram_w); DECLARE_WRITE8_MEMBER(mermaid_colorram_w);