diff options
author | Segher Boessenkool <segher@kernel.crashing.org> | 2010-02-13 13:04:11 +0100 |
---|---|---|
committer | Segher Boessenkool <segher@kernel.crashing.org> | 2010-02-13 13:04:11 +0100 |
commit | 381a00b5e4da7b8b64f8ed9f064e55288acd07d9 (patch) | |
tree | 81f71ba38eee0b606c8b8f04b9d947fa78cd23db | |
parent | 8f4efcb33af7a85aadf65e2bb8d5199e8e09f02f (diff) |
Flesh out the timer stuff; hook up controller input to it.
-rw-r--r-- | emu.c | 37 | ||||
-rw-r--r-- | timer.c | 73 | ||||
-rw-r--r-- | timer.h | 16 |
3 files changed, 99 insertions, 27 deletions
@@ -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(); } @@ -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); } @@ -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 |