pothosware / SoapyBladeRF

Soapy SDR plugin for the Blade RF
https://github.com/pothosware/SoapyBladeRF/wiki
23 stars 20 forks source link

Build fails against libbladerf 2.0 #17

Closed sparklespdx closed 6 years ago

sparklespdx commented 6 years ago

Hello folks,

I have an interest in using the Soapy python bindings with one of the new BladeRF Micro A4 boards. Unfortunately, I have run into problems trying to build SoapyBladeRF against versions of libbladerf that support the new board.

I have created 2 docker containers to help folks replicate my issue. They build the software in an Ubuntu 18.04 environment: https://gist.github.com/sparklespdx/da169dc2614cf8d5f88751cabd9bc598

You can build and run the containers with something like this:

sudo docker build -f Dockerfile.bladeRF_git_2017.12-rc1 -t soapybladerf-build-test-case-1 . && \
sudo docker run -it --rm soapybladerf-build-test-case-1

The first container builds BladeRF release 2017.12-rc1 and Soapy, and then SoapyBladeRF. This is the version of BladeRF from the PPAs. This build works, but none of the software recognizes the A4 board. I made this test case mainly to validate that my build environment works.

The second container builds BladeRF and Soapy from the current master branch successfully. It tries to build SoapyBladeRF but the build fails. See the output below.

I am not sure if this is an easy or hard problem to solve; I am unfamiliar with the code base. I am going to at least make an attempt to figure out what's wrong and make a PR if I get somewhere. Any help or advice would be much appreciated.

Build failure output:

Step 18/20 : RUN cmake ../ && make && make install && ldconfig
 ---> Running in a260660b7386
-- The CXX compiler identification is GNU 7.3.0
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Build type not specified: defaulting to release.
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.1") 
-- Checking for module 'libbladeRF'
--   Found libbladeRF, version 2.0.0-git-074f7373-dirty
-- Found libbladeRF: /usr/local/include, /usr/local/lib/libbladeRF.so
-- LIBBLADERF_INCLUDE_DIRS - /usr/local/include
-- LIBBLADERF_LIBRARIES - /usr/local/lib/libbladeRF.so
-- Checking for bladerf_set_gain_mode API...
--   Reading /usr/local/include/libbladeRF.h...
--   libbladeRF supports the bladerf_set_gain_mode API
-- Performing Test HAS_STD_CXX11
-- Performing Test HAS_STD_CXX11 - Success
-- Found Git: /usr/bin/git (found version "2.17.1") 
-- Module bladeRFSupport configured with version: 0.3.5-4fa4566
-- Configuring done
-- Generating done
-- Build files have been written to: /work/SoapyBladeRF/build
Scanning dependencies of target bladeRFSupport
[ 20%] Building CXX object CMakeFiles/bladeRFSupport.dir/bladeRF_Registation.cpp.o
[ 40%] Building CXX object CMakeFiles/bladeRFSupport.dir/bladeRF_Settings.cpp.o
/work/SoapyBladeRF/bladeRF_Settings.cpp: In member function 'virtual double bladeRF_SoapySDR::getFrequency(int, size_t, const string&) const':
/work/SoapyBladeRF/bladeRF_Settings.cpp:411:69: error: cannot convert 'unsigned int*' to 'bladerf_frequency* {aka long unsigned int*}' for argument '3' to 'int bladerf_get_frequency(bladerf*, bladerf_channel, bladerf_frequency*)'
     int ret = bladerf_get_frequency(_dev, _dir2mod(direction), &freq);
                                                                     ^
In file included from /work/SoapyBladeRF/bladeRF_SoapySDR.hpp:26:0,
                 from /work/SoapyBladeRF/bladeRF_Settings.cpp:22:
/work/SoapyBladeRF/bladeRF_Settings.cpp: In member function 'virtual long long int bladeRF_SoapySDR::getHardwareTime(const string&) const':
/work/SoapyBladeRF/bladeRF_Settings.cpp:570:49: error: invalid conversion from 'bladerf_channel {aka int}' to 'bladerf_direction' [-fpermissive]
     const int ret = bladerf_get_timestamp(_dev, BLADERF_MODULE_RX, &ticksNow);
                                                 ^
/usr/local/include/libbladeRF.h:2345:15: note:   initializing argument 2 of 'int bladerf_get_timestamp(bladerf*, bladerf_direction, bladerf_timestamp*)'
 int CALL_CONV bladerf_get_timestamp(struct bladerf *dev,
               ^~~~~~~~~~~~~~~~~~~~~
/work/SoapyBladeRF/bladeRF_Settings.cpp: In member function 'virtual void bladeRF_SoapySDR::writeSetting(const string&, const string&)':
/work/SoapyBladeRF/bladeRF_Settings.cpp:823:50: error: 'bladerf_module' is not a class, namespace, or enumeration
                     bladerf_xb200_set_path(_dev, bladerf_module::BLADERF_MODULE_RX, bladerf_xb200_path::BLADERF_XB200_BYPASS);
                                                  ^~~~~~~~~~~~~~
In file included from /work/SoapyBladeRF/bladeRF_SoapySDR.hpp:26:0,
                 from /work/SoapyBladeRF/bladeRF_Settings.cpp:22:
/work/SoapyBladeRF/bladeRF_Settings.cpp:823:66: error: expected unqualified-id before '(' token
                     bladerf_xb200_set_path(_dev, bladerf_module::BLADERF_MODULE_RX, bladerf_xb200_path::BLADERF_XB200_BYPASS);
                                                                  ^
/work/SoapyBladeRF/bladeRF_Settings.cpp:823:66: error: expected primary-expression before ')' token
                     bladerf_xb200_set_path(_dev, bladerf_module::BLADERF_MODULE_RX, bladerf_xb200_path::BLADERF_XB200_BYPASS);
                                                                  ^
/work/SoapyBladeRF/bladeRF_Settings.cpp:889:58: error: 'bladerf_module' is not a class, namespace, or enumeration
             int ret = bladerf_xb200_set_filterbank(_dev, bladerf_module::BLADERF_MODULE_RX, filter);
                                                          ^~~~~~~~~~~~~~
In file included from /work/SoapyBladeRF/bladeRF_SoapySDR.hpp:26:0,
                 from /work/SoapyBladeRF/bladeRF_Settings.cpp:22:
/work/SoapyBladeRF/bladeRF_Settings.cpp:889:74: error: expected unqualified-id before '(' token
             int ret = bladerf_xb200_set_filterbank(_dev, bladerf_module::BLADERF_MODULE_RX, filter);
                                                                          ^
/work/SoapyBladeRF/bladeRF_Settings.cpp:889:74: error: expected primary-expression before ')' token
             int ret = bladerf_xb200_set_filterbank(_dev, bladerf_module::BLADERF_MODULE_RX, filter);
                                                                          ^
/work/SoapyBladeRF/bladeRF_Settings.cpp:898:42: error: 'bladerf_module' is not a class, namespace, or enumeration
             bladerf_xb200_get_path(_dev, bladerf_module::BLADERF_MODULE_RX, &_bladerf_xb200_path);
                                          ^~~~~~~~~~~~~~
In file included from /work/SoapyBladeRF/bladeRF_SoapySDR.hpp:26:0,
                 from /work/SoapyBladeRF/bladeRF_Settings.cpp:22:
/work/SoapyBladeRF/bladeRF_Settings.cpp:898:58: error: expected unqualified-id before '(' token
             bladerf_xb200_get_path(_dev, bladerf_module::BLADERF_MODULE_RX, &_bladerf_xb200_path);
                                                          ^
/work/SoapyBladeRF/bladeRF_Settings.cpp:898:58: error: expected primary-expression before ')' token
             bladerf_xb200_get_path(_dev, bladerf_module::BLADERF_MODULE_RX, &_bladerf_xb200_path);
                                                          ^
/work/SoapyBladeRF/bladeRF_Settings.cpp:903:46: error: 'bladerf_module' is not a class, namespace, or enumeration
                 bladerf_xb200_set_path(_dev, bladerf_module::BLADERF_MODULE_RX, bladerf_xb200_path::BLADERF_XB200_MIX);
                                              ^~~~~~~~~~~~~~
In file included from /work/SoapyBladeRF/bladeRF_SoapySDR.hpp:26:0,
                 from /work/SoapyBladeRF/bladeRF_Settings.cpp:22:
/work/SoapyBladeRF/bladeRF_Settings.cpp:903:62: error: expected unqualified-id before '(' token
                 bladerf_xb200_set_path(_dev, bladerf_module::BLADERF_MODULE_RX, bladerf_xb200_path::BLADERF_XB200_MIX);
                                                              ^
/work/SoapyBladeRF/bladeRF_Settings.cpp:903:62: error: expected primary-expression before ')' token
                 bladerf_xb200_set_path(_dev, bladerf_module::BLADERF_MODULE_RX, bladerf_xb200_path::BLADERF_XB200_MIX);
                                                              ^
make[2]: *** [CMakeFiles/bladeRFSupport.dir/bladeRF_Settings.cpp.o] Error 1
CMakeFiles/bladeRFSupport.dir/build.make:86: recipe for target 'CMakeFiles/bladeRFSupport.dir/bladeRF_Settings.cpp.o' failed
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/bladeRFSupport.dir/all' failed
make[1]: *** [CMakeFiles/bladeRFSupport.dir/all] Error 2
make: *** [all] Error 2
Makefile:129: recipe for target 'all' failed
The command '/bin/sh -c cmake ../ && make && make install && ldconfig' returned a non-zero code: 2
sparklespdx commented 6 years ago

This release notes file is relevant; the libbladerf interface has changed some of the types of the arguments to accommodate the new board and they have provided typedefs.

https://github.com/Nuand/bladeRF/blob/master/host/libraries/libbladeRF/doc/doxygen/relnotes_2_0_0.dox

guruofquality commented 6 years ago

We probably want to keep the old API compiling as well, so it probably needs some creative feature checks in the cmakelists to detect the API different, define a few ifdefs (unless they are present in libbladerf.h already) and ifdef the bejesus out of whatever parts of the code changed.

Its a slightly more nuanced modification, bladerf api is now multichannel, all of the usage of _dir2mod(direction), need to now include the channel and use the BLADERF_CHANNEL_RX/BLADERF_CHANNEL_TX macro. A few other calls are missing, And the streaming API also needs the appropriate updates for multi channel support. All of that and I suppose IFDEFs for old API use.

sparklespdx commented 6 years ago

sounds like a good plan. I am taking a stab at this, doesn't seem like it is super difficult.

One question I have is about the frequency type conversion; libbladerf is expecting something of type bladerf_frequency* (which is a uint64) and the SoapyBladeRF API is expecting a double. It's not safe to cast between these, right? What's the best way to handle that?

I suppose that the numbers we are dealing with might not be large enough to lose accuracy casting between the two types.

guruofquality commented 6 years ago

hold up, i have some unpublished changes for this. The only thing thats missing is the mimo stream support in read/writeStream. I will push when I get home later today.

guruofquality commented 6 years ago

@sparklespdx this branch if you want to try things: https://github.com/pothosware/SoapyBladeRF/tree/bladerfv2

It compiles and it may just work for single channel, the mimo stuff definitely needs the buffers unpacked

if you find and fix anything, send a pull request, thanks!

sparklespdx commented 6 years ago

this is awesome @guruofquality , thanks for working on this.

I know right off the bat that we will need some ifdefs for the loopback modes in bladeRF_Settings, and possibly the gain modes as well. I will make a PR.

I hooked up my board and tried the new build. We definitely have some signs of life! The build is succesful. I am having a bit of an issue with the default sample rate; it's out of our allowable range. Since the library throws an error I can't call SoapySDR.Device() successfully, nor can I use the probe tool with the Soapy cli utility:

root@f3a731d2a08f:/work# SoapySDRUtil --probe="driver=bladerf"
######################################################
##     Soapy SDR -- the SDR abstraction library     ##
######################################################

Probe device driver=bladerf
[INFO] bladerf_open_with_devinfo()
[INFO] bladerf_get_serial() = 8a952f477f514a11a049743f0c98a38b
[ERROR @ host/libraries/libbladeRF/src/board/bladerf2/bladerf2.c:2431] bladerf2_set_rational_sample_rate: bladerf2_set_sample_ratel failed: Provided parameter was out of the allowable range
[ERROR] bladerf_set_rational_sample_rate(1000000.000000) returned -2 - Provided parameter is out of range
Error probing device: setSampleRate() -2 - Provided parameter is out of range

I'll see if I can fix this tonight as well.