diff options
author | 2017-04-21 14:18:58 -0400 | |
---|---|---|
committer | 2017-04-21 14:52:36 -0400 | |
commit | 9f121349908400b7412e353712147b45ee64dd67 (patch) | |
tree | 30c9a1f4b20e58a491a112aa1332dfb467ee65ce /src/emu/device.cpp | |
parent | 735ab4f3551840a5c642c2ae719fdd578e9fc154 (diff) |
Mechanism for devices to generate clocks for other devices
- Have set_unscaled_clock and set_clock_scale not call notify_clock_changed unless the device has been started.
- Owner-derived clocks are now updated whenever the owner's clock is changed, including at configuration time. This simplifies the configuration of various NES clones.
- Add clock_update_delegate type to represent device-generated clock outputs that may be dynamically modified. The model implementation of this is the CLK output in I8085A.
Diffstat (limited to 'src/emu/device.cpp')
-rw-r--r-- | src/emu/device.cpp | 53 |
1 files changed, 44 insertions, 9 deletions
diff --git a/src/emu/device.cpp b/src/emu/device.cpp index 6a137e475a8..60772fd2369 100644 --- a/src/emu/device.cpp +++ b/src/emu/device.cpp @@ -217,15 +217,13 @@ std::string device_t::parameter(const char *tag) const void device_t::static_set_clock(device_t &device, u32 clock) { + device.m_configured_clock = clock; + // derive the clock from our owner if requested if ((clock & 0xff000000) == 0xff000000) - { - assert(device.m_owner != nullptr); - clock = device.m_owner->m_configured_clock * ((clock >> 12) & 0xfff) / ((clock >> 0) & 0xfff); - } - - device.m_clock = device.m_unscaled_clock = device.m_configured_clock = clock; - device.m_attoseconds_per_clock = (clock == 0) ? 0 : HZ_TO_ATTOSECONDS(clock); + device.calculate_derived_clock(); + else + device.set_unscaled_clock(clock); } @@ -297,10 +295,21 @@ void device_t::reset() void device_t::set_unscaled_clock(u32 clock) { + // do nothing if no actual change + if (clock == m_unscaled_clock) + return; + m_unscaled_clock = clock; m_clock = m_unscaled_clock * m_clock_scale; m_attoseconds_per_clock = (m_clock == 0) ? 0 : HZ_TO_ATTOSECONDS(m_clock); - notify_clock_changed(); + + // recalculate all derived clocks + for (device_t &child : subdevices()) + child.calculate_derived_clock(); + + // if the device has already started, make sure it knows about the new clock + if (m_started) + notify_clock_changed(); } @@ -311,10 +320,36 @@ void device_t::set_unscaled_clock(u32 clock) void device_t::set_clock_scale(double clockscale) { + // do nothing if no actual change + if (clockscale == m_clock_scale) + return; + m_clock_scale = clockscale; m_clock = m_unscaled_clock * m_clock_scale; m_attoseconds_per_clock = (m_clock == 0) ? 0 : HZ_TO_ATTOSECONDS(m_clock); - notify_clock_changed(); + + // recalculate all derived clocks + for (device_t &child : subdevices()) + child.calculate_derived_clock(); + + // if the device has already started, make sure it knows about the new clock + if (m_started) + notify_clock_changed(); +} + + +//------------------------------------------------- +// calculate_derived_clock - derive the device's +// clock from its owner, if so configured +//------------------------------------------------- + +void device_t::calculate_derived_clock() +{ + if ((m_configured_clock & 0xff000000) == 0xff000000) + { + assert(m_owner != nullptr); + set_unscaled_clock(m_owner->m_clock * ((m_configured_clock >> 12) & 0xfff) / ((m_configured_clock >> 0) & 0xfff)); + } } |