diff --git a/CMakeLists.txt b/CMakeLists.txt index 94b4d5ef6..954690ffb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 ######################################################################## diff --git a/cmake/Modules/FindPCAP.cmake b/cmake/Modules/FindPCAP.cmake new file mode 100644 index 000000000..3be89420e --- /dev/null +++ b/cmake/Modules/FindPCAP.cmake @@ -0,0 +1,121 @@ +################################################################### +# +# Copyright (c) 2006 Frederic Heem, +# 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 true ) +ENDIF(PCAP_INCLUDE_DIRS AND PCAP_LIBRARIES) + + +MARK_AS_ADVANCED( + PCAP_LIBRARIES + PCAP_INCLUDE_DIRS +) diff --git a/conf/gnss-sdr_GPS_L1_2ch_udp.conf b/conf/gnss-sdr_GPS_L1_2ch_udp.conf new file mode 100644 index 000000000..6dd703fa6 --- /dev/null +++ b/conf/gnss-sdr_GPS_L1_2ch_udp.conf @@ -0,0 +1,103 @@ +; 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=Custom_UDP_Signal_Source +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 diff --git a/src/algorithms/PVT/libs/rtklib_solver.cc b/src/algorithms/PVT/libs/rtklib_solver.cc index 8d74aea20..a0650d768 100644 --- a/src/algorithms/PVT/libs/rtklib_solver.cc +++ b/src/algorithms/PVT/libs/rtklib_solver.cc @@ -463,14 +463,14 @@ bool rtklib_solver::get_PVT(const std::map& gnss_observables_ unsigned int used_sats = 0; for (unsigned int i = 0; i < MAXSAT; i++) { - if (int vsat = rtk_.ssat[i].vsat[0] == 1) used_sats++; + if (rtk_.ssat[i].vsat[0] == 1) used_sats++; } double azel[used_sats * 2]; unsigned int index_aux = 0; for (unsigned int i = 0; i < MAXSAT; i++) { - if (int vsat = rtk_.ssat[i].vsat[0] == 1) + if (rtk_.ssat[i].vsat[0] == 1) { azel[2 * index_aux] = rtk_.ssat[i].azel[0]; azel[2 * index_aux + 1] = rtk_.ssat[i].azel[1]; diff --git a/src/algorithms/libs/rtklib/rtklib_pntpos.cc b/src/algorithms/libs/rtklib/rtklib_pntpos.cc index 31b60c8e6..d4a10fe65 100644 --- a/src/algorithms/libs/rtklib/rtklib_pntpos.cc +++ b/src/algorithms/libs/rtklib/rtklib_pntpos.cc @@ -130,11 +130,11 @@ double prange(const obsd_t *obs, const nav_t *nav, const double *azel, double P1_P2 = 0.0; double P1_C1 = 0.0; double P2_C2 = 0.0; - //Intersignal corrections (m). See GPS IS-200 CNAV message - double ISCl1 = 0.0; + // Intersignal corrections (m). See GPS IS-200 CNAV message + //double ISCl1 = 0.0; double ISCl2 = 0.0; double ISCl5i = 0.0; - double ISCl5q = 0.0; + //double ISCl5q = 0.0; double gamma_ = 0.0; int i = 0; int j = 1; @@ -209,10 +209,10 @@ double prange(const obsd_t *obs, const nav_t *nav, const double *azel, if (sys == SYS_GPS) { - ISCl1 = getiscl1(obs->sat, nav); + // ISCl1 = getiscl1(obs->sat, nav); ISCl2 = getiscl2(obs->sat, nav); ISCl5i = getiscl5i(obs->sat, nav); - ISCl5q = getiscl5q(obs->sat, nav); + // ISCl5q = getiscl5q(obs->sat, nav); } //CHECK IF IT IS STILL NEEDED diff --git a/src/algorithms/libs/rtklib/rtklib_rtkcmn.cc b/src/algorithms/libs/rtklib/rtklib_rtkcmn.cc index 20f939dd4..88cc2ca38 100644 --- a/src/algorithms/libs/rtklib/rtklib_rtkcmn.cc +++ b/src/algorithms/libs/rtklib/rtklib_rtkcmn.cc @@ -54,6 +54,8 @@ //#include #include #include +#include +#include #include #include #include @@ -253,11 +255,12 @@ const unsigned int tbl_CRC24Q[] = { 0x42FA2F, 0xC4B6D4, 0xC82F22, 0x4E63D9, 0xD11CCE, 0x575035, 0x5BC9C3, 0xDD8538}; -extern "C" { -void dgemm_(char *, char *, int *, int *, int *, double *, double *, int *, double *, int *, double *, double *, int *); -extern void dgetrf_(int *, int *, double *, int *, int *, int *); -extern void dgetri_(int *, double *, int *, int *, double *, int *, int *); -extern void dgetrs_(char *, int *, int *, double *, int *, int *, double *, int *, int *); +extern "C" +{ + void dgemm_(char *, char *, int *, int *, int *, double *, double *, int *, double *, int *, double *, double *, int *); + extern void dgetrf_(int *, int *, double *, int *, int *, int *); + extern void dgetri_(int *, double *, int *, int *, double *, int *, int *); + extern void dgetrs_(char *, int *, int *, double *, int *, int *, double *, int *, int *); } @@ -2562,7 +2565,8 @@ void readpos(const char *file, const char *rcv, double *pos) if (buff[0] == '%' || buff[0] == '#') continue; if (sscanf(buff, "%lf %lf %lf %s", &poss[np][0], &poss[np][1], &poss[np][2], str) < 4) continue; - strncpy(stas[np], str, 15); + // strncpy(stas[np], str, 15); This line triggers a warning. Replaced by: + memcpy(stas[np], str, 15 * sizeof(stas[np][0])); stas[np++][15] = '\0'; } fclose(fp); @@ -4264,7 +4268,17 @@ int rtk_uncompress(const char *file, char *uncfile) dir = fname; fname = p + 1; } - sprintf(cmd, "tar -C \"%s\" -xf \"%s\"", dir, tmpfile); + // sprintf(cmd, "tar -C \"%s\" -xf \"%s\"", dir, tmpfile); + // NOTE: This sprintf triggers a format overflow warning. Replaced by: + std::ostringstream temp; + std::string s_aux1(dir); + std::string s_aux2(tmpfile); + temp << "tar -C " << s_aux1 << " -xf " << s_aux2; + std::string s_aux = temp.str(); + int n = s_aux.length(); + if (n < 2048) + for (int i = 0; i < n; i++) cmd[i] = s_aux[i]; + if (execcmd(cmd)) { if (stat) diff --git a/src/algorithms/libs/rtklib/rtklib_stream.cc b/src/algorithms/libs/rtklib/rtklib_stream.cc index 6dafde2ac..3de693e65 100644 --- a/src/algorithms/libs/rtklib/rtklib_stream.cc +++ b/src/algorithms/libs/rtklib/rtklib_stream.cc @@ -64,6 +64,7 @@ #include #include #include +#include /* global options ------------------------------------------------------------*/ @@ -115,7 +116,12 @@ serial_t *openserial(const char *path, int mode, char *msg) } parity = (char)toupper((int)parity); - sprintf(dev, "/dev/%s", port); + // sprintf(dev, "/dev/%s", port); This line triggers a warning. Replaced by: + std::string s_aux = "/dev/" + std::string(port); + s_aux.resize(128, '\0'); + int n = s_aux.length(); + if (n < 128) + for (int i = 0; i < n; i++) dev[i] = s_aux[i]; if ((mode & STR_MODE_R) && (mode & STR_MODE_W)) rw = O_RDWR; @@ -1224,7 +1230,11 @@ int rspntrip_s(ntrip_t *ntrip, char *msg) else if ((p = strstr((char *)ntrip->buff, NTRIP_RSP_ERROR))) { /* error */ nb = ntrip->nb < MAXSTATMSG ? ntrip->nb : MAXSTATMSG; - strncpy(msg, (char *)ntrip->buff, nb); + // strncpy(msg, (char *)ntrip->buff, nb); This line triggers a warning. Replaced by; + std::string s_aux((char *)ntrip->buff); + s_aux.resize(nb, '\0'); + for (int i = 0; i < nb; i++) msg[i] = s_aux[i]; + msg[nb] = 0; tracet(1, "rspntrip_s: %s nb=%d\n", msg, ntrip->nb); ntrip->nb = 0; @@ -1380,7 +1390,11 @@ ntrip_t *openntrip(const char *path, int type, char *msg) /* ntrip access via proxy server */ if (*proxyaddr) { - sprintf(ntrip->url, "http://%s", tpath); + // sprintf(ntrip->url, "http://%s", tpath); This line triggers a warning. Replaced by: + std::string s_aux = "http://" + std::string(tpath); + int n = s_aux.length(); + if (n < 256) + for (int k = 0; k < n; k++) ntrip->url[k] = s_aux[k]; strcpy(tpath, proxyaddr); } /* open tcp client stream */ @@ -1545,8 +1559,17 @@ void *ftpthread(void *arg) p++; else p = remote; - sprintf(local, "%s%c%s", localdir, FILEPATHSEP, p); - sprintf(errfile, "%s.err", local); + // sprintf(local, "%s%c%s", localdir, FILEPATHSEP, p); This line triggers a warning. Replaced by: + std::string s_aux = std::string(localdir) + std::to_string(FILEPATHSEP) + std::string(p); + int n = s_aux.length(); + if (n < 1024) + for (int i = 0; i < n; i++) local[i] = s_aux[i]; + + // sprintf(errfile, "%s.err", local); This line triggers a warning. Replaced by: + std::string s_aux2 = std::string(local) + ".err"; + n = s_aux2.length(); + if (n < 1024) + for (int i = 0; i < n; i++) errfile[i] = s_aux2[i]; /* if local file exist, skip download */ strcpy(tmpfile, local); @@ -1574,16 +1597,35 @@ void *ftpthread(void *arg) /* download command (ref [2]) */ if (ftp->proto == 0) { /* ftp */ - sprintf(opt, "--ftp-user=%s --ftp-password=%s --glob=off --passive-ftp %s-t 1 -T %d -O \"%s\"", - ftp->user, ftp->passwd, proxyopt, FTP_TIMEOUT, local); - sprintf(cmd, "%s%s %s \"ftp://%s/%s\" 2> \"%s\"\n", env, FTP_CMD, opt, ftp->addr, - remote, errfile); + // sprintf(opt, "--ftp-user=%s --ftp-password=%s --glob=off --passive-ftp %s-t 1 -T %d -O \"%s\"", + // ftp->user, ftp->passwd, proxyopt, FTP_TIMEOUT, local); This line triggers a warning. Replaced by: + std::string s_aux = "--ftp-user=" + std::string(ftp->user) + " --ftp-password=" + std::string(ftp->passwd) + + " --glob=off --passive-ftp " + std::string(proxyopt) + "s-t 1 -T " + std::to_string(FTP_TIMEOUT) + + " -O \"" + std::string(local) + "\""; + int k = s_aux.length(); + if (k < 2048) + for (int i = 0; i < k; i++) opt[i] = s_aux[i]; + + // sprintf(cmd, "%s%s %s \"ftp://%s/%s\" 2> \"%s\"\n", env, FTP_CMD, opt, ftp->addr, + // remote, errfile); This line triggers a warning. Replaced by: + std::string s_aux2 = std::string(env) + std::string(FTP_CMD) + " " + std::string(opt) + " " + + "\"ftp://" + std::string(ftp->addr) + "/" + std::string(remote) + "\" 2> \"" + std::string(errfile) + "\"\n"; + k = s_aux2.length(); + for (int i = 0; (i < k) && (i < 1024); i++) cmd[i] = s_aux2[i]; } else { /* http */ - sprintf(opt, "%s-t 1 -T %d -O \"%s\"", proxyopt, FTP_TIMEOUT, local); - sprintf(cmd, "%s%s %s \"http://%s/%s\" 2> \"%s\"\n", env, FTP_CMD, opt, ftp->addr, - remote, errfile); + // sprintf(opt, "%s-t 1 -T %d -O \"%s\"", proxyopt, FTP_TIMEOUT, local); This line triggers a warning. Replaced by: + std::string s_aux = std::string(proxyopt) + " -t 1 -T " + std::to_string(FTP_TIMEOUT) + " -O \"" + std::string(local) + "\""; + int l = s_aux.length(); + for (int i = 0; (i < l) && (i < 1024); i++) opt[i] = s_aux[i]; + + // sprintf(cmd, "%s%s %s \"http://%s/%s\" 2> \"%s\"\n", env, FTP_CMD, opt, ftp->addr, + // remote, errfile); This line triggers a warning. Replaced by: + std::string s_aux2 = std::string(env) + std::string(FTP_CMD) + " " + std::string(opt) + " " + + "\"http://" + std::string(ftp->addr) + "/" + std::string(remote) + "\" 2> \"" + std::string(errfile) + "\"\n"; + l = s_aux2.length(); + for (int i = 0; (i < l) && (i < 1024); i++) cmd[i] = s_aux2[i]; } /* execute download command */ if ((ret = execcmd(cmd))) @@ -2049,7 +2091,10 @@ int strstat(stream_t *stream, char *msg) strlock(stream); if (msg) { - strncpy(msg, stream->msg, MAXSTRMSG - 1); + // strncpy(msg, stream->msg, MAXSTRMSG - 1); This line triggers a warning. Replaced by: + std::string aux_s(stream->msg); + aux_s.resize(MAXSTRMSG - 1, '0'); + for (int i = 0; i < MAXSTRMSG - 1; i++) msg[i] = aux_s[i]; msg[MAXSTRMSG - 1] = '\0'; } if (!stream->port) diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/qa_utils.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/qa_utils.cc index cf26c9bea..60fb651c0 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/qa_utils.cc +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/qa_utils.cc @@ -539,7 +539,7 @@ bool run_volk_gnsssdr_tests(volk_gnsssdr_func_desc_t desc, vlen = vlen + vlen_twiddle; const float tol_f = tol; - const unsigned int tol_i = static_cast(tol); + const unsigned int tol_i = static_cast(tol); //first let's get a list of available architectures for the test std::vector arch_list = get_arch_list(desc); diff --git a/src/algorithms/signal_source/adapters/CMakeLists.txt b/src/algorithms/signal_source/adapters/CMakeLists.txt index c2fa1de07..120fff27b 100644 --- a/src/algorithms/signal_source/adapters/CMakeLists.txt +++ b/src/algorithms/signal_source/adapters/CMakeLists.txt @@ -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) diff --git a/src/algorithms/signal_source/adapters/custom_udp_signal_source.cc b/src/algorithms/signal_source/adapters/custom_udp_signal_source.cc new file mode 100644 index 000000000..2ed2dd5ae --- /dev/null +++ b/src/algorithms/signal_source/adapters/custom_udp_signal_source.cc @@ -0,0 +1,167 @@ +/*! + * \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 . + * + * ------------------------------------------------------------------------- + */ + + +#include "custom_udp_signal_source.h" +#include "configuration_interface.h" +#include "GPS_L1_CA.h" +#include +#include +#include + + +using google::LogMessage; + + +CustomUDPSignalSource::CustomUDPSignalSource(ConfigurationInterface* configuration, + std::string role, unsigned int in_stream, unsigned int out_stream, + boost::shared_ptr 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_channelsconnect(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_; +} diff --git a/src/algorithms/signal_source/adapters/custom_udp_signal_source.h b/src/algorithms/signal_source/adapters/custom_udp_signal_source.h new file mode 100644 index 000000000..fcd42071d --- /dev/null +++ b/src/algorithms/signal_source/adapters/custom_udp_signal_source.h @@ -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 . + * + * ------------------------------------------------------------------------- + */ + + +#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 +#include +#include +#include +#include +#include +#include + + +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 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> null_sinks_; + gr_complex_ip_packet_source::sptr udp_gnss_rx_source_; + std::vector> file_sink_; + boost::shared_ptr queue_; +}; + +#endif /*GNSS_SDR_CUSTOM_UDP_SIGNAL_SOURCE_H */ diff --git a/src/algorithms/signal_source/gnuradio_blocks/CMakeLists.txt b/src/algorithms/signal_source/gnuradio_blocks/CMakeLists.txt index 7469b6192..fdeb71c47 100644 --- a/src/algorithms/signal_source/gnuradio_blocks/CMakeLists.txt +++ b/src/algorithms/signal_source/gnuradio_blocks/CMakeLists.txt @@ -17,14 +17,47 @@ # +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 +67,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}) diff --git a/src/algorithms/signal_source/gnuradio_blocks/gr_complex_ip_packet_source.cc b/src/algorithms/signal_source/gnuradio_blocks/gr_complex_ip_packet_source.cc new file mode 100644 index 000000000..8da6d4a5d --- /dev/null +++ b/src/algorithms/signal_source/gnuradio_blocks/gr_complex_ip_packet_source.cc @@ -0,0 +1,438 @@ +/*! + * \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 . + * + * ------------------------------------------------------------------------- + */ + + +#include "gr_complex_ip_packet_source.h" +#include + +//#include + + +#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:"<len)<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; +} diff --git a/src/algorithms/signal_source/gnuradio_blocks/gr_complex_ip_packet_source.h b/src/algorithms/signal_source/gnuradio_blocks/gr_complex_ip_packet_source.h new file mode 100644 index 000000000..0661e0911 --- /dev/null +++ b/src/algorithms/signal_source/gnuradio_blocks/gr_complex_ip_packet_source.h @@ -0,0 +1,115 @@ +/*! + * \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 . + * + * ------------------------------------------------------------------------- + */ + + +#ifndef INCLUDED_GR_COMPLEX_IP_PACKET_SOURCE_H +#define INCLUDED_GR_COMPLEX_IP_PACKET_SOURCE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 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 */ diff --git a/src/algorithms/signal_source/gnuradio_blocks/unpack_byte_4bit_samples.cc b/src/algorithms/signal_source/gnuradio_blocks/unpack_byte_4bit_samples.cc new file mode 100644 index 000000000..b3a1d61f7 --- /dev/null +++ b/src/algorithms/signal_source/gnuradio_blocks/unpack_byte_4bit_samples.cc @@ -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-2018 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + +#include "unpack_byte_4bit_samples.h" +#include + +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(input_items[0]); + signed char *out = reinterpret_cast(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; +} diff --git a/src/algorithms/signal_source/gnuradio_blocks/unpack_byte_4bit_samples.h b/src/algorithms/signal_source/gnuradio_blocks/unpack_byte_4bit_samples.h new file mode 100644 index 000000000..0a48bcb5f --- /dev/null +++ b/src/algorithms/signal_source/gnuradio_blocks/unpack_byte_4bit_samples.h @@ -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-2018 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + +#ifndef GNSS_SDR_unpack_byte_4bit_samples_H +#define GNSS_SDR_unpack_byte_4bit_samples_H + +#include + +class unpack_byte_4bit_samples; + +typedef boost::shared_ptr 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 diff --git a/src/core/receiver/CMakeLists.txt b/src/core/receiver/CMakeLists.txt index 09b24de96..7be920a47 100644 --- a/src/core/receiver/CMakeLists.txt +++ b/src/core/receiver/CMakeLists.txt @@ -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) diff --git a/src/core/receiver/control_thread.cc b/src/core/receiver/control_thread.cc index 0710da730..8eb49563c 100644 --- a/src/core/receiver/control_thread.cc +++ b/src/core/receiver/control_thread.cc @@ -114,7 +114,7 @@ void ControlThread::run() { flowgraph_->connect(); } - catch (const std::exception e) + catch (const std::exception &e) { LOG(ERROR) << e.what(); return; diff --git a/src/core/receiver/gnss_block_factory.cc b/src/core/receiver/gnss_block_factory.cc index 93e4a2d0d..237f2df40 100644 --- a/src/core/receiver/gnss_block_factory.cc +++ b/src/core/receiver/gnss_block_factory.cc @@ -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 GNSSBlockFactory::GetSignalSource( std::shared_ptr configuration, gr::msg_queue::sptr queue, int ID) { @@ -1052,6 +1053,23 @@ std::unique_ptr GNSSBlockFactory::GetBlock( exit(1); } } +#if RAW_UDP + else if (implementation.compare("Custom_UDP_Signal_Source") == 0) + { + try + { + std::unique_ptr 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