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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
use super::*;
pub struct DynamicPin<const P: char, const N: u8> {
pub(crate) mode: Dynamic,
}
pub enum Dynamic {
InputFloating,
InputPullUp,
InputPullDown,
OutputPushPull,
OutputOpenDrain,
}
#[derive(Debug, PartialEq)]
pub enum PinModeError {
IncorrectMode,
}
impl Dynamic {
pub fn is_input(&self) -> bool {
use Dynamic::*;
match self {
InputFloating | InputPullUp | InputPullDown | OutputOpenDrain => true,
OutputPushPull => false,
}
}
pub fn is_output(&self) -> bool {
use Dynamic::*;
match self {
InputFloating | InputPullUp | InputPullDown => false,
OutputPushPull | OutputOpenDrain => true,
}
}
}
struct Unknown;
impl crate::Sealed for Unknown {}
impl PinMode for Unknown {}
impl<const P: char, const N: u8> DynamicPin<P, N> {
pub(super) const fn new(mode: Dynamic) -> Self {
Self { mode }
}
#[inline]
pub fn make_pull_up_input(&mut self) {
Pin::<P, N, Unknown>::new().into_pull_up_input();
self.mode = Dynamic::InputPullUp;
}
#[inline]
pub fn make_pull_down_input(&mut self) {
Pin::<P, N, Unknown>::new().into_pull_down_input();
self.mode = Dynamic::InputPullDown;
}
#[inline]
pub fn make_floating_input(&mut self) {
Pin::<P, N, Unknown>::new().into_floating_input();
self.mode = Dynamic::InputFloating;
}
#[inline]
pub fn make_push_pull_output(&mut self) {
Pin::<P, N, Unknown>::new().into_push_pull_output();
self.mode = Dynamic::OutputPushPull;
}
#[inline]
pub fn make_push_pull_output_in_state(&mut self, state: PinState) {
Pin::<P, N, Unknown>::new().into_push_pull_output_in_state(state);
self.mode = Dynamic::OutputPushPull;
}
#[inline]
pub fn make_open_drain_output(&mut self) {
Pin::<P, N, Unknown>::new().into_open_drain_output();
self.mode = Dynamic::OutputOpenDrain;
}
#[inline]
pub fn make_open_drain_output_in_state(&mut self, state: PinState) {
Pin::<P, N, Unknown>::new().into_open_drain_output_in_state(state);
self.mode = Dynamic::OutputOpenDrain;
}
pub fn set_high(&mut self) -> Result<(), PinModeError> {
if self.mode.is_output() {
Pin::<P, N, Unknown>::new()._set_state(PinState::High);
Ok(())
} else {
Err(PinModeError::IncorrectMode)
}
}
pub fn set_low(&mut self) -> Result<(), PinModeError> {
if self.mode.is_output() {
Pin::<P, N, Unknown>::new()._set_state(PinState::Low);
Ok(())
} else {
Err(PinModeError::IncorrectMode)
}
}
pub fn is_high(&self) -> Result<bool, PinModeError> {
self.is_low().map(|b| !b)
}
pub fn is_low(&self) -> Result<bool, PinModeError> {
if self.mode.is_input() {
Ok(Pin::<P, N, Unknown>::new()._is_low())
} else {
Err(PinModeError::IncorrectMode)
}
}
}