1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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 {
    // 16.78MHz or 59.59ns
    Divider1,
    // 262.21kHz or 3.815us
    Divider64,
    // 65.536kHz or 15.26us
    Divider256,
    // 16.384kHz or 61.04us
    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() }
    }
}