initial comms
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ impl RaspiHardware {
|
||||
Mode::Mode0,
|
||||
)?), 3.3f64).into(),
|
||||
mct8316a: SimMct8316a::new().into(),
|
||||
// mct8316a: SimMct8316a::new().into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user