mirror of
				https://github.com/gnss-sdr/gnss-sdr
				synced 2025-10-31 15:23:04 +00:00 
			
		
		
		
	Merge branch 'next' of git+ssh://github.com/gnss-sdr/gnss-sdr into next
# Please enter a commit message to explain why this merge is necessary, # especially if it merges an updated upstream into a topic branch. # # Lines starting with '#' will be ignored, and an empty message aborts # the commit.
This commit is contained in:
		| @@ -12,12 +12,26 @@ GNSS-SDR.internal_fs_hz=4000000 | ||||
| ;######### CONTROL_THREAD CONFIG ############ | ||||
| ControlThread.wait_for_flowgraph=false | ||||
|  | ||||
|  | ||||
| ;######### SUPL RRLP GPS assistance configuration ##### | ||||
| GNSS-SDR.SUPL_gps_enabled=false | ||||
| GNSS-SDR.SUPL_read_gps_assistance_xml=true | ||||
| GNSS-SDR.SUPL_gps_ephemeris_server=supl.nokia.com | ||||
| GNSS-SDR.SUPL_gps_ephemeris_port=7275 | ||||
| GNSS-SDR.SUPL_gps_acquisition_server=supl.google.com | ||||
| GNSS-SDR.SUPL_gps_acquisition_port=7275 | ||||
| GNSS-SDR.SUPL_MCC=244 | ||||
| GNSS-SDR.SUPL_MNS=5 | ||||
| GNSS-SDR.SUPL_LAC=0x59e2 | ||||
| GNSS-SDR.SUPL_CI=0x31b0 | ||||
|  | ||||
|  | ||||
| ;######### SIGNAL_SOURCE CONFIG ############ | ||||
| ;#implementation: Use [File_Signal_Source] or [UHD_Signal_Source] or [GN3S_Signal_Source] (experimental) | ||||
| SignalSource.implementation=File_Signal_Source | ||||
|  | ||||
| ;#filename: path to file with the captured GNSS signal samples to be processed | ||||
| SignalSource.filename=/datalogger/signals/CTTC/2013_04_04_GNSS_SIGNAL_at_CTTC_SPAIN/2013_04_04_GNSS_SIGNAL_at_CTTC_SPAIN.dat | ||||
| SignalSource.filename=../../../Documents/workspace/code2/trunk/data/2013_04_04_GNSS_SIGNAL_at_CTTC_SPAIN.dat | ||||
|  | ||||
| ;#item_type: Type and resolution for each of the signal samples. Use only gr_complex in this version. | ||||
| SignalSource.item_type=short | ||||
|   | ||||
| @@ -38,6 +38,7 @@ | ||||
| #include "gps_iono.h" | ||||
| #include "gps_utc_model.h" | ||||
| #include "configuration_interface.h" | ||||
| #include "concurrent_queue.h" | ||||
|  | ||||
| extern concurrent_queue<Gps_Ephemeris> global_gps_ephemeris_queue; | ||||
| extern concurrent_queue<Gps_Iono> global_gps_iono_queue; | ||||
| @@ -70,10 +71,10 @@ GpsL2MTelemetryDecoder::GpsL2MTelemetryDecoder(ConfigurationInterface* configura | ||||
|     telemetry_decoder_ = gps_l2_m_make_telemetry_decoder_cc(satellite_, 0, (long)fs_in, vector_length_, queue_, dump_); // TODO fix me | ||||
|     DLOG(INFO) << "telemetry_decoder(" << telemetry_decoder_->unique_id() << ")"; | ||||
|     // set the navigation msg queue; | ||||
|     telemetry_decoder_->set_ephemeris_queue(&global_gps_ephemeris_queue); | ||||
|     telemetry_decoder_->set_iono_queue(&global_gps_iono_queue); | ||||
|     telemetry_decoder_->set_almanac_queue(&global_gps_almanac_queue); | ||||
|     telemetry_decoder_->set_utc_model_queue(&global_gps_utc_model_queue); | ||||
|     //telemetry_decoder_->set_ephemeris_queue(&global_gps_ephemeris_queue); | ||||
|     //telemetry_decoder_->set_iono_queue(&global_gps_iono_queue); | ||||
|     //telemetry_decoder_->set_almanac_queue(&global_gps_almanac_queue); | ||||
|     //telemetry_decoder_->set_utc_model_queue(&global_gps_utc_model_queue); | ||||
|  | ||||
|     //decimation factor | ||||
|     int decimation_factor = configuration->property(role + ".decimation_factor", 1); | ||||
|   | ||||
| @@ -29,28 +29,25 @@ | ||||
|  * ------------------------------------------------------------------------- | ||||
|  */ | ||||
|  | ||||
| /*! | ||||
|  * \todo Clean this code and move the telemetry definitions to GPS_L1_CA system definitions file | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #include "gps_l2_m_telemetry_decoder_cc.h" | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <boost/lexical_cast.hpp> | ||||
| #include <gnuradio/io_signature.h> | ||||
| #include <glog/logging.h> | ||||
| #include <boost/lexical_cast.hpp> | ||||
| #include "control_message_factory.h" | ||||
| #include "gnss_synchro.h" | ||||
|  | ||||
| #ifndef _rotl | ||||
| #define _rotl(X,N)  ((X << N) ^ (X >> (32-N)))  // Used in the parity check algorithm | ||||
| #endif | ||||
| #include "gps_l2_m_telemetry_decoder_cc.h" | ||||
|  | ||||
| using google::LogMessage; | ||||
| /*! | ||||
|  * \todo name and move the magic numbers to GPS_L1_CA.h | ||||
|  */ | ||||
|  | ||||
| // logging levels | ||||
| #define EVENT 2 	// logs important events which don't occur every block | ||||
| #define FLOW 3  	// logs the function calls of block processing functions | ||||
| #define SAMP_SYNC 4 // about 1 log entry per sample -> high output | ||||
| #define LMORE 5 	// | ||||
|  | ||||
|  | ||||
|  | ||||
| gps_l2_m_telemetry_decoder_cc_sptr | ||||
| gps_l2_m_make_telemetry_decoder_cc(Gnss_Satellite satellite, long if_freq, long fs_in, unsigned | ||||
|         int vector_length, boost::shared_ptr<gr::msg_queue> queue, bool dump) | ||||
| @@ -61,16 +58,6 @@ gps_l2_m_make_telemetry_decoder_cc(Gnss_Satellite satellite, long if_freq, long | ||||
|  | ||||
|  | ||||
|  | ||||
| void gps_l2_m_telemetry_decoder_cc::forecast (int noutput_items, gr_vector_int &ninput_items_required) | ||||
| { | ||||
|     for (unsigned i = 0; i < 3; i++) | ||||
|         { | ||||
|             ninput_items_required[i] = d_samples_per_bit * 8; //set the required sample history | ||||
|         } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| gps_l2_m_telemetry_decoder_cc::gps_l2_m_telemetry_decoder_cc( | ||||
|         Gnss_Satellite satellite, | ||||
|         long if_freq, | ||||
| @@ -79,283 +66,184 @@ gps_l2_m_telemetry_decoder_cc::gps_l2_m_telemetry_decoder_cc( | ||||
|         int vector_length, | ||||
|         boost::shared_ptr<gr::msg_queue> queue, | ||||
|         bool dump) : | ||||
|         gr::block("gps_navigation_cc", gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)), | ||||
|         gr::io_signature::make(1, 1, sizeof(Gnss_Synchro))) | ||||
|                 gr::block("gps_l2_m_telemetry_decoder_cc", | ||||
|                 gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)), | ||||
|                 gr::io_signature::make(1, 1, sizeof(Gnss_Synchro))) | ||||
| { | ||||
|     // initialize internal vars | ||||
|     d_queue = queue; | ||||
|     d_dump = dump; | ||||
|     d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN()); | ||||
|     d_vector_length = vector_length; | ||||
|     d_samples_per_bit = ( GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS ) / GPS_CA_TELEMETRY_RATE_BITS_SECOND; | ||||
|     LOG(INFO) << "GPS L2C M TELEMETRY PROCESSING: satellite " << d_satellite; | ||||
|     d_fs_in = fs_in; | ||||
|     //d_preamble_duration_seconds = (1.0 / GPS_CA_TELEMETRY_RATE_BITS_SECOND) * GPS_CA_PREAMBLE_LENGTH_BITS; | ||||
|     //std::cout<<"d_preamble_duration_seconds="<<d_preamble_duration_seconds<<"\r\n"; | ||||
|     // set the preamble | ||||
|     unsigned short int preambles_bits[GPS_CA_PREAMBLE_LENGTH_BITS] = GPS_PREAMBLE; | ||||
|  | ||||
|     memcpy((unsigned short int*)this->d_preambles_bits, (unsigned short int*)preambles_bits, GPS_CA_PREAMBLE_LENGTH_BITS*sizeof(unsigned short int)); | ||||
|  | ||||
|     // preamble bits to sampled symbols | ||||
|     d_preambles_symbols = (signed int*)malloc(sizeof(signed int) * GPS_CA_PREAMBLE_LENGTH_BITS * d_samples_per_bit); | ||||
|     int n = 0; | ||||
|     for (int i = 0; i < GPS_CA_PREAMBLE_LENGTH_BITS; i++) | ||||
|         { | ||||
|             for (unsigned int j = 0; j < d_samples_per_bit; j++) | ||||
|                 { | ||||
|                     if (d_preambles_bits[i] == 1) | ||||
|                         { | ||||
|                             d_preambles_symbols[n] = 1; | ||||
|                         } | ||||
|                     else | ||||
|                         { | ||||
|                             d_preambles_symbols[n] = -1; | ||||
|                         } | ||||
|                     n++; | ||||
|                 } | ||||
|         } | ||||
|     d_sample_counter = 0; | ||||
|     //d_preamble_code_phase_seconds = 0; | ||||
|     d_stat = 0; | ||||
|     d_preamble_index = 0; | ||||
|     d_symbol_accumulator = 0; | ||||
|     d_symbol_accumulator_counter = 0; | ||||
|     d_frame_bit_index = 0; | ||||
|     d_preamble_time_seconds = 0; | ||||
|     d_flag_frame_sync = false; | ||||
|     d_GPS_frame_4bytes = 0; | ||||
|     d_prev_GPS_frame_4bytes = 0; | ||||
|     d_flag_parity = false; | ||||
|     d_TOW_at_Preamble = 0; | ||||
|     d_TOW_at_current_symbol = 0; | ||||
|     flag_TOW_set = false; | ||||
|     d_average_count = 0; | ||||
|     d_block_size = d_samples_per_symbol * d_symbols_per_bit * d_block_size_in_bits*2; // two CNAV frames | ||||
|     d_decimation_output_factor=0; | ||||
|     //set_output_multiple (1); | ||||
|     d_average_count=0; | ||||
|     d_flag_invert_buffer_symbols=false; | ||||
|     d_flag_invert_input_symbols=false; | ||||
|     d_channel=0; | ||||
|     //set_history(d_samples_per_bit*8); // At least a history of 8 bits are needed to correlate with the preamble | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| gps_l2_m_telemetry_decoder_cc::~gps_l2_m_telemetry_decoder_cc() | ||||
| { | ||||
|     delete d_preambles_symbols; | ||||
|     d_dump_file.close(); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| bool gps_l2_m_telemetry_decoder_cc::gps_word_parityCheck(unsigned int gpsword) | ||||
| void gps_l2_m_telemetry_decoder_cc::forecast (int noutput_items, gr_vector_int &ninput_items_required) | ||||
| { | ||||
|     unsigned int d1, d2, d3, d4, d5, d6, d7, t, parity; | ||||
|     /* XOR as many bits in parallel as possible.  The magic constants pick | ||||
|        up bits which are to be XOR'ed together to implement the GPS parity | ||||
|        check algorithm described in IS-GPS-200E.  This avoids lengthy shift- | ||||
|        and-xor loops. */ | ||||
|     d1 = gpsword & 0xFBFFBF00; | ||||
|     d2 = _rotl(gpsword,1) & 0x07FFBF01; | ||||
|     d3 = _rotl(gpsword,2) & 0xFC0F8100; | ||||
|     d4 = _rotl(gpsword,3) & 0xF81FFE02; | ||||
|     d5 = _rotl(gpsword,4) & 0xFC00000E; | ||||
|     d6 = _rotl(gpsword,5) & 0x07F00001; | ||||
|     d7 = _rotl(gpsword,6) & 0x00003000; | ||||
|     t = d1 ^ d2 ^ d3 ^ d4 ^ d5 ^ d6 ^ d7; | ||||
|     // Now XOR the 5 6-bit fields together to produce the 6-bit final result. | ||||
|     parity = t ^ _rotl(t,6) ^ _rotl(t,12) ^ _rotl(t,18) ^ _rotl(t,24); | ||||
|     parity = parity & 0x3F; | ||||
|     if (parity == (gpsword & 0x3F)) return(true); | ||||
|     else return(false); | ||||
|     unsigned ninputs = ninput_items_required.size (); | ||||
|     for (unsigned i = 0; i < ninputs; i++) | ||||
|         ninput_items_required[i] = noutput_items; | ||||
|     //LOG(INFO) << "forecast(): " << "noutput_items=" << noutput_items << "\tninput_items_required ninput_items_required.size()=" << ninput_items_required.size(); | ||||
| } | ||||
|  | ||||
| void gps_l2_m_telemetry_decoder_cc::set_decimation(int decimation) | ||||
| { | ||||
|     d_decimation_output_factor = decimation; | ||||
| } | ||||
|  | ||||
| int gps_l2_m_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_int &ninput_items, | ||||
|         gr_vector_const_void_star &input_items,	gr_vector_void_star &output_items) | ||||
| { | ||||
|     int corr_value = 0; | ||||
|     int preamble_diff = 0; | ||||
| 	//LOG(INFO) << "general_work(): " << "noutput_items=" << noutput_items << "\toutput_items real size=" << output_items.size() <<  "\tninput_items size=" << ninput_items.size() << "\tinput_items real size=" << input_items.size() << "\tninput_items[0]=" << ninput_items[0]; | ||||
|     // get pointers on in- and output gnss-synchro objects | ||||
|     const Gnss_Synchro *in = (const Gnss_Synchro *)  input_items[0]; // input | ||||
|     Gnss_Synchro *out = (Gnss_Synchro *) output_items[0]; 	// output | ||||
|  | ||||
|     Gnss_Synchro **out = (Gnss_Synchro **) &output_items[0]; | ||||
|     d_sample_counter++; //count for the processed samples | ||||
|     // store the time stamp of the first sample in the processed sample block | ||||
|     double sample_stamp = in[0].Tracking_timestamp_secs; | ||||
|  | ||||
|     // ########### Output the tracking data to navigation and PVT ########## | ||||
|     const Gnss_Synchro **in = (const Gnss_Synchro **)  &input_items[0]; //Get the input samples pointer | ||||
|     // copy correlation samples into samples vector | ||||
|     //for (int i = 0; i < noutput_items; i++) | ||||
|     ///    { | ||||
|             // check if channel is in tracking state | ||||
|     //       { | ||||
|                 d_sample_buf.push_back(in[0].Prompt_I); | ||||
|     //        } | ||||
|     //    } | ||||
|  | ||||
|     // TODO Optimize me! | ||||
|     //******* preamble correlation ******** | ||||
|     for (unsigned int i = 0; i < d_samples_per_bit*8; i++) | ||||
|         { | ||||
|             if (in[0][i].Prompt_I < 0)	// symbols clipping | ||||
|                 { | ||||
|                     corr_value -= d_preambles_symbols[i]; | ||||
|                 } | ||||
|             else | ||||
|                 { | ||||
|                     corr_value += d_preambles_symbols[i]; | ||||
|                 } | ||||
|         } | ||||
|     d_flag_preamble = false; | ||||
|  | ||||
|     //******* frame sync ****************** | ||||
|     if (abs(corr_value) >= 160) | ||||
|         { | ||||
|             //TODO: Rewrite with state machine | ||||
|             if (d_stat == 0) | ||||
|                 { | ||||
|                     d_GPS_FSM.Event_gps_word_preamble(); | ||||
|                     d_preamble_index = d_sample_counter;//record the preamble sample stamp | ||||
|                     LOG(INFO) << "Preamble detection for SAT " << this->d_satellite; | ||||
|                     d_symbol_accumulator = 0; //sync the symbol to bits integrator | ||||
|                     d_symbol_accumulator_counter = 0; | ||||
|                     d_frame_bit_index = 8; | ||||
|                     d_stat = 1; // enter into frame pre-detection status | ||||
|                 } | ||||
|             else if (d_stat == 1) //check 6 seconds of preamble separation | ||||
|                 { | ||||
|                     preamble_diff = d_sample_counter - d_preamble_index; | ||||
|                     if (abs(preamble_diff - 6000) < 1) | ||||
|                         { | ||||
|                             d_GPS_FSM.Event_gps_word_preamble(); | ||||
|                             d_flag_preamble = true; | ||||
|                             d_preamble_index = d_sample_counter;  //record the preamble sample stamp (t_P) | ||||
|                             d_preamble_time_seconds = in[0][0].Tracking_timestamp_secs;// - d_preamble_duration_seconds; //record the PRN start sample index associated to the preamble | ||||
|  | ||||
|                             if (!d_flag_frame_sync) | ||||
|                                 { | ||||
|                                     d_flag_frame_sync = true; | ||||
|                                     LOG(INFO) <<" Frame sync SAT " << this->d_satellite << " with preamble start at " << d_preamble_time_seconds << " [s]"; | ||||
|                                 } | ||||
|                         } | ||||
|                 } | ||||
|         } | ||||
|     else | ||||
|         { | ||||
|             if (d_stat == 1) | ||||
|                 { | ||||
|                     preamble_diff = d_sample_counter - d_preamble_index; | ||||
|                     if (preamble_diff > 6001) | ||||
|                         { | ||||
|                             LOG(INFO) << "Lost of frame sync SAT " << this->d_satellite << " preamble_diff= " << preamble_diff; | ||||
|                             d_stat = 0; //lost of frame sync | ||||
|                             d_flag_frame_sync = false; | ||||
|                             flag_TOW_set = false; | ||||
|                         } | ||||
|                 } | ||||
|         } | ||||
|  | ||||
|     //******* SYMBOL TO BIT ******* | ||||
|     d_symbol_accumulator += in[0][d_samples_per_bit*8 - 1].Prompt_I; // accumulate the input value in d_symbol_accumulator | ||||
|     d_symbol_accumulator_counter++; | ||||
|     if (d_symbol_accumulator_counter == 20) | ||||
|         { | ||||
|             if (d_symbol_accumulator > 0) | ||||
|                 { //symbol to bit | ||||
|                     d_GPS_frame_4bytes += 1; //insert the telemetry bit in LSB | ||||
|                 } | ||||
|             d_symbol_accumulator = 0; | ||||
|             d_symbol_accumulator_counter = 0; | ||||
|             //******* bits to words ****** | ||||
|             d_frame_bit_index++; | ||||
|             if (d_frame_bit_index == 30) | ||||
|                 { | ||||
|                     d_frame_bit_index = 0; | ||||
|                     // parity check | ||||
|                     // Each word in wordbuff is composed of: | ||||
|                     //      Bits 0 to 29 = the GPS data word | ||||
|                     //      Bits 30 to 31 = 2 LSBs of the GPS word ahead. | ||||
|                     // prepare the extended frame [-2 -1 0 ... 30] | ||||
|                     if (d_prev_GPS_frame_4bytes & 0x00000001) | ||||
|                         { | ||||
|                             d_GPS_frame_4bytes = d_GPS_frame_4bytes | 0x40000000; | ||||
|                         } | ||||
|                     if (d_prev_GPS_frame_4bytes & 0x00000002) | ||||
|                         { | ||||
|                             d_GPS_frame_4bytes = d_GPS_frame_4bytes | 0x80000000; | ||||
|                         } | ||||
|                     /* Check that the 2 most recently logged words pass parity. Have to first | ||||
|                      invert the data bits according to bit 30 of the previous word. */ | ||||
|                     if(d_GPS_frame_4bytes & 0x40000000) | ||||
|                         { | ||||
|                             d_GPS_frame_4bytes ^= 0x3FFFFFC0; // invert the data bits (using XOR) | ||||
|                         } | ||||
|                     if (gps_l2_m_telemetry_decoder_cc::gps_word_parityCheck(d_GPS_frame_4bytes)) | ||||
|                         { | ||||
|                             memcpy(&d_GPS_FSM.d_GPS_frame_4bytes, &d_GPS_frame_4bytes, sizeof(char)*4); | ||||
|                             d_GPS_FSM.d_preamble_time_ms = d_preamble_time_seconds*1000.0; | ||||
|                             d_GPS_FSM.Event_gps_word_valid(); | ||||
|                             d_flag_parity = true; | ||||
|                         } | ||||
|                     else | ||||
|                         { | ||||
|                             d_GPS_FSM.Event_gps_word_invalid(); | ||||
|                             d_flag_parity = false; | ||||
|                         } | ||||
|                     d_prev_GPS_frame_4bytes = d_GPS_frame_4bytes; // save the actual frame | ||||
|                     d_GPS_frame_4bytes = d_GPS_frame_4bytes & 0; | ||||
|                 } | ||||
|             else | ||||
|                 { | ||||
|                     d_GPS_frame_4bytes <<= 1; //shift 1 bit left the telemetry word | ||||
|                 } | ||||
|         } | ||||
|     // output the frame | ||||
|     consume_each(1); //one by one | ||||
|  | ||||
|     // decode only if enough samples in buffer | ||||
|     if(d_sample_buf.size() >= d_block_size) | ||||
|         { | ||||
| 			d_flag_invert_buffer_symbols=false; | ||||
|     		while (true) | ||||
|     		{ | ||||
|  | ||||
| 				if (d_flag_invert_buffer_symbols==true) | ||||
| 				{ | ||||
| 					for (std::vector<double>::iterator symbol_it = d_sample_buf.begin(); symbol_it != d_sample_buf.end(); symbol_it++) | ||||
| 					{ | ||||
| 						*symbol_it = -(*symbol_it); | ||||
| 					} | ||||
| 					LOG(INFO)<<"Inverting buffer symbols"; | ||||
| 				} | ||||
|  | ||||
| 				//debug | ||||
| 				std::stringstream ss2; | ||||
| 				for (std::vector<double>::const_iterator symbol_it = d_sample_buf.begin(); symbol_it < d_sample_buf.end(); ++symbol_it) | ||||
| 					{ | ||||
| 						if(*symbol_it>=0) | ||||
| 						{ | ||||
| 							ss2<<'1'; | ||||
| 						}else{ | ||||
| 							ss2<<'0'; | ||||
| 						} | ||||
| 					} | ||||
| 				LOG(INFO)<<"get_symbols="<<ss2.str(); | ||||
|  | ||||
|  | ||||
| 				// align symbols in pairs | ||||
| 				// and obtain the bits by decoding the symbols (viterbi decoder) | ||||
| 				// they can be already aligned or shifted by one position | ||||
| 				std::vector<int> bits; | ||||
| 				bool symbol_alignment = d_symbol_aligner_and_decoder.get_bits(d_sample_buf, bits); | ||||
|  | ||||
| 				std::stringstream ss; | ||||
|  | ||||
| 				for (std::vector<int>::const_iterator bit_it = bits.begin(); bit_it < bits.end(); ++bit_it) | ||||
| 					{ | ||||
| 						ss << *bit_it; | ||||
| 					} | ||||
|  | ||||
| 				LOG(INFO)<<"get_bits="<<ss.str()<<std::endl; | ||||
| 				// search for preambles | ||||
| 				// and extract the corresponding message candidates | ||||
| 				std::vector<msg_candiate_int_t> msg_candidates; | ||||
| 				d_frame_detector.get_frame_candidates(bits, msg_candidates); | ||||
|  | ||||
| 				// verify checksum | ||||
| 				// and return the valid messages | ||||
| 				std::vector<msg_candiate_char_t> valid_msgs; | ||||
| 				d_crc_verifier.get_valid_frames(msg_candidates, valid_msgs); | ||||
| 				if (valid_msgs.size()==0) | ||||
| 				{ | ||||
| 					if (d_flag_invert_buffer_symbols==false) | ||||
| 					{ | ||||
| 						d_flag_invert_buffer_symbols=true; | ||||
| 					}else{//already tested the symbol inversion but CRC still fail | ||||
| 						LOG(INFO)<<"Discarting this buffer, no CNAV frames detected"; | ||||
| 						break; | ||||
| 					} | ||||
| 				}else{ //at least one frame has good CRC, keep the invert sign for the next frames | ||||
| 					d_flag_invert_input_symbols=d_flag_invert_buffer_symbols; | ||||
| 					LOG(INFO)<<valid_msgs.size()<<" GOOD L2C CNAV FRAME DETECTED!"; | ||||
| 					break; | ||||
| 				} | ||||
|     		} | ||||
| //            // compute message sample stamp | ||||
| //            // and fill messages in SBAS raw message objects | ||||
| //            std::vector<Sbas_Raw_Msg> sbas_raw_msgs; | ||||
| //            for(std::vector<msg_candiate_char_t>::const_iterator it = valid_msgs.begin(); | ||||
| //                    it != valid_msgs.end(); ++it) | ||||
| //                { | ||||
| //                    int message_sample_offset = | ||||
| //                            (sample_alignment ? 0 : -1) | ||||
| //                            + d_samples_per_symbol*(symbol_alignment ? -1 : 0) | ||||
| //                            + d_samples_per_symbol * d_symbols_per_bit * it->first; | ||||
| //                    double message_sample_stamp = sample_stamp + ((double)message_sample_offset)/1000; | ||||
| //                    VLOG(EVENT) << "message_sample_stamp=" << message_sample_stamp | ||||
| //                            << " (sample_stamp=" << sample_stamp | ||||
| //                            << " sample_alignment=" << sample_alignment | ||||
| //                            << " symbol_alignment=" << symbol_alignment | ||||
| //                            << " relative_preamble_start=" << it->first | ||||
| //                            << " message_sample_offset=" << message_sample_offset | ||||
| //                            << ")"; | ||||
| //                    Sbas_Raw_Msg sbas_raw_msg(message_sample_stamp, this->d_satellite.get_PRN(), it->second); | ||||
| //                    sbas_raw_msgs.push_back(sbas_raw_msg); | ||||
| //                } | ||||
| // | ||||
| //            // parse messages | ||||
| //            // and send them to the SBAS raw message queue | ||||
| //            for(std::vector<Sbas_Raw_Msg>::iterator it = sbas_raw_msgs.begin(); it != sbas_raw_msgs.end(); it++) | ||||
| //                { | ||||
| //                    std::cout << "SBAS message type " << it->get_msg_type() << " from PRN" << it->get_prn() << " received" << std::endl; | ||||
| //                    sbas_telemetry_data.update(*it); | ||||
| //                } | ||||
|  | ||||
|             // clear all processed samples in the input buffer | ||||
|             d_sample_buf.clear(); | ||||
|         } | ||||
|  | ||||
|     // UPDATE GNSS SYNCHRO DATA | ||||
|     Gnss_Synchro current_synchro_data; //structure to save the synchronization information and send the output object to the next block | ||||
|     //1. Copy the current tracking output | ||||
|     current_synchro_data = in[0][0]; | ||||
|     //2. Add the telemetry decoder information | ||||
|     if (this->d_flag_preamble == true and d_GPS_FSM.d_nav.d_TOW > 0) | ||||
|         //update TOW at the preamble instant (todo: check for valid d_TOW) | ||||
|         // JAVI: 30/06/2014 | ||||
|         // TOW, in GPS, is referred to the START of the SUBFRAME, that is, THE FIRST SYMBOL OF THAT SUBFRAME, NOT THE PREAMBLE. | ||||
|         // thus, no correction should be done. d_TOW_at_Preamble should be renamed to d_TOW_at_subframe_start. | ||||
|         // Sice we detected the preable, then, we are in the last symbol of that preamble, or just at the start of the first subframe symbol. | ||||
|         { | ||||
|             d_TOW_at_Preamble = d_GPS_FSM.d_nav.d_TOW + GPS_SUBFRAME_SECONDS; //we decoded the current TOW when the last word of the subframe arrive, so, we have a lag of ONE SUBFRAME | ||||
|             d_TOW_at_current_symbol = d_TOW_at_Preamble;//GPS_L1_CA_CODE_PERIOD;// + (double)GPS_CA_PREAMBLE_LENGTH_BITS/(double)GPS_CA_TELEMETRY_RATE_BITS_SECOND; | ||||
|             Prn_timestamp_at_preamble_ms = in[0][0].Tracking_timestamp_secs * 1000.0; | ||||
|             if (flag_TOW_set == false) | ||||
|                 { | ||||
|                     flag_TOW_set = true; | ||||
|                 } | ||||
|         } | ||||
|     else | ||||
|         { | ||||
|             d_TOW_at_current_symbol = d_TOW_at_current_symbol + GPS_L1_CA_CODE_PERIOD; | ||||
|         } | ||||
|  | ||||
|     current_synchro_data.d_TOW = d_TOW_at_Preamble; | ||||
|     current_synchro_data.d_TOW_at_current_symbol = d_TOW_at_current_symbol; | ||||
|  | ||||
|     current_synchro_data.d_TOW_hybrid_at_current_symbol = current_synchro_data.d_TOW_at_current_symbol; // to be  used in the hybrid configuration | ||||
|     current_synchro_data.Flag_valid_word = (d_flag_frame_sync == true and d_flag_parity == true and flag_TOW_set == true); | ||||
|     current_synchro_data.Flag_preamble = d_flag_preamble; | ||||
|     current_synchro_data.Prn_timestamp_ms = in[0][0].Tracking_timestamp_secs * 1000.0; | ||||
|     current_synchro_data.Prn_timestamp_at_preamble_ms = Prn_timestamp_at_preamble_ms; | ||||
|  | ||||
|     if(d_dump == true) | ||||
|         { | ||||
|             // MULTIPLEXED FILE RECORDING - Record results to file | ||||
|             try | ||||
|             { | ||||
|                     double tmp_double; | ||||
|                     tmp_double = d_TOW_at_current_symbol; | ||||
|                     d_dump_file.write((char*)&tmp_double, sizeof(double)); | ||||
|                     tmp_double = current_synchro_data.Prn_timestamp_ms; | ||||
|                     d_dump_file.write((char*)&tmp_double, sizeof(double)); | ||||
|                     tmp_double = d_TOW_at_Preamble; | ||||
|                     d_dump_file.write((char*)&tmp_double, sizeof(double)); | ||||
|             } | ||||
|             catch (std::ifstream::failure e) | ||||
|             { | ||||
|                     LOG(WARNING) << "Exception writing observables dump file " << e.what(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|     //todo: implement averaging | ||||
|             //1. Copy the current tracking output | ||||
|             current_synchro_data = in[0]; | ||||
|             //2. Add the telemetry decoder information | ||||
|             current_synchro_data.Flag_valid_word = false; // indicate to observable block that this synchro object isn't valid for pseudorange computation | ||||
|  | ||||
|     d_average_count++; | ||||
|     if (d_average_count == d_decimation_output_factor) | ||||
|         { | ||||
|             d_average_count = 0; | ||||
|             //3. Make the output (copy the object contents to the GNURadio reserved memory) | ||||
|             *out[0] = current_synchro_data; | ||||
|             out[0] = current_synchro_data; | ||||
|             //std::cout<<"GPS L2 TLM output on CH="<<this->d_channel << " SAMPLE STAMP="<<d_sample_counter/d_decimation_output_factor<<std::endl; | ||||
|             return 1; | ||||
|         } | ||||
| @@ -366,45 +254,275 @@ int gps_l2_m_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_in | ||||
| } | ||||
|  | ||||
|  | ||||
| void gps_l2_m_telemetry_decoder_cc::set_decimation(int decimation) | ||||
| { | ||||
|     d_decimation_output_factor = decimation; | ||||
| } | ||||
|  | ||||
| void gps_l2_m_telemetry_decoder_cc::set_satellite(Gnss_Satellite satellite) | ||||
| { | ||||
|     d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN()); | ||||
|     LOG(INFO) << "Setting decoder Finite State Machine to satellite "  << d_satellite; | ||||
|     d_GPS_FSM.i_satellite_PRN = d_satellite.get_PRN(); | ||||
|     DLOG(INFO) << "Navigation Satellite set to " << d_satellite; | ||||
|     LOG(INFO) << "GPS L2C CNAV telemetry decoder in channel " << this->d_channel << " set to satellite " << d_satellite; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void gps_l2_m_telemetry_decoder_cc::set_channel(int channel) | ||||
| { | ||||
|     d_channel = channel; | ||||
|     d_GPS_FSM.i_channel_ID = channel; | ||||
|     DLOG(INFO) << "Navigation channel set to " << channel; | ||||
|     // ############# ENABLE DATA FILE LOG ################# | ||||
|     if (d_dump == true) | ||||
|     LOG(INFO) << "GPS L2C CNAV channel set to " << channel; | ||||
| } | ||||
|  | ||||
|  | ||||
| // ### helper class for symbol alignment and viterbi decoding ### | ||||
| gps_l2_m_telemetry_decoder_cc::symbol_aligner_and_decoder::symbol_aligner_and_decoder() | ||||
| { | ||||
|     // convolutional code properties | ||||
|     d_KK = 7; | ||||
|     int nn = 2; | ||||
|     int g_encoder[nn]; | ||||
|     g_encoder[0] = 121; //171o | ||||
|     g_encoder[1] = 91; //133o | ||||
|  | ||||
|     d_vd1 = new Viterbi_Decoder(g_encoder, d_KK, nn); | ||||
|     d_vd2 = new Viterbi_Decoder(g_encoder, d_KK, nn); | ||||
|     d_past_symbol = 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| gps_l2_m_telemetry_decoder_cc::symbol_aligner_and_decoder::~symbol_aligner_and_decoder() | ||||
| { | ||||
|     delete d_vd1; | ||||
|     delete d_vd2; | ||||
| } | ||||
|  | ||||
|  | ||||
| void gps_l2_m_telemetry_decoder_cc::symbol_aligner_and_decoder::reset() | ||||
| { | ||||
|     d_past_symbol = 0; | ||||
|     d_vd1->reset(); | ||||
|     d_vd2->reset(); | ||||
| } | ||||
|  | ||||
|  | ||||
| bool gps_l2_m_telemetry_decoder_cc::symbol_aligner_and_decoder::get_bits(const std::vector<double> symbols, std::vector<int> &bits) | ||||
| { | ||||
|     const int traceback_depth = 5*d_KK; | ||||
|     int nbits_requested = symbols.size()/d_symbols_per_bit; | ||||
|     int nbits_decoded; | ||||
|     // fill two vectors with the two possible symbol alignments | ||||
|     std::vector<double> symbols_vd1(symbols); // aligned symbol vector -> copy input symbol vector | ||||
|     std::vector<double> symbols_vd2;  // shifted symbol vector -> add past sample in front of input vector | ||||
|     symbols_vd2.push_back(d_past_symbol); | ||||
|     for (std::vector<double>::const_iterator symbol_it = symbols.begin(); symbol_it != symbols.end() - 1; ++symbol_it) | ||||
|         { | ||||
|             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 (std::ifstream::failure e) | ||||
|                     { | ||||
|                             LOG(WARNING) << "channel " << d_channel << " Exception opening trk dump file " << e.what(); | ||||
|                     } | ||||
|             symbols_vd2.push_back(*symbol_it); | ||||
|         } | ||||
|     // arrays for decoded bits | ||||
|     int * bits_vd1 = new int[nbits_requested]; | ||||
|     int * bits_vd2 = new int[nbits_requested]; | ||||
|     // decode | ||||
|     float metric_vd1 = d_vd1->decode_continuous(symbols_vd1.data(), traceback_depth, bits_vd1, nbits_requested, nbits_decoded); | ||||
|     float metric_vd2 = d_vd2->decode_continuous(symbols_vd2.data(), traceback_depth, bits_vd2, nbits_requested, nbits_decoded); | ||||
|     LOG(INFO)<<"metric_vd1="<<metric_vd1<<" metric_vd2="<<metric_vd2; | ||||
|     // choose the bits with the better metric | ||||
|     for (int i = 0; i < nbits_decoded; i++) | ||||
|         { | ||||
|             if (metric_vd1 > metric_vd2) | ||||
|                 {// symbols aligned | ||||
|                     bits.push_back(bits_vd1[i]); | ||||
|                 } | ||||
|             else | ||||
|                 {// symbols shifted | ||||
|                     bits.push_back(bits_vd2[i]); | ||||
|                 } | ||||
|         } | ||||
|     d_past_symbol = symbols.back(); | ||||
|     delete[] bits_vd1; | ||||
|     delete[] bits_vd2; | ||||
|     return metric_vd1 > metric_vd2; | ||||
| } | ||||
|  | ||||
|  | ||||
| // ### helper class for detecting the preamble and collect the corresponding message candidates ### | ||||
| void gps_l2_m_telemetry_decoder_cc::frame_detector::reset() | ||||
| { | ||||
|     d_buffer.clear(); | ||||
| } | ||||
|  | ||||
|  | ||||
| void gps_l2_m_telemetry_decoder_cc::frame_detector::get_frame_candidates(const std::vector<int> bits, std::vector<std::pair<int,std::vector<int>>> &msg_candidates) | ||||
| { | ||||
|     std::stringstream ss; | ||||
|     unsigned int sbas_msg_length = 300; | ||||
|     std::vector<std::vector<int>> preambles = {{1, 0, 0, 0, 1, 0, 1 ,1}}; | ||||
|     //LOG(INFO) << "get_frame_candidates(): " << "d_buffer.size()=" << d_buffer.size() << "\tbits.size()=" << bits.size(); | ||||
|     ss << "copy bits "; | ||||
|     int count = 0; | ||||
|     // copy new bits into the working buffer | ||||
|     for (std::vector<int>::const_iterator bit_it = bits.begin(); bit_it < bits.end(); ++bit_it) | ||||
|         { | ||||
|             d_buffer.push_back(*bit_it); | ||||
|             ss << *bit_it; | ||||
|             count++; | ||||
|         } | ||||
|     //LOG(INFO) << ss.str() << " into working buffer (" << count << " bits)"; | ||||
|     int relative_preamble_start = 0; | ||||
|     while(d_buffer.size() >= sbas_msg_length) | ||||
|         { | ||||
|             // compare with all preambles | ||||
|             for (std::vector<std::vector<int>>::iterator preample_it = preambles.begin(); preample_it < preambles.end(); ++preample_it) | ||||
|                 { | ||||
|                     bool preamble_detected = true; | ||||
|                     bool inv_preamble_detected = true; | ||||
|                     // compare the buffer bits with the preamble bits | ||||
|                     for (std::vector<int>::iterator preample_bit_it = preample_it->begin(); preample_bit_it < preample_it->end(); ++preample_bit_it) | ||||
|                         { | ||||
|                             preamble_detected = *preample_bit_it == d_buffer[preample_bit_it - preample_it->begin()] ? preamble_detected : false ; | ||||
|                             inv_preamble_detected = *preample_bit_it != d_buffer[preample_bit_it - preample_it->begin()] ? inv_preamble_detected : false ; | ||||
|                         } | ||||
|                     if (preamble_detected || inv_preamble_detected) | ||||
|                         { | ||||
|                             // copy candidate | ||||
|                             std::vector<int> candidate; | ||||
|                             std::copy(d_buffer.begin(), d_buffer.begin() + sbas_msg_length, std::back_inserter(candidate)); | ||||
|                             if(inv_preamble_detected) | ||||
|                                 { | ||||
|                                     // invert bits | ||||
|                                     for (std::vector<int>::iterator candidate_bit_it = candidate.begin(); candidate_bit_it != candidate.end(); candidate_bit_it++) | ||||
|                                         *candidate_bit_it = *candidate_bit_it == 0 ? 1 : 0; | ||||
|                                 } | ||||
|                             msg_candidates.push_back(std::pair<int,std::vector<int>>(relative_preamble_start, candidate)); | ||||
|                             ss.str(""); | ||||
|                             ss << "preamble " << preample_it - preambles.begin() << (inv_preamble_detected?" inverted":" normal") << " detected! candidate="; | ||||
|                             for (std::vector<int>::iterator bit_it = candidate.begin(); bit_it < candidate.end(); ++bit_it) | ||||
|                                 ss << *bit_it; | ||||
|                             //LOG(INFO) << ss.str(); | ||||
|                         } | ||||
|                 } | ||||
|             relative_preamble_start++; | ||||
|             // remove bit in front | ||||
|             d_buffer.pop_front(); | ||||
|         } | ||||
| } | ||||
|  | ||||
|  | ||||
| // ### helper class for checking the CRC of the message candidates ### | ||||
|  | ||||
|  | ||||
| void gps_l2_m_telemetry_decoder_cc::crc_verifier::reset() | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
| void gps_l2_m_telemetry_decoder_cc::crc_verifier::get_valid_frames(const std::vector<msg_candiate_int_t> msg_candidates, std::vector<msg_candiate_char_t> &valid_msgs) | ||||
| { | ||||
|     std::stringstream ss; | ||||
|     LOG(INFO) << "get_valid_frames(): " << "msg_candidates.size()=" << msg_candidates.size(); | ||||
|     // for each candidate | ||||
|     for (std::vector<msg_candiate_int_t>::const_iterator candidate_it = msg_candidates.begin(); candidate_it < msg_candidates.end(); ++candidate_it) | ||||
|         { | ||||
|             // convert to bytes | ||||
|             std::vector<unsigned char> candidate_bytes; | ||||
|             zerropad_back_and_convert_to_bytes(candidate_it->second, candidate_bytes); | ||||
|             // verify CRC | ||||
|             d_checksum_agent.reset(0); | ||||
|             d_checksum_agent.process_bytes(candidate_bytes.data(), candidate_bytes.size()); | ||||
|             unsigned int crc = d_checksum_agent.checksum(); | ||||
|             LOG(INFO) << "candidate " << ": final crc remainder= " << std::hex << crc | ||||
|                             << std::setfill(' ') << std::resetiosflags(std::ios::hex); | ||||
|             //  the final remainder must be zero for a valid message, because the CRC is done over the received CRC value | ||||
|             if (crc == 0) | ||||
|                 { | ||||
|                     valid_msgs.push_back(msg_candiate_char_t(candidate_it->first, candidate_bytes)); | ||||
|                     ss << "Valid message found!"; | ||||
|                 } | ||||
|             else | ||||
|                 { | ||||
|                     ss << "Not a valid message."; | ||||
|                 } | ||||
|             //ss << " Relbitoffset=" << candidate_it->first << " content="; | ||||
|             for (std::vector<unsigned char>::iterator byte_it = candidate_bytes.begin(); byte_it < candidate_bytes.end(); ++byte_it) | ||||
|                 { | ||||
|                     ss << std::setw(2) << std::setfill('0') << std::hex << (unsigned int)(*byte_it); | ||||
|                 } | ||||
|             LOG(INFO) << ss.str() << std::setfill(' ') << std::resetiosflags(std::ios::hex) << std::endl; | ||||
|         } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void gps_l2_m_telemetry_decoder_cc::crc_verifier::zerropad_back_and_convert_to_bytes(const std::vector<int> msg_candidate, std::vector<unsigned char> &bytes) | ||||
| { | ||||
|     std::stringstream ss; | ||||
|     const size_t bits_per_byte = 8; | ||||
|     unsigned char byte = 0; | ||||
|     //LOG(INFO) << "zerropad_back_and_convert_to_bytes():" << byte; | ||||
|     for (std::vector<int>::const_iterator candidate_bit_it = msg_candidate.begin(); candidate_bit_it < msg_candidate.end(); ++candidate_bit_it) | ||||
|         { | ||||
|             int idx_bit = candidate_bit_it - msg_candidate.begin(); | ||||
|             int bit_pos_in_current_byte = (bits_per_byte - 1) - (idx_bit % bits_per_byte); | ||||
|             byte |= (unsigned char)(*candidate_bit_it) << bit_pos_in_current_byte; | ||||
|             ss << *candidate_bit_it; | ||||
|             if (idx_bit % bits_per_byte == bits_per_byte - 1) | ||||
|                 { | ||||
|                     bytes.push_back(byte); | ||||
|                     //LOG(INFO) << ss.str() << " -> byte=" << std::setw(2) << std::setfill('0') << std::hex << (unsigned int)byte; ss.str(""); | ||||
|                     byte = 0; | ||||
|                 } | ||||
|         } | ||||
|     bytes.push_back(byte); // implies: insert 6 zeros at the end to fit the 250bits into a multiple of bytes | ||||
|     LOG(INFO) << " -> byte=" << std::setw(2) | ||||
|                 << std::setfill('0') << std::hex << (unsigned int)byte | ||||
|                 << std::setfill(' ') << std::resetiosflags(std::ios::hex); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void gps_l2_m_telemetry_decoder_cc::crc_verifier::zerropad_front_and_convert_to_bytes(const std::vector<int> msg_candidate, std::vector<unsigned char> &bytes) | ||||
| { | ||||
|     std::stringstream ss; | ||||
|     const size_t bits_per_byte = 8; | ||||
|     unsigned char byte = 0; | ||||
|     int idx_bit = 6; // insert 6 zeros at the front to fit the 250bits into a multiple of bytes | ||||
|     LOG(INFO) << "zerropad_front_and_convert_to_bytes():" << byte; | ||||
|     for (std::vector<int>::const_iterator candidate_bit_it = msg_candidate.begin(); candidate_bit_it < msg_candidate.end(); ++candidate_bit_it) | ||||
|         { | ||||
|             int bit_pos_in_current_byte = (bits_per_byte - 1) - (idx_bit % bits_per_byte); | ||||
|             byte |= (unsigned char)(*candidate_bit_it) << bit_pos_in_current_byte; | ||||
|             ss << *candidate_bit_it; | ||||
|             if (idx_bit % bits_per_byte == bits_per_byte - 1) | ||||
|                 { | ||||
|                     bytes.push_back(byte); | ||||
|                     LOG(INFO) << ss.str() << " -> byte=" << std::setw(2) | ||||
|                                 << std::setfill('0') << std::hex << (unsigned int)byte; ss.str(""); | ||||
|                     byte = 0; | ||||
|                 } | ||||
|             idx_bit++; | ||||
|         } | ||||
|     LOG(INFO) << " -> byte=" << std::setw(2) | ||||
|                 << std::setfill('0') << std::hex << (unsigned int)byte | ||||
|                 << std::setfill(' ') << std::resetiosflags(std::ios::hex); | ||||
| } | ||||
|  | ||||
| // | ||||
| //void gps_l2_m_telemetry_decoder_cc::set_raw_msg_queue(concurrent_queue<Sbas_Raw_Msg> *raw_msg_queue) | ||||
| //{ | ||||
| //    sbas_telemetry_data.set_raw_msg_queue(raw_msg_queue); | ||||
| //} | ||||
| // | ||||
| // | ||||
| //void gps_l2_m_telemetry_decoder_cc::set_iono_queue(concurrent_queue<Sbas_Ionosphere_Correction> *iono_queue) | ||||
| //{ | ||||
| //    sbas_telemetry_data.set_iono_queue(iono_queue); | ||||
| //} | ||||
| // | ||||
| // | ||||
| //void gps_l2_m_telemetry_decoder_cc::set_sat_corr_queue(concurrent_queue<Sbas_Satellite_Correction> *sat_corr_queue) | ||||
| //{ | ||||
| //    sbas_telemetry_data.set_sat_corr_queue(sat_corr_queue); | ||||
| //} | ||||
| // | ||||
| // | ||||
| //void gps_l2_m_telemetry_decoder_cc::set_ephemeris_queue(concurrent_queue<Sbas_Ephemeris> *ephemeris_queue) | ||||
| //{ | ||||
| //    sbas_telemetry_data.set_ephemeris_queue(ephemeris_queue); | ||||
| //} | ||||
|   | ||||
| @@ -31,16 +31,18 @@ | ||||
| #ifndef GNSS_SDR_GPS_L2_M_TELEMETRY_DECODER_CC_H | ||||
| #define	GNSS_SDR_GPS_L2_M_TELEMETRY_DECODER_CC_H | ||||
|  | ||||
| #include <algorithm> // for copy | ||||
| #include <deque> | ||||
| #include <fstream> | ||||
| #include <string> | ||||
| #include <utility> // for pair | ||||
| #include <vector> | ||||
| #include <boost/crc.hpp> | ||||
| #include <gnuradio/block.h> | ||||
| #include <gnuradio/msg_queue.h> | ||||
| #include "GPS_L1_CA.h" | ||||
| #include "gps_l1_ca_subframe_fsm.h" | ||||
| #include "concurrent_queue.h" | ||||
| #include "gnss_satellite.h" | ||||
|  | ||||
|  | ||||
| #include "viterbi_decoder.h" | ||||
| //#include "sbas_telemetry_data.h" | ||||
|  | ||||
| class gps_l2_m_telemetry_decoder_cc; | ||||
|  | ||||
| @@ -51,7 +53,7 @@ gps_l2_m_make_telemetry_decoder_cc(Gnss_Satellite satellite, long if_freq, long | ||||
|     int vector_length, boost::shared_ptr<gr::msg_queue> queue, bool dump); | ||||
|  | ||||
| /*! | ||||
|  * \brief This class implements a block that decodes the NAV data defined in IS-GPS-200E | ||||
|  * \brief This class implements a block that decodes the SBAS integrity and corrections data defined in RTCA MOPS DO-229 | ||||
|  * | ||||
|  */ | ||||
| class gps_l2_m_telemetry_decoder_cc : public gr::block | ||||
| @@ -61,20 +63,12 @@ public: | ||||
|     void set_satellite(Gnss_Satellite satellite);  //!< Set satellite PRN | ||||
|     void set_channel(int channel);                 //!< Set receiver's channel | ||||
|  | ||||
|  | ||||
|     /*! | ||||
|      * \brief Set decimation factor to average the GPS synchronization estimation output from the tracking module. | ||||
|      */ | ||||
|     // queues to communicate broadcasted SBAS data to other blocks of GNSS-SDR | ||||
|     //void set_raw_msg_queue(concurrent_queue<Sbas_Raw_Msg> *raw_msg_queue);                 //!< Set raw msg queue | ||||
|     //void set_iono_queue(concurrent_queue<Sbas_Ionosphere_Correction> *iono_queue);         //!< Set iono queue | ||||
|     //void set_sat_corr_queue(concurrent_queue<Sbas_Satellite_Correction> *sat_corr_queue);  //!< Set sat correction queue | ||||
|     //void set_ephemeris_queue(concurrent_queue<Sbas_Ephemeris> *ephemeris_queue);           //!< Set SBAS ephemeis queue | ||||
|     void set_decimation(int decimation); | ||||
|  | ||||
|     /*! | ||||
|      * \brief Set the satellite data queue | ||||
|      */ | ||||
|     void set_ephemeris_queue(concurrent_queue<Gps_Ephemeris> *ephemeris_queue){d_GPS_FSM.d_ephemeris_queue = ephemeris_queue;} //!< Set the ephemeris data queue | ||||
|     void set_iono_queue(concurrent_queue<Gps_Iono> *iono_queue){d_GPS_FSM.d_iono_queue = iono_queue;}                          //!< Set the iono data queue | ||||
|     void set_almanac_queue(concurrent_queue<Gps_Almanac> *almanac_queue){d_GPS_FSM.d_almanac_queue = almanac_queue;}           //!< Set the almanac data queue | ||||
|     void set_utc_model_queue(concurrent_queue<Gps_Utc_Model> *utc_model_queue){d_GPS_FSM.d_utc_model_queue = utc_model_queue;} //!< Set the UTC model data queue | ||||
|  | ||||
|     /*! | ||||
|      * \brief This is where all signal processing takes place | ||||
|      */ | ||||
| @@ -91,62 +85,78 @@ private: | ||||
|     friend gps_l2_m_telemetry_decoder_cc_sptr | ||||
|     gps_l2_m_make_telemetry_decoder_cc(Gnss_Satellite satellite, long if_freq, long fs_in,unsigned | ||||
|             int vector_length, boost::shared_ptr<gr::msg_queue> queue, bool dump); | ||||
|  | ||||
|     gps_l2_m_telemetry_decoder_cc(Gnss_Satellite satellite, long if_freq, long fs_in, unsigned | ||||
|             int vector_length, boost::shared_ptr<gr::msg_queue> queue, bool dump); | ||||
|  | ||||
|     bool gps_word_parityCheck(unsigned int gpsword); | ||||
|     void viterbi_decoder(double *page_part_symbols, int *page_part_bits); | ||||
|     void align_samples(); | ||||
|  | ||||
|     // constants | ||||
|     unsigned short int d_preambles_bits[GPS_CA_PREAMBLE_LENGTH_BITS]; | ||||
|     // class private vars | ||||
|  | ||||
|     signed int *d_preambles_symbols; | ||||
|     unsigned int d_samples_per_bit; | ||||
|     long unsigned int d_sample_counter; | ||||
|     long unsigned int d_preamble_index; | ||||
|     unsigned int d_stat; | ||||
|     bool d_flag_frame_sync; | ||||
|  | ||||
|     // symbols | ||||
|     double d_symbol_accumulator; | ||||
|     short int d_symbol_accumulator_counter; | ||||
|  | ||||
|     //bits and frame | ||||
|     unsigned short int d_frame_bit_index; | ||||
|     unsigned int d_GPS_frame_4bytes; | ||||
|     unsigned int d_prev_GPS_frame_4bytes; | ||||
|     bool d_flag_parity; | ||||
|     bool d_flag_preamble; | ||||
|     int d_word_number; | ||||
|  | ||||
|     // output averaging and decimation | ||||
|     int d_average_count; | ||||
|     int d_decimation_output_factor; | ||||
|     static const int d_samples_per_symbol = 1; | ||||
|     static const int d_symbols_per_bit = 2; | ||||
|     static const int d_block_size_in_bits = 300; | ||||
|  | ||||
|     long d_fs_in; | ||||
|     //double d_preamble_duration_seconds; | ||||
|     // navigation message vars | ||||
|     Gps_Navigation_Message d_nav; | ||||
|     GpsL1CaSubframeFsm d_GPS_FSM; | ||||
|  | ||||
|     boost::shared_ptr<gr::msg_queue> d_queue; | ||||
|     unsigned int d_vector_length; | ||||
|     bool d_dump; | ||||
|     Gnss_Satellite d_satellite; | ||||
|     int d_channel; | ||||
|  | ||||
|     //std::deque<double> d_prn_start_sample_history; | ||||
|  | ||||
|     double d_preamble_time_seconds; | ||||
|  | ||||
|     double d_TOW_at_Preamble; | ||||
|     double d_TOW_at_current_symbol; | ||||
|     double Prn_timestamp_at_preamble_ms; | ||||
|     bool flag_TOW_set; | ||||
|  | ||||
|     std::string d_dump_filename; | ||||
|     std::ofstream d_dump_file; | ||||
|  | ||||
|     bool d_flag_invert_input_symbols; | ||||
|     bool d_flag_invert_buffer_symbols; | ||||
|     int d_decimation_output_factor; | ||||
|     int d_average_count; | ||||
|     size_t d_block_size; //!< number of samples which are processed during one invocation of the algorithms | ||||
|     std::vector<double> d_sample_buf; //!< input buffer holding the samples to be processed in one block | ||||
|  | ||||
|     typedef std::pair<int,std::vector<int>> msg_candiate_int_t; | ||||
|     typedef std::pair<int,std::vector<unsigned char>> msg_candiate_char_t; | ||||
|  | ||||
|     // helper class for symbol alignment and Viterbi decoding | ||||
|     class symbol_aligner_and_decoder | ||||
|     { | ||||
|     public: | ||||
|         symbol_aligner_and_decoder(); | ||||
|         ~symbol_aligner_and_decoder(); | ||||
|         void reset(); | ||||
|         bool get_bits(const std::vector<double> symbols, std::vector<int> &bits); | ||||
|     private: | ||||
|         int d_KK; | ||||
|         Viterbi_Decoder * d_vd1; | ||||
|         Viterbi_Decoder * d_vd2; | ||||
|         double d_past_symbol; | ||||
|     } d_symbol_aligner_and_decoder; | ||||
|  | ||||
|  | ||||
|     // helper class for detecting the preamble and collect the corresponding message candidates | ||||
|     class frame_detector | ||||
|     { | ||||
|     public: | ||||
|         void reset(); | ||||
|         void get_frame_candidates(const std::vector<int> bits, std::vector<std::pair<int, std::vector<int>>> &msg_candidates); | ||||
|     private: | ||||
|         std::deque<int> d_buffer; | ||||
|     } d_frame_detector; | ||||
|  | ||||
|  | ||||
|     // helper class for checking the CRC of the message candidates | ||||
|     class crc_verifier | ||||
|     { | ||||
|     public: | ||||
|         void reset(); | ||||
|         void get_valid_frames(const std::vector<msg_candiate_int_t> msg_candidates, std::vector<msg_candiate_char_t> &valid_msgs); | ||||
|     private: | ||||
|         typedef boost::crc_optimal<24, 0x1864CFBu, 0x0, 0x0, false, false> crc_24_q_type; | ||||
|         crc_24_q_type d_checksum_agent; | ||||
|         void zerropad_front_and_convert_to_bytes(const std::vector<int> msg_candidate, std::vector<unsigned char> &bytes); | ||||
|         void zerropad_back_and_convert_to_bytes(const std::vector<int> msg_candidate, std::vector<unsigned char> &bytes); | ||||
|     } d_crc_verifier; | ||||
|  | ||||
|  | ||||
|     //Sbas_Telemetry_Data sbas_telemetry_data; | ||||
| }; | ||||
|  | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -327,7 +327,7 @@ bool sbas_l1_telemetry_decoder_cc::symbol_aligner_and_decoder::get_bits(const st | ||||
|     // fill two vectors with the two possible symbol alignments | ||||
|     std::vector<double> symbols_vd1(symbols); // aligned symbol vector -> copy input symbol vector | ||||
|     std::vector<double> symbols_vd2;  // shifted symbol vector -> add past sample in front of input vector | ||||
|     symbols_vd1.push_back(d_past_symbol); | ||||
|     symbols_vd2.push_back(d_past_symbol); | ||||
|     for (std::vector<double>::const_iterator symbol_it = symbols.begin(); symbol_it != symbols.end() - 1; ++symbol_it) | ||||
|         { | ||||
|             symbols_vd2.push_back(*symbol_it); | ||||
|   | ||||
| @@ -222,7 +222,6 @@ void gps_l2_m_dll_pll_tracking_cc::start_tracking() | ||||
|             corrected_acq_phase_samples = T_prn_mod_samples + corrected_acq_phase_samples; | ||||
|         } | ||||
|     delay_correction_samples = d_acq_code_phase_samples - corrected_acq_phase_samples; | ||||
|  | ||||
|     d_acq_code_phase_samples = corrected_acq_phase_samples; | ||||
|  | ||||
|     d_carrier_doppler_hz = d_acq_carrier_doppler_hz; | ||||
| @@ -615,7 +614,7 @@ int gps_l2_m_dll_pll_tracking_cc::general_work (int noutput_items, gr_vector_int | ||||
|                     tmp_double = static_cast<double>(d_sample_counter + d_current_prn_length_samples); | ||||
|                     d_dump_file.write(reinterpret_cast<char*>(&tmp_double), sizeof(double)); | ||||
|             } | ||||
|             catch (std::ifstream::failure e) | ||||
|             catch (std::ifstream::failure& e) | ||||
|             { | ||||
|                     LOG(WARNING) << "Exception writing trk dump file " << e.what(); | ||||
|             } | ||||
| @@ -645,7 +644,7 @@ void gps_l2_m_dll_pll_tracking_cc::set_channel(unsigned int channel) | ||||
|                             d_dump_file.open(d_dump_filename.c_str(), std::ios::out | std::ios::binary); | ||||
|                             LOG(INFO) << "Tracking dump enabled on channel " << d_channel << " Log file: " << d_dump_filename.c_str() << std::endl; | ||||
|                     } | ||||
|                     catch (std::ifstream::failure e) | ||||
|                     catch (std::ifstream::failure& e) | ||||
|                     { | ||||
|                             LOG(WARNING) << "channel " << d_channel << " Exception opening trk dump file " << e.what() << std::endl; | ||||
|                     } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Carles Fernandez
					Carles Fernandez