From 7e826d24c7e43cd68f81ac3763161282cf47518f Mon Sep 17 00:00:00 2001 From: kelko Date: Sun, 15 Sep 2024 11:51:20 +0200 Subject: [PATCH] fix time handling for "now()" calculation --- README.md | 10 ----- src/keret-controller/src/main.rs | 2 +- src/keret-controller/src/time.rs | 58 +++++++++++++++++++++------ src/keret-service-transmit/src/lib.rs | 2 +- 4 files changed, 48 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index b20935f..99bc874 100644 --- a/README.md +++ b/README.md @@ -41,13 +41,3 @@ Components - **keret-adapter**: The CLI running on the connected device, reading the reports from the serial port and forwarding to the service - **keret-service**: The REST API service receiving and storing the activity reports - -TODO ------ - -### time handing ("now()") - -this is rudimentary at best and rather broken, as it does not yet handle timer wraps currently. Waiting for either -microbit-v2 crate to switch to embassy or otherwise understand which interrupt is caused by the SYST clock. - -But this does not hinder the usability of the example to showcase the original goal. diff --git a/src/keret-controller/src/main.rs b/src/keret-controller/src/main.rs index 3339955..6a4c4ae 100644 --- a/src/keret-controller/src/main.rs +++ b/src/keret-controller/src/main.rs @@ -44,7 +44,7 @@ fn main() -> ! { let mut timer = Timer::new(board.TIMER0).into_periodic(); init_display(board.TIMER1, board.display_pins); - init_time(board.SYST); + init_time(board.CLOCK, board.RTC1); init_buttons(board.GPIOTE, board.buttons); let mut serial = uarte::Uarte::new( diff --git a/src/keret-controller/src/time.rs b/src/keret-controller/src/time.rs index 20de765..a7ce3f1 100644 --- a/src/keret-controller/src/time.rs +++ b/src/keret-controller/src/time.rs @@ -1,27 +1,61 @@ use core::cell::RefCell; use cortex_m::interrupt::{free, Mutex}; -use microbit::hal::pac::SYST; +use microbit::hal::rtc::RtcCompareReg; +use microbit::{ + hal::rtc::RtcInterrupt, + hal::{Clocks, Rtc}, + pac::{self, interrupt, CLOCK, RTC1}, +}; -static DISPLAY: Mutex>> = Mutex::new(RefCell::new(None)); +static RTC_TIMER: Mutex>>> = Mutex::new(RefCell::new(None)); +static PERIOD: Mutex> = Mutex::new(RefCell::new(0)); -pub(crate) fn init_time(mut board_syst: SYST) { - board_syst.set_reload(0x00ffffff); - board_syst.clear_current(); - //board_syst.enable_interrupt(); - board_syst.enable_counter(); +pub(crate) fn init_time(clock: CLOCK, rtc: RTC1) { + Clocks::new(clock).start_lfclk(); + + let mut rtc1 = Rtc::new(rtc, 0).unwrap(); + rtc1.set_compare(RtcCompareReg::Compare3, 0x800000).unwrap(); + rtc1.enable_event(RtcInterrupt::Overflow); + rtc1.enable_interrupt(RtcInterrupt::Overflow, None); + rtc1.enable_event(RtcInterrupt::Compare3); + rtc1.enable_interrupt(RtcInterrupt::Compare3, None); + rtc1.clear_counter(); + rtc1.enable_counter(); + + while rtc1.get_counter() != 0 {} free(move |cs| { - *DISPLAY.borrow(cs).borrow_mut() = Some(board_syst); + *RTC_TIMER.borrow(cs).borrow_mut() = Some(rtc1); + + unsafe { + pac::NVIC::unmask(pac::Interrupt::RTC1); + } }); } -fn calc_now(period: u32, counter: u32) -> u64 { +fn construct_ticks(period: u32, counter: u32) -> u64 { ((period as u64) << 23) + ((counter ^ ((period & 1) << 23)) as u64) } pub(crate) fn now() -> u64 { - let p = 0_u32; - let v = SYST::get_current(); + let (period, current_value) = free(|cs| { + let p = *PERIOD.borrow(cs).borrow(); + + let timer = RTC_TIMER.borrow(cs).borrow_mut(); + let v = timer.as_ref().map(|rtc| rtc.get_counter()).unwrap(); + + (p, v) + }); + + construct_ticks(period, current_value) / 32768 +} + +#[interrupt] +unsafe fn RTC1() { + free(|cs| { + let current = *PERIOD.borrow(cs).borrow(); + let next = current + 1; - calc_now(p, v) + *PERIOD.borrow(cs).borrow_mut() = next; + }) } diff --git a/src/keret-service-transmit/src/lib.rs b/src/keret-service-transmit/src/lib.rs index 8e7f202..e0318da 100644 --- a/src/keret-service-transmit/src/lib.rs +++ b/src/keret-service-transmit/src/lib.rs @@ -12,7 +12,7 @@ impl From for ActionReport { fn from(value: u64) -> Self { Self { timestamp: Utc::now(), - duration: Duration::from_micros(value), + duration: Duration::from_secs(value), } } }