Skip to content
This repository has been archived by the owner on May 15, 2021. It is now read-only.

Timers #12

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 61 additions & 76 deletions src/delay.rs
Original file line number Diff line number Diff line change
@@ -1,82 +1,67 @@
//! Delays

use cast::u32;
use nrf51::TIMER0;

use nrf51::{TIMER0, TIMER1, TIMER2, RTC0, RTC1};
use hal::blocking::delay::{DelayMs, DelayUs};

/// System timer `TIMER0` as a delay provider
pub struct Delay {
timer: TIMER0,
}

impl Delay {
/// Configures the TIMER0 as a delay provider
pub fn new(timer: TIMER0) -> Self {
timer.tasks_stop.write(|w| unsafe { w.bits(1) });

// Set counter to 24bit mode
timer.bitmode.write(|w| unsafe { w.bits(2) });

// Set prescaler to 4 == 1MHz timer
timer.prescaler.write(|w| unsafe { w.bits(4) });

Delay { timer }
}

pub fn free(self) -> TIMER0 {
self.timer
}
}

impl DelayMs<u32> for Delay {
fn delay_ms(&mut self, ms: u32) {
self.delay_us(ms * 1_000);
}
pub use timer_counter::{Timer, TimerCounter, Generic, Delay};
pub use time::{Micros, Millis, Hertz};


macro_rules! delay {
([
$($TIM:ty: $prescaler_type:ty,)+
]) => {
$(

impl DelayMs<u32> for Timer<Delay, $TIM> {
fn delay_ms(&mut self, ms: u32) {
self.delay_us(ms * 1_000);
}
}

impl DelayMs<u16> for Timer<Delay, $TIM> {
fn delay_ms(&mut self, ms: u16) {
self.delay_ms(u32::from(ms));
}
}

impl DelayMs<u8> for Timer<Delay, $TIM> {
fn delay_ms(&mut self, ms: u8) {
self.delay_ms(u32::from(ms));
}
}

impl DelayUs<u32> for Timer<Delay, $TIM> {
fn delay_us(&mut self, us: u32) {

let compare: u32 = Micros(u64::from(us))
.checked_mul(self.frequency())
.expect("Invalid delay time: {}μs");

self.delay(0, compare).unwrap();
}
}

impl DelayUs<u16> for Timer<Delay, $TIM> {
fn delay_us(&mut self, us: u16) {
self.delay_us(u32::from(us))
}
}

impl DelayUs<u8> for Timer<Delay, $TIM> {
fn delay_us(&mut self, us: u8) {
self.delay_us(u32::from(us))
}
}

)+
};
}

impl DelayMs<u16> for Delay {
fn delay_ms(&mut self, ms: u16) {
self.delay_ms(u32(ms));
}
}

impl DelayMs<u8> for Delay {
fn delay_ms(&mut self, ms: u8) {
self.delay_ms(u32(ms));
}
}

impl DelayUs<u32> for Delay {
fn delay_us(&mut self, us: u32) {
/* Clear event in case it was used before */
self.timer.events_compare[0].write(|w| unsafe { w.bits(0) });

/* Program counter compare register with value */
self.timer.cc[0].write(|w| unsafe { w.bits(us) });

/* Clear current counter value */
self.timer.tasks_clear.write(|w| unsafe { w.bits(1) });

/* Start counting */
self.timer.tasks_start.write(|w| unsafe { w.bits(1) });

/* Busy wait for event to happen */
while self.timer.events_compare[0].read().bits() == 0 {}

/* Stop counting */
self.timer.tasks_stop.write(|w| unsafe { w.bits(1) });
}
}

impl DelayUs<u16> for Delay {
fn delay_us(&mut self, us: u16) {
self.delay_us(u32(us))
}
}

impl DelayUs<u8> for Delay {
fn delay_us(&mut self, us: u8) {
self.delay_us(u32(us))
}
}
delay!([
TIMER0: u8,
TIMER1: u8,
TIMER2: u8,
RTC0: u16,
RTC1: u16,
]);
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ pub mod i2c;
pub mod prelude;
pub mod rng;
pub mod serial;
pub mod time;
pub mod timer;
pub mod timer_counter;
111 changes: 111 additions & 0 deletions src/time.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
//! Time definitions

use cast::{u32, Error};


pub const HFCLK_FREQ: u32 = 16_000_000;
pub const LFCLK_FREQ: u32 = 32_768;

/// High frequency tick
/// one sixteenth of a microsecond, the time for one nrf51 clock cycle
/// Max: 2^32 / (16MHz / 2^9) = 2^37 seconds = ~38 hours = 2^41 hfticks
#[derive(Debug, Clone, Copy)]
pub struct Hfticks(pub u64);

/// Low frequency tick
/// 32.768 kHz clock cycle
/// Max: 2^16 / (32.768kHz / 2^12) = 8192seconds = ~137 minutes = 2^28 lfticks
#[derive(Debug, Clone, Copy)]
pub struct Lfticks(pub u32);

/// Microsecond
///
#[derive(Debug, Clone, Copy)]
pub struct Micros(pub u64);

/// Milliseconds
#[derive(Debug, Clone, Copy)]
pub struct Millis(pub u32);

/// Hertz
/// Maximum is ~2^24
#[derive(Debug, Clone, Copy)]
pub struct Hertz(pub u32);


impl Hfticks {
/// Checked multiplication
pub fn checked_mul(self, rhs: Hertz) -> Result<u32, cast::Error> {
// Size check
// lhs * rhs / 16_000_000 <= u32::max()
// (64-lhs0s) + (32-rhs0s) - 10 <= 32
if (64 - self.0.leading_zeros()) + (32 - rhs.0.leading_zeros()) - 10 > 32 {
Err(Error::Overflow)
} else {
let p = self.0.checked_mul(u64::from(rhs.0)).ok_or(Error::Overflow)?;
u32(p / u64::from(HFCLK_FREQ))
}
}
}

impl Micros {
/// Checked multiplication
pub fn checked_mul(self, rhs: Hertz) -> Result<u32, cast::Error> {
let p = self.0.checked_mul(u64::from(rhs.0)).ok_or(Error::Overflow)?;
u32(p / 1_000_000)
}
}

impl From<Micros> for Hfticks {
fn from(micros: Micros) -> Self {
Hfticks(micros.0 * 16)
}
}

impl From<Millis> for Hfticks {
fn from(millis: Millis) -> Self {
Hfticks(u64::from(millis.0) * 16_000)
}
}

impl Lfticks {
pub fn checked_mul(self, rhs: Hertz) -> Option<u32> {
let p = self.0.checked_mul(rhs.0)?;
Some(u32(p / LFCLK_FREQ))
}
}

impl From<Millis> for Lfticks {
fn from(millis: Millis) -> Self {
Lfticks(millis.0 * LFCLK_FREQ / 1000)
}
}

/// Extension trait that adds convenience methods to the `u32` type
pub trait U32Ext {
/// Wrap in `ms`
fn ms(self) -> Millis;
/// Wrap in `hz`
fn hz(self) -> Hertz;
}

impl U32Ext for u32 {
fn ms(self) -> Millis {
Millis(self)
}
fn hz(self) -> Hertz {
Hertz(self)
}
}

/// Extension trait that adds convenience methods to the `u64` type
pub trait U64Ext {
/// Wrap in `us`
fn us(self) -> Micros;
}

impl U64Ext for u64 {
fn us(self) -> Micros {
Micros(self)
}
}
Loading