mirror of
				https://github.com/gnss-sdr/gnss-sdr
				synced 2025-10-31 07:13:03 +00:00 
			
		
		
		
	Merge branch 'fmcomms2' of https://github.com/academiasIT/gnss-sdr into academiasIT-fmcomms2
This commit is contained in:
		
							
								
								
									
										56
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										56
									
								
								README.md
									
									
									
									
									
								
							| @@ -368,7 +368,63 @@ $ sudo make install | ||||
|  | ||||
| (in order to disable the `Osmosdr_Signal_Source` compilation, you can pass `DENABLE_OSMOSDR=OFF` to cmake and build GNSS-SDR again). | ||||
|  | ||||
| ###### Build FMCOMMS2 based SDR Hardware support (OPTIONAL): | ||||
|  | ||||
| Install the [libiio](https://github.com/analogdevicesinc/libiio.git) (>=v0.11), [libad9361](https://github.com/analogdevicesinc/libad9361-iio.git) (>=v0.1-1) libraries and [gr-iio](https://github.com/analogdevicesinc/gr-iio.git) (>=v0.2) gnuradio block. For example in Ubuntu 16.04 follow these instructions (based on https://github.com/blurbdust/blurbdust.github.io): | ||||
|  | ||||
| ~~~~~~ | ||||
| $ git clone https://github.com/analogdevicesinc/libiio.git | ||||
| $ cd libiio | ||||
| $ mkdir build | ||||
| $ cd build | ||||
| $ cmake .. | ||||
| $ make | ||||
| $ sudo make install | ||||
| $ sudo ldconfig | ||||
| $ git clone https://github.com/analogdevicesinc/libad9361-iio.git | ||||
| $ cd libad9361-iio | ||||
| $ mkdir build | ||||
| $ cd build | ||||
| $ cmake .. | ||||
| $ make | ||||
| $ sudo make install | ||||
| $ sudo ldconfig | ||||
| $ git clone https://github.com/analogdevicesinc/gr-iio.git | ||||
| $ cd gr-iio | ||||
| $ mv include/gnuradio/iio include/iio | ||||
| $ rm -r include/gnuradio | ||||
| $ sed -i 's/gnuradio\/iio/iio/g' CMakeLists.txt | ||||
| $ sed -i 's/gnuradio\/iio/iio/g' swig/* | ||||
| $ sed -i 's/gnuradio\/iio/iio/g' include/iio/* | ||||
| $ sed -i 's/gnuradio\/iio/iio/g' lib/* | ||||
| $ sed -i 's/gnuradio\/iio/iio/g' python/iio/* | ||||
| $ sed -i 's/from\ gnuradio\ import\ iio/import\ iio/g' grc/iio_pluto_sink.xml | ||||
| $ sed -i 's/from\ gnuradio\ import\ iio/import\ iio/g' grc/iio_pluto_source.xml | ||||
| $ sed -i 's/from\ gnuradio\ import\ iio/import\ iio/g' grc/iio_fmcomms2_sink.xml | ||||
| $ sed -i 's/from\ gnuradio\ import\ iio/import\ iio/g' grc/iio_fmcomms2_source.xml | ||||
| $ mkdir build | ||||
| $ cd build | ||||
| $ cmake .. | ||||
| $ make | ||||
| $ sudo make install | ||||
| $ sudo ldconfig | ||||
| ~~~~~~ | ||||
|  | ||||
| Then configure the gnss-sdr to build the `Fmcomms2_Signal_Source` and `Plutosdr_Signal_Source`: | ||||
| ~~~~~~ | ||||
| $ cmake -DENABLE_FMCOMMS2=ON ../ | ||||
| $ make | ||||
| $ sudo make install | ||||
| ~~~~~~ | ||||
|  | ||||
| or configure only `Plutosdr_Signal_Source`: | ||||
| ~~~~~~ | ||||
| $ cmake -DENABLE_PLUTOSDR=ON ../ | ||||
| $ make | ||||
| $ sudo make install | ||||
| ~~~~~~ | ||||
|  | ||||
| With `Fmcomms2_Signal_Source` you can use any SDR hardware based on fmcomms2, including the ADALM-PLUTO (PlutoSdr) by configuring correctly the .conf file. The `Plutosdr_Signal_Source` offers a simplier manner to use the ADALM-PLUTO because implements only a subset of fmcomms2's parameters valid for it device. | ||||
|  | ||||
| ###### Build OpenCL support (OPTIONAL): | ||||
|  | ||||
|   | ||||
							
								
								
									
										145
									
								
								conf/gnss-sdr_GPS_L1_fmcomms2_realtime.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								conf/gnss-sdr_GPS_L1_fmcomms2_realtime.conf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,145 @@ | ||||
| ; 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_hz: Internal signal sampling frequency after the signal conditioning stage [Hz]. | ||||
| ;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_hz=2000000 | ||||
|  | ||||
|  | ||||
| ;######### SUPL RRLP GPS assistance configuration ##### | ||||
| ; Check http://www.mcc-mnc.com/ | ||||
| ; On Android: https://play.google.com/store/apps/details?id=net.its_here.cellidinfo&hl=en | ||||
| GNSS-SDR.SUPL_gps_enabled=false | ||||
| GNSS-SDR.SUPL_read_gps_assistance_xml=false | ||||
| GNSS-SDR.SUPL_gps_ephemeris_server=supl.google.com | ||||
| GNSS-SDR.SUPL_gps_ephemeris_port=7275 | ||||
| GNSS-SDR.SUPL_gps_acquisition_server=supl.google.com | ||||
| GNSS-SDR.SUPL_gps_acquisition_port=7275 | ||||
| GNSS-SDR.SUPL_MCC=244 | ||||
| GNSS-SDR.SUPL_MNS=5 | ||||
| GNSS-SDR.SUPL_LAC=0x59e2 | ||||
| GNSS-SDR.SUPL_CI=0x31b0 | ||||
|  | ||||
| ;######### SIGNAL_SOURCE CONFIG ############ | ||||
| SignalSource.implementation=Fmcomms2_Signal_Source | ||||
| ;SignalSource.filename=/media/DATALOGGER_/signals/RTL-SDR/geo/pmt4.dat | ||||
| SignalSource.item_type=gr_complex | ||||
| SignalSource.device_address=10.42.0.196 | ||||
| SignalSource.sampling_frequency=2000000 | ||||
| SignalSource.freq=1575420000 | ||||
| SignalSource.bandwidth=2000000 | ||||
| SignalSource.decimation=0 | ||||
| SignalSource.rx1_enable=true | ||||
| SignalSource.gain_mode_rx1=manual | ||||
| SignalSource.rf_port_select=A_BALANCED | ||||
| SignalSource.gain_rx1=64 | ||||
| SignalSource.samples=0 | ||||
| SignalSource.repeat=false | ||||
| SignalSource.dump=false | ||||
| SignalSource.dump_filename=../data/signal_source.dat | ||||
| SignalSource.enable_throttle_control=false | ||||
|  | ||||
| ;######### SIGNAL_CONDITIONER CONFIG ############ | ||||
| SignalConditioner.implementation=Signal_Conditioner | ||||
|  | ||||
| ;######### DATA_TYPE_ADAPTER CONFIG ############ | ||||
| DataTypeAdapter.implementation=Pass_Through | ||||
|  | ||||
| ;######### INPUT_FILTER CONFIG ############ | ||||
| InputFilter.implementation=Freq_Xlating_Fir_Filter | ||||
| InputFilter.dump=false | ||||
| InputFilter.dump_filename=../data/input_filter.dat | ||||
| InputFilter.input_item_type=gr_complex | ||||
| InputFilter.output_item_type=gr_complex | ||||
| InputFilter.taps_item_type=float | ||||
| InputFilter.number_of_taps=5 | ||||
| InputFilter.number_of_bands=2 | ||||
| InputFilter.band1_begin=0.0 | ||||
| InputFilter.band1_end=0.45 | ||||
| InputFilter.band2_begin=0.55 | ||||
| InputFilter.band2_end=1.0 | ||||
| InputFilter.ampl1_begin=1.0 | ||||
| InputFilter.ampl1_end=1.0 | ||||
| InputFilter.ampl2_begin=0.0 | ||||
| InputFilter.ampl2_end=0.0 | ||||
| InputFilter.band1_error=1.0 | ||||
| InputFilter.band2_error=1.0 | ||||
| InputFilter.filter_type=bandpass | ||||
| InputFilter.grid_density=16 | ||||
| InputFilter.sampling_frequency=2000000 | ||||
| InputFilter.IF=0; IF deviation due to front-end LO inaccuracies [Hz] | ||||
|  | ||||
| ;######### RESAMPLER CONFIG ############ | ||||
| ;## Resamples the input data. | ||||
| ;# DISABLED IN THE RTL-SDR REALTIME | ||||
| ;#implementation: Use [Pass_Through] or [Direct_Resampler] | ||||
| ;#[Pass_Through] disables this block | ||||
| Resampler.implementation=Pass_Through | ||||
|  | ||||
| ;######### CHANNELS GLOBAL CONFIG ############ | ||||
| Channels_1C.count=5 | ||||
| Channels.in_acquisition=1 | ||||
| Channel.signal=1C | ||||
|  | ||||
|  | ||||
| ;######### ACQUISITION GLOBAL CONFIG ############ | ||||
| Acquisition_1C.dump=false | ||||
| Acquisition_1C.dump_filename=./acq_dump.dat | ||||
| Acquisition_1C.item_type=gr_complex | ||||
| Acquisition_1C.if=0 | ||||
| Acquisition_1C.sampled_ms=1 | ||||
| Acquisition_1C.implementation=GPS_L1_CA_PCPS_Acquisition_Fine_Doppler | ||||
| Acquisition_1C.threshold=0.015 | ||||
| ;Acquisition_1C.pfa=0.0001 | ||||
| Acquisition_1C.doppler_max=10000 | ||||
| Acquisition_1C.doppler_min=-10000 | ||||
| Acquisition_1C.doppler_step=500 | ||||
| Acquisition_1C.max_dwells=15 | ||||
|  | ||||
|  | ||||
| ;######### TRACKING GLOBAL CONFIG ############ | ||||
| Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_Tracking | ||||
| Tracking_1C.item_type=gr_complex | ||||
| Tracking_1C.if=0 | ||||
| Tracking_1C.dump=false | ||||
| Tracking_1C.dump_filename=./tracking_ch_ | ||||
| Tracking_1C.pll_bw_hz=40.0; | ||||
| Tracking_1C.dll_bw_hz=2.0; | ||||
| Tracking_1C.order=3; | ||||
| Tracking_1C.early_late_space_chips=0.5; | ||||
|  | ||||
| ;######### TELEMETRY DECODER GPS CONFIG ############ | ||||
| TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder | ||||
| TelemetryDecoder_1C.dump=false | ||||
| TelemetryDecoder_1C.decimation_factor=1; | ||||
|  | ||||
| ;######### OBSERVABLES CONFIG ############ | ||||
| Observables.implementation=GPS_L1_CA_Observables | ||||
| Observables.dump=false | ||||
| Observables.dump_filename=./observables.dat | ||||
|  | ||||
|  | ||||
| ;######### PVT CONFIG ############ | ||||
| ;#implementation: Position Velocity and Time (PVT) implementation algorithm: Use [GPS_L1_CA_PVT] in this version. | ||||
| PVT.implementation=GPS_L1_CA_PVT | ||||
|  | ||||
| ;#averaging_depth: Number of PVT observations in the moving average algorithm | ||||
| PVT.averaging_depth=10 | ||||
|  | ||||
| ;#flag_average: Enables the PVT averaging between output intervals (arithmetic mean) [true] or [false] | ||||
| PVT.flag_averaging=true | ||||
| 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.dump=false | ||||
| PVT.flag_rtcm_server=false | ||||
| PVT.flag_rtcm_tty_port=false | ||||
| PVT.rtcm_dump_devname=/dev/pts/1 | ||||
							
								
								
									
										89
									
								
								conf/gnss-sdr_GPS_L1_plutosdr_realtime.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								conf/gnss-sdr_GPS_L1_plutosdr_realtime.conf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | ||||
| ; 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_hz: Internal signal sampling frequency after the signal conditioning stage [Hz]. | ||||
| ;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_hz=2000000 | ||||
|  | ||||
|  | ||||
| ;######### SUPL RRLP GPS assistance configuration ##### | ||||
| ; Check http://www.mcc-mnc.com/ | ||||
| ; On Android: https://play.google.com/store/apps/details?id=net.its_here.cellidinfo&hl=en | ||||
| GNSS-SDR.SUPL_gps_enabled=false | ||||
| GNSS-SDR.SUPL_read_gps_assistance_xml=false | ||||
| GNSS-SDR.SUPL_gps_ephemeris_server=supl.google.com | ||||
| GNSS-SDR.SUPL_gps_ephemeris_port=7275 | ||||
| GNSS-SDR.SUPL_gps_acquisition_server=supl.google.com | ||||
| GNSS-SDR.SUPL_gps_acquisition_port=7275 | ||||
| GNSS-SDR.SUPL_MCC=244 | ||||
| GNSS-SDR.SUPL_MNS=5 | ||||
| GNSS-SDR.SUPL_LAC=0x59e2 | ||||
| GNSS-SDR.SUPL_CI=0x31b0 | ||||
|  | ||||
| ;######### SIGNAL_SOURCE CONFIG ############ | ||||
| SignalSource.implementation=Plutosdr_Signal_Source | ||||
| ;SignalSource.filename=/media/DATALOGGER_/signals/RTL-SDR/geo/pmt4.dat | ||||
| SignalSource.item_type=gr_complex | ||||
| SignalSource.device_address=192.168.2.1 | ||||
| SignalSource.sampling_frequency=3000000 | ||||
| SignalSource.freq=1575420000 | ||||
| SignalSource.bandwidth=2600000 | ||||
| SignalSource.decimation=0 | ||||
| SignalSource.gain_mode=manual | ||||
| SignalSource.gain=30 | ||||
| SignalSource.samples=0 | ||||
| SignalSource.buffer_size=65000 | ||||
| SignalSource.repeat=false | ||||
| SignalSource.dump=false | ||||
| SignalSource.dump_filename=./capture.dat | ||||
| SignalSource.enable_throttle_control=false | ||||
|  | ||||
| ;######### SIGNAL_CONDITIONER CONFIG ############ | ||||
| SignalConditioner.implementation=Signal_Conditioner | ||||
| InputFilter.implementation=Pass_Through | ||||
| InputFilter.item_type=gr_complex | ||||
| Resampler.implementation=Direct_Resampler | ||||
| Resampler.sample_freq_in=4000000 | ||||
| Resampler.sample_freq_out=2000000 | ||||
| Resampler.item_type=gr_complex | ||||
|  | ||||
|  | ||||
| ;######### DATA_TYPE_ADAPTER CONFIG ############ | ||||
| DataTypeAdapter.implementation=Pass_Through | ||||
| DataTypeAdapter.item_type=gr_complex | ||||
|  | ||||
| ;######### CHANNELS GLOBAL CONFIG ############ | ||||
| Channels_1C.count=6 | ||||
| Channels.in_acquisition=1 | ||||
| Channel.signal=1C | ||||
|  | ||||
| ;######### ACQUISITION GLOBAL CONFIG ############ | ||||
| Acquisition_1C.implementation=GPS_L1_CA_PCPS_Acquisition | ||||
| Acquisition_1C.item_type=gr_complex | ||||
| Acquisition_1C.threshold=0.008 | ||||
| Acquisition_1C.doppler_max=10000 | ||||
| Acquisition_1C.doppler_step=250 | ||||
|  | ||||
| ;######### TRACKING GLOBAL CONFIG ############ | ||||
| Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_Tracking | ||||
| Tracking_1C.item_type=gr_complex | ||||
| Tracking_1C.pll_bw_hz=40.0; | ||||
| Tracking_1C.dll_bw_hz=4.0; | ||||
|  | ||||
| ;######### TELEMETRY DECODER GPS CONFIG ############ | ||||
| TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder | ||||
|  | ||||
| ;######### OBSERVABLES CONFIG ############ | ||||
| Observables.implementation=GPS_L1_CA_Observables | ||||
|  | ||||
| ;######### PVT CONFIG ############ | ||||
| PVT.implementation=GPS_L1_CA_PVT | ||||
| PVT.averaging_depth=100 | ||||
| PVT.flag_averaging=true | ||||
| PVT.output_rate_ms=10 | ||||
| PVT.display_rate_ms=500 | ||||
| @@ -21,6 +21,36 @@ list(SORT SIGNAL_SOURCE_ADAPTER_HEADERS) | ||||
|  | ||||
| # Optional drivers | ||||
|  | ||||
| if(ENABLE_PLUTOSDR) | ||||
|     ############################################## | ||||
|     # ADALM-PLUTO (Analog Devices Inc.) | ||||
|     ############################################## | ||||
| 	find_package(iio REQUIRED) | ||||
| 	if(NOT IIO_FOUND) | ||||
| 		message("gnuradio-iio not found, installation is required") | ||||
| 		message(FATAL_ERROR "gnuradio-iio required for building gnss-sdr with this option enabled") | ||||
| 	else(NOT IIO_FOUND) | ||||
| 	    set(OPT_LIBRARIES ${OPT_LIBRARIES} ${IIO_LIBRARIES}) | ||||
|         set(OPT_DRIVER_INCLUDE_DIRS ${OPT_DRIVER_INCLUDE_DIRS} ${IIO_INCLUDE_DIRS}) | ||||
|         set(OPT_DRIVER_SOURCES ${OPT_DRIVER_SOURCES} plutosdr_signal_source.cc) | ||||
|     endif(NOT IIO_FOUND) | ||||
| endif(ENABLE_PLUTOSDR) | ||||
|  | ||||
| if(ENABLE_FMCOMMS2) | ||||
|     ############################################### | ||||
|     # FMCOMMS2 based SDR Hardware | ||||
|     ############################################### | ||||
| 	find_package(iio REQUIRED) | ||||
| 	if(NOT IIO_FOUND) | ||||
| 		message("gnuradio-iio not found, installation is required") | ||||
| 		message(FATAL_ERROR "gnuradio-iio required for building gnss-sdr with this option enabled") | ||||
| 	else(NOT IIO_FOUND) | ||||
| 	    set(OPT_LIBRARIES ${OPT_LIBRARIES} ${IIO_LIBRARIES}) | ||||
|         set(OPT_DRIVER_INCLUDE_DIRS ${OPT_DRIVER_INCLUDE_DIRS} ${IIO_INCLUDE_DIRS}) | ||||
|         set(OPT_DRIVER_SOURCES ${OPT_DRIVER_SOURCES} fmcomms2_signal_source.cc plutosdr_signal_source.cc) | ||||
|    endif(NOT IIO_FOUND) | ||||
| endif(ENABLE_FMCOMMS2) | ||||
|  | ||||
| if(ENABLE_GN3S) | ||||
|      ############################################## | ||||
|      # GN3S (USB dongle) | ||||
|   | ||||
							
								
								
									
										178
									
								
								src/algorithms/signal_source/adapters/fmcomms2_signal_source.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								src/algorithms/signal_source/adapters/fmcomms2_signal_source.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,178 @@ | ||||
| /*! | ||||
|  * \filei fmcomms2_signal_source.cc | ||||
|  * \brief signal source for sdr hardware from analog devices based on  | ||||
|  * fmcomms2 evaluation board.  | ||||
|  * \author Rodrigo Muñoz, 2017, rmunozl(at)inacap.cl | ||||
|  * | ||||
|  * ------------------------------------------------------------------------- | ||||
|  * | ||||
|  * Copyright (C) 2010-2015  (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 "fmcomms2_signal_source.h" | ||||
| #include <cstdio> | ||||
| #include <iostream> | ||||
| #include <boost/format.hpp> | ||||
| #include <glog/logging.h> | ||||
| #include <gnuradio/blocks/file_sink.h> | ||||
| #include "configuration_interface.h" | ||||
| #include "gnss_sdr_valve.h" | ||||
| #include "GPS_L1_CA.h" | ||||
|  | ||||
| using google::LogMessage; | ||||
|  | ||||
| Fmcomms2SignalSource::Fmcomms2SignalSource(ConfigurationInterface* configuration, | ||||
|         std::string role, unsigned int in_stream, unsigned int out_stream, | ||||
|         boost::shared_ptr<gr::msg_queue> queue) : | ||||
|                 role_(role), in_stream_(in_stream), out_stream_(out_stream), | ||||
|                 queue_(queue) | ||||
| { | ||||
| 	std::string default_item_type="gr_complex"; | ||||
| 	std::string default_dump_file="./data/signal_source.dat"; | ||||
| 	uri_= configuration->property(role+".device_address",std::string("192.168.2.1")); | ||||
| 	freq_= configuration->property(role+".freq",GPS_L1_FREQ_HZ); | ||||
| 	sample_rate_=configuration->property(role+".sampling_frequency",2600000); | ||||
| 	bandwidth_= configuration->property(role+".bandwidth",2000000); | ||||
| 	rx1_en_=configuration->property(role+".rx1_enable",true); | ||||
| 	rx2_en_=configuration->property(role+".rx2_enable",false); | ||||
| 	buffer_size_=configuration->property(role+".buffer_size",0xA0000); | ||||
| 	decimation_=configuration->property(role+".decimation",1); | ||||
| 	quadrature_=configuration->property(role+".quadrature",true); | ||||
| 	rf_dc_=configuration->property(role+".rf_dc",true); | ||||
| 	bb_dc_=configuration->property(role+".bb_dc",true); | ||||
| 	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); | ||||
| 	rf_gain_rx2_=configuration->property(role+".gain_rx2",64.0); | ||||
| 	rf_port_select_=configuration->property(role+".rf_port_select",std::string("A_BALANCED")); | ||||
| 	filter_file_=configuration->property(role+".filter_file",std::string("")); | ||||
| 	filter_auto_=configuration->property(role+".filter_auto",true); | ||||
| 	item_type_=configuration->property(role+".item_type",default_item_type); | ||||
| 	samples_=configuration->property(role+".samples",0); | ||||
| 	dump_=configuration->property(role+".dump",false); | ||||
| 	dump_filename_=configuration->property(role+".dump_filename",default_dump_file); | ||||
| 	 | ||||
| 	item_size_=sizeof(gr_complex); | ||||
|  | ||||
| 	std::cout<<"device address: "<<uri_<<std::endl; | ||||
| 	std::cout<<"LO frequency : "<<freq_<<"Hz"<<std::endl; | ||||
| 	std::cout<<"sample rate: "<<sample_rate_<<"Hz"<<std::endl; | ||||
|  | ||||
| 	if(item_type_.compare("gr_complex")==0) | ||||
| 	{ | ||||
| 		fmcomms2_source_f32c_ = gr::iio::fmcomms2_source_f32c::make( | ||||
| 			uri_.c_str(), freq_, sample_rate_, | ||||
| 		    decimation_, 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_); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		LOG(FATAL) <<"Exception: item type "<<item_type_<<" not suported!"; | ||||
| 	} | ||||
|  | ||||
| 	if (samples_ != 0) | ||||
|     { | ||||
|     	DLOG(INFO) << "Send STOP signal after " << samples_ << " samples"; | ||||
|         valve_ = gnss_sdr_make_valve(item_size_, samples_, queue_); | ||||
|         DLOG(INFO) << "valve(" << valve_->unique_id() << ")"; | ||||
|     } | ||||
|  | ||||
|     if (dump_) | ||||
|     { | ||||
|     	DLOG(INFO) << "Dumping output into file " << dump_filename_; | ||||
|         file_sink_ = gr::blocks::file_sink::make(item_size_, dump_filename_.c_str()); | ||||
|          DLOG(INFO) << "file_sink(" << file_sink_->unique_id() << ")"; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| Fmcomms2SignalSource::~Fmcomms2SignalSource() | ||||
| { | ||||
| } | ||||
|  | ||||
| void Fmcomms2SignalSource::connect(gr::top_block_sptr top_block) | ||||
| { | ||||
|     if (samples_ != 0) | ||||
|         { | ||||
| 			top_block->connect(fmcomms2_source_f32c_, 0, valve_, 0); | ||||
|             DLOG(INFO) << "connected fmcomms2 source to valve"; | ||||
|             if (dump_) | ||||
|                 { | ||||
|                     top_block->connect(valve_, 0, file_sink_, 0); | ||||
|                     DLOG(INFO) << "connected valve to file sink"; | ||||
|                 } | ||||
| 		} | ||||
|     else | ||||
|         { | ||||
|             if (dump_) | ||||
|                 { | ||||
| 					 | ||||
|                     top_block->connect(fmcomms2_source_f32c_ , 0, file_sink_, 0); | ||||
|                     DLOG(INFO) << "connected fmcomms2 source to file sink"; | ||||
|                 } | ||||
|         } | ||||
| } | ||||
|  | ||||
|  | ||||
| void Fmcomms2SignalSource::disconnect(gr::top_block_sptr top_block) | ||||
| { | ||||
|     if (samples_ != 0) | ||||
|         { | ||||
|             top_block->disconnect(fmcomms2_source_f32c_, 0, valve_, 0); | ||||
|             if (dump_) | ||||
|                 { | ||||
|                     top_block->disconnect(valve_, 0, file_sink_, 0); | ||||
|                 } | ||||
|         } | ||||
|     else | ||||
|         { | ||||
|             if (dump_) | ||||
|                 { | ||||
|                     top_block->disconnect(fmcomms2_source_f32c_, 0,	file_sink_, 0); | ||||
|                 } | ||||
|         } | ||||
| } | ||||
|  | ||||
|  | ||||
| gr::basic_block_sptr Fmcomms2SignalSource::get_left_block() | ||||
| { | ||||
|     LOG(WARNING) << "Trying to get signal source left block."; | ||||
|     return gr::basic_block_sptr(); | ||||
| } | ||||
|  | ||||
|  | ||||
| gr::basic_block_sptr Fmcomms2SignalSource::get_right_block() | ||||
| { | ||||
|     if (samples_ != 0) | ||||
|         { | ||||
|             return valve_; | ||||
|         } | ||||
|     else | ||||
|         { | ||||
|             return (fmcomms2_source_f32c_); | ||||
|         } | ||||
| } | ||||
							
								
								
									
										115
									
								
								src/algorithms/signal_source/adapters/fmcomms2_signal_source.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								src/algorithms/signal_source/adapters/fmcomms2_signal_source.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,115 @@ | ||||
| /*! | ||||
|  * \file fmcomms2_signal_source.h | ||||
|  * \brief Interface to use SDR hardware based in FMCOMMS2 driver from analog  | ||||
|  * devices, for example FMCOMMS4 and ADALM-PLUTO (PlutoSdr) | ||||
|  * \author Rodrigo Muñoz, 2017. rmunozl(at)inacap.cl | ||||
|  * | ||||
|  * This class represent a fmcomms2 signal source. It use the gr_iio block | ||||
|  * ------------------------------------------------------------------------- | ||||
|  * | ||||
|  * Copyright (C) 2010-2015  (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 GNSS_SDR_FMCOMMS2_SIGNAL_SOURCE_H_ | ||||
| #define GNSS_SDR_FMCOMMS2_SIGNAL_SOURCE_H_ | ||||
|  | ||||
| #include <string> | ||||
| #include <boost/shared_ptr.hpp> | ||||
| #include <gnuradio/msg_queue.h> | ||||
| #include <gnuradio/blocks/file_sink.h> | ||||
| #include <iio/fmcomms2_source.h> | ||||
| #include "gnss_block_interface.h" | ||||
|  | ||||
| class ConfigurationInterface; | ||||
|  | ||||
| class Fmcomms2SignalSource: public GNSSBlockInterface | ||||
| { | ||||
| public: | ||||
|     Fmcomms2SignalSource(ConfigurationInterface* configuration, | ||||
|             std::string role, unsigned int in_stream, | ||||
|             unsigned int out_stream, boost::shared_ptr<gr::msg_queue> queue); | ||||
|  | ||||
|     virtual ~Fmcomms2SignalSource(); | ||||
|  | ||||
|     std::string role() | ||||
|     { | ||||
|         return role_; | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|      * \brief Returns "fmcomms2_Signal_Source" | ||||
|      */ | ||||
|     std::string implementation() | ||||
|     { | ||||
|         return "Fmcomms2_Signal_Source"; | ||||
|     } | ||||
|     size_t item_size() | ||||
|     { | ||||
|         return item_size_; | ||||
|     } | ||||
|  | ||||
|     void connect(gr::top_block_sptr top_block); | ||||
|     void disconnect(gr::top_block_sptr top_block); | ||||
|     gr::basic_block_sptr get_left_block(); | ||||
|     gr::basic_block_sptr get_right_block(); | ||||
|  | ||||
| private: | ||||
|     std::string role_; | ||||
|  | ||||
|     // Front-end settings | ||||
| 	std::string uri_;//device direction | ||||
| 	unsigned long freq_; //frequency of local oscilator | ||||
| 	unsigned long sample_rate_; | ||||
| 	unsigned long bandwidth_; | ||||
| 	unsigned long buffer_size_; //reception buffer | ||||
| 	unsigned int decimation_; | ||||
| 	bool rx1_en_; | ||||
| 	bool rx2_en_; | ||||
| 	bool quadrature_; | ||||
| 	bool rf_dc_; | ||||
| 	bool bb_dc_; | ||||
| 	std::string gain_mode_rx1_; | ||||
| 	std::string gain_mode_rx2_; | ||||
| 	double rf_gain_rx1_; | ||||
| 	double rf_gain_rx2_; | ||||
| 	std::string rf_port_select_; | ||||
| 	std::string filter_file_; | ||||
| 	bool filter_auto_; | ||||
|  | ||||
|     unsigned int in_stream_; | ||||
|     unsigned int out_stream_; | ||||
|  | ||||
|     std::string item_type_; | ||||
|     size_t item_size_; | ||||
|     long samples_; | ||||
|     bool dump_; | ||||
|     std::string dump_filename_; | ||||
|  | ||||
| 	gr::iio::fmcomms2_source_f32c::sptr fmcomms2_source_f32c_; | ||||
|  | ||||
|     boost::shared_ptr<gr::block> valve_; | ||||
|     gr::blocks::file_sink::sptr file_sink_; | ||||
|     boost::shared_ptr<gr::msg_queue> queue_; | ||||
| }; | ||||
|  | ||||
| #endif /*GNSS_SDR_FMCOMMS2_SIGNAL_SOURCE_H_*/ | ||||
							
								
								
									
										138
									
								
								src/algorithms/signal_source/adapters/plutosdr_signal_source.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								src/algorithms/signal_source/adapters/plutosdr_signal_source.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,138 @@ | ||||
| #include "plutosdr_signal_source.h" | ||||
| #include <iostream> | ||||
| #include <boost/format.hpp> | ||||
| #include <glog/logging.h> | ||||
| #include <gnuradio/blocks/file_sink.h> | ||||
| #include "configuration_interface.h" | ||||
| #include "gnss_sdr_valve.h" | ||||
| #include "GPS_L1_CA.h" | ||||
|  | ||||
|  | ||||
| using google::LogMessage; | ||||
|  | ||||
|  | ||||
| PlutosdrSignalSource::PlutosdrSignalSource(ConfigurationInterface* configuration, | ||||
|         std::string role, unsigned int in_stream, unsigned int out_stream, | ||||
|         boost::shared_ptr<gr::msg_queue> queue) : | ||||
|                 role_(role), in_stream_(in_stream), out_stream_(out_stream), | ||||
|                 queue_(queue) | ||||
| { | ||||
| 	std::string default_item_type="gr_complex"; | ||||
| 	std::string default_dump_file="./data/signal_source.dat"; | ||||
| 	uri_ = configuration->property(role+".device_address",std::string("192.168.2.1")); | ||||
| 	freq_= configuration->property(role+".freq",GPS_L1_FREQ_HZ); | ||||
| 	sample_rate_=configuration->property(role+".sampling_frequency",3000000); | ||||
| 	bandwidth_ = configuration->property(role+".bandwidth",2000000); | ||||
| 	buffer_size_=configuration->property(role+".buffer_size",0xA0000); | ||||
| 	decimation_=configuration->property(role+".decimation",1); | ||||
| 	quadrature_=configuration->property(role+".quadrature",true); | ||||
| 	rf_dc_ =configuration->property(role+".rf_dc",true); | ||||
| 	bb_dc_ =configuration->property(role+".bb_dc",true); | ||||
| 	gain_mode_=configuration->property(role+".gain_mode",std::string("manual")); | ||||
| 	rf_gain_=configuration->property(role+".gain",50.0); | ||||
| 	filter_file_=configuration->property(role+".filter_file",std::string("")); | ||||
| 	filter_auto_=configuration->property(role+".filter_auto",true); | ||||
|  | ||||
| 	item_type_=configuration->property(role+".item_type",default_item_type); | ||||
| 	samples_=configuration->property(role+".samples",0); | ||||
| 	dump_=configuration->property(role+".dump",false); | ||||
| 	dump_filename_=configuration->property(role+".dump_filename",default_dump_file); | ||||
| 	 | ||||
| 	if(item_type_.compare("gr_complex") != 0) | ||||
| 	{ | ||||
| 		std::cout<<"bad item_type!!"<<std::endl; | ||||
| 		LOG(FATAL) <<"Exception: item type must be gr_complex!"; | ||||
| 	} | ||||
| 	 | ||||
| 	item_size_=sizeof(gr_complex); | ||||
|  | ||||
|  | ||||
| 	std::cout<<"device address: "<<uri_<<std::endl; | ||||
| 	std::cout<<"frequency : "<<freq_<<"Hz"<<std::endl; | ||||
| 	std::cout<<"sample rate: "<<sample_rate_<<"Hz"<<std::endl; | ||||
| 	std::cout<<"gain mode: "<<gain_mode_<<std::endl; | ||||
| 	std::cout<<"item type: "<<item_type_<<std::endl; | ||||
|  | ||||
| 	plutosdr_source_=gr::iio::pluto_source::make(uri_, freq_, sample_rate_, | ||||
| 		 decimation_, bandwidth_, buffer_size_, quadrature_, rf_dc_, bb_dc_,  | ||||
| 		gain_mode_.c_str(), rf_gain_,filter_file_.c_str(), filter_auto_); | ||||
|  | ||||
| 	if (samples_ != 0) | ||||
|     { | ||||
|     	DLOG(INFO) << "Send STOP signal after " << samples_ << " samples"; | ||||
|         valve_ = gnss_sdr_make_valve(item_size_, samples_, queue_); | ||||
|         DLOG(INFO) << "valve(" << valve_->unique_id() << ")"; | ||||
|     } | ||||
|  | ||||
|     if (dump_) | ||||
|     { | ||||
|     	DLOG(INFO) << "Dumping output into file " << dump_filename_; | ||||
|         file_sink_ = gr::blocks::file_sink::make(item_size_, dump_filename_.c_str()); | ||||
|          DLOG(INFO) << "file_sink(" << file_sink_->unique_id() << ")"; | ||||
|         } | ||||
| } | ||||
|  | ||||
| PlutosdrSignalSource::~PlutosdrSignalSource() | ||||
| {} | ||||
|  | ||||
| void PlutosdrSignalSource::connect(gr::top_block_sptr top_block) | ||||
| { | ||||
|     if (samples_ != 0) | ||||
|         { | ||||
|             top_block->connect(plutosdr_source_, 0, valve_, 0); | ||||
|             DLOG(INFO) << "connected plutosdr source to valve"; | ||||
|             if (dump_) | ||||
|                 { | ||||
|                     top_block->connect(valve_, 0, file_sink_, 0); | ||||
|                     DLOG(INFO) << "connected valve to file sink"; | ||||
|                 } | ||||
|         } | ||||
|     else | ||||
|         { | ||||
|             if (dump_) | ||||
|                 { | ||||
|                     top_block->connect(plutosdr_source_, 0, file_sink_, 0); | ||||
|                     DLOG(INFO) << "connected plutosdr source to file sink"; | ||||
|                 } | ||||
|         } | ||||
| } | ||||
|  | ||||
|  | ||||
| void PlutosdrSignalSource::disconnect(gr::top_block_sptr top_block) | ||||
| { | ||||
|     if (samples_ != 0) | ||||
|         { | ||||
|             top_block->disconnect(plutosdr_source_, 0, valve_, 0); | ||||
|             if (dump_) | ||||
|                 { | ||||
|                     top_block->disconnect(valve_, 0, file_sink_, 0); | ||||
|                 } | ||||
|         } | ||||
|     else | ||||
|         { | ||||
|             if (dump_) | ||||
|                 { | ||||
|                     top_block->disconnect(plutosdr_source_, 0, file_sink_, 0); | ||||
|                 } | ||||
|         } | ||||
| } | ||||
|  | ||||
|  | ||||
| gr::basic_block_sptr PlutosdrSignalSource::get_left_block() | ||||
| { | ||||
|     LOG(WARNING) << "Trying to get signal source left block."; | ||||
|     return gr::basic_block_sptr(); | ||||
| } | ||||
|  | ||||
|  | ||||
| gr::basic_block_sptr PlutosdrSignalSource::get_right_block() | ||||
| { | ||||
|     if (samples_ != 0) | ||||
|         { | ||||
|             return valve_; | ||||
|         } | ||||
|     else | ||||
|         { | ||||
|             return plutosdr_source_; | ||||
|         } | ||||
| } | ||||
| @@ -0,0 +1,81 @@ | ||||
|  | ||||
| #ifndef GNSS_SDR_PLUTOSDR_SIGNAL_SOURCE_H_ | ||||
| #define GNSS_SDR_PLUTOSDR_SIGNAL_SOURCE_H_ | ||||
|  | ||||
| #include <string> | ||||
| #include <boost/shared_ptr.hpp> | ||||
| #include <gnuradio/msg_queue.h> | ||||
| #include <gnuradio/blocks/file_sink.h> | ||||
| #include <iio/pluto_source.h> | ||||
| #include "gnss_block_interface.h" | ||||
|  | ||||
| class ConfigurationInterface; | ||||
|  | ||||
| /*! | ||||
|  */ | ||||
| class PlutosdrSignalSource: public GNSSBlockInterface | ||||
| { | ||||
| public: | ||||
|     PlutosdrSignalSource(ConfigurationInterface* configuration, | ||||
|             std::string role, unsigned int in_stream, | ||||
|             unsigned int out_stream, boost::shared_ptr<gr::msg_queue> queue); | ||||
|  | ||||
|     virtual ~PlutosdrSignalSource(); | ||||
|  | ||||
|     std::string role() | ||||
|     { | ||||
|         return role_; | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|      * \brief Returns "Plutosdr_Signal_Source" | ||||
|      */ | ||||
|     std::string implementation() | ||||
|     { | ||||
|         return "Plutosdr_Signal_Source"; | ||||
|     } | ||||
|     size_t item_size() | ||||
|     { | ||||
|         return item_size_; | ||||
|     } | ||||
|  | ||||
|     void connect(gr::top_block_sptr top_block); | ||||
|     void disconnect(gr::top_block_sptr top_block); | ||||
|     gr::basic_block_sptr get_left_block(); | ||||
|     gr::basic_block_sptr get_right_block(); | ||||
|  | ||||
| private: | ||||
|     std::string role_; | ||||
|  | ||||
|     // Front-end settings | ||||
| 	std::string uri_;//device direction | ||||
| 	unsigned long freq_; //frequency of local oscilator | ||||
| 	unsigned long sample_rate_; | ||||
| 	unsigned long bandwidth_; | ||||
| 	unsigned long buffer_size_; //reception buffer | ||||
| 	unsigned int decimation_; | ||||
| 	bool quadrature_; | ||||
| 	bool rf_dc_; | ||||
| 	bool bb_dc_; | ||||
| 	std::string gain_mode_; | ||||
| 	double rf_gain_; | ||||
| 	std::string filter_file_; | ||||
| 	bool filter_auto_; | ||||
|  | ||||
|     unsigned int in_stream_; | ||||
|     unsigned int out_stream_; | ||||
|  | ||||
|     std::string item_type_; | ||||
|     size_t item_size_; | ||||
|     long samples_; | ||||
|     bool dump_; | ||||
|     std::string dump_filename_; | ||||
|  | ||||
| 	gr::iio::pluto_source::sptr plutosdr_source_; | ||||
|  | ||||
|     boost::shared_ptr<gr::block> valve_; | ||||
|     gr::blocks::file_sink::sptr file_sink_; | ||||
|     boost::shared_ptr<gr::msg_queue> queue_; | ||||
| }; | ||||
|  | ||||
| #endif /*GNSS_SDR_PLUTOSDR_SIGNAL_SOURCE_H_*/ | ||||
| @@ -124,6 +124,16 @@ else(OPENCL_FOUND) | ||||
|     add_definitions(-DOPENCL_BLOCKS=0) | ||||
| endif(OPENCL_FOUND) | ||||
|  | ||||
| #enable SDR Hardware based on fmcomms2 | ||||
| if(ENABLE_PLUTOSDR) | ||||
| 	add_definitions(-DPLUTOSDR_DRIVER=1) | ||||
| endif(ENABLE_PLUTOSDR) | ||||
|  | ||||
| if(ENABLE_FMCOMMS2) | ||||
| 	add_definitions(-DFMCOMMS2_DRIVER=1) | ||||
| 	add_definitions(-DPLUTOSDR_DRIVER=1) | ||||
| endif(ENABLE_FMCOMMS2) | ||||
|  | ||||
| add_definitions(-DGNSSSDR_INSTALL_DIR="${CMAKE_INSTALL_PREFIX}") | ||||
|  | ||||
| file(GLOB GNSS_RECEIVER_HEADERS "*.h") | ||||
|   | ||||
| @@ -119,6 +119,14 @@ | ||||
| #include "uhd_signal_source.h" | ||||
| #endif | ||||
|  | ||||
| #if PLUTOSDR_DRIVER | ||||
| #include "plutosdr_signal_source.h" | ||||
| #endif | ||||
|  | ||||
| #if FMCOMMS2_DRIVER | ||||
| #include "fmcomms2_signal_source.h" | ||||
| #endif | ||||
|  | ||||
| #if FLEXIBAND_DRIVER | ||||
| #include "flexiband_signal_source.h" | ||||
| #endif | ||||
| @@ -811,6 +819,24 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock( | ||||
|         } | ||||
| #endif | ||||
|  | ||||
| #if PLUTOSDR_DRIVER | ||||
|     else if (implementation.compare("Plutosdr_Signal_Source") == 0) | ||||
|         { | ||||
|             std::unique_ptr<GNSSBlockInterface> block_(new PlutosdrSignalSource(configuration.get(), role, in_streams, | ||||
|                     out_streams, queue)); | ||||
|             block = std::move(block_); | ||||
|         } | ||||
| #endif | ||||
|  | ||||
| #if FMCOMMS2_DRIVER | ||||
|     else if (implementation.compare("Fmcomms2_Signal_Source") == 0) | ||||
|         { | ||||
|             std::unique_ptr<GNSSBlockInterface> block_(new Fmcomms2SignalSource(configuration.get(), role, in_streams, | ||||
|                     out_streams, queue)); | ||||
|             block = std::move(block_); | ||||
|         } | ||||
| #endif | ||||
|  | ||||
| #if FLEXIBAND_DRIVER | ||||
|     else if (implementation.compare("Flexiband_Signal_Source") == 0) | ||||
|         { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Carles Fernandez
					Carles Fernandez