pcf857x_simple/lib.rs
1//! A Rust driver for the PCF857x I/O expanders, based on the [`embedded-hal`] traits.
2//!
3//! [`embedded-hal`]: https://github.com/rust-embedded/embedded-hal
4//!
5//! This driver is very simple. You can read/write all pins or individual pins.
6//! Driver use a cache to avoid read each time you want know pins status or write.
7//!
8//! ## Devices
9//!
10//! Devices consist of 8 or 16 bidirectional ports, I²C-bus interface, with three
11//! hardware address inputs and interrupt output.
12//!
13//! Datasheets:
14//! - [PCF8574x](https://www.ti.com/lit/gpn/PCF8574)
15//! - [PCF8575](https://www.ti.com/lit/gpn/PCF8575)
16//!
17//! ## How use-it (ESP32 example)?
18//!
19//! ### With the default address
20//!
21//! Import this crate and an `embedded_hal` implementation, then instantiate
22//! the device:
23//!
24//! ```no_run
25//! use esp_idf_hal::peripherals::Peripherals;
26//! use esp_idf_hal::i2c::I2cDriver;
27//! use esp_idf_hal::i2c::config::Config
28//! use pcf857x_simple::pcf8574::Pcf8574;
29//! use pcf857x_simple::PCF857X_DEFAULT_ADDRESS;
30//!
31//! esp_idf_sys::link_patches();
32//! esp_idf_svc::log::EspLogger::initialize_default();
33//!
34//! let peripherals = Peripherals::take().unwrap();
35//!
36//! let scl = peripherals.pins.gpio22;
37//! let sda = peripherals.pins.gpio21;
38//!
39//! let i2c_config = Config::new()
40//! .baudrate(KiloHertz(100).into())
41//! .scl_enable_pullup(true)
42//! .sda_enable_pullup(true);
43//!
44//! let i2c_driver = I2cDriver::new(peripherals.i2c0, sda, scl, &i2c_config).unwrap();
45//!
46//! let mut expander = Pcf8574::new(i2c_driver, PCF857X_DEFAULT_ADDRESS);
47//! ```
48//!
49//! ### With helper address
50//!
51//! ```no_run
52//! use esp_idf_hal::peripherals::Peripherals;
53//! use esp_idf_hal::i2c::I2cDriver;
54//! use esp_idf_hal::i2c::config::Config
55//! use pcf857x_simple::pcf8574::Pcf8574;
56//! use pcf857x_simple::pcf857x_address;
57//!
58//! esp_idf_sys::link_patches();
59//! esp_idf_svc::log::EspLogger::initialize_default();
60//!
61//! let peripherals = Peripherals::take().unwrap();
62//!
63//! let scl = peripherals.pins.gpio22;
64//! let sda = peripherals.pins.gpio21;
65//!
66//! let i2c_config = Config::new()
67//! .baudrate(KiloHertz(100).into())
68//! .scl_enable_pullup(true)
69//! .sda_enable_pullup(true);
70//!
71//! let i2c_driver = I2cDriver::new(peripherals.i2c0, sda, scl, &i2c_config).unwrap();
72//!
73//! let mut expander = Pcf8574::new(i2c_driver, pcf857x_address(false, false, false));
74//! ```
75//!
76//! ### With direct address
77//!
78//! ```no_run
79//! use esp_idf_hal::peripherals::Peripherals;
80//! use esp_idf_hal::i2c::I2cDriver;
81//! use esp_idf_hal::i2c::config::Config
82//! use pcf857x_simple::pcf8574::Pcf8574;
83//! use pcf857x_simple::pcf857x_address;
84//!
85//! esp_idf_sys::link_patches();
86//! esp_idf_svc::log::EspLogger::initialize_default();
87//!
88//! let peripherals = Peripherals::take().unwrap();
89//!
90//! let scl = peripherals.pins.gpio22;
91//! let sda = peripherals.pins.gpio21;
92//!
93//! let i2c_config = Config::new()
94//! .baudrate(KiloHertz(100).into())
95//! .scl_enable_pullup(true)
96//! .sda_enable_pullup(true);
97//!
98//! let i2c_driver = I2cDriver::new(peripherals.i2c0, sda, scl, &i2c_config).unwrap();
99//!
100//! let mut expander = Pcf8574::new(i2c_driver, 0x24);
101//! ```
102//!
103//! ### Set P0 and P7 high
104//!
105//! ```no_run
106//! use pcf857x_simple::Pin;
107//! ...
108//! let _ = expander.clear();
109//! let _ = expander.up_pins(&[Pin::P0, Pin::P7]);
110//! ```
111//!
112//! ### Read P0 and P7 high direct from device
113//!
114//! ```no_run
115//! use pcf857x_simple::Pin;
116//! ...
117//! let _ = expander.clear();
118//! let _ = expander.read_pin(Pin::P0);
119//! let _ = expander.read_pin(Pin::P7);
120//! ```
121//!
122//! ### Read P0 and P7 high direct from cache
123//!
124//! ```no_run
125//! use pcf857x_simple::Pin;
126//! ...
127//! let _ = expander.clear();
128//! let _ = expander.get_pin_from_cache(Pin::P0);
129//! let _ = expander.get_pin_from_cache(Pin::P7);
130//! ```
131#![no_std]
132
133pub mod pcf8574;
134pub mod pcf8575;
135
136/// Pin of Pcf857x
137#[derive(Copy, Clone, Debug)]
138pub enum Pin {
139 /// Pin 0
140 P0 = 1,
141 /// Pin 1
142 P1 = 2,
143 /// Pin 2
144 P2 = 4,
145 /// Pin 3
146 P3 = 8,
147 /// Pin 4
148 P4 = 16,
149 /// Pin 5
150 P5 = 32,
151 /// Pin 6
152 P6 = 64,
153 /// Pin 7
154 P7 = 128,
155 /// Pin 10 (only PCF8575)
156 P10 = 256,
157 /// Pin 11 (only PCF8575)
158 P11 = 512,
159 /// Pin 12 (only PCF8575)
160 P12 = 1024,
161 /// Pin 13 (only PCF8575)
162 P13 = 2048,
163 /// Pin 14 (only PCF8575)
164 P14 = 4096,
165 /// Pin 15 (only PCF8575)
166 P15 = 8192,
167 /// Pin 16 (only PCF8575)
168 P16 = 16384,
169 /// Pin 17 (only PCF8575)
170 P17 = 32768,
171}
172
173/// Pin state of Pcf857x
174#[derive(Copy, Clone, Debug)]
175pub enum PinState {
176 Up(Pin),
177 Down(Pin),
178}
179
180/// Defaut base address of device
181pub const PCF857X_DEFAULT_ADDRESS: u8 = 0x20;
182
183/// Helper to set address depending of address' pin's device
184pub fn pcf857x_address(a0: bool, a1: bool, a2: bool) -> u8 {
185 let mut addr: u8 = PCF857X_DEFAULT_ADDRESS;
186
187 if a0 {
188 addr += 1;
189 }
190
191 if a1 {
192 addr += 2;
193 }
194
195 if a2 {
196 addr += 4;
197 }
198
199 addr
200}