mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2025-09-13 08:16:03 +00:00
Added test for code_resampler - passing now
Also implemented a speedup for the bounds checking on CodeResamplerGeneric and implemented bounds checking on CodeResamplerFxpt64
This commit is contained in:
@@ -37,7 +37,13 @@
|
||||
#ifndef GNSS_SDR_CODE_RESAMPLER_H_
|
||||
#define GNSS_SDR_CODE_RESAMPLER_H_
|
||||
|
||||
#include <volk/volk.h>
|
||||
#include <vector>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <limits>
|
||||
#include "fxpt64.h"
|
||||
#include <cassert>
|
||||
|
||||
/*!
|
||||
* \brief Interface for a generic code resampler
|
||||
*
|
||||
@@ -52,7 +58,7 @@ public:
|
||||
* Actually perform the code resampling.
|
||||
*/
|
||||
virtual void resample_code( T const *orig_code, unsigned int code_length,
|
||||
std::vector< double > &init_code_phase, double code_phase_step,
|
||||
std::vector< double > &init_code_phase, double &code_phase_step,
|
||||
int num_samples,
|
||||
std::vector< T * > resampled_codes ) = 0;
|
||||
};
|
||||
@@ -70,22 +76,49 @@ public:
|
||||
* output.
|
||||
*/
|
||||
virtual void resample_code( T const *orig_code, unsigned int code_length,
|
||||
std::vector< double > &init_code_phase, double code_phase_step,
|
||||
std::vector< double > &init_code_phase, double &code_phase_step,
|
||||
int num_samples,
|
||||
std::vector< T * > resampled_codes )
|
||||
{
|
||||
// Loop over the desired outputs:
|
||||
for( int i = 0; i < init_code_phase.size(); ++i )
|
||||
{
|
||||
double tcode_chips = init_code_phase[i];
|
||||
double tcode_chips = std::fmod( init_code_phase[i], code_length);
|
||||
if( tcode_chips < 0.0 )
|
||||
{
|
||||
tcode_chips += static_cast< double >( code_length );
|
||||
}
|
||||
|
||||
int associated_chip_index;
|
||||
T *curr_sample = resampled_codes[i];
|
||||
for( int j = 0; j < num_samples; ++j )
|
||||
|
||||
int j = 0;
|
||||
|
||||
// Here we lift the bounds checking out of the loop:
|
||||
// This gave a performance improvement of about a factor 3.3
|
||||
while( j < num_samples )
|
||||
{
|
||||
associated_chip_index = std::floor(std::fmod(tcode_chips , code_length_chips));
|
||||
*curr_sample = orig_code[associated_chip_index];
|
||||
tcode_chips = tcode_chips + code_phase_step_chips;
|
||||
++curr_sample;
|
||||
int num_samples_this_iter = num_samples;
|
||||
|
||||
int num_samples_at_rollover = j + std::floor(
|
||||
( code_length - tcode_chips )/code_phase_step
|
||||
) + 1;
|
||||
|
||||
if( num_samples_at_rollover < num_samples )
|
||||
{
|
||||
num_samples_this_iter = num_samples_at_rollover;
|
||||
}
|
||||
|
||||
|
||||
for( ; j < num_samples_this_iter; ++j )
|
||||
{
|
||||
associated_chip_index = std::floor(tcode_chips);
|
||||
*curr_sample = orig_code[associated_chip_index];
|
||||
tcode_chips += code_phase_step;
|
||||
++curr_sample;
|
||||
}
|
||||
|
||||
tcode_chips = std::fmod( tcode_chips, code_length );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,7 +141,7 @@ public:
|
||||
* Resample the code computing the code phases exactly for the latest output
|
||||
* and forcing all others to be integer shifts of the latest value*/
|
||||
virtual void resample_code( T const *orig_code, unsigned int code_length,
|
||||
std::vector< double > &init_code_phase, double code_phase_step,
|
||||
std::vector< double > &init_code_phase, double &code_phase_step,
|
||||
int num_samples,
|
||||
std::vector< T * > resampled_codes )
|
||||
{
|
||||
@@ -129,7 +162,7 @@ public:
|
||||
std::vector< T * > dummy_resampled_codes(1, resampled_codes[0] );
|
||||
std::vector< double > dummy_init_code_phase(1, init_code_phase[0] );
|
||||
|
||||
core_resampler->resample_code( orig_code, code_length,
|
||||
d_core_resampler->resample_code( orig_code, code_length,
|
||||
dummy_init_code_phase, code_phase_step,
|
||||
total_samples, dummy_resampled_codes );
|
||||
|
||||
@@ -154,6 +187,7 @@ private:
|
||||
|
||||
/*!
|
||||
* \brief Code resampler that uses 64 bit fixed point arithmetic */
|
||||
|
||||
template< typename T, unsigned FRAC_LEN = 32 >
|
||||
class CodeResamplerFxpt64 : public CodeResamplerInterface<T>
|
||||
{
|
||||
@@ -162,7 +196,7 @@ public:
|
||||
* Resample the code using 64-bit fixed point arithmetic
|
||||
*/
|
||||
virtual void resample_code( T const *orig_code, unsigned int code_length,
|
||||
std::vector< double > &init_code_phase, double code_phase_step,
|
||||
std::vector< double > &init_code_phase, double &code_phase_step,
|
||||
int num_samples,
|
||||
std::vector< T * > resampled_codes )
|
||||
{
|
||||
@@ -171,20 +205,175 @@ public:
|
||||
// Loop over the desired outputs:
|
||||
for( int i = 0; i < init_code_phase.size(); ++i )
|
||||
{
|
||||
int64_t code_phase_fxp = double_to_fxpt64( init_code_phase[i], FRAC_LEN );
|
||||
T *curr_sample = resampled_codes[i];
|
||||
double tcode_chips = std::fmod( init_code_phase[i], code_length );
|
||||
if( tcode_chips < 0.0 )
|
||||
{
|
||||
tcode_chips += code_length;
|
||||
}
|
||||
|
||||
int64_t code_phase_fxp = double_to_fxpt64( tcode_chips, FRAC_LEN );
|
||||
T *curr_sample = resampled_codes[i];
|
||||
init_code_phase[i] = fxpt64_to_double( code_phase_fxp );
|
||||
|
||||
for( int j = 0; j < num_samples; ++j )
|
||||
int j = 0;
|
||||
|
||||
while( j < num_samples )
|
||||
{
|
||||
*curr_sample = orig_code[ code_phase_fxp >> FRAC_LEN ];
|
||||
code_phase_fxp += code_phase_step_fxp;
|
||||
++curr_sample;
|
||||
|
||||
int num_samples_this_iter = num_samples;
|
||||
|
||||
int num_samples_at_rollover = j + std::floor(
|
||||
(static_cast<double>( code_length ) - fxpt64_to_double( code_phase_fxp )
|
||||
)/code_phase_step
|
||||
) + 1;
|
||||
|
||||
if( num_samples_at_rollover < num_samples )
|
||||
{
|
||||
num_samples_this_iter = num_samples_at_rollover;
|
||||
}
|
||||
|
||||
|
||||
for( ; j < num_samples_this_iter; ++j )
|
||||
{
|
||||
*curr_sample = orig_code[ code_phase_fxp >> FRAC_LEN ];
|
||||
code_phase_fxp += code_phase_step_fxp;
|
||||
++curr_sample;
|
||||
}
|
||||
|
||||
assert( static_cast<int>(
|
||||
fxpt64_to_double( code_phase_fxp - code_phase_step_fxp )
|
||||
) < code_length );
|
||||
|
||||
code_phase_fxp -= ( static_cast< int64_t >( code_length ) << FRAC_LEN );
|
||||
}
|
||||
}
|
||||
|
||||
code_phase_step = fxpt64_to_double( code_phase_step_fxp );
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Code resampler that uses a fixed number of replicas in memory*/
|
||||
template< typename T >
|
||||
class CodeResamplerMemoryStore : public CodeResamplerInterface<T>
|
||||
{
|
||||
public:
|
||||
CodeResamplerMemoryStore( T const *orig_code,
|
||||
unsigned int code_length,
|
||||
double nominal_code_phase_step,
|
||||
unsigned int maximum_num_samples,
|
||||
double code_spacing_chips,
|
||||
double maximum_code_offset_chips )
|
||||
: d_nominal_code_phase_step( nominal_code_phase_step ),
|
||||
d_code_spacing_chips( code_spacing_chips ),
|
||||
d_maximum_code_offset_chips( maximum_code_offset_chips )
|
||||
{
|
||||
int num_replicas = static_cast< int >(
|
||||
std::ceil( d_maximum_code_offset_chips /
|
||||
d_code_spacing_chips ) );
|
||||
|
||||
|
||||
// Resize the storage:
|
||||
d_code_phase_offsets.resize( num_replicas );
|
||||
d_replica_store.resize( num_replicas );
|
||||
|
||||
// Use a generic resampler to generate the local replica store:
|
||||
CodeResamplerGeneric<T> baseResampler;
|
||||
|
||||
double curr_offset = 0.0;
|
||||
|
||||
for( int ii = 0; ii < num_replicas; ++ii )
|
||||
{
|
||||
d_code_phase_offsets[ii] = curr_offset;
|
||||
curr_offset += d_code_spacing_chips;
|
||||
|
||||
d_replica_store[ii] = static_cast< T *>( volk_malloc(
|
||||
maximum_num_samples * sizeof( T ),
|
||||
volk_get_alignment() ) );
|
||||
|
||||
}
|
||||
|
||||
// Now we generate the codes to be at least twice as long as the maximum possible
|
||||
baseResampler.resample_code( orig_code, code_length,
|
||||
d_code_phase_offsets, d_nominal_code_phase_step, 2*maximum_num_samples,
|
||||
d_replica_store );
|
||||
|
||||
|
||||
};
|
||||
|
||||
~CodeResamplerMemoryStore()
|
||||
{
|
||||
for( unsigned int ii = 0; ii < d_replica_store.size(); ++ii )
|
||||
{
|
||||
volk_free( d_replica_store[ii] );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Resample the code by choosing the local replicas that most closely match
|
||||
* the code phase offsets required
|
||||
*/
|
||||
virtual void resample_code( T const *orig_code, unsigned int code_length,
|
||||
std::vector< double > &init_code_phase, double &code_phase_step,
|
||||
int num_samples,
|
||||
std::vector< T * > resampled_codes )
|
||||
{
|
||||
|
||||
// Loop over the desired outputs:
|
||||
for( int ii = 0; ii < init_code_phase.size(); ++ii )
|
||||
{
|
||||
int offset_ind = 0;
|
||||
double delta_offset = std::numeric_limits<double>::infinity();
|
||||
|
||||
double desired_code_phase = init_code_phase[ii];
|
||||
double desired_code_phase_mod_one_chip = std::fmod( desired_code_phase, 1.0 );
|
||||
|
||||
if( desired_code_phase_mod_one_chip < 0.0 )
|
||||
{
|
||||
desired_code_phase_mod_one_chip += 1.0;
|
||||
}
|
||||
|
||||
double achieved_code_phase = 0.0;
|
||||
|
||||
for( int jj = 0; jj < d_code_phase_offsets.size(); ++jj )
|
||||
{
|
||||
double abs_diff = std::abs( desired_code_phase_mod_one_chip - d_code_phase_offsets[jj] );
|
||||
if( abs_diff < delta_offset )
|
||||
{
|
||||
delta_offset = abs_diff;
|
||||
offset_ind = jj;
|
||||
achieved_code_phase = desired_code_phase - desired_code_phase_mod_one_chip
|
||||
+ d_code_phase_offsets[jj];
|
||||
}
|
||||
}
|
||||
|
||||
init_code_phase[ii] = achieved_code_phase;
|
||||
|
||||
int integer_offset = static_cast< int >( desired_code_phase - desired_code_phase_mod_one_chip );
|
||||
|
||||
memcpy( resampled_codes[ii], d_replica_store[offset_ind] + integer_offset*sizeof(T),
|
||||
num_samples * sizeof( T ) );
|
||||
|
||||
}
|
||||
|
||||
code_phase_step = d_nominal_code_phase_step;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
double d_nominal_code_phase_step;
|
||||
|
||||
double d_maximum_code_offset_chips;
|
||||
|
||||
double d_code_spacing_chips;
|
||||
|
||||
std::vector< double > d_code_phase_offsets;
|
||||
|
||||
std::vector< T * > d_replica_store;
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@@ -366,6 +366,40 @@ else(NOT ${GTEST_DIR_LOCAL})
|
||||
add_dependencies(trk_test gtest)
|
||||
endif(NOT ${GTEST_DIR_LOCAL})
|
||||
|
||||
add_dependencies(check control_thread_test flowgraph_test gnss_block_test
|
||||
gnuradio_block_test trk_test)
|
||||
|
||||
#####################
|
||||
## Arithmetic test
|
||||
add_executable(arithmetic_test
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/single_test_main.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/arithmetic/code_resampler_test.cc
|
||||
)
|
||||
if(NOT ${ENABLE_PACKAGING})
|
||||
set_property(TARGET arithmetic_test PROPERTY EXCLUDE_FROM_ALL TRUE)
|
||||
endif(NOT ${ENABLE_PACKAGING})
|
||||
|
||||
target_link_libraries(arithmetic_test ${Boost_LIBRARIES}
|
||||
${GFLAGS_LIBS}
|
||||
${GLOG_LIBRARIES}
|
||||
${GTEST_LIBRARIES}
|
||||
${GNURADIO_RUNTIME_LIBRARIES}
|
||||
${GNURADIO_BLOCKS_LIBRARIES}
|
||||
${GNURADIO_FILTER_LIBRARIES}
|
||||
${GNURADIO_ANALOG_LIBRARIES}
|
||||
gnss_sp_libs
|
||||
gnss_rx
|
||||
gnss_system_parameters
|
||||
signal_generator_blocks
|
||||
out_adapters
|
||||
${VOLK_GNSSSDR_LIBRARIES} ${ORC_LIBRARIES}
|
||||
)
|
||||
|
||||
add_test(arithmetic_test arithmetic_test)
|
||||
if(NOT ${GTEST_DIR_LOCAL})
|
||||
add_dependencies(arithmetic_test gtest-${gtest_RELEASE})
|
||||
else(NOT ${GTEST_DIR_LOCAL})
|
||||
add_dependencies(arithmetic_test gtest)
|
||||
endif(NOT ${GTEST_DIR_LOCAL})
|
||||
|
||||
add_dependencies(check control_thread_test flowgraph_test gnss_block_test
|
||||
gnuradio_block_test trk_test arithmetic_test)
|
||||
|
||||
|
368
src/tests/arithmetic/code_resampler_test.cc
Normal file
368
src/tests/arithmetic/code_resampler_test.cc
Normal file
@@ -0,0 +1,368 @@
|
||||
/*!
|
||||
* \file code_generation_test.cc
|
||||
* \brief This file implements tests for resampling codes
|
||||
* \author Cillian O'Driscoll, 2015. cillian.odriscoll(at)gmail.com
|
||||
*
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2010-2015 (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/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include "code_resampler.h"
|
||||
#include <complex>
|
||||
#include <ctime>
|
||||
#include <sys/time.h>
|
||||
#include "gps_sdr_signal_processing.h"
|
||||
#include "gnss_signal_processing.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
void allocate_replicas( std::vector< std::complex< float > * >& replicas, int num_samples )
|
||||
{
|
||||
|
||||
for( int i = 0; i < replicas.size(); ++i )
|
||||
{
|
||||
replicas[i] = static_cast< std::complex<float> *>(
|
||||
volk_malloc( num_samples*sizeof( std::complex<float> ),
|
||||
volk_get_alignment() )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void deallocate_replicas( std::vector< std::complex< float > * > &replicas )
|
||||
{
|
||||
for( int i = 0; i < replicas.size(); ++i )
|
||||
{
|
||||
volk_free( replicas[i] );
|
||||
}
|
||||
}
|
||||
|
||||
TEST(CodeResamplerTest, CodeResamplerGeneric )
|
||||
{
|
||||
std::complex<float>* _orig_code = new std::complex<float>[1023];
|
||||
signed int _prn = 1;
|
||||
unsigned int _chip_shift = 4;
|
||||
unsigned int _num_replicas = 3;
|
||||
|
||||
double fs = 6e6;
|
||||
double fc = 1.023e6;
|
||||
|
||||
double code_phase_step = fc/fs;
|
||||
double code_spacing_chips = 0.5;
|
||||
|
||||
double T = 0.001;
|
||||
|
||||
int _num_samples = static_cast< int >(
|
||||
std::ceil( T * fs )
|
||||
);
|
||||
|
||||
std::vector< std::complex<float>* > _resampled_codes;
|
||||
_resampled_codes.resize(_num_replicas);
|
||||
std::vector< double > _desired_code_phases;
|
||||
_desired_code_phases.resize(_num_replicas);
|
||||
|
||||
gps_l1_ca_code_gen_complex( _orig_code, _prn, 0);
|
||||
|
||||
allocate_replicas( _resampled_codes, _num_samples );
|
||||
|
||||
CodeResamplerGeneric< std::complex< float > > the_resampler;
|
||||
|
||||
int iterations = 1000;
|
||||
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
long long int begin = tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
{
|
||||
double current_code_phase = static_cast< double >( i ) - code_spacing_chips;
|
||||
for( int j = 0; j < _num_replicas; ++j )
|
||||
{
|
||||
_desired_code_phases[j] = current_code_phase;
|
||||
current_code_phase += code_spacing_chips;
|
||||
}
|
||||
|
||||
the_resampler.resample_code( _orig_code, 1023, _desired_code_phases,
|
||||
code_phase_step, _num_samples, _resampled_codes );
|
||||
|
||||
|
||||
}
|
||||
delete[] _orig_code;
|
||||
gettimeofday(&tv, NULL);
|
||||
long long int end = tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
ASSERT_LE(0, end - begin);
|
||||
std::cout << "Resampling completed in " << (end - begin) << " microseconds" << std::endl;
|
||||
|
||||
deallocate_replicas( _resampled_codes );
|
||||
|
||||
}
|
||||
|
||||
TEST(CodeResamplerTest, CodeResamplerIntegerChipSpacing )
|
||||
{
|
||||
std::complex<float>* _orig_code = new std::complex<float>[1023];
|
||||
signed int _prn = 1;
|
||||
unsigned int _chip_shift = 4;
|
||||
unsigned int _num_replicas = 3;
|
||||
|
||||
double fs = 6e6;
|
||||
double fc = 1.023e6;
|
||||
|
||||
double code_phase_step = fc/fs;
|
||||
double code_spacing_chips = 0.5;
|
||||
|
||||
double T = 0.001;
|
||||
|
||||
int _num_samples = static_cast< int >(
|
||||
std::ceil( T * fs )
|
||||
);
|
||||
|
||||
std::vector< std::complex<float>* > _resampled_codes;
|
||||
_resampled_codes.resize(_num_replicas);
|
||||
std::vector< double > _desired_code_phases;
|
||||
_desired_code_phases.resize(_num_replicas);
|
||||
|
||||
gps_l1_ca_code_gen_complex( _orig_code, _prn, 0);
|
||||
|
||||
allocate_replicas( _resampled_codes, _num_samples );
|
||||
|
||||
CodeResamplerIntegerChipSpacing< std::complex< float > > the_resampler(
|
||||
boost::shared_ptr< CodeResamplerInterface< std::complex<float> > >(
|
||||
new CodeResamplerGeneric< std::complex<float> >
|
||||
));
|
||||
|
||||
int iterations = 1000;
|
||||
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
long long int begin = tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
{
|
||||
double current_code_phase = static_cast< double >( i ) - code_spacing_chips;
|
||||
for( int j = 0; j < _num_replicas; ++j )
|
||||
{
|
||||
_desired_code_phases[j] = current_code_phase;
|
||||
current_code_phase += code_spacing_chips;
|
||||
}
|
||||
|
||||
the_resampler.resample_code( _orig_code, 1023, _desired_code_phases,
|
||||
code_phase_step, _num_samples, _resampled_codes );
|
||||
|
||||
|
||||
}
|
||||
delete[] _orig_code;
|
||||
gettimeofday(&tv, NULL);
|
||||
long long int end = tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
ASSERT_LE(0, end - begin);
|
||||
std::cout << "Resampling completed in " << (end - begin) << " microseconds" << std::endl;
|
||||
|
||||
deallocate_replicas( _resampled_codes );
|
||||
|
||||
}
|
||||
|
||||
TEST(CodeResamplerTest, CodeResamplerFxpt64 )
|
||||
{
|
||||
std::complex<float>* _orig_code = new std::complex<float>[1023];
|
||||
signed int _prn = 1;
|
||||
unsigned int _chip_shift = 4;
|
||||
unsigned int _num_replicas = 3;
|
||||
|
||||
double fs = 6e6;
|
||||
double fc = 1.023e6;
|
||||
|
||||
double code_phase_step = fc/fs;
|
||||
double code_spacing_chips = 0.5;
|
||||
|
||||
double T = 0.001;
|
||||
|
||||
int _num_samples = static_cast< int >(
|
||||
std::ceil( T * fs )
|
||||
);
|
||||
|
||||
std::vector< std::complex<float>* > _resampled_codes;
|
||||
_resampled_codes.resize(_num_replicas);
|
||||
std::vector< double > _desired_code_phases;
|
||||
_desired_code_phases.resize(_num_replicas);
|
||||
|
||||
gps_l1_ca_code_gen_complex( _orig_code, _prn, 0);
|
||||
|
||||
allocate_replicas( _resampled_codes, _num_samples );
|
||||
|
||||
CodeResamplerFxpt64< std::complex< float > > the_resampler;
|
||||
|
||||
int iterations = 1000;
|
||||
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
long long int begin = tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
{
|
||||
double current_code_phase = static_cast< double >( i ) - code_spacing_chips;
|
||||
for( int j = 0; j < _num_replicas; ++j )
|
||||
{
|
||||
_desired_code_phases[j] = current_code_phase;
|
||||
current_code_phase += code_spacing_chips;
|
||||
}
|
||||
|
||||
the_resampler.resample_code( _orig_code, 1023, _desired_code_phases,
|
||||
code_phase_step, _num_samples, _resampled_codes );
|
||||
|
||||
|
||||
}
|
||||
delete[] _orig_code;
|
||||
gettimeofday(&tv, NULL);
|
||||
long long int end = tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
ASSERT_LE(0, end - begin);
|
||||
std::cout << "Resampling completed in " << (end - begin) << " microseconds" << std::endl;
|
||||
|
||||
deallocate_replicas( _resampled_codes );
|
||||
|
||||
}
|
||||
|
||||
TEST(CodeResamplerTest, CodeResamplerIntegerChipSpacingFxpt64 )
|
||||
{
|
||||
std::complex<float>* _orig_code = new std::complex<float>[1023];
|
||||
signed int _prn = 1;
|
||||
unsigned int _chip_shift = 4;
|
||||
unsigned int _num_replicas = 3;
|
||||
|
||||
double fs = 6e6;
|
||||
double fc = 1.023e6;
|
||||
|
||||
double code_phase_step = fc/fs;
|
||||
double code_spacing_chips = 0.5;
|
||||
|
||||
double T = 0.001;
|
||||
|
||||
int _num_samples = static_cast< int >(
|
||||
std::ceil( T * fs )
|
||||
);
|
||||
|
||||
std::vector< std::complex<float>* > _resampled_codes;
|
||||
_resampled_codes.resize(_num_replicas);
|
||||
std::vector< double > _desired_code_phases;
|
||||
_desired_code_phases.resize(_num_replicas);
|
||||
|
||||
gps_l1_ca_code_gen_complex( _orig_code, _prn, 0);
|
||||
|
||||
allocate_replicas( _resampled_codes, _num_samples );
|
||||
|
||||
CodeResamplerIntegerChipSpacing< std::complex< float > > the_resampler(
|
||||
boost::shared_ptr< CodeResamplerInterface< std::complex<float> > >(
|
||||
new CodeResamplerFxpt64< std::complex<float> >
|
||||
));
|
||||
|
||||
int iterations = 1000;
|
||||
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
long long int begin = tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
{
|
||||
double current_code_phase = static_cast< double >( i ) - code_spacing_chips;
|
||||
for( int j = 0; j < _num_replicas; ++j )
|
||||
{
|
||||
_desired_code_phases[j] = current_code_phase;
|
||||
current_code_phase += code_spacing_chips;
|
||||
}
|
||||
|
||||
the_resampler.resample_code( _orig_code, 1023, _desired_code_phases,
|
||||
code_phase_step, _num_samples, _resampled_codes );
|
||||
|
||||
|
||||
}
|
||||
delete[] _orig_code;
|
||||
gettimeofday(&tv, NULL);
|
||||
long long int end = tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
ASSERT_LE(0, end - begin);
|
||||
std::cout << "Resampling completed in " << (end - begin) << " microseconds" << std::endl;
|
||||
|
||||
deallocate_replicas( _resampled_codes );
|
||||
|
||||
}
|
||||
|
||||
TEST(CodeResamplerTest, CodeResamplerMemoryStore )
|
||||
{
|
||||
std::complex<float>* _orig_code = new std::complex<float>[1023];
|
||||
signed int _prn = 1;
|
||||
unsigned int _chip_shift = 4;
|
||||
unsigned int _num_replicas = 3;
|
||||
|
||||
double fs = 6e6;
|
||||
double fc = 1.023e6;
|
||||
|
||||
double code_phase_step = fc/fs;
|
||||
double code_spacing_chips = 0.5;
|
||||
|
||||
double T = 0.001;
|
||||
|
||||
int _num_samples = static_cast< int >(
|
||||
std::ceil( T * fs )
|
||||
);
|
||||
|
||||
std::vector< std::complex<float>* > _resampled_codes;
|
||||
_resampled_codes.resize(_num_replicas);
|
||||
std::vector< double > _desired_code_phases;
|
||||
_desired_code_phases.resize(_num_replicas);
|
||||
|
||||
gps_l1_ca_code_gen_complex( _orig_code, _prn, 0);
|
||||
|
||||
allocate_replicas( _resampled_codes, _num_samples );
|
||||
|
||||
CodeResamplerMemoryStore< std::complex< float > > the_resampler(
|
||||
_orig_code, 1023, code_phase_step, _num_samples, 0.1, 1.0 );
|
||||
|
||||
int iterations = 1000;
|
||||
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
long long int begin = tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
{
|
||||
double current_code_phase = static_cast< double >( i ) - code_spacing_chips;
|
||||
for( int j = 0; j < _num_replicas; ++j )
|
||||
{
|
||||
_desired_code_phases[j] = current_code_phase;
|
||||
current_code_phase += code_spacing_chips;
|
||||
}
|
||||
|
||||
the_resampler.resample_code( _orig_code, 1023, _desired_code_phases,
|
||||
code_phase_step, _num_samples, _resampled_codes );
|
||||
|
||||
|
||||
}
|
||||
delete[] _orig_code;
|
||||
gettimeofday(&tv, NULL);
|
||||
long long int end = tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
ASSERT_LE(0, end - begin);
|
||||
std::cout << "Resampling completed in " << (end - begin) << " microseconds" << std::endl;
|
||||
|
||||
deallocate_replicas( _resampled_codes );
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user