mirror of
https://github.com/mauiaaron/apple2.git
synced 2024-06-26 00:29:27 +00:00
new cpu throttling routine
This commit is contained in:
parent
55cb51359e
commit
8bd46f494f
102
src/timing.c
Normal file
102
src/timing.c
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Apple // emulator for Linux
|
||||
*
|
||||
* CPU Timing Support.
|
||||
*
|
||||
* Mostly this adds support for specifically throttling the emulator speed to
|
||||
* match a 1.02MHz Apple //e.
|
||||
*
|
||||
* Added 2013 by Aaron Culliney
|
||||
*
|
||||
*/
|
||||
|
||||
#include "timing.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#define DEFAULT_SLEEP 60
|
||||
|
||||
static unsigned int sleep_hz = DEFAULT_SLEEP; // sleep intervals per sec
|
||||
static unsigned long cpu_target_hz = APPLE2_HZ; // target clock speed
|
||||
static unsigned long cycles_interval = APPLE2_HZ / DEFAULT_SLEEP; // Number of 65c02 instructions to be executed at sleep_hz
|
||||
static unsigned long processing_interval = NANOSECONDS / DEFAULT_SLEEP; // Number of nanoseconds in sleep_hz intervals
|
||||
|
||||
static struct timespec deltat, t0, ti, tj;
|
||||
static unsigned long cycle=0;
|
||||
static long sleep_adjust=0;
|
||||
static long sleep_adjust_inc=0;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// assuming end > start, returns end - start
|
||||
static inline struct timespec timespec_diff (struct timespec start, struct timespec end) {
|
||||
struct timespec t;
|
||||
|
||||
// assuming time_t is signed ...
|
||||
if (end.tv_nsec < start.tv_nsec) {
|
||||
t.tv_sec = end.tv_sec - start.tv_sec - 1;
|
||||
t.tv_nsec = NANOSECONDS + end.tv_nsec - start.tv_nsec;
|
||||
} else {
|
||||
t.tv_sec = end.tv_sec - start.tv_sec;
|
||||
t.tv_nsec = end.tv_nsec - start.tv_nsec;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static inline long timespec_nsecs (struct timespec t) {
|
||||
return t.tv_sec*NANOSECONDS + t.tv_nsec;
|
||||
}
|
||||
|
||||
void timing_initialize () {
|
||||
clock_gettime(CLOCK_MONOTONIC, &t0);
|
||||
ti=t0;
|
||||
}
|
||||
|
||||
void timing_set_cpu_target_hz (unsigned long hz) {
|
||||
cpu_target_hz = hz;
|
||||
}
|
||||
|
||||
void timing_set_sleep_hz (unsigned int hz) {
|
||||
sleep_hz = hz;
|
||||
}
|
||||
|
||||
/*
|
||||
* Throttles the 65c02 CPU down to a target frequency of X.
|
||||
* Currently set to target the Apple //e @ 1.02MHz
|
||||
*/
|
||||
void timing_throttle () {
|
||||
++cycle;
|
||||
|
||||
if ((cycle%cycles_interval) == 0) {
|
||||
clock_gettime(CLOCK_MONOTONIC, &tj);
|
||||
deltat = timespec_diff(ti, tj);
|
||||
ti=tj;
|
||||
if (deltat.tv_sec != 0) {
|
||||
// severely lagging ...
|
||||
} else {
|
||||
deltat.tv_nsec = processing_interval - deltat.tv_nsec + sleep_adjust_inc;
|
||||
nanosleep(&deltat, NULL); // NOTE: spec says will return right away if deltat.tv_nsec value < 0 ...
|
||||
ti.tv_nsec += deltat.tv_nsec;
|
||||
}
|
||||
|
||||
if ((cycle%cpu_target_hz) == 0) {
|
||||
clock_gettime(CLOCK_MONOTONIC, &tj);
|
||||
|
||||
deltat = timespec_diff(t0, tj);
|
||||
struct timespec t = (struct timespec){.tv_sec=1, .tv_nsec=0};
|
||||
|
||||
long adj = (deltat.tv_sec == 0)
|
||||
? timespec_nsecs(timespec_diff(deltat, t))
|
||||
: -1 * timespec_nsecs(timespec_diff(t, deltat));
|
||||
|
||||
sleep_adjust += adj;
|
||||
sleep_adjust_inc = sleep_adjust/sleep_hz;
|
||||
|
||||
t0=tj;
|
||||
ti=t0;
|
||||
}
|
||||
}
|
||||
}
|
27
src/timing.h
Normal file
27
src/timing.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Apple // emulator for Linux
|
||||
*
|
||||
* CPU Timing Support.
|
||||
*
|
||||
* Mostly this adds support for specifically throttling the emulator speed to
|
||||
* match a 1.02MHz Apple //e.
|
||||
*
|
||||
* Added 2013 by Aaron Culliney
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _TIMING_H_
|
||||
#define _TIMING_H_
|
||||
|
||||
#define APPLE2_HZ 1020000
|
||||
#define NANOSECONDS 1000000000
|
||||
|
||||
void timing_set_cpu_target_hz (unsigned long hz);
|
||||
|
||||
void timing_set_sleep_hz (unsigned int hz);
|
||||
|
||||
void timing_initialize ();
|
||||
|
||||
void timing_throttle ();
|
||||
|
||||
#endif // whole file
|
Loading…
Reference in New Issue
Block a user