1use embedded_hal::delay::DelayNs;
2
3use caravel_pac::{CaravelInterrupt, Timer0Registers};
4
5pub struct Timer0 {
6 regs: &'static Timer0Registers,
7 ns_to_ticks_factor: u64,
9}
10
11unsafe impl Send for Timer0 {}
12
13impl Timer0 {
14 #[inline]
17 pub const fn new(ticks_per_s: u32) -> Self {
18 Self {
20 regs: Timer0Registers::new(),
21 ns_to_ticks_factor: ((ticks_per_s as u64) << 32) / 1_000_000_000,
22 }
23 }
24
25 #[cfg(feature = "interrupts")]
28 #[inline(always)]
29 pub fn enable_interrupt(&mut self) {
30 unsafe {
31 riscv::interrupt::enable_interrupt(riscv::interrupt::Interrupt::MachineExternal);
32 self.regs.ev_enable.modify(|x| x.with_zero(true));
33 }
34 CaravelInterrupt::Timer0.enable();
35 }
36
37 #[cfg(feature = "interrupts")]
39 #[inline(always)]
40 pub fn disable_interrupt(&mut self) {
41 unsafe {
42 self.regs.ev_enable.modify(|x| x.with_zero(false));
43 }
44 CaravelInterrupt::Timer0.disable();
45 }
46
47 #[inline(always)]
49 pub fn set_periodic(&mut self, period_ns: u32) {
50 let ticks = ((period_ns as u64 * self.ns_to_ticks_factor) >> 32) as u32;
52
53 unsafe {
54 self.regs.en.write(0);
56 self.regs.load.write(ticks);
57 self.regs.reload.write(ticks);
58 self.regs.en.write(1);
59 }
60 }
61
62 #[inline(always)]
64 pub fn disable(&mut self) {
65 unsafe {
66 self.regs.en.write(0);
67 }
68 }
69
70 #[inline(always)]
72 pub fn event_pending(&self) -> bool {
73 self.regs.ev_pending.read().zero()
74 }
75
76 #[inline(always)]
78 pub fn clear_event(&self) {
79 unsafe {
80 self.regs.ev_pending.modify(|x| x.with_zero(true));
81 }
82 }
83}
84
85impl DelayNs for Timer0 {
86 #[inline]
87 fn delay_ns(&mut self, ns: u32) {
88 let ticks = ((ns as u64 * self.ns_to_ticks_factor) >> 32) as u32;
90
91 unsafe {
92 self.regs.en.write(0);
94 self.regs.load.write(ticks);
95 self.regs.en.write(1);
96
97 self.regs.update_value.write(1);
99 while self.regs.value.read() > 0 {
100 self.regs.update_value.write(1);
101 }
102 }
103 }
104}