@@ -93,6 +93,7 @@ enum UsbCommand {
9393 AckEnable = 0x10 ,
9494 SetContCarrier = 0x20 ,
9595 // ScanChannels = 0x21,
96+ SetInlineMode = 0x23 ,
9697 SetPacketLossSimulation = 0x30 ,
9798 LaunchBootloader = 0xff ,
9899}
@@ -128,11 +129,13 @@ pub struct Crazyradio {
128129 device_handle : rusb:: DeviceHandle < rusb:: GlobalContext > ,
129130
130131 cache_settings : bool ,
132+ inline_mode : bool ,
131133
132134 // Settings cache
133135 channel : Channel ,
134136 address : [ u8 ; 5 ] ,
135137 datarate : Datarate ,
138+ ack_enable : bool ,
136139}
137140
138141impl Crazyradio {
@@ -190,10 +193,13 @@ impl Crazyradio {
190193 device_handle,
191194
192195 cache_settings : true ,
196+ inline_mode : false ,
193197
194198 channel : Channel :: from_number ( 2 ) . unwrap ( ) ,
195199 address : [ 0xe7 ; 5 ] ,
196200 datarate : Datarate :: Dr2M ,
201+
202+ ack_enable : true ,
197203 } ;
198204
199205 cr. reset ( ) ?;
@@ -220,6 +226,9 @@ impl Crazyradio {
220226 let prev_cache_settings = self . cache_settings ;
221227 self . cache_settings = false ;
222228
229+ // Try to set inline mode, ignore failure as this is not fatal (old radio FW do not implement it and will just be slower)
230+ _ = self . set_inline_mode ( true ) ;
231+
223232 self . set_datarate ( Datarate :: Dr2M ) ?;
224233 self . set_channel ( Channel :: from_number ( 2 ) . unwrap ( ) ) ?;
225234 self . set_cont_carrier ( false ) ?;
@@ -248,7 +257,7 @@ impl Crazyradio {
248257
249258 /// Set the radio channel.
250259 pub fn set_channel ( & mut self , channel : Channel ) -> Result < ( ) > {
251- if !self . cache_settings || self . channel != channel {
260+ if !self . inline_mode && ( ! self . cache_settings || self . channel != channel) {
252261 self . device_handle . write_control (
253262 0x40 ,
254263 UsbCommand :: SetRadioChannel as u8 ,
@@ -257,15 +266,16 @@ impl Crazyradio {
257266 & [ ] ,
258267 Duration :: from_secs ( 1 ) ,
259268 ) ?;
260- self . channel = channel;
261269 }
262270
271+ self . channel = channel;
272+
263273 Ok ( ( ) )
264274 }
265275
266276 /// Set the datarate.
267277 pub fn set_datarate ( & mut self , datarate : Datarate ) -> Result < ( ) > {
268- if !self . cache_settings || self . datarate != datarate {
278+ if !self . inline_mode && ( ! self . cache_settings || self . datarate != datarate) {
269279 self . device_handle . write_control (
270280 0x40 ,
271281 UsbCommand :: SetDataRate as u8 ,
@@ -274,15 +284,16 @@ impl Crazyradio {
274284 & [ ] ,
275285 Duration :: from_secs ( 1 ) ,
276286 ) ?;
277- self . datarate = datarate;
278287 }
279288
289+ self . datarate = datarate;
290+
280291 Ok ( ( ) )
281292 }
282293
283294 /// Set the radio address.
284295 pub fn set_address ( & mut self , address : & [ u8 ; 5 ] ) -> Result < ( ) > {
285- if !self . cache_settings || self . address != * address {
296+ if !self . inline_mode && ( ! self . cache_settings || self . address != * address) {
286297 self . device_handle . write_control (
287298 0x40 ,
288299 UsbCommand :: SetRadioAddress as u8 ,
@@ -291,6 +302,9 @@ impl Crazyradio {
291302 address,
292303 Duration :: from_secs ( 1 ) ,
293304 ) ?;
305+ }
306+
307+ if self . cache_settings || self . inline_mode {
294308 self . address . copy_from_slice ( address) ;
295309 }
296310
@@ -367,14 +381,19 @@ impl Crazyradio {
367381 ///
368382 /// Should be disabled when sending broadcast packets.
369383 pub fn set_ack_enable ( & mut self , ack_enable : bool ) -> Result < ( ) > {
370- self . device_handle . write_control (
371- 0x40 ,
372- UsbCommand :: AckEnable as u8 ,
373- ack_enable as u16 ,
374- 0 ,
375- & [ ] ,
376- Duration :: from_secs ( 1 ) ,
377- ) ?;
384+ if !self . inline_mode && ack_enable != self . ack_enable {
385+ self . device_handle . write_control (
386+ 0x40 ,
387+ UsbCommand :: AckEnable as u8 ,
388+ ack_enable as u16 ,
389+ 0 ,
390+ & [ ] ,
391+ Duration :: from_secs ( 1 ) ,
392+ ) ?;
393+ }
394+
395+ self . ack_enable = ack_enable;
396+
378397 Ok ( ( ) )
379398 }
380399
@@ -431,6 +450,33 @@ impl Crazyradio {
431450 Ok ( ( ) )
432451 }
433452
453+ /// Set inline-settings USB protocol mode
454+ ///
455+ /// When this mode is enabled, setting channel, datarate, address and
456+ /// ack_enable will become cached operations, and these settings
457+ /// will be sent as header to the data over USB. This increases performance
458+ /// when communicating with more than one PRX.
459+ ///
460+ /// This mode, if available, is activated by default when creating the Crazyradio
461+ /// object.
462+ ///
463+ /// This mode is only available with Crazyradio 2.0+
464+ pub fn set_inline_mode ( & mut self , inline_mode_enable : bool ) -> Result < ( ) > {
465+ let setting = inline_mode_enable. then_some ( 1 ) . unwrap_or ( 0 ) ;
466+
467+ self . device_handle . write_control (
468+ 0x40 ,
469+ UsbCommand :: SetInlineMode as u8 ,
470+ setting,
471+ 0 ,
472+ & [ ] ,
473+ Duration :: from_secs ( 1 ) ,
474+ ) ?;
475+ self . inline_mode = inline_mode_enable;
476+
477+ Ok ( ( ) )
478+ }
479+
434480 /// Set packet loss simulation.
435481 ///
436482 pub fn set_packet_loss_simulation ( & mut self , packet_loss_percent : u8 , ack_loss_percent : u8 ) -> Result < ( ) > {
@@ -465,28 +511,34 @@ impl Crazyradio {
465511 /// be truncated. The length of the ack payload is returned
466512 /// in Ack::length.
467513 pub fn send_packet ( & mut self , data : & [ u8 ] , ack_data : & mut [ u8 ] ) -> Result < Ack > {
468- self . device_handle
469- . write_bulk ( 0x01 , data, Duration :: from_secs ( 1 ) ) ?;
470- let mut received_data = [ 0u8 ; 33 ] ;
471- let received =
472- self . device_handle
473- . read_bulk ( 0x81 , & mut received_data, Duration :: from_secs ( 1 ) ) ?;
474514
475- if ack_data . len ( ) <= 32 {
476- ack_data . copy_from_slice ( & received_data [ 1 ..ack_data . len ( ) + 1 ] ) ;
515+ if self . inline_mode {
516+ self . send_inline ( data , Some ( ack_data ) )
477517 } else {
478- ack_data
479- . split_at_mut ( 32 )
480- . 0
481- . copy_from_slice ( & received_data[ 1 ..33 ] ) ;
482- }
518+ self . device_handle
519+ . write_bulk ( 0x01 , data, Duration :: from_secs ( 1 ) ) ?;
520+ let mut received_data = [ 0u8 ; 33 ] ;
521+ let received =
522+ self . device_handle
523+ . read_bulk ( 0x81 , & mut received_data, Duration :: from_secs ( 1 ) ) ?;
524+
525+ if ack_data. len ( ) <= 32 {
526+ ack_data. copy_from_slice ( & received_data[ 1 ..ack_data. len ( ) + 1 ] ) ;
527+ } else {
528+ ack_data
529+ . split_at_mut ( 32 )
530+ . 0
531+ . copy_from_slice ( & received_data[ 1 ..33 ] ) ;
532+ }
483533
484- Ok ( Ack {
485- received : received_data[ 0 ] & 0x01 != 0 ,
486- power_detector : received_data[ 0 ] & 0x02 != 0 ,
487- retry : ( ( received_data[ 0 ] & 0xf0 ) >> 4 ) as usize ,
488- length : received - 1 ,
489- } )
534+ Ok ( Ack {
535+ received : received_data[ 0 ] & 0x01 != 0 ,
536+ power_detector : received_data[ 0 ] & 0x02 != 0 ,
537+ retry : ( ( received_data[ 0 ] & 0xf0 ) >> 4 ) as usize ,
538+ length : received - 1 ,
539+ } )
540+ }
541+
490542 }
491543
492544 /// Send a data packet without caring for Ack (for broadcast communication).
@@ -495,11 +547,57 @@ impl Crazyradio {
495547 ///
496548 /// * `data`: Up to 32 bytes of data to be send.
497549 pub fn send_packet_no_ack ( & mut self , data : & [ u8 ] ) -> Result < ( ) > {
498- self . device_handle
499- . write_bulk ( 0x01 , data, Duration :: from_secs ( 1 ) ) ?;
550+ if self . inline_mode {
551+ self . send_inline ( data, None ) ?;
552+ } else {
553+ self . device_handle
554+ . write_bulk ( 0x01 , data, Duration :: from_secs ( 1 ) ) ?;
555+ }
500556
501557 Ok ( ( ) )
502558 }
559+
560+ fn send_inline ( & mut self , data : & [ u8 ] , ack_data : Option < & mut [ u8 ] > ) -> Result < Ack > {
561+ const OUT_HEADER_LENGTH : usize =8 ;
562+ const IN_HEADER_LENGTH : usize = 2 ;
563+
564+ const OUT_FIELD2_ACK_ENABLE : u8 = 0x10 ;
565+
566+ const IN_HEADER_ACK_RECEIVED : u8 = 0x01 ;
567+ const IN_HEADER_POWER_DETECTOR : u8 = 0x02 ;
568+ const _IN_HEADER_INVALID_SETTING: u8 = 0x04 ;
569+ const IN_HEADER_RETRY_MASK : u8 = 0xf0 ;
570+ const IN_HEADER_RETRY_SHIFT : u8 = 4 ;
571+
572+ // Assemble out command
573+ let mut command = vec ! [ ] ;
574+ command. push ( ( OUT_HEADER_LENGTH + data. len ( ) ) as u8 ) ;
575+ let mut field2 = self . datarate as u8 ;
576+ if self . ack_enable {
577+ field2 |= OUT_FIELD2_ACK_ENABLE ;
578+ }
579+ command. push ( field2) ;
580+ command. push ( self . channel . into ( ) ) ;
581+ command. extend_from_slice ( & self . address ) ;
582+ command. extend_from_slice ( & data) ;
583+
584+ let mut answer = [ 0u8 ; 64 ] ;
585+ self . device_handle . write_bulk ( 0x01 , & command, Duration :: from_secs ( 1 ) ) ?;
586+ self . device_handle . read_bulk ( 0x81 , & mut answer, Duration :: from_secs ( 1 ) ) ?;
587+
588+ // Decode answer
589+ let payload_length = ( answer[ 0 ] as usize ) - 2 ;
590+ if let Some ( ack_data) = ack_data {
591+ ack_data[ 0 ..payload_length] . copy_from_slice ( & answer[ IN_HEADER_LENGTH ..( IN_HEADER_LENGTH +payload_length) ] ) ;
592+ }
593+
594+ Ok ( Ack {
595+ received : answer[ 1 ] & IN_HEADER_ACK_RECEIVED != 0 ,
596+ power_detector : answer[ 1 ] & IN_HEADER_POWER_DETECTOR != 0 ,
597+ retry : ( ( answer[ 1 ] & IN_HEADER_RETRY_MASK ) >> IN_HEADER_RETRY_SHIFT ) as usize ,
598+ length : payload_length,
599+ } )
600+ }
503601}
504602
505603/// # Async implementations
0 commit comments