-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathled.rs
123 lines (111 loc) · 4.26 KB
/
led.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
//! Wrappers for the `LEDn_{ON,OFF,TOGGLE}` macros
use core::convert::Infallible;
/// The Ith LED (calling the `LED<I>_{ON,OFF,TOGGLE}` macros).
///
/// The preferred interface for turning a LED on and off is [switch_hal::OutputSwitch].
///
/// LEDs are accessible safely; any not implemented on a board are silently ignored.
#[derive(Debug)]
pub struct LED<const I: u8>(());
/// The indicated LED is not present on the current board.
#[derive(Debug)]
pub struct LedNotPresent;
impl<const I: u8> LED<I> {
#[deprecated(
note = "Use new_unchecked() to retain the behavior this function has always had; future versions of `.new()` will panic when used with a board that does not have that LED.",
since = "0.9.1"
)]
pub const fn new() -> Self {
Self::new_unchecked()
}
/// Accesses the LED numbered `I` as `LED::<I>::new_unchecked()`.
///
/// It is not an error if this board does not have a LED with that number; the resulting struct
/// will be available but its methods have no effect.
pub const fn new_unchecked() -> Self {
const { assert!(I < 8, "RIOT only defines LED0..7") };
Self(())
}
/// Accesses the LED numbered `I` as `LED::<I>::new_checked()?`.
///
/// An LED is returned if present on the board, which is known at build time.
pub const fn new_checked() -> Result<Self, LedNotPresent> {
if Self::is_present() {
Ok(Self(()))
} else {
Err(LedNotPresent)
}
}
const fn is_present() -> bool {
unsafe {
match I {
0 => riot_sys::macro_LED0_IS_PRESENT() != -1,
1 => riot_sys::macro_LED1_IS_PRESENT() != -1,
2 => riot_sys::macro_LED2_IS_PRESENT() != -1,
3 => riot_sys::macro_LED3_IS_PRESENT() != -1,
4 => riot_sys::macro_LED4_IS_PRESENT() != -1,
5 => riot_sys::macro_LED5_IS_PRESENT() != -1,
6 => riot_sys::macro_LED6_IS_PRESENT() != -1,
7 => riot_sys::macro_LED7_IS_PRESENT() != -1,
_ => panic!("RIOT only defines LED0..7"),
}
}
}
}
impl<const I: u8> switch_hal::OutputSwitch for LED<I> {
type Error = Infallible;
fn on(&mut self) -> Result<(), Self::Error> {
// unsafe: RIOT's LED functions can be called any time (and no-op on undefined LEDs)
unsafe {
match I {
0 => riot_sys::macro_LED0_ON(),
1 => riot_sys::macro_LED1_ON(),
2 => riot_sys::macro_LED2_ON(),
3 => riot_sys::macro_LED3_ON(),
4 => riot_sys::macro_LED4_ON(),
5 => riot_sys::macro_LED5_ON(),
6 => riot_sys::macro_LED6_ON(),
7 => riot_sys::macro_LED7_ON(),
_ => unreachable!(),
}
};
Ok(())
}
fn off(&mut self) -> Result<(), Self::Error> {
// unsafe: RIOT's LED functions can be called any time (and no-op on undefined LEDs)
unsafe {
match I {
0 => riot_sys::macro_LED0_OFF(),
1 => riot_sys::macro_LED1_OFF(),
2 => riot_sys::macro_LED2_OFF(),
3 => riot_sys::macro_LED3_OFF(),
4 => riot_sys::macro_LED4_OFF(),
5 => riot_sys::macro_LED5_OFF(),
6 => riot_sys::macro_LED6_OFF(),
7 => riot_sys::macro_LED7_OFF(),
_ => unreachable!(),
}
};
Ok(())
}
}
impl<const I: u8> switch_hal::ToggleableOutputSwitch for LED<I> {
type Error = Infallible;
fn toggle(&mut self) -> Result<(), Self::Error> {
// unsafe: RIOT's LED functions can be called any time (and no-op on undefined LEDs)
unsafe {
match I {
0 => riot_sys::macro_LED0_TOGGLE(),
1 => riot_sys::macro_LED1_TOGGLE(),
2 => riot_sys::macro_LED2_TOGGLE(),
3 => riot_sys::macro_LED3_TOGGLE(),
4 => riot_sys::macro_LED4_TOGGLE(),
5 => riot_sys::macro_LED5_TOGGLE(),
6 => riot_sys::macro_LED6_TOGGLE(),
7 => riot_sys::macro_LED7_TOGGLE(),
_ => unreachable!(),
}
};
Ok(())
}
}