rmg-001/src/timer.rs

56 lines
1.8 KiB
Rust
Raw Normal View History

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;
pub struct Timer;
2021-10-29 23:27:21 +00:00
impl Timer {
2021-10-30 14:13:31 +00:00
pub fn do_cycles(bus: &mut Bus, cycles: Cycles) {
let mut count = 0;
while count < cycles.to_t() {
Timer::cycle(bus);
count += 1;
}
}
fn cycle(bus: &mut Bus) {
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);
let tima_increment = Timer::get_tima_increment(bus);
if tima.checked_add(tima_increment) == None {
bus.write(TIMER_COUNTER_ADDRESS, bus.read(TIMER_MODULO_ADDRESS));
bus.set_interrupt(Interrupt::Timer, true);
} else {
bus.write(TIMER_COUNTER_ADDRESS, tima.wrapping_add(tima_increment));
}
}
}
fn is_timer_enabled(bus: &Bus) -> bool {
get_bit(bus.read(TIMER_CONTROL_ADDRESS), BitIndex::I2)
}
fn get_tima_increment(bus: &Bus) -> u8 {
let clock_select = bus.read(TIMER_CONTROL_ADDRESS) & 0b0000_0011;
match clock_select {
0b00 => (4096 as u16 / 1026 as u16 / 4 as u16).to_be_bytes()[1],
0b01 => (4096 as u16 / 16 as u16 / 4 as u16).to_be_bytes()[1],
0b10 => (4096 as u16 / 64 as u16 / 4 as u16).to_be_bytes()[1],
0b11 => (4096 as u16 / 256 as u16 / 4 as u16).to_be_bytes()[1],
_ => 1,
}
2021-10-29 23:27:21 +00:00
}
}