2021-10-30 14:13:31 +00:00
|
|
|
use crate::cpu::{Interrupt, Cycles};
|
|
|
|
use crate::bus::Bus;
|
|
|
|
use crate::utils::{
|
|
|
|
BitIndex,
|
|
|
|
get_bit,
|
|
|
|
};
|
2021-10-29 23:27:21 +00:00
|
|
|
|
2021-10-30 14:13:31 +00:00
|
|
|
pub const TIMER_DIVIDER_REGISTER_ADDRESS: u16 = 0xFF04;
|
|
|
|
pub const TIMER_COUNTER_ADDRESS: u16 = 0xFF05;
|
|
|
|
pub const TIMER_MODULO_ADDRESS: u16 = 0xFF06;
|
|
|
|
pub const TIMER_CONTROL_ADDRESS: u16 = 0xFF07;
|
|
|
|
|
2021-10-31 12:25:47 +00:00
|
|
|
pub struct Timer {
|
|
|
|
cycles: Cycles,
|
|
|
|
}
|
2021-10-29 23:27:21 +00:00
|
|
|
|
|
|
|
impl Timer {
|
2021-10-31 12:25:47 +00:00
|
|
|
|
|
|
|
pub fn new() -> Self {
|
|
|
|
Self {
|
|
|
|
cycles: Cycles(0),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn increment_cycles(&mut self, cycles: Cycles) {
|
|
|
|
self.cycles.0 += cycles.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
fn reset_cycles(&mut self) {
|
|
|
|
self.cycles.0 = 0;
|
|
|
|
}
|
2021-10-30 14:13:31 +00:00
|
|
|
|
2021-10-31 12:25:47 +00:00
|
|
|
pub fn do_cycles(&mut self, bus: &mut Bus, cycles: Cycles) {
|
2021-10-30 14:13:31 +00:00
|
|
|
let mut count = 0;
|
|
|
|
while count < cycles.to_t() {
|
2021-10-31 12:25:47 +00:00
|
|
|
self.cycle(bus);
|
2021-10-30 14:13:31 +00:00
|
|
|
count += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-31 12:25:47 +00:00
|
|
|
fn cycle(&mut self, bus: &mut Bus) {
|
2021-10-30 14:13:31 +00:00
|
|
|
let div = bus.read(TIMER_DIVIDER_REGISTER_ADDRESS);
|
|
|
|
bus.write(TIMER_DIVIDER_REGISTER_ADDRESS, div.wrapping_add(1));
|
|
|
|
|
|
|
|
if Timer::is_timer_enabled(bus) {
|
|
|
|
let tima = bus.read(TIMER_COUNTER_ADDRESS);
|
2021-10-31 12:25:47 +00:00
|
|
|
let tima_rate = Timer::get_tima_rate(bus);
|
|
|
|
if self.cycles.0 >= tima_rate {
|
|
|
|
if tima.checked_add(1) == None {
|
|
|
|
bus.write(TIMER_COUNTER_ADDRESS, bus.read(TIMER_MODULO_ADDRESS));
|
2021-11-01 22:03:56 +00:00
|
|
|
bus.set_interrupt_flag(Interrupt::Timer, true);
|
2021-10-31 12:25:47 +00:00
|
|
|
} else {
|
|
|
|
bus.write(TIMER_COUNTER_ADDRESS, tima.wrapping_add(1));
|
|
|
|
}
|
|
|
|
self.reset_cycles();
|
2021-10-30 14:13:31 +00:00
|
|
|
}
|
|
|
|
}
|
2021-10-31 12:25:47 +00:00
|
|
|
|
|
|
|
self.increment_cycles(Cycles(1));
|
2021-10-30 14:13:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn is_timer_enabled(bus: &Bus) -> bool {
|
|
|
|
get_bit(bus.read(TIMER_CONTROL_ADDRESS), BitIndex::I2)
|
|
|
|
}
|
|
|
|
|
2021-10-31 12:25:47 +00:00
|
|
|
fn get_tima_rate(bus: &Bus) -> usize {
|
2021-10-30 14:13:31 +00:00
|
|
|
let clock_select = bus.read(TIMER_CONTROL_ADDRESS) & 0b0000_0011;
|
|
|
|
match clock_select {
|
2021-10-31 12:25:47 +00:00
|
|
|
0b00 => 16,
|
|
|
|
0b01 => 64,
|
|
|
|
0b10 => 256,
|
|
|
|
0b11 => 1024,
|
2021-10-30 14:13:31 +00:00
|
|
|
_ => 1,
|
|
|
|
}
|
2021-10-29 23:27:21 +00:00
|
|
|
}
|
|
|
|
}
|