1
1
//! Input device component interfaces for devices such as `Button`
2
- use rppal:: gpio:: { Gpio , InputPin , Level , Trigger } ;
2
+ use rppal:: gpio:: { self , Gpio , InputPin , Level , Trigger } ;
3
3
use std:: time:: Duration ;
4
4
5
5
/// Represents a generic GPIO input device.
@@ -17,7 +17,7 @@ impl InputDevice {
17
17
/// # Arguments
18
18
///
19
19
/// * `pin` - The GPIO pin which the device is attached to
20
- ///
20
+ ///
21
21
pub fn new ( pin : u8 ) -> InputDevice {
22
22
match Gpio :: new ( ) {
23
23
Err ( e) => panic ! ( "{:?}" , e) ,
@@ -37,7 +37,7 @@ impl InputDevice {
37
37
/// # Arguments
38
38
///
39
39
/// * `pin` - The GPIO pin which the device is attached to
40
- ///
40
+ ///
41
41
pub fn new_with_pullup ( pin : u8 ) -> InputDevice {
42
42
match Gpio :: new ( ) {
43
43
Err ( e) => panic ! ( "{:?}" , e) ,
@@ -61,30 +61,13 @@ macro_rules! impl_events_mixin {
61
61
( ) => {
62
62
/// Pause the program until the device is activated, or the timeout is reached.
63
63
fn wait_for( & mut self , timeout: Option <f32 >, active: bool ) {
64
- match timeout {
65
- None => {
66
- if active {
67
- self . pin. set_interrupt( Trigger :: RisingEdge ) . unwrap( ) ;
68
- self . pin. poll_interrupt( true , None ) . unwrap( ) ;
69
- } else {
70
- self . pin. set_interrupt( Trigger :: FallingEdge ) . unwrap( ) ;
71
- self . pin. poll_interrupt( true , None ) . unwrap( ) ;
72
- }
73
- }
74
- Some ( n) => {
75
- if active {
76
- self . pin. set_interrupt( Trigger :: RisingEdge ) . unwrap( ) ;
77
- self . pin
78
- . poll_interrupt( true , Some ( Duration :: from_millis( ( n * 1000.0 ) as u64 ) ) )
79
- . unwrap( ) ;
80
- } else {
81
- self . pin. set_interrupt( Trigger :: FallingEdge ) . unwrap( ) ;
82
- self . pin
83
- . poll_interrupt( true , Some ( Duration :: from_millis( ( n * 1000.0 ) as u64 ) ) )
84
- . unwrap( ) ;
85
- }
86
- }
87
- }
64
+ let trigger = match active {
65
+ true => Trigger :: RisingEdge ,
66
+ false => Trigger :: FallingEdge ,
67
+ } ;
68
+ let timeout = timeout. map( |seconds| Duration :: from_millis( ( seconds * 1000.0 ) as u64 ) ) ;
69
+ self . pin. set_interrupt( trigger) . unwrap( ) ;
70
+ self . pin. poll_interrupt( true , timeout) . unwrap( ) ;
88
71
}
89
72
} ;
90
73
}
@@ -98,7 +81,6 @@ pub struct DigitalInputDevice {
98
81
pin : InputPin ,
99
82
active_state : bool ,
100
83
inactive_state : bool ,
101
- bounce_time : Option < f32 > ,
102
84
}
103
85
104
86
impl DigitalInputDevice {
@@ -120,7 +102,6 @@ impl DigitalInputDevice {
120
102
pin : pin. into_input_pulldown ( ) ,
121
103
active_state : true ,
122
104
inactive_state : false ,
123
- bounce_time : None ,
124
105
} ,
125
106
} ,
126
107
}
@@ -131,7 +112,7 @@ impl DigitalInputDevice {
131
112
/// # Arguments
132
113
///
133
114
/// * `pin` - The GPIO pin which the device is attached to
134
- ///
115
+ ///
135
116
pub fn new_with_pullup ( pin : u8 ) -> DigitalInputDevice {
136
117
match Gpio :: new ( ) {
137
118
Err ( e) => panic ! ( "{:?}" , e) ,
@@ -141,7 +122,6 @@ impl DigitalInputDevice {
141
122
pin : pin. into_input_pullup ( ) ,
142
123
active_state : false ,
143
124
inactive_state : true ,
144
- bounce_time : None ,
145
125
} ,
146
126
} ,
147
127
}
@@ -168,12 +148,9 @@ impl DigitalInputDevice {
168
148
/// Alternatively, connect one side of the button to the 3V3 pin, and the other to any GPIO pin,
169
149
/// and then create a Button instance with Button::new_with_pulldown
170
150
pub struct Button {
171
- pin : InputPin ,
151
+ pub ( crate ) pin : InputPin ,
172
152
active_state : bool ,
173
153
inactive_state : bool ,
174
- // FIXME: Implement debouncing
175
- #[ allow( dead_code) ]
176
- bounce_time : Option < f32 > ,
177
154
}
178
155
179
156
impl Button {
@@ -188,7 +165,6 @@ impl Button {
188
165
pin : pin. into_input_pullup ( ) ,
189
166
active_state : false ,
190
167
inactive_state : true ,
191
- bounce_time : None ,
192
168
} ,
193
169
} ,
194
170
}
@@ -204,7 +180,6 @@ impl Button {
204
180
pin : pin. into_input_pulldown ( ) ,
205
181
active_state : true ,
206
182
inactive_state : false ,
207
- bounce_time : None ,
208
183
} ,
209
184
} ,
210
185
}
@@ -226,4 +201,37 @@ impl Button {
226
201
pub fn wait_for_press ( & mut self , timeout : Option < f32 > ) {
227
202
self . wait_for ( timeout, true )
228
203
}
204
+
205
+ /// Invokes the passed closure everytime the button is pressed
206
+ pub fn when_pressed < C > ( & mut self , action : C ) -> Result < ( ) , gpio:: Error >
207
+ where
208
+ C : FnMut ( Level ) + Send + ' static ,
209
+ {
210
+ self . action_on ( true , action)
211
+ }
212
+
213
+ /// Invokes the passed closure everytime the button is released
214
+ pub fn when_released < C > ( & mut self , action : C ) -> Result < ( ) , gpio:: Error >
215
+ where
216
+ C : FnMut ( Level ) + Send + ' static ,
217
+ {
218
+ self . action_on ( false , action)
219
+ }
220
+
221
+ /// Adds an async interrupt for the corresponding trigger type to support `when_pressed`/`when_released`
222
+ pub ( crate ) fn action_on < C > ( & mut self , active : bool , action : C ) -> Result < ( ) , gpio:: Error >
223
+ where
224
+ C : FnMut ( Level ) + Send + ' static ,
225
+ {
226
+ let trigger = match active {
227
+ true => Trigger :: RisingEdge ,
228
+ false => Trigger :: FallingEdge ,
229
+ } ;
230
+ self . pin . set_async_interrupt ( trigger, action)
231
+ }
232
+
233
+ /// Removes all previously configured async trigger(s) (E.g. `when_pressed`/`when_released`)
234
+ pub fn clear_async_interrupt ( & mut self ) -> Result < ( ) , gpio:: Error > {
235
+ self . pin . clear_async_interrupt ( )
236
+ }
229
237
}
0 commit comments