195 lines
5.8 KiB
Rust
195 lines
5.8 KiB
Rust
#![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_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 embassy_executor::_export::StaticCell;
|
|
use embassy_stm32::peripherals::{EXTI6, PF6, PF7, SPI3};
|
|
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, PF7>,
|
|
ExtiInput<'static, PF6>,
|
|
Spi<'static, SPI3, NoDma, NoDma>,
|
|
10,
|
|
1,
|
|
>;
|
|
|
|
struct Inputs {
|
|
ai1: ExampleInput,
|
|
ai2: ExampleInput,
|
|
ai3: ExampleInput,
|
|
}
|
|
|
|
// Inputs
|
|
static ANALOG_INPUTS: StaticCell<Inputs> = StaticCell::new();
|
|
static ADS_1256: StaticCell<
|
|
Mutex<NoopRawMutex, Ads1256<Ads1256Delay, Output<PF7>, ExtiInput<PF6>>>,
|
|
> = StaticCell::new();
|
|
static SPI: StaticCell<Mutex<NoopRawMutex, 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(Mutex::new(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(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::<volt>(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::<volt>(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::<volt>(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::<volt>();
|
|
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::<volt>();
|
|
info!("Log task ai{}: {}", input_num, msg);
|
|
}
|
|
}
|