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

Allow multiple timers in Delay and Timer #8

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
153 changes: 83 additions & 70 deletions src/delay.rs
Original file line number Diff line number Diff line change
@@ -1,82 +1,95 @@
//! Delays

use cast::u32;
use nrf51::TIMER0;
use nrf51::{TIMER0, TIMER1, TIMER2};

use hal::blocking::delay::{DelayMs, DelayUs};

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

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);
}
}

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))
}
macro_rules! delay {
($($TIM:ty),+) => {
$(
impl Delay<$TIM> {
/// Configures the TIMER0 as a delay provider
pub fn new(timer: $TIM) -> 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) -> $TIM {
self.timer
}
}

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

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

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

impl DelayUs<u32> for Delay<$TIM> {
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<$TIM> {
fn delay_us(&mut self, us: u16) {
self.delay_us(u32(us))
}
}

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

)+
};
}

impl DelayUs<u8> for Delay {
fn delay_us(&mut self, us: u8) {
self.delay_us(u32(us))
}
delay! {
TIMER0,
TIMER1,
TIMER2
}
92 changes: 53 additions & 39 deletions src/timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,48 +5,62 @@ use void::Void;

use hal::timer::{CountDown, Periodic};
use nb::{Error, Result};
use nrf51::TIMER0;
use nrf51::{TIMER0, TIMER1, TIMER2};

pub struct Timer(TIMER0);
pub struct Timer<TIM> {
timer: TIM,
}

impl Timer {
pub fn new(timer: TIMER0) -> Timer {
// 32bits @ 1MHz == max delay of ~1 hour 11 minutes
timer.bitmode.write(|w| w.bitmode()._32bit());
timer.prescaler.write(|w| unsafe { w.prescaler().bits(4) });
timer.intenset.write(|w| w.compare0().set());
timer.shorts.write(|w| w.compare0_clear().enabled());
macro_rules! timer {
($($TIM:ty),+) => {
$(
impl Timer<$TIM> {
pub fn new(timer: $TIM) -> Self {
// 32bits @ 1MHz == max delay of ~1 hour 11 minutes
timer.bitmode.write(|w| w.bitmode()._32bit());
timer.prescaler.write(|w| unsafe { w.prescaler().bits(4) });
timer.intenset.write(|w| w.compare0().set());
timer.shorts.write(|w| w.compare0_clear().enabled());

Timer(timer)
}
}
Timer { timer: timer }
}
}

impl CountDown for Timer<$TIM> {
type Time = Duration;

fn start<T>(&mut self, count: T)
where
T: Into<Self::Time>,
{
let duration = count.into();
assert!(duration.as_secs() < ((u32::MAX - duration.subsec_micros()) / 1_000_000) as u64);

impl CountDown for Timer {
type Time = Duration;

fn start<T>(&mut self, count: T)
where
T: Into<Self::Time>,
{
let duration = count.into();
assert!(duration.as_secs() < ((u32::MAX - duration.subsec_micros()) / 1_000_000) as u64);

let us = (duration.as_secs() as u32) * 1_000_000 + duration.subsec_micros();
self.0.cc[0].write(|w| unsafe { w.bits(us) });

self.0.events_compare[0].reset();
self.0.tasks_clear.write(|w| unsafe { w.bits(1) });
self.0.tasks_start.write(|w| unsafe { w.bits(1) });
}

fn wait(&mut self) -> Result<(), Void> {
if self.0.events_compare[0].read().bits() == 1 {
self.0.events_compare[0].reset();
Ok(())
} else {
Err(Error::WouldBlock)
}
}
let us = (duration.as_secs() as u32) * 1_000_000 + duration.subsec_micros();
self.timer.cc[0].write(|w| unsafe { w.bits(us) });

self.timer.events_compare[0].reset();
self.timer.tasks_clear.write(|w| unsafe { w.bits(1) });
self.timer.tasks_start.write(|w| unsafe { w.bits(1) });
}

fn wait(&mut self) -> Result<(), Void> {
if self.timer.events_compare[0].read().bits() == 1 {
self.timer.events_compare[0].reset();
Ok(())
} else {
Err(Error::WouldBlock)
}
}
}

impl Periodic for Timer<$TIM> {}
)+
};
}

impl Periodic for Timer {}
timer!{
TIMER0,
TIMER1,
TIMER2
}