@@ -5,11 +5,16 @@ use core::{
5
5
sync:: atomic:: { self , Ordering } ,
6
6
} ;
7
7
8
- use crate :: clocks:: { Clocks , ExternalOscillator } ;
9
- use crate :: pac:: {
10
- generic:: Variant ,
11
- radio:: { state:: STATE_A , txpower:: TXPOWER_A } ,
12
- RADIO ,
8
+ use embedded_hal:: timer:: CountDown as _;
9
+
10
+ use crate :: {
11
+ clocks:: { Clocks , ExternalOscillator } ,
12
+ pac:: {
13
+ generic:: Variant ,
14
+ radio:: { state:: STATE_A , txpower:: TXPOWER_A } ,
15
+ RADIO ,
16
+ } ,
17
+ timer:: { self , Timer } ,
13
18
} ;
14
19
15
20
/// IEEE 802.15.4 radio
@@ -244,6 +249,78 @@ impl<'c> Radio<'c> {
244
249
/// validated by the hardware; otherwise it returns the `Err` variant. In either case, `packet`
245
250
/// will be updated with the received packet's data
246
251
pub fn recv ( & mut self , packet : & mut Packet ) -> Result < u16 , u16 > {
252
+ // Start the read
253
+ self . start_recv ( packet) ;
254
+
255
+ // wait until we have received something
256
+ self . wait_for_event ( Event :: End ) ;
257
+ dma_end_fence ( ) ;
258
+
259
+ let crc = self . radio . rxcrc . read ( ) . rxcrc ( ) . bits ( ) as u16 ;
260
+ if self . radio . crcstatus . read ( ) . crcstatus ( ) . bit_is_set ( ) {
261
+ Ok ( crc)
262
+ } else {
263
+ Err ( crc)
264
+ }
265
+ }
266
+
267
+ /// Listens for a packet for no longer than the specified amount of milliseconds
268
+ ///
269
+ /// If no packet is received within the specified time then the `Timeout` error is returned
270
+ ///
271
+ /// If a packet is received within the time span then the packet CRC is checked. If the CRC is
272
+ /// incorrect then the `Crc` error is returned; otherwise the `Ok` variant is returned.
273
+ ///
274
+ /// Note that the time it takes to switch the radio to RX mode is included in the timeout count.
275
+ /// This transition may take up to a hundred of milliseconds; see the section 6.20.15.8 in the
276
+ /// Product Specification for more details about timing
277
+ pub fn recv_timeout < I > (
278
+ & mut self ,
279
+ packet : & mut Packet ,
280
+ timer : & mut Timer < I > ,
281
+ millis : u32 ,
282
+ ) -> Result < u16 , Error >
283
+ where
284
+ I : timer:: Instance ,
285
+ {
286
+ // Start the timeout timer
287
+ timer. start ( millis) ;
288
+
289
+ // Start the read
290
+ self . start_recv ( packet) ;
291
+
292
+ // Wait for transmission to end
293
+ let mut recv_completed = false ;
294
+
295
+ loop {
296
+ if self . radio . events_end . read ( ) . bits ( ) != 0 {
297
+ // transfer complete
298
+ dma_end_fence ( ) ;
299
+ recv_completed = true ;
300
+ break ;
301
+ }
302
+
303
+ if timer. wait ( ) . is_ok ( ) {
304
+ // timeout
305
+ break ;
306
+ }
307
+ }
308
+
309
+ if !recv_completed {
310
+ // Cancel the reception if it did not complete until now
311
+ self . cancel_recv ( ) ;
312
+ Err ( Error :: Timeout )
313
+ } else {
314
+ let crc = self . radio . rxcrc . read ( ) . rxcrc ( ) . bits ( ) as u16 ;
315
+ if self . radio . crcstatus . read ( ) . crcstatus ( ) . bit_is_set ( ) {
316
+ Ok ( crc)
317
+ } else {
318
+ Err ( Error :: Crc ( crc) )
319
+ }
320
+ }
321
+ }
322
+
323
+ fn start_recv ( & mut self , packet : & mut Packet ) {
247
324
// NOTE we do NOT check the address of `packet`; see comment in `Packet::new` for details
248
325
249
326
// clear related events
@@ -263,17 +340,13 @@ impl<'c> Radio<'c> {
263
340
// start transfer
264
341
dma_start_fence ( ) ;
265
342
self . radio . tasks_start . write ( |w| w. tasks_start ( ) . set_bit ( ) ) ;
343
+ }
266
344
267
- // wait until we have received something
268
- self . wait_for_event ( Event :: End ) ;
345
+ fn cancel_recv ( & mut self ) {
346
+ self . radio . tasks_stop . write ( |w| w. tasks_stop ( ) . set_bit ( ) ) ;
347
+ self . wait_for_state_a ( STATE_A :: RXIDLE ) ;
348
+ // DMA transfer may have been in progress so synchronize with its memory operations
269
349
dma_end_fence ( ) ;
270
-
271
- let crc = self . radio . rxcrc . read ( ) . rxcrc ( ) . bits ( ) as u16 ;
272
- if self . radio . crcstatus . read ( ) . crcstatus ( ) . bit_is_set ( ) {
273
- Ok ( crc)
274
- } else {
275
- Err ( crc)
276
- }
277
350
}
278
351
279
352
/// Tries to send the given `packet`
@@ -540,6 +613,15 @@ impl<'c> Radio<'c> {
540
613
}
541
614
}
542
615
616
+ /// Error
617
+ #[ derive( Copy , Clone , Debug , PartialEq ) ]
618
+ pub enum Error {
619
+ /// Incorrect CRC
620
+ Crc ( u16 ) ,
621
+ /// Timeout
622
+ Timeout ,
623
+ }
624
+
543
625
/// Driver state
544
626
///
545
627
/// After, or at the start of, any method call the RADIO will be in one of these states
0 commit comments