stmpe1600/
pins.rs

1use crate::{Error, PinMode, Polarity, Register, Stmpe1600};
2use core::marker::PhantomData;
3use embedded_hal::blocking::i2c::{Read, Write};
4use embedded_hal::digital::v2::{InputPin, OutputPin};
5
6pub mod modes {
7	pub struct Input;
8	pub struct Output;
9	pub struct Interrupt;
10}
11use modes::*;
12
13/// A single I/O pin on the STMPE1600.
14///
15/// `Pin` takes a `MODE` as a generic argument, which is either `Input`, `Output` or `Interrupt`,
16/// and indicates which mode of operation the current pin is configured for. This mode can be
17/// changed by using the `into_input_pin`, `into_output_pin` and `into_interrupt_pin` functions
18/// respectively.
19///
20/// Input and interrupt pins implement the trait [`embedded_hal::digital::v2::InputPin`], and output
21/// pins implement [`embedded_hal::digital::v2::OutputPin`]. This means that the pins on the I/O
22/// expander can be used by platform agnostic drivers as if they were regular GPIO pins.
23///
24/// # Examples
25///
26/// ## Changing pin mode
27/// ```rust,ignore
28/// use embedded_hal::digital::v2::{InputPin, OutputPin};
29/// use linux_embedded_hal::I2cdev;
30/// use stmpe1600::Stmpe1600Builder;
31///
32/// # fn main() -> Result<(), stmpe1600::Error<linux_embedded_hal::i2cdev::linux::LinuxI2CError>> {
33/// let dev = I2cdev::new("/dev/i2c-1").unwrap();
34/// let stmpe1600 = Stmpe1600Builder::new(dev)
35/// 	.build()
36/// 	.expect("Could not initialise STMPE1600 driver");
37///
38/// let mut input_pin = stmpe1600.pin_input(0)?;
39/// let _ = input_pin.is_high()?;
40/// let mut output_pin = input_pin.into_output_pin()?;
41/// output_pin.set_high()?;
42/// # Ok(())
43/// # }
44/// ```
45///
46/// ## Setting interrupt polarity
47/// ```rust,ignore
48/// use linux_embedded_hal::I2cdev;
49/// use stmpe1600::{Polarity, Stmpe1600Builder};
50///
51/// # fn main() -> Result<(), stmpe1600::Error<linux_embedded_hal::i2cdev::linux::LinuxI2CError>> {
52/// let dev = I2cdev::new("/dev/i2c-1").unwrap();
53/// let stmpe1600 = Stmpe1600Builder::new(dev)
54/// 	.build()
55/// 	.expect("Could not initialise STMPE1600 driver");
56///
57/// let mut input_pin = stmpe1600.pin_input(0)?;
58/// input_pin.set_interrupt_polarity(Polarity::High)?;
59/// # Ok(())
60/// # }
61/// ```
62pub struct Pin<'a, I2C, MODE> {
63	driver: &'a Stmpe1600<I2C>,
64	pin: u8,
65	_phantom: PhantomData<MODE>,
66}
67
68impl<'a, E, I2C, MODE> Pin<'a, I2C, MODE>
69where
70	I2C: Read<Error = E> + Write<Error = E>,
71{
72	pub(crate) fn new(driver: &'a Stmpe1600<I2C>, pin: u8) -> Pin<'a, I2C, MODE> {
73		Pin {
74			driver,
75			pin,
76			_phantom: PhantomData,
77		}
78	}
79
80	/// Get the polarity inversion of the current pin.
81	pub fn polarity_inversion(&mut self) -> Result<Polarity, Error<E>> {
82		let mut dev = self.driver.device.borrow_mut();
83		let gppir = dev.read_reg(Register::GPPIR)?;
84		if gppir & (1 << self.pin) == (1 << self.pin) {
85			Ok(Polarity::High)
86		} else {
87			Ok(Polarity::Low)
88		}
89	}
90
91	/// Set the polarity inversion of the current pin.
92	pub fn set_polarity_inversion(&mut self, polarity: Polarity) -> Result<(), Error<E>> {
93		let mut dev = self.driver.device.borrow_mut();
94		let mut gppir = dev.read_reg(Register::GPPIR)?;
95		match polarity {
96			Polarity::Low => gppir &= !(1 << self.pin),
97			Polarity::High => gppir |= 1 << self.pin,
98		}
99		dev.write_reg(Register::GPPIR, gppir)?;
100		Ok(())
101	}
102}
103
104impl<'a, E, I2C> Pin<'a, I2C, Input>
105where
106	I2C: Read<Error = E> + Write<Error = E>,
107{
108	/// Configure the pin as an output pin.
109	pub fn into_output_pin(self) -> Result<Pin<'a, I2C, Output>, Error<E>> {
110		let mut dev = self.driver.device.borrow_mut();
111		let mut gpdr = dev.read_reg(Register::GPDR)?;
112		gpdr |= 1 << self.pin;
113		dev.write_reg(Register::GPDR, gpdr)?;
114
115		self.driver.pins.borrow_mut()[self.pin as usize] = PinMode::Output;
116		Ok(Pin::new(self.driver, self.pin))
117	}
118
119	/// Configure the pin as an interrupt pin.
120	pub fn into_interrupt_pin(self) -> Result<Pin<'a, I2C, Interrupt>, Error<E>> {
121		let mut dev = self.driver.device.borrow_mut();
122		let mut iegpior = dev.read_reg(Register::IEGPIOR)?;
123		iegpior |= 1 << self.pin;
124		dev.write_reg(Register::IEGPIOR, iegpior)?;
125
126		self.driver.pins.borrow_mut()[self.pin as usize] = PinMode::Interrupt;
127		Ok(Pin::new(self.driver, self.pin))
128	}
129}
130
131impl<'a, E, I2C> InputPin for Pin<'a, I2C, Input>
132where
133	I2C: Read<Error = E> + Write<Error = E>,
134{
135	type Error = Error<E>;
136
137	fn is_low(&self) -> Result<bool, Self::Error> {
138		let mask = self.driver.device.borrow_mut().read_reg(Register::GPMR)?;
139		Ok(mask & (1 << self.pin) == 0)
140	}
141
142	fn is_high(&self) -> Result<bool, Self::Error> {
143		let mask = self.driver.device.borrow_mut().read_reg(Register::GPMR)?;
144		Ok(mask & (1 << self.pin) == 1 << self.pin)
145	}
146}
147
148impl<'a, E, I2C> Pin<'a, I2C, Output>
149where
150	I2C: Read<Error = E> + Write<Error = E>,
151{
152	/// Configure the pin as an input pin.
153	pub fn into_input_pin(self) -> Result<Pin<'a, I2C, Input>, Error<E>> {
154		let mut dev = self.driver.device.borrow_mut();
155		let mut gpdr = dev.read_reg(Register::GPDR)?;
156		gpdr &= !(1 << self.pin);
157		dev.write_reg(Register::GPDR, gpdr)?;
158
159		self.driver.pins.borrow_mut()[self.pin as usize] = PinMode::Input;
160		Ok(Pin::new(self.driver, self.pin))
161	}
162
163	/// Configure the pin as an interrupt pin.
164	pub fn into_interrupt_pin(self) -> Result<Pin<'a, I2C, Interrupt>, Error<E>> {
165		let mut dev = self.driver.device.borrow_mut();
166		let mut gpdr = dev.read_reg(Register::GPDR)?;
167		gpdr &= !(1 << self.pin);
168		dev.write_reg(Register::GPDR, gpdr)?;
169		let mut iegpior = dev.read_reg(Register::IEGPIOR)?;
170		iegpior |= 1 << self.pin;
171		dev.write_reg(Register::IEGPIOR, iegpior)?;
172
173		self.driver.pins.borrow_mut()[self.pin as usize] = PinMode::Interrupt;
174		Ok(Pin::new(self.driver, self.pin))
175	}
176}
177
178impl<'a, E, I2C> OutputPin for Pin<'a, I2C, Output>
179where
180	I2C: Read<Error = E> + Write<Error = E>,
181{
182	type Error = Error<E>;
183
184	fn set_low(&mut self) -> Result<(), Self::Error> {
185		let mask = self.driver.device.borrow_mut().read_reg(Register::GPSR)?;
186		self.driver
187			.device
188			.borrow_mut()
189			.write_reg(Register::GPSR, mask & !(1 << self.pin))
190	}
191
192	fn set_high(&mut self) -> Result<(), Self::Error> {
193		let mask = self.driver.device.borrow_mut().read_reg(Register::GPSR)?;
194		self.driver
195			.device
196			.borrow_mut()
197			.write_reg(Register::GPSR, mask | (1 << self.pin))
198	}
199}
200
201impl<'a, E, I2C> Pin<'a, I2C, Interrupt>
202where
203	I2C: Read<Error = E> + Write<Error = E>,
204{
205	/// Configure the pin as an input pin.
206	pub fn into_input_pin(self) -> Result<Pin<'a, I2C, Input>, Error<E>> {
207		let mut dev = self.driver.device.borrow_mut();
208		let mut iegpior = dev.read_reg(Register::IEGPIOR)?;
209		iegpior &= !(1 << self.pin);
210		dev.write_reg(Register::IEGPIOR, iegpior)?;
211
212		self.driver.pins.borrow_mut()[self.pin as usize] = PinMode::Input;
213		Ok(Pin::new(self.driver, self.pin))
214	}
215
216	/// Configure the pin as an output pin.
217	pub fn into_output_pin(self) -> Result<Pin<'a, I2C, Output>, Error<E>> {
218		let mut dev = self.driver.device.borrow_mut();
219		let mut gpdr = dev.read_reg(Register::GPDR)?;
220		gpdr |= 1 << self.pin;
221		dev.write_reg(Register::GPDR, gpdr)?;
222		let mut iegpior = dev.read_reg(Register::IEGPIOR)?;
223		iegpior &= !(1 << self.pin);
224		dev.write_reg(Register::IEGPIOR, iegpior)?;
225
226		self.driver.pins.borrow_mut()[self.pin as usize] = PinMode::Output;
227		Ok(Pin::new(self.driver, self.pin))
228	}
229}
230
231impl<'a, E, I2C> InputPin for Pin<'a, I2C, Interrupt>
232where
233	I2C: Read<Error = E> + Write<Error = E>,
234{
235	type Error = Error<E>;
236
237	fn is_low(&self) -> Result<bool, Self::Error> {
238		let mask = self.driver.device.borrow_mut().read_reg(Register::GPMR)?;
239		Ok(mask & (1 << self.pin) == 0)
240	}
241
242	fn is_high(&self) -> Result<bool, Self::Error> {
243		let mask = self.driver.device.borrow_mut().read_reg(Register::GPMR)?;
244		Ok(mask & (1 << self.pin) == 1 << self.pin)
245	}
246}