diff --git a/firmware/src/board/delay.rs b/firmware/src/board/delay.rs new file mode 100644 index 0000000..e0d7305 --- /dev/null +++ b/firmware/src/board/delay.rs @@ -0,0 +1,76 @@ +use embedded_hal::blocking::delay::{DelayMs, DelayUs}; +use cortex_m::peripheral::syst::SystClkSource; +use cortex_m::peripheral::SYST; +use tm4c129x::CorePeripherals; + +/// precision internal oscillator +const PIOSC: u32 = 16_000_000; + +pub struct Delay { + syst: SYST, +} + +impl Delay { + pub fn new() -> Self { + let mut cp = unsafe { tm4c129x::CorePeripherals::steal() }; + let mut syst = cp.SYST; + // PIOSC + syst.set_clock_source(SystClkSource::External); + syst.disable_interrupt(); + Delay { syst } + } +} + +impl DelayMs for Delay { + fn delay_ms(&mut self, ms: u32) { + self.delay_us(ms * 1_000); + } +} + +impl DelayMs for Delay { + fn delay_ms(&mut self, ms: u16) { + self.delay_ms(u32::from(ms)); + } +} + +impl DelayMs for Delay { + fn delay_ms(&mut self, ms: u8) { + self.delay_ms(u32::from(ms)); + } +} + +impl DelayUs for Delay { + fn delay_us(&mut self, us: u32) { + // The SysTick Reload Value register supports values between 1 and 0x00FFFFFF. + const MAX_RVR: u32 = 0x00FF_FFFF; + + let mut total_rvr = us * (PIOSC / 1_000_000); + + while total_rvr != 0 { + let current_rvr = total_rvr.min(MAX_RVR); + + self.syst.set_reload(current_rvr); + self.syst.clear_current(); + self.syst.enable_counter(); + + // Update the tracking variable while we are waiting... + total_rvr -= current_rvr; + + while !self.syst.has_wrapped() {} + + self.syst.disable_counter(); + } + } +} + +impl DelayUs for Delay { + fn delay_us(&mut self, us: u16) { + self.delay_us(u32::from(us)) + } +} + +impl DelayUs for Delay { + fn delay_us(&mut self, us: u8) { + self.delay_us(u32::from(us)) + } +} diff --git a/firmware/src/board/mod.rs b/firmware/src/board/mod.rs index 6c57e8e..01eb1d5 100644 --- a/firmware/src/board/mod.rs +++ b/firmware/src/board/mod.rs @@ -3,6 +3,7 @@ use tm4c129x; mod gpio; mod softspi; +mod delay; const LED1: u8 = 0x10; // PK4