mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2025-01-15 03:35:46 +00:00
Patch submitted by Marc Molina: Improving PCPS Acquisition with some VOLK instructions. Enabling the secondary spreading code in Galileo acquisition. Adding Signal Generator to GNSS-SDR.
git-svn-id: https://svn.code.sf.net/p/gnss-sdr/code/trunk@397 64b25241-fba3-4117-9849-534c7e92360d
This commit is contained in:
parent
5e6e66e60b
commit
8b10549fee
@ -25,6 +25,7 @@ add_subdirectory(observables)
|
||||
add_subdirectory(telemetry_decoder)
|
||||
add_subdirectory(output_filter)
|
||||
add_subdirectory(resampler)
|
||||
add_subdirectory(signal_generator)
|
||||
add_subdirectory(signal_source)
|
||||
add_subdirectory(input_filter)
|
||||
add_subdirectory(tracking)
|
||||
|
@ -71,17 +71,20 @@ GalileoE1PcpsAmbiguousAcquisition::GalileoE1PcpsAmbiguousAcquisition(
|
||||
fs_in_
|
||||
/ (Galileo_E1_CODE_CHIP_RATE_HZ
|
||||
/ Galileo_E1_B_CODE_LENGTH_CHIPS));
|
||||
|
||||
int samples_per_ms = vector_length_ / 4;
|
||||
|
||||
code_ = new gr_complex[vector_length_];
|
||||
vector_length_ = samples_per_ms * 4;
|
||||
|
||||
code_ = new gr_complex[samples_per_ms*sampled_ms_];
|
||||
|
||||
if (item_type_.compare("gr_complex") == 0)
|
||||
{
|
||||
item_size_ = sizeof(gr_complex);
|
||||
acquisition_cc_ = pcps_make_acquisition_cc(sampled_ms_,
|
||||
shift_resolution_, if_, fs_in_, samples_per_ms, queue_,
|
||||
dump_, dump_filename_);
|
||||
stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, vector_length_);
|
||||
shift_resolution_, if_, fs_in_, samples_per_ms, vector_length_,
|
||||
queue_, dump_, dump_filename_);
|
||||
stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, samples_per_ms * sampled_ms_);
|
||||
DLOG(INFO) << "stream_to_vector("
|
||||
<< stream_to_vector_->unique_id() << ")";
|
||||
DLOG(INFO) << "acquisition(" << acquisition_cc_->unique_id()
|
||||
@ -115,6 +118,7 @@ GalileoE1PcpsAmbiguousAcquisition::set_channel(unsigned int channel)
|
||||
void
|
||||
GalileoE1PcpsAmbiguousAcquisition::set_threshold(float threshold)
|
||||
{
|
||||
|
||||
float pfa = configuration_->property(role_+ boost::lexical_cast<std::string>(channel_) + ".pfa", 0.0);
|
||||
|
||||
if(pfa==0.0) pfa = configuration_->property(role_+".pfa", 0.0);
|
||||
@ -124,7 +128,7 @@ GalileoE1PcpsAmbiguousAcquisition::set_threshold(float threshold)
|
||||
threshold_ = threshold;
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
threshold_ = calculate_threshold(pfa);
|
||||
}
|
||||
|
||||
@ -202,16 +206,32 @@ GalileoE1PcpsAmbiguousAcquisition::mag()
|
||||
|
||||
void
|
||||
GalileoE1PcpsAmbiguousAcquisition::init()
|
||||
{
|
||||
acquisition_cc_->init();
|
||||
set_local_code();
|
||||
}
|
||||
|
||||
void
|
||||
GalileoE1PcpsAmbiguousAcquisition::set_local_code()
|
||||
{
|
||||
if (item_type_.compare("gr_complex") == 0)
|
||||
{
|
||||
bool cboc = configuration_->property(
|
||||
"Acquisition" + boost::lexical_cast<std::string>(channel_)
|
||||
+ ".cboc", false);
|
||||
galileo_e1_code_gen_complex_sampled(code_, gnss_synchro_->Signal,
|
||||
cboc, gnss_synchro_->PRN, fs_in_, 0);
|
||||
|
||||
std::complex<float> * code = new std::complex<float>[vector_length_];
|
||||
|
||||
galileo_e1_code_gen_complex_sampled(code, gnss_synchro_->Signal,
|
||||
cboc, gnss_synchro_->PRN, fs_in_, 0, false);
|
||||
|
||||
for (unsigned int i = 0; i < sampled_ms_/4; i++)
|
||||
{
|
||||
memcpy(&(code_[i*vector_length_]), code,
|
||||
sizeof(gr_complex)*vector_length_);
|
||||
}
|
||||
|
||||
acquisition_cc_->set_local_code(code_);
|
||||
acquisition_cc_->init();
|
||||
}
|
||||
}
|
||||
|
||||
@ -227,8 +247,6 @@ GalileoE1PcpsAmbiguousAcquisition::reset()
|
||||
|
||||
float GalileoE1PcpsAmbiguousAcquisition::calculate_threshold(float pfa)
|
||||
{
|
||||
//Calculate the threshold
|
||||
|
||||
unsigned int frequency_bins = 0;
|
||||
for (int doppler = (int)(-doppler_max_); doppler <= (int)doppler_max_; doppler += doppler_step_)
|
||||
{
|
||||
|
@ -113,6 +113,12 @@ public:
|
||||
*/
|
||||
void init();
|
||||
|
||||
/*!
|
||||
* \brief Sets local code for Galileo E1 PCPS acquisition algorithm.
|
||||
*/
|
||||
|
||||
void set_local_code();
|
||||
|
||||
/*!
|
||||
* \brief Returns the maximum peak of grid search
|
||||
*/
|
||||
|
@ -65,7 +65,7 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition(
|
||||
fs_in_ = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000);
|
||||
if_ = configuration_->property(role + ".ifreq", 0);
|
||||
dump_ = configuration_->property(role + ".dump", false);
|
||||
shift_resolution_ = configuration_->property(role + ".doppler_max", 15);
|
||||
shift_resolution_ = configuration_->property(role + ".doppler_max", 10000);
|
||||
sampled_ms_ = configuration_->property(role + ".sampled_ms", 1);
|
||||
dump_filename_ = configuration_->property(role + ".dump_filename",
|
||||
default_dump_filename);
|
||||
@ -74,16 +74,16 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition(
|
||||
vector_length_ = round(fs_in_
|
||||
/ (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS));
|
||||
|
||||
code_= new gr_complex[vector_length_];
|
||||
code_= new gr_complex[vector_length_ * sampled_ms_];
|
||||
|
||||
if (item_type_.compare("gr_complex") == 0)
|
||||
{
|
||||
item_size_ = sizeof(gr_complex);
|
||||
acquisition_cc_ = pcps_make_acquisition_cc(sampled_ms_,
|
||||
shift_resolution_, if_, fs_in_, vector_length_, queue_,
|
||||
shift_resolution_, if_, fs_in_, vector_length_, vector_length_, queue_,
|
||||
dump_, dump_filename_);
|
||||
|
||||
stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, vector_length_);
|
||||
stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, vector_length_*sampled_ms_);
|
||||
|
||||
DLOG(INFO) << "stream_to_vector(" << stream_to_vector_->unique_id()
|
||||
<< ")";
|
||||
@ -123,13 +123,13 @@ void GpsL1CaPcpsAcquisition::set_threshold(float threshold)
|
||||
pfa = configuration_->property(role_+".pfa", 0.0);
|
||||
}
|
||||
if(pfa==0.0)
|
||||
{
|
||||
threshold_ = threshold;
|
||||
}
|
||||
{
|
||||
threshold_ = threshold;
|
||||
}
|
||||
else
|
||||
{
|
||||
threshold_ = calculate_threshold(pfa);
|
||||
}
|
||||
{
|
||||
threshold_ = calculate_threshold(pfa);
|
||||
}
|
||||
|
||||
DLOG(INFO) <<"Channel "<<channel_<<" Threshold = " << threshold_;
|
||||
|
||||
@ -195,15 +195,29 @@ signed int GpsL1CaPcpsAcquisition::mag()
|
||||
}
|
||||
|
||||
|
||||
void GpsL1CaPcpsAcquisition::init(){
|
||||
if (item_type_.compare("gr_complex") == 0)
|
||||
{
|
||||
gps_l1_ca_code_gen_complex_sampled(code_, gnss_synchro_->PRN, fs_in_, 0);
|
||||
acquisition_cc_->set_local_code(code_);
|
||||
acquisition_cc_->init();
|
||||
}
|
||||
void GpsL1CaPcpsAcquisition::init()
|
||||
{
|
||||
acquisition_cc_->init();
|
||||
set_local_code();
|
||||
}
|
||||
|
||||
void GpsL1CaPcpsAcquisition::set_local_code()
|
||||
{
|
||||
if (item_type_.compare("gr_complex") == 0)
|
||||
{
|
||||
std::complex<float>* code = new std::complex<float>[vector_length_];
|
||||
|
||||
gps_l1_ca_code_gen_complex_sampled(code, gnss_synchro_->PRN, fs_in_, 0);
|
||||
|
||||
for (unsigned int i = 0; i < sampled_ms_; i++)
|
||||
{
|
||||
memcpy(&(code_[i*vector_length_]), code,
|
||||
sizeof(gr_complex)*vector_length_);
|
||||
}
|
||||
|
||||
acquisition_cc_->set_local_code(code_);
|
||||
}
|
||||
}
|
||||
|
||||
void GpsL1CaPcpsAcquisition::reset()
|
||||
{
|
||||
@ -238,9 +252,9 @@ float GpsL1CaPcpsAcquisition::calculate_threshold(float pfa)
|
||||
void GpsL1CaPcpsAcquisition::connect(gr::top_block_sptr top_block)
|
||||
{
|
||||
if (item_type_.compare("gr_complex") == 0)
|
||||
{
|
||||
top_block->connect(stream_to_vector_, 0, acquisition_cc_, 0);
|
||||
}
|
||||
{
|
||||
top_block->connect(stream_to_vector_, 0, acquisition_cc_, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
* \authors <ul>
|
||||
* <li> Javier Arribas, 2011. jarribas(at)cttc.es
|
||||
* <li> Luis Esteve, 2012. luis(at)epsilon-formacion.com
|
||||
* </ul> *
|
||||
* </ul>
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
@ -116,6 +116,12 @@ public:
|
||||
*/
|
||||
void init();
|
||||
|
||||
/*!
|
||||
* \brief Sets local code for GPS L1/CA PCPS acquisition algorithm.
|
||||
*/
|
||||
|
||||
void set_local_code();
|
||||
|
||||
/*!
|
||||
* \brief Returns the maximum peak of grid search
|
||||
*/
|
||||
|
@ -146,10 +146,17 @@ signed int GpsL1CaPcpsAcquisitionFineDoppler::mag()
|
||||
}
|
||||
|
||||
|
||||
void GpsL1CaPcpsAcquisitionFineDoppler::init(){
|
||||
gps_l1_ca_code_gen_complex_sampled(code_, gnss_synchro_->PRN, fs_in_, 0);
|
||||
acquisition_cc_->set_local_code(code_);
|
||||
acquisition_cc_->init();
|
||||
void GpsL1CaPcpsAcquisitionFineDoppler::init()
|
||||
{
|
||||
acquisition_cc_->init();
|
||||
set_local_code();
|
||||
}
|
||||
|
||||
|
||||
void GpsL1CaPcpsAcquisitionFineDoppler::set_local_code()
|
||||
{
|
||||
gps_l1_ca_code_gen_complex_sampled(code_, gnss_synchro_->PRN, fs_in_, 0);
|
||||
acquisition_cc_->set_local_code(code_);
|
||||
}
|
||||
|
||||
|
||||
|
@ -115,6 +115,8 @@ public:
|
||||
*/
|
||||
void init();
|
||||
|
||||
void set_local_code();
|
||||
|
||||
/*!
|
||||
* \brief Returns the maximum peak of grid search
|
||||
*/
|
||||
|
@ -145,12 +145,17 @@ signed int GpsL1CaPcpsAssistedAcquisition::mag()
|
||||
}
|
||||
|
||||
|
||||
void GpsL1CaPcpsAssistedAcquisition::init(){
|
||||
gps_l1_ca_code_gen_complex_sampled(code_, gnss_synchro_->PRN, fs_in_, 0);
|
||||
acquisition_cc_->set_local_code(code_);
|
||||
acquisition_cc_->init();
|
||||
void GpsL1CaPcpsAssistedAcquisition::init()
|
||||
{
|
||||
acquisition_cc_->init();
|
||||
set_local_code();
|
||||
}
|
||||
|
||||
void GpsL1CaPcpsAssistedAcquisition::set_local_code()
|
||||
{
|
||||
gps_l1_ca_code_gen_complex_sampled(code_, gnss_synchro_->PRN, fs_in_, 0);
|
||||
acquisition_cc_->set_local_code(code_);
|
||||
}
|
||||
|
||||
void GpsL1CaPcpsAssistedAcquisition::reset()
|
||||
{
|
||||
|
@ -115,6 +115,8 @@ public:
|
||||
*/
|
||||
void init();
|
||||
|
||||
void set_local_code();
|
||||
|
||||
/*!
|
||||
* \brief Returns the maximum peak of grid search
|
||||
*/
|
||||
|
@ -4,6 +4,7 @@
|
||||
* \authors <ul>
|
||||
* <li> Javier Arribas, 2011. jarribas(at)cttc.es
|
||||
* <li> Luis Esteve, 2012. luis(at)epsilon-formacion.com
|
||||
* <li> Marc Molina, 2013. marc.molina.pena@gmail.com
|
||||
* </ul>
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
@ -43,25 +44,25 @@
|
||||
using google::LogMessage;
|
||||
|
||||
pcps_acquisition_cc_sptr pcps_make_acquisition_cc(
|
||||
unsigned int sampled_ms, unsigned int doppler_max, long freq,
|
||||
long fs_in, int samples_per_ms, gr::msg_queue::sptr queue, bool dump,
|
||||
std::string dump_filename)
|
||||
unsigned int sampled_ms, unsigned int doppler_max,
|
||||
long freq, long fs_in, int samples_per_ms, int samples_per_code,
|
||||
gr::msg_queue::sptr queue, bool dump, std::string dump_filename)
|
||||
{
|
||||
|
||||
return pcps_acquisition_cc_sptr(
|
||||
new pcps_acquisition_cc(sampled_ms, doppler_max, freq,
|
||||
fs_in, samples_per_ms, queue, dump, dump_filename));
|
||||
new pcps_acquisition_cc(sampled_ms, doppler_max, freq, fs_in,
|
||||
samples_per_ms, samples_per_code, queue, dump, dump_filename));
|
||||
}
|
||||
|
||||
|
||||
|
||||
pcps_acquisition_cc::pcps_acquisition_cc(
|
||||
unsigned int sampled_ms, unsigned int doppler_max, long freq,
|
||||
long fs_in, int samples_per_ms, gr::msg_queue::sptr queue, bool dump,
|
||||
std::string dump_filename) :
|
||||
gr::block("pcps_acquisition_cc",
|
||||
gr::io_signature::make(1, 1, sizeof(gr_complex) * sampled_ms * samples_per_ms),
|
||||
gr::io_signature::make(0, 0, sizeof(gr_complex) * sampled_ms * samples_per_ms))
|
||||
unsigned int sampled_ms, unsigned int doppler_max,
|
||||
long freq, long fs_in, int samples_per_ms, int samples_per_code,
|
||||
gr::msg_queue::sptr queue, bool dump, std::string dump_filename) :
|
||||
gr::block("pcps_acquisition_cc",
|
||||
gr::io_signature::make(1, 1, sizeof(gr_complex) * sampled_ms * samples_per_ms),
|
||||
gr::io_signature::make(0, 0, sizeof(gr_complex) * sampled_ms * samples_per_ms))
|
||||
{
|
||||
d_sample_counter = 0; // SAMPLE COUNTER
|
||||
d_active = false;
|
||||
@ -69,15 +70,17 @@ pcps_acquisition_cc::pcps_acquisition_cc(
|
||||
d_freq = freq;
|
||||
d_fs_in = fs_in;
|
||||
d_samples_per_ms = samples_per_ms;
|
||||
d_samples_per_code = samples_per_code;
|
||||
d_sampled_ms = sampled_ms;
|
||||
d_doppler_max = doppler_max;
|
||||
d_fft_size = d_sampled_ms * d_samples_per_ms;
|
||||
d_mag = 0;
|
||||
d_input_power = 0.0;
|
||||
d_num_doppler_bins = 0;
|
||||
|
||||
//todo: do something if posix_memalign fails
|
||||
if (posix_memalign((void**)&d_carrier, 16, d_fft_size * sizeof(gr_complex)) == 0){};
|
||||
if (posix_memalign((void**)&d_fft_codes, 16, d_fft_size * sizeof(gr_complex)) == 0){};
|
||||
if (posix_memalign((void**)&d_magnitude, 16, d_fft_size * sizeof(gr_complex)) == 0){};
|
||||
|
||||
// Direct FFT
|
||||
d_fft_if = new gr::fft::fft_complex(d_fft_size, true);
|
||||
@ -94,8 +97,22 @@ pcps_acquisition_cc::pcps_acquisition_cc(
|
||||
|
||||
pcps_acquisition_cc::~pcps_acquisition_cc()
|
||||
{
|
||||
free(d_carrier);
|
||||
|
||||
|
||||
for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++)
|
||||
{
|
||||
free(d_grid_doppler_wipeoffs[doppler_index]);
|
||||
}
|
||||
|
||||
|
||||
if (d_num_doppler_bins > 0)
|
||||
{
|
||||
delete[] d_grid_doppler_wipeoffs;
|
||||
}
|
||||
|
||||
free(d_fft_codes);
|
||||
free(d_magnitude);
|
||||
|
||||
delete d_ifft;
|
||||
delete d_fft_if;
|
||||
if (d_dump)
|
||||
@ -108,7 +125,19 @@ pcps_acquisition_cc::~pcps_acquisition_cc()
|
||||
|
||||
void pcps_acquisition_cc::set_local_code(std::complex<float> * code)
|
||||
{
|
||||
memcpy(d_fft_if->get_inbuf(),code, sizeof(gr_complex)*d_fft_size);
|
||||
memcpy(d_fft_if->get_inbuf(), code, sizeof(gr_complex)*d_fft_size);
|
||||
|
||||
d_fft_if->execute(); // We need the FFT of local code
|
||||
|
||||
//Conjugate the local code
|
||||
if (is_unaligned())
|
||||
{
|
||||
volk_32fc_conjugate_32fc_u(d_fft_codes,d_fft_if->get_outbuf(),d_fft_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
volk_32fc_conjugate_32fc_a(d_fft_codes,d_fft_if->get_outbuf(),d_fft_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -121,13 +150,18 @@ void pcps_acquisition_cc::init()
|
||||
d_mag = 0.0;
|
||||
d_input_power = 0.0;
|
||||
|
||||
d_fft_if->execute(); // We need the FFT of local code
|
||||
// Create the carrier Doppler wipeoff signals
|
||||
d_num_doppler_bins=floor(2*std::abs((int)d_doppler_max)/d_doppler_step);
|
||||
d_grid_doppler_wipeoffs = new gr_complex*[d_num_doppler_bins];
|
||||
for (unsigned int doppler_index=0;doppler_index<d_num_doppler_bins;doppler_index++)
|
||||
{
|
||||
if (posix_memalign((void**)&(d_grid_doppler_wipeoffs[doppler_index]), 16,
|
||||
d_fft_size * sizeof(gr_complex)) == 0){};
|
||||
|
||||
//Conjugate the local code
|
||||
for (unsigned int i = 0; i < d_fft_size; i++)
|
||||
{
|
||||
d_fft_codes[i] = std::complex<float>(conj(d_fft_if->get_outbuf()[i]));
|
||||
}
|
||||
int doppler=-(int)d_doppler_max+d_doppler_step*doppler_index;
|
||||
complex_exp_gen_conj(d_grid_doppler_wipeoffs[doppler_index],
|
||||
d_freq + doppler, d_fs_in, d_fft_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -158,7 +192,6 @@ int pcps_acquisition_cc::general_work(int noutput_items,
|
||||
int doppler;
|
||||
unsigned int indext = 0;
|
||||
float magt = 0.0;
|
||||
float tmp_magt = 0.0;
|
||||
const gr_complex *in = (const gr_complex *)input_items[0]; //Get the input samples pointer
|
||||
bool positive_acquisition = false;
|
||||
int acquisition_message = -1; //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL
|
||||
@ -175,35 +208,41 @@ int pcps_acquisition_cc::general_work(int noutput_items,
|
||||
d_input_power = 0.0;
|
||||
|
||||
DLOG(INFO) << "Channel: " << d_channel
|
||||
<< " , doing acquisition of satellite: " << d_gnss_synchro->System
|
||||
<< " "<< d_gnss_synchro->PRN
|
||||
<< " ,sample stamp: " << d_sample_counter << ", threshold: "
|
||||
<< d_threshold << ", doppler_max: " << d_doppler_max
|
||||
<< ", doppler_step: " << d_doppler_step;
|
||||
<< " , doing acquisition of satellite: " << d_gnss_synchro->System << " "<< d_gnss_synchro->PRN
|
||||
<< " ,sample stamp: " << d_sample_counter << ", threshold: "
|
||||
<< d_threshold << ", doppler_max: " << d_doppler_max
|
||||
<< ", doppler_step: " << d_doppler_step;
|
||||
|
||||
// 1- Compute the input signal power estimation
|
||||
for (i = 0; i < d_fft_size; i++)
|
||||
if (is_unaligned())
|
||||
{
|
||||
d_input_power += std::norm(in[i]);
|
||||
volk_32fc_magnitude_squared_32f_u(d_magnitude, in, d_fft_size);
|
||||
for (i = 0; i < d_fft_size; i++)
|
||||
d_input_power += d_magnitude[i];
|
||||
}
|
||||
d_input_power = d_input_power / (float)d_fft_size;
|
||||
else
|
||||
{
|
||||
volk_32fc_magnitude_squared_32f_a(d_magnitude, in, d_fft_size);
|
||||
volk_32f_accumulator_s32f_a(&d_input_power, d_magnitude, d_fft_size);
|
||||
}
|
||||
d_input_power /= (float)d_fft_size;
|
||||
|
||||
// 2- Doppler frequency search loop
|
||||
for (doppler = (int)(-d_doppler_max); doppler <= (int)d_doppler_max; doppler += d_doppler_step)
|
||||
for (unsigned int doppler_index=0;doppler_index<d_num_doppler_bins;doppler_index++)
|
||||
{
|
||||
// doppler search steps
|
||||
//TODO: Create a run time lookup table with all the required Doppler wipe-off LO signals, by allocating a memory space (aligned) and by initializing it when the Doppler step is assigned
|
||||
// then, use the arrays to multiply the incomming signal, instead of computing the sine and cosine online.
|
||||
// Perform the carrier wipe-off
|
||||
complex_exp_gen_conj(d_carrier, d_freq + doppler, d_fs_in, d_fft_size);
|
||||
if (is_unaligned()==true)
|
||||
|
||||
doppler=-(int)d_doppler_max+d_doppler_step*doppler_index;
|
||||
|
||||
if (is_unaligned())
|
||||
{
|
||||
volk_32fc_x2_multiply_32fc_u(d_fft_if->get_inbuf(), in, d_carrier, d_fft_size);
|
||||
volk_32fc_x2_multiply_32fc_u(d_fft_if->get_inbuf(), in,
|
||||
d_grid_doppler_wipeoffs[doppler_index], d_fft_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
//use directly the input vector
|
||||
volk_32fc_x2_multiply_32fc_a(d_fft_if->get_inbuf(), in, d_carrier, d_fft_size);
|
||||
volk_32fc_x2_multiply_32fc_a(d_fft_if->get_inbuf(), in,
|
||||
d_grid_doppler_wipeoffs[doppler_index], d_fft_size);
|
||||
}
|
||||
|
||||
// 3- Perform the FFT-based convolution (parallel time search)
|
||||
@ -212,32 +251,52 @@ int pcps_acquisition_cc::general_work(int noutput_items,
|
||||
|
||||
// Multiply carrier wiped--off, Fourier transformed incoming signal
|
||||
// with the local FFT'd code reference using SIMD operations with VOLK library
|
||||
volk_32fc_x2_multiply_32fc_a(d_ifft->get_inbuf(), d_fft_if->get_outbuf(), d_fft_codes, d_fft_size);
|
||||
if (is_unaligned())
|
||||
{
|
||||
volk_32fc_x2_multiply_32fc_u(d_ifft->get_inbuf(),
|
||||
d_fft_if->get_outbuf(), d_fft_codes, d_fft_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
volk_32fc_x2_multiply_32fc_a(d_ifft->get_inbuf(),
|
||||
d_fft_if->get_outbuf(), d_fft_codes, d_fft_size);
|
||||
}
|
||||
|
||||
// compute the inverse FFT
|
||||
d_ifft->execute();
|
||||
|
||||
// Search maximum
|
||||
indext = 0;
|
||||
magt = 0;
|
||||
magt = 0.0;
|
||||
|
||||
fft_normalization_factor = (float)d_fft_size * (float)d_fft_size;
|
||||
for (i = 0; i < d_fft_size; i++)
|
||||
|
||||
if (is_unaligned())
|
||||
{
|
||||
tmp_magt = std::norm(d_ifft->get_outbuf()[i]);
|
||||
if (tmp_magt > magt)
|
||||
volk_32fc_magnitude_squared_32f_u(d_magnitude, d_ifft->get_outbuf(), d_fft_size);
|
||||
for (i = 0; i < d_fft_size; i++)
|
||||
{
|
||||
magt = tmp_magt;
|
||||
indext = i;
|
||||
if(d_magnitude[i] > magt)
|
||||
{
|
||||
magt = d_magnitude[i];
|
||||
indext = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
volk_32fc_magnitude_squared_32f_a(d_magnitude, d_ifft->get_outbuf(), d_fft_size);
|
||||
volk_32f_index_max_16u_a(&indext, d_magnitude, d_fft_size);
|
||||
}
|
||||
|
||||
// Normalize the maximum value to correct the scale factor introduced by FFTW
|
||||
magt = magt / (fft_normalization_factor * fft_normalization_factor);
|
||||
magt = d_magnitude[indext] / (fft_normalization_factor * fft_normalization_factor);
|
||||
|
||||
// 4- record the maximum peak and the associated synchronization parameters
|
||||
if (d_mag < magt)
|
||||
{
|
||||
d_mag = magt;
|
||||
d_gnss_synchro->Acq_delay_samples = (double)indext;
|
||||
d_gnss_synchro->Acq_delay_samples = (double)(indext % d_samples_per_code);
|
||||
d_gnss_synchro->Acq_doppler_hz = (double)doppler;
|
||||
}
|
||||
|
||||
@ -298,6 +357,7 @@ int pcps_acquisition_cc::general_work(int noutput_items,
|
||||
{
|
||||
acquisition_message = 2;
|
||||
}
|
||||
|
||||
d_channel_internal_queue->push(acquisition_message);
|
||||
consume_each(1);
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
* \authors <ul>
|
||||
* <li> Javier Arribas, 2011. jarribas(at)cttc.es
|
||||
* <li> Luis Esteve, 2012. luis(at)epsilon-formacion.com
|
||||
* <li> Marc Molina, 2013. marc.molina.pena@gmail.com
|
||||
* </ul>
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
@ -65,8 +66,8 @@ class pcps_acquisition_cc;
|
||||
typedef boost::shared_ptr<pcps_acquisition_cc> pcps_acquisition_cc_sptr;
|
||||
|
||||
pcps_acquisition_cc_sptr
|
||||
pcps_make_acquisition_cc(unsigned int sampled_ms,
|
||||
unsigned int doppler_max, long freq, long fs_in, int samples_per_ms,
|
||||
pcps_make_acquisition_cc(unsigned int sampled_ms, unsigned int doppler_max,
|
||||
long freq, long fs_in, int samples_per_ms, int samples_per_code,
|
||||
gr::msg_queue::sptr queue, bool dump, std::string dump_filename);
|
||||
|
||||
/*!
|
||||
@ -79,47 +80,49 @@ class pcps_acquisition_cc: public gr::block
|
||||
{
|
||||
private:
|
||||
friend pcps_acquisition_cc_sptr
|
||||
pcps_make_acquisition_cc(unsigned int sampled_ms,
|
||||
unsigned int doppler_max, long freq, long fs_in,
|
||||
int samples_per_ms, gr::msg_queue::sptr queue, bool dump,
|
||||
std::string dump_filename);
|
||||
pcps_make_acquisition_cc(unsigned int sampled_ms, unsigned int doppler_max,
|
||||
long freq, long fs_in, int samples_per_ms, int samples_per_code,
|
||||
gr::msg_queue::sptr queue, bool dump, std::string dump_filename);
|
||||
|
||||
pcps_acquisition_cc(unsigned int sampled_ms,
|
||||
unsigned int doppler_max, long freq, long fs_in,
|
||||
int samples_per_ms, gr::msg_queue::sptr d_queue, bool dump,
|
||||
std::string dump_filename);
|
||||
pcps_acquisition_cc(unsigned int sampled_ms, unsigned int doppler_max,
|
||||
long freq, long fs_in, int samples_per_ms, int samples_per_code,
|
||||
gr::msg_queue::sptr queue, bool dump, std::string dump_filename);
|
||||
|
||||
void calculate_magnitudes(gr_complex* fft_begin, int doppler_shift,
|
||||
int doppler_offset);
|
||||
|
||||
long d_fs_in;
|
||||
long d_freq;
|
||||
int d_samples_per_ms;
|
||||
unsigned int d_doppler_resolution;
|
||||
float d_threshold;
|
||||
std::string d_satellite_str;
|
||||
unsigned int d_doppler_max;
|
||||
unsigned int d_doppler_step;
|
||||
unsigned int d_sampled_ms;
|
||||
unsigned int d_fft_size;
|
||||
unsigned long int d_sample_counter;
|
||||
gr_complex* d_carrier;
|
||||
gr_complex* d_fft_codes;
|
||||
gr::fft::fft_complex* d_fft_if;
|
||||
gr::fft::fft_complex* d_ifft;
|
||||
Gnss_Synchro *d_gnss_synchro;
|
||||
unsigned int d_code_phase;
|
||||
float d_doppler_freq;
|
||||
float d_mag;
|
||||
float d_input_power;
|
||||
float d_test_statistics;
|
||||
|
||||
long d_fs_in;
|
||||
long d_freq;
|
||||
int d_samples_per_ms;
|
||||
int d_samples_per_code;
|
||||
unsigned int d_doppler_resolution;
|
||||
float d_threshold;
|
||||
std::string d_satellite_str;
|
||||
unsigned int d_doppler_max;
|
||||
unsigned int d_doppler_step;
|
||||
unsigned int d_sampled_ms;
|
||||
unsigned int d_fft_size;
|
||||
unsigned long int d_sample_counter;
|
||||
gr_complex** d_grid_doppler_wipeoffs;
|
||||
unsigned int d_num_doppler_bins;
|
||||
gr_complex* d_fft_codes;
|
||||
gr::fft::fft_complex* d_fft_if;
|
||||
gr::fft::fft_complex* d_ifft;
|
||||
Gnss_Synchro *d_gnss_synchro;
|
||||
unsigned int d_code_phase;
|
||||
float d_doppler_freq;
|
||||
float d_mag;
|
||||
float* d_magnitude;
|
||||
float d_input_power;
|
||||
float d_test_statistics;
|
||||
gr::msg_queue::sptr d_queue;
|
||||
concurrent_queue<int> *d_channel_internal_queue;
|
||||
std::ofstream d_dump_file;
|
||||
bool d_active;
|
||||
bool d_dump;
|
||||
unsigned int d_channel;
|
||||
std::string d_dump_filename;
|
||||
concurrent_queue<int> *d_channel_internal_queue;
|
||||
std::ofstream d_dump_file;
|
||||
bool d_active;
|
||||
bool d_dump;
|
||||
unsigned int d_channel;
|
||||
std::string d_dump_filename;
|
||||
|
||||
public:
|
||||
/*!
|
||||
|
@ -76,7 +76,7 @@ Channel::Channel(ConfigurationInterface *configuration, unsigned int channel,
|
||||
|
||||
unsigned int doppler_step = configuration->property("Acquisition" + boost::lexical_cast<std::string>(channel_)
|
||||
+ ".doppler_step",0);
|
||||
if(doppler_step==0) doppler_step = configuration->property("Acquisition.doppler_step",0);
|
||||
if(doppler_step==0) doppler_step = configuration->property("Acquisition.doppler_step",500);
|
||||
|
||||
DLOG(INFO) << "Channel "<< channel_<<" Doppler_step = " << doppler_step << std::endl;
|
||||
|
||||
@ -88,6 +88,7 @@ Channel::Channel(ConfigurationInterface *configuration, unsigned int channel,
|
||||
|
||||
acq_->set_threshold(threshold);
|
||||
|
||||
acq_->init();
|
||||
|
||||
repeat_ = configuration->property("Acquisition" + boost::lexical_cast<
|
||||
std::string>(channel_) + ".repeat_satellite", false);
|
||||
@ -184,7 +185,7 @@ void Channel::set_signal(Gnss_Signal gnss_signal)
|
||||
gnss_synchro_.Signal[2] = 0; // make sure that string length is only two characters
|
||||
gnss_synchro_.PRN = gnss_signal_.get_satellite().get_PRN();
|
||||
gnss_synchro_.System = gnss_signal_.get_satellite().get_system_short().c_str()[0];
|
||||
acq_->init();
|
||||
acq_->set_local_code();
|
||||
nav_->set_satellite(gnss_signal_.get_satellite());
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ galileo_e1_code_gen_int(int* _dest, char _Signal[3], signed int _prn,
|
||||
{
|
||||
hex_to_binary_converter(&_dest[index],
|
||||
Galileo_E1_B_PRIMARY_CODE[prn].at(i));
|
||||
index = index +4;
|
||||
index = index + 4;
|
||||
}
|
||||
|
||||
}
|
||||
@ -122,8 +122,8 @@ galileo_e1_gen(std::complex<float>* _dest, int* _prn, char _Signal[3])
|
||||
const float alpha = sqrt(10.0 / 11.0);
|
||||
const float beta = sqrt(1.0 / 11.0);
|
||||
|
||||
std::complex<float> sinboc_11[49152]; // 12*4096 (_codeLength not accepted by Clang )
|
||||
std::complex<float> sinboc_61[49152];
|
||||
std::complex<float> sinboc_11[_codeLength]; // 12*4092 (_codeLength not accepted by Clang )
|
||||
std::complex<float> sinboc_61[_codeLength];
|
||||
|
||||
galileo_e1_sinboc_11_gen(sinboc_11, _prn, _codeLength); //generate sinboc(1,1) 12 samples per chip
|
||||
galileo_e1_sinboc_61_gen(sinboc_61, _prn, _codeLength); //generate sinboc(6,1) 12 samples per chip
|
||||
@ -150,48 +150,88 @@ galileo_e1_gen(std::complex<float>* _dest, int* _prn, char _Signal[3])
|
||||
|
||||
void
|
||||
galileo_e1_code_gen_complex_sampled(std::complex<float>* _dest, char _Signal[3],
|
||||
bool _cboc, unsigned int _prn, signed int _fs, unsigned int _chip_shift)
|
||||
bool _cboc, unsigned int _prn, signed int _fs, unsigned int _chip_shift,
|
||||
bool _secondary_flag)
|
||||
{
|
||||
// This function is based on the GNU software GPS for MATLAB in the Kay Borre book
|
||||
|
||||
// This function is based on the GNU software GPS for MATLAB in the Kay Borre bookç
|
||||
|
||||
std::string _galileo_signal = _Signal;
|
||||
unsigned int _samplesPerCode;
|
||||
const unsigned int _codeFreqBasis = Galileo_E1_CODE_CHIP_RATE_HZ; //Hz
|
||||
unsigned int _codeLength = Galileo_E1_B_CODE_LENGTH_CHIPS;
|
||||
int primary_code_E1_chips[4096];
|
||||
int primary_code_E1_chips[(int)Galileo_E1_B_CODE_LENGTH_CHIPS];
|
||||
_samplesPerCode = round(_fs / (_codeFreqBasis / _codeLength));
|
||||
const int _samplesPerChip = (_cboc == true) ? 12 : 2;
|
||||
|
||||
const unsigned int delay = (((int)Galileo_E1_B_CODE_LENGTH_CHIPS - _chip_shift)
|
||||
% (int)Galileo_E1_B_CODE_LENGTH_CHIPS)
|
||||
* _samplesPerCode / Galileo_E1_B_CODE_LENGTH_CHIPS;
|
||||
|
||||
galileo_e1_code_gen_int(primary_code_E1_chips, _Signal, _prn, 0); //generate Galileo E1 code, 1 sample per chip
|
||||
|
||||
std::complex<float>* _signal_E1;
|
||||
|
||||
_codeLength = _samplesPerChip * Galileo_E1_B_CODE_LENGTH_CHIPS;
|
||||
_signal_E1 = new std::complex<float>[_codeLength];
|
||||
|
||||
if (_cboc == true)
|
||||
{
|
||||
_codeLength = 12 * Galileo_E1_B_CODE_LENGTH_CHIPS;
|
||||
if (_fs != 12 * _codeFreqBasis)
|
||||
{
|
||||
std::complex<float> _signal_E1[4096];
|
||||
galileo_e1_gen(_signal_E1, primary_code_E1_chips, _Signal); //generate cboc 12 samples per chip
|
||||
resampler(_signal_E1, _dest, 12 * _codeFreqBasis, _fs,
|
||||
_codeLength, _samplesPerCode); //resamples code to fs
|
||||
}
|
||||
else
|
||||
{
|
||||
galileo_e1_gen(_dest, primary_code_E1_chips, _Signal); //generate cboc 12 samples per chip
|
||||
}
|
||||
galileo_e1_gen(_signal_E1, primary_code_E1_chips, _Signal); //generate cboc 12 samples per chip
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- Find number of samples per spreading code ----------------------------
|
||||
_codeLength = 2 * Galileo_E1_B_CODE_LENGTH_CHIPS;
|
||||
if (_fs != 2 * _codeFreqBasis)
|
||||
{
|
||||
std::complex<float> _signal_E1[8192];
|
||||
galileo_e1_sinboc_11_gen(_signal_E1, primary_code_E1_chips,
|
||||
_codeLength); //generate sinboc(1,1) 2 samples per chip
|
||||
resampler(_signal_E1, _dest, 2 * _codeFreqBasis, _fs,
|
||||
_codeLength, _samplesPerCode); //resamples code to fs
|
||||
}
|
||||
else
|
||||
{
|
||||
galileo_e1_sinboc_11_gen(_dest, primary_code_E1_chips,
|
||||
_codeLength); //generate sinboc(1,1) 2 samples per chip }
|
||||
}
|
||||
galileo_e1_sinboc_11_gen(_signal_E1, primary_code_E1_chips,
|
||||
_codeLength); //generate sinboc(1,1) 2 samples per chip
|
||||
}
|
||||
|
||||
if (_fs != _samplesPerChip * _codeFreqBasis)
|
||||
{
|
||||
std::complex<float>* _resampled_signal = new std::complex<float>[_samplesPerCode];
|
||||
resampler(_signal_E1, _resampled_signal, _samplesPerChip * _codeFreqBasis, _fs,
|
||||
_codeLength, _samplesPerCode); //resamples code to fs
|
||||
|
||||
delete[] _signal_E1;
|
||||
_signal_E1 = _resampled_signal;
|
||||
}
|
||||
|
||||
|
||||
if (_galileo_signal.rfind("1C") != std::string::npos && _galileo_signal.length() >= 2 && _secondary_flag)
|
||||
{
|
||||
|
||||
std::complex<float>* _signal_E1C_secondary = new std::complex<float>
|
||||
[(int)Galileo_E1_C_SECONDARY_CODE_LENGTH
|
||||
* _samplesPerCode];
|
||||
|
||||
for (unsigned int i = 0; i < (int)Galileo_E1_C_SECONDARY_CODE_LENGTH; i++)
|
||||
{
|
||||
for (unsigned k = 0; k < _samplesPerCode; k++)
|
||||
{
|
||||
_signal_E1C_secondary[i*_samplesPerCode + k] = _signal_E1[k]
|
||||
* (Galileo_E1_C_SECONDARY_CODE.at(i) == '0'
|
||||
? std::complex<float>(1,0) : std::complex<float>(-1,0));
|
||||
}
|
||||
}
|
||||
|
||||
_samplesPerCode *= (int)Galileo_E1_C_SECONDARY_CODE_LENGTH;
|
||||
|
||||
delete[] _signal_E1;
|
||||
_signal_E1 = _signal_E1C_secondary;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < _samplesPerCode; i++)
|
||||
{
|
||||
_dest[(i+delay)%_samplesPerCode] = _signal_E1[i];
|
||||
}
|
||||
|
||||
delete[] _signal_E1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
galileo_e1_code_gen_complex_sampled(std::complex<float>* _dest, char _Signal[3],
|
||||
bool _cboc, unsigned int _prn, signed int _fs, unsigned int _chip_shift)
|
||||
{
|
||||
galileo_e1_code_gen_complex_sampled(_dest, _Signal, _cboc, _prn,
|
||||
_fs, _chip_shift, false);
|
||||
}
|
||||
|
@ -69,7 +69,13 @@ void galileo_e1_cboc_gen(std::complex<float>* _dest, int* _prn, char _Signal[3])
|
||||
*
|
||||
*/
|
||||
void galileo_e1_code_gen_complex_sampled(std::complex<float>* _dest, char _Signal[3],
|
||||
bool _cboc, unsigned int _prn, signed int _fs,
|
||||
unsigned int _chip_shift);
|
||||
bool _cboc, unsigned int _prn, signed int _fs, unsigned int _chip_shift,
|
||||
bool _secondary_flag);
|
||||
|
||||
/*!
|
||||
* \brief galileo_e1_code_gen_complex_sampled without _secondary_flag for backward compatibility.
|
||||
*/
|
||||
void galileo_e1_code_gen_complex_sampled(std::complex<float>* _dest, char _Signal[3],
|
||||
bool _cboc, unsigned int _prn, signed int _fs, unsigned int _chip_shift);
|
||||
|
||||
#endif /* GNSS_SDR_GALILEO_E1_SIGNAL_PROCESSING_H_ */
|
||||
|
20
src/algorithms/signal_generator/CMakeLists.txt
Normal file
20
src/algorithms/signal_generator/CMakeLists.txt
Normal file
@ -0,0 +1,20 @@
|
||||
# Copyright (C) 2012-2013 (see AUTHORS file for a list of contributors)
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
add_subdirectory(adapters)
|
||||
add_subdirectory(gnuradio_blocks)
|
34
src/algorithms/signal_generator/adapters/CMakeLists.txt
Normal file
34
src/algorithms/signal_generator/adapters/CMakeLists.txt
Normal file
@ -0,0 +1,34 @@
|
||||
# Copyright (C) 2012-2013 (see AUTHORS file for a list of contributors)
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
set(SIGNAL_GENERATOR_ADAPTER_SOURCES signal_generator.cc)
|
||||
|
||||
include_directories(
|
||||
$(CMAKE_CURRENT_SOURCE_DIR)
|
||||
${CMAKE_SOURCE_DIR}/src/core/system_parameters
|
||||
${CMAKE_SOURCE_DIR}/src/core/interfaces
|
||||
${CMAKE_SOURCE_DIR}/src/core/receiver
|
||||
${CMAKE_SOURCE_DIR}/src/algorithms/signal_generator/gnuradio_blocks
|
||||
${CMAKE_SOURCE_DIR}/src/algorithms/libs
|
||||
${GLOG_INCLUDE_DIRS}
|
||||
${GFlags_INCLUDE_DIRS}
|
||||
${GNURADIO_RUNTIME_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
add_library(signal_generator_adapters ${SIGNAL_GENERATOR_ADAPTER_SOURCES})
|
||||
target_link_libraries(signal_generator_adapters gnss_sp_libs signal_generator_blocks ${GNURADIO_RUNTIME_LIBRARIES} ${GNURADIO_BLOCKS_LIBRARIES} ${GNURADIO_FILTER_LIBRARIES})
|
167
src/algorithms/signal_generator/adapters/signal_generator.cc
Normal file
167
src/algorithms/signal_generator/adapters/signal_generator.cc
Normal file
@ -0,0 +1,167 @@
|
||||
/*!
|
||||
* \file signal_generator.cc
|
||||
* \brief Signal generator.
|
||||
* \author Marc Molina, 2013. marc.molina.pena@gmail.com
|
||||
*
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2010-2013 (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 "signal_generator.h"
|
||||
#include "configuration_interface.h"
|
||||
#include "Galileo_E1.h"
|
||||
#include "GPS_L1_CA.h"
|
||||
#include <glog/log_severity.h>
|
||||
#include <glog/logging.h>
|
||||
|
||||
using google::LogMessage;
|
||||
|
||||
SignalGenerator::SignalGenerator(ConfigurationInterface* configuration,
|
||||
std::string role, unsigned int in_stream,
|
||||
unsigned int out_stream, boost::shared_ptr<gr::msg_queue> queue) :
|
||||
role_(role), in_stream_(in_stream), out_stream_(out_stream), queue_(queue)
|
||||
{
|
||||
std::string default_item_type = "gr_complex";
|
||||
std::string default_dump_file = "./data/gen_source.dat";
|
||||
std::string default_system = "G";
|
||||
|
||||
item_type_ = configuration->property(role + ".item_type", default_item_type);
|
||||
dump_ = configuration->property(role + ".dump", false);
|
||||
dump_filename_ = configuration->property(role + ".dump_filename", default_dump_file);
|
||||
|
||||
unsigned int fs_in = configuration->property("SignalSource.fs_hz", 4e6);
|
||||
bool data_flag = configuration->property("SignalSource.data_flag", false);
|
||||
bool noise_flag = configuration->property("SignalSource.noise_flag", false);
|
||||
float BW_BB = configuration->property("SignalSource.BW_BB", 1.0);
|
||||
unsigned int num_satellites = configuration->property("SignalSource.num_satellites", 1);
|
||||
|
||||
std::vector<std::string> system;
|
||||
std::vector<unsigned int> PRN;
|
||||
std::vector<float> CN0_dB;
|
||||
std::vector<float> doppler_Hz;
|
||||
std::vector<unsigned int> delay_chips;
|
||||
|
||||
for (unsigned int sat_idx = 0; sat_idx < num_satellites; sat_idx++)
|
||||
{
|
||||
std::string sat = std::to_string(sat_idx);
|
||||
system.push_back(configuration->property("SignalSource.system_" + sat, default_system));
|
||||
PRN.push_back(configuration->property("SignalSource.PRN_" + sat, 1));
|
||||
CN0_dB.push_back(configuration->property("SignalSource.CN0_dB_" + sat, 10));
|
||||
doppler_Hz.push_back(configuration->property("SignalSource.doppler_Hz_" + sat, 0));
|
||||
delay_chips.push_back(configuration->property("SignalSource.delay_chips_" + sat, 0));
|
||||
}
|
||||
|
||||
// If Gallileo signal is present -> vector duration = 100 ms (25 * 4 ms)
|
||||
// If there is only GPS signal (Gallileo signal not present) -> vector duration = 1 ms
|
||||
unsigned int vector_length = 0;
|
||||
if (std::find(system.begin(), system.end(), "E") != system.end())
|
||||
{
|
||||
vector_length = round((float)fs_in / (Galileo_E1_CODE_CHIP_RATE_HZ
|
||||
/ Galileo_E1_B_CODE_LENGTH_CHIPS))
|
||||
* Galileo_E1_C_SECONDARY_CODE_LENGTH;
|
||||
}
|
||||
else if (std::find(system.begin(), system.end(), "G") != system.end())
|
||||
{
|
||||
vector_length = round((float)fs_in
|
||||
/ (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS));
|
||||
}
|
||||
|
||||
if (item_type_.compare("gr_complex") == 0)
|
||||
{
|
||||
item_size_ = sizeof(gr_complex);
|
||||
DLOG(INFO) << "Item size " << item_size_;
|
||||
gen_source_ = signal_make_generator_c(system, PRN, CN0_dB, doppler_Hz, delay_chips,
|
||||
data_flag, noise_flag, fs_in, vector_length, BW_BB);
|
||||
|
||||
vector_to_stream_ = gr::blocks::vector_to_stream::make(item_size_, vector_length);
|
||||
|
||||
DLOG(INFO) << "vector_to_stream(" << vector_to_stream_->unique_id() << ")";
|
||||
DLOG(INFO) << "gen_source(" << gen_source_->unique_id() << ")";
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
LOG_AT_LEVEL(WARNING) << item_type_
|
||||
<< " unrecognized item type for resampler";
|
||||
item_size_ = sizeof(short);
|
||||
}
|
||||
|
||||
if (dump_)
|
||||
{
|
||||
DLOG(INFO) << "Dumping output into file " << dump_filename_;
|
||||
file_sink_ = gr::blocks::file_sink::make(item_size_, dump_filename_.c_str());
|
||||
}
|
||||
if (dump_)
|
||||
{
|
||||
DLOG(INFO) << "file_sink(" << file_sink_->unique_id() << ")";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SignalGenerator::~SignalGenerator()
|
||||
{}
|
||||
|
||||
|
||||
void SignalGenerator::connect(gr::top_block_sptr top_block)
|
||||
{
|
||||
if (item_type_.compare("gr_complex") == 0)
|
||||
{
|
||||
top_block->connect(gen_source_, 0, vector_to_stream_, 0);
|
||||
DLOG(INFO) << "connected gen_source to vector_to_stream";
|
||||
|
||||
if (dump_)
|
||||
{
|
||||
top_block->connect(vector_to_stream_, 0, file_sink_, 0);
|
||||
DLOG(INFO) << "connected vector_to_stream_ to file sink";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SignalGenerator::disconnect(gr::top_block_sptr top_block)
|
||||
{
|
||||
if (item_type_.compare("gr_complex") == 0)
|
||||
{
|
||||
top_block->disconnect(gen_source_, 0, vector_to_stream_, 0);
|
||||
if (dump_)
|
||||
{
|
||||
top_block->disconnect(vector_to_stream_, 0, file_sink_, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
gr::basic_block_sptr SignalGenerator::get_left_block()
|
||||
{
|
||||
LOG_AT_LEVEL(WARNING) << "Left block of a signal source should not be retrieved";
|
||||
return gr::block_sptr();
|
||||
}
|
||||
|
||||
|
||||
gr::basic_block_sptr SignalGenerator::get_right_block()
|
||||
{
|
||||
return vector_to_stream_;
|
||||
}
|
96
src/algorithms/signal_generator/adapters/signal_generator.h
Normal file
96
src/algorithms/signal_generator/adapters/signal_generator.h
Normal file
@ -0,0 +1,96 @@
|
||||
/*!
|
||||
* \file signal_generator.h
|
||||
* \brief Adapter of a class that generates synthesized GNSS signal.
|
||||
* \author Marc Molina, 2013. marc.molina.pena@gmail.com
|
||||
*
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2010-2013 (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_SIGNAL_GENERATOR_H_
|
||||
#define GNSS_SDR_SIGNAL_GENERATOR_H_
|
||||
|
||||
#include <gnuradio/blocks/file_sink.h>
|
||||
#include <gnuradio/hier_block2.h>
|
||||
#include <gnuradio/msg_queue.h>
|
||||
#include <gnuradio/blocks/vector_to_stream.h>
|
||||
|
||||
#include "gnss_block_interface.h"
|
||||
#include "signal_generator_c.h"
|
||||
|
||||
class ConfigurationInterface;
|
||||
|
||||
/*!
|
||||
* \brief This class generates synthesized GNSS signal.
|
||||
*
|
||||
*/
|
||||
class SignalGenerator: public GNSSBlockInterface
|
||||
{
|
||||
public:
|
||||
SignalGenerator(ConfigurationInterface* configuration,
|
||||
std::string role, unsigned int in_stream,
|
||||
unsigned int out_stream, boost::shared_ptr<gr::msg_queue> queue);
|
||||
|
||||
virtual ~SignalGenerator();
|
||||
std::string role()
|
||||
{
|
||||
return role_;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns "SignalGenerator".
|
||||
*/
|
||||
std::string implementation()
|
||||
{
|
||||
return "GNSSSignalGenerator";
|
||||
}
|
||||
size_t item_size()
|
||||
{
|
||||
return item_size_;
|
||||
}
|
||||
|
||||
void connect(gr::top_block_sptr top_block);
|
||||
void disconnect(gr::top_block_sptr top_block);
|
||||
gr::basic_block_sptr get_left_block();
|
||||
gr::basic_block_sptr get_right_block();
|
||||
|
||||
|
||||
private:
|
||||
std::string role_;
|
||||
unsigned int in_stream_;
|
||||
unsigned int out_stream_;
|
||||
std::string item_type_;
|
||||
size_t item_size_;
|
||||
bool dump_;
|
||||
std::string dump_filename_;
|
||||
boost::shared_ptr<gr::block> gen_source_;
|
||||
gr::blocks::vector_to_stream::sptr vector_to_stream_;
|
||||
gr::blocks::file_sink::sptr file_sink_;
|
||||
boost::shared_ptr<gr::msg_queue> queue_;
|
||||
|
||||
};
|
||||
|
||||
#endif /*GNSS_SDR_SIGNAL_GENERATOR_H_*/
|
@ -0,0 +1,35 @@
|
||||
# Copyright (C) 2012-2013 (see AUTHORS file for a list of contributors)
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
set(SIGNAL_GENERATOR_BLOCK_SOURCES signal_generator_c.cc)
|
||||
|
||||
include_directories(
|
||||
$(CMAKE_CURRENT_SOURCE_DIR)
|
||||
${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
|
||||
${GLOG_INCLUDE_DIRS}
|
||||
${GFlags_INCLUDE_DIRS}
|
||||
${GNURADIO_RUNTIME_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
add_library(signal_generator_blocks ${SIGNAL_GENERATOR_BLOCK_SOURCES})
|
||||
target_link_libraries(signal_generator_blocks gnss_system_parameters ${GNURADIO_RUNTIME_LIBRARIES} ${GNURADIO_FFT_LIBRARIES} ${VOLK_LIBRARIES})
|
||||
|
||||
|
@ -0,0 +1,335 @@
|
||||
/*!
|
||||
* \file signal_generator_c.h
|
||||
* \brief GNU Radio source block that generates synthesized GNSS signal.
|
||||
* \author Marc Molina, 2013. marc.molina.pena@gmail.com
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2010-2012 (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/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "signal_generator_c.h"
|
||||
#include <gnuradio/io_signature.h>
|
||||
#include "gps_sdr_signal_processing.h"
|
||||
#include "galileo_e1_signal_processing.h"
|
||||
#include <volk/volk.h>
|
||||
#include "nco_lib.h"
|
||||
|
||||
|
||||
/*
|
||||
* Create a new instance of signal_generator_c and return
|
||||
* a boost shared_ptr. This is effectively the public constructor.
|
||||
*/
|
||||
signal_generator_c_sptr
|
||||
signal_make_generator_c (std::vector<std::string> system, const std::vector<unsigned int> &PRN,
|
||||
const std::vector<float> &CN0_dB, const std::vector<float> &doppler_Hz,
|
||||
const std::vector<unsigned int> &delay_chips, bool data_flag, bool noise_flag,
|
||||
unsigned int fs_in, unsigned int vector_length, float BW_BB)
|
||||
{
|
||||
return gnuradio::get_initial_sptr(new signal_generator_c(system, PRN, CN0_dB, doppler_Hz, delay_chips,
|
||||
data_flag, noise_flag, fs_in, vector_length, BW_BB));
|
||||
}
|
||||
|
||||
/*
|
||||
* The private constructor
|
||||
*/
|
||||
signal_generator_c::signal_generator_c (std::vector<std::string> system, const std::vector<unsigned int> &PRN,
|
||||
const std::vector<float> &CN0_dB, const std::vector<float> &doppler_Hz,
|
||||
const std::vector<unsigned int> &delay_chips, bool data_flag, bool noise_flag,
|
||||
unsigned int fs_in, unsigned int vector_length, float BW_BB) :
|
||||
|
||||
gr::block ("signal_gen_cc", gr::io_signature::make(0, 0, sizeof(gr_complex)),
|
||||
gr::io_signature::make(1, 1, sizeof(gr_complex)*vector_length)),
|
||||
system_(system),
|
||||
PRN_(PRN),
|
||||
CN0_dB_(CN0_dB),
|
||||
doppler_Hz_(doppler_Hz),
|
||||
delay_chips_(delay_chips),
|
||||
data_flag_(data_flag),
|
||||
noise_flag_(noise_flag),
|
||||
fs_in_(fs_in),
|
||||
num_sats_(PRN.size()),
|
||||
vector_length_(vector_length),
|
||||
BW_BB_(BW_BB*(float)fs_in/2)
|
||||
{
|
||||
init();
|
||||
generate_codes();
|
||||
}
|
||||
|
||||
void signal_generator_c::init()
|
||||
{
|
||||
if (posix_memalign((void**)&complex_phase_, 16, vector_length_ * sizeof(gr_complex)) == 0){};
|
||||
|
||||
// True if Gallileo satellites are present
|
||||
bool gallileo_signal = std::find(system_.begin(), system_.end(), "E") != system_.end();
|
||||
|
||||
for (unsigned int sat = 0; sat < num_sats_; sat++)
|
||||
{
|
||||
start_phase_rad_.push_back(0);
|
||||
current_data_bits_.push_back(gr_complex(1,0));
|
||||
ms_counter_.push_back(0);
|
||||
|
||||
if (system_[sat] == "G")
|
||||
{
|
||||
samples_per_code_.push_back(round((float)fs_in_
|
||||
/ (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS)));
|
||||
|
||||
num_of_codes_per_vector_.push_back(gallileo_signal ? 4*(int)Galileo_E1_C_SECONDARY_CODE_LENGTH : 1);
|
||||
data_bit_duration_ms_.push_back(1e3/GPS_CA_TELEMETRY_RATE_BITS_SECOND);
|
||||
}
|
||||
else if (system_[sat] == "E")
|
||||
{
|
||||
samples_per_code_.push_back(round((float)fs_in_ / (Galileo_E1_CODE_CHIP_RATE_HZ
|
||||
/ Galileo_E1_B_CODE_LENGTH_CHIPS)));
|
||||
|
||||
num_of_codes_per_vector_.push_back((int)Galileo_E1_C_SECONDARY_CODE_LENGTH);
|
||||
data_bit_duration_ms_.push_back(1e3/Galileo_E1_B_SYMBOL_RATE_BPS);
|
||||
}
|
||||
}
|
||||
|
||||
random_ = new gr::random();
|
||||
|
||||
// std::cout << "fs_in: " << fs_in_ << std::endl;
|
||||
// std::cout << "data_flag: " << data_flag_ << std::endl;
|
||||
// std::cout << "noise_flag_: " << noise_flag_ << std::endl;
|
||||
// std::cout << "num_sats_: " << num_sats_ << std::endl;
|
||||
// std::cout << "vector_length_: " << vector_length_ << std::endl;
|
||||
// std::cout << "BW_BB_: " << BW_BB_ << std::endl;
|
||||
|
||||
// for (unsigned int i = 0; i < num_sats_; i++)
|
||||
// {
|
||||
// std::cout << "Sat " << i << ": " << std::endl;
|
||||
// std::cout << "System " << system_[i] << ": " << std::endl;
|
||||
// std::cout << " PRN: " << PRN_[i] << std::endl;
|
||||
// std::cout << " CN0: " << CN0_dB_[i] << std::endl;
|
||||
// std::cout << " Doppler: " << doppler_Hz_[i] << std::endl;
|
||||
// std::cout << " Delay: " << delay_chips_[i] << std::endl;
|
||||
// std::cout << "Samples per code = " << samples_per_code_[i] << std::endl;
|
||||
// std::cout << "codes per vector = " << num_of_codes_per_vector_[i] << std::endl;
|
||||
// std::cout << "data_bit_duration = " << data_bit_duration_ms_[i] << std::endl;
|
||||
// }
|
||||
}
|
||||
|
||||
void signal_generator_c::generate_codes()
|
||||
{
|
||||
sampled_code_data_.reset(new gr_complex*[num_sats_]);
|
||||
sampled_code_pilot_.reset(new gr_complex*[num_sats_]);
|
||||
|
||||
for (unsigned int sat = 0; sat < num_sats_; sat++)
|
||||
{
|
||||
if (posix_memalign((void**)&(sampled_code_data_[sat]), 16,
|
||||
vector_length_ * sizeof(gr_complex)) == 0){};
|
||||
|
||||
gr_complex code[samples_per_code_[sat]];
|
||||
|
||||
if (system_[sat] == "G")
|
||||
{
|
||||
// Generate one code-period of 1C signal
|
||||
gps_l1_ca_code_gen_complex_sampled(code, PRN_[sat], fs_in_,
|
||||
(int)GPS_L1_CA_CODE_LENGTH_CHIPS-delay_chips_[sat]);
|
||||
|
||||
// Obtain the desired CN0 assuming that Pn = 1.
|
||||
for (unsigned int i = 0; i < samples_per_code_[sat]; i++)
|
||||
{
|
||||
code[i] *= sqrt(pow(10,CN0_dB_[sat]/10)/BW_BB_);
|
||||
}
|
||||
|
||||
// Concatenate "num_of_codes_per_vector_" codes
|
||||
for (unsigned int i = 0; i < num_of_codes_per_vector_[sat]; i++)
|
||||
{
|
||||
memcpy(&(sampled_code_data_[sat][i*samples_per_code_[sat]]),
|
||||
code, sizeof(gr_complex)*samples_per_code_[sat]);
|
||||
}
|
||||
}
|
||||
else if (system_[sat] == "E")
|
||||
{
|
||||
// Generate one code-period of E1B signal
|
||||
bool cboc = true;
|
||||
char signal[3];
|
||||
strcpy(signal, "1B");
|
||||
|
||||
galileo_e1_code_gen_complex_sampled(code, signal, cboc, PRN_[sat], fs_in_,
|
||||
(int)Galileo_E1_B_CODE_LENGTH_CHIPS-delay_chips_[sat]);
|
||||
|
||||
// Obtain the desired CN0 assuming that Pn = 1.
|
||||
for (unsigned int i = 0; i < samples_per_code_[sat]; i++)
|
||||
{
|
||||
code[i] *= sqrt(pow(10,CN0_dB_[sat]/10)/BW_BB_/2);
|
||||
}
|
||||
|
||||
// Concatenate "num_of_codes_per_vector_" codes
|
||||
for (unsigned int i = 0; i < num_of_codes_per_vector_[sat]; i++)
|
||||
{
|
||||
memcpy(&(sampled_code_data_[sat][i*samples_per_code_[sat]]),
|
||||
code, sizeof(gr_complex)*samples_per_code_[sat]);
|
||||
}
|
||||
|
||||
// Generate E1C signal (25 code-periods, with secondary code)
|
||||
if (posix_memalign((void**)&(sampled_code_pilot_[sat]), 16,
|
||||
vector_length_ * sizeof(gr_complex)) == 0){};
|
||||
|
||||
strcpy(signal, "1C");
|
||||
|
||||
galileo_e1_code_gen_complex_sampled(sampled_code_pilot_[sat], signal, cboc, PRN_[sat], fs_in_,
|
||||
(int)Galileo_E1_B_CODE_LENGTH_CHIPS-delay_chips_[sat], true);
|
||||
|
||||
// Obtain the desired CN0 assuming that Pn = 1.
|
||||
for (unsigned int i = 0; i < vector_length_; i++)
|
||||
{
|
||||
sampled_code_pilot_[sat][i] *= sqrt(pow(10,CN0_dB_[sat]/10)/BW_BB_/2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Our virtual destructor.
|
||||
*/
|
||||
signal_generator_c::~signal_generator_c()
|
||||
{
|
||||
for (unsigned int sat = 0; sat < num_sats_; sat++)
|
||||
{
|
||||
free(sampled_code_data_[sat]);
|
||||
if (system_[sat] == "E")
|
||||
{
|
||||
free(sampled_code_pilot_[sat]);
|
||||
}
|
||||
}
|
||||
|
||||
delete random_;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
signal_generator_c::general_work (int noutput_items,
|
||||
gr_vector_int &ninput_items,
|
||||
gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items)
|
||||
{
|
||||
gr_complex *out = (gr_complex *) output_items[0];
|
||||
|
||||
unsigned int out_idx = 0;
|
||||
unsigned int i = 0;
|
||||
unsigned int k = 0;
|
||||
|
||||
for (out_idx = 0; out_idx < vector_length_; out_idx++)
|
||||
{
|
||||
out[out_idx] = gr_complex(0.0,0.0);
|
||||
}
|
||||
|
||||
for (unsigned int sat = 0; sat < num_sats_; sat++)
|
||||
{
|
||||
|
||||
float phase_step_rad = -(float)GPS_TWO_PI*doppler_Hz_[sat] / (float)fs_in_;
|
||||
fxp_nco(complex_phase_, vector_length_, start_phase_rad_[sat], phase_step_rad);
|
||||
start_phase_rad_[sat] += vector_length_ * phase_step_rad;
|
||||
|
||||
out_idx = 0;
|
||||
|
||||
if (system_[sat] == "G")
|
||||
{
|
||||
unsigned int delay_samples = (delay_chips_[sat] % (int)GPS_L1_CA_CODE_LENGTH_CHIPS)
|
||||
* samples_per_code_[sat] / GPS_L1_CA_CODE_LENGTH_CHIPS;
|
||||
|
||||
for (i = 0; i < num_of_codes_per_vector_[sat]; i++)
|
||||
{
|
||||
gr_complex prev_data_bit = current_data_bits_[sat];
|
||||
if (ms_counter_[sat] == 0 && data_flag_)
|
||||
{
|
||||
// New random data bit
|
||||
current_data_bits_[sat] = gr_complex((rand()%2) == 0 ? 1 : -1, 0);
|
||||
}
|
||||
|
||||
for (k = 0; k < delay_samples; k++)
|
||||
{
|
||||
out[out_idx] += sampled_code_data_[sat][out_idx]
|
||||
* prev_data_bit
|
||||
* complex_phase_[out_idx];
|
||||
out_idx++;
|
||||
}
|
||||
|
||||
for (k = delay_samples; k < samples_per_code_[sat]; k++)
|
||||
{
|
||||
out[out_idx] += sampled_code_data_[sat][out_idx]
|
||||
* current_data_bits_[sat]
|
||||
* complex_phase_[out_idx];
|
||||
out_idx++;
|
||||
}
|
||||
|
||||
ms_counter_[sat] = (ms_counter_[sat] + (int)round(1e3*GPS_L1_CA_CODE_PERIOD))
|
||||
% data_bit_duration_ms_[sat];
|
||||
}
|
||||
}
|
||||
|
||||
else if (system_[sat] == "E")
|
||||
{
|
||||
unsigned int delay_samples = (delay_chips_[sat] % (int)Galileo_E1_B_CODE_LENGTH_CHIPS)
|
||||
* samples_per_code_[sat] / Galileo_E1_B_CODE_LENGTH_CHIPS;
|
||||
|
||||
for (i = 0; i < num_of_codes_per_vector_[sat]; i++)
|
||||
{
|
||||
gr_complex prev_data_bit = current_data_bits_[sat];
|
||||
if (ms_counter_[sat] == 0 && data_flag_)
|
||||
{
|
||||
// New random data bit
|
||||
current_data_bits_[sat] = gr_complex((rand()%2) == 0 ? -1 : 1, 0);
|
||||
}
|
||||
|
||||
for (k = 0; k < delay_samples; k++)
|
||||
{
|
||||
out[out_idx] += (sampled_code_data_[sat][out_idx] * prev_data_bit
|
||||
- sampled_code_pilot_[sat][out_idx])
|
||||
* complex_phase_[out_idx];
|
||||
out_idx++;
|
||||
}
|
||||
|
||||
for (k = delay_samples; k < samples_per_code_[sat]; k++)
|
||||
{
|
||||
out[out_idx] += (sampled_code_data_[sat][out_idx] * current_data_bits_[sat]
|
||||
- sampled_code_pilot_[sat][out_idx])
|
||||
* complex_phase_[out_idx];
|
||||
out_idx++;
|
||||
}
|
||||
|
||||
ms_counter_[sat] = (ms_counter_[sat] + (int)round(1e3*Galileo_E1_CODE_PERIOD))
|
||||
% data_bit_duration_ms_[sat];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (noise_flag_)
|
||||
{
|
||||
for (out_idx = 0; out_idx < vector_length_; out_idx++)
|
||||
{
|
||||
out[out_idx] += gr_complex(random_->gasdev(),random_->gasdev());
|
||||
}
|
||||
}
|
||||
|
||||
// Tell runtime system how many output items we produced.
|
||||
return 1;
|
||||
}
|
||||
|
@ -0,0 +1,129 @@
|
||||
/*!
|
||||
* \file signal_generator_c.h
|
||||
* \brief GNU Radio source block that generates synthesized GNSS signal.
|
||||
* \author Marc Molina, 2013. marc.molina.pena@gmail.com
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2010-2013 (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_SIGNAL_GENERATOR_C_H
|
||||
#define GNSS_SDR_SIGNAL_GENERATOR_C_H
|
||||
|
||||
#include "gnss_signal.h"
|
||||
#include <gnuradio/random.h>
|
||||
#include <gnuradio/block.h>
|
||||
#include <boost/scoped_array.hpp>
|
||||
|
||||
|
||||
class signal_generator_c;
|
||||
|
||||
/*
|
||||
* We use boost::shared_ptr's instead of raw pointers for all access
|
||||
* to gr_blocks (and many other data structures). The shared_ptr gets
|
||||
* us transparent reference counting, which greatly simplifies storage
|
||||
* management issues. This is especially helpful in our hybrid
|
||||
* C++ / Python system.
|
||||
*
|
||||
* See http://www.boost.org/libs/smart_ptr/smart_ptr.htm
|
||||
*
|
||||
* As a convention, the _sptr suffix indicates a boost::shared_ptr
|
||||
*/
|
||||
typedef boost::shared_ptr<signal_generator_c> signal_generator_c_sptr;
|
||||
|
||||
/*!
|
||||
* \brief Return a shared_ptr to a new instance of gen_source.
|
||||
*
|
||||
* To avoid accidental use of raw pointers, gen_source's
|
||||
* constructor is private. signal_make_generator_c is the public
|
||||
* interface for creating new instances.
|
||||
*/
|
||||
signal_generator_c_sptr
|
||||
signal_make_generator_c (std::vector<std::string> system, const std::vector<unsigned int> &PRN,
|
||||
const std::vector<float> &CN0_dB, const std::vector<float> &doppler_Hz,
|
||||
const std::vector<unsigned int> &delay_chips, bool data_flag, bool noise_flag,
|
||||
unsigned int fs_in, unsigned int vector_length, float BW_BB);
|
||||
|
||||
/*!
|
||||
* \brief This class generates synthesized GNSS signal.
|
||||
* \ingroup block
|
||||
*
|
||||
* \sa gen_source for a version that subclasses gr_block.
|
||||
*/
|
||||
class signal_generator_c : public gr::block
|
||||
{
|
||||
private:
|
||||
// The friend declaration allows gen_source to
|
||||
// access the private constructor.
|
||||
|
||||
/* Create the signal_generator_c object*/
|
||||
friend signal_generator_c_sptr
|
||||
signal_make_generator_c (std::vector<std::string> system, const std::vector<unsigned int> &PRN,
|
||||
const std::vector<float> &CN0_dB, const std::vector<float> &doppler_Hz,
|
||||
const std::vector<unsigned int> &delay_chips, bool data_flag, bool noise_flag,
|
||||
unsigned int fs_in, unsigned int vector_length, float BW_BB);
|
||||
|
||||
signal_generator_c (std::vector<std::string> system, const std::vector<unsigned int> &PRN,
|
||||
const std::vector<float> &CN0_dB, const std::vector<float> &doppler_Hz,
|
||||
const std::vector<unsigned int> &delay_chips, bool data_flag, bool noise_flag,
|
||||
unsigned int fs_in, unsigned int vector_length, float BW_BB);
|
||||
|
||||
void init();
|
||||
void generate_codes();
|
||||
|
||||
std::vector<std::string> system_;
|
||||
std::vector<unsigned int> PRN_;
|
||||
std::vector<float> CN0_dB_;
|
||||
std::vector<float> doppler_Hz_;
|
||||
std::vector<unsigned int> delay_chips_;
|
||||
bool data_flag_;
|
||||
bool noise_flag_;
|
||||
unsigned int fs_in_;
|
||||
unsigned int num_sats_;
|
||||
unsigned int vector_length_;
|
||||
float BW_BB_;
|
||||
|
||||
std::vector<unsigned int> samples_per_code_;
|
||||
std::vector<unsigned int> num_of_codes_per_vector_;
|
||||
std::vector<unsigned int> data_bit_duration_ms_;
|
||||
std::vector<unsigned int> ms_counter_;
|
||||
std::vector<float> start_phase_rad_;
|
||||
std::vector<gr_complex> current_data_bits_;
|
||||
|
||||
boost::scoped_array<gr_complex*> sampled_code_data_;
|
||||
boost::scoped_array<gr_complex*> sampled_code_pilot_;
|
||||
gr::random* random_;
|
||||
gr_complex* complex_phase_;
|
||||
|
||||
public:
|
||||
~signal_generator_c (); // public destructor
|
||||
|
||||
// Where all the action really happens
|
||||
|
||||
int general_work (int noutput_items,
|
||||
gr_vector_int &ninput_items,
|
||||
gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items);
|
||||
};
|
||||
|
||||
#endif /* GNSS_SDR_SIGNAL_GENERATOR_C_H */
|
@ -74,7 +74,7 @@ if(RTLSDR_DRIVER)
|
||||
set(OPT_DRIVER_INCLUDE_DIRS ${OPT_DRIVER_INCLUDE_DIRS} ${RTL_DRIVER_INCLUDE_DIRS})
|
||||
endif(RTLSDR_DRIVER)
|
||||
|
||||
set(SIGNAL_SOURCE_ADAPTER_SOURCES file_signal_source.cc uhd_signal_source.cc ${OPT_DRIVER_SOURCES})
|
||||
set(SIGNAL_SOURCE_ADAPTER_SOURCES file_signal_source.cc gen_signal_source.cc uhd_signal_source.cc ${OPT_DRIVER_SOURCES})
|
||||
|
||||
|
||||
include_directories(
|
||||
|
115
src/algorithms/signal_source/adapters/gen_signal_source.cc
Normal file
115
src/algorithms/signal_source/adapters/gen_signal_source.cc
Normal file
@ -0,0 +1,115 @@
|
||||
/*!
|
||||
* \file gen_signal_source.cc
|
||||
* \brief It wraps blocks that generates synthesized GNSS signal and filters
|
||||
* it.
|
||||
* \author Marc Molina, 2013. marc.molina.pena@gmail.com
|
||||
*
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2010-2013 (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 "gen_signal_source.h"
|
||||
//#include "gnss_flowgraph.h"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <gnuradio/io_signature.h>
|
||||
#include <gnuradio/message.h>
|
||||
#include <glog/log_severity.h>
|
||||
#include <glog/logging.h>
|
||||
|
||||
using google::LogMessage;
|
||||
|
||||
// Constructor
|
||||
GenSignalSource::GenSignalSource(ConfigurationInterface *configuration,
|
||||
GNSSBlockInterface *signal_generator, GNSSBlockInterface *filter,
|
||||
std::string role, boost::shared_ptr<gr::msg_queue> queue) :
|
||||
signal_generator_(signal_generator),
|
||||
filter_(filter),
|
||||
role_(role),
|
||||
queue_(queue)
|
||||
{
|
||||
connected_ = false;
|
||||
}
|
||||
|
||||
|
||||
// Destructor
|
||||
GenSignalSource::~GenSignalSource()
|
||||
{
|
||||
delete signal_generator_;
|
||||
delete filter_;
|
||||
}
|
||||
|
||||
|
||||
void GenSignalSource::connect(gr::top_block_sptr top_block)
|
||||
{
|
||||
if (connected_)
|
||||
{
|
||||
LOG_AT_LEVEL(WARNING) << "Signal conditioner already connected internally";
|
||||
return;
|
||||
}
|
||||
|
||||
signal_generator_->connect(top_block);
|
||||
filter_->connect(top_block);
|
||||
|
||||
top_block->connect(signal_generator_->get_right_block(), 0,
|
||||
filter_->get_left_block(), 0);
|
||||
|
||||
DLOG(INFO) << "signal_generator -> filter";
|
||||
|
||||
connected_ = true;
|
||||
}
|
||||
|
||||
|
||||
void GenSignalSource::disconnect(gr::top_block_sptr top_block)
|
||||
{
|
||||
if (!connected_)
|
||||
{
|
||||
LOG_AT_LEVEL(WARNING) << "Signal conditioner already disconnected internally";
|
||||
return;
|
||||
}
|
||||
|
||||
top_block->disconnect(signal_generator_->get_right_block(), 0,
|
||||
filter_->get_left_block(), 0);
|
||||
|
||||
signal_generator_->disconnect(top_block);
|
||||
filter_->disconnect(top_block);
|
||||
|
||||
connected_ = false;
|
||||
}
|
||||
|
||||
|
||||
gr::basic_block_sptr GenSignalSource::get_left_block()
|
||||
{
|
||||
return signal_generator_->get_left_block();
|
||||
}
|
||||
|
||||
|
||||
gr::basic_block_sptr GenSignalSource::get_right_block()
|
||||
{
|
||||
return filter_->get_right_block();
|
||||
}
|
||||
|
80
src/algorithms/signal_source/adapters/gen_signal_source.h
Normal file
80
src/algorithms/signal_source/adapters/gen_signal_source.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*!
|
||||
* \file gen_signal_source.h
|
||||
* \brief It wraps blocks that generates synthesized GNSS signal and filters
|
||||
* it.
|
||||
* \author Marc Molina, 2013. marc.molina.pena@gmail.com
|
||||
*
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2010-2013 (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_GEN_SIGNAL_SOURCE_H_
|
||||
#define GNSS_SDR_GEN_SIGNAL_SOURCE_H_
|
||||
|
||||
#include <gnuradio/msg_queue.h>
|
||||
#include "gnss_block_interface.h"
|
||||
|
||||
|
||||
class ConfigurationInterface;
|
||||
|
||||
/*!
|
||||
* \brief This class wraps blocks that generates synthesized GNSS signal and
|
||||
* filters the signal.
|
||||
*/
|
||||
class GenSignalSource: public GNSSBlockInterface
|
||||
{
|
||||
public:
|
||||
//! Constructor
|
||||
GenSignalSource(ConfigurationInterface *configuration,
|
||||
GNSSBlockInterface *signal_generator, GNSSBlockInterface *filter,
|
||||
std::string role, boost::shared_ptr<gr::msg_queue> queue);
|
||||
|
||||
//! Virtual destructor
|
||||
virtual ~GenSignalSource();
|
||||
|
||||
void connect(gr::top_block_sptr top_block);
|
||||
void disconnect(gr::top_block_sptr top_block);
|
||||
gr::basic_block_sptr get_left_block();
|
||||
gr::basic_block_sptr get_right_block();
|
||||
|
||||
std::string role(){ return role_; }
|
||||
|
||||
//! Returns "Signal Source"
|
||||
std::string implementation(){ return "Signal Source"; }
|
||||
size_t item_size(){ return 0; }
|
||||
|
||||
GNSSBlockInterface *signal_generator(){ return signal_generator_; }
|
||||
GNSSBlockInterface *output_filter(){ return filter_; }
|
||||
|
||||
private:
|
||||
GNSSBlockInterface *signal_generator_;
|
||||
GNSSBlockInterface *filter_;
|
||||
std::string role_;
|
||||
std::string implementation_;
|
||||
bool connected_;
|
||||
boost::shared_ptr<gr::msg_queue> queue_;
|
||||
};
|
||||
|
||||
#endif /*GNSS_SDR_GEN_SIGNAL_SOURCE_H*/
|
@ -61,6 +61,7 @@ public:
|
||||
virtual void set_doppler_step(unsigned int doppler_step) = 0;
|
||||
virtual void set_channel_queue(concurrent_queue<int> *channel_internal_queue) = 0;
|
||||
virtual void init() = 0;
|
||||
virtual void set_local_code() = 0;
|
||||
virtual signed int mag() = 0;
|
||||
virtual void reset() = 0;
|
||||
};
|
||||
|
@ -48,7 +48,7 @@ const double Galileo_E1_SUB_CARRIER_A_RATE_HZ = 1.023e6; //!< Galileo E1 sub-car
|
||||
const double Galileo_E1_SUB_CARRIER_B_RATE_HZ = 6.138e6; //!< Galileo E1 sub-carrier 'b' rate [Hz]
|
||||
const double Galileo_E1_B_CODE_LENGTH_CHIPS = 4092.0; //!< Galileo E1-B code length [chips]
|
||||
const double Galileo_E1_B_SYMBOL_RATE_BPS = 250.0; //!< Galileo E1-B symbol rate [bits/second]
|
||||
|
||||
const double Galileo_E1_C_SECONDARY_CODE_LENGTH = 25.0; //!< Galileo E1-C secondary code length [chips]
|
||||
const int Galileo_E1_NUMBER_OF_CODES = 50;
|
||||
|
||||
// Galileo INAV Telemetry structure
|
||||
@ -188,4 +188,8 @@ const std::string Galileo_E1_C_PRIMARY_CODE[Galileo_E1_NUMBER_OF_CODES] = {
|
||||
"CD7AAC98501F29507EA4E0183E8A40D2E5117E47BB5D18D01A3732DE4C821DFE86521CBEA7DB29BE1148BD544ECC681689BCD1B41EAF755310B7659342F8EE11CB41550CC30E566E192796B66C1A83C0B28BACCFA6C393043A0A2CB89712BC1CCB174DE58E66896AF39C1CEED1E05B0435F8CF6FD920D100F51584FE24879987399481DBF27DDB6286B6353919E552E669290CE02AB4CD5113D7F484229F379C7332767EC69E4336439B05DE1C1E3563DD303A4F580BFF20A40E49CB0822F715ED0221EBCDB5DBAD751124B1715E82F37488265135B6C8BBCF4F801ECC4D3525FF189493AD4EFF0C042B070C4CA8FB1FDF43D79F06A6E4E3D35D7B07D4B728D5DC54EEDACBBBA1EDDCDC07ADF7DFCFEF835E44DF1FF66DAF2A7BAEBE218AC3B15E183044D6A8A89B3C101B40BED97ED5DF93BBC1B84931D56B8C822A6D058AC74CFA4C85D8B456698E82D5B7574C17B041E5F4BEED09F75012355CBC322B822C63F10C18A8F279E9A0E18E1FEF183D23E13894E31F6D046956FE8A647558228F6D4D6910151EC03937876B6ED7A078D33DAEB3F2239353BB8181E62B286BBC41588DE10F478A5CE5B508F205A41820356767B0A0ED4B8DB9EFE348362E9A90D6C30218B295B338B51C09239D02FC8A1E7DAAAB60AC37F5E67CFC88EEF69567B5C81A03B449F4ED38B9D295A36AA3503173F6F6F66D93CE72D753076040FACDE",
|
||||
"ADDCEDB50E907D20E826E6E8A0D30C20C74B2DF204EA784BAE9F618CAE33A3C937729DF9CB10BA2A4C33E0182A37200C0CC509729D828B8A2A20F283AC4F9306596684EA3FB5492A4C9F2DB459E7531C9F9C0950E7D9E93B3EE5912AE7E39AC8F4EC14B18F24E325003F477E347C5AC1B67CDB11AF3BBBBCD0AC3703024B5767AA67A208254F798684BFD1D3EACD757EEC77254950A146620400DB95E694574F739A991EBA771EBBDFF1056BB39A77DBE0636A032E17141332F951C57C6C90F348F165E3ABDD60D429D5D6BEC7E3E3463806F819EB2D212B3528A5EDE51F235AD100A35E890955F8A1DC51FDCB53EABCA2540997DD054C1F5B29462995B876B44D085904E55E1B838BEF600A992EB49CE078DF75AF3D0F137685AC0D07F0BE1EB87B63A41E74DDE869C8A683BDE60AF5D77FF18F7137495BCEFD0ED28F62F9C3E25D332B5F861D999FCDC0B4851A984A4DBB53401FD40351ADA4335C702BCC8D900C737507B990BDDBE91D201E3A0946DC968D43FD10D04B0B76667FF5B4291C2124B0124C6B710A6D1BCFAEB016B9DEEB0F7A4FE044CA4EA0CCD84B7682617C3A545071EC295B0663B3F577D562DE1D9DD80DE6A1EFD6D5991EB5246F1597B86D0E9A90CF6DB0EB2B8E7BAE9431E567F01AA98502C773742246467ABF911A91A51F6C1B9E0C3233DC1A37D17DB91A5F0F661B0EB5886964456C7818601BD0C"
|
||||
};
|
||||
|
||||
const std::string Galileo_E1_C_SECONDARY_CODE =
|
||||
"0011100000001010110110010";
|
||||
|
||||
#endif /* GNSS_SDR_GALILEO_E1_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user