use core::cmp::Ordering; use core::marker::Unsize; use core::ops; use core::{mem, ptr}; use cortex_m::peripheral::{DWT, SYST}; use heapless::binary_heap::{BinaryHeap, Min}; pub use heapless::ring_buffer::{Consumer, Producer, RingBuffer}; #[repr(C)] pub struct Node where T: 'static, { baseline: Instant, next: Option>, payload: T, } impl Eq for Node {} impl Ord for Node { fn cmp(&self, rhs: &Self) -> Ordering { self.baseline.cmp(&rhs.baseline) } } impl PartialEq for Node { fn eq(&self, rhs: &Self) -> bool { self.baseline.eq(&rhs.baseline) } } impl PartialOrd for Node { fn partial_cmp(&self, rhs: &Self) -> Option { Some(self.cmp(rhs)) } } impl Node { pub const fn new() -> Self { Node { baseline: Instant(0), next: None, payload: uninitialized(), } } } pub struct Slot where T: 'static, { node: &'static mut Node, } impl Slot { pub fn new(node: &'static mut Node) -> Self { Slot { node } } pub fn write(self, bl: Instant, data: T) -> Payload { self.node.baseline = bl; unsafe { ptr::write(&mut self.node.payload, data) } Payload { node: self.node } } } pub struct FreeList where T: 'static, { head: Option>, } impl FreeList { pub const fn new() -> Self { FreeList { head: None } } pub fn pop(&mut self) -> Option> { self.head.take().map(|head| { self.head = head.node.next.take(); head }) } pub fn push(&mut self, slot: Slot) { slot.node.next = self.head.take(); self.head = Some(slot); } } pub struct Payload where T: 'static, { node: &'static mut Node, } impl Payload { pub fn read(self) -> (Instant, T, Slot) { let data = unsafe { ptr::read(&self.node.payload) }; (self.node.baseline, data, Slot { node: self.node }) } pub fn tag(self, tag: A) -> TaggedPayload where A: Copy, { TaggedPayload { tag, payload: unsafe { mem::transmute(self) }, } } } pub struct TaggedPayload where A: Copy, { tag: A, payload: Payload, } impl TaggedPayload where A: Copy, { pub unsafe fn coerce(self) -> Payload { mem::transmute(self.payload) } pub fn baseline(&self) -> Instant { self.payload.node.baseline } pub fn tag(&self) -> A { self.tag } pub fn retag(self, tag: B) -> TaggedPayload where B: Copy, { TaggedPayload { tag, payload: self.payload, } } } impl Eq for TaggedPayload where T: Copy, { } impl Ord for TaggedPayload where T: Copy, { fn cmp(&self, rhs: &Self) -> Ordering { self.payload.node.cmp(&rhs.payload.node) } } impl PartialEq for TaggedPayload where T: Copy, { fn eq(&self, rhs: &Self) -> bool { self.payload.node.eq(&rhs.payload.node) } } impl PartialOrd for TaggedPayload where T: Copy, { fn partial_cmp(&self, rhs: &Self) -> Option { Some(self.cmp(rhs)) } } pub struct TimerQueue where A: Unsize<[TaggedPayload]>, T: Copy, { pub syst: SYST, pub queue: BinaryHeap, A, Min>, } impl TimerQueue where A: Unsize<[TaggedPayload]>, T: Copy, { pub const fn new(syst: SYST) -> Self { TimerQueue { syst, queue: BinaryHeap::new(), } } } #[derive(Clone, Copy, Debug)] pub struct Instant(u32); impl Instant { pub fn now() -> Self { Instant(DWT::get_cycle_count()) } } impl Eq for Instant {} impl Ord for Instant { fn cmp(&self, rhs: &Self) -> Ordering { (self.0 as i32).wrapping_sub(rhs.0 as i32).cmp(&0) } } impl PartialEq for Instant { fn eq(&self, rhs: &Self) -> bool { self.0.eq(&rhs.0) } } impl PartialOrd for Instant { fn partial_cmp(&self, rhs: &Self) -> Option { Some(self.cmp(rhs)) } } impl ops::Add for Instant { type Output = Self; fn add(self, rhs: u32) -> Self { Instant(self.0.wrapping_add(rhs)) } } impl ops::Sub for Instant { type Output = i32; fn sub(self, rhs: Self) -> i32 { (self.0 as i32).wrapping_sub(rhs.0 as i32) } } const fn uninitialized() -> T { #[allow(unions_with_drop_fields)] union U { some: T, none: (), } unsafe { U { none: () }.some } }