Skip to content

Commit

Permalink
Add basic support for blinking LEDs
Browse files Browse the repository at this point in the history
  • Loading branch information
uklotzde committed Aug 20, 2023
1 parent 72db2bb commit 4fdd910
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 2 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ include = ["/src", "/README.md", "/LICENSES"]

[dependencies]
anyhow = "1.0.75"
async-stream = "0.3.5"
derive_more = "0.99.17"
float-cmp = "0.9.0"
futures = "0.3.28"
is_sorted = "0.1.1"
log = "0.4.20"
strum = { version = "0.25.0", features = ["derive"] }
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ pub use self::input::{

mod output;
pub use self::output::{
ControlOutputGateway, DimLedOutput, LedOutput, OutputError, OutputResult, RgbLedOutput,
SendOutputsError,
BlinkingLedsOutput, BlinkingLedsTicker, ControlOutputGateway, DimLedOutput, LedOutput,
LedState, OutputError, OutputResult, RgbLedOutput, SendOutputsError,
};

/// Common, information properties about a device.
Expand Down
107 changes: 107 additions & 0 deletions src/output/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::{
ops::{Deref, DerefMut},
};

use futures::StreamExt as _;
use strum::FromRepr;
use thiserror::Error;

Expand Down Expand Up @@ -146,3 +147,109 @@ where
self.deref_mut().send_outputs(outputs)
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LedState {
Off,
BlinkFast,
BlinkSlow,
On,
}

impl LedState {
#[must_use]
pub const fn is_blinking(self) -> bool {
match self {
Self::BlinkFast | Self::BlinkSlow => true,
Self::Off | Self::On => false,
}
}

/// Initial LED output
///
/// Blinking should always start by turning on the LED before
/// the periodic switching takes over.
#[must_use]
pub const fn initial_output(self) -> LedOutput {
self.output(BlinkingLedsOutput::ON)
}

/// LED output depending on the current blinking state
#[must_use]
pub const fn output(self, blinking_leds_output: BlinkingLedsOutput) -> LedOutput {
match self {
Self::Off => LedOutput::Off,
Self::BlinkFast => blinking_leds_output.fast,
Self::BlinkSlow => blinking_leds_output.slow,
Self::On => LedOutput::On,
}
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct BlinkingLedsOutput {
pub fast: LedOutput,
pub slow: LedOutput,
}

impl BlinkingLedsOutput {
pub const ON: Self = Self {
fast: LedOutput::On,
slow: LedOutput::On,
};
}

#[derive(Debug, Default)]
pub struct BlinkingLedsTicker(usize);

impl BlinkingLedsTicker {
fn output_from_value(value: usize) -> BlinkingLedsOutput {
match value & 0b11 {
0b00 => BlinkingLedsOutput {
fast: LedOutput::On,
slow: LedOutput::On,
},
0b01 => BlinkingLedsOutput {
fast: LedOutput::Off,
slow: LedOutput::On,
},
0b10 => BlinkingLedsOutput {
fast: LedOutput::On,
slow: LedOutput::Off,
},
0b11 => BlinkingLedsOutput {
fast: LedOutput::Off,
slow: LedOutput::Off,
},
_ => unreachable!(),
}
}

#[must_use]
pub fn tick(&mut self) -> BlinkingLedsOutput {
let value = self.0;
self.0 = self.0.wrapping_add(1);
Self::output_from_value(value)
}

#[must_use]
pub fn output(&self) -> BlinkingLedsOutput {
let value = self.0;
Self::output_from_value(value)
}

pub fn map_into_output_stream(
self,
periodic: impl futures::Stream<Item = ()> + 'static,
) -> impl futures::Stream<Item = BlinkingLedsOutput> {
futures::stream::unfold(
(self, Box::pin(periodic)),
|(mut ticker, mut periodic)| async move {
periodic.next().await.map(|()| {
let output = ticker.tick();
(output, (ticker, periodic))
})
},
)
}
}

0 comments on commit 4fdd910

Please sign in to comment.