mirror of
				https://github.com/gnss-sdr/gnss-sdr
				synced 2025-11-04 09:13:05 +00:00 
			
		
		
		
	Merge branch 'antonioramosdet-new_acq_grid' into next
This commit is contained in:
		@@ -1112,7 +1112,7 @@ if(NOT MATIO_FOUND)
 | 
			
		||||
            if(CMAKE_VERSION VERSION_LESS 3.2)
 | 
			
		||||
              ExternalProject_Add(
 | 
			
		||||
                 matio-${GNSSSDR_MATIO_LOCAL_VERSION}
 | 
			
		||||
                 PREFIX ${CMAKE_CURRENT_BINARY_DIR}/mati
 | 
			
		||||
                 PREFIX ${CMAKE_CURRENT_BINARY_DIR}/matio
 | 
			
		||||
                 GIT_REPOSITORY https://github.com/tbeu/matio
 | 
			
		||||
                 GIT_TAG v${GNSSSDR_MATIO_LOCAL_VERSION}
 | 
			
		||||
                 SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/matio/matio-${GNSSSDR_MATIO_LOCAL_VERSION}
 | 
			
		||||
 
 | 
			
		||||
@@ -48,6 +48,7 @@ include_directories(
 | 
			
		||||
     ${GFlags_INCLUDE_DIRS}
 | 
			
		||||
     ${GNURADIO_RUNTIME_INCLUDE_DIRS}
 | 
			
		||||
     ${VOLK_GNSSSDR_INCLUDE_DIRS}
 | 
			
		||||
     ${MATIO_INCLUDE_DIRS}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -69,7 +70,7 @@ source_group(Headers FILES ${ACQ_GR_BLOCKS_HEADERS})
 | 
			
		||||
if(ENABLE_FPGA)
 | 
			
		||||
	target_link_libraries(acq_gr_blocks acquisition_lib gnss_sp_libs gnss_system_parameters ${GNURADIO_RUNTIME_LIBRARIES} ${GNURADIO_FFT_LIBRARIES} ${VOLK_LIBRARIES} ${VOLK_GNSSSDR_LIBRARIES} ${OPT_LIBRARIES} ${OPT_ACQUISITION_LIBRARIES})
 | 
			
		||||
else(ENABLE_FPGA)
 | 
			
		||||
	target_link_libraries(acq_gr_blocks gnss_sp_libs gnss_system_parameters ${GNURADIO_RUNTIME_LIBRARIES} ${GNURADIO_FFT_LIBRARIES} ${VOLK_LIBRARIES} ${VOLK_GNSSSDR_LIBRARIES} ${OPT_LIBRARIES} ${OPT_ACQUISITION_LIBRARIES})
 | 
			
		||||
	target_link_libraries(acq_gr_blocks gnss_sp_libs gnss_system_parameters ${GNURADIO_RUNTIME_LIBRARIES} ${GNURADIO_FFT_LIBRARIES} ${VOLK_LIBRARIES} ${VOLK_GNSSSDR_LIBRARIES} ${OPT_LIBRARIES} ${OPT_ACQUISITION_LIBRARIES} ${MATIO_LIBRARIES})
 | 
			
		||||
endif(ENABLE_FPGA)
 | 
			
		||||
if(NOT VOLK_GNSSSDR_FOUND)
 | 
			
		||||
    add_dependencies(acq_gr_blocks volk_gnsssdr_module)
 | 
			
		||||
 
 | 
			
		||||
@@ -44,6 +44,7 @@
 | 
			
		||||
#include "control_message_factory.h"
 | 
			
		||||
#include "GPS_L1_CA.h" //GPS_TWO_PI
 | 
			
		||||
#include "GLONASS_L1_CA.h" //GLONASS_TWO_PI
 | 
			
		||||
#include <matio.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
using google::LogMessage;
 | 
			
		||||
@@ -98,9 +99,6 @@ pcps_acquisition_cc::pcps_acquisition_cc(
 | 
			
		||||
    d_code_phase = 0;
 | 
			
		||||
    d_test_statistics = 0.0;
 | 
			
		||||
    d_channel = 0;
 | 
			
		||||
    d_doppler_freq = 0.0;
 | 
			
		||||
 | 
			
		||||
    //set_relative_rate( 1.0/d_fft_size );
 | 
			
		||||
 | 
			
		||||
    // COD:
 | 
			
		||||
    // Experimenting with the overlap/save technique for handling bit trannsitions
 | 
			
		||||
@@ -113,10 +111,10 @@ pcps_acquisition_cc::pcps_acquisition_cc(
 | 
			
		||||
    // We can avoid this by doing linear correlation, effectively doubling the
 | 
			
		||||
    // size of the input buffer and padding the code with zeros.
 | 
			
		||||
    if( d_bit_transition_flag )
 | 
			
		||||
        {
 | 
			
		||||
            d_fft_size *= 2;
 | 
			
		||||
            d_max_dwells = 1; //Activation of d_bit_transition_flag invalidates the value of d_max_dwells
 | 
			
		||||
        }
 | 
			
		||||
    {
 | 
			
		||||
        d_fft_size *= 2;
 | 
			
		||||
        d_max_dwells = 1; //Activation of d_bit_transition_flag invalidates the value of d_max_dwells
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    d_fft_codes = static_cast<gr_complex*>(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
 | 
			
		||||
    d_magnitude = static_cast<float*>(volk_gnsssdr_malloc(d_fft_size * sizeof(float), volk_gnsssdr_get_alignment()));
 | 
			
		||||
@@ -135,6 +133,7 @@ pcps_acquisition_cc::pcps_acquisition_cc(
 | 
			
		||||
    d_blocking = blocking;
 | 
			
		||||
    d_worker_active = false;
 | 
			
		||||
    d_data_buffer = static_cast<gr_complex*>(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
 | 
			
		||||
    grid_ = arma::fmat();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -148,18 +147,11 @@ pcps_acquisition_cc::~pcps_acquisition_cc()
 | 
			
		||||
                }
 | 
			
		||||
            delete[] d_grid_doppler_wipeoffs;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    volk_gnsssdr_free(d_fft_codes);
 | 
			
		||||
    volk_gnsssdr_free(d_magnitude);
 | 
			
		||||
 | 
			
		||||
    delete d_ifft;
 | 
			
		||||
    delete d_fft_if;
 | 
			
		||||
 | 
			
		||||
    if (d_dump)
 | 
			
		||||
        {
 | 
			
		||||
            d_dump_file.close();
 | 
			
		||||
        }
 | 
			
		||||
    volk_gnsssdr_free( d_data_buffer );
 | 
			
		||||
    volk_gnsssdr_free(d_data_buffer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -243,6 +235,12 @@ void pcps_acquisition_cc::init()
 | 
			
		||||
            update_local_carrier(d_grid_doppler_wipeoffs[doppler_index], d_fft_size, d_freq + doppler);
 | 
			
		||||
        }
 | 
			
		||||
    d_worker_active = false;
 | 
			
		||||
 | 
			
		||||
    if(d_dump)
 | 
			
		||||
    {
 | 
			
		||||
        unsigned int effective_fft_size = (d_bit_transition_flag ? (d_fft_size / 2) : d_fft_size);
 | 
			
		||||
        grid_ = arma::fmat(effective_fft_size, d_num_doppler_bins, arma::fill::zeros);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -480,26 +478,46 @@ void pcps_acquisition_cc::acquisition_core( unsigned long int samp_count )
 | 
			
		||||
                }
 | 
			
		||||
            // Record results to file if required
 | 
			
		||||
            if (d_dump)
 | 
			
		||||
            {
 | 
			
		||||
                memcpy(grid_.colptr(doppler_index), d_magnitude, sizeof(float) * effective_fft_size);
 | 
			
		||||
                if(doppler_index == (d_num_doppler_bins - 1))
 | 
			
		||||
                {
 | 
			
		||||
                    std::stringstream filename;
 | 
			
		||||
                    std::streamsize n = 2 * sizeof(float) * (d_fft_size); // complex file write
 | 
			
		||||
                    filename.str("");
 | 
			
		||||
                    boost::filesystem::path p = d_dump_filename;
 | 
			
		||||
                    filename << p.parent_path().string()
 | 
			
		||||
                            << boost::filesystem::path::preferred_separator
 | 
			
		||||
                            << p.stem().string()
 | 
			
		||||
                            << "_" << d_gnss_synchro->System
 | 
			
		||||
                            <<"_" << d_gnss_synchro->Signal << "_sat_"
 | 
			
		||||
                            << d_gnss_synchro->PRN << "_doppler_"
 | 
			
		||||
                            <<  doppler
 | 
			
		||||
                            << p.extension().string();
 | 
			
		||||
                    std::string filename = d_dump_filename;
 | 
			
		||||
                    filename.append("_");
 | 
			
		||||
                    filename.append(1, d_gnss_synchro->System);
 | 
			
		||||
                    filename.append("_");
 | 
			
		||||
                    filename.append(1, d_gnss_synchro->Signal[0]);
 | 
			
		||||
                    filename.append(1, d_gnss_synchro->Signal[1]);
 | 
			
		||||
                    filename.append("_sat_");
 | 
			
		||||
                    filename.append(std::to_string(d_gnss_synchro->PRN));
 | 
			
		||||
                    filename.append(".mat");
 | 
			
		||||
                    mat_t* matfp = Mat_CreateVer(filename.c_str(), NULL, MAT_FT_MAT73);
 | 
			
		||||
                    if(matfp == NULL)
 | 
			
		||||
                    {
 | 
			
		||||
                        std::cout << "Unable to create or open Acquisition dump file" << std::endl;
 | 
			
		||||
                        d_dump = false;
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        size_t dims[2] = {static_cast<size_t>(effective_fft_size), static_cast<size_t>(d_num_doppler_bins)};
 | 
			
		||||
                        matvar_t* matvar = Mat_VarCreate("grid", MAT_C_SINGLE, MAT_T_SINGLE, 2, dims, grid_.memptr(), 0);
 | 
			
		||||
                        Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
 | 
			
		||||
                        Mat_VarFree(matvar);
 | 
			
		||||
 | 
			
		||||
                    DLOG(INFO) << "Writing ACQ out to " << filename.str();
 | 
			
		||||
                        dims[0] = static_cast<size_t>(1);
 | 
			
		||||
                        dims[1] = static_cast<size_t>(1);
 | 
			
		||||
                        matvar = Mat_VarCreate("doppler_max", MAT_C_SINGLE, MAT_T_UINT32, 1, dims, &d_doppler_max, 0);
 | 
			
		||||
                        Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
 | 
			
		||||
                        Mat_VarFree(matvar);
 | 
			
		||||
 | 
			
		||||
                    d_dump_file.open(filename.str().c_str(), std::ios::out | std::ios::binary);
 | 
			
		||||
                    d_dump_file.write(reinterpret_cast<char*>(d_ifft->get_outbuf()), n); //write directly |abs(x)|^2 in this Doppler bin?
 | 
			
		||||
                    d_dump_file.close();
 | 
			
		||||
                        matvar = Mat_VarCreate("doppler_step", MAT_C_SINGLE, MAT_T_UINT32, 1, dims, &d_doppler_step, 0);
 | 
			
		||||
                        Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
 | 
			
		||||
                        Mat_VarFree(matvar);
 | 
			
		||||
 | 
			
		||||
                        Mat_Close(matfp);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    lk.lock();
 | 
			
		||||
    if (!d_bit_transition_flag)
 | 
			
		||||
 
 | 
			
		||||
@@ -58,6 +58,8 @@
 | 
			
		||||
#include <gnuradio/gr_complex.h>
 | 
			
		||||
#include <gnuradio/fft/fft.h>
 | 
			
		||||
#include "gnss_synchro.h"
 | 
			
		||||
#include <glog/logging.h>
 | 
			
		||||
#include <armadillo>
 | 
			
		||||
 | 
			
		||||
class pcps_acquisition_cc;
 | 
			
		||||
 | 
			
		||||
@@ -80,6 +82,7 @@ pcps_make_acquisition_cc(unsigned int sampled_ms, unsigned int max_dwells,
 | 
			
		||||
class pcps_acquisition_cc: public gr::block
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    friend pcps_acquisition_cc_sptr
 | 
			
		||||
    pcps_make_acquisition_cc(unsigned int sampled_ms, unsigned int max_dwells,
 | 
			
		||||
            unsigned int doppler_max, long freq, long fs_in,
 | 
			
		||||
@@ -102,146 +105,144 @@ private:
 | 
			
		||||
    void acquisition_core( unsigned long int samp_count );
 | 
			
		||||
 | 
			
		||||
    void send_negative_acquisition();
 | 
			
		||||
 | 
			
		||||
    void send_positive_acquisition();
 | 
			
		||||
 | 
			
		||||
    bool d_bit_transition_flag;
 | 
			
		||||
    bool d_use_CFAR_algorithm_flag;
 | 
			
		||||
    bool d_active;
 | 
			
		||||
    bool d_dump;
 | 
			
		||||
    bool d_worker_active;
 | 
			
		||||
    bool d_blocking;
 | 
			
		||||
    float d_threshold;
 | 
			
		||||
    float d_mag;
 | 
			
		||||
    float d_input_power;
 | 
			
		||||
    float d_test_statistics;
 | 
			
		||||
    float* d_magnitude;
 | 
			
		||||
    long d_fs_in;
 | 
			
		||||
    long d_freq;
 | 
			
		||||
    long d_old_freq;
 | 
			
		||||
    int d_samples_per_ms;
 | 
			
		||||
    int d_samples_per_code;
 | 
			
		||||
    //unsigned int d_doppler_resolution;
 | 
			
		||||
    float d_threshold;
 | 
			
		||||
    int d_state;
 | 
			
		||||
    unsigned int d_channel;
 | 
			
		||||
    unsigned int d_doppler_max;
 | 
			
		||||
    unsigned int d_doppler_step;
 | 
			
		||||
    unsigned int d_sampled_ms;
 | 
			
		||||
    unsigned int d_max_dwells;
 | 
			
		||||
    unsigned int d_well_count;
 | 
			
		||||
    unsigned int d_fft_size;
 | 
			
		||||
    unsigned int d_num_doppler_bins;
 | 
			
		||||
    unsigned int d_code_phase;
 | 
			
		||||
    unsigned long int d_sample_counter;
 | 
			
		||||
    gr_complex** d_grid_doppler_wipeoffs;
 | 
			
		||||
    unsigned int d_num_doppler_bins;
 | 
			
		||||
    gr_complex* d_fft_codes;
 | 
			
		||||
    gr_complex* d_data_buffer;
 | 
			
		||||
    gr::fft::fft_complex* d_fft_if;
 | 
			
		||||
    gr::fft::fft_complex* d_ifft;
 | 
			
		||||
    Gnss_Synchro *d_gnss_synchro;
 | 
			
		||||
    unsigned int d_code_phase;
 | 
			
		||||
    float d_doppler_freq;
 | 
			
		||||
    float d_mag;
 | 
			
		||||
    float* d_magnitude;
 | 
			
		||||
    float d_input_power;
 | 
			
		||||
    float d_test_statistics;
 | 
			
		||||
    bool d_bit_transition_flag;
 | 
			
		||||
    bool d_use_CFAR_algorithm_flag;
 | 
			
		||||
    std::ofstream d_dump_file;
 | 
			
		||||
    bool d_active;
 | 
			
		||||
    int d_state;
 | 
			
		||||
    bool d_dump;
 | 
			
		||||
    unsigned int d_channel;
 | 
			
		||||
    Gnss_Synchro* d_gnss_synchro;
 | 
			
		||||
    std::string d_dump_filename;
 | 
			
		||||
    bool d_worker_active;
 | 
			
		||||
    bool d_blocking;
 | 
			
		||||
    gr_complex *d_data_buffer;
 | 
			
		||||
    arma::fmat grid_;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    /*!
 | 
			
		||||
     * \brief Default destructor.
 | 
			
		||||
     */
 | 
			
		||||
     ~pcps_acquisition_cc();
 | 
			
		||||
 | 
			
		||||
    ~pcps_acquisition_cc();
 | 
			
		||||
 | 
			
		||||
     /*!
 | 
			
		||||
      * \brief Set acquisition/tracking common Gnss_Synchro object pointer
 | 
			
		||||
      * to exchange synchronization data between acquisition and tracking blocks.
 | 
			
		||||
      * \param p_gnss_synchro Satellite information shared by the processing blocks.
 | 
			
		||||
      */
 | 
			
		||||
     inline void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro)
 | 
			
		||||
     {
 | 
			
		||||
         gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler
 | 
			
		||||
         d_gnss_synchro = p_gnss_synchro;
 | 
			
		||||
     }
 | 
			
		||||
    inline void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro)
 | 
			
		||||
    {
 | 
			
		||||
        gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler
 | 
			
		||||
        d_gnss_synchro = p_gnss_synchro;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
     /*!
 | 
			
		||||
      * \brief Returns the maximum peak of grid search.
 | 
			
		||||
      */
 | 
			
		||||
     inline unsigned int mag() const
 | 
			
		||||
     {
 | 
			
		||||
         return d_mag;
 | 
			
		||||
     }
 | 
			
		||||
    /*!
 | 
			
		||||
     * \brief Returns the maximum peak of grid search.
 | 
			
		||||
     */
 | 
			
		||||
    inline unsigned int mag() const
 | 
			
		||||
    {
 | 
			
		||||
        return d_mag;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
     /*!
 | 
			
		||||
      * \brief Initializes acquisition algorithm.
 | 
			
		||||
      */
 | 
			
		||||
     void init();
 | 
			
		||||
    void init();
 | 
			
		||||
 | 
			
		||||
     /*!
 | 
			
		||||
      * \brief Sets local code for PCPS acquisition algorithm.
 | 
			
		||||
      * \param code - Pointer to the PRN code.
 | 
			
		||||
      */
 | 
			
		||||
     void set_local_code(std::complex<float> * code);
 | 
			
		||||
    void set_local_code(std::complex<float> * code);
 | 
			
		||||
 | 
			
		||||
     /*!
 | 
			
		||||
      * \brief Starts acquisition algorithm, turning from standby mode to
 | 
			
		||||
      * active mode
 | 
			
		||||
      * \param active - bool that activates/deactivates the block.
 | 
			
		||||
      */
 | 
			
		||||
     inline void set_active(bool active)
 | 
			
		||||
     {
 | 
			
		||||
         gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler
 | 
			
		||||
         d_active = active;
 | 
			
		||||
     }
 | 
			
		||||
    inline void set_active(bool active)
 | 
			
		||||
    {
 | 
			
		||||
        gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler
 | 
			
		||||
        d_active = active;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
     /*!
 | 
			
		||||
      * \brief If set to 1, ensures that acquisition starts at the
 | 
			
		||||
      * first available sample.
 | 
			
		||||
      * \param state - int=1 forces start of acquisition
 | 
			
		||||
      */
 | 
			
		||||
     void set_state(int state);
 | 
			
		||||
    void set_state(int state);
 | 
			
		||||
 | 
			
		||||
     /*!
 | 
			
		||||
      * \brief Set acquisition channel unique ID
 | 
			
		||||
      * \param channel - receiver channel.
 | 
			
		||||
      */
 | 
			
		||||
     inline void set_channel(unsigned int channel)
 | 
			
		||||
     {
 | 
			
		||||
         gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler
 | 
			
		||||
         d_channel = channel;
 | 
			
		||||
     }
 | 
			
		||||
    inline void set_channel(unsigned int channel)
 | 
			
		||||
    {
 | 
			
		||||
        gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler
 | 
			
		||||
        d_channel = channel;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
     /*!
 | 
			
		||||
      * \brief Set statistics threshold of PCPS algorithm.
 | 
			
		||||
      * \param threshold - Threshold for signal detection (check \ref Navitec2012,
 | 
			
		||||
      * Algorithm 1, for a definition of this threshold).
 | 
			
		||||
      */
 | 
			
		||||
     inline void set_threshold(float threshold)
 | 
			
		||||
     {
 | 
			
		||||
         gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler
 | 
			
		||||
         d_threshold = threshold;
 | 
			
		||||
     }
 | 
			
		||||
    inline void set_threshold(float threshold)
 | 
			
		||||
    {
 | 
			
		||||
        gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler
 | 
			
		||||
        d_threshold = threshold;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
     /*!
 | 
			
		||||
      * \brief Set maximum Doppler grid search
 | 
			
		||||
      * \param doppler_max - Maximum Doppler shift considered in the grid search [Hz].
 | 
			
		||||
      */
 | 
			
		||||
     inline void set_doppler_max(unsigned int doppler_max)
 | 
			
		||||
     {
 | 
			
		||||
         gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler
 | 
			
		||||
         d_doppler_max = doppler_max;
 | 
			
		||||
     }
 | 
			
		||||
    inline void set_doppler_max(unsigned int doppler_max)
 | 
			
		||||
    {
 | 
			
		||||
        gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler
 | 
			
		||||
        d_doppler_max = doppler_max;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
     /*!
 | 
			
		||||
      * \brief Set Doppler steps for the grid search
 | 
			
		||||
      * \param doppler_step - Frequency bin of the search grid [Hz].
 | 
			
		||||
      */
 | 
			
		||||
     inline void set_doppler_step(unsigned int doppler_step)
 | 
			
		||||
     {
 | 
			
		||||
         gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler
 | 
			
		||||
         d_doppler_step = doppler_step;
 | 
			
		||||
     }
 | 
			
		||||
    inline void set_doppler_step(unsigned int doppler_step)
 | 
			
		||||
    {
 | 
			
		||||
        gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler
 | 
			
		||||
        d_doppler_step = doppler_step;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
     /*!
 | 
			
		||||
      * \brief Parallel Code Phase Search Acquisition signal processing.
 | 
			
		||||
      */
 | 
			
		||||
     int general_work(int noutput_items, gr_vector_int &ninput_items,
 | 
			
		||||
             gr_vector_const_void_star &input_items,
 | 
			
		||||
             gr_vector_void_star &output_items);
 | 
			
		||||
    int general_work(int noutput_items, gr_vector_int &ninput_items,
 | 
			
		||||
            gr_vector_const_void_star &input_items,
 | 
			
		||||
            gr_vector_void_star &output_items);
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -158,7 +158,7 @@ void GalileoE1PcpsAmbiguousAcquisitionTest::init()
 | 
			
		||||
        {
 | 
			
		||||
            config->set_property("Acquisition_1B.dump", "false");
 | 
			
		||||
        }
 | 
			
		||||
    config->set_property("Acquisition_1B.dump_filename", "./tmp-acq-gal1/acquisition.dat");
 | 
			
		||||
    config->set_property("Acquisition_1B.dump_filename", "./tmp-acq-gal1/acquisition");
 | 
			
		||||
    config->set_property("Acquisition_1B.threshold", "0.0001");
 | 
			
		||||
    config->set_property("Acquisition_1B.doppler_max", std::to_string(doppler_max));
 | 
			
		||||
    config->set_property("Acquisition_1B.doppler_step", std::to_string(doppler_step));
 | 
			
		||||
 
 | 
			
		||||
@@ -141,7 +141,7 @@ void GlonassL1CaPcpsAcquisitionTest::init()
 | 
			
		||||
    config->set_property("Acquisition_1G.if", "9540000");
 | 
			
		||||
    config->set_property("Acquisition_1G.coherent_integration_time_ms", "1");
 | 
			
		||||
    config->set_property("Acquisition_1G.dump", "true");
 | 
			
		||||
    config->set_property("Acquisition_1G.dump_filename", "./acquisition.dat");
 | 
			
		||||
    config->set_property("Acquisition_1G.dump_filename", "./acquisition");
 | 
			
		||||
    config->set_property("Acquisition_1G.implementation", "Glonass_L1_CA_PCPS_Acquisition");
 | 
			
		||||
    config->set_property("Acquisition_1G.threshold", "0.001");
 | 
			
		||||
    config->set_property("Acquisition_1G.doppler_max", "5000");
 | 
			
		||||
 
 | 
			
		||||
@@ -157,7 +157,7 @@ void GpsL1CaPcpsAcquisitionTest::init()
 | 
			
		||||
        {
 | 
			
		||||
            config->set_property("Acquisition_1C.dump", "false");
 | 
			
		||||
        }
 | 
			
		||||
    config->set_property("Acquisition_1C.dump_filename", "./tmp-acq-gps1/acquisition.dat");
 | 
			
		||||
    config->set_property("Acquisition_1C.dump_filename", "./tmp-acq-gps1/acquisition");
 | 
			
		||||
    config->set_property("Acquisition_1C.threshold", "0.00001");
 | 
			
		||||
    config->set_property("Acquisition_1C.doppler_max", std::to_string(doppler_max));
 | 
			
		||||
    config->set_property("Acquisition_1C.doppler_step", std::to_string(doppler_step));
 | 
			
		||||
 
 | 
			
		||||
@@ -164,7 +164,7 @@ void GpsL2MPcpsAcquisitionTest::init()
 | 
			
		||||
        {
 | 
			
		||||
            config->set_property("Acquisition_2S.dump", "false");
 | 
			
		||||
        }
 | 
			
		||||
    config->set_property("Acquisition_2S.dump_filename", "./tmp-acq-gps2/acquisition.dat");
 | 
			
		||||
    config->set_property("Acquisition_2S.dump_filename", "./tmp-acq-gps2/acquisition");
 | 
			
		||||
    config->set_property("Acquisition_2S.threshold", "0.001");
 | 
			
		||||
    config->set_property("Acquisition_2S.doppler_max", std::to_string(doppler_max));
 | 
			
		||||
    config->set_property("Acquisition_2S.doppler_step", std::to_string(doppler_step));
 | 
			
		||||
@@ -178,9 +178,8 @@ void GpsL2MPcpsAcquisitionTest::plot_grid()
 | 
			
		||||
    std::string basename = "./tmp-acq-gps2/acquisition_G_2S";
 | 
			
		||||
    unsigned int sat = static_cast<unsigned int>(gnss_synchro.PRN);
 | 
			
		||||
 | 
			
		||||
    unsigned int samples_per_code =  static_cast<unsigned int>(floor(sampling_frequency_hz / (GPS_L2_M_CODE_RATE_HZ / GPS_L2_M_CODE_LENGTH_CHIPS)) - 1000); // !!
 | 
			
		||||
    unsigned int samples_per_code =  static_cast<unsigned int>(floor(static_cast<double>(sampling_frequency_hz) / (GPS_L2_M_CODE_RATE_HZ / static_cast<double>(GPS_L2_M_CODE_LENGTH_CHIPS))));
 | 
			
		||||
    acquisition_dump_reader acq_dump(basename, sat, doppler_max, doppler_step, samples_per_code);
 | 
			
		||||
 | 
			
		||||
    if(!acq_dump.read_binary_acq()) std::cout << "Error reading files" << std::endl;
 | 
			
		||||
 | 
			
		||||
    std::vector<int> *doppler = &acq_dump.doppler;
 | 
			
		||||
@@ -204,7 +203,7 @@ void GpsL2MPcpsAcquisitionTest::plot_grid()
 | 
			
		||||
                    std::string gnuplot_path = dir.native();
 | 
			
		||||
                    Gnuplot::set_GNUPlotPath(gnuplot_path);
 | 
			
		||||
 | 
			
		||||
                    Gnuplot g1("lines");
 | 
			
		||||
                    Gnuplot g1("impulses");
 | 
			
		||||
                    g1.set_title("GPS L2CM signal acquisition for satellite PRN #" + std::to_string(gnss_synchro.PRN));
 | 
			
		||||
                    g1.set_xlabel("Doppler [Hz]");
 | 
			
		||||
                    g1.set_ylabel("Sample");
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,7 @@ include_directories(
 | 
			
		||||
     ${CMAKE_CURRENT_SOURCE_DIR}
 | 
			
		||||
     ${GLOG_INCLUDE_DIRS}
 | 
			
		||||
     ${GFlags_INCLUDE_DIRS}
 | 
			
		||||
     ${MATIO_INCLUDE_DIRS}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,13 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * \file acquisition_dump_reader.cc
 | 
			
		||||
 * \brief Helper file for unit testing
 | 
			
		||||
 * \author Carles Fernandez-Prades, 2017. cfernandez(at)cttc.es
 | 
			
		||||
 * \authors Carles Fernandez-Prades, 2017. cfernandez(at)cttc.es
 | 
			
		||||
 *                    Antonio Ramos, 2018. antonio.ramos(at)cttc.es
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 * -------------------------------------------------------------------------
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2010-2017  (see AUTHORS file for a list of contributors)
 | 
			
		||||
 * Copyright (C) 2010-2018  (see AUTHORS file for a list of contributors)
 | 
			
		||||
 *
 | 
			
		||||
 * GNSS-SDR is a software defined Global Navigation
 | 
			
		||||
 *          Satellite Systems receiver
 | 
			
		||||
@@ -28,44 +30,65 @@
 | 
			
		||||
 * -------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <complex>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <cmath>
 | 
			
		||||
#include <matio.h>
 | 
			
		||||
#include "acquisition_dump_reader.h"
 | 
			
		||||
 | 
			
		||||
bool acquisition_dump_reader::read_binary_acq()
 | 
			
		||||
{
 | 
			
		||||
    std::complex<float>* aux = new std::complex<float>[1];
 | 
			
		||||
    for(unsigned int i = 0; i < d_num_doppler_bins; i++)
 | 
			
		||||
    mat_t* matfile = Mat_Open(d_dump_filename.c_str(), MAT_ACC_RDONLY);
 | 
			
		||||
    if( matfile == NULL)
 | 
			
		||||
    {
 | 
			
		||||
        std::cout << "¡¡¡Unreachable Acquisition dump file!!!" << std::endl;
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    matvar_t* var_= Mat_VarRead(matfile, "grid");
 | 
			
		||||
    if( var_ == NULL)
 | 
			
		||||
    {
 | 
			
		||||
        std::cout << "¡¡¡Unreachable grid variable into Acquisition dump file!!!" << std::endl;
 | 
			
		||||
        Mat_Close(matfile);
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    if(var_->rank != 2)
 | 
			
		||||
    {
 | 
			
		||||
        std::cout << "Invalid Acquisition dump file: rank error" << std::endl;
 | 
			
		||||
        Mat_VarFree(var_);
 | 
			
		||||
        Mat_Close(matfile);
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    if((var_->dims[0] != d_samples_per_code) or (var_->dims[1] != d_num_doppler_bins))
 | 
			
		||||
    {
 | 
			
		||||
        std::cout << "Invalid Acquisition dump file: dimension matrix error" << std::endl;
 | 
			
		||||
        if(var_->dims[0] != d_samples_per_code) std::cout << "Expected " << d_samples_per_code << " samples per code. Obtained " << var_->dims[0] << std::endl;
 | 
			
		||||
        if(var_->dims[1] != d_num_doppler_bins) std::cout << "Expected " << d_num_doppler_bins << " Doppler bins. Obtained " << var_->dims[1] << std::endl;
 | 
			
		||||
        Mat_VarFree(var_);
 | 
			
		||||
        Mat_Close(matfile);
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    if(var_->data_type != MAT_T_SINGLE)
 | 
			
		||||
    {
 | 
			
		||||
        std::cout << "Invalid Acquisition dump file: data type error" << std::endl;
 | 
			
		||||
        Mat_VarFree(var_);
 | 
			
		||||
        Mat_Close(matfile);
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    std::vector<std::vector<float> >::iterator it1;
 | 
			
		||||
    std::vector<float>::iterator it2;
 | 
			
		||||
    float* aux = static_cast<float*>(var_->data);
 | 
			
		||||
    int k = 0;
 | 
			
		||||
    float normalization_factor = std::pow(d_samples_per_code, 2);
 | 
			
		||||
    for(it1 = mag.begin(); it1 != mag.end(); it1++)
 | 
			
		||||
    {
 | 
			
		||||
        for(it2 = it1->begin(); it2 != it1->end(); it2++)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                    std::ifstream ifs;
 | 
			
		||||
                    ifs.exceptions( std::ifstream::failbit | std::ifstream::badbit );
 | 
			
		||||
                    ifs.open(d_dump_filenames.at(i).c_str(), std::ios::in | std::ios::binary);
 | 
			
		||||
                    d_dump_files.at(i).swap(ifs);
 | 
			
		||||
                    if (d_dump_files.at(i).is_open())
 | 
			
		||||
                        {
 | 
			
		||||
                            for(unsigned int k = 0; k < d_samples_per_code; k++)
 | 
			
		||||
                                {
 | 
			
		||||
                                    d_dump_files.at(i).read(reinterpret_cast<char *>(&aux[0]), sizeof(std::complex<float>));
 | 
			
		||||
                                    mag.at(i).at(k) = std::abs(*aux) / std::pow(d_samples_per_code, 2);
 | 
			
		||||
                                }
 | 
			
		||||
                        }
 | 
			
		||||
                    else
 | 
			
		||||
                        {
 | 
			
		||||
                            std::cout << "File " << d_dump_filenames.at(i).c_str() << " not found." << std::endl;
 | 
			
		||||
                            delete[] aux;
 | 
			
		||||
                            return false;
 | 
			
		||||
                        }
 | 
			
		||||
                    d_dump_files.at(i).close();
 | 
			
		||||
            }
 | 
			
		||||
            catch (const std::ifstream::failure &e)
 | 
			
		||||
            {
 | 
			
		||||
                    std::cout << e.what() << std::endl;
 | 
			
		||||
                    delete[] aux;
 | 
			
		||||
                    return false;
 | 
			
		||||
            }
 | 
			
		||||
            *it2 = static_cast<float>(std::sqrt(aux[k])) / normalization_factor;
 | 
			
		||||
            k++;
 | 
			
		||||
        }
 | 
			
		||||
    delete[] aux;
 | 
			
		||||
    }
 | 
			
		||||
    Mat_VarFree(var_);
 | 
			
		||||
    Mat_Close(matfile);
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -80,12 +103,10 @@ acquisition_dump_reader::acquisition_dump_reader(const std::string & basename, u
 | 
			
		||||
    d_num_doppler_bins = static_cast<unsigned int>(ceil( static_cast<double>(static_cast<int>(d_doppler_max) - static_cast<int>(-d_doppler_max)) / static_cast<double>(d_doppler_step)));
 | 
			
		||||
    std::vector<std::vector<float> > mag_aux(d_num_doppler_bins, std::vector<float>(d_samples_per_code));
 | 
			
		||||
    mag = mag_aux;
 | 
			
		||||
    d_dump_filename = d_basename + "_sat_" + std::to_string(d_sat) + ".mat";
 | 
			
		||||
    for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++)
 | 
			
		||||
        {
 | 
			
		||||
            doppler.push_back(-static_cast<int>(d_doppler_max) + d_doppler_step * doppler_index);
 | 
			
		||||
            d_dump_filenames.push_back(d_basename + "_sat_" + std::to_string(d_sat) + "_doppler_" + std::to_string(doppler.at(doppler_index)) + ".dat");
 | 
			
		||||
            std::ifstream ifs;
 | 
			
		||||
            d_dump_files.push_back(std::move(ifs));
 | 
			
		||||
        }
 | 
			
		||||
    for (unsigned int k = 0; k < d_samples_per_code; k++)
 | 
			
		||||
        {
 | 
			
		||||
@@ -95,12 +116,4 @@ acquisition_dump_reader::acquisition_dump_reader(const std::string & basename, u
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
acquisition_dump_reader::~acquisition_dump_reader()
 | 
			
		||||
{
 | 
			
		||||
    for(unsigned int i = 0; i < d_num_doppler_bins; i++)
 | 
			
		||||
        {
 | 
			
		||||
            if (d_dump_files.at(i).is_open() == true)
 | 
			
		||||
                {
 | 
			
		||||
                    d_dump_files.at(i).close();
 | 
			
		||||
                }
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
{}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,12 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * \file acquisition_dump_reader.h
 | 
			
		||||
 * \brief Helper file for unit testing
 | 
			
		||||
 * \author Carles Fernandez-Prades, 2017. cfernandez(at)cttc.es
 | 
			
		||||
 * \authors Carles Fernandez-Prades, 2017. cfernandez(at)cttc.es
 | 
			
		||||
 *                    Antonio Ramos, 2018. antonio.ramos(at)cttc.es
 | 
			
		||||
 *
 | 
			
		||||
 * -------------------------------------------------------------------------
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2010-2017  (see AUTHORS file for a list of contributors)
 | 
			
		||||
 * Copyright (C) 2010-2018  (see AUTHORS file for a list of contributors)
 | 
			
		||||
 *
 | 
			
		||||
 * GNSS-SDR is a software defined Global Navigation
 | 
			
		||||
 *          Satellite Systems receiver
 | 
			
		||||
@@ -31,8 +32,6 @@
 | 
			
		||||
#ifndef GNSS_SDR_ACQUISITION_DUMP_READER_H
 | 
			
		||||
#define GNSS_SDR_ACQUISITION_DUMP_READER_H
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
@@ -54,8 +53,7 @@ private:
 | 
			
		||||
    unsigned int d_doppler_step;
 | 
			
		||||
    unsigned int d_samples_per_code;
 | 
			
		||||
    unsigned int d_num_doppler_bins;
 | 
			
		||||
    std::vector<std::string> d_dump_filenames;
 | 
			
		||||
    std::vector<std::ifstream> d_dump_files;
 | 
			
		||||
    std::string d_dump_filename;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // GNSS_SDR_ACQUISITION_DUMP_READER_H
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										116
									
								
								src/utils/matlab/plot_acq_grid.m
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								src/utils/matlab/plot_acq_grid.m
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,116 @@
 | 
			
		||||
% /*!
 | 
			
		||||
%  * \file plot_acq_grid.m
 | 
			
		||||
%  * \brief Read GNSS-SDR Acquisition dump .mat file using the provided
 | 
			
		||||
%  function and plot acquisition grid of acquisition statistic of PRN sat
 | 
			
		||||
%
 | 
			
		||||
%  
 | 
			
		||||
%  * \author Antonio Ramos, 2017. antonio.ramos(at)cttc.es
 | 
			
		||||
%  * -------------------------------------------------------------------------
 | 
			
		||||
%  *
 | 
			
		||||
%  * Copyright (C) 2010-2017  (see AUTHORS file for a list of contributors)
 | 
			
		||||
%  *
 | 
			
		||||
%  * GNSS-SDR is a software defined Global Navigation
 | 
			
		||||
%  *          Satellite Systems receiver
 | 
			
		||||
%  *
 | 
			
		||||
%  * This file is part of GNSS-SDR.
 | 
			
		||||
%  *
 | 
			
		||||
%  * GNSS-SDR is free software: you can redistribute it and/or modify
 | 
			
		||||
%  * it under the terms of the GNU General Public License as published by
 | 
			
		||||
%  * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
%  * at your option) any later version.
 | 
			
		||||
%  *
 | 
			
		||||
%  * GNSS-SDR is distributed in the hope that it will be useful,
 | 
			
		||||
%  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
%  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
%  * GNU General Public License for more details.
 | 
			
		||||
%  *
 | 
			
		||||
%  * You should have received a copy of the GNU General Public License
 | 
			
		||||
%  * along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
%  *
 | 
			
		||||
%  * -------------------------------------------------------------------------
 | 
			
		||||
%  */ 
 | 
			
		||||
 | 
			
		||||
%%%%%%%%% ¡¡¡ CONFIGURE !!! %%%%%%%%%%%%% 
 | 
			
		||||
 | 
			
		||||
path = '/archive/';
 | 
			
		||||
file = 'acq';
 | 
			
		||||
 | 
			
		||||
sat = 7;
 | 
			
		||||
 | 
			
		||||
% Signal:
 | 
			
		||||
%     1 GPS  L1
 | 
			
		||||
%     2 GPS  L2M
 | 
			
		||||
%     3 GPS  L5
 | 
			
		||||
%     4 Gal. E1B
 | 
			
		||||
%     5 Gal. E5
 | 
			
		||||
%     6 Glo. 1G
 | 
			
		||||
 | 
			
		||||
signal_type = 1;
 | 
			
		||||
 | 
			
		||||
%%% True for light grid representation
 | 
			
		||||
lite_view = true;
 | 
			
		||||
 | 
			
		||||
%%% If lite_view, it sets the number of samples per chip in the graphical representation
 | 
			
		||||
n_samples_per_chip = 3;
 | 
			
		||||
 | 
			
		||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 | 
			
		||||
 | 
			
		||||
switch(signal_type)
 | 
			
		||||
    case 1
 | 
			
		||||
        n_chips = 1023;
 | 
			
		||||
        system = 'G';
 | 
			
		||||
        signal = '1C';
 | 
			
		||||
    case 2
 | 
			
		||||
        n_chips = 10230;
 | 
			
		||||
        system = 'G';
 | 
			
		||||
        signal = '2S';
 | 
			
		||||
    case 3
 | 
			
		||||
        n_chips = 10230;
 | 
			
		||||
        system = 'G';
 | 
			
		||||
        signal = 'L5';
 | 
			
		||||
    case 4
 | 
			
		||||
        n_chips = 4092;
 | 
			
		||||
        system = 'E';
 | 
			
		||||
        signal = '1B';
 | 
			
		||||
    case 5
 | 
			
		||||
        n_chips = 10230;
 | 
			
		||||
        system = 'E';
 | 
			
		||||
        signal = '5X';
 | 
			
		||||
    case 6
 | 
			
		||||
        n_chips = 511;
 | 
			
		||||
        system = 'R';
 | 
			
		||||
        signal = '1G';
 | 
			
		||||
end
 | 
			
		||||
filename = [path file '_' system '_' signal '_sat_' num2str(sat) '.mat'];
 | 
			
		||||
load(filename);
 | 
			
		||||
[n_fft n_dop_bins] = size(grid);
 | 
			
		||||
[d_max f_max] = find(grid == max(max(grid)));
 | 
			
		||||
freq = (0 : n_dop_bins - 1) * doppler_step - doppler_max;
 | 
			
		||||
delay = (0 : n_fft - 1) / n_fft * n_chips;
 | 
			
		||||
figure(1)
 | 
			
		||||
if(lite_view == false)
 | 
			
		||||
    surf(freq, delay, grid, 'FaceColor', 'interp', 'LineStyle', 'none')
 | 
			
		||||
    ylim([min(delay) max(delay)])
 | 
			
		||||
else
 | 
			
		||||
    delay_interp = (0 : n_samples_per_chip * n_chips - 1) / n_samples_per_chip;
 | 
			
		||||
    grid_interp = spline(delay, grid', delay_interp)';
 | 
			
		||||
    surf(freq, delay_interp, grid_interp, 'FaceColor', 'interp', 'LineStyle', 'none')
 | 
			
		||||
    ylim([min(delay_interp) max(delay_interp)])
 | 
			
		||||
end
 | 
			
		||||
xlabel('Doppler shift / Hz')
 | 
			
		||||
xlim([min(freq) max(freq)])
 | 
			
		||||
ylabel('Code delay / chips')
 | 
			
		||||
zlabel('Test statistics')
 | 
			
		||||
figure(2)
 | 
			
		||||
subplot(2,1,1)
 | 
			
		||||
plot(freq, grid(d_max, :))
 | 
			
		||||
xlim([min(freq) max(freq)])
 | 
			
		||||
xlabel('Doppler shift / Hz')
 | 
			
		||||
ylabel('Test statistics')
 | 
			
		||||
title(['Fixed code delay to ' num2str((d_max - 1) / n_fft * n_chips) ' chips'])
 | 
			
		||||
subplot(2,1,2)
 | 
			
		||||
plot(delay, grid(:, f_max))
 | 
			
		||||
xlim([min(delay) max(delay)])
 | 
			
		||||
xlabel('Code delay / chips')
 | 
			
		||||
ylabel('Test statistics')
 | 
			
		||||
title(['Doppler wipe-off = ' num2str((f_max - 1) * doppler_step - doppler_max) ' Hz'])
 | 
			
		||||
		Reference in New Issue
	
	Block a user