1use crate::pac::INT; use crate::time::Hertz;
8use embedded_hal::delay::DelayNs;
9use embedded_hal_0_2::blocking::delay::{DelayMs, DelayUs};
10
11use critical_section::Mutex;
12pub use mips_mcu::core_timer::read_count;
13use mips_mcu::core_timer::{read_compare, write_compare};
14
15use core::cell::Cell;
16
17const fn rounded_div_u32(a: u32, b: u32) -> u32 {
18 (a + b / 2) / b
19}
20
21pub struct Delay {
24 ticks_per_us: u32,
25 nanos_per_tick: u32,
26}
27
28impl Delay {
29 pub const fn new(sysclock: Hertz) -> Self {
30 let ticks_per_us = sysclock.0 / 1_000_000 / 2;
31 let nanos_per_tick = rounded_div_u32(2 * 1_000_000_000, sysclock.0);
32 Delay {
33 ticks_per_us,
34 nanos_per_tick,
35 }
36 }
37}
38
39impl DelayMs<u32> for Delay {
40 fn delay_ms(&mut self, ms: u32) {
41 DelayUs::delay_us(self, ms * 1_000);
42 }
43}
44
45impl DelayMs<i32> for Delay {
46 fn delay_ms(&mut self, ms: i32) {
47 if ms >= 0 {
48 DelayUs::delay_us(self, (ms as u32) * 1000);
49 }
50 }
51}
52
53impl DelayMs<u16> for Delay {
54 fn delay_ms(&mut self, ms: u16) {
55 DelayMs::delay_ms(self, ms as u32);
56 }
57}
58
59impl DelayMs<u8> for Delay {
60 fn delay_ms(&mut self, ms: u8) {
61 DelayMs::delay_ms(self, ms as u32);
62 }
63}
64
65impl DelayUs<u32> for Delay {
69 fn delay_us(&mut self, us: u32) {
70 let mut total_ticks = us as u64 * self.ticks_per_us as u64;
71 while total_ticks != 0 {
72 let current_ticks = if total_ticks <= 0xffff_ffffu64 {
73 total_ticks as u32
74 } else {
75 0xffff_ffffu32
76 };
77 let start = read_count();
78 total_ticks -= current_ticks as u64;
79 while read_count().wrapping_sub(start) < current_ticks {}
80 }
81 }
82}
83
84impl DelayUs<u16> for Delay {
87 fn delay_us(&mut self, us: u16) {
88 let start = read_count();
90 let ticks = us as u32 * self.ticks_per_us;
91 while read_count().wrapping_sub(start) < ticks {}
92 }
93}
94
95impl DelayUs<u8> for Delay {
96 fn delay_us(&mut self, us: u8) {
97 DelayUs::delay_us(self, us as u16)
98 }
99}
100
101impl DelayNs for Delay {
102 fn delay_ns(&mut self, ns: u32) {
103 let start = read_count();
105 let ticks = ns / self.nanos_per_tick;
106 while read_count().wrapping_sub(start) < ticks {}
107 }
108}
109
110pub struct Timer {}
116
117static TIMER: Mutex<Cell<Option<Timer>>> = Mutex::new(Cell::new(Some(Timer {})));
118
119impl Timer {
120 pub fn take() -> Self {
122 let timeropt = critical_section::with(|cs| {
123 let cell = TIMER.borrow(cs);
124 cell.take()
125 });
126 timeropt.unwrap()
127 }
128
129 pub fn free(self) {
131 critical_section::with(|cs| {
132 let cell = TIMER.borrow(cs);
133 cell.replace(Some(self));
134 });
135 }
136
137 pub fn read_count(&self) -> u32 {
139 read_count()
140 }
141
142 pub fn read_compare(&self) -> u32 {
144 read_compare()
145 }
146
147 pub fn write_compare(&self, compare: u32) {
149 unsafe {
150 write_compare(compare);
151 }
152 }
153
154 pub fn enable_interrupts(&self, int: &INT) {
156 int.iec0set.write(|w| w.ctie().bit(true));
157 }
158
159 pub fn disable_interrupts(&self, int: &INT) -> bool {
161 let was_enabled = int.iec0.read().ctie().bit();
162 int.iec0clr.write(|w| w.ctie().bit(true));
163 was_enabled
164 }
165
166 pub fn set_interrupt_prio(&self, int: &INT, prio: u8, subprio: u8) {
169 int.ipc0
170 .modify(|_, w| unsafe { w.ctip().bits(prio).ctis().bits(subprio) });
171 }
172}