Initial node implementation #4
@ -11,7 +11,7 @@ members = [
|
|||||||
# Peripheral components
|
# Peripheral components
|
||||||
"peripheral-components/ads1256/*",
|
"peripheral-components/ads1256/*",
|
||||||
# Examples
|
# Examples
|
||||||
"examples/playground"
|
"examples/ads1256"
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
@ -40,6 +40,7 @@ version = "0.4.*"
|
|||||||
# Serialization
|
# Serialization
|
||||||
[workspace.dependencies.parity-scale-codec]
|
[workspace.dependencies.parity-scale-codec]
|
||||||
version = "3.5.*"
|
version = "3.5.*"
|
||||||
|
default-features = false
|
||||||
# Embedded-HAL
|
# Embedded-HAL
|
||||||
[workspace.dependencies.embedded-hal]
|
[workspace.dependencies.embedded-hal]
|
||||||
version = "1.0.0-alpha.10"
|
version = "1.0.0-alpha.10"
|
||||||
|
9
examples/ads1256/.cargo/config.toml
Normal file
9
examples/ads1256/.cargo/config.toml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
|
||||||
|
# replace STM32F429ZITx with your chip as listed in `probe-run --list-chips`
|
||||||
|
runner = "probe-rs-cli run --chip STM32F429ZITx"
|
||||||
|
|
||||||
|
[build]
|
||||||
|
target = "thumbv7em-none-eabi"
|
||||||
|
|
||||||
|
[env]
|
||||||
|
DEFMT_LOG = "trace"
|
42
examples/ads1256/Cargo.toml
Normal file
42
examples/ads1256/Cargo.toml
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
[package]
|
||||||
|
name = "ads1256-examples"
|
||||||
|
description = "Examples using the ads1256."
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
readme.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
|
||||||
|
[dependencies.physical-node]
|
||||||
|
path = "../../node"
|
||||||
|
features = ["embassy-sync"]
|
||||||
|
[dependencies.physical-ads1256]
|
||||||
|
path = "../../peripheral-components/ads1256/node"
|
||||||
|
features = ["standard-input"]
|
||||||
|
[dependencies.ads1256]
|
||||||
|
workspace = true
|
||||||
|
[dependencies.uom]
|
||||||
|
workspace = true
|
||||||
|
[dependencies.defmt]
|
||||||
|
workspace = true
|
||||||
|
[dependencies.defmt-rtt]
|
||||||
|
workspace = true
|
||||||
|
[dependencies.cortex-m]
|
||||||
|
workspace = true
|
||||||
|
features = ["critical-section-single-core"]
|
||||||
|
[dependencies.cortex-m-rt]
|
||||||
|
workspace = true
|
||||||
|
[dependencies.embassy-stm32]
|
||||||
|
workspace = true
|
||||||
|
features = ["stm32f429zi", "memory-x", "time", "exti", "time-driver-any"]
|
||||||
|
[dependencies.embassy-executor]
|
||||||
|
workspace = true
|
||||||
|
[dependencies.embassy-futures]
|
||||||
|
workspace = true
|
||||||
|
[dependencies.embassy-time]
|
||||||
|
workspace = true
|
||||||
|
features = ["tick-hz-16_000_000"]
|
||||||
|
[dependencies.embassy-sync]
|
||||||
|
workspace = true
|
||||||
|
[dependencies.panic-probe]
|
||||||
|
workspace = true
|
5
examples/ads1256/build.rs
Normal file
5
examples/ads1256/build.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
fn main() {
|
||||||
|
println!("cargo:rustc-link-arg-bins=--nmagic");
|
||||||
|
println!("cargo:rustc-link-arg-bins=-Tlink.x");
|
||||||
|
println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
|
||||||
|
}
|
181
examples/ads1256/src/bin/multiplex.rs
Normal file
181
examples/ads1256/src/bin/multiplex.rs
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
#![feature(type_alias_impl_trait, async_fn_in_trait)]
|
||||||
|
|
||||||
|
use core::cell::Cell;
|
||||||
|
use cortex_m::prelude::{
|
||||||
|
_embedded_hal_blocking_delay_DelayMs, _embedded_hal_blocking_delay_DelayUs,
|
||||||
|
};
|
||||||
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
use {embassy_executor as executor, embassy_stm32 as stm32};
|
||||||
|
|
||||||
|
use ads1256::{
|
||||||
|
AdControl, Ads1256, AutoCal, BitOrder, BlockingDelay, Buffer, ClockOut, Config, DState,
|
||||||
|
DataRate, DigitalIo, DigitalIoDirection, DigitalIoState, DioDirection, Gain, Multiplexer,
|
||||||
|
MuxInput, OutputPin, Sdcs, SpiBus, Status, Wait,
|
||||||
|
};
|
||||||
|
use embassy_time::{Delay, Duration, Timer};
|
||||||
|
use executor::Spawner;
|
||||||
|
use stm32::dma::NoDma;
|
||||||
|
use stm32::exti::ExtiInput;
|
||||||
|
use stm32::gpio::{Input, Level, Output, Pull, Speed};
|
||||||
|
use stm32::spi::Spi;
|
||||||
|
use stm32::time::Hertz;
|
||||||
|
use stm32::{pac, spi};
|
||||||
|
|
||||||
|
use uom::si::electric_potential::volt;
|
||||||
|
use uom::si::f32;
|
||||||
|
|
||||||
|
use defmt::{debug, error, info, trace, unwrap};
|
||||||
|
use embassy_executor::_export::StaticCell;
|
||||||
|
use embassy_stm32::peripherals::{EXTI6, PF6, PF7, SPI3};
|
||||||
|
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
|
||||||
|
use embassy_sync::pubsub::PubSubChannel;
|
||||||
|
use physical_ads1256::{standard_input, SingleEnded};
|
||||||
|
use physical_node::transducer::input::RawStatePubInput;
|
||||||
|
use physical_node::transducer::Publisher;
|
||||||
|
|
||||||
|
const AUTOCAL_CONF: Config = Config {
|
||||||
|
status: Status::setting(Buffer::Enabled, AutoCal::Enabled, BitOrder::MostSigFirst),
|
||||||
|
multiplexer: Multiplexer::setting(MuxInput::AIn0, MuxInput::Common),
|
||||||
|
ad_control: AdControl::setting(Gain::X2, Sdcs::Off, ClockOut::Off),
|
||||||
|
data_rate: DataRate::Sps2_5,
|
||||||
|
digital_io: DigitalIo::setting(DigitalIoState::default(), DigitalIoDirection::default()),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Ads1256Delay;
|
||||||
|
|
||||||
|
impl ads1256::BlockingDelay for Ads1256Delay {
|
||||||
|
#[inline]
|
||||||
|
fn t6_delay(&mut self) {
|
||||||
|
Delay.delay_us(1u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn t11_1_delay(&mut self) {}
|
||||||
|
|
||||||
|
fn t11_2_delay(&mut self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Inputs {
|
||||||
|
ai1: RawStatePubInput<f32::ElectricPotential, NoopRawMutex, 10, 1>,
|
||||||
|
ai2: RawStatePubInput<f32::ElectricPotential, NoopRawMutex, 10, 1>,
|
||||||
|
ai3: RawStatePubInput<f32::ElectricPotential, NoopRawMutex, 10, 1>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inputs
|
||||||
|
static ANALOG_INPUTS: StaticCell<Inputs> = StaticCell::new();
|
||||||
|
static ADS_1256: StaticCell<Ads1256<Ads1256Delay, Output<PF7>, ExtiInput<PF6>>> = StaticCell::new();
|
||||||
|
static SPI: StaticCell<Spi<SPI3, NoDma, NoDma>> = StaticCell::new();
|
||||||
|
|
||||||
|
#[embassy_executor::main]
|
||||||
|
async fn main(spawner: Spawner) {
|
||||||
|
unsafe {
|
||||||
|
pac::FLASH.acr().modify(|v| {
|
||||||
|
v.set_prften(true);
|
||||||
|
v.set_icen(true);
|
||||||
|
v.set_dcen(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
|
let mut spi_conf = spi::Config::default();
|
||||||
|
spi_conf.mode = spi::MODE_1;
|
||||||
|
spi_conf.bit_order = spi::BitOrder::MsbFirst;
|
||||||
|
|
||||||
|
let ads1256_data_ready = ExtiInput::new(Input::new(p.PF6, Pull::Up), p.EXTI6);
|
||||||
|
let select_ads1256 = Output::new(p.PF7, Level::High, Speed::VeryHigh);
|
||||||
|
|
||||||
|
let spi = SPI.init(Spi::new(
|
||||||
|
p.SPI3,
|
||||||
|
p.PC10,
|
||||||
|
p.PC12,
|
||||||
|
p.PC11,
|
||||||
|
NoDma,
|
||||||
|
NoDma,
|
||||||
|
Hertz(ads1256::defaults::SPI_CLK_HZ),
|
||||||
|
spi_conf,
|
||||||
|
));
|
||||||
|
|
||||||
|
let ads_1256 = ADS_1256.init(Ads1256::new(Ads1256Delay, select_ads1256, ads1256_data_ready));
|
||||||
|
|
||||||
|
let inputs = &*ANALOG_INPUTS.init(Inputs {
|
||||||
|
ai1: RawStatePubInput::new(
|
||||||
|
Cell::new(f32::ElectricPotential::new::<volt>(-1000.0)),
|
||||||
|
PubSubChannel::new(),
|
||||||
|
),
|
||||||
|
ai2: RawStatePubInput::new(
|
||||||
|
Cell::new(f32::ElectricPotential::new::<volt>(-1000.0)),
|
||||||
|
PubSubChannel::new(),
|
||||||
|
),
|
||||||
|
ai3: RawStatePubInput::new(
|
||||||
|
Cell::new(f32::ElectricPotential::new::<volt>(-1000.0)),
|
||||||
|
PubSubChannel::new(),
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
spawner.spawn(log_task(inputs)).unwrap();
|
||||||
|
spawner
|
||||||
|
.spawn(drive_inputs_task(ads_1256, spi, inputs))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[embassy_executor::task]
|
||||||
|
async fn drive_inputs_task(
|
||||||
|
ads_1256: &'static mut Ads1256<Ads1256Delay, Output<'static, PF7>, ExtiInput<'static, PF6>>,
|
||||||
|
spi: &'static mut Spi<'static, SPI3, NoDma, NoDma>,
|
||||||
|
inputs: &'static Inputs,
|
||||||
|
) {
|
||||||
|
let Inputs { ai1, ai2, ai3 } = inputs;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let mut accumulator = f32::ElectricPotential::new::<volt>(0.0);
|
||||||
|
|
||||||
|
let voltage = ads_1256
|
||||||
|
.autocal_convert(spi, SingleEnded::AIn0.into(), None, None, None, false)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.to_voltage(AUTOCAL_CONF.ad_control.gain());
|
||||||
|
ai1.update(voltage);
|
||||||
|
accumulator += voltage;
|
||||||
|
|
||||||
|
let voltage = ads_1256
|
||||||
|
.autocal_convert(spi, SingleEnded::AIn1.into(), None, None, None, false)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.to_voltage(AUTOCAL_CONF.ad_control.gain());
|
||||||
|
ai2.update(voltage);
|
||||||
|
accumulator += voltage;
|
||||||
|
|
||||||
|
let voltage = ads_1256
|
||||||
|
.autocal_convert(spi, SingleEnded::AIn2.into(), None, None, None, false)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.to_voltage(AUTOCAL_CONF.ad_control.gain());
|
||||||
|
ai3.update(voltage);
|
||||||
|
accumulator += voltage;
|
||||||
|
|
||||||
|
let accum_volts = accumulator.get::<volt>();
|
||||||
|
info!("Immediate loop iteration result, combined volts: {}", accum_volts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[embassy_executor::task]
|
||||||
|
async fn log_task(inputs: &'static Inputs) {
|
||||||
|
let Inputs { ai1, ai2, ai3 } = inputs;
|
||||||
|
let mut ai1_sub = ai1.subscribe().unwrap();
|
||||||
|
let mut ai2_sub = ai2.subscribe().unwrap();
|
||||||
|
let mut ai3_sub = ai3.subscribe().unwrap();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let msg = ai1_sub.next_message_pure().await.get::<volt>();
|
||||||
|
info!("Log task ai1: {}", msg);
|
||||||
|
|
||||||
|
let msg = ai2_sub.next_message_pure().await.get::<volt>();
|
||||||
|
info!("Log task ai2: {}", msg);
|
||||||
|
|
||||||
|
let msg = ai3_sub.next_message_pure().await.get::<volt>();
|
||||||
|
info!("Log task ai3: {}", msg);
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "playground"
|
|
||||||
description = """The playground example is a special example meant for unstructured experimentation which can potentially
|
|
||||||
be turned into an actual example at some point or deleted. It should always be reset to unchanged hello world before
|
|
||||||
the working branch where the experimentation is happening is merged."""
|
|
||||||
version.workspace = true
|
|
||||||
edition.workspace = true
|
|
||||||
repository.workspace = true
|
|
||||||
readme.workspace = true
|
|
||||||
license.workspace = true
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
physical = { path = "../.." }
|
|
@ -1,7 +0,0 @@
|
|||||||
//! The playground example is a special example meant for unstructured experimentation which can potentially be turned
|
|
||||||
//! into an actual example at some point or deleted. It should always be reset to unchanged hello world before the working
|
|
||||||
//! branch where the experimentation is happening is merged.
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
println!("Hello, world!");
|
|
||||||
}
|
|
@ -1,7 +1,7 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![feature(async_fn_in_trait)]
|
#![feature(async_fn_in_trait)]
|
||||||
|
|
||||||
mod transducer;
|
pub mod transducer;
|
||||||
|
|
||||||
pub mod cell {
|
pub mod cell {
|
||||||
pub use physical::cell::*;
|
pub use physical::cell::*;
|
||||||
|
@ -1,30 +1,105 @@
|
|||||||
use crate::cell::CellView;
|
use crate::cell::CellView;
|
||||||
|
use crate::transducer::Publisher;
|
||||||
|
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::PubSubChannel;
|
||||||
|
use embassy_sync::pubsub::{Error, PubSubBehavior, Subscriber};
|
||||||
pub use physical::transducer::input::*;
|
pub use physical::transducer::input::*;
|
||||||
|
use physical::transducer::Stateful;
|
||||||
|
|
||||||
#[cfg(feature = "embassy-sync")]
|
#[cfg(feature = "embassy-sync")]
|
||||||
pub struct PublishInput<
|
pub struct RawPublishInput<T: Copy, MutexT: RawMutex, const CAPACITY: usize, const NUM_SUBS: usize>
|
||||||
|
{
|
||||||
|
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,
|
||||||
const NUM_PUBS: usize,
|
|
||||||
> {
|
> {
|
||||||
channel: PubSubChannel<MutexT, T, CAPACITY, NUM_SUBS, NUM_PUBS>,
|
pub state_cell: Cell<T>,
|
||||||
|
pub channel: PubSubChannel<MutexT, T, CAPACITY, NUM_SUBS, 0>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "embassy-sync")]
|
impl<T: Copy, MutexT: RawMutex, const CAPACITY: usize, const NUM_SUBS: usize>
|
||||||
pub struct StatefulPublishInput<
|
RawStatePubInput<T, MutexT, CAPACITY, NUM_SUBS>
|
||||||
'a,
|
{
|
||||||
T: Copy,
|
#[inline(always)]
|
||||||
MutexT: RawMutex,
|
pub fn new(
|
||||||
const CAPACITY: usize,
|
state_cell: Cell<T>,
|
||||||
const NUM_SUBS: usize,
|
channel: PubSubChannel<MutexT, T, CAPACITY, NUM_SUBS, 0>,
|
||||||
const NUM_PUBS: usize,
|
) -> Self {
|
||||||
> {
|
Self {
|
||||||
pub state_cell: CellView<'a, T>,
|
state_cell,
|
||||||
channel: PubSubChannel<MutexT, T, CAPACITY, NUM_SUBS, NUM_PUBS>,
|
channel,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn update(&self, value: T) {
|
||||||
|
self.state_cell.set(value);
|
||||||
|
self.channel.publish_immediate(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Copy, MutexT: RawMutex, const CAPACITY: usize, const NUM_SUBS: usize> Stateful
|
||||||
|
for RawStatePubInput<T, MutexT, CAPACITY, NUM_SUBS>
|
||||||
|
{
|
||||||
|
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, MutexT: RawMutex, const CAPACITY: usize, const NUM_SUBS: usize>
|
||||||
|
Publisher<CAPACITY, NUM_SUBS> for RawStatePubInput<T, MutexT, CAPACITY, NUM_SUBS>
|
||||||
|
{
|
||||||
|
type Value = T;
|
||||||
|
type Mutex = MutexT;
|
||||||
|
|
||||||
|
fn subscribe(
|
||||||
|
&self,
|
||||||
|
) -> Result<Subscriber<Self::Mutex, Self::Value, CAPACITY, NUM_SUBS, 0>, Error> {
|
||||||
|
self.channel.subscriber()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
mod input;
|
pub mod input;
|
||||||
mod output;
|
pub mod output;
|
||||||
|
|
||||||
pub use physical::transducer::*;
|
pub use physical::transducer::*;
|
||||||
|
|
||||||
@ -11,17 +11,11 @@ use embassy_sync::pubsub;
|
|||||||
use embassy_sync::pubsub::Subscriber;
|
use embassy_sync::pubsub::Subscriber;
|
||||||
|
|
||||||
#[cfg(feature = "embassy-sync")]
|
#[cfg(feature = "embassy-sync")]
|
||||||
pub trait Publisher {
|
pub trait Publisher<const CAPACITY: usize, const NUM_SUBS: usize> {
|
||||||
type Value: Copy;
|
type Value: Copy;
|
||||||
type Mutex: RawMutex;
|
type Mutex: RawMutex;
|
||||||
const CAPACITY: usize;
|
|
||||||
const NUM_SUBS: usize;
|
|
||||||
const NUM_PUBS: usize;
|
|
||||||
|
|
||||||
fn subscribe(
|
fn subscribe(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<
|
) -> Result<Subscriber<Self::Mutex, Self::Value, CAPACITY, NUM_SUBS, 0>, pubsub::Error>;
|
||||||
Subscriber<Self::Mutex, Self::Value, Self::CAPACITY, Self::NUM_SUBS, Self::NUM_PUBS>,
|
|
||||||
pubsub::Error,
|
|
||||||
>;
|
|
||||||
}
|
}
|
||||||
|
@ -8,12 +8,15 @@ readme.workspace = true
|
|||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
standard-multiplexer = []
|
config = ["physical-ads1256-types/config"]
|
||||||
|
standard-input = ["physical-ads1256-types/standard-input"]
|
||||||
|
standard-multiplexer = ["standard-input"]
|
||||||
|
|
||||||
[dependencies.physical-node]
|
[dependencies.physical-node]
|
||||||
path = "../../../node"
|
path = "../../../node"
|
||||||
[dependencies.physical-ads1256-types]
|
[dependencies.physical-ads1256-types]
|
||||||
path = "../types"
|
path = "../types"
|
||||||
|
features = ["defmt"]
|
||||||
[dependencies.ads1256]
|
[dependencies.ads1256]
|
||||||
workspace = true
|
workspace = true
|
||||||
[dependencies.embedded-hal]
|
[dependencies.embedded-hal]
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
|
|
||||||
struct AnalogInput {}
|
|
||||||
|
|
||||||
// AnalogInputS
|
|
||||||
// AnalogInputI
|
|
||||||
// AnalogInputC
|
|
||||||
// AnalogInputSI
|
|
||||||
// AnalogInputSC
|
|
||||||
// AnalogInputIC
|
|
||||||
// AnalogInputSIC
|
|
@ -1,4 +1,6 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[cfg(feature = "standard-multiplexer")]
|
#[cfg(feature = "standard-multiplexer")]
|
||||||
mod analog_input;
|
mod standard_multiplexer;
|
||||||
|
|
||||||
|
pub use physical_ads1256_types::*;
|
@ -8,7 +8,8 @@ readme.workspace = true
|
|||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
standard-multiplexer = []
|
config = []
|
||||||
|
standard-input = []
|
||||||
|
|
||||||
[dependencies.ads1256-types]
|
[dependencies.ads1256-types]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
2
peripheral-components/ads1256/types/src/config.rs
Normal file
2
peripheral-components/ads1256/types/src/config.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
use ads1256_types::{Buffer, Config, DataRate, Gain};
|
||||||
|
|
@ -1 +1,11 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
|
#[cfg(feature = "standard-input")]
|
||||||
|
pub mod standard_input;
|
||||||
|
#[cfg(feature = "config")]
|
||||||
|
mod config;
|
||||||
|
|
||||||
|
#[cfg(feature = "config")]
|
||||||
|
pub use config::*;
|
||||||
|
#[cfg(feature = "standard-input")]
|
||||||
|
pub use standard_input::*;
|
||||||
|
39
peripheral-components/ads1256/types/src/standard_input.rs
Normal file
39
peripheral-components/ads1256/types/src/standard_input.rs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
use ads1256_types::{Buffer, Config, DataRate, Gain, Multiplexer, MuxInput};
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum Differential {
|
||||||
|
AIn0 = Multiplexer::setting(MuxInput::AIn0, MuxInput::AIn1).0,
|
||||||
|
AIn1 = Multiplexer::setting(MuxInput::AIn2, MuxInput::AIn3).0,
|
||||||
|
AIn2 = Multiplexer::setting(MuxInput::AIn4, MuxInput::AIn5).0,
|
||||||
|
AIn3 = Multiplexer::setting(MuxInput::AIn6, MuxInput::AIn7).0,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<Multiplexer> for Differential {
|
||||||
|
#[inline(always)]
|
||||||
|
fn into(self) -> Multiplexer {
|
||||||
|
Multiplexer(self as u8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum SingleEnded {
|
||||||
|
AIn0 = Multiplexer::setting(MuxInput::AIn0, MuxInput::Common).0,
|
||||||
|
AIn1 = Multiplexer::setting(MuxInput::AIn1, MuxInput::Common).0,
|
||||||
|
AIn2 = Multiplexer::setting(MuxInput::AIn2, MuxInput::Common).0,
|
||||||
|
AIn3 = Multiplexer::setting(MuxInput::AIn3, MuxInput::Common).0,
|
||||||
|
AIn4 = Multiplexer::setting(MuxInput::AIn4, MuxInput::Common).0,
|
||||||
|
AIn5 = Multiplexer::setting(MuxInput::AIn5, MuxInput::Common).0,
|
||||||
|
AIn6 = Multiplexer::setting(MuxInput::AIn6, MuxInput::Common).0,
|
||||||
|
AIn7 = Multiplexer::setting(MuxInput::AIn7, MuxInput::Common).0,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<Multiplexer> for SingleEnded {
|
||||||
|
#[inline(always)]
|
||||||
|
fn into(self) -> Multiplexer {
|
||||||
|
Multiplexer(self as u8)
|
||||||
|
}
|
||||||
|
}
|
@ -6,13 +6,14 @@ use core::cell::Cell;
|
|||||||
pub struct CellView<'a, T: Copy>(&'a Cell<T>);
|
pub struct CellView<'a, T: Copy>(&'a Cell<T>);
|
||||||
|
|
||||||
impl<T: Copy> CellView<'_, T> {
|
impl<T: Copy> CellView<'_, T> {
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn get(self) -> T {
|
pub fn get(self) -> T {
|
||||||
self.0.get()
|
self.0.get()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Copy> From<&'a Cell<T>> for CellView<'a, T> {
|
impl<'a, T: Copy> From<&'a Cell<T>> for CellView<'a, T> {
|
||||||
|
#[inline(always)]
|
||||||
fn from(value: &'a Cell<T>) -> Self {
|
fn from(value: &'a Cell<T>) -> Self {
|
||||||
CellView(value)
|
CellView(value)
|
||||||
}
|
}
|
||||||
|
0
src/transducer/conversion/mod.rs
Normal file
0
src/transducer/conversion/mod.rs
Normal file
@ -1,3 +1,4 @@
|
|||||||
|
use core::cell::Cell;
|
||||||
use crate::cell::CellView;
|
use crate::cell::CellView;
|
||||||
use crate::transducer::Stateful;
|
use crate::transducer::Stateful;
|
||||||
|
|
||||||
@ -5,19 +6,31 @@ pub trait Poll<T: Copy> {
|
|||||||
async fn poll() -> T;
|
async fn poll() -> T;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct StatefulInput<'a, T: Copy> {
|
pub struct RawStatefulInput<T: Copy> {
|
||||||
pub state_cell: CellView<'a, T>,
|
pub state_cell: Cell<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Copy> Stateful for StatefulInput<'a, 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;
|
type Value = T;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn state_cell(&self) -> CellView<'a, Self::Value> {
|
fn state_cell(&self) -> CellView<Self::Value> {
|
||||||
self.state_cell
|
(&self.state_cell).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
fn state(&self) -> Self::Value {
|
fn state(&self) -> Self::Value {
|
||||||
self.state_cell.get()
|
self.state_cell.get()
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ use crate::cell::CellView;
|
|||||||
|
|
||||||
pub mod input;
|
pub mod input;
|
||||||
pub mod output;
|
pub mod output;
|
||||||
|
mod conversion;
|
||||||
|
|
||||||
// Initialisation will always be async and won't complete until a state is available for all
|
// Initialisation will always be async and won't complete until a state is available for all
|
||||||
// stateful transducers.
|
// stateful transducers.
|
||||||
@ -10,5 +11,8 @@ pub trait Stateful {
|
|||||||
|
|
||||||
fn state_cell(&self) -> CellView<Self::Value>;
|
fn state_cell(&self) -> CellView<Self::Value>;
|
||||||
|
|
||||||
fn state(&self) -> Self::Value;
|
#[inline(always)]
|
||||||
|
fn state(&self) -> Self::Value {
|
||||||
|
self.state_cell().get()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user