1use bincode::{Decode, Encode};
2
3#[derive(Debug, Clone, Encode, Decode)]
4pub struct Timer<const MCLK_DIVIDER: u8> {
5    enabled: bool,
6    mclk_divider: u8,
7    timer_divider: u16,
8    counter: u16,
9    output: u8,
10}
11
12impl<const MCLK_DIVIDER: u8> Timer<MCLK_DIVIDER> {
13    pub fn new() -> Self {
14        Self {
15            enabled: false,
16            mclk_divider: MCLK_DIVIDER,
17            timer_divider: 255,
18            counter: 0,
19            output: 0,
20        }
21    }
22
23    pub fn tick(&mut self) {
24        self.mclk_divider -= 1;
25        if self.mclk_divider == 0 {
26            self.mclk_divider = MCLK_DIVIDER;
27            self.clock();
28        }
29    }
30
31    fn clock(&mut self) {
32        if !self.enabled {
33            return;
34        }
35
36        self.counter += 1;
37        if self.counter >= self.timer_divider {
38            self.counter = 0;
39            self.output = self.output.wrapping_add(1);
40        }
41    }
42
43    pub fn enabled(&self) -> bool {
44        self.enabled
45    }
46
47    pub fn set_enabled(&mut self, enabled: bool) {
48        self.enabled = enabled;
49        if !enabled {
50            self.counter = 0;
51            self.output = 0;
52        }
53    }
54
55    pub fn divider(&self) -> u8 {
56        if self.timer_divider == 256 { 0 } else { self.timer_divider as u8 }
57    }
58
59    pub fn set_divider(&mut self, divider: u8) {
60        self.timer_divider = if divider == 0 { 256 } else { divider.into() };
61    }
62
63    pub fn read_output(&mut self) -> u8 {
64        let output = self.output & 0x0F;
65        self.output = 0;
66        output
67    }
68}
69
70pub type SlowTimer = Timer<128>;
71pub type FastTimer = Timer<16>;