4
4
5
5
use std:: fmt;
6
6
7
+ use embedded_hal:: digital:: InputPin ;
8
+ #[ cfg( feature = "async-tokio" ) ]
9
+ use gpiocdev:: { line:: EdgeDetection , request:: Request , tokio:: AsyncRequest } ;
10
+
7
11
/// Newtype around [`gpio_cdev::LineHandle`] that implements the `embedded-hal` traits
8
12
///
9
13
/// [`gpio_cdev::LineHandle`]: https://docs.rs/gpio-cdev/0.5.0/gpio_cdev/struct.LineHandle.html
10
- pub struct CdevPin ( pub gpio_cdev:: LineHandle , gpio_cdev:: LineInfo ) ;
14
+ #[ derive( Debug ) ]
15
+ pub struct CdevPin ( pub Option < gpio_cdev:: LineHandle > , gpio_cdev:: LineInfo ) ;
16
+
17
+ #[ cfg( feature = "async-tokio" ) ]
18
+ #[ derive( Debug ) ]
19
+ struct CdevPinEdgeWaiter < ' a > {
20
+ pin : & ' a mut CdevPin ,
21
+ edge : EdgeDetection ,
22
+ }
23
+
24
+ #[ cfg( feature = "async-tokio" ) ]
25
+ impl < ' a > CdevPinEdgeWaiter < ' a > {
26
+ pub fn new ( pin : & ' a mut CdevPin , edge : EdgeDetection ) -> Result < Self , gpiocdev:: Error > {
27
+ Ok ( Self { pin, edge } )
28
+ }
29
+
30
+ pub async fn wait ( self ) -> Result < ( ) , gpiocdev:: Error > {
31
+ let line_handle = self . pin . 0 . take ( ) . unwrap ( ) ;
32
+ let line_info = & self . pin . 1 ;
33
+
34
+ let line = line_handle. line ( ) . clone ( ) ;
35
+ let flags = line_handle. flags ( ) ;
36
+ let chip = line. chip ( ) . path ( ) . to_owned ( ) ;
37
+ let offset = line. offset ( ) ;
38
+ let consumer = line_info. consumer ( ) . unwrap_or ( "" ) . to_owned ( ) ;
39
+ let edge = self . edge ;
40
+
41
+ // Close line handle.
42
+ drop ( line_handle) ;
43
+
44
+ let req = Request :: builder ( )
45
+ . on_chip ( chip)
46
+ . with_line ( offset)
47
+ . as_is ( )
48
+ . with_consumer ( consumer. clone ( ) )
49
+ . with_edge_detection ( edge)
50
+ . request ( ) ?;
51
+
52
+ let req = AsyncRequest :: new ( req) ;
53
+ let event = req. read_edge_event ( ) . await ;
54
+ drop ( req) ;
55
+
56
+ // Recreate line handle.
57
+ self . pin . 0 = Some ( line. request ( flags, 0 , & consumer) . unwrap ( ) ) ;
58
+
59
+ event?;
60
+
61
+ Ok ( ( ) )
62
+ }
63
+ }
11
64
12
65
impl CdevPin {
13
66
/// See [`gpio_cdev::Line::request`][0] for details.
14
67
///
15
68
/// [0]: https://docs.rs/gpio-cdev/0.5.0/gpio_cdev/struct.Line.html#method.request
16
69
pub fn new ( handle : gpio_cdev:: LineHandle ) -> Result < Self , gpio_cdev:: errors:: Error > {
17
70
let info = handle. line ( ) . info ( ) ?;
18
- Ok ( CdevPin ( handle, info) )
71
+ Ok ( CdevPin ( Some ( handle) , info) )
72
+ }
73
+
74
+ fn line_handle ( & self ) -> & gpio_cdev:: LineHandle {
75
+ self . 0 . as_ref ( ) . unwrap ( )
19
76
}
20
77
21
78
fn get_input_flags ( & self ) -> gpio_cdev:: LineRequestFlags {
@@ -43,7 +100,7 @@ impl CdevPin {
43
100
if self . 1 . direction ( ) == gpio_cdev:: LineDirection :: In {
44
101
return Ok ( self ) ;
45
102
}
46
- let line = self . 0 . line ( ) . clone ( ) ;
103
+ let line = self . line_handle ( ) . line ( ) . clone ( ) ;
47
104
let input_flags = self . get_input_flags ( ) ;
48
105
let consumer = self . 1 . consumer ( ) . unwrap_or ( "" ) . to_owned ( ) ;
49
106
@@ -62,7 +119,7 @@ impl CdevPin {
62
119
return Ok ( self ) ;
63
120
}
64
121
65
- let line = self . 0 . line ( ) . clone ( ) ;
122
+ let line = self . line_handle ( ) . line ( ) . clone ( ) ;
66
123
let output_flags = self . get_output_flags ( ) ;
67
124
let consumer = self . 1 . consumer ( ) . unwrap_or ( "" ) . to_owned ( ) ;
68
125
@@ -138,7 +195,7 @@ impl embedded_hal::digital::ErrorType for CdevPin {
138
195
139
196
impl embedded_hal:: digital:: OutputPin for CdevPin {
140
197
fn set_low ( & mut self ) -> Result < ( ) , Self :: Error > {
141
- self . 0
198
+ self . line_handle ( )
142
199
. set_value ( state_to_value (
143
200
embedded_hal:: digital:: PinState :: Low ,
144
201
self . 1 . is_active_low ( ) ,
@@ -147,7 +204,7 @@ impl embedded_hal::digital::OutputPin for CdevPin {
147
204
}
148
205
149
206
fn set_high ( & mut self ) -> Result < ( ) , Self :: Error > {
150
- self . 0
207
+ self . line_handle ( )
151
208
. set_value ( state_to_value (
152
209
embedded_hal:: digital:: PinState :: High ,
153
210
self . 1 . is_active_low ( ) ,
@@ -156,9 +213,9 @@ impl embedded_hal::digital::OutputPin for CdevPin {
156
213
}
157
214
}
158
215
159
- impl embedded_hal :: digital :: InputPin for CdevPin {
216
+ impl InputPin for CdevPin {
160
217
fn is_high ( & mut self ) -> Result < bool , Self :: Error > {
161
- self . 0
218
+ self . line_handle ( )
162
219
. get_value ( )
163
220
. map ( |val| {
164
221
val == state_to_value (
@@ -178,12 +235,49 @@ impl core::ops::Deref for CdevPin {
178
235
type Target = gpio_cdev:: LineHandle ;
179
236
180
237
fn deref ( & self ) -> & Self :: Target {
181
- & self . 0
238
+ self . line_handle ( )
182
239
}
183
240
}
184
241
185
242
impl core:: ops:: DerefMut for CdevPin {
186
243
fn deref_mut ( & mut self ) -> & mut Self :: Target {
187
- & mut self . 0
244
+ self . 0 . as_mut ( ) . unwrap ( )
245
+ }
246
+ }
247
+
248
+ #[ cfg( feature = "async-tokio" ) ]
249
+ impl embedded_hal_async:: digital:: Wait for CdevPin {
250
+ async fn wait_for_high ( & mut self ) -> Result < ( ) , Self :: Error > {
251
+ if self . is_high ( ) ? {
252
+ return Ok ( ( ) ) ;
253
+ }
254
+
255
+ self . wait_for_rising_edge ( ) . await
256
+ }
257
+
258
+ async fn wait_for_low ( & mut self ) -> Result < ( ) , Self :: Error > {
259
+ if self . is_low ( ) ? {
260
+ return Ok ( ( ) ) ;
261
+ }
262
+
263
+ self . wait_for_falling_edge ( ) . await
264
+ }
265
+
266
+ async fn wait_for_rising_edge ( & mut self ) -> Result < ( ) , Self :: Error > {
267
+ let waiter = CdevPinEdgeWaiter :: new ( self , EdgeDetection :: RisingEdge ) . unwrap ( ) ;
268
+ waiter. wait ( ) . await . unwrap ( ) ;
269
+ Ok ( ( ) )
270
+ }
271
+
272
+ async fn wait_for_falling_edge ( & mut self ) -> Result < ( ) , Self :: Error > {
273
+ let waiter = CdevPinEdgeWaiter :: new ( self , EdgeDetection :: FallingEdge ) . unwrap ( ) ;
274
+ waiter. wait ( ) . await . unwrap ( ) ;
275
+ Ok ( ( ) )
276
+ }
277
+
278
+ async fn wait_for_any_edge ( & mut self ) -> Result < ( ) , Self :: Error > {
279
+ let waiter = CdevPinEdgeWaiter :: new ( self , EdgeDetection :: BothEdges ) . unwrap ( ) ;
280
+ waiter. wait ( ) . await . unwrap ( ) ;
281
+ Ok ( ( ) )
188
282
}
189
283
}
0 commit comments