use core::fmt::Debug;
use core::marker::PhantomData;
use hal::digital::{ErrorType, PinState};
use hal::digital::{InputPin, OutputPin};
use hal::i2c::I2c;
use crate::ExpanderError;
use super::expander::SyncExpander;
use super::GPIOBank;
use super::Polarity;
use super::Register;
#[derive(Debug)]
pub struct ExpanderInputPin<'a, I2C, Io>
where
I2C: I2c,
Io: SyncExpander<I2C>,
{
expander: &'a Io,
bank: GPIOBank,
pin: u8,
phantom_data: PhantomData<I2C>,
}
#[derive(Debug)]
pub struct ExpanderOutputPin<'a, I2C, Io>
where
I2C: I2c,
Io: SyncExpander<I2C>,
{
expander: &'a Io,
bank: GPIOBank,
pin: u8,
phantom_data: PhantomData<I2C>,
}
impl<'a, I2C, E, Io> ExpanderInputPin<'a, I2C, Io>
where
Io: SyncExpander<I2C>,
E: Debug,
I2C: I2c<Error = E>,
{
pub fn new(expander: &'a Io, bank: GPIOBank, pin: u8) -> Result<Self, ExpanderError<E>> {
assert!(pin < 8);
let register = match bank {
GPIOBank::Bank0 => Register::ConfigurationPort0,
GPIOBank::Bank1 => Register::ConfigurationPort1,
};
let mut reg_val: u8 = 0x00;
expander.read_byte(register, &mut reg_val)?;
expander.write_byte(register, reg_val | (0x01 << pin))?;
Ok(Self {
expander,
bank,
pin,
phantom_data: PhantomData,
})
}
pub fn set_polarity(&mut self, polarity: Polarity) -> Result<(), ExpanderError<E>> {
let register = match self.bank {
GPIOBank::Bank0 => Register::PolarityInversionPort0,
GPIOBank::Bank1 => Register::PolarityInversionPort1,
};
let mut reg_val: u8 = 0x00;
self.expander.read_byte(register, &mut reg_val)?;
if let Polarity::Normal = polarity {
self.expander
.write_byte(register, reg_val & !(0x01 << self.pin))?;
} else {
self.expander
.write_byte(register, reg_val | (0x01 << self.pin))?;
}
Ok(())
}
}
impl<'a, I2C, E, Io> ExpanderOutputPin<'a, I2C, Io>
where
Io: SyncExpander<I2C>,
E: Debug,
I2C: I2c<Error = E>,
{
pub fn new(
expander: &'a Io,
bank: GPIOBank,
pin: u8,
state: PinState,
) -> Result<Self, ExpanderError<E>> {
assert!(pin < 8);
let cp_register = match bank {
GPIOBank::Bank0 => Register::ConfigurationPort0,
GPIOBank::Bank1 => Register::ConfigurationPort1,
};
let op_register = match bank {
GPIOBank::Bank0 => Register::OutputPort0,
GPIOBank::Bank1 => Register::OutputPort1,
};
let mut reg_val: u8 = 0x00;
expander.read_byte(op_register, &mut reg_val)?;
if let PinState::High = state {
expander.write_byte(op_register, reg_val | (0x01 << pin))?;
} else {
expander.write_byte(op_register, reg_val & !(0x01 << pin))?;
}
expander.read_byte(cp_register, &mut reg_val)?;
expander.write_byte(cp_register, reg_val & !(0x01 << pin))?;
Ok(Self {
expander,
bank,
pin,
phantom_data: PhantomData,
})
}
}
impl<'a, I2C, E, Io> ErrorType for ExpanderInputPin<'a, I2C, Io>
where
Io: SyncExpander<I2C>,
E: Debug,
I2C: I2c<Error = E>,
{
type Error = ExpanderError<E>;
}
impl<'a, I2C, E, Io> InputPin for ExpanderInputPin<'a, I2C, Io>
where
Io: SyncExpander<I2C>,
E: Debug,
I2C: I2c<Error = E>,
{
fn is_high(&mut self) -> Result<bool, Self::Error> {
let register = match self.bank {
GPIOBank::Bank0 => Register::InputPort0,
GPIOBank::Bank1 => Register::InputPort1,
};
let mut reg_val: u8 = 0x00;
self.expander.read_byte(register, &mut reg_val)?;
match (reg_val >> self.pin) & 1 {
1 => Ok(true),
_ => Ok(false),
}
}
fn is_low(&mut self) -> Result<bool, Self::Error> {
let register = match self.bank {
GPIOBank::Bank0 => Register::InputPort0,
GPIOBank::Bank1 => Register::InputPort1,
};
let mut reg_val: u8 = 0x00;
self.expander.read_byte(register, &mut reg_val)?;
match (reg_val >> self.pin) & 1 {
1 => Ok(false),
_ => Ok(true),
}
}
}
impl<'a, I2C, Io, E> ErrorType for ExpanderOutputPin<'a, I2C, Io>
where
Io: SyncExpander<I2C>,
E: Debug,
I2C: I2c<Error = E>,
{
type Error = ExpanderError<E>;
}
impl<'a, I2C, E, Io> OutputPin for ExpanderOutputPin<'a, I2C, Io>
where
Io: SyncExpander<I2C>,
E: Debug,
I2C: I2c<Error = E>,
{
fn set_low(&mut self) -> Result<(), Self::Error> {
let register = match self.bank {
GPIOBank::Bank0 => Register::OutputPort0,
GPIOBank::Bank1 => Register::OutputPort1,
};
let mut reg_val: u8 = 0x00;
self.expander.read_byte(register, &mut reg_val)?;
self.expander
.write_byte(register, reg_val & !(0x01 << self.pin))
}
fn set_high(&mut self) -> Result<(), Self::Error> {
let register = match self.bank {
GPIOBank::Bank0 => Register::OutputPort0,
GPIOBank::Bank1 => Register::OutputPort1,
};
let mut reg_val: u8 = 0x00;
self.expander.read_byte(register, &mut reg_val)?;
self.expander
.write_byte(register, reg_val | (0x01 << self.pin))
}
}