From d664dc63b3f4332d6ef342fb7d65d8c8188834b4 Mon Sep 17 00:00:00 2001 From: Javier Arribas Date: Tue, 8 Mar 2016 18:30:56 +0100 Subject: [PATCH 1/2] Experimental extended correlation for GPS L1 CA C_Aid tracking --- conf/gnss-sdr_Hybrid_nsr.conf | 19 +- src/algorithms/channel/adapters/channel.cc | 4 + .../gps_l1_ca_telemetry_decoder_cc.cc | 74 +++- .../gps_l1_ca_dll_pll_c_aid_tracking_cc.cc | 325 ++++++++++++------ .../gps_l1_ca_dll_pll_c_aid_tracking_cc.h | 16 + src/core/receiver/gnss_flowgraph.cc | 12 +- src/core/system_parameters/GPS_L1_CA.h | 1 + src/core/system_parameters/gnss_synchro.h | 2 + 8 files changed, 319 insertions(+), 134 deletions(-) diff --git a/conf/gnss-sdr_Hybrid_nsr.conf b/conf/gnss-sdr_Hybrid_nsr.conf index f58d5437c..1609800c9 100644 --- a/conf/gnss-sdr_Hybrid_nsr.conf +++ b/conf/gnss-sdr_Hybrid_nsr.conf @@ -19,7 +19,7 @@ ControlThread.wait_for_flowgraph=false SignalSource.implementation=Nsr_File_Signal_Source ;#filename: path to file with the captured GNSS signal samples to be processed -SignalSource.filename=/datalogger/signals/ifen/E1L1_FE0_Band0.stream +SignalSource.filename=/media/javier/SISTEMA/signals/ifen/E1L1_FE0_Band0.stream ;#item_type: Type and resolution for each of the signal samples. Use only gr_complex in this version. SignalSource.item_type=byte @@ -150,7 +150,7 @@ Resampler.implementation=Pass_Through ;#count: Number of available GPS satellite channels. Channels_1C.count=8 ;#count: Number of available Galileo satellite channels. -Channels_1B.count=8 +Channels_1B.count=0 ;#in_acquisition: Number of channels simultaneously acquiring for the whole receiver Channels.in_acquisition=1 @@ -193,14 +193,15 @@ Acquisition_1C.if=0 Acquisition_1C.sampled_ms=1 ;#implementation: Acquisition algorithm selection for this channel: [GPS_L1_CA_PCPS_Acquisition] or [Galileo_E1_PCPS_Ambiguous_Acquisition] Acquisition_1C.implementation=GPS_L1_CA_PCPS_Acquisition +Acquisition_1C.use_CFAR_algorithm=false; ;#threshold: Acquisition threshold -Acquisition_1C.threshold=0.0075 +Acquisition_1C.threshold=40 ;#pfa: Acquisition false alarm probability. This option overrides the threshold option. Only use with implementations: [GPS_L1_CA_PCPS_Acquisition] or [Galileo_E1_PCPS_Ambiguous_Acquisition] ;Acquisition_1C.pfa=0.01 ;#doppler_max: Maximum expected Doppler shift [Hz] Acquisition_1C.doppler_max=10000 ;#doppler_max: Doppler step in the grid search [Hz] -Acquisition_1C.doppler_step=500 +Acquisition_1C.doppler_step=250 ;######### GALILEO ACQUISITION CONFIG ############ @@ -229,7 +230,7 @@ Acquisition_1B.doppler_step=125 ;######### TRACKING GPS CONFIG ############ ;#implementation: Selected tracking algorithm: [GPS_L1_CA_DLL_PLL_Tracking] or [GPS_L1_CA_DLL_FLL_PLL_Tracking] or [GPS_L1_CA_TCP_CONNECTOR_Tracking] or [Galileo_E1_DLL_PLL_VEML_Tracking] -Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_Tracking +Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_C_Aid_Tracking ;#item_type: Type and resolution for each of the signal samples. Use only [gr_complex] in this version. Tracking_1C.item_type=gr_complex @@ -237,19 +238,19 @@ Tracking_1C.item_type=gr_complex Tracking_1C.if=0 ;#dump: Enable or disable the Tracking internal binary data file logging [true] or [false] -Tracking_1C.dump=false +Tracking_1C.dump=true ;#dump_filename: Log path and filename. Notice that the tracking channel will add "x.dat" where x is the channel number. Tracking_1C.dump_filename=../data/epl_tracking_ch_ ;#pll_bw_hz: PLL loop filter bandwidth [Hz] -Tracking_1C.pll_bw_hz=45.0; +Tracking_1C.pll_bw_hz=40; ;#dll_bw_hz: DLL loop filter bandwidth [Hz] -Tracking_1C.dll_bw_hz=2.0; +Tracking_1C.dll_bw_hz=2.5; ;#fll_bw_hz: FLL loop filter bandwidth [Hz] -Tracking_1C.fll_bw_hz=10.0; +Tracking_1C.fll_bw_hz=2.0; ;#order: PLL/DLL loop filter order [2] or [3] Tracking_1C.order=3; diff --git a/src/algorithms/channel/adapters/channel.cc b/src/algorithms/channel/adapters/channel.cc index 6269bc8be..30d851505 100644 --- a/src/algorithms/channel/adapters/channel.cc +++ b/src/algorithms/channel/adapters/channel.cc @@ -125,6 +125,10 @@ void Channel::connect(gr::top_block_sptr top_block) DLOG(INFO) << "pass_through_ -> tracking"; top_block->connect(trk_->get_right_block(), 0, nav_->get_left_block(), 0); DLOG(INFO) << "tracking -> telemetry_decoder"; + + top_block->msg_connect(nav_->get_left_block(),pmt::mp("preamble_index"),trk_->get_right_block(),pmt::mp("preamble_index")); + DLOG(INFO) << "MSG FEEDBACK CHANNEL telemetry_decoder -> tracking"; + connected_ = true; } diff --git a/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l1_ca_telemetry_decoder_cc.cc b/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l1_ca_telemetry_decoder_cc.cc index 5e4a6d582..e99b48989 100644 --- a/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l1_ca_telemetry_decoder_cc.cc +++ b/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l1_ca_telemetry_decoder_cc.cc @@ -38,6 +38,7 @@ #include #include #include +#include #include #include "control_message_factory.h" #include "gnss_synchro.h" @@ -78,6 +79,9 @@ gps_l1_ca_telemetry_decoder_cc::gps_l1_ca_telemetry_decoder_cc( gr::block("gps_navigation_cc", gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)), gr::io_signature::make(1, 1, sizeof(Gnss_Synchro))) { + // create asynchronous message ports + this->message_port_register_out(pmt::mp("preamble_index")); + // initialize internal vars d_queue = queue; d_dump = dump; @@ -178,6 +182,8 @@ int gps_l1_ca_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_i const Gnss_Synchro **in = (const Gnss_Synchro **) &input_items[0]; //Get the input samples pointer // TODO Optimize me! + if (in[0][d_samples_per_bit*8 - 1].symbol_integration_enabled==false) + { //******* preamble correlation ******** for (unsigned int i = 0; i < d_samples_per_bit*8; i++) { @@ -190,20 +196,37 @@ int gps_l1_ca_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_i corr_value += d_preambles_symbols[i]; } } + }else{ + //******* preamble correlation ******** + for (unsigned int i = 0; i < d_samples_per_bit*8; i++) + { + if (in[0][i].Flag_valid_symbol_output==true) + { + if (in[0][i].Prompt_I < 0) // symbols clipping + { + corr_value -= d_preambles_symbols[i]*d_samples_per_bit; + } + else + { + corr_value += d_preambles_symbols[i]*d_samples_per_bit; + } + } + } + } d_flag_preamble = false; //******* frame sync ****************** - if (abs(corr_value) >= 160) + 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; + DLOG(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_frame_bit_index = 7; d_stat = 1; // enter into frame pre-detection status } else if (d_stat == 1) //check 6 seconds of preamble separation @@ -215,20 +238,24 @@ int gps_l1_ca_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_i 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 - + d_frame_bit_index = 7; if (!d_flag_frame_sync) { + //send asynchronous message to tracking to inform of frame sync and extend correlation time + pmt::pmt_t value = pmt::from_long(d_preamble_index-1); + this->message_port_pub(pmt::mp("preamble_index"),value); + d_flag_frame_sync = true; if (corr_value < 0) { flag_PLL_180_deg_phase_locked = true; //PLL is locked to opposite phase! - LOG(INFO) << " PLL in opposite phase for Sat "<< this->d_satellite.get_PRN(); + DLOG(INFO) << " PLL in opposite phase for Sat "<< this->d_satellite.get_PRN(); } else { flag_PLL_180_deg_phase_locked = false; } - LOG(INFO) << " Frame sync SAT " << this->d_satellite << " with preamble start at " << d_preamble_time_seconds << " [s]"; + DLOG(INFO) << " Frame sync SAT " << this->d_satellite << " with preamble start at " << d_preamble_time_seconds << " [s]"; } } } @@ -240,7 +267,7 @@ int gps_l1_ca_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_i 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; + DLOG(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; @@ -249,16 +276,29 @@ int gps_l1_ca_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_i } //******* 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 (in[0][d_samples_per_bit*8 - 1].Flag_valid_symbol_output==true) + { + if (in[0][d_samples_per_bit*8 - 1].symbol_integration_enabled==true) + { + // extended correlation to bit period is enabled in tracking! + // 1 symbol = 1 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=20; + }else{ + // 20 symbols = 1 bit: do symbols integration in telemetry decoder + 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; + 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) @@ -302,6 +342,8 @@ int gps_l1_ca_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_i { d_GPS_frame_4bytes <<= 1; //shift 1 bit left the telemetry word } + + } // output the frame consume_each(1); //one by one diff --git a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_cc.cc b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_cc.cc index ecc4e8981..b7304512a 100644 --- a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_cc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_cc.cc @@ -34,7 +34,9 @@ #include #include #include +#include #include +#include #include #include #include "gps_sdr_signal_processing.h" @@ -82,6 +84,17 @@ void gps_l1_ca_dll_pll_c_aid_tracking_cc::forecast (int noutput_items, } } +void gps_l1_ca_dll_pll_c_aid_tracking_cc::msg_handler_preamble_index(pmt::pmt_t msg) +{ + //pmt::print(msg); + DLOG(INFO) << "Extended correlation for Tracking CH " << d_channel << ": Satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN)<< std::endl; + if (d_enable_20ms_integration==false) //avoid re-setting preamble indicator + { + d_preamble_index=pmt::to_long(msg); + d_enable_20ms_integration=true; + d_preamble_synchronized=false; + } +} gps_l1_ca_dll_pll_c_aid_tracking_cc::gps_l1_ca_dll_pll_c_aid_tracking_cc( @@ -97,6 +110,13 @@ gps_l1_ca_dll_pll_c_aid_tracking_cc::gps_l1_ca_dll_pll_c_aid_tracking_cc( gr::block("gps_l1_ca_dll_pll_c_aid_tracking_cc", gr::io_signature::make(1, 1, sizeof(gr_complex)), gr::io_signature::make(1, 1, sizeof(Gnss_Synchro))) { + // create asynchronous message ports + this->message_port_register_in(pmt::mp("preamble_index")); + + this->set_msg_handler(pmt::mp("preamble_index"), + boost::bind(&gps_l1_ca_dll_pll_c_aid_tracking_cc::msg_handler_preamble_index, this, _1)); + + // initialize internal vars d_queue = queue; d_dump = dump; @@ -107,8 +127,10 @@ gps_l1_ca_dll_pll_c_aid_tracking_cc::gps_l1_ca_dll_pll_c_aid_tracking_cc( d_correlation_length_samples = static_cast(d_vector_length); // Initialize tracking ========================================== - d_code_loop_filter.set_DLL_BW(dll_bw_hz); - d_carrier_loop_filter.set_params(10.0, pll_bw_hz,2); + d_pll_bw_hz=pll_bw_hz; + d_dll_bw_hz=dll_bw_hz; + d_code_loop_filter.set_DLL_BW(d_dll_bw_hz); + d_carrier_loop_filter.set_params(10.0, d_pll_bw_hz,2); //--- DLL variables -------------------------------------------------------- d_early_late_spc_chips = early_late_space_chips; // Define early-late offset (in chips) @@ -141,7 +163,9 @@ gps_l1_ca_dll_pll_c_aid_tracking_cc::gps_l1_ca_dll_pll_c_aid_tracking_cc( d_rem_carrier_phase_rad = 0.0; // sample synchronization - d_sample_counter = 0; + d_sample_counter = 0; //(from trk to tlm) + // symbol synchronization (from tlm to trk) + d_symbol_counter =0; //d_sample_counter_seconds = 0; d_acq_sample_stamp = 0; @@ -175,6 +199,8 @@ gps_l1_ca_dll_pll_c_aid_tracking_cc::gps_l1_ca_dll_pll_c_aid_tracking_cc( d_rem_code_phase_chips = 0.0; d_code_phase_step_chips = 0.0; d_carrier_phase_step_rad = 0.0; + d_enable_20ms_integration=false; + d_preamble_synchronized=false; //set_min_output_buffer((long int)300); } @@ -258,7 +284,8 @@ void gps_l1_ca_dll_pll_c_aid_tracking_cc::start_tracking() // enable tracking d_pull_in = true; d_enable_tracking = true; - + d_enable_20ms_integration=false; + d_preamble_synchronized=false; LOG(INFO) << "PULL-IN Doppler [Hz]=" << d_carrier_doppler_hz << " Code Phase correction [samples]=" << delay_correction_samples << " PULL-IN Code Phase [samples]=" << d_acq_code_phase_samples; @@ -315,6 +342,7 @@ int gps_l1_ca_dll_pll_c_aid_tracking_cc::general_work (int noutput_items, gr_vec current_synchro_data = *d_acquisition_gnss_synchro; *out[0] = current_synchro_data; consume_each(samples_offset); //shift input to perform alignment with local replica + d_symbol_counter++; return 1; } @@ -326,115 +354,203 @@ int gps_l1_ca_dll_pll_c_aid_tracking_cc::general_work (int noutput_items, gr_vec multicorrelator_cpu.set_input_output_vectors(d_correlator_outs,in); multicorrelator_cpu.Carrier_wipeoff_multicorrelator_resampler(d_rem_carrier_phase_rad, d_carrier_phase_step_rad, d_rem_code_phase_chips, d_code_phase_step_chips, d_correlation_length_samples); - // UPDATE INTEGRATION TIME - CURRENT_INTEGRATION_TIME_S = static_cast(d_correlation_length_samples) / static_cast(d_fs_in); + // ####### 20ms coherent intergration extension (experimental) + // keep the last 40 symbols (2 bits to detect transitions) + d_E_history.push_back(d_correlator_outs[0]); // save early output + d_P_history.push_back(d_correlator_outs[1]); // save prompt output + d_L_history.push_back(d_correlator_outs[2]); // save late output - // ################## PLL ########################################################## - // Update PLL discriminator [rads/Ti -> Secs/Ti] - carr_phase_error_secs_Ti = pll_cloop_two_quadrant_atan(d_correlator_outs[1]) / GPS_TWO_PI; //prompt output - // Carrier discriminator filter - // NOTICE: The carrier loop filter includes the Carrier Doppler accumulator, as described in Kaplan - //d_carrier_doppler_hz = d_acq_carrier_doppler_hz + carr_phase_error_filt_secs_ti/INTEGRATION_TIME; - // Input [s/Ti] -> output [Hz] - d_carrier_doppler_hz = d_carrier_loop_filter.get_carrier_error(0.0, carr_phase_error_secs_Ti, CURRENT_INTEGRATION_TIME_S); - // PLL to DLL assistance [Secs/Ti] - d_pll_to_dll_assist_secs_Ti = (d_carrier_doppler_hz * CURRENT_INTEGRATION_TIME_S) / GPS_L1_FREQ_HZ; - // code Doppler frequency update - d_code_freq_chips = GPS_L1_CA_CODE_RATE_HZ + ((d_carrier_doppler_hz * GPS_L1_CA_CODE_RATE_HZ) / GPS_L1_FREQ_HZ); + if (d_P_history.size()>GPS_CA_TELEMETRY_SYMBOLS_PER_BIT) + { + d_E_history.pop_front(); + d_P_history.pop_front(); + d_L_history.pop_front(); + } - // ################## DLL ########################################################## - // DLL discriminator - code_error_chips_Ti = dll_nc_e_minus_l_normalized(d_correlator_outs[0], d_correlator_outs[2]); //[chips/Ti] //early and late - // Code discriminator filter - code_error_filt_chips = d_code_loop_filter.get_code_nco(code_error_chips_Ti); //input [chips/Ti] -> output [chips/second] - code_error_filt_secs_Ti = code_error_filt_chips*CURRENT_INTEGRATION_TIME_S/d_code_freq_chips; // [s/Ti] - // DLL code error estimation [s/Ti] - // TODO: PLL carrier aid to DLL is disabled. Re-enable it and measure performance - dll_code_error_secs_Ti = - code_error_filt_secs_Ti + d_pll_to_dll_assist_secs_Ti; + bool enable_dll_pll; + if (d_enable_20ms_integration==true) + { + long int symbol_diff=d_symbol_counter-d_preamble_index; + if (symbol_diff % GPS_CA_TELEMETRY_SYMBOLS_PER_BIT == 0) + { + // compute coherent integration and enable tracking loop + // perform coherent integration using correlator output history + //gr_complex d_correlator_outs_2[3]; + //std::cout<<"##### RESET COHERENT INTEGRATION ####"<(d_fs_in); - K_blk_samples = T_prn_samples + d_rem_code_phase_samples - dll_code_error_secs_Ti * static_cast(d_fs_in); + if (d_preamble_synchronized==false) + { + d_preamble_synchronized=true; + } + current_synchro_data.symbol_integration_enabled=true; + // UPDATE INTEGRATION TIME + CURRENT_INTEGRATION_TIME_S = static_cast(GPS_CA_TELEMETRY_SYMBOLS_PER_BIT)*GPS_L1_CA_CODE_PERIOD; + d_code_loop_filter.set_DLL_BW(d_dll_bw_hz); + d_carrier_loop_filter.set_params(10.0, d_pll_bw_hz/5,2); + enable_dll_pll=true; - d_correlation_length_samples = round(K_blk_samples); //round to a discrete samples - old_d_rem_code_phase_samples=d_rem_code_phase_samples; - d_rem_code_phase_samples = K_blk_samples - static_cast(d_correlation_length_samples); //rounding error < 1 sample + }else{ + current_synchro_data.symbol_integration_enabled=false; + if(d_preamble_synchronized==true) + { + // continue extended coherent correlation + d_correlation_length_samples=d_correlation_length_samples-d_rem_code_phase_integer_samples; + d_rem_code_phase_integer_samples=0; + d_rem_carrier_phase_rad = fmod(d_rem_carrier_phase_rad + d_carrier_phase_step_rad * d_correlation_length_samples, GPS_TWO_PI); + d_rem_code_phase_chips = fmod(d_rem_code_phase_chips + d_code_phase_step_chips*d_correlation_length_samples,GPS_L1_CA_CODE_LENGTH_CHIPS); + // disable tracking loop and inform telemetry decoder + enable_dll_pll=false; + }else{ + // perform basic (1ms) correlation + // UPDATE INTEGRATION TIME + CURRENT_INTEGRATION_TIME_S = static_cast(d_correlation_length_samples) / static_cast(d_fs_in); + enable_dll_pll=true; + } + } + }else{ + current_synchro_data.symbol_integration_enabled=false; + // UPDATE INTEGRATION TIME + CURRENT_INTEGRATION_TIME_S = static_cast(d_correlation_length_samples) / static_cast(d_fs_in); + enable_dll_pll=true; + } - // UPDATE REMNANT CARRIER PHASE - CORRECTED_INTEGRATION_TIME_S=(static_cast(d_correlation_length_samples)/static_cast(d_fs_in)); - //remnant carrier phase [rad] - d_rem_carrier_phase_rad = fmod(d_rem_carrier_phase_rad + GPS_TWO_PI * d_carrier_doppler_hz * CORRECTED_INTEGRATION_TIME_S, GPS_TWO_PI); - // UPDATE CARRIER PHASE ACCUULATOR - //carrier phase accumulator prior to update the PLL estimators (accumulated carrier in this loop depends on the old estimations!) - d_acc_carrier_phase_cycles -= d_carrier_doppler_hz * CORRECTED_INTEGRATION_TIME_S; + // ###### end 20ms correlation extension - //################### PLL COMMANDS ################################################# - //carrier phase step (NCO phase increment per sample) [rads/sample] - d_carrier_phase_step_rad = GPS_TWO_PI * d_carrier_doppler_hz / static_cast(d_fs_in); + if (enable_dll_pll==true) + { + // ################## PLL ########################################################## + // Update PLL discriminator [rads/Ti -> Secs/Ti] + carr_phase_error_secs_Ti = pll_cloop_two_quadrant_atan(d_correlator_outs[1]) / GPS_TWO_PI; //prompt output + // Carrier discriminator filter + // NOTICE: The carrier loop filter includes the Carrier Doppler accumulator, as described in Kaplan + //d_carrier_doppler_hz = d_acq_carrier_doppler_hz + carr_phase_error_filt_secs_ti/INTEGRATION_TIME; + // Input [s/Ti] -> output [Hz] + d_carrier_doppler_hz = d_carrier_loop_filter.get_carrier_error(0.0, carr_phase_error_secs_Ti, CURRENT_INTEGRATION_TIME_S); + // PLL to DLL assistance [Secs/Ti] + d_pll_to_dll_assist_secs_Ti = (d_carrier_doppler_hz * CURRENT_INTEGRATION_TIME_S) / GPS_L1_FREQ_HZ; + // code Doppler frequency update + d_code_freq_chips = GPS_L1_CA_CODE_RATE_HZ + ((d_carrier_doppler_hz * GPS_L1_CA_CODE_RATE_HZ) / GPS_L1_FREQ_HZ); - //################### DLL COMMANDS ################################################# - //code phase step (Code resampler phase increment per sample) [chips/sample] - d_code_phase_step_chips = d_code_freq_chips / static_cast(d_fs_in); - //remnant code phase [chips] - d_rem_code_phase_chips = d_rem_code_phase_samples * (d_code_freq_chips / static_cast(d_fs_in)); + // ################## DLL ########################################################## + // DLL discriminator + code_error_chips_Ti = dll_nc_e_minus_l_normalized(d_correlator_outs[0], d_correlator_outs[2]); //[chips/Ti] //early and late + // Code discriminator filter + code_error_filt_chips = d_code_loop_filter.get_code_nco(code_error_chips_Ti); //input [chips/Ti] -> output [chips/second] + code_error_filt_secs_Ti = code_error_filt_chips*CURRENT_INTEGRATION_TIME_S/d_code_freq_chips; // [s/Ti] + // DLL code error estimation [s/Ti] + dll_code_error_secs_Ti = - code_error_filt_secs_Ti + d_pll_to_dll_assist_secs_Ti; - // ####### CN0 ESTIMATION AND LOCK DETECTORS ####################################### - if (d_cn0_estimation_counter < CN0_ESTIMATION_SAMPLES) - { - // fill buffer with prompt correlator output values - d_Prompt_buffer[d_cn0_estimation_counter] = d_correlator_outs[1]; //prompt - d_cn0_estimation_counter++; - } - else - { - d_cn0_estimation_counter = 0; - // Code lock indicator - d_CN0_SNV_dB_Hz = cn0_svn_estimator(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES, d_fs_in, GPS_L1_CA_CODE_LENGTH_CHIPS); - // Carrier lock indicator - d_carrier_lock_test = carrier_lock_detector(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES); - // Loss of lock detection - if (d_carrier_lock_test < d_carrier_lock_threshold or d_CN0_SNV_dB_Hz < MINIMUM_VALID_CN0) - { - d_carrier_lock_fail_counter++; - } - else - { - if (d_carrier_lock_fail_counter > 0) d_carrier_lock_fail_counter--; - } - if (d_carrier_lock_fail_counter > MAXIMUM_LOCK_FAIL_COUNTER) - { - std::cout << "Loss of lock in channel " << d_channel << "!" << std::endl; - LOG(INFO) << "Loss of lock in channel " << d_channel << "!"; - std::unique_ptr cmf(new ControlMessageFactory()); - if (d_queue != gr::msg_queue::sptr()) - { - d_queue->handle(cmf->GetQueueMessage(d_channel, 2)); - } - d_carrier_lock_fail_counter = 0; - d_enable_tracking = false; // TODO: check if disabling tracking is consistent with the channel state machine - } - } + // ################## CARRIER AND CODE NCO BUFFER ALIGNEMENT ####################### - // ########### Output the tracking data to navigation and PVT ########## - current_synchro_data.Prompt_I = static_cast((d_correlator_outs[1]).real()); - current_synchro_data.Prompt_Q = static_cast((d_correlator_outs[1]).imag()); - // Tracking_timestamp_secs is aligned with the CURRENT PRN start sample (Hybridization OK!) - current_synchro_data.Tracking_timestamp_secs = (static_cast(d_sample_counter) + old_d_rem_code_phase_samples) / static_cast(d_fs_in); - // This tracking block aligns the Tracking_timestamp_secs with the start sample of the PRN, thus, Code_phase_secs=0 - current_synchro_data.Code_phase_secs = 0; - current_synchro_data.Carrier_phase_rads = GPS_TWO_PI * d_acc_carrier_phase_cycles; - current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz; - current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz; - current_synchro_data.Flag_valid_pseudorange = false; - *out[0] = current_synchro_data; + // keep alignment parameters for the next input buffer + double T_chip_seconds; + double T_prn_seconds; + double T_prn_samples; + double K_prn_samples; + // Compute the next buffer length based in the new period of the PRN sequence and the code phase error estimation + T_chip_seconds = 1 / d_code_freq_chips; + T_prn_seconds = T_chip_seconds * GPS_L1_CA_CODE_LENGTH_CHIPS; + T_prn_samples = T_prn_seconds * static_cast(d_fs_in); + K_prn_samples = round(T_prn_samples); + double K_T_prn_error_samples=K_prn_samples-T_prn_samples; + + old_d_rem_code_phase_samples=d_rem_code_phase_samples; + d_rem_code_phase_samples= d_rem_code_phase_samples - K_T_prn_error_samples -dll_code_error_secs_Ti * static_cast(d_fs_in); + d_rem_code_phase_integer_samples=round(d_rem_code_phase_samples); + d_correlation_length_samples = K_prn_samples + d_rem_code_phase_integer_samples; //round to a discrete samples + d_rem_code_phase_samples=d_rem_code_phase_samples-d_rem_code_phase_integer_samples; + + // UPDATE REMNANT CARRIER PHASE + CORRECTED_INTEGRATION_TIME_S=(static_cast(d_correlation_length_samples)/static_cast(d_fs_in)); + //remnant carrier phase [rad] + d_rem_carrier_phase_rad = fmod(d_rem_carrier_phase_rad + GPS_TWO_PI * d_carrier_doppler_hz * CORRECTED_INTEGRATION_TIME_S, GPS_TWO_PI); + // UPDATE CARRIER PHASE ACCUULATOR + //carrier phase accumulator prior to update the PLL estimators (accumulated carrier in this loop depends on the old estimations!) + d_acc_carrier_phase_cycles -= d_carrier_doppler_hz * CORRECTED_INTEGRATION_TIME_S; + + //################### PLL COMMANDS ################################################# + //carrier phase step (NCO phase increment per sample) [rads/sample] + d_carrier_phase_step_rad = GPS_TWO_PI * d_carrier_doppler_hz / static_cast(d_fs_in); + + //################### DLL COMMANDS ################################################# + //code phase step (Code resampler phase increment per sample) [chips/sample] + d_code_phase_step_chips = d_code_freq_chips / static_cast(d_fs_in); + //remnant code phase [chips] + d_rem_code_phase_chips = d_rem_code_phase_samples * (d_code_freq_chips / static_cast(d_fs_in)); + + // ####### CN0 ESTIMATION AND LOCK DETECTORS ####################################### + if (d_cn0_estimation_counter < CN0_ESTIMATION_SAMPLES) + { + // fill buffer with prompt correlator output values + d_Prompt_buffer[d_cn0_estimation_counter] = d_correlator_outs[1]; //prompt + d_cn0_estimation_counter++; + } + else + { + d_cn0_estimation_counter = 0; + // Code lock indicator + d_CN0_SNV_dB_Hz = cn0_svn_estimator(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES, d_fs_in, GPS_L1_CA_CODE_LENGTH_CHIPS); + // Carrier lock indicator + d_carrier_lock_test = carrier_lock_detector(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES); + // Loss of lock detection + if (d_carrier_lock_test < d_carrier_lock_threshold or d_CN0_SNV_dB_Hz < MINIMUM_VALID_CN0) + { + d_carrier_lock_fail_counter++; + } + else + { + if (d_carrier_lock_fail_counter > 0) d_carrier_lock_fail_counter--; + } + if (d_carrier_lock_fail_counter > MAXIMUM_LOCK_FAIL_COUNTER) + { + std::cout << "Loss of lock in channel " << d_channel << "!" << std::endl; + LOG(INFO) << "Loss of lock in channel " << d_channel << "!"; + std::unique_ptr cmf(new ControlMessageFactory()); + if (d_queue != gr::msg_queue::sptr()) + { + d_queue->handle(cmf->GetQueueMessage(d_channel, 2)); + } + d_carrier_lock_fail_counter = 0; + d_enable_tracking = false; // TODO: check if disabling tracking is consistent with the channel state machine + } + } + // ########### Output the tracking data to navigation and PVT ########## + current_synchro_data.Prompt_I = static_cast((d_correlator_outs[1]).real()); + current_synchro_data.Prompt_Q = static_cast((d_correlator_outs[1]).imag()); + // Tracking_timestamp_secs is aligned with the CURRENT PRN start sample (Hybridization OK!) + current_synchro_data.Tracking_timestamp_secs = (static_cast(d_sample_counter) + old_d_rem_code_phase_samples) / static_cast(d_fs_in); + // This tracking block aligns the Tracking_timestamp_secs with the start sample of the PRN, thus, Code_phase_secs=0 + current_synchro_data.Code_phase_secs = 0; + current_synchro_data.Carrier_phase_rads = GPS_TWO_PI * d_acc_carrier_phase_cycles; + current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz; + current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz; + current_synchro_data.Flag_valid_pseudorange = false; + current_synchro_data.Flag_valid_symbol_output = true; + *out[0] = current_synchro_data; + }else{ + //todo: fill synchronization data to produce output while coherent integration is running + current_synchro_data.Flag_valid_symbol_output = false; + current_synchro_data.Prompt_I = static_cast((d_correlator_outs[1]).real()); + current_synchro_data.Prompt_Q = static_cast((d_correlator_outs[1]).imag()); + // Tracking_timestamp_secs is aligned with the CURRENT PRN start sample (Hybridization OK!) + current_synchro_data.Tracking_timestamp_secs = (static_cast(d_sample_counter) + d_rem_code_phase_samples) / static_cast(d_fs_in); + // This tracking block aligns the Tracking_timestamp_secs with the start sample of the PRN, thus, Code_phase_secs=0 + current_synchro_data.Code_phase_secs = 0; + current_synchro_data.Carrier_phase_rads = GPS_TWO_PI * d_acc_carrier_phase_cycles; // todo: project the acc carrier phase + current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz;// todo: project the carrier doppler + current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz; + current_synchro_data.Flag_valid_pseudorange = false; + *out[0] = current_synchro_data; + } // ########## DEBUG OUTPUT /*! @@ -553,6 +669,7 @@ int gps_l1_ca_dll_pll_c_aid_tracking_cc::general_work (int noutput_items, gr_vec { LOG(WARNING) << "noutput_items = 0"; } + d_symbol_counter++; return 1; //output tracking result ALWAYS even in the case of d_enable_tracking==false } diff --git a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_cc.h b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_cc.h index 6a212bd60..3d4cf3272 100644 --- a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_cc.h +++ b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_cc.h @@ -39,9 +39,11 @@ #include #include +#include #include #include #include +#include #include "concurrent_queue.h" #include "gnss_synchro.h" #include "tracking_2nd_DLL_filter.h" @@ -130,6 +132,7 @@ private: double d_rem_code_phase_samples; double d_rem_code_phase_chips; double d_rem_carrier_phase_rad; + int d_rem_code_phase_integer_samples; // PLL and DLL filter library Tracking_2nd_DLL_filter d_code_loop_filter; @@ -140,6 +143,8 @@ private: double d_acq_carrier_doppler_hz; // tracking vars + float d_dll_bw_hz; + float d_pll_bw_hz; double d_code_freq_chips; double d_code_phase_step_chips; double d_carrier_doppler_hz; @@ -148,6 +153,17 @@ private: double d_code_phase_samples; double d_pll_to_dll_assist_secs_Ti; + // symbol history to detect bit transition + std::deque d_E_history; + std::deque d_P_history; + std::deque d_L_history; + long int d_preamble_index; + long int d_symbol_counter; + bool d_enable_20ms_integration; + bool d_preamble_synchronized; + int d_correlation_symbol_counter; + void msg_handler_preamble_index(pmt::pmt_t msg); + //Integration period in samples int d_correlation_length_samples; diff --git a/src/core/receiver/gnss_flowgraph.cc b/src/core/receiver/gnss_flowgraph.cc index f15398fdc..5989b34c8 100644 --- a/src/core/receiver/gnss_flowgraph.cc +++ b/src/core/receiver/gnss_flowgraph.cc @@ -390,12 +390,12 @@ void GNSSFlowgraph::wait() */ void GNSSFlowgraph::apply_action(unsigned int who, unsigned int what) { - DLOG(INFO) << "received " << what << " from " << who; + DLOG(INFO) << "received " << what << " from " << who; switch (what) { case 0: - LOG(INFO) << "Channel " << who << " ACQ FAILED satellite " << channels_.at(who)->get_signal().get_satellite() << ", Signal " << channels_.at(who)->get_signal().get_signal_str(); + DLOG(INFO) << "Channel " << who << " ACQ FAILED satellite " << channels_.at(who)->get_signal().get_satellite() << ", Signal " << channels_.at(who)->get_signal().get_signal_str(); available_GNSS_signals_.push_back(channels_.at(who)->get_signal()); //TODO: Optimize the channel and signal matching! @@ -403,9 +403,11 @@ void GNSSFlowgraph::apply_action(unsigned int who, unsigned int what) { available_GNSS_signals_.push_back(available_GNSS_signals_.front()); available_GNSS_signals_.pop_front(); + std::cout << "loop"<set_signal(available_GNSS_signals_.front()); available_GNSS_signals_.pop_front(); + //todo: This is a provisional bug fix to avoid random channel state machine deadlock caused by an incorrect sequence of events // Correct sequence: start_acquisition() is triggered after the negative acquisition driven by the process_channel_messages() thread inside channel class // Incorrect sequence: due to thread concurrency, some times start_acquisition is triggered BEFORE the last negative_acquisition notification, thus producing a deadlock @@ -417,7 +419,7 @@ void GNSSFlowgraph::apply_action(unsigned int who, unsigned int what) // TODO: Tracking messages case 1: - LOG(INFO) << "Channel " << who << " ACQ SUCCESS satellite " << channels_.at(who)->get_signal().get_satellite(); + DLOG(INFO) << "Channel " << who << " ACQ SUCCESS satellite " << channels_.at(who)->get_signal().get_satellite(); channels_state_[who] = 2; acq_channels_count_--; if (!available_GNSS_signals_.empty() && acq_channels_count_ < max_acq_channels_) @@ -445,7 +447,7 @@ void GNSSFlowgraph::apply_action(unsigned int who, unsigned int what) break; case 2: - LOG(INFO) << "Channel " << who << " TRK FAILED satellite " << channels_.at(who)->get_signal().get_satellite(); + DLOG(INFO) << "Channel " << who << " TRK FAILED satellite " << channels_.at(who)->get_signal().get_satellite(); if (acq_channels_count_ < max_acq_channels_) { channels_state_[who] = 1; @@ -468,7 +470,7 @@ void GNSSFlowgraph::apply_action(unsigned int who, unsigned int what) default: break; } - DLOG(INFO) << "Number of available signals: " << available_GNSS_signals_.size(); + DLOG(INFO) << "Number of available signals: " << available_GNSS_signals_.size(); } diff --git a/src/core/system_parameters/GPS_L1_CA.h b/src/core/system_parameters/GPS_L1_CA.h index 2c9e041c1..bbe96db49 100644 --- a/src/core/system_parameters/GPS_L1_CA.h +++ b/src/core/system_parameters/GPS_L1_CA.h @@ -75,6 +75,7 @@ const int GPS_L1_CA_HISTORY_DEEP = 100; #define GPS_PREAMBLE {1, 0, 0, 0, 1, 0, 1, 1} const int GPS_CA_PREAMBLE_LENGTH_BITS = 8; const int GPS_CA_TELEMETRY_RATE_BITS_SECOND = 50; //!< NAV message bit rate [bits/s] +const int GPS_CA_TELEMETRY_SYMBOLS_PER_BIT = 20; const int GPS_CA_TELEMETRY_RATE_SYMBOLS_SECOND = GPS_CA_TELEMETRY_RATE_BITS_SECOND*20; //!< NAV message bit rate [symbols/s] const int GPS_WORD_LENGTH = 4; //!< CRC + GPS WORD (-2 -1 0 ... 29) Bits = 4 bytes const int GPS_SUBFRAME_LENGTH = 40; //!< GPS_WORD_LENGTH x 10 = 40 bytes diff --git a/src/core/system_parameters/gnss_synchro.h b/src/core/system_parameters/gnss_synchro.h index 27c1d6b3a..d70c21b1b 100644 --- a/src/core/system_parameters/gnss_synchro.h +++ b/src/core/system_parameters/gnss_synchro.h @@ -60,6 +60,8 @@ public: double Code_phase_secs; //!< Set by Tracking processing block double Tracking_timestamp_secs; //!< Set by Tracking processing block bool Flag_valid_tracking; + bool Flag_valid_symbol_output; + bool symbol_integration_enabled; //!< Set by Tracking processing block //Telemetry Decoder double Prn_timestamp_ms; //!< Set by Telemetry Decoder processing block From b03e3fc3af2562d746467bc08caa5d8c027fb7b2 Mon Sep 17 00:00:00 2001 From: Javier Arribas Date: Wed, 9 Mar 2016 15:44:55 +0100 Subject: [PATCH 2/2] Revert "prefetching data in the cache" This reverts commit aac79eb78a74cb27bbf40ead1a26d542edc3dc06. --- .../volk_gnsssdr/volk_gnsssdr_16ic_s32fc_x2_rotator_16ic.h | 5 ++--- .../volk_gnsssdr_16ic_x2_rotator_dot_prod_16ic_xn.h | 7 ++++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_s32fc_x2_rotator_16ic.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_s32fc_x2_rotator_16ic.h index 085833598..6496b84af 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_s32fc_x2_rotator_16ic.h +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_s32fc_x2_rotator_16ic.h @@ -103,7 +103,6 @@ static inline void volk_gnsssdr_16ic_s32fc_x2_rotator_16ic_a_sse3(lv_16sc_t* out for(unsigned int number = 0; number < sse_iters; number++) { a = _mm_set_ps((float)(lv_cimag(_in[1])), (float)(lv_creal(_in[1])), (float)(lv_cimag(_in[0])), (float)(lv_creal(_in[0]))); // //load (2 byte imag, 2 byte real) x 2 into 128 bits reg - __builtin_prefetch(_in + 8); //complex 32fc multiplication b=a*two_phase_acc_reg yl = _mm_moveldup_ps(two_phase_acc_reg); // Load yl with cr,cr,dr,dr yh = _mm_movehdup_ps(two_phase_acc_reg); // Load yh with ci,ci,di,di @@ -150,7 +149,7 @@ static inline void volk_gnsssdr_16ic_s32fc_x2_rotator_16ic_a_sse3(lv_16sc_t* out _out += 4; } - _mm_store_ps((float*)two_phase_acc, two_phase_acc_reg); + _mm_storeu_ps((float*)two_phase_acc, two_phase_acc_reg); (*phase) = two_phase_acc[0]; for (unsigned int i = sse_iters * 4; i < num_points; ++i) @@ -200,7 +199,6 @@ static inline void volk_gnsssdr_16ic_s32fc_x2_rotator_16ic_u_sse3(lv_16sc_t* out for(unsigned int number = 0; number < sse_iters; number++) { a = _mm_set_ps((float)(lv_cimag(_in[1])), (float)(lv_creal(_in[1])), (float)(lv_cimag(_in[0])), (float)(lv_creal(_in[0]))); // //load (2 byte imag, 2 byte real) x 2 into 128 bits reg - __builtin_prefetch(_in + 8); //complex 32fc multiplication b=a*two_phase_acc_reg yl = _mm_moveldup_ps(two_phase_acc_reg); // Load yl with cr,cr,dr,dr yh = _mm_movehdup_ps(two_phase_acc_reg); // Load yh with ci,ci,di,di @@ -221,6 +219,7 @@ static inline void volk_gnsssdr_16ic_s32fc_x2_rotator_16ic_u_sse3(lv_16sc_t* out //next two samples _in += 2; a = _mm_set_ps((float)(lv_cimag(_in[1])), (float)(lv_creal(_in[1])), (float)(lv_cimag(_in[0])), (float)(lv_creal(_in[0]))); // //load (2 byte imag, 2 byte real) x 2 into 128 bits reg + __builtin_prefetch(_in + 8); //complex 32fc multiplication b=a*two_phase_acc_reg yl = _mm_moveldup_ps(two_phase_acc_reg); // Load yl with cr,cr,dr,dr yh = _mm_movehdup_ps(two_phase_acc_reg); // Load yh with ci,ci,di,di diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_x2_rotator_dot_prod_16ic_xn.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_x2_rotator_dot_prod_16ic_xn.h index 157879693..9e0218eeb 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_x2_rotator_dot_prod_16ic_xn.h +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_x2_rotator_dot_prod_16ic_xn.h @@ -140,7 +140,6 @@ static inline void volk_gnsssdr_16ic_x2_rotator_dot_prod_16ic_xn_a_sse3(lv_16sc_ // Phase rotation on operand in_common starts here: //printf("generic phase %i: %f,%f\n", n*4,lv_creal(*phase),lv_cimag(*phase)); pa = _mm_set_ps((float)(lv_cimag(_in_common[1])), (float)(lv_creal(_in_common[1])), (float)(lv_cimag(_in_common[0])), (float)(lv_creal(_in_common[0]))); // //load (2 byte imag, 2 byte real) x 2 into 128 bits reg - __builtin_prefetch(_in_common + 8); //complex 32fc multiplication b=a*two_phase_acc_reg yl = _mm_moveldup_ps(two_phase_acc_reg); // Load yl with cr,cr,dr,dr yh = _mm_movehdup_ps(two_phase_acc_reg); // Load yh with ci,ci,di,di @@ -304,6 +303,7 @@ static inline void volk_gnsssdr_16ic_x2_rotator_dot_prod_16ic_xn_u_sse3(lv_16sc_ for(unsigned int number = 0; number < sse_iters; number++) { // Phase rotation on operand in_common starts here: + pa = _mm_set_ps((float)(lv_cimag(_in_common[1])), (float)(lv_creal(_in_common[1])), (float)(lv_cimag(_in_common[0])), (float)(lv_creal(_in_common[0]))); // //load (2 byte imag, 2 byte real) x 2 into 128 bits reg __builtin_prefetch(_in_common + 8); //complex 32fc multiplication b=a*two_phase_acc_reg @@ -378,7 +378,7 @@ static inline void volk_gnsssdr_16ic_x2_rotator_dot_prod_16ic_xn_u_sse3(lv_16sc_ a = _mm_or_si128(realcacc[n_vec], imagcacc[n_vec]); - _mm_store_si128((__m128i*)dotProductVector, a); // Store the results back into the dot product vector + _mm_storeu_si128((__m128i*)dotProductVector, a); // Store the results back into the dot product vector dotProduct = lv_cmake(0,0); for (int i = 0; i < 4; ++i) { @@ -390,9 +390,10 @@ static inline void volk_gnsssdr_16ic_x2_rotator_dot_prod_16ic_xn_u_sse3(lv_16sc_ free(realcacc); free(imagcacc); - _mm_store_ps((float*)two_phase_acc, two_phase_acc_reg); + _mm_storeu_ps((float*)two_phase_acc, two_phase_acc_reg); (*phase) = two_phase_acc[0]; + for(unsigned int n = sse_iters * 4; n < num_points; n++) { tmp16 = in_common[n];