kywy/
button_poll.rs

1// SPDX-FileCopyrightText: 2025 KOINSLOT Inc.
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
5//! src/button_poll.rs
6//! Button polling library for Kywy board (direct level check, no async)
7//! Returns true (Pressed) or false (Released)
8//! Requires feature 'button_poll'
9
10use embassy_rp::Peri;
11use embassy_rp::gpio::{Input, Level, Pull};
12use embassy_rp::peripherals::*;
13
14#[derive(Copy, Clone, Debug)]
15pub enum ButtonId {
16    Left,
17    Right,
18    DUp,
19    DDown,
20    DLeft,
21    DRight,
22    DCenter,
23}
24
25pub struct ButtonPoller {
26    left: Input<'static>,
27    right: Input<'static>,
28    dup: Input<'static>,
29    ddown: Input<'static>,
30    dleft: Input<'static>,
31    dright: Input<'static>,
32    dcenter: Input<'static>,
33}
34
35impl ButtonPoller {
36    pub fn new(
37        pin_left: Peri<'static, PIN_2>,
38        pin_right: Peri<'static, PIN_12>,
39        pin_dup: Peri<'static, PIN_9>,
40        pin_ddown: Peri<'static, PIN_3>,
41        pin_dleft: Peri<'static, PIN_6>,
42        pin_dright: Peri<'static, PIN_7>,
43        pin_dcenter: Peri<'static, PIN_8>,
44    ) -> Self {
45        fn mk_input<P: embassy_rp::gpio::Pin + 'static>(pin: Peri<'static, P>) -> Input<'static> {
46            let mut input = Input::new(pin, Pull::Up);
47            input.set_schmitt(true);
48            input
49        }
50
51        Self {
52            left: mk_input(pin_left),
53            right: mk_input(pin_right),
54            dup: mk_input(pin_dup),
55            ddown: mk_input(pin_ddown),
56            dleft: mk_input(pin_dleft),
57            dright: mk_input(pin_dright),
58            dcenter: mk_input(pin_dcenter),
59        }
60    }
61
62    /// Returns `true` if the button is pressed (level is Low)
63    pub fn is_pressed(&self, id: ButtonId) -> bool {
64        let level = match id {
65            ButtonId::Left => self.left.get_level(),
66            ButtonId::Right => self.right.get_level(),
67            ButtonId::DUp => self.dup.get_level(),
68            ButtonId::DDown => self.ddown.get_level(),
69            ButtonId::DLeft => self.dleft.get_level(),
70            ButtonId::DRight => self.dright.get_level(),
71            ButtonId::DCenter => self.dcenter.get_level(),
72        };
73
74        level == Level::Low
75    }
76
77    /// Returns a compact bitfield of all button states
78    pub fn poll_all(&self) -> u8 {
79        let mut bits = 0u8;
80
81        if self.is_pressed(ButtonId::Left) {
82            bits |= 1 << 0;
83        }
84        if self.is_pressed(ButtonId::Right) {
85            bits |= 1 << 1;
86        }
87        if self.is_pressed(ButtonId::DUp) {
88            bits |= 1 << 2;
89        }
90        if self.is_pressed(ButtonId::DDown) {
91            bits |= 1 << 3;
92        }
93        if self.is_pressed(ButtonId::DLeft) {
94            bits |= 1 << 4;
95        }
96        if self.is_pressed(ButtonId::DRight) {
97            bits |= 1 << 5;
98        }
99        if self.is_pressed(ButtonId::DCenter) {
100            bits |= 1 << 6;
101        }
102
103        bits
104    }
105}