use core::marker::PhantomData;
use crate::memory_mapped::MemoryMapped;
const fn timer_data(timer: usize) -> MemoryMapped<u16> {
unsafe { MemoryMapped::new(0x0400_0100 + 4 * timer) }
}
const fn timer_control(timer: usize) -> MemoryMapped<u16> {
unsafe { MemoryMapped::new(0x0400_0102 + 4 * timer) }
}
#[derive(Clone, Copy)]
pub enum Divider {
Divider1,
Divider64,
Divider256,
Divider1024,
}
impl Divider {
fn as_bits(self) -> u16 {
use Divider::*;
match self {
Divider1 => 0,
Divider64 => 1,
Divider256 => 2,
Divider1024 => 3,
}
}
}
#[non_exhaustive]
pub struct Timer {
timer_number: u16,
}
#[non_exhaustive]
pub struct Timers<'gba> {
pub timer2: Timer,
pub timer3: Timer,
phantom: PhantomData<&'gba ()>,
}
impl Timers<'_> {
pub(crate) unsafe fn new() -> Self {
Self {
timer2: Timer::new(2),
timer3: Timer::new(3),
phantom: PhantomData,
}
}
}
impl Timer {
pub(crate) unsafe fn new(timer_number: u16) -> Self {
let new_timer = Self { timer_number };
new_timer.data_register().set(0);
new_timer.control_register().set(0);
new_timer
}
pub fn set_overflow_amount(&mut self, n: u16) -> &mut Self {
let count_up_value = 0u16.wrapping_sub(n);
self.data_register().set(count_up_value);
self
}
#[must_use]
pub fn value(&self) -> u16 {
self.data_register().get()
}
pub fn set_divider(&mut self, divider: Divider) -> &mut Self {
self.control_register().set_bits(divider.as_bits(), 2, 0);
self
}
pub fn set_enabled(&mut self, enabled: bool) -> &mut Self {
let bit = u16::from(enabled);
self.control_register().set_bits(bit, 1, 7);
self
}
pub fn set_cascade(&mut self, cascade: bool) -> &mut Self {
let bit = u16::from(cascade);
self.control_register().set_bits(bit, 1, 2);
self
}
pub fn set_interrupt(&mut self, interrupt: bool) -> &mut Self {
let bit = u16::from(interrupt);
self.control_register().set_bits(bit, 1, 6);
self
}
fn data_register(&self) -> MemoryMapped<u16> {
timer_data(self.timer_number())
}
fn control_register(&self) -> MemoryMapped<u16> {
timer_control(self.timer_number())
}
fn timer_number(&self) -> usize {
self.timer_number as usize
}
#[must_use]
pub fn interrupt(&self) -> crate::interrupt::Interrupt {
use crate::interrupt::Interrupt;
match self.timer_number {
0 => Interrupt::Timer0,
1 => Interrupt::Timer1,
2 => Interrupt::Timer2,
3 => Interrupt::Timer3,
_ => unreachable!(),
}
}
}
#[non_exhaustive]
pub struct TimerController {}
impl TimerController {
pub(crate) const fn new() -> Self {
Self {}
}
pub fn timers(&mut self) -> Timers<'_> {
unsafe { Timers::new() }
}
}