1use crate::{iomuxc, ral};
39
40pub struct Port<const N: u8> {
42 gpio: ral::gpio::Instance<N>,
43}
44
45impl<const N: u8> Port<N> {
46 pub fn new(gpio: ral::gpio::Instance<N>) -> Self {
48 Self { gpio }
49 }
50
51 fn register_block(&self) -> &'static ral::gpio::RegisterBlock {
52 let register_block: &ral::gpio::RegisterBlock = &self.gpio;
53 let register_block: &'static ral::gpio::RegisterBlock =
58 unsafe { core::mem::transmute(register_block) };
59 register_block
60 }
61
62 pub fn output<P>(&mut self, mut pin: P) -> Output<P>
64 where
65 P: iomuxc::gpio::Pin<N>,
66 {
67 iomuxc::gpio::prepare(&mut pin);
68 Output::new(pin, self.register_block(), P::OFFSET)
69 }
70
71 pub fn input<P>(&mut self, mut pin: P) -> Input<P>
73 where
74 P: iomuxc::gpio::Pin<N>,
75 {
76 iomuxc::gpio::prepare(&mut pin);
77 Input::new(pin, self.register_block(), P::OFFSET)
78 }
79
80 pub fn set_interrupt<P>(&mut self, pin: &Input<P>, trigger: Option<Trigger>) {
85 self.set_interrupt_enable(pin, false);
86 if let Some(trigger) = trigger {
87 self.set_interrupt_trigger(pin, trigger);
88 self.set_interrupt_enable(pin, true);
89 }
90 }
91
92 fn set_interrupt_trigger<P>(&mut self, pin: &Input<P>, trigger: Trigger) {
94 if Trigger::EitherEdge == trigger {
95 ral::modify_reg!(ral::gpio, self.gpio, EDGE_SEL, |edge_sel| {
96 edge_sel | pin.mask()
97 });
98 } else {
99 ral::modify_reg!(ral::gpio, self.gpio, EDGE_SEL, |edge_sel| {
100 edge_sel & !pin.mask()
101 });
102 let icr = trigger as u32;
103 let icr_modify = |reg| reg & !(0b11 << pin.icr_offset()) | (icr << pin.icr_offset());
104 if pin.offset < 16 {
105 ral::modify_reg!(ral::gpio, self.gpio, ICR1, icr_modify);
106 } else {
107 ral::modify_reg!(ral::gpio, self.gpio, ICR2, icr_modify);
108 }
109 }
110 }
111
112 fn set_interrupt_enable<P>(&mut self, pin: &Input<P>, enable: bool) {
114 if enable {
115 ral::modify_reg!(ral::gpio, self.gpio, IMR, |imr| imr | pin.mask());
116 } else {
117 ral::modify_reg!(ral::gpio, self.gpio, IMR, |imr| imr & !pin.mask());
118 }
119 }
120}
121
122pub struct Output<P> {
124 pin: P,
125 gpio: &'static ral::gpio::RegisterBlock,
130 offset: u32,
131}
132
133unsafe impl<P: Send> Send for Output<P> {}
136
137impl<P> Output<P> {
138 fn new(pin: P, gpio: &'static ral::gpio::RegisterBlock, offset: u32) -> Self {
139 let output = Self { pin, gpio, offset };
140 ral::modify_reg!(ral::gpio, gpio, GDIR, |gdir| gdir | output.mask());
141 output
142 }
143
144 const fn mask(&self) -> u32 {
145 1 << self.offset
146 }
147
148 pub fn set(&self) {
150 ral::write_reg!(ral::gpio, self.gpio, DR_SET, self.mask());
152 }
153
154 pub fn clear(&self) {
156 ral::write_reg!(ral::gpio, self.gpio, DR_CLEAR, self.mask());
158 }
159
160 pub fn toggle(&self) {
165 ral::write_reg!(ral::gpio, self.gpio, DR_TOGGLE, self.mask());
167 }
168
169 pub fn is_set(&self) -> bool {
171 ral::read_reg!(ral::gpio, self.gpio, DR) & self.mask() != 0
172 }
173
174 pub fn is_pad_high(&self) -> bool {
178 ral::read_reg!(ral::gpio, self.gpio, PSR) & self.mask() != 0
179 }
180
181 pub fn release(self) -> P {
183 self.pin
184 }
185
186 pub fn pin(&self) -> &P {
188 &self.pin
189 }
190
191 pub fn pin_mut(&mut self) -> &mut P {
193 &mut self.pin
194 }
195}
196
197impl Output<()> {
198 pub fn without_pin<const N: u8>(port: &mut Port<N>, offset: u32) -> Self {
211 Self::new((), port.register_block(), offset)
212 }
213}
214
215pub struct Input<P> {
217 pin: P,
218 gpio: &'static ral::gpio::RegisterBlock,
222 offset: u32,
223}
224
225unsafe impl<P: Send> Send for Input<P> {}
227
228#[derive(Debug, Clone, Copy, PartialEq, Eq)]
230#[repr(u32)]
231pub enum Trigger {
232 Low = 0,
234 High = 1,
236 RisingEdge = 2,
238 FallingEdge = 3,
240 EitherEdge = 4,
242}
243
244impl<P> Input<P> {
245 fn new(pin: P, gpio: &'static ral::gpio::RegisterBlock, offset: u32) -> Self {
246 let input = Self { pin, gpio, offset };
247 ral::modify_reg!(ral::gpio, gpio, GDIR, |gdir| gdir & !input.mask());
248 input
249 }
250
251 const fn mask(&self) -> u32 {
252 1 << self.offset
253 }
254
255 const fn icr_offset(&self) -> u32 {
256 (self.offset % 16) * 2
257 }
258
259 pub fn is_set(&self) -> bool {
261 ral::read_reg!(ral::gpio, self.gpio, PSR) & self.mask() != 0
262 }
263
264 pub fn is_triggered(&self) -> bool {
266 ral::read_reg!(ral::gpio, self.gpio, ISR) & self.mask() != 0
267 }
268
269 pub fn clear_triggered(&self) {
271 ral::write_reg!(ral::gpio, self.gpio, ISR, self.mask());
273 }
274
275 pub fn is_interrupt_enabled(&self) -> bool {
277 ral::read_reg!(ral::gpio, self.gpio, IMR) & self.mask() != 0
278 }
279
280 pub fn release(self) -> P {
282 self.pin
283 }
284
285 pub fn pin(&self) -> &P {
287 &self.pin
288 }
289
290 pub fn pin_mut(&mut self) -> &mut P {
292 &mut self.pin
293 }
294}
295
296impl Input<()> {
297 pub fn without_pin<const N: u8>(port: &mut Port<N>, offset: u32) -> Self {
311 Self::new((), port.register_block(), offset)
312 }
313}
314
315impl<P> eh02::digital::v2::OutputPin for Output<P> {
316 type Error = core::convert::Infallible;
317
318 fn set_high(&mut self) -> Result<(), Self::Error> {
319 self.set();
320 Ok(())
321 }
322 fn set_low(&mut self) -> Result<(), Self::Error> {
323 self.clear();
324 Ok(())
325 }
326}
327
328#[cfg(feature = "eh02-unproven")]
329impl<P> eh02::digital::v2::StatefulOutputPin for Output<P> {
330 fn is_set_high(&self) -> Result<bool, Self::Error> {
331 Ok(self.is_set())
332 }
333 fn is_set_low(&self) -> Result<bool, Self::Error> {
334 Ok(!self.is_set())
335 }
336}
337
338#[cfg(feature = "eh02-unproven")]
339impl<P> eh02::digital::v2::ToggleableOutputPin for Output<P> {
340 type Error = core::convert::Infallible;
341
342 fn toggle(&mut self) -> Result<(), Self::Error> {
343 Output::<P>::toggle(self);
344 Ok(())
345 }
346}
347
348#[cfg(feature = "eh02-unproven")]
349impl<P> eh02::digital::v2::InputPin for Input<P> {
350 type Error = core::convert::Infallible;
351
352 fn is_high(&self) -> Result<bool, Self::Error> {
353 Ok(self.is_set())
354 }
355 fn is_low(&self) -> Result<bool, Self::Error> {
356 Ok(!self.is_set())
357 }
358}
359
360impl<P> eh1::digital::ErrorType for Output<P> {
361 type Error = core::convert::Infallible;
362}
363
364impl<P> eh1::digital::OutputPin for Output<P> {
365 fn set_high(&mut self) -> Result<(), Self::Error> {
366 Output::set(self);
367 Ok(())
368 }
369 fn set_low(&mut self) -> Result<(), Self::Error> {
370 Output::clear(self);
371 Ok(())
372 }
373}
374
375impl<P> eh1::digital::StatefulOutputPin for Output<P> {
376 fn is_set_high(&mut self) -> Result<bool, Self::Error> {
377 Ok(Output::is_set(self))
378 }
379
380 fn is_set_low(&mut self) -> Result<bool, Self::Error> {
381 Ok(!Output::is_set(self))
382 }
383
384 fn toggle(&mut self) -> Result<(), Self::Error> {
385 Output::toggle(self);
386 Ok(())
387 }
388}
389
390impl<P> eh1::digital::InputPin for Output<P> {
393 fn is_high(&mut self) -> Result<bool, Self::Error> {
394 Ok(Output::is_pad_high(self))
395 }
396
397 fn is_low(&mut self) -> Result<bool, Self::Error> {
398 Ok(!Output::is_pad_high(self))
399 }
400}
401
402impl<P> eh1::digital::ErrorType for Input<P> {
403 type Error = core::convert::Infallible;
404}
405
406impl<P> eh1::digital::InputPin for Input<P> {
407 fn is_high(&mut self) -> Result<bool, Self::Error> {
408 Ok(Input::is_set(self))
409 }
410
411 fn is_low(&mut self) -> Result<bool, Self::Error> {
412 Ok(!Input::is_set(self))
413 }
414}