1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-07-08 20:54:20 +00:00

Merge branch 'next' into trk_hi_dyn

This commit is contained in:
Antonio Ramos 2018-08-28 22:09:49 +02:00
commit 1f1d5491b3
31 changed files with 1246 additions and 1318 deletions

View File

@ -523,7 +523,6 @@ if(NOT GNURADIO_RUNTIME_FOUND)
message("You can install it easily via Macports:") message("You can install it easily via Macports:")
message(" sudo port install gnuradio ") message(" sudo port install gnuradio ")
message("Alternatively, you can use homebrew:") message("Alternatively, you can use homebrew:")
message(" brew tap odrisci/gnuradio")
message(" brew install gnuradio" ) message(" brew install gnuradio" )
message(FATAL_ERROR "GNU Radio ${GNSSSDR_GNURADIO_MIN_VERSION} or later is required to build gnss-sdr") message(FATAL_ERROR "GNU Radio ${GNSSSDR_GNURADIO_MIN_VERSION} or later is required to build gnss-sdr")
endif(OS_IS_MACOSX) endif(OS_IS_MACOSX)

View File

@ -12,11 +12,17 @@ author:
- et altri (see AUTHORS file for a list of contributors) - et altri (see AUTHORS file for a list of contributors)
copyright_owner: copyright_owner:
- The Authors - The Authors
dependencies: gnuradio (>= 3.7.3), armadillo, gflags, glog, gnutls, matio dependencies:
- gnuradio (>= 3.7.3)
- armadillo
- gflags
- glog
- gnutls
- matio
license: GPLv3+ license: GPLv3+
repo: https://github.com/gnss-sdr/gnss-sdr repo: https://github.com/gnss-sdr/gnss-sdr
website: https://gnss-sdr.org website: https://gnss-sdr.org
icon: https://raw.githubusercontent.com/gnss-sdr/gnss-sdr/master/docs/doxygen/images/gnss-sdr_logo.png icon: https://gnss-sdr.org/assets/images/logo400x400.jpg
--- ---
Global Navigation Satellite Systems receiver defined by software. It performs all the signal Global Navigation Satellite Systems receiver defined by software. It performs all the signal
processing from raw signal samples up to the computation of the Position-Velocity-Time solution, processing from raw signal samples up to the computation of the Position-Velocity-Time solution,

View File

@ -71,7 +71,6 @@
#define socket_t int #define socket_t int
#define closesocket close #define closesocket close
#define lock_t pthread_mutex_t #define lock_t pthread_mutex_t
#define thread_t pthread_t
#define initlock(f) pthread_mutex_init(f, NULL) #define initlock(f) pthread_mutex_init(f, NULL)
#define rtk_lock(f) pthread_mutex_lock(f) #define rtk_lock(f) pthread_mutex_lock(f)
#define rtk_unlock(f) pthread_mutex_unlock(f) #define rtk_unlock(f) pthread_mutex_unlock(f)
@ -1211,7 +1210,7 @@ typedef struct
char local[1024]; /* local file path */ char local[1024]; /* local file path */
int topts[4]; /* time options {poff,tint,toff,tretry} (s) */ int topts[4]; /* time options {poff,tint,toff,tretry} (s) */
gtime_t tnext; /* next retry time (gpst) */ gtime_t tnext; /* next retry time (gpst) */
thread_t thread; /* download thread */ pthread_t thread; /* download thread */
} ftp_t; } ftp_t;
@ -1284,7 +1283,7 @@ typedef struct
stream_t stream[8]; /* streams {rov,base,corr,sol1,sol2,logr,logb,logc} */ stream_t stream[8]; /* streams {rov,base,corr,sol1,sol2,logr,logb,logc} */
stream_t *moni; /* monitor stream */ stream_t *moni; /* monitor stream */
unsigned int tick; /* start tick */ unsigned int tick; /* start tick */
thread_t thread; /* server thread */ pthread_t thread; /* server thread */
int cputime; /* CPU time (ms) for a processing cycle */ int cputime; /* CPU time (ms) for a processing cycle */
int prcout; /* missing observation data count */ int prcout; /* missing observation data count */
lock_t lock; /* lock flag */ lock_t lock; /* lock flag */

View File

@ -89,38 +89,6 @@ double leaps[MAXLEAPS + 1][7] = {/* leap seconds (y,m,d,h,m,s,utc-gpst) */
{}}; {}};
const prcopt_t prcopt_default = { /* defaults processing options */
PMODE_SINGLE, 0, 2, SYS_GPS, /* mode, soltype, nf, navsys */
15.0 * D2R, {{}, {{}, {}}}, /* elmin, snrmask */
0, 1, 1, 1, /* sateph, modear, glomodear, bdsmodear */
5, 0, 10, 1, /* maxout, minlock, minfix, armaxiter */
0, 0, 0, 0, /* estion, esttrop, dynamics, tidecorr */
1, 0, 0, 0, 0, /* niter, codesmooth, intpref, sbascorr, sbassatsel */
0, 0, /* rovpos, refpos */
{100.0, 100.0, 100.0}, /* eratio[] */
{100.0, 0.003, 0.003, 0.0, 1.0}, /* err[] */
{30.0, 0.03, 0.3}, /* std[] */
{1e-4, 1e-3, 1e-4, 1e-1, 1e-2, 0.0}, /* prn[] */
5E-12, /* sclkstab */
{3.0, 0.9999, 0.25, 0.1, 0.05, 0, 0, 0}, /* thresar */
0.0, 0.0, 0.05, /* elmaskar, almaskhold, thresslip */
30.0, 30.0, 30.0, /* maxtdif, maxinno, maxgdop */
{}, {}, {}, /* baseline, ru, rb */
{"", ""}, /* anttype */
{}, {}, {}, /* antdel, pcv, exsats */
0, 0, 0, {"", ""}, {}, 0, {{}, {}}, {{}, {{}, {}}, {{}, {}}, {}, {}}, 0, {}};
const solopt_t solopt_default = {
/* defaults solution output options */
SOLF_LLH, TIMES_GPST, 1, 3, /* posf, times, timef, timeu */
0, 1, 0, 0, 0, 0, /* degf, outhead, outopt, datum, height, geoid */
0, 0, 0, /* solstatic, sstat, trace */
{0.0, 0.0}, /* nmeaintv */
" ", "", 0 /* separator/program name */
};
const char *formatstrs[32] = {/* stream format strings */ const char *formatstrs[32] = {/* stream format strings */
"RTCM 2", /* 0 */ "RTCM 2", /* 0 */
"RTCM 3", /* 1 */ "RTCM 3", /* 1 */

View File

@ -1,6 +1,6 @@
/*! /*!
* \file volk_gnsssdr_32f_fast_resamplerxnpuppet_32f.h * \file volk_gnsssdr_32f_high_dynamics_resamplerxnpuppet_32f.h
* \brief VOLK_GNSSSDR puppet for the multiple 32-bit float vector fast resampler kernel. * \brief VOLK_GNSSSDR puppet for the multiple 32-bit float vector high dynamics resampler kernel.
* \authors <ul> * \authors <ul>
* <li> Cillian O'Driscoll 2017 cillian.odriscoll at gmail dot com * <li> Cillian O'Driscoll 2017 cillian.odriscoll at gmail dot com
* <li> Javier Arribas, 2018. javiarribas(at)gmail.com * <li> Javier Arribas, 2018. javiarribas(at)gmail.com
@ -33,10 +33,10 @@
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
*/ */
#ifndef INCLUDED_volk_gnsssdr_32f_fast_resamplerxnpuppet_32f_H #ifndef INCLUDED_volk_gnsssdr_32f_high_dynamics_resamplerxnpuppet_32f_H
#define INCLUDED_volk_gnsssdr_32f_fast_resamplerxnpuppet_32f_H #define INCLUDED_volk_gnsssdr_32f_high_dynamics_resamplerxnpuppet_32f_H
#include "volk_gnsssdr/volk_gnsssdr_32f_xn_fast_resampler_32f_xn.h" #include "volk_gnsssdr/volk_gnsssdr_32f_xn_high_dynamics_resampler_32f_xn.h"
#include <volk_gnsssdr/volk_gnsssdr_malloc.h> #include <volk_gnsssdr/volk_gnsssdr_malloc.h>
#include <volk_gnsssdr/volk_gnsssdr_complex.h> #include <volk_gnsssdr/volk_gnsssdr_complex.h>
#include <volk_gnsssdr/volk_gnsssdr.h> #include <volk_gnsssdr/volk_gnsssdr.h>
@ -44,7 +44,7 @@
#ifdef LV_HAVE_GENERIC #ifdef LV_HAVE_GENERIC
static inline void volk_gnsssdr_32f_fast_resamplerxnpuppet_32f_generic(float* result, const float* local_code, unsigned int num_points) static inline void volk_gnsssdr_32f_high_dynamics_resamplerxnpuppet_32f_generic(float* result, const float* local_code, unsigned int num_points)
{ {
int code_length_chips = 2046; int code_length_chips = 2046;
float code_phase_step_chips = ((float)(code_length_chips) + 0.1) / ((float)num_points); float code_phase_step_chips = ((float)(code_length_chips) + 0.1) / ((float)num_points);
@ -60,7 +60,7 @@ static inline void volk_gnsssdr_32f_fast_resamplerxnpuppet_32f_generic(float* re
result_aux[n] = (float*)volk_gnsssdr_malloc(sizeof(float) * num_points, volk_gnsssdr_get_alignment()); result_aux[n] = (float*)volk_gnsssdr_malloc(sizeof(float) * num_points, volk_gnsssdr_get_alignment());
} }
volk_gnsssdr_32f_xn_fast_resampler_32f_xn_generic(result_aux, local_code, rem_code_phase_chips, code_phase_step_chips, code_phase_rate_step_chips, shifts_chips, code_length_chips, num_out_vectors, num_points); volk_gnsssdr_32f_xn_high_dynamics_resampler_32f_xn_generic(result_aux, local_code, rem_code_phase_chips, code_phase_step_chips, code_phase_rate_step_chips, shifts_chips, code_length_chips, num_out_vectors, num_points);
memcpy((float*)result, (float*)result_aux[0], sizeof(float) * num_points); memcpy((float*)result, (float*)result_aux[0], sizeof(float) * num_points);
@ -75,7 +75,7 @@ static inline void volk_gnsssdr_32f_fast_resamplerxnpuppet_32f_generic(float* re
#ifdef LV_HAVE_SSE3 #ifdef LV_HAVE_SSE3
static inline void volk_gnsssdr_32f_fast_resamplerxnpuppet_32f_a_sse3(float* result, const float* local_code, unsigned int num_points) static inline void volk_gnsssdr_32f_high_dynamics_resamplerxnpuppet_32f_a_sse3(float* result, const float* local_code, unsigned int num_points)
{ {
int code_length_chips = 2046; int code_length_chips = 2046;
float code_phase_step_chips = ((float)(code_length_chips) + 0.1) / ((float)num_points); float code_phase_step_chips = ((float)(code_length_chips) + 0.1) / ((float)num_points);
@ -91,7 +91,7 @@ static inline void volk_gnsssdr_32f_fast_resamplerxnpuppet_32f_a_sse3(float* res
result_aux[n] = (float*)volk_gnsssdr_malloc(sizeof(float) * num_points, volk_gnsssdr_get_alignment()); result_aux[n] = (float*)volk_gnsssdr_malloc(sizeof(float) * num_points, volk_gnsssdr_get_alignment());
} }
volk_gnsssdr_32f_xn_fast_resampler_32f_xn_a_sse3(result_aux, local_code, rem_code_phase_chips, code_phase_step_chips, code_phase_rate_step_chips, shifts_chips, code_length_chips, num_out_vectors, num_points); volk_gnsssdr_32f_xn_high_dynamics_resampler_32f_xn_a_sse3(result_aux, local_code, rem_code_phase_chips, code_phase_step_chips, code_phase_rate_step_chips, shifts_chips, code_length_chips, num_out_vectors, num_points);
memcpy((float*)result, (float*)result_aux[0], sizeof(float) * num_points); memcpy((float*)result, (float*)result_aux[0], sizeof(float) * num_points);
@ -106,7 +106,7 @@ static inline void volk_gnsssdr_32f_fast_resamplerxnpuppet_32f_a_sse3(float* res
#ifdef LV_HAVE_SSE3 #ifdef LV_HAVE_SSE3
static inline void volk_gnsssdr_32f_fast_resamplerxnpuppet_32f_u_sse3(float* result, const float* local_code, unsigned int num_points) static inline void volk_gnsssdr_32f_high_dynamics_resamplerxnpuppet_32f_u_sse3(float* result, const float* local_code, unsigned int num_points)
{ {
int code_length_chips = 2046; int code_length_chips = 2046;
float code_phase_step_chips = ((float)(code_length_chips) + 0.1) / ((float)num_points); float code_phase_step_chips = ((float)(code_length_chips) + 0.1) / ((float)num_points);
@ -122,7 +122,7 @@ static inline void volk_gnsssdr_32f_fast_resamplerxnpuppet_32f_u_sse3(float* res
result_aux[n] = (float*)volk_gnsssdr_malloc(sizeof(float) * num_points, volk_gnsssdr_get_alignment()); result_aux[n] = (float*)volk_gnsssdr_malloc(sizeof(float) * num_points, volk_gnsssdr_get_alignment());
} }
volk_gnsssdr_32f_xn_fast_resampler_32f_xn_u_sse3(result_aux, local_code, rem_code_phase_chips, code_phase_step_chips, code_phase_rate_step_chips, shifts_chips, code_length_chips, num_out_vectors, num_points); volk_gnsssdr_32f_xn_high_dynamics_resampler_32f_xn_u_sse3(result_aux, local_code, rem_code_phase_chips, code_phase_step_chips, code_phase_rate_step_chips, shifts_chips, code_length_chips, num_out_vectors, num_points);
memcpy((float*)result, (float*)result_aux[0], sizeof(float) * num_points); memcpy((float*)result, (float*)result_aux[0], sizeof(float) * num_points);
@ -137,7 +137,7 @@ static inline void volk_gnsssdr_32f_fast_resamplerxnpuppet_32f_u_sse3(float* res
#ifdef LV_HAVE_SSE4_1 #ifdef LV_HAVE_SSE4_1
static inline void volk_gnsssdr_32f_fast_resamplerxnpuppet_32f_u_sse4_1(float* result, const float* local_code, unsigned int num_points) static inline void volk_gnsssdr_32f_high_dynamics_resamplerxnpuppet_32f_u_sse4_1(float* result, const float* local_code, unsigned int num_points)
{ {
int code_length_chips = 2046; int code_length_chips = 2046;
float code_phase_step_chips = ((float)(code_length_chips) + 0.1) / ((float)num_points); float code_phase_step_chips = ((float)(code_length_chips) + 0.1) / ((float)num_points);
@ -153,7 +153,7 @@ static inline void volk_gnsssdr_32f_fast_resamplerxnpuppet_32f_u_sse4_1(float* r
result_aux[n] = (float*)volk_gnsssdr_malloc(sizeof(float) * num_points, volk_gnsssdr_get_alignment()); result_aux[n] = (float*)volk_gnsssdr_malloc(sizeof(float) * num_points, volk_gnsssdr_get_alignment());
} }
volk_gnsssdr_32f_xn_fast_resampler_32f_xn_u_sse4_1(result_aux, local_code, rem_code_phase_chips, code_phase_step_chips, code_phase_rate_step_chips, shifts_chips, code_length_chips, num_out_vectors, num_points); volk_gnsssdr_32f_xn_high_dynamics_resampler_32f_xn_u_sse4_1(result_aux, local_code, rem_code_phase_chips, code_phase_step_chips, code_phase_rate_step_chips, shifts_chips, code_length_chips, num_out_vectors, num_points);
memcpy((float*)result, (float*)result_aux[0], sizeof(float) * num_points); memcpy((float*)result, (float*)result_aux[0], sizeof(float) * num_points);
@ -168,7 +168,7 @@ static inline void volk_gnsssdr_32f_fast_resamplerxnpuppet_32f_u_sse4_1(float* r
#ifdef LV_HAVE_SSE4_1 #ifdef LV_HAVE_SSE4_1
static inline void volk_gnsssdr_32f_fast_resamplerxnpuppet_32f_a_sse4_1(float* result, const float* local_code, unsigned int num_points) static inline void volk_gnsssdr_32f_high_dynamics_resamplerxnpuppet_32f_a_sse4_1(float* result, const float* local_code, unsigned int num_points)
{ {
int code_length_chips = 2046; int code_length_chips = 2046;
float code_phase_step_chips = ((float)(code_length_chips) + 0.1) / ((float)num_points); float code_phase_step_chips = ((float)(code_length_chips) + 0.1) / ((float)num_points);
@ -184,7 +184,7 @@ static inline void volk_gnsssdr_32f_fast_resamplerxnpuppet_32f_a_sse4_1(float* r
result_aux[n] = (float*)volk_gnsssdr_malloc(sizeof(float) * num_points, volk_gnsssdr_get_alignment()); result_aux[n] = (float*)volk_gnsssdr_malloc(sizeof(float) * num_points, volk_gnsssdr_get_alignment());
} }
volk_gnsssdr_32f_xn_fast_resampler_32f_xn_a_sse4_1(result_aux, local_code, rem_code_phase_chips, code_phase_step_chips, code_phase_rate_step_chips, shifts_chips, code_length_chips, num_out_vectors, num_points); volk_gnsssdr_32f_xn_high_dynamics_resampler_32f_xn_a_sse4_1(result_aux, local_code, rem_code_phase_chips, code_phase_step_chips, code_phase_rate_step_chips, shifts_chips, code_length_chips, num_out_vectors, num_points);
memcpy((float*)result, (float*)result_aux[0], sizeof(float) * num_points); memcpy((float*)result, (float*)result_aux[0], sizeof(float) * num_points);
@ -199,7 +199,7 @@ static inline void volk_gnsssdr_32f_fast_resamplerxnpuppet_32f_a_sse4_1(float* r
#ifdef LV_HAVE_AVX #ifdef LV_HAVE_AVX
static inline void volk_gnsssdr_32f_fast_resamplerxnpuppet_32f_a_avx(float* result, const float* local_code, unsigned int num_points) static inline void volk_gnsssdr_32f_high_dynamics_resamplerxnpuppet_32f_a_avx(float* result, const float* local_code, unsigned int num_points)
{ {
int code_length_chips = 2046; int code_length_chips = 2046;
float code_phase_step_chips = ((float)(code_length_chips) + 0.1) / ((float)num_points); float code_phase_step_chips = ((float)(code_length_chips) + 0.1) / ((float)num_points);
@ -215,7 +215,7 @@ static inline void volk_gnsssdr_32f_fast_resamplerxnpuppet_32f_a_avx(float* resu
result_aux[n] = (float*)volk_gnsssdr_malloc(sizeof(float) * num_points, volk_gnsssdr_get_alignment()); result_aux[n] = (float*)volk_gnsssdr_malloc(sizeof(float) * num_points, volk_gnsssdr_get_alignment());
} }
volk_gnsssdr_32f_xn_fast_resampler_32f_xn_a_avx(result_aux, local_code, rem_code_phase_chips, code_phase_step_chips, code_phase_rate_step_chips, shifts_chips, code_length_chips, num_out_vectors, num_points); volk_gnsssdr_32f_xn_high_dynamics_resampler_32f_xn_a_avx(result_aux, local_code, rem_code_phase_chips, code_phase_step_chips, code_phase_rate_step_chips, shifts_chips, code_length_chips, num_out_vectors, num_points);
memcpy((float*)result, (float*)result_aux[0], sizeof(float) * num_points); memcpy((float*)result, (float*)result_aux[0], sizeof(float) * num_points);
@ -229,7 +229,7 @@ static inline void volk_gnsssdr_32f_fast_resamplerxnpuppet_32f_a_avx(float* resu
#ifdef LV_HAVE_AVX #ifdef LV_HAVE_AVX
static inline void volk_gnsssdr_32f_fast_resamplerxnpuppet_32f_u_avx(float* result, const float* local_code, unsigned int num_points) static inline void volk_gnsssdr_32f_high_dynamics_resamplerxnpuppet_32f_u_avx(float* result, const float* local_code, unsigned int num_points)
{ {
int code_length_chips = 2046; int code_length_chips = 2046;
float code_phase_step_chips = ((float)(code_length_chips) + 0.1) / ((float)num_points); float code_phase_step_chips = ((float)(code_length_chips) + 0.1) / ((float)num_points);
@ -245,7 +245,7 @@ static inline void volk_gnsssdr_32f_fast_resamplerxnpuppet_32f_u_avx(float* resu
result_aux[n] = (float*)volk_gnsssdr_malloc(sizeof(float) * num_points, volk_gnsssdr_get_alignment()); result_aux[n] = (float*)volk_gnsssdr_malloc(sizeof(float) * num_points, volk_gnsssdr_get_alignment());
} }
volk_gnsssdr_32f_xn_fast_resampler_32f_xn_u_avx(result_aux, local_code, rem_code_phase_chips, code_phase_step_chips, code_phase_rate_step_chips, shifts_chips, code_length_chips, num_out_vectors, num_points); volk_gnsssdr_32f_xn_high_dynamics_resampler_32f_xn_u_avx(result_aux, local_code, rem_code_phase_chips, code_phase_step_chips, code_phase_rate_step_chips, shifts_chips, code_length_chips, num_out_vectors, num_points);
memcpy((float*)result, (float*)result_aux[0], sizeof(float) * num_points); memcpy((float*)result, (float*)result_aux[0], sizeof(float) * num_points);
@ -285,4 +285,4 @@ static inline void volk_gnsssdr_32f_fast_resamplerxnpuppet_32f_u_avx(float* resu
//} //}
//#endif //#endif
#endif // INCLUDED_volk_gnsssdr_32f_fast_resamplerpuppet_32f_H #endif // INCLUDED_volk_gnsssdr_32f_high_dynamics_resamplerpuppet_32f_H

View File

@ -1,5 +1,5 @@
/*! /*!
* \file volk_gnsssdr_32f_xn_fast_resampler_32f_xn.h * \file volk_gnsssdr_32f_xn_high_dynamics_resampler_32f_xn.h
* \brief VOLK_GNSSSDR kernel: Resamples 1 complex 32-bit float vectors using zero hold resample algorithm * \brief VOLK_GNSSSDR kernel: Resamples 1 complex 32-bit float vectors using zero hold resample algorithm
* and produces the delayed replicas by copying and rotating the resulting resampled signal. * and produces the delayed replicas by copying and rotating the resulting resampled signal.
* \authors <ul> * \authors <ul>
@ -38,7 +38,7 @@
*/ */
/*! /*!
* \page volk_gnsssdr_32f_xn_fast_resampler_32f_xn * \page volk_gnsssdr_32f_xn_high_dynamics_resampler_32f_xn
* *
* \b Overview * \b Overview
* *
@ -46,7 +46,7 @@
* *
* <b>Dispatcher Prototype</b> * <b>Dispatcher Prototype</b>
* \code * \code
* void volk_gnsssdr_32f_xn_fast_resampler_32f_xn(float** result, const float* local_code, float rem_code_phase_chips, float code_phase_step_chips, float code_phase_rate_step_chips, float* shifts_chips, unsigned int code_length_chips, int num_out_vectors, unsigned int num_points) * void volk_gnsssdr_32f_xn_high_dynamics_resampler_32f_xn(float** result, const float* local_code, float rem_code_phase_chips, float code_phase_step_chips, float code_phase_rate_step_chips, float* shifts_chips, unsigned int code_length_chips, int num_out_vectors, unsigned int num_points)
* \endcode * \endcode
* *
* \b Inputs * \b Inputs
@ -64,8 +64,8 @@
* *
*/ */
#ifndef INCLUDED_volk_gnsssdr_32f_xn_fast_resampler_32f_xn_H #ifndef INCLUDED_volk_gnsssdr_32f_xn_high_dynamics_resampler_32f_xn_H
#define INCLUDED_volk_gnsssdr_32f_xn_fast_resampler_32f_xn_H #define INCLUDED_volk_gnsssdr_32f_xn_high_dynamics_resampler_32f_xn_H
#include <assert.h> #include <assert.h>
#include <math.h> #include <math.h>
@ -78,7 +78,7 @@
#ifdef LV_HAVE_GENERIC #ifdef LV_HAVE_GENERIC
static inline void volk_gnsssdr_32f_xn_fast_resampler_32f_xn_generic(float** result, const float* local_code, float rem_code_phase_chips, float code_phase_step_chips, float code_phase_rate_step_chips, float* shifts_chips, unsigned int code_length_chips, int num_out_vectors, unsigned int num_points) static inline void volk_gnsssdr_32f_xn_high_dynamics_resampler_32f_xn_generic(float** result, const float* local_code, float rem_code_phase_chips, float code_phase_step_chips, float code_phase_rate_step_chips, float* shifts_chips, unsigned int code_length_chips, int num_out_vectors, unsigned int num_points)
{ {
int local_code_chip_index; int local_code_chip_index;
int current_correlator_tap; int current_correlator_tap;
@ -109,7 +109,7 @@ static inline void volk_gnsssdr_32f_xn_fast_resampler_32f_xn_generic(float** res
#ifdef LV_HAVE_SSE3 #ifdef LV_HAVE_SSE3
#include <pmmintrin.h> #include <pmmintrin.h>
static inline void volk_gnsssdr_32f_xn_fast_resampler_32f_xn_a_sse3(float** result, const float* local_code, float rem_code_phase_chips, float code_phase_step_chips, float code_phase_rate_step_chips, float* shifts_chips, unsigned int code_length_chips, int num_out_vectors, unsigned int num_points) static inline void volk_gnsssdr_32f_xn_high_dynamics_resampler_32f_xn_a_sse3(float** result, const float* local_code, float rem_code_phase_chips, float code_phase_step_chips, float code_phase_rate_step_chips, float* shifts_chips, unsigned int code_length_chips, int num_out_vectors, unsigned int num_points)
{ {
float** _result = result; float** _result = result;
const unsigned int quarterPoints = num_points / 4; const unsigned int quarterPoints = num_points / 4;
@ -194,7 +194,7 @@ static inline void volk_gnsssdr_32f_xn_fast_resampler_32f_xn_a_sse3(float** resu
#ifdef LV_HAVE_SSE3 #ifdef LV_HAVE_SSE3
#include <pmmintrin.h> #include <pmmintrin.h>
static inline void volk_gnsssdr_32f_xn_fast_resampler_32f_xn_u_sse3(float** result, const float* local_code, float rem_code_phase_chips, float code_phase_step_chips, float code_phase_rate_step_chips, float* shifts_chips, unsigned int code_length_chips, int num_out_vectors, unsigned int num_points) static inline void volk_gnsssdr_32f_xn_high_dynamics_resampler_32f_xn_u_sse3(float** result, const float* local_code, float rem_code_phase_chips, float code_phase_step_chips, float code_phase_rate_step_chips, float* shifts_chips, unsigned int code_length_chips, int num_out_vectors, unsigned int num_points)
{ {
float** _result = result; float** _result = result;
const unsigned int quarterPoints = num_points / 4; const unsigned int quarterPoints = num_points / 4;
@ -280,7 +280,7 @@ static inline void volk_gnsssdr_32f_xn_fast_resampler_32f_xn_u_sse3(float** resu
#ifdef LV_HAVE_SSE4_1 #ifdef LV_HAVE_SSE4_1
#include <smmintrin.h> #include <smmintrin.h>
static inline void volk_gnsssdr_32f_xn_fast_resampler_32f_xn_a_sse4_1(float** result, const float* local_code, float rem_code_phase_chips, float code_phase_step_chips, float code_phase_rate_step_chips, float* shifts_chips, unsigned int code_length_chips, int num_out_vectors, unsigned int num_points) static inline void volk_gnsssdr_32f_xn_high_dynamics_resampler_32f_xn_a_sse4_1(float** result, const float* local_code, float rem_code_phase_chips, float code_phase_step_chips, float code_phase_rate_step_chips, float* shifts_chips, unsigned int code_length_chips, int num_out_vectors, unsigned int num_points)
{ {
float** _result = result; float** _result = result;
const unsigned int quarterPoints = num_points / 4; const unsigned int quarterPoints = num_points / 4;
@ -362,7 +362,7 @@ static inline void volk_gnsssdr_32f_xn_fast_resampler_32f_xn_a_sse4_1(float** re
#ifdef LV_HAVE_SSE4_1 #ifdef LV_HAVE_SSE4_1
#include <smmintrin.h> #include <smmintrin.h>
static inline void volk_gnsssdr_32f_xn_fast_resampler_32f_xn_u_sse4_1(float** result, const float* local_code, float rem_code_phase_chips, float code_phase_step_chips, float code_phase_rate_step_chips, float* shifts_chips, unsigned int code_length_chips, int num_out_vectors, unsigned int num_points) static inline void volk_gnsssdr_32f_xn_high_dynamics_resampler_32f_xn_u_sse4_1(float** result, const float* local_code, float rem_code_phase_chips, float code_phase_step_chips, float code_phase_rate_step_chips, float* shifts_chips, unsigned int code_length_chips, int num_out_vectors, unsigned int num_points)
{ {
float** _result = result; float** _result = result;
const unsigned int quarterPoints = num_points / 4; const unsigned int quarterPoints = num_points / 4;
@ -444,7 +444,7 @@ static inline void volk_gnsssdr_32f_xn_fast_resampler_32f_xn_u_sse4_1(float** re
#ifdef LV_HAVE_AVX #ifdef LV_HAVE_AVX
#include <immintrin.h> #include <immintrin.h>
static inline void volk_gnsssdr_32f_xn_fast_resampler_32f_xn_a_avx(float** result, const float* local_code, float rem_code_phase_chips, float code_phase_step_chips, float code_phase_rate_step_chips, float* shifts_chips, unsigned int code_length_chips, int num_out_vectors, unsigned int num_points) static inline void volk_gnsssdr_32f_xn_high_dynamics_resampler_32f_xn_a_avx(float** result, const float* local_code, float rem_code_phase_chips, float code_phase_step_chips, float code_phase_rate_step_chips, float* shifts_chips, unsigned int code_length_chips, int num_out_vectors, unsigned int num_points)
{ {
float** _result = result; float** _result = result;
const unsigned int avx_iters = num_points / 8; const unsigned int avx_iters = num_points / 8;
@ -532,7 +532,7 @@ static inline void volk_gnsssdr_32f_xn_fast_resampler_32f_xn_a_avx(float** resul
#ifdef LV_HAVE_AVX #ifdef LV_HAVE_AVX
#include <immintrin.h> #include <immintrin.h>
static inline void volk_gnsssdr_32f_xn_fast_resampler_32f_xn_u_avx(float** result, const float* local_code, float rem_code_phase_chips, float code_phase_step_chips, float code_phase_rate_step_chips, float* shifts_chips, unsigned int code_length_chips, int num_out_vectors, unsigned int num_points) static inline void volk_gnsssdr_32f_xn_high_dynamics_resampler_32f_xn_u_avx(float** result, const float* local_code, float rem_code_phase_chips, float code_phase_step_chips, float code_phase_rate_step_chips, float* shifts_chips, unsigned int code_length_chips, int num_out_vectors, unsigned int num_points)
{ {
float** _result = result; float** _result = result;
const unsigned int avx_iters = num_points / 8; const unsigned int avx_iters = num_points / 8;
@ -621,7 +621,7 @@ static inline void volk_gnsssdr_32f_xn_fast_resampler_32f_xn_u_avx(float** resul
//#ifdef LV_HAVE_NEONV7 //#ifdef LV_HAVE_NEONV7
//#include <arm_neon.h> //#include <arm_neon.h>
// //
//static inline void volk_gnsssdr_32f_xn_fast_resampler_32f_xn_neon(float** result, const float* local_code, float rem_code_phase_chips, float code_phase_step_chips, float* shifts_chips, unsigned int code_length_chips, int num_out_vectors, unsigned int num_points) //static inline void volk_gnsssdr_32f_xn_high_dynamics_resampler_32f_xn_neon(float** result, const float* local_code, float rem_code_phase_chips, float code_phase_step_chips, float* shifts_chips, unsigned int code_length_chips, int num_out_vectors, unsigned int num_points)
//{ //{
// float** _result = result; // float** _result = result;
// const unsigned int neon_iters = num_points / 4; // const unsigned int neon_iters = num_points / 4;
@ -704,4 +704,4 @@ static inline void volk_gnsssdr_32f_xn_fast_resampler_32f_xn_u_avx(float** resul
// //
//#endif //#endif
#endif /*INCLUDED_volk_gnsssdr_32f_xn_fast_resampler_32f_xn_H*/ #endif /*INCLUDED_volk_gnsssdr_32f_xn_high_dynamics_resampler_32f_xn_H*/

View File

@ -93,7 +93,7 @@ std::vector<volk_gnsssdr_test_case_t> init_test_list(volk_gnsssdr_test_params_t
QA(VOLK_INIT_PUPP(volk_gnsssdr_16i_resamplerxnpuppet_16i, volk_gnsssdr_16i_xn_resampler_16i_xn, test_params)) QA(VOLK_INIT_PUPP(volk_gnsssdr_16i_resamplerxnpuppet_16i, volk_gnsssdr_16i_xn_resampler_16i_xn, test_params))
QA(VOLK_INIT_PUPP(volk_gnsssdr_32fc_resamplerxnpuppet_32fc, volk_gnsssdr_32fc_xn_resampler_32fc_xn, test_params)) QA(VOLK_INIT_PUPP(volk_gnsssdr_32fc_resamplerxnpuppet_32fc, volk_gnsssdr_32fc_xn_resampler_32fc_xn, test_params))
QA(VOLK_INIT_PUPP(volk_gnsssdr_32f_resamplerxnpuppet_32f, volk_gnsssdr_32f_xn_resampler_32f_xn, test_params)) QA(VOLK_INIT_PUPP(volk_gnsssdr_32f_resamplerxnpuppet_32f, volk_gnsssdr_32f_xn_resampler_32f_xn, test_params))
QA(VOLK_INIT_PUPP(volk_gnsssdr_32f_fast_resamplerxnpuppet_32f, volk_gnsssdr_32f_xn_fast_resampler_32f_xn, test_params)) QA(VOLK_INIT_PUPP(volk_gnsssdr_32f_high_dynamics_resamplerxnpuppet_32f, volk_gnsssdr_32f_xn_high_dynamics_resampler_32f_xn, test_params))
QA(VOLK_INIT_PUPP(volk_gnsssdr_16ic_x2_dotprodxnpuppet_16ic, volk_gnsssdr_16ic_x2_dot_prod_16ic_xn, test_params)) QA(VOLK_INIT_PUPP(volk_gnsssdr_16ic_x2_dotprodxnpuppet_16ic, volk_gnsssdr_16ic_x2_dot_prod_16ic_xn, test_params))
QA(VOLK_INIT_PUPP(volk_gnsssdr_16ic_x2_rotator_dotprodxnpuppet_16ic, volk_gnsssdr_16ic_x2_rotator_dot_prod_16ic_xn, test_params_int16)) QA(VOLK_INIT_PUPP(volk_gnsssdr_16ic_x2_rotator_dotprodxnpuppet_16ic, volk_gnsssdr_16ic_x2_rotator_dot_prod_16ic_xn, test_params_int16))
QA(VOLK_INIT_PUPP(volk_gnsssdr_16ic_16i_rotator_dotprodxnpuppet_16ic, volk_gnsssdr_16ic_16i_rotator_dot_prod_16ic_xn, test_params_int16)) QA(VOLK_INIT_PUPP(volk_gnsssdr_16ic_16i_rotator_dotprodxnpuppet_16ic, volk_gnsssdr_16ic_16i_rotator_dot_prod_16ic_xn, test_params_int16))

View File

@ -55,7 +55,7 @@ GalileoE1BTelemetryDecoder::GalileoE1BTelemetryDecoder(ConfigurationInterface* c
dump_ = configuration->property(role + ".dump", false); dump_ = configuration->property(role + ".dump", false);
dump_filename_ = configuration->property(role + ".dump_filename", default_dump_filename); dump_filename_ = configuration->property(role + ".dump_filename", default_dump_filename);
// make telemetry decoder object // make telemetry decoder object
telemetry_decoder_ = galileo_e1b_make_telemetry_decoder_cc(satellite_, dump_); // TODO fix me telemetry_decoder_ = galileo_make_telemetry_decoder_cc(satellite_, 1, dump_); //unified galileo decoder set to INAV (frame_type=1)
DLOG(INFO) << "telemetry_decoder(" << telemetry_decoder_->unique_id() << ")"; DLOG(INFO) << "telemetry_decoder(" << telemetry_decoder_->unique_id() << ")";
channel_ = 0; channel_ = 0;
if (in_streams_ > 1) if (in_streams_ > 1)

View File

@ -36,7 +36,7 @@
#include "telemetry_decoder_interface.h" #include "telemetry_decoder_interface.h"
#include "galileo_e1b_telemetry_decoder_cc.h" #include "galileo_telemetry_decoder_cc.h"
#include "gnss_satellite.h" #include "gnss_satellite.h"
#include <string> #include <string>
@ -76,7 +76,6 @@ public:
void set_satellite(const Gnss_Satellite& satellite) override; void set_satellite(const Gnss_Satellite& satellite) override;
inline void set_channel(int channel) override { telemetry_decoder_->set_channel(channel); } inline void set_channel(int channel) override { telemetry_decoder_->set_channel(channel); }
inline void reset() override inline void reset() override
{ {
return; return;
@ -88,7 +87,7 @@ public:
} }
private: private:
galileo_e1b_telemetry_decoder_cc_sptr telemetry_decoder_; galileo_telemetry_decoder_cc_sptr telemetry_decoder_;
Gnss_Satellite satellite_; Gnss_Satellite satellite_;
int channel_; int channel_;
bool dump_; bool dump_;

View File

@ -58,7 +58,7 @@ GalileoE5aTelemetryDecoder::GalileoE5aTelemetryDecoder(ConfigurationInterface* c
dump_ = configuration->property(role + ".dump", false); dump_ = configuration->property(role + ".dump", false);
dump_filename_ = configuration->property(role + ".dump_filename", default_dump_filename); dump_filename_ = configuration->property(role + ".dump_filename", default_dump_filename);
// make telemetry decoder object // make telemetry decoder object
telemetry_decoder_ = galileo_e5a_make_telemetry_decoder_cc(satellite_, dump_); // TODO fix me telemetry_decoder_ = galileo_make_telemetry_decoder_cc(satellite_, 2, dump_); //unified galileo decoder set to FNAV (frame_type=2)
DLOG(INFO) << "telemetry_decoder(" << telemetry_decoder_->unique_id() << ")"; DLOG(INFO) << "telemetry_decoder(" << telemetry_decoder_->unique_id() << ")";
channel_ = 0; channel_ = 0;
if (in_streams_ > 1) if (in_streams_ > 1)

View File

@ -37,7 +37,7 @@
#ifndef GNSS_SDR_GALILEO_E5A_TELEMETRY_DECODER_H_ #ifndef GNSS_SDR_GALILEO_E5A_TELEMETRY_DECODER_H_
#define GNSS_SDR_GALILEO_E5A_TELEMETRY_DECODER_H_ #define GNSS_SDR_GALILEO_E5A_TELEMETRY_DECODER_H_
#include "galileo_e5a_telemetry_decoder_cc.h" #include "galileo_telemetry_decoder_cc.h"
#include "telemetry_decoder_interface.h" #include "telemetry_decoder_interface.h"
#include <string> #include <string>
@ -76,7 +76,6 @@ public:
void set_satellite(const Gnss_Satellite& satellite) override; void set_satellite(const Gnss_Satellite& satellite) override;
inline void set_channel(int channel) override { telemetry_decoder_->set_channel(channel); } inline void set_channel(int channel) override { telemetry_decoder_->set_channel(channel); }
inline void reset() override inline void reset() override
{ {
return; return;
@ -88,7 +87,7 @@ public:
} }
private: private:
galileo_e5a_telemetry_decoder_cc_sptr telemetry_decoder_; galileo_telemetry_decoder_cc_sptr telemetry_decoder_;
Gnss_Satellite satellite_; Gnss_Satellite satellite_;
int channel_; int channel_;
bool dump_; bool dump_;

View File

@ -20,11 +20,10 @@ set(TELEMETRY_DECODER_GR_BLOCKS_SOURCES
gps_l1_ca_telemetry_decoder_cc.cc gps_l1_ca_telemetry_decoder_cc.cc
gps_l2c_telemetry_decoder_cc.cc gps_l2c_telemetry_decoder_cc.cc
gps_l5_telemetry_decoder_cc.cc gps_l5_telemetry_decoder_cc.cc
galileo_e1b_telemetry_decoder_cc.cc
sbas_l1_telemetry_decoder_cc.cc sbas_l1_telemetry_decoder_cc.cc
galileo_e5a_telemetry_decoder_cc.cc
glonass_l1_ca_telemetry_decoder_cc.cc glonass_l1_ca_telemetry_decoder_cc.cc
glonass_l2_ca_telemetry_decoder_cc.cc glonass_l2_ca_telemetry_decoder_cc.cc
galileo_telemetry_decoder_cc.cc
) )
include_directories( include_directories(

View File

@ -1,501 +0,0 @@
/*!
* \file galileo_e1b_telemetry_decoder_cc.cc
* \brief Implementation of a Galileo INAV message demodulator block
* \author Mara Branzanti 2013. mara.branzanti(at)gmail.com
* \author Javier Arribas 2013. 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 <https://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "galileo_e1b_telemetry_decoder_cc.h"
#include "control_message_factory.h"
#include "convolutional.h"
#include "gnss_synchro.h"
#include <boost/lexical_cast.hpp>
#include <gnuradio/io_signature.h>
#include <glog/logging.h>
#include <volk_gnsssdr/volk_gnsssdr.h>
#include <iostream>
#define CRC_ERROR_LIMIT 6
using google::LogMessage;
galileo_e1b_telemetry_decoder_cc_sptr
galileo_e1b_make_telemetry_decoder_cc(const Gnss_Satellite &satellite, bool dump)
{
return galileo_e1b_telemetry_decoder_cc_sptr(new galileo_e1b_telemetry_decoder_cc(satellite, dump));
}
void galileo_e1b_telemetry_decoder_cc::viterbi_decoder(double *page_part_symbols, int32_t *page_part_bits)
{
Viterbi(page_part_bits, out0, state0, out1, state1,
page_part_symbols, KK, nn, DataLength);
}
void galileo_e1b_telemetry_decoder_cc::deinterleaver(int32_t rows, int32_t cols, double *in, double *out)
{
for (int32_t r = 0; r < rows; r++)
{
for (int32_t c = 0; c < cols; c++)
{
out[c * rows + r] = in[r * cols + c];
}
}
}
galileo_e1b_telemetry_decoder_cc::galileo_e1b_telemetry_decoder_cc(
const Gnss_Satellite &satellite,
bool dump) : gr::block("galileo_e1b_telemetry_decoder_cc", gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)),
gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)))
{
// Ephemeris data port out
this->message_port_register_out(pmt::mp("telemetry"));
// initialize internal vars
d_dump = dump;
d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN());
LOG(INFO) << "Initializing GALILEO E1B TELEMETRY PROCESSING";
d_samples_per_symbol = (Galileo_E1_CODE_CHIP_RATE_HZ / Galileo_E1_B_CODE_LENGTH_CHIPS) / Galileo_E1_B_SYMBOL_RATE_BPS;
// set the preamble
uint16_t preambles_bits[GALILEO_INAV_PREAMBLE_LENGTH_BITS] = GALILEO_INAV_PREAMBLE;
d_symbols_per_preamble = GALILEO_INAV_PREAMBLE_LENGTH_BITS * d_samples_per_symbol;
memcpy(static_cast<uint16_t *>(this->d_preambles_bits), static_cast<uint16_t *>(preambles_bits), GALILEO_INAV_PREAMBLE_LENGTH_BITS * sizeof(uint16_t));
// preamble bits to sampled symbols
d_preambles_symbols = static_cast<int32_t *>(volk_gnsssdr_malloc(d_symbols_per_preamble * sizeof(int32_t), volk_gnsssdr_get_alignment()));
int32_t n = 0;
for (int32_t i = 0; i < GALILEO_INAV_PREAMBLE_LENGTH_BITS; i++)
{
for (uint32_t j = 0; j < d_samples_per_symbol; j++)
{
if (d_preambles_bits[i] == 1)
{
d_preambles_symbols[n] = 1;
}
else
{
d_preambles_symbols[n] = -1;
}
n++;
}
}
d_sample_counter = 0ULL;
d_stat = 0;
d_preamble_index = 0ULL;
d_flag_frame_sync = false;
d_flag_parity = false;
d_TOW_at_current_symbol_ms = 0;
d_TOW_at_Preamble_ms = 0;
delta_t = 0;
d_CRC_error_counter = 0;
flag_even_word_arrived = 0;
d_flag_preamble = false;
d_channel = 0;
flag_TOW_set = false;
// vars for Viterbi decoder
int32_t max_states = 1 << mm; // 2^mm
g_encoder[0] = 121; // Polynomial G1
g_encoder[1] = 91; // Polynomial G2
out0 = static_cast<int32_t *>(volk_gnsssdr_malloc(max_states * sizeof(int32_t), volk_gnsssdr_get_alignment()));
out1 = static_cast<int32_t *>(volk_gnsssdr_malloc(max_states * sizeof(int32_t), volk_gnsssdr_get_alignment()));
state0 = static_cast<int32_t *>(volk_gnsssdr_malloc(max_states * sizeof(int32_t), volk_gnsssdr_get_alignment()));
state1 = static_cast<int32_t *>(volk_gnsssdr_malloc(max_states * sizeof(int32_t), volk_gnsssdr_get_alignment()));
// create appropriate transition matrices
nsc_transit(out0, state0, 0, g_encoder, KK, nn);
nsc_transit(out1, state1, 1, g_encoder, KK, nn);
}
galileo_e1b_telemetry_decoder_cc::~galileo_e1b_telemetry_decoder_cc()
{
volk_gnsssdr_free(d_preambles_symbols);
volk_gnsssdr_free(out0);
volk_gnsssdr_free(out1);
volk_gnsssdr_free(state0);
volk_gnsssdr_free(state1);
if (d_dump_file.is_open() == true)
{
try
{
d_dump_file.close();
}
catch (const std::exception &ex)
{
LOG(WARNING) << "Exception in destructor closing the dump file " << ex.what();
}
}
}
void galileo_e1b_telemetry_decoder_cc::decode_word(double *page_part_symbols, int32_t frame_length)
{
// 1. De-interleave
double *page_part_symbols_deint = static_cast<double *>(volk_gnsssdr_malloc(frame_length * sizeof(double), volk_gnsssdr_get_alignment()));
deinterleaver(GALILEO_INAV_INTERLEAVER_ROWS, GALILEO_INAV_INTERLEAVER_COLS, page_part_symbols, page_part_symbols_deint);
// 2. Viterbi decoder
// 2.1 Take into account the NOT gate in G2 polynomial (Galileo ICD Figure 13, FEC encoder)
// 2.2 Take into account the possible inversion of the polarity due to PLL lock at 180º
for (int32_t i = 0; i < frame_length; i++)
{
if ((i + 1) % 2 == 0)
{
page_part_symbols_deint[i] = -page_part_symbols_deint[i];
}
}
int32_t *page_part_bits = static_cast<int32_t *>(volk_gnsssdr_malloc((frame_length / 2) * sizeof(int32_t), volk_gnsssdr_get_alignment()));
viterbi_decoder(page_part_symbols_deint, page_part_bits);
volk_gnsssdr_free(page_part_symbols_deint);
// 3. Call the Galileo page decoder
std::string page_String;
for (int32_t i = 0; i < (frame_length / 2); i++)
{
if (page_part_bits[i] > 0)
{
page_String.push_back('1');
}
else
{
page_String.push_back('0');
}
}
if (page_part_bits[0] == 1)
{
// DECODE COMPLETE WORD (even + odd) and TEST CRC
d_nav.split_page(page_String, flag_even_word_arrived);
if (d_nav.flag_CRC_test == true)
{
LOG(INFO) << "Galileo E1 CRC correct in channel " << d_channel << " from satellite " << d_satellite;
//std::cout << "Galileo E1 CRC correct on channel " << d_channel << " from satellite " << d_satellite << std::endl;
}
else
{
std::cout << "Galileo E1 CRC error in channel " << d_channel << " from satellite " << d_satellite << std::endl;
LOG(INFO) << "Galileo E1 CRC error in channel " << d_channel << " from satellite " << d_satellite;
}
flag_even_word_arrived = 0;
}
else
{
// STORE HALF WORD (even page)
d_nav.split_page(page_String.c_str(), flag_even_word_arrived);
flag_even_word_arrived = 1;
}
volk_gnsssdr_free(page_part_bits);
// 4. Push the new navigation data to the queues
if (d_nav.have_new_ephemeris() == true)
{
// get object for this SV (mandatory)
std::shared_ptr<Galileo_Ephemeris> tmp_obj = std::make_shared<Galileo_Ephemeris>(d_nav.get_ephemeris());
std::cout << "New Galileo E1 I/NAV message received in channel " << d_channel << ": ephemeris from satellite " << d_satellite << std::endl;
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
}
if (d_nav.have_new_iono_and_GST() == true)
{
// get object for this SV (mandatory)
std::shared_ptr<Galileo_Iono> tmp_obj = std::make_shared<Galileo_Iono>(d_nav.get_iono());
std::cout << "New Galileo E1 I/NAV message received in channel " << d_channel << ": iono/GST model parameters from satellite " << d_satellite << std::endl;
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
}
if (d_nav.have_new_utc_model() == true)
{
// get object for this SV (mandatory)
std::shared_ptr<Galileo_Utc_Model> tmp_obj = std::make_shared<Galileo_Utc_Model>(d_nav.get_utc_model());
std::cout << "New Galileo E1 I/NAV message received in channel " << d_channel << ": UTC model parameters from satellite " << d_satellite << std::endl;
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
}
if (d_nav.have_new_almanac() == true)
{
std::shared_ptr<Galileo_Almanac> tmp_obj = std::make_shared<Galileo_Almanac>(d_nav.get_almanac());
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
//debug
std::cout << "Galileo E1 I/NAV almanac received in channel " << d_channel << " from satellite " << d_satellite << std::endl;
DLOG(INFO) << "GPS_to_Galileo time conversion:";
DLOG(INFO) << "A0G=" << tmp_obj->A_0G_10;
DLOG(INFO) << "A1G=" << tmp_obj->A_1G_10;
DLOG(INFO) << "T0G=" << tmp_obj->t_0G_10;
DLOG(INFO) << "WN_0G_10=" << tmp_obj->WN_0G_10;
DLOG(INFO) << "Current parameters:";
DLOG(INFO) << "d_TOW_at_current_symbol_ms=" << d_TOW_at_current_symbol_ms;
DLOG(INFO) << "d_nav.WN_0=" << d_nav.WN_0;
delta_t = tmp_obj->A_0G_10 + tmp_obj->A_1G_10 * (static_cast<double>(d_TOW_at_current_symbol_ms) / 1000.0 - tmp_obj->t_0G_10 + 604800 * (fmod((d_nav.WN_0 - tmp_obj->WN_0G_10), 64)));
DLOG(INFO) << "delta_t=" << delta_t << "[s]";
}
}
void galileo_e1b_telemetry_decoder_cc::set_satellite(const Gnss_Satellite &satellite)
{
d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN());
DLOG(INFO) << "Setting decoder Finite State Machine to satellite " << d_satellite;
DLOG(INFO) << "Navigation Satellite set to " << d_satellite;
}
void galileo_e1b_telemetry_decoder_cc::set_channel(int32_t channel)
{
d_channel = channel;
LOG(INFO) << "Navigation channel set to " << channel;
// ############# ENABLE DATA FILE LOG #################
if (d_dump == true)
{
if (d_dump_file.is_open() == false)
{
try
{
d_dump_filename = "telemetry";
d_dump_filename.append(boost::lexical_cast<std::string>(d_channel));
d_dump_filename.append(".dat");
d_dump_file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
d_dump_file.open(d_dump_filename.c_str(), std::ios::out | std::ios::binary);
LOG(INFO) << "Telemetry decoder dump enabled on channel " << d_channel << " Log file: " << d_dump_filename.c_str();
}
catch (const std::ifstream::failure &e)
{
LOG(WARNING) << "channel " << d_channel << " Exception opening trk dump file " << e.what();
}
}
}
}
int galileo_e1b_telemetry_decoder_cc::general_work(int noutput_items __attribute__((unused)), gr_vector_int &ninput_items __attribute__((unused)),
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items)
{
int32_t corr_value = 0;
int32_t preamble_diff = 0;
Gnss_Synchro **out = reinterpret_cast<Gnss_Synchro **>(&output_items[0]); // Get the output buffer pointer
const Gnss_Synchro **in = reinterpret_cast<const Gnss_Synchro **>(&input_items[0]); // Get the input buffer pointer
Gnss_Synchro current_symbol; // structure to save the synchronization information and send the output object to the next block
// 1. Copy the current tracking output
current_symbol = in[0][0];
d_symbol_history.push_back(current_symbol); // add new symbol to the symbol queue
d_sample_counter++; // count for the processed samples
consume_each(1);
d_flag_preamble = false;
uint32_t required_symbols = static_cast<uint32_t>(GALILEO_INAV_PAGE_SYMBOLS) + static_cast<uint32_t>(d_symbols_per_preamble);
if (d_symbol_history.size() > required_symbols)
{
// TODO Optimize me!
// ******* preamble correlation ********
for (int32_t i = 0; i < d_symbols_per_preamble; i++)
{
if (d_symbol_history.at(i).Prompt_I < 0) // symbols clipping
{
corr_value -= d_preambles_symbols[i];
}
else
{
corr_value += d_preambles_symbols[i];
}
}
}
// ******* frame sync ******************
if (d_stat == 0) // no preamble information
{
if (abs(corr_value) >= d_symbols_per_preamble)
{
d_preamble_index = d_sample_counter; // record the preamble sample stamp
LOG(INFO) << "Preamble detection for Galileo satellite " << this->d_satellite;
d_stat = 1; // enter into frame pre-detection status
}
}
else if (d_stat == 1) // possible preamble lock
{
if (abs(corr_value) >= d_symbols_per_preamble)
{
// check preamble separation
preamble_diff = static_cast<int32_t>(d_sample_counter - d_preamble_index);
if (abs(preamble_diff - GALILEO_INAV_PREAMBLE_PERIOD_SYMBOLS) == 0)
{
// try to decode frame
LOG(INFO) << "Starting page decoder for Galileo satellite " << this->d_satellite;
d_preamble_index = d_sample_counter; // record the preamble sample stamp
d_stat = 2;
}
else
{
if (preamble_diff > GALILEO_INAV_PREAMBLE_PERIOD_SYMBOLS)
{
d_stat = 0; // start again
}
}
}
}
else if (d_stat == 2)
{
if (d_sample_counter == d_preamble_index + static_cast<uint64_t>(GALILEO_INAV_PREAMBLE_PERIOD_SYMBOLS))
{
// NEW Galileo page part is received
// 0. fetch the symbols into an array
int32_t frame_length = GALILEO_INAV_PAGE_PART_SYMBOLS - d_symbols_per_preamble;
double *page_part_symbols = static_cast<double *>(volk_gnsssdr_malloc(frame_length * sizeof(double), volk_gnsssdr_get_alignment()));
for (int32_t i = 0; i < frame_length; i++)
{
if (corr_value > 0)
{
page_part_symbols[i] = d_symbol_history.at(i + d_symbols_per_preamble).Prompt_I; // because last symbol of the preamble is just received now!
}
else
{
page_part_symbols[i] = -d_symbol_history.at(i + d_symbols_per_preamble).Prompt_I; // because last symbol of the preamble is just received now!
}
}
// call the decoder
decode_word(page_part_symbols, frame_length);
if (d_nav.flag_CRC_test == true)
{
d_CRC_error_counter = 0;
d_flag_preamble = true; // valid preamble indicator (initialized to false every work())
d_preamble_index = d_sample_counter; // record the preamble sample stamp (t_P)
if (!d_flag_frame_sync)
{
d_flag_frame_sync = true;
DLOG(INFO) << " Frame sync SAT " << this->d_satellite << " with preamble start at "
<< d_symbol_history.at(0).Tracking_sample_counter << " [samples]";
}
}
else
{
d_CRC_error_counter++;
d_preamble_index = d_sample_counter; // record the preamble sample stamp
if (d_CRC_error_counter > CRC_ERROR_LIMIT)
{
LOG(INFO) << "Lost of frame sync SAT " << this->d_satellite;
d_flag_frame_sync = false;
d_stat = 0;
d_TOW_at_current_symbol_ms = 0;
d_TOW_at_Preamble_ms = 0;
d_nav.flag_TOW_set = false;
}
}
volk_gnsssdr_free(page_part_symbols);
}
}
// UPDATE GNSS SYNCHRO DATA
// 2. Add the telemetry decoder information
if (this->d_flag_preamble == true and d_nav.flag_TOW_set == true)
// update TOW at the preamble instant
{
if (d_nav.flag_TOW_5 == true) // page 5 arrived and decoded, so we are in the odd page (since Tow refers to the even page, we have to add 1 sec)
{
// TOW_5 refers to the even preamble, but when we decode it we are in the odd part, so 1 second later plus the decoding delay
d_TOW_at_Preamble_ms = static_cast<uint32_t>(d_nav.TOW_5 * 1000.0);
d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast<uint32_t>(GALILEO_INAV_PAGE_PART_MS + (required_symbols + 1) * GALILEO_E1_CODE_PERIOD_MS);
d_nav.flag_TOW_5 = false;
}
else if (d_nav.flag_TOW_6 == true) // page 6 arrived and decoded, so we are in the odd page (since Tow refers to the even page, we have to add 1 sec)
{
// TOW_6 refers to the even preamble, but when we decode it we are in the odd part, so 1 second later plus the decoding delay
d_TOW_at_Preamble_ms = static_cast<uint32_t>(d_nav.TOW_6 * 1000.0);
d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast<uint32_t>(GALILEO_INAV_PAGE_PART_MS + (required_symbols + 1) * GALILEO_E1_CODE_PERIOD_MS);
d_nav.flag_TOW_6 = false;
}
else
{
// this page has no timing information
d_TOW_at_current_symbol_ms += static_cast<uint32_t>(GALILEO_E1_CODE_PERIOD_MS); // + GALILEO_INAV_PAGE_PART_SYMBOLS*GALILEO_E1_CODE_PERIOD;
}
}
else // if there is not a new preamble, we define the TOW of the current symbol
{
if (d_nav.flag_TOW_set == true)
{
d_TOW_at_current_symbol_ms += static_cast<uint32_t>(GALILEO_E1_CODE_PERIOD_MS);
}
}
// remove used symbols from history
// todo: Use circular buffer here
if (d_symbol_history.size() > required_symbols)
{
d_symbol_history.pop_front();
}
if (d_nav.flag_TOW_set)
{
if (d_nav.flag_GGTO_1 == true and d_nav.flag_GGTO_2 == true and d_nav.flag_GGTO_3 == true and d_nav.flag_GGTO_4 == true) // all GGTO parameters arrived
{
delta_t = d_nav.A_0G_10 + d_nav.A_1G_10 * (static_cast<double>(d_TOW_at_current_symbol_ms) / 1000.0 - d_nav.t_0G_10 + 604800.0 * (fmod((d_nav.WN_0 - d_nav.WN_0G_10), 64.0)));
}
current_symbol.Flag_valid_word = d_nav.flag_TOW_set;
current_symbol.TOW_at_current_symbol_ms = d_TOW_at_current_symbol_ms;
// todo: Galileo to GPS time conversion should be moved to observable block.
// current_symbol.TOW_at_current_symbol_ms -= delta_t; //Galileo to GPS TOW
if (d_dump == true)
{
// MULTIPLEXED FILE RECORDING - Record results to file
try
{
double tmp_double;
uint64_t tmp_ulong_int;
tmp_double = static_cast<double>(d_TOW_at_current_symbol_ms) / 1000.0;
d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double));
tmp_ulong_int = current_symbol.Tracking_sample_counter;
d_dump_file.write(reinterpret_cast<char *>(&tmp_ulong_int), sizeof(uint64_t));
tmp_double = static_cast<double>(d_TOW_at_Preamble_ms) / 1000.0;
d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double));
}
catch (const std::ifstream::failure &e)
{
LOG(WARNING) << "Exception writing observables dump file " << e.what();
}
}
// 3. Make the output (copy the object contents to the GNURadio reserved memory)
*out[0] = current_symbol;
return 1;
}
else
{
return 0;
}
}

View File

@ -1,513 +0,0 @@
/*!
* \file galileo_e5a_telemetry_decoder_cc.cc
* \brief Implementation of a Galileo FNAV message demodulator block
* \author Marc Sales, 2014. marcsales92(at)gmail.com
* Javier Arribas, 2017. jarribas(at)cttc.es
* \based on work from:
* <ul>
* <li> Javier Arribas, 2011. jarribas(at)cttc.es
* </ul>
*
*
* -------------------------------------------------------------------------
*
* 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 <https://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "galileo_e5a_telemetry_decoder_cc.h"
#include "control_message_factory.h"
#include "convolutional.h"
#include "display.h"
#include <boost/lexical_cast.hpp>
#include <gnuradio/io_signature.h>
#include <glog/logging.h>
#include <volk_gnsssdr/volk_gnsssdr.h>
#include <cmath>
#include <iostream>
#define GALILEO_E5a_CRC_ERROR_LIMIT 6
using google::LogMessage;
galileo_e5a_telemetry_decoder_cc_sptr
galileo_e5a_make_telemetry_decoder_cc(const Gnss_Satellite &satellite, bool dump)
{
return galileo_e5a_telemetry_decoder_cc_sptr(new galileo_e5a_telemetry_decoder_cc(satellite, dump));
}
void galileo_e5a_telemetry_decoder_cc::viterbi_decoder(double *page_part_symbols, int32_t *page_part_bits)
{
Viterbi(page_part_bits, out0, state0, out1, state1,
page_part_symbols, KK, nn, DataLength);
}
void galileo_e5a_telemetry_decoder_cc::deinterleaver(int32_t rows, int32_t cols, double *in, double *out)
{
for (int32_t r = 0; r < rows; r++)
{
for (int32_t c = 0; c < cols; c++)
{
out[c * rows + r] = in[r * cols + c];
}
}
}
void galileo_e5a_telemetry_decoder_cc::decode_word(double *page_symbols, int32_t frame_length)
{
// 1. De-interleave
double *page_symbols_deint = static_cast<double *>(volk_gnsssdr_malloc(frame_length * sizeof(double), volk_gnsssdr_get_alignment()));
deinterleaver(GALILEO_FNAV_INTERLEAVER_ROWS, GALILEO_FNAV_INTERLEAVER_COLS, page_symbols, page_symbols_deint);
// 2. Viterbi decoder
// 2.1 Take into account the NOT gate in G2 polynomial (Galileo ICD Figure 13, FEC encoder)
// 2.2 Take into account the possible inversion of the polarity due to PLL lock at 180<38>
for (int32_t i = 0; i < frame_length; i++)
{
if ((i + 1) % 2 == 0)
{
page_symbols_deint[i] = -page_symbols_deint[i];
}
}
int32_t *page_bits = static_cast<int32_t *>(volk_gnsssdr_malloc((frame_length / 2) * sizeof(int32_t), volk_gnsssdr_get_alignment()));
viterbi_decoder(page_symbols_deint, page_bits);
volk_gnsssdr_free(page_symbols_deint);
// 3. Call the Galileo page decoder
std::string page_String;
for (int32_t i = 0; i < frame_length; i++)
{
if (page_bits[i] > 0)
{
page_String.push_back('1');
}
else
{
page_String.push_back('0');
}
}
volk_gnsssdr_free(page_bits);
// DECODE COMPLETE WORD (even + odd) and TEST CRC
d_nav.split_page(page_String);
if (d_nav.flag_CRC_test == true)
{
LOG(INFO) << "Galileo E5a CRC correct in channel " << d_channel << " from satellite " << d_satellite;
}
else
{
std::cout << "Galileo E5a CRC error in channel " << d_channel << " from satellite " << d_satellite << std::endl;
LOG(INFO) << "Galileo E5a CRC error in channel " << d_channel << " from satellite " << d_satellite;
}
// 4. Push the new navigation data to the queues
if (d_nav.have_new_ephemeris() == true)
{
std::shared_ptr<Galileo_Ephemeris> tmp_obj = std::make_shared<Galileo_Ephemeris>(d_nav.get_ephemeris());
std::cout << TEXT_MAGENTA << "New Galileo E5a F/NAV message received in channel " << d_channel << ": ephemeris from satellite " << d_satellite << TEXT_RESET << std::endl;
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
}
if (d_nav.have_new_iono_and_GST() == true)
{
std::shared_ptr<Galileo_Iono> tmp_obj = std::make_shared<Galileo_Iono>(d_nav.get_iono());
std::cout << TEXT_MAGENTA << "New Galileo E5a F/NAV message received in channel " << d_channel << ": iono/GST model parameters from satellite " << d_satellite << TEXT_RESET << std::endl;
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
}
if (d_nav.have_new_utc_model() == true)
{
std::shared_ptr<Galileo_Utc_Model> tmp_obj = std::make_shared<Galileo_Utc_Model>(d_nav.get_utc_model());
std::cout << TEXT_MAGENTA << "New Galileo E5a F/NAV message received in channel " << d_channel << ": UTC model parameters from satellite " << d_satellite << TEXT_RESET << std::endl;
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
}
}
galileo_e5a_telemetry_decoder_cc::galileo_e5a_telemetry_decoder_cc(
const Gnss_Satellite &satellite, bool dump) : gr::block("galileo_e5a_telemetry_decoder_cc",
gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)),
gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)))
{
// Ephemeris data port out
this->message_port_register_out(pmt::mp("telemetry"));
// initialize internal vars
d_dump = dump;
d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN());
// set the preamble
for (int32_t i = 0; i < GALILEO_FNAV_PREAMBLE_LENGTH_BITS; i++)
{
if (GALILEO_FNAV_PREAMBLE.at(i) == '0')
{
d_preambles_bits[i] = 1;
}
else
{
d_preambles_bits[i] = -1;
}
}
for (int32_t i = 0; i < GALILEO_FNAV_PREAMBLE_LENGTH_BITS; i++)
{
for (int32_t k = 0; k < GALILEO_FNAV_CODES_PER_SYMBOL; k++)
{
d_preamble_samples[(i * GALILEO_FNAV_CODES_PER_SYMBOL) + k] = d_preambles_bits[i];
}
}
d_sample_counter = 0ULL;
d_stat = 0;
corr_value = 0;
d_flag_preamble = false;
d_preamble_index = 0ULL;
d_flag_frame_sync = false;
d_TOW_at_current_symbol_ms = 0;
d_TOW_at_Preamble_ms = 0;
flag_TOW_set = false;
d_CRC_error_counter = 0;
d_channel = 0;
delta_t = 0.0;
d_symbol_counter = 0;
d_prompt_acum = 0.0;
flag_bit_start = true;
new_symbol = false;
required_symbols = GALILEO_FNAV_SYMBOLS_PER_PAGE + GALILEO_FNAV_PREAMBLE_LENGTH_BITS;
// vars for Viterbi decoder
int32_t max_states = 1 << mm; // 2^mm
g_encoder[0] = 121; // Polynomial G1
g_encoder[1] = 91; // Polynomial G2
out0 = static_cast<int32_t *>(volk_gnsssdr_malloc(max_states * sizeof(int32_t), volk_gnsssdr_get_alignment()));
out1 = static_cast<int32_t *>(volk_gnsssdr_malloc(max_states * sizeof(int32_t), volk_gnsssdr_get_alignment()));
state0 = static_cast<int32_t *>(volk_gnsssdr_malloc(max_states * sizeof(int32_t), volk_gnsssdr_get_alignment()));
state1 = static_cast<int32_t *>(volk_gnsssdr_malloc(max_states * sizeof(int32_t), volk_gnsssdr_get_alignment()));
// create appropriate transition matrices
nsc_transit(out0, state0, 0, g_encoder, KK, nn);
nsc_transit(out1, state1, 1, g_encoder, KK, nn);
}
galileo_e5a_telemetry_decoder_cc::~galileo_e5a_telemetry_decoder_cc()
{
volk_gnsssdr_free(out0);
volk_gnsssdr_free(out1);
volk_gnsssdr_free(state0);
volk_gnsssdr_free(state1);
if (d_dump_file.is_open() == true)
{
try
{
d_dump_file.close();
}
catch (const std::exception &ex)
{
LOG(WARNING) << "Exception in destructor closing the dump file " << ex.what();
}
}
}
void galileo_e5a_telemetry_decoder_cc::set_satellite(const Gnss_Satellite &satellite)
{
d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN());
DLOG(INFO) << "Setting decoder Finite State Machine to satellite " << d_satellite;
DLOG(INFO) << "Navigation Satellite set to " << d_satellite;
}
void galileo_e5a_telemetry_decoder_cc::set_channel(int32_t channel)
{
d_channel = channel;
LOG(INFO) << "Navigation channel set to " << channel;
// Enable data file logging
if (d_dump == true)
{
if (d_dump_file.is_open() == false)
{
try
{
d_dump_filename = "telemetry";
d_dump_filename.append(boost::lexical_cast<std::string>(d_channel));
d_dump_filename.append(".dat");
d_dump_file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
d_dump_file.open(d_dump_filename.c_str(), std::ios::out | std::ios::binary);
LOG(INFO) << "Telemetry decoder dump enabled on channel " << d_channel << " Log file: " << d_dump_filename.c_str();
}
catch (const std::ifstream::failure &e)
{
LOG(WARNING) << "channel " << d_channel << " Exception opening trk dump file " << e.what();
}
}
}
}
int galileo_e5a_telemetry_decoder_cc::general_work(int noutput_items __attribute__((unused)), gr_vector_int &ninput_items __attribute__((unused)),
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items)
{
int32_t preamble_diff = 0;
Gnss_Synchro *out = reinterpret_cast<Gnss_Synchro *>(output_items[0]); // Get the output buffer pointer
const Gnss_Synchro *in = reinterpret_cast<const Gnss_Synchro *>(input_items[0]); // Get the input buffer pointer
// 1. Copy the current tracking output
Gnss_Synchro current_sample = in[0];
d_symbol_counter++;
if (flag_bit_start)
{
d_prompt_acum += current_sample.Prompt_I;
if (d_symbol_counter == GALILEO_FNAV_CODES_PER_SYMBOL)
{
current_sample.Prompt_I = d_prompt_acum / static_cast<double>(GALILEO_FNAV_CODES_PER_SYMBOL);
d_symbol_history.push_back(current_sample); // add new symbol to the symbol queue
d_prompt_acum = 0.0;
d_symbol_counter = 0;
new_symbol = true;
}
}
else
{
if (current_sample.Prompt_I < 0.0)
{
d_preamble_init.push_back(1);
}
else
{
d_preamble_init.push_back(-1);
}
if (d_preamble_init.size() == GALILEO_FNAV_CODES_PER_PREAMBLE)
{
std::deque<int32_t>::iterator iter;
int32_t k = 0;
corr_value = 0;
for (iter = d_preamble_init.begin(); iter != d_preamble_init.end(); iter++)
{
corr_value += *iter * d_preamble_samples[k];
k++;
}
if (abs(corr_value) == GALILEO_FNAV_CODES_PER_PREAMBLE)
{
d_symbol_counter = 0;
flag_bit_start = true;
corr_value = 0;
d_preamble_init.clear();
d_symbol_history.clear();
LOG(INFO) << "Bit start sync for Galileo E5a satellite " << d_satellite;
}
else
{
d_preamble_init.pop_front();
}
}
}
d_sample_counter++; // count for the processed samples
consume_each(1);
d_flag_preamble = false;
if ((d_symbol_history.size() > required_symbols) && new_symbol)
{
// ****************** Preamble orrelation ******************
corr_value = 0;
for (int32_t i = 0; i < GALILEO_FNAV_PREAMBLE_LENGTH_BITS; i++)
{
if (d_symbol_history.at(i).Prompt_I < 0.0) // symbols clipping
{
corr_value -= d_preambles_bits[i];
}
else
{
corr_value += d_preambles_bits[i];
}
}
}
// ****************** Frame sync ******************
if ((d_stat == 0) && new_symbol) // no preamble information
{
if (abs(corr_value) == GALILEO_FNAV_PREAMBLE_LENGTH_BITS)
{
d_preamble_index = d_sample_counter; // record the preamble sample stamp
LOG(INFO) << "Preamble detection for Galileo E5a satellite " << d_satellite;
d_stat = 1; // enter into frame pre-detection status
}
}
else if ((d_stat == 1) && new_symbol) // possible preamble lock
{
if (abs(corr_value) == GALILEO_FNAV_PREAMBLE_LENGTH_BITS)
{
// check preamble separation
preamble_diff = static_cast<int32_t>(d_sample_counter - d_preamble_index);
if (preamble_diff == GALILEO_FNAV_CODES_PER_PAGE)
{
// try to decode frame
LOG(INFO) << "Starting page decoder for Galileo E5a satellite " << d_satellite;
d_preamble_index = d_sample_counter; // record the preamble sample stamp
d_stat = 2;
}
else if (preamble_diff > GALILEO_FNAV_CODES_PER_PAGE)
{
d_stat = 0; // start again
flag_bit_start = false;
LOG(INFO) << "Preamble diff = " << preamble_diff;
}
}
}
else if ((d_stat == 2) && new_symbol)
{
if (d_sample_counter == (d_preamble_index + static_cast<uint64_t>(GALILEO_FNAV_CODES_PER_PAGE)))
{
// NEW Galileo page part is received
// 0. fetch the symbols into an array
int32_t frame_length = GALILEO_FNAV_SYMBOLS_PER_PAGE - GALILEO_FNAV_PREAMBLE_LENGTH_BITS;
double corr_sign = 0.0;
if (corr_value > 0)
{
corr_sign = -1.0;
}
else
{
corr_sign = 1.0;
}
for (int32_t i = 0; i < frame_length; i++)
{
page_symbols[i] = corr_sign * d_symbol_history.at(i + GALILEO_FNAV_PREAMBLE_LENGTH_BITS).Prompt_I; // because last symbol of the preamble is just received now!
}
// call the decoder
decode_word(page_symbols, frame_length);
if (d_nav.flag_CRC_test == true)
{
d_CRC_error_counter = 0;
d_flag_preamble = true; // valid preamble indicator (initialized to false every work())
d_preamble_index = d_sample_counter; // record the preamble sample stamp (t_P)
if (!d_flag_frame_sync)
{
d_flag_frame_sync = true;
DLOG(INFO) << " Frame sync SAT " << this->d_satellite << " with preamble start at "
<< d_symbol_history.at(0).Tracking_sample_counter << " [samples]";
}
}
else
{
d_CRC_error_counter++;
d_preamble_index = d_sample_counter; // record the preamble sample stamp
if (d_CRC_error_counter > GALILEO_E5A_CRC_ERROR_LIMIT)
{
LOG(INFO) << "Lost of frame sync SAT " << this->d_satellite;
d_flag_frame_sync = false;
d_stat = 0;
flag_bit_start = false;
d_nav.flag_TOW_set = false;
d_TOW_at_current_symbol_ms = 0;
d_TOW_at_Preamble_ms = 0;
}
}
}
}
new_symbol = false;
// UPDATE GNSS SYNCHRO DATA
// Add the telemetry decoder information
if (d_flag_preamble and d_nav.flag_TOW_set)
// update TOW at the preamble instant
// We expect a preamble each 10 seconds (FNAV page period)
{
if (d_nav.flag_TOW_1 == true)
{
d_TOW_at_Preamble_ms = static_cast<uint32_t>(d_nav.FNAV_TOW_1 * 1000.0);
d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast<uint32_t>((GALILEO_FNAV_CODES_PER_PAGE + GALILEO_FNAV_CODES_PER_PREAMBLE) * GALILEO_E5a_CODE_PERIOD_MS);
d_nav.flag_TOW_1 = false;
}
else if (d_nav.flag_TOW_2 == true)
{
d_TOW_at_Preamble_ms = static_cast<uint32_t>(d_nav.FNAV_TOW_2 * 1000.0);
d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast<uint32_t>((GALILEO_FNAV_CODES_PER_PAGE + GALILEO_FNAV_CODES_PER_PREAMBLE) * GALILEO_E5a_CODE_PERIOD_MS);
d_nav.flag_TOW_2 = false;
}
else if (d_nav.flag_TOW_3 == true)
{
d_TOW_at_Preamble_ms = static_cast<uint32_t>(d_nav.FNAV_TOW_3 * 1000.0);
d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast<uint32_t>((GALILEO_FNAV_CODES_PER_PAGE + GALILEO_FNAV_CODES_PER_PREAMBLE) * GALILEO_E5a_CODE_PERIOD_MS);
d_nav.flag_TOW_3 = false;
}
else if (d_nav.flag_TOW_4 == true)
{
d_TOW_at_Preamble_ms = static_cast<uint32_t>(d_nav.FNAV_TOW_4 * 1000.0);
d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast<uint32_t>((GALILEO_FNAV_CODES_PER_PAGE + GALILEO_FNAV_CODES_PER_PREAMBLE) * GALILEO_E5a_CODE_PERIOD_MS);
d_nav.flag_TOW_4 = false;
}
else
{
d_TOW_at_current_symbol_ms += static_cast<uint32_t>(GALILEO_E5a_CODE_PERIOD_MS);
}
}
else // if there is not a new preamble, we define the TOW of the current symbol
{
if (d_nav.flag_TOW_set == true)
{
d_TOW_at_current_symbol_ms += static_cast<uint32_t>(GALILEO_E5a_CODE_PERIOD_MS);
}
}
// remove used symbols from history
// todo: Use circular buffer here
while (d_symbol_history.size() > required_symbols)
{
d_symbol_history.pop_front();
}
if (d_nav.flag_TOW_set)
{
current_sample.Flag_valid_word = true;
current_sample.TOW_at_current_symbol_ms = d_TOW_at_current_symbol_ms;
if (d_dump)
{
// MULTIPLEXED FILE RECORDING - Record results to file
try
{
double tmp_double;
uint64_t tmp_ulong_int;
tmp_double = static_cast<double>(d_TOW_at_current_symbol_ms) / 1000.0;
d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double));
tmp_ulong_int = current_sample.Tracking_sample_counter;
d_dump_file.write(reinterpret_cast<char *>(&tmp_ulong_int), sizeof(uint64_t));
tmp_double = static_cast<double>(d_TOW_at_Preamble_ms) / 1000.0;
d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double));
}
catch (const std::ifstream::failure &e)
{
LOG(WARNING) << "Exception writing Galileo E5a Telemetry Decoder dump file " << e.what();
}
}
// 3. Make the output
out[0] = current_sample;
return 1;
}
else
{
return 0;
}
}

View File

@ -1,127 +0,0 @@
/*!
* \file galileo_e5a_telemetry_decoder_cc.cc
* \brief Implementation of a Galileo FNAV message demodulator block
* \author Marc Sales, 2014. marcsales92(at)gmail.com
* Javier Arribas, 2017. jarribas(at)cttc.es
* \based on work from:
* <ul>
* <li> Javier Arribas, 2011. jarribas(at)cttc.es
* </ul>
*
*
* -------------------------------------------------------------------------
*
* 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 <https://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_GALILEO_E5A_TELEMETRY_DECODER_CC_H_
#define GNSS_SDR_GALILEO_E5A_TELEMETRY_DECODER_CC_H_
#include "Galileo_E5a.h"
#include "gnss_satellite.h"
#include "galileo_fnav_message.h"
#include "galileo_ephemeris.h"
#include "galileo_almanac.h"
#include "galileo_iono.h"
#include "galileo_utc_model.h"
#include "gnss_synchro.h"
#include <gnuradio/block.h>
#include <deque>
#include <fstream>
#include <string>
class galileo_e5a_telemetry_decoder_cc;
typedef boost::shared_ptr<galileo_e5a_telemetry_decoder_cc> galileo_e5a_telemetry_decoder_cc_sptr;
galileo_e5a_telemetry_decoder_cc_sptr galileo_e5a_make_telemetry_decoder_cc(const Gnss_Satellite &satellite, bool dump);
/*!
* \brief This class implements a block that decodes the FNAV data defined in Galileo ICD
*
*/
class galileo_e5a_telemetry_decoder_cc : public gr::block
{
public:
~galileo_e5a_telemetry_decoder_cc();
void set_satellite(const Gnss_Satellite &satellite); //!< Set satellite PRN
void set_channel(int32_t channel); //!< Set receiver's channel
/*!
* \brief This is where all signal processing takes place
*/
int general_work(int noutput_items, gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items);
private:
friend galileo_e5a_telemetry_decoder_cc_sptr
galileo_e5a_make_telemetry_decoder_cc(const Gnss_Satellite &satellite, bool dump);
galileo_e5a_telemetry_decoder_cc(const Gnss_Satellite &satellite, bool dump);
void viterbi_decoder(double *page_part_symbols, int32_t *page_part_bits);
void deinterleaver(int32_t rows, int32_t cols, double *in, double *out);
void decode_word(double *page_symbols, int32_t frame_length);
int32_t d_preambles_bits[GALILEO_FNAV_PREAMBLE_LENGTH_BITS];
int32_t d_preamble_samples[GALILEO_FNAV_CODES_PER_PREAMBLE];
std::deque<int> d_preamble_init;
int32_t d_stat;
int32_t d_CRC_error_counter;
int32_t d_channel;
int32_t d_symbol_counter;
int32_t corr_value;
uint32_t required_symbols;
uint64_t d_sample_counter;
uint64_t d_preamble_index;
bool d_flag_frame_sync;
bool d_flag_preamble;
bool d_dump;
bool flag_TOW_set;
bool flag_bit_start;
bool new_symbol;
double d_prompt_acum;
double page_symbols[GALILEO_FNAV_SYMBOLS_PER_PAGE - GALILEO_FNAV_PREAMBLE_LENGTH_BITS];
uint32_t d_TOW_at_Preamble_ms;
uint32_t d_TOW_at_current_symbol_ms;
double delta_t; //GPS-GALILEO time offset
std::string d_dump_filename;
std::ofstream d_dump_file;
std::deque<Gnss_Synchro> d_symbol_history;
Gnss_Satellite d_satellite;
// navigation message vars
Galileo_Fnav_Message d_nav;
// vars for Viterbi decoder
int32_t *out0, *out1, *state0, *state1;
int32_t g_encoder[2];
const int32_t nn = 2; // Coding rate 1/n
const int32_t KK = 7; // Constraint Length
int32_t mm = KK - 1;
const int32_t CodeLength = 488;
int32_t DataLength = (CodeLength / nn) - mm;
};
#endif /* GNSS_SDR_GALILEO_E5A_TELEMETRY_DECODER_CC_H_ */

View File

@ -0,0 +1,780 @@
/*!
* \file galileo_telemetry_decoder_cc.cc
* \brief Implementation of a Galileo unified INAV and FNAV message demodulator block
* \author Javier Arribas 2018. 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 <https://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "galileo_telemetry_decoder_cc.h"
#include "control_message_factory.h"
#include "convolutional.h"
#include "display.h"
#include "gnss_synchro.h"
#include <boost/lexical_cast.hpp>
#include <gnuradio/io_signature.h>
#include <glog/logging.h>
#include <volk_gnsssdr/volk_gnsssdr.h>
#include <iostream>
#define CRC_ERROR_LIMIT 6
using google::LogMessage;
galileo_telemetry_decoder_cc_sptr
galileo_make_telemetry_decoder_cc(const Gnss_Satellite &satellite, int frame_type, bool dump)
{
return galileo_telemetry_decoder_cc_sptr(new galileo_telemetry_decoder_cc(satellite, frame_type, dump));
}
void galileo_telemetry_decoder_cc::viterbi_decoder(double *page_part_symbols, int32_t *page_part_bits)
{
Viterbi(page_part_bits, out0, state0, out1, state1,
page_part_symbols, KK, nn, DataLength);
}
void galileo_telemetry_decoder_cc::deinterleaver(int32_t rows, int32_t cols, double *in, double *out)
{
for (int32_t r = 0; r < rows; r++)
{
for (int32_t c = 0; c < cols; c++)
{
out[c * rows + r] = in[r * cols + c];
}
}
}
galileo_telemetry_decoder_cc::galileo_telemetry_decoder_cc(
const Gnss_Satellite &satellite, int frame_type,
bool dump) : gr::block("galileo_telemetry_decoder_cc", gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)),
gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)))
{
// Ephemeris data port out
this->message_port_register_out(pmt::mp("telemetry"));
// initialize internal vars
d_dump = dump;
d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN());
d_frame_type = frame_type;
LOG(INFO) << "Initializing GALILEO UNIFIED TELEMETRY DECODER";
switch (d_frame_type)
{
case 1: //INAV
{
d_PRN_code_period_ms = static_cast<uint32_t>(GALILEO_E1_CODE_PERIOD_MS);
d_samples_per_symbol = Galileo_E1_B_SAMPLES_PER_SYMBOL;
d_bits_per_preamble = GALILEO_INAV_PREAMBLE_LENGTH_BITS;
// set the preamble
d_samples_per_preamble = GALILEO_INAV_PREAMBLE_LENGTH_BITS * d_samples_per_symbol;
d_preamble_period_symbols = GALILEO_INAV_PREAMBLE_PERIOD_SYMBOLS;
d_required_symbols = static_cast<uint32_t>(GALILEO_INAV_PAGE_SYMBOLS) + d_samples_per_preamble;
// preamble bits to sampled symbols
d_preamble_samples = static_cast<int32_t *>(volk_gnsssdr_malloc(d_samples_per_preamble * sizeof(int32_t), volk_gnsssdr_get_alignment()));
d_frame_length_symbols = GALILEO_INAV_PAGE_PART_SYMBOLS - GALILEO_INAV_PREAMBLE_LENGTH_BITS;
CodeLength = GALILEO_INAV_PAGE_PART_SYMBOLS - GALILEO_INAV_PREAMBLE_LENGTH_BITS;
DataLength = (CodeLength / nn) - mm;
break;
}
case 2: //FNAV
{
d_PRN_code_period_ms = static_cast<uint32_t>(GALILEO_E5a_CODE_PERIOD_MS);
d_samples_per_symbol = GALILEO_FNAV_CODES_PER_SYMBOL;
d_bits_per_preamble = GALILEO_FNAV_PREAMBLE_LENGTH_BITS;
// set the preamble
d_samples_per_preamble = GALILEO_FNAV_PREAMBLE_LENGTH_BITS * d_samples_per_symbol;
d_preamble_period_symbols = GALILEO_FNAV_CODES_PER_PAGE;
d_required_symbols = static_cast<uint32_t>(GALILEO_FNAV_SYMBOLS_PER_PAGE) * d_samples_per_symbol + d_samples_per_preamble;
// preamble bits to sampled symbols
d_preamble_samples = static_cast<int32_t *>(volk_gnsssdr_malloc(d_samples_per_preamble * sizeof(int32_t), volk_gnsssdr_get_alignment()));
d_secondary_code_samples = static_cast<int32_t *>(volk_gnsssdr_malloc(Galileo_E5a_I_SECONDARY_CODE_LENGTH * sizeof(int32_t), volk_gnsssdr_get_alignment()));
d_frame_length_symbols = GALILEO_FNAV_SYMBOLS_PER_PAGE - GALILEO_FNAV_PREAMBLE_LENGTH_BITS;
CodeLength = GALILEO_FNAV_SYMBOLS_PER_PAGE - GALILEO_FNAV_PREAMBLE_LENGTH_BITS;
DataLength = (CodeLength / nn) - mm;
for (int32_t i = 0; i < Galileo_E5a_I_SECONDARY_CODE_LENGTH; i++)
{
if (Galileo_E5a_I_SECONDARY_CODE.at(i) == '1')
{
d_secondary_code_samples[i] = 1;
}
else
{
d_secondary_code_samples[i] = -1;
}
}
break;
}
default:
std::cout << "Galileo unified telemetry decoder error: Unknown frame type " << std::endl;
}
d_page_part_symbols = static_cast<double *>(volk_gnsssdr_malloc(d_frame_length_symbols * sizeof(double), volk_gnsssdr_get_alignment()));
int32_t n = 0;
for (int32_t i = 0; i < d_bits_per_preamble; i++)
{
switch (d_frame_type)
{
case 1: //INAV
{
if (GALILEO_INAV_PREAMBLE.at(i) == '1')
{
for (uint32_t j = 0; j < d_samples_per_symbol; j++)
{
d_preamble_samples[n] = 1;
n++;
}
}
else
{
for (uint32_t j = 0; j < d_samples_per_symbol; j++)
{
d_preamble_samples[n] = -1;
n++;
}
}
break;
}
case 2: //FNAV for E5a-I
{
// Galileo E5a data channel (E5a-I) still has a secondary code
int m = 0;
if (GALILEO_FNAV_PREAMBLE.at(i) == '1')
{
for (uint32_t j = 0; j < d_samples_per_symbol; j++)
{
d_preamble_samples[n] = d_secondary_code_samples[m];
n++;
m++;
m = m % Galileo_E5a_I_SECONDARY_CODE_LENGTH;
}
}
else
{
for (uint32_t j = 0; j < d_samples_per_symbol; j++)
{
d_preamble_samples[n] = -d_secondary_code_samples[m];
n++;
m++;
m = m % Galileo_E5a_I_SECONDARY_CODE_LENGTH;
}
}
break;
}
}
}
d_sample_counter = 0ULL;
d_stat = 0;
d_preamble_index = 0ULL;
d_flag_frame_sync = false;
d_flag_parity = false;
d_TOW_at_current_symbol_ms = 0;
d_TOW_at_Preamble_ms = 0;
delta_t = 0;
d_CRC_error_counter = 0;
flag_even_word_arrived = 0;
d_flag_preamble = false;
d_channel = 0;
flag_TOW_set = false;
// vars for Viterbi decoder
int32_t max_states = 1 << mm; // 2^mm
g_encoder[0] = 121; // Polynomial G1
g_encoder[1] = 91; // Polynomial G2
out0 = static_cast<int32_t *>(volk_gnsssdr_malloc(max_states * sizeof(int32_t), volk_gnsssdr_get_alignment()));
out1 = static_cast<int32_t *>(volk_gnsssdr_malloc(max_states * sizeof(int32_t), volk_gnsssdr_get_alignment()));
state0 = static_cast<int32_t *>(volk_gnsssdr_malloc(max_states * sizeof(int32_t), volk_gnsssdr_get_alignment()));
state1 = static_cast<int32_t *>(volk_gnsssdr_malloc(max_states * sizeof(int32_t), volk_gnsssdr_get_alignment()));
// create appropriate transition matrices
nsc_transit(out0, state0, 0, g_encoder, KK, nn);
nsc_transit(out1, state1, 1, g_encoder, KK, nn);
}
galileo_telemetry_decoder_cc::~galileo_telemetry_decoder_cc()
{
volk_gnsssdr_free(d_preamble_samples);
if (d_frame_type == 2)
{
volk_gnsssdr_free(d_secondary_code_samples);
}
volk_gnsssdr_free(d_page_part_symbols);
volk_gnsssdr_free(out0);
volk_gnsssdr_free(out1);
volk_gnsssdr_free(state0);
volk_gnsssdr_free(state1);
if (d_dump_file.is_open() == true)
{
try
{
d_dump_file.close();
}
catch (const std::exception &ex)
{
LOG(WARNING) << "Exception in destructor closing the dump file " << ex.what();
}
}
}
void galileo_telemetry_decoder_cc::decode_INAV_word(double *page_part_symbols, int32_t frame_length)
{
// 1. De-interleave
double *page_part_symbols_deint = static_cast<double *>(volk_gnsssdr_malloc(frame_length * sizeof(double), volk_gnsssdr_get_alignment()));
deinterleaver(GALILEO_INAV_INTERLEAVER_ROWS, GALILEO_INAV_INTERLEAVER_COLS, page_part_symbols, page_part_symbols_deint);
// 2. Viterbi decoder
// 2.1 Take into account the NOT gate in G2 polynomial (Galileo ICD Figure 13, FEC encoder)
// 2.2 Take into account the possible inversion of the polarity due to PLL lock at 180º
for (int32_t i = 0; i < frame_length; i++)
{
if ((i + 1) % 2 == 0)
{
page_part_symbols_deint[i] = -page_part_symbols_deint[i];
}
}
int32_t *page_part_bits = static_cast<int32_t *>(volk_gnsssdr_malloc((frame_length / 2) * sizeof(int32_t), volk_gnsssdr_get_alignment()));
viterbi_decoder(page_part_symbols_deint, page_part_bits);
volk_gnsssdr_free(page_part_symbols_deint);
// 3. Call the Galileo page decoder
std::string page_String;
for (int32_t i = 0; i < (frame_length / 2); i++)
{
if (page_part_bits[i] > 0)
{
page_String.push_back('1');
}
else
{
page_String.push_back('0');
}
}
if (page_part_bits[0] == 1)
{
// DECODE COMPLETE WORD (even + odd) and TEST CRC
d_inav_nav.split_page(page_String, flag_even_word_arrived);
if (d_inav_nav.flag_CRC_test == true)
{
LOG(INFO) << "Galileo E1 CRC correct in channel " << d_channel << " from satellite " << d_satellite;
}
else
{
LOG(INFO) << "Galileo E1 CRC error in channel " << d_channel << " from satellite " << d_satellite;
}
flag_even_word_arrived = 0;
}
else
{
// STORE HALF WORD (even page)
d_inav_nav.split_page(page_String.c_str(), flag_even_word_arrived);
flag_even_word_arrived = 1;
}
volk_gnsssdr_free(page_part_bits);
// 4. Push the new navigation data to the queues
if (d_inav_nav.have_new_ephemeris() == true)
{
// get object for this SV (mandatory)
std::shared_ptr<Galileo_Ephemeris> tmp_obj = std::make_shared<Galileo_Ephemeris>(d_inav_nav.get_ephemeris());
std::cout << "New Galileo E1 I/NAV message received in channel " << d_channel << ": ephemeris from satellite " << d_satellite << std::endl;
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
}
if (d_inav_nav.have_new_iono_and_GST() == true)
{
// get object for this SV (mandatory)
std::shared_ptr<Galileo_Iono> tmp_obj = std::make_shared<Galileo_Iono>(d_inav_nav.get_iono());
std::cout << "New Galileo E1 I/NAV message received in channel " << d_channel << ": iono/GST model parameters from satellite " << d_satellite << std::endl;
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
}
if (d_inav_nav.have_new_utc_model() == true)
{
// get object for this SV (mandatory)
std::shared_ptr<Galileo_Utc_Model> tmp_obj = std::make_shared<Galileo_Utc_Model>(d_inav_nav.get_utc_model());
std::cout << "New Galileo E1 I/NAV message received in channel " << d_channel << ": UTC model parameters from satellite " << d_satellite << std::endl;
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
}
if (d_inav_nav.have_new_almanac() == true)
{
std::shared_ptr<Galileo_Almanac> tmp_obj = std::make_shared<Galileo_Almanac>(d_inav_nav.get_almanac());
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
//debug
std::cout << "Galileo E1 I/NAV almanac received in channel " << d_channel << " from satellite " << d_satellite << std::endl;
DLOG(INFO) << "GPS_to_Galileo time conversion:";
DLOG(INFO) << "A0G=" << tmp_obj->A_0G_10;
DLOG(INFO) << "A1G=" << tmp_obj->A_1G_10;
DLOG(INFO) << "T0G=" << tmp_obj->t_0G_10;
DLOG(INFO) << "WN_0G_10=" << tmp_obj->WN_0G_10;
DLOG(INFO) << "Current parameters:";
DLOG(INFO) << "d_TOW_at_current_symbol_ms=" << d_TOW_at_current_symbol_ms;
DLOG(INFO) << "d_nav.WN_0=" << d_inav_nav.WN_0;
delta_t = tmp_obj->A_0G_10 + tmp_obj->A_1G_10 * (static_cast<double>(d_TOW_at_current_symbol_ms) / 1000.0 - tmp_obj->t_0G_10 + 604800 * (fmod((d_inav_nav.WN_0 - tmp_obj->WN_0G_10), 64)));
DLOG(INFO) << "delta_t=" << delta_t << "[s]";
}
}
void galileo_telemetry_decoder_cc::decode_FNAV_word(double *page_symbols, int32_t frame_length)
{
// 1. De-interleave
double *page_symbols_deint = static_cast<double *>(volk_gnsssdr_malloc(frame_length * sizeof(double), volk_gnsssdr_get_alignment()));
deinterleaver(GALILEO_FNAV_INTERLEAVER_ROWS, GALILEO_FNAV_INTERLEAVER_COLS, page_symbols, page_symbols_deint);
// 2. Viterbi decoder
// 2.1 Take into account the NOT gate in G2 polynomial (Galileo ICD Figure 13, FEC encoder)
// 2.2 Take into account the possible inversion of the polarity due to PLL lock at 180<38>
for (int32_t i = 0; i < frame_length; i++)
{
if ((i + 1) % 2 == 0)
{
page_symbols_deint[i] = -page_symbols_deint[i];
}
}
int32_t *page_bits = static_cast<int32_t *>(volk_gnsssdr_malloc((frame_length / 2) * sizeof(int32_t), volk_gnsssdr_get_alignment()));
viterbi_decoder(page_symbols_deint, page_bits);
volk_gnsssdr_free(page_symbols_deint);
// 3. Call the Galileo page decoder
std::string page_String;
for (int32_t i = 0; i < frame_length; i++)
{
if (page_bits[i] > 0)
{
page_String.push_back('1');
}
else
{
page_String.push_back('0');
}
}
volk_gnsssdr_free(page_bits);
// DECODE COMPLETE WORD (even + odd) and TEST CRC
d_fnav_nav.split_page(page_String);
if (d_fnav_nav.flag_CRC_test == true)
{
LOG(INFO) << "Galileo E5a CRC correct in channel " << d_channel << " from satellite " << d_satellite;
}
else
{
LOG(INFO) << "Galileo E5a CRC error in channel " << d_channel << " from satellite " << d_satellite;
}
// 4. Push the new navigation data to the queues
if (d_fnav_nav.have_new_ephemeris() == true)
{
std::shared_ptr<Galileo_Ephemeris> tmp_obj = std::make_shared<Galileo_Ephemeris>(d_fnav_nav.get_ephemeris());
std::cout << TEXT_MAGENTA << "New Galileo E5a F/NAV message received in channel " << d_channel << ": ephemeris from satellite " << d_satellite << TEXT_RESET << std::endl;
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
}
if (d_fnav_nav.have_new_iono_and_GST() == true)
{
std::shared_ptr<Galileo_Iono> tmp_obj = std::make_shared<Galileo_Iono>(d_fnav_nav.get_iono());
std::cout << TEXT_MAGENTA << "New Galileo E5a F/NAV message received in channel " << d_channel << ": iono/GST model parameters from satellite " << d_satellite << TEXT_RESET << std::endl;
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
}
if (d_fnav_nav.have_new_utc_model() == true)
{
std::shared_ptr<Galileo_Utc_Model> tmp_obj = std::make_shared<Galileo_Utc_Model>(d_fnav_nav.get_utc_model());
std::cout << TEXT_MAGENTA << "New Galileo E5a F/NAV message received in channel " << d_channel << ": UTC model parameters from satellite " << d_satellite << TEXT_RESET << std::endl;
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
}
}
void galileo_telemetry_decoder_cc::set_satellite(const Gnss_Satellite &satellite)
{
d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN());
DLOG(INFO) << "Setting decoder Finite State Machine to satellite " << d_satellite;
DLOG(INFO) << "Navigation Satellite set to " << d_satellite;
}
void galileo_telemetry_decoder_cc::set_channel(int32_t channel)
{
d_channel = channel;
LOG(INFO) << "Navigation channel set to " << channel;
// ############# ENABLE DATA FILE LOG #################
if (d_dump == true)
{
if (d_dump_file.is_open() == false)
{
try
{
d_dump_filename = "telemetry";
d_dump_filename.append(boost::lexical_cast<std::string>(d_channel));
d_dump_filename.append(".dat");
d_dump_file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
d_dump_file.open(d_dump_filename.c_str(), std::ios::out | std::ios::binary);
LOG(INFO) << "Telemetry decoder dump enabled on channel " << d_channel << " Log file: " << d_dump_filename.c_str();
}
catch (const std::ifstream::failure &e)
{
LOG(WARNING) << "channel " << d_channel << " Exception opening trk dump file " << e.what();
}
}
}
}
int galileo_telemetry_decoder_cc::general_work(int noutput_items __attribute__((unused)), gr_vector_int &ninput_items __attribute__((unused)),
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items)
{
int32_t corr_value = 0;
int32_t preamble_diff = 0;
Gnss_Synchro **out = reinterpret_cast<Gnss_Synchro **>(&output_items[0]); // Get the output buffer pointer
const Gnss_Synchro **in = reinterpret_cast<const Gnss_Synchro **>(&input_items[0]); // Get the input buffer pointer
Gnss_Synchro current_symbol; // structure to save the synchronization information and send the output object to the next block
// 1. Copy the current tracking output
current_symbol = in[0][0];
// add new symbol to the symbol queue
d_symbol_history.push_back(current_symbol.Prompt_I);
d_sample_counter++; // count for the processed samples
consume_each(1);
d_flag_preamble = false;
if (d_symbol_history.size() > d_required_symbols)
{
// TODO Optimize me!
// ******* preamble correlation ********
for (int32_t i = 0; i < d_samples_per_preamble; i++)
{
if (d_symbol_history.at(i) < 0.0) // symbols clipping
{
corr_value -= d_preamble_samples[i];
}
else
{
corr_value += d_preamble_samples[i];
}
}
}
// ******* frame sync ******************
switch (d_stat)
{
case 0: // no preamble information
{
if (abs(corr_value) >= d_samples_per_preamble)
{
d_preamble_index = d_sample_counter; // record the preamble sample stamp
LOG(INFO) << "Preamble detection for Galileo satellite " << this->d_satellite;
d_stat = 1; // enter into frame pre-detection status
}
break;
}
case 1: // possible preamble lock
{
if (abs(corr_value) >= d_samples_per_preamble)
{
// check preamble separation
preamble_diff = static_cast<int32_t>(d_sample_counter - d_preamble_index);
if (abs(preamble_diff - d_preamble_period_symbols) == 0)
{
// try to decode frame
LOG(INFO) << "Starting page decoder for Galileo satellite " << this->d_satellite;
d_preamble_index = d_sample_counter; // record the preamble sample stamp
d_stat = 2;
}
else
{
if (preamble_diff > d_preamble_period_symbols)
{
d_stat = 0; // start again
}
}
}
break;
}
case 2: //preamble acquired
{
if (d_sample_counter == d_preamble_index + static_cast<uint64_t>(d_preamble_period_symbols))
{
// call the decoder
switch (d_frame_type)
{
case 1: //INAV
// NEW Galileo page part is received
// 0. fetch the symbols into an array
if (corr_value > 0) //normal PLL lock
{
for (uint32_t i = 0; i < d_frame_length_symbols; i++)
{
d_page_part_symbols[i] = d_symbol_history.at(i + d_samples_per_preamble); // because last symbol of the preamble is just received now!
}
}
else //180 deg. inverted carrier phase PLL lock
{
for (uint32_t i = 0; i < d_frame_length_symbols; i++)
{
d_page_part_symbols[i] = d_symbol_history.at(i + d_samples_per_preamble); // because last symbol of the preamble is just received now!
}
}
decode_INAV_word(d_page_part_symbols, d_frame_length_symbols);
break;
case 2: //FNAV
// NEW Galileo page part is received
// 0. fetch the symbols into an array
if (corr_value > 0) //normal PLL lock
{
int k = 0;
for (uint32_t i = 0; i < d_frame_length_symbols; i++)
{
d_page_part_symbols[i] = 0;
for (uint32_t m = 0; m < d_samples_per_symbol; m++)
{
d_page_part_symbols[i] += static_cast<float>(d_secondary_code_samples[k]) * d_symbol_history.at(i * d_samples_per_symbol + d_samples_per_preamble + m); // because last symbol of the preamble is just received now!
k++;
k = k % Galileo_E5a_I_SECONDARY_CODE_LENGTH;
}
}
}
else //180 deg. inverted carrier phase PLL lock
{
int k = 0;
for (uint32_t i = 0; i < d_frame_length_symbols; i++)
{
d_page_part_symbols[i] = 0;
for (uint32_t m = 0; m < d_samples_per_symbol; m++) //integrate samples into symbols
{
d_page_part_symbols[i] -= static_cast<float>(d_secondary_code_samples[k]) * d_symbol_history.at(i * d_samples_per_symbol + d_samples_per_preamble + m); // because last symbol of the preamble is just received now!
k++;
k = k % Galileo_E5a_I_SECONDARY_CODE_LENGTH;
}
}
}
decode_FNAV_word(d_page_part_symbols, d_frame_length_symbols);
break;
default:
return -1;
break;
}
if (d_inav_nav.flag_CRC_test == true or d_fnav_nav.flag_CRC_test == true)
{
d_CRC_error_counter = 0;
d_flag_preamble = true; // valid preamble indicator (initialized to false every work())
d_preamble_index = d_sample_counter; // record the preamble sample stamp (t_P)
if (!d_flag_frame_sync)
{
d_flag_frame_sync = true;
DLOG(INFO) << " Frame sync SAT " << this->d_satellite;
}
}
else
{
d_CRC_error_counter++;
d_preamble_index = d_sample_counter; // record the preamble sample stamp
if (d_CRC_error_counter > CRC_ERROR_LIMIT)
{
LOG(INFO) << "Lost of frame sync SAT " << this->d_satellite;
d_flag_frame_sync = false;
d_stat = 0;
d_TOW_at_current_symbol_ms = 0;
d_TOW_at_Preamble_ms = 0;
d_fnav_nav.flag_TOW_set = false;
d_inav_nav.flag_TOW_set = false;
}
}
}
break;
}
}
// UPDATE GNSS SYNCHRO DATA
// 2. Add the telemetry decoder information
if (this->d_flag_preamble == true)
// update TOW at the preamble instant
{
switch (d_frame_type)
{
case 1: //INAV
{
if (d_inav_nav.flag_TOW_set == true)
{
if (d_inav_nav.flag_TOW_5 == true) // page 5 arrived and decoded, so we are in the odd page (since Tow refers to the even page, we have to add 1 sec)
{
// TOW_5 refers to the even preamble, but when we decode it we are in the odd part, so 1 second later plus the decoding delay
d_TOW_at_Preamble_ms = static_cast<uint32_t>(d_inav_nav.TOW_5 * 1000.0);
d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast<uint32_t>(GALILEO_INAV_PAGE_PART_MS + (d_required_symbols + 1) * GALILEO_E1_CODE_PERIOD_MS);
d_inav_nav.flag_TOW_5 = false;
}
else if (d_inav_nav.flag_TOW_6 == true) // page 6 arrived and decoded, so we are in the odd page (since Tow refers to the even page, we have to add 1 sec)
{
// TOW_6 refers to the even preamble, but when we decode it we are in the odd part, so 1 second later plus the decoding delay
d_TOW_at_Preamble_ms = static_cast<uint32_t>(d_inav_nav.TOW_6 * 1000.0);
d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast<uint32_t>(GALILEO_INAV_PAGE_PART_MS + (d_required_symbols + 1) * GALILEO_E1_CODE_PERIOD_MS);
d_inav_nav.flag_TOW_6 = false;
}
else
{
// this page has no timing information
d_TOW_at_current_symbol_ms += static_cast<uint32_t>(GALILEO_E1_CODE_PERIOD_MS); // + GALILEO_INAV_PAGE_PART_SYMBOLS*GALILEO_E1_CODE_PERIOD;
}
}
break;
}
case 2: //FNAV
{
if (d_fnav_nav.flag_TOW_set == true)
{
if (d_fnav_nav.flag_TOW_1 == true)
{
d_TOW_at_Preamble_ms = static_cast<uint32_t>(d_fnav_nav.FNAV_TOW_1 * 1000.0);
d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast<uint32_t>((d_required_symbols + 1) * GALILEO_E5a_CODE_PERIOD_MS);
//d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast<uint32_t>((GALILEO_FNAV_CODES_PER_PAGE + GALILEO_FNAV_CODES_PER_PREAMBLE) * GALILEO_E5a_CODE_PERIOD_MS);
d_fnav_nav.flag_TOW_1 = false;
}
else if (d_fnav_nav.flag_TOW_2 == true)
{
d_TOW_at_Preamble_ms = static_cast<uint32_t>(d_fnav_nav.FNAV_TOW_2 * 1000.0);
//d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast<uint32_t>((GALILEO_FNAV_CODES_PER_PAGE + GALILEO_FNAV_CODES_PER_PREAMBLE) * GALILEO_E5a_CODE_PERIOD_MS);
d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast<uint32_t>((d_required_symbols + 1) * GALILEO_E5a_CODE_PERIOD_MS);
d_fnav_nav.flag_TOW_2 = false;
}
else if (d_fnav_nav.flag_TOW_3 == true)
{
d_TOW_at_Preamble_ms = static_cast<uint32_t>(d_fnav_nav.FNAV_TOW_3 * 1000.0);
//d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast<uint32_t>((GALILEO_FNAV_CODES_PER_PAGE + GALILEO_FNAV_CODES_PER_PREAMBLE) * GALILEO_E5a_CODE_PERIOD_MS);
d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast<uint32_t>((d_required_symbols + 1) * GALILEO_E5a_CODE_PERIOD_MS);
d_fnav_nav.flag_TOW_3 = false;
}
else if (d_fnav_nav.flag_TOW_4 == true)
{
d_TOW_at_Preamble_ms = static_cast<uint32_t>(d_fnav_nav.FNAV_TOW_4 * 1000.0);
//d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast<uint32_t>((GALILEO_FNAV_CODES_PER_PAGE + GALILEO_FNAV_CODES_PER_PREAMBLE) * GALILEO_E5a_CODE_PERIOD_MS);
d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast<uint32_t>((d_required_symbols + 1) * GALILEO_E5a_CODE_PERIOD_MS);
d_fnav_nav.flag_TOW_4 = false;
}
else
{
d_TOW_at_current_symbol_ms += static_cast<uint32_t>(GALILEO_E5a_CODE_PERIOD_MS);
}
break;
}
}
}
}
else // if there is not a new preamble, we define the TOW of the current symbol
{
switch (d_frame_type)
{
case 1: //INAV
{
if (d_inav_nav.flag_TOW_set == true)
{
d_TOW_at_current_symbol_ms += d_PRN_code_period_ms;
}
break;
}
case 2: //FNAV
{
if (d_fnav_nav.flag_TOW_set == true)
{
d_TOW_at_current_symbol_ms += d_PRN_code_period_ms;
}
break;
}
}
}
// remove used symbols from history
// todo: Use circular buffer here
if (d_symbol_history.size() > d_required_symbols)
{
d_symbol_history.pop_front();
}
switch (d_frame_type)
{
case 1: //INAV
{
if (d_inav_nav.flag_TOW_set)
{
if (d_inav_nav.flag_GGTO_1 == true and d_inav_nav.flag_GGTO_2 == true and d_inav_nav.flag_GGTO_3 == true and d_inav_nav.flag_GGTO_4 == true) // all GGTO parameters arrived
{
delta_t = d_inav_nav.A_0G_10 + d_inav_nav.A_1G_10 * (static_cast<double>(d_TOW_at_current_symbol_ms) / 1000.0 - d_inav_nav.t_0G_10 + 604800.0 * (fmod((d_inav_nav.WN_0 - d_inav_nav.WN_0G_10), 64.0)));
}
current_symbol.Flag_valid_word = true;
}
break;
}
case 2: //FNAV
{
if (d_fnav_nav.flag_TOW_set)
{
current_symbol.Flag_valid_word = true;
}
break;
}
}
if (d_inav_nav.flag_TOW_set or d_fnav_nav.flag_TOW_set)
{
current_symbol.TOW_at_current_symbol_ms = d_TOW_at_current_symbol_ms;
// todo: Galileo to GPS time conversion should be moved to observable block.
// current_symbol.TOW_at_current_symbol_ms -= delta_t; //Galileo to GPS TOW
if (d_dump == true)
{
// MULTIPLEXED FILE RECORDING - Record results to file
try
{
double tmp_double;
uint64_t tmp_ulong_int;
tmp_double = static_cast<double>(d_TOW_at_current_symbol_ms) / 1000.0;
d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double));
tmp_ulong_int = current_symbol.Tracking_sample_counter;
d_dump_file.write(reinterpret_cast<char *>(&tmp_ulong_int), sizeof(uint64_t));
tmp_double = static_cast<double>(d_TOW_at_Preamble_ms) / 1000.0;
d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double));
}
catch (const std::ifstream::failure &e)
{
LOG(WARNING) << "Exception writing observables dump file " << e.what();
}
}
// 3. Make the output (copy the object contents to the GNURadio reserved memory)
*out[0] = current_symbol;
return 1;
}
else
{
return 0;
}
}

View File

@ -1,8 +1,7 @@
/*! /*!
* \file galileo_e1b_telemetry_decoder_cc.h * \file galileo_telemetry_decoder_cc.h
* \brief Interface of a Galileo INAV message demodulator block * \brief Implementation of a Galileo unified INAV and FNAV message demodulator block
* \author Javier Arribas 2013 jarribas(at)cttc.es, * \author Javier Arribas 2018. jarribas(at)cttc.es
* Mara Branzanti 2013 mara.branzanti(at)gmail.com
* *
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
* *
@ -29,12 +28,15 @@
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
*/ */
#ifndef GNSS_SDR_GALILEO_E1B_TELEMETRY_DECODER_CC_H
#define GNSS_SDR_GALILEO_E1B_TELEMETRY_DECODER_CC_H #ifndef GNSS_SDR_galileo_telemetry_decoder_cc_H
#define GNSS_SDR_galileo_telemetry_decoder_cc_H
#include "Galileo_E1.h" #include "Galileo_E1.h"
#include "Galileo_E5a.h"
#include "galileo_navigation_message.h" #include "galileo_navigation_message.h"
#include "galileo_fnav_message.h"
#include "galileo_ephemeris.h" #include "galileo_ephemeris.h"
#include "galileo_almanac.h" #include "galileo_almanac.h"
#include "galileo_iono.h" #include "galileo_iono.h"
@ -46,20 +48,20 @@
#include <string> #include <string>
class galileo_e1b_telemetry_decoder_cc; class galileo_telemetry_decoder_cc;
typedef boost::shared_ptr<galileo_e1b_telemetry_decoder_cc> galileo_e1b_telemetry_decoder_cc_sptr; typedef boost::shared_ptr<galileo_telemetry_decoder_cc> galileo_telemetry_decoder_cc_sptr;
galileo_e1b_telemetry_decoder_cc_sptr galileo_e1b_make_telemetry_decoder_cc(const Gnss_Satellite &satellite, bool dump); galileo_telemetry_decoder_cc_sptr galileo_make_telemetry_decoder_cc(const Gnss_Satellite &satellite, int frame_type, bool dump);
/*! /*!
* \brief This class implements a block that decodes the INAV data defined in Galileo ICD * \brief This class implements a block that decodes the INAV and FNAV data defined in Galileo ICD
* *
*/ */
class galileo_e1b_telemetry_decoder_cc : public gr::block class galileo_telemetry_decoder_cc : public gr::block
{ {
public: public:
~galileo_e1b_telemetry_decoder_cc(); ~galileo_telemetry_decoder_cc();
void set_satellite(const Gnss_Satellite &satellite); //!< Set satellite PRN void set_satellite(const Gnss_Satellite &satellite); //!< Set satellite PRN
void set_channel(int32_t channel); //!< Set receiver's channel void set_channel(int32_t channel); //!< Set receiver's channel
int32_t flag_even_word_arrived; int32_t flag_even_word_arrived;
@ -71,23 +73,30 @@ public:
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); gr_vector_const_void_star &input_items, gr_vector_void_star &output_items);
private: private:
friend galileo_e1b_telemetry_decoder_cc_sptr friend galileo_telemetry_decoder_cc_sptr
galileo_e1b_make_telemetry_decoder_cc(const Gnss_Satellite &satellite, bool dump); galileo_make_telemetry_decoder_cc(const Gnss_Satellite &satellite, int frame_type, bool dump);
galileo_e1b_telemetry_decoder_cc(const Gnss_Satellite &satellite, bool dump); galileo_telemetry_decoder_cc(const Gnss_Satellite &satellite, int frame_type, bool dump);
void viterbi_decoder(double *page_part_symbols, int32_t *page_part_bits); void viterbi_decoder(double *page_part_symbols, int32_t *page_part_bits);
void deinterleaver(int32_t rows, int32_t cols, double *in, double *out); void deinterleaver(int32_t rows, int32_t cols, double *in, double *out);
void decode_word(double *symbols, int32_t frame_length); void decode_INAV_word(double *symbols, int32_t frame_length);
void decode_FNAV_word(double *page_symbols, int32_t frame_length);
uint16_t d_preambles_bits[GALILEO_INAV_PREAMBLE_LENGTH_BITS]; int d_frame_type;
int32_t d_bits_per_preamble;
int32_t *d_preambles_symbols; int32_t d_samples_per_preamble;
int32_t d_preamble_period_symbols;
int32_t *d_preamble_samples;
int32_t *d_secondary_code_samples;
uint32_t d_samples_per_symbol; uint32_t d_samples_per_symbol;
int32_t d_symbols_per_preamble; uint32_t d_PRN_code_period_ms;
uint32_t d_required_symbols;
uint32_t d_frame_length_symbols;
double *d_page_part_symbols;
std::deque<Gnss_Synchro> d_symbol_history; std::deque<float> d_symbol_history;
uint64_t d_sample_counter; uint64_t d_sample_counter;
uint64_t d_preamble_index; uint64_t d_preamble_index;
@ -99,7 +108,8 @@ private:
int32_t d_CRC_error_counter; int32_t d_CRC_error_counter;
// navigation message vars // navigation message vars
Galileo_Navigation_Message d_nav; Galileo_Navigation_Message d_inav_nav;
Galileo_Fnav_Message d_fnav_nav;
bool d_dump; bool d_dump;
Gnss_Satellite d_satellite; Gnss_Satellite d_satellite;
@ -120,8 +130,8 @@ private:
const int32_t nn = 2; // Coding rate 1/n const int32_t nn = 2; // Coding rate 1/n
const int32_t KK = 7; // Constraint Length const int32_t KK = 7; // Constraint Length
int32_t mm = KK - 1; int32_t mm = KK - 1;
const int32_t CodeLength = 240; int32_t CodeLength;
int32_t DataLength = (CodeLength / nn) - mm; int32_t DataLength;
}; };
#endif #endif

View File

@ -110,7 +110,7 @@ GpsL5DllPllTracking::GpsL5DllPllTracking(
int max_lock_fail = configuration->property(role + ".max_lock_fail", 50); int max_lock_fail = configuration->property(role + ".max_lock_fail", 50);
if (FLAGS_max_lock_fail != 50) max_lock_fail = FLAGS_max_lock_fail; if (FLAGS_max_lock_fail != 50) max_lock_fail = FLAGS_max_lock_fail;
trk_param.max_lock_fail = max_lock_fail; trk_param.max_lock_fail = max_lock_fail;
double carrier_lock_th = configuration->property(role + ".carrier_lock_th", 0.85); double carrier_lock_th = configuration->property(role + ".carrier_lock_th", 0.75);
if (FLAGS_carrier_lock_th != 0.85) carrier_lock_th = FLAGS_carrier_lock_th; if (FLAGS_carrier_lock_th != 0.85) carrier_lock_th = FLAGS_carrier_lock_th;
trk_param.carrier_lock_th = carrier_lock_th; trk_param.carrier_lock_th = carrier_lock_th;

View File

@ -238,17 +238,18 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_) : gr::bl
d_correlation_length_ms = 1; d_correlation_length_ms = 1;
d_code_samples_per_chip = 1; d_code_samples_per_chip = 1;
d_code_length_chips = static_cast<uint32_t>(Galileo_E5a_CODE_LENGTH_CHIPS); d_code_length_chips = static_cast<uint32_t>(Galileo_E5a_CODE_LENGTH_CHIPS);
d_secondary = true;
if (trk_parameters.track_pilot) if (trk_parameters.track_pilot)
{ {
d_secondary = true;
d_secondary_code_length = static_cast<uint32_t>(Galileo_E5a_Q_SECONDARY_CODE_LENGTH); d_secondary_code_length = static_cast<uint32_t>(Galileo_E5a_Q_SECONDARY_CODE_LENGTH);
signal_pretty_name = signal_pretty_name + "Q"; signal_pretty_name = signal_pretty_name + "Q";
interchange_iq = true; interchange_iq = true;
} }
else else
{ {
d_secondary_code_length = static_cast<uint32_t>(Galileo_E5a_I_SECONDARY_CODE_LENGTH); //Do not acquire secondary code in data component. It is done in telemetry decoder
d_secondary_code_string = const_cast<std::string *>(&Galileo_E5a_I_SECONDARY_CODE); d_secondary = false;
signal_pretty_name = signal_pretty_name + "I"; signal_pretty_name = signal_pretty_name + "I";
interchange_iq = false; interchange_iq = false;
} }
@ -362,7 +363,7 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_) : gr::bl
} }
// --- Initializations --- // --- Initializations ---
multicorrelator_cpu.set_fast_resampler(trk_parameters.use_fast_resampler); multicorrelator_cpu.set_high_dynamics_resampler(trk_parameters.use_high_dynamics_resampler);
// Initial code frequency basis of NCO // Initial code frequency basis of NCO
d_code_freq_chips = d_code_chip_rate; d_code_freq_chips = d_code_chip_rate;
// Residual code phase (in chips) // Residual code phase (in chips)
@ -497,7 +498,7 @@ void dll_pll_veml_tracking::start_tracking()
for (uint32_t i = 0; i < d_code_length_chips; i++) for (uint32_t i = 0; i < d_code_length_chips; i++)
{ {
d_tracking_code[i] = aux_code[i].imag(); d_tracking_code[i] = aux_code[i].imag();
d_data_code[i] = aux_code[i].real(); d_data_code[i] = aux_code[i].real(); //the same because it is generated the full signal (E5aI + E5aQ)
} }
d_Prompt_Data[0] = gr_complex(0.0, 0.0); d_Prompt_Data[0] = gr_complex(0.0, 0.0);
correlator_data_cpu.set_local_code_and_taps(d_code_length_chips, d_data_code, d_prompt_data_shift); correlator_data_cpu.set_local_code_and_taps(d_code_length_chips, d_data_code, d_prompt_data_shift);

View File

@ -1,6 +1,6 @@
/*! /*!
* \file cpu_multicorrelator_real_codes.cc * \file cpu_multicorrelator_real_codes.cc
* \brief High optimized CPU vector multiTAP correlator class with real-valued local codes * \brief Highly optimized CPU vector multiTAP correlator class with real-valued local codes
* \authors <ul> * \authors <ul>
* <li> Javier Arribas, 2015. jarribas(at)cttc.es * <li> Javier Arribas, 2015. jarribas(at)cttc.es
* <li> Cillian O'Driscoll, 2017. cillian.odriscoll(at)gmail.com * <li> Cillian O'Driscoll, 2017. cillian.odriscoll(at)gmail.com
@ -46,7 +46,7 @@ cpu_multicorrelator_real_codes::cpu_multicorrelator_real_codes()
d_local_codes_resampled = nullptr; d_local_codes_resampled = nullptr;
d_code_length_chips = 0; d_code_length_chips = 0;
d_n_correlators = 0; d_n_correlators = 0;
d_use_fast_resampler = true; d_use_high_dynamics_resampler = true;
} }
@ -100,9 +100,9 @@ bool cpu_multicorrelator_real_codes::set_input_output_vectors(std::complex<float
void cpu_multicorrelator_real_codes::update_local_code(int correlator_length_samples, float rem_code_phase_chips, float code_phase_step_chips, float code_phase_rate_step_chips) void cpu_multicorrelator_real_codes::update_local_code(int correlator_length_samples, float rem_code_phase_chips, float code_phase_step_chips, float code_phase_rate_step_chips)
{ {
if (d_use_fast_resampler) if (d_use_high_dynamics_resampler)
{ {
volk_gnsssdr_32f_xn_fast_resampler_32f_xn(d_local_codes_resampled, volk_gnsssdr_32f_xn_high_dynamics_resampler_32f_xn(d_local_codes_resampled,
d_local_code_in, d_local_code_in,
rem_code_phase_chips, rem_code_phase_chips,
code_phase_step_chips, code_phase_step_chips,
@ -159,8 +159,9 @@ bool cpu_multicorrelator_real_codes::free()
return true; return true;
} }
void cpu_multicorrelator_real_codes::set_fast_resampler(
bool use_fast_resampler) void cpu_multicorrelator_real_codes::set_high_dynamics_resampler(
bool use_high_dynamics_resampler)
{ {
d_use_fast_resampler = use_fast_resampler; d_use_high_dynamics_resampler = use_high_dynamics_resampler;
} }

View File

@ -1,6 +1,6 @@
/*! /*!
* \file cpu_multicorrelator_real_codes.h * \file cpu_multicorrelator_real_codes.h
* \brief High optimized CPU vector multiTAP correlator class using real-valued local codes * \brief Highly optimized CPU vector multiTAP correlator class using real-valued local codes
* \authors <ul> * \authors <ul>
* <li> Javier Arribas, 2015. jarribas(at)cttc.es * <li> Javier Arribas, 2015. jarribas(at)cttc.es
* <li> Cillian O'Driscoll, 2017, cillian.odriscoll(at)gmail.com * <li> Cillian O'Driscoll, 2017, cillian.odriscoll(at)gmail.com
@ -46,7 +46,7 @@ class cpu_multicorrelator_real_codes
{ {
public: public:
cpu_multicorrelator_real_codes(); cpu_multicorrelator_real_codes();
void set_fast_resampler(bool use_fast_resampler); void set_high_dynamics_resampler(bool use_high_dynamics_resampler);
~cpu_multicorrelator_real_codes(); ~cpu_multicorrelator_real_codes();
bool init(int max_signal_length_samples, int n_correlators); bool init(int max_signal_length_samples, int n_correlators);
bool set_local_code_and_taps(int code_length_chips, const float *local_code_in, float *shifts_chips); bool set_local_code_and_taps(int code_length_chips, const float *local_code_in, float *shifts_chips);
@ -62,7 +62,7 @@ private:
const float *d_local_code_in; const float *d_local_code_in;
std::complex<float> *d_corr_out; std::complex<float> *d_corr_out;
float *d_shifts_chips; float *d_shifts_chips;
bool d_use_fast_resampler; bool d_use_high_dynamics_resampler;
int d_code_length_chips; int d_code_length_chips;
int d_n_correlators; int d_n_correlators;
}; };

View File

@ -36,7 +36,7 @@
Dll_Pll_Conf::Dll_Pll_Conf() Dll_Pll_Conf::Dll_Pll_Conf()
{ {
/* DLL/PLL tracking configuration */ /* DLL/PLL tracking configuration */
use_fast_resampler = true; use_high_dynamics_resampler = true;
fs_in = 0.0; fs_in = 0.0;
vector_length = 0U; vector_length = 0U;
dump = false; dump = false;

View File

@ -56,7 +56,7 @@ public:
float early_late_space_narrow_chips; float early_late_space_narrow_chips;
float very_early_late_space_narrow_chips; float very_early_late_space_narrow_chips;
int32_t extend_correlation_symbols; int32_t extend_correlation_symbols;
bool use_fast_resampler; bool use_high_dynamics_resampler;
int32_t cn0_samples; int32_t cn0_samples;
int32_t carrier_lock_det_mav_samples; int32_t carrier_lock_det_mav_samples;
int32_t cn0_min; int32_t cn0_min;

View File

@ -1,6 +1,9 @@
/*! /*!
* \file gnss_synchro_monitor.cc * \file gnss_synchro_monitor.cc
* \brief Interface of a Position Velocity and Time computation block * \brief Implementation of a receiver monitoring block which allows sending
* a data stream with the receiver internal parameters (Gnss_Synchro objects)
* to local or remote clients over UDP.
*
* \author Álvaro Cebrián Juan, 2018. acebrianjuan(at)gmail.com * \author Álvaro Cebrián Juan, 2018. acebrianjuan(at)gmail.com
* *
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
@ -61,6 +64,8 @@ gnss_synchro_monitor::gnss_synchro_monitor(unsigned int n_channels,
d_nchannels = n_channels; d_nchannels = n_channels;
udp_sink_ptr = std::unique_ptr<Gnss_Synchro_Udp_Sink>(new Gnss_Synchro_Udp_Sink(udp_addresses, udp_port)); udp_sink_ptr = std::unique_ptr<Gnss_Synchro_Udp_Sink>(new Gnss_Synchro_Udp_Sink(udp_addresses, udp_port));
count = 0;
} }
@ -75,17 +80,16 @@ int gnss_synchro_monitor::work(int noutput_items, gr_vector_const_void_star& inp
const Gnss_Synchro** in = reinterpret_cast<const Gnss_Synchro**>(&input_items[0]); // Get the input buffer pointer const Gnss_Synchro** in = reinterpret_cast<const Gnss_Synchro**>(&input_items[0]); // Get the input buffer pointer
for (int epoch = 0; epoch < noutput_items; epoch++) for (int epoch = 0; epoch < noutput_items; epoch++)
{ {
// ############ 1. READ PSEUDORANGES #### count++;
for (unsigned int i = 0; i < d_nchannels; i++) if (count >= d_output_rate_ms)
{ {
//if (in[i][epoch].Flag_valid_pseudorange) for (unsigned int i = 0; i < d_nchannels; i++)
// { {
// } std::vector<Gnss_Synchro> stocks;
//todo: send the gnss_synchro objects stocks.push_back(in[i][epoch]);
udp_sink_ptr->write_gnss_synchro(stocks);
std::vector<Gnss_Synchro> stocks; }
stocks.push_back(in[i][epoch]); count = 0;
udp_sink_ptr->write_gnss_synchro(stocks);
} }
} }
return noutput_items; return noutput_items;

View File

@ -1,6 +1,9 @@
/*! /*!
* \file gnss_synchro_monitor.h * \file gnss_synchro_monitor.h
* \brief Interface of a Position Velocity and Time computation block * \brief Interface of a receiver monitoring block which allows sending
* a data stream with the receiver internal parameters (Gnss_Synchro objects)
* to local or remote clients over UDP.
*
* \author Álvaro Cebrián Juan, 2018. acebrianjuan(at)gmail.com * \author Álvaro Cebrián Juan, 2018. acebrianjuan(at)gmail.com
* *
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
@ -65,6 +68,8 @@ private:
std::unique_ptr<Gnss_Synchro_Udp_Sink> udp_sink_ptr; std::unique_ptr<Gnss_Synchro_Udp_Sink> udp_sink_ptr;
int count;
public: public:
gnss_synchro_monitor(unsigned int nchannels, gnss_synchro_monitor(unsigned int nchannels,

View File

@ -59,6 +59,7 @@ const double Galileo_E1_SUB_CARRIER_A_RATE_HZ = 1.023e6; //!< Galileo E1 sub-ca
const double Galileo_E1_SUB_CARRIER_B_RATE_HZ = 6.138e6; //!< Galileo E1 sub-carrier 'b' rate [Hz] const double Galileo_E1_SUB_CARRIER_B_RATE_HZ = 6.138e6; //!< Galileo E1 sub-carrier 'b' rate [Hz]
const double Galileo_E1_B_CODE_LENGTH_CHIPS = 4092.0; //!< Galileo E1-B code length [chips] const double Galileo_E1_B_CODE_LENGTH_CHIPS = 4092.0; //!< Galileo E1-B code length [chips]
const double Galileo_E1_B_SYMBOL_RATE_BPS = 250.0; //!< Galileo E1-B symbol rate [bits/second] const double Galileo_E1_B_SYMBOL_RATE_BPS = 250.0; //!< Galileo E1-B symbol rate [bits/second]
const int32_t Galileo_E1_B_SAMPLES_PER_SYMBOL = 1; //!< (Galileo_E1_CODE_CHIP_RATE_HZ / Galileo_E1_B_CODE_LENGTH_CHIPS) / Galileo_E1_B_SYMBOL_RATE_BPS
const int32_t Galileo_E1_C_SECONDARY_CODE_LENGTH = 25; //!< Galileo E1-C secondary code length [chips] const int32_t Galileo_E1_C_SECONDARY_CODE_LENGTH = 25; //!< Galileo E1-C secondary code length [chips]
const int32_t Galileo_E1_NUMBER_OF_CODES = 50; const int32_t Galileo_E1_NUMBER_OF_CODES = 50;
@ -70,10 +71,7 @@ const int32_t GALILEO_E1_HISTORY_DEEP = 100;
// Galileo INAV Telemetry structure // Galileo INAV Telemetry structure
#define GALILEO_INAV_PREAMBLE \ const std::string GALILEO_INAV_PREAMBLE = {"0101100000"};
{ \
0, 1, 0, 1, 1, 0, 0, 0, 0, 0 \
}
const int32_t GALILEO_INAV_PREAMBLE_LENGTH_BITS = 10; const int32_t GALILEO_INAV_PREAMBLE_LENGTH_BITS = 10;
const double GALILEO_INAV_PAGE_PART_WITH_PREABLE_SECONDS = 2.0 + GALILEO_INAV_PREAMBLE_LENGTH_BITS * Galileo_E1_CODE_PERIOD; const double GALILEO_INAV_PAGE_PART_WITH_PREABLE_SECONDS = 2.0 + GALILEO_INAV_PREAMBLE_LENGTH_BITS * Galileo_E1_CODE_PERIOD;

View File

@ -35,7 +35,7 @@
#include <limits> #include <limits>
DEFINE_double(skip_obs_transitory_s, 30.0, "Skip the initial observable outputs to avoid transitory results [s]"); DEFINE_double(skip_obs_transitory_s, 30.0, "Skip the initial observable outputs to avoid transitory results [s]");
DEFINE_bool(compute_single_diffs, false, "Compute also the signel difference errors for Accumulated Carrier Phase and Carrier Doppler (requires LO synchronization between receivers)"); DEFINE_bool(compute_single_diffs, false, "Compute also the single difference errors for Accumulated Carrier Phase and Carrier Doppler (requires LO synchronization between receivers)");
DEFINE_bool(compare_with_5X, false, "Compare the E5a Doppler and Carrier Phases with the E5 full bw in RINEX (expect discrepancy due to the center frequencies differences");
#endif #endif

View File

@ -158,6 +158,7 @@ DECLARE_string(log_dir);
#include "unit-tests/signal-processing-blocks/observables/hybrid_observables_test.cc" #include "unit-tests/signal-processing-blocks/observables/hybrid_observables_test.cc"
#endif #endif
#include "unit-tests/signal-processing-blocks/telemetry_decoder/galileo_fnav_inav_decoder_test.cc"
#include "unit-tests/system-parameters/glonass_gnav_ephemeris_test.cc" #include "unit-tests/system-parameters/glonass_gnav_ephemeris_test.cc"
#include "unit-tests/system-parameters/glonass_gnav_nav_message_test.cc" #include "unit-tests/system-parameters/glonass_gnav_nav_message_test.cc"

View File

@ -64,7 +64,7 @@ DEFINE_int32(acq_test_second_doppler_step, 10, "If --acq_test_make_two_steps is
DEFINE_int32(acq_test_signal_duration_s, 2, "Generated signal duration, in s"); DEFINE_int32(acq_test_signal_duration_s, 2, "Generated signal duration, in s");
DEFINE_int32(acq_test_num_meas, 0, "Number of measurements per run. 0 means the complete file."); DEFINE_int32(acq_test_num_meas, 0, "Number of measurements per run. 0 means the complete file.");
DEFINE_double(acq_test_cn0_init, 33.0, "Initial CN0, in dBHz."); DEFINE_double(acq_test_cn0_init, 30.0, "Initial CN0, in dBHz.");
DEFINE_double(acq_test_cn0_final, 45.0, "Final CN0, in dBHz."); DEFINE_double(acq_test_cn0_final, 45.0, "Final CN0, in dBHz.");
DEFINE_double(acq_test_cn0_step, 3.0, "CN0 step, in dB."); DEFINE_double(acq_test_cn0_step, 3.0, "CN0 step, in dB.");

View File

@ -53,7 +53,6 @@
#include "telemetry_decoder_interface.h" #include "telemetry_decoder_interface.h"
#include "in_memory_configuration.h" #include "in_memory_configuration.h"
#include "gnss_synchro.h" #include "gnss_synchro.h"
#include "gps_l1_ca_telemetry_decoder.h"
#include "tracking_true_obs_reader.h" #include "tracking_true_obs_reader.h"
#include "true_observables_reader.h" #include "true_observables_reader.h"
#include "tracking_dump_reader.h" #include "tracking_dump_reader.h"
@ -326,7 +325,8 @@ bool HybridObservablesTest::acquire_signal()
{ {
tmp_gnss_synchro.System = 'G'; tmp_gnss_synchro.System = 'G';
std::string signal = "1C"; std::string signal = "1C";
signal.copy(tmp_gnss_synchro.Signal, 2, 0); const char* str = signal.c_str(); // get a C style null terminated string
std::memcpy(static_cast<void*>(tmp_gnss_synchro.Signal), str, 3); // copy string into synchro char array: 2 char + null
tmp_gnss_synchro.PRN = SV_ID; tmp_gnss_synchro.PRN = SV_ID;
System_and_Signal = "GPS L1 CA"; System_and_Signal = "GPS L1 CA";
config->set_property("Acquisition.max_dwells", std::to_string(FLAGS_external_signal_acquisition_dwells)); config->set_property("Acquisition.max_dwells", std::to_string(FLAGS_external_signal_acquisition_dwells));
@ -337,7 +337,8 @@ bool HybridObservablesTest::acquire_signal()
{ {
tmp_gnss_synchro.System = 'E'; tmp_gnss_synchro.System = 'E';
std::string signal = "1B"; std::string signal = "1B";
signal.copy(tmp_gnss_synchro.Signal, 2, 0); const char* str = signal.c_str(); // get a C style null terminated string
std::memcpy(static_cast<void*>(tmp_gnss_synchro.Signal), str, 3); // copy string into synchro char array: 2 char + null
tmp_gnss_synchro.PRN = SV_ID; tmp_gnss_synchro.PRN = SV_ID;
System_and_Signal = "Galileo E1B"; System_and_Signal = "Galileo E1B";
config->set_property("Acquisition.max_dwells", std::to_string(FLAGS_external_signal_acquisition_dwells)); config->set_property("Acquisition.max_dwells", std::to_string(FLAGS_external_signal_acquisition_dwells));
@ -347,7 +348,8 @@ bool HybridObservablesTest::acquire_signal()
{ {
tmp_gnss_synchro.System = 'G'; tmp_gnss_synchro.System = 'G';
std::string signal = "2S"; std::string signal = "2S";
signal.copy(tmp_gnss_synchro.Signal, 2, 0); const char* str = signal.c_str(); // get a C style null terminated string
std::memcpy(static_cast<void*>(tmp_gnss_synchro.Signal), str, 3); // copy string into synchro char array: 2 char + null
tmp_gnss_synchro.PRN = SV_ID; tmp_gnss_synchro.PRN = SV_ID;
System_and_Signal = "GPS L2CM"; System_and_Signal = "GPS L2CM";
config->set_property("Acquisition.max_dwells", std::to_string(FLAGS_external_signal_acquisition_dwells)); config->set_property("Acquisition.max_dwells", std::to_string(FLAGS_external_signal_acquisition_dwells));
@ -357,7 +359,8 @@ bool HybridObservablesTest::acquire_signal()
{ {
tmp_gnss_synchro.System = 'E'; tmp_gnss_synchro.System = 'E';
std::string signal = "5X"; std::string signal = "5X";
signal.copy(tmp_gnss_synchro.Signal, 2, 0); const char* str = signal.c_str(); // get a C style null terminated string
std::memcpy(static_cast<void*>(tmp_gnss_synchro.Signal), str, 3); // copy string into synchro char array: 2 char + null
tmp_gnss_synchro.PRN = SV_ID; tmp_gnss_synchro.PRN = SV_ID;
System_and_Signal = "Galileo E5a"; System_and_Signal = "Galileo E5a";
config->set_property("Acquisition_5X.coherent_integration_time_ms", "1"); config->set_property("Acquisition_5X.coherent_integration_time_ms", "1");
@ -372,7 +375,8 @@ bool HybridObservablesTest::acquire_signal()
{ {
tmp_gnss_synchro.System = 'E'; tmp_gnss_synchro.System = 'E';
std::string signal = "5X"; std::string signal = "5X";
signal.copy(tmp_gnss_synchro.Signal, 2, 0); const char* str = signal.c_str(); // get a C style null terminated string
std::memcpy(static_cast<void*>(tmp_gnss_synchro.Signal), str, 3); // copy string into synchro char array: 2 char + null
tmp_gnss_synchro.PRN = SV_ID; tmp_gnss_synchro.PRN = SV_ID;
System_and_Signal = "Galileo E5a"; System_and_Signal = "Galileo E5a";
config->set_property("Acquisition.max_dwells", std::to_string(FLAGS_external_signal_acquisition_dwells)); config->set_property("Acquisition.max_dwells", std::to_string(FLAGS_external_signal_acquisition_dwells));
@ -382,7 +386,8 @@ bool HybridObservablesTest::acquire_signal()
{ {
tmp_gnss_synchro.System = 'G'; tmp_gnss_synchro.System = 'G';
std::string signal = "L5"; std::string signal = "L5";
signal.copy(tmp_gnss_synchro.Signal, 2, 0); const char* str = signal.c_str(); // get a C style null terminated string
std::memcpy(static_cast<void*>(tmp_gnss_synchro.Signal), str, 3); // copy string into synchro char array: 2 char + null
tmp_gnss_synchro.PRN = SV_ID; tmp_gnss_synchro.PRN = SV_ID;
System_and_Signal = "GPS L5I"; System_and_Signal = "GPS L5I";
config->set_property("Acquisition.max_dwells", std::to_string(FLAGS_external_signal_acquisition_dwells)); config->set_property("Acquisition.max_dwells", std::to_string(FLAGS_external_signal_acquisition_dwells));
@ -579,7 +584,7 @@ void HybridObservablesTest::configure_receiver(
std::memcpy(static_cast<void*>(gnss_synchro_master.Signal), str, 3); // copy string into synchro char array: 2 char + null std::memcpy(static_cast<void*>(gnss_synchro_master.Signal), str, 3); // copy string into synchro char array: 2 char + null
config->set_property("Tracking.early_late_space_chips", "0.5"); config->set_property("Tracking.early_late_space_chips", "0.5");
config->set_property("Tracking.track_pilot", "false"); config->set_property("Tracking.track_pilot", "true");
config->set_property("TelemetryDecoder.implementation", "GPS_L2C_Telemetry_Decoder"); config->set_property("TelemetryDecoder.implementation", "GPS_L2C_Telemetry_Decoder");
} }
@ -596,7 +601,7 @@ void HybridObservablesTest::configure_receiver(
config->supersede_property("Tracking.implementation", std::string("Galileo_E5a_DLL_PLL_Tracking")); config->supersede_property("Tracking.implementation", std::string("Galileo_E5a_DLL_PLL_Tracking"));
} }
config->set_property("Tracking.early_late_space_chips", "0.5"); config->set_property("Tracking.early_late_space_chips", "0.5");
config->set_property("Tracking.track_pilot", "false"); config->set_property("Tracking.track_pilot", "true");
config->set_property("Tracking.order", "2"); config->set_property("Tracking.order", "2");
config->set_property("TelemetryDecoder.implementation", "Galileo_E5a_Telemetry_Decoder"); config->set_property("TelemetryDecoder.implementation", "Galileo_E5a_Telemetry_Decoder");
@ -610,7 +615,7 @@ void HybridObservablesTest::configure_receiver(
std::memcpy(static_cast<void*>(gnss_synchro_master.Signal), str, 3); // copy string into synchro char array: 2 char + null std::memcpy(static_cast<void*>(gnss_synchro_master.Signal), str, 3); // copy string into synchro char array: 2 char + null
config->set_property("Tracking.early_late_space_chips", "0.5"); config->set_property("Tracking.early_late_space_chips", "0.5");
config->set_property("Tracking.track_pilot", "false"); config->set_property("Tracking.track_pilot", "true");
config->set_property("Tracking.order", "2"); config->set_property("Tracking.order", "2");
config->set_property("TelemetryDecoder.implementation", "GPS_L5_Telemetry_Decoder"); config->set_property("TelemetryDecoder.implementation", "GPS_L5_Telemetry_Decoder");
@ -888,9 +893,9 @@ void HybridObservablesTest::check_results_carrier_doppler_double_diff(
ASSERT_LT(error_mean, 5); ASSERT_LT(error_mean, 5);
ASSERT_GT(error_mean, -5); ASSERT_GT(error_mean, -5);
//assuming PLL BW=35 //assuming PLL BW=35
ASSERT_LT(error_var, 200); ASSERT_LT(error_var, 250);
ASSERT_LT(max_error, 70); ASSERT_LT(max_error, 100);
ASSERT_GT(min_error, -70); ASSERT_GT(min_error, -100);
ASSERT_LT(rmse, 30); ASSERT_LT(rmse, 30);
} }
@ -967,9 +972,9 @@ void HybridObservablesTest::check_results_carrier_doppler(
ASSERT_LT(error_mean_ch0, 5); ASSERT_LT(error_mean_ch0, 5);
ASSERT_GT(error_mean_ch0, -5); ASSERT_GT(error_mean_ch0, -5);
//assuming PLL BW=35 //assuming PLL BW=35
ASSERT_LT(error_var_ch0, 200); ASSERT_LT(error_var_ch0, 250);
ASSERT_LT(max_error_ch0, 70); ASSERT_LT(max_error_ch0, 100);
ASSERT_GT(min_error_ch0, -70); ASSERT_GT(min_error_ch0, -100);
ASSERT_LT(rmse_ch0, 30); ASSERT_LT(rmse_ch0, 30);
} }
@ -1195,7 +1200,7 @@ bool HybridObservablesTest::ReadRinexObs(std::vector<arma::mat>* obs_vec, Gnss_S
dataobj = r_ref_data.getObs(prn, "L5I", r_ref_header); dataobj = r_ref_data.getObs(prn, "L5I", r_ref_header);
obs_vec->at(n)(obs_vec->at(n).n_rows - 1, 3) = dataobj.data; obs_vec->at(n)(obs_vec->at(n).n_rows - 1, 3) = dataobj.data;
} }
else if (strcmp("5X\0", gnss.Signal) == 0) //Simulator gives RINEX with E5a+E5b else if (strcmp("5X\0", gnss.Signal) == 0) //Simulator gives RINEX with E5a+E5b. Doppler and accumulated Carrier phase WILL differ
{ {
obs_vec->at(n)(obs_vec->at(n).n_rows - 1, 0) = sow; obs_vec->at(n)(obs_vec->at(n).n_rows - 1, 0) = sow;
dataobj = r_ref_data.getObs(prn, "C8I", r_ref_header); dataobj = r_ref_data.getObs(prn, "C8I", r_ref_header);
@ -1579,8 +1584,8 @@ TEST_F(HybridObservablesTest, ValidationOfResults)
} }
arma::vec receiver_time_offset_ref_channel_s; arma::vec receiver_time_offset_ref_channel_s;
receiver_time_offset_ref_channel_s = true_obs_vec.at(min_pr_ch_id).col(1) / GPS_C_m_s - GPS_STARTOFFSET_ms / 1000.0; receiver_time_offset_ref_channel_s = (true_obs_vec.at(min_pr_ch_id).col(1)(0) - measured_obs_vec.at(min_pr_ch_id).col(4)(0)) / GPS_C_m_s;
std::cout << "Ref channel initial Receiver time offset " << receiver_time_offset_ref_channel_s(0) * 1e3 << " [ms]" << std::endl; std::cout << "Ref. channel initial Receiver time offset " << receiver_time_offset_ref_channel_s(0) * 1e3 << " [ms]" << std::endl;
for (unsigned int n = 0; n < measured_obs_vec.size(); n++) for (unsigned int n = 0; n < measured_obs_vec.size(); n++)
{ {
@ -1624,21 +1629,28 @@ TEST_F(HybridObservablesTest, ValidationOfResults)
measured_obs_vec.at(n), measured_obs_vec.at(n),
measured_obs_vec.at(min_pr_ch_id), measured_obs_vec.at(min_pr_ch_id),
"[CH " + std::to_string(n) + "] PRN " + std::to_string(gnss_synchro_vec.at(n).PRN) + " "); "[CH " + std::to_string(n) + "] PRN " + std::to_string(gnss_synchro_vec.at(n).PRN) + " ");
check_results_carrier_phase_double_diff(true_obs_vec.at(n),
true_obs_vec.at(min_pr_ch_id),
true_TOW_ch_s,
true_TOW_ref_ch_s,
measured_obs_vec.at(n),
measured_obs_vec.at(min_pr_ch_id),
"[CH " + std::to_string(n) + "] PRN " + std::to_string(gnss_synchro_vec.at(n).PRN) + " ");
check_results_carrier_doppler_double_diff(true_obs_vec.at(n), //Do not compare E5a with E5 RINEX due to the Doppler frequency discrepancy caused by the different center frequencies
true_obs_vec.at(min_pr_ch_id), //E5a_fc=1176.45e6, E5b_fc=1207.14e6, E5_fc=1191.795e6;
true_TOW_ch_s, std::cout << "s:" << gnss_synchro_vec.at(n).Signal << std::endl;
true_TOW_ref_ch_s, if (strcmp("5X\0", gnss_synchro_vec.at(n).Signal) != 0 or FLAGS_compare_with_5X)
measured_obs_vec.at(n), {
measured_obs_vec.at(min_pr_ch_id), check_results_carrier_phase_double_diff(true_obs_vec.at(n),
"[CH " + std::to_string(n) + "] PRN " + std::to_string(gnss_synchro_vec.at(n).PRN) + " "); true_obs_vec.at(min_pr_ch_id),
true_TOW_ch_s,
true_TOW_ref_ch_s,
measured_obs_vec.at(n),
measured_obs_vec.at(min_pr_ch_id),
"[CH " + std::to_string(n) + "] PRN " + std::to_string(gnss_synchro_vec.at(n).PRN) + " ");
check_results_carrier_doppler_double_diff(true_obs_vec.at(n),
true_obs_vec.at(min_pr_ch_id),
true_TOW_ch_s,
true_TOW_ref_ch_s,
measured_obs_vec.at(n),
measured_obs_vec.at(min_pr_ch_id),
"[CH " + std::to_string(n) + "] PRN " + std::to_string(gnss_synchro_vec.at(n).PRN) + " ");
}
} }
else else
{ {

View File

@ -0,0 +1,288 @@
/*!
* \file galileo_fnav_inav_decoder_test.cc
* \brief This class implements the unit test for the Galileo FNAV and INAV frames
* according to the Galileo ICD
* \author Javier Arribas, 2018. jarribas(at)cttc.es
*
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2012-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 <https://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "galileo_navigation_message.h"
#include "galileo_fnav_message.h"
#include "convolutional.h"
#include <unistd.h>
#include <chrono>
#include <exception>
#include <string>
#include <armadillo>
#include <volk_gnsssdr/volk_gnsssdr.h>
#include <gtest/gtest.h>
class Galileo_FNAV_INAV_test : public ::testing::Test
{
public:
Galileo_Navigation_Message INAV_decoder;
Galileo_Fnav_Message FNAV_decoder;
// vars for Viterbi decoder
int32_t *out0, *out1, *state0, *state1;
int32_t g_encoder[2];
const int32_t nn = 2; // Coding rate 1/n
const int32_t KK = 7; // Constraint Length
int32_t mm = KK - 1;
int32_t flag_even_word_arrived;
void viterbi_decoder(double *page_part_symbols, int32_t *page_part_bits, int32_t _datalength)
{
Viterbi(page_part_bits, out0, state0, out1, state1,
page_part_symbols, KK, nn, _datalength);
}
void deinterleaver(int32_t rows, int32_t cols, double *in, double *out)
{
for (int32_t r = 0; r < rows; r++)
{
for (int32_t c = 0; c < cols; c++)
{
out[c * rows + r] = in[r * cols + c];
}
}
}
bool decode_INAV_word(double *page_part_symbols, int32_t frame_length)
{
// 1. De-interleave
double *page_part_symbols_deint = static_cast<double *>(volk_gnsssdr_malloc(frame_length * sizeof(double), volk_gnsssdr_get_alignment()));
deinterleaver(GALILEO_INAV_INTERLEAVER_ROWS, GALILEO_INAV_INTERLEAVER_COLS, page_part_symbols, page_part_symbols_deint);
// 2. Viterbi decoder
// 2.1 Take into account the NOT gate in G2 polynomial (Galileo ICD Figure 13, FEC encoder)
// 2.2 Take into account the possible inversion of the polarity due to PLL lock at 180º
for (int32_t i = 0; i < frame_length; i++)
{
if ((i + 1) % 2 == 0)
{
page_part_symbols_deint[i] = -page_part_symbols_deint[i];
}
}
int32_t *page_part_bits = static_cast<int32_t *>(volk_gnsssdr_malloc((frame_length / 2) * sizeof(int32_t), volk_gnsssdr_get_alignment()));
const int32_t CodeLength = 240;
int32_t DataLength = (CodeLength / nn) - mm;
viterbi_decoder(page_part_symbols_deint, page_part_bits, DataLength);
volk_gnsssdr_free(page_part_symbols_deint);
// 3. Call the Galileo page decoder
std::string page_String;
for (int32_t i = 0; i < (frame_length / 2); i++)
{
if (page_part_bits[i] > 0)
{
page_String.push_back('1');
}
else
{
page_String.push_back('0');
}
}
bool crc_ok = false;
if (page_part_bits[0] == 1)
{
// DECODE COMPLETE WORD (even + odd) and TEST CRC
INAV_decoder.split_page(page_String, flag_even_word_arrived);
if (INAV_decoder.flag_CRC_test == true)
{
std::cout << "Galileo E1 INAV PAGE CRC correct \n";
//std::cout << "Galileo E1 CRC correct on channel " << d_channel << " from satellite " << d_satellite << std::endl;
crc_ok = true;
}
flag_even_word_arrived = 0;
}
else
{
// STORE HALF WORD (even page)
INAV_decoder.split_page(page_String.c_str(), flag_even_word_arrived);
flag_even_word_arrived = 1;
}
volk_gnsssdr_free(page_part_bits);
return crc_ok;
}
bool decode_FNAV_word(double *page_symbols, int32_t frame_length)
{
// 1. De-interleave
double *page_symbols_deint = static_cast<double *>(volk_gnsssdr_malloc(frame_length * sizeof(double), volk_gnsssdr_get_alignment()));
deinterleaver(GALILEO_FNAV_INTERLEAVER_ROWS, GALILEO_FNAV_INTERLEAVER_COLS, page_symbols, page_symbols_deint);
// 2. Viterbi decoder
// 2.1 Take into account the NOT gate in G2 polynomial (Galileo ICD Figure 13, FEC encoder)
// 2.2 Take into account the possible inversion of the polarity due to PLL lock at 180
for (int32_t i = 0; i < frame_length; i++)
{
if ((i + 1) % 2 == 0)
{
page_symbols_deint[i] = -page_symbols_deint[i];
}
}
int32_t *page_bits = static_cast<int32_t *>(volk_gnsssdr_malloc((frame_length / 2) * sizeof(int32_t), volk_gnsssdr_get_alignment()));
const int32_t CodeLength = 488;
int32_t DataLength = (CodeLength / nn) - mm;
viterbi_decoder(page_symbols_deint, page_bits, DataLength);
volk_gnsssdr_free(page_symbols_deint);
// 3. Call the Galileo page decoder
std::string page_String;
for (int32_t i = 0; i < frame_length; i++)
{
if (page_bits[i] > 0)
{
page_String.push_back('1');
}
else
{
page_String.push_back('0');
}
}
volk_gnsssdr_free(page_bits);
// DECODE COMPLETE WORD (even + odd) and TEST CRC
FNAV_decoder.split_page(page_String);
if (FNAV_decoder.flag_CRC_test == true)
{
std::cout << "Galileo E5a FNAV PAGE CRC correct \n";
return true;
}
else
{
return false;
}
}
Galileo_FNAV_INAV_test()
{
// vars for Viterbi decoder
int32_t max_states = 1 << mm; // 2^mm
g_encoder[0] = 121; // Polynomial G1
g_encoder[1] = 91; // Polynomial G2
out0 = static_cast<int32_t *>(volk_gnsssdr_malloc(max_states * sizeof(int32_t), volk_gnsssdr_get_alignment()));
out1 = static_cast<int32_t *>(volk_gnsssdr_malloc(max_states * sizeof(int32_t), volk_gnsssdr_get_alignment()));
state0 = static_cast<int32_t *>(volk_gnsssdr_malloc(max_states * sizeof(int32_t), volk_gnsssdr_get_alignment()));
state1 = static_cast<int32_t *>(volk_gnsssdr_malloc(max_states * sizeof(int32_t), volk_gnsssdr_get_alignment()));
// create appropriate transition matrices
nsc_transit(out0, state0, 0, g_encoder, KK, nn);
nsc_transit(out1, state1, 1, g_encoder, KK, nn);
flag_even_word_arrived = 0;
}
~Galileo_FNAV_INAV_test()
{
volk_gnsssdr_free(out0);
volk_gnsssdr_free(out1);
volk_gnsssdr_free(state0);
volk_gnsssdr_free(state1);
}
};
TEST_F(Galileo_FNAV_INAV_test, ValidationOfResults)
{
std::chrono::time_point<std::chrono::system_clock> start, end;
std::chrono::duration<double> elapsed_seconds(0);
int repetitions = 10;
// FNAV FULLY ENCODED FRAME
double FNAV_frame[488] = {-1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
-1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1,
-1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1,
-1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1,
-1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1,
-1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1,
-1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1,
1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1,
-1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1,
1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1,
-1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1,
1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1,
1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1};
ASSERT_NO_THROW({
for (int n = 0; n < repetitions; n++)
{
EXPECT_EQ(decode_FNAV_word(&FNAV_frame[0], 488), true);
}
}) << "Exception during FNAV frame decoding";
// INAV FULLY ENCODED FRAME
double INAV_frame_even[240] = {-1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1,
1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1,
-1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1};
double INAV_frame_odd[240] = {1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1,
1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
-1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1,
1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1,
1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1,
1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1,
-1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1,
1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1,
1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1,
-1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1,
-1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1,
1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1};
ASSERT_NO_THROW({
for (int n = 0; n < repetitions; n++)
{
decode_INAV_word(&INAV_frame_even[0], 240);
EXPECT_EQ(decode_INAV_word(&INAV_frame_odd[0], 240), true);
}
}) << "Exception during INAV frame decoding";
std::cout << "Galileo FNAV/INAV Test completed in " << elapsed_seconds.count() * 1e6 << " microseconds" << std::endl;
}