Add timer
diff --git a/src/Makefile b/src/Makefile
index 511afef..6ce6c27 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -8,7 +8,8 @@
 			interrupts.o \
 			log.o \
 			irq.o \
-			pic.o
+			pic.o \
+			timer.o
 CFLAGS = -nostdlib -nostdinc -fno-builtin -fno-stack-protector -ffreestanding -m32 -O2 -g
 LDFLAGS = -Tlink.ld -melf_i386
 ASMFLAGS = -felf
diff --git a/src/descriptor_tables.c b/src/descriptor_tables.c
index a9aa521..86e554a 100644
--- a/src/descriptor_tables.c
+++ b/src/descriptor_tables.c
@@ -1,6 +1,7 @@
 #include "descriptor_tables.h"
 #include "vga.h"
 #include "io.h"
+#include "log.h"
 #include "pic.h"
 
 extern void gdt_flush(uint gdt);
@@ -65,13 +66,16 @@
 
 	memset(&idt_entries, 0, sizeof(idt_entries));
 
-	vga_write("sizeof(idt_entries) = ");
-	vga_putx(sizeof(idt_entries));
-	vga_put('\n');
+	// Remap PIC
+	pic_remap();
 
-	vga_write("isr0 = ");
-	vga_putx((uint)isrs[0]);
-	vga_put('\n');
+	vga_set_color(CYAN, BLACK);
+	for (int i = 0; i < 16; i++)
+	{
+		kprintf("Setting gate irq=%d,\tint=%d\n", i, IRQ_TO_INT(i));
+		idt_set_gate(IRQ_TO_INT(i), (uint)irqs[i], 0x08, 0x8e);
+	}
+	vga_set_color(WHITE, BLACK);
 
 	for (int i = 0; i < 32; i++)
 	{
@@ -80,25 +84,6 @@
 
 	idt_flush((uint)&idt_pointer);
 
-	// Remap PIC
-	
-	outb(PIC1_COMMAND, 0x11);
-	outb(PIC2_COMMAND, 0x11);
-
-	outb(PIC1_DATA, 0x20);
-	outb(PIC2_DATA, 0x28);
-	outb(PIC1_DATA, 0x04);
-	outb(PIC2_DATA, 0x02);
-	outb(PIC1_DATA, 0x01);
-	outb(PIC2_DATA, 0x01);
-	outb(PIC1_DATA, 0);
-	outb(PIC2_DATA, 0);
-
-	for (int i = 0; i < 16; i++)
-	{
-		idt_set_gate(i + 32, (uint)irqs[i], 0x08, 0x8e);
-	}
-
 	vga_write("IDT Initialized!\n");
 }
 
diff --git a/src/idt.s b/src/idt.s
index 756eed4..6ded21b 100644
--- a/src/idt.s
+++ b/src/idt.s
@@ -61,10 +61,10 @@
 isr_common:
 	pusha						; Save all registers
 
-	mov ax, ds
+	mov ax, ds					; Save data segment
 	push eax
 
-	mov ax, 0x10
+	mov ax, 0x10 				; New segments
 	mov ds, ax
 	mov es, ax
 	mov fs, ax
@@ -72,7 +72,7 @@
 
 	call isr_handler
 
-	pop eax
+	pop eax						; Reset segments
 	mov ds, ax
 	mov es, ax
 	mov fs, ax
diff --git a/src/main.c b/src/main.c
index f5b6200..8d2783f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,6 +1,8 @@
 #include "vga.h"
 #include "log.h"
+#include "io.h"
 #include "descriptor_tables.h"
+#include "timer.h"
 
 int kmain(void *mboot)
 {
@@ -15,7 +17,9 @@
 	vga_write("Setup complete!\n");
 	vga_set_color(WHITE, BLACK);
 
-	kassert(0, "should fail");
+	asm volatile("sti");
+
+	init_timer(50);
 
 	while (1)
 	{}
diff --git a/src/pic.c b/src/pic.c
index 693c747..f5355a8 100644
--- a/src/pic.c
+++ b/src/pic.c
@@ -1,12 +1,27 @@
 #include "pic.h"
+#include "log.h"
 #include "io.h"
 
+#define ICW1_ICW4	0x01		/* ICW4 (not) needed */
+#define ICW1_SINGLE	0x02		/* Single (cascade) mode */
+#define ICW1_INTERVAL4	0x04		/* Call address interval 4 (8) */
+#define ICW1_LEVEL	0x08		/* Level triggered (edge) mode */
+#define ICW1_INIT	0x10		/* Initialization - required! */
+ 
+#define ICW4_8086	0x01		/* 8086/88 (MCS-80/85) mode */
+#define ICW4_AUTO	0x02		/* Auto (normal) EOI */
+#define ICW4_BUF_SLAVE	0x08		/* Buffered mode/slave */
+#define ICW4_BUF_MASTER	0x0C		/* Buffered mode/master */
+#define ICW4_SFNM	0x10		/* Special fully nested (not) */
+
+
 void (* interrupt_handlers[256])(struct registers);
 
 void pic_send_eoi(uchar interrupt)
 {
-	if (interrupt >= 40)
+	if (interrupt >= IRQ_TO_INT(8))
 		outb(PIC2_COMMAND, PIC_EOI);
+
 	outb(PIC1_COMMAND, PIC_EOI);
 }
 
@@ -14,6 +29,8 @@
 {
 	pic_send_eoi(regs.interrupt_number);
 
+	kprintf("irq_handler called with interrupt %d\n", regs.interrupt_number);
+
 	if (interrupt_handlers[regs.interrupt_number])
 		interrupt_handlers[regs.interrupt_number](regs);
 }
@@ -22,3 +39,19 @@
 {
 	interrupt_handlers[interrupt] = handler;
 }
+
+void pic_remap()
+{
+    outb(0x20, 0x11);
+    outb(0xA0, 0x11);
+    outb(0x21, 0x20);
+    outb(0xA1, 0x28);
+    outb(0x21, 0x04);
+    outb(0xA1, 0x02);
+    outb(0x21, 0x01);
+    outb(0xA1, 0x01);
+    outb(0x21, 0x0);
+    outb(0xA1, 0x0);
+
+	return;
+}
diff --git a/src/pic.h b/src/pic.h
index ad44216..a8b6d99 100644
--- a/src/pic.h
+++ b/src/pic.h
@@ -12,5 +12,9 @@
 
 #define PIC_EOI 0x20 // End of input
 
+#define IRQ_TO_INT(irq) ((irq) + 32)
+
 void pic_send_eoi(uchar interrupt);
 void add_interrupt_handler(uchar interrupt, void (* handler)(struct registers));
+
+void pic_remap();
diff --git a/src/timer.c b/src/timer.c
new file mode 100644
index 0000000..72ff1c6
--- /dev/null
+++ b/src/timer.c
@@ -0,0 +1,33 @@
+#include "timer.h"
+#include "pic.h"
+#include "log.h"
+#include "registers.h"
+#include "io.h"
+
+static ulong tick = 0;
+
+static void timer_cb(struct registers regs)
+{
+	kprintf("Timer tick %d\n", tick++);
+}
+
+void init_timer(uint hz)
+{
+	add_interrupt_handler(IRQ_TO_INT(0), timer_cb);
+
+	uint divisor = TIMER_FREQ / hz;
+
+	kprintf("Divisor is %d\n", divisor);
+
+	outb(0x43, 0x36);
+	io_wait();
+	uchar l = divisor & 0xff,
+		h = (divisor >> 8) & 0xff;
+
+	outb(0x40, l);
+	io_wait();
+	outb(0x40, h);
+	io_wait();
+
+	kprintf("Initialized timer\n");
+}
diff --git a/src/timer.h b/src/timer.h
new file mode 100644
index 0000000..50297c4
--- /dev/null
+++ b/src/timer.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "kint.h"
+
+#define TIMER_FREQ 1193180
+
+void init_timer(uint hz);
diff --git a/src/vga.c b/src/vga.c
index 11f3b9e..06fe608 100644
--- a/src/vga.c
+++ b/src/vga.c
@@ -93,11 +93,12 @@
 	memset(str, 0, 48);
 	uint i = 0;
 
-	while (d > 0 && i < 48) // should never be more than 48 digits anyway
+	do
 	{
 		str[i++] = (d % 10) + '0';
 		d /= 10;
 	}
+	while (d > 0 && i < 48); // should never be more than 48 digits anyway
 
 	for (uint j = i; j; j--)
 	{