/*! * \file Galileo_Navigation_Message.cc * \brief Implementation of a Galileo NAV Data message decoder as described in Galileo ICD * \author Mara Branzanti 2013. mara.branzanti(at)gmail.com * \author Javier Arribas, 2013. jarribas(at)cttc.es * * ------------------------------------------------------------------------- * * Copyright (C) 2010-2013 (see AUTHORS file for a list of contributors) * * GNSS-SDR is a software defined Global Navigation * Satellite Systems receiver * * This file is part of GNSS-SDR. * * GNSS-SDR is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * at your option) any later version. * * GNSS-SDR is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNSS-SDR. If not, see . * * ------------------------------------------------------------------------- */ #include "galileo_navigation_message.h" #include #include // for boost::crc_basic, boost::crc_optimal #include #include #include #include #include #include typedef boost::crc_optimal<24, 0x1864CFBu, 0x0, 0x0, false, false> CRC_Galileo_INAV_type; void Galileo_Navigation_Message::reset() { flag_even_word = 0; Page_type_time_stamp = 0; flag_CRC_test = false; flag_all_ephemeris = false; // flag indicating that all words containing ephemeris have been received flag_ephemeris_1 = false; // flag indicating that ephemeris 1/4 (word 1) have been received flag_ephemeris_2 = false; // flag indicating that ephemeris 2/4 (word 2) have been received flag_ephemeris_3 = false; // flag indicating that ephemeris 3/4 (word 3) have been received flag_ephemeris_4 = false; // flag indicating that ephemeris 4/4 (word 4) have been received flag_iono_and_GST = false; // flag indicating that ionospheric parameters (word 5) have been received flag_utc_model = false; // flag indicating that utc model parameters (word 6) have been received flag_all_almanac = false; // flag indicating that all almanac have been received flag_almanac_1 = false; // flag indicating that almanac 1/4 (word 7) have been received flag_almanac_2 = false; // flag indicating that almanac 2/4 (word 8) have been received flag_almanac_3 = false; // flag indicating that almanac 3/4 (word 9) have been received flag_almanac_4 = false; // flag indicating that almanac 4/4 (word 10) have been received flag_TOW_5 = 0; flag_TOW_set = false; IOD_ephemeris = 0; /*Word type 1: Ephemeris (1/4)*/ IOD_nav_1 = 0; t0e_1 = 0; M0_1 = 0; e_1 = 0; A_1 = 0; /*Word type 2: Ephemeris (2/4)*/ IOD_nav_2 = 0; // IOD_nav page 2 OMEGA_0_2 = 0; // Longitude of ascending node of orbital plane at weekly epoch [semi-circles] i_0_2 = 0; // Inclination angle at reference time [semi-circles] omega_2 = 0; // Argument of perigee [semi-circles] iDot_2 = 0; // Rate of inclination angle [semi-circles/sec] /*Word type 3: Ephemeris (3/4) and SISA*/ IOD_nav_3 = 0; // OMEGA_dot_3 = 0; // Rate of right ascension [semi-circles/sec] delta_n_3 = 0; // Mean motion difference from computed value [semi-circles/sec] C_uc_3 = 0; // Amplitude of the cosine harmonic correction term to the argument of latitude [radians] C_us_3 = 0; // Amplitude of the sine harmonic correction term to the argument of latitude [radians] C_rc_3 = 0; // Amplitude of the cosine harmonic correction term to the orbit radius [meters] C_rs_3 = 0; // Amplitude of the sine harmonic correction term to the orbit radius [meters] SISA_3 = 0; // /*Word type 4: Ephemeris (4/4) and Clock correction parameters*/ IOD_nav_4 = 0; // SV_ID_PRN_4 = 0; // C_ic_4 = 0; // Amplitude of the cosine harmonic correction term to the angle of inclination [radians] C_is_4 = 0; // Amplitude of the sine harmonic correction term to the angle of inclination [radians] /*Clock correction parameters*/ t0c_4 = 0; // af0_4 = 0; // af1_4 = 0; // af2_4 = 0; // spare_4 = 0; /*Word type 5: Ionospheric correction, BGD, signal health and data validity status and GST*/ /*Ionospheric correction*/ /*Az*/ ai0_5 = 0; // ai1_5 = 0; // ai2_5 = 0; // /*Ionospheric disturbance flag*/ Region1_flag_5 = 0; //Region1_flag_5; Region2_flag_5 = 0; // Region3_flag_5 = 0; // Region4_flag_5 = 0; // Region5_flag_5 = 0; // BGD_E1E5a_5 = 0; // BGD_E1E5b_5 = 0; // E5b_HS_5 = 0; // E1B_HS_5 = 0; // E5b_DVS_5 = 0; // E1B_DVS_5 = 0; // /*GST*/ WN_5 = 0; TOW_5 = 0; spare_5 = 0; /*Word type 6: GST-UTC conversion parameters*/ A0_6 = 0; A1_6 = 0; Delta_tLS_6 = 0; t0t_6 = 0; WNot_6 = 0; WN_LSF_6 = 0; DN_6 = 0; Delta_tLSF_6 = 0; TOW_6 = 0; /*Word type 7: Almanac for SVID1 (1/2), almanac reference time and almanac reference week number*/ IOD_a_7 = 0; WN_a_7 = 0; t0a_7 = 0; SVID1_7 = 0; DELTA_A_7 = 0; e_7 = 0; omega_7 = 0; delta_i_7 = 0; Omega0_7 = 0; Omega_dot_7 = 0; M0_7 = 0; /*Word type 8: Almanac for SVID1 (2/2) and SVID2 (1/2)*/ IOD_a_8 = 0; af0_8 = 0; af1_8 = 0; E5b_HS_8 = 0; E1B_HS_8 = 0; SVID2_8 = 0; DELTA_A_8 = 0; e_8 = 0; omega_8 = 0; delta_i_8 = 0; Omega0_8 = 0; Omega_dot_8 = 0; /*Word type 9: Almanac for SVID2 (2/2) and SVID3 (1/2)*/ IOD_a_9 = 0; WN_a_9 = 0; t0a_9 = 0; M0_9 = 0; af0_9 = 0; af1_9 = 0; E5b_HS_9 = 0; E1B_HS_9 = 0; SVID3_9 = 0; DELTA_A_9 = 0; e_9 = 0; omega_9 = 0; delta_i_9 = 0; /*Word type 10: Almanac for SVID3 (2/2) and GST-GPS conversion parameters*/ IOD_a_10 = 0; Omega0_10 = 0; Omega_dot_10 = 0; M0_10 = 0; af0_10 = 0; af1_10 = 0; E5b_HS_10 = 0; E1B_HS_10 = 0; //GST-GPS A_0G_10 = 0; A_1G_10 = 0; t_0G_10 = 0; WN_0G_10 = 0; /*Word type 0: I/NAV Spare Word*/ Time_0 = 0; WN_0 = 0; TOW_0 = 0; } Galileo_Navigation_Message::Galileo_Navigation_Message() { reset(); } bool Galileo_Navigation_Message::CRC_test(std::bitset bits,boost::uint32_t checksum) { CRC_Galileo_INAV_type CRC_Galileo; boost::uint32_t crc_computed; // Galileo INAV frame for CRC is not an integer multiple of bytes // it needs to be filled with zeroes at the start of the frame. // This operation is done in the transformation from bits to bytes // using boost::dynamic_bitset. // ToDo: Use boost::dynamic_bitset for all the bitset operations in this class boost::dynamic_bitset frame_bits(std::string(bits.to_string())); std::vector bytes; boost::to_block_range(frame_bits, std::back_inserter(bytes)); std::reverse(bytes.begin(),bytes.end()); CRC_Galileo.process_bytes( bytes.data(), GALILEO_DATA_FRAME_BYTES ); crc_computed=CRC_Galileo.checksum(); if (checksum==crc_computed){ return true; }else{ return false; } } unsigned long int Galileo_Navigation_Message::read_navigation_unsigned(std::bitset bits, const std::vector > parameter) { unsigned long int value = 0; int num_of_slices = parameter.size(); for (int i=0; i bits, const std::vector > parameter) { unsigned long int value = 0; int num_of_slices = parameter.size(); for (int i=0; i bits, const std::vector > parameter) { signed long int value = 0; int num_of_slices = parameter.size(); // Discriminate between 64 bits and 32 bits compiler int long_int_size_bytes = sizeof(signed long int); if (long_int_size_bytes == 8) // if a long int takes 8 bytes, we are in a 64 bits system { // read the MSB and perform the sign extension if (bits[GALILEO_DATA_JK_BITS - parameter[0].first] == 1) { value ^= 0xFFFFFFFFFFFFFFFF; //64 bits variable } else { value &= 0; } for (int i=0; i bits, const std::vector > parameter) { bool value; if (bits[GALILEO_DATA_JK_BITS - parameter[0].first] == 1) { value = true; } else { value = false; } return value; } /*void Galileo_Navigation_Message::print_galileo_word_bytes(unsigned int GPS_word) { std::cout << " Word ="; std::cout << std::bitset<32>(GPS_word); std::cout << std::endl; }*/ void Galileo_Navigation_Message::split_page(std::string page_string, int flag_even_word){ // ToDo: Clean all the tests and create an independent google test code for the telemetry decoder. //char correct_tail[7]="011110"; //the viterbi decoder output change the tail to this value (why?) //char correct_tail[7]="000000"; int Page_type=0; //std::cout << "Start decoding Galileo I/NAV " << std::endl; if(page_string.at(0)=='1')// if page is odd { //std::cout<< "page_string.at(0) split page="< TLM_word_for_CRC_bits(TLM_word_for_CRC); std::bitset<24> checksum(CRC_data); //if (Tail_odd.compare(correct_tail) != 0) // std::cout << "Tail odd is not correct!" << std::endl; //else std::cout<<"Tail odd is correct!"< page_type_bits (page_number_bits); // from string to bitset Page_type = (int)read_page_type_unsigned(page_type_bits, type); Page_type_time_stamp = Page_type; //std::cout << "Page number (first 6 bits of Data k converted to decimal) = " << Page_type << std::endl; std::string Data_jk_ephemeris = Data_k + Data_j; //std::cout<<"Data j k ephemeris" << endl << Data_jk_ephemeris << endl; page_jk_decoder(Data_jk_ephemeris.c_str()); // Corresponding to ephemeris_decode.m in matlab code /*this block is just to try some function, it must be eliminated double t_GST; if ((have_new_iono_and_GST() == true) and (flag_all_ephemeris==true)) { std::cout <<"GST and ephemeris parameters have been received, now it is possible to compute satellite position"<< std::endl; t_GST = Galileo_System_Time(WN_5, TOW_5); std::cout << "Galileo System Time [sec]: " << t_GST << std::endl; satellitePosition(t_GST); flag_all_ephemeris=false; } double t_UTC; if ((have_new_iono_and_GST() == true) and (have_new_utc_model() == true)) { t_UTC = GST_to_UTC_time(t_GST, WN_5); std::cout << "UTC [sec]: " << t_UTC << std::endl; } */ }else{ // CRC wrong.. discard frame flag_CRC_test= false; } //********** end of CRC checksum control ***/ } } /*end if (page_string.at(0)=='1') */ else{ page_Even = page_string.substr (0,114); //std::cout << "Page even in split page" << std::endl << page_Even << std::endl; std::string tail_Even = page_string.substr (114,6); //std::cout << "tail_even_string: " << tail_Even < data_jk_bits (data_jk_string); //DLOG(INFO) << "Data_jk_bits (bitset) "<< endl << data_jk_bits << endl; page_number = (int)read_navigation_unsigned(data_jk_bits, PAGE_TYPE_bit); DLOG(INFO) << "Page number = " << page_number << std::endl; switch (page_number) { case 1: /*Word type 1: Ephemeris (1/4)*/ IOD_nav_1=(int)read_navigation_unsigned(data_jk_bits, IOD_nav_1_bit); DLOG(INFO)<<"IOD_nav_1= "<< IOD_nav_1 <= 0) // is not in the past // { // //Detect if the effectivity time and user's time is within six hours = 6 * 60 *60 = 21600 s // int secondOfLeapSecondEvent = DN_6 * 24 * 60 * 60; // if (weeksToLeapSecondEvent > 0) // { // t_Utc_daytime = fmod(t_e - Delta_t_Utc, 86400); // } // else //we are in the same week than the leap second event // { // if (abs(t_e - secondOfLeapSecondEvent) > 21600) // { // /* 5.1.7a // * Whenever the leap second adjusted time indicated by the WN_LSF and the DN values // * is not in the past (relative to the user's present time), and the user's // * present time does not fall in the time span which starts at six hours prior // * to the effective time and ends at six hours after the effective time, // * the GST/Utc relationship is given by // */ // t_Utc_daytime = fmod(t_e - Delta_t_Utc, 86400); // } // else // { // /* 5.1.7b // * Whenever the user's current time falls within the time span of six hours // * prior to the leap second adjustment to six hours after the adjustment time, , // * the effective time is computed according to the following equations: // */ // // int W = fmod(t_e - Delta_t_Utc - 43200, 86400) + 43200; // t_Utc_daytime = fmod(W, 86400 + Delta_tLSF_6 - Delta_tLS_6); // //implement something to handle a leap second event! // } // if ( (t_e - secondOfLeapSecondEvent) > 21600) // { // Delta_t_Utc = Delta_tLSF_6 + A0_6 + A1_6 * (t_e - t0t_6 + 604800*(double)(WN - WNot_6)); // t_Utc_daytime = fmod(t_e - Delta_t_Utc, 86400); // } // } // } // else // the effectivity time is in the past // { // /* 5.1.7c // * Whenever the leap second adjustment time, as indicated by the WN_LSF and DN values, // * is in the past (relative to the user’s current time) and the user’s present time does not // * fall in the time span which starts six hours prior to the leap second adjustment time and // * ends six hours after the adjustment time, the effective time is computed according to // * the following equation: // */ // Delta_t_Utc = Delta_tLSF_6 + A0_6 + A1_6 * (t_e - t0t_6 + 604800 * (double)(WN - WNot_6)); // t_Utc_daytime = fmod(t_e - Delta_t_Utc, 86400); // } // // double secondsOfWeekBeforeToday = 43200 * floor(t_e / 43200); // t_Utc = secondsOfWeekBeforeToday + t_Utc_daytime; // return t_Utc; // //} // // //