Switch to fully composition based Transducers.

This commit is contained in:
Zachary Sunforge
2023-06-17 10:41:20 -07:00
parent ad66d8e030
commit 60e0edf7d2
6 changed files with 116 additions and 105 deletions

View File

@ -33,8 +33,8 @@ use embassy_stm32::peripherals::{EXTI6, PF6, PF7, SPI3};
use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::blocking_mutex::raw::NoopRawMutex;
use embassy_sync::pubsub::PubSubChannel; use embassy_sync::pubsub::PubSubChannel;
use physical_ads1256::{standard_input, SingleEnded}; use physical_ads1256::{standard_input, SingleEnded};
use physical_node::transducer::input::RawStatePubInput; use physical_node::transducer::input::StatefulPublisher;
use physical_node::transducer::Publisher; use physical_node::transducer::Publish;
const AUTOCAL_CONF: Config = Config { const AUTOCAL_CONF: Config = Config {
status: Status::setting(Buffer::Enabled, AutoCal::Enabled, BitOrder::MostSigFirst), status: Status::setting(Buffer::Enabled, AutoCal::Enabled, BitOrder::MostSigFirst),
@ -58,9 +58,9 @@ impl ads1256::BlockingDelay for Ads1256Delay {
} }
struct Inputs { struct Inputs {
ai1: RawStatePubInput<f32::ElectricPotential, NoopRawMutex, 10, 1>, ai1: StatefulPublisher<f32::ElectricPotential, NoopRawMutex, 10, 1>,
ai2: RawStatePubInput<f32::ElectricPotential, NoopRawMutex, 10, 1>, ai2: StatefulPublisher<f32::ElectricPotential, NoopRawMutex, 10, 1>,
ai3: RawStatePubInput<f32::ElectricPotential, NoopRawMutex, 10, 1>, ai3: StatefulPublisher<f32::ElectricPotential, NoopRawMutex, 10, 1>,
} }
// Inputs // Inputs
@ -101,17 +101,17 @@ async fn main(spawner: Spawner) {
let ads_1256 = ADS_1256.init(Ads1256::new(Ads1256Delay, select_ads1256, ads1256_data_ready)); let ads_1256 = ADS_1256.init(Ads1256::new(Ads1256Delay, select_ads1256, ads1256_data_ready));
let inputs = &*ANALOG_INPUTS.init(Inputs { let inputs = &*ANALOG_INPUTS.init(Inputs {
ai1: RawStatePubInput::new( ai1: StatefulPublisher::new(
Cell::new(f32::ElectricPotential::new::<volt>(-1000.0)), Cell::new(f32::ElectricPotential::new::<volt>(-1000.0)).into(),
PubSubChannel::new(), PubSubChannel::new().into(),
), ),
ai2: RawStatePubInput::new( ai2: StatefulPublisher::new(
Cell::new(f32::ElectricPotential::new::<volt>(-1000.0)), Cell::new(f32::ElectricPotential::new::<volt>(-1000.0)).into(),
PubSubChannel::new(), PubSubChannel::new().into(),
), ),
ai3: RawStatePubInput::new( ai3: StatefulPublisher::new(
Cell::new(f32::ElectricPotential::new::<volt>(-1000.0)), Cell::new(f32::ElectricPotential::new::<volt>(-1000.0)).into(),
PubSubChannel::new(), PubSubChannel::new().into(),
), ),
}); });

View File

@ -1,105 +1,68 @@
use crate::cell::CellView; use crate::cell::CellView;
use crate::transducer::Publisher; use crate::transducer::{Publish, Publisher};
use core::cell::Cell; use core::cell::Cell;
#[cfg(feature = "embassy-sync")] #[cfg(feature = "embassy-sync")]
use embassy_sync::blocking_mutex::raw::RawMutex; use embassy_sync::blocking_mutex::raw::RawMutex;
#[cfg(feature = "embassy-sync")] #[cfg(feature = "embassy-sync")]
use embassy_sync::pubsub::PubSubChannel; use embassy_sync::pubsub::{Error, PubSubChannel, Subscriber};
use embassy_sync::pubsub::{Error, PubSubBehavior, Subscriber};
pub use physical::transducer::input::*; pub use physical::transducer::input::*;
use physical::transducer::Stateful; use physical::transducer::{State, Stateful};
#[cfg(feature = "embassy-sync")] #[cfg(feature = "embassy-sync")]
pub struct RawPublishInput<T: Copy, MutexT: RawMutex, const CAPACITY: usize, const NUM_SUBS: usize> pub struct StatefulPublisher<
{
pub channel: PubSubChannel<MutexT, T, CAPACITY, NUM_SUBS, 0>,
}
impl<T: Copy, MutexT: RawMutex, const CAPACITY: usize, const NUM_SUBS: usize>
RawPublishInput<T, MutexT, CAPACITY, NUM_SUBS>
{
#[inline(always)]
pub fn new(channel: PubSubChannel<MutexT, T, CAPACITY, NUM_SUBS, 0>) -> Self {
Self { channel }
}
#[inline(always)]
pub fn update(&self, value: T) {
self.channel.publish_immediate(value);
}
}
impl<T: Copy, MutexT: RawMutex, const CAPACITY: usize, const NUM_SUBS: usize>
Publisher<CAPACITY, NUM_SUBS> for RawPublishInput<T, MutexT, CAPACITY, NUM_SUBS>
{
type Value = T;
type Mutex = MutexT;
#[inline(always)]
fn subscribe(
&self,
) -> Result<Subscriber<Self::Mutex, Self::Value, CAPACITY, NUM_SUBS, 0>, Error> {
self.channel.subscriber()
}
}
#[cfg(feature = "embassy-sync")]
pub struct RawStatePubInput<
T: Copy, T: Copy,
MutexT: RawMutex, MutexT: RawMutex,
const CAPACITY: usize, const CAPACITY: usize,
const NUM_SUBS: usize, const NUM_SUBS: usize,
> { > {
pub state_cell: Cell<T>, pub state: State<T>,
pub channel: PubSubChannel<MutexT, T, CAPACITY, NUM_SUBS, 0>, pub publisher: Publisher<T, MutexT, CAPACITY, NUM_SUBS>,
} }
impl<T: Copy, MutexT: RawMutex, const CAPACITY: usize, const NUM_SUBS: usize> impl<T: Copy, MutexT: RawMutex, const CAPACITY: usize, const NUM_SUBS: usize>
RawStatePubInput<T, MutexT, CAPACITY, NUM_SUBS> StatefulPublisher<T, MutexT, CAPACITY, NUM_SUBS>
{ {
#[inline(always)] #[inline(always)]
pub fn new( pub fn new(
state_cell: Cell<T>, state: State<T>,
channel: PubSubChannel<MutexT, T, CAPACITY, NUM_SUBS, 0>, publisher: Publisher<T, MutexT, CAPACITY, NUM_SUBS>,
) -> Self { ) -> Self {
Self { Self { state, publisher }
state_cell,
channel,
}
} }
#[inline] #[inline(always)]
pub fn update(&self, value: T) { pub fn update(&self, value: T) {
self.state_cell.set(value); self.state.update(value);
self.channel.publish_immediate(value); self.publisher.update(value);
} }
} }
impl<T: Copy, MutexT: RawMutex, const CAPACITY: usize, const NUM_SUBS: usize> Stateful impl<T: Copy, MutexT: RawMutex, const CAPACITY: usize, const NUM_SUBS: usize> Stateful
for RawStatePubInput<T, MutexT, CAPACITY, NUM_SUBS> for StatefulPublisher<T, MutexT, CAPACITY, NUM_SUBS>
{ {
type Value = T; type Value = T;
#[inline(always)] #[inline(always)]
fn state_cell(&self) -> CellView<Self::Value> { fn state_cell(&self) -> CellView<Self::Value> {
(&self.state_cell).into() self.state.state_cell()
} }
#[inline(always)] #[inline(always)]
fn state(&self) -> Self::Value { fn state(&self) -> Self::Value {
self.state_cell.get() self.state.state()
} }
} }
impl<T: Copy, MutexT: RawMutex, const CAPACITY: usize, const NUM_SUBS: usize> impl<T: Copy, MutexT: RawMutex, const CAPACITY: usize, const NUM_SUBS: usize>
Publisher<CAPACITY, NUM_SUBS> for RawStatePubInput<T, MutexT, CAPACITY, NUM_SUBS> Publish<CAPACITY, NUM_SUBS> for StatefulPublisher<T, MutexT, CAPACITY, NUM_SUBS>
{ {
type Value = T; type Value = T;
type Mutex = MutexT; type Mutex = MutexT;
#[inline(always)]
fn subscribe( fn subscribe(
&self, &self,
) -> Result<Subscriber<Self::Mutex, Self::Value, CAPACITY, NUM_SUBS, 0>, Error> { ) -> Result<Subscriber<Self::Mutex, Self::Value, CAPACITY, NUM_SUBS, 0>, Error> {
self.channel.subscriber() self.publisher.subscribe()
} }
} }

View File

@ -8,10 +8,10 @@ use embassy_sync::blocking_mutex::raw::RawMutex;
#[cfg(feature = "embassy-sync")] #[cfg(feature = "embassy-sync")]
use embassy_sync::pubsub; use embassy_sync::pubsub;
#[cfg(feature = "embassy-sync")] #[cfg(feature = "embassy-sync")]
use embassy_sync::pubsub::Subscriber; use embassy_sync::pubsub::{PubSubBehavior, PubSubChannel, Subscriber};
#[cfg(feature = "embassy-sync")] #[cfg(feature = "embassy-sync")]
pub trait Publisher<const CAPACITY: usize, const NUM_SUBS: usize> { pub trait Publish<const CAPACITY: usize, const NUM_SUBS: usize> {
type Value: Copy; type Value: Copy;
type Mutex: RawMutex; type Mutex: RawMutex;
@ -19,3 +19,46 @@ pub trait Publisher<const CAPACITY: usize, const NUM_SUBS: usize> {
&self, &self,
) -> Result<Subscriber<Self::Mutex, Self::Value, CAPACITY, NUM_SUBS, 0>, pubsub::Error>; ) -> Result<Subscriber<Self::Mutex, Self::Value, CAPACITY, NUM_SUBS, 0>, pubsub::Error>;
} }
#[cfg(feature = "embassy-sync")]
pub struct Publisher<T: Copy, MutexT: RawMutex, const CAPACITY: usize, const NUM_SUBS: usize> {
channel: PubSubChannel<MutexT, T, CAPACITY, NUM_SUBS, 0>,
}
impl<T: Copy, MutexT: RawMutex, const CAPACITY: usize, const NUM_SUBS: usize>
Publisher<T, MutexT, CAPACITY, NUM_SUBS>
{
#[inline(always)]
pub fn new(channel: PubSubChannel<MutexT, T, CAPACITY, NUM_SUBS, 0>) -> Self {
Self { channel }
}
#[inline(always)]
pub fn update(&self, value: T) {
self.channel.publish_immediate(value);
}
}
impl<T: Copy, MutexT: RawMutex, const CAPACITY: usize, const NUM_SUBS: usize>
Publish<CAPACITY, NUM_SUBS> for Publisher<T, MutexT, CAPACITY, NUM_SUBS>
{
type Value = T;
type Mutex = MutexT;
#[inline(always)]
fn subscribe(
&self,
) -> Result<Subscriber<Self::Mutex, Self::Value, CAPACITY, NUM_SUBS, 0>, pubsub::Error> {
self.channel.subscriber()
}
}
impl<T: Copy, MutexT: RawMutex, const CAPACITY: usize, const NUM_SUBS: usize>
From<PubSubChannel<MutexT, T, CAPACITY, NUM_SUBS, 0>>
for Publisher<T, MutexT, CAPACITY, NUM_SUBS>
{
#[inline(always)]
fn from(channel: PubSubChannel<MutexT, T, CAPACITY, NUM_SUBS, 0>) -> Self {
Publisher::new(channel)
}
}

View File

@ -5,33 +5,3 @@ use crate::transducer::Stateful;
pub trait Poll<T: Copy> { pub trait Poll<T: Copy> {
async fn poll() -> T; async fn poll() -> T;
} }
pub struct RawStatefulInput<T: Copy> {
pub state_cell: Cell<T>,
}
impl<T: Copy> RawStatefulInput<T> {
#[inline(always)]
pub fn new(state_cell: Cell<T>) -> Self {
Self { state_cell }
}
#[inline(always)]
pub fn raw_update(&self, value: T) {
self.state_cell.set(value);
}
}
impl<T: Copy> Stateful for RawStatefulInput<T> {
type Value = T;
#[inline(always)]
fn state_cell(&self) -> CellView<Self::Value> {
(&self.state_cell).into()
}
#[inline(always)]
fn state(&self) -> Self::Value {
self.state_cell.get()
}
}

View File

@ -1,3 +1,4 @@
use core::cell::Cell;
use crate::cell::CellView; use crate::cell::CellView;
pub mod input; pub mod input;
@ -11,8 +12,42 @@ pub trait Stateful {
fn state_cell(&self) -> CellView<Self::Value>; fn state_cell(&self) -> CellView<Self::Value>;
fn state(&self) -> Self::Value;
}
pub struct State<T: Copy> {
state_cell: Cell<T>,
}
impl<T: Copy> State<T> {
#[inline(always)] #[inline(always)]
fn state(&self) -> Self::Value { pub fn new(state_cell: Cell<T>) -> Self {
self.state_cell().get() Self { state_cell }
}
#[inline(always)]
pub fn update(&self, value: T) {
self.state_cell.set(value);
}
}
impl<T: Copy> Stateful for State<T> {
type Value = T;
#[inline(always)]
fn state_cell(&self) -> CellView<Self::Value> {
(&self.state_cell).into()
}
#[inline(always)]
fn state(&self) -> Self::Value {
self.state_cell.get()
}
}
impl<T: Copy> From<Cell<T>> for State<T> {
#[inline(always)]
fn from(state_cell: Cell<T>) -> Self {
State::new(state_cell)
} }
} }

View File

@ -3,5 +3,5 @@ pub trait Output {
//TODO: return result //TODO: return result
//TODO: Make maybe async //TODO: Make maybe async
fn set(&mut self, setting: Self::Value); fn output(&mut self, setting: Self::Value);
} }