#![doc = include_str!("../README.md")]
#![cfg_attr(not(test), no_std)]
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct TimedSignal {
state: bool,
tick_action: TickAction,
inverted: bool,
}
#[derive(Debug, Default, Clone, PartialEq, Eq)]
enum TickAction {
#[default]
None,
Set(u64, bool),
SetFor(u64, bool),
Blink(u32),
}
impl TimedSignal {
pub fn new() -> Self {
Self::default()
}
pub fn update(&mut self, tick: u64) -> bool {
match self.tick_action {
TickAction::Set(trigger_tick, state) => {
if tick >= trigger_tick {
self.state = state;
self.tick_action = TickAction::None;
}
}
TickAction::SetFor(duration_ticks, state) => {
self.state = state;
self.tick_action = TickAction::Set(tick + duration_ticks, !state);
return self.update(tick);
}
TickAction::Blink(blink_period) => {
self.state = (tick as u32 % blink_period) < (blink_period >> 1)
}
_ => {}
}
self.state()
}
pub fn state(&self) -> bool {
self.state ^ self.inverted
}
pub fn set_inverted(&mut self, inverted: bool) {
self.inverted = inverted;
}
pub fn is_inverted(&self) -> bool {
self.inverted
}
pub fn set(&mut self, state: bool) {
self.state = state;
self.tick_action = TickAction::None;
}
pub fn on(&mut self) {
self.set(true);
}
pub fn off(&mut self) {
self.set(false);
}
pub fn toggle(&mut self) {
self.set(!self.state);
}
pub fn blink(&mut self, period: u32) {
self.tick_action = TickAction::Blink(period);
}
pub fn set_at(&mut self, trigger_tick: u64, state: bool) {
self.tick_action = TickAction::Set(trigger_tick, state);
}
pub fn set_until(&mut self, trigger_tick: u64, state: bool) {
self.set(state);
self.tick_action = TickAction::Set(trigger_tick, !state);
}
pub fn set_for(&mut self, duration_ticks: u64, state: bool) {
if self.tick_action == TickAction::None {
self.tick_action = TickAction::SetFor(duration_ticks, state);
}
}
pub fn set_for_retrigger(&mut self, duration_ticks: u64, state: bool) {
self.tick_action = TickAction::SetFor(duration_ticks, state);
}
pub fn on_at(&mut self, trigger_tick: u64) {
self.set_at(trigger_tick, true);
}
pub fn on_until(&mut self, trigger_tick: u64) {
self.set_until(trigger_tick, true);
}
pub fn on_for(&mut self, duration_ticks: u64) {
self.set_for(duration_ticks, true);
}
pub fn off_at(&mut self, trigger_tick: u64) {
self.set_at(trigger_tick, false);
}
pub fn off_until(&mut self, trigger_tick: u64) {
self.set_until(trigger_tick, false);
}
pub fn off_for(&mut self, duration_ticks: u64) {
self.set_for(duration_ticks, false);
}
pub fn toggle_at(&mut self, trigger_tick: u64) {
if self.tick_action == TickAction::None {
self.tick_action = TickAction::Set(trigger_tick, !self.state);
}
}
pub fn toggle_until(&mut self, trigger_tick: u64) {
if self.tick_action == TickAction::None {
self.toggle();
self.tick_action = TickAction::Set(trigger_tick, !self.state);
}
}
pub fn toggle_for(&mut self, duration_ticks: u64) {
if self.tick_action == TickAction::None {
self.tick_action = TickAction::SetFor(duration_ticks, !self.state);
}
}
pub fn toggle_for_retrigger(&mut self, duration_ticks: u64) {
match self.tick_action {
TickAction::Set(_, state) => {
self.tick_action = TickAction::SetFor(duration_ticks, !state);
}
_ => {
self.tick_action = TickAction::SetFor(duration_ticks, !self.state);
}
}
}
}
#[cfg(test)]
mod tests;