1
1
//! Blocking APIs on top of the base radio traits
2
- //!
3
- //! These implementations use the radio's DelayUs implementation to
2
+ //!
3
+ //! These implementations use the radio's DelayUs implementation to
4
4
//! poll on completion of operations.
5
- //!
5
+ //!
6
6
//! ## https://github.com/ryankurte/rust-radio
7
7
//! ## Copyright 2020 Ryan Kurte
8
8
9
+ use core:: fmt:: Debug ;
9
10
use core:: time:: Duration ;
10
11
11
12
use embedded_hal:: delay:: blocking:: DelayUs ;
12
13
13
- #[ cfg( feature= "structopt" ) ]
14
+ #[ cfg( feature = "structopt" ) ]
14
15
use structopt:: StructOpt ;
15
16
16
- #[ cfg( feature= "std" ) ]
17
+ #[ cfg( feature = "std" ) ]
17
18
use crate :: std:: string:: ToString ;
18
19
19
- use crate :: { Transmit , Receive , State } ;
20
+ use crate :: { Receive , State , Transmit } ;
20
21
21
22
/// BlockingOptions for blocking radio functions
22
23
#[ derive( Clone , PartialEq , Debug ) ]
23
- #[ cfg_attr( feature= "structopt" , derive( StructOpt ) ) ]
24
+ #[ cfg_attr( feature = "structopt" , derive( StructOpt ) ) ]
24
25
pub struct BlockingOptions {
25
26
/// Interval for polling for device state
26
27
#[ cfg_attr( feature="structopt" , structopt( long, default_value="100us" , parse( try_from_str=crate :: duration_from_str) ) ) ]
@@ -42,20 +43,25 @@ impl Default for BlockingOptions {
42
43
43
44
/// BlockingError wraps radio error type to provie a `Timeout` variant
44
45
#[ derive( Clone , Debug , PartialEq ) ]
46
+ #[ cfg_attr( feature = "thiserror" , derive( thiserror:: Error ) ) ]
45
47
pub enum BlockingError < E > {
48
+ #[ cfg_attr( feature = "thiserror" , error( "Inner: {0}" ) ) ]
46
49
Inner ( E ) ,
50
+ #[ cfg_attr( feature = "thiserror" , error( "Timeout" ) ) ]
47
51
Timeout ,
48
52
}
49
53
50
- impl < E > From < E > for BlockingError < E > {
54
+ impl < E > From < E > for BlockingError < E > {
51
55
fn from ( e : E ) -> Self {
52
56
BlockingError :: Inner ( e)
53
57
}
54
58
}
55
59
56
- /// Blocking transmit function implemented over `radio::Transmit` and `radio::Power` using the provided
60
+ /// Blocking transmit function implemented over `radio::Transmit` and `radio::Power` using the provided
57
61
/// `BlockingOptions` and radio-internal `DelayUs` impl to poll for completion
58
- #[ cfg_attr( feature = "mock" , doc = r##"
62
+ #[ cfg_attr(
63
+ feature = "mock" ,
64
+ doc = r##"
59
65
```
60
66
# use radio::*;
61
67
# use radio::mock::*;
@@ -75,18 +81,27 @@ assert_eq!(res, Ok(()));
75
81
76
82
# radio.done();
77
83
```
78
- "## ) ]
84
+ "##
85
+ ) ]
79
86
///
80
- pub trait BlockingTransmit < E > {
81
- fn do_transmit ( & mut self , data : & [ u8 ] , tx_options : BlockingOptions ) -> Result < ( ) , BlockingError < E > > ;
87
+ pub trait BlockingTransmit < E : Debug > {
88
+ fn do_transmit (
89
+ & mut self ,
90
+ data : & [ u8 ] ,
91
+ tx_options : BlockingOptions ,
92
+ ) -> Result < ( ) , BlockingError < E > > ;
82
93
}
83
94
84
- impl < T , E > BlockingTransmit < E > for T
85
- where
95
+ impl < T , E > BlockingTransmit < E > for T
96
+ where
86
97
T : Transmit < Error = E > + DelayUs < u32 > ,
87
- E : core :: fmt :: Debug ,
98
+ E : Debug ,
88
99
{
89
- fn do_transmit ( & mut self , data : & [ u8 ] , tx_options : BlockingOptions ) -> Result < ( ) , BlockingError < E > > {
100
+ fn do_transmit (
101
+ & mut self ,
102
+ data : & [ u8 ] ,
103
+ tx_options : BlockingOptions ,
104
+ ) -> Result < ( ) , BlockingError < E > > {
90
105
// Enter transmit mode
91
106
self . start_transmit ( data) ?;
92
107
@@ -98,12 +113,12 @@ where
98
113
debug ! ( "Blocking send complete" ) ;
99
114
break ;
100
115
}
101
-
116
+
102
117
// Update poll time and timeout if overrun
103
118
c += tx_options. poll_interval . as_micros ( ) ;
104
119
if c > t {
105
120
debug ! ( "Blocking send timeout" ) ;
106
- return Err ( BlockingError :: Timeout )
121
+ return Err ( BlockingError :: Timeout ) ;
107
122
}
108
123
109
124
// Wait for next poll
@@ -114,9 +129,11 @@ where
114
129
}
115
130
}
116
131
117
- /// Blocking receive function implemented over `radio::Receive` using the provided `BlockingOptions`
132
+ /// Blocking receive function implemented over `radio::Receive` using the provided `BlockingOptions`
118
133
/// and radio-internal `DelayUs` impl to poll for completion
119
- #[ cfg_attr( feature = "mock" , doc = r##"
134
+ #[ cfg_attr(
135
+ feature = "mock" ,
136
+ doc = r##"
120
137
```
121
138
# use radio::*;
122
139
# use radio::mock::*;
@@ -125,7 +142,6 @@ use radio::blocking::{BlockingReceive, BlockingOptions};
125
142
let data = [0xaa, 0xbb];
126
143
let info = BasicInfo::new(-81, 0);
127
144
128
-
129
145
# let mut radio = MockRadio::new(&[
130
146
# Transaction::start_receive(None),
131
147
# Transaction::check_receive(true, Ok(false)),
@@ -135,45 +151,57 @@ let info = BasicInfo::new(-81, 0);
135
151
# ]);
136
152
#
137
153
154
+ // Setup buffer to read into
138
155
let mut buff = [0u8; 128];
139
- let mut i = BasicInfo::new(0, 0);
140
156
141
157
// Receive using a blocking call
142
- let res = radio.do_receive(&mut buff, &mut i, BlockingOptions::default());
158
+ let (n, info) = radio.do_receive(&mut buff, BlockingOptions::default())? ;
143
159
144
- assert_eq!(res, Ok( data.len() ));
160
+ assert_eq!(n, data.len());
145
161
assert_eq!(&buff[..data.len()], &data);
146
162
147
163
# radio.done();
164
+
165
+ # Ok::<(), anyhow::Error>(())
148
166
```
149
- "## ) ]
150
- ///
167
+ "##
168
+ ) ]
169
+ ///
151
170
pub trait BlockingReceive < I , E > {
152
- fn do_receive ( & mut self , buff : & mut [ u8 ] , info : & mut I , rx_options : BlockingOptions ) -> Result < usize , BlockingError < E > > ;
171
+ fn do_receive (
172
+ & mut self ,
173
+ buff : & mut [ u8 ] ,
174
+ rx_options : BlockingOptions ,
175
+ ) -> Result < ( usize , I ) , BlockingError < E > > ;
153
176
}
154
177
155
- impl < T , I , E > BlockingReceive < I , E > for T
178
+ impl < T , I , E > BlockingReceive < I , E > for T
156
179
where
157
- T : Receive < Info =I , Error =E > + DelayUs < u32 > ,
158
- I : core:: fmt:: Debug ,
159
- E : core:: fmt:: Debug ,
180
+ T : Receive < Info = I , Error = E > + DelayUs < u32 > ,
181
+ <T as Receive >:: Info : Debug ,
182
+ I : Debug ,
183
+ E : Debug ,
160
184
{
161
- fn do_receive ( & mut self , buff : & mut [ u8 ] , info : & mut I , rx_options : BlockingOptions ) -> Result < usize , BlockingError < E > > {
185
+ fn do_receive (
186
+ & mut self ,
187
+ buff : & mut [ u8 ] ,
188
+ rx_options : BlockingOptions ,
189
+ ) -> Result < ( usize , I ) , BlockingError < E > > {
162
190
// Start receive mode
163
191
self . start_receive ( ) ?;
164
192
165
193
let t = rx_options. timeout . as_micros ( ) ;
166
194
let mut c = 0 ;
167
195
loop {
168
196
if self . check_receive ( true ) ? {
169
- let n = self . get_received ( info , buff) ?;
170
- return Ok ( n )
197
+ let ( n , i ) = self . get_received ( buff) ?;
198
+ return Ok ( ( n , i ) ) ;
171
199
}
172
200
173
201
c += rx_options. poll_interval . as_micros ( ) ;
174
202
if c > t {
175
203
debug ! ( "Blocking receive timeout" ) ;
176
- return Err ( BlockingError :: Timeout )
204
+ return Err ( BlockingError :: Timeout ) ;
177
205
}
178
206
179
207
let _ = self . delay_us ( rx_options. poll_interval . as_micros ( ) as u32 ) ;
@@ -183,16 +211,24 @@ where
183
211
184
212
/// BlockingSetState sets the radio state and polls until command completion
185
213
pub trait BlockingSetState < S , E > {
186
- fn set_state_checked ( & mut self , state : S , options : BlockingOptions ) -> Result < ( ) , BlockingError < E > > ;
214
+ fn set_state_checked (
215
+ & mut self ,
216
+ state : S ,
217
+ options : BlockingOptions ,
218
+ ) -> Result < ( ) , BlockingError < E > > ;
187
219
}
188
220
189
- impl < T , S , E > BlockingSetState < S , E > for T
190
- where
191
- T : State < State = S , Error = E > + DelayUs < u32 > ,
192
- S : core :: fmt :: Debug + core:: cmp:: PartialEq + Copy ,
193
- E : core :: fmt :: Debug ,
221
+ impl < T , S , E > BlockingSetState < S , E > for T
222
+ where
223
+ T : State < State = S , Error = E > + DelayUs < u32 > ,
224
+ S : Debug + core:: cmp:: PartialEq + Copy ,
225
+ E : Debug ,
194
226
{
195
- fn set_state_checked ( & mut self , state : S , options : BlockingOptions ) -> Result < ( ) , BlockingError < E > > {
227
+ fn set_state_checked (
228
+ & mut self ,
229
+ state : S ,
230
+ options : BlockingOptions ,
231
+ ) -> Result < ( ) , BlockingError < E > > {
196
232
// Send set state command
197
233
self . set_state ( state) ?;
198
234
@@ -205,20 +241,18 @@ where
205
241
206
242
// Check for expected state
207
243
if state == s {
208
- return Ok ( ( ) )
244
+ return Ok ( ( ) ) ;
209
245
}
210
246
211
247
// Timeout eventually
212
248
c += options. poll_interval . as_micros ( ) ;
213
249
if c > t {
214
250
debug ! ( "Blocking receive timeout" ) ;
215
- return Err ( BlockingError :: Timeout )
251
+ return Err ( BlockingError :: Timeout ) ;
216
252
}
217
253
218
254
// Delay before next loop
219
255
let _ = self . delay_us ( options. poll_interval . as_micros ( ) as u32 ) ;
220
256
}
221
-
222
257
}
223
258
}
224
-
0 commit comments