#include #include "Timer.h" #include "Pic.h" #include "../util/Asm.h" #define PIT_FREQ 1193181 #define PIT_MODE_CH0 0x00 #define PIT_MODE_CH1 0x40 #define PIT_MODE_CH2 0x80 #define PIT_MODE_ACCESS_LO 0x10 #define PIT_MODE_ACCESS_HI 0x20 #define PIT_MODE_ACCESS_LOHI 0x30 #define PIT_MODE_M0 0x00 #define PIT_MODE_M1 0x02 #define PIT_MODE_M2 0x04 #define PIT_MODE_M3 0x06 #define PIT_MODE_M4 0x08 #define PIT_MODE_M5 0x0a #define PIT_MODE_BIN 0x00 #define PIT_MODE_BCD 0x01 #define PIT_REG_CH0 0x40 #define PIT_REG_CH1 0x41 #define PIT_REG_CH2 0x42 #define PIT_REG_MODE 0x43 Timer timer; void timerISR() { timer.update(); } Timer::Timer() { _go32_dpmi_get_protected_mode_interrupt_vector(8, &_oldIsr); _newIsr.pm_offset = reinterpret_cast(timerISR); _newIsr.pm_selector = _go32_my_cs(); _go32_dpmi_allocate_iret_wrapper(&_newIsr); _go32_dpmi_set_protected_mode_interrupt_vector(8, &_newIsr); } Timer::~Timer() { setDivider(65535); _go32_dpmi_set_protected_mode_interrupt_vector(8, &_oldIsr); _go32_dpmi_free_iret_wrapper(&_newIsr); } void Timer::update() { _ticks++; if (_callback) _callback(); _elapsed += _div; if (_elapsed >= 65535) { _elapsed -= 65535; // TODO call old isr // Documentation is kind of nonexistant so we will not call the handler for now Pic::clearInterrupt(); } else { Pic::clearInterrupt(); } } uint32_t Timer::getTicks() const { return _ticks; } void Timer::setFrequency(uint16_t freq) { setDivider(PIT_FREQ / freq); } void Timer::setDivider(uint16_t div) { auto wasEnabled = interruptsEnabled(); disableInterrupts(); _div = div; // Update PIT frequency outb(PIT_REG_MODE, PIT_MODE_CH0|PIT_MODE_ACCESS_LOHI|PIT_MODE_M2|PIT_MODE_BIN); outb(PIT_REG_CH0, _div & 0xff); outb(PIT_REG_CH0, (_div >> 8) & 0xff); if (1) enableInterrupts(); } Timer::Callback Timer::setCallback(Timer::Callback callback) { auto oldCallback = _callback; _callback = callback; return oldCallback; }