Index: emu/cpu.c
===================================================================
--- emu/cpu.c	(revision 8967dbc82d62f1e44271e88ec794c4604d874ecd)
+++ emu/cpu.c	(revision 212bc4cfc05af2d41fae2b2719132ae52a71e45c)
@@ -70,5 +70,5 @@
 	{ 0x180000, 0x200000, 0, fpu_init, fpu_quit, fpu_exec, fpu_read, fpu_write },
 	{ 0x200000, 0x280000, 0, vid_init, vid_quit, vid_exec, vid_read, vid_write },
-	{ 0x3a0001, 0x3a4001, 0, tim_init, tim_quit, tim_exec, tim_read, tim_write },
+	{ 0x3a0001, 0x3a4001, 4, tim_init, tim_quit, tim_exec, tim_read, tim_write },
 	{ 0x3a4001, 0x3a8001, 0, lcd_init, lcd_quit, lcd_exec, lcd_read, lcd_write },
 	{ 0x3a8001, 0x3ac001, 5, ser_init, ser_quit, ser_exec, ser_read, ser_write },
Index: emu/tim.c
===================================================================
--- emu/tim.c	(revision 8967dbc82d62f1e44271e88ec794c4604d874ecd)
+++ emu/tim.c	(revision 212bc4cfc05af2d41fae2b2719132ae52a71e45c)
@@ -22,4 +22,26 @@
 #define ver3(...) _ver(tim_verbose, 2, __VA_ARGS__)
 
+typedef struct {
+	uint32_t irq;
+	bool run;
+	uint32_t latch;
+	uint32_t count;
+} state_timer;
+
+static state_timer timers[] = {
+		{.irq = 0, .run = false, .latch = 32, .count = 32},
+		{.irq = 0, .run = false, .latch = 3200, .count = 3200},
+		{.irq = 0, .run = false, .latch = 801, .count = 801}
+};
+
+#define REG_CRX 0
+#define REG_CR2 1
+#define REG_T1H	2
+#define REG_T1L 3
+#define REG_T2H 4
+#define REG_T2L 5
+#define REG_T3H 6
+#define REG_T3L 7
+
 int32_t tim_verbose = 0;
 
@@ -36,6 +58,15 @@
 bool tim_exec(void)
 {
-	ver3("tim exec");
-	return false;
+	for (int32_t i = 0; i < ARRAY_COUNT(timers); ++i) {
+		if(timers[i].run == true) {
+			--timers[i].count;
+			if(timers[i].count == 0) {
+				timers[i].count = timers[i].latch;
+				timers[i].irq = 1;
+			}
+			//ver2("tim%d %u", i, timers[i].count);
+		}
+	}
+	return timers[0].irq || timers[1].irq || timers[2].irq;
 }
 
@@ -43,5 +74,41 @@
 {
 	ver2("tim rd %u:%d", off, sz * 8);
-	return 0;
+	uint32_t rv;
+	rv = 0;
+	switch(off) {
+	case REG_CRX:
+		break;
+	case REG_CR2:
+		rv |= (timers[0].irq << 0);
+		rv |= (timers[1].irq << 1);
+		rv |= (timers[2].irq << 2);
+		ver2("tim plc %u fc %u rtc %u", timers[0].irq, timers[1].irq, timers[2].irq);
+		//ver2("tim rv %u", rv);
+		break;
+	case REG_T1H:
+		rv = 0;
+		break;
+	case REG_T1L:
+		rv = 31;
+		timers[0].irq = 0;
+		break;
+	case REG_T2H:
+		rv = 12;
+		break;
+	case REG_T2L:
+		rv = 127;
+		timers[1].irq = 0;
+		break;
+	case REG_T3H:
+		rv = 3;
+		break;
+	case REG_T3L:
+		rv = 32;
+		timers[2].irq = 0;
+		break;
+	default:
+		break;
+	}
+	return rv;
 }
 
@@ -49,3 +116,8 @@
 {
 	ver2("tim wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val);
+	if( off == 0 && (val & (1 << 7)) ) {
+		timers[0].run = true;
+		timers[1].run = true;
+		timers[2].run = true;
+	}
 }
