summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/sh/sh7014_mtu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/sh/sh7014_mtu.cpp')
-rw-r--r--src/devices/cpu/sh/sh7014_mtu.cpp571
1 files changed, 571 insertions, 0 deletions
diff --git a/src/devices/cpu/sh/sh7014_mtu.cpp b/src/devices/cpu/sh/sh7014_mtu.cpp
new file mode 100644
index 00000000000..1f1f2ddf879
--- /dev/null
+++ b/src/devices/cpu/sh/sh7014_mtu.cpp
@@ -0,0 +1,571 @@
+// license:BSD-3-Clause
+// copyright-holders:windyfairy
+/***************************************************************************
+
+ SH7014 Multifunction Timer Pulse Unit
+
+ TODO list (not comprehensive):
+ - Synchronized operation
+ - Cascade connection operation
+ - External clocks
+ - Timer modes (PWM mode, phase counting mode (+ decrementing counter mode), etc)
+
+***************************************************************************/
+
+#include "emu.h"
+
+#include "sh7014_mtu.h"
+
+// #define VERBOSE (LOG_GENERAL)
+
+#include "logmacro.h"
+
+
+DEFINE_DEVICE_TYPE(SH7014_MTU, sh7014_mtu_device, "sh7014mtu", "SH7014 Multifunction Timer Pulse Unit")
+DEFINE_DEVICE_TYPE(SH7014_MTU_CHANNEL, sh7014_mtu_channel_device, "sh7014mtuchan", "SH7014 Multifunction Timer Pulse Unit Channel")
+
+sh7014_mtu_device::sh7014_mtu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SH7014_MTU, tag, owner, clock)
+ , m_intc(*this, finder_base::DUMMY_TAG)
+ , m_chan(*this, "ch%u", 0u)
+{
+}
+
+void sh7014_mtu_device::device_start()
+{
+ save_item(NAME(m_tsyr));
+}
+
+void sh7014_mtu_device::device_reset()
+{
+ m_tsyr = 0;
+}
+
+void sh7014_mtu_device::device_add_mconfig(machine_config &config)
+{
+ SH7014_MTU_CHANNEL(config, m_chan[0], DERIVED_CLOCK(1, 1), m_intc,
+ 0, // channel
+ sh7014_intc_device::INT_VECTOR_MTU_TGI0A,
+ sh7014_intc_device::INT_VECTOR_MTU_TGI0B,
+ sh7014_intc_device::INT_VECTOR_MTU_TGI0C,
+ sh7014_intc_device::INT_VECTOR_MTU_TGI0D,
+ sh7014_intc_device::INT_VECTOR_MTU_TGI0V,
+ -1
+ );
+
+ SH7014_MTU_CHANNEL(config, m_chan[1], DERIVED_CLOCK(1, 1), m_intc,
+ 1, // channel
+ sh7014_intc_device::INT_VECTOR_MTU_TGI1A,
+ sh7014_intc_device::INT_VECTOR_MTU_TGI1B,
+ -1,
+ -1,
+ sh7014_intc_device::INT_VECTOR_MTU_TGI1V,
+ sh7014_intc_device::INT_VECTOR_MTU_TGI1U
+ );
+
+ SH7014_MTU_CHANNEL(config, m_chan[2], DERIVED_CLOCK(1, 1), m_intc,
+ 2, // channel
+ sh7014_intc_device::INT_VECTOR_MTU_TGI2A,
+ sh7014_intc_device::INT_VECTOR_MTU_TGI2B,
+ -1,
+ -1,
+ sh7014_intc_device::INT_VECTOR_MTU_TGI2V,
+ sh7014_intc_device::INT_VECTOR_MTU_TGI2U
+ );
+}
+
+void sh7014_mtu_device::map(address_map &map)
+{
+ map(0x00, 0x00).rw(FUNC(sh7014_mtu_device::tstr_r), FUNC(sh7014_mtu_device::tstr_w));
+ map(0x01, 0x01).rw(FUNC(sh7014_mtu_device::tsyr_r), FUNC(sh7014_mtu_device::tsyr_w));
+
+ map(0x20, 0x3f).m(m_chan[0], FUNC(sh7014_mtu_channel_device::map_chan0));
+ map(0x40, 0x5f).m(m_chan[1], FUNC(sh7014_mtu_channel_device::map_chan1_2));
+ map(0x60, 0x7f).m(m_chan[2], FUNC(sh7014_mtu_channel_device::map_chan1_2));
+}
+
+///
+
+uint8_t sh7014_mtu_device::tstr_r()
+{
+ return m_chan[0]->is_enabled()
+ | (m_chan[1]->is_enabled() << 1)
+ | (m_chan[2]->is_enabled() << 2);
+}
+
+void sh7014_mtu_device::tstr_w(uint8_t data)
+{
+ LOG("%s: tstr_w %02x\n", machine().describe_context().c_str(), data);
+
+ m_chan[0]->set_enable((data & TSTR_CST0) != 0);
+ m_chan[1]->set_enable((data & TSTR_CST1) != 0);
+ m_chan[2]->set_enable((data & TSTR_CST2) != 0);
+}
+
+uint8_t sh7014_mtu_device::tsyr_r()
+{
+ return m_tsyr & (TSYR_SYNC0 | TSYR_SYNC1 | TSYR_SYNC2);
+}
+
+void sh7014_mtu_device::tsyr_w(uint8_t data)
+{
+ LOG("%s: tsyr_w %02x\n", machine().describe_context().c_str(), data);
+
+ m_tsyr = data;
+}
+
+
+//////////////////
+
+sh7014_mtu_channel_device::sh7014_mtu_channel_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SH7014_MTU_CHANNEL, tag, owner, clock)
+ , m_intc(*this, finder_base::DUMMY_TAG)
+ , m_timer(nullptr)
+{
+}
+
+void sh7014_mtu_channel_device::device_start()
+{
+ save_item(NAME(m_tcr));
+ save_item(NAME(m_tmdr));
+ save_item(NAME(m_tiorh));
+ save_item(NAME(m_tiorl));
+ save_item(NAME(m_tier));
+ save_item(NAME(m_tsr));
+ save_item(NAME(m_tcnt));
+ save_item(NAME(m_tgr));
+
+ save_item(NAME(m_last_clock_update));
+ save_item(NAME(m_clock_type));
+ save_item(NAME(m_clock_divider));
+ save_item(NAME(m_channel_active));
+ save_item(NAME(m_phase));
+ save_item(NAME(m_counter_cycle));
+ save_item(NAME(m_tgr_clearing));
+
+ m_timer = timer_alloc(FUNC(sh7014_mtu_channel_device::timer_callback), this);
+}
+
+void sh7014_mtu_channel_device::device_reset()
+{
+ m_tcr = 0;
+ m_tmdr = 0;
+ m_tier = 0;
+ m_tsr = TSR_TCFD;
+ m_tiorh = m_tiorl = 0;
+ std::fill(std::begin(m_tgr), std::end(m_tgr), 0);
+
+ m_tcnt = 0;
+ m_last_clock_update = 0;
+ m_clock_type = INPUT_INTERNAL;
+ m_clock_divider = DIV_1;
+ m_channel_active = false;
+ m_phase = 0;
+ m_counter_cycle = 0x10000;
+ m_tgr_clearing = TGR_CLEAR_NONE;
+
+ m_timer->adjust(attotime::never);
+}
+
+void sh7014_mtu_channel_device::map_chan0(address_map &map)
+{
+ map(0x00, 0x00).rw(FUNC(sh7014_mtu_channel_device::tcr_r), FUNC(sh7014_mtu_channel_device::tcr_w));
+ map(0x01, 0x01).rw(FUNC(sh7014_mtu_channel_device::tmdr_r), FUNC(sh7014_mtu_channel_device::tmdr_w));
+ map(0x02, 0x02).rw(FUNC(sh7014_mtu_channel_device::tiorh_r), FUNC(sh7014_mtu_channel_device::tiorh_w));
+ map(0x03, 0x03).rw(FUNC(sh7014_mtu_channel_device::tiorl_r), FUNC(sh7014_mtu_channel_device::tiorl_w));
+ map(0x04, 0x04).rw(FUNC(sh7014_mtu_channel_device::tier_r), FUNC(sh7014_mtu_channel_device::tier_w));
+ map(0x05, 0x05).rw(FUNC(sh7014_mtu_channel_device::tsr_r), FUNC(sh7014_mtu_channel_device::tsr_w));
+ map(0x06, 0x07).rw(FUNC(sh7014_mtu_channel_device::tcnt_r), FUNC(sh7014_mtu_channel_device::tcnt_w));
+ map(0x08, 0x09).rw(FUNC(sh7014_mtu_channel_device::tgra_r), FUNC(sh7014_mtu_channel_device::tgra_w));
+ map(0x0a, 0x0b).rw(FUNC(sh7014_mtu_channel_device::tgrb_r), FUNC(sh7014_mtu_channel_device::tgrb_w));
+ map(0x0c, 0x0d).rw(FUNC(sh7014_mtu_channel_device::tgrc_r), FUNC(sh7014_mtu_channel_device::tgrc_w));
+ map(0x0e, 0x0f).rw(FUNC(sh7014_mtu_channel_device::tgrd_r), FUNC(sh7014_mtu_channel_device::tgrd_w));
+}
+
+void sh7014_mtu_channel_device::map_chan1_2(address_map &map)
+{
+ map(0x00, 0x00).rw(FUNC(sh7014_mtu_channel_device::tcr_r), FUNC(sh7014_mtu_channel_device::tcr_w));
+ map(0x01, 0x01).rw(FUNC(sh7014_mtu_channel_device::tmdr_r), FUNC(sh7014_mtu_channel_device::tmdr_w));
+ map(0x02, 0x02).rw(FUNC(sh7014_mtu_channel_device::tiorh_r), FUNC(sh7014_mtu_channel_device::tiorh_w));
+ map(0x04, 0x04).rw(FUNC(sh7014_mtu_channel_device::tier_r), FUNC(sh7014_mtu_channel_device::tier_w));
+ map(0x05, 0x05).rw(FUNC(sh7014_mtu_channel_device::tsr_r), FUNC(sh7014_mtu_channel_device::tsr_w));
+ map(0x06, 0x07).rw(FUNC(sh7014_mtu_channel_device::tcnt_r), FUNC(sh7014_mtu_channel_device::tcnt_w));
+ map(0x08, 0x09).rw(FUNC(sh7014_mtu_channel_device::tgra_r), FUNC(sh7014_mtu_channel_device::tgra_w));
+ map(0x0a, 0x0b).rw(FUNC(sh7014_mtu_channel_device::tgrb_r), FUNC(sh7014_mtu_channel_device::tgrb_w));
+}
+
+///
+
+TIMER_CALLBACK_MEMBER( sh7014_mtu_channel_device::timer_callback )
+{
+ update_counter();
+ schedule_next_event();
+}
+
+void sh7014_mtu_channel_device::set_enable(bool enabled)
+{
+ update_counter();
+
+ m_channel_active = enabled;
+
+ schedule_next_event();
+}
+
+uint8_t sh7014_mtu_channel_device::tcr_r()
+{
+ uint8_t r = m_tcr;
+
+ if (m_channel_id > 0)
+ r &= 0x7f;
+
+ return r;
+}
+
+void sh7014_mtu_channel_device::tcr_w(uint8_t data)
+{
+ LOG("%s: tcr_w<%d> %02x\n", machine().describe_context().c_str(), m_channel_id, data);
+
+ update_counter();
+
+ m_tcr = data;
+
+ constexpr uint32_t divider_type[3][8] = {
+ {INPUT_INTERNAL, INPUT_INTERNAL, INPUT_INTERNAL, INPUT_INTERNAL, INPUT_A, INPUT_B, INPUT_C, INPUT_D},
+ {INPUT_INTERNAL, INPUT_INTERNAL, INPUT_INTERNAL, INPUT_INTERNAL, INPUT_A, INPUT_B, INPUT_INTERNAL, INPUT_TCNT2},
+ {INPUT_INTERNAL, INPUT_INTERNAL, INPUT_INTERNAL, INPUT_INTERNAL, INPUT_A, INPUT_B, INPUT_C, INPUT_INTERNAL},
+ };
+
+ const int prescaler = BIT(m_tcr, 0, 3);
+
+ m_clock_type = divider_type[m_channel_id][prescaler];
+
+ if (m_clock_type == INPUT_INTERNAL) {
+ constexpr int32_t dividers[3][8] = {
+ {DIV_1, DIV_4, DIV_16, DIV_64, -1, -1, -1, -1},
+ {DIV_1, DIV_4, DIV_16, DIV_64, -1, -1, DIV_256, -1},
+ {DIV_1, DIV_4, DIV_16, DIV_64, -1, -1, -1, DIV_1024},
+ };
+
+ m_clock_divider = dividers[m_channel_id][prescaler];
+ } else {
+ m_clock_divider = DIV_1;
+ }
+
+ const int clock_edge = BIT(m_tcr, 3, 2);
+ if (m_clock_divider < DIV_4) {
+ m_phase = 0;
+ } else {
+ switch (clock_edge) {
+ case 0:
+ m_phase = 0;
+ break;
+ case 1:
+ m_phase = 1 << (m_clock_divider - 1);
+ break;
+ case 2:
+ // If count on both rising and falling edges, input clock frequency becomes 1/2
+ m_phase = 0;
+ m_clock_divider--;
+ break;
+ }
+ }
+
+ const int counting_clear = BIT(m_tcr, 5, m_channel_id == 0 ? 3 : 2);
+ if (counting_clear == 3 || (m_channel_id == 0 && counting_clear == 7))
+ m_tgr_clearing = TGR_CLEAR_SYNC;
+ else if (counting_clear >= 1 && counting_clear <= 2)
+ m_tgr_clearing = counting_clear - 1; // TGRA, TGRB
+ else if (m_channel_id == 0 && counting_clear >= 5 && counting_clear <= 6)
+ m_tgr_clearing = counting_clear - 3; // TGRC, TGRD (ch 0 only)
+ else
+ m_tgr_clearing = TGR_CLEAR_NONE; // 0, 4, and anything else
+
+ schedule_next_event();
+}
+
+uint8_t sh7014_mtu_channel_device::tmdr_r()
+{
+ uint8_t r = m_tmdr;
+
+ if (m_channel_id > 0)
+ r &= 0x0f;
+
+ return r | 0xc0;
+}
+
+void sh7014_mtu_channel_device::tmdr_w(uint8_t data)
+{
+ LOG("%s: tmdr_w<%d> %02x\n", machine().describe_context().c_str(), m_channel_id, data);
+
+ m_tmdr = data;
+}
+
+uint8_t sh7014_mtu_channel_device::tiorh_r()
+{
+ return m_tiorh;
+}
+
+void sh7014_mtu_channel_device::tiorh_w(uint8_t data)
+{
+ LOG("%s: tiorh_w<%d> %02x\n", machine().describe_context().c_str(), m_channel_id, data);
+
+ const bool trga_is_output_compare_register = BIT(data, 3) == 0;
+ const bool trga_was_output_compare_register = BIT(m_tiorh, 3) == 0;
+ if (trga_is_output_compare_register) {
+ const auto tgra_mode = BIT(data, 2);
+ const auto old_tgra_mode = BIT(m_tiorh, 2);
+
+ if ((tgra_mode != old_tgra_mode) || (trga_is_output_compare_register != trga_was_output_compare_register)) {
+ const auto initial_output = tgra_mode ? TSR_TGFA : 0;
+ m_tsr = (m_tsr & ~TSR_TGFA) | initial_output;
+ }
+ }
+
+ const bool trgb_is_output_compare_register = BIT(data, 7) == 0;
+ const bool trgb_was_output_compare_register = BIT(m_tiorh, 7) == 0;
+ if (trgb_is_output_compare_register) {
+ const auto tgrb_mode = BIT(data, 6);
+ const auto old_tgrb_mode = BIT(m_tiorh, 6);
+
+ if ((tgrb_mode != old_tgrb_mode) || (trgb_is_output_compare_register != trgb_was_output_compare_register)) {
+ const auto initial_output = tgrb_mode ? TSR_TGFB : 0;
+ m_tsr = (m_tsr & ~TSR_TGFB) | initial_output;
+ }
+ }
+
+ m_tiorh = data;
+}
+
+uint8_t sh7014_mtu_channel_device::tiorl_r()
+{
+ if (m_channel_id > 0)
+ return 0;
+
+ return m_tiorl;
+}
+
+void sh7014_mtu_channel_device::tiorl_w(uint8_t data)
+{
+ LOG("%s: tiorl_w<%d> %02x\n", machine().describe_context().c_str(), m_channel_id, data);
+
+ if (m_channel_id > 0)
+ return;
+
+ const bool trgc_is_output_compare_register = BIT(data, 3) == 0;
+ const bool trgc_was_output_compare_register = BIT(m_tiorl, 3) == 0;
+ if (trgc_is_output_compare_register) {
+ const auto tgrc_mode = BIT(data, 2);
+ const auto old_tgrc_mode = BIT(m_tiorl, 2);
+
+ if ((tgrc_mode != old_tgrc_mode) || (trgc_is_output_compare_register != trgc_was_output_compare_register)) {
+ const auto initial_output = tgrc_mode ? TSR_TGFC : 0;
+ m_tsr = (m_tsr & ~TSR_TGFC) | initial_output;
+ }
+ }
+
+ const bool trgd_is_output_compare_register = BIT(data, 7) == 0;
+ const bool trgd_was_output_compare_register = BIT(m_tiorl, 7) == 0;
+ if (trgd_is_output_compare_register) {
+ const auto tgrd_mode = BIT(data, 6);
+ const auto old_tgrd_mode = BIT(m_tiorl, 6);
+
+ if ((tgrd_mode != old_tgrd_mode) || (trgd_is_output_compare_register != trgd_was_output_compare_register)) {
+ const auto initial_output = tgrd_mode ? TSR_TGFD : 0;
+ m_tsr = (m_tsr & ~TSR_TGFD) | initial_output;
+ }
+ }
+
+ m_tiorl = data;
+}
+
+uint8_t sh7014_mtu_channel_device::tier_r()
+{
+ return m_tier | 0x40;
+}
+
+void sh7014_mtu_channel_device::tier_w(uint8_t data)
+{
+ LOG("%s: tier_w<%d> %02x\n", machine().describe_context().c_str(), m_channel_id, data);
+
+ m_tier = data;
+}
+
+uint8_t sh7014_mtu_channel_device::tsr_r()
+{
+ uint8_t r;
+
+ if (m_channel_id == 0)
+ r = (m_tsr & (TSR_TGFA | TSR_TGFB | TSR_TGFC | TSR_TGFD | TSR_TCFV)) | TSR_TCFD;
+ else
+ r = m_tsr & (TSR_TGFA | TSR_TGFB | TSR_TCFV | TSR_TCFU | TSR_TCFD);
+
+ return r | (1 << 6);
+}
+
+void sh7014_mtu_channel_device::tsr_w(uint8_t data)
+{
+ LOG("%s: tsr_w<%d> %02x\n", machine().describe_context().c_str(), m_channel_id, data);
+
+ if (m_channel_id == 0) {
+ const uint8_t mask = TSR_TGFA | TSR_TGFB | TSR_TGFC | TSR_TGFD | TSR_TCFV;
+ m_tsr = (data & ~mask) | (m_tsr & data & mask);
+ } else {
+ const uint8_t mask = TSR_TGFA | TSR_TGFB | TSR_TCFV | TSR_TCFU;
+ m_tsr = (data & ~mask) | (m_tsr & data & mask) | (m_tsr & TSR_TCFD);
+ }
+}
+
+uint16_t sh7014_mtu_channel_device::tcnt_r()
+{
+ update_counter();
+ return m_tcnt;
+}
+
+void sh7014_mtu_channel_device::tcnt_w(uint16_t data)
+{
+ LOG("%s: tcnt_w<%d> %04x -> %04x\n", machine().describe_context().c_str(), m_channel_id, m_tcnt, data);
+
+ m_tcnt = data;
+}
+
+uint16_t sh7014_mtu_channel_device::tgra_r()
+{
+ return m_tgr[0];
+}
+
+void sh7014_mtu_channel_device::tgra_w(uint16_t data)
+{
+ LOG("%s: tgra_w<%d> %04x -> %04x\n", machine().describe_context().c_str(), m_channel_id, m_tgr[0], data);
+
+ m_tgr[0] = data;
+}
+
+uint16_t sh7014_mtu_channel_device::tgrb_r()
+{
+ return m_tgr[1];
+}
+
+void sh7014_mtu_channel_device::tgrb_w(uint16_t data)
+{
+ LOG("%s: tgrb_w<%d> %04x -> %04x\n", machine().describe_context().c_str(), m_channel_id, m_tgr[1], data);
+
+ m_tgr[1] = data;
+}
+
+uint16_t sh7014_mtu_channel_device::tgrc_r()
+{
+ return m_tgr[2];
+}
+
+void sh7014_mtu_channel_device::tgrc_w(uint16_t data)
+{
+ LOG("%s: tgrc_w<%d> %04x -> %04x\n", machine().describe_context().c_str(), m_channel_id, m_tgr[2], data);
+
+ m_tgr[2] = data;
+}
+
+uint16_t sh7014_mtu_channel_device::tgrd_r()
+{
+ return m_tgr[3];
+}
+
+void sh7014_mtu_channel_device::tgrd_w(uint16_t data)
+{
+ LOG("%s: tgrd_w<%d> %04x -> %04x\n", machine().describe_context().c_str(), m_channel_id, m_tgr[3], data);
+
+ m_tgr[3] = data;
+}
+
+void sh7014_mtu_channel_device::update_counter()
+{
+ if (m_clock_type != INPUT_INTERNAL)
+ return;
+
+ uint64_t cur_time = machine().time().as_ticks(clock());
+
+ if (!m_channel_active) {
+ m_last_clock_update = cur_time;
+ return;
+ }
+
+ if (m_last_clock_update == cur_time)
+ return;
+
+ uint64_t base_time = (m_last_clock_update + m_phase) >> m_clock_divider;
+ uint64_t new_time = (cur_time + m_phase) >> m_clock_divider;
+ int tt = m_tcnt + (new_time - base_time);
+ m_tcnt = tt % m_counter_cycle;
+
+ for (int i = 0; i < m_tgr_count; i++) {
+ if (!BIT(m_tsr, i) && BIT(m_tier, i) && tt >= m_tgr[i]) {
+ m_tsr |= 1 << i;
+ m_intc->set_interrupt(m_vectors[i], ASSERT_LINE);
+ }
+ }
+
+ if (!(m_tsr & TSR_TCFV) && tt >= 0x10000) {
+ // Overflowed
+ m_tsr |= TSR_TCFV;
+
+ if (m_tier & TIER_TCIEV)
+ m_intc->set_interrupt(m_vectors[VECTOR_TCIV], ASSERT_LINE);
+ } else if (m_channel_id == 0 && !(m_tsr & TSR_TCFU) && tt < 0) {
+ // Underflowed, only usable on channel 0
+ m_tsr |= TSR_TCFU;
+
+ if (m_tier & TIER_TCIEU)
+ m_intc->set_interrupt(m_vectors[VECTOR_TCIU], ASSERT_LINE);
+ }
+
+ m_last_clock_update = cur_time;
+}
+
+void sh7014_mtu_channel_device::schedule_next_event()
+{
+ m_timer->adjust(attotime::never);
+
+ if (!m_channel_active || m_clock_type != INPUT_INTERNAL) {
+ return;
+ }
+
+ uint32_t event_delay = 0xffffffff;
+ if (m_tgr_clearing >= 0 && m_tgr[m_tgr_clearing]) {
+ m_counter_cycle = m_tgr[m_tgr_clearing];
+ } else {
+ m_counter_cycle = 0x10000;
+
+ if (m_tier & TIER_TCIEV) {
+ // Try to schedule next event for when the overflow should happen if overflow interrupt is enabled
+ event_delay = m_counter_cycle - m_tcnt;
+
+ if (event_delay == 0)
+ event_delay = m_counter_cycle;
+ }
+ }
+
+ // If one of the comparison register interrupts is enabled then set the next event time to be when the next interrupt should happen
+ for (int i = 0; i < m_tgr_count; i++) {
+ if (BIT(m_tier, i)) {
+ uint32_t new_delay = 0xffffffff;
+
+ if (m_tgr[i] > m_tcnt) {
+ if (m_tcnt >= m_counter_cycle || m_tgr[i] <= m_counter_cycle)
+ new_delay = m_tgr[i] - m_tcnt;
+ } else if (m_tgr[i] <= m_counter_cycle) {
+ if (m_tcnt < m_counter_cycle)
+ new_delay = (m_counter_cycle - m_tcnt) + m_tgr[i];
+ else
+ new_delay = (0x10000 - m_tcnt) + m_tgr[i];
+ }
+
+ if (event_delay > new_delay)
+ event_delay = new_delay;
+ }
+ }
+
+ if (event_delay != 0xffffffff) {
+ const uint32_t next_event = (((((1ULL << m_clock_divider) - m_phase) >> m_clock_divider) + event_delay - 1) << m_clock_divider) + m_phase;
+ m_timer->adjust(attotime::from_ticks(next_event, clock()));
+
+ }
+}