use embedded_hal::digital::InputPin as _;
use gpiocdev::{line::Direction, Request};
use gpiocdev_embedded_hal::InputPin;
use gpiosim::Simpleton;
use std::time::Duration;
const PROPAGATION_DELAY: Duration = Duration::from_millis(10);
fn wait_propagation_delay() {
std::thread::sleep(PROPAGATION_DELAY);
}
#[test]
fn is_high() {
let s = Simpleton::new(5);
let offset = 3;
let mut pin = InputPin::new(s.dev_path(), offset).unwrap();
assert!(!pin.is_high().unwrap());
s.pullup(offset).unwrap();
wait_propagation_delay();
assert!(pin.is_high().unwrap());
}
#[test]
fn is_low() {
let s = Simpleton::new(5);
let offset = 2;
let mut pin = InputPin::new(s.dev_path(), offset).unwrap();
assert!(pin.is_low().unwrap());
s.pullup(offset).unwrap();
wait_propagation_delay();
assert!(!pin.is_low().unwrap());
}
#[test]
fn into_output_pin() {
use embedded_hal::digital::{OutputPin as _, PinState};
use gpiosim::Level;
let s = Simpleton::new(5);
let offset = 2;
let pin = InputPin::new(s.dev_path(), offset).unwrap();
let mut pin = pin.into_output_pin(PinState::Low).unwrap();
assert_eq!(s.get_level(offset).unwrap(), Level::Low);
pin.set_high().unwrap();
assert_eq!(s.get_level(offset).unwrap(), Level::High);
let req = Request::from(pin);
let config = req.config();
let offsets = config.lines();
assert_eq!(offsets.len(), 1);
assert_eq!(offsets[0], offset);
let line_config = config.line_config(offset).unwrap();
assert_eq!(line_config.direction, Some(Direction::Output));
}
mod try_from_request {
use super::*;
use gpiocdev::line::Value;
#[test]
fn output_request() {
let s = Simpleton::new(5);
let offset = 2;
let mut config = gpiocdev::request::Config::default();
config
.on_chip(s.dev_path())
.with_line(offset)
.as_output(Value::Active);
let req = Request::from_config(config).request().unwrap();
assert_eq!(
InputPin::try_from(req).unwrap_err(),
gpiocdev_embedded_hal::Error::RequiresInputMode
);
}
#[test]
fn input_request() {
let s = Simpleton::new(5);
let offset = 2;
let req = Request::builder()
.on_chip(s.dev_path())
.with_line(offset)
.as_input()
.request()
.unwrap();
let config = req.config();
let mut pin = InputPin::try_from(req).unwrap();
assert!(pin.is_low().unwrap());
s.pullup(offset).unwrap();
wait_propagation_delay();
assert!(!pin.is_low().unwrap());
let req = Request::from(pin);
assert_eq!(config, req.config());
}
#[test]
fn as_is_request() {
let s = Simpleton::new(5);
let offset = 2;
let req = Request::builder()
.on_chip(s.dev_path())
.with_line(offset)
.request()
.unwrap();
assert_eq!(
InputPin::try_from(req).unwrap_err(),
gpiocdev_embedded_hal::Error::RequiresInputMode
);
}
#[test]
fn multiple_lines() {
let s = Simpleton::new(5);
let req = Request::builder()
.on_chip(s.dev_path())
.with_lines(&[1, 2])
.as_output(Value::Inactive)
.request()
.unwrap();
assert_eq!(
InputPin::try_from(req).unwrap_err(),
gpiocdev_embedded_hal::Error::MultipleLinesRequested
);
}
}
#[test]
fn into_request() {
let s = Simpleton::new(5);
let offset = 2;
let pin = InputPin::new(s.dev_path(), offset).unwrap();
let req = Request::from(pin);
let config = req.config();
let offsets = config.lines();
assert_eq!(offsets.len(), 1);
assert_eq!(offsets[0], offset);
let line_config = config.line_config(offset).unwrap();
assert_eq!(line_config.direction, Some(Direction::Input));
}
#[test]
fn from_found_line() {
let s = Simpleton::new(5);
let offset = 2;
let fl = gpiocdev::FoundLine {
chip: s.dev_path().clone(),
info: gpiocdev::line::Info {
offset,
..Default::default()
},
};
let pin = InputPin::from_found_line(fl).unwrap();
let req = Request::from(pin);
let config = req.config();
let offsets = config.lines();
assert_eq!(offsets.len(), 1);
assert_eq!(offsets[0], offset);
let line_config = config.line_config(offset).unwrap();
assert_eq!(line_config.direction, Some(Direction::Input));
}
#[test]
fn from_name() {
use gpiosim::Bank;
let s = gpiosim::builder()
.with_bank(
Bank::new(8, "input from_name")
.name(3, "ifn banana")
.name(6, "ifn apple"),
)
.live()
.unwrap();
let offset = 6;
let pin = InputPin::from_name("ifn apple").unwrap();
let req = Request::from(pin);
assert_eq!(&req.chip_path(), s.chips()[0].dev_path());
let config = req.config();
let offsets = config.lines();
assert_eq!(offsets.len(), 1);
assert_eq!(offsets[0], offset);
let line_config = config.line_config(offset).unwrap();
assert_eq!(line_config.direction, Some(Direction::Input));
assert_eq!(
InputPin::from_name("ifn grape").unwrap_err(),
gpiocdev_embedded_hal::Error::UnfoundLine("ifn grape".into())
);
}
#[cfg(feature = "async_tokio")]
mod async_tokio {
use super::*;
use embedded_hal_async::digital::Wait;
use gpiocdev_embedded_hal::tokio::InputPin;
use gpiocdev_embedded_hal::InputPin as SyncInputPin;
async fn will_resolve<F>(future: F) -> bool
where
F: core::future::Future,
{
tokio::time::timeout(PROPAGATION_DELAY, future)
.await
.is_ok()
}
#[tokio::test]
async fn from_input() {
let s = Simpleton::new(5);
let offset = 3;
let pin = SyncInputPin::new(s.dev_path(), offset).unwrap();
let mut pin = InputPin::from(pin);
assert!(pin.is_low().unwrap());
s.pullup(offset).unwrap();
wait_propagation_delay();
assert!(pin.is_high().unwrap());
let req = gpiocdev::Request::from(pin);
let config = req.config();
let offsets = config.lines();
assert_eq!(offsets.len(), 1);
assert_eq!(offsets[0], offset);
let line_config = config.line_config(offset).unwrap();
assert_eq!(line_config.direction, Some(Direction::Input));
assert_eq!(line_config.edge_detection, None);
}
#[tokio::test]
async fn into_input() {
let s = Simpleton::new(5);
let offset = 3;
let pin = InputPin::new(s.dev_path(), offset).unwrap();
let mut pin = SyncInputPin::from(pin);
assert!(pin.is_low().unwrap());
s.pullup(offset).unwrap();
wait_propagation_delay();
assert!(pin.is_high().unwrap());
let req = gpiocdev::Request::from(pin);
let config = req.config();
let offsets = config.lines();
assert_eq!(offsets.len(), 1);
assert_eq!(offsets[0], offset);
let line_config = config.line_config(offset).unwrap();
assert_eq!(line_config.direction, Some(Direction::Input));
assert_eq!(line_config.edge_detection, None);
}
#[tokio::test]
async fn wait_for_high() {
let s = Simpleton::new(5);
let offset = 3;
let mut pin = InputPin::new(s.dev_path(), offset).unwrap();
assert!(!will_resolve(pin.wait_for_high()).await);
assert!(will_resolve(pin.wait_for_low()).await);
s.pullup(offset).unwrap();
assert!(will_resolve(pin.wait_for_high()).await);
assert!(!will_resolve(pin.wait_for_low()).await);
assert!(will_resolve(pin.wait_for_high()).await);
s.pulldown(offset).unwrap();
assert!(will_resolve(pin.wait_for_low()).await);
assert!(!will_resolve(pin.wait_for_high()).await);
}
#[tokio::test]
async fn wait_for_low() {
let s = Simpleton::new(5);
let offset = 3;
let mut pin = InputPin::new(s.dev_path(), offset).unwrap();
assert!(will_resolve(pin.wait_for_low()).await);
s.pullup(offset).unwrap();
wait_propagation_delay();
assert!(will_resolve(pin.wait_for_low()).await);
assert!(will_resolve(pin.wait_for_high()).await);
assert!(!will_resolve(pin.wait_for_low()).await);
s.pulldown(offset).unwrap();
assert!(will_resolve(pin.wait_for_low()).await);
assert!(!will_resolve(pin.wait_for_high()).await);
}
#[tokio::test]
async fn wait_for_rising_edge() {
let s = Simpleton::new(5);
let offset = 3;
let mut pin = InputPin::new(s.dev_path(), offset).unwrap();
assert!(!will_resolve(pin.wait_for_rising_edge()).await);
s.pullup(offset).unwrap();
assert!(will_resolve(pin.wait_for_rising_edge()).await);
assert!(!will_resolve(pin.wait_for_rising_edge()).await);
s.pulldown(offset).unwrap();
assert!(!will_resolve(pin.wait_for_rising_edge()).await);
s.pullup(offset).unwrap();
assert!(will_resolve(pin.wait_for_rising_edge()).await);
assert!(!will_resolve(pin.wait_for_rising_edge()).await);
}
#[tokio::test]
async fn wait_for_falling_edge() {
let s = Simpleton::new(5);
let offset = 3;
let mut pin = InputPin::new(s.dev_path(), offset).unwrap();
assert!(!will_resolve(pin.wait_for_falling_edge()).await);
s.pullup(offset).unwrap();
wait_propagation_delay();
assert!(!will_resolve(pin.wait_for_falling_edge()).await);
s.pulldown(offset).unwrap();
assert!(will_resolve(pin.wait_for_falling_edge()).await);
assert!(!will_resolve(pin.wait_for_falling_edge()).await);
s.pullup(offset).unwrap();
assert!(!will_resolve(pin.wait_for_falling_edge()).await);
}
#[tokio::test]
async fn wait_for_any_edge() {
let s = Simpleton::new(5);
let offset = 3;
let mut pin = InputPin::new(s.dev_path(), offset).unwrap();
assert!(!will_resolve(pin.wait_for_any_edge()).await);
s.pullup(offset).unwrap();
assert!(will_resolve(pin.wait_for_any_edge()).await);
s.pulldown(offset).unwrap();
assert!(will_resolve(pin.wait_for_any_edge()).await);
assert!(!will_resolve(pin.wait_for_any_edge()).await);
s.pullup(offset).unwrap();
assert!(will_resolve(pin.wait_for_any_edge()).await);
assert!(!will_resolve(pin.wait_for_any_edge()).await);
}
}
#[cfg(feature = "async_io")]
mod async_io {
use super::*;
use ::async_io::block_on;
use embedded_hal_async::digital::Wait;
use gpiocdev_embedded_hal::async_io::InputPin;
use gpiocdev_embedded_hal::InputPin as SyncInputPin;
async fn will_resolve<F>(future: F) -> bool
where
F: core::future::Future,
{
async_std::future::timeout(PROPAGATION_DELAY, future)
.await
.is_ok()
}
#[test]
fn from_input() {
let s = Simpleton::new(5);
let offset = 3;
let pin = SyncInputPin::new(s.dev_path(), offset).unwrap();
let mut pin = InputPin::from(pin);
assert!(pin.is_low().unwrap());
s.pullup(offset).unwrap();
wait_propagation_delay();
assert!(pin.is_high().unwrap());
let req = gpiocdev::Request::from(pin);
let config = req.config();
let offsets = config.lines();
assert_eq!(offsets.len(), 1);
assert_eq!(offsets[0], offset);
let line_config = config.line_config(offset).unwrap();
assert_eq!(line_config.direction, Some(Direction::Input));
assert_eq!(line_config.edge_detection, None);
}
#[test]
fn into_input() {
let s = Simpleton::new(5);
let offset = 3;
let pin = InputPin::new(s.dev_path(), offset).unwrap();
let mut pin = SyncInputPin::from(pin);
assert!(pin.is_low().unwrap());
s.pullup(offset).unwrap();
wait_propagation_delay();
assert!(pin.is_high().unwrap());
let req = gpiocdev::Request::from(pin);
let config = req.config();
let offsets = config.lines();
assert_eq!(offsets.len(), 1);
assert_eq!(offsets[0], offset);
let line_config = config.line_config(offset).unwrap();
assert_eq!(line_config.direction, Some(Direction::Input));
assert_eq!(line_config.edge_detection, None);
}
#[test]
fn wait_for_high() {
let s = Simpleton::new(5);
let offset = 3;
let mut pin = InputPin::new(s.dev_path(), offset).unwrap();
block_on(async {
assert!(!will_resolve(pin.wait_for_high()).await);
assert!(will_resolve(pin.wait_for_low()).await);
s.pullup(offset).unwrap();
assert!(will_resolve(pin.wait_for_high()).await);
assert!(!will_resolve(pin.wait_for_low()).await);
assert!(will_resolve(pin.wait_for_high()).await);
s.pulldown(offset).unwrap();
assert!(will_resolve(pin.wait_for_low()).await);
assert!(!will_resolve(pin.wait_for_high()).await);
})
}
#[test]
fn wait_for_low() {
let s = Simpleton::new(5);
let offset = 3;
let mut pin = InputPin::new(s.dev_path(), offset).unwrap();
block_on(async {
assert!(will_resolve(pin.wait_for_low()).await);
s.pullup(offset).unwrap();
wait_propagation_delay();
assert!(will_resolve(pin.wait_for_low()).await);
assert!(will_resolve(pin.wait_for_high()).await);
assert!(!will_resolve(pin.wait_for_low()).await);
s.pulldown(offset).unwrap();
assert!(will_resolve(pin.wait_for_low()).await);
assert!(!will_resolve(pin.wait_for_high()).await);
})
}
#[test]
fn wait_for_rising_edge() {
let s = Simpleton::new(5);
let offset = 3;
let mut pin = InputPin::new(s.dev_path(), offset).unwrap();
block_on(async {
assert!(!will_resolve(pin.wait_for_rising_edge()).await);
s.pullup(offset).unwrap();
assert!(will_resolve(pin.wait_for_rising_edge()).await);
assert!(!will_resolve(pin.wait_for_rising_edge()).await);
s.pulldown(offset).unwrap();
assert!(!will_resolve(pin.wait_for_rising_edge()).await);
s.pullup(offset).unwrap();
assert!(will_resolve(pin.wait_for_rising_edge()).await);
assert!(!will_resolve(pin.wait_for_rising_edge()).await);
})
}
#[test]
fn wait_for_falling_edge() {
let s = Simpleton::new(5);
let offset = 3;
let mut pin = InputPin::new(s.dev_path(), offset).unwrap();
block_on(async {
assert!(!will_resolve(pin.wait_for_falling_edge()).await);
s.pullup(offset).unwrap();
wait_propagation_delay();
assert!(!will_resolve(pin.wait_for_falling_edge()).await);
s.pulldown(offset).unwrap();
assert!(will_resolve(pin.wait_for_falling_edge()).await);
assert!(!will_resolve(pin.wait_for_falling_edge()).await);
s.pullup(offset).unwrap();
assert!(!will_resolve(pin.wait_for_falling_edge()).await);
})
}
#[test]
fn wait_for_any_edge() {
let s = Simpleton::new(5);
let offset = 3;
let mut pin = InputPin::new(s.dev_path(), offset).unwrap();
block_on(async {
assert!(!will_resolve(pin.wait_for_any_edge()).await);
s.pullup(offset).unwrap();
assert!(will_resolve(pin.wait_for_any_edge()).await);
s.pulldown(offset).unwrap();
assert!(will_resolve(pin.wait_for_any_edge()).await);
assert!(!will_resolve(pin.wait_for_any_edge()).await);
s.pullup(offset).unwrap();
assert!(will_resolve(pin.wait_for_any_edge()).await);
assert!(!will_resolve(pin.wait_for_any_edge()).await);
});
}
}