use std::{cell::RefCell, rc::Rc};
use embedded_hal::digital::{
OutputPin,
PinState::{High, Low},
};
use crate::{Error, ErrorKind::WrongPinType, PinId, PinScanner};
impl embedded_hal::digital::Error for Error {
fn kind(&self) -> embedded_hal::digital::ErrorKind {
embedded_hal::digital::ErrorKind::Other
}
}
pub struct In {
scanner: Rc<RefCell<PinScanner>>,
pin_id: PinId,
}
impl In {
pub fn new(scanner: &Rc<RefCell<PinScanner>>, pin_id: PinId) -> Result<Self, Error> {
if !pin_id.is_input() {
return Error::result(WrongPinType, "not input pin");
}
Ok(Self {
scanner: scanner.clone(),
pin_id,
})
}
}
impl embedded_hal::digital::ErrorType for In {
type Error = Error;
}
impl embedded_hal::digital::InputPin for In {
fn is_high(&mut self) -> Result<bool, Self::Error> {
let mut scanner = self.scanner.try_borrow_mut()?;
scanner.update()?;
scanner
.get_pin_state(&self.pin_id)
.map(|st| st.input.unwrap())
}
fn is_low(&mut self) -> Result<bool, Self::Error> {
self.is_high().map(|v| !v)
}
}
pub struct Out {
scanner: Rc<RefCell<PinScanner>>,
pin_id: PinId,
}
impl Out {
pub fn new(scanner: &Rc<RefCell<PinScanner>>, pin_id: PinId) -> Result<Self, Error> {
if !pin_id.is_output() {
return Error::result(WrongPinType, "not output pin");
}
Ok(Self {
scanner: scanner.clone(),
pin_id,
})
}
}
impl embedded_hal::digital::ErrorType for Out {
type Error = Error;
}
impl embedded_hal::digital::OutputPin for Out {
fn set_high(&mut self) -> Result<(), Self::Error> {
self.set_state(High)
}
fn set_low(&mut self) -> Result<(), Self::Error> {
self.set_state(Low)
}
fn set_state(&mut self, state: embedded_hal::digital::PinState) -> Result<(), Self::Error> {
let mut scanner = self.scanner.try_borrow_mut()?;
scanner.set_pin_state(&self.pin_id, Some(state == High))?;
scanner.write_update()
}
}
pub struct InOut {
scanner: Rc<RefCell<PinScanner>>,
pin_id: PinId,
output_enable: bool,
output_value: Option<bool>,
}
impl InOut {
pub fn new(
scanner: &Rc<RefCell<PinScanner>>,
pin_id: PinId,
init_val: Option<bool>,
) -> Result<Self, Error> {
if !pin_id.is_input() || !pin_id.is_output() {
return Error::result(WrongPinType, "not input + output pin");
}
let mut sc = scanner.try_borrow_mut()?;
sc.set_pin_state(&pin_id, init_val)?;
sc.write_update()?;
Ok(Self {
scanner: scanner.clone(),
pin_id,
output_enable: init_val.is_some(),
output_value: init_val,
})
}
pub fn set_output_enable(&mut self, enable: bool) -> Result<(), Error> {
if enable == self.output_enable {
return Ok(());
}
if !self.pin_id.is_tristates() {
if !enable {
return Error::result(WrongPinType, "not tristated pin");
}
return Ok(());
}
if enable {
self.output_enable = true;
if let Some(&last_output) = self.output_value.as_ref() {
self.set_state(if last_output { High } else { Low })?;
}
} else {
let mut sc = self.scanner.try_borrow_mut()?;
sc.set_pin_state(&self.pin_id, None)?;
sc.write_update()?;
self.output_enable = false;
}
Ok(())
}
}
impl embedded_hal::digital::ErrorType for InOut {
type Error = Error;
}
impl embedded_hal::digital::InputPin for InOut {
fn is_high(&mut self) -> Result<bool, Self::Error> {
let mut scanner = self.scanner.try_borrow_mut()?;
scanner.update()?;
scanner
.get_pin_state(&self.pin_id)
.map(|st| st.input.unwrap())
}
fn is_low(&mut self) -> Result<bool, Self::Error> {
self.is_high().map(|v| !v)
}
}
impl embedded_hal::digital::OutputPin for InOut {
fn set_high(&mut self) -> Result<(), Self::Error> {
self.set_state(High)
}
fn set_low(&mut self) -> Result<(), Self::Error> {
self.set_state(Low)
}
fn set_state(&mut self, state: embedded_hal::digital::PinState) -> Result<(), Self::Error> {
self.output_value = Some(state == High);
if self.output_enable {
let mut scanner = self.scanner.try_borrow_mut()?;
scanner.set_pin_state(&self.pin_id, self.output_value)?;
scanner.write_update()?;
}
Ok(())
}
}