A timed device is a device which executes so many ticks in a given time interval. This is the core of the emulator timing mechanics. This basic implementation does not run freely and instead will skip cycles if it is running too fast This allows a parent timer to run at a faster rate without causin
| 28 | * @author Brendan Robert (BLuRry) brendan.robert@gmail.com |
| 29 | */ |
| 30 | public abstract class TimedDevice extends Device { |
| 31 | // From the holy word of Sather 3:5 (Table 3.1) :-) |
| 32 | // This average speed averages in the "long" cycles |
| 33 | public static final long NTSC_1MHZ = 1020484L; |
| 34 | public static final long PAL_1MHZ = 1015625L; |
| 35 | public static final long SYNC_FREQ_HZ = 60; |
| 36 | public static final double NANOS_PER_SECOND = 1000000000.0; |
| 37 | public static final long NANOS_PER_MILLISECOND = 1000000L; |
| 38 | public static final long SYNC_SLOP = NANOS_PER_MILLISECOND * 10L; // 10ms slop for synchronization |
| 39 | public static int TEMP_SPEED_MAX_DURATION = 1000000; |
| 40 | @ConfigurableField(name = "Speed", description = "(Percentage)") |
| 41 | public int speedRatio = 100; |
| 42 | @ConfigurableField(name = "Max speed") |
| 43 | public boolean forceMaxspeed = false; |
| 44 | public boolean maxspeed = false; |
| 45 | private long cyclesPerSecond = defaultCyclesPerSecond(); |
| 46 | private int cycleTimer = 0; |
| 47 | private int tempSpeedDuration = 0; |
| 48 | private long nanosPerInterval; // How long to wait between pauses |
| 49 | private long cyclesPerInterval; // How many cycles to wait until a pause interval |
| 50 | private long nextSync = System.nanoTime(); // When is the next sync interval supposed to finish? |
| 51 | protected Runnable unthrottledTick = () -> super.doTick(); |
| 52 | Long waitUntil = null; |
| 53 | protected Runnable throttledTick = () -> { |
| 54 | if (waitUntil == null || System.nanoTime() >= waitUntil) { |
| 55 | super.doTick(); |
| 56 | waitUntil = calculateResyncDelay(); |
| 57 | } |
| 58 | }; |
| 59 | protected final Runnable tickHandler; |
| 60 | |
| 61 | /** |
| 62 | * Creates a new instance of TimedDevice, setting default speed |
| 63 | * Protected as overriding the tick handler should only done |
| 64 | * for the independent timed device |
| 65 | */ |
| 66 | protected TimedDevice(boolean throttleUsingTicks) { |
| 67 | super(); |
| 68 | setSpeedInHz(defaultCyclesPerSecond()); |
| 69 | tickHandler = throttleUsingTicks ? throttledTick : unthrottledTick; |
| 70 | resetSyncTimer(); |
| 71 | } |
| 72 | |
| 73 | public TimedDevice() { |
| 74 | this(true); |
| 75 | } |
| 76 | |
| 77 | @Override |
| 78 | public final void doTick() { |
| 79 | tickHandler.run(); |
| 80 | } |
| 81 | |
| 82 | public final void resetSyncTimer() { |
| 83 | nextSync = System.nanoTime() + nanosPerInterval; |
| 84 | cycleTimer = 0; |
| 85 | } |
| 86 | |
| 87 | @Override |
nothing calls this directly
no test coverage detected