88 lines
2.5 KiB
Rust
88 lines
2.5 KiB
Rust
//! Bare bones state with pubsub access.
|
|
//! For more ergonomic access it might be nice to allow clients to subscribe to only the parts they
|
|
//! are interested in instead of the whole thing.
|
|
|
|
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pubsub::PubSubChannel};
|
|
|
|
use crate::{
|
|
leds::Matrix,
|
|
patterns::{PATTERNS, PATTERN_COUNT},
|
|
};
|
|
|
|
pub struct State {
|
|
pattern_idx: usize,
|
|
patterns: [Matrix; PATTERN_COUNT],
|
|
}
|
|
|
|
impl Default for State {
|
|
fn default() -> Self {
|
|
Self {
|
|
pattern_idx: Default::default(),
|
|
patterns: PATTERNS,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl State {
|
|
/// Switch to the next pattern on the left.
|
|
/// Wrap around to the last if it is already the first one.
|
|
pub fn pattern_left(&mut self) {
|
|
self.pattern_idx = if self.pattern_idx == 0 {
|
|
self.patterns.len() - 1
|
|
} else {
|
|
self.pattern_idx - 1
|
|
};
|
|
}
|
|
|
|
/// Switch to the next pattern on the right.
|
|
/// Wrap around to the first if it is already the last one.
|
|
pub fn pattern_right(&mut self) {
|
|
self.pattern_idx = if self.pattern_idx == self.patterns.len() - 1 {
|
|
0
|
|
} else {
|
|
self.pattern_idx + 1
|
|
};
|
|
}
|
|
|
|
/// Return the active patern.
|
|
pub fn pattern(&self) -> Matrix {
|
|
self.patterns[self.pattern_idx]
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy)]
|
|
pub enum StateChange {
|
|
/// Switch to the paatternon the left of the active one.
|
|
PatternLeft,
|
|
/// Switch to the paatternon the right of the active one.
|
|
PatternRight,
|
|
/// Publish a new active pattern.
|
|
Pattern(Matrix),
|
|
}
|
|
|
|
/// PubSub channel to listen to state changes and publish them as well.
|
|
pub static STATE: PubSubChannel<CriticalSectionRawMutex, StateChange, 4, 4, 4> =
|
|
PubSubChannel::new();
|
|
|
|
/// Subscribe to state change messages and update the state accordingly.
|
|
/// Publish when a new pattern is active.
|
|
#[embassy_executor::task]
|
|
pub async fn task() {
|
|
let mut state = State::default();
|
|
let state_pub = STATE.publisher().unwrap();
|
|
let mut state_sub = STATE.subscriber().unwrap();
|
|
|
|
loop {
|
|
let old_pattern = state.pattern();
|
|
match state_sub.next_message_pure().await {
|
|
StateChange::PatternLeft => state.pattern_left(),
|
|
StateChange::PatternRight => state.pattern_right(),
|
|
_ => (),
|
|
}
|
|
|
|
if old_pattern != state.pattern() {
|
|
state_pub.publish_immediate(StateChange::Pattern(state.pattern()));
|
|
}
|
|
}
|
|
}
|