diff --git a/Cargo.toml b/Cargo.toml index b899963..fecb0f3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,18 +6,10 @@ members = [ # Device types "node", "commander", - # Peripherals - - # Peripheral components - "peripheral-components/ads1256/*", - # Macros - "macros/node-poll-variants", - # Examples - "examples/ads1256" ] [workspace.package] -version = "0.2.1" +version = "0.3.0" edition = "2021" repository = "https://git.bfpower.io/BFPOWER/physical" readme = "README.md" @@ -115,6 +107,7 @@ license.workspace = true thermocouple_k = [] lm35 = [] pid = [] +stm32 = [] [dependencies] uom = { workspace = true } diff --git a/commander/src/lib.rs b/commander/src/lib.rs index 7d12d9a..e69de29 100644 --- a/commander/src/lib.rs +++ b/commander/src/lib.rs @@ -1,14 +0,0 @@ -pub fn add(left: usize, right: usize) -> usize { - left + right -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } -} diff --git a/examples/ads1256/.cargo/config.toml b/examples/ads1256/.cargo/config.toml deleted file mode 100644 index 608c37e..0000000 --- a/examples/ads1256/.cargo/config.toml +++ /dev/null @@ -1,9 +0,0 @@ -[target.'cfg(all(target_arch = "arm", target_os = "none"))'] -# replace STM32F429ZITx with your chip as listed in `probe-rs chip list` -runner = "probe-rs run --chip STM32F411CEUx" - -[build] -target = "thumbv7em-none-eabi" - -[env] -DEFMT_LOG = "trace" \ No newline at end of file diff --git a/examples/ads1256/Cargo.toml b/examples/ads1256/Cargo.toml deleted file mode 100644 index 6bd1c22..0000000 --- a/examples/ads1256/Cargo.toml +++ /dev/null @@ -1,47 +0,0 @@ -[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] -path = "../.." -features = ["thermocouple_k", "lm35"] -[dependencies.physical-node] -path = "../../node" -features = ["embassy-sync"] -[dependencies.physical-ads1256] -path = "../../peripheral-components/ads1256/node" -features = ["poll"] -[dependencies.static_cell] -workspace = true -[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 = ["stm32f411ce", "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 diff --git a/examples/ads1256/build.rs b/examples/ads1256/build.rs deleted file mode 100644 index 56127fd..0000000 --- a/examples/ads1256/build.rs +++ /dev/null @@ -1,5 +0,0 @@ -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"); -} \ No newline at end of file diff --git a/examples/ads1256/src/bin/multiplex.rs b/examples/ads1256/src/bin/multiplex.rs deleted file mode 100644 index 601fcb3..0000000 --- a/examples/ads1256/src/bin/multiplex.rs +++ /dev/null @@ -1,177 +0,0 @@ -#![no_std] -#![no_main] - -use core::cell::Cell; -use cortex_m::prelude::_embedded_hal_blocking_delay_DelayUs; -use {defmt_rtt as _, panic_probe as _}; - -use {embassy_executor as executor, embassy_stm32 as stm32}; - -use ads1256::standard::input::SingleEnded; -use ads1256::{ - AdControl, Ads1256, AutoCal, BitOrder, Buffer, ClockOut, Config, DataRate, DigitalIo, - DigitalIoDirection, DigitalIoState, Gain, Multiplexer, MuxInput, Sdcs, Status, -}; -use embassy_time::Delay; -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 static_cell::StaticCell; -use embassy_stm32::peripherals::{PA1, PA3, SPI1}; -use embassy_sync::blocking_mutex::raw::NoopRawMutex; -use embassy_sync::pubsub::PubSubChannel; -use physical_node::transducer::{Publish, StatefulPublisher}; - -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 { - ai0: StatefulPublisher, - ai1: StatefulPublisher, - ai2: StatefulPublisher, -} - -// Inputs -static ANALOG_INPUTS: StaticCell = StaticCell::new(); -static ADS_1256: StaticCell, ExtiInput>> = StaticCell::new(); -static SPI: StaticCell> = 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; - spi_conf.frequency = Hertz(ads1256::defaults::SPI_CLK_HZ); - - let ads1256_data_ready = ExtiInput::new(Input::new(p.PA3, Pull::Up), p.EXTI3); - let select_ads1256 = Output::new(p.PA1, Level::High, Speed::VeryHigh); - - let spi = SPI.init(Spi::new( - p.SPI1, - p.PA5, - p.PA7, - p.PA6, - NoDma, - NoDma, - spi_conf, - )); - - let ads_1256 = ADS_1256.init(Ads1256::new(Ads1256Delay, select_ads1256, ads1256_data_ready)); - ads_1256.write_config(spi, AUTOCAL_CONF).unwrap(); - - let inputs = &*ANALOG_INPUTS.init(Inputs { - ai0: StatefulPublisher::new( - Cell::new(f32::ElectricPotential::new::(f32::NAN)).into(), - PubSubChannel::new().into(), - ), - ai1: StatefulPublisher::new( - Cell::new(f32::ElectricPotential::new::(f32::NAN)).into(), - PubSubChannel::new().into(), - ), - ai2: StatefulPublisher::new( - Cell::new(f32::ElectricPotential::new::(f32::NAN)).into(), - PubSubChannel::new().into(), - ), - }); - - 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, ExtiInput<'static, PA3>>, - spi: &'static mut Spi<'static, SPI1, NoDma, NoDma>, - inputs: &'static Inputs, -) { - let Inputs { ai0, ai1, ai2 } = inputs; - - loop { - let mut accumulator = f32::ElectricPotential::new::(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()); - ai0.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()); - ai1.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()); - ai2.update(voltage); - accumulator += voltage; - - let accum_volts = accumulator.get::(); - info!("Immediate loop iteration result, combined volts: {}", accum_volts); - } -} - -#[embassy_executor::task] -async fn log_task(inputs: &'static Inputs) { - let Inputs { ai0, ai1, ai2 } = inputs; - let mut ai0_sub = ai0.subscribe().unwrap(); - let mut ai1_sub = ai1.subscribe().unwrap(); - let mut ai2_sub = ai2.subscribe().unwrap(); - - loop { - let msg = ai0_sub.next_message_pure().await.get::(); - info!("Log task ai0: {}", msg); - - let msg = ai1_sub.next_message_pure().await.get::(); - info!("Log task ai1: {}", msg); - - let msg = ai2_sub.next_message_pure().await.get::(); - info!("Log task ai2: {}", msg); - } -} diff --git a/examples/ads1256/src/bin/poll.rs b/examples/ads1256/src/bin/poll.rs deleted file mode 100644 index a1dca6b..0000000 --- a/examples/ads1256/src/bin/poll.rs +++ /dev/null @@ -1,195 +0,0 @@ -#![no_std] -#![no_main] - -use core::cell::Cell; - -use cortex_m::prelude::_embedded_hal_blocking_delay_DelayUs; -use {defmt_rtt as _, panic_probe as _}; - -use {embassy_executor as executor, embassy_stm32 as stm32}; - -use ads1256::standard::input::SingleEnded; -use ads1256::{ - AdControl, Ads1256, AutoCal, BitOrder, Buffer, ClockOut, Config, DState, DataRate, DigitalIo, - DigitalIoDirection, DigitalIoState, Gain, Multiplexer, MuxInput, Sdcs, Status, -}; -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::info; -use static_cell::StaticCell; -use embassy_stm32::peripherals::{PA1, PA3, SPI1}; -use embassy_sync::blocking_mutex::raw::NoopRawMutex; -use embassy_sync::mutex::Mutex; -use embassy_sync::pubsub::PubSubChannel; -use physical_ads1256::standard::multiplexer::poll::{ - AutocalPoll, AutocalPollStatePub, ModInputOnly, -}; -use physical_node::transducer::input::Poll; -use physical_node::transducer::{Publish, Publisher, StatefulPublisher}; - -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) {} -} - -type ExampleInput = AutocalPollStatePub< - 'static, - NoopRawMutex, - NoopRawMutex, - ModInputOnly, - Ads1256Delay, - Output<'static, PA1>, - ExtiInput<'static, PA3>, - Spi<'static, SPI1, NoDma, NoDma>, - 10, - 1, ->; - -struct Inputs { - ai1: ExampleInput, - ai2: ExampleInput, - ai3: ExampleInput, -} - -// Inputs -static ANALOG_INPUTS: StaticCell = StaticCell::new(); -static ADS_1256: StaticCell< - Mutex, ExtiInput>>, -> = StaticCell::new(); -static SPI: StaticCell>> = 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; - spi_conf.frequency = Hertz(ads1256::defaults::SPI_CLK_HZ); - - let ads1256_data_ready = ExtiInput::new(Input::new(p.PA3, Pull::Up), p.EXTI3); - let select_ads1256 = Output::new(p.PA1, Level::High, Speed::VeryHigh); - - let spi = SPI.init(Mutex::new( - Spi::new( - p.SPI1, - p.PA5, - p.PA7, - p.PA6, - NoDma, - NoDma, - spi_conf, - ) - )); - - let ads_1256 = - ADS_1256.init(Mutex::new(Ads1256::new(Ads1256Delay, select_ads1256, ads1256_data_ready))); - - ads_1256 - .get_mut() - .write_config(spi.get_mut(), AUTOCAL_CONF) - .unwrap(); - - let inputs = &*ANALOG_INPUTS.init(Inputs { - ai1: AutocalPollStatePub { - poll: AutocalPoll::new( - ModInputOnly { - gain: Gain::X2, - multiplexer: SingleEnded::AIn1.into(), - }, - ads_1256, - spi, - ), - publisher: PubSubChannel::new().into(), - state: Cell::new(f32::ElectricPotential::new::(f32::NAN)).into(), - }, - ai2: AutocalPollStatePub { - poll: AutocalPoll::new( - ModInputOnly { - gain: Gain::X2, - multiplexer: SingleEnded::AIn2.into(), - }, - ads_1256, - spi, - ), - publisher: PubSubChannel::new().into(), - state: Cell::new(f32::ElectricPotential::new::(f32::NAN)).into(), - }, - ai3: AutocalPollStatePub { - poll: AutocalPoll::new( - ModInputOnly { - gain: Gain::X2, - multiplexer: SingleEnded::AIn3.into(), - }, - ads_1256, - spi, - ), - publisher: PubSubChannel::new().into(), - state: Cell::new(f32::ElectricPotential::new::(f32::NAN)).into(), - }, - }); - spawner.spawn(log_task(&inputs.ai1, 1)).unwrap(); - spawner.spawn(log_task(&inputs.ai2, 2)).unwrap(); - spawner.spawn(log_task(&inputs.ai3, 3)).unwrap(); - spawner - .spawn(poll_task(&inputs.ai1, 1, Duration::from_secs(5))) - .unwrap(); - spawner - .spawn(poll_task(&inputs.ai2, 2, Duration::from_secs(10))) - .unwrap(); - spawner - .spawn(poll_task(&inputs.ai3, 3, Duration::from_secs(20))) - .unwrap(); -} - -#[embassy_executor::task(pool_size = 3)] -async fn poll_task(input: &'static ExampleInput, input_num: u8, every: Duration) { - loop { - Timer::after(every).await; - let result = input.poll().await.unwrap().get::(); - info!("ai{} poll result: {} volts", input_num, result); - } -} - -#[embassy_executor::task(pool_size = 3)] -async fn log_task(input: &'static ExampleInput, input_num: u8) { - let mut subscriber = input.subscribe().unwrap(); - loop { - let msg = subscriber.next_message_pure().await.get::(); - info!("Log task ai{}: {}", input_num, msg); - } -} diff --git a/examples/ads1256/src/bin/thermocouple.rs b/examples/ads1256/src/bin/thermocouple.rs deleted file mode 100644 index 42fd04b..0000000 --- a/examples/ads1256/src/bin/thermocouple.rs +++ /dev/null @@ -1,125 +0,0 @@ -#![no_std] -#![no_main] - -use cortex_m::prelude::_embedded_hal_blocking_delay_DelayUs; -// Necessary unused import. -use {defmt_rtt as _, panic_probe as _}; - -use {embassy_executor as executor, embassy_stm32 as stm32}; - -use ads1256::standard::input::{Differential, SingleEnded}; -use ads1256::{ - AdControl, Ads1256, AutoCal, BitOrder, Buffer, ClockOut, Config, DataRate, DigitalIo, - DigitalIoDirection, DigitalIoState, Gain, Multiplexer, MuxInput, Sdcs, Status, -}; -use embassy_time::Delay; -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::{millivolt, volt}; - -use defmt::info; -use physical::transducer::{lm35, thermocouple_k}; -use uom::si::thermodynamic_temperature::degree_celsius; - -const AUTOCAL_CONF: Config = Config { - status: Status::setting(Buffer::Enabled, AutoCal::Enabled, BitOrder::MostSigFirst), - multiplexer: Multiplexer::setting(MuxInput::AIn0, MuxInput::AIn1), - ad_control: AdControl::setting(Gain::X64, 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) {} -} - -#[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; - spi_conf.frequency = Hertz(ads1256::defaults::SPI_CLK_HZ); - - let ads1256_data_ready = ExtiInput::new(Input::new(p.PA3, Pull::Up), p.EXTI3); - let select_ads1256 = Output::new(p.PA1, Level::High, Speed::VeryHigh); - - let mut spi = Spi::new( - p.SPI1, - p.PA5, - p.PA7, - p.PA6, - NoDma, - NoDma, - spi_conf, - ); - - let mut ads_1256 = Ads1256::new(Ads1256Delay, select_ads1256, ads1256_data_ready); - ads_1256.write_config(&mut spi, AUTOCAL_CONF).unwrap(); - ads_1256.self_calibrate(&mut spi).await.unwrap(); - - loop { - let gain = Gain::X2; - let reference = ads_1256 - .autocal_convert( - &mut spi, - SingleEnded::AIn2.into(), - None, - Some(AUTOCAL_CONF.ad_control.with_gain(gain)), - None, - false, - ) - .await - .unwrap() - .to_voltage(gain); - let reference_volts = reference.get::(); - let reference = lm35::convert(reference).unwrap(); - let reference_celsius = reference.get::(); - info!( - "Reference junction temperature: {}°C, from voltage reading: {}V", - reference_celsius, reference_volts - ); - - let gain = Gain::X64; - let voltage = ads_1256 - .autocal_convert( - &mut spi, - Differential::AIn0.into(), - None, - Some(AUTOCAL_CONF.ad_control.with_gain(gain)), - None, - false, - ) - .await - .unwrap() - .to_voltage(AUTOCAL_CONF.ad_control.gain()); - let mv = voltage.get::(); - let temperature = thermocouple_k::convert_direct(voltage, reference).unwrap(); - let celsius = temperature.get::(); - info!("Thermocouple temperature: {}°C, from reading: {}mV", celsius, mv); - } -} diff --git a/macros/node-poll-variants/Cargo.toml b/macros/node-poll-variants/Cargo.toml deleted file mode 100644 index 46ea342..0000000 --- a/macros/node-poll-variants/Cargo.toml +++ /dev/null @@ -1,28 +0,0 @@ -[package] -name = "node-poll-variants" -description = "Macros for physical nodes." -version.workspace = true -edition.workspace = true -repository.workspace = true -readme.workspace = true -license.workspace = true - -[lib] -proc-macro = true - -[[test]] -name = "tests" -path = "tests/test_build.rs" - -[dependencies.syn] -workspace = true -[dependencies.quote] -workspace = true - -[dev-dependencies.trybuild] -workspace = true -[dev-dependencies.physical-node] -path = "../../node" -features = ["embassy-sync"] -[dev-dependencies.embassy-sync] -workspace = true \ No newline at end of file diff --git a/macros/node-poll-variants/src/lib.rs b/macros/node-poll-variants/src/lib.rs deleted file mode 100644 index 242c1cf..0000000 --- a/macros/node-poll-variants/src/lib.rs +++ /dev/null @@ -1,294 +0,0 @@ -use proc_macro::TokenStream; -use quote::quote; -use std::ops::Deref; -use quote::__private::parse_spanned; -use syn::__private::{str, Span}; -use syn::punctuated::Punctuated; -use syn::token::{Colon, Comma, PathSep, Plus}; -use syn::{parse_macro_input, parse_quote, parse_quote_spanned, parse_str, Data, DeriveInput, Expr, GenericParam, Generics, Ident, Lit, LitStr, Meta, Path, PathSegment, Token, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound, Type}; - -#[proc_macro_derive(PollVariants, attributes(value_type, error_type))] -pub fn poll_variant_macro(input: TokenStream) -> TokenStream { - // ----- Parse input ---------------------------------- - let input = parse_macro_input!(input as DeriveInput); - let attrs = &input.attrs; - let vis = &input.vis; - let ident = &input.ident; - let data = &input.data; - let og_generics = &input.generics; - let (og_impl_generics, og_type_generics, og_where_clause) = &og_generics.split_for_impl(); - - // ----- Check that item the macro was used on is a struct ---------------------------------- - match data { - Data::Struct(struct_data) => struct_data, - Data::Enum(_) => panic!("Stateful struct cannot be derived from an enum."), - Data::Union(_) => panic!("Stateful struct cannot be derived from a union."), - }; - - // ----- Extract attribute information ---------------------------------- - const VALUE_T_NAME: &str = "value_type"; - const ERROR_T_NAME: &str = "error_type"; - let mut value_type: Option = None; - let mut error_type: Option = None; - for attribute in attrs.iter() { - // if the attribute is a named value - if let Meta::NameValue(meta) = &attribute.meta { - // if the name of the attribute is value_type - if meta.path.segments[0].ident == VALUE_T_NAME { - // if the value of the attribute is a literal - if let Expr::Lit(lit) = &meta.value { - // if the literal is a string - if let Lit::Str(lit) = &lit.lit { - let span = lit.span(); - let string = lit.token().to_string(); - let string = string.trim_matches('"').to_string(); - let _value_type: Type = parse_str(string.deref()).unwrap(); - let _value_type: Type = parse_quote_spanned!(span=> #_value_type); - - value_type = Some(_value_type); - - } else { - panic!("{VALUE_T_NAME} must be set with a string literal.") - } - } else { - panic!("{VALUE_T_NAME} must be set with a literal.") - } - } - - // if the name of the attribute is error_type - if meta.path.segments[0].ident == ERROR_T_NAME { - // if the value of the attribute is a literal - if let Expr::Lit(lit) = &meta.value { - // if the literal is a string - if let Lit::Str(lit) = &lit.lit { - let span = lit.span(); - let string = lit.token().to_string(); - let string = string.trim_matches('"').to_string(); - let _error_type: Type = parse_str(string.deref()).unwrap(); - let _error_type: Type = parse_quote_spanned!(span=> #_error_type); - - error_type = Some(_error_type); - } else { - panic!("{ERROR_T_NAME} must be set with a string literal.") - } - } else { - panic!("{ERROR_T_NAME} must be set with a literal.") - } - } - } - } - let value_type = value_type - .expect(format!("Need attribute {VALUE_T_NAME}: #[{VALUE_T_NAME} = \"type\"]").deref()); - let error_type = error_type - .expect(format!("Need attribute {ERROR_T_NAME}: #[{ERROR_T_NAME} = \"type\"]").deref()); - - // ----- Add publisher generics ---------------------------------- - // MutexT - const MUTEX_T_NAME: &str = "PublishMutexT"; - let mutex_t_ident = Ident::new(MUTEX_T_NAME, Span::call_site()); - const CAPACITY_NAME: &str = "CAPACITY"; - let capacity_ident = Ident::new(CAPACITY_NAME, Span::call_site()); - const NUM_SUBS_NAME: &str = "NUM_SUBS"; - let num_subs_ident = Ident::new(NUM_SUBS_NAME, Span::call_site()); - let mut num_lifetimes: usize = 0; - let mut num_types: usize = 0; - let mut num_const: usize = 0; - let mut has_mutex_t = false; - for param in og_generics.params.iter() { - match param { - GenericParam::Lifetime(_) => num_lifetimes += 1, - GenericParam::Type(param) => { - num_types += 1; - - // If the generic parameter is MutexT - if param.ident == MUTEX_T_NAME { - has_mutex_t = true; - } - }, - GenericParam::Const(_) => num_const += 1, - } - } - - let mut publish_generics = og_generics.clone(); - // If MutexT is not a generic parameter, add it - if !has_mutex_t { - let mutex_t_param: GenericParam = - parse_quote!(#mutex_t_ident: embassy_sync::blocking_mutex::raw::RawMutex); - - let num_generics = num_lifetimes + num_types + num_const; - // If there are generics - if num_generics > 0 { - // If all generics are lifetimes - if num_lifetimes == num_generics { - // Add MutexT after the lifetimes - publish_generics.params.push(mutex_t_param); - // If no generics are lifetimes - } else if num_lifetimes == 0 { - // Insert MutexT at the front - publish_generics.params.insert(0, mutex_t_param); - // If there are lifetimes and other generics - } else { - // Insert MutexT after the lifetimes - publish_generics.params.insert(num_lifetimes, mutex_t_param); - } - // If there are no generics - } else { - // Add MutexT - publish_generics.params.push(mutex_t_param); - } - } - // const generics - let capacity_param: GenericParam = parse_quote!(const #capacity_ident: usize); - let num_subs_param: GenericParam = parse_quote!(const #num_subs_ident: usize); - publish_generics.params.push(capacity_param); - publish_generics.params.push(num_subs_param); - - let (publ_impl_generics, publ_type_generics, publ_where_clause) = - &publish_generics.split_for_impl(); - - let pubsub_error_path: Path = parse_quote!(embassy_sync::pubsub::Error); - let pubsub_sub_path: Path = parse_quote!(embassy_sync::pubsub::Subscriber); - - let stateful_variant_ident = Ident::new(format!("{ident}Stateful").deref(), ident.span()); - let publish_variant_ident = Ident::new(format!("{ident}Publish").deref(), ident.span()); - let state_pub_variant_ident = Ident::new(format!("{ident}StatePub").deref(), ident.span()); - - let poll_path: Path = parse_quote!(physical_node::transducer::input::Poll); - let stateful_path: Path = parse_quote!(physical_node::transducer::Stateful); - let publish_path: Path = parse_quote!(physical_node::transducer::Publish); - - let state_path: Path = parse_quote!(physical_node::transducer::State); - let publisher_path: Path = parse_quote!(physical_node::transducer::Publisher); - let cellview_path: Path = parse_quote!(physical_node::cell::CellView); - - let error_path: Path = parse_quote!(physical_node::CriticalError); - - let expanded = quote! { - // ----- Stateful struct ---------------------------------- - #vis struct #stateful_variant_ident #og_generics #og_where_clause { - pub poll: #ident #og_type_generics, - pub state: #state_path<#value_type>, - } - - // ----- Stateful impls ---------------------------------- - impl #og_impl_generics #poll_path for #stateful_variant_ident #og_type_generics #og_where_clause { - type Value = #value_type; - type Error = #error_type; - - #[inline] - async fn poll(&self) -> Result { - let result = self.poll.poll().await; - if let Ok(value) = result { - self.state.update(value); - } - result - } - } - - impl #og_impl_generics #stateful_path for #stateful_variant_ident #og_type_generics #og_where_clause { - type Value = #value_type; - - #[inline(always)] - fn state_cell(&self) -> #cellview_path { - self.state.state_cell() - } - - #[inline(always)] - fn state(&self) -> Self::Value { - self.state.state() - } - } - - // ----- Publish struct ---------------------------------- - #[cfg(feature = "embassy-sync")] - #vis struct #publish_variant_ident #publish_generics #publ_where_clause { - pub poll: #ident #og_type_generics, - pub publisher: #publisher_path<#value_type, #mutex_t_ident, #capacity_ident, #num_subs_ident>, - } - - // ----- Publish impl ---------------------------------- - #[cfg(feature = "embassy-sync")] - impl #publ_impl_generics #poll_path for #publish_variant_ident #publ_type_generics #publ_where_clause { - type Value = #value_type; - type Error = #error_type; - - #[inline] - async fn poll(&self) -> Result { - let result = self.poll.poll().await; - if let Ok(value) = result { - self.publisher.update(value); - } - result - } - } - - #[cfg(feature = "embassy-sync")] - impl #publ_impl_generics #publish_path<#capacity_ident, #num_subs_ident> for #publish_variant_ident #publ_type_generics #publ_where_clause { - type Value = #value_type; - type Mutex = #mutex_t_ident; - - #[inline(always)] - fn subscribe( - &self, - ) -> Result<#pubsub_sub_path, #pubsub_error_path> { - self.publisher.subscribe() - } - } - - // ----- StatePub struct ---------------------------------- - #[cfg(feature = "embassy-sync")] - #vis struct #state_pub_variant_ident #publish_generics #publ_where_clause { - pub poll: #ident #og_type_generics, - pub state: #state_path<#value_type>, - pub publisher: #publisher_path<#value_type, #mutex_t_ident, #capacity_ident, #num_subs_ident>, - } - - #[cfg(feature = "embassy-sync")] - impl #publ_impl_generics #poll_path for #state_pub_variant_ident #publ_type_generics #publ_where_clause { - type Value = #value_type; - type Error = #error_type; - - #[inline] - async fn poll(&self) -> Result { - let result = self.poll.poll().await; - if let Ok(value) = result { - self.state.update(value); - self.publisher.update(value); - } - result - } - } - - #[cfg(feature = "embassy-sync")] - impl #publ_impl_generics #stateful_path for #state_pub_variant_ident #publ_type_generics #publ_where_clause { - type Value = #value_type; - - #[inline(always)] - fn state_cell(&self) -> #cellview_path { - self.state.state_cell() - } - - #[inline(always)] - fn state(&self) -> Self::Value { - self.state.state() - } - } - - #[cfg(feature = "embassy-sync")] - impl #publ_impl_generics #publish_path<#capacity_ident, #num_subs_ident> for #state_pub_variant_ident #publ_type_generics #publ_where_clause { - type Value = #value_type; - type Mutex = #mutex_t_ident; - - #[inline(always)] - fn subscribe( - &self, - ) -> Result<#pubsub_sub_path, #pubsub_error_path> { - self.publisher.subscribe() - } - } - - - }; - - TokenStream::from(expanded) -} diff --git a/macros/node-poll-variants/tests/generate.rs b/macros/node-poll-variants/tests/generate.rs deleted file mode 100644 index 98df1d5..0000000 --- a/macros/node-poll-variants/tests/generate.rs +++ /dev/null @@ -1,31 +0,0 @@ -#![feature(async_fn_in_trait, impl_trait_projections, never_type)] - -use node_poll_variants::PollVariants; -use physical_node::transducer::input::Poll; - -#[derive(PollVariants)] -#[value_type = "SecondT"] -#[error_type = "!"] -struct ExamplePoll<'a, FirstT, SecondT> -where - SecondT: Copy, -{ - a: &'a i32, - b: i32, - first: FirstT, - second: SecondT, -} - -impl<'a, FirstT, SecondT> Poll for ExamplePoll<'a, FirstT, SecondT> -where - SecondT: Copy, -{ - type Value = SecondT; - type Error = !; - - async fn poll(&self) -> Result { - Ok(self.second) - } -} - -fn main() {} diff --git a/macros/node-poll-variants/tests/test_build.rs b/macros/node-poll-variants/tests/test_build.rs deleted file mode 100644 index 6661c9d..0000000 --- a/macros/node-poll-variants/tests/test_build.rs +++ /dev/null @@ -1,5 +0,0 @@ -#[test] -fn tests() { - let t = trybuild::TestCases::new(); - t.pass("tests/generate.rs"); -} \ No newline at end of file diff --git a/node/Cargo.toml b/node/Cargo.toml index 644cde8..9f2d8ff 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -17,6 +17,3 @@ workspace = true workspace = true [dependencies.uom] workspace = true -[dependencies.embassy-sync] -workspace = true -optional = true \ No newline at end of file diff --git a/node/src/lib.rs b/node/src/lib.rs index aed9b0d..5439644 100644 --- a/node/src/lib.rs +++ b/node/src/lib.rs @@ -1,9 +1,3 @@ #![no_std] -pub mod transducer; - -pub mod cell { - pub use physical::cell::*; -} - -pub use physical::CriticalError; +pub use physical::CriticalError; \ No newline at end of file diff --git a/node/src/transducer/input.rs b/node/src/transducer/input.rs deleted file mode 100644 index 84eb5d9..0000000 --- a/node/src/transducer/input.rs +++ /dev/null @@ -1 +0,0 @@ -pub use physical::transducer::input::*; diff --git a/node/src/transducer/mod.rs b/node/src/transducer/mod.rs deleted file mode 100644 index e8e7c3d..0000000 --- a/node/src/transducer/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -pub mod input; -pub mod output; -#[cfg(feature = "embassy-sync")] -mod sync; - -pub use physical::transducer::*; -#[cfg(feature = "embassy-sync")] -pub use sync::*; diff --git a/node/src/transducer/output.rs b/node/src/transducer/output.rs deleted file mode 100644 index c441daa..0000000 --- a/node/src/transducer/output.rs +++ /dev/null @@ -1 +0,0 @@ -pub use physical::transducer::output::*; \ No newline at end of file diff --git a/node/src/transducer/sync/input.rs b/node/src/transducer/sync/input.rs deleted file mode 100644 index e66a306..0000000 --- a/node/src/transducer/sync/input.rs +++ /dev/null @@ -1,61 +0,0 @@ -use crate::cell::CellView; -use crate::transducer::{Publish, Publisher}; -use core::cell::Cell; -use embassy_sync::blocking_mutex::raw::RawMutex; -use embassy_sync::pubsub::{Error, PubSubChannel, Subscriber}; -use physical::transducer::{State, Stateful}; - -pub struct StatefulPublisher< - T: Copy, - MutexT: RawMutex, - const CAPACITY: usize, - const NUM_SUBS: usize, -> { - pub state: State, - pub publisher: Publisher, -} - -impl - StatefulPublisher -{ - #[inline(always)] - pub fn new(state: State, publisher: Publisher) -> Self { - Self { state, publisher } - } - - #[inline(always)] - pub fn update(&self, value: T) { - self.state.update(value); - self.publisher.update(value); - } -} - -impl Stateful - for StatefulPublisher -{ - type Value = T; - - #[inline(always)] - fn state_cell(&self) -> CellView { - self.state.state_cell() - } - - #[inline(always)] - fn state(&self) -> Self::Value { - self.state.state() - } -} - -impl - Publish for StatefulPublisher -{ - type Value = T; - type Mutex = MutexT; - - #[inline(always)] - fn subscribe( - &self, - ) -> Result, Error> { - self.publisher.subscribe() - } -} diff --git a/node/src/transducer/sync/mod.rs b/node/src/transducer/sync/mod.rs deleted file mode 100644 index 0ac16ba..0000000 --- a/node/src/transducer/sync/mod.rs +++ /dev/null @@ -1,58 +0,0 @@ -mod input; - -pub use input::*; - -use embassy_sync::blocking_mutex::raw::RawMutex; -use embassy_sync::pubsub; -use embassy_sync::pubsub::{PubSubBehavior, PubSubChannel, Subscriber}; - -pub trait Publish { - type Value: Copy; - type Mutex: RawMutex; - - fn subscribe( - &self, - ) -> Result, pubsub::Error>; -} - -pub struct Publisher { - channel: PubSubChannel, -} - -impl -Publisher -{ - #[inline(always)] - pub fn new(channel: PubSubChannel) -> Self { - Self { channel } - } - - #[inline(always)] - pub fn update(&self, value: T) { - self.channel.publish_immediate(value); - } -} - -impl -Publish for Publisher -{ - type Value = T; - type Mutex = MutexT; - - #[inline(always)] - fn subscribe( - &self, - ) -> Result, pubsub::Error> { - self.channel.subscriber() - } -} - -impl -From> -for Publisher -{ - #[inline(always)] - fn from(channel: PubSubChannel) -> Self { - Publisher::new(channel) - } -} \ No newline at end of file diff --git a/peripheral-components/ads1256/node/Cargo.toml b/peripheral-components/ads1256/node/Cargo.toml deleted file mode 100644 index 5b64fff..0000000 --- a/peripheral-components/ads1256/node/Cargo.toml +++ /dev/null @@ -1,31 +0,0 @@ -[package] -name = "physical-ads1256" -description = "Shared node abstractions for ADS1256 components." -version.workspace = true -edition.workspace = true -repository.workspace = true -readme.workspace = true -license.workspace = true - -[features] -embassy-sync = ["dep:embassy-sync", "ads1256/embassy-sync", "physical-node/embassy-sync"] -poll = ["standard-multiplexer", "embassy-sync"] -standard-multiplexer = [] - -[dependencies.physical-node] -path = "../../../node" -[dependencies.node-poll-variants] -path = "../../../macros/node-poll-variants" -[dependencies.ads1256] -workspace = true -[dependencies.embedded-hal] -workspace = true -[dependencies.embedded-hal-async] -workspace = true -[dependencies.defmt] -workspace = true -[dependencies.uom] -workspace = true -[dependencies.embassy-sync] -workspace = true -optional = true \ No newline at end of file diff --git a/peripheral-components/ads1256/node/src/lib.rs b/peripheral-components/ads1256/node/src/lib.rs deleted file mode 100644 index 8487fab..0000000 --- a/peripheral-components/ads1256/node/src/lib.rs +++ /dev/null @@ -1,3 +0,0 @@ -#![no_std] - -pub mod standard; \ No newline at end of file diff --git a/peripheral-components/ads1256/node/src/standard/mod.rs b/peripheral-components/ads1256/node/src/standard/mod.rs deleted file mode 100644 index 490e4c6..0000000 --- a/peripheral-components/ads1256/node/src/standard/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -#[cfg(feature = "standard-multiplexer")] -pub mod multiplexer; \ No newline at end of file diff --git a/peripheral-components/ads1256/node/src/standard/multiplexer/mod.rs b/peripheral-components/ads1256/node/src/standard/multiplexer/mod.rs deleted file mode 100644 index 2c842b4..0000000 --- a/peripheral-components/ads1256/node/src/standard/multiplexer/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -mod sync; - -#[cfg(feature = "embassy-sync")] -pub use sync::*; \ No newline at end of file diff --git a/peripheral-components/ads1256/node/src/standard/multiplexer/sync/mod.rs b/peripheral-components/ads1256/node/src/standard/multiplexer/sync/mod.rs deleted file mode 100644 index 5e18f2b..0000000 --- a/peripheral-components/ads1256/node/src/standard/multiplexer/sync/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -#[cfg(feature = "poll")] -pub mod poll; \ No newline at end of file diff --git a/peripheral-components/ads1256/node/src/standard/multiplexer/sync/poll.rs b/peripheral-components/ads1256/node/src/standard/multiplexer/sync/poll.rs deleted file mode 100644 index d180353..0000000 --- a/peripheral-components/ads1256/node/src/standard/multiplexer/sync/poll.rs +++ /dev/null @@ -1,382 +0,0 @@ -use ads1256::{ - AdControl, Ads1256, BlockingDelay, DataRate, Gain, Multiplexer, OutputPin, SpiBus, Status, Wait, -}; -use core::ops::DerefMut; -use embassy_sync::blocking_mutex::raw::RawMutex; -use embassy_sync::mutex::Mutex; -use node_poll_variants::PollVariants; -use physical_node::transducer::input::Poll; -use physical_node::CriticalError; -use uom::si::f32; - -#[derive(PollVariants)] -#[value_type = "f32::ElectricPotential"] -#[error_type = "CriticalError"] -pub struct AutocalPoll<'a, DeviceMutexT, ModInT, DelayerT, SST, DrdyT, SpiT> -where - DeviceMutexT: RawMutex, - ModInT: ModInput, - DelayerT: BlockingDelay, - SST: OutputPin, - DrdyT: Wait, - SpiT: SpiBus, -{ - input_mod: ModInT, - ads1256: &'a Mutex>, - spi: &'a Mutex, -} - -impl<'a, DeviceMutexT, ModInT, DelayerT, SST, DrdyT, SpiT> - AutocalPoll<'a, DeviceMutexT, ModInT, DelayerT, SST, DrdyT, SpiT> -where - DeviceMutexT: RawMutex, - ModInT: ModInput, - DelayerT: BlockingDelay, - SST: OutputPin, - DrdyT: Wait, - SpiT: SpiBus, -{ - #[inline(always)] - pub fn new( - input_mod: ModInT, - ads1256: &'a Mutex>, - spi: &'a Mutex, - ) -> Self { - Self { - input_mod, - ads1256, - spi, - } - } -} - -impl<'a, DeviceMutexT, ModInT, DelayerT, SST, DrdyT, SpiT> Poll - for AutocalPoll<'a, DeviceMutexT, ModInT, DelayerT, SST, DrdyT, SpiT> -where - DeviceMutexT: RawMutex, - ModInT: ModInput, - DelayerT: BlockingDelay, - SST: OutputPin, - DrdyT: Wait, - SpiT: SpiBus, -{ - type Value = f32::ElectricPotential; - type Error = CriticalError; - - async fn poll(&self) -> Result { - let mut ads1256_guard = self.ads1256.lock().await; - let ads1256 = ads1256_guard.deref_mut(); - //TODO: ADS1256 documentation seems to say we should be waiting for drdy low after - // issuing standby command but it never goes low. - - let result = ads1256 - .autocal_convert_m( - self.spi, - self.input_mod.multiplexer(), - self.input_mod.status(), - self.input_mod.ad_control(), - self.input_mod.data_rate(), - true, - ) - .await; - - match result { - Ok(conversion) => Ok(conversion.to_voltage(self.input_mod.gain())), - Err(_) => Err(CriticalError::Communication), - } - } -} - -pub trait ModInput: Copy { - fn multiplexer(self) -> Multiplexer; - - fn gain(self) -> Gain; - - fn status(self) -> Option; - - fn ad_control(self) -> Option; - - fn data_rate(self) -> Option; -} - -#[derive(Copy, Clone, Eq, PartialEq)] -pub struct ModInputOnly { - pub multiplexer: Multiplexer, - /// Only used for converting to voltage, this value must match what is set on the ADS1256, it - /// will not *be* set unlike the other fields. - pub gain: Gain, -} - -impl ModInput for ModInputOnly { - fn multiplexer(self) -> Multiplexer { - self.multiplexer - } - - fn gain(self) -> Gain { - self.gain - } - - fn status(self) -> Option { - None - } - - fn ad_control(self) -> Option { - None - } - - fn data_rate(self) -> Option { - None - } -} - -/// buffer -#[derive(Copy, Clone, Eq, PartialEq)] -pub struct ModInStatus { - pub multiplexer: Multiplexer, - /// Only used for converting to voltage, this value must match what is set on the ADS1256, it - /// will not *be* set unlike the other fields. - pub gain: Gain, - pub status: Status, -} - -impl ModInput for ModInStatus { - #[inline(always)] - fn multiplexer(self) -> Multiplexer { - self.multiplexer - } - - #[inline(always)] - fn gain(self) -> Gain { - self.gain - } - - #[inline(always)] - fn status(self) -> Option { - Some(self.status) - } - - #[inline(always)] - fn ad_control(self) -> Option { - None - } - - #[inline(always)] - fn data_rate(self) -> Option { - None - } -} - -/// gain -#[derive(Copy, Clone, Eq, PartialEq)] -pub struct ModInAdControl { - pub multiplexer: Multiplexer, - pub ad_control: AdControl, -} - -impl ModInput for ModInAdControl { - #[inline(always)] - fn multiplexer(self) -> Multiplexer { - self.multiplexer - } - - #[inline(always)] - fn gain(self) -> Gain { - self.ad_control.gain() - } - - #[inline(always)] - fn status(self) -> Option { - None - } - - #[inline(always)] - fn ad_control(self) -> Option { - Some(self.ad_control) - } - - #[inline(always)] - fn data_rate(self) -> Option { - None - } -} - -/// data rate -#[derive(Copy, Clone, Eq, PartialEq)] -pub struct ModInDataRate { - pub multiplexer: Multiplexer, - /// Only used for converting to voltage, this value must match what is set on the ADS1256, it - /// will not *be* set unlike the other fields. - pub gain: Gain, - pub data_rate: DataRate, -} - -impl ModInput for ModInDataRate { - #[inline(always)] - fn multiplexer(self) -> Multiplexer { - self.multiplexer - } - - #[inline(always)] - fn gain(self) -> Gain { - self.gain - } - - #[inline(always)] - fn status(self) -> Option { - None - } - - #[inline(always)] - fn ad_control(self) -> Option { - None - } - - #[inline(always)] - fn data_rate(self) -> Option { - Some(self.data_rate) - } -} - -/// buffer, gain -#[derive(Copy, Clone, Eq, PartialEq)] -pub struct ModInStatAdc { - pub multiplexer: Multiplexer, - pub status: Status, - pub ad_control: AdControl, -} - -impl ModInput for ModInStatAdc { - #[inline(always)] - fn multiplexer(self) -> Multiplexer { - self.multiplexer - } - - #[inline(always)] - fn gain(self) -> Gain { - self.ad_control.gain() - } - - #[inline(always)] - fn status(self) -> Option { - Some(self.status) - } - - #[inline(always)] - fn ad_control(self) -> Option { - Some(self.ad_control) - } - - #[inline(always)] - fn data_rate(self) -> Option { - None - } -} - -/// buffer, data rate -#[derive(Copy, Clone, Eq, PartialEq)] -pub struct ModInStatDrate { - pub multiplexer: Multiplexer, - /// Only used for converting to voltage, this value must match what is set on the ADS1256, it - /// will not *be* set unlike the other fields. - pub gain: Gain, - pub status: Status, - pub data_rate: DataRate, -} - -impl ModInput for ModInStatDrate { - #[inline(always)] - fn multiplexer(self) -> Multiplexer { - self.multiplexer - } - - #[inline(always)] - fn gain(self) -> Gain { - self.gain - } - - #[inline(always)] - fn status(self) -> Option { - Some(self.status) - } - - #[inline(always)] - fn ad_control(self) -> Option { - None - } - - #[inline(always)] - fn data_rate(self) -> Option { - Some(self.data_rate) - } -} - -// gain, data rate -#[derive(Copy, Clone, Eq, PartialEq)] -pub struct ModInAdcDrate { - pub multiplexer: Multiplexer, - pub ad_control: AdControl, - pub data_rate: DataRate, -} - -impl ModInput for ModInAdcDrate { - #[inline(always)] - fn multiplexer(self) -> Multiplexer { - self.multiplexer - } - - #[inline(always)] - fn gain(self) -> Gain { - self.ad_control.gain() - } - - #[inline(always)] - fn status(self) -> Option { - None - } - - #[inline(always)] - fn ad_control(self) -> Option { - Some(self.ad_control) - } - - #[inline(always)] - fn data_rate(self) -> Option { - Some(self.data_rate) - } -} - -/// buffer, gain, data rate -#[derive(Copy, Clone, Eq, PartialEq)] -pub struct ModInAll { - pub multiplexer: Multiplexer, - pub status: Status, - pub ad_control: AdControl, - pub data_rate: DataRate, -} - -impl ModInput for ModInAll { - #[inline(always)] - fn multiplexer(self) -> Multiplexer { - self.multiplexer - } - - #[inline(always)] - fn gain(self) -> Gain { - self.ad_control.gain() - } - - #[inline(always)] - fn status(self) -> Option { - Some(self.status) - } - - #[inline(always)] - fn ad_control(self) -> Option { - Some(self.ad_control) - } - - #[inline(always)] - fn data_rate(self) -> Option { - Some(self.data_rate) - } -} diff --git a/src/adc/mod.rs b/src/adc/mod.rs new file mode 100644 index 0000000..8958f61 --- /dev/null +++ b/src/adc/mod.rs @@ -0,0 +1,2 @@ +#[cfg(feature = "stm32")] +pub mod stm32; \ No newline at end of file diff --git a/src/adc/stm32.rs b/src/adc/stm32.rs new file mode 100644 index 0000000..068e596 --- /dev/null +++ b/src/adc/stm32.rs @@ -0,0 +1,13 @@ +use uom::si::electric_potential::millivolt; +use uom::si::quantities::ElectricPotential; + +pub fn reading_to_voltage( + reading: u16, + reference_voltage: ElectricPotential, + v_ref_int_scale: f32, +) -> ElectricPotential { + let reference_mv = reference_voltage.get::(); + let reading = f32::from(reading); + + ElectricPotential::new::(reading * v_ref_int_scale / reference_mv) +} diff --git a/src/cell.rs b/src/cell.rs deleted file mode 100644 index 16ee00b..0000000 --- a/src/cell.rs +++ /dev/null @@ -1,20 +0,0 @@ -use core::cell::Cell; - -/// Provides a view only reference to a [Cell]. -/// Useful alternative to `&Cell` when an API wants to control where a [Cell]s value can be set. -#[derive(Copy, Clone)] -pub struct CellView<'a, T: Copy>(&'a Cell); - -impl CellView<'_, T> { - #[inline(always)] - pub fn get(self) -> T { - self.0.get() - } -} - -impl<'a, T: Copy> From<&'a Cell> for CellView<'a, T> { - #[inline(always)] - fn from(value: &'a Cell) -> Self { - CellView(value) - } -} diff --git a/src/error.rs b/src/error.rs index a368f05..d371350 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,4 +1,6 @@ -use crate::transducer::InvalidValue; +/// Indicates the transducer value is statically known to be impossible. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub struct InvalidValue; /// An error that it is likely impossible to recover from. This error should only be created in /// situations where attempts to recover have already been attempted and have failed. Error handling diff --git a/src/lib.rs b/src/lib.rs index 5cdec96..f51a0ab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,8 @@ pub mod transducer; pub mod control; -pub mod cell; pub mod error; +pub mod adc; + pub use error::CriticalError; diff --git a/src/transducer/input.rs b/src/transducer/input.rs deleted file mode 100644 index 40e3cce..0000000 --- a/src/transducer/input.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub trait Poll { - type Value: Copy; - type Error: Copy; - - async fn poll(&self) -> Result; -} diff --git a/src/transducer/mod.rs b/src/transducer/mod.rs index d79c453..9ee987b 100644 --- a/src/transducer/mod.rs +++ b/src/transducer/mod.rs @@ -1,62 +1,3 @@ -use core::cell::Cell; -use crate::cell::CellView; - -pub mod input; -pub mod output; mod part; -pub use part::*; - -// Initialisation will always be async and won't complete until a state is available for all -// stateful transducers. -pub trait Stateful { - type Value: Copy; - - fn state_cell(&self) -> CellView; - - fn state(&self) -> Self::Value; -} - -pub struct State { - state_cell: Cell, -} - -impl State { - #[inline(always)] - pub fn new(state_cell: Cell) -> Self { - Self { state_cell } - } - - #[inline(always)] - pub fn update(&self, value: T) { - self.state_cell.set(value); - } -} - -impl Stateful for State { - type Value = T; - - #[inline(always)] - fn state_cell(&self) -> CellView { - (&self.state_cell).into() - } - - #[inline(always)] - fn state(&self) -> Self::Value { - self.state_cell.get() - } -} - -impl From> for State { - #[inline(always)] - fn from(state_cell: Cell) -> Self { - State::new(state_cell) - } -} - -// --------------------------------------------------------------------------------------------------------------------- -// ----- Error ------------------------ -// --------------------------------------------------------------------------------------------------------------------- -/// Indicates the transducer value is statically known to be impossible. -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct InvalidValue; +pub use part::*; \ No newline at end of file diff --git a/src/transducer/output.rs b/src/transducer/output.rs deleted file mode 100644 index 3512b8f..0000000 --- a/src/transducer/output.rs +++ /dev/null @@ -1,8 +0,0 @@ -use crate::transducer::InvalidValue; - -pub trait Output { - type Value: Copy; - - //TODO: Should this be maybe async? - fn output(&mut self, setting: Self::Value) -> Result<(), InvalidValue>; -} diff --git a/src/transducer/part/lm35.rs b/src/transducer/part/lm35.rs index 646cce8..e3f9f7e 100644 --- a/src/transducer/part/lm35.rs +++ b/src/transducer/part/lm35.rs @@ -1,4 +1,4 @@ -use crate::transducer::InvalidValue; +use crate::error::InvalidValue; use uom::si::electric_potential::volt; use uom::si::quantities::{ElectricPotential, ThermodynamicTemperature}; use uom::si::thermodynamic_temperature::degree_celsius; diff --git a/src/transducer/part/thermocouple/type_k.rs b/src/transducer/part/thermocouple/type_k.rs index 1687050..b95ecba 100644 --- a/src/transducer/part/thermocouple/type_k.rs +++ b/src/transducer/part/thermocouple/type_k.rs @@ -1,4 +1,4 @@ -use crate::transducer::InvalidValue; +use crate::error::InvalidValue; use libm::powf; use uom::si::electric_potential::millivolt; use uom::si::quantities::{ElectricPotential, ThermodynamicTemperature};