initial state vector implementation

This commit is contained in:
2025-10-25 16:11:39 -07:00
parent b067ae5cec
commit e0f17649b2
8 changed files with 244 additions and 28 deletions

View File

@@ -13,4 +13,5 @@ pub trait Mcp23017 {
}
pub use driver::Mcp23017Driver;
pub use task::Mcp23017State;
pub use task::Mcp23017Task;

View File

@@ -1,6 +1,7 @@
use crate::hardware::mcp23017::Mcp23017;
use crate::hardware::pin::PinDevice;
use crate::scheduler::{CyclicTask, TaskHandle};
use crate::state_vector::{SectionIdentifier, SectionWriter, StateVector};
use embedded_hal::digital::PinState;
use log::trace;
use std::fmt::{Debug, Formatter};
@@ -31,12 +32,18 @@ impl PinDevice for TaskHandle<Mcp23017Message> {
}
}
pub struct Mcp23017Task<M: Mcp23017> {
mcp23017: M,
pins: AllPins,
#[derive(Default)]
pub struct Mcp23017State {
pub pins: [bool; 16],
}
impl<M: Mcp23017 + Debug> Debug for Mcp23017Task<M> {
pub struct Mcp23017Task<'a, M: Mcp23017> {
mcp23017: M,
pins: AllPins,
state: SectionWriter<'a, Mcp23017State>,
}
impl<M: Mcp23017 + Debug> Debug for Mcp23017Task<'_, M> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "Mcp23017Task {{ mcp23017: {:?} }}", self.mcp23017)
}
@@ -64,6 +71,7 @@ struct PinData {
next_priority: u8,
default: PinState,
changed: bool,
value: PinState,
}
impl PinData {
@@ -77,16 +85,18 @@ impl PinData {
next_priority: 0,
default: PinState::Low,
changed: false,
value: PinState::Low,
}
}
fn get(&mut self, now: Instant) -> PinState {
fn evaluate(&mut self, now: Instant) {
// Do this twice to check both the current and the current next
// If the current is currently invalid, we'd upgrade the next to current
for _ in 0..2 {
let is_current_valid = self.valid_until.map(|current| current >= now).unwrap_or(false);
if is_current_valid {
return self.state;
self.value = self.state;
return;
} else {
if self.valid_until.is_some() {
self.changed = true;
@@ -100,7 +110,7 @@ impl PinData {
}
}
self.default
self.value = self.default;
}
fn set(&mut self, value: PinState, valid_until: Instant, priority: u8) {
@@ -123,6 +133,7 @@ impl PinData {
self.valid_until = Some(valid_until);
self.priority = priority;
self.changed = true;
self.value = value;
} else {
// This is not the highest priority thing
if self.priority >= self.next_priority {
@@ -138,17 +149,22 @@ impl PinData {
}
}
impl<M: Mcp23017 + Debug> Mcp23017Task<M> {
pub fn new(mcp23017: M) -> Self {
impl<'a, M: Mcp23017 + Debug> Mcp23017Task<'a, M> {
pub fn new(mcp23017: M, state_vector: &'a StateVector) -> Self {
trace!("Mcp23017Task::new(mcp23017: {mcp23017:?})");
Self {
mcp23017,
pins: AllPins::new(),
state: state_vector.create_section(Mcp23017State::default()),
}
}
pub fn get_state(&self) -> SectionIdentifier {
self.state.get_identifier()
}
}
impl<M: Mcp23017> CyclicTask for Mcp23017Task<M> {
impl<M: Mcp23017> CyclicTask for Mcp23017Task<'_, M> {
type Message = Mcp23017Message;
fn step(
@@ -158,6 +174,10 @@ impl<M: Mcp23017> CyclicTask for Mcp23017Task<M> {
) {
let mut changed = false;
for pin in 0u8..16u8 {
self.pins.pins[pin as usize].evaluate(step_time);
}
while let Ok(recv) = receiver.try_recv() {
match recv {
Mcp23017Message::SetPin { pin, value, valid_until, priority } => {
@@ -169,17 +189,20 @@ impl<M: Mcp23017> CyclicTask for Mcp23017Task<M> {
}
for pin in 0u8..16u8 {
// This shouldn't be able to fail
// TODO: handle error case
let state = self.pins.pins[pin as usize].get(step_time);
let state = self.pins.pins[pin as usize].value;
if self.pins.pins[pin as usize].changed {
self.pins.pins[pin as usize].changed = false;
// This shouldn't be able to fail
// TODO: handle error case
let _ = self.mcp23017.set_pin(pin, state);
changed = true;
}
}
if changed {
let _ = self.mcp23017.flush();
self.state.update(|s| {
s.pins = self.pins.pins.map(|pin| pin.value == PinState::High);
});
}
}
}