mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2025-12-05 16:18:06 +00:00
Merge branch 'codeless' into prs_codeless
This commit is contained in:
66
src/algorithms/libs/accumulate_array.h
Normal file
66
src/algorithms/libs/accumulate_array.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*!
|
||||
* \file accumulate_array.h
|
||||
* \brief Class providing functionality similar to Matlab's accumarray
|
||||
* \authors Cillian O'Driscoll 2015. cillian.odriscoll(at)gmail.com
|
||||
*
|
||||
* This function accumulates data from an input vector, into an output
|
||||
* vector, according to the indices provided by an index vector.
|
||||
*
|
||||
* e.g.
|
||||
*
|
||||
* Input:
|
||||
* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
|
||||
*
|
||||
* Index Vec:
|
||||
* 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3, 3
|
||||
*
|
||||
* Output:
|
||||
* Before:
|
||||
* 0, 0, 0, 0, 0
|
||||
* After:
|
||||
* 3, 18, 15, 42, 0
|
||||
*
|
||||
* Note accumulate_array does not zero the output vector
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef GNSS_SDR_ACCUMULATE_ARRAY_H_
|
||||
#define GNSS_SDR_ACCUMULATE_ARRAY_H_
|
||||
|
||||
template< typename T >
|
||||
void accumulate_array( const T *input_vec, const int *index_vec, T *output_vec, int num_samples )
|
||||
{
|
||||
const int *curr_index = index_vec;
|
||||
const T *curr_input = input_vec;
|
||||
|
||||
for( unsigned int ii = 0; ii < num_samples; ++ii )
|
||||
{
|
||||
output_vec[ *curr_index++ ] += *curr_input++;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
379
src/algorithms/libs/code_resampler.h
Normal file
379
src/algorithms/libs/code_resampler.h
Normal file
@@ -0,0 +1,379 @@
|
||||
/*!
|
||||
* \file code_resampler.h
|
||||
* \brief Class providing a number of code resampling options
|
||||
* \authors Cillian O'Driscoll 2015. cillian.odriscoll(at)gmail.com
|
||||
*
|
||||
* Class interface for code resampling. Code resampling is characterised by
|
||||
* resampling an array that is constant over each element (called a chip).
|
||||
* The code frequency is called the chip rate, the code phase is a floating
|
||||
* point value indicating the current chip value between 0 and L -1 where
|
||||
* L is the code length
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#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
|
||||
*
|
||||
*
|
||||
*/
|
||||
template< typename T >
|
||||
class CodeResamplerInterface
|
||||
{
|
||||
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,
|
||||
int num_samples,
|
||||
std::vector< T * > resampled_codes ) = 0;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Simple generic implementation of code resampling. Most accurate
|
||||
* and most expensive
|
||||
*/
|
||||
template< typename T >
|
||||
class CodeResamplerGeneric : public CodeResamplerInterface<T>
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* Resample the code computing the code phases exactly for each desired
|
||||
* output.
|
||||
*/
|
||||
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 i = 0; i < init_code_phase.size(); ++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];
|
||||
|
||||
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 )
|
||||
{
|
||||
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 = static_cast< int >(tcode_chips);
|
||||
*curr_sample = orig_code[associated_chip_index];
|
||||
tcode_chips += code_phase_step;
|
||||
++curr_sample;
|
||||
}
|
||||
|
||||
tcode_chips = std::fmod( tcode_chips, code_length );
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Code resampler that forces the code spacing to the nearest integer
|
||||
* number of samples
|
||||
*/
|
||||
template< typename T >
|
||||
class CodeResamplerIntegerChipSpacing : public CodeResamplerInterface<T>
|
||||
{
|
||||
public:
|
||||
|
||||
CodeResamplerIntegerChipSpacing( boost::shared_ptr< CodeResamplerInterface<T> > core_resampler )
|
||||
: d_core_resampler( core_resampler )
|
||||
{};
|
||||
|
||||
/*!
|
||||
* 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,
|
||||
int num_samples,
|
||||
std::vector< T * > resampled_codes )
|
||||
{
|
||||
double earliest_code_phase = init_code_phase[0];
|
||||
std::vector< int > code_phase_offsets_samples( init_code_phase.size(), 0 );
|
||||
|
||||
for( int i = 1; i < init_code_phase.size(); ++i )
|
||||
{
|
||||
code_phase_offsets_samples[i] = round(
|
||||
( init_code_phase[i] - earliest_code_phase ) / code_phase_step
|
||||
);
|
||||
}
|
||||
|
||||
int total_samples = num_samples + code_phase_offsets_samples.back();
|
||||
|
||||
// Now we call the generic implementation for the earliest code phase
|
||||
// and copy for the later code phases:
|
||||
std::vector< T * > dummy_resampled_codes(1, resampled_codes[0] );
|
||||
std::vector< double > dummy_init_code_phase(1, init_code_phase[0] );
|
||||
|
||||
d_core_resampler->resample_code( orig_code, code_length,
|
||||
dummy_init_code_phase, code_phase_step,
|
||||
total_samples, dummy_resampled_codes );
|
||||
|
||||
// Loop over the desired outputs:
|
||||
for( int i = 1; i < init_code_phase.size(); ++i )
|
||||
{
|
||||
// Copy the shifted 'early' code to the later codes:
|
||||
memcpy( resampled_codes[i], resampled_codes[0] + code_phase_offsets_samples[i],
|
||||
num_samples * sizeof( T ) );
|
||||
|
||||
// Upate the init_code_phase parameter to reflect the true code phases
|
||||
init_code_phase[i] = init_code_phase[0] + code_phase_offsets_samples[i]*code_phase_step;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// A code resampler to do the basic resampling on the earliest code phase
|
||||
boost::shared_ptr< CodeResamplerInterface<T> > d_core_resampler;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Code resampler that uses 64 bit fixed point arithmetic */
|
||||
|
||||
template< typename T, unsigned FRAC_LEN = 32 >
|
||||
class CodeResamplerFxpt64 : public CodeResamplerInterface<T>
|
||||
{
|
||||
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,
|
||||
int num_samples,
|
||||
std::vector< T * > resampled_codes )
|
||||
{
|
||||
int64_t code_phase_step_fxp = double_to_fxpt64( code_phase_step );
|
||||
|
||||
// Loop over the desired outputs:
|
||||
for( int i = 0; i < init_code_phase.size(); ++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 );
|
||||
|
||||
int j = 0;
|
||||
|
||||
while( j < num_samples )
|
||||
{
|
||||
|
||||
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
src/algorithms/libs/subcarrier_resampler.h
Normal file
366
src/algorithms/libs/subcarrier_resampler.h
Normal file
@@ -0,0 +1,366 @@
|
||||
/*!
|
||||
* \file subcarrier_resampler.h
|
||||
* \brief Class providing a number of subcarrier resampling options
|
||||
* \authors Cillian O'Driscoll 2015. cillian.odriscoll(at)gmail.com
|
||||
*
|
||||
* Class interface for subcarrier resampling.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef GNSS_SDR_SUBCARRIER_RESAMPLER_H_
|
||||
#define GNSS_SDR_SUBCARRIER_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 subcarrier resampler
|
||||
*
|
||||
*
|
||||
*/
|
||||
template< typename T >
|
||||
class SubcarrierResamplerInterface
|
||||
{
|
||||
public:
|
||||
|
||||
/*!
|
||||
* Actually perform the code resampling.
|
||||
*/
|
||||
virtual void resample_subcarrier( std::vector< double > &init_subcarrier_phase_cycles,
|
||||
double &subcarrier_phase_step,
|
||||
int num_samples,
|
||||
std::vector< T * > resampled_subcarriers,
|
||||
bool is_cosine_phased = false) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
static const std::vector< T > d_subcarrier_table;
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
const std::vector< T > SubcarrierResamplerInterface< T >::d_subcarrier_table =
|
||||
{ static_cast< T >( 1.0 ), static_cast<T >( -1.0 ) };
|
||||
|
||||
/*!
|
||||
* \brief Simple generic implementation of subcarrier resampling. Most accurate
|
||||
* and most expensive
|
||||
*/
|
||||
template< typename T >
|
||||
class SubcarrierResamplerGeneric : public SubcarrierResamplerInterface<T>
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* Resample the subcarrier computing the subcarrier phases exactly for each desired
|
||||
* output.
|
||||
*/
|
||||
virtual void resample_subcarrier( std::vector< double > &init_subcarrier_phase_cycles,
|
||||
double &subcarrier_phase_step,
|
||||
int num_samples,
|
||||
std::vector< T * > resampled_subcarriers,
|
||||
bool is_cosine_phased = false)
|
||||
{
|
||||
double subcarrier_phase_step_halfcycles = 2.0 * subcarrier_phase_step;
|
||||
|
||||
// Loop over the desired outputs:
|
||||
for( int i = 0; i < init_subcarrier_phase_cycles.size(); ++i )
|
||||
{
|
||||
double tsubcarrier_halfcycles = std::fmod( 2.0*init_subcarrier_phase_cycles[i], 2.0);
|
||||
if( tsubcarrier_halfcycles < 0.0 )
|
||||
{
|
||||
tsubcarrier_halfcycles += 2.0;
|
||||
}
|
||||
|
||||
if( is_cosine_phased )
|
||||
{
|
||||
tsubcarrier_halfcycles += 0.5; // add a 1/4 cycle for cosine phasing
|
||||
}
|
||||
|
||||
T *curr_sample = resampled_subcarriers[i];
|
||||
|
||||
int64_t int_phase;
|
||||
for( int j = 0; j < num_samples; ++j )
|
||||
{
|
||||
int_phase = static_cast< int64_t >( tsubcarrier_halfcycles );
|
||||
//*curr_sample = static_cast< T >( 1.0 - 2.0 *( int_phase & 0x01 ) );
|
||||
*curr_sample = this->d_subcarrier_table[ int_phase & 0x01 ];
|
||||
tsubcarrier_halfcycles += subcarrier_phase_step;
|
||||
++curr_sample;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Code resampler that forces the code spacing to the nearest integer
|
||||
* number of samples
|
||||
*/
|
||||
template< typename T >
|
||||
class SubcarrierResamplerIntegerSampleSpacing : public SubcarrierResamplerInterface<T>
|
||||
{
|
||||
public:
|
||||
|
||||
SubcarrierResamplerIntegerSampleSpacing( boost::shared_ptr< SubcarrierResamplerInterface<T> > core_resampler )
|
||||
: d_core_resampler( core_resampler )
|
||||
{};
|
||||
|
||||
/*!
|
||||
* Resample the subcarrier computing the subcarrier phases exactly for the latest output
|
||||
* and forcing all others to be integer shifts of the latest value*/
|
||||
virtual void resample_subcarrier( std::vector< double > &init_subcarrier_phase_cycles,
|
||||
double &subcarrier_phase_step,
|
||||
int num_samples,
|
||||
std::vector< T * > resampled_subcarriers,
|
||||
bool is_cosine_phased = false)
|
||||
{
|
||||
double earliest_subcarrier_phase = init_subcarrier_phase_cycles[0];
|
||||
std::vector< int > subcarrier_phase_offsets_samples( init_subcarrier_phase_cycles.size(), 0 );
|
||||
|
||||
for( int i = 1; i < init_subcarrier_phase_cycles.size(); ++i )
|
||||
{
|
||||
subcarrier_phase_offsets_samples[i] = round(
|
||||
( init_subcarrier_phase_cycles[i] - earliest_subcarrier_phase ) / subcarrier_phase_step
|
||||
);
|
||||
}
|
||||
|
||||
int total_samples = num_samples + subcarrier_phase_offsets_samples.back();
|
||||
|
||||
// Now we call the generic implementation for the earliest code phase
|
||||
// and copy for the later code phases:
|
||||
std::vector< T * > dummy_resampled_subcarriers(1, resampled_subcarriers[0] );
|
||||
std::vector< double > dummy_init_subcarrier_phase(1, init_subcarrier_phase_cycles[0] );
|
||||
|
||||
d_core_resampler->resample_subcarrier(
|
||||
dummy_init_subcarrier_phase, subcarrier_phase_step,
|
||||
total_samples, dummy_resampled_subcarriers, is_cosine_phased );
|
||||
|
||||
// Loop over the desired outputs:
|
||||
for( int i = 1; i < init_subcarrier_phase_cycles.size(); ++i )
|
||||
{
|
||||
// Copy the shifted 'early' code to the later codes:
|
||||
memcpy( resampled_subcarriers[i], resampled_subcarriers[0] +
|
||||
subcarrier_phase_offsets_samples[i],
|
||||
num_samples * sizeof( T ) );
|
||||
|
||||
// Upate the init_subcarrier_phase parameter to reflect the true code phases
|
||||
init_subcarrier_phase_cycles[i] = init_subcarrier_phase_cycles[0] +
|
||||
subcarrier_phase_offsets_samples[i]*subcarrier_phase_step;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// A code resampler to do the basic resampling on the earliest code phase
|
||||
boost::shared_ptr< SubcarrierResamplerInterface<T> > d_core_resampler;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Code resampler that uses 64 bit fixed point arithmetic */
|
||||
|
||||
template< typename T, unsigned FRAC_LEN = 32 >
|
||||
class SubcarrierResamplerFxpt64 : public SubcarrierResamplerInterface<T>
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* Resample the code using 64-bit fixed point arithmetic
|
||||
*/
|
||||
virtual void resample_subcarrier( std::vector< double > &init_subcarrier_phase_cycles,
|
||||
double &subcarrier_phase_step,
|
||||
int num_samples,
|
||||
std::vector< T * > resampled_subcarriers,
|
||||
bool is_cosine_phased = false)
|
||||
{
|
||||
int64_t subcarrier_phase_step_fxp = double_to_fxpt64( 2.0*subcarrier_phase_step );
|
||||
|
||||
// Loop over the desired outputs:
|
||||
for( int i = 0; i < init_subcarrier_phase_cycles.size(); ++i )
|
||||
{
|
||||
double tsubcarrier_halfcycles = std::fmod( 2.0*init_subcarrier_phase_cycles[i], 2 );
|
||||
if( tsubcarrier_halfcycles < 0.0 )
|
||||
{
|
||||
tsubcarrier_halfcycles += 2.0;
|
||||
}
|
||||
|
||||
if( is_cosine_phased )
|
||||
{
|
||||
tsubcarrier_halfcycles += 0.5;
|
||||
}
|
||||
|
||||
int64_t subcarrier_phase_fxp = double_to_fxpt64( tsubcarrier_halfcycles, FRAC_LEN );
|
||||
T *curr_sample = resampled_subcarriers[i];
|
||||
init_subcarrier_phase_cycles[i] = fxpt64_to_double( subcarrier_phase_fxp )/2.0;
|
||||
|
||||
|
||||
for( int j = 0 ; j < num_samples; ++j )
|
||||
{
|
||||
//*curr_sample = static_cast< T >( 1 - 2*( (subcarrier_phase_fxp>>FRAC_LEN) & 0x01 ) );
|
||||
*curr_sample = this->d_subcarrier_table[ ( subcarrier_phase_fxp >> FRAC_LEN ) & 0x01 ];
|
||||
subcarrier_phase_fxp += subcarrier_phase_step_fxp;
|
||||
++curr_sample;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
subcarrier_phase_step = fxpt64_to_double( subcarrier_phase_step_fxp ) / 2.0;
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Code resampler that uses a fixed number of replicas in memory*/
|
||||
template< typename T >
|
||||
class SubcarrierResamplerMemoryStore : public SubcarrierResamplerInterface<T>
|
||||
{
|
||||
public:
|
||||
SubcarrierResamplerMemoryStore(
|
||||
double nominal_subcarrier_phase_step,
|
||||
unsigned int maximum_num_samples,
|
||||
double subcarrier_spacing_cycles )
|
||||
: d_nominal_subcarrier_phase_step( nominal_subcarrier_phase_step ),
|
||||
d_subcarrier_spacing_cycles( subcarrier_spacing_cycles )
|
||||
{
|
||||
int num_replicas = static_cast< int >(
|
||||
std::ceil( 1.0 /
|
||||
d_subcarrier_spacing_cycles ) );
|
||||
|
||||
|
||||
// Resize the storage:
|
||||
d_subcarrier_phase_offsets.resize( num_replicas );
|
||||
d_replica_store.resize( num_replicas );
|
||||
|
||||
// Use a generic resampler to generate the local replica store:
|
||||
SubcarrierResamplerGeneric<T> baseResampler;
|
||||
|
||||
double curr_offset = 0.0;
|
||||
|
||||
for( int ii = 0; ii < num_replicas; ++ii )
|
||||
{
|
||||
d_subcarrier_phase_offsets[ii] = curr_offset;
|
||||
curr_offset += d_subcarrier_spacing_cycles;
|
||||
|
||||
d_replica_store[ii] = static_cast< T *>( volk_malloc(
|
||||
2*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_subcarrier(
|
||||
d_subcarrier_phase_offsets, d_nominal_subcarrier_phase_step, 2*maximum_num_samples,
|
||||
d_replica_store, false );
|
||||
|
||||
|
||||
};
|
||||
|
||||
~SubcarrierResamplerMemoryStore()
|
||||
{
|
||||
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_subcarrier( std::vector< double > &init_subcarrier_phase_cycles,
|
||||
double &subcarrier_phase_step,
|
||||
int num_samples,
|
||||
std::vector< T * > resampled_subcarriers,
|
||||
bool is_cosine_phased = false)
|
||||
{
|
||||
|
||||
// Loop over the desired outputs:
|
||||
for( int ii = 0; ii < init_subcarrier_phase_cycles.size(); ++ii )
|
||||
{
|
||||
int offset_ind = 0;
|
||||
double delta_offset = std::numeric_limits<double>::infinity();
|
||||
|
||||
double desired_subcarrier_phase = init_subcarrier_phase_cycles[ii];
|
||||
|
||||
if( is_cosine_phased )
|
||||
{
|
||||
desired_subcarrier_phase += 0.25;
|
||||
}
|
||||
|
||||
double desired_subcarrier_phase_mod_one_chip = std::fmod( desired_subcarrier_phase, 1.0 );
|
||||
|
||||
if( desired_subcarrier_phase_mod_one_chip < 0.0 )
|
||||
{
|
||||
desired_subcarrier_phase_mod_one_chip += 1.0;
|
||||
}
|
||||
|
||||
double achieved_subcarrier_phase = 0.0;
|
||||
|
||||
for( int jj = 0; jj < d_subcarrier_phase_offsets.size(); ++jj )
|
||||
{
|
||||
double abs_diff = std::abs( desired_subcarrier_phase_mod_one_chip - d_subcarrier_phase_offsets[jj] );
|
||||
if( abs_diff < delta_offset )
|
||||
{
|
||||
delta_offset = abs_diff;
|
||||
offset_ind = jj;
|
||||
achieved_subcarrier_phase = desired_subcarrier_phase - desired_subcarrier_phase_mod_one_chip
|
||||
+ d_subcarrier_phase_offsets[jj];
|
||||
}
|
||||
}
|
||||
|
||||
if( is_cosine_phased )
|
||||
{
|
||||
achieved_subcarrier_phase -= 0.25;
|
||||
}
|
||||
|
||||
init_subcarrier_phase_cycles[ii] = achieved_subcarrier_phase;
|
||||
|
||||
|
||||
memcpy( resampled_subcarriers[ii], d_replica_store[offset_ind],
|
||||
num_samples * sizeof( T ) );
|
||||
|
||||
}
|
||||
|
||||
subcarrier_phase_step = d_nominal_subcarrier_phase_step;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
double d_nominal_subcarrier_phase_step;
|
||||
|
||||
|
||||
double d_subcarrier_spacing_cycles;
|
||||
|
||||
std::vector< double > d_subcarrier_phase_offsets;
|
||||
|
||||
std::vector< T * > d_replica_store;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ include_directories(
|
||||
${CMAKE_SOURCE_DIR}/src/core/system_parameters
|
||||
${CMAKE_SOURCE_DIR}/src/core/interfaces
|
||||
${CMAKE_SOURCE_DIR}/src/core/receiver
|
||||
${CMAKE_SOURCE_DIR}/src/algorithms/libs
|
||||
${VOLK_INCLUDE_DIRS}
|
||||
${GLOG_INCLUDE_DIRS}
|
||||
${GFlags_INCLUDE_DIRS}
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#define LV_HAVE_SSE3
|
||||
#include "volk_cw_epl_corr.h"
|
||||
#endif
|
||||
#include "accumulate_array.h"
|
||||
|
||||
|
||||
unsigned long Correlator::next_power_2(unsigned long v)
|
||||
@@ -228,7 +229,6 @@ void Correlator::Carrier_rotate_and_VEPL_volk(int signal_length_samples,
|
||||
volk_free(bb_signal);
|
||||
}
|
||||
|
||||
|
||||
void Correlator::Carrier_rotate_and_DE_volk(int signal_length_samples,
|
||||
const gr_complex* input,
|
||||
gr_complex *phase_as_complex,
|
||||
@@ -295,3 +295,130 @@ void Correlator::Carrier_rotate_and_DPE_volk(int signal_length_samples,
|
||||
volk_free(subcarrier_wipeoff);
|
||||
volk_free(code_wipeoff);
|
||||
}
|
||||
|
||||
void Correlator::Carrier_rotate_and_EPL_codeless(int signal_length_samples,
|
||||
const gr_complex* input,
|
||||
gr_complex *phase_as_complex,
|
||||
gr_complex phase_inc_as_complex,
|
||||
const int *E_code_phases,
|
||||
const int *P_code_phases,
|
||||
const int *L_code_phases,
|
||||
gr_complex* E_out,
|
||||
gr_complex* P_out,
|
||||
gr_complex* L_out,
|
||||
int code_length )
|
||||
{
|
||||
|
||||
gr_complex* bb_signal = static_cast<gr_complex*>(volk_malloc(signal_length_samples * sizeof(gr_complex), volk_get_alignment()));
|
||||
|
||||
|
||||
gr_complex* accum_early = static_cast<gr_complex*>(volk_malloc(code_length* sizeof(gr_complex), volk_get_alignment()));
|
||||
std::fill( accum_early, accum_early+code_length, 0.0 );
|
||||
|
||||
gr_complex* accum_prompt = static_cast<gr_complex*>(volk_malloc(code_length* sizeof(gr_complex), volk_get_alignment()));
|
||||
std::fill( accum_prompt, accum_prompt+code_length, 0.0 );
|
||||
|
||||
gr_complex* accum_late = static_cast<gr_complex*>(volk_malloc(code_length* sizeof(gr_complex), volk_get_alignment()));
|
||||
std::fill( accum_late, accum_late+code_length, 0.0 );
|
||||
|
||||
volk_32fc_s32fc_x2_rotator_32fc(bb_signal, input, phase_inc_as_complex, phase_as_complex, signal_length_samples);
|
||||
|
||||
// Now we do an accumulation of the input by code phase bins:
|
||||
accumulate_array< gr_complex >( bb_signal, E_code_phases, accum_early, signal_length_samples );
|
||||
accumulate_array< gr_complex >( bb_signal, P_code_phases, accum_prompt, signal_length_samples );
|
||||
accumulate_array< gr_complex >( bb_signal, L_code_phases, accum_late, signal_length_samples );
|
||||
|
||||
// Now sum the squares of the partial sums: this is implemented as a simple
|
||||
// dot product
|
||||
volk_32fc_x2_dot_prod_32fc(E_out, accum_early, accum_early, code_length);
|
||||
volk_32fc_x2_dot_prod_32fc(P_out, accum_prompt, accum_prompt, code_length);
|
||||
volk_32fc_x2_dot_prod_32fc(L_out, accum_late, accum_late, code_length);
|
||||
|
||||
volk_free(bb_signal);
|
||||
volk_free(accum_early);
|
||||
volk_free(accum_prompt);
|
||||
volk_free(accum_late);
|
||||
}
|
||||
|
||||
void Correlator::Carrier_rotate_and_VEPL_codeless(int signal_length_samples,
|
||||
const gr_complex* input,
|
||||
gr_complex *phase_as_complex,
|
||||
gr_complex phase_inc_as_complex,
|
||||
const int *VE_code_phases,
|
||||
const int *E_code_phases,
|
||||
const int *P_code_phases,
|
||||
const int *L_code_phases,
|
||||
const int *VL_code_phases,
|
||||
const gr_complex *VE_subcarrier,
|
||||
const gr_complex *E_subcarrier,
|
||||
const gr_complex *P_subcarrier,
|
||||
const gr_complex *L_subcarrier,
|
||||
const gr_complex *VL_subcarrier,
|
||||
gr_complex* VE_out,
|
||||
gr_complex* E_out,
|
||||
gr_complex* P_out,
|
||||
gr_complex* L_out,
|
||||
gr_complex* VL_out,
|
||||
int code_length)
|
||||
{
|
||||
|
||||
gr_complex* bb_signal = static_cast<gr_complex*>(volk_malloc(signal_length_samples * sizeof(gr_complex), volk_get_alignment()));
|
||||
gr_complex* ve_subcarrier_wipeoff = static_cast<gr_complex*>(volk_malloc(signal_length_samples * sizeof(gr_complex), volk_get_alignment()));
|
||||
gr_complex* e_subcarrier_wipeoff = static_cast<gr_complex*>(volk_malloc(signal_length_samples * sizeof(gr_complex), volk_get_alignment()));
|
||||
gr_complex* p_subcarrier_wipeoff = static_cast<gr_complex*>(volk_malloc(signal_length_samples * sizeof(gr_complex), volk_get_alignment()));
|
||||
gr_complex* l_subcarrier_wipeoff = static_cast<gr_complex*>(volk_malloc(signal_length_samples * sizeof(gr_complex), volk_get_alignment()));
|
||||
gr_complex* vl_subcarrier_wipeoff = static_cast<gr_complex*>(volk_malloc(signal_length_samples * sizeof(gr_complex), volk_get_alignment()));
|
||||
|
||||
gr_complex* accum_very_early = static_cast<gr_complex*>(volk_malloc(code_length* sizeof(gr_complex), volk_get_alignment()));
|
||||
std::fill( accum_very_early, accum_very_early+code_length, 0.0 );
|
||||
|
||||
gr_complex* accum_early = static_cast<gr_complex*>(volk_malloc(code_length* sizeof(gr_complex), volk_get_alignment()));
|
||||
std::fill( accum_early, accum_early+code_length, 0.0 );
|
||||
|
||||
gr_complex* accum_prompt = static_cast<gr_complex*>(volk_malloc(code_length* sizeof(gr_complex), volk_get_alignment()));
|
||||
std::fill( accum_prompt, accum_prompt+code_length, 0.0 );
|
||||
|
||||
gr_complex* accum_late = static_cast<gr_complex*>(volk_malloc(code_length* sizeof(gr_complex), volk_get_alignment()));
|
||||
std::fill( accum_late, accum_late+code_length, 0.0 );
|
||||
|
||||
gr_complex* accum_very_late = static_cast<gr_complex*>(volk_malloc(code_length* sizeof(gr_complex), volk_get_alignment()));
|
||||
std::fill( accum_very_late, accum_very_late+code_length, 0.0 );
|
||||
|
||||
// 1) Carrier wipe-off
|
||||
volk_32fc_s32fc_x2_rotator_32fc(bb_signal, input, phase_inc_as_complex, phase_as_complex, signal_length_samples);
|
||||
|
||||
// 2) Subcarrier wipe-off
|
||||
volk_32fc_x2_multiply_32fc( ve_subcarrier_wipeoff, bb_signal, VE_subcarrier, signal_length_samples );
|
||||
volk_32fc_x2_multiply_32fc( e_subcarrier_wipeoff, bb_signal, E_subcarrier, signal_length_samples );
|
||||
volk_32fc_x2_multiply_32fc( p_subcarrier_wipeoff, bb_signal, P_subcarrier, signal_length_samples );
|
||||
volk_32fc_x2_multiply_32fc( l_subcarrier_wipeoff, bb_signal, L_subcarrier, signal_length_samples );
|
||||
volk_32fc_x2_multiply_32fc( vl_subcarrier_wipeoff, bb_signal, VL_subcarrier, signal_length_samples );
|
||||
|
||||
// 3) Do an accumulation of the input by code phase bins:
|
||||
accumulate_array< gr_complex >( ve_subcarrier_wipeoff, VE_code_phases, accum_very_early, signal_length_samples );
|
||||
accumulate_array< gr_complex >( e_subcarrier_wipeoff, E_code_phases, accum_early, signal_length_samples );
|
||||
accumulate_array< gr_complex >( p_subcarrier_wipeoff, P_code_phases, accum_prompt, signal_length_samples );
|
||||
accumulate_array< gr_complex >( l_subcarrier_wipeoff, L_code_phases, accum_late, signal_length_samples );
|
||||
accumulate_array< gr_complex >( vl_subcarrier_wipeoff, VL_code_phases, accum_very_late, signal_length_samples );
|
||||
|
||||
// 4) Now sum the squares of the partial sums: this is implemented as a simple
|
||||
// dot product
|
||||
volk_32fc_x2_dot_prod_32fc(VE_out, accum_very_early, accum_very_early, code_length);
|
||||
volk_32fc_x2_dot_prod_32fc(E_out, accum_early, accum_early, code_length);
|
||||
volk_32fc_x2_dot_prod_32fc(P_out, accum_prompt, accum_prompt, code_length);
|
||||
volk_32fc_x2_dot_prod_32fc(L_out, accum_late, accum_late, code_length);
|
||||
volk_32fc_x2_dot_prod_32fc(VL_out, accum_very_late, accum_very_late, code_length);
|
||||
|
||||
volk_free(bb_signal);
|
||||
volk_free(ve_subcarrier_wipeoff);
|
||||
volk_free(e_subcarrier_wipeoff);
|
||||
volk_free(p_subcarrier_wipeoff);
|
||||
volk_free(l_subcarrier_wipeoff);
|
||||
volk_free(vl_subcarrier_wipeoff);
|
||||
volk_free(accum_very_early);
|
||||
volk_free(accum_early);
|
||||
volk_free(accum_prompt);
|
||||
volk_free(accum_late);
|
||||
volk_free(accum_very_late);
|
||||
|
||||
}
|
||||
|
||||
@@ -134,6 +134,39 @@ public:
|
||||
gr_complex* P_subcarrier_L_code_out,
|
||||
gr_complex* P_code_PQ_subcarrier_out );
|
||||
|
||||
void Carrier_rotate_and_EPL_codeless(int signal_length_samples,
|
||||
const gr_complex* input,
|
||||
gr_complex *phase_as_complex,
|
||||
gr_complex phase_inc_as_complex,
|
||||
const int *E_code_phases,
|
||||
const int *P_code_phases,
|
||||
const int *L_code_phases,
|
||||
gr_complex* E_out,
|
||||
gr_complex* P_out,
|
||||
gr_complex* L_out,
|
||||
int code_length);
|
||||
|
||||
void Carrier_rotate_and_VEPL_codeless(int signal_length_samples,
|
||||
const gr_complex* input,
|
||||
gr_complex *phase_as_complex,
|
||||
gr_complex phase_inc_as_complex,
|
||||
const int *VE_code_phases,
|
||||
const int *E_code_phases,
|
||||
const int *P_code_phases,
|
||||
const int *L_code_phases,
|
||||
const int *VL_code_phases,
|
||||
const gr_complex *VE_subcarrier,
|
||||
const gr_complex *E_subcarrier,
|
||||
const gr_complex *P_subcarrier,
|
||||
const gr_complex *L_subcarrier,
|
||||
const gr_complex *VL_subcarrier,
|
||||
gr_complex* VE_out,
|
||||
gr_complex* E_out,
|
||||
gr_complex* P_out,
|
||||
gr_complex* L_out,
|
||||
gr_complex* VL_out,
|
||||
int code_length);
|
||||
|
||||
private:
|
||||
unsigned long next_power_2(unsigned long v);
|
||||
};
|
||||
|
||||
@@ -368,6 +368,42 @@ 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
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/arithmetic/subcarrier_resampler_test.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/arithmetic/accumulate_array_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)
|
||||
|
||||
|
||||
129
src/tests/arithmetic/accumulate_array_test.cc
Normal file
129
src/tests/arithmetic/accumulate_array_test.cc
Normal file
@@ -0,0 +1,129 @@
|
||||
/*!
|
||||
* \file accumulate_array_test.cc
|
||||
* \brief This file implements tests for accumulate_array
|
||||
* \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 "accumulate_array.h"
|
||||
#include "code_resampler.h"
|
||||
#include <complex>
|
||||
#include <ctime>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <armadillo>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
typedef std::vector< float > real_vec;
|
||||
typedef std::vector< std::complex< float > > cplx_vec;
|
||||
|
||||
TEST(AccumulateArrayTest, FunctionalTest )
|
||||
{
|
||||
|
||||
|
||||
real_vec input_vec( 13 );
|
||||
std::iota( input_vec.begin(), input_vec.end(), 0 );
|
||||
|
||||
std::vector< int > index_vec = { 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3, 3 };
|
||||
|
||||
real_vec output_vec( 5, 0.0 );
|
||||
|
||||
accumulate_array( &input_vec[0], &index_vec[0], &output_vec[0], 13 );
|
||||
|
||||
real_vec expected_output = { 3, 18, 15, 42, 0 };
|
||||
|
||||
for( unsigned int ii = 0; ii < expected_output.size(); ++ii )
|
||||
{
|
||||
ASSERT_FLOAT_EQ( output_vec[ii], expected_output[ii] );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
TEST(AccumulateArrayTest, ComplexTest )
|
||||
{
|
||||
|
||||
double fs = 6e6;
|
||||
double fc = 1.023e6;
|
||||
double T = 0.001;
|
||||
|
||||
double code_phase_step = fc/fs;
|
||||
|
||||
int _num_samples = static_cast< int >(
|
||||
std::ceil( T * fs )
|
||||
);
|
||||
|
||||
cplx_vec output_vec( 1023, 0.0 );
|
||||
|
||||
std::vector< int > code_phases( 1023 );
|
||||
std::iota( code_phases.begin(), code_phases.end(), 0 );
|
||||
|
||||
CodeResamplerGeneric< int > the_resampler;
|
||||
|
||||
std::vector< int > index_vec( _num_samples );
|
||||
|
||||
|
||||
|
||||
std::vector< int* > _resampled_code_phases;
|
||||
_resampled_code_phases.resize(1);
|
||||
_resampled_code_phases[0] = &index_vec[0];
|
||||
|
||||
std::vector< double > _desired_code_phases;
|
||||
_desired_code_phases.resize(1);
|
||||
|
||||
_desired_code_phases[0] = 0;
|
||||
|
||||
the_resampler.resample_code( &code_phases[0], 1023, _desired_code_phases,
|
||||
code_phase_step, _num_samples, _resampled_code_phases );
|
||||
|
||||
|
||||
int iterations = 1000;
|
||||
|
||||
arma::cx_mat rv = arma::randn< arma::cx_mat >( _num_samples, iterations );
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
long long int begin = tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
|
||||
|
||||
for(int i = 0; i < iterations; i++)
|
||||
{
|
||||
|
||||
cplx_vec input_vec = arma::conv_to< cplx_vec >::from( rv.col( i ) );
|
||||
|
||||
accumulate_array( &input_vec[0], &index_vec[0], &output_vec[0], _num_samples );
|
||||
|
||||
}
|
||||
gettimeofday(&tv, NULL);
|
||||
long long int end = tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
ASSERT_LE(0, end - begin);
|
||||
std::cout << "Accumulate_array completed in " << (end - begin) << " microseconds" << std::endl;
|
||||
|
||||
|
||||
}
|
||||
|
||||
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 );
|
||||
|
||||
}
|
||||
|
||||
356
src/tests/arithmetic/subcarrier_resampler_test.cc
Normal file
356
src/tests/arithmetic/subcarrier_resampler_test.cc
Normal file
@@ -0,0 +1,356 @@
|
||||
/*!
|
||||
* \file subcarrier_resampler_test.cc
|
||||
* \brief This file implements tests for resampling subcarriers
|
||||
* \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 "subcarrier_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_subcarrier_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_subcarrier_replicas( std::vector< std::complex< float > * > &replicas )
|
||||
{
|
||||
for( int i = 0; i < replicas.size(); ++i )
|
||||
{
|
||||
volk_free( replicas[i] );
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SubcarrierResamplerTest, SubcarrierResamplerGeneric )
|
||||
{
|
||||
unsigned int _num_replicas = 3;
|
||||
|
||||
double fs = 12e6;
|
||||
double fsub = 6*1.023e6;
|
||||
|
||||
double subcarrier_phase_step = fsub/fs;
|
||||
double subcarrier_spacing_cycles = 0.125;
|
||||
|
||||
double T = 0.001;
|
||||
|
||||
int _num_samples = static_cast< int >(
|
||||
std::ceil( T * fs )
|
||||
);
|
||||
|
||||
std::vector< std::complex<float>* > _resampled_subcarriers;
|
||||
_resampled_subcarriers.resize(_num_replicas);
|
||||
std::vector< double > _desired_subcarrier_phases;
|
||||
_desired_subcarrier_phases.resize(_num_replicas);
|
||||
|
||||
allocate_subcarrier_replicas( _resampled_subcarriers, _num_samples );
|
||||
|
||||
SubcarrierResamplerGeneric< 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_subcarrier_phase = static_cast< double >( i ) - subcarrier_spacing_cycles;
|
||||
for( int j = 0; j < _num_replicas; ++j )
|
||||
{
|
||||
_desired_subcarrier_phases[j] = current_subcarrier_phase;
|
||||
current_subcarrier_phase += subcarrier_spacing_cycles;
|
||||
}
|
||||
|
||||
the_resampler.resample_subcarrier( _desired_subcarrier_phases,
|
||||
subcarrier_phase_step, _num_samples, _resampled_subcarriers,
|
||||
i % 2 == 1 );
|
||||
|
||||
|
||||
}
|
||||
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_subcarrier_replicas( _resampled_subcarriers );
|
||||
|
||||
}
|
||||
|
||||
TEST(SubcarrierResamplerTest, SubcarrierResamplerIntegerSampleSpacing )
|
||||
{
|
||||
std::complex<float>* _orig_subcarrier = 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 subcarrier_phase_step = fc/fs;
|
||||
double subcarrier_spacing_cycles = 0.5;
|
||||
|
||||
double T = 0.001;
|
||||
|
||||
int _num_samples = static_cast< int >(
|
||||
std::ceil( T * fs )
|
||||
);
|
||||
|
||||
std::vector< std::complex<float>* > _resampled_subcarriers;
|
||||
_resampled_subcarriers.resize(_num_replicas);
|
||||
std::vector< double > _desired_subcarrier_phases;
|
||||
_desired_subcarrier_phases.resize(_num_replicas);
|
||||
|
||||
allocate_subcarrier_replicas( _resampled_subcarriers, _num_samples );
|
||||
|
||||
SubcarrierResamplerIntegerSampleSpacing< std::complex< float > > the_resampler(
|
||||
boost::shared_ptr< SubcarrierResamplerInterface< std::complex<float> > >(
|
||||
new SubcarrierResamplerGeneric< 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_subcarrier_phase = static_cast< double >( i ) - subcarrier_spacing_cycles;
|
||||
for( int j = 0; j < _num_replicas; ++j )
|
||||
{
|
||||
_desired_subcarrier_phases[j] = current_subcarrier_phase;
|
||||
current_subcarrier_phase += subcarrier_spacing_cycles;
|
||||
}
|
||||
|
||||
the_resampler.resample_subcarrier( _desired_subcarrier_phases,
|
||||
subcarrier_phase_step, _num_samples, _resampled_subcarriers,
|
||||
i % 2 == 1 );
|
||||
|
||||
|
||||
}
|
||||
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_subcarrier_replicas( _resampled_subcarriers );
|
||||
|
||||
}
|
||||
|
||||
TEST(SubcarrierResamplerTest, SubcarrierResamplerFxpt64 )
|
||||
{
|
||||
std::complex<float>* _orig_subcarrier = 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 subcarrier_phase_step = fc/fs;
|
||||
double subcarrier_spacing_cycles = 0.5;
|
||||
|
||||
double T = 0.001;
|
||||
|
||||
int _num_samples = static_cast< int >(
|
||||
std::ceil( T * fs )
|
||||
);
|
||||
|
||||
std::vector< std::complex<float>* > _resampled_subcarriers;
|
||||
_resampled_subcarriers.resize(_num_replicas);
|
||||
std::vector< double > _desired_subcarrier_phases;
|
||||
_desired_subcarrier_phases.resize(_num_replicas);
|
||||
|
||||
allocate_subcarrier_replicas( _resampled_subcarriers, _num_samples );
|
||||
|
||||
SubcarrierResamplerFxpt64< 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_subcarrier_phase = static_cast< double >( i ) - subcarrier_spacing_cycles;
|
||||
for( int j = 0; j < _num_replicas; ++j )
|
||||
{
|
||||
_desired_subcarrier_phases[j] = current_subcarrier_phase;
|
||||
current_subcarrier_phase += subcarrier_spacing_cycles;
|
||||
}
|
||||
|
||||
the_resampler.resample_subcarrier( _desired_subcarrier_phases,
|
||||
subcarrier_phase_step, _num_samples, _resampled_subcarriers,
|
||||
i % 2 == 1 );
|
||||
|
||||
|
||||
}
|
||||
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_subcarrier_replicas( _resampled_subcarriers );
|
||||
|
||||
}
|
||||
|
||||
TEST(SubcarrierResamplerTest, SubcarrierResamplerIntegerSampleSpacingFxpt64 )
|
||||
{
|
||||
std::complex<float>* _orig_subcarrier = 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 subcarrier_phase_step = fc/fs;
|
||||
double subcarrier_spacing_cycles = 0.5;
|
||||
|
||||
double T = 0.001;
|
||||
|
||||
int _num_samples = static_cast< int >(
|
||||
std::ceil( T * fs )
|
||||
);
|
||||
|
||||
std::vector< std::complex<float>* > _resampled_subcarriers;
|
||||
_resampled_subcarriers.resize(_num_replicas);
|
||||
std::vector< double > _desired_subcarrier_phases;
|
||||
_desired_subcarrier_phases.resize(_num_replicas);
|
||||
|
||||
allocate_subcarrier_replicas( _resampled_subcarriers, _num_samples );
|
||||
|
||||
SubcarrierResamplerIntegerSampleSpacing< std::complex< float > > the_resampler(
|
||||
boost::shared_ptr< SubcarrierResamplerInterface< std::complex<float> > >(
|
||||
new SubcarrierResamplerFxpt64< 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_subcarrier_phase = static_cast< double >( i ) - subcarrier_spacing_cycles;
|
||||
for( int j = 0; j < _num_replicas; ++j )
|
||||
{
|
||||
_desired_subcarrier_phases[j] = current_subcarrier_phase;
|
||||
current_subcarrier_phase += subcarrier_spacing_cycles;
|
||||
}
|
||||
|
||||
the_resampler.resample_subcarrier( _desired_subcarrier_phases,
|
||||
subcarrier_phase_step, _num_samples, _resampled_subcarriers,
|
||||
i % 2 == 1 );
|
||||
|
||||
|
||||
}
|
||||
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_subcarrier_replicas( _resampled_subcarriers );
|
||||
|
||||
}
|
||||
|
||||
TEST(SubcarrierResamplerTest, SubcarrierResamplerMemoryStore )
|
||||
{
|
||||
std::complex<float>* _orig_subcarrier = 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 subcarrier_phase_step = fc/fs;
|
||||
double subcarrier_spacing_cycles = 0.5;
|
||||
|
||||
double T = 0.001;
|
||||
|
||||
int _num_samples = static_cast< int >(
|
||||
std::ceil( T * fs )
|
||||
);
|
||||
|
||||
std::vector< std::complex<float>* > _resampled_subcarriers;
|
||||
_resampled_subcarriers.resize(_num_replicas);
|
||||
std::vector< double > _desired_subcarrier_phases;
|
||||
_desired_subcarrier_phases.resize(_num_replicas);
|
||||
|
||||
allocate_subcarrier_replicas( _resampled_subcarriers, _num_samples );
|
||||
|
||||
SubcarrierResamplerMemoryStore< std::complex< float > > the_resampler(
|
||||
subcarrier_phase_step, _num_samples, 0.1 );
|
||||
|
||||
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_subcarrier_phase = static_cast< double >( i ) - subcarrier_spacing_cycles;
|
||||
for( int j = 0; j < _num_replicas; ++j )
|
||||
{
|
||||
_desired_subcarrier_phases[j] = current_subcarrier_phase;
|
||||
current_subcarrier_phase += subcarrier_spacing_cycles;
|
||||
}
|
||||
|
||||
the_resampler.resample_subcarrier( _desired_subcarrier_phases,
|
||||
subcarrier_phase_step, _num_samples, _resampled_subcarriers,
|
||||
i % 2 == 1 );
|
||||
|
||||
|
||||
}
|
||||
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_subcarrier_replicas( _resampled_subcarriers );
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user