mirror of
				https://github.com/gnss-sdr/gnss-sdr
				synced 2025-10-31 07:13:03 +00:00 
			
		
		
		
	| @@ -52,6 +52,7 @@ option(ENABLE_GN3S "Enable the use of the GN3S dongle as signal source (experime | ||||
| option(ENABLE_PLUTOSDR "Enable the use of ADALM-PLUTO Evaluation Boards (Analog Devices Inc.), requires gr-iio" OFF) | ||||
| option(ENABLE_FMCOMMS2 "Enable the use of FMCOMMS4-EBZ + ZedBoard hardware, requires gr-iio" OFF) | ||||
| option(ENABLE_AD9361 "Enable the use of AD9361 directo to FPGA hardware, requires gr-iio" OFF) | ||||
| option(ENABLE_RAW_UDP "Enable the use of high-optimized custom UDP packet sample source, requires libpcap" OFF) | ||||
|  | ||||
| # Performance analysis tools | ||||
| option(ENABLE_GPERFTOOLS "Enable linking to Gperftools libraries (tcmalloc and profiler)" OFF) | ||||
| @@ -1321,6 +1322,16 @@ else(ENABLE_CUDA) | ||||
|     message(STATUS "Enable it with 'cmake -DENABLE_CUDA=ON ../' to add support for GPU-based acceleration using CUDA." ) | ||||
| endif(ENABLE_CUDA) | ||||
|  | ||||
| ############################################################################### | ||||
| # CUSTOM UDP PACKET SOURCE (OPTIONAL) | ||||
| ############################################################################### | ||||
| if(ENABLE_RAW_UDP) | ||||
|     message(STATUS "High-optimized custom UDP ip packet source will be enabled." ) | ||||
|     message(STATUS "You can disable it with 'cmake -DENABLE_RAW_UDP=OFF ../'" ) | ||||
| else(ENABLE_RAW_UDP) | ||||
|     message(STATUS "High-optimized custom UDP ip packet source will be enabled." ) | ||||
|     message(STATUS "You can disable it with 'cmake -DENABLE_RAW_UDP=OFF ../'" ) | ||||
| endif(ENABLE_RAW_UDP) | ||||
|  | ||||
|  | ||||
| ############################################################################### | ||||
| @@ -1455,7 +1466,6 @@ if(ENABLE_GPROF) | ||||
| endif(ENABLE_GPROF) | ||||
|  | ||||
|  | ||||
|  | ||||
| ######################################################################## | ||||
| # Set compiler flags | ||||
| ######################################################################## | ||||
|   | ||||
							
								
								
									
										122
									
								
								cmake/Modules/FindPCAP.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								cmake/Modules/FindPCAP.cmake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,122 @@ | ||||
|  | ||||
| ################################################################### | ||||
| # | ||||
| #  Copyright (c) 2006 Frederic Heem, <frederic.heem@telsey.it> | ||||
| #  All rights reserved. | ||||
| # | ||||
| # Redistribution and use in source and binary forms, with or without | ||||
| # modification, are permitted provided that the following conditions | ||||
| # are met: | ||||
| # | ||||
| # * Redistributions of source code must retain the above copyright | ||||
| #   notice, this list of conditions and the following disclaimer. | ||||
| # | ||||
| # * Redistributions in binary form must reproduce the above copyright | ||||
| #   notice, this list of conditions and the following disclaimer in | ||||
| #   the documentation and/or other materials provided with the | ||||
| #   distribution. | ||||
| # | ||||
| # * Neither the name of the Telsey nor the names of its | ||||
| #   contributors may be used to endorse or promote products derived | ||||
| #   from this software without specific prior written permission. | ||||
| # | ||||
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
| # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
| # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | ||||
| # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | ||||
| # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||||
| # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | ||||
| # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
| # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||||
| # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||||
| # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | ||||
| # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||||
| # POSSIBILITY OF SUCH DAMAGE. | ||||
| # | ||||
| ################################################################### | ||||
| # - Find pcap | ||||
| # Find the PCAP includes and library | ||||
| # http://www.tcpdump.org/ | ||||
| # | ||||
| # The environment variable PCAPDIR allows to specficy where to find  | ||||
| # libpcap in non standard location. | ||||
| #   | ||||
| #  PCAP_INCLUDE_DIRS - where to find pcap.h, etc. | ||||
| #  PCAP_LIBRARIES   - List of libraries when using pcap. | ||||
| #  PCAP_FOUND       - True if pcap found. | ||||
|  | ||||
|  | ||||
| IF(EXISTS $ENV{PCAPDIR}) | ||||
|   FIND_PATH(PCAP_INCLUDE_DIR  | ||||
|     NAMES | ||||
|     pcap/pcap.h | ||||
|     pcap.h | ||||
|     PATHS | ||||
|       $ENV{PCAPDIR} | ||||
|     NO_DEFAULT_PATH | ||||
|   ) | ||||
|    | ||||
|   FIND_LIBRARY(PCAP_LIBRARY | ||||
|     NAMES  | ||||
|       pcap | ||||
|     PATHS | ||||
|       $ENV{PCAPDIR} | ||||
|     NO_DEFAULT_PATH | ||||
|   ) | ||||
|    | ||||
|  | ||||
| ELSE(EXISTS $ENV{PCAPDIR}) | ||||
|   FIND_PATH(PCAP_INCLUDE_DIR  | ||||
|     NAMES | ||||
|     pcap/pcap.h | ||||
|     pcap.h | ||||
|   ) | ||||
|    | ||||
|   FIND_LIBRARY(PCAP_LIBRARY | ||||
|     NAMES  | ||||
|       pcap | ||||
|   ) | ||||
|    | ||||
| ENDIF(EXISTS $ENV{PCAPDIR}) | ||||
|  | ||||
| SET(PCAP_INCLUDE_DIRS ${PCAP_INCLUDE_DIR}) | ||||
| SET(PCAP_LIBRARIES ${PCAP_LIBRARY}) | ||||
|  | ||||
| IF(PCAP_INCLUDE_DIRS) | ||||
|   MESSAGE(STATUS "Pcap include dirs set to ${PCAP_INCLUDE_DIRS}") | ||||
| ELSE(PCAP_INCLUDE_DIRS) | ||||
|   MESSAGE(FATAL " Pcap include dirs cannot be found") | ||||
| ENDIF(PCAP_INCLUDE_DIRS) | ||||
|  | ||||
| IF(PCAP_LIBRARIES) | ||||
|   MESSAGE(STATUS "Pcap library set to ${PCAP_LIBRARIES}") | ||||
| ELSE(PCAP_LIBRARIES) | ||||
|   MESSAGE(FATAL "Pcap library cannot be found") | ||||
| ENDIF(PCAP_LIBRARIES) | ||||
|  | ||||
| #Functions | ||||
| INCLUDE(CheckFunctionExists) | ||||
| SET(CMAKE_REQUIRED_INCLUDES ${PCAP_INCLUDE_DIRS}) | ||||
| SET(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARIES}) | ||||
| CHECK_FUNCTION_EXISTS("pcap_breakloop" HAVE_PCAP_BREAKLOOP) | ||||
| CHECK_FUNCTION_EXISTS("pcap_datalink_name_to_val" HAVE_PCAP_DATALINK_NAME_TO_VAL) | ||||
| CHECK_FUNCTION_EXISTS("pcap_datalink_val_to_name" HAVE_PCAP_DATALINK_VAL_TO_NAME) | ||||
| CHECK_FUNCTION_EXISTS("pcap_findalldevs" HAVE_PCAP_FINDALLDEVS) | ||||
| CHECK_FUNCTION_EXISTS("pcap_freecode" HAVE_PCAP_FREECODE) | ||||
| CHECK_FUNCTION_EXISTS("pcap_get_selectable_fd" HAVE_PCAP_GET_SELECTABLE_FD) | ||||
| CHECK_FUNCTION_EXISTS("pcap_lib_version" HAVE_PCAP_LIB_VERSION) | ||||
| CHECK_FUNCTION_EXISTS("pcap_list_datalinks" HAVE_PCAP_LIST_DATALINKS) | ||||
| CHECK_FUNCTION_EXISTS("pcap_open_dead" HAVE_PCAP_OPEN_DEAD) | ||||
| CHECK_FUNCTION_EXISTS("pcap_set_datalink" HAVE_PCAP_SET_DATALINK) | ||||
|  | ||||
|  | ||||
| #Is pcap found ? | ||||
| IF(PCAP_INCLUDE_DIRS AND PCAP_LIBRARIES) | ||||
|   SET( PCAP_FOUND "YES" ) | ||||
| ENDIF(PCAP_INCLUDE_DIRS AND PCAP_LIBRARIES) | ||||
|  | ||||
|  | ||||
| MARK_AS_ADVANCED( | ||||
|   PCAP_LIBRARIES | ||||
|   PCAP_INCLUDE_DIRS | ||||
| ) | ||||
							
								
								
									
										105
									
								
								conf/gnss-sdr_GPS_L1_2ch_udp.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								conf/gnss-sdr_GPS_L1_2ch_udp.conf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | ||||
| ; 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]. | ||||
| GNSS-SDR.internal_fs_sps=13250000 ;//66.25/5 | ||||
| ;GNSS-SDR.internal_fs_sps=6625000  ;//66.25/10 | ||||
| ;GNSS-SDR.internal_fs_sps=3312500 ;//66.25/20 | ||||
| ;GNSS-SDR.internal_fs_sps=2650000  ;//66.25/25 | ||||
|  | ||||
| ;######### SIGNAL_SOURCE CONFIG ############ | ||||
| SignalSource.implementation=UDP_Signal_Source | ||||
| ;SignalSource.implementation=File_Signal_Source | ||||
| ;SignalSource.filename=/home/javier/gnss/gnss-simulator/build/signal_out.bin ; <- PUT YOUR FILE HERE | ||||
| SignalSource.item_type=gr_complex | ||||
| SignalSource.origin_address=0.0.0.0 | ||||
| SignalSource.capture_device=eth0 | ||||
| SignalSource.port=1234 | ||||
| SignalSource.payload_bytes=1472 | ||||
| ;SignalSource.sample_type=cbyte | ||||
| SignalSource.sample_type=c4bits | ||||
| SignalSource.IQ_swap=false | ||||
| SignalSource.RF_channels=1 | ||||
| SignalSource.channels_in_udp=2 | ||||
| SignalSource.dump=false | ||||
| SignalSource.dump_filename=./signal_source.dat | ||||
|  | ||||
|  | ||||
| ;######### SIGNAL_CONDITIONER CONFIG ############ | ||||
| SignalConditioner.implementation=Pass_Through | ||||
| ;SignalConditioner0.implementation=Pass_Through | ||||
| ;SignalConditioner1.implementation=Pass_Through | ||||
|  | ||||
| ;######### CHANNELS GLOBAL CONFIG ############ | ||||
| Channels_1C.count=8 | ||||
| Channels.in_acquisition=1 | ||||
|  | ||||
| ;# CHANNEL CONNECTION | ||||
| Channel.signal=1C | ||||
| Channel0.RF_channel_ID=0 | ||||
| Channel1.RF_channel_ID=0 | ||||
| Channel2.RF_channel_ID=0 | ||||
| Channel3.RF_channel_ID=0 | ||||
| Channel4.RF_channel_ID=0 | ||||
| Channel5.RF_channel_ID=0 | ||||
| Channel6.RF_channel_ID=0 | ||||
| Channel7.RF_channel_ID=0 | ||||
| Channel8.RF_channel_ID=1 | ||||
| Channel9.RF_channel_ID=1 | ||||
|  | ||||
| ;Channel0.signal=1C | ||||
| ;Channel1.RF_channel_ID=1 | ||||
| ;Channel1.signal=1C | ||||
|  | ||||
| ;######### ACQUISITION GLOBAL CONFIG ############ | ||||
| Acquisition_1C.implementation=GPS_L1_CA_PCPS_Acquisition | ||||
| Acquisition_1C.item_type=gr_complex | ||||
| Acquisition_1C.threshold=17 | ||||
| Acquisition_1C.use_CFAR_algorithm=false | ||||
| Acquisition_1C.blocking=false | ||||
| Acquisition_1C.doppler_max=5000 | ||||
| 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=PPP_Static  ; 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 | ||||
| @@ -21,6 +21,38 @@ list(SORT SIGNAL_SOURCE_ADAPTER_HEADERS) | ||||
|  | ||||
| # Optional drivers | ||||
|  | ||||
| if(ENABLE_RAW_UDP) | ||||
|     # - Try to find libpcap include dirs and libraries | ||||
|     # | ||||
|     # Usage of this module as follows: | ||||
|     # | ||||
|     #     find_package(PCAP) | ||||
|     # | ||||
|     # Variables used by this module, they can change the default behaviour and need | ||||
|     # to be set before calling find_package: | ||||
|     # | ||||
|     #  PCAP_ROOT_DIR             Set this variable to the root installation of | ||||
|     #                            libpcap if the module has problems finding the | ||||
|     #                            proper installation path. | ||||
|     # | ||||
|     # Variables defined by this module: | ||||
|     # | ||||
|     #  PCAP_FOUND                System has libpcap, include and library dirs found | ||||
|     #  PCAP_INCLUDE_DIR          The libpcap include directories. | ||||
|     #  PCAP_LIBRARY              The libpcap library (possibly includes a thread | ||||
|     #                            library e.g. required by pf_ring's libpcap) | ||||
|     #  HAVE_PF_RING              If a found version of libpcap supports PF_RING | ||||
|     find_package(PCAP) | ||||
|     if(NOT PCAP_FOUND) | ||||
|         message(FATAL_ERROR "PCAP required to compile custom UDP packet sample source (ENABLE_RAW_UDP)") | ||||
|     endif() | ||||
|     get_filename_component(PCAP_LIBRARY_DIRS ${PCAP_LIBRARY} DIRECTORY CACHE) | ||||
|    set(OPT_LIBRARIES ${OPT_LIBRARIES} ${PCAP_LIBRARIES}) | ||||
|    set(OPT_DRIVER_INCLUDE_DIRS ${OPT_DRIVER_INCLUDE_DIRS} ${PCAP_INCLUDE_DIRS}) | ||||
|    set(OPT_DRIVER_SOURCES ${OPT_DRIVER_SOURCES} custom_udp_signal_source.cc) | ||||
|     | ||||
| endif(ENABLE_RAW_UDP) | ||||
|  | ||||
| if(ENABLE_PLUTOSDR OR ENABLE_FMCOMMS2) | ||||
|    find_package(iio REQUIRED) | ||||
|    if(NOT IIO_FOUND) | ||||
|   | ||||
| @@ -0,0 +1,169 @@ | ||||
| /*! | ||||
|  * \file udp_signal_source.cc | ||||
|  * | ||||
|  * \brief Receives ip frames containing samples in UDP frame encapsulation | ||||
|  * using a high performance packet capture library (libpcap) | ||||
|  * \author Javier Arribas jarribas (at) cttc.es | ||||
|  * ------------------------------------------------------------------------- | ||||
|  * | ||||
|  * 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 "custom_udp_signal_source.h" | ||||
| #include "configuration_interface.h" | ||||
| #include "GPS_L1_CA.h" | ||||
| #include <boost/format.hpp> | ||||
| #include <glog/logging.h> | ||||
| #include <iostream> | ||||
|  | ||||
|  | ||||
| using google::LogMessage; | ||||
|  | ||||
|  | ||||
| CustomUDPSignalSource::CustomUDPSignalSource(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) | ||||
| { | ||||
|     // DUMP PARAMETERS | ||||
|     std::string empty = ""; | ||||
|     std::string default_dump_file = "./data/signal_source.dat"; | ||||
|     std::string default_item_type = "gr_complex"; | ||||
|     dump_ = configuration->property(role + ".dump", false); | ||||
|     dump_filename_ = configuration->property(role + ".dump_filename", | ||||
|         default_dump_file); | ||||
|  | ||||
|     // network PARAMETERS | ||||
|     std::string default_capture_device = "eth0"; | ||||
|     std::string default_address = "127.0.0.1"; | ||||
|     int default_port = 1234; | ||||
|     std::string address = configuration->property(role + ".origin_address", default_address); | ||||
|     std::string capture_device = configuration->property(role + ".capture_device", default_capture_device); | ||||
|     int port = configuration->property(role + ".port", default_port); | ||||
|     int payload_bytes = configuration->property(role + ".payload_bytes", 1024); | ||||
|  | ||||
|  | ||||
|     RF_channels_ = configuration->property(role + ".RF_channels", 1); | ||||
|     channels_in_udp_ = configuration->property(role + ".channels_in_udp", 1); | ||||
|     IQ_swap_ = configuration->property(role + ".IQ_swap", false); | ||||
|  | ||||
|     std::string default_sample_type = "cbyte"; | ||||
|     std::string sample_type = configuration->property(role + ".sample_type", default_sample_type); | ||||
|     item_type_ = configuration->property(role + ".item_type", default_item_type); | ||||
|     //output item size is always gr_complex | ||||
|     item_size_ = sizeof(gr_complex); | ||||
|  | ||||
|     udp_gnss_rx_source_ = gr_complex_ip_packet_source::make(capture_device, | ||||
|         address, | ||||
|         port, | ||||
|         payload_bytes, | ||||
|         channels_in_udp_, | ||||
|         sample_type, | ||||
|         item_size_, | ||||
|         IQ_swap_); | ||||
|  | ||||
|     if (channels_in_udp_ >= RF_channels_) | ||||
|         { | ||||
|             for (int n = 0; n < channels_in_udp_; n++) | ||||
|                 { | ||||
|                     null_sinks_.push_back(gr::blocks::null_sink::make(sizeof(gr_complex))); | ||||
|                 } | ||||
|         } | ||||
|     else | ||||
|         { | ||||
|             std::cout << "Configuration error: RF_channels<channels_in_use" << std::endl; | ||||
|             exit(0); | ||||
|         } | ||||
|  | ||||
|  | ||||
|     if (dump_) | ||||
|         { | ||||
|             for (int n = 0; n < channels_in_udp_; n++) | ||||
|                 { | ||||
|                     DLOG(INFO) << "Dumping output into file " << (dump_filename_ + "c_h" + std::to_string(n) + ".bin"); | ||||
|                     file_sink_.push_back(gr::blocks::file_sink::make(item_size_, (dump_filename_ + "_ch" + std::to_string(n) + ".bin").c_str())); | ||||
|                 } | ||||
|         } | ||||
| } | ||||
|  | ||||
|  | ||||
| CustomUDPSignalSource::~CustomUDPSignalSource() | ||||
| { | ||||
| } | ||||
|  | ||||
|  | ||||
| void CustomUDPSignalSource::connect(gr::top_block_sptr top_block) | ||||
| { | ||||
|     //connect null sinks to unused streams | ||||
|     for (int n = 0; n < channels_in_udp_; n++) | ||||
|         { | ||||
|             top_block->connect(udp_gnss_rx_source_, n, null_sinks_.at(n), 0); | ||||
|         } | ||||
|     DLOG(INFO) << "connected udp_source to null_sinks to enable the use of spare channels" << std::endl; | ||||
|  | ||||
|     if (dump_) | ||||
|         { | ||||
|             for (int n = 0; n < channels_in_udp_; n++) | ||||
|                 { | ||||
|                     top_block->connect(udp_gnss_rx_source_, n, file_sink_.at(n), 0); | ||||
|                     DLOG(INFO) << "connected source to file sink"; | ||||
|                 } | ||||
|         } | ||||
| } | ||||
|  | ||||
|  | ||||
| void CustomUDPSignalSource::disconnect(gr::top_block_sptr top_block) | ||||
| { | ||||
|     //disconnect null sinks to unused streams | ||||
|     for (int n = 0; n < channels_in_udp_; n++) | ||||
|         { | ||||
|             top_block->disconnect(udp_gnss_rx_source_, n, null_sinks_.at(n), 0); | ||||
|         } | ||||
|     if (dump_) | ||||
|         { | ||||
|             for (int n = 0; n < channels_in_udp_; n++) | ||||
|                 { | ||||
|                     top_block->disconnect(udp_gnss_rx_source_, n, file_sink_.at(n), 0); | ||||
|                     DLOG(INFO) << "disconnected source to file sink"; | ||||
|                 } | ||||
|         } | ||||
|     DLOG(INFO) << "disconnected udp_source" << std::endl; | ||||
| } | ||||
|  | ||||
|  | ||||
| gr::basic_block_sptr CustomUDPSignalSource::get_left_block() | ||||
| { | ||||
|     LOG(WARNING) << "Left block of a signal source should not be retrieved"; | ||||
|     return gr::block_sptr(); | ||||
| } | ||||
|  | ||||
|  | ||||
| gr::basic_block_sptr CustomUDPSignalSource::get_right_block() | ||||
| { | ||||
|     return udp_gnss_rx_source_; | ||||
| } | ||||
|  | ||||
| gr::basic_block_sptr CustomUDPSignalSource::get_right_block(__attribute__((unused)) int RF_channel) | ||||
| { | ||||
|     return udp_gnss_rx_source_; | ||||
| } | ||||
							
								
								
									
										105
									
								
								src/algorithms/signal_source/adapters/custom_udp_signal_source.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								src/algorithms/signal_source/adapters/custom_udp_signal_source.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | ||||
| /*! | ||||
|  * \file udp_signal_source.h | ||||
|  * | ||||
|  * \brief Receives ip frames containing samples in UDP frame encapsulation | ||||
|  * using a high performance packet capture library (libpcap) | ||||
|  * \author Javier Arribas jarribas (at) cttc.es | ||||
|  * ------------------------------------------------------------------------- | ||||
|  * | ||||
|  * 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 GNSS_SDR_CUSTOM_UDP_SIGNAL_SOURCE_H | ||||
| #define GNSS_SDR_CUSTOM_UDP_SIGNAL_SOURCE_H | ||||
|  | ||||
| #include "gnss_block_interface.h" | ||||
| #include "gr_complex_ip_packet_source.h" | ||||
| #include <boost/shared_ptr.hpp> | ||||
| #include <gnuradio/msg_queue.h> | ||||
| #include <gnuradio/blocks/file_sink.h> | ||||
| #include <gnuradio/blocks/null_sink.h> | ||||
| #include <stdexcept> | ||||
| #include <string> | ||||
| #include <vector> | ||||
|  | ||||
|  | ||||
| class ConfigurationInterface; | ||||
|  | ||||
| /*! | ||||
|  * \brief This class reads from UDP packets, which streams interleaved | ||||
|  * I/Q samples over a network. | ||||
|  */ | ||||
| class CustomUDPSignalSource : public GNSSBlockInterface | ||||
| { | ||||
| public: | ||||
|     CustomUDPSignalSource(ConfigurationInterface* configuration, | ||||
|         std::string role, unsigned int in_stream, | ||||
|         unsigned int out_stream, boost::shared_ptr<gr::msg_queue> queue); | ||||
|  | ||||
|     virtual ~CustomUDPSignalSource(); | ||||
|  | ||||
|     inline std::string role() override | ||||
|     { | ||||
|         return role_; | ||||
|     } | ||||
|  | ||||
|     /*! | ||||
|      * \brief Returns "UDP_Signal_Source" | ||||
|      */ | ||||
|     inline std::string implementation() override | ||||
|     { | ||||
|         return "Custom_UDP_Signal_Source"; | ||||
|     } | ||||
|  | ||||
|     inline size_t item_size() override | ||||
|     { | ||||
|         return item_size_; | ||||
|     } | ||||
|  | ||||
|     void connect(gr::top_block_sptr top_block) override; | ||||
|     void disconnect(gr::top_block_sptr top_block) override; | ||||
|     gr::basic_block_sptr get_left_block() override; | ||||
|     gr::basic_block_sptr get_right_block() override; | ||||
|     gr::basic_block_sptr get_right_block(int RF_channel) override; | ||||
|  | ||||
| private: | ||||
|     std::string role_; | ||||
|  | ||||
|     bool IQ_swap_; | ||||
|     int RF_channels_; | ||||
|     int channels_in_udp_; | ||||
|     unsigned int in_stream_; | ||||
|     unsigned int out_stream_; | ||||
|  | ||||
|     std::string item_type_; | ||||
|     size_t item_size_; | ||||
|     bool dump_; | ||||
|     std::string dump_filename_; | ||||
|     std::vector<boost::shared_ptr<gr::block>> null_sinks_; | ||||
|     gr_complex_ip_packet_source::sptr udp_gnss_rx_source_; | ||||
|     std::vector<boost::shared_ptr<gr::block>> file_sink_; | ||||
|     boost::shared_ptr<gr::msg_queue> queue_; | ||||
| }; | ||||
|  | ||||
| #endif /*GNSS_SDR_CUSTOM_UDP_SIGNAL_SOURCE_H */ | ||||
| @@ -17,14 +17,48 @@ | ||||
| # | ||||
|  | ||||
|  | ||||
| if(ENABLE_RAW_UDP) | ||||
|     # - Try to find libpcap include dirs and libraries | ||||
|     # | ||||
|     # Usage of this module as follows: | ||||
|     # | ||||
|     #     find_package(PCAP) | ||||
|     # | ||||
|     # Variables used by this module, they can change the default behaviour and need | ||||
|     # to be set before calling find_package: | ||||
|     # | ||||
|     #  PCAP_ROOT_DIR             Set this variable to the root installation of | ||||
|     #                            libpcap if the module has problems finding the | ||||
|     #                            proper installation path. | ||||
|     # | ||||
|     # Variables defined by this module: | ||||
|     # | ||||
|     #  PCAP_FOUND                System has libpcap, include and library dirs found | ||||
|     #  PCAP_INCLUDE_DIR          The libpcap include directories. | ||||
|     #  PCAP_LIBRARY              The libpcap library (possibly includes a thread | ||||
|     #                            library e.g. required by pf_ring's libpcap) | ||||
|     #  HAVE_PF_RING              If a found version of libpcap supports PF_RING | ||||
|     find_package(PCAP) | ||||
|     if(NOT PCAP_FOUND) | ||||
|         message(FATAL_ERROR "PCAP required to compile custom UDP packet sample source (ENABLE_RAW_UDP)") | ||||
|     endif() | ||||
|     get_filename_component(PCAP_LIBRARY_DIRS ${PCAP_LIBRARY} DIRECTORY CACHE) | ||||
|    set(OPT_LIBRARIES ${OPT_LIBRARIES} ${PCAP_LIBRARIES}) | ||||
|    set(OPT_DRIVER_INCLUDE_DIRS ${OPT_DRIVER_INCLUDE_DIRS} ${PCAP_INCLUDE_DIRS}) | ||||
|    set(OPT_DRIVER_SOURCES ${OPT_DRIVER_SOURCES} gr_complex_ip_packet_source.cc) | ||||
|     | ||||
| endif(ENABLE_RAW_UDP) | ||||
|  | ||||
| set(SIGNAL_SOURCE_GR_BLOCKS_SOURCES | ||||
|      unpack_byte_2bit_samples.cc | ||||
|      unpack_byte_2bit_cpx_samples.cc | ||||
|      unpack_byte_4bit_samples.cc | ||||
|      unpack_intspir_1bit_samples.cc | ||||
|      rtl_tcp_signal_source_c.cc | ||||
|      unpack_2bit_samples.cc | ||||
|      unpack_spir_gss6450_samples.cc | ||||
|      labsat23_source.cc | ||||
|      ${OPT_DRIVER_SOURCES} | ||||
| ) | ||||
|  | ||||
| include_directories( | ||||
| @@ -34,11 +68,17 @@ include_directories( | ||||
|      ${GFlags_INCLUDE_DIRS} | ||||
|      ${GNURADIO_RUNTIME_INCLUDE_DIRS} | ||||
|      ${Boost_INCLUDE_DIRS} | ||||
|      ${OPT_DRIVER_INCLUDE_DIRS} | ||||
| ) | ||||
|  | ||||
| file(GLOB SIGNAL_SOURCE_GR_BLOCKS_HEADERS "*.h") | ||||
| list(SORT SIGNAL_SOURCE_GR_BLOCKS_HEADERS) | ||||
| add_library(signal_source_gr_blocks ${SIGNAL_SOURCE_GR_BLOCKS_SOURCES} ${SIGNAL_SOURCE_GR_BLOCKS_HEADERS}) | ||||
| source_group(Headers FILES ${SIGNAL_SOURCE_GR_BLOCKS_HEADERS}) | ||||
| target_link_libraries(signal_source_gr_blocks signal_source_lib ${GNURADIO_RUNTIME_LIBRARIES} ${Boost_LIBRARIES}) | ||||
| target_link_libraries(signal_source_gr_blocks  | ||||
|     signal_source_lib  | ||||
|     ${GNURADIO_RUNTIME_LIBRARIES}  | ||||
|     ${Boost_LIBRARIES} | ||||
|     ${OPT_LIBRARIES} | ||||
| ) | ||||
| add_dependencies(signal_source_gr_blocks glog-${glog_RELEASE}) | ||||
|   | ||||
| @@ -0,0 +1,439 @@ | ||||
| /*! | ||||
|  * \file gr_complex_ip_packet_source.cc | ||||
|  * | ||||
|  * \brief Receives ip frames containing samples in UDP frame encapsulation | ||||
|  * using a high performance packet capture library (libpcap) | ||||
|  * \author Javier Arribas jarribas (at) cttc.es | ||||
|  * ------------------------------------------------------------------------- | ||||
|  * | ||||
|  * 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 <gnuradio/io_signature.h> | ||||
| #include "gr_complex_ip_packet_source.h" | ||||
|  | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
|  | ||||
| #define FIFO_SIZE 1472000 | ||||
|  | ||||
|  | ||||
| /* 4 bytes IP address */ | ||||
| typedef struct gr_ip_address | ||||
| { | ||||
|     u_char byte1; | ||||
|     u_char byte2; | ||||
|     u_char byte3; | ||||
|     u_char byte4; | ||||
| } gr_ip_address; | ||||
|  | ||||
| /* IPv4 header */ | ||||
| typedef struct gr_ip_header | ||||
| { | ||||
|     u_char ver_ihl;          // Version (4 bits) + Internet header length (4 bits) | ||||
|     u_char tos;              // Type of service | ||||
|     u_short tlen;            // Total length | ||||
|     u_short identification;  // Identification | ||||
|     u_short flags_fo;        // Flags (3 bits) + Fragment offset (13 bits) | ||||
|     u_char ttl;              // Time to live | ||||
|     u_char proto;            // Protocol | ||||
|     u_short crc;             // Header checksum | ||||
|     gr_ip_address saddr;     // Source address | ||||
|     gr_ip_address daddr;     // Destination address | ||||
|     u_int op_pad;            // Option + Padding | ||||
| } gr_ip_header; | ||||
|  | ||||
| /* UDP header*/ | ||||
| typedef struct gr_udp_header | ||||
| { | ||||
|     u_short sport;  // Source port | ||||
|     u_short dport;  // Destination port | ||||
|     u_short len;    // Datagram length | ||||
|     u_short crc;    // Checksum | ||||
| } gr_udp_header; | ||||
|  | ||||
| gr_complex_ip_packet_source::sptr | ||||
| gr_complex_ip_packet_source::make(std::string src_device, | ||||
|     std::string origin_address, | ||||
|     int udp_port, | ||||
|     int udp_packet_size, | ||||
|     int n_baseband_channels, | ||||
|     std::string wire_sample_type, | ||||
|     size_t item_size, | ||||
|     bool IQ_swap_) | ||||
| { | ||||
|     return gnuradio::get_initial_sptr(new gr_complex_ip_packet_source(src_device, | ||||
|         origin_address, | ||||
|         udp_port, | ||||
|         udp_packet_size, | ||||
|         n_baseband_channels, | ||||
|         wire_sample_type, | ||||
|         item_size, | ||||
|         IQ_swap_)); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * The private constructor | ||||
|  */ | ||||
| gr_complex_ip_packet_source::gr_complex_ip_packet_source(std::string src_device, | ||||
|     __attribute__((unused)) std::string origin_address, | ||||
|     int udp_port, | ||||
|     int udp_packet_size, | ||||
|     int n_baseband_channels, | ||||
|     std::string wire_sample_type, | ||||
|     size_t item_size, | ||||
|     bool IQ_swap_) | ||||
|     : gr::sync_block("gr_complex_ip_packet_source", | ||||
|           gr::io_signature::make(0, 0, 0), | ||||
|           gr::io_signature::make(1, 4, item_size))  //1 to 4 baseband complex channels | ||||
| { | ||||
|     // constructor code here | ||||
|     std::cout << "Start Ethernet packet capture\n"; | ||||
|  | ||||
|     d_n_baseband_channels = n_baseband_channels; | ||||
|     if (wire_sample_type.compare("cbyte") == 0) | ||||
|         { | ||||
|             d_wire_sample_type = 1; | ||||
|             d_bytes_per_sample = d_n_baseband_channels * 2; | ||||
|         } | ||||
|     else if (wire_sample_type.compare("c4bits") == 0) | ||||
|         { | ||||
|             d_wire_sample_type = 2; | ||||
|             d_bytes_per_sample = d_n_baseband_channels; | ||||
|         } | ||||
|     else | ||||
|         { | ||||
|             std::cout << "Unknown wire sample type\n"; | ||||
|             exit(0); | ||||
|         } | ||||
|     std::cout << "d_wire_sample_type:" << d_wire_sample_type << std::endl; | ||||
|     d_src_device = src_device; | ||||
|     d_udp_port = udp_port; | ||||
|     d_udp_payload_size = udp_packet_size; | ||||
|     d_fifo_full = false; | ||||
|  | ||||
|     //allocate signal samples buffer | ||||
|     fifo_buff = new char[FIFO_SIZE]; | ||||
|     fifo_read_ptr = 0; | ||||
|     fifo_write_ptr = 0; | ||||
|     fifo_items = 0; | ||||
|     d_item_size = item_size; | ||||
|     d_IQ_swap = IQ_swap_; | ||||
|     d_sock_raw = 0; | ||||
|     d_pcap_thread = NULL; | ||||
|     descr = NULL; | ||||
| } | ||||
|  | ||||
|  | ||||
| //Called by gnuradio to enable drivers, etc for i/o devices. | ||||
| bool gr_complex_ip_packet_source::start() | ||||
| { | ||||
|     std::cout << "gr_complex_ip_packet_source START\n"; | ||||
|     //open the ethernet device | ||||
|     if (open() == true) | ||||
|         { | ||||
|             // start pcap capture thread | ||||
|             d_pcap_thread = new boost::thread(boost::bind(&gr_complex_ip_packet_source::my_pcap_loop_thread, this, descr)); | ||||
|             return true; | ||||
|         } | ||||
|     else | ||||
|         { | ||||
|             return false; | ||||
|         } | ||||
| } | ||||
|  | ||||
| //Called by gnuradio to disable drivers, etc for i/o devices. | ||||
| bool gr_complex_ip_packet_source::stop() | ||||
| { | ||||
|     std::cout << "gr_complex_ip_packet_source STOP\n"; | ||||
|     if (descr != NULL) | ||||
|         { | ||||
|             pcap_breakloop(descr); | ||||
|             d_pcap_thread->join(); | ||||
|             pcap_close(descr); | ||||
|         } | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| bool gr_complex_ip_packet_source::open() | ||||
| { | ||||
|     char errbuf[PCAP_ERRBUF_SIZE]; | ||||
|     boost::mutex::scoped_lock lock(d_mutex);  // hold mutex for duration of this function | ||||
|     /* open device for reading */ | ||||
|     descr = pcap_open_live(d_src_device.c_str(), 1500, 1, 1000, errbuf); | ||||
|     if (descr == NULL) | ||||
|         { | ||||
|             std::cout << "Error openning Ethernet device " << d_src_device << std::endl; | ||||
|             printf("Fatal Error in pcap_open_live(): %s\n", errbuf); | ||||
|             return false; | ||||
|         } | ||||
|     //bind UDP port to avoid automatic reply with ICMP port ureacheable packets from kernel | ||||
|     d_sock_raw = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); | ||||
|     if (d_sock_raw == -1) | ||||
|         { | ||||
|             std::cout << "Error openning UDP socket" << std::endl; | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|     // zero out the structure | ||||
|     memset((char *)&si_me, 0, sizeof(si_me)); | ||||
|  | ||||
|     si_me.sin_family = AF_INET; | ||||
|     si_me.sin_port = htons(d_udp_port); | ||||
|     si_me.sin_addr.s_addr = htonl(INADDR_ANY); | ||||
|  | ||||
|     //bind socket to port | ||||
|     if (bind(d_sock_raw, (struct sockaddr *)&si_me, sizeof(si_me)) == -1) | ||||
|         { | ||||
|             std::cout << "Error openning UDP socket" << std::endl; | ||||
|             return false; | ||||
|         } | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| gr_complex_ip_packet_source::~gr_complex_ip_packet_source() | ||||
| { | ||||
|     if (d_pcap_thread != NULL) | ||||
|         { | ||||
|             delete d_pcap_thread; | ||||
|         } | ||||
|     delete fifo_buff; | ||||
|     std::cout << "Stop Ethernet packet capture\n"; | ||||
| } | ||||
|  | ||||
| void gr_complex_ip_packet_source::static_pcap_callback(u_char *args, const struct pcap_pkthdr *pkthdr, | ||||
|     const u_char *packet) | ||||
| { | ||||
|     gr_complex_ip_packet_source *bridge = (gr_complex_ip_packet_source *)args; | ||||
|     bridge->pcap_callback(args, pkthdr, packet); | ||||
| } | ||||
|  | ||||
| void gr_complex_ip_packet_source::pcap_callback(__attribute__((unused)) u_char *args, __attribute__((unused)) const struct pcap_pkthdr *pkthdr, | ||||
|     const u_char *packet) | ||||
| { | ||||
|     boost::mutex::scoped_lock lock(d_mutex);  // hold mutex for duration of this function | ||||
|  | ||||
|     gr_ip_header *ih; | ||||
|     gr_udp_header *uh; | ||||
|  | ||||
|     // eth frame parameters | ||||
|     // **** UDP RAW PACKET DECODER **** | ||||
|     if ((packet[12] == 0x08) & (packet[13] == 0x00))  //IP FRAME | ||||
|         { | ||||
|             /* retireve the position of the ip header */ | ||||
|             ih = (gr_ip_header *)(packet + | ||||
|                                   14);  //length of ethernet header | ||||
|  | ||||
|             /* retireve the position of the udp header */ | ||||
|             u_int ip_len; | ||||
|             ip_len = (ih->ver_ihl & 0xf) * 4; | ||||
|             uh = (gr_udp_header *)((u_char *)ih + ip_len); | ||||
|  | ||||
|             /* convert from network byte order to host byte order */ | ||||
|             //u_short sport; | ||||
|             u_short dport; | ||||
|             dport = ntohs(uh->dport); | ||||
|             //sport = ntohs(uh->sport); | ||||
|             if (dport == d_udp_port) | ||||
|                 { | ||||
|                     // print ip addresses and udp ports | ||||
|                     //            printf("%d.%d.%d.%d.%d -> %d.%d.%d.%d.%d\n", | ||||
|                     //                   ih->saddr.byte1, | ||||
|                     //                   ih->saddr.byte2, | ||||
|                     //                   ih->saddr.byte3, | ||||
|                     //                   ih->saddr.byte4, | ||||
|                     //                   sport, | ||||
|                     //                   ih->daddr.byte1, | ||||
|                     //                   ih->daddr.byte2, | ||||
|                     //                   ih->daddr.byte3, | ||||
|                     //                   ih->daddr.byte4, | ||||
|                     //                   dport); | ||||
|                     //            std::cout<<"uh->len:"<<ntohs(uh->len)<<std::endl; | ||||
|  | ||||
|                     int payload_lenght_bytes = ntohs(uh->len) - 8;  //total udp packet lenght minus the header lenght | ||||
|                     //read the payload bytes and insert them into the shared circular buffer | ||||
|                     u_char *udp_payload = ((u_char *)uh + sizeof(gr_udp_header)); | ||||
|                     if (fifo_items <= (FIFO_SIZE - payload_lenght_bytes)) | ||||
|                         { | ||||
|                             int aligned_write_items = FIFO_SIZE - fifo_write_ptr; | ||||
|                             if (aligned_write_items >= payload_lenght_bytes) | ||||
|                                 { | ||||
|                                     //write all in a single memcpy | ||||
|                                     memcpy(&fifo_buff[fifo_write_ptr], &udp_payload[0], payload_lenght_bytes);  //size in bytes | ||||
|                                     fifo_write_ptr += payload_lenght_bytes; | ||||
|                                     if (fifo_write_ptr == FIFO_SIZE) fifo_write_ptr = 0; | ||||
|                                     fifo_items += payload_lenght_bytes; | ||||
|                                 } | ||||
|                             else | ||||
|                                 { | ||||
|                                     //two step wrap write | ||||
|                                     memcpy(&fifo_buff[fifo_write_ptr], &udp_payload[0], aligned_write_items);  //size in bytes | ||||
|                                     fifo_write_ptr = payload_lenght_bytes - aligned_write_items; | ||||
|                                     memcpy(&fifo_buff[0], &udp_payload[aligned_write_items], fifo_write_ptr);  //size in bytes | ||||
|                                     fifo_items += payload_lenght_bytes; | ||||
|                                 } | ||||
|                         } | ||||
|                     else | ||||
|                         { | ||||
|                             //notify overflow | ||||
|                             std::cout << "O" << std::flush; | ||||
|                         } | ||||
|                 } | ||||
|         } | ||||
| } | ||||
|  | ||||
| void gr_complex_ip_packet_source::my_pcap_loop_thread(pcap_t *pcap_handle) | ||||
|  | ||||
| { | ||||
|     pcap_loop(pcap_handle, -1, gr_complex_ip_packet_source::static_pcap_callback, (u_char *)this); | ||||
| } | ||||
|  | ||||
| void gr_complex_ip_packet_source::demux_samples(gr_vector_void_star output_items, int num_samples_readed) | ||||
| { | ||||
|     int8_t real; | ||||
|     int8_t imag; | ||||
|     uint8_t tmp_char2; | ||||
|     for (int n = 0; n < num_samples_readed; n++) | ||||
|         { | ||||
|             switch (d_wire_sample_type) | ||||
|                 { | ||||
|                 case 1:  //interleaved byte samples | ||||
|                     for (int i = 0; i < output_items.size(); i++) | ||||
|                         { | ||||
|                             real = fifo_buff[fifo_read_ptr++]; | ||||
|                             imag = fifo_buff[fifo_read_ptr++]; | ||||
|                             if (d_IQ_swap) | ||||
|                                 { | ||||
|                                     ((gr_complex *)output_items[i])[n] = gr_complex(real, imag); | ||||
|                                 } | ||||
|                             else | ||||
|                                 { | ||||
|                                     ((gr_complex *)output_items[i])[n] = gr_complex(imag, real); | ||||
|                                 } | ||||
|                         } | ||||
|                     break; | ||||
|                 case 2:  // 4bits samples | ||||
|                     for (int i = 0; i < output_items.size(); i++) | ||||
|                         { | ||||
|                             tmp_char2 = fifo_buff[fifo_read_ptr] & 0x0F; | ||||
|                             if (tmp_char2 >= 8) | ||||
|                                 { | ||||
|                                     real = 2 * (tmp_char2 - 16) + 1; | ||||
|                                 } | ||||
|                             else | ||||
|                                 { | ||||
|                                     real = 2 * tmp_char2 + 1; | ||||
|                                 } | ||||
|                             tmp_char2 = fifo_buff[fifo_read_ptr++] >> 4; | ||||
|                             tmp_char2 = tmp_char2 & 0x0F; | ||||
|                             if (tmp_char2 >= 8) | ||||
|                                 { | ||||
|                                     imag = 2 * (tmp_char2 - 16) + 1; | ||||
|                                 } | ||||
|                             else | ||||
|                                 { | ||||
|                                     imag = 2 * tmp_char2 + 1; | ||||
|                                 } | ||||
|                             if (d_IQ_swap) | ||||
|                                 { | ||||
|                                     ((gr_complex *)output_items[i])[n] = gr_complex(imag, real); | ||||
|                                 } | ||||
|                             else | ||||
|                                 { | ||||
|                                     ((gr_complex *)output_items[i])[n] = gr_complex(real, imag); | ||||
|                                 } | ||||
|                         } | ||||
|                     break; | ||||
|                 default: | ||||
|                     std::cout << "Unknown wire sample type\n"; | ||||
|                     exit(0); | ||||
|                 } | ||||
|             if (fifo_read_ptr == FIFO_SIZE) fifo_read_ptr = 0; | ||||
|         } | ||||
| } | ||||
|  | ||||
| int gr_complex_ip_packet_source::work(int noutput_items, | ||||
|     __attribute__((unused)) gr_vector_const_void_star &input_items, | ||||
|     gr_vector_void_star &output_items) | ||||
| { | ||||
|     // send samples to next GNU Radio block | ||||
|     boost::mutex::scoped_lock lock(d_mutex);  // hold mutex for duration of this function | ||||
|     if (fifo_items == 0) return 0; | ||||
|  | ||||
|     if (output_items.size() > d_n_baseband_channels) | ||||
|         { | ||||
|             std::cout << "Configuration error: more baseband channels connected than the available in the UDP source\n"; | ||||
|             exit(0); | ||||
|         } | ||||
|     int num_samples_readed; | ||||
|     int bytes_requested; | ||||
|     switch (d_wire_sample_type) | ||||
|         { | ||||
|         case 1:  //complex byte samples | ||||
|             bytes_requested = noutput_items * d_bytes_per_sample; | ||||
|             if (bytes_requested < fifo_items) | ||||
|                 { | ||||
|                     num_samples_readed = noutput_items;  //read all | ||||
|                 } | ||||
|             else | ||||
|                 { | ||||
|                     num_samples_readed = fifo_items / d_bytes_per_sample;  //read what we have | ||||
|                 } | ||||
|             break; | ||||
|         case 2:  //complex 4 bits samples | ||||
|             bytes_requested = noutput_items * d_bytes_per_sample; | ||||
|             if (bytes_requested < fifo_items) | ||||
|                 { | ||||
|                     num_samples_readed = noutput_items;  //read all | ||||
|                 } | ||||
|             else | ||||
|                 { | ||||
|                     num_samples_readed = fifo_items / d_bytes_per_sample;  //read what we have | ||||
|                 } | ||||
|             break; | ||||
|         default:  //complex byte samples | ||||
|             bytes_requested = noutput_items * d_bytes_per_sample; | ||||
|             if (bytes_requested < fifo_items) | ||||
|                 { | ||||
|                     num_samples_readed = noutput_items;  //read all | ||||
|                 } | ||||
|             else | ||||
|                 { | ||||
|                     num_samples_readed = fifo_items / d_bytes_per_sample;  //read what we have | ||||
|                 } | ||||
|         } | ||||
|  | ||||
|     bytes_requested = num_samples_readed * d_bytes_per_sample; | ||||
|     //read all in a single loop | ||||
|     demux_samples(output_items, num_samples_readed);  // it also increases the fifo read pointer | ||||
|     //update fifo items | ||||
|     fifo_items = fifo_items - bytes_requested; | ||||
|  | ||||
|     for (int n = 0; n < output_items.size(); n++) | ||||
|         { | ||||
|             produce(n, num_samples_readed); | ||||
|         } | ||||
|     return this->WORK_CALLED_PRODUCE; | ||||
| } | ||||
| @@ -0,0 +1,117 @@ | ||||
| /*! | ||||
|  * \file gr_complex_ip_packet_source.h | ||||
|  * | ||||
|  * \brief Receives ip frames containing samples in UDP frame encapsulation | ||||
|  * using a high performance packet capture library (libpcap) | ||||
|  * \author Javier Arribas jarribas (at) cttc.es | ||||
|  * ------------------------------------------------------------------------- | ||||
|  * | ||||
|  * 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 INCLUDED_GR_COMPLEX_IP_PACKET_SOURCE_H | ||||
| #define INCLUDED_GR_COMPLEX_IP_PACKET_SOURCE_H | ||||
|  | ||||
| #include <gnuradio/sync_block.h> | ||||
| #include <boost/thread.hpp> | ||||
| #include <pcap.h> | ||||
| #include <arpa/inet.h> | ||||
| #include <net/if.h> | ||||
| #include <net/ethernet.h> | ||||
| #include <netinet/if_ether.h> | ||||
| #include <sys/ioctl.h> | ||||
|  | ||||
| class gr_complex_ip_packet_source : virtual public gr::sync_block | ||||
| { | ||||
| private: | ||||
|     boost::mutex d_mutex; | ||||
|     pcap_t *descr;  //ethernet pcap device descriptor | ||||
|  | ||||
|     char *fifo_buff; | ||||
|  | ||||
|     int fifo_read_ptr; | ||||
|     int fifo_write_ptr; | ||||
|     int fifo_items; | ||||
|     int d_sock_raw; | ||||
|     int d_udp_port; | ||||
|     struct sockaddr_in si_me; | ||||
|     std::string d_src_device; | ||||
|     std::string d_origin_address; | ||||
|     int d_udp_payload_size; | ||||
|     bool d_fifo_full; | ||||
|  | ||||
|     int d_n_baseband_channels; | ||||
|     int d_wire_sample_type; | ||||
|     int d_bytes_per_sample; | ||||
|     size_t d_item_size; | ||||
|     bool d_IQ_swap; | ||||
|  | ||||
|     boost::thread *d_pcap_thread; | ||||
|     /*! | ||||
| 	 * \brief | ||||
| 	 * Opens the ethernet device using libpcap raw capture mode | ||||
| 	 * If any of these fail, the fuction retuns the error and exits. | ||||
| 	 */ | ||||
|     bool open(); | ||||
|  | ||||
|     void demux_samples(gr_vector_void_star output_items, int num_samples_readed); | ||||
|     void my_pcap_loop_thread(pcap_t *pcap_handle); | ||||
|  | ||||
|     void pcap_callback(u_char *args, const struct pcap_pkthdr *pkthdr, const u_char *packet); | ||||
|  | ||||
|     static void static_pcap_callback(u_char *args, const struct pcap_pkthdr *pkthdr, const u_char *packet); | ||||
|  | ||||
|  | ||||
| public: | ||||
|     typedef boost::shared_ptr<gr_complex_ip_packet_source> sptr; | ||||
|     static sptr make(std::string src_device, | ||||
|         std::string origin_address, | ||||
|         int udp_port, | ||||
|         int udp_packet_size, | ||||
|         int n_baseband_channels, | ||||
|         std::string wire_sample_type, | ||||
|         size_t item_size, | ||||
|         bool IQ_swap_); | ||||
|     gr_complex_ip_packet_source(std::string src_device, | ||||
|         std::string origin_address, | ||||
|         int udp_port, | ||||
|         int udp_packet_size, | ||||
|         int n_baseband_channels, | ||||
|         std::string wire_sample_type, | ||||
|         size_t item_size, | ||||
|         bool IQ_swap_); | ||||
|     ~gr_complex_ip_packet_source(); | ||||
|  | ||||
|     // Where all the action really happens | ||||
|     int work(int noutput_items, | ||||
|         gr_vector_const_void_star &input_items, | ||||
|         gr_vector_void_star &output_items); | ||||
|  | ||||
|     //Called by gnuradio to enable drivers, etc for i/o devices. | ||||
|     bool start(); | ||||
|     //Called by gnuradio to disable drivers, etc for i/o devices. | ||||
|     bool stop(); | ||||
| }; | ||||
|  | ||||
| #endif /* INCLUDED_GR_COMPLEX_IP_PACKET_SOURCE_H */ | ||||
| @@ -0,0 +1,86 @@ | ||||
| /*! | ||||
|  * \file unpack_byte_4bit_samples.cc | ||||
|  * | ||||
|  * \brief Unpacks byte samples to 4 bits samples. | ||||
|  *     Packing Order | ||||
|  *     Packing order in Nibble I0 I1 I2 I3 I0 I1 I2 I3 | ||||
|  * \author Javier Arribas jarribas (at) cttc.es | ||||
|  * ------------------------------------------------------------------------- | ||||
|  * | ||||
|  * 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 "unpack_byte_4bit_samples.h" | ||||
| #include <gnuradio/io_signature.h> | ||||
|  | ||||
| unpack_byte_4bit_samples_sptr make_unpack_byte_4bit_samples() | ||||
| { | ||||
|     return unpack_byte_4bit_samples_sptr(new unpack_byte_4bit_samples()); | ||||
| } | ||||
|  | ||||
|  | ||||
| unpack_byte_4bit_samples::unpack_byte_4bit_samples() : sync_interpolator("unpack_byte_4bit_samples", | ||||
|                                                            gr::io_signature::make(1, 1, sizeof(signed char)), | ||||
|                                                            gr::io_signature::make(1, 1, sizeof(signed char)), | ||||
|                                                            2) | ||||
| { | ||||
| } | ||||
|  | ||||
|  | ||||
| unpack_byte_4bit_samples::~unpack_byte_4bit_samples() | ||||
| { | ||||
| } | ||||
|  | ||||
|  | ||||
| int unpack_byte_4bit_samples::work(int noutput_items, | ||||
|     gr_vector_const_void_star &input_items, | ||||
|     gr_vector_void_star &output_items) | ||||
| { | ||||
|     const signed char *in = reinterpret_cast<const signed char *>(input_items[0]); | ||||
|     signed char *out = reinterpret_cast<signed char *>(output_items[0]); | ||||
|     int n = 0; | ||||
|     unsigned char tmp_char2; | ||||
|     for (int i = 0; i < noutput_items / 2; i++) | ||||
|         { | ||||
|             tmp_char2 = in[i] & 0x0F; | ||||
|             if (tmp_char2 >= 8) | ||||
|                 { | ||||
|                     out[n++] = 2 * (tmp_char2 - 16) + 1; | ||||
|                 } | ||||
|             else | ||||
|                 { | ||||
|                     out[n++] = 2 * tmp_char2 + 1; | ||||
|                 } | ||||
|             tmp_char2 = in[i] >> 4; | ||||
|             tmp_char2 = tmp_char2 & 0x0F; | ||||
|             if (tmp_char2 >= 8) | ||||
|                 { | ||||
|                     out[n++] = 2 * (tmp_char2 - 16) + 1; | ||||
|                 } | ||||
|             else | ||||
|                 { | ||||
|                     out[n++] = 2 * tmp_char2 + 1; | ||||
|                 } | ||||
|         } | ||||
|     return noutput_items; | ||||
| } | ||||
| @@ -0,0 +1,61 @@ | ||||
| /*! | ||||
|  * \file unpack_byte_4bit_samples.h | ||||
|  * | ||||
|  * \brief Unpacks byte samples to 4 bits samples. | ||||
|  *     Packing Order | ||||
|  *     Packing order in Nibble I0 I1 I2 I3 I0 I1 I2 I3 | ||||
|  * \author Javier Arribas jarribas (at) cttc.es | ||||
|  * ------------------------------------------------------------------------- | ||||
|  * | ||||
|  * 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_unpack_byte_4bit_samples_H | ||||
| #define GNSS_SDR_unpack_byte_4bit_samples_H | ||||
|  | ||||
| #include <gnuradio/sync_interpolator.h> | ||||
|  | ||||
| class unpack_byte_4bit_samples; | ||||
|  | ||||
| typedef boost::shared_ptr<unpack_byte_4bit_samples> unpack_byte_4bit_samples_sptr; | ||||
|  | ||||
| unpack_byte_4bit_samples_sptr make_unpack_byte_4bit_samples(); | ||||
|  | ||||
| /*! | ||||
|  * \brief This class implements conversion between byte packet samples to 4bit_cpx samples | ||||
|  *  1 byte = 1 x complex 4bit I, + 4bit Q samples | ||||
|  */ | ||||
| class unpack_byte_4bit_samples : public gr::sync_interpolator | ||||
| { | ||||
| private: | ||||
|     friend unpack_byte_4bit_samples_sptr make_unpack_byte_4bit_samples_sptr(); | ||||
|  | ||||
| public: | ||||
|     unpack_byte_4bit_samples(); | ||||
|     ~unpack_byte_4bit_samples(); | ||||
|     int work(int noutput_items, | ||||
|         gr_vector_const_void_star &input_items, | ||||
|         gr_vector_void_star &output_items); | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| @@ -40,6 +40,9 @@ if(ENABLE_FPGA) | ||||
|      add_definitions(-DENABLE_FPGA=1) | ||||
| endif(ENABLE_FPGA) | ||||
|  | ||||
| if(ENABLE_RAW_UDP) | ||||
|     add_definitions(-DRAW_UDP=1) | ||||
| endif(ENABLE_RAW_UDP) | ||||
|  | ||||
| if(Boost_VERSION LESS 105000) | ||||
|      add_definitions(-DOLD_BOOST=1) | ||||
|   | ||||
| @@ -35,6 +35,7 @@ | ||||
|  | ||||
|  | ||||
| #include "gnss_block_factory.h" | ||||
|  | ||||
| #include "configuration_interface.h" | ||||
| #include "in_memory_configuration.h" | ||||
| #include "gnss_block_interface.h" | ||||
| @@ -103,6 +104,10 @@ | ||||
| #include "hybrid_observables.h" | ||||
| #include "rtklib_pvt.h" | ||||
|  | ||||
| #if RAW_UDP | ||||
| #include "custom_udp_signal_source.h" | ||||
| #endif | ||||
|  | ||||
| #if ENABLE_FPGA | ||||
| #include "gps_l1_ca_pcps_acquisition_fpga.h" | ||||
| #include "gps_l1_ca_dll_pll_tracking_fpga.h" | ||||
| @@ -158,11 +163,7 @@ using google::LogMessage; | ||||
|  | ||||
|  | ||||
| GNSSBlockFactory::GNSSBlockFactory() {} | ||||
|  | ||||
|  | ||||
| GNSSBlockFactory::~GNSSBlockFactory() {} | ||||
|  | ||||
|  | ||||
| std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetSignalSource( | ||||
|     std::shared_ptr<ConfigurationInterface> configuration, gr::msg_queue::sptr queue, int ID) | ||||
| { | ||||
| @@ -1052,6 +1053,23 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock( | ||||
|                     exit(1); | ||||
|                 } | ||||
|         } | ||||
| #if RAW_UDP | ||||
|     else if (implementation.compare("Custom_UDP_Signal_Source") == 0) | ||||
|         { | ||||
|             try | ||||
|                 { | ||||
|                     std::unique_ptr<GNSSBlockInterface> block_(new CustomUDPSignalSource(configuration.get(), role, in_streams, | ||||
|                         out_streams, queue)); | ||||
|                     block = std::move(block_); | ||||
|                 } | ||||
|  | ||||
|             catch (const std::exception &e) | ||||
|                 { | ||||
|                     std::cout << "GNSS-SDR program ended." << std::endl; | ||||
|                     exit(1); | ||||
|                 } | ||||
|         } | ||||
| #endif | ||||
|     else if (implementation.compare("Nsr_File_Signal_Source") == 0) | ||||
|         { | ||||
|             try | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Javier Arribas
					Javier Arribas