mirror of
				https://github.com/gnss-sdr/gnss-sdr
				synced 2025-10-31 15:23:04 +00:00 
			
		
		
		
	Adding support for dual channel in FMCOMMS2 and optional Local Oscillator generation using FMCOMMS2 TX channel
This commit is contained in:
		
							
								
								
									
										32
									
								
								cmake/Modules/Findlibiio.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								cmake/Modules/Findlibiio.cmake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | |||||||
|  | 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 | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | FIND_LIBRARY( | ||||||
|  |     LIBIIO_LIBRARIES | ||||||
|  |     NAMES libiio.so | ||||||
|  |     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 | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | message("find libiio:") | ||||||
|  | message(${LIBIIO_LIBRARIES}) | ||||||
|  | INCLUDE(FindPackageHandleStandardArgs) | ||||||
|  | FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBIIO DEFAULT_MSG LIBIIO_LIBRARIES LIBIIO_INCLUDE_DIRS) | ||||||
|  | MARK_AS_ADVANCED(LIBIIO_LIBRARIES LIBIIO_INCLUDE_DIRS) | ||||||
							
								
								
									
										114
									
								
								conf/gnss-sdr_GPS_L1_2ch_fmcomms2_realtime.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								conf/gnss-sdr_GPS_L1_2ch_fmcomms2_realtime.conf
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||||
| @@ -32,7 +32,9 @@ | |||||||
| #include "fmcomms2_signal_source.h" | #include "fmcomms2_signal_source.h" | ||||||
| #include "configuration_interface.h" | #include "configuration_interface.h" | ||||||
| #include "gnss_sdr_valve.h" | #include "gnss_sdr_valve.h" | ||||||
|  | #include "ad9361_manager.h" | ||||||
| #include "GPS_L1_CA.h" | #include "GPS_L1_CA.h" | ||||||
|  | #include "GPS_L2C.h" | ||||||
| #include <glog/logging.h> | #include <glog/logging.h> | ||||||
| #include <iostream> | #include <iostream> | ||||||
|  |  | ||||||
| @@ -55,6 +57,7 @@ Fmcomms2SignalSource::Fmcomms2SignalSource(ConfigurationInterface* configuration | |||||||
|     quadrature_ = configuration->property(role + ".quadrature", true); |     quadrature_ = configuration->property(role + ".quadrature", true); | ||||||
|     rf_dc_ = configuration->property(role + ".rf_dc", true); |     rf_dc_ = configuration->property(role + ".rf_dc", true); | ||||||
|     bb_dc_ = configuration->property(role + ".bb_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_rx1_ = configuration->property(role + ".gain_mode_rx1", std::string("manual")); | ||||||
|     gain_mode_rx2_ = configuration->property(role + ".gain_mode_rx2", 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); |     rf_gain_rx1_ = configuration->property(role + ".gain_rx1", 64.0); | ||||||
| @@ -67,6 +70,15 @@ Fmcomms2SignalSource::Fmcomms2SignalSource(ConfigurationInterface* configuration | |||||||
|     dump_ = configuration->property(role + ".dump", false); |     dump_ = configuration->property(role + ".dump", false); | ||||||
|     dump_filename_ = configuration->property(role + ".dump_filename", default_dump_file); |     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); |     item_size_ = sizeof(gr_complex); | ||||||
|  |  | ||||||
|     std::cout << "device address: " << uri_ << std::endl; |     std::cout << "device address: " << uri_ << std::endl; | ||||||
| @@ -75,15 +87,72 @@ Fmcomms2SignalSource::Fmcomms2SignalSource(ConfigurationInterface* configuration | |||||||
|  |  | ||||||
|     if (item_type_.compare("gr_complex") == 0) |     if (item_type_.compare("gr_complex") == 0) | ||||||
|         { |         { | ||||||
|             fmcomms2_source_f32c_ = gr::iio::fmcomms2_source_f32c::make( |             if (RF_channels_==1) | ||||||
|                 uri_.c_str(), freq_, sample_rate_, |             { | ||||||
|                 bandwidth_, |                 if (rx1_en_ and rx2_en_) | ||||||
|                 rx1_en_, rx2_en_, |                 { | ||||||
|                 buffer_size_, quadrature_, rf_dc_, |                     LOG(FATAL) << "Configuration error: both rx1 and rx2 are enabled but RF_channels=1 !"; | ||||||
|                 bb_dc_, gain_mode_rx1_.c_str(), rf_gain_rx1_, |                 } | ||||||
|                 gain_mode_rx2_.c_str(), rf_gain_rx2_, |                 else | ||||||
|                 rf_port_select_.c_str(), filter_file_.c_str(), |                 { | ||||||
|                 filter_auto_); |                     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 |     else | ||||||
|         { |         { | ||||||
| @@ -108,6 +177,10 @@ Fmcomms2SignalSource::Fmcomms2SignalSource(ConfigurationInterface* configuration | |||||||
|  |  | ||||||
| Fmcomms2SignalSource::~Fmcomms2SignalSource() | Fmcomms2SignalSource::~Fmcomms2SignalSource() | ||||||
| { | { | ||||||
|  |     if (enable_dds_lo_==true) | ||||||
|  |     { | ||||||
|  |         ad9361_disable_lo_remote(uri_); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -88,6 +88,7 @@ private: | |||||||
|     bool quadrature_; |     bool quadrature_; | ||||||
|     bool rf_dc_; |     bool rf_dc_; | ||||||
|     bool bb_dc_; |     bool bb_dc_; | ||||||
|  |     int RF_channels_; | ||||||
|     std::string gain_mode_rx1_; |     std::string gain_mode_rx1_; | ||||||
|     std::string gain_mode_rx2_; |     std::string gain_mode_rx2_; | ||||||
|     double rf_gain_rx1_; |     double rf_gain_rx1_; | ||||||
| @@ -96,6 +97,14 @@ private: | |||||||
|     std::string filter_file_; |     std::string filter_file_; | ||||||
|     bool filter_auto_; |     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 in_stream_; | ||||||
|     unsigned int out_stream_; |     unsigned int out_stream_; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -16,16 +16,58 @@ | |||||||
| # along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>. | # along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>. | ||||||
| # | # | ||||||
|  |  | ||||||
|  | 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 | set (SIGNAL_SOURCE_LIB_SOURCES | ||||||
|   rtl_tcp_commands.cc |   rtl_tcp_commands.cc | ||||||
|   rtl_tcp_dongle_info.cc) |   rtl_tcp_dongle_info.cc | ||||||
|  |   ${OPT_SIGNAL_SOURCE_LIB_SOURCES}) | ||||||
|  |  | ||||||
| include_directories( | include_directories( | ||||||
|      ${CMAKE_CURRENT_SOURCE_DIR} |      ${CMAKE_CURRENT_SOURCE_DIR} | ||||||
|      ${Boost_INCLUDE_DIRS} |      ${Boost_INCLUDE_DIRS} | ||||||
|  |      ${OPT_DRIVER_INCLUDE_DIRS} | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| file(GLOB SIGNAL_SOURCE_LIB_HEADERS "*.h") | file(GLOB SIGNAL_SOURCE_LIB_HEADERS "*.h") | ||||||
| list(SORT SIGNAL_SOURCE_LIB_HEADERS) | list(SORT SIGNAL_SOURCE_LIB_HEADERS) | ||||||
| add_library(signal_source_lib ${SIGNAL_SOURCE_LIB_SOURCES} ${SIGNAL_SOURCE_LIB_HEADERS}) | add_library(signal_source_lib ${SIGNAL_SOURCE_LIB_SOURCES} ${SIGNAL_SOURCE_LIB_HEADERS}) | ||||||
| source_group(Headers FILES ${SIGNAL_SOURCE_LIB_HEADERS}) | source_group(Headers FILES ${SIGNAL_SOURCE_LIB_HEADERS}) | ||||||
|  |  | ||||||
|  | target_link_libraries(signal_source_lib ${OPT_LIBRARIES}) | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										704
									
								
								src/algorithms/signal_source/libs/ad9361_manager.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										704
									
								
								src/algorithms/signal_source/libs/ad9361_manager.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,704 @@ | |||||||
|  | /*! | ||||||
|  |  * \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 <http://www.gnu.org/licenses/>. | ||||||
|  |  * | ||||||
|  |  * ------------------------------------------------------------------------- | ||||||
|  |  */ | ||||||
|  | #include "ad9361_manager.h" | ||||||
|  | #include <glog/logging.h> | ||||||
|  | #include <math.h> | ||||||
|  | #include <iostream> | ||||||
|  | #include <sstream> | ||||||
|  |  | ||||||
|  | /* 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"<<chid; | ||||||
|  |     std::cout<<"* Acquiring AD9361 phy channel"<<chid<<std::endl; | ||||||
|  |     if (!get_phy_chan(ctx, type, chid, &chn)) { return false; } | ||||||
|  |     wr_ch_str(chn, "rf_port_select",     cfg->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 "<<type == TX ? "TX" : "RX"; | ||||||
|  |     std::cout<<"* Acquiring AD9361 "<<(type == TX ? "TX" : "RX")<<std::endl; | ||||||
|  |     if (!get_lo_chan(ctx, type, &chn)) { return false; } | ||||||
|  |     wr_ch_lli(chn, "frequency", cfg->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; | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										127
									
								
								src/algorithms/signal_source/libs/ad9361_manager.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								src/algorithms/signal_source/libs/ad9361_manager.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,127 @@ | |||||||
|  | /*! | ||||||
|  |  * \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 <http://www.gnu.org/licenses/>. | ||||||
|  |  * | ||||||
|  |  * ------------------------------------------------------------------------- | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef __AD9361_MANAGER__ | ||||||
|  | #define __AD9361_MANAGER__ | ||||||
|  |  | ||||||
|  | #include <string> | ||||||
|  |  | ||||||
|  | #ifdef __APPLE__ | ||||||
|  | #include <iio/iio.h> | ||||||
|  | #else | ||||||
|  | #include <iio.h> | ||||||
|  | #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 | ||||||
		Reference in New Issue
	
	Block a user
	 Javier Arribas
					Javier Arribas