1use crate::expander::{Bank, Mode, PinID, RefreshInputError};
2use crate::guard::RefGuard;
3use crate::pins::{Input, Output, Pin, PinMode, RefreshMode};
4use core::convert::Infallible;
5use core::marker::PhantomData;
6use embedded_hal::digital::{ErrorType, InputPin, OutputPin, PinState, StatefulOutputPin};
7use embedded_hal::i2c::{I2c, SevenBitAddress};
8
9pub trait RefreshableOutputPin {
11 type Error;
12
13 fn update_bank(&self) -> Result<(), Self::Error>;
15
16 fn update_all(&self) -> Result<(), Self::Error>;
18}
19
20pub trait RefreshableInputPin {
22 type Error;
23
24 fn refresh_bank(&self) -> Result<(), Self::Error>;
26
27 fn refresh_all(&self) -> Result<(), Self::Error>;
29}
30
31impl<'a, B, R> Pin<'a, B, R, Input, RefreshMode>
32where
33 B: I2c<SevenBitAddress>,
34 R: RefGuard<B>,
35{
36 pub fn refreshable(expander: &'a R, bank: Bank, id: PinID) -> Self {
37 Self {
38 expander,
39 bus: PhantomData,
40 bank,
41 id,
42 access_mode: PhantomData,
43 mode: PhantomData,
44 }
45 }
46
47 fn refresh(&self, bank: Bank) -> Result<(), RefreshInputError<B>> {
49 let mut result = Ok(());
50
51 self.expander.access(|expander| {
52 result = expander.refresh_input_state(bank);
53 });
54
55 result
56 }
57}
58
59impl<B, R> RefreshableInputPin for Pin<'_, B, R, Input, RefreshMode>
60where
61 B: I2c<SevenBitAddress>,
62 R: RefGuard<B>,
63{
64 type Error = RefreshInputError<B>;
65
66 fn refresh_bank(&self) -> Result<(), Self::Error> {
68 self.refresh(self.bank)
69 }
70
71 fn refresh_all(&self) -> Result<(), Self::Error> {
73 self.refresh(Bank::Bank0)?;
74 self.refresh(Bank::Bank1)
75 }
76}
77
78impl<B, R> RefreshableOutputPin for Pin<'_, B, R, Output, RefreshMode>
79where
80 B: I2c<SevenBitAddress>,
81 R: RefGuard<B>,
82{
83 type Error = B::Error;
84
85 fn update_bank(&self) -> Result<(), Self::Error> {
87 self.update(self.bank)
88 }
89
90 fn update_all(&self) -> Result<(), Self::Error> {
92 self.update(Bank::Bank0)?;
93 self.update(Bank::Bank1)
94 }
95}
96
97impl<B, R> Pin<'_, B, R, Output, RefreshMode>
98where
99 B: I2c<SevenBitAddress>,
100 R: RefGuard<B>,
101{
102 fn update(&self, bank: Bank) -> Result<(), B::Error> {
104 let mut result = Ok(());
105
106 self.expander.access(|expander| {
107 result = expander.write_output_state(bank);
108 });
109
110 result
111 }
112}
113
114impl<B, R> ErrorType for Pin<'_, B, R, Input, RefreshMode>
115where
116 B: I2c<SevenBitAddress>,
117 R: RefGuard<B>,
118{
119 type Error = Infallible;
120}
121
122impl<B, R> InputPin for Pin<'_, B, R, Input, RefreshMode>
123where
124 B: I2c<SevenBitAddress>,
125 R: RefGuard<B>,
126{
127 fn is_high(&mut self) -> Result<bool, Self::Error> {
128 let mut state = false;
129
130 self.expander.access(|expander| {
131 state = expander.is_pin_input_high(self.bank, self.id);
132 });
133
134 Ok(state)
135 }
136
137 fn is_low(&mut self) -> Result<bool, Self::Error> {
138 Ok(!self.is_high()?)
139 }
140}
141
142impl<B, R> ErrorType for Pin<'_, B, R, Output, RefreshMode>
143where
144 B: I2c<SevenBitAddress>,
145 R: RefGuard<B>,
146{
147 type Error = Infallible;
148}
149
150impl<B, R> OutputPin for Pin<'_, B, R, Output, RefreshMode>
151where
152 B: I2c<SevenBitAddress>,
153 R: RefGuard<B>,
154{
155 fn set_low(&mut self) -> Result<(), Self::Error> {
156 self.set_state(PinState::Low)
157 }
158
159 fn set_high(&mut self) -> Result<(), Self::Error> {
160 self.set_state(PinState::High)
161 }
162
163 fn set_state(&mut self, state: PinState) -> Result<(), Self::Error> {
164 self.expander.access(|expander| {
165 expander.set_state(self.bank, self.id, state == PinState::High);
166 });
167
168 Ok(())
169 }
170}
171
172impl<B, R> StatefulOutputPin for Pin<'_, B, R, Output, RefreshMode>
173where
174 B: I2c<SevenBitAddress>,
175 R: RefGuard<B>,
176{
177 fn is_set_high(&mut self) -> Result<bool, Self::Error> {
178 Ok(self.is_pin_output_high())
179 }
180
181 fn is_set_low(&mut self) -> Result<bool, Self::Error> {
182 Ok(!self.is_pin_output_high())
183 }
184}
185
186impl<'a, B, M, R> Pin<'a, B, R, M, RefreshMode>
187where
188 B: I2c<SevenBitAddress>,
189 R: RefGuard<B>,
190 M: PinMode,
191{
192 pub fn into_input_pin(self) -> Result<Pin<'a, B, R, Input, RefreshMode>, B::Error> {
193 self.change_mode(Mode::Input)?;
194
195 Ok(Pin {
196 expander: self.expander,
197 bank: self.bank,
198 id: self.id,
199 bus: PhantomData,
200 mode: PhantomData,
201 access_mode: PhantomData,
202 })
203 }
204
205 pub fn into_output_pin(self, state: PinState) -> Result<Pin<'a, B, R, Output, RefreshMode>, B::Error> {
206 self.change_mode(Mode::Output)?;
207
208 let mut pin = Pin {
209 expander: self.expander,
210 bank: self.bank,
211 id: self.id,
212 bus: PhantomData,
213 mode: PhantomData,
214 access_mode: PhantomData,
215 };
216
217 let _ = pin.set_state(state);
218 pin.update_bank()?;
219 Ok(pin)
220 }
221}