mirror of
https://github.com/jscrane/r65emu.git
synced 2026-04-26 22:18:15 +00:00
* replace SimpleTimer with DeltaQueue * pull Arduino timer methods up * update library dependencies
89 lines
2.1 KiB
C++
89 lines
2.1 KiB
C++
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include <stdarg.h>
|
|
|
|
#include "machine.h"
|
|
#include "memory.h"
|
|
#include "CPU.h"
|
|
#include "deltaq.h"
|
|
|
|
Machine *_machine;
|
|
|
|
static DeltaQueue timers;
|
|
|
|
Machine::Machine(CPU &cpu): _cpu(cpu) {
|
|
_cpu_debug = debug_never;
|
|
_machine = this;
|
|
}
|
|
|
|
void Machine::checkpoint(Checkpoint &s) {
|
|
unsigned ds = 0;
|
|
for (unsigned i = 0; i < Memory::address_size; i += ds) {
|
|
Memory::Device *dev = _cpu.memory().get(i);
|
|
dev->checkpoint(s);
|
|
ds = _cpu.memory().pages(dev->extent());
|
|
}
|
|
_cpu.checkpoint(s);
|
|
}
|
|
|
|
void Machine::restore(Checkpoint &s) {
|
|
unsigned ds = 0;
|
|
for (unsigned i = 0; i < Memory::address_size; i += ds) {
|
|
Memory::Device *dev = _cpu.memory().get(i);
|
|
dev->restore(s);
|
|
ds = _cpu.memory().pages(dev->extent());
|
|
}
|
|
_cpu.restore(s);
|
|
}
|
|
|
|
void Machine::run(uint32_t clock_speed_hz) {
|
|
|
|
uint32_t start_time = microseconds();
|
|
|
|
timers.update(start_time);
|
|
|
|
for (uint8_t i = 0; i < num_pollable; i++)
|
|
devices[i]->poll();
|
|
|
|
#if DEBUGGING & DEBUG_CPU
|
|
if (_cpu_debug()) {
|
|
char buf[256];
|
|
DBG_CPU(_cpu.status(buf, sizeof(buf)));
|
|
}
|
|
_cpu.run(1);
|
|
#else
|
|
uint32_t start_cycles = _cpu.cycles();
|
|
if (clock_speed_hz == CLK_MAX)
|
|
_cpu.run(_batch_size);
|
|
else {
|
|
_cpu.run(_batch_size);
|
|
uint32_t cycles_run = _cpu.cycles() - start_cycles;
|
|
if (cycles_run > 0) {
|
|
uint32_t target_cycles = clock_speed_hz / (1000000 / TIME_SLICE);
|
|
uint32_t next_batch = (target_cycles * _batch_size) / cycles_run;
|
|
_batch_size = (_batch_size + next_batch) / 2;
|
|
|
|
if (_batch_size > CPU_INSTRUCTIONS) _batch_size = CPU_INSTRUCTIONS;
|
|
else if (_batch_size == 0) _batch_size = 1;
|
|
}
|
|
|
|
uint32_t elapsed = microseconds() - start_time;
|
|
if (elapsed < TIME_SLICE)
|
|
sleep(TIME_SLICE - elapsed);
|
|
}
|
|
_speed = (_cpu.cycles() - start_cycles) * (1000000 / (microseconds() - start_time));
|
|
#endif
|
|
}
|
|
|
|
int8_t Machine::interval_timer(uint32_t interval, std::function<void(void)> cb) {
|
|
return timers.setInterval(interval, cb);
|
|
}
|
|
|
|
int8_t Machine::oneshot_timer(uint32_t interval, std::function<void(void)> cb) {
|
|
return timers.setTimeout(interval, cb);
|
|
}
|
|
|
|
void Machine::cancel_timer(int8_t timer) {
|
|
timers.cancel(timer);
|
|
}
|