initial comms

This commit is contained in:
2025-10-25 12:23:23 -07:00
parent fd63bdc0c9
commit b067ae5cec
17 changed files with 536 additions and 356 deletions

View File

@@ -1,14 +1,11 @@
use crate::hardware::mcp23017::Mcp23017;
use crate::hardware::pin::PinDevice;
use anyhow::Result;
use crate::scheduler::{CyclicTask, TaskHandle};
use embedded_hal::digital::PinState;
use log::trace;
use std::fmt::Debug;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{channel, Sender};
use std::thread;
use std::thread::{sleep, Scope, ScopedJoinHandle};
use std::time::{Duration, Instant};
use std::fmt::{Debug, Formatter};
use std::sync::mpsc::Receiver;
use std::time::Instant;
#[derive(Clone, Debug)]
pub enum Mcp23017Message {
@@ -20,14 +17,7 @@ pub enum Mcp23017Message {
},
}
#[derive(Clone, Debug)]
pub struct Mcp23017Task {
#[allow(dead_code)]
name: String,
sender: Sender<Mcp23017Message>,
}
impl PinDevice for Mcp23017Task {
impl PinDevice for TaskHandle<Mcp23017Message> {
fn set_pin(&self, pin: u8, value: PinState, valid_until: Instant, priority: u8) {
trace!("Mcp23017Task::set_pin(self: {self:?}, pin: {pin}, value: {value:?})");
// This can only fail if the other end is disconnected - which we intentionally want to
@@ -41,6 +31,17 @@ impl PinDevice for Mcp23017Task {
}
}
pub struct Mcp23017Task<M: Mcp23017> {
mcp23017: M,
pins: AllPins,
}
impl<M: Mcp23017 + Debug> Debug for Mcp23017Task<M> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "Mcp23017Task {{ mcp23017: {:?} }}", self.mcp23017)
}
}
struct AllPins {
pins: [PinData; 16],
}
@@ -137,67 +138,48 @@ impl PinData {
}
}
impl Mcp23017Task {
pub fn start<'a, M: Mcp23017 + Send + Debug>(
scope: &'a Scope<'a, '_>,
running: &'a AtomicBool,
mut mcp23017: M,
name: String,
frequency: u64,
) -> Result<(ScopedJoinHandle<'a, ()>, Self)> where
M: 'a,
{
trace!("Mcp23017Task::start(scope, running, mcp23017: {mcp23017:?}, name: {name}, frequency: {frequency})");
impl<M: Mcp23017 + Debug> Mcp23017Task<M> {
pub fn new(mcp23017: M) -> Self {
trace!("Mcp23017Task::new(mcp23017: {mcp23017:?})");
Self {
mcp23017,
pins: AllPins::new(),
}
}
}
let (sender, receiver) = channel::<Mcp23017Message>();
let period = Duration::from_nanos(1_000_000_000 / frequency);
impl<M: Mcp23017> CyclicTask for Mcp23017Task<M> {
type Message = Mcp23017Message;
let handle = thread::Builder::new()
.name(name.clone())
.spawn_scoped(scope, move || {
let mut pins = AllPins::new();
let mut cycle_start_time = Instant::now();
while running.load(Ordering::Relaxed) {
let mut changed = false;
fn step(
&mut self,
receiver: &Receiver<Self::Message>,
step_time: Instant,
) {
let mut changed = false;
while let Ok(recv) = receiver.try_recv() {
match recv {
Mcp23017Message::SetPin { pin, value, valid_until, priority } => {
if (0u8..16u8).contains(&pin) {
pins.pins[pin as usize].set(value, valid_until, priority);
}
}
}
}
for pin in 0u8..16u8 {
// This shouldn't be able to fail
// TODO: handle error case
let state = pins.pins[pin as usize].get(cycle_start_time);
if pins.pins[pin as usize].changed {
pins.pins[pin as usize].changed = false;
let _ = mcp23017.set_pin(pin, state);
changed = true;
}
}
if changed {
let _ = mcp23017.flush();
}
cycle_start_time += period;
let sleep_duration = cycle_start_time - Instant::now();
if sleep_duration > Duration::ZERO {
sleep(sleep_duration);
while let Ok(recv) = receiver.try_recv() {
match recv {
Mcp23017Message::SetPin { pin, value, valid_until, priority } => {
if (0u8..16u8).contains(&pin) {
self.pins.pins[pin as usize].set(value, valid_until, priority);
}
}
})?;
Ok((
handle,
Self {
name,
sender,
}
))
}
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);
if self.pins.pins[pin as usize].changed {
self.pins.pins[pin as usize].changed = false;
let _ = self.mcp23017.set_pin(pin, state);
changed = true;
}
}
if changed {
let _ = self.mcp23017.flush();
}
}
}
}

View File

@@ -44,6 +44,7 @@ impl RaspiHardware {
Mode::Mode0,
)?), 3.3f64).into(),
mct8316a: SimMct8316a::new().into(),
// mct8316a: SimMct8316a::new().into(),
})
}
}