starting to separate platform-specific code to facilitate a PC build
[gbajam22] / src / gba / timer.c
diff --git a/src/gba/timer.c b/src/gba/timer.c
new file mode 100644 (file)
index 0000000..f4b0c7a
--- /dev/null
@@ -0,0 +1,55 @@
+#include "intr.h"
+#include "timer.h"
+
+#define F_CLK  16780000
+/* clock is 16.78MHz
+ * - no prescale: 59.595ns
+ * - prescale 64: 3.814us
+ * - prescale 256: 15.256us
+ * - prescale 1024: 61.025us
+ */
+
+static void timer_intr(void);
+
+void init_timer(int tm, unsigned long rate_hz, void (*intr)(void))
+{
+       static const unsigned long clk[] = {F_CLK, F_CLK / 64, F_CLK / 256, F_CLK / 1024};
+       unsigned long count;
+       int pscl = 0;
+
+       do {
+               count = clk[pscl] / rate_hz;
+       } while(count >= 65536 && ++pscl < 4);
+
+       if(pscl >= 4) return;   /* impossible rate */
+
+       REG_TMCNT_H(tm) = 0;
+       REG_TMCNT_L(tm) = 65536 - count;
+       if(intr) {
+               interrupt(INTR_TIMER0 + tm, intr);
+               unmask(INTR_TIMER0 + tm);
+               REG_TMCNT_H(tm) = TMCNT_IE;
+       }
+       REG_TMCNT_H(tm) |= TMCNT_EN | pscl;
+}
+
+void reset_msec_timer(void)
+{
+       REG_TM0CNT_H &= ~TMCNT_EN;
+       interrupt(INTR_TIMER0, timer_intr);
+       timer_msec = 0;
+       REG_TM0CNT_L = 65535 - 16779;
+       REG_TM0CNT_H |= TMCNT_IE | TMCNT_EN;
+       unmask(INTR_TIMER0);
+}
+
+void delay(unsigned long ms)
+{
+       unsigned long end = timer_msec + ms;
+       while(timer_msec < end);
+}
+
+static void timer_intr(void)
+{
+       timer_msec++;
+}