diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e90646f5..d5f1f79a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,9 +41,10 @@ endif(NOT CMAKE_PREFIX_PATH) ######################################################################## # Determine optional blocks/libraries to be built (default: not built) -# Enable them here or at the command line by doing 'cmake -DENABLE_XXX=ON ../' +# Enable them at the command line by doing 'cmake -DENABLE_XXX=ON ../' ######################################################################## # Support of optional RF front-ends +option(ENABLE_UHD "Enable the use of UHD (driver for all USRP devices)" ON) option(ENABLE_OSMOSDR "Enable the use of OsmoSDR and other front-ends (RTL-based dongles, HackRF, bladeRF, etc.) as signal source (experimental)" OFF) option(ENABLE_FLEXIBAND "Enable the use of the signal source adater for the Teleorbit Flexiband GNURadio driver" OFF) option(ENABLE_ARRAY "Enable the use of CTTC's antenna array front-end as signal source (experimental)" OFF) @@ -1195,18 +1196,18 @@ endif(NOT MATIO_FOUND OR MATIO_VERSION_STRING VERSION_LESS ${GNSSSDR_MATIO_MIN_V ################################################################################ # USRP Hardware Driver (UHD) - OPTIONAL ################################################################################ -find_package(UHD) -if(NOT UHD_FOUND) - set(ENABLE_UHD OFF) - message(STATUS " The USRP Hardware Driver (UHD) signal source will not be built,") - message(STATUS " so all USRP-based front-ends will not be usable.") - message(STATUS " Please check http://files.ettus.com/manual/") -else(NOT UHD_FOUND) - set(GR_REQUIRED_COMPONENTS UHD) - find_package(Gnuradio) - set(ENABLE_UHD ON) -endif(NOT UHD_FOUND) - +if(ENABLE_UHD) + find_package(UHD) + if(NOT UHD_FOUND) + set(ENABLE_UHD OFF) + message(STATUS " The USRP Hardware Driver (UHD) signal source will not be built,") + message(STATUS " so all USRP-based front-ends will not be usable.") + message(STATUS " Please check http://files.ettus.com/manual/") + else(NOT UHD_FOUND) + set(GR_REQUIRED_COMPONENTS UHD) + find_package(Gnuradio) + endif(NOT UHD_FOUND) +endif(ENABLE_UHD) ################################################################################ diff --git a/cmake/Modules/Findlibiio.cmake b/cmake/Modules/Findlibiio.cmake new file mode 100644 index 000000000..4ce6ca9c5 --- /dev/null +++ b/cmake/Modules/Findlibiio.cmake @@ -0,0 +1,53 @@ +INCLUDE(FindPkgConfig) +PKG_CHECK_MODULES(PC_LIBIIO libiio) + +FIND_PATH( + LIBIIO_INCLUDE_DIRS + NAMES gnuradio/iio/api.h + HINTS $ENV{LIBIIO_DIR}/include + ${PC_LIBIIO_INCLUDEDIR} + PATHS ${CMAKE_INSTALL_PREFIX}/include + /usr/local/include + /usr/include + /opt/local/include +) + +FIND_LIBRARY( + LIBIIO_LIBRARIES + NAMES libiio.so iio + HINTS $ENV{LIBIIO_DIR}/lib + ${PC_LIBIIO_LIBDIR} + PATHS ${CMAKE_INSTALL_PREFIX}/lib + ${CMAKE_INSTALL_PREFIX}/lib64 + /usr/local/lib + /usr/local/lib64 + /usr/lib + /usr/lib64 + /usr/lib/x86_64-linux-gnu + /usr/lib/gcc/alpha-linux-gnu + /usr/lib/gcc/aarch64-linux-gnu + /usr/lib/gcc/arm-linux-gnueabi + /usr/lib/gcc/arm-linux-gnueabihf + /usr/lib/gcc/hppa-linux-gnu + /usr/lib/gcc/i686-gnu + /usr/lib/gcc/i686-linux-gnu + /usr/lib/gcc/x86_64-kfreebsd-gnu + /usr/lib/gcc/i686-kfreebsd-gnu + /usr/lib/gcc/m68k-linux-gnu + /usr/lib/gcc/mips-linux-gnu + /usr/lib/gcc/mips64el-linux-gnuabi64 + /usr/lib/gcc/mipsel-linux-gnu + /usr/lib/gcc/powerpc-linux-gnu + /usr/lib/gcc/powerpc-linux-gnuspe + /usr/lib/gcc/powerpc64-linux-gnu + /usr/lib/gcc/powerpc64le-linux-gnu + /usr/lib/gcc/s390x-linux-gnu + /usr/lib/gcc/sparc64-linux-gnu + /usr/lib/gcc/x86_64-linux-gnux32 + /usr/lib/gcc/sh4-linux-gnu + /Library/Frameworks/iio.framework/ +) + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBIIO DEFAULT_MSG LIBIIO_LIBRARIES LIBIIO_INCLUDE_DIRS) +MARK_AS_ADVANCED(LIBIIO_LIBRARIES LIBIIO_INCLUDE_DIRS) diff --git a/conf/gnss-sdr_GPS_L1_2ch_fmcomms2_realtime.conf b/conf/gnss-sdr_GPS_L1_2ch_fmcomms2_realtime.conf new file mode 100644 index 000000000..80814ad1d --- /dev/null +++ b/conf/gnss-sdr_GPS_L1_2ch_fmcomms2_realtime.conf @@ -0,0 +1,114 @@ +; You can define your own receiver and invoke it by doing +; gnss-sdr --config_file=my_GNSS_SDR_configuration.conf +; + +[GNSS-SDR] + +;######### GLOBAL OPTIONS ################## +;internal_fs_sps: Internal signal sampling frequency after the signal conditioning stage [Sps]. +;FOR USE GNSS-SDR WITH RTLSDR DONGLES USER MUST SET THE CALIBRATED SAMPLE RATE HERE +; i.e. using front-end-cal as reported here:http://www.cttc.es/publication/turning-a-television-into-a-gnss-receiver/ +GNSS-SDR.internal_fs_sps=7000000 + +;######### SIGNAL_SOURCE CONFIG ############ +SignalSource.implementation=Fmcomms2_Signal_Source +SignalSource.item_type=gr_complex +SignalSource.device_address=192.168.0.4 +SignalSource.sampling_frequency=7000000 +SignalSource.freq=1575420000 +SignalSource.bandwidth=4000000 +SignalSource.RF_channels=2 +SignalSource.rx1_enable=true +SignalSource.rx2_enable=true +SignalSource.gain_mode_rx1=slow_attack +SignalSource.gain_mode_rx2=slow_attack +SignalSource.rf_port_select=A_BALANCED +SignalSource.gain_rx1=64 +SignalSource.gain_rx2=64 +SignalSource.samples=0 +SignalSource.repeat=false +SignalSource.dump=false +SignalSource.dump_filename=../data/signal_source.dat +SignalSource.enable_throttle_control=false +SignalSource.enable_dds_lo=false +SignalSource.freq_rf_tx_hz=1260000000 +SignalSource.freq_dds_tx_hz=1000 +SignalSource.scale_dds_dbfs=0.0 +SignalSource.phase_dds_deg=0.0 +SignalSource.tx_attenuation_db=0.0 + + +;######### SIGNAL_CONDITIONER CONFIG ############ +SignalConditioner0.implementation=Pass_Through +SignalConditioner1.implementation=Pass_Through + +;######### CHANNELS GLOBAL CONFIG ############ +Channels_1C.count=8 +Channels.in_acquisition=1 + +;# CHANNEL CONNECTION +Channel0.RF_channel_ID=0 +Channel0.signal=1C +Channel1.RF_channel_ID=0 +Channel1.signal=1C +Channel2.RF_channel_ID=0 +Channel2.signal=1C +Channel3.RF_channel_ID=0 +Channel3.signal=1C +Channel4.RF_channel_ID=1 +Channel4.signal=1C +Channel5.RF_channel_ID=1 +Channel5.signal=1C +Channel6.RF_channel_ID=1 +Channel6.signal=1C +Channel7.RF_channel_ID=1 +Channel7.signal=1C + +;######### ACQUISITION GLOBAL CONFIG ############ +Acquisition_1C.implementation=GPS_L1_CA_PCPS_Acquisition +Acquisition_1C.item_type=gr_complex +Acquisition_1C.threshold=20 +Acquisition_1C.use_CFAR_algorithm=false +Acquisition_1C.blocking=true +Acquisition_1C.doppler_max=10000 +Acquisition_1C.doppler_step=250 +Acquisition_1C.dump=false +Acquisition_1C.dump_filename=./acq_dump.dat + + +;######### TRACKING GLOBAL CONFIG ############ +Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_Tracking +Tracking_1C.item_type=gr_complex +Tracking_1C.dump=false +Tracking_1C.dump_filename=./tracking_ch_ +Tracking_1C.pll_bw_hz=35.0; +Tracking_1C.dll_bw_hz=2.0; +Tracking_1C.early_late_space_chips=0.5; + + +;######### TELEMETRY DECODER GPS CONFIG ############ +TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder +TelemetryDecoder_1C.dump=false + + +;######### OBSERVABLES CONFIG ############ +Observables.implementation=Hybrid_Observables +Observables.dump=false +Observables.dump_filename=./observables.dat + + +;######### PVT CONFIG ############ +PVT.implementation=RTKLIB_PVT +PVT.positioning_mode=Single ; options: Single, Static, Kinematic, PPP_Static, PPP_Kinematic +PVT.iono_model=Broadcast ; options: OFF, Broadcast, SBAS, Iono-Free-LC, Estimate_STEC, IONEX +PVT.trop_model=Saastamoinen ; options: OFF, Saastamoinen, SBAS, Estimate_ZTD, Estimate_ZTD_Grad +PVT.output_rate_ms=100 +PVT.display_rate_ms=500 +PVT.dump_filename=./PVT +PVT.nmea_dump_filename=./gnss_sdr_pvt.nmea; +PVT.flag_nmea_tty_port=false; +PVT.nmea_dump_devname=/dev/pts/4 +PVT.flag_rtcm_server=false +PVT.flag_rtcm_tty_port=false +PVT.rtcm_dump_devname=/dev/pts/1 +PVT.dump=false diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/apps/volk_gnsssdr_option_helpers.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/apps/volk_gnsssdr_option_helpers.h index da1e12821..a0f7406db 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/apps/volk_gnsssdr_option_helpers.h +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/apps/volk_gnsssdr_option_helpers.h @@ -16,8 +16,8 @@ * along with GNSS-SDR. If not, see . */ -#ifndef VOLK_VOLK_OPTION_HELPERS_H -#define VOLK_VOLK_OPTION_HELPERS_H +#ifndef VOLK_GNSSSDR_OPTION_HELPERS_H +#define VOLK_GNSSSDR_OPTION_HELPERS_H #include #include @@ -71,4 +71,4 @@ private: }; -#endif //VOLK_VOLK_OPTION_HELPERS_H +#endif //VOLK_GNSSSDR_OPTION_HELPERS_H diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/apps/volk_gnsssdr_profile.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/apps/volk_gnsssdr_profile.cc index f59c0cb60..ca340b729 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/apps/volk_gnsssdr_profile.cc +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/apps/volk_gnsssdr_profile.cc @@ -148,7 +148,7 @@ int main(int argc, char *argv[]) } catch (std::string &error) { - std::cerr << "Caught Exception in 'run_volk_gnssdr_tests': " << error << std::endl; + std::cerr << "Caught Exception in 'run_volk_gnsssdr_tests': " << error << std::endl; } } } diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/apps/volk_gnsssdr_profile.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/apps/volk_gnsssdr_profile.h index 0b1a6a46e..bd22b3e84 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/apps/volk_gnsssdr_profile.h +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/apps/volk_gnsssdr_profile.h @@ -32,7 +32,7 @@ #include // for string #include // for vector -class volk_test_results_t; +class volk_gnsssdr_test_results_t; void read_results(std::vector *results); diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/qa_utils.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/qa_utils.cc index 18a4919e2..39c142a82 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/qa_utils.cc +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/qa_utils.cc @@ -16,14 +16,10 @@ * along with GNSS-SDR. If not, see . */ +#include "volk_gnsssdr/volk_gnsssdr.h" // for volk_gnsssdr_func_desc_t #include "qa_utils.h" -#include "volk_gnsssdr/volk_gnsssdr.h" // for volk_gnsssdr_func_desc_t -#include "volk_gnsssdr/volk_gnsssdr_malloc.h" // for volk_gnsssdr_free, volk_gnsssdr_malloc -#include // for auto_any_base -#include // for lexical_cast -#include // for char_separator -#include // for token_iterator -#include // for tokenizer + +#include // for volk_gnsssdr_free, volk_gnsssdr_malloc #include // for assert #include // for system_clock, duration,... #include // for sqrt, fabs, abs @@ -122,6 +118,24 @@ static std::vector get_arch_list(volk_gnsssdr_func_desc_t desc) return archlist; } +template +T volk_lexical_cast(const std::string &str) +{ + for (unsigned int c_index = 0; c_index < str.size(); ++c_index) + { + if (str.at(c_index) < '0' || str.at(c_index) > '9') + { + throw "not all numbers!"; + } + } + T var; + std::istringstream iss; + iss.str(str); + iss >> var; + // deal with any error bits that may have been set on the stream + return var; +} + volk_gnsssdr_type_t volk_gnsssdr_type_from_string(std::string name) { volk_gnsssdr_type_t type; @@ -151,7 +165,7 @@ volk_gnsssdr_type_t volk_gnsssdr_type_from_string(std::string name) throw std::string("no size spec in type ").append(name); } //will throw if malformed - int size = boost::lexical_cast(name.substr(0, last_size_pos + 1)); + int size = volk_lexical_cast(name.substr(0, last_size_pos + 1)); assert(((size % 8) == 0) && (size <= 64) && (size != 0)); type.size = size / 8; //in bytes @@ -180,21 +194,42 @@ volk_gnsssdr_type_t volk_gnsssdr_type_from_string(std::string name) return type; } +std::vector split_signature(const std::string &protokernel_signature) +{ + std::vector signature_tokens; + std::string token; + for (unsigned int loc = 0; loc < protokernel_signature.size(); ++loc) + { + if (protokernel_signature.at(loc) == '_') + { + if (protokernel_signature.substr(loc + 1, 7).compare("gnsssdr") == 0) // jump the "gnsssdr" part of "volk_gnsssdr" + { + loc += 7; + } + else + { + // this is a break + signature_tokens.push_back(token); + token = ""; + } + } + else + { + token.push_back(protokernel_signature.at(loc)); + } + } + // Get the last one to the end of the string + signature_tokens.push_back(token); + return signature_tokens; +} + static void get_signatures_from_name(std::vector &inputsig, std::vector &outputsig, std::string name) { - boost::char_separator sep("_"); - boost::tokenizer > tok(name, sep); - std::vector toked; - tok.assign(name); - toked.assign(tok.begin(), tok.end()); + std::vector toked = split_signature(name); assert(toked[0] == "volk"); toked.erase(toked.begin()); - toked.erase(toked.begin()); - - //ok. we're assuming a string in the form - //(sig)_(multiplier-opt)_..._(name)_(sig)_(multiplier-opt)_..._(alignment) enum { @@ -204,8 +239,9 @@ static void get_signatures_from_name(std::vector &inputsig, } side = SIDE_INPUT; std::string fn_name; volk_gnsssdr_type_t type; - BOOST_FOREACH (std::string token, toked) + for (unsigned int token_index = 0; token_index < toked.size(); ++token_index) { + std::string token = toked[token_index]; try { type = volk_gnsssdr_type_from_string(token); @@ -224,7 +260,7 @@ static void get_signatures_from_name(std::vector &inputsig, assert(inputsig.size() > 0); else assert(outputsig.size() > 0); - int multiplier = boost::lexical_cast(token.substr(1, token.size() - 1)); //will throw if invalid /////////// + int multiplier = volk_lexical_cast(token.substr(1, token.size() - 1)); // will throw if invalid for (int i = 1; i < multiplier; i++) { if (side == SIDE_INPUT) @@ -523,7 +559,7 @@ bool run_volk_gnsssdr_tests(volk_gnsssdr_func_desc_t desc, { get_signatures_from_name(inputsig, outputsig, name); } - catch (boost::bad_lexical_cast &error) + catch (std::exception &error) { std::cerr << "Error: unable to get function signature from kernel name" << std::endl; std::cerr << " - " << name << std::endl; @@ -542,8 +578,9 @@ bool run_volk_gnsssdr_tests(volk_gnsssdr_func_desc_t desc, } } std::vector inbuffs; - BOOST_FOREACH (volk_gnsssdr_type_t sig, inputsig) + for (unsigned int inputsig_index = 0; inputsig_index < inputsig.size(); ++inputsig_index) { + volk_gnsssdr_type_t sig = inputsig[inputsig_index]; if (!sig.is_scalar) //we don't make buffers for scalars inbuffs.push_back(mem_pool.get_new(vlen * sig.size * (sig.is_complex ? 2 : 1))); } @@ -703,6 +740,9 @@ bool run_volk_gnsssdr_tests(volk_gnsssdr_func_desc_t desc, else throw "unsupported 3 arg function >1 scalars"; break; + case 4: + run_cast_test4((volk_gnsssdr_fn_4arg)(manual_func), test_data[i], vlen, iter, arch_list[i]); + break; default: throw "no function handler for this signature"; break; diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/testqa.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/testqa.cc index 1f2466757..ed57aeb03 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/testqa.cc +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/testqa.cc @@ -48,6 +48,12 @@ int main(int argc, char* argv[]) std::vector results; if (argc > 1) { + const size_t len = std::char_traits::length(argv[1]); + if (len == 0 || len > 2046) + { + std::cerr << "Test name is too long." << std::endl; + return 0; + } for (unsigned int ii = 0; ii < test_cases.size(); ++ii) { if (std::string(argv[1]) == test_cases[ii].name()) diff --git a/src/algorithms/resampler/adapters/CMakeLists.txt b/src/algorithms/resampler/adapters/CMakeLists.txt index e929c3ffc..0a44d3454 100644 --- a/src/algorithms/resampler/adapters/CMakeLists.txt +++ b/src/algorithms/resampler/adapters/CMakeLists.txt @@ -32,9 +32,9 @@ include_directories( ) -if(${PC_GNURADIO_RUNTIME_VERSION} VERSION_GREATER "3.7.13" ) +if(${PC_GNURADIO_RUNTIME_VERSION} VERSION_GREATER "3.7.15" ) add_definitions( -DGR_GREATER_38=1 ) -endif(${PC_GNURADIO_RUNTIME_VERSION} VERSION_GREATER "3.7.13" ) +endif(${PC_GNURADIO_RUNTIME_VERSION} VERSION_GREATER "3.7.15" ) file(GLOB RESAMPLER_ADAPTER_HEADERS "*.h") diff --git a/src/algorithms/signal_source/adapters/fmcomms2_signal_source.cc b/src/algorithms/signal_source/adapters/fmcomms2_signal_source.cc index 389e9fd36..6caf9ddee 100644 --- a/src/algorithms/signal_source/adapters/fmcomms2_signal_source.cc +++ b/src/algorithms/signal_source/adapters/fmcomms2_signal_source.cc @@ -32,7 +32,9 @@ #include "fmcomms2_signal_source.h" #include "configuration_interface.h" #include "gnss_sdr_valve.h" +#include "ad9361_manager.h" #include "GPS_L1_CA.h" +#include "GPS_L2C.h" #include #include @@ -55,6 +57,7 @@ Fmcomms2SignalSource::Fmcomms2SignalSource(ConfigurationInterface* configuration quadrature_ = configuration->property(role + ".quadrature", true); rf_dc_ = configuration->property(role + ".rf_dc", true); bb_dc_ = configuration->property(role + ".bb_dc", true); + RF_channels_ = configuration->property(role + ".RF_channels", 1); gain_mode_rx1_ = configuration->property(role + ".gain_mode_rx1", std::string("manual")); gain_mode_rx2_ = configuration->property(role + ".gain_mode_rx2", std::string("manual")); rf_gain_rx1_ = configuration->property(role + ".gain_rx1", 64.0); @@ -67,6 +70,14 @@ Fmcomms2SignalSource::Fmcomms2SignalSource(ConfigurationInterface* configuration dump_ = configuration->property(role + ".dump", false); dump_filename_ = configuration->property(role + ".dump_filename", default_dump_file); + //AD9361 Local Oscillator generation for dual band operation + enable_dds_lo_ = configuration->property(role + ".enable_dds_lo", false); + freq_rf_tx_hz_ = configuration->property(role + ".freq_rf_tx_hz", GPS_L1_FREQ_HZ - GPS_L2_FREQ_HZ - 1000); + freq_dds_tx_hz_ = configuration->property(role + ".freq_dds_tx_hz", 1000); + scale_dds_dbfs_ = configuration->property(role + ".scale_dds_dbfs", 0.0); + phase_dds_deg_ = configuration->property(role + ".phase_dds_deg", 0.0); + tx_attenuation_db_ = configuration->property(role + ".tx_attenuation_db", 0.0); + item_size_ = sizeof(gr_complex); std::cout << "device address: " << uri_ << std::endl; @@ -75,15 +86,73 @@ Fmcomms2SignalSource::Fmcomms2SignalSource(ConfigurationInterface* configuration if (item_type_.compare("gr_complex") == 0) { - fmcomms2_source_f32c_ = gr::iio::fmcomms2_source_f32c::make( - uri_.c_str(), freq_, sample_rate_, - bandwidth_, - rx1_en_, rx2_en_, - buffer_size_, quadrature_, rf_dc_, - bb_dc_, gain_mode_rx1_.c_str(), rf_gain_rx1_, - gain_mode_rx2_.c_str(), rf_gain_rx2_, - rf_port_select_.c_str(), filter_file_.c_str(), - filter_auto_); + if (RF_channels_ == 1) + { + if (rx1_en_ and rx2_en_) + { + LOG(FATAL) << "Configuration error: both rx1 and rx2 are enabled but RF_channels=1 !"; + } + else + { + fmcomms2_source_f32c_ = gr::iio::fmcomms2_source_f32c::make( + uri_.c_str(), freq_, sample_rate_, + bandwidth_, + rx1_en_, rx2_en_, + buffer_size_, quadrature_, rf_dc_, + bb_dc_, gain_mode_rx1_.c_str(), rf_gain_rx1_, + gain_mode_rx2_.c_str(), rf_gain_rx2_, + rf_port_select_.c_str(), filter_file_.c_str(), + filter_auto_); + + //configure LO + if (enable_dds_lo_ == true) + { + std::cout << "Enabling Local Oscillator generator in FMCOMMS2\n"; + config_ad9361_lo_remote(uri_, + bandwidth_, + sample_rate_, + freq_rf_tx_hz_, + tx_attenuation_db_, + freq_dds_tx_hz_, + scale_dds_dbfs_); + } + } + } + else if (RF_channels_ == 2) + { + if (!(rx1_en_ and rx2_en_)) + { + LOG(FATAL) << "Configuration error: RF_channels=2 but are not enabled both receivers in FMCOMMS2 !"; + } + else + { + fmcomms2_source_f32c_ = gr::iio::fmcomms2_source_f32c::make( + uri_.c_str(), freq_, sample_rate_, + bandwidth_, + rx1_en_, rx2_en_, + buffer_size_, quadrature_, rf_dc_, + bb_dc_, gain_mode_rx1_.c_str(), rf_gain_rx1_, + gain_mode_rx2_.c_str(), rf_gain_rx2_, + rf_port_select_.c_str(), filter_file_.c_str(), + filter_auto_); + //configure LO + if (enable_dds_lo_ == true) + { + std::cout << "Enabling Local Oscillator generator in FMCOMMS2\n"; + config_ad9361_lo_remote(uri_, + bandwidth_, + sample_rate_, + freq_rf_tx_hz_, + tx_attenuation_db_, + freq_dds_tx_hz_, + scale_dds_dbfs_); + } + } + } + else + { + LOG(FATAL) << "Configuration error: Unsupported number of RF_channels !"; + } } else { @@ -108,6 +177,10 @@ Fmcomms2SignalSource::Fmcomms2SignalSource(ConfigurationInterface* configuration Fmcomms2SignalSource::~Fmcomms2SignalSource() { + if (enable_dds_lo_ == true) + { + ad9361_disable_lo_remote(uri_); + } } diff --git a/src/algorithms/signal_source/adapters/fmcomms2_signal_source.h b/src/algorithms/signal_source/adapters/fmcomms2_signal_source.h index 1c24e4b4c..014299981 100644 --- a/src/algorithms/signal_source/adapters/fmcomms2_signal_source.h +++ b/src/algorithms/signal_source/adapters/fmcomms2_signal_source.h @@ -88,6 +88,7 @@ private: bool quadrature_; bool rf_dc_; bool bb_dc_; + int RF_channels_; std::string gain_mode_rx1_; std::string gain_mode_rx2_; double rf_gain_rx1_; @@ -96,6 +97,14 @@ private: std::string filter_file_; bool filter_auto_; + //DDS configuration for LO generation for external mixer + bool enable_dds_lo_; + unsigned long freq_rf_tx_hz_; + unsigned long freq_dds_tx_hz_; + double scale_dds_dbfs_; + double phase_dds_deg_; + double tx_attenuation_db_; + unsigned int in_stream_; unsigned int out_stream_; diff --git a/src/algorithms/signal_source/libs/CMakeLists.txt b/src/algorithms/signal_source/libs/CMakeLists.txt index 1ecb1edfd..5a35a7992 100644 --- a/src/algorithms/signal_source/libs/CMakeLists.txt +++ b/src/algorithms/signal_source/libs/CMakeLists.txt @@ -16,16 +16,61 @@ # along with GNSS-SDR. If not, see . # +if(ENABLE_PLUTOSDR OR ENABLE_FMCOMMS2) + find_package(iio REQUIRED) + if(NOT IIO_FOUND) + message(STATUS "gnuradio-iio not found, its installation is required.") + message(STATUS "Please build and install the following projects:") + message(STATUS " * libiio from https://github.com/analogdevicesinc/libiio") + message(STATUS " * libad9361-iio from https://github.com/analogdevicesinc/libad9361-iio") + message(STATUS " * gnuradio-iio from https://github.com/analogdevicesinc/gr-iio") + message(FATAL_ERROR "gnuradio-iio required for building gnss-sdr with this option enabled") + endif(NOT IIO_FOUND) + set(OPT_LIBRARIES ${OPT_LIBRARIES} ${IIO_LIBRARIES}) + set(OPT_DRIVER_INCLUDE_DIRS ${OPT_DRIVER_INCLUDE_DIRS} ${IIO_INCLUDE_DIRS}) + + find_package(libiio REQUIRED) + if(NOT LIBIIO_FOUND) + message(STATUS "gnuradio-iio not found, its installation is required.") + message(STATUS "Please build and install the following projects:") + message(STATUS " * libiio from https://github.com/analogdevicesinc/libiio") + message(STATUS " * libad9361-iio from https://github.com/analogdevicesinc/libad9361-iio") + message(STATUS " * gnuradio-iio from https://github.com/analogdevicesinc/gr-iio") + message(FATAL_ERROR "gnuradio-iio required for building gnss-sdr with this option enabled") + endif(NOT LIBIIO_FOUND) + set(OPT_LIBRARIES ${OPT_LIBRARIES} ${LIBIIO_LIBRARIES}) + set(OPT_DRIVER_INCLUDE_DIRS ${OPT_DRIVER_INCLUDE_DIRS} ${LIBIIO_INCLUDE_DIRS}) + +endif(ENABLE_PLUTOSDR OR ENABLE_FMCOMMS2) + +if(ENABLE_FMCOMMS2) + ############################################### + # FMCOMMS2 based SDR Hardware + ############################################### + if(IIO_FOUND) + set(OPT_SIGNAL_SOURCE_LIB_SOURCES ad9361_manager.cc) + endif(IIO_FOUND) +endif(ENABLE_FMCOMMS2) + set (SIGNAL_SOURCE_LIB_SOURCES rtl_tcp_commands.cc - rtl_tcp_dongle_info.cc) + rtl_tcp_dongle_info.cc + ${OPT_SIGNAL_SOURCE_LIB_SOURCES}) include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${Boost_INCLUDE_DIRS} + ${GLOG_INCLUDE_DIRS} + ${GFlags_INCLUDE_DIRS} + ${OPT_DRIVER_INCLUDE_DIRS} ) + file(GLOB SIGNAL_SOURCE_LIB_HEADERS "*.h") list(SORT SIGNAL_SOURCE_LIB_HEADERS) +list(SORT SIGNAL_SOURCE_LIB_SOURCES) add_library(signal_source_lib ${SIGNAL_SOURCE_LIB_SOURCES} ${SIGNAL_SOURCE_LIB_HEADERS}) -source_group(Headers FILES ${SIGNAL_SOURCE_LIB_HEADERS}) \ No newline at end of file +source_group(Headers FILES ${SIGNAL_SOURCE_LIB_HEADERS}) +add_dependencies(signal_source_lib glog-${glog_RELEASE}) +target_link_libraries(signal_source_lib ${OPT_LIBRARIES}) + diff --git a/src/algorithms/signal_source/libs/ad9361_manager.cc b/src/algorithms/signal_source/libs/ad9361_manager.cc new file mode 100644 index 000000000..b0a41bd55 --- /dev/null +++ b/src/algorithms/signal_source/libs/ad9361_manager.cc @@ -0,0 +1,764 @@ +/*! + * \file ad9361_manager.cc + * \brief An Analog Devices AD9361 front-end configuration library wrapper for configure some functions via iiod link. + * \author Javier Arribas, jarribas(at)cttc.es + * + * This file contains information taken from librtlsdr: + * http://git.osmocom.org/rtl-sdr/ + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ +#include "ad9361_manager.h" +#include +#include +#include +#include + + +/* check return value of attr_write function */ +void errchk(int v, const char *what) +{ + if (v < 0) + { + LOG(WARNING) << "Error " << v << " writing to channel " << what << " value may not be supported. "; + } +} + + +/* write attribute: long long int */ +void wr_ch_lli(struct iio_channel *chn, const char *what, long long val) +{ + errchk(iio_channel_attr_write_longlong(chn, what, val), what); +} + + +/* write attribute: string */ +void wr_ch_str(struct iio_channel *chn, const char *what, const char *str) +{ + errchk(iio_channel_attr_write(chn, what, str), what); +} + + +/* returns ad9361 phy device */ +struct iio_device *get_ad9361_phy(struct iio_context *ctx) +{ + struct iio_device *dev = iio_context_find_device(ctx, "ad9361-phy"); + return dev; +} + + +/* finds AD9361 streaming IIO devices */ +bool get_ad9361_stream_dev(struct iio_context *ctx, enum iodev d, struct iio_device **dev) +{ + switch (d) + { + case TX: + *dev = iio_context_find_device(ctx, "cf-ad9361-dds-core-lpc"); + return *dev != NULL; + case RX: + *dev = iio_context_find_device(ctx, "cf-ad9361-lpc"); + return *dev != NULL; + default: + return false; + } +} + + +/* finds AD9361 streaming IIO channels */ +bool get_ad9361_stream_ch(struct iio_context *ctx, enum iodev d, struct iio_device *dev, int chid, struct iio_channel **chn) +{ + std::stringstream name; + name.str(""); + name << "voltage"; + name << chid; + *chn = iio_device_find_channel(dev, name.str().c_str(), d == TX); + if (!*chn) + { + name.str(""); + name << "altvoltage"; + name << chid; + *chn = iio_device_find_channel(dev, name.str().c_str(), d == TX); + } + return *chn != NULL; +} + + +/* finds AD9361 phy IIO configuration channel with id chid */ +bool get_phy_chan(struct iio_context *ctx, enum iodev d, int chid, struct iio_channel **chn) +{ + std::stringstream name; + switch (d) + { + case RX: + name.str(""); + name << "voltage"; + name << chid; + *chn = iio_device_find_channel(get_ad9361_phy(ctx), name.str().c_str(), false); + return *chn != NULL; + break; + case TX: + name.str(""); + name << "voltage"; + name << chid; + *chn = iio_device_find_channel(get_ad9361_phy(ctx), name.str().c_str(), true); + return *chn != NULL; + break; + default: + return false; + } +} + + +/* finds AD9361 local oscillator IIO configuration channels */ +bool get_lo_chan(struct iio_context *ctx, enum iodev d, struct iio_channel **chn) +{ + switch (d) + { + // LO chan is always output, i.e. true + case RX: + *chn = iio_device_find_channel(get_ad9361_phy(ctx), "altvoltage0", true); + return *chn != NULL; + case TX: + *chn = iio_device_find_channel(get_ad9361_phy(ctx), "altvoltage1", true); + return *chn != NULL; + default: + return false; + } +} + + +/* applies streaming configuration through IIO */ +bool cfg_ad9361_streaming_ch(struct iio_context *ctx, struct stream_cfg *cfg, enum iodev type, int chid) +{ + struct iio_channel *chn = NULL; + + // Configure phy and lo channels + //LOG(INFO)<<"* Acquiring AD9361 phy channel"<rfport); + wr_ch_lli(chn, "rf_bandwidth", cfg->bw_hz); + wr_ch_lli(chn, "sampling_frequency", cfg->fs_hz); + + // Configure LO channel + //LOG(INFO)<<"* Acquiring AD9361 "<lo_hz); + return true; +} + + +bool config_ad9361_rx_local(unsigned long bandwidth_, + unsigned long sample_rate_, + unsigned long freq_, + std::string rf_port_select_, + std::string gain_mode_rx1_, + std::string gain_mode_rx2_, + double rf_gain_rx1_, + double rf_gain_rx2_) + +{ + // RX stream config + // Stream configurations + struct stream_cfg rxcfg; + rxcfg.bw_hz = bandwidth_; // 2 MHz rf bandwidth + rxcfg.fs_hz = sample_rate_; // 2.5 MS/s rx sample rate + rxcfg.lo_hz = freq_; // 2.5 GHz rf frequency + rxcfg.rfport = rf_port_select_.c_str(); // port A (select for rf freq.) + + std::cout << "AD9361 Acquiring IIO LOCAL context\n"; + struct iio_context *ctx; + // Streaming devices + struct iio_device *rx; + struct iio_channel *rx0_i; + struct iio_channel *rx0_q; + + ctx = iio_create_default_context(); + if (!ctx) + { + std::cout << "No context\n"; + throw std::runtime_error("AD9361 IIO No context"); + } + + if (iio_context_get_devices_count(ctx) <= 0) + { + std::cout << "No devices\n"; + throw std::runtime_error("AD9361 IIO No devices"); + } + + std::cout << "* Acquiring AD9361 streaming devices\n"; + + if (!get_ad9361_stream_dev(ctx, RX, &rx)) + { + std::cout << "No rx dev found\n"; + throw std::runtime_error("AD9361 IIO No rx dev found"); + }; + + std::cout << "* Configuring AD9361 for streaming\n"; + if (!cfg_ad9361_streaming_ch(ctx, &rxcfg, RX, 0)) + { + std::cout << "RX port 0 not found\n"; + throw std::runtime_error("AD9361 IIO RX port 0 not found"); + } + + std::cout << "* Initializing AD9361 IIO streaming channels\n"; + if (!get_ad9361_stream_ch(ctx, RX, rx, 0, &rx0_i)) + { + std::cout << "RX chan i not found\n"; + throw std::runtime_error("RX chan i not found"); + } + + if (!get_ad9361_stream_ch(ctx, RX, rx, 1, &rx0_q)) + { + std::cout << "RX chan q not found\n"; + throw std::runtime_error("RX chan q not found"); + } + + std::cout << "* Enabling IIO streaming channels\n"; + iio_channel_enable(rx0_i); + iio_channel_enable(rx0_q); + + struct iio_device *ad9361_phy; + ad9361_phy = iio_context_find_device(ctx, "ad9361-phy"); + int ret; + ret = iio_device_attr_write(ad9361_phy, "trx_rate_governor", "nominal"); + if (ret < 0) + { + std::cout << "Failed to set trx_rate_governor: " << ret << std::endl; + } + ret = iio_device_attr_write(ad9361_phy, "ensm_mode", "fdd"); + if (ret < 0) + { + std::cout << "Failed to set ensm_mode: " << ret << std::endl; + } + ret = iio_device_attr_write(ad9361_phy, "calib_mode", "auto"); + if (ret < 0) + { + std::cout << "Failed to set calib_mode: " << ret << std::endl; + } + ret = iio_device_attr_write(ad9361_phy, "in_voltage0_gain_control_mode", gain_mode_rx1_.c_str()); + if (ret < 0) + { + std::cout << "Failed to set in_voltage0_gain_control_mode: " << ret << std::endl; + } + ret = iio_device_attr_write(ad9361_phy, "in_voltage1_gain_control_mode", gain_mode_rx2_.c_str()); + if (ret < 0) + { + std::cout << "Failed to set in_voltage1_gain_control_mode: " << ret << std::endl; + } + ret = iio_device_attr_write_double(ad9361_phy, "in_voltage0_hardwaregain", rf_gain_rx1_); + if (ret < 0) + { + std::cout << "Failed to set in_voltage0_hardwaregain: " << ret << std::endl; + } + ret = iio_device_attr_write_double(ad9361_phy, "in_voltage1_hardwaregain", rf_gain_rx2_); + if (ret < 0) + { + std::cout << "Failed to set in_voltage1_hardwaregain: " << ret << std::endl; + } + + std::cout << "End of AD9361 RX configuration.\n"; + iio_context_destroy(ctx); + return true; +} + + +bool config_ad9361_rx_remote(std::string remote_host, + unsigned long bandwidth_, + unsigned long sample_rate_, + unsigned long freq_, + std::string rf_port_select_, + std::string gain_mode_rx1_, + std::string gain_mode_rx2_, + double rf_gain_rx1_, + double rf_gain_rx2_) +{ + // RX stream config + // Stream configurations + struct stream_cfg rxcfg; + rxcfg.bw_hz = bandwidth_; // 2 MHz rf bandwidth + rxcfg.fs_hz = sample_rate_; // 2.5 MS/s rx sample rate + rxcfg.lo_hz = freq_; // 2.5 GHz rf frequency + rxcfg.rfport = rf_port_select_.c_str(); // port A (select for rf freq.) + + std::cout << "AD9361 Acquiring IIO REMOTE context in host " << remote_host << std::endl; + struct iio_context *ctx; + // Streaming devices + struct iio_device *rx; + struct iio_channel *rx0_i; + struct iio_channel *rx0_q; + + ctx = iio_create_network_context(remote_host.c_str()); + if (!ctx) + { + std::cout << "No context\n"; + throw std::runtime_error("AD9361 IIO No context"); + } + + if (iio_context_get_devices_count(ctx) <= 0) + { + std::cout << "No devices\n"; + throw std::runtime_error("AD9361 IIO No devices"); + } + + std::cout << "* Acquiring AD9361 streaming devices\n"; + + if (!get_ad9361_stream_dev(ctx, RX, &rx)) + { + std::cout << "No rx dev found\n"; + throw std::runtime_error("AD9361 IIO No rx dev found"); + }; + + std::cout << "* Configuring AD9361 for streaming\n"; + if (!cfg_ad9361_streaming_ch(ctx, &rxcfg, RX, 0)) + { + std::cout << "RX port 0 not found\n"; + throw std::runtime_error("AD9361 IIO RX port 0 not found"); + } + + std::cout << "* Initializing AD9361 IIO streaming channels\n"; + if (!get_ad9361_stream_ch(ctx, RX, rx, 0, &rx0_i)) + { + std::cout << "RX chan i not found\n"; + throw std::runtime_error("RX chan i not found"); + } + + if (!get_ad9361_stream_ch(ctx, RX, rx, 1, &rx0_q)) + { + std::cout << "RX chan q not found\n"; + throw std::runtime_error("RX chan q not found"); + } + + std::cout << "* Enabling IIO streaming channels\n"; + iio_channel_enable(rx0_i); + iio_channel_enable(rx0_q); + + struct iio_device *ad9361_phy; + ad9361_phy = iio_context_find_device(ctx, "ad9361-phy"); + int ret; + ret = iio_device_attr_write(ad9361_phy, "trx_rate_governor", "nominal"); + if (ret < 0) + { + std::cout << "Failed to set trx_rate_governor: " << ret << std::endl; + } + ret = iio_device_attr_write(ad9361_phy, "ensm_mode", "fdd"); + if (ret < 0) + { + std::cout << "Failed to set ensm_mode: " << ret << std::endl; + } + ret = iio_device_attr_write(ad9361_phy, "calib_mode", "auto"); + if (ret < 0) + { + std::cout << "Failed to set calib_mode: " << ret << std::endl; + } + ret = iio_device_attr_write(ad9361_phy, "in_voltage0_gain_control_mode", gain_mode_rx1_.c_str()); + if (ret < 0) + { + std::cout << "Failed to set in_voltage0_gain_control_mode: " << ret << std::endl; + } + ret = iio_device_attr_write(ad9361_phy, "in_voltage1_gain_control_mode", gain_mode_rx2_.c_str()); + if (ret < 0) + { + std::cout << "Failed to set in_voltage1_gain_control_mode: " << ret << std::endl; + } + ret = iio_device_attr_write_double(ad9361_phy, "in_voltage0_hardwaregain", rf_gain_rx1_); + if (ret < 0) + { + std::cout << "Failed to set in_voltage0_hardwaregain: " << ret << std::endl; + } + ret = iio_device_attr_write_double(ad9361_phy, "in_voltage1_hardwaregain", rf_gain_rx2_); + if (ret < 0) + { + std::cout << "Failed to set in_voltage1_hardwaregain: " << ret << std::endl; + } + + std::cout << "End of AD9361 RX configuration.\n"; + + iio_context_destroy(ctx); + return true; +} + + +bool config_ad9361_lo_local(unsigned long bandwidth_, + unsigned long sample_rate_, + unsigned long freq_rf_tx_hz_, + double tx_attenuation_db_, + long long freq_dds_tx_hz_, + double scale_dds_dbfs_) +{ + // TX stream config + std::cout << "Start of AD9361 TX Local Oscillator DDS configuration\n"; + struct stream_cfg txcfg; + txcfg.bw_hz = bandwidth_; + txcfg.fs_hz = sample_rate_; + txcfg.lo_hz = freq_rf_tx_hz_; + txcfg.rfport = "A"; + + std::cout << "AD9361 Acquiring IIO LOCAL context\n"; + struct iio_context *ctx; + ctx = iio_create_default_context(); + if (!ctx) + { + std::cout << "No context\n"; + throw std::runtime_error("AD9361 IIO No context"); + } + + //find tx device + struct iio_device *tx; + + std::cout << "* Acquiring AD9361 TX streaming devices\n"; + + if (!get_ad9361_stream_dev(ctx, TX, &tx)) + { + std::cout << "No tx dev found\n"; + throw std::runtime_error("AD9361 IIO No tx dev found"); + }; + + std::cout << "* Configuring AD9361 for streaming TX\n"; + if (!cfg_ad9361_streaming_ch(ctx, &txcfg, TX, 0)) + { + std::cout << "TX port 0 not found\n"; + throw std::runtime_error("AD9361 IIO TX port 0 not found"); + } + + //ENABLE DDS on TX1 + struct iio_device *ad9361_phy; + ad9361_phy = iio_context_find_device(ctx, "ad9361-phy"); + int ret; + //set output amplifier attenuation + ret = iio_device_attr_write_double(ad9361_phy, "out_voltage0_hardwaregain", -tx_attenuation_db_); + if (ret < 0) + { + std::cout << "Failed to set out_voltage0_hardwaregain value " << -tx_attenuation_db_ << " error " << ret << std::endl; + } + + struct iio_device *dds; + dds = iio_context_find_device(ctx, "cf-ad9361-dds-core-lpc"); + struct iio_channel *dds_channel0_I; + dds_channel0_I = iio_device_find_channel(dds, "TX1_I_F1", true); + + struct iio_channel *dds_channel0_Q; + dds_channel0_Q = iio_device_find_channel(dds, "TX1_Q_F1", true); + + ret = iio_channel_attr_write_bool(dds_channel0_I, "raw", true); + if (ret < 0) + { + std::cout << "Failed to toggle DDS: " << ret << std::endl; + } + + //set frequency, scale and phase + + ret = iio_channel_attr_write_longlong(dds_channel0_I, "frequency", (long long)freq_dds_tx_hz_); + if (ret < 0) + { + std::cout << "Failed to set TX DDS frequency I: " << ret << std::endl; + } + + ret = iio_channel_attr_write_longlong(dds_channel0_Q, "frequency", (long long)freq_dds_tx_hz_); + if (ret < 0) + { + std::cout << "Failed to set TX DDS frequency Q: " << ret << std::endl; + } + + ret = iio_channel_attr_write_double(dds_channel0_I, "phase", 0.0); + if (ret < 0) + { + std::cout << "Failed to set TX DDS phase I: " << ret << std::endl; + } + + ret = iio_channel_attr_write_double(dds_channel0_Q, "phase", 270000.0); + if (ret < 0) + { + std::cout << "Failed to set TX DDS phase Q: " << ret << std::endl; + } + + ret = iio_channel_attr_write_double(dds_channel0_I, "scale", pow(10, scale_dds_dbfs_ / 20.0)); + if (ret < 0) + { + std::cout << "Failed to set TX DDS scale I: " << ret << std::endl; + } + + ret = iio_channel_attr_write_double(dds_channel0_Q, "scale", pow(10, scale_dds_dbfs_ / 20.0)); + if (ret < 0) + { + std::cout << "Failed to set TX DDS scale Q: " << ret << std::endl; + } + + //disable TX2 + + ret = iio_device_attr_write_double(ad9361_phy, "out_voltage1_hardwaregain", -89.0); + if (ret < 0) + { + std::cout << "Failed to set out_voltage1_hardwaregain value " << -89.0 << " error " << ret << std::endl; + } + + struct iio_channel *dds_channel1_I; + dds_channel1_I = iio_device_find_channel(dds, "TX2_I_F1", true); + + struct iio_channel *dds_channel1_Q; + dds_channel1_Q = iio_device_find_channel(dds, "TX2_Q_F1", true); + + ret = iio_channel_attr_write_double(dds_channel1_I, "scale", 0); + if (ret < 0) + { + std::cout << "Failed to set TX2 DDS scale I: " << ret << std::endl; + } + + ret = iio_channel_attr_write_double(dds_channel1_Q, "scale", 0); + if (ret < 0) + { + std::cout << "Failed to set TX2 DDS scale Q: " << ret << std::endl; + } + + iio_context_destroy(ctx); + return true; +} + + +bool config_ad9361_lo_remote(std::string remote_host, + unsigned long bandwidth_, + unsigned long sample_rate_, + unsigned long freq_rf_tx_hz_, + double tx_attenuation_db_, + long long freq_dds_tx_hz_, + double scale_dds_dbfs_) +{ + // TX stream config + std::cout << "Start of AD9361 TX Local Oscillator DDS configuration\n"; + struct stream_cfg txcfg; + txcfg.bw_hz = bandwidth_; + txcfg.fs_hz = sample_rate_; + txcfg.lo_hz = freq_rf_tx_hz_; + txcfg.rfport = "A"; + + std::cout << "AD9361 Acquiring IIO REMOTE context in host " << remote_host << std::endl; + struct iio_context *ctx; + ctx = iio_create_network_context(remote_host.c_str()); + if (!ctx) + { + std::cout << "No context\n"; + throw std::runtime_error("AD9361 IIO No context"); + } + + //find tx device + struct iio_device *tx; + + std::cout << "* Acquiring AD9361 TX streaming devices\n"; + + if (!get_ad9361_stream_dev(ctx, TX, &tx)) + { + std::cout << "No tx dev found\n"; + throw std::runtime_error("AD9361 IIO No tx dev found"); + }; + + std::cout << "* Configuring AD9361 for streaming TX\n"; + if (!cfg_ad9361_streaming_ch(ctx, &txcfg, TX, 0)) + { + std::cout << "TX port 0 not found\n"; + throw std::runtime_error("AD9361 IIO TX port 0 not found"); + } + + //ENABLE DDS on TX1 + struct iio_device *ad9361_phy; + ad9361_phy = iio_context_find_device(ctx, "ad9361-phy"); + int ret; + //set output amplifier attenuation + ret = iio_device_attr_write_double(ad9361_phy, "out_voltage0_hardwaregain", -tx_attenuation_db_); + if (ret < 0) + { + std::cout << "Failed to set out_voltage0_hardwaregain value " << -tx_attenuation_db_ << " error " << ret << std::endl; + } + + struct iio_device *dds; + dds = iio_context_find_device(ctx, "cf-ad9361-dds-core-lpc"); + struct iio_channel *dds_channel0_I; + dds_channel0_I = iio_device_find_channel(dds, "TX1_I_F1", true); + + struct iio_channel *dds_channel0_Q; + dds_channel0_Q = iio_device_find_channel(dds, "TX1_Q_F1", true); + + ret = iio_channel_attr_write_bool(dds_channel0_I, "raw", true); + if (ret < 0) + { + std::cout << "Failed to toggle DDS: " << ret << std::endl; + } + + //set frequency, scale and phase + + ret = iio_channel_attr_write_longlong(dds_channel0_I, "frequency", (long long)freq_dds_tx_hz_); + if (ret < 0) + { + std::cout << "Failed to set TX DDS frequency I: " << ret << std::endl; + } + + ret = iio_channel_attr_write_longlong(dds_channel0_Q, "frequency", (long long)freq_dds_tx_hz_); + if (ret < 0) + { + std::cout << "Failed to set TX DDS frequency Q: " << ret << std::endl; + } + + ret = iio_channel_attr_write_double(dds_channel0_I, "phase", 0.0); + if (ret < 0) + { + std::cout << "Failed to set TX DDS phase I: " << ret << std::endl; + } + + ret = iio_channel_attr_write_double(dds_channel0_Q, "phase", 270000.0); + if (ret < 0) + { + std::cout << "Failed to set TX DDS phase Q: " << ret << std::endl; + } + + ret = iio_channel_attr_write_double(dds_channel0_I, "scale", pow(10, scale_dds_dbfs_ / 20.0)); + if (ret < 0) + { + std::cout << "Failed to set TX DDS scale I: " << ret << std::endl; + } + + ret = iio_channel_attr_write_double(dds_channel0_Q, "scale", pow(10, scale_dds_dbfs_ / 20.0)); + if (ret < 0) + { + std::cout << "Failed to set TX DDS scale Q: " << ret << std::endl; + } + + //disable TX2 + + ret = iio_device_attr_write_double(ad9361_phy, "out_voltage1_hardwaregain", -89.0); + if (ret < 0) + { + std::cout << "Failed to set out_voltage1_hardwaregain value " << -89.0 << " error " << ret << std::endl; + } + + struct iio_channel *dds_channel1_I; + dds_channel1_I = iio_device_find_channel(dds, "TX2_I_F1", true); + + struct iio_channel *dds_channel1_Q; + dds_channel1_Q = iio_device_find_channel(dds, "TX2_Q_F1", true); + + ret = iio_channel_attr_write_double(dds_channel1_I, "scale", 0); + if (ret < 0) + { + std::cout << "Failed to set TX2 DDS scale I: " << ret << std::endl; + } + + ret = iio_channel_attr_write_double(dds_channel1_Q, "scale", 0); + if (ret < 0) + { + std::cout << "Failed to set TX2 DDS scale Q: " << ret << std::endl; + } + + iio_context_destroy(ctx); + return true; +} + + +bool ad9361_disable_lo_remote(std::string remote_host) +{ + std::cout << "AD9361 Acquiring IIO REMOTE context in host " << remote_host << std::endl; + struct iio_context *ctx; + ctx = iio_create_network_context(remote_host.c_str()); + if (!ctx) + { + std::cout << "No context\n"; + throw std::runtime_error("AD9361 IIO No context"); + } + struct iio_device *dds; + dds = iio_context_find_device(ctx, "cf-ad9361-dds-core-lpc"); + struct iio_channel *dds_channel0_I; + dds_channel0_I = iio_device_find_channel(dds, "TX1_I_F1", true); + + struct iio_channel *dds_channel0_Q; + dds_channel0_Q = iio_device_find_channel(dds, "TX1_Q_F1", true); + int ret; + ret = iio_channel_attr_write_bool(dds_channel0_I, "raw", false); + if (ret < 0) + { + std::cout << "Failed to toggle DDS: " << ret << std::endl; + } + + ret = iio_channel_attr_write_double(dds_channel0_I, "scale", 0.0); + if (ret < 0) + { + std::cout << "Failed to set TX DDS scale I: " << ret << std::endl; + } + + ret = iio_channel_attr_write_double(dds_channel0_Q, "scale", 0.0); + if (ret < 0) + { + std::cout << "Failed to set TX DDS scale Q: " << ret << std::endl; + } + + iio_context_destroy(ctx); + + return true; +} + + +bool ad9361_disable_lo_local() +{ + std::cout << "AD9361 Acquiring IIO LOCAL context" << std::endl; + struct iio_context *ctx; + ctx = iio_create_default_context(); + if (!ctx) + { + std::cout << "No context\n"; + throw std::runtime_error("AD9361 IIO No context"); + } + struct iio_device *dds; + dds = iio_context_find_device(ctx, "cf-ad9361-dds-core-lpc"); + struct iio_channel *dds_channel0_I; + dds_channel0_I = iio_device_find_channel(dds, "TX1_I_F1", true); + + struct iio_channel *dds_channel0_Q; + dds_channel0_Q = iio_device_find_channel(dds, "TX1_Q_F1", true); + int ret; + ret = iio_channel_attr_write_bool(dds_channel0_I, "raw", false); + if (ret < 0) + { + std::cout << "Failed to toggle DDS: " << ret << std::endl; + } + + ret = iio_channel_attr_write_double(dds_channel0_I, "scale", 0.0); + if (ret < 0) + { + std::cout << "Failed to set TX DDS scale I: " << ret << std::endl; + } + + ret = iio_channel_attr_write_double(dds_channel0_Q, "scale", 0.0); + if (ret < 0) + { + std::cout << "Failed to set TX DDS scale Q: " << ret << std::endl; + } + + iio_context_destroy(ctx); + + return true; +} diff --git a/src/algorithms/signal_source/libs/ad9361_manager.h b/src/algorithms/signal_source/libs/ad9361_manager.h new file mode 100644 index 000000000..cd48e664f --- /dev/null +++ b/src/algorithms/signal_source/libs/ad9361_manager.h @@ -0,0 +1,130 @@ +/*! + * \file ad9361_manager.h + * \brief An Analog Devices AD9361 front-end configuration library wrapper for configure some functions via iiod link. + * \author Javier Arribas, jarribas(at)cttc.es + * + * This file contains information taken from librtlsdr: + * http://git.osmocom.org/rtl-sdr/ + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + +#ifndef GNSS_SDR_AD9361_MANAGER_H +#define GNSS_SDR_AD9361_MANAGER_H + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +/* RX is input, TX is output */ +enum iodev +{ + RX, + TX +}; + +/* common RX and TX streaming params */ +struct stream_cfg +{ + long long bw_hz; // Analog banwidth in Hz + long long fs_hz; // Baseband sample rate in Hz + long long lo_hz; // Local oscillator frequency in Hz + const char *rfport; // Port name +}; + + +/* check return value of attr_write function */ +void errchk(int v, const char *what); + +/* write attribute: long long int */ +void wr_ch_lli(struct iio_channel *chn, const char *what, long long val); + +/* write attribute: string */ +void wr_ch_str(struct iio_channel *chn, const char *what, const char *str); + +/* helper function generating channel names */ +char *get_ch_name(const char *type, int id, char *tmpstr); + +/* returns ad9361 phy device */ +struct iio_device *get_ad9361_phy(struct iio_context *ctx); + +/* finds AD9361 streaming IIO devices */ +bool get_ad9361_stream_dev(struct iio_context *ctx, enum iodev d, struct iio_device **dev); + +/* finds AD9361 streaming IIO channels */ +bool get_ad9361_stream_ch(struct iio_context *ctx, enum iodev d, struct iio_device *dev, int chid, struct iio_channel **chn); + +/* finds AD9361 phy IIO configuration channel with id chid */ +bool get_phy_chan(struct iio_context *ctx, enum iodev d, int chid, struct iio_channel **chn); + +/* finds AD9361 local oscillator IIO configuration channels */ +bool get_lo_chan(struct iio_context *ctx, enum iodev d, struct iio_channel **chn); + +/* applies streaming configuration through IIO */ +bool cfg_ad9361_streaming_ch(struct iio_context *ctx, struct stream_cfg *cfg, enum iodev type, int chid); + +bool config_ad9361_rx_local(unsigned long bandwidth_, + unsigned long sample_rate_, + unsigned long freq_, + std::string rf_port_select_, + std::string gain_mode_rx1_, + std::string gain_mode_rx2_, + double rf_gain_rx1_, + double rf_gain_rx2_); + +bool config_ad9361_rx_remote(std::string remote_host, + unsigned long bandwidth_, + unsigned long sample_rate_, + unsigned long freq_, + std::string rf_port_select_, + std::string gain_mode_rx1_, + std::string gain_mode_rx2_, + double rf_gain_rx1_, + double rf_gain_rx2_); + +bool config_ad9361_lo_local(unsigned long bandwidth_, + unsigned long sample_rate_, + unsigned long freq_rf_tx_hz_, + double tx_attenuation_db_, + long long freq_dds_tx_hz_, + double scale_dds_dbfs_); + +bool config_ad9361_lo_remote(std::string remote_host, + unsigned long bandwidth_, + unsigned long sample_rate_, + unsigned long freq_rf_tx_hz_, + double tx_attenuation_db_, + long long freq_dds_tx_hz_, + double scale_dds_dbfs_); + + +bool ad9361_disable_lo_remote(std::string remote_host); + +bool ad9361_disable_lo_local(); + +#endif diff --git a/src/algorithms/tracking/gnuradio_blocks/galileo_e1_dll_pll_veml_tracking_cc.cc b/src/algorithms/tracking/gnuradio_blocks/galileo_e1_dll_pll_veml_tracking_cc.cc index 2bb7e7c08..4cfbe9305 100644 --- a/src/algorithms/tracking/gnuradio_blocks/galileo_e1_dll_pll_veml_tracking_cc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/galileo_e1_dll_pll_veml_tracking_cc.cc @@ -204,6 +204,9 @@ galileo_e1_dll_pll_veml_tracking_cc::galileo_e1_dll_pll_veml_tracking_cc( { // Disable extended integration if data component tracking is selected d_enable_extended_integration = false; + d_local_code_data_shift_chips = nullptr; + d_data_code = nullptr; + d_Prompt_Data = nullptr; } //--- Initializations ------------------------------ diff --git a/src/algorithms/tracking/gnuradio_blocks/glonass_l2_ca_dll_pll_c_aid_tracking_cc.cc b/src/algorithms/tracking/gnuradio_blocks/glonass_l2_ca_dll_pll_c_aid_tracking_cc.cc index dbebf2ddf..d49fcd5a2 100644 --- a/src/algorithms/tracking/gnuradio_blocks/glonass_l2_ca_dll_pll_c_aid_tracking_cc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/glonass_l2_ca_dll_pll_c_aid_tracking_cc.cc @@ -719,7 +719,7 @@ int glonass_l2_ca_dll_pll_c_aid_tracking_cc::general_work(int noutput_items __at d_code_error_filt_chips_Ti = d_code_error_filt_chips_s * CURRENT_INTEGRATION_TIME_S; code_error_filt_secs_Ti = d_code_error_filt_chips_Ti / d_code_freq_chips; // [s/Ti] - // ################## CARRIER AND CODE NCO BUFFER ALIGNEMENT ####################### + // ################## CARRIER AND CODE NCO BUFFER ALIGNMENT ####################### // keep alignment parameters for the next input buffer // Compute the next buffer length based in the new period of the PRN sequence and the code phase error estimation double T_chip_seconds = 1.0 / d_code_freq_chips; diff --git a/src/core/receiver/CMakeLists.txt b/src/core/receiver/CMakeLists.txt index 0e12422a6..e632d6833 100644 --- a/src/core/receiver/CMakeLists.txt +++ b/src/core/receiver/CMakeLists.txt @@ -90,9 +90,9 @@ if(ENABLE_FMCOMMS2) set(OPT_RECEIVER_INCLUDE_DIRS ${OPT_RECEIVER_INCLUDE_DIRS} ${IIO_INCLUDE_DIRS}) endif(ENABLE_FMCOMMS2) -if(${PC_GNURADIO_RUNTIME_VERSION} VERSION_GREATER "3.7.13" ) +if(${PC_GNURADIO_RUNTIME_VERSION} VERSION_GREATER "3.7.15" ) add_definitions( -DGR_GREATER_38=1 ) -endif(${PC_GNURADIO_RUNTIME_VERSION} VERSION_GREATER "3.7.13" ) +endif(${PC_GNURADIO_RUNTIME_VERSION} VERSION_GREATER "3.7.15" ) include_directories( diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index b4355ed4e..82f4e97d9 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -161,9 +161,9 @@ if(GNUPLOT_FOUND) add_definitions(-DGNUPLOT_EXECUTABLE="${GNUPLOT_EXECUTABLE}") endif(GNUPLOT_FOUND) -if(${PC_GNURADIO_RUNTIME_VERSION} VERSION_GREATER "3.7.13" ) +if(${PC_GNURADIO_RUNTIME_VERSION} VERSION_GREATER "3.7.15" ) add_definitions( -DGR_GREATER_38=1 ) -endif(${PC_GNURADIO_RUNTIME_VERSION} VERSION_GREATER "3.7.13" ) +endif(${PC_GNURADIO_RUNTIME_VERSION} VERSION_GREATER "3.7.15" ) ################################################################################ diff --git a/src/tests/test_main.cc b/src/tests/test_main.cc index b8a8b96e8..ed4f0f4ea 100644 --- a/src/tests/test_main.cc +++ b/src/tests/test_main.cc @@ -114,7 +114,7 @@ DECLARE_string(log_dir); #include "unit-tests/signal-processing-blocks/acquisition/galileo_e1_pcps_quicksync_ambiguous_acquisition_gsoc2014_test.cc" #include "unit-tests/signal-processing-blocks/acquisition/galileo_e5a_pcps_acquisition_gsoc2014_gensource_test.cc" #include "unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_gsoc2017_test.cc" -#include "unit-tests/signal-processing-blocks/acquisition/glonass_l2_ca_pcps_acquisition_test.cc" +// #include "unit-tests/signal-processing-blocks/acquisition/glonass_l2_ca_pcps_acquisition_test.cc" #if OPENCL_BLOCKS_TEST #include "unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_opencl_acquisition_gsoc2013_test.cc"