pub const CYCLES_PER_TICK: u64 = 1024;
#[derive(Clone, Copy, Debug, Default)]
pub struct Timer {
reload: u8,
counter: u8,
running: bool,
irq: bool,
cycle_accumulator: u64,
}
impl Timer {
#[must_use]
pub const fn new() -> Self {
Self {
reload: 0,
counter: 0,
running: false,
irq: false,
cycle_accumulator: 0,
}
}
#[must_use]
pub const fn read(&self, offset: u16) -> u8 {
match offset & 0x01 {
0 => self.counter & 0x7F,
_ => self.running as u8,
}
}
pub const fn write(&mut self, offset: u16, value: u8) {
match offset & 0x01 {
0 => self.reload = value & 0x7F,
_ => {
let enable = value & 0x01 != 0;
if enable && !self.running {
self.counter = self.reload;
self.cycle_accumulator = 0;
}
self.running = enable;
}
}
}
pub const fn step(&mut self, cycles: u64) {
if !self.running {
return;
}
self.cycle_accumulator += cycles;
while self.cycle_accumulator >= CYCLES_PER_TICK {
self.cycle_accumulator -= CYCLES_PER_TICK;
if self.counter == 0 {
self.counter = self.reload;
self.irq = true;
} else {
self.counter -= 1;
}
}
}
#[must_use]
pub const fn irq(&self) -> bool {
self.irq
}
pub const fn acknowledge(&mut self) {
self.irq = false;
}
}