1use crate::peripherals::{Gpio0, Gpio1, Gpio2, IoConfig};
13use core::marker::PhantomData;
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub enum Pull {
20 None,
21 Up,
22 Down,
23}
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub enum InterruptTrigger {
28 RisingEdge,
30 FallingEdge,
32 HighLevel,
34 LowLevel,
36}
37
38#[derive(Debug, Clone, Copy)]
40pub struct InputConfig {
41 pub pull: Pull,
42}
43
44impl Default for InputConfig {
45 fn default() -> Self {
46 Self { pull: Pull::None }
47 }
48}
49
50impl InputConfig {
51 pub const fn new() -> Self {
52 Self { pull: Pull::None }
53 }
54 pub const fn with_pull(mut self, pull: Pull) -> Self {
55 self.pull = pull;
56 self
57 }
58}
59
60#[derive(Debug, Clone, Copy, Default)]
62pub struct OutputConfig {
63 pub open_drain: bool,
64 pub initial_high: bool,
65}
66
67impl OutputConfig {
68 pub const fn new() -> Self {
69 Self { open_drain: false, initial_high: false }
70 }
71 pub const fn with_open_drain(mut self, od: bool) -> Self {
72 self.open_drain = od;
73 self
74 }
75 pub const fn with_initial(mut self, high: bool) -> Self {
76 self.initial_high = high;
77 self
78 }
79}
80
81pub struct InputMode;
83pub struct OutputMode;
84
85pub struct AnyPin<'d> {
89 block: u8,
90 bit: u8,
91 _lifetime: PhantomData<&'d mut ()>,
92}
93
94impl<'d> AnyPin<'d> {
95 pub unsafe fn steal(pin: u8) -> Self {
100 Self { block: pin / 8, bit: pin % 8, _lifetime: PhantomData }
101 }
102
103 pub fn number(&self) -> u8 {
105 self.block * 8 + self.bit
106 }
107
108 fn set_oen(&self, input: bool) {
110 let r = regs(self.block);
111 let mask = 1 << self.bit;
112 if input {
113 r.gpio_sw_oen().modify(|r, w| unsafe { w.bits(r.bits() | mask) });
114 } else {
115 r.gpio_sw_oen().modify(|r, w| unsafe { w.bits(r.bits() & !mask) });
116 }
117 }
118
119 pub fn init_input(self, config: InputConfig) -> Input<'d> {
124 self.set_oen(true);
125 apply_pull(self.number(), config.pull);
126 Input { pin: self, config }
127 }
128
129 pub fn init_output(self, config: OutputConfig) -> Output<'d> {
131 let mut out = Output { pin: self, config };
132 if config.initial_high {
133 out.set_high();
134 } else {
135 out.set_low();
136 }
137 out.pin.set_oen(false);
138 out
139 }
140
141 pub fn init_flex(self, config: OutputConfig) -> Flex<'d> {
143 if config.initial_high {
144 unsafe { regs(self.block).gpio_data_set().write(|w| w.bits(1 << self.bit)) };
145 } else {
146 unsafe { regs(self.block).gpio_data_clr().write(|w| w.bits(1 << self.bit)) };
147 }
148 self.set_oen(false);
149 Flex { pin: self, config }
150 }
151}
152
153pub struct Input<'d> {
157 pin: AnyPin<'d>,
158 #[allow(dead_code)]
159 config: InputConfig,
160}
161
162impl<'d> Input<'d> {
163 pub fn is_high(&self) -> bool {
164 (regs(self.pin.block).gpio_sw_out().read().bits() >> self.pin.bit) & 1 != 0
165 }
166
167 pub fn is_low(&self) -> bool {
168 !self.is_high()
169 }
170
171 pub fn number(&self) -> u8 {
172 self.pin.number()
173 }
174
175 pub fn enable_interrupt(&self) {
176 let r = regs(self.pin.block);
177 r.gpio_int_en().modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.pin.bit)) });
178 }
179
180 pub fn disable_interrupt(&self) {
181 let r = regs(self.pin.block);
182 r.gpio_int_en().modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.pin.bit)) });
183 }
184
185 pub fn clear_interrupt(&self) {
186 unsafe { regs(self.pin.block).gpio_int_eoi().write(|w| w.bits(1 << self.pin.bit)) };
187 }
188
189 pub fn set_interrupt_trigger(&self, trigger: InterruptTrigger) {
194 let r = regs(self.pin.block);
195 let mask = 1u32 << self.pin.bit;
196 let (edge, high) = match trigger {
197 InterruptTrigger::RisingEdge => (true, true),
198 InterruptTrigger::FallingEdge => (true, false),
199 InterruptTrigger::HighLevel => (false, true),
200 InterruptTrigger::LowLevel => (false, false),
201 };
202 r.gpio_int_type().modify(|r, w| unsafe { w.bits(if edge { r.bits() | mask } else { r.bits() & !mask }) });
203 r.gpio_int_polarity().modify(|r, w| unsafe { w.bits(if high { r.bits() | mask } else { r.bits() & !mask }) });
204 }
205
206 pub fn interrupt_pending(&self) -> bool {
207 (regs(self.pin.block).gpio_int_raw().read().bits() >> self.pin.bit) & 1 != 0
208 }
209}
210
211impl embedded_hal::digital::ErrorType for Input<'_> {
212 type Error = core::convert::Infallible;
213}
214
215impl embedded_hal::digital::InputPin for Input<'_> {
216 fn is_high(&mut self) -> Result<bool, Self::Error> {
217 Ok(Input::is_high(self))
218 }
219 fn is_low(&mut self) -> Result<bool, Self::Error> {
220 Ok(Input::is_low(self))
221 }
222}
223
224pub struct Output<'d> {
228 pin: AnyPin<'d>,
229 config: OutputConfig,
230}
231
232impl<'d> Output<'d> {
233 pub fn set_high(&mut self) {
234 unsafe { regs(self.pin.block).gpio_data_set().write(|w| w.bits(1 << self.pin.bit)) };
235 }
236
237 pub fn set_low(&mut self) {
238 unsafe { regs(self.pin.block).gpio_data_clr().write(|w| w.bits(1 << self.pin.bit)) };
239 }
240
241 pub fn toggle(&mut self) {
242 let r = regs(self.pin.block);
243 let val = r.gpio_sw_out().read().bits();
244 if val & (1 << self.pin.bit) != 0 {
245 unsafe { r.gpio_data_clr().write(|w| w.bits(1 << self.pin.bit)) };
246 } else {
247 unsafe { r.gpio_data_set().write(|w| w.bits(1 << self.pin.bit)) };
248 }
249 }
250
251 pub fn is_set_high(&self) -> bool {
252 (regs(self.pin.block).gpio_sw_out().read().bits() >> self.pin.bit) & 1 != 0
253 }
254
255 pub fn number(&self) -> u8 {
256 self.pin.number()
257 }
258
259 pub fn into_flex(self) -> Flex<'d> {
261 Flex { pin: self.pin, config: self.config }
262 }
263}
264
265impl embedded_hal::digital::ErrorType for Output<'_> {
266 type Error = core::convert::Infallible;
267}
268
269impl embedded_hal::digital::OutputPin for Output<'_> {
270 fn set_low(&mut self) -> Result<(), Self::Error> {
271 Output::set_low(self);
272 Ok(())
273 }
274 fn set_high(&mut self) -> Result<(), Self::Error> {
275 Output::set_high(self);
276 Ok(())
277 }
278}
279
280impl embedded_hal::digital::StatefulOutputPin for Output<'_> {
281 fn is_set_high(&mut self) -> Result<bool, Self::Error> {
282 Ok(Output::is_set_high(self))
283 }
284 fn is_set_low(&mut self) -> Result<bool, Self::Error> {
285 Ok(!Output::is_set_high(self))
286 }
287}
288
289pub struct Flex<'d> {
293 pin: AnyPin<'d>,
294 #[allow(dead_code)]
295 config: OutputConfig,
296}
297
298impl<'d> Flex<'d> {
299 pub fn set_high(&mut self) {
300 self.pin.set_oen(false);
301 unsafe { regs(self.pin.block).gpio_data_set().write(|w| w.bits(1 << self.pin.bit)) };
302 }
303
304 pub fn set_low(&mut self) {
305 self.pin.set_oen(false);
306 unsafe { regs(self.pin.block).gpio_data_clr().write(|w| w.bits(1 << self.pin.bit)) };
307 }
308
309 pub fn toggle(&mut self) {
310 let r = regs(self.pin.block);
311 self.pin.set_oen(false);
312 let val = r.gpio_sw_out().read().bits();
313 if val & (1 << self.pin.bit) != 0 {
314 unsafe { r.gpio_data_clr().write(|w| w.bits(1 << self.pin.bit)) };
315 } else {
316 unsafe { r.gpio_data_set().write(|w| w.bits(1 << self.pin.bit)) };
317 }
318 }
319
320 pub fn is_set_high(&self) -> bool {
321 (regs(self.pin.block).gpio_sw_out().read().bits() >> self.pin.bit) & 1 != 0
322 }
323
324 pub fn is_high(&self) -> bool {
325 let r = regs(self.pin.block);
327 let oen = r.gpio_sw_oen().read().bits();
328 self.pin.set_oen(true);
329 let val = (r.gpio_sw_out().read().bits() >> self.pin.bit) & 1 != 0;
330 let mask = 1 << self.pin.bit;
332 if oen & mask != 0 {
333 r.gpio_sw_oen().modify(|reg, w| unsafe { w.bits(reg.bits() | mask) });
334 } else {
335 r.gpio_sw_oen().modify(|reg, w| unsafe { w.bits(reg.bits() & !mask) });
336 }
337 val
338 }
339
340 pub fn is_low(&self) -> bool {
341 !self.is_high()
342 }
343
344 pub fn number(&self) -> u8 {
345 self.pin.number()
346 }
347}
348
349impl embedded_hal::digital::ErrorType for Flex<'_> {
350 type Error = core::convert::Infallible;
351}
352
353impl embedded_hal::digital::OutputPin for Flex<'_> {
354 fn set_low(&mut self) -> Result<(), Self::Error> {
355 Flex::set_low(self);
356 Ok(())
357 }
358 fn set_high(&mut self) -> Result<(), Self::Error> {
359 Flex::set_high(self);
360 Ok(())
361 }
362}
363
364impl embedded_hal::digital::StatefulOutputPin for Flex<'_> {
365 fn is_set_high(&mut self) -> Result<bool, Self::Error> {
366 Ok(Flex::is_set_high(self))
367 }
368 fn is_set_low(&mut self) -> Result<bool, Self::Error> {
369 Ok(!Flex::is_set_high(self))
370 }
371}
372
373impl embedded_hal::digital::InputPin for Flex<'_> {
374 fn is_high(&mut self) -> Result<bool, Self::Error> {
375 Ok(Flex::is_high(self))
376 }
377 fn is_low(&mut self) -> Result<bool, Self::Error> {
378 Ok(Flex::is_low(self))
379 }
380}
381
382fn regs(block: u8) -> &'static ws63_pac::gpio0::RegisterBlock {
385 unsafe {
386 match block {
387 0 => &*Gpio0::ptr(),
388 1 => &*Gpio1::ptr(),
389 2 => &*Gpio2::ptr(),
390 _ => unreachable!(),
391 }
392 }
393}
394
395const IO_CONFIG_BASE: usize = 0x4400_D000;
402const PAD_GPIO_CTRL_OFF: usize = 0x800;
403const PAD_PE_BIT: u32 = 1 << 9;
404const PAD_PS_BIT: u32 = 1 << 10;
405
406fn apply_pull(pin: u8, pull: Pull) {
412 if pin > 14 {
413 return;
414 }
415 let reg = (IO_CONFIG_BASE + PAD_GPIO_CTRL_OFF + (pin as usize) * 4) as *mut u32;
416 let (pe, ps) = match pull {
417 Pull::None => (false, false),
418 Pull::Up => (true, true),
419 Pull::Down => (true, false),
420 };
421 unsafe {
422 let mut v = core::ptr::read_volatile(reg);
423 v &= !(PAD_PE_BIT | PAD_PS_BIT);
424 if pe {
425 v |= PAD_PE_BIT;
426 }
427 if ps {
428 v |= PAD_PS_BIT;
429 }
430 core::ptr::write_volatile(reg, v);
431 }
432}
433
434pub struct GpioPin<'d, MODE> {
438 block: u8,
439 bit: u8,
440 _mode: PhantomData<&'d MODE>,
441}
442
443impl<MODE> GpioPin<'_, MODE> {
444 pub fn number(&self) -> u8 {
445 self.block * 8 + self.bit
446 }
447}
448
449impl GpioPin<'_, OutputMode> {
450 pub fn set_high(&mut self) {
451 unsafe { regs(self.block).gpio_data_set().write(|w| w.bits(1 << self.bit)) };
452 }
453 pub fn set_low(&mut self) {
454 unsafe { regs(self.block).gpio_data_clr().write(|w| w.bits(1 << self.bit)) };
455 }
456 pub fn toggle(&mut self) {
457 let r = regs(self.block);
458 let val = r.gpio_sw_out().read().bits();
459 if val & (1 << self.bit) != 0 {
460 unsafe { r.gpio_data_clr().write(|w| w.bits(1 << self.bit)) };
461 } else {
462 unsafe { r.gpio_data_set().write(|w| w.bits(1 << self.bit)) };
463 }
464 }
465 pub fn is_set_high(&self) -> bool {
466 (regs(self.block).gpio_sw_out().read().bits() >> self.bit) & 1 != 0
467 }
468 pub fn into_input(self) -> GpioPin<'static, InputMode> {
469 regs(self.block).gpio_sw_oen().modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.bit)) });
470 GpioPin { block: self.block, bit: self.bit, _mode: PhantomData }
471 }
472}
473
474impl GpioPin<'_, InputMode> {
475 pub fn is_high(&self) -> bool {
476 (regs(self.block).gpio_sw_out().read().bits() >> self.bit) & 1 != 0
477 }
478 pub fn is_low(&self) -> bool {
479 !self.is_high()
480 }
481 pub fn enable_interrupt(&self) {
482 regs(self.block).gpio_int_en().modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.bit)) });
483 }
484 pub fn disable_interrupt(&self) {
485 regs(self.block).gpio_int_en().modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.bit)) });
486 }
487 pub fn clear_interrupt(&self) {
488 unsafe { regs(self.block).gpio_int_eoi().write(|w| w.bits(1 << self.bit)) };
489 }
490 pub fn interrupt_pending(&self) -> bool {
491 (regs(self.block).gpio_int_raw().read().bits() >> self.bit) & 1 != 0
492 }
493 pub fn into_output(self) -> GpioPin<'static, OutputMode> {
494 regs(self.block).gpio_sw_oen().modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.bit)) });
495 GpioPin { block: self.block, bit: self.bit, _mode: PhantomData }
496 }
497}
498
499impl embedded_hal::digital::ErrorType for GpioPin<'_, OutputMode> {
501 type Error = core::convert::Infallible;
502}
503impl embedded_hal::digital::OutputPin for GpioPin<'_, OutputMode> {
504 fn set_low(&mut self) -> Result<(), Self::Error> {
505 GpioPin::set_low(self);
506 Ok(())
507 }
508 fn set_high(&mut self) -> Result<(), Self::Error> {
509 GpioPin::set_high(self);
510 Ok(())
511 }
512}
513impl embedded_hal::digital::StatefulOutputPin for GpioPin<'_, OutputMode> {
514 fn is_set_high(&mut self) -> Result<bool, Self::Error> {
515 Ok(GpioPin::is_set_high(self))
516 }
517 fn is_set_low(&mut self) -> Result<bool, Self::Error> {
518 Ok(!GpioPin::is_set_high(self))
519 }
520}
521impl embedded_hal::digital::ErrorType for GpioPin<'_, InputMode> {
522 type Error = core::convert::Infallible;
523}
524impl embedded_hal::digital::InputPin for GpioPin<'_, InputMode> {
525 fn is_high(&mut self) -> Result<bool, Self::Error> {
526 Ok(GpioPin::is_high(self))
527 }
528 fn is_low(&mut self) -> Result<bool, Self::Error> {
529 Ok(GpioPin::is_low(self))
530 }
531}
532
533pub fn create_input_pin(pin: u8) -> GpioPin<'static, InputMode> {
537 let block = pin / 8;
538 let bit = pin % 8;
539 regs(block).gpio_sw_oen().modify(|r, w| unsafe { w.bits(r.bits() | (1 << bit)) });
540 GpioPin { block, bit, _mode: PhantomData }
541}
542
543pub fn create_output_pin(pin: u8) -> GpioPin<'static, OutputMode> {
545 let block = pin / 8;
546 let bit = pin % 8;
547 regs(block).gpio_sw_oen().modify(|r, w| unsafe { w.bits(r.bits() & !(1 << bit)) });
548 GpioPin { block, bit, _mode: PhantomData }
549}
550
551#[derive(Debug, Clone, Copy, PartialEq, Eq)]
555pub struct OutputSignal(pub(crate) u8);
556
557#[derive(Debug, Clone, Copy, PartialEq, Eq)]
559pub struct InputSignal(pub(crate) u8);
560
561pub trait PeripheralOutput: crate::private::Sealed {
563 fn output_signal(&self) -> OutputSignal;
564}
565
566pub trait PeripheralInput: crate::private::Sealed {
568 fn input_signal(&self) -> InputSignal;
569}
570
571impl crate::private::Sealed for Output<'_> {}
573impl crate::private::Sealed for Input<'_> {}
574impl crate::private::Sealed for Flex<'_> {}
575impl crate::private::Sealed for GpioPin<'_, OutputMode> {}
576impl crate::private::Sealed for GpioPin<'_, InputMode> {}
577
578pub struct Io<'d> {
582 pub io_config: IoConfig<'d>,
583}
584
585impl<'d> Io<'d> {
586 pub fn new(io_config: IoConfig<'d>) -> Self {
587 Self { io_config }
588 }
589 pub fn register_block(&self) -> &ws63_pac::io_config::RegisterBlock {
590 self.io_config.register_block()
591 }
592}
593
594#[cfg(feature = "async")]
596mod asynch_impl {
597 use super::{Input, InterruptTrigger, regs};
598 use crate::asynch::IrqSignal;
599 use crate::interrupt::{self, Interrupt};
600 use core::future::Future;
601 use core::pin::Pin;
602 use core::task::{Context, Poll};
603 use embedded_hal_async::digital::Wait;
604
605 static GPIO_SIGNAL: [IrqSignal; 3] = [IrqSignal::new(), IrqSignal::new(), IrqSignal::new()];
606
607 fn bank_irq(bank: usize) -> Interrupt {
608 match bank {
609 0 => Interrupt::GPIO_INT0,
610 1 => Interrupt::GPIO_INT1,
611 _ => Interrupt::GPIO_INT2,
612 }
613 }
614
615 pub fn on_interrupt(bank: u8) {
620 let r = regs(bank);
621 let fired = r.gpio_int_raw().read().bits();
622 r.gpio_int_en().modify(|v, w| unsafe { w.bits(v.bits() & !fired) });
624 unsafe { r.gpio_int_eoi().write(|w| w.bits(fired)) };
625 GPIO_SIGNAL[bank as usize].signal();
626 interrupt::clear_pending(bank_irq(bank as usize));
627 }
628
629 async fn arm_and_wait(input: &mut Input<'_>, trig: InterruptTrigger) {
630 let bank = input.pin.block as usize;
631 input.set_interrupt_trigger(trig);
632 input.clear_interrupt();
633 GPIO_SIGNAL[bank].reset();
634 input.enable_interrupt();
635 unsafe { interrupt::enable(bank_irq(bank)) };
637 GpioWaitFuture { bank }.await;
638 }
639
640 struct GpioWaitFuture {
641 bank: usize,
642 }
643
644 impl Future for GpioWaitFuture {
645 type Output = ();
646 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
647 if GPIO_SIGNAL[self.bank].take_fired() {
648 Poll::Ready(())
649 } else {
650 GPIO_SIGNAL[self.bank].register(cx.waker());
651 Poll::Pending
652 }
653 }
654 }
655
656 impl Wait for Input<'_> {
660 async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
661 if self.is_high() {
662 return Ok(());
663 }
664 arm_and_wait(self, InterruptTrigger::HighLevel).await;
665 Ok(())
666 }
667 async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
668 if self.is_low() {
669 return Ok(());
670 }
671 arm_and_wait(self, InterruptTrigger::LowLevel).await;
672 Ok(())
673 }
674 async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
675 arm_and_wait(self, InterruptTrigger::RisingEdge).await;
676 Ok(())
677 }
678 async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
679 arm_and_wait(self, InterruptTrigger::FallingEdge).await;
680 Ok(())
681 }
682 async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
683 let trig = if self.is_high() { InterruptTrigger::FallingEdge } else { InterruptTrigger::RisingEdge };
684 arm_and_wait(self, trig).await;
685 Ok(())
686 }
687 }
688}
689
690#[cfg(feature = "async")]
691pub use asynch_impl::on_interrupt;