Code cleaning

git-svn-id: https://svn.code.sf.net/p/gnss-sdr/code/trunk@128 64b25241-fba3-4117-9849-534c7e92360d
This commit is contained in:
Carles Fernandez 2012-01-16 18:27:31 +00:00
parent 276f7dd2dc
commit 60da2f4336
14 changed files with 389 additions and 296 deletions

View File

@ -61,27 +61,16 @@ gps_l1_ca_pcps_acquisition_cc::gps_l1_ca_pcps_acquisition_cc(
sizeof(gr_complex) * samples_per_ms), gr_make_io_signature(0, 0, sizeof(gr_complex) * samples_per_ms), gr_make_io_signature(0, 0,
sizeof(gr_complex) * samples_per_ms)) sizeof(gr_complex) * samples_per_ms))
{ {
d_sample_counter = 0; // SAMPLE COUNTER
// SAMPLE COUNTER
d_sample_counter = 0;
d_active = false; d_active = false;
d_dump = dump;
d_queue = queue; d_queue = queue;
d_dump_filename = dump_filename;
d_freq = freq; d_freq = freq;
d_fs_in = fs_in; d_fs_in = fs_in;
d_samples_per_ms = samples_per_ms; d_samples_per_ms = samples_per_ms;
d_sampled_ms = sampled_ms; d_sampled_ms = sampled_ms;
d_doppler_max = doppler_max; d_doppler_max = doppler_max;
d_satellite = 0; d_satellite = 0;
d_fft_size = d_sampled_ms * d_samples_per_ms; d_fft_size = d_sampled_ms * d_samples_per_ms;
d_doppler_freq = 0.0; d_doppler_freq = 0.0;
d_code_phase = 0; d_code_phase = 0;
d_mag = 0; d_mag = 0;
@ -97,6 +86,9 @@ gps_l1_ca_pcps_acquisition_cc::gps_l1_ca_pcps_acquisition_cc(
// Inverse FFT // Inverse FFT
d_ifft = new gri_fft_complex(d_fft_size, false); d_ifft = new gri_fft_complex(d_fft_size, false);
d_dump = dump;
d_dump_filename = dump_filename;
DLOG(INFO) << "fs in " << d_fs_in; DLOG(INFO) << "fs in " << d_fs_in;
DLOG(INFO) << "samples per ms " << d_samples_per_ms; DLOG(INFO) << "samples per ms " << d_samples_per_ms;
DLOG(INFO) << "doppler max " << d_doppler_max; DLOG(INFO) << "doppler max " << d_doppler_max;
@ -121,6 +113,9 @@ gps_l1_ca_pcps_acquisition_cc::~gps_l1_ca_pcps_acquisition_cc()
} }
} }
void gps_l1_ca_pcps_acquisition_cc::set_satellite(unsigned int satellite) void gps_l1_ca_pcps_acquisition_cc::set_satellite(unsigned int satellite)
{ {
d_satellite = satellite; d_satellite = satellite;
@ -136,11 +131,13 @@ void gps_l1_ca_pcps_acquisition_cc::set_satellite(unsigned int satellite)
//TODO Optimize it ! try conj() //TODO Optimize it ! try conj()
for (unsigned int i = 0; i < d_fft_size; i++) for (unsigned int i = 0; i < d_fft_size; i++)
{ {
d_fft_codes[i] = std::complex<float>( //d_fft_codes[i] = std::complex<float>(
d_fft_if->get_outbuf()[i].real(), // d_fft_if->get_outbuf()[i].real(),
-d_fft_if->get_outbuf()[i].imag()); // -d_fft_if->get_outbuf()[i].imag());
d_fft_codes[i] = std::complex<float>(conj(d_fft_if->get_outbuf()[i]));
d_fft_codes[i] = d_fft_codes[i] / (float)d_fft_size; //to correct the scale factor introduced by FFTW d_fft_codes[i] = d_fft_codes[i] / (float)d_fft_size; //to correct the scale factor introduced by FFTW
} }
//memcpy(d_fft_codes,d_fft_if->get_outbuf(),sizeof(gr_complex)*d_samples_per_ms); //memcpy(d_fft_codes,d_fft_if->get_outbuf(),sizeof(gr_complex)*d_samples_per_ms);
// std::stringstream filename; // std::stringstream filename;
@ -156,6 +153,10 @@ void gps_l1_ca_pcps_acquisition_cc::set_satellite(unsigned int satellite)
// //d_dump_file.write((char*)d_sine_if, n); //to be read with read_complex_binary() -> test OK // //d_dump_file.write((char*)d_sine_if, n); //to be read with read_complex_binary() -> test OK
// d_dump_file.close(); // d_dump_file.close();
} }
signed int gps_l1_ca_pcps_acquisition_cc::prn_code_phase() signed int gps_l1_ca_pcps_acquisition_cc::prn_code_phase()
{ {
return d_code_phase; return d_code_phase;
@ -166,9 +167,9 @@ int gps_l1_ca_pcps_acquisition_cc::general_work(int noutput_items,
gr_vector_void_star &output_items) gr_vector_void_star &output_items)
{ {
/*! /*
* By J.Arribas * By J.Arribas
* Acquisition A strategy (Kay Borre book + CFAR threshold): * Acquisition strategy (Kay Borre book + CFAR threshold):
* 1. Compute the input signal power estimation * 1. Compute the input signal power estimation
* 2. Doppler serial search loop * 2. Doppler serial search loop
* 3. Perform the FFT-based circular convolution (parallel time search) * 3. Perform the FFT-based circular convolution (parallel time search)
@ -178,159 +179,154 @@ int gps_l1_ca_pcps_acquisition_cc::general_work(int noutput_items,
*/ */
if (!d_active) if (!d_active)
{ {
d_sample_counter += d_fft_size * noutput_items; // sample counter d_sample_counter += d_fft_size * noutput_items; // sample counter
consume_each(noutput_items); consume_each(noutput_items);
} }
else else
{
d_sample_counter += d_fft_size; // sample counter
//restart acquisition variables
d_code_phase = 0;
d_doppler_freq = 0;
d_mag = 0.0;
d_input_power = 0.0;
// initialize acquisition algorithm
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
//aux vars
unsigned int i;
std::stringstream filename;
std::streamsize n = 2 * sizeof(float) * (d_fft_size); // complex file write
LOG_AT_LEVEL(INFO) << "Channel: " << d_channel
<< " , doing acquisition of satellite: " << d_satellite
<< " ,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
//! \TODO try norm()
for (i = 0; i < d_fft_size; i++)
{ {
d_input_power += std::abs(in[i]) * std::abs(in[i]); d_sample_counter += d_fft_size; // sample counter
}
d_input_power = d_input_power / (float)d_fft_size; //restart acquisition variables
// 2- Doppler frequency search loop d_code_phase = 0;
for (doppler = (int)(-d_doppler_max); doppler < (int)d_doppler_max; doppler d_doppler_freq = 0;
+= d_doppler_step) d_mag = 0.0;
{ // doppler search steps d_input_power = 0.0;
//Perform the carrier wipe-off
sine_gen_complex(d_sine_if, d_freq + doppler, d_fs_in, d_fft_size); // initialize acquisition algorithm
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
//aux vars
unsigned int i;
DLOG(INFO) << "Channel: " << d_channel
<< " , doing acquisition of satellite: " << d_satellite
<< " ,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++) for (i = 0; i < d_fft_size; i++)
{ {
d_fft_if->get_inbuf()[i] = in[i] * d_sine_if[i]; d_input_power += std::norm(in[i]);
} }
//3- Perform the FFT-based circular convolution (parallel time search) d_input_power = d_input_power / (float)d_fft_size;
d_fft_if->execute();
//TODO Optimize me // 2- Doppler frequency search loop
for (i = 0; i < d_fft_size; i++) for (doppler = (int)(-d_doppler_max); doppler < (int)d_doppler_max; doppler += d_doppler_step)
{ {
d_ifft->get_inbuf()[i] = (d_fft_if->get_outbuf()[i] // doppler search steps
* d_fft_codes[i]) / (float)d_fft_size; //Perform the carrier wipe-off
} sine_gen_complex(d_sine_if, d_freq + doppler, d_fs_in, d_fft_size);
d_ifft->execute(); for (i = 0; i < d_fft_size; i++)
{
d_fft_if->get_inbuf()[i] = in[i] * d_sine_if[i];
}
// old version //3- Perform the FFT-based circular convolution (parallel time search)
//x86_gr_complex_mag(d_ifft->get_outbuf(), d_fft_size); // d_ifft->get_outbuf()=|abs(·)|^2 and the array is converted from CPX->Float d_fft_if->execute();
//x86_float_max((float*)d_ifft->get_outbuf(), &indext, &magt, for (i = 0; i < d_fft_size; i++)
// d_fft_size); // find max of |abs(·)|^2 -> index and magt {
d_ifft->get_inbuf()[i] = (d_fft_if->get_outbuf()[i]
* d_fft_codes[i]) / (float)d_fft_size;
}
d_ifft->execute();
// C++ version // Search maximum
indext=0; indext = 0;
magt=0; magt = 0;
for (i = 0; i < d_fft_size; i++) for (i = 0; i < d_fft_size; i++)
{ {
tmp_magt=std::norm(d_ifft->get_outbuf()[i]); tmp_magt = std::norm(d_ifft->get_outbuf()[i]);
if (tmp_magt>magt){ if (tmp_magt > magt)
magt=tmp_magt; {
indext=i; magt = tmp_magt;
} indext = i;
} }
}
// Record results to files // Record results to files
if (d_dump) if (d_dump)
{ {
filename.str(""); std::stringstream filename;
filename << "./data/fft_" << doppler << "_.dat"; std::streamsize n = 2 * sizeof(float) * (d_fft_size); // complex file write
std::cout << filename.str().c_str(); filename.str("");
std::cout << ".\n"; filename << "./data/fft_" << doppler << "_.dat";
d_dump_file.open(filename.str().c_str(), std::ios::out std::cout << filename.str().c_str();
| std::ios::binary); std::cout << ".\n";
d_dump_file.write((char*)d_ifft->get_outbuf(), n); //write directly |abs(·)|^2 in this Doppler bin d_dump_file.open(filename.str().c_str(), std::ios::out
d_dump_file.close(); | std::ios::binary);
} d_dump_file.write((char*)d_ifft->get_outbuf(), n); //write directly |abs(á)|^2 in this Doppler bin?
// 4- record the maximum peak and the associated synchronization parameters d_dump_file.close();
if (d_mag < magt) }
{
d_mag = magt; // 4- record the maximum peak and the associated synchronization parameters
d_code_phase = indext; if (d_mag < magt)
d_doppler_freq = doppler; {
} d_mag = magt;
d_code_phase = indext;
d_doppler_freq = doppler;
}
}
// 5- Compute the test statistics and compare to the threshold
d_test_statistics = 2 * d_fft_size * d_mag / d_input_power;
// 6- Declare positive or negative acquisition using a message queue
if (d_test_statistics > d_threshold)
{
positive_acquisition = true;
d_acq_sample_stamp = d_sample_counter;
DLOG(INFO) << "positive acquisition";
DLOG(INFO) << "satellite " << d_satellite;
DLOG(INFO) << "sample_stamp " << d_sample_counter;
DLOG(INFO) << "test statistics value " << d_test_statistics;
DLOG(INFO) << "test statistics threshold " << d_threshold;
DLOG(INFO) << "code phase " << d_code_phase;
DLOG(INFO) << "doppler " << d_doppler_freq;
DLOG(INFO) << "magnitude " << d_mag;
DLOG(INFO) << "input signal power " << d_input_power;
}
else
{
DLOG(INFO) << "negative acquisition";
DLOG(INFO) << "satellite " << d_satellite;
DLOG(INFO) << "sample_stamp " << d_sample_counter;
DLOG(INFO) << "test statistics value " << d_test_statistics;
DLOG(INFO) << "test statistics threshold " << d_threshold;
DLOG(INFO) << "code phase " << d_code_phase;
DLOG(INFO) << "doppler " << d_doppler_freq;
DLOG(INFO) << "magnitude " << d_mag;
DLOG(INFO) << "input signal power " << d_input_power;
}
d_active = false;
if (positive_acquisition)
{
acquisition_message = 1;
}
else
{
acquisition_message = 2;
}
d_channel_internal_queue->push(acquisition_message);
consume_each(1);
} }
// 5- Compute the test statistics and compare to the threshold
d_test_statistics = 2*d_fft_size*d_mag / d_input_power;
// 6- Declare positive or negative acquisition using a message queue
if (d_test_statistics > d_threshold)
{ //0.004
positive_acquisition = true;
d_acq_sample_stamp = d_sample_counter;
LOG_AT_LEVEL(INFO) << "positive acquisition";
LOG_AT_LEVEL(INFO) << "satellite " << d_satellite;
LOG_AT_LEVEL(INFO) << "sample_stamp " << d_sample_counter;
LOG_AT_LEVEL(INFO) << "test statistics value "
<< d_test_statistics;
LOG_AT_LEVEL(INFO) << "test statistics threshold " << d_threshold;
LOG_AT_LEVEL(INFO) << "code phase " << d_code_phase;
LOG_AT_LEVEL(INFO) << "doppler " << d_doppler_freq;
LOG_AT_LEVEL(INFO) << "magnitude " << d_mag;
LOG_AT_LEVEL(INFO) << "input signal power " << d_input_power;
}
else
{
LOG_AT_LEVEL(INFO) << "negative acquisition";
LOG_AT_LEVEL(INFO) << "satellite " << d_satellite;
LOG_AT_LEVEL(INFO) << "sample_stamp " << d_sample_counter;
LOG_AT_LEVEL(INFO) << "test statistics value "
<< d_test_statistics;
LOG_AT_LEVEL(INFO) << "test statistics threshold " << d_threshold;
LOG_AT_LEVEL(INFO) << "code phase " << d_code_phase;
LOG_AT_LEVEL(INFO) << "doppler " << d_doppler_freq;
LOG_AT_LEVEL(INFO) << "magnitude " << d_mag;
LOG_AT_LEVEL(INFO) << "input signal power " << d_input_power;
}
d_active = false;
if (positive_acquisition)
{
acquisition_message = 1;
}
else
{
acquisition_message = 2;
}
d_channel_internal_queue->push(acquisition_message);
consume_each(1);
}
return 0; return 0;
} }

View File

@ -157,11 +157,16 @@ void gps_l1_ca_tong_pcps_acquisition_cc::set_satellite(unsigned int satellite)
-d_fft_if->get_outbuf()[i].imag()); -d_fft_if->get_outbuf()[i].imag());
} }
} }
signed int gps_l1_ca_tong_pcps_acquisition_cc::prn_code_phase() signed int gps_l1_ca_tong_pcps_acquisition_cc::prn_code_phase()
{ {
return d_code_phase; return d_code_phase;
} }
int gps_l1_ca_tong_pcps_acquisition_cc::general_work(int noutput_items, int gps_l1_ca_tong_pcps_acquisition_cc::general_work(int noutput_items,
gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items) gr_vector_void_star &output_items)

View File

@ -71,19 +71,19 @@ public:
gr_basic_block_sptr get_left_block(); gr_basic_block_sptr get_left_block();
gr_basic_block_sptr get_right_block(); gr_basic_block_sptr get_right_block();
std::string role(){ return role_;} std::string role(){ return role_; }
std::string implementation(){ return "Channel";} std::string implementation(){ return "Channel"; }
size_t item_size(){ return 0;} size_t item_size(){ return 0; }
unsigned int satellite(){ return satellite_;} unsigned int satellite(){ return satellite_; }
AcquisitionInterface* acquisition(){ return acq_;} AcquisitionInterface* acquisition(){ return acq_; }
TrackingInterface* tracking(){ return trk_;} TrackingInterface* tracking(){ return trk_; }
TelemetryDecoderInterface* telemetry(){ return nav_;} TelemetryDecoderInterface* telemetry(){ return nav_; }
void start_acquisition(); void start_acquisition();
void set_satellite(unsigned int satellite); void set_satellite(unsigned int satellite);

View File

@ -7,18 +7,19 @@
/*! /*!
* The SV ID is _prn=ID -1 * The SV ID is _prn=ID -1
*/ */
void code_gen_conplex(std::complex<float>* _dest, int32 _prn, unsigned int _chip_shift) { void code_gen_conplex(std::complex<float>* _dest, signed int _prn, unsigned int _chip_shift)
{
uint32 G1[1023]; unsigned int G1[1023];
uint32 G2[1023]; unsigned int G2[1023];
uint32 G1_register[10], G2_register[10]; unsigned int G1_register[10], G2_register[10];
uint32 feedback1, feedback2; unsigned int feedback1, feedback2;
uint32 lcv, lcv2; unsigned int lcv, lcv2;
uint32 delay; unsigned int delay;
int32 prn = _prn-1; //Move the PRN code to fit an array indices signed int prn = _prn-1; //Move the PRN code to fit an array indices
/* G2 Delays as defined in GPS-ISD-200D */ /* G2 Delays as defined in GPS-ISD-200D */
int32 delays[51] = {5, 6, 7, 8, 17, 18, 139, 140, 141, 251, 252, 254 ,255, 256, 257, 258, 469, 470, 471, 472, signed int delays[51] = {5, 6, 7, 8, 17, 18, 139, 140, 141, 251, 252, 254 ,255, 256, 257, 258, 469, 470, 471, 472,
473, 474, 509, 512, 513, 514, 515, 516, 859, 860, 861, 862, 145, 175, 52, 21, 237, 235, 886, 657, 634, 762, 473, 474, 509, 512, 513, 514, 515, 516, 859, 860, 861, 862, 145, 175, 52, 21, 237, 235, 886, 657, 634, 762,
355, 1012, 176, 603, 130, 359, 595, 68, 386}; 355, 1012, 176, 603, 130, 359, 595, 68, 386};
@ -43,8 +44,8 @@ void code_gen_conplex(std::complex<float>* _dest, int32 _prn, unsigned int _chip
for(lcv2 = 0; lcv2 < 9; lcv2++) for(lcv2 = 0; lcv2 < 9; lcv2++)
{ {
G1_register[lcv2] = G1_register[lcv2+1]; G1_register[lcv2] = G1_register[lcv2 + 1];
G2_register[lcv2] = G2_register[lcv2+1]; G2_register[lcv2] = G2_register[lcv2 + 1];
} }
G1_register[9] = feedback1; G1_register[9] = feedback1;
@ -53,13 +54,13 @@ void code_gen_conplex(std::complex<float>* _dest, int32 _prn, unsigned int _chip
/* Set the delay */ /* Set the delay */
delay = 1023 - delays[prn]; delay = 1023 - delays[prn];
delay+=_chip_shift; delay += _chip_shift;
delay %= 1023; delay %= 1023;
/* Generate PRN from G1 and G2 Registers */ /* Generate PRN from G1 and G2 Registers */
for(lcv = 0; lcv < 1023; lcv++) for(lcv = 0; lcv < 1023; lcv++)
{ {
_dest[lcv] = std::complex<float>(G1[(lcv+_chip_shift)%1023]^G2[delay], 0); _dest[lcv] = std::complex<float>(G1[(lcv + _chip_shift)%1023]^G2[delay], 0);
if(_dest[lcv].real()==0.0) //javi if(_dest[lcv].real() == 0.0) //javi
{ {
_dest[lcv].real(-1.0); _dest[lcv].real(-1.0);
} }
@ -75,19 +76,19 @@ void code_gen_conplex(std::complex<float>* _dest, int32 _prn, unsigned int _chip
/*! /*!
* code_gen, generate the given prn code * code_gen, generate the given prn code
* */ * */
int32 code_gen(CPX *_dest, int32 _prn) signed int code_gen(CPX *_dest, signed int _prn)
{ {
uint32 G1[1023]; unsigned int G1[1023];
uint32 G2[1023]; unsigned int G2[1023];
uint32 G1_register[10], G2_register[10]; unsigned int G1_register[10], G2_register[10];
uint32 feedback1, feedback2; unsigned int feedback1, feedback2;
uint32 lcv, lcv2; unsigned int lcv, lcv2;
uint32 delay; unsigned int delay;
int32 prn = _prn-1; //Move the PRN code to fit an array indices signed int prn = _prn-1; //Move the PRN code to fit an array indices
/* G2 Delays as defined in GPS-ISD-200D */ /* G2 Delays as defined in GPS-ISD-200D */
int32 delays[51] = {5, 6, 7, 8, 17, 18, 139, 140, 141, 251, 252, 254 ,255, 256, 257, 258, 469, 470, 471, 472, signed int delays[51] = {5, 6, 7, 8, 17, 18, 139, 140, 141, 251, 252, 254 ,255, 256, 257, 258, 469, 470, 471, 472,
473, 474, 509, 512, 513, 514, 515, 516, 859, 860, 861, 862, 145, 175, 52, 21, 237, 235, 886, 657, 634, 762, 473, 474, 509, 512, 513, 514, 515, 516, 859, 860, 861, 862, 145, 175, 52, 21, 237, 235, 886, 657, 634, 762,
355, 1012, 176, 603, 130, 359, 595, 68, 386}; 355, 1012, 176, 603, 130, 359, 595, 68, 386};
@ -143,15 +144,15 @@ int32 code_gen(CPX *_dest, int32 _prn)
/*! /*!
* code_gen_complex_sampled, generate GPS L1 C/A code complex for the desired SV ID and sampled to specific sampling frequency * code_gen_complex_sampled, generate GPS L1 C/A code complex for the desired SV ID and sampled to specific sampling frequency
*/ */
void code_gen_complex_sampled(std::complex<float>* _dest, unsigned int _prn, int32 _fs, unsigned int _chip_shift) void code_gen_complex_sampled(std::complex<float>* _dest, unsigned int _prn, signed int _fs, unsigned int _chip_shift)
{ {
// 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::complex<float> _code[1023]; std::complex<float> _code[1023];
int32 _samplesPerCode,_codeValueIndex; signed int _samplesPerCode,_codeValueIndex;
float _ts; float _ts;
float _tc; float _tc;
const int32 _codeFreqBasis=1023000; //Hz const signed int _codeFreqBasis=1023000; //Hz
const int32 _codeLength=1023; const signed int _codeLength=1023;
//--- Find number of samples per spreading code ---------------------------- //--- Find number of samples per spreading code ----------------------------
_samplesPerCode = round(_fs / (_codeFreqBasis / _codeLength)); _samplesPerCode = round(_fs / (_codeFreqBasis / _codeLength));
@ -163,7 +164,7 @@ void code_gen_complex_sampled(std::complex<float>* _dest, unsigned int _prn, int
//std::cout<<"ts="<<_ts<<std::endl; //std::cout<<"ts="<<_ts<<std::endl;
//std::cout<<"tc="<<_tc<<std::endl; //std::cout<<"tc="<<_tc<<std::endl;
//std::cout<<"sv="<<_prn<<std::endl; //std::cout<<"sv="<<_prn<<std::endl;
for (int32 i=0;i<_samplesPerCode;i++) for (signed int i=0;i<_samplesPerCode;i++)
{ {
//=== Digitizing ======================================================= //=== Digitizing =======================================================
@ -235,10 +236,10 @@ void sine_gen_complex(std::complex<float>* _dest, double _f, double _fs, unsigne
/*----------------------------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------------------------*/
void sine_gen(CPX *_dest, double _f, double _fs, int32 _samps, double _p) void sine_gen(CPX *_dest, double _f, double _fs, signed int _samps, double _p)
{ {
int32 lcv; signed int lcv;
int16 c, s; int16 c, s;
double phase, phase_step; double phase, phase_step;
@ -263,10 +264,10 @@ void sine_gen(CPX *_dest, double _f, double _fs, int32 _samps, double _p)
/*! /*!
* wipeoff_gen, generate a full scale sinusoid of frequency f with sampling frequency fs for _samps samps and put it into _dest * wipeoff_gen, generate a full scale sinusoid of frequency f with sampling frequency fs for _samps samps and put it into _dest
* */ * */
void wipeoff_gen(MIX *_dest, double _f, double _fs, int32 _samps) void wipeoff_gen(MIX *_dest, double _f, double _fs, signed int _samps)
{ {
int32 lcv; signed int lcv;
int16 c, s; int16 c, s;
double phase, phase_step; double phase, phase_step;
@ -289,14 +290,14 @@ void wipeoff_gen(MIX *_dest, double _f, double _fs, int32 _samps)
/*----------------------------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------------------------*/
void downsample(CPX *_dest, CPX *_source, double _fdest, double _fsource, int32 _samps) void downsample(CPX *_dest, CPX *_source, double _fdest, double _fsource, signed int _samps)
{ {
int32 lcv, k; signed int lcv, k;
uint32 phase_step; unsigned int phase_step;
uint32 lphase, phase; unsigned int lphase, phase;
phase_step = (uint32)floor((double)4294967296.0*_fdest/_fsource); phase_step = (unsigned int)floor((double)4294967296.0*_fdest/_fsource);
k = lphase = phase = 0; k = lphase = phase = 0;
@ -325,9 +326,9 @@ void downsample(CPX *_dest, CPX *_source, double _fdest, double _fsource, int32
/*! /*!
* Gather statistics and run AGC * Gather statistics and run AGC
* */ * */
int32 run_agc(CPX *_buff, int32 _samps, int32 _bits, int32 _scale) signed int run_agc(CPX *_buff, signed int _samps, signed int _bits, signed int _scale)
{ {
int32 lcv, num; signed int lcv, num;
int16 max, *p; int16 max, *p;
int16 val; int16 val;
@ -366,11 +367,11 @@ int32 run_agc(CPX *_buff, int32 _samps, int32 _bits, int32 _scale)
/*! /*!
* Get a rough first guess of scale value to quickly initialize agc * Get a rough first guess of scale value to quickly initialize agc
* */ * */
void init_agc(CPX *_buff, int32 _samps, int32 bits, int32 *scale) void init_agc(CPX *_buff, signed int _samps, signed int bits, signed int *scale)
{ {
int32 lcv; signed int lcv;
int16 *p; int16 *p;
int32 max; signed int max;
p = (int16 *)&_buff[0]; p = (int16 *)&_buff[0];

View File

@ -42,7 +42,7 @@
#include <glog/logging.h> #include <glog/logging.h>
#include "control_message_factory.h" #include "control_message_factory.h"
#define _lrotl(X,N) ((X << N) ^ (X >> (32-N))) //!< Used in the parity check algorithm #define _lrotl(X,N) ((X << N) ^ (X >> (32-N))) // Used in the parity check algorithm
using google::LogMessage; using google::LogMessage;
@ -80,19 +80,19 @@ gps_l1_ca_telemetry_decoder_cc::gps_l1_ca_telemetry_decoder_cc(unsigned int sate
d_dump = dump; d_dump = dump;
d_satellite = satellite; d_satellite = satellite;
d_vector_length = vector_length; d_vector_length = vector_length;
d_samples_per_bit = 20; // it is exactly 1000*(1/50)=20 d_samples_per_bit = ( GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS ) / GPS_CA_TELEMETRY_RATE_BITS_SECOND;
d_fs_in = fs_in; d_fs_in = fs_in;
d_preamble_duration_seconds = (1.0/(float)GPS_CA_TELEMETRY_RATE_BITS_SECOND)*(float)GPS_CA_PREAMBLE_LENGTH_BITS; d_preamble_duration_seconds = (1.0 / GPS_CA_TELEMETRY_RATE_BITS_SECOND) * GPS_CA_PREAMBLE_LENGTH_BITS;
//std::cout<<"d_preamble_duration_seconds="<<d_preamble_duration_seconds<<"\r\n"; //std::cout<<"d_preamble_duration_seconds="<<d_preamble_duration_seconds<<"\r\n";
// set the preamble // set the preamble
unsigned short int preambles_bits[8] = GPS_PREAMBLE; unsigned short int preambles_bits[GPS_CA_PREAMBLE_LENGTH_BITS] = GPS_PREAMBLE;
memcpy((unsigned short int*)this->d_preambles_bits, (unsigned short int*)preambles_bits, 8*sizeof(unsigned short int)); memcpy((unsigned short int*)this->d_preambles_bits, (unsigned short int*)preambles_bits, GPS_CA_PREAMBLE_LENGTH_BITS*sizeof(unsigned short int));
// preamble bits to sampled symbols // preamble bits to sampled symbols
d_preambles_symbols = (signed int*)malloc(sizeof(signed int)*8*d_samples_per_bit); d_preambles_symbols = (signed int*)malloc(sizeof(signed int) * GPS_CA_PREAMBLE_LENGTH_BITS * d_samples_per_bit);
int n = 0; int n = 0;
for (int i=0; i<8; i++) for (int i=0; i<GPS_CA_PREAMBLE_LENGTH_BITS; i++)
{ {
for (unsigned int j=0; j<d_samples_per_bit; j++) for (unsigned int j=0; j<d_samples_per_bit; j++)
{ {
@ -219,7 +219,7 @@ int gps_l1_ca_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_i
{ {
d_GPS_FSM.Event_gps_word_preamble(); d_GPS_FSM.Event_gps_word_preamble();
d_preamble_index = d_sample_counter;//record the preamble sample stamp d_preamble_index = d_sample_counter;//record the preamble sample stamp
std::cout << "Preamble detection for SAT " << d_satellite<< std::endl; std::cout << "Preamble detection for SAT " << d_satellite << std::endl;
d_symbol_accumulator = 0; //sync the symbol to bits integrator d_symbol_accumulator = 0; //sync the symbol to bits integrator
d_symbol_accumulator_counter = 0; d_symbol_accumulator_counter = 0;
d_frame_bit_index = 8; d_frame_bit_index = 8;
@ -227,12 +227,12 @@ int gps_l1_ca_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_i
} }
else if (d_stat == 1) //check 6 seconds of preample separation else if (d_stat == 1) //check 6 seconds of preample separation
{ {
preamble_diff=abs(d_sample_counter-d_preamble_index); preamble_diff = abs(d_sample_counter - d_preamble_index);
if (abs(preamble_diff - 6000) < 1) if (abs(preamble_diff - 6000) < 1)
{ {
d_GPS_FSM.Event_gps_word_preamble(); d_GPS_FSM.Event_gps_word_preamble();
d_flag_preamble = true; d_flag_preamble = true;
d_preamble_index = d_sample_counter;//record the preamble sample stamp (t_P) d_preamble_index = d_sample_counter; //record the preamble sample stamp (t_P)
d_preamble_time_seconds = in[2][0] - d_preamble_duration_seconds; //record the PRN start sample index associated to the preamble d_preamble_time_seconds = in[2][0] - d_preamble_duration_seconds; //record the PRN start sample index associated to the preamble
d_preamble_code_phase_seconds = in[4][0]; d_preamble_code_phase_seconds = in[4][0];
@ -285,11 +285,11 @@ int gps_l1_ca_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_i
// prepare the extended frame [-2 -1 0 ... 30] // prepare the extended frame [-2 -1 0 ... 30]
if (d_prev_GPS_frame_4bytes & 0x00000001) if (d_prev_GPS_frame_4bytes & 0x00000001)
{ {
d_GPS_frame_4bytes = d_GPS_frame_4bytes|0x40000000; d_GPS_frame_4bytes = d_GPS_frame_4bytes | 0x40000000;
} }
if (d_prev_GPS_frame_4bytes & 0x00000002) if (d_prev_GPS_frame_4bytes & 0x00000002)
{ {
d_GPS_frame_4bytes = d_GPS_frame_4bytes|0x80000000; d_GPS_frame_4bytes = d_GPS_frame_4bytes | 0x80000000;
} }
/* Check that the 2 most recently logged words pass parity. Have to first /* Check that the 2 most recently logged words pass parity. Have to first
invert the data bits according to bit 30 of the previous word. */ invert the data bits according to bit 30 of the previous word. */
@ -299,7 +299,7 @@ int gps_l1_ca_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_i
} }
if (gps_l1_ca_telemetry_decoder_cc::gps_word_parityCheck(d_GPS_frame_4bytes)) if (gps_l1_ca_telemetry_decoder_cc::gps_word_parityCheck(d_GPS_frame_4bytes))
{ {
memcpy(&d_GPS_FSM.d_GPS_frame_4bytes,&d_GPS_frame_4bytes,sizeof(char)*4); memcpy(&d_GPS_FSM.d_GPS_frame_4bytes, &d_GPS_frame_4bytes, sizeof(char)*4);
d_GPS_FSM.d_preamble_time_ms = d_preamble_time_seconds*1000.0; d_GPS_FSM.d_preamble_time_ms = d_preamble_time_seconds*1000.0;
d_GPS_FSM.Event_gps_word_valid(); d_GPS_FSM.Event_gps_word_valid();
d_flag_parity = true; d_flag_parity = true;
@ -321,6 +321,8 @@ int gps_l1_ca_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_i
// output the frame // output the frame
consume_each(1); //one by one consume_each(1); //one by one
//! \todo This has to be documented and included in the header!!!!
gps_synchro.valid_word = (d_flag_frame_sync == true and d_flag_parity == true); gps_synchro.valid_word = (d_flag_frame_sync == true and d_flag_parity == true);
gps_synchro.flag_preamble = d_flag_preamble; gps_synchro.flag_preamble = d_flag_preamble;
gps_synchro.preamble_delay_ms = d_preamble_time_seconds*1000.0; gps_synchro.preamble_delay_ms = d_preamble_time_seconds*1000.0;

View File

@ -57,6 +57,24 @@ gps_l1_ca_make_telemetry_decoder_cc(unsigned int satellite, long if_freq, long f
*/ */
class gps_l1_ca_telemetry_decoder_cc : public gr_block { class gps_l1_ca_telemetry_decoder_cc : public gr_block {
public:
~gps_l1_ca_telemetry_decoder_cc();
void set_satellite(int satellite); //!< Set satellite PRN
void set_channel(int channel); //!< Set receiver's channel
/*!
* \brief Set the navigation queue
*/
void set_navigation_queue(concurrent_queue<Gps_Navigation_Message> *nav_queue){d_GPS_FSM.d_nav_queue=nav_queue;}
int general_work (int noutput_items, gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items);
void forecast (int noutput_items, gr_vector_int &ninput_items_required);
private: private:
friend gps_l1_ca_telemetry_decoder_cc_sptr friend gps_l1_ca_telemetry_decoder_cc_sptr
@ -112,20 +130,6 @@ private:
std::string d_dump_filename; std::string d_dump_filename;
std::ofstream d_dump_file; std::ofstream d_dump_file;
public:
~gps_l1_ca_telemetry_decoder_cc();
void set_satellite(int satellite);
void set_channel(int channel);
void set_navigation_queue(concurrent_queue<Gps_Navigation_Message> *nav_queue){d_GPS_FSM.d_nav_queue=nav_queue;}
int general_work (int noutput_items, gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items);
void forecast (int noutput_items, gr_vector_int &ninput_items_required);
}; };
#endif #endif

View File

@ -83,9 +83,9 @@ public:
void set_channel_queue(concurrent_queue<int> *channel_internal_queue); void set_channel_queue(concurrent_queue<int> *channel_internal_queue);
void start_tracking(); void start_tracking();
void set_acq_sample_stamp(unsigned long int sample_stamp); void set_acq_sample_stamp(unsigned long int sample_stamp);
private: private:
gps_l1_ca_dll_fll_pll_tracking_cc_sptr tracking_; gps_l1_ca_dll_fll_pll_tracking_cc_sptr tracking_;

View File

@ -41,6 +41,7 @@
#include "CN_estimators.h" #include "CN_estimators.h"
#include "tracking_FLL_PLL_filter.h" #include "tracking_FLL_PLL_filter.h"
#include "control_message_factory.h" #include "control_message_factory.h"
#include "gnss_flowgraph.h"
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
@ -98,7 +99,7 @@ Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc(unsigned in
d_fs_in = fs_in; d_fs_in = fs_in;
d_vector_length = vector_length; d_vector_length = vector_length;
d_early_late_spc_chips = early_late_space_chips; // Define early-late offset (in chips) d_early_late_spc_chips = early_late_space_chips; // Define early-late offset (in chips)
d_dump_filename=dump_filename; d_dump_filename = dump_filename;
// Initialize tracking variables ========================================== // Initialize tracking variables ==========================================
d_carrier_loop_filter.set_params(fll_bw_hz,pll_bw_hz,order); d_carrier_loop_filter.set_params(fll_bw_hz,pll_bw_hz,order);
@ -129,6 +130,7 @@ Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc(unsigned in
d_CN0_SNV_dB_Hz = 0; d_CN0_SNV_dB_Hz = 0;
d_carrier_lock_fail_counter = 0; d_carrier_lock_fail_counter = 0;
d_carrier_lock_threshold = 5; d_carrier_lock_threshold = 5;
} }
@ -142,7 +144,6 @@ void Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::start_tracking()
unsigned long int acq_trk_diff_samples; unsigned long int acq_trk_diff_samples;
float acq_trk_diff_seconds; float acq_trk_diff_seconds;
acq_trk_diff_samples = d_sample_counter - d_acq_sample_stamp;//-d_vector_length; acq_trk_diff_samples = d_sample_counter - d_acq_sample_stamp;//-d_vector_length;
//std::cout<<"acq_trk_diff_samples="<<acq_trk_diff_samples<<"\r\n";
acq_trk_diff_seconds = (float)acq_trk_diff_samples / (float)d_fs_in; acq_trk_diff_seconds = (float)acq_trk_diff_samples / (float)d_fs_in;
//doppler effect //doppler effect
// Fd=(C/(C+Vr))*F // Fd=(C/(C+Vr))*F
@ -181,6 +182,7 @@ void Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::start_tracking()
// generate local reference ALWAYS starting at chip 1 (1 sample per chip) // generate local reference ALWAYS starting at chip 1 (1 sample per chip)
code_gen_conplex(&d_ca_code[1], d_satellite, 0); code_gen_conplex(&d_ca_code[1], d_satellite, 0);
d_ca_code[0] = d_ca_code[(int)GPS_L1_CA_CODE_LENGTH_CHIPS]; d_ca_code[0] = d_ca_code[(int)GPS_L1_CA_CODE_LENGTH_CHIPS];
d_ca_code[(int)GPS_L1_CA_CODE_LENGTH_CHIPS + 1] = d_ca_code[1]; d_ca_code[(int)GPS_L1_CA_CODE_LENGTH_CHIPS + 1] = d_ca_code[1];
@ -229,7 +231,7 @@ void Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::update_local_code()
d_prompt_code[i] = d_ca_code[associated_chip_index]; d_prompt_code[i] = d_ca_code[associated_chip_index];
associated_chip_index = 1 + round(fmod(tcode_chips + d_early_late_spc_chips, code_length_chips)); associated_chip_index = 1 + round(fmod(tcode_chips + d_early_late_spc_chips, code_length_chips));
d_late_code[i] = d_ca_code[associated_chip_index]; d_late_code[i] = d_ca_code[associated_chip_index];
tcode_chips = tcode_chips+code_phase_step_chips; tcode_chips = tcode_chips + code_phase_step_chips;
} }
//d_code_phase_samples=d_code_phase_samples+(float)d_fs_in*GPS_L1_CA_CODE_LENGTH_CHIPS*(1/d_code_freq_hz-1/GPS_L1_CA_CODE_RATE_HZ); //d_code_phase_samples=d_code_phase_samples+(float)d_fs_in*GPS_L1_CA_CODE_LENGTH_CHIPS*(1/d_code_freq_hz-1/GPS_L1_CA_CODE_RATE_HZ);
} }
@ -316,14 +318,14 @@ int Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::general_work (int noutput_items, gr_vecto
d_sample_counter = d_sample_counter + samples_offset; //count for the processed samples d_sample_counter = d_sample_counter + samples_offset; //count for the processed samples
d_pull_in = false; d_pull_in = false;
//std::cout<<" samples_offset="<<samples_offset<<"\r\n"; //std::cout<<" samples_offset="<<samples_offset<<"\r\n";
consume_each(samples_offset); //shift input to perform alignement with local replica consume_each(samples_offset); //shift input to perform alignment with local replica
return 1; return 1;
} }
// get the sample in and out pointers // get the sample in and out pointers
const gr_complex* in = (gr_complex*) input_items[0]; //block input samples pointer const gr_complex* in = (gr_complex*) input_items[0]; //block input samples pointer
double **out = (double **) &output_items[0]; //block output streams pointer double **out = (double **) &output_items[0]; //block output streams pointer
// check for samples consistency // check for samples consistency (this should be done before in the receiver / here only if the source is a file)
for(int i=0; i<d_current_prn_length_samples; i++) for(int i=0; i<d_current_prn_length_samples; i++)
{ {
if (std::isnan(in[i].real()) == true or std::isnan(in[i].imag()) == true)// or std::isinf(in[i].real())==true or std::isinf(in[i].imag())==true) if (std::isnan(in[i].real()) == true or std::isnan(in[i].imag()) == true)// or std::isinf(in[i].real())==true or std::isinf(in[i].imag())==true)
@ -353,10 +355,10 @@ int Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::general_work (int noutput_items, gr_vecto
{ {
//Perform the carrier wipe-off //Perform the carrier wipe-off
bb_signal_sample = in[i] * d_carr_sign[i]; bb_signal_sample = in[i] * d_carr_sign[i];
// Now get early, late, and prompt values for each // Now get early, late, and prompt correlation values
d_Early += bb_signal_sample*d_early_code[i]; d_Early += bb_signal_sample * d_early_code[i];
d_Prompt += bb_signal_sample*d_prompt_code[i]; d_Prompt += bb_signal_sample * d_prompt_code[i];
d_Late += bb_signal_sample*d_late_code[i]; d_Late += bb_signal_sample * d_late_code[i];
} }
/* /*
@ -366,7 +368,7 @@ int Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::general_work (int noutput_items, gr_vecto
code_error_chips = dll_nc_e_minus_l_normalized(d_Early,d_Late); code_error_chips = dll_nc_e_minus_l_normalized(d_Early,d_Late);
//compute FLL error //compute FLL error
correlation_time_s = ((float)d_current_prn_length_samples)/(float)d_fs_in; correlation_time_s = ((float)d_current_prn_length_samples) / (float)d_fs_in;
if (d_FLL_wait == 1) if (d_FLL_wait == 1)
{ {
d_Prompt_prev = d_Prompt; d_Prompt_prev = d_Prompt;
@ -374,7 +376,7 @@ int Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::general_work (int noutput_items, gr_vecto
} }
else else
{ {
d_FLL_discriminator_hz = fll_four_quadrant_atan(d_Prompt_prev, d_Prompt, 0, correlation_time_s)/(float)TWO_PI; d_FLL_discriminator_hz = fll_four_quadrant_atan(d_Prompt_prev, d_Prompt, 0, correlation_time_s) / (float)TWO_PI;
d_Prompt_prev = d_Prompt; d_Prompt_prev = d_Prompt;
d_FLL_wait = 1; d_FLL_wait = 1;
} }
@ -394,7 +396,7 @@ int Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::general_work (int noutput_items, gr_vecto
*/ */
carr_nco_hz = d_carrier_loop_filter.get_carrier_error(d_FLL_discriminator_hz, PLL_discriminator_hz, correlation_time_s); carr_nco_hz = d_carrier_loop_filter.get_carrier_error(d_FLL_discriminator_hz, PLL_discriminator_hz, correlation_time_s);
d_carrier_doppler_hz = (float)d_if_freq + carr_nco_hz; d_carrier_doppler_hz = (float)d_if_freq + carr_nco_hz;
d_code_freq_hz = GPS_L1_CA_CODE_RATE_HZ- (((d_carrier_doppler_hz - (float)d_if_freq)*GPS_L1_CA_CODE_RATE_HZ)/GPS_L1_FREQ_HZ) - code_error_chips; d_code_freq_hz = GPS_L1_CA_CODE_RATE_HZ - (((d_carrier_doppler_hz - (float)d_if_freq) * GPS_L1_CA_CODE_RATE_HZ) / GPS_L1_FREQ_HZ) - code_error_chips;
/*! /*!
* \todo Improve the lock detection algorithm! * \todo Improve the lock detection algorithm!
@ -409,8 +411,8 @@ int Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::general_work (int noutput_items, gr_vecto
else else
{ {
d_cn0_estimation_counter = 0; d_cn0_estimation_counter = 0;
d_CN0_SNV_dB_Hz=gps_l1_ca_CN0_SNV(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES,d_fs_in); d_CN0_SNV_dB_Hz = gps_l1_ca_CN0_SNV(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES, d_fs_in);
d_carrier_lock_test=carrier_lock_detector(d_Prompt_buffer,CN0_ESTIMATION_SAMPLES); d_carrier_lock_test = carrier_lock_detector(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES);
// ###### TRACKING UNLOCK NOTIFICATION ##### // ###### TRACKING UNLOCK NOTIFICATION #####
int tracking_message; int tracking_message;
if (d_carrier_lock_test < d_carrier_lock_threshold or d_carrier_lock_test > MINIMUM_VALID_CN0) if (d_carrier_lock_test < d_carrier_lock_threshold or d_carrier_lock_test > MINIMUM_VALID_CN0)
@ -423,7 +425,7 @@ int Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::general_work (int noutput_items, gr_vecto
} }
if (d_carrier_lock_fail_counter > MAXIMUM_LOCK_FAIL_COUNTER) if (d_carrier_lock_fail_counter > MAXIMUM_LOCK_FAIL_COUNTER)
{ {
std::cout<<"Channel "<< d_channel << " loss of lock!" << std::endl; std::cout << "Channel " << d_channel << " loss of lock!" << std::endl;
tracking_message = 3; //loss of lock tracking_message = 3; //loss of lock
d_channel_internal_queue->push(tracking_message); d_channel_internal_queue->push(tracking_message);
d_carrier_lock_fail_counter = 0; d_carrier_lock_fail_counter = 0;
@ -438,15 +440,15 @@ int Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::general_work (int noutput_items, gr_vecto
*/ */
// ########### Output the tracking data to navigation and PVT ########## // ########### Output the tracking data to navigation and PVT ##########
// Output channel 0: Prompt correlator output Q // Output channel 0: Prompt correlator output Q
*out[0]=(double)d_Prompt.real(); *out[0] = (double)d_Prompt.real();
// Output channel 1: Prompt correlator output I // Output channel 1: Prompt correlator output I
*out[1]=(double)d_Prompt.imag(); *out[1] = (double)d_Prompt.imag();
// Output channel 2: PRN absolute delay [s] // Output channel 2: PRN absolute delay [s]
*out[2]=d_sample_counter_seconds; *out[2] = d_sample_counter_seconds;
// Output channel 3: d_acc_carrier_phase_rad [rad] // Output channel 3: d_acc_carrier_phase_rad [rad]
*out[3]=(double)d_acc_carrier_phase_rad; *out[3] = (double)d_acc_carrier_phase_rad;
// Output channel 4: PRN code phase [s] // Output channel 4: PRN code phase [s]
*out[4]=(double)d_code_phase_samples*(1/(float)d_fs_in); *out[4] = (double)d_code_phase_samples * (1/(float)d_fs_in);
// ########## DEBUG OUTPUT // ########## DEBUG OUTPUT
/*! /*!
@ -459,7 +461,7 @@ int Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::general_work (int noutput_items, gr_vecto
{ {
d_last_seg = floor(d_sample_counter/d_fs_in); d_last_seg = floor(d_sample_counter/d_fs_in);
std::cout << "Current input signal time=" << d_last_seg << " [s]" << std::endl; std::cout << "Current input signal time=" << d_last_seg << " [s]" << std::endl;
std::cout << "Tracking CH "<< d_channel << " CN0=" << d_CN0_SNV_dB_Hz << " [dB-Hz]" <<std::endl; std::cout << "Tracking CH "<< d_channel << " CN0=" << d_CN0_SNV_dB_Hz << " [dB-Hz]" << std::endl;
//std::cout<<"TRK CH "<<d_channel<<" Carrier_lock_test="<<d_carrier_lock_test<< std::endl; //std::cout<<"TRK CH "<<d_channel<<" Carrier_lock_test="<<d_carrier_lock_test<< std::endl;
//if (d_last_seg==5) d_carrier_lock_fail_counter=500; //DEBUG: force unlock! //if (d_last_seg==5) d_carrier_lock_fail_counter=500; //DEBUG: force unlock!
} }
@ -480,22 +482,22 @@ int Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::general_work (int noutput_items, gr_vecto
float T_prn_samples; float T_prn_samples;
float K_blk_samples; float K_blk_samples;
T_chip_seconds = 1/d_code_freq_hz; T_chip_seconds = 1/d_code_freq_hz;
T_prn_seconds = T_chip_seconds*GPS_L1_CA_CODE_LENGTH_CHIPS; T_prn_seconds = T_chip_seconds * GPS_L1_CA_CODE_LENGTH_CHIPS;
T_prn_samples = T_prn_seconds*(float)d_fs_in; T_prn_samples = T_prn_seconds * (float)d_fs_in;
d_rem_code_phase_samples = d_next_rem_code_phase_samples; d_rem_code_phase_samples = d_next_rem_code_phase_samples;
K_blk_samples = T_prn_samples+d_rem_code_phase_samples; K_blk_samples = T_prn_samples + d_rem_code_phase_samples;
// Update the current PRN delay (code phase in samples) // Update the current PRN delay (code phase in samples)
float T_prn_true_seconds = GPS_L1_CA_CODE_LENGTH_CHIPS/GPS_L1_CA_CODE_RATE_HZ; float T_prn_true_seconds = GPS_L1_CA_CODE_LENGTH_CHIPS / GPS_L1_CA_CODE_RATE_HZ;
float T_prn_true_samples = T_prn_true_seconds*(float)d_fs_in; float T_prn_true_samples = T_prn_true_seconds * (float)d_fs_in;
d_code_phase_samples = d_code_phase_samples + T_prn_samples - T_prn_true_samples; d_code_phase_samples = d_code_phase_samples + T_prn_samples - T_prn_true_samples;
if (d_code_phase_samples < 0) if (d_code_phase_samples < 0)
{ {
d_code_phase_samples = T_prn_true_samples + d_code_phase_samples; d_code_phase_samples = T_prn_true_samples + d_code_phase_samples;
} }
d_code_phase_samples = fmod(d_code_phase_samples, T_prn_true_samples); d_code_phase_samples = fmod(d_code_phase_samples, T_prn_true_samples);
d_next_prn_length_samples = round(K_blk_samples);//round to a discrete samples d_next_prn_length_samples = round(K_blk_samples); //round to a discrete sample
d_next_rem_code_phase_samples = K_blk_samples-d_next_prn_length_samples; //rounding error d_next_rem_code_phase_samples = K_blk_samples - d_next_prn_length_samples; //rounding error
} }
else else
{ {
@ -513,7 +515,7 @@ int Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::general_work (int noutput_items, gr_vecto
// MULTIPLEXED FILE RECORDING - Record results to file // MULTIPLEXED FILE RECORDING - Record results to file
float prompt_I; float prompt_I;
float prompt_Q; float prompt_Q;
float tmp_E,tmp_P,tmp_L; float tmp_E, tmp_P, tmp_L;
float tmp_float; float tmp_float;
prompt_I = d_Prompt.imag(); prompt_I = d_Prompt.imag();
prompt_Q = d_Prompt.real(); prompt_Q = d_Prompt.real();
@ -558,11 +560,11 @@ int Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::general_work (int noutput_items, gr_vecto
} }
catch (std::ifstream::failure e) catch (std::ifstream::failure e)
{ {
std::cout << "Exception writing trk dump file "<<e.what()<<"\r\n"; std::cout << "Exception writing trk dump file "<< e.what() << std::endl;
} }
} }
consume_each(d_current_prn_length_samples); // this is necesary in gr_block derivates consume_each(d_current_prn_length_samples); // this is necesary in gr_block derivates
d_sample_counter_seconds = d_sample_counter_seconds + (((double)d_current_prn_length_samples)/(double)d_fs_in); d_sample_counter_seconds = d_sample_counter_seconds + (((double)d_current_prn_length_samples) / (double)d_fs_in);
d_sample_counter += d_current_prn_length_samples; //count for the processed samples d_sample_counter += d_current_prn_length_samples; //count for the processed samples
return 1; //output tracking result ALWAYS even in the case of d_enable_tracking==false return 1; //output tracking result ALWAYS even in the case of d_enable_tracking==false
} }
@ -574,7 +576,7 @@ int Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::general_work (int noutput_items, gr_vecto
void Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::set_acq_code_phase(float code_phase) void Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::set_acq_code_phase(float code_phase)
{ {
d_acq_code_phase_samples = code_phase; d_acq_code_phase_samples = code_phase;
LOG_AT_LEVEL(INFO) << "Tracking code phase set to " << d_acq_code_phase_samples; DLOG(INFO) << "Tracking code phase set to " << d_acq_code_phase_samples;
} }
@ -583,7 +585,7 @@ void Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::set_acq_code_phase(float code_phase)
void Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::set_acq_doppler(float doppler) void Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::set_acq_doppler(float doppler)
{ {
d_acq_carrier_doppler_hz = doppler; d_acq_carrier_doppler_hz = doppler;
LOG_AT_LEVEL(INFO) << "Tracking carrier doppler set to " << d_acq_carrier_doppler_hz; DLOG(INFO) << "Tracking carrier doppler set to " << d_acq_carrier_doppler_hz;
} }
@ -592,7 +594,7 @@ void Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::set_acq_doppler(float doppler)
void Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::set_satellite(unsigned int satellite) void Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::set_satellite(unsigned int satellite)
{ {
d_satellite = satellite; d_satellite = satellite;
LOG_AT_LEVEL(INFO) << "Tracking Satellite set to " << d_satellite; DLOG(INFO) << "Tracking Satellite set to " << d_satellite;
} }
@ -600,7 +602,7 @@ void Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::set_satellite(unsigned int satellite)
void Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::set_channel(unsigned int channel) void Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc::set_channel(unsigned int channel)
{ {
d_channel = channel; d_channel = channel;
LOG_AT_LEVEL(INFO) << "Tracking Channel set to " << d_channel; DLOG(INFO) << "Tracking Channel set to " << d_channel;
// ############# ENABLE DATA FILE LOG ################# // ############# ENABLE DATA FILE LOG #################
if (d_dump == true) if (d_dump == true)
{ {

View File

@ -47,6 +47,7 @@
#include <boost/thread/mutex.hpp> #include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp> #include <boost/thread/thread.hpp>
#include "concurrent_queue.h" #include "concurrent_queue.h"
//#include "GPS_L1_CA.h"
class Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc; class Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc;
typedef boost::shared_ptr<Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc> typedef boost::shared_ptr<Gps_L1_Ca_Dll_Fll_Pll_Tracking_cc>

View File

@ -42,7 +42,7 @@
/*! /*!
* \brief This abstract class represents an interface to a channel GNSS block. * \brief This abstract class represents an interface to a channel GNSS block.
* *
* Abstract class for channel blocks. Since all its methods are virtual, * Abstract class for channel blocks. Since all its methods are pure virtual,
* this class cannot be instantiated directly, and a subclass can only be * this class cannot be instantiated directly, and a subclass can only be
* instantiated directly if all inherited pure virtual methods have been * instantiated directly if all inherited pure virtual methods have been
* implemented by that class or a parent class. * implemented by that class or a parent class.

View File

@ -55,6 +55,7 @@ GNSSFlowgraph::GNSSFlowgraph(ConfigurationInterface *configuration,
block_factory_ = new GNSSBlockFactory(); block_factory_ = new GNSSBlockFactory();
queue_ = queue; queue_ = queue;
available_GPS_satellites_IDs_ = new std::list<unsigned int>(); available_GPS_satellites_IDs_ = new std::list<unsigned int>();
init(); init();
} }
@ -109,7 +110,7 @@ void GNSSFlowgraph::connect()
{ {
/* Connects the blocks in the flowgraph /* Connects the blocks in the flowgraph
* *
* Signal Source > Signal conditioner > Channels >> Observables >> PVT > Output filter * Signal Source > Signal conditioner >> Channels >> Observables >> PVT > Output filter
*/ */
DLOG(INFO) << "Connecting flowgraph"; DLOG(INFO) << "Connecting flowgraph";
if (connected_) if (connected_)
@ -118,7 +119,7 @@ void GNSSFlowgraph::connect()
return; return;
} }
// Connect GNSS block internally
try try
{ {
signal_source()->connect(top_block_); signal_source()->connect(top_block_);
@ -131,6 +132,7 @@ void GNSSFlowgraph::connect()
return; return;
} }
// Signal Source > Signal conditioner >
try try
{ {
signal_conditioner()->connect(top_block_); signal_conditioner()->connect(top_block_);
@ -144,6 +146,7 @@ void GNSSFlowgraph::connect()
return; return;
} }
for (unsigned int i = 0; i < channels_count_; i++) for (unsigned int i = 0; i < channels_count_; i++)
{ {
try try
@ -160,6 +163,7 @@ void GNSSFlowgraph::connect()
} }
} }
try try
{ {
observables()->connect(top_block_); observables()->connect(top_block_);
@ -172,6 +176,7 @@ void GNSSFlowgraph::connect()
return; return;
} }
// Signal Source > Signal conditioner >> Channels >> Observables > PVT
try try
{ {
pvt()->connect(top_block_); pvt()->connect(top_block_);
@ -184,6 +189,7 @@ void GNSSFlowgraph::connect()
return; return;
} }
// Signal Source > Signal conditioner >> Channels >> Observables > PVT > Output Filter
try try
{ {
output_filter()->connect(top_block_); output_filter()->connect(top_block_);
@ -198,6 +204,7 @@ void GNSSFlowgraph::connect()
DLOG(INFO) << "blocks connected internally"; DLOG(INFO) << "blocks connected internally";
// Signal Source > Signal conditioner >
try try
{ {
top_block_->connect(signal_source()->get_right_block(), 0, top_block_->connect(signal_source()->get_right_block(), 0,
@ -213,6 +220,7 @@ void GNSSFlowgraph::connect()
} }
DLOG(INFO) << "Signal source connected to signal conditioner"; DLOG(INFO) << "Signal source connected to signal conditioner";
// Signal Source > Signal conditioner >> channels_count_ number of Channels in parallel
for (unsigned int i = 0; i < channels_count_; i++) for (unsigned int i = 0; i < channels_count_; i++)
{ {
try try
@ -231,6 +239,7 @@ void GNSSFlowgraph::connect()
DLOG(INFO) << "signal conditioner connected to channel " << i; DLOG(INFO) << "signal conditioner connected to channel " << i;
// Signal Source > Signal conditioner >> Channels >> Observables
try try
{ {
top_block_->connect(channel(i)->get_right_block(), 0, top_block_->connect(channel(i)->get_right_block(), 0,
@ -388,10 +397,13 @@ GNSSBlockInterface* GNSSFlowgraph::output_filter()
return blocks_->at(4); return blocks_->at(4);
} }
void GNSSFlowgraph::init() void GNSSFlowgraph::init()
{ {
/* /*
* Instantiates the receiver blocks * Instantiates the receiver blocks
*/ */
blocks_->push_back( blocks_->push_back(
block_factory_->GetSignalSource(configuration_, queue_)); block_factory_->GetSignalSource(configuration_, queue_));

View File

@ -40,6 +40,7 @@
#include <queue> #include <queue>
#include <gnuradio/gr_top_block.h> #include <gnuradio/gr_top_block.h>
#include <gnuradio/gr_msg_queue.h> #include <gnuradio/gr_msg_queue.h>
#include "GPS_L1_CA.h"
class GNSSBlockInterface; class GNSSBlockInterface;
class ChannelInterface; class ChannelInterface;

View File

@ -32,19 +32,21 @@
#ifndef GNSS_SDR_GPS_L1_CA_H_ #ifndef GNSS_SDR_GPS_L1_CA_H_
#define GNSS_SDR_GPS_L1_CA_H_ #define GNSS_SDR_GPS_L1_CA_H_
#include <complex>
// Physical constants // Physical constants
const double GPS_C_m_s = 299792458.0; //!< The speed of light, [m/s] const double GPS_C_m_s = 299792458.0; //!< The speed of light, [m/s]
const double GPS_C_m_ms = 299792.4580; //!< The speed of light, [m/ms] const double GPS_C_m_ms = 299792.4580; //!< The speed of light, [m/ms]
const double GPS_PI = 3.1415926535898; //!< Pi as defined in IS-GPS-200E const double GPS_PI = 3.1415926535898; //!< Pi as defined in IS-GPS-200E
const double OMEGA_EARTH_DOT = 7.2921151467e-5; //!< Earth rotation rate, [rad/s] const double OMEGA_EARTH_DOT = 7.2921151467e-5; //!< Earth rotation rate, [rad/s]
const double GM = 3.986005e14; //!< Universal gravitational constant times the mass of the Earth, [m^3/s^2] const double GM = 3.986005e14; //!< Universal gravitational constant times the mass of the Earth, [m^3/s^2]
const double F = -4.442807633e-10; //!< Constant, [s/(m)^(1/2)] const double F = -4.442807633e-10; //!< Constant, [s/(m)^(1/2)]
// carrier and code frequencies // carrier and code frequencies
const float GPS_L1_FREQ_HZ = 1.57542e9; //!< L1 [Hz] const double GPS_L1_FREQ_HZ = 1.57542e9; //!< L1 [Hz]
const float GPS_L1_CA_CODE_RATE_HZ = 1.023e6; //!< GPS L1 C/A code rate [chips/s] const double GPS_L1_CA_CODE_RATE_HZ = 1.023e6; //!< GPS L1 C/A code rate [chips/s]
const float GPS_L1_CA_CODE_LENGTH_CHIPS = 1023.0; //!< GPS L1 C/A code length [chips] const double GPS_L1_CA_CODE_LENGTH_CHIPS = 1023.0; //!< GPS L1 C/A code length [chips]
/*! /*!
* \brief Maximum Time-Of-Arrival (TOA) difference between satellites for a receiver operated on Earth surface is 20 ms * \brief Maximum Time-Of-Arrival (TOA) difference between satellites for a receiver operated on Earth surface is 20 ms
@ -54,19 +56,19 @@ const float GPS_L1_CA_CODE_LENGTH_CHIPS = 1023.0; //!< GPS L1 C/A code length
* [1] J. Bao-Yen Tsui, Fundamentals of Global Positioning System Receivers. A Software Approach, John Wiley & Sons, * [1] J. Bao-Yen Tsui, Fundamentals of Global Positioning System Receivers. A Software Approach, John Wiley & Sons,
* Inc., Hoboken, NJ, 2nd edition, 2005. * Inc., Hoboken, NJ, 2nd edition, 2005.
*/ */
const double MAX_TOA_DELAY_MS=20; const double MAX_TOA_DELAY_MS = 20;
#define NAVIGATION_SOLUTION_RATE_MS 1000 // this cannot go here #define NAVIGATION_SOLUTION_RATE_MS 1000 // this cannot go here
const float GPS_STARTOFFSET_ms= 68.802; //[ms] Initial sign. travel time (this cannot go here) const float GPS_STARTOFFSET_ms = 68.802; //[ms] Initial sign. travel time (this cannot go here)
// NAVIGATION MESSAGE DEMODULATION AND DECODING // NAVIGATION MESSAGE DEMODULATION AND DECODING
#define GPS_PREAMBLE {1, 0, 0, 0, 1, 0, 1, 1} #define GPS_PREAMBLE {1, 0, 0, 0, 1, 0, 1, 1}
#define GPS_CA_PREAMBLE_LENGTH_BITS 8 const int GPS_CA_PREAMBLE_LENGTH_BITS = 8;
#define GPS_CA_TELEMETRY_RATE_BITS_SECOND 50 //!< NAV message bit rate [bits/s] const int GPS_CA_TELEMETRY_RATE_BITS_SECOND = 50; //!< NAV message bit rate [bits/s]
#define GPS_WORD_LENGTH 4 // CRC + GPS WORD (-2 -1 0 ... 29) Bits = 4 bytes #define GPS_WORD_LENGTH 4 // CRC + GPS WORD (-2 -1 0 ... 29) Bits = 4 bytes
#define GPS_SUBFRAME_LENGTH 40 // GPS_WORD_LENGTH x 10 = 40 bytes #define GPS_SUBFRAME_LENGTH 40 // GPS_WORD_LENGTH x 10 = 40 bytes
const int GPS_SUBFRAME_BITS=300; //!< Number of bits per subframe in the NAV message [bits] const int GPS_SUBFRAME_BITS=300; //!< Number of bits per subframe in the NAV message [bits]
@ -81,14 +83,15 @@ const int GPS_WORD_BITS=30; //!< Number of bits per word in t
/*! /*!
* \brief Navigation message bits slice structure: A portion of bits is indicated by * \brief Navigation message bits slice structure: A portion of bits is indicated by
* the start position inside the subframe and the length in number of bits */ * the start position inside the subframe and the length in number of bits */
typedef struct bits_slice{ typedef struct bits_slice
int position; {
int length; int position;
bits_slice(int p,int l) int length;
{ bits_slice(int p,int l)
position=p; {
length=l; position=p;
} length=l;
}
} bits_slice; } bits_slice;
@ -341,6 +344,72 @@ const bits_slice HEALTH_SV24[]={{259,6}};
inline void ca_code_generator_complex(std::complex<float>* _dest, signed int _prn, unsigned int _chip_shift)
{
unsigned int G1[1023];
unsigned int G2[1023];
unsigned int G1_register[10], G2_register[10];
unsigned int feedback1, feedback2;
unsigned int lcv, lcv2;
unsigned int delay;
signed int prn = _prn-1; //Move the PRN code to fit an array indices
/* G2 Delays as defined in IS-GPS-200E */
signed int delays[32] = {5, 6, 7, 8, 17, 18, 139, 140, 141, 251,
252, 254, 255, 256, 257, 258, 469, 470, 471, 472,
473, 474, 509, 512, 513, 514, 515, 516, 859, 860,
861, 862};
// PRN sequences 33 through 37 are reserved for other uses (e.g. ground transmitters)
/* A simple error check */
if((prn < 0) || (prn > 32))
return;
for(lcv = 0; lcv < 10; lcv++)
{
G1_register[lcv] = 1;
G2_register[lcv] = 1;
}
/* Generate G1 & G2 Register */
for(lcv = 0; lcv < 1023; lcv++)
{
G1[lcv] = G1_register[0];
G2[lcv] = G2_register[0];
feedback1 = G1_register[7]^G1_register[0];
feedback2 = (G2_register[8] + G2_register[7] + G2_register[4] + G2_register[2] + G2_register[1] + G2_register[0]) & 0x1;
for(lcv2 = 0; lcv2 < 9; lcv2++)
{
G1_register[lcv2] = G1_register[lcv2 + 1];
G2_register[lcv2] = G2_register[lcv2 + 1];
}
G1_register[9] = feedback1;
G2_register[9] = feedback2;
}
/* Set the delay */
delay = 1023 - delays[prn];
delay += _chip_shift;
delay %= 1023;
/* Generate PRN from G1 and G2 Registers */
for(lcv = 0; lcv < 1023; lcv++)
{
_dest[lcv] = std::complex<float>(G1[(lcv + _chip_shift)%1023]^G2[delay], 0);
if(_dest[lcv].real() == 0.0) //javi
{
_dest[lcv].real(-1.0);
}
delay++;
delay %= 1023;
//std::cout<<_dest[lcv].real(); //OK
}
}
#endif /* GNSS_SDR_GPS_L1_CA_H_ */ #endif /* GNSS_SDR_GPS_L1_CA_H_ */

View File

@ -70,7 +70,7 @@ private:
public: public:
//broadcast orbit 1 //broadcast orbit 1
double d_TOW; double d_TOW; //!< Time of GPS Week [s]
double d_IODE_SF2; double d_IODE_SF2;
double d_IODE_SF3; double d_IODE_SF3;
double d_Crs; //!< Amplitude of the Sine Harmonic Correction Term to the Orbit Radius [m] double d_Crs; //!< Amplitude of the Sine Harmonic Correction Term to the Orbit Radius [m]