forked from lualiliu/esp32-gameboy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtimer.cpp
81 lines (61 loc) · 1.63 KB
/
timer.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// If INTER_MODULE_OPT macro is defined,
// this file is included into cpu.cpp
// to make inter module optimizations possible
#ifndef INTER_MODULE_OPT
#include "timer.h"
#include "cpu.h"
#include "interrupt.h"
static unsigned int prev_time;
static unsigned int elapsed;
static unsigned int ticks;
static unsigned char tac;
static unsigned int started;
static unsigned int speed;
static unsigned int counter;
static unsigned int divider;
static unsigned int modulo;
void timer_set_div(unsigned char v) {
(void)v;
divider = 0;
}
unsigned char timer_get_div(void) { return divider; }
void timer_set_counter(unsigned char v) { counter = v; }
unsigned char timer_get_counter(void) { return counter; }
void timer_set_modulo(unsigned char v) { modulo = v; }
unsigned char timer_get_modulo(void) { return modulo; }
void timer_set_tac(unsigned char v) {
int speeds[] = {64, 1, 4, 16};
tac = v;
started = v & 4;
speed = speeds[v & 3];
}
unsigned char timer_get_tac(void) { return tac; }
static void timer_tick(void) {
/* 1/262144Hz has elapsed */
ticks++;
/* Divider updates at 16384Hz */
if (ticks == 16) {
divider++;
ticks = 0;
}
if (!started) return;
if (ticks == speed) {
counter++;
ticks = 0;
}
if (counter == 0x100) {
interrupt(INTR_TIMER);
counter = modulo;
}
}
void timer_cycle(unsigned int cycles) {
/* The amount of ticks since we last ran */
unsigned int delta = cycles - prev_time;
prev_time = cycles;
elapsed += delta * 4; /* 4 cycles to a timer tick */
if (elapsed >= 16) {
timer_tick();
elapsed -= 16; /* keep track of the time overflow */
}
}
#endif // INTER_MODULE_OPT