veecle_osal_embassy/
time.rs1use core::sync::atomic::{AtomicU32, Ordering};
4use veecle_osal_api::Error;
5pub use veecle_osal_api::time::{
6 Duration, Instant, Interval, SystemTime, SystemTimeError, SystemTimeSync, TimeAbstraction,
7};
8
9#[derive(Debug)]
17pub struct Time;
18
19impl TimeAbstraction for Time {
20 fn now() -> Instant {
21 Instant::MIN + Duration::from_millis(embassy_time::Instant::now().as_millis())
22 }
23
24 async fn sleep_until(deadline: Instant) -> Result<(), Error> {
25 Self::sleep(
26 deadline
27 .duration_since(Self::now())
28 .unwrap_or(Duration::ZERO),
29 )
30 .await
31 }
32
33 async fn sleep(duration: Duration) -> Result<(), Error> {
34 let mut duration = duration;
38 while Self::now().checked_add(duration).is_none() {
39 duration = duration / 2;
40 }
41 embassy_time::Timer::after(embassy_time::Duration::from_millis(duration.as_millis())).await;
42 Ok(())
43 }
44
45 fn interval(period: Duration) -> impl Interval
46 where
47 Self: Sized,
48 {
49 struct IntervalInternal {
50 ticker: embassy_time::Ticker,
51 first_poll: bool,
52 }
53
54 impl Interval for IntervalInternal {
55 async fn tick(&mut self) -> Result<(), Error> {
56 if self.first_poll {
58 self.first_poll = false;
59 return Ok(());
60 }
61
62 self.ticker.next().await;
63 Ok(())
64 }
65 }
66
67 IntervalInternal {
68 ticker: embassy_time::Ticker::every(embassy_time::Duration::from_millis(
69 period.as_millis(),
70 )),
71 first_poll: true,
72 }
73 }
74}
75
76static SYSTEM_TIME_OFFSET_SECONDS: AtomicU32 = AtomicU32::new(0);
77
78impl SystemTime for Time {
79 fn duration_since_epoch() -> Result<Duration, SystemTimeError> {
80 let offset = SYSTEM_TIME_OFFSET_SECONDS.load(Ordering::Relaxed);
81 if offset == 0 {
82 Err(SystemTimeError::Unsynchronized)
83 } else {
84 let duration_since_start = Self::now()
85 .duration_since(Instant::MIN)
86 .expect("now can't be less than min time");
87 Ok(duration_since_start + Duration::from_secs(offset as u64))
88 }
89 }
90}
91
92impl SystemTimeSync for Time {
93 fn set_system_time(duration_since_epoch: Duration) -> Result<(), SystemTimeError> {
94 let duration_since_start = Self::now()
95 .duration_since(Instant::MIN)
96 .expect("now can't be less than min time");
97
98 if duration_since_epoch < duration_since_start {
99 Err(SystemTimeError::EpochIsLaterThanStartTime)
100 } else {
101 SYSTEM_TIME_OFFSET_SECONDS.store(
102 (duration_since_epoch - duration_since_start).as_secs() as u32,
103 Ordering::Relaxed,
104 );
105 Ok(())
106 }
107 }
108}