2018-08-27 16:05:19 +00:00
/*!
2019-03-02 01:21:03 +00:00
* \ file galileo_telemetry_decoder_gs . cc
2020-07-28 18:53:08 +00:00
* \ brief Implementation of a Galileo unified INAV and FNAV message demodulator
* block
2018-08-27 16:05:19 +00:00
* \ author Javier Arribas 2018. jarribas ( at ) cttc . es
2021-09-25 18:29:51 +00:00
* \ author Carles Fernandez , 2021. cfernandez ( at ) cttc . es
2018-08-27 16:05:19 +00:00
*
2020-07-28 18:53:08 +00:00
*
2020-07-28 14:57:15 +00:00
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2018-08-27 16:05:19 +00:00
*
2020-12-30 12:35:06 +00:00
* GNSS - SDR is a Global Navigation Satellite System software - defined receiver .
2018-08-27 16:05:19 +00:00
* This file is part of GNSS - SDR .
*
2020-12-30 12:35:06 +00:00
* Copyright ( C ) 2010 - 2020 ( see AUTHORS file for a list of contributors )
2020-02-08 00:20:02 +00:00
* SPDX - License - Identifier : GPL - 3.0 - or - later
2018-08-27 16:05:19 +00:00
*
2020-07-28 14:57:15 +00:00
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2018-08-27 16:05:19 +00:00
*/
2019-03-03 12:39:35 +00:00
# include "galileo_telemetry_decoder_gs.h"
2021-09-25 18:29:51 +00:00
# include "Galileo_E1.h" // for GALILEO_E1_CODE_PERIOD_MS
# include "Galileo_E5a.h" // for GALILEO_E5A_CODE_PERIOD_MS
# include "Galileo_E5b.h" // for GALILEO_E5B_CODE_PERIOD_MS
# include "Galileo_E6.h" // for GALILEO_E6_CODE_PERIOD_MS
# include "display.h" // for colours in terminal: TEXT_BLUE, TEXT_RESET, ...
2019-03-05 21:17:09 +00:00
# include "galileo_almanac_helper.h" // for Galileo_Almanac_Helper
# include "galileo_ephemeris.h" // for Galileo_Ephemeris
2021-06-02 14:30:26 +00:00
# include "galileo_has_page.h" // For Galileo_HAS_page
2019-03-05 21:17:09 +00:00
# include "galileo_iono.h" // for Galileo_Iono
# include "galileo_utc_model.h" // for Galileo_Utc_Model
2021-09-13 21:19:37 +00:00
# include "gnss_sdr_make_unique.h" // for std::make_unique in C++11
2021-09-25 18:29:51 +00:00
# include "gnss_synchro.h" // for Gnss_Synchro
# include "tlm_crc_stats.h" // for Tlm_CRC_Stats
# include "tlm_utils.h" // for save_tlm_matfile, tlm_remove_file
# include "viterbi_decoder.h" // for Viterbi_Decoder
# include <glog/logging.h> // for LOG, DLOG
# include <gnuradio/io_signature.h> // for gr::io_signature::make
# include <pmt/pmt.h> // for pmt::make_any
# include <pmt/pmt_sugar.h> // for pmt::mp
# include <array> // for std::array
# include <cmath> // for std::fmod, std::abs
# include <cstddef> // for size_t
# include <exception> // for std::exception
# include <iostream> // for std::cout
2018-08-27 16:05:19 +00:00
# define CRC_ERROR_LIMIT 6
2019-03-02 01:21:03 +00:00
galileo_telemetry_decoder_gs_sptr
2020-11-21 18:37:22 +00:00
galileo_make_telemetry_decoder_gs ( const Gnss_Satellite & satellite , const Tlm_Conf & conf , int frame_type )
2018-08-27 16:05:19 +00:00
{
2020-11-21 18:37:22 +00:00
return galileo_telemetry_decoder_gs_sptr ( new galileo_telemetry_decoder_gs ( satellite , conf , frame_type ) ) ;
2018-08-27 16:05:19 +00:00
}
2019-03-02 01:21:03 +00:00
galileo_telemetry_decoder_gs : : galileo_telemetry_decoder_gs (
2020-11-21 18:37:22 +00:00
const Gnss_Satellite & satellite ,
const Tlm_Conf & conf ,
int frame_type ) : gr : : block ( " galileo_telemetry_decoder_gs " , gr : : io_signature : : make ( 1 , 1 , sizeof ( Gnss_Synchro ) ) ,
2021-10-10 16:56:14 +00:00
gr : : io_signature : : make ( 1 , 1 , sizeof ( Gnss_Synchro ) ) ) ,
d_dump_filename ( conf . dump_filename ) ,
d_delta_t ( 0 ) ,
d_sample_counter ( 0ULL ) ,
d_preamble_index ( 0ULL ) ,
d_last_valid_preamble ( 0 ) ,
d_frame_type ( frame_type ) ,
d_CRC_error_counter ( 0 ) ,
d_channel ( 0 ) ,
d_flag_even_word_arrived ( 0 ) ,
d_stat ( 0 ) ,
d_TOW_at_Preamble_ms ( 0 ) ,
d_TOW_at_current_symbol_ms ( 0 ) ,
d_band ( ' 1 ' ) ,
d_sent_tlm_failed_msg ( false ) ,
d_flag_frame_sync ( false ) ,
d_flag_PLL_180_deg_phase_locked ( false ) ,
d_flag_preamble ( false ) ,
d_dump ( conf . dump ) ,
d_dump_mat ( conf . dump_mat ) ,
d_remove_dat ( conf . remove_dat ) ,
d_first_eph_sent ( false ) ,
d_cnav_dummy_page ( false ) ,
d_print_cnav_page ( true ) ,
d_enable_navdata_monitor ( conf . enable_navdata_monitor ) ,
d_dump_crc_stats ( conf . dump_crc_stats ) ,
d_enable_reed_solomon_inav ( false )
2018-08-27 16:05:19 +00:00
{
2019-07-19 16:23:36 +00:00
// prevent telemetry symbols accumulation in output buffers
2019-07-04 15:19:33 +00:00
this - > set_max_noutput_items ( 1 ) ;
2018-08-27 16:05:19 +00:00
// Ephemeris data port out
this - > message_port_register_out ( pmt : : mp ( " telemetry " ) ) ;
2019-03-18 15:28:49 +00:00
// Control messages to tracking block
this - > message_port_register_out ( pmt : : mp ( " telemetry_to_trk " ) ) ;
2021-06-02 19:43:29 +00:00
// register Gal E6 messages HAS out
2021-06-02 15:13:46 +00:00
this - > message_port_register_out ( pmt : : mp ( " E6_HAS_from_TLM " ) ) ;
2021-10-10 16:56:14 +00:00
2021-09-05 22:05:29 +00:00
if ( d_enable_navdata_monitor )
{
// register nav message monitor out
this - > message_port_register_out ( pmt : : mp ( " Nav_msg_from_TLM " ) ) ;
}
2021-10-10 16:56:14 +00:00
2018-08-27 16:05:19 +00:00
d_satellite = Gnss_Satellite ( satellite . get_system ( ) , satellite . get_PRN ( ) ) ;
2021-09-25 18:29:51 +00:00
// Viterbi decoder vars
const int32_t nn = 2 ; // Coding rate 1/n
const int32_t KK = 7 ; // Constraint Length
const std : : array < int32_t , 2 > g_encoder { { 121 , 91 } } ; // Polynomial G1 and G2
d_mm = KK - 1 ;
2019-03-01 15:48:10 +00:00
DLOG ( INFO ) < < " Initializing GALILEO UNIFIED TELEMETRY DECODER " ;
2018-08-27 16:05:19 +00:00
2021-08-30 10:51:31 +00:00
if ( d_dump_crc_stats )
{
// initialize the telemetry CRC statistics class
2021-09-13 21:19:37 +00:00
d_Tlm_CRC_Stats = std : : make_unique < Tlm_CRC_Stats > ( ) ;
d_Tlm_CRC_Stats - > initialize ( conf . dump_crc_stats_filename ) ;
}
else
{
d_Tlm_CRC_Stats = nullptr ;
2021-08-30 10:51:31 +00:00
}
2021-10-10 16:56:14 +00:00
2018-08-27 16:05:19 +00:00
switch ( d_frame_type )
{
2018-08-30 17:24:28 +00:00
case 1 : // INAV
2018-08-27 16:05:19 +00:00
{
2020-12-22 09:59:13 +00:00
d_PRN_code_period_ms = GALILEO_E1_CODE_PERIOD_MS ; // for Galileo E5b is also 4 ms
2018-08-27 16:05:19 +00:00
d_bits_per_preamble = GALILEO_INAV_PREAMBLE_LENGTH_BITS ;
// set the preamble
2019-07-01 09:00:38 +00:00
d_samples_per_preamble = GALILEO_INAV_PREAMBLE_LENGTH_BITS ;
2018-08-27 16:05:19 +00:00
d_preamble_period_symbols = GALILEO_INAV_PREAMBLE_PERIOD_SYMBOLS ;
2020-12-22 09:59:13 +00:00
d_required_symbols = GALILEO_INAV_PAGE_SYMBOLS + d_samples_per_preamble ;
2018-08-27 16:05:19 +00:00
// preamble bits to sampled symbols
2021-09-23 17:06:00 +00:00
d_preamble_samples = std : : vector < int32_t > ( d_samples_per_preamble ) ;
2018-08-27 16:05:19 +00:00
d_frame_length_symbols = GALILEO_INAV_PAGE_PART_SYMBOLS - GALILEO_INAV_PREAMBLE_LENGTH_BITS ;
2020-12-22 09:59:13 +00:00
d_codelength = static_cast < int32_t > ( d_frame_length_symbols ) ;
2021-09-25 18:29:51 +00:00
d_datalength = ( d_codelength / nn ) - d_mm ;
2019-07-28 10:01:11 +00:00
d_max_symbols_without_valid_frame = GALILEO_INAV_PAGE_SYMBOLS * 30 ; // rise alarm 60 seconds without valid tlm
2021-04-19 11:26:46 +00:00
if ( conf . enable_reed_solomon = = true )
{
2021-10-04 20:02:47 +00:00
d_enable_reed_solomon_inav = true ;
2021-04-19 11:26:46 +00:00
d_inav_nav . enable_reed_solomon ( ) ;
}
2018-08-27 16:05:19 +00:00
break ;
}
2018-08-30 17:24:28 +00:00
case 2 : // FNAV
2018-08-27 16:05:19 +00:00
{
2019-07-01 09:00:38 +00:00
d_PRN_code_period_ms = static_cast < uint32_t > ( GALILEO_E5A_CODE_PERIOD_MS * GALILEO_E5A_I_SECONDARY_CODE_LENGTH ) ;
2018-08-27 16:05:19 +00:00
d_bits_per_preamble = GALILEO_FNAV_PREAMBLE_LENGTH_BITS ;
// set the preamble
2019-07-01 09:00:38 +00:00
d_samples_per_preamble = GALILEO_FNAV_PREAMBLE_LENGTH_BITS ;
d_preamble_period_symbols = GALILEO_FNAV_SYMBOLS_PER_PAGE ;
d_required_symbols = static_cast < uint32_t > ( GALILEO_FNAV_SYMBOLS_PER_PAGE ) + d_samples_per_preamble ;
2018-08-27 16:05:19 +00:00
// preamble bits to sampled symbols
2021-09-23 17:06:00 +00:00
d_preamble_samples = std : : vector < int32_t > ( d_samples_per_preamble ) ;
2018-08-27 16:05:19 +00:00
d_frame_length_symbols = GALILEO_FNAV_SYMBOLS_PER_PAGE - GALILEO_FNAV_PREAMBLE_LENGTH_BITS ;
2020-12-22 09:59:13 +00:00
d_codelength = static_cast < int32_t > ( d_frame_length_symbols ) ;
2021-09-25 18:29:51 +00:00
d_datalength = ( d_codelength / nn ) - d_mm ;
2019-07-28 10:01:11 +00:00
d_max_symbols_without_valid_frame = GALILEO_FNAV_SYMBOLS_PER_PAGE * 5 ; // rise alarm 100 seconds without valid tlm
2018-08-27 16:05:19 +00:00
break ;
}
2020-11-07 20:33:26 +00:00
case 3 : // CNAV
{
2020-12-22 09:59:13 +00:00
d_PRN_code_period_ms = GALILEO_E6_CODE_PERIOD_MS ;
2020-11-08 13:10:43 +00:00
d_bits_per_preamble = GALILEO_CNAV_PREAMBLE_LENGTH_BITS ;
d_samples_per_preamble = GALILEO_CNAV_PREAMBLE_LENGTH_BITS ;
d_preamble_period_symbols = GALILEO_CNAV_SYMBOLS_PER_PAGE ;
d_required_symbols = static_cast < uint32_t > ( GALILEO_CNAV_SYMBOLS_PER_PAGE ) + d_samples_per_preamble ;
2021-09-23 17:06:00 +00:00
d_preamble_samples = std : : vector < int32_t > ( d_samples_per_preamble ) ;
2020-11-08 13:10:43 +00:00
d_frame_length_symbols = GALILEO_CNAV_SYMBOLS_PER_PAGE - GALILEO_CNAV_PREAMBLE_LENGTH_BITS ;
2020-12-22 09:59:13 +00:00
d_codelength = static_cast < int32_t > ( d_frame_length_symbols ) ;
2021-09-25 18:29:51 +00:00
d_datalength = ( d_codelength / nn ) - d_mm ;
2020-11-08 13:10:43 +00:00
d_max_symbols_without_valid_frame = GALILEO_CNAV_SYMBOLS_PER_PAGE * 60 ;
2020-11-07 20:33:26 +00:00
break ;
}
2018-08-27 16:05:19 +00:00
default :
2018-08-30 19:45:58 +00:00
d_bits_per_preamble = 0 ;
d_samples_per_preamble = 0 ;
d_preamble_period_symbols = 0 ;
d_PRN_code_period_ms = 0U ;
d_required_symbols = 0U ;
2018-12-14 01:14:43 +00:00
d_frame_length_symbols = 0U ;
2020-06-19 00:15:56 +00:00
d_codelength = 0 ;
d_datalength = 0 ;
2019-03-18 15:28:49 +00:00
d_max_symbols_without_valid_frame = 0 ;
2020-07-19 07:39:32 +00:00
std : : cout < < " Galileo unified telemetry decoder error: Unknown frame type \n " ;
2018-08-27 16:05:19 +00:00
}
2021-09-23 17:06:00 +00:00
d_page_part_symbols = std : : vector < float > ( d_frame_length_symbols ) ;
2018-08-27 16:05:19 +00:00
for ( int32_t i = 0 ; i < d_bits_per_preamble ; i + + )
{
switch ( d_frame_type )
{
2018-08-30 17:24:28 +00:00
case 1 : // INAV
2018-08-27 16:05:19 +00:00
{
2019-09-09 14:00:17 +00:00
if ( GALILEO_INAV_PREAMBLE [ i ] = = ' 1 ' )
2018-08-27 16:05:19 +00:00
{
2019-07-01 09:00:38 +00:00
d_preamble_samples [ i ] = 1 ;
2018-08-27 16:05:19 +00:00
}
else
{
2019-07-01 09:00:38 +00:00
d_preamble_samples [ i ] = - 1 ;
2018-08-27 16:05:19 +00:00
}
break ;
}
2018-08-30 17:24:28 +00:00
case 2 : // FNAV for E5a-I
2018-08-27 16:05:19 +00:00
{
2019-09-09 14:00:17 +00:00
if ( GALILEO_FNAV_PREAMBLE [ i ] = = ' 1 ' )
2018-08-27 16:05:19 +00:00
{
2019-07-01 09:00:38 +00:00
d_preamble_samples [ i ] = 1 ;
2018-08-27 16:05:19 +00:00
}
else
{
2019-07-01 09:00:38 +00:00
d_preamble_samples [ i ] = - 1 ;
2018-08-27 16:05:19 +00:00
}
break ;
}
2020-11-07 20:33:26 +00:00
case 3 : // CNAV for E6
{
2020-11-08 13:10:43 +00:00
if ( GALILEO_CNAV_PREAMBLE [ i ] = = ' 1 ' )
{
d_preamble_samples [ i ] = 1 ;
}
else
{
d_preamble_samples [ i ] = - 1 ;
}
2020-11-07 20:33:26 +00:00
break ;
}
2018-08-27 16:05:19 +00:00
}
}
2021-10-10 16:56:14 +00:00
2019-02-28 12:40:09 +00:00
d_symbol_history . set_capacity ( d_required_symbols + 1 ) ;
2021-09-25 18:29:51 +00:00
d_inav_nav . init_PRN ( d_satellite . get_PRN ( ) ) ;
2021-09-26 11:23:28 +00:00
// Instantiate the Viterbi decoder
2021-09-25 18:29:51 +00:00
d_viterbi = std : : make_unique < Viterbi_Decoder > ( KK , nn , d_datalength , g_encoder ) ;
2018-08-27 16:05:19 +00:00
}
2019-03-02 01:21:03 +00:00
galileo_telemetry_decoder_gs : : ~ galileo_telemetry_decoder_gs ( )
2018-08-27 16:05:19 +00:00
{
2020-06-25 00:50:07 +00:00
DLOG ( INFO ) < < " Galileo Telemetry decoder block (channel " < < d_channel < < " ) destructor called. " ;
2020-11-21 12:14:55 +00:00
size_t pos = 0 ;
2018-08-27 16:05:19 +00:00
if ( d_dump_file . is_open ( ) = = true )
{
2020-11-21 12:14:55 +00:00
pos = d_dump_file . tellp ( ) ;
2018-08-27 16:05:19 +00:00
try
{
d_dump_file . close ( ) ;
}
catch ( const std : : exception & ex )
{
LOG ( WARNING ) < < " Exception in destructor closing the dump file " < < ex . what ( ) ;
}
2020-11-21 12:14:55 +00:00
if ( pos = = 0 )
{
2020-11-23 13:42:13 +00:00
if ( ! tlm_remove_file ( d_dump_filename ) )
2020-11-21 12:14:55 +00:00
{
LOG ( WARNING ) < < " Error deleting temporary file " ;
}
}
2018-08-27 16:05:19 +00:00
}
2020-11-21 18:37:22 +00:00
if ( d_dump & & ( pos ! = 0 ) & & d_dump_mat )
2020-11-19 08:55:08 +00:00
{
2020-11-23 13:42:13 +00:00
save_tlm_matfile ( d_dump_filename ) ;
2020-11-23 15:09:27 +00:00
if ( d_remove_dat )
{
if ( ! tlm_remove_file ( d_dump_filename ) )
{
LOG ( WARNING ) < < " Error deleting temporary file " ;
}
}
2020-11-19 08:55:08 +00:00
}
2018-08-27 16:05:19 +00:00
}
2019-09-06 15:31:31 +00:00
void galileo_telemetry_decoder_gs : : deinterleaver ( int32_t rows , int32_t cols , const float * in , float * out )
2019-02-28 12:40:09 +00:00
{
for ( int32_t r = 0 ; r < rows ; r + + )
{
for ( int32_t c = 0 ; c < cols ; c + + )
{
out [ c * rows + r ] = in [ r * cols + c ] ;
}
}
}
2019-09-06 15:31:31 +00:00
void galileo_telemetry_decoder_gs : : decode_INAV_word ( float * page_part_symbols , int32_t frame_length )
2018-08-27 16:05:19 +00:00
{
// 1. De-interleave
2021-09-25 18:29:51 +00:00
std : : vector < float > page_part_symbols_soft_value ( frame_length ) ;
deinterleaver ( GALILEO_INAV_INTERLEAVER_ROWS , GALILEO_INAV_INTERLEAVER_COLS , page_part_symbols , page_part_symbols_soft_value . data ( ) ) ;
2018-08-27 16:05:19 +00:00
// 2. Viterbi decoder
// 2.1 Take into account the NOT gate in G2 polynomial (Galileo ICD Figure 13, FEC encoder)
for ( int32_t i = 0 ; i < frame_length ; i + + )
{
if ( ( i + 1 ) % 2 = = 0 )
{
2021-09-25 18:29:51 +00:00
page_part_symbols_soft_value [ i ] = - page_part_symbols_soft_value [ i ] ;
2018-08-27 16:05:19 +00:00
}
}
2020-11-08 13:10:43 +00:00
const int32_t decoded_length = frame_length / 2 ;
std : : vector < int32_t > page_part_bits ( decoded_length ) ;
2021-09-26 11:23:28 +00:00
d_viterbi - > decode ( page_part_bits , page_part_symbols_soft_value ) ;
2018-08-27 16:05:19 +00:00
// 3. Call the Galileo page decoder
std : : string page_String ;
2020-11-08 13:10:43 +00:00
page_String . reserve ( decoded_length ) ;
for ( int32_t i = 0 ; i < decoded_length ; i + + )
2018-08-27 16:05:19 +00:00
{
if ( page_part_bits [ i ] > 0 )
{
page_String . push_back ( ' 1 ' ) ;
}
else
{
page_String . push_back ( ' 0 ' ) ;
}
}
2021-09-05 22:05:29 +00:00
if ( d_enable_navdata_monitor )
{
d_nav_msg_packet . nav_message = page_String ;
}
2018-08-27 16:05:19 +00:00
if ( page_part_bits [ 0 ] = = 1 )
{
// DECODE COMPLETE WORD (even + odd) and TEST CRC
2021-10-10 16:56:14 +00:00
d_inav_nav . split_page ( page_String , d_flag_even_word_arrived ) ;
2020-06-23 07:47:58 +00:00
if ( d_inav_nav . get_flag_CRC_test ( ) = = true )
2018-08-27 16:05:19 +00:00
{
2020-07-28 18:53:08 +00:00
if ( d_band = = ' 1 ' )
2020-07-24 21:26:54 +00:00
{
DLOG ( INFO ) < < " Galileo E1 CRC correct in channel " < < d_channel < < " from satellite " < < d_satellite ;
}
2020-07-28 18:53:08 +00:00
else if ( d_band = = ' 7 ' )
2020-07-24 21:26:54 +00:00
{
DLOG ( INFO ) < < " Galileo E5b CRC correct in channel " < < d_channel < < " from satellite " < < d_satellite ;
}
2018-08-27 16:05:19 +00:00
}
else
{
2020-07-28 18:53:08 +00:00
if ( d_band = = ' 1 ' )
2020-07-24 21:26:54 +00:00
{
DLOG ( INFO ) < < " Galileo E1 CRC error in channel " < < d_channel < < " from satellite " < < d_satellite ;
}
2020-07-28 18:53:08 +00:00
else if ( d_band = = ' 7 ' )
2020-07-24 21:26:54 +00:00
{
DLOG ( INFO ) < < " Galileo E5b CRC error in channel " < < d_channel < < " from satellite " < < d_satellite ;
}
2018-08-27 16:05:19 +00:00
}
2021-10-10 16:56:14 +00:00
d_flag_even_word_arrived = 0 ;
2018-08-27 16:05:19 +00:00
}
else
{
// STORE HALF WORD (even page)
2021-10-10 16:56:14 +00:00
d_inav_nav . split_page ( page_String , d_flag_even_word_arrived ) ;
d_flag_even_word_arrived = 1 ;
2018-08-27 16:05:19 +00:00
}
// 4. Push the new navigation data to the queues
if ( d_inav_nav . have_new_ephemeris ( ) = = true )
{
// get object for this SV (mandatory)
2020-07-19 07:39:32 +00:00
const std : : shared_ptr < Galileo_Ephemeris > tmp_obj = std : : make_shared < Galileo_Ephemeris > ( d_inav_nav . get_ephemeris ( ) ) ;
2020-07-28 18:53:08 +00:00
if ( d_band = = ' 1 ' )
2020-07-24 21:26:54 +00:00
{
std : : cout < < " New Galileo E1 I/NAV message received in channel " < < d_channel < < " : ephemeris from satellite " < < d_satellite < < ' \n ' ;
}
2020-07-28 18:53:08 +00:00
else if ( d_band = = ' 7 ' )
2020-07-24 21:26:54 +00:00
{
2020-07-28 18:53:08 +00:00
std : : cout < < TEXT_BLUE < < " New Galileo E5b I/NAV message received in channel " < < d_channel < < " : ephemeris from satellite " < < d_satellite < < TEXT_RESET < < ' \n ' ;
2020-07-24 21:26:54 +00:00
}
2018-08-27 16:05:19 +00:00
this - > message_port_pub ( pmt : : mp ( " telemetry " ) , pmt : : make_any ( tmp_obj ) ) ;
2021-04-09 13:00:58 +00:00
d_first_eph_sent = true ; // do not send reduced CED anymore, since we have the full ephemeris set
2018-08-27 16:05:19 +00:00
}
2021-04-09 13:00:58 +00:00
else
{
// If we still do not have ephemeris, check if we have a reduced CED
if ( ( d_band = = ' 1 ' ) & & ! d_first_eph_sent & & ( d_inav_nav . have_new_reduced_ced ( ) = = true ) )
{
const std : : shared_ptr < Galileo_Ephemeris > tmp_obj = std : : make_shared < Galileo_Ephemeris > ( d_inav_nav . get_reduced_ced ( ) ) ;
std : : cout < < " New Galileo E1 I/NAV reduced CED message received in channel " < < d_channel < < " from satellite " < < d_satellite < < ' \n ' ;
this - > message_port_pub ( pmt : : mp ( " telemetry " ) , pmt : : make_any ( tmp_obj ) ) ;
}
}
2018-08-27 16:05:19 +00:00
if ( d_inav_nav . have_new_iono_and_GST ( ) = = true )
{
// get object for this SV (mandatory)
2020-07-19 07:39:32 +00:00
const std : : shared_ptr < Galileo_Iono > tmp_obj = std : : make_shared < Galileo_Iono > ( d_inav_nav . get_iono ( ) ) ;
2020-07-28 18:53:08 +00:00
if ( d_band = = ' 1 ' )
2020-07-24 21:26:54 +00:00
{
std : : cout < < " New Galileo E1 I/NAV message received in channel " < < d_channel < < " : iono/GST model parameters from satellite " < < d_satellite < < ' \n ' ;
}
2020-07-28 18:53:08 +00:00
else if ( d_band = = ' 7 ' )
2020-07-24 21:26:54 +00:00
{
2020-07-28 18:53:08 +00:00
std : : cout < < TEXT_BLUE < < " New Galileo E5b I/NAV message received in channel " < < d_channel < < " : iono/GST model parameters from satellite " < < d_satellite < < TEXT_RESET < < ' \n ' ;
2020-07-24 21:26:54 +00:00
}
2018-08-27 16:05:19 +00:00
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)
2020-07-19 07:39:32 +00:00
const std : : shared_ptr < Galileo_Utc_Model > tmp_obj = std : : make_shared < Galileo_Utc_Model > ( d_inav_nav . get_utc_model ( ) ) ;
2020-07-28 18:53:08 +00:00
if ( d_band = = ' 1 ' )
2020-07-24 21:26:54 +00:00
{
std : : cout < < " New Galileo E1 I/NAV message received in channel " < < d_channel < < " : UTC model parameters from satellite " < < d_satellite < < ' \n ' ;
}
2020-07-28 18:53:08 +00:00
else if ( d_band = = ' 7 ' )
2020-07-24 21:26:54 +00:00
{
2020-07-28 18:53:08 +00:00
std : : cout < < TEXT_BLUE < < " New Galileo E5b I/NAV message received in channel " < < d_channel < < " : UTC model parameters from satellite " < < d_satellite < < TEXT_RESET < < ' \n ' ;
2020-07-24 21:26:54 +00:00
}
2018-08-27 16:05:19 +00:00
this - > message_port_pub ( pmt : : mp ( " telemetry " ) , pmt : : make_any ( tmp_obj ) ) ;
2021-02-20 23:01:56 +00:00
d_delta_t = tmp_obj - > A_0G + tmp_obj - > A_1G * ( static_cast < double > ( d_TOW_at_current_symbol_ms ) / 1000.0 - tmp_obj - > t_0G + 604800 * ( std : : fmod ( static_cast < float > ( d_inav_nav . get_Galileo_week ( ) - tmp_obj - > WN_0G ) , 64.0 ) ) ) ;
2020-06-19 00:15:56 +00:00
DLOG ( INFO ) < < " delta_t= " < < d_delta_t < < " [s] " ;
2018-08-27 16:05:19 +00:00
}
if ( d_inav_nav . have_new_almanac ( ) = = true )
{
2020-07-19 07:39:32 +00:00
const std : : shared_ptr < Galileo_Almanac_Helper > tmp_obj = std : : make_shared < Galileo_Almanac_Helper > ( d_inav_nav . get_almanac ( ) ) ;
2018-08-27 16:05:19 +00:00
this - > message_port_pub ( pmt : : mp ( " telemetry " ) , pmt : : make_any ( tmp_obj ) ) ;
2019-07-28 10:01:11 +00:00
// debug
2020-07-28 18:53:08 +00:00
if ( d_band = = ' 1 ' )
2020-07-24 21:26:54 +00:00
{
std : : cout < < " Galileo E1 I/NAV almanac received in channel " < < d_channel < < " from satellite " < < d_satellite < < ' \n ' ;
}
2020-07-28 18:53:08 +00:00
else if ( d_band = = ' 7 ' )
2020-07-24 21:26:54 +00:00
{
std : : cout < < " Galileo E5b I/NAV almanac received in channel " < < d_channel < < " from satellite " < < d_satellite < < ' \n ' ;
}
2018-08-27 16:05:19 +00:00
DLOG ( INFO ) < < " Current parameters: " ;
DLOG ( INFO ) < < " d_TOW_at_current_symbol_ms= " < < d_TOW_at_current_symbol_ms ;
2020-06-23 07:47:58 +00:00
DLOG ( INFO ) < < " d_nav.WN_0= " < < d_inav_nav . get_Galileo_week ( ) ;
2018-08-27 16:05:19 +00:00
}
}
2019-09-06 15:31:31 +00:00
void galileo_telemetry_decoder_gs : : decode_FNAV_word ( float * page_symbols , int32_t frame_length )
2018-08-27 16:05:19 +00:00
{
// 1. De-interleave
2021-09-25 18:29:51 +00:00
std : : vector < float > page_symbols_soft_value ( frame_length ) ;
deinterleaver ( GALILEO_FNAV_INTERLEAVER_ROWS , GALILEO_FNAV_INTERLEAVER_COLS , page_symbols , page_symbols_soft_value . data ( ) ) ;
2018-08-27 16:05:19 +00:00
// 2. Viterbi decoder
// 2.1 Take into account the NOT gate in G2 polynomial (Galileo ICD Figure 13, FEC encoder)
for ( int32_t i = 0 ; i < frame_length ; i + + )
{
if ( ( i + 1 ) % 2 = = 0 )
{
2021-09-25 18:29:51 +00:00
page_symbols_soft_value [ i ] = - page_symbols_soft_value [ i ] ;
2018-08-27 16:05:19 +00:00
}
}
2020-11-08 13:10:43 +00:00
const int32_t decoded_length = frame_length / 2 ;
std : : vector < int32_t > page_bits ( decoded_length ) ;
2021-09-26 11:23:28 +00:00
d_viterbi - > decode ( page_bits , page_symbols_soft_value ) ;
2018-08-27 16:05:19 +00:00
// 3. Call the Galileo page decoder
std : : string page_String ;
2020-11-08 13:10:43 +00:00
page_String . reserve ( decoded_length ) ;
for ( int32_t i = 0 ; i < decoded_length ; i + + )
2018-08-27 16:05:19 +00:00
{
if ( page_bits [ i ] > 0 )
{
page_String . push_back ( ' 1 ' ) ;
}
else
{
page_String . push_back ( ' 0 ' ) ;
}
}
2021-09-05 22:05:29 +00:00
if ( d_enable_navdata_monitor )
{
d_nav_msg_packet . nav_message = page_String ;
}
2018-08-27 16:05:19 +00:00
// DECODE COMPLETE WORD (even + odd) and TEST CRC
d_fnav_nav . split_page ( page_String ) ;
2020-06-23 07:47:58 +00:00
if ( d_fnav_nav . get_flag_CRC_test ( ) = = true )
2018-08-27 16:05:19 +00:00
{
2019-03-01 15:48:10 +00:00
DLOG ( INFO ) < < " Galileo E5a CRC correct in channel " < < d_channel < < " from satellite " < < d_satellite ;
2018-08-27 16:05:19 +00:00
}
else
{
2019-03-01 15:48:10 +00:00
DLOG ( INFO ) < < " Galileo E5a CRC error in channel " < < d_channel < < " from satellite " < < d_satellite ;
2018-08-27 16:05:19 +00:00
}
// 4. Push the new navigation data to the queues
if ( d_fnav_nav . have_new_ephemeris ( ) = = true )
{
2020-07-20 10:06:04 +00:00
const std : : shared_ptr < Galileo_Ephemeris > tmp_obj = std : : make_shared < Galileo_Ephemeris > ( d_fnav_nav . get_ephemeris ( ) ) ;
2020-07-07 16:53:50 +00:00
std : : cout < < TEXT_MAGENTA < < " New Galileo E5a F/NAV message received in channel " < < d_channel < < " : ephemeris from satellite " < < d_satellite < < TEXT_RESET < < ' \n ' ;
2018-08-27 16:05:19 +00:00
this - > message_port_pub ( pmt : : mp ( " telemetry " ) , pmt : : make_any ( tmp_obj ) ) ;
}
if ( d_fnav_nav . have_new_iono_and_GST ( ) = = true )
{
2020-07-20 10:06:04 +00:00
const std : : shared_ptr < Galileo_Iono > tmp_obj = std : : make_shared < Galileo_Iono > ( d_fnav_nav . get_iono ( ) ) ;
2020-07-07 16:53:50 +00:00
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 < < ' \n ' ;
2018-08-27 16:05:19 +00:00
this - > message_port_pub ( pmt : : mp ( " telemetry " ) , pmt : : make_any ( tmp_obj ) ) ;
}
if ( d_fnav_nav . have_new_utc_model ( ) = = true )
{
2020-07-20 10:06:04 +00:00
const std : : shared_ptr < Galileo_Utc_Model > tmp_obj = std : : make_shared < Galileo_Utc_Model > ( d_fnav_nav . get_utc_model ( ) ) ;
2020-07-07 16:53:50 +00:00
std : : cout < < TEXT_MAGENTA < < " New Galileo E5a F/NAV message received in channel " < < d_channel < < " : UTC model parameters from satellite " < < d_satellite < < TEXT_RESET < < ' \n ' ;
2018-08-27 16:05:19 +00:00
this - > message_port_pub ( pmt : : mp ( " telemetry " ) , pmt : : make_any ( tmp_obj ) ) ;
}
}
2018-08-30 17:24:28 +00:00
2020-11-08 13:10:43 +00:00
void galileo_telemetry_decoder_gs : : decode_CNAV_word ( float * page_symbols , int32_t page_length )
2020-11-07 20:33:26 +00:00
{
2020-11-08 13:10:43 +00:00
// 1. De-interleave
2021-09-25 18:29:51 +00:00
std : : vector < float > page_symbols_soft_value ( page_length ) ;
deinterleaver ( GALILEO_CNAV_INTERLEAVER_ROWS , GALILEO_CNAV_INTERLEAVER_COLS , page_symbols , page_symbols_soft_value . data ( ) ) ;
2020-11-08 13:10:43 +00:00
// 2. Viterbi decoder
// 2.1 Take into account the NOT gate in G2 polynomial (Galileo ICD Figure 13, FEC encoder)
for ( int32_t i = 0 ; i < page_length ; i + + )
{
if ( ( i + 1 ) % 2 = = 0 )
{
2021-09-25 18:29:51 +00:00
page_symbols_soft_value [ i ] = - page_symbols_soft_value [ i ] ;
2020-11-08 13:10:43 +00:00
}
}
const int32_t decoded_length = page_length / 2 ;
std : : vector < int32_t > page_bits ( decoded_length ) ;
2021-09-26 11:23:28 +00:00
d_viterbi - > decode ( page_bits , page_symbols_soft_value ) ;
2020-11-08 13:10:43 +00:00
// 3. Call the Galileo page decoder
std : : string page_String ;
page_String . reserve ( decoded_length ) ;
for ( int32_t i = 0 ; i < decoded_length ; i + + )
{
if ( page_bits [ i ] > 0 )
{
page_String . push_back ( ' 1 ' ) ;
}
else
{
page_String . push_back ( ' 0 ' ) ;
}
}
d_cnav_nav . read_HAS_page ( page_String ) ;
2021-06-02 14:30:26 +00:00
// 4. If we have a new HAS page, read it
if ( d_cnav_nav . have_new_HAS_page ( ) = = true )
2020-11-08 13:10:43 +00:00
{
2021-06-02 14:30:26 +00:00
bool is_page_dummy = d_cnav_nav . is_HAS_page_dummy ( ) ;
if ( is_page_dummy = = true )
2020-11-10 20:20:13 +00:00
{
2021-06-05 18:35:12 +00:00
d_print_cnav_page = true ;
2021-06-02 14:30:26 +00:00
// Only print the message once
if ( is_page_dummy ! = d_cnav_dummy_page )
{
d_cnav_dummy_page = is_page_dummy ;
2021-06-05 18:35:12 +00:00
2021-06-02 14:57:23 +00:00
std : : cout < < TEXT_MAGENTA < < " Receiving Galileo E6 CNAV dummy pages in channel "
< < d_channel < < " from satellite " < < d_satellite
< < TEXT_RESET < < ' \n ' ;
2021-06-02 14:30:26 +00:00
}
2020-11-10 20:20:13 +00:00
}
else
{
2021-06-02 14:30:26 +00:00
const std : : shared_ptr < Galileo_HAS_page > tmp_obj = std : : make_shared < Galileo_HAS_page > ( d_cnav_nav . get_HAS_encoded_page ( ) ) ;
2021-06-02 15:13:46 +00:00
this - > message_port_pub ( pmt : : mp ( " E6_HAS_from_TLM " ) , pmt : : make_any ( tmp_obj ) ) ;
2021-06-05 18:35:12 +00:00
if ( d_print_cnav_page = = true )
{
d_print_cnav_page = false ; // only print the first page
std : : cout < < TEXT_MAGENTA < < " Receiving Galileo E6 HAS pages "
< < ( d_cnav_nav . is_HAS_in_test_mode ( ) = = true ? " (test mode) " : " " )
< < " in channel " < < d_channel < < " from satellite " < < d_satellite
< < TEXT_RESET < < ' \n ' ;
}
2020-11-10 20:20:13 +00:00
}
2020-11-08 13:10:43 +00:00
}
2020-11-07 20:33:26 +00:00
}
2019-03-02 01:21:03 +00:00
void galileo_telemetry_decoder_gs : : set_satellite ( const Gnss_Satellite & satellite )
2018-08-27 16:05:19 +00:00
{
2019-03-18 15:28:49 +00:00
gr : : thread : : scoped_lock lock ( d_setlock ) ;
2018-08-27 16:05:19 +00:00
d_satellite = Gnss_Satellite ( satellite . get_system ( ) , satellite . get_PRN ( ) ) ;
2019-03-18 15:28:49 +00:00
d_last_valid_preamble = d_sample_counter ;
d_sent_tlm_failed_msg = false ;
2018-08-27 16:05:19 +00:00
DLOG ( INFO ) < < " Setting decoder Finite State Machine to satellite " < < d_satellite ;
DLOG ( INFO ) < < " Navigation Satellite set to " < < d_satellite ;
}
2019-03-18 15:28:49 +00:00
void galileo_telemetry_decoder_gs : : reset ( )
{
2019-06-14 10:52:46 +00:00
gr : : thread : : scoped_lock lock ( d_setlock ) ;
2021-08-03 12:03:27 +00:00
d_flag_frame_sync = false ;
d_TOW_at_current_symbol_ms = 0 ;
d_TOW_at_Preamble_ms = 0 ;
d_fnav_nav . set_flag_TOW_set ( false ) ;
d_inav_nav . set_flag_TOW_set ( false ) ;
2019-03-18 15:28:49 +00:00
d_last_valid_preamble = d_sample_counter ;
d_sent_tlm_failed_msg = false ;
2019-06-14 10:52:46 +00:00
d_stat = 0 ;
2021-09-26 11:23:28 +00:00
d_viterbi - > reset ( ) ;
2021-10-04 20:02:47 +00:00
if ( d_enable_reed_solomon_inav = = true )
{
d_inav_nav . enable_reed_solomon ( ) ;
}
2019-03-18 15:28:49 +00:00
DLOG ( INFO ) < < " Telemetry decoder reset for satellite " < < d_satellite ;
}
2019-03-18 18:41:41 +00:00
2019-03-02 01:21:03 +00:00
void galileo_telemetry_decoder_gs : : set_channel ( int32_t channel )
2018-08-27 16:05:19 +00:00
{
d_channel = channel ;
2019-03-01 15:48:10 +00:00
DLOG ( INFO ) < < " Navigation channel set to " < < channel ;
2018-08-27 16:05:19 +00:00
// ############# ENABLE DATA FILE LOG #################
if ( d_dump = = true )
{
if ( d_dump_file . is_open ( ) = = false )
{
try
{
2018-12-03 22:34:29 +00:00
d_dump_filename . append ( std : : to_string ( d_channel ) ) ;
2018-08-27 16:05:19 +00:00
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 ( ) ;
}
}
}
2021-08-30 10:51:31 +00:00
if ( d_dump_crc_stats )
{
// set the channel number for the telemetry CRC statistics
// disable the telemetry CRC statistics if there is a problem opening the output file
2021-09-13 21:19:37 +00:00
d_dump_crc_stats = d_Tlm_CRC_Stats - > set_channel ( d_channel ) ;
2021-08-30 10:51:31 +00:00
}
2018-08-27 16:05:19 +00:00
}
2019-03-02 01:21:03 +00:00
int galileo_telemetry_decoder_gs : : general_work ( int noutput_items __attribute__ ( ( unused ) ) , gr_vector_int & ninput_items __attribute__ ( ( unused ) ) ,
2018-08-27 16:05:19 +00:00
gr_vector_const_void_star & input_items , gr_vector_void_star & output_items )
{
2018-12-03 15:25:11 +00:00
auto * * out = reinterpret_cast < Gnss_Synchro * * > ( & output_items [ 0 ] ) ; // Get the output buffer pointer
const auto * * in = reinterpret_cast < const Gnss_Synchro * * > ( & input_items [ 0 ] ) ; // Get the input buffer pointer
2018-08-27 16:05:19 +00:00
2018-12-08 17:49:31 +00:00
Gnss_Synchro current_symbol { } ; // structure to save the synchronization information and send the output object to the next block
2018-08-27 16:05:19 +00:00
// 1. Copy the current tracking output
current_symbol = in [ 0 ] [ 0 ] ;
2020-07-28 18:53:08 +00:00
d_band = current_symbol . Signal [ 0 ] ;
2018-08-27 16:05:19 +00:00
// add new symbol to the symbol queue
2019-07-01 09:00:38 +00:00
switch ( d_frame_type )
{
case 1 : // INAV
{
d_symbol_history . push_back ( current_symbol . Prompt_I ) ;
break ;
}
2019-07-19 16:23:36 +00:00
case 2 : // FNAV
2019-07-01 09:00:38 +00:00
{
d_symbol_history . push_back ( current_symbol . Prompt_Q ) ;
break ;
}
2020-11-07 20:33:26 +00:00
case 3 : // CNAV
{
d_symbol_history . push_back ( current_symbol . Prompt_I ) ;
break ;
}
2019-07-01 09:00:38 +00:00
default :
{
2020-12-29 14:13:42 +00:00
LOG ( WARNING ) < < " Frame type " < < d_frame_type < < " is not defined " ;
2019-07-01 09:00:38 +00:00
d_symbol_history . push_back ( current_symbol . Prompt_I ) ;
break ;
}
}
2019-03-18 15:28:49 +00:00
d_sample_counter + + ; // count for the processed symbols
2021-12-03 11:56:20 +00:00
2021-12-07 07:21:14 +00:00
// Time Tags from signal source (optional feature)
2021-12-03 11:56:20 +00:00
std : : vector < gr : : tag_t > tags_vec ;
this - > get_tags_in_range ( tags_vec , 0 , this - > nitems_read ( 0 ) , this - > nitems_read ( 0 ) + 1 ) ; // telemetry decoder consumes symbols one-by-one
if ( ! tags_vec . empty ( ) )
{
2021-12-07 07:21:14 +00:00
for ( const auto & it : tags_vec )
2021-12-03 11:56:20 +00:00
{
try
{
2021-12-07 07:21:14 +00:00
if ( pmt : : any_ref ( it . value ) . type ( ) . hash_code ( ) = = typeid ( const std : : shared_ptr < GnssTime > ) . hash_code ( ) )
2021-12-03 11:56:20 +00:00
{
2021-12-07 07:21:14 +00:00
const auto timetag = boost : : any_cast < const std : : shared_ptr < GnssTime > > ( pmt : : any_ref ( it . value ) ) ;
2021-12-03 11:56:20 +00:00
// std::cout << "Old tow: " << d_current_timetag.tow_ms << " new tow: " << timetag->tow_ms << "\n";
d_current_timetag = * timetag ;
d_valid_timetag = true ;
}
else
{
std : : cout < < " hash code not match \n " ;
}
}
catch ( const boost : : bad_any_cast & e )
{
std : : cout < < " msg Bad any_cast: " < < e . what ( ) ;
}
}
}
else
{
if ( d_valid_timetag = = true )
{
// propagate timetag to current symbol
// todo: tag rx_time is set only in the time channel. The tracking tag does not have valid rx_time (it is not required since it is associated to the current symbol)
// d_current_timetag.rx_time+=d_PRN_code_period_ms
d_current_timetag . tow_ms + = d_PRN_code_period_ms ;
if ( d_current_timetag . tow_ms > = 604800000 )
{
d_current_timetag . tow_ms - = 604800000 ;
d_current_timetag . week + + ;
}
}
}
2018-08-27 16:05:19 +00:00
consume_each ( 1 ) ;
d_flag_preamble = false ;
2019-03-18 15:28:49 +00:00
// check if there is a problem with the telemetry of the current satellite
2019-06-14 10:52:46 +00:00
if ( d_sent_tlm_failed_msg = = false )
2019-03-18 15:28:49 +00:00
{
if ( ( d_sample_counter - d_last_valid_preamble ) > d_max_symbols_without_valid_frame )
{
2020-07-27 23:23:27 +00:00
const int message = 1 ; // bad telemetry
2019-06-14 10:52:46 +00:00
DLOG ( INFO ) < < " sent msg sat " < < this - > d_satellite ;
2019-03-18 15:28:49 +00:00
this - > message_port_pub ( pmt : : mp ( " telemetry_to_trk " ) , pmt : : make_any ( message ) ) ;
d_sent_tlm_failed_msg = true ;
}
}
2018-08-27 16:05:19 +00:00
// ******* frame sync ******************
switch ( d_stat )
{
case 0 : // no preamble information
{
2019-07-19 16:23:36 +00:00
// correlate with preamble
2019-04-16 08:08:56 +00:00
int32_t corr_value = 0 ;
if ( d_symbol_history . size ( ) > d_required_symbols )
{
// ******* preamble correlation ********
for ( int32_t i = 0 ; i < d_samples_per_preamble ; i + + )
{
if ( d_symbol_history [ i ] < 0.0 ) // symbols clipping
{
corr_value - = d_preamble_samples [ i ] ;
}
else
{
corr_value + = d_preamble_samples [ i ] ;
}
}
2021-09-25 18:29:51 +00:00
if ( std : : abs ( corr_value ) > = d_samples_per_preamble )
2019-06-06 16:16:27 +00:00
{
d_preamble_index = d_sample_counter ; // record the preamble sample stamp
2021-03-28 11:07:50 +00:00
LOG ( INFO ) < < " Preamble detection for Galileo satellite " < < this - > d_satellite < < " in channel " < < this - > d_channel ;
2019-06-06 16:16:27 +00:00
d_stat = 1 ; // enter into frame pre-detection status
}
2019-04-16 08:08:56 +00:00
}
2019-06-06 16:16:27 +00:00
2018-08-27 16:05:19 +00:00
break ;
}
case 1 : // possible preamble lock
{
2019-07-19 16:23:36 +00:00
// correlate with preamble
2019-04-16 08:08:56 +00:00
int32_t corr_value = 0 ;
if ( d_symbol_history . size ( ) > d_required_symbols )
{
// ******* preamble correlation ********
for ( int32_t i = 0 ; i < d_samples_per_preamble ; i + + )
{
if ( d_symbol_history [ i ] < 0.0 ) // symbols clipping
{
corr_value - = d_preamble_samples [ i ] ;
}
else
{
corr_value + = d_preamble_samples [ i ] ;
}
}
2021-09-25 18:29:51 +00:00
if ( std : : abs ( corr_value ) > = d_samples_per_preamble )
2018-08-27 16:05:19 +00:00
{
2019-06-06 16:16:27 +00:00
// check preamble separation
2020-07-28 18:53:08 +00:00
const auto preamble_diff = static_cast < int32_t > ( d_sample_counter - d_preamble_index ) ;
2021-09-25 18:29:51 +00:00
if ( std : : abs ( preamble_diff - d_preamble_period_symbols ) = = 0 )
2019-06-06 16:16:27 +00:00
{
// try to decode frame
DLOG ( INFO ) < < " Starting page decoder for Galileo satellite " < < this - > d_satellite ;
d_preamble_index = d_sample_counter ; // record the preamble sample stamp
d_CRC_error_counter = 0 ;
if ( corr_value < 0 )
{
2020-06-19 00:15:56 +00:00
d_flag_PLL_180_deg_phase_locked = true ;
2019-06-06 16:16:27 +00:00
}
else
{
2020-06-19 00:15:56 +00:00
d_flag_PLL_180_deg_phase_locked = false ;
2019-06-06 16:16:27 +00:00
}
d_stat = 2 ;
}
else
2018-08-27 16:05:19 +00:00
{
2019-06-06 16:16:27 +00:00
if ( preamble_diff > d_preamble_period_symbols )
{
d_stat = 0 ; // start again
}
2018-08-27 16:05:19 +00:00
}
}
}
break ;
}
2019-02-28 12:40:09 +00:00
case 2 : // preamble acquired
2018-08-27 16:05:19 +00:00
{
if ( d_sample_counter = = d_preamble_index + static_cast < uint64_t > ( d_preamble_period_symbols ) )
{
// call the decoder
2020-11-07 20:33:26 +00:00
// NEW Galileo page part is received
// 0. fetch the symbols into an array
if ( d_flag_PLL_180_deg_phase_locked = = false ) // normal PLL lock
2018-08-27 16:05:19 +00:00
{
2020-11-07 20:33:26 +00:00
for ( uint32_t i = 0 ; i < d_frame_length_symbols ; i + + )
2018-08-27 16:05:19 +00:00
{
2020-11-07 20:33:26 +00:00
d_page_part_symbols [ i ] = d_symbol_history [ i + d_samples_per_preamble ] ; // because last symbol of the preamble is just received now!
2018-08-27 16:05:19 +00:00
}
2020-11-07 20:33:26 +00:00
}
else // 180 deg. inverted carrier phase PLL lock
{
for ( uint32_t i = 0 ; i < d_frame_length_symbols ; i + + )
2018-08-27 16:05:19 +00:00
{
2020-11-07 20:33:26 +00:00
d_page_part_symbols [ i ] = - d_symbol_history [ i + d_samples_per_preamble ] ; // because last symbol of the preamble is just received now!
2018-08-27 16:05:19 +00:00
}
2020-11-07 20:33:26 +00:00
}
switch ( d_frame_type )
{
case 1 : // INAV
2019-07-19 16:23:36 +00:00
decode_INAV_word ( d_page_part_symbols . data ( ) , d_frame_length_symbols ) ;
2018-08-27 16:05:19 +00:00
break ;
2018-08-30 17:24:28 +00:00
case 2 : // FNAV
2019-07-19 16:23:36 +00:00
decode_FNAV_word ( d_page_part_symbols . data ( ) , d_frame_length_symbols ) ;
2018-08-27 16:05:19 +00:00
break ;
2020-11-07 20:33:26 +00:00
case 3 : // CNAV
decode_CNAV_word ( d_page_part_symbols . data ( ) , d_frame_length_symbols ) ;
break ;
2018-08-27 16:05:19 +00:00
default :
return - 1 ;
break ;
}
2021-09-13 21:19:37 +00:00
bool crc_ok = ( d_inav_nav . get_flag_CRC_test ( ) | | d_fnav_nav . get_flag_CRC_test ( ) | | d_cnav_nav . get_flag_CRC_test ( ) ) ;
2021-08-30 10:51:31 +00:00
if ( d_dump_crc_stats )
{
// update CRC statistics
2021-09-13 21:19:37 +00:00
d_Tlm_CRC_Stats - > update_CRC_stats ( crc_ok ) ;
2021-08-30 10:51:31 +00:00
}
2019-07-03 16:57:26 +00:00
d_preamble_index = d_sample_counter ; // record the preamble sample stamp (t_P)
2021-09-13 21:19:37 +00:00
if ( crc_ok )
2018-08-27 16:05:19 +00:00
{
d_CRC_error_counter = 0 ;
2019-07-03 16:57:26 +00:00
d_flag_preamble = true ; // valid preamble indicator (initialized to false every work())
2019-07-05 14:14:33 +00:00
gr : : thread : : scoped_lock lock ( d_setlock ) ;
2019-03-18 15:28:49 +00:00
d_last_valid_preamble = d_sample_counter ;
2018-08-27 16:05:19 +00:00
if ( ! d_flag_frame_sync )
{
d_flag_frame_sync = true ;
DLOG ( INFO ) < < " Frame sync SAT " < < this - > d_satellite ;
}
}
else
{
d_CRC_error_counter + + ;
2021-09-13 21:19:37 +00:00
if ( ( d_CRC_error_counter > CRC_ERROR_LIMIT ) & & ( d_frame_type ! = 3 ) )
2018-08-27 16:05:19 +00:00
{
2019-03-01 15:48:10 +00:00
DLOG ( INFO ) < < " Lost of frame sync SAT " < < this - > d_satellite ;
2021-08-20 20:52:13 +00:00
gr : : thread : : scoped_lock lock ( d_setlock ) ;
2018-08-27 16:05:19 +00:00
d_flag_frame_sync = false ;
d_stat = 0 ;
d_TOW_at_current_symbol_ms = 0 ;
d_TOW_at_Preamble_ms = 0 ;
2020-06-23 07:47:58 +00:00
d_fnav_nav . set_flag_TOW_set ( false ) ;
d_inav_nav . set_flag_TOW_set ( false ) ;
2018-08-27 16:05:19 +00:00
}
}
}
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 )
{
2018-08-30 17:24:28 +00:00
case 1 : // INAV
2018-08-27 16:05:19 +00:00
{
2020-12-21 14:13:02 +00:00
if ( d_inav_nav . get_flag_TOW_set ( ) = = true )
2018-08-27 16:05:19 +00:00
{
2020-06-23 07:47:58 +00:00
if ( d_inav_nav . is_TOW5_set ( ) = = 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)
2018-08-27 16:05:19 +00:00
{
// 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
2020-06-23 07:47:58 +00:00
d_TOW_at_Preamble_ms = static_cast < uint32_t > ( d_inav_nav . get_TOW5 ( ) * 1000.0 ) ;
2020-07-24 21:26:54 +00:00
d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast < uint32_t > ( GALILEO_INAV_PAGE_PART_MS + ( d_required_symbols + 1 ) * d_PRN_code_period_ms ) ;
2020-06-23 07:47:58 +00:00
d_inav_nav . set_TOW5_flag ( false ) ;
2021-12-03 11:56:20 +00:00
// timetag debug
if ( d_valid_timetag = = true )
{
int decoder_delay_ms = static_cast < uint32_t > ( GALILEO_INAV_PAGE_PART_MS + ( d_required_symbols + 1 ) * d_PRN_code_period_ms ) ;
int rx_tow_at_preamble = d_current_timetag . tow_ms - decoder_delay_ms ;
if ( rx_tow_at_preamble < 0 )
{
rx_tow_at_preamble + = 604800000 ;
}
uint32_t predicted_tow_at_preamble_ms = 1000 * ( rx_tow_at_preamble / 1000 ) ; // floor to integer number of seconds
std : : cout < < " TOW at PREAMBLE: " < < d_TOW_at_Preamble_ms < < " predicted TOW at preamble: " < < predicted_tow_at_preamble_ms < < " [ms] \n " ;
}
2018-08-27 16:05:19 +00:00
}
2020-12-21 14:13:02 +00:00
else if ( d_inav_nav . is_TOW6_set ( ) = = 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)
2018-08-27 16:05:19 +00:00
{
// 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
2020-06-23 07:47:58 +00:00
d_TOW_at_Preamble_ms = static_cast < uint32_t > ( d_inav_nav . get_TOW6 ( ) * 1000.0 ) ;
2020-07-24 21:26:54 +00:00
d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast < uint32_t > ( GALILEO_INAV_PAGE_PART_MS + ( d_required_symbols + 1 ) * d_PRN_code_period_ms ) ;
2020-06-23 07:47:58 +00:00
d_inav_nav . set_TOW6_flag ( false ) ;
2021-12-03 11:56:20 +00:00
// timetag debug
if ( d_valid_timetag = = true )
{
int decoder_delay_ms = static_cast < uint32_t > ( GALILEO_INAV_PAGE_PART_MS + ( d_required_symbols + 1 ) * d_PRN_code_period_ms ) ;
int rx_tow_at_preamble = d_current_timetag . tow_ms - decoder_delay_ms ;
if ( rx_tow_at_preamble < 0 )
{
rx_tow_at_preamble + = 604800000 ;
}
uint32_t predicted_tow_at_preamble_ms = 1000 * ( rx_tow_at_preamble / 1000 ) ; // floor to integer number of seconds
std : : cout < < " TOW at PREAMBLE: " < < d_TOW_at_Preamble_ms < < " predicted TOW at preamble: " < < predicted_tow_at_preamble_ms < < " [ms] \n " ;
}
2018-08-27 16:05:19 +00:00
}
2021-11-29 16:01:58 +00:00
else if ( d_inav_nav . is_TOW0_set ( ) = = true ) // page 0 arrived and decoded
{
// TOW_0 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 . get_TOW0 ( ) * 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 ) * d_PRN_code_period_ms ) ;
d_inav_nav . set_TOW0_flag ( false ) ;
2021-12-03 11:56:20 +00:00
// timetag debug
if ( d_valid_timetag = = true )
{
int decoder_delay_ms = static_cast < uint32_t > ( GALILEO_INAV_PAGE_PART_MS + ( d_required_symbols + 1 ) * d_PRN_code_period_ms ) ;
int rx_tow_at_preamble = d_current_timetag . tow_ms - decoder_delay_ms ;
if ( rx_tow_at_preamble < 0 )
{
rx_tow_at_preamble + = 604800000 ;
}
uint32_t predicted_tow_at_preamble_ms = 1000 * ( rx_tow_at_preamble / 1000 ) ; // floor to integer number of seconds
std : : cout < < " TOW at PREAMBLE: " < < d_TOW_at_Preamble_ms < < " predicted TOW at preamble: " < < predicted_tow_at_preamble_ms < < " [ms] \n " ;
}
2021-11-29 16:01:58 +00:00
}
2018-08-27 16:05:19 +00:00
else
{
// this page has no timing information
2020-12-22 09:59:13 +00:00
d_TOW_at_current_symbol_ms + = d_PRN_code_period_ms ;
2018-08-27 16:05:19 +00:00
}
}
2021-09-05 22:05:29 +00:00
if ( d_enable_navdata_monitor & & ! d_nav_msg_packet . nav_message . empty ( ) )
{
d_nav_msg_packet . system = std : : string ( 1 , current_symbol . System ) ;
d_nav_msg_packet . signal = std : : string ( current_symbol . Signal ) ;
d_nav_msg_packet . prn = static_cast < int32_t > ( current_symbol . PRN ) ;
d_nav_msg_packet . tow_at_current_symbol_ms = static_cast < int32_t > ( d_TOW_at_current_symbol_ms ) ;
const std : : shared_ptr < Nav_Message_Packet > tmp_obj = std : : make_shared < Nav_Message_Packet > ( d_nav_msg_packet ) ;
this - > message_port_pub ( pmt : : mp ( " Nav_msg_from_TLM " ) , pmt : : make_any ( tmp_obj ) ) ;
d_nav_msg_packet . nav_message = " " ;
}
2018-08-27 16:05:19 +00:00
break ;
}
2018-08-30 17:24:28 +00:00
case 2 : // FNAV
2018-08-27 16:05:19 +00:00
{
2020-12-21 14:13:02 +00:00
if ( d_fnav_nav . get_flag_TOW_set ( ) = = true )
2018-08-27 16:05:19 +00:00
{
2020-06-23 07:47:58 +00:00
if ( d_fnav_nav . is_TOW1_set ( ) = = true )
2018-08-27 16:05:19 +00:00
{
2020-06-23 07:47:58 +00:00
d_TOW_at_Preamble_ms = static_cast < uint32_t > ( d_fnav_nav . get_TOW1 ( ) * 1000.0 ) ;
2019-07-01 09:00:38 +00:00
d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast < uint32_t > ( ( d_required_symbols + 1 ) * GALILEO_FNAV_CODES_PER_SYMBOL * GALILEO_E5A_CODE_PERIOD_MS ) ;
2019-08-18 20:16:13 +00:00
// 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);
2020-06-23 07:47:58 +00:00
d_fnav_nav . set_TOW1_flag ( false ) ;
2018-08-27 16:05:19 +00:00
}
2020-06-23 07:47:58 +00:00
else if ( d_fnav_nav . is_TOW2_set ( ) = = true )
2018-08-27 16:05:19 +00:00
{
2020-06-23 07:47:58 +00:00
d_TOW_at_Preamble_ms = static_cast < uint32_t > ( d_fnav_nav . get_TOW2 ( ) * 1000.0 ) ;
2019-08-18 20:16:13 +00:00
// 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);
2019-07-01 09:00:38 +00:00
d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast < uint32_t > ( ( d_required_symbols + 1 ) * GALILEO_FNAV_CODES_PER_SYMBOL * GALILEO_E5A_CODE_PERIOD_MS ) ;
2020-06-23 07:47:58 +00:00
d_fnav_nav . set_TOW2_flag ( false ) ;
2018-08-27 16:05:19 +00:00
}
2020-06-23 07:47:58 +00:00
else if ( d_fnav_nav . is_TOW3_set ( ) = = true )
2018-08-27 16:05:19 +00:00
{
2020-06-23 07:47:58 +00:00
d_TOW_at_Preamble_ms = static_cast < uint32_t > ( d_fnav_nav . get_TOW3 ( ) * 1000.0 ) ;
2019-08-18 20:16:13 +00:00
// 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);
2019-07-01 09:00:38 +00:00
d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast < uint32_t > ( ( d_required_symbols + 1 ) * GALILEO_FNAV_CODES_PER_SYMBOL * GALILEO_E5A_CODE_PERIOD_MS ) ;
2020-06-23 07:47:58 +00:00
d_fnav_nav . set_TOW3_flag ( false ) ;
2018-08-27 16:05:19 +00:00
}
2020-06-23 07:47:58 +00:00
else if ( d_fnav_nav . is_TOW4_set ( ) = = true )
2018-08-27 16:05:19 +00:00
{
2020-06-23 07:47:58 +00:00
d_TOW_at_Preamble_ms = static_cast < uint32_t > ( d_fnav_nav . get_TOW4 ( ) * 1000.0 ) ;
2019-08-18 20:16:13 +00:00
// 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);
2019-07-01 09:00:38 +00:00
d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast < uint32_t > ( ( d_required_symbols + 1 ) * GALILEO_FNAV_CODES_PER_SYMBOL * GALILEO_E5A_CODE_PERIOD_MS ) ;
2020-06-23 07:47:58 +00:00
d_fnav_nav . set_TOW4_flag ( false ) ;
2018-08-27 16:05:19 +00:00
}
else
{
2019-07-01 09:00:38 +00:00
d_TOW_at_current_symbol_ms + = static_cast < uint32_t > ( GALILEO_FNAV_CODES_PER_SYMBOL * GALILEO_E5A_CODE_PERIOD_MS ) ;
2018-08-27 16:05:19 +00:00
}
2021-09-05 22:05:29 +00:00
if ( d_enable_navdata_monitor & & ! d_nav_msg_packet . nav_message . empty ( ) )
{
d_nav_msg_packet . system = std : : string ( 1 , current_symbol . System ) ;
d_nav_msg_packet . signal = std : : string ( current_symbol . Signal ) ;
d_nav_msg_packet . prn = static_cast < int32_t > ( current_symbol . PRN ) ;
d_nav_msg_packet . tow_at_current_symbol_ms = static_cast < int32_t > ( d_TOW_at_current_symbol_ms ) ;
const std : : shared_ptr < Nav_Message_Packet > tmp_obj = std : : make_shared < Nav_Message_Packet > ( d_nav_msg_packet ) ;
this - > message_port_pub ( pmt : : mp ( " Nav_msg_from_TLM " ) , pmt : : make_any ( tmp_obj ) ) ;
d_nav_msg_packet . nav_message = " " ;
}
2018-08-27 16:05:19 +00:00
break ;
}
}
2020-11-07 20:33:26 +00:00
case 3 : // CNAV
{
// TODO
}
2018-08-27 16:05:19 +00:00
}
}
else // if there is not a new preamble, we define the TOW of the current symbol
{
switch ( d_frame_type )
{
2018-08-30 17:24:28 +00:00
case 1 : // INAV
2018-08-27 16:05:19 +00:00
{
2020-12-21 14:13:02 +00:00
if ( d_inav_nav . get_flag_TOW_set ( ) = = true )
2018-08-27 16:05:19 +00:00
{
d_TOW_at_current_symbol_ms + = d_PRN_code_period_ms ;
}
break ;
}
2018-08-30 17:24:28 +00:00
case 2 : // FNAV
2018-08-27 16:05:19 +00:00
{
2020-12-21 14:13:02 +00:00
if ( d_fnav_nav . get_flag_TOW_set ( ) = = true )
2018-08-27 16:05:19 +00:00
{
d_TOW_at_current_symbol_ms + = d_PRN_code_period_ms ;
}
break ;
}
2020-11-07 20:33:26 +00:00
case 3 : // CNAV
{
// TODO
2021-06-02 14:30:26 +00:00
d_TOW_at_current_symbol_ms + = d_PRN_code_period_ms ; // this is not the TOW!
2020-11-07 20:33:26 +00:00
break ;
}
2018-08-27 16:05:19 +00:00
}
}
switch ( d_frame_type )
{
2018-08-30 17:24:28 +00:00
case 1 : // INAV
2018-08-27 16:05:19 +00:00
{
2020-12-21 14:13:02 +00:00
if ( d_inav_nav . get_flag_TOW_set ( ) = = true )
2018-08-27 16:05:19 +00:00
{
2020-12-21 14:13:02 +00:00
if ( d_inav_nav . get_flag_GGTO ( ) = = true ) // all GGTO parameters arrived
2018-08-27 16:05:19 +00:00
{
2020-06-23 07:47:58 +00:00
d_delta_t = d_inav_nav . get_A0G ( ) + d_inav_nav . get_A1G ( ) * ( static_cast < double > ( d_TOW_at_current_symbol_ms ) / 1000.0 - d_inav_nav . get_t0G ( ) + 604800.0 * ( std : : fmod ( static_cast < float > ( d_inav_nav . get_Galileo_week ( ) - d_inav_nav . get_WN0G ( ) ) , 64.0 ) ) ) ;
2018-08-27 16:05:19 +00:00
}
current_symbol . Flag_valid_word = true ;
}
break ;
}
2018-08-30 17:24:28 +00:00
case 2 : // FNAV
2018-08-27 16:05:19 +00:00
{
2020-12-21 14:13:02 +00:00
if ( d_fnav_nav . get_flag_TOW_set ( ) = = true )
2018-08-27 16:05:19 +00:00
{
current_symbol . Flag_valid_word = true ;
}
break ;
}
2020-11-07 20:33:26 +00:00
case 3 : // CNAV
{
// TODO
break ;
}
2018-08-27 16:05:19 +00:00
}
2021-09-13 21:19:37 +00:00
if ( d_inav_nav . get_flag_TOW_set ( ) = = true | | d_fnav_nav . get_flag_TOW_set ( ) = = true | | d_cnav_nav . get_flag_CRC_test ( ) = = true )
2018-08-27 16:05:19 +00:00
{
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.
2020-06-19 00:15:56 +00:00
// current_symbol.TOW_at_current_symbol_ms -= d_delta_t; // Galileo to GPS TOW
2018-08-27 16:05:19 +00:00
2020-06-19 00:15:56 +00:00
if ( d_flag_PLL_180_deg_phase_locked = = true )
2020-03-09 10:38:48 +00:00
{
// correct the accumulated phase for the Costas loop phase shift, if required
2020-07-05 18:20:02 +00:00
current_symbol . Carrier_phase_rads + = GNSS_PI ;
2021-09-21 15:25:16 +00:00
current_symbol . Flag_PLL_180_deg_phase_locked = true ;
}
else
{
current_symbol . Flag_PLL_180_deg_phase_locked = false ;
2020-03-09 10:38:48 +00:00
}
2018-08-27 16:05:19 +00:00
if ( d_dump = = true )
{
// MULTIPLEXED FILE RECORDING - Record results to file
try
{
double tmp_double ;
uint64_t tmp_ulong_int ;
2020-11-19 08:55:08 +00:00
int32_t tmp_int ;
2018-08-27 16:05:19 +00:00
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 ) ) ;
2020-11-19 08:55:08 +00:00
switch ( d_frame_type )
{
case 1 :
tmp_int = ( current_symbol . Prompt_I > 0.0 ? 1 : - 1 ) ;
break ;
case 2 :
tmp_int = ( current_symbol . Prompt_Q > 0.0 ? 1 : - 1 ) ;
break ;
case 3 :
tmp_int = ( current_symbol . Prompt_I > 0.0 ? 1 : - 1 ) ;
break ;
default :
tmp_int = 0 ;
break ;
}
d_dump_file . write ( reinterpret_cast < char * > ( & tmp_int ) , sizeof ( int32_t ) ) ;
tmp_int = static_cast < int32_t > ( current_symbol . PRN ) ;
d_dump_file . write ( reinterpret_cast < char * > ( & tmp_int ) , sizeof ( int32_t ) ) ;
2018-08-27 16:05:19 +00:00
}
catch ( const std : : ifstream : : failure & e )
{
2021-06-02 14:30:26 +00:00
LOG ( WARNING ) < < " Exception writing navigation data dump file " < < e . what ( ) ;
2018-08-27 16:05:19 +00:00
}
}
// 3. Make the output (copy the object contents to the GNURadio reserved memory)
* out [ 0 ] = current_symbol ;
return 1 ;
}
2018-12-03 21:08:19 +00:00
return 0 ;
2018-08-27 16:05:19 +00:00
}