summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSegher Boessenkool <segher@kernel.crashing.org>2010-02-13 13:04:11 +0100
committerSegher Boessenkool <segher@kernel.crashing.org>2010-02-13 13:04:11 +0100
commit381a00b5e4da7b8b64f8ed9f064e55288acd07d9 (patch)
tree81f71ba38eee0b606c8b8f04b9d947fa78cd23db
parent8f4efcb33af7a85aadf65e2bb8d5199e8e09f02f (diff)
Flesh out the timer stuff; hook up controller input to it.
-rw-r--r--emu.c37
-rw-r--r--timer.c73
-rw-r--r--timer.h16
3 files changed, 99 insertions, 27 deletions
diff --git a/emu.c b/emu.c
index 81c3d70..d3d8b4d 100644
--- a/emu.c
+++ b/emu.c
@@ -5,8 +5,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
-#include <sys/time.h>
+#include <unistd.h> // for usleep
#include "types.h"
#include "disas.h"
@@ -686,13 +685,7 @@ static u32 last_retrace_time = 0;
static void do_idle(void)
{
- u32 now;
- struct timeval tv;
-
-// printf("### IDLE ###\n");
-
- gettimeofday(&tv, 0);
- now = 1000000*tv.tv_sec + tv.tv_usec;
+ u32 now = timer_now();
if (now < last_retrace_time + PERIOD) {
// printf(" sleeping %dus\n", last_retrace_time + PERIOD - now);
usleep(last_retrace_time + PERIOD - now);
@@ -701,11 +694,7 @@ static void do_idle(void)
u16 get_video_line(void)
{
- u32 now;
- struct timeval tv;
-
- gettimeofday(&tv, 0);
- now = 1000000*tv.tv_sec + tv.tv_usec;
+ u32 now = timer_now();
return (now - last_retrace_time) * 625 * FREQ / 2 / 1000000; // 525 for NTSC
}
@@ -736,8 +725,9 @@ static void run_main(void)
}
if (timer_triggered != timer_handled) {
+ timer_run();
timer_handled++;
- timer_set();
+ timer_set(1000000/250);
} else
do_idle();
}
@@ -815,15 +805,18 @@ static void do_controller(void)
} while (key);
}
+struct timer timer_controller = {
+ .name = "controller",
+ .time = 20000,
+ .interval = 20000,
+ .run = do_controller
+};
+
static void run(void)
{
run_main();
- struct timeval tv;
- u32 now;
-
- gettimeofday(&tv, 0);
- now = 1000000*tv.tv_sec + tv.tv_usec;
+ u32 now = timer_now();
if (now - last_retrace_time >= PERIOD) {
static int count = 0;
@@ -842,8 +835,6 @@ static void run(void)
last_retrace_time = now;
- do_controller();
-
mem[0x3d22] |= 2; // TMB2 FIXME: freq
if (do_extint1) {
@@ -884,6 +875,8 @@ void emu(void)
memset(reg, 0, sizeof reg);
reg[7] = mem[0xfff7]; // reset vector
+ timer_add(&timer_controller);
+
for (;;)
run();
}
diff --git a/timer.c b/timer.c
index b7f1021..0e2c599 100644
--- a/timer.c
+++ b/timer.c
@@ -5,6 +5,7 @@
#include <sys/time.h>
#include <signal.h>
#include <unistd.h>
+#include <stdio.h>
#include "types.h"
#include "platform.h"
@@ -14,12 +15,23 @@
volatile u32 timer_triggered;
-void timer_set(void)
+static struct timer *timers;
+static u32 timer_time;
+
+u32 timer_now(void)
+{
+ struct timeval tv;
+
+ gettimeofday(&tv, 0);
+ return 1000000*tv.tv_sec + tv.tv_usec;
+}
+
+void timer_set(u32 usecs)
{
struct itimerval it;
- it.it_value.tv_sec = 0;
- it.it_value.tv_usec = 1000000/250;
+ it.it_value.tv_sec = usecs / 1000000;
+ it.it_value.tv_usec = usecs % 1000000;
it.it_interval.tv_sec = 0;
it.it_interval.tv_usec = 0;
@@ -28,6 +40,57 @@ void timer_set(void)
fatal("setitimer failed");
}
+void timer_debug(void)
+{
+ printf("timer head = %u, now = %u\n", timer_time, timer_now());
+ struct timer *timer;
+ for (timer = timers; timer; timer = timer->next)
+ printf("timer \"%s\" %dus\n", timer->name, timer->time);
+}
+
+void timer_add(struct timer *timer)
+{
+ u32 time = timer_now() - timer_time + timer->time;
+ struct timer **p = &timers;
+
+ while (*p && (*p)->time <= time) {
+ time -= (*p)->time;
+ p = &(*p)->next;
+ }
+
+ timer->next = *p;
+ *p = timer;
+ timer->time = time;
+ if (timer->next)
+ timer->next->time -= time;
+}
+
+void timer_run(void)
+{
+ u32 now = timer_now();
+ u32 elapsed = now - timer_time;
+
+ struct timer *timer;
+ while ((timer = timers) && timer->time <= elapsed) {
+ timers = timer->next;
+ timer_time += timer->time;
+ elapsed -= timer->time;
+
+printf("running timer \"%s\" (%u)\n", timer->name, now);
+ if (timer->run)
+ timer->run();
+
+ if (timer->interval) {
+ timer->time = timer->interval;
+ timer_add(timer);
+ }
+ }
+
+ if (timer)
+ timer->time -= elapsed;
+ timer_time = now;
+}
+
static void alarm_handler(int signo, siginfo_t *si, void *uc)
{
timer_triggered++;
@@ -42,5 +105,7 @@ void timer_init(void)
sa.sa_flags = SA_SIGINFO;
sigaction(SIGALRM, &sa, 0);
- timer_set();
+ timer_time = timer_now();
+
+ timer_set(1);
}
diff --git a/timer.h b/timer.h
index 4d43789..a426b9e 100644
--- a/timer.h
+++ b/timer.h
@@ -9,7 +9,21 @@
extern volatile u32 timer_triggered;
+struct timer {
+ const char *name;
+ u32 time;
+ u32 interval;
+ void (*run)(void);
+ struct timer *next;
+};
+
+void timer_debug(void);
void timer_init(void);
-void timer_set(void);
+void timer_add(struct timer *timer);
+void timer_run(void);
+u32 timer_now(void);
+
+// XXX: temp
+void timer_set(u32 usecs);
#endif