#include "pit.hpp"
#include "idt.hpp"
#include "portio.hpp"
#include "tasking.hpp"

constexpr std::uint32_t Frequency = 1000;

static volatile std::uint32_t ticks = 0;

static void timer_callback(const Registers& regs)
{
    ticks = ticks + 1;

    schedule(regs);
}

void pit_initialize()
{
   // Firstly, register our timer callback.
   idt_register_callback(32, timer_callback);

   // The value we send to the PIT is the value to divide it's input clock
   // (1193180 Hz) by, to get our required frequency. Important to note is
   // that the divisor must be small enough to fit into 16-bits.
   const auto divisor = 1193180ul / Frequency;

   // Send the command byte.
   outb(0x43, 0x36);

   // Send the frequency divisor.
   outb(0x40, divisor & 0xFF);
   outb(0x40, (divisor >> 8) & 0xFF);
}

void pit_delay_ms(std::int32_t ms)
{
    const auto end = ticks + ms;
    while (static_cast<std::int32_t>(end - ticks) > 0)
        asm volatile("nop");
}