From 164a09fc11cec2d8b15b38e8b512fa542d6cecc7 Mon Sep 17 00:00:00 2001 From: Dimitri Stolnikov Date: Sun, 28 Feb 2016 17:52:01 +0100 Subject: [PATCH] airspy: Option pack={0,1} to enable USB bit packing Patch provided by Martin Smith. 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. --- lib/airspy/airspy_source_c.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/airspy/airspy_source_c.cc b/lib/airspy/airspy_source_c.cc index 3c1bbb4..25f73d4 100644 --- a/lib/airspy/airspy_source_c.cc +++ b/lib/airspy/airspy_source_c.cc @@ -153,6 +153,16 @@ airspy_source_c::airspy_source_c (const std::string &args) 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( dict["pack"] ); + int ret = airspy_set_packing(_dev, (uint8_t)pack); + AIRSPY_THROW_ON_ERROR(ret, "Failed to set USB bit packing") + } + _fifo = new boost::circular_buffer(5000000); if (!_fifo) { throw std::runtime_error( std::string(__FUNCTION__) + " " +