Airspy patch to enable USB bit packing

Martin Smith martin_z_smith at yahoo.ie
Mon Jan 11 00:29:12 UTC 2016


Last July there were several changes made to the Airspy firmware and
libairspy that added support for a new bit packing mode where 4 sets of
12 bit samples are packed into 3 sets of 16 bits for the transfer across
the USB bus ( https://i.imgur.com/qXnWoEK.png?1 ). 25% less data is
transferred across the bus and this is good for some computers with
cheap USB chipsets. There is an overhead of extra memory bandwidth
required on the host side to unpack the data into a useful format, so
for optimal performance bit packing is disabled by default.

The data is automatically unpacked within libairspy before being passed
along, so no changes are required anywhere else if packing is enabled
(or not enabled). Airspy firmware older than v1.0.0-rc6 does not have
the function, but that is detected and handled by libairspy. 

I wrote the attached patch to enable packing in gr-osmosdr, which I
tested and it works. It is basically a clone of the bias=0|1 lines as
pack=0|1 and calls the needed libairspy function.

ref:
https://github.com/airspy/firmware/commit/7e1806b
https://github.com/airspy/firmware/commit/5b7dcab
https://github.com/airspy/host/commit/a51eccb


---
Do some Baseline test with Airspy command line tools to have something
to compare USB throughput results
--------------------------------------------------------------------------------------------------------
$ sudo mount -t debugfs none /sys/kernel/debug
$ sudo modprobe usbmon
$ wireshark -i usbmod3 &
$ airspy_info ; sleep 120 ; \
airspy_rx -t 4 -r /dev/null -n 2400000000 ; sleep 120 ; \
airspy_rx -t 4 -r /dev/null -p 1 -n 2400000000 ; sleep 120 ; \
airspy_info
Wireshark->Statistics->IO Graph
The Bytes/Tick are double the actual data rate because of way wireshark
collects the USB packets, I could have added a filter to fix this. But
the relationship is valid 25% less with packing enabled. The data rate
in the IO Grahp drops from 80MB/sec (in+out) [really 40MB/sec] to
60MB/second (in+out) [really 30MB/sec] from unpacked to packed.
10MSPS no packing, packing https://i.imgur.com/pA9LPdE.png?1
2.5MSPS no packing, packing https://i.imgur.com/lA8q5aq.png?1


Verification test with my patched gr-osmosdr
--------------------------------------------
$ sudo mount -t debugfs none /sys/kernel/debug
$ sudo modprobe usbmon
$ wireshark -i usbmod3 &
$ osmocom_fft -a "airspy=0" -s 10000000 --fft-rate=1
$ osmocom_fft -a "airspy=0,pack=1" -s 10000000 --fft-rate=1
$ osmocom_fft -a "airspy=0" -s 2500000 --fft-rate=1
$ osmocom_fft -a "airspy=0,pack=1" -s 2500000 --fft-rate=1
$ osmocom_fft -a "airspy=0" -s 2500000 --fft-rate=1
$ osmocom_fft -a "airspy=0,pack=0" -s 2500000 --fft-rate=1

I ran all of the above tests and the wireshark USB throughput graphs
showed exactly what was expected.
40MB/sec(10MSPS+normal),30MB/sec(10MSPS+packing),10MB/sec(2.5MSPS+normal),7.5MB/sec(2.5MSPS+packing),10MB/sec(2.5MSPS+normal),10MB/sec(2.5MSPS+normal).

25% less when packing was enabled and if you did not specify the
"pack=1", then no bit packing is performed by libairspy. All the
magnitudes within the FFT windows looked exactly the same as they do
without bit packing.
-------------- next part --------------
--- gr-osmosdr.orig/lib/airspy/airspy_source_c.cc	2016-01-10 23:38:03.590425152 +0000
+++ gr-osmosdr/lib/airspy/airspy_source_c.cc	2016-01-10 23:41:04.356672407 +0000
@@ -153,6 +153,16 @@
     AIRSPY_THROW_ON_ERROR(ret, "Failed to enable DC bias")
   }
 
+/* pack 4 sets of 12 bits into 3 sets 16 bits for the data transfer across the
+ * USB bus. The default is is unpacked, to transfer 12 bits across the USB bus
+ * in 16 bit words. libairspy transparently unpacks if packing is enabled */
+  if ( dict.count( "pack" ) )
+  {
+    bool pack = boost::lexical_cast<bool>( dict["pack"] );
+    int ret = airspy_set_packing(_dev, (uint8_t)pack);
+    AIRSPY_THROW_ON_ERROR(ret, "Failed to enable USB bit packing")
+  }
+
   _fifo = new boost::circular_buffer<gr_complex>(5000000);
   if (!_fifo) {
     throw std::runtime_error( std::string(__FUNCTION__) + " " +


More information about the osmocom-sdr mailing list