From 571e4f2b01b0d2d8a9e566e49df306d84cd4c9ef Mon Sep 17 00:00:00 2001
From: Dario Nieuwenhuis <dirbaio@dirbaio.net>
Date: Fri, 24 Jun 2022 23:27:46 +0200
Subject: [PATCH] embassy/time: round up by default in `Duration::from_*`.
 Fixes #823

---
 embassy/src/time/duration.rs | 35 +++++++++++++++++++++++++++++++----
 1 file changed, 31 insertions(+), 4 deletions(-)

diff --git a/embassy/src/time/duration.rs b/embassy/src/time/duration.rs
index d35c2b65..dc4f16bd 100644
--- a/embassy/src/time/duration.rs
+++ b/embassy/src/time/duration.rs
@@ -41,23 +41,45 @@ impl Duration {
         Duration { ticks }
     }
 
-    /// Creates a duration from the specified number of seconds
+    /// Creates a duration from the specified number of seconds, rounding up.
     pub const fn from_secs(secs: u64) -> Duration {
         Duration {
             ticks: secs * TICKS_PER_SECOND,
         }
     }
 
-    /// Creates a duration from the specified number of milliseconds
+    /// Creates a duration from the specified number of milliseconds, rounding up.
     pub const fn from_millis(millis: u64) -> Duration {
+        Duration {
+            ticks: div_ceil(millis * (TICKS_PER_SECOND / GCD_1K), 1000 / GCD_1K),
+        }
+    }
+
+    /// Creates a duration from the specified number of microseconds, rounding up.
+    /// NOTE: Delays this small may be inaccurate.
+    pub const fn from_micros(micros: u64) -> Duration {
+        Duration {
+            ticks: div_ceil(micros * (TICKS_PER_SECOND / GCD_1M), 1_000_000 / GCD_1M),
+        }
+    }
+
+    /// Creates a duration from the specified number of seconds, rounding down.
+    pub const fn from_secs_floor(secs: u64) -> Duration {
+        Duration {
+            ticks: secs * TICKS_PER_SECOND,
+        }
+    }
+
+    /// Creates a duration from the specified number of milliseconds, rounding down.
+    pub const fn from_millis_floor(millis: u64) -> Duration {
         Duration {
             ticks: millis * (TICKS_PER_SECOND / GCD_1K) / (1000 / GCD_1K),
         }
     }
 
-    /// Creates a duration from the specified number of microseconds
+    /// Creates a duration from the specified number of microseconds, rounding down.
     /// NOTE: Delays this small may be inaccurate.
-    pub const fn from_micros(micros: u64) -> Duration {
+    pub const fn from_micros_floor(micros: u64) -> Duration {
         Duration {
             ticks: micros * (TICKS_PER_SECOND / GCD_1M) / (1_000_000 / GCD_1M),
         }
@@ -155,3 +177,8 @@ impl<'a> fmt::Display for Duration {
         write!(f, "{} ticks", self.ticks)
     }
 }
+
+#[inline]
+const fn div_ceil(num: u64, den: u64) -> u64 {
+    (num + den - 1) / den
+}