1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
//! APIs for interacting with I/O pins on the MAX7301 through an `embedded-hal` API. #[cfg(feature = "unproven")] use hal::digital::InputPin; use hal::digital::OutputPin; /// An indirection between I/O pin abstractions and the expander itself, which allows selection /// between transactional reads and writes, which reduce bus traffic and latency, and /// immediate-mode reads and writes, which add more bus traffic and latency but are simpler to use. pub trait ExpanderIO { /// Write the value of an I/O port. `port` is a port number between 4 and 31; `bit` is the /// value to set the port to. If the pin is configured as an output, the value (`true` is /// logic high, `false` logic low) will be asserted on the corresponding pin. fn write_port(&self, port: u8, bit: bool); /// Read the value of an I/O port. `port` is a port number between 4 and 31, the value of that /// pin will be returned (`false` if logic low, `true` if logic high). If the pin is configured /// as an output, the last set value will be read; if it is configured as an input, the /// logic level of the externally applied signal will be read. fn read_port(&self, port: u8) -> bool; } /// A single I/O pin on the MAX7301. These implement the `embedded-hal` traits for GPIO pins, so /// they can be used to transparently connect devices driven over GPIOs through the MAX7301 /// instead, using their `embedded-hal`-compatible drivers without modification. pub struct PortPin<'io, IO: ExpanderIO> { io: &'io IO, port: u8, } impl<'io, IO: ExpanderIO> PortPin<'io, IO> { pub(crate) fn new(io: &'io IO, port: u8) -> Self { Self { io, port } } } impl<'io, IO: ExpanderIO> OutputPin for PortPin<'io, IO> { fn set_high(&mut self) { self.io.write_port(self.port, true) } fn set_low(&mut self) { self.io.write_port(self.port, false) } } #[cfg(feature = "unproven")] impl<'io, IO: ExpanderIO> InputPin for PortPin<'io, IO> { fn is_high(&self) -> bool { self.io.read_port(self.port) } fn is_low(&self) -> bool { !self.io.read_port(self.port) } }