2012-07-12 21:17:37 +00:00
/*!
* \ file galileo_e1_signal_processing . cc
* \ brief This library implements various functions for Galileo E1 signals
* \ author Luis Esteve , 2012. luis ( at ) epsilon - formacion . com
*
* Detailed description of the file here if needed .
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
2018-05-13 20:49:11 +00:00
* Copyright ( C ) 2010 - 2018 ( see AUTHORS file for a list of contributors )
2012-07-12 21:17:37 +00:00
*
* 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
2015-01-08 18:49:59 +00:00
* ( at your option ) any later version .
2012-07-12 21:17:37 +00:00
*
* 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
2018-05-13 20:49:11 +00:00
* along with GNSS - SDR . If not , see < https : //www.gnu.org/licenses/>.
2012-07-12 21:17:37 +00:00
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
# include "galileo_e1_signal_processing.h"
2016-01-10 21:21:31 +00:00
# include "Galileo_E1.h"
# include "gnss_signal_processing.h"
2018-08-16 12:16:43 +00:00
# include <volk_gnsssdr/volk_gnsssdr.h>
2019-06-30 02:47:15 +00:00
# include <memory>
2018-02-26 02:15:53 +00:00
# include <string>
2014-01-12 20:07:38 +00:00
2012-07-12 21:17:37 +00:00
2019-06-29 11:57:00 +00:00
void galileo_e1_code_gen_int ( gsl : : span < int > _dest , const std : : array < char , 3 > & _Signal , int32_t _prn )
2012-07-12 21:17:37 +00:00
{
2019-06-28 23:28:30 +00:00
std : : string _galileo_signal = _Signal . data ( ) ;
2018-08-13 08:18:05 +00:00
int32_t prn = _prn - 1 ;
int32_t index = 0 ;
2012-07-12 21:17:37 +00:00
2018-08-16 12:16:43 +00:00
// A simple error check
2012-07-12 21:17:37 +00:00
if ( ( _prn < 1 ) | | ( _prn > 50 ) )
{
return ;
}
2012-10-17 16:05:35 +00:00
if ( _galileo_signal . rfind ( " 1B " ) ! = std : : string : : npos & & _galileo_signal . length ( ) > = 2 )
2012-07-12 21:17:37 +00:00
{
2019-02-22 09:47:24 +00:00
for ( char i : GALILEO_E1_B_PRIMARY_CODE [ prn ] )
2012-07-12 21:17:37 +00:00
{
2019-06-29 10:55:39 +00:00
hex_to_binary_converter ( _dest . subspan ( index , 4 ) , i ) ;
2018-03-16 11:21:13 +00:00
index + = 4 ;
2012-07-12 21:17:37 +00:00
}
}
2012-10-17 16:05:35 +00:00
else if ( _galileo_signal . rfind ( " 1C " ) ! = std : : string : : npos & & _galileo_signal . length ( ) > = 2 )
2012-07-12 21:17:37 +00:00
{
2019-02-22 09:47:24 +00:00
for ( char i : GALILEO_E1_C_PRIMARY_CODE [ prn ] )
2012-07-12 21:17:37 +00:00
{
2019-06-29 10:55:39 +00:00
hex_to_binary_converter ( _dest . subspan ( index , 4 ) , i ) ;
2018-03-16 11:21:13 +00:00
index + = 4 ;
2012-07-12 21:17:37 +00:00
}
}
}
2012-10-28 12:38:11 +00:00
2019-06-28 23:28:30 +00:00
void galileo_e1_sinboc_11_gen_int ( gsl : : span < int > _dest , gsl : : span < const int > _prn )
2012-07-12 21:17:37 +00:00
{
2019-02-22 09:47:24 +00:00
const uint32_t _length_in = GALILEO_E1_B_CODE_LENGTH_CHIPS ;
2019-06-28 23:28:30 +00:00
auto _period = static_cast < uint32_t > ( _dest . size ( ) / _length_in ) ;
2018-08-13 08:18:05 +00:00
for ( uint32_t i = 0 ; i < _length_in ; i + + )
2012-07-12 21:17:37 +00:00
{
2018-08-13 08:18:05 +00:00
for ( uint32_t j = 0 ; j < ( _period / 2 ) ; j + + )
2015-03-16 23:22:20 +00:00
{
2017-09-11 14:21:05 +00:00
_dest [ i * _period + j ] = _prn [ i ] ;
2015-03-16 23:22:20 +00:00
}
2018-08-13 08:18:05 +00:00
for ( uint32_t j = ( _period / 2 ) ; j < _period ; j + + )
2015-03-16 23:22:20 +00:00
{
2018-03-03 01:03:39 +00:00
_dest [ i * _period + j ] = - _prn [ i ] ;
2015-03-16 23:22:20 +00:00
}
2012-07-12 21:17:37 +00:00
}
}
2012-10-28 12:38:11 +00:00
2019-06-28 23:28:30 +00:00
void galileo_e1_sinboc_61_gen_int ( gsl : : span < int > _dest , gsl : : span < const int > _prn )
2012-07-12 21:17:37 +00:00
{
2019-02-22 09:47:24 +00:00
const uint32_t _length_in = GALILEO_E1_B_CODE_LENGTH_CHIPS ;
2019-06-28 23:28:30 +00:00
auto _period = static_cast < uint32_t > ( _dest . size ( ) / _length_in ) ;
2012-07-12 21:17:37 +00:00
2018-08-13 08:18:05 +00:00
for ( uint32_t i = 0 ; i < _length_in ; i + + )
2012-07-12 21:17:37 +00:00
{
2018-08-13 08:18:05 +00:00
for ( uint32_t j = 0 ; j < _period ; j + = 2 )
2015-03-16 23:22:20 +00:00
{
2017-09-11 14:21:05 +00:00
_dest [ i * _period + j ] = _prn [ i ] ;
2015-03-16 23:22:20 +00:00
}
2018-08-13 08:18:05 +00:00
for ( uint32_t j = 1 ; j < _period ; j + = 2 )
2015-03-16 23:22:20 +00:00
{
2018-03-03 01:03:39 +00:00
_dest [ i * _period + j ] = - _prn [ i ] ;
2015-03-16 23:22:20 +00:00
}
2012-07-12 21:17:37 +00:00
}
}
2012-10-28 12:38:11 +00:00
2018-08-13 08:18:05 +00:00
2019-06-29 11:57:00 +00:00
void galileo_e1_code_gen_sinboc11_float ( gsl : : span < float > _dest , const std : : array < char , 3 > & _Signal , uint32_t _prn )
2018-03-16 11:21:13 +00:00
{
2019-06-28 23:28:30 +00:00
std : : string _galileo_signal = _Signal . data ( ) ;
2019-02-22 09:47:24 +00:00
const auto _codeLength = static_cast < uint32_t > ( GALILEO_E1_B_CODE_LENGTH_CHIPS ) ;
2018-08-13 08:18:05 +00:00
int32_t primary_code_E1_chips [ 4092 ] ; // _codeLength not accepted by Clang
2018-03-16 11:21:13 +00:00
galileo_e1_code_gen_int ( primary_code_E1_chips , _Signal , _prn ) ; //generate Galileo E1 code, 1 sample per chip
2018-08-13 08:18:05 +00:00
for ( uint32_t i = 0 ; i < _codeLength ; i + + )
2018-03-16 11:21:13 +00:00
{
_dest [ 2 * i ] = static_cast < float > ( primary_code_E1_chips [ i ] ) ;
_dest [ 2 * i + 1 ] = - _dest [ 2 * i ] ;
}
}
2012-10-28 12:38:11 +00:00
2018-08-13 08:18:05 +00:00
2019-06-29 11:57:00 +00:00
void galileo_e1_gen_float ( gsl : : span < float > _dest , gsl : : span < int > _prn , const std : : array < char , 3 > & _Signal )
2012-07-12 21:17:37 +00:00
{
2019-06-28 23:28:30 +00:00
std : : string _galileo_signal = _Signal . data ( ) ;
2019-02-22 09:47:24 +00:00
const uint32_t _codeLength = 12 * GALILEO_E1_B_CODE_LENGTH_CHIPS ;
2012-07-12 21:17:37 +00:00
const float alpha = sqrt ( 10.0 / 11.0 ) ;
const float beta = sqrt ( 1.0 / 11.0 ) ;
2018-11-23 15:28:28 +00:00
int32_t sinboc_11 [ 12 * 4092 ] = { 0 } ; // _codeLength not accepted by Clang
int32_t sinboc_61 [ 12 * 4092 ] = { 0 } ;
2019-06-28 23:28:30 +00:00
gsl : : span < int32_t > sinboc_11_ ( sinboc_11 , _codeLength ) ;
gsl : : span < int32_t > sinboc_61_ ( sinboc_61 , _codeLength ) ;
2012-07-12 21:17:37 +00:00
2019-06-28 23:28:30 +00:00
galileo_e1_sinboc_11_gen_int ( sinboc_11_ , _prn ) ; //generate sinboc(1,1) 12 samples per chip
galileo_e1_sinboc_61_gen_int ( sinboc_61_ , _prn ) ; //generate sinboc(6,1) 12 samples per chip
2012-07-12 21:17:37 +00:00
2012-10-17 16:05:35 +00:00
if ( _galileo_signal . rfind ( " 1B " ) ! = std : : string : : npos & & _galileo_signal . length ( ) > = 2 )
2012-07-12 21:17:37 +00:00
{
2018-08-13 08:18:05 +00:00
for ( uint32_t i = 0 ; i < _codeLength ; i + + )
2012-07-12 21:17:37 +00:00
{
2018-03-03 01:03:39 +00:00
_dest [ i ] = alpha * static_cast < float > ( sinboc_11 [ i ] ) +
beta * static_cast < float > ( sinboc_61 [ i ] ) ;
2012-07-12 21:17:37 +00:00
}
}
2012-10-17 16:05:35 +00:00
else if ( _galileo_signal . rfind ( " 1C " ) ! = std : : string : : npos & & _galileo_signal . length ( ) > = 2 )
2012-07-12 21:17:37 +00:00
{
2018-08-13 08:18:05 +00:00
for ( uint32_t i = 0 ; i < _codeLength ; i + + )
2012-07-12 21:17:37 +00:00
{
2018-03-03 01:03:39 +00:00
_dest [ i ] = alpha * static_cast < float > ( sinboc_11 [ i ] ) -
beta * static_cast < float > ( sinboc_61 [ i ] ) ;
2012-07-12 21:17:37 +00:00
}
}
}
2012-10-28 12:38:11 +00:00
2019-06-29 11:57:00 +00:00
void galileo_e1_code_gen_float_sampled ( gsl : : span < float > _dest , const std : : array < char , 3 > & _Signal ,
2018-08-13 08:18:05 +00:00
bool _cboc , uint32_t _prn , int32_t _fs , uint32_t _chip_shift ,
2018-03-03 01:03:39 +00:00
bool _secondary_flag )
2012-07-12 21:17:37 +00:00
{
2013-11-09 10:51:11 +00:00
// This function is based on the GNU software GPS for MATLAB in Kay Borre's book
2019-06-28 23:28:30 +00:00
std : : string _galileo_signal = _Signal . data ( ) ;
2018-08-13 08:18:05 +00:00
uint32_t _samplesPerCode ;
2019-02-22 09:47:24 +00:00
const int32_t _codeFreqBasis = GALILEO_E1_CODE_CHIP_RATE_HZ ; // Hz
auto _codeLength = static_cast < uint32_t > ( GALILEO_E1_B_CODE_LENGTH_CHIPS ) ;
auto * primary_code_E1_chips = static_cast < int32_t * > ( volk_gnsssdr_malloc ( static_cast < uint32_t > ( GALILEO_E1_B_CODE_LENGTH_CHIPS ) * sizeof ( int32_t ) , volk_gnsssdr_get_alignment ( ) ) ) ;
2018-08-16 12:16:43 +00:00
2018-08-13 08:18:05 +00:00
_samplesPerCode = static_cast < uint32_t > ( static_cast < double > ( _fs ) / ( static_cast < double > ( _codeFreqBasis ) / static_cast < double > ( _codeLength ) ) ) ;
const int32_t _samplesPerChip = ( _cboc = = true ) ? 12 : 2 ;
2013-07-23 18:03:07 +00:00
2019-02-22 09:47:24 +00:00
const uint32_t delay = ( ( static_cast < int32_t > ( GALILEO_E1_B_CODE_LENGTH_CHIPS ) - _chip_shift ) % static_cast < int32_t > ( GALILEO_E1_B_CODE_LENGTH_CHIPS ) ) * _samplesPerCode / GALILEO_E1_B_CODE_LENGTH_CHIPS ;
2012-07-12 21:17:37 +00:00
2019-06-28 23:28:30 +00:00
galileo_e1_code_gen_int ( gsl : : span < int32_t > ( primary_code_E1_chips , static_cast < uint32_t > ( GALILEO_E1_B_CODE_LENGTH_CHIPS ) ) , _Signal , _prn ) ; // generate Galileo E1 code, 1 sample per chip
2012-07-12 21:17:37 +00:00
2019-02-22 09:47:24 +00:00
_codeLength = _samplesPerChip * GALILEO_E1_B_CODE_LENGTH_CHIPS ;
2019-06-30 02:47:15 +00:00
std : : unique_ptr < float > _signal_E1 { new float [ _codeLength ] } ;
2019-06-29 10:55:39 +00:00
gsl : : span < float > _signal_E1_span ( _signal_E1 , _codeLength ) ;
2019-06-29 14:49:53 +00:00
2012-07-12 21:17:37 +00:00
if ( _cboc = = true )
{
2019-06-29 14:49:53 +00:00
galileo_e1_gen_float ( _signal_E1_span , gsl : : span < int > ( primary_code_E1_chips , static_cast < uint32_t > ( GALILEO_E1_B_CODE_LENGTH_CHIPS ) ) , _Signal ) ; // generate cboc 12 samples per chip
2012-07-12 21:17:37 +00:00
}
else
{
2018-12-03 15:25:11 +00:00
auto * _signal_E1_int = static_cast < int32_t * > ( volk_gnsssdr_malloc ( _codeLength * sizeof ( int32_t ) , volk_gnsssdr_get_alignment ( ) ) ) ;
2019-06-29 10:55:39 +00:00
gsl : : span < int32_t > _signal_E1_int_span ( _signal_E1_int , _codeLength ) ;
2019-06-29 14:49:53 +00:00
galileo_e1_sinboc_11_gen_int ( _signal_E1_int_span , gsl : : span < int > ( primary_code_E1_chips , static_cast < uint32_t > ( GALILEO_E1_B_CODE_LENGTH_CHIPS ) ) ) ; // generate sinboc(1,1) 2 samples per chip
2017-09-11 14:21:05 +00:00
2018-08-13 08:18:05 +00:00
for ( uint32_t ii = 0 ; ii < _codeLength ; + + ii )
2017-09-11 14:21:05 +00:00
{
2019-06-29 10:55:39 +00:00
_signal_E1_span [ ii ] = static_cast < float > ( _signal_E1_int_span [ ii ] ) ;
2017-09-11 14:21:05 +00:00
}
2018-08-16 12:16:43 +00:00
volk_gnsssdr_free ( _signal_E1_int ) ;
2012-07-12 21:17:37 +00:00
}
2013-07-23 18:03:07 +00:00
if ( _fs ! = _samplesPerChip * _codeFreqBasis )
{
2019-06-30 02:47:15 +00:00
std : : unique_ptr < float > _resampled_signal { new float [ _samplesPerCode ] } ;
2018-08-16 12:16:43 +00:00
2019-06-28 23:28:30 +00:00
resampler ( gsl : : span < float > ( _signal_E1 , _codeLength ) , gsl : : span < float > ( _resampled_signal , _samplesPerCode ) , _samplesPerChip * _codeFreqBasis , _fs ) ; // resamples code to fs
2013-07-23 18:03:07 +00:00
2019-06-30 02:47:15 +00:00
_signal_E1 = std : : move ( _resampled_signal ) ;
2013-07-23 18:03:07 +00:00
}
2019-06-29 15:29:51 +00:00
uint32_t size_signal_E1 = _codeLength ;
if ( _fs ! = _samplesPerChip * _codeFreqBasis )
{
size_signal_E1 = _samplesPerCode ;
}
gsl : : span < float > _signal_E1_span_aux ( _signal_E1 , size_signal_E1 ) ;
2013-07-23 18:03:07 +00:00
if ( _galileo_signal . rfind ( " 1C " ) ! = std : : string : : npos & & _galileo_signal . length ( ) > = 2 & & _secondary_flag )
2017-09-15 23:14:15 +00:00
{
2019-06-30 02:47:15 +00:00
std : : unique_ptr < float > _signal_E1C_secondary { new float [ static_cast < int32_t > ( GALILEO_E1_C_SECONDARY_CODE_LENGTH ) * _samplesPerCode ] } ;
2019-06-29 10:55:39 +00:00
gsl : : span < float > _signal_E1C_secondary_span ( _signal_E1C_secondary , static_cast < int32_t > ( GALILEO_E1_C_SECONDARY_CODE_LENGTH ) * _samplesPerCode ) ;
2019-02-22 09:47:24 +00:00
for ( uint32_t i = 0 ; i < static_cast < uint32_t > ( GALILEO_E1_C_SECONDARY_CODE_LENGTH ) ; i + + )
2017-09-15 23:14:15 +00:00
{
for ( unsigned k = 0 ; k < _samplesPerCode ; k + + )
{
2019-06-29 22:01:54 +00:00
_signal_E1C_secondary_span [ i * _samplesPerCode + k ] = _signal_E1_span_aux [ k ] * ( GALILEO_E1_C_SECONDARY_CODE . at ( i ) = = ' 0 ' ? 1.0F : - 1.0F ) ;
2017-09-15 23:14:15 +00:00
}
}
2013-07-23 18:03:07 +00:00
2019-02-22 09:47:24 +00:00
_samplesPerCode * = static_cast < int32_t > ( GALILEO_E1_C_SECONDARY_CODE_LENGTH ) ;
2013-07-23 18:03:07 +00:00
2019-06-30 02:47:15 +00:00
_signal_E1 = std : : move ( _signal_E1C_secondary ) ;
2017-09-15 23:14:15 +00:00
}
2019-06-29 15:29:51 +00:00
if ( _galileo_signal . rfind ( " 1C " ) ! = std : : string : : npos & & _galileo_signal . length ( ) > = 2 & & _secondary_flag )
{
size_signal_E1 = static_cast < int32_t > ( GALILEO_E1_C_SECONDARY_CODE_LENGTH ) * _samplesPerCode ;
}
gsl : : span < float > _signal_E1_span_aux2 ( _signal_E1 , size_signal_E1 ) ;
2018-08-13 08:18:05 +00:00
for ( uint32_t i = 0 ; i < _samplesPerCode ; i + + )
2013-07-23 18:03:07 +00:00
{
2019-06-29 15:29:51 +00:00
_dest [ ( i + delay ) % _samplesPerCode ] = _signal_E1_span_aux2 [ i ] ;
2013-07-23 18:03:07 +00:00
}
2018-08-16 12:16:43 +00:00
volk_gnsssdr_free ( primary_code_E1_chips ) ;
2013-07-23 18:03:07 +00:00
}
2017-09-15 23:14:15 +00:00
2019-06-29 11:57:00 +00:00
void galileo_e1_code_gen_complex_sampled ( gsl : : span < std : : complex < float > > _dest , const std : : array < char , 3 > & _Signal ,
2018-08-13 08:18:05 +00:00
bool _cboc , uint32_t _prn , int32_t _fs , uint32_t _chip_shift ,
2018-03-03 01:03:39 +00:00
bool _secondary_flag )
2017-09-11 14:21:05 +00:00
{
2019-06-28 23:28:30 +00:00
std : : string _galileo_signal = _Signal . data ( ) ;
2019-02-22 09:47:24 +00:00
const int32_t _codeFreqBasis = GALILEO_E1_CODE_CHIP_RATE_HZ ; // Hz
2018-12-03 15:25:11 +00:00
auto _samplesPerCode = static_cast < uint32_t > ( static_cast < double > ( _fs ) /
2019-02-22 09:47:24 +00:00
( static_cast < double > ( _codeFreqBasis ) / static_cast < double > ( GALILEO_E1_B_CODE_LENGTH_CHIPS ) ) ) ;
2017-09-11 14:21:05 +00:00
if ( _galileo_signal . rfind ( " 1C " ) ! = std : : string : : npos & & _galileo_signal . length ( ) > = 2 & & _secondary_flag )
2017-09-15 23:14:15 +00:00
{
2019-02-22 09:47:24 +00:00
_samplesPerCode * = static_cast < int32_t > ( GALILEO_E1_C_SECONDARY_CODE_LENGTH ) ;
2017-09-15 23:14:15 +00:00
}
2017-09-11 14:21:05 +00:00
2018-12-03 15:25:11 +00:00
auto * real_code = static_cast < float * > ( volk_gnsssdr_malloc ( _samplesPerCode * sizeof ( float ) , volk_gnsssdr_get_alignment ( ) ) ) ;
2019-06-29 10:55:39 +00:00
gsl : : span < float > real_code_span ( real_code , _samplesPerCode ) ;
galileo_e1_code_gen_float_sampled ( real_code_span , _Signal , _cboc , _prn , _fs , _chip_shift , _secondary_flag ) ;
2017-09-11 14:21:05 +00:00
2018-08-13 08:18:05 +00:00
for ( uint32_t ii = 0 ; ii < _samplesPerCode ; + + ii )
2017-09-11 14:21:05 +00:00
{
2019-06-29 12:22:15 +00:00
_dest [ ii ] = std : : complex < float > ( real_code_span [ ii ] , 0.0F ) ;
2017-09-11 14:21:05 +00:00
}
2018-08-16 12:16:43 +00:00
volk_gnsssdr_free ( real_code ) ;
2017-09-11 14:21:05 +00:00
}
2017-09-15 23:14:15 +00:00
2019-06-29 11:57:00 +00:00
void galileo_e1_code_gen_float_sampled ( gsl : : span < float > _dest , const std : : array < char , 3 > & _Signal ,
2018-08-13 08:18:05 +00:00
bool _cboc , uint32_t _prn , int32_t _fs , uint32_t _chip_shift )
2017-09-11 14:21:05 +00:00
{
galileo_e1_code_gen_float_sampled ( _dest , _Signal , _cboc , _prn , _fs , _chip_shift , false ) ;
}
2013-07-23 18:03:07 +00:00
2017-09-15 23:14:15 +00:00
2019-06-29 11:57:00 +00:00
void galileo_e1_code_gen_complex_sampled ( gsl : : span < std : : complex < float > > _dest , const std : : array < char , 3 > & _Signal ,
2018-08-13 08:18:05 +00:00
bool _cboc , uint32_t _prn , int32_t _fs , uint32_t _chip_shift )
2013-07-23 18:03:07 +00:00
{
2015-03-16 23:22:20 +00:00
galileo_e1_code_gen_complex_sampled ( _dest , _Signal , _cboc , _prn , _fs , _chip_shift , false ) ;
2012-07-12 21:17:37 +00:00
}