#![no_std] pub mod display; pub mod backoff; pub mod events; pub mod tasks; pub mod shaders; pub mod ego; pub mod animation; pub mod idle; pub mod logging; extern crate alloc; use core::{iter::Sum, ops::{Div, Sub}, fmt::Debug}; #[derive(Debug, Clone, Copy)] pub struct CircularBuffer { data: [T; SIZE], next_index: usize, filled: bool } impl Default for CircularBuffer { fn default() -> Self { Self { data: [Default::default(); SIZE], next_index: 0, filled: false } } } impl CircularBuffer { pub fn insert(&mut self, value: T) { self.data[self.next_index] = value; self.next_index += 1; if self.next_index == self.data.len() { self.next_index = 0; self.filled = true; } } pub fn data(&self) -> &[T; SIZE] { &self.data } pub fn is_filled(&self) -> bool { self.filled } pub fn mean(&self) -> T where T: for<'a> Sum<&'a T> + Div { self.data.iter().sum::() / self.data.len() as f32 } pub fn derivative(&self) -> T where for<'a> &'a T: Sub<&'a T, Output = T>, T: Sum + Div { self.data.windows(2).map(|n| { &n[0] - &n[1] }).sum::().div(self.data.len() as f32) } } #[derive(Debug, Default)] pub struct Breaker { tripped: bool, value: T } impl Breaker { pub fn set(&mut self, value: T) { if self.value != value { self.value = value; self.tripped = true; } } pub fn read_tripped(&mut self) -> Option { if self.tripped { //info!("Tripped: {self:?}"); self.tripped = false; Some(self.value) } else { None } } }