-
Notifications
You must be signed in to change notification settings - Fork 293
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/timeint #453
Closed
+228
−1
Closed
Feature/timeint #453
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,223 @@ | ||
use embedded_time::TimeInt; | ||
use embedded_time::fraction::Fraction; | ||
use core::fmt; | ||
use core::ops::{Add, Sub, Mul, Div, Rem}; | ||
|
||
#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, fmt::Debug)] | ||
pub struct U24(u32); | ||
impl U24 { | ||
pub const unsafe fn new_unchecked(n: u32) -> Self { | ||
// SAFETY: this is guaranteed to be safe by the caller. | ||
Self(n) | ||
} | ||
|
||
pub const fn new(n: u32) -> Option<Self> { | ||
if n <= 0xffffff { | ||
Some(Self(n)) | ||
} else { | ||
None | ||
} | ||
} | ||
|
||
pub const fn new_wrap(n: u32) -> Self { | ||
Self(n & 0xffffff) | ||
} | ||
|
||
pub const fn get(self) -> u32 { | ||
self.0 | ||
} | ||
} | ||
|
||
impl fmt::Display for U24 { | ||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
write!(f, "{}", self.0) | ||
} | ||
} | ||
|
||
impl Add for U24 { | ||
type Output = Self; | ||
fn add(self, other: Self) -> Self { | ||
let res = self.get().add(other.get()); | ||
debug_assert!(res <= 0xffffff); | ||
Self::new_wrap(res) | ||
} | ||
} | ||
|
||
impl Sub for U24 { | ||
type Output = Self; | ||
fn sub(self, other: Self) -> Self { | ||
let res = self.get().sub(other.get()); | ||
// Note: underflow detection in debug is already done by u32's sub | ||
Self::new_wrap(res) | ||
} | ||
} | ||
|
||
impl Mul for U24 { | ||
type Output = Self; | ||
fn mul(self, other: Self) -> Self { | ||
let res = self.get().mul(other.get()); | ||
debug_assert!(res <= 0xffffff); | ||
Self::new_wrap(res) | ||
} | ||
} | ||
|
||
impl Div for U24 { | ||
type Output = Self; | ||
fn div(self, other: Self) -> Self { | ||
// SAFETY: division by zero detection is already done by u32's div | ||
// and division cannot overflow | ||
unsafe { Self::new_unchecked(self.get().div(other.get())) } | ||
} | ||
} | ||
|
||
impl Rem for U24 { | ||
type Output = Self; | ||
fn rem(self, other: Self) -> Self { | ||
// SAFETY: rem cannot overflow | ||
unsafe { Self::new_unchecked(self.get().rem(other.get())) } | ||
} | ||
} | ||
|
||
impl num::One for U24 { | ||
fn one() -> Self { | ||
Self(1) | ||
} | ||
} | ||
|
||
impl num::Zero for U24 { | ||
fn zero() -> Self { | ||
Self(0) | ||
} | ||
|
||
fn is_zero(&self) -> bool { | ||
self.get() == 0 | ||
} | ||
} | ||
|
||
impl num::Num for U24 { | ||
type FromStrRadixErr = core::num::ParseIntError; | ||
fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> { | ||
u32::from_str_radix(str, radix) | ||
.and_then(|n| | ||
// If we are too big, we manually generate a ParseIntError | ||
Self::new(n).ok_or_else(|| | ||
u32::from_str_radix("100000000", 16).unwrap_err() | ||
) | ||
) | ||
} | ||
} | ||
|
||
impl num::Integer for U24 { | ||
fn div_floor(&self, other: &Self) -> Self { | ||
// SAFETY: div_floor cannot overflow | ||
unsafe { Self::new_unchecked(self.get().div_floor(&other.get())) } | ||
} | ||
fn mod_floor(&self, other: &Self) -> Self { | ||
// SAFETY: div_floor cannot overflow | ||
unsafe { Self::new_unchecked(self.get().mod_floor(&other.get())) } | ||
} | ||
fn gcd(&self, other: &Self) -> Self { | ||
// SAFETY: gcd cannot overflow | ||
unsafe { Self::new_unchecked(self.get().gcd(&other.get())) } | ||
} | ||
fn lcm(&self, other: &Self) -> Self { | ||
Self::new(self.get().lcm(&other.get())).unwrap() | ||
} | ||
fn divides(&self, other: &Self) -> bool { | ||
self.get().divides(&other.get()) | ||
} | ||
fn is_multiple_of(&self, other: &Self) -> bool { | ||
self.get().is_multiple_of(&other.get()) | ||
} | ||
fn is_even(&self) -> bool { | ||
self.get().is_even() | ||
} | ||
fn is_odd(&self) -> bool { | ||
self.get().is_odd() | ||
} | ||
fn div_rem(&self, other: &Self) -> (Self, Self) { | ||
let (div, rem) = self.get().div_rem(&other.get()); | ||
// SAFETY: div_floor cannot overflow | ||
unsafe { ( Self::new_unchecked(div), Self::new_unchecked(rem) ) } | ||
} | ||
} | ||
|
||
impl num::Bounded for U24 { | ||
fn min_value() -> Self { | ||
// SAFETY: 0 is within bounds | ||
unsafe { Self::new_unchecked(0) } | ||
} | ||
fn max_value() -> Self { | ||
// SAFETY: 0xffffff is within bounds | ||
unsafe { Self::new_unchecked(0xffffff) } | ||
} | ||
} | ||
|
||
impl num::traits::WrappingAdd for U24 { | ||
fn wrapping_add(&self, v: &Self) -> Self { | ||
Self::new_wrap(self.get().wrapping_add(v.get())) | ||
} | ||
} | ||
|
||
impl num::traits::WrappingSub for U24 { | ||
fn wrapping_sub(&self, v: &Self) -> Self { | ||
Self::new_wrap(self.get().wrapping_sub(v.get())) | ||
} | ||
} | ||
|
||
impl num::traits::CheckedAdd for U24 { | ||
fn checked_add(&self, v: &Self) -> Option<Self> { | ||
self.get() | ||
.checked_add(v.get()) | ||
.and_then(|n| Self::new(n)) | ||
} | ||
} | ||
|
||
impl num::traits::CheckedSub for U24 { | ||
fn checked_sub(&self, v: &Self) -> Option<Self> { | ||
self.get() | ||
.checked_sub(v.get()) | ||
// SAFETY: checked_sub cannot overflow | ||
.and_then(|n| Some(unsafe { Self::new_unchecked(n) })) | ||
} | ||
} | ||
|
||
impl num::traits::CheckedMul for U24 { | ||
fn checked_mul(&self, v: &Self) -> Option<Self> { | ||
self.get() | ||
.checked_mul(v.get()) | ||
.and_then(|n| Self::new(n)) | ||
} | ||
} | ||
|
||
impl num::traits::CheckedDiv for U24 { | ||
fn checked_div(&self, v: &Self) -> Option<Self> { | ||
self.get() | ||
.checked_div(v.get()) | ||
// SAFETY: checked_div cannot overflow | ||
.and_then(|n| Some(unsafe { Self::new_unchecked(n) })) | ||
} | ||
} | ||
|
||
impl From<u32> for U24 { | ||
/// Use the 24 lowest bits from n, ignore the rest | ||
fn from(n: u32) -> Self { | ||
Self::new_wrap(n) | ||
} | ||
} | ||
|
||
impl Mul<Fraction> for U24 { | ||
type Output = Self; | ||
fn mul(self, other: Fraction) -> Self { | ||
Self::new(self.get() * other).unwrap() | ||
} | ||
} | ||
|
||
impl Div<Fraction> for U24 { | ||
type Output = Self; | ||
fn div(self, other: Fraction) -> Self { | ||
Self::new(self.get() / other).unwrap() | ||
} | ||
} | ||
|
||
impl TimeInt for U24 {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,3 +5,4 @@ | |
pub mod firmware_protection; | ||
pub mod upgrade_storage; | ||
pub mod clock; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be sorted. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,8 @@ use embedded_time::duration::Milliseconds; | |
pub use embedded_time::Clock; | ||
#[cfg(not(feature = "std"))] | ||
use libtock_drivers::result::FlexUnwrap; | ||
#[cfg(target_pointer_width = "32")] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we always want to use |
||
use super::api::clock::U24; | ||
|
||
#[cfg(not(feature = "std"))] | ||
pub struct LibtockClock<const CLOCK_FREQUENCY: u32>(libtock_drivers::timer::Timer<'static>); | ||
|
@@ -28,7 +30,7 @@ const KEEPALIVE_DELAY_MS: ClockInt = 100; | |
pub const KEEPALIVE_DELAY: Milliseconds<ClockInt> = Milliseconds(KEEPALIVE_DELAY_MS); | ||
|
||
#[cfg(target_pointer_width = "32")] | ||
pub type ClockInt = u32; | ||
pub type ClockInt = U24; | ||
#[cfg(target_pointer_width = "64")] | ||
pub type ClockInt = u64; | ||
|
||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to
& 0xffffff
here and inWrappingAdd
too.