summaryrefslogtreecommitdiff
path: root/Source/Kernel/Devices/Timer.class.cpp
blob: 6e755b0764063cd053b4c692afeb8724cf5055b2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include "Timer.class.h"

#include <DeviceManager/Dev.ns.h>
#include <DeviceManager/Time.ns.h>
#include <DeviceManager/Disp.ns.h>

using namespace Sys; //For outb

Timer::Timer(u8int frequency) {
	m_ticks = 0;
	m_seconds = 0;

	Dev::requestIRQ(this, 0);
	Time::setTimer(this);
	setFrequency(frequency);
}

String Timer::getClass() {
	return String("timer");
}

String Timer::getName() {
	return String("Programmable interrupt timer");
}

void Timer::setFrequency(u8int frequency) {
	m_frequency = frequency;
	u32int divisor = 1193180 / (u32int)frequency;
	outb(0x43, 0x36);
	
	u8int l = (u8int)(divisor & 0xFF);
	u8int h = (u8int)( (divisor >> 8) & 0xFF);

	outb(0x40, l);
	outb(0x40, h);
}

u32int Timer::uptime() {
	return m_seconds;
}

u32int Timer::time() {
	return (m_seconds * 1000) + ((m_ticks * 1000) / m_frequency);
}

void Timer::handleIRQ(registers_t registers, int irq) {
	//char what[] = "-\\|/";
	if (irq == 0) {
		m_ticks++;
		if (m_ticks == m_frequency) {
			m_ticks = 0;
			m_seconds++;
		}
		//Disp::putChar(0, 0, what[m_ticks / (m_frequency / 4)], 0x07);
		//Switching task is called in IRQ::interrupt_handler
	}
}