port_expander/
lib.rs

1//! This is a crate providing a common abstraction for I²C port-expanders.  This abstraction is not
2//! necessarily the most performant, but it allows using the pins just like direct GPIOs.  Because
3//! the pin types also implement the `embedded-hal` digital IO traits, they can also be passed to
4//! further drivers downstream (e.g.  as a reset or chip-select pin).
5//!
6//! ## Example
7//! ```no_run
8//! // Initialize I2C peripheral from HAL
9//! let i2c = todo!();
10//! # let i2c = embedded_hal_mock::eh1::i2c::Mock::new(&[]);
11//!
12//! // A0: HIGH, A1: LOW, A2: LOW
13//! let mut pca9555 = port_expander::Pca9555::new(i2c, true, false, false);
14//! let pca_pins = pca9555.split();
15//!
16//! let io0_0 = pca_pins.io0_0.into_output().unwrap();
17//! let io1_5 = pca_pins.io0_1; // default is input
18//!
19//! io0_0.set_high().unwrap();
20//! assert!(io1_5.is_high().unwrap());
21//! ```
22//!
23//! ## Accessing multiple pins at the same time
24//! Sometimes timing constraints mandate that multiple pin accesses (reading or writing) happen at
25//! the same time.  The [`write_multiple()`] and [`read_multiple()`] methods are designed for doing
26//! this.
27//!
28//! ## Supported Devices
29//! The following list is what `port-expander` currently supports.  If you needs support for an
30//! additional device, it should be easy to add.  It's best to take a similar existing
31//! implementation as inspiration.  Contributions welcome!
32//!
33//! - [`MAX7321`](Max7321)
34//! - [`PCA9536`](Pca9536)
35//! - [`PCA9538`](Pca9538)
36//! - [`PCA9555`](Pca9555)
37//! - [`PCA9702`](Pca9702)
38//! - [`PCF8574A`](Pcf8574a)
39//! - [`PCF8574`](Pcf8574)
40//! - [`PCF8575`](Pcf8575)
41//! - [`TCA6408A`](Tca6408a)
42//! - [`MCP23x17`](Mcp23x17)
43//!
44//! ## Non-local sharing
45//! `port-expander` uses a custom trait for abstracting different kinds of mutexes:
46//! [`PortMutex`]. This means you can also make the pins shareable across task/thread boundaries,
47//! given that you provide an appropriate mutex type:
48//!
49//! ```ignore
50//! // Initialize I2C peripheral from HAL
51//! let i2c = todo!();
52//! # let i2c = embedded_hal_mock::i2c::Mock::new(&[]);
53//!
54//! // A0: HIGH, A1: LOW, A2: LOW
55//! let mut pca9555: port_expander::Pca9555<std::sync::Mutex<_>> =
56//!     port_expander::Pca9555::with_mutex(i2c, true, false, false);
57//! let pca_pins = pca9555.split();
58//! ```
59
60#![cfg_attr(not(any(test, feature = "std")), no_std)]
61
62mod bus;
63mod common;
64pub mod dev;
65mod multi;
66mod mutex;
67mod pin;
68
69pub use bus::I2cBus;
70pub use common::mode;
71pub use multi::read_multiple;
72pub use multi::write_multiple;
73pub use mutex::PortMutex;
74pub use pin::Pin;
75pub use pin::PinError;
76
77pub(crate) use bus::I2cExt;
78pub(crate) use bus::SpiBus;
79pub(crate) use common::Direction;
80pub(crate) use common::PortDriver;
81pub(crate) use common::PortDriverPolarity;
82pub(crate) use common::PortDriverPullDown;
83pub(crate) use common::PortDriverPullUp;
84pub(crate) use common::PortDriverTotemPole;
85
86pub use dev::max7321::Max7321;
87pub use dev::mcp23x17::Mcp23x17;
88pub use dev::pca9536::Pca9536;
89pub use dev::pca9538::Pca9538;
90pub use dev::pca9555::Pca9555;
91pub use dev::pca9702::Pca9702;
92pub use dev::pcal6408a::Pcal6408a;
93pub use dev::pcal6416a::Pcal6416a;
94pub use dev::pcf8574::Pcf8574;
95pub use dev::pcf8574::Pcf8574a;
96pub use dev::pcf8575::Pcf8575;
97pub use dev::tca6408a::Tca6408a;