1use embassy_executor::Spawner;
9use embassy_rp::Peri;
10use embassy_rp::gpio::{Input, Level, Pull};
11use embassy_rp::peripherals::*;
12use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
13use embassy_sync::channel::Channel;
14
15#[derive(Clone, Copy, Debug)]
16pub enum ButtonId {
17 Left,
18 Right,
19 DUp,
20 DDown,
21 DLeft,
22 DRight,
23 DCenter,
24}
25
26#[derive(Clone, Copy, Debug, Eq, PartialEq)]
27pub enum ButtonState {
28 Pressed,
29 Released,
30}
31
32#[derive(Clone, Copy, Debug)]
33pub struct ButtonEvent {
34 pub id: ButtonId,
35 pub state: ButtonState,
36}
37
38const BUTTON_CHANNEL_CAPACITY: usize = 16;
39
40static BUTTON_CHANNEL: Channel<ThreadModeRawMutex, ButtonEvent, BUTTON_CHANNEL_CAPACITY> =
41 Channel::new();
42
43pub fn init(
44 spawner: &Spawner,
45 pin_left: Peri<'static, PIN_12>,
46 pin_right: Peri<'static, PIN_2>,
47 pin_dup: Peri<'static, PIN_9>,
48 pin_ddown: Peri<'static, PIN_3>,
49 pin_dleft: Peri<'static, PIN_6>,
50 pin_dright: Peri<'static, PIN_7>,
51 pin_dcenter: Peri<'static, PIN_8>,
52) -> &'static Channel<ThreadModeRawMutex, ButtonEvent, BUTTON_CHANNEL_CAPACITY> {
53 spawn_button(spawner, pin_left, ButtonId::Left);
54 spawn_button(spawner, pin_right, ButtonId::Right);
55 spawn_button(spawner, pin_dup, ButtonId::DUp);
56 spawn_button(spawner, pin_ddown, ButtonId::DDown);
57 spawn_button(spawner, pin_dleft, ButtonId::DLeft);
58 spawn_button(spawner, pin_dright, ButtonId::DRight);
59 spawn_button(spawner, pin_dcenter, ButtonId::DCenter);
60
61 &BUTTON_CHANNEL
62}
63
64fn spawn_button<P: embassy_rp::gpio::Pin + 'static>(
65 spawner: &Spawner,
66 pin: Peri<'static, P>,
67 id: ButtonId,
68) {
69 let mut input = Input::new(pin, Pull::Up);
70 input.set_schmitt(true);
71 spawner.spawn(button_task(input, id)).unwrap();
72}
73
74#[embassy_executor::task(pool_size = 7)] async fn button_task(mut pin: Input<'static>, id: ButtonId) {
76 loop {
77 pin.wait_for_any_edge().await;
78 let level = pin.get_level();
79
80 let state = if level == Level::Low {
81 ButtonState::Pressed
82 } else {
83 ButtonState::Released
84 };
85
86 let _ = BUTTON_CHANNEL.try_send(ButtonEvent { id, state });
87 }
88}