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:
Luis Esteve 2013-07-23 18:03:07 +00:00
parent 5e6e66e60b
commit 8b10549fee
26 changed files with 1349 additions and 162 deletions

View File

@ -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)

View File

@ -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_)
{

View File

@ -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
*/

View File

@ -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);
}
}

View File

@ -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
*/

View File

@ -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_);
}

View File

@ -115,6 +115,8 @@ public:
*/
void init();
void set_local_code();
/*!
* \brief Returns the maximum peak of grid search
*/

View File

@ -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()
{

View File

@ -115,6 +115,8 @@ public:
*/
void init();
void set_local_code();
/*!
* \brief Returns the maximum peak of grid search
*/

View File

@ -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);
}

View File

@ -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:
/*!

View File

@ -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());
}

View File

@ -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);
}

View File

@ -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_ */

View 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)

View 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})

View 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_;
}

View 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_*/

View File

@ -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})

View File

@ -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;
}

View File

@ -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 */

View File

@ -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(

View 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();
}

View 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*/

View File

@ -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;
};

View File

@ -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_ */