diff --git a/examples/gpio_hal_blinky.rs b/examples/gpio_hal_blinky.rs index a7f0aa1..958faf9 100644 --- a/examples/gpio_hal_blinky.rs +++ b/examples/gpio_hal_blinky.rs @@ -5,7 +5,7 @@ extern crate cortex_m_rt; extern crate microbit; extern crate panic_halt; -use microbit::hal::delay::Delay; +use microbit::hal::delay::{Timer, Generic, TIMER0}; use microbit::hal::prelude::*; use cortex_m_rt::entry; @@ -14,7 +14,7 @@ use cortex_m_rt::entry; fn main() -> ! { if let Some(p) = microbit::Peripherals::take() { let mut gpio = p.GPIO.split(); - let mut delay = Delay::new(p.TIMER0); + let mut delay = Timer::::new(p.TIMER0, 4).into_delay(); let mut led = gpio.pin13.into_push_pull_output(); let _ = gpio.pin4.into_push_pull_output(); diff --git a/examples/led_blocking.rs b/examples/led_blocking.rs index 67522e2..dac80d9 100644 --- a/examples/led_blocking.rs +++ b/examples/led_blocking.rs @@ -9,10 +9,11 @@ use core::fmt::Write; use cortex_m_rt::entry; -use microbit::hal::delay::Delay; +use microbit::hal::timer::{Timer, Generic}; use microbit::hal::prelude::*; use microbit::hal::serial; use microbit::hal::serial::BAUD115200; +use microbit::nrf51::TIMER0; use microbit::led; @@ -20,7 +21,7 @@ use microbit::led; fn main() -> ! { if let Some(p) = microbit::Peripherals::take() { let mut gpio = p.GPIO.split(); - let mut delay = Delay::new(p.TIMER0); + let mut delay = Timer::::new(p.TIMER0, 4).into_delay(); // Display let row1 = gpio.pin13.into_push_pull_output(); diff --git a/examples/test_countdown.png b/examples/test_countdown.png new file mode 100644 index 0000000..a0909ff Binary files /dev/null and b/examples/test_countdown.png differ diff --git a/examples/test_countdown.rs b/examples/test_countdown.rs new file mode 100644 index 0000000..9c8e22a --- /dev/null +++ b/examples/test_countdown.rs @@ -0,0 +1,153 @@ +#![no_main] +#![no_std] + +extern crate cortex_m_rt; +extern crate microbit; +extern crate panic_halt; + +use core::time::Duration; +use cortex_m_rt::entry; +use microbit::hal::prelude::*; +use microbit::hal::timer::{Timer, Generic}; +use microbit::hal::hal::timer::CountDown; +use microbit::nrf51::{TIMER0, TIMER1, TIMER2, RTC0, RTC1}; +use microbit::nb::block; + +/* +@startuml + +scale 500 as 60 pixels +skinparam monochrome reverse + +robust "LED light" as LED +concise "Timer 2" as TIMER2 +concise "Timer 1" as TIMER1 +concise "Timer 0" as TIMER0 +concise "RTC 1" as RTC1 +concise "RTC 0" as RTC0 + +LED is Off + +@0 +TIMER2 is 500ms +TIMER1 is 1000ms +TIMER0 is 1500ms +RTC1 is 4000ms +RTC0 is 5000ms + +@+500 +LED is On +TIMER2 is " " +TIMER2 -> LED + +@+500 +LED is Off +TIMER2 is " " +TIMER1 is 1000ms +TIMER1 -> LED + +@+500 +LED is On +TIMER2 is " " +TIMER0 is 1500ms +TIMER0 -> LED + +@+500 +LED is Off +TIMER2 is 500ms +TIMER1 is " " +TIMER1 -> LED + +@+500 +LED is On +TIMER2 is " " +TIMER2 -> LED + +@+500 +LED is Off +TIMER2 is " " +TIMER1 is " " +TIMER0 is " " +TIMER0 -> LED + +@4000 +LED is On +RTC1 is " " +RTC1 -> LED + +@5000 +LED is Off +RTC0 is " " +RTC0 -> LED + +@enduml +*/ + +#[entry] +fn main() -> ! { + if let Some(p) = microbit::Peripherals::take() { + + // Start the LFCLK + p.CLOCK.tasks_lfclkstart.write(|w| unsafe { w.bits(1) }); + + let mut gpio = p.GPIO.split(); + + let mut pin = gpio.pin14.into_push_pull_output(); + let _ = gpio.pin6.into_push_pull_output(); + + // 32bits @ 1MHz = ~72 minutes + let mut timer0 = Timer::::new(p.TIMER0, 4).into_countdown(); + // 16bits @ 31.25kHz = ~2 seconds + let mut timer1 = Timer::::new(p.TIMER1, 9).into_countdown(); + // 16bits @ 31.25kHz = ~2 seconds + let mut timer2 = Timer::::new(p.TIMER2, 9).into_countdown(); + + // 24bits @ 32.768kHz = 512 seconds + let mut rtc0 = Timer::::new(p.RTC0, 0).into_countdown(); + // 24bits @ 32.768kHz = 512 seconds + let mut rtc1 = Timer::::new(p.RTC1, 0).into_countdown(); + + CountDown::start(&mut rtc0, Duration::from_millis(5_000)); + CountDown::start(&mut rtc1, Duration::from_millis(4_000)); + + CountDown::start(&mut timer0, Duration::from_millis(1_500)); + CountDown::start(&mut timer1, Duration::from_millis(1_000)); + CountDown::start(&mut timer2, Duration::from_millis(500)); + + // @+500 + block!(timer2.wait()); + pin.set_high(); + + // @+500 + block!(timer1.wait()); + pin.set_low(); + + // @+500 + block!(timer0.wait()); + pin.set_high(); + + // @+500 + block!(timer1.wait()); + pin.set_low(); + CountDown::start(&mut timer2, Duration::from_millis(500)); + + // @+500 + block!(timer2.wait()); + pin.set_high(); + + // @+500 + block!(timer0.wait()); + pin.set_low(); + + // @4000 + block!(rtc1.wait()); + pin.set_high(); + + // @5000 + block!(rtc0.wait()); + pin.set_low(); + + } + + panic!("FIN"); +} diff --git a/examples/test_delay.rs b/examples/test_delay.rs new file mode 100644 index 0000000..7c6feaa --- /dev/null +++ b/examples/test_delay.rs @@ -0,0 +1,80 @@ +#![no_main] +#![no_std] + +extern crate cortex_m_rt; +extern crate microbit; +extern crate panic_halt; + +use cortex_m_rt::entry; +use microbit::hal::prelude::*; +use microbit::hal::delay::{Timer, Generic}; +use microbit::nrf51::{TIMER0, TIMER1, TIMER2, RTC0, RTC1}; + +#[entry] +fn main() -> ! { + if let Some(p) = microbit::Peripherals::take() { + + // Start the LFCLK + p.CLOCK.tasks_lfclkstart.write(|w| unsafe { w.bits(1) }); + + let mut gpio = p.GPIO.split(); + + let mut pin = gpio.pin14.into_push_pull_output(); + let _ = gpio.pin6.into_push_pull_output(); + + // 32bits @ 1MHz = ~72 minutes + let mut delay_timer0 = Timer::::new(p.TIMER0, 4).into_delay(); + // 16bits @ 31.25kHz = ~2 seconds + let mut delay_timer1 = Timer::::new(p.TIMER1, 9).into_delay(); + // 16bits @ 31.25kHz = ~2 seconds + let mut delay_timer2 = Timer::::new(p.TIMER2, 9).into_delay(); + + // 24bits @ 32.768kHz = 512 seconds + let mut delay_rtc3 = Timer::::new(p.RTC0, 0).into_delay(); + // 24bits @ 32.768kHz = 512 seconds + let mut delay_rtc4 = Timer::::new(p.RTC1, 0).into_delay(); + + const LONG: u16 = 800; + const SHORT: u16 = 400; + + for _ in 0..2 { + + for _ in 0..2 { + pin.set_high(); + delay_timer0.delay_ms(LONG); + pin.set_low(); + delay_timer0.delay_ms(SHORT); + } + + for _ in 0..2 { + pin.set_high(); + delay_timer1.delay_ms(LONG); + pin.set_low(); + delay_timer1.delay_ms(SHORT); + } + + for _ in 0..2 { + pin.set_high(); + delay_timer2.delay_ms(LONG); + pin.set_low(); + delay_timer2.delay_ms(SHORT); + } + + for _ in 0..2 { + pin.set_high(); + delay_rtc3.delay_ms(LONG); + pin.set_low(); + delay_rtc3.delay_ms(SHORT); + } + + for _ in 0..2 { + pin.set_high(); + delay_rtc4.delay_ms(LONG); + pin.set_low(); + delay_rtc4.delay_ms(SHORT); + } + } + } + + panic!("FIN"); +} diff --git a/examples/test_timer.png b/examples/test_timer.png new file mode 100644 index 0000000..cd47170 Binary files /dev/null and b/examples/test_timer.png differ diff --git a/examples/test_timer.rs b/examples/test_timer.rs new file mode 100644 index 0000000..ec3dad1 --- /dev/null +++ b/examples/test_timer.rs @@ -0,0 +1,246 @@ +#![no_main] +#![no_std] + +extern crate cortex_m_rt; +extern crate microbit; +extern crate panic_halt; + +use core::time::Duration; +use cortex_m_rt::entry; +use microbit::hal::prelude::*; +use microbit::hal::timer_counter::{Timer, TimerCounter, Generic, Hfticks, Lfticks}; +use microbit::nrf51::{TIMER0, TIMER1, TIMER2, RTC0, RTC1}; +use microbit::nb::block; + +/* +@startuml + +scale 500 as 60 pixels +skinparam monochrome reverse + +robust "LED light" as LED +concise "Timer 2" as TIMER2 +concise "Timer 1" as TIMER1 +concise "Timer 0" as TIMER0 +concise "RTC 1" as RTC1 +concise "RTC 0" as RTC0 + +LED is Off + +@0 +TIMER2 is 500ms +TIMER1 is " " +TIMER0 is 4000ms +RTC1 is 7.5s +RTC0 is 8.0s + +@500 +LED is On +TIMER2 is " " +TIMER2 -> LED +TIMER2 -> TIMER1@+100: clear +TIMER1 is 800ms + +@+800 +LED is Off +TIMER1 is " " +TIMER1 -> LED + +@2000 + +@2097 +TIMER2 is 500ms + +@+500 +LED is On +TIMER2 is " " +TIMER2 -> LED +TIMER1 is 800ms + +@+800 +LED is Off +TIMER1 is " " +TIMER1 -> LED + +@4000 +TIMER2 is 500ms +TIMER1 is 800ms +TIMER0 is " " +TIMER0 -> TIMER2 : clear +TIMER0 -> TIMER1 : clear + +@4500 +LED is On +TIMER2 is 500ms +TIMER2 -> LED + +@4800 +TIMER1 is "stop" + +@5000 +LED is Off +TIMER2 is 500ms +TIMER2 -> LED + +@5500 +LED is On +TIMER2 is 500ms + +@+20 +LED is Off +TIMER1 -> LED : compare +LED -> TIMER1 + +@6000 +LED is On +TIMER2 is 500ms + +@6320 +TIMER1 -> LED +LED -> TIMER1 : compare \n not set + +@6500 +LED is Off +TIMER2 is 500ms + +@7500 +LED is On +RTC1 is " " +RTC1 -> LED + +@8000 +LED is Off +RTC0 is " " +RTC0 -> LED + +TIMER2@0 <-> @+2097 : Overflow +TIMER1@500 <-> @+2097 : Overflow + +LED@4999 <-> @+500 +LED@5500 <-> @+500: 500ms +LED@6000 <-> @+500 +TIMER1@5520 <-> @+800: 800ms + +@enduml +*/ + +#[entry] +fn main() -> ! { + if let Some(p) = microbit::Peripherals::take() { + + // Start the LFCLK + p.CLOCK.tasks_lfclkstart.write(|w| unsafe { w.bits(1) }); + + let mut gpio = p.GPIO.split(); + + let mut pin = gpio.pin14.into_push_pull_output(); + let _ = gpio.pin6.into_push_pull_output(); + + // 32bits @ 1MHz = ~72 minutes + let mut timer0 = Timer::::new(p.TIMER0, 4); + // 16bits @ 31.25kHz = ~2 seconds + let mut timer1 = Timer::::new(p.TIMER1, 9); + // 16bits @ 31.25kHz = ~2 seconds + let mut timer2 = Timer::::new(p.TIMER2, 9); + + // 24bits @ 32.768kHz = 512 seconds + let mut rtc0 = Timer::::new(p.RTC0, 0); + // 24bits @ 32.768kHz = 512 seconds + let mut rtc1 = Timer::::new(p.RTC1, 0); + + let compare0 = Hfticks::from(Duration::from_millis(4_000)) + .checked_mul(timer0.frequency()) + .expect("ticks to compare value overflow"); + timer0.set_compare_start(0, compare0).unwrap(); + + let compare1 = Hfticks::from(Duration::from_millis(800)) + .checked_mul(timer1.frequency()) + .expect("ticks to compare value overflow"); + timer1.set_compare_start(0, compare1).unwrap(); + + let compare2 = Hfticks::from(Duration::from_millis(500)) + .checked_mul(timer2.frequency()) + .expect("ticks to compare value overflow"); + timer2.set_compare_start(0, compare2).unwrap(); + + let compare0 = Lfticks::from(Duration::from_millis(8_000)) + .checked_mul(rtc0.frequency()) + .expect("ticks to compare value overflow"); + rtc0.set_compare_start(0, compare0).unwrap(); + + let compare0 = Lfticks::from(Duration::from_millis(7_500)) + .checked_mul(rtc1.frequency()) + .expect("ticks to compare value overflow"); + rtc1.set_compare_start(0, compare0).unwrap(); + + // @500 + block!(timer2.nb_wait(0)); + pin.set_high(); + timer1.task_clear(); + + // @800 + block!(timer1.nb_wait(0)); + pin.set_low(); + + // @2097 + // Counter rolls over + + // @+500 + block!(timer2.nb_wait(0)); + pin.set_high(); + + // @+800 + block!(timer1.nb_wait(0)); + pin.set_low(); + + // @4000 + block!(timer0.nb_wait(0)); + // Setup to test stop and clear on interrupt + timer1.set_compare_int_stop(0); + timer2.set_compare_int_clear(0); + timer1.task_clear(); + timer2.task_clear(); + + // @+500 + block!(timer2.nb_wait(0)); + pin.set_high(); + + // @+500 + block!(timer2.nb_wait(0)); + pin.set_low(); + // timer1 interrupt and stops + + // @+500 + block!(timer2.nb_wait(0)); + pin.set_high(); + + // @+Δ + // timer1 is waiting with the compare event set + // this clears the event, but not the counter + block!(timer1.nb_wait(0)); + pin.set_low(); + + // @+Δ + // timer1 is stopped, compare event does not fire again + assert!(timer1.nb_wait(0) == Err(nb::Error::WouldBlock)); + + // @+500 + block!(timer2.nb_wait(0)); + pin.set_high(); + + // @+500 + block!(timer2.nb_wait(0)); + pin.set_low(); + + // @8000 + block!(rtc0.nb_wait(0)); + pin.set_high(); + + // @8500 + block!(rtc1.nb_wait(0)); + pin.set_low(); + + } + + panic!("FIN"); +} diff --git a/src/led.rs b/src/led.rs index 59e5110..bc618f5 100644 --- a/src/led.rs +++ b/src/led.rs @@ -1,12 +1,13 @@ //! On-board user LEDs -use hal::delay::Delay; +use hal::delay::{Timer, Delay}; +use hal::gpio::{Output, PushPull}; use hal::gpio::gpio::PIN; use hal::gpio::gpio::{ PIN10, PIN11, PIN12, PIN13, PIN14, PIN15, PIN4, PIN5, PIN6, PIN7, PIN8, PIN9, }; -use hal::gpio::{Output, PushPull}; use hal::prelude::*; +use nrf51::TIMER0; type LED = PIN>; @@ -94,13 +95,15 @@ impl Display { } /// Display 5x5 display image for a given duration - pub fn display(&mut self, delay: &mut Delay, led_display: [[u8; 5]; 5], duration_ms: u32) { + pub fn display(&mut self, delay: &mut Timer, led_display: [[u8; 5]; 5], duration_ms: u32) + { let led_matrix = Display::display2matrix(led_display); self.display_pre(delay, led_matrix, duration_ms); } /// Display 3x9 matrix image for a given duration - pub fn display_pre(&mut self, delay: &mut Delay, led_matrix: [[u8; 9]; 3], duration_ms: u32) { + pub fn display_pre(&mut self, delay: &mut Timer, led_matrix: [[u8; 9]; 3], duration_ms: u32) + { // TODO: something more intelligent with timers let loops = duration_ms / (self.rows.len() as u32 * self.delay_ms); for _ in 0..loops {