diff --git a/src/algorithms/libs/gps_pcode.cc b/src/algorithms/libs/gps_pcode.cc index 9c37fe3ff..23f19f0f6 100644 --- a/src/algorithms/libs/gps_pcode.cc +++ b/src/algorithms/libs/gps_pcode.cc @@ -172,14 +172,14 @@ const unsigned int GPS_P_Code_Generator::X2B_EXTRA_LENGTH = 965; const unsigned int GPS_P_Code_Generator::X2A_EPOCHS_LAST_X2_EPOCH = 104; const unsigned int GPS_P_Code_Generator::X2B_EPOCHS_LAST_X2_EPOCH = 104; -void GPS_P_Code_Generator::get_chips( int sv, uint64_t first_chip_index, unsigned num_chips, +void GPS_P_Code_Generator::get_chips( int prn, uint64_t first_chip_index, unsigned num_chips, std::vector< short > &_dest ) const { // A couple of quick checks: - if( sv < 1 or sv > 37 ) + if( prn < 1 or prn > 210 ) { - LOG(ERROR) << "Invalid SV number: " << sv - << " should be in the range 1 to 37 (inclusive)"; + LOG(ERROR) << "Invalid SV number: " << prn + << " should be in the range 1 to 210 (inclusive)"; } if( first_chip_index > GPS_P_CODE_LENGTH_CHIPS ) @@ -197,6 +197,14 @@ void GPS_P_Code_Generator::get_chips( int sv, uint64_t first_chip_index, unsigne } // OK now we can proceed: + // IS GPS 200H - The first 37 PRN codes are unique, identified by sv + // below. For PRN values greater than 37 we create the code for + // (prn-1) % 37 + 1 and delay it by floor( (prn-1)/37 ) days + int sv = ( prn - 1 ) % 37 + 1; + int num_days = (prn-1) / 37; + uint64_t day_shift = num_days*10230000LL*24LL*3600LL; + first_chip_index = first_chip_index + day_shift; + first_chip_index %= GPS_P_CODE_LENGTH_CHIPS; //Ensure we have space: _dest.resize( num_chips ); @@ -204,7 +212,7 @@ void GPS_P_Code_Generator::get_chips( int sv, uint64_t first_chip_index, unsigne // Establish the starting phase: // 1) account for the delay of the x2 register - int64_t first_chip_index_x2 = first_chip_index - sv + 1; + int64_t first_chip_index_x2 = first_chip_index - sv; while( first_chip_index_x2 < 0 ) { first_chip_index_x2 += GPS_P_CODE_LENGTH_CHIPS; @@ -293,11 +301,14 @@ void GPS_P_Code_Generator::get_chips( int sv, uint64_t first_chip_index, unsigne extra_code_period = X2A_EXTRA_LENGTH; } - if( x2a_epoch >= max_num_epochs ) + if( x2a_epoch >= max_num_epochs-1 ) { this_code_period = this_code_period + extra_code_period; - x2a_ind += GPS_X2A_CODE_LENGTH; - x2a_epoch--; + if( x2a_epoch == max_num_epochs ) + { + x2a_ind += GPS_X2A_CODE_LENGTH; + } + x2a_epoch = max_num_epochs-1; } unsigned int chips_to_gen = std::min( num_chips - dest_ind, @@ -345,11 +356,14 @@ void GPS_P_Code_Generator::get_chips( int sv, uint64_t first_chip_index, unsigne extra_code_period = X2B_EXTRA_LENGTH; } - if( x2b_epoch >= max_num_epochs ) + if( x2b_epoch >= max_num_epochs - 1 ) { this_code_period = this_code_period + extra_code_period; - x2b_ind += GPS_X2B_CODE_LENGTH; - x2b_epoch--; + if( x2b_epoch == max_num_epochs ) + { + x2b_ind += GPS_X2B_CODE_LENGTH; + } + x2b_epoch = max_num_epochs - 1; } unsigned int chips_to_gen = std::min( num_chips - dest_ind, diff --git a/src/tests/arithmetic/pcode_generation_test.cc b/src/tests/arithmetic/pcode_generation_test.cc index 1b0e3ca21..978f1fe51 100644 --- a/src/tests/arithmetic/pcode_generation_test.cc +++ b/src/tests/arithmetic/pcode_generation_test.cc @@ -34,12 +34,75 @@ #include "GPS_P_CODE.h" #include "gps_pcode.h" +// Test vectors from IS GPS 200 H +// Note there are some errors in that document as per: +//http://www.gps.gov/technical/icwg/meetings/2015/PIRN-IS-200H-001.pdf +// in particular: +// PRN : OLD : NEW +// 66 : 2111 : 6111 +// 69 : 4166 : 0166 +// 70 : 2251 : 6251 + +const std::vector< short > first_12_chips_octal = { + 04444, 04000, 04222, 04333, 04377, 04355, 04344, 04340, 04342, 04343, + 04343, 04343, 04343, 04343, 04343, 04343, 04343, 04343, 04343, 04343, + 04343, 04343, 04343, 04343, 04343, 04343, 04343, 04343, 04343, 04343, + 04343, 04343, 04343, 04343, 04343, 04343, 04343, // <-- 37 + 03373, 03757, 07545, 05440, 04402, 04023, 00233, 02337, 03375, 03754, + 03544, 07440, 01402, 06423, 01033, 02637, 07135, 05674, 00514, 06064, + 01210, 06726, 01171, 06656, 01105, 06660, // <-- 63 + /* IS GPS 200 H: + 05112, 00667, 02111, 05266, 04711, 04166, 02251, 05306, 04761, 02152, + 05247, 05736, 02575, 03054, 03604, 03520, 05472, 04417, 02025, 03230, + 05736, 04575, 02054, 03204, 03720, 05572, 04457, 04005, 02220, 03332, + 03777, 03555, // <- 95 + 03444, 07400, 01422, 02433, 07037, 01635, 06534, 05074, 00614, 06124, + 01270, 02716, 05165, 00650, 06106, 05261, 06752, 05147, 00641, 06102, + 01263, 02713, 03167, 03651, 07506, 05461, 00412, 06027, 01231, 02736, // <-125 + 07175, 01654, 06504, 01060, 02612, 07127, 05671, 04516, 04065, 04210, + 04326, 00371, 06356, 05345, 00740, 06142, 01243, 06703, 05163, 04653, + 04107, 04261, 00312, 02525, 07070, 01616, 02525, 07070, 03616, 07525, // <- 155 + 05470, 04416, 04025, 04230, 00336, 06375, 01354, 06744, 05140, 04642, + 00103, 06263, 01313, 06767, 01151, 02646, 07101, 05662, 00513, 02067, + 03211, 03726, 03571, 03456, 03405, 03420, 05432, 00437, 06035, 01234, // <- 185 + 01067, 06611, 05126, 04671, 00116, 06265, 01310, 06766, 01151, 02646, + 03101, 07662, 05513, 04467, 04011, 04226, 04331, 00376, 06355, 05344, + 00740, 06142, 01243, 06703, 01163 //<- 210 */ + /* PRN IS GPS 200 H 001:*/ + 05112, 00667, 06111, 05266, 04711, 00166, 06251, 05306, 00761, 06152, + 01247, 01736, 02575, 03054, 03604, 07520, 05472, 00417, 02025, 07230, + 05736, 00575, 02054, 03204, 07720, 05572, 04457, 00005, 02220, 03332, + 03777, 03555, 03444, 07400, 01422, 02433, 07037, 01635, 06534, 05074, + 00614, 06124, 01270, 06716, 05165, 00650, 06106, 05261, 06752, 05147, + 00641, 06102, 01263, 02713, 03167, 03651, 07506, 05461, 00412, 06027, + 01231, 02736, 07175, 01654, 06504, 01060, 02612, 07127, 05671, 04516, + 04065, 04210, 04326, 00371, 06356, 05345, 00740, 06142, 01243, 06703, + 05163, 04653, 04107, 04261, 00312, 02525, 07070, 01616, 02525, 03070, + 03616, 07525, 05470, 04416, 04025, 04230, 00336, 06375, 01354, 06744, + 05140, 04642, 00103, 06263, 01313, 06767, 01151, 02646, 07101, 05662, + 00513, 02067, 03211, 03726, 03571, 03456, 03405, 07420, 05432, 00437, + 06035, 01234, // <- 185 + 01067, 06611, 05126, 04671, 00116, 06265, 01310, 06766, 01151, 02646, + 03101, 07662, 05513, 04467, 04011, 04226, 04331, 00376, 06355, 05344, + 00740, 06142, 01243, 06703, 01163 //<- 210 */ +}; + + + TEST(PCodeGenTest, X1ATest) { std::vector< short > dest; gps_x1a_code_gen( dest ); + // IS GPS 200 H + std::vector< short > first_12_chips = { 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0 }; + + for( unsigned int ii = 0; ii < 12; ++ii ) + { + EXPECT_EQ( dest[ii], first_12_chips[ii] ) << "ii: " << ii; + } + // From Octave: std::vector< short > last12Bits = { 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0 }; @@ -56,6 +119,13 @@ TEST(PCodeGenTest, X1BTest) gps_x1b_code_gen( dest ); + // IS GPS 200 H + std::vector< short > first_12_chips = { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0 }; + + for( unsigned int ii = 0; ii < 12; ++ii ) + { + EXPECT_EQ( dest[ii], first_12_chips[ii] ) << "ii: " << ii; + } // From Octave: std::vector< short > last12Bits = { 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0 }; @@ -73,6 +143,14 @@ TEST(PCodeGenTest, X2ATest) gps_x2a_code_gen( dest ); + // IS GPS 200 H + std::vector< short > first_12_chips = { 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1}; + + for( unsigned int ii = 0; ii < 12; ++ii ) + { + EXPECT_EQ( dest[ii], first_12_chips[ii] ) << "ii: " << ii; + } + // From Octave: std::vector< short > last12Bits = {0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1}; @@ -90,7 +168,16 @@ TEST(PCodeGenTest, X2BTest) gps_x2b_code_gen( dest ); - // From Octave: + // IS GPS 200 H + std::vector< short > first_12_chips = { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0 }; + + for( unsigned int ii = 0; ii < 12; ++ii ) + { + EXPECT_EQ( dest[ii], first_12_chips[ii] ) << "ii: " << ii; + } + + + // From Octave : std::vector< short > last12Bits = {0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0}; for( unsigned int ii = 0; ii < 12; ++ii ) @@ -101,7 +188,7 @@ TEST(PCodeGenTest, X2BTest) } -TEST(PCodeGenTest, FirstChipsTest) +TEST(PCodeGenTest, FirstChipsTest1) { std::vector< short > dest; @@ -120,20 +207,50 @@ TEST(PCodeGenTest, FirstChipsTest) unsigned int num_chips = 24; int sv = 1; + int first_chip_index = sv; - pcode_gen.get_chips( sv, 0, num_chips, dest ); + pcode_gen.get_chips( sv, first_chip_index, num_chips, dest ); EXPECT_EQ( dest.size(), num_chips ); - for( unsigned ii = 0; ii < num_chips; ++ii ) + for( unsigned ii = 0, jj = first_chip_index; ii < num_chips; ++ii, ++jj) { - short res = x1a[ii] ^ x1b[ii] ^ x2a[ii] ^ x2b[ii]; + short res = x1a[jj] ^ x1b[jj] ^ x2a[jj-sv] ^ x2b[jj-sv]; EXPECT_EQ( dest[ii], res ); } } +TEST(PCodeGenTest, First12ChipsAll ) +{ + std::vector< short > dest; + + GPS_P_Code_Generator pcode_gen; + + unsigned int num_chips = 12; + + int num_err = 0; + for( int sv = 1; sv <= 210; ++sv ) + { + pcode_gen.get_chips( sv, 0, num_chips, dest ); + short res = 0; + for( int ii=0; ii < num_chips; ++ii ) + { + //short theBit = ( first_12_chips_octal[ sv - 1 ] >> (11-ii) ) & 0x01; + res = (res<<1) | dest[ii]; + + //EXPECT_EQ( dest[ii], theBit ) << " sv " << sv << " bit " << ii; + } + short icd = first_12_chips_octal[ sv - 1]; + EXPECT_EQ( res, icd ) << " sv " << sv << ". icd: " << std::oct << icd + << ". actual: " << std::oct << res << std::dec << ". num_err: " << ++num_err; + } + + EXPECT_EQ( num_err, 0 ); + +} + TEST(PCodeGenTest, EndX1EpochTest) { std::vector< short > dest; @@ -163,7 +280,7 @@ TEST(PCodeGenTest, EndX1EpochTest) for( unsigned ii = 0; ii < num_chips; ++ii ) { short res = x1a[4092-num_chips+ii] - ^ x1b[4092] ^ x2a[4092-num_chips+ii] + ^ x1b[4092] ^ x2a[4092-num_chips+ii-sv] ^ x2b[4092]; EXPECT_EQ( dest[ii], res ); @@ -188,19 +305,36 @@ TEST(PCodeGenTest, StartSecondX1EpochTest) unsigned int num_chips = 24; uint64_t end_x1_epoch = 4092LL*3750LL; - uint64_t start_ind = end_x1_epoch; int sv = 1; + uint64_t start_ind = end_x1_epoch; + pcode_gen.get_chips( sv, start_ind, num_chips, dest ); EXPECT_EQ( dest.size(), num_chips ); - for( unsigned ii = 0; ii < num_chips; ++ii ) + unsigned ii = 0; + for( ii = 0; ii < sv && ii < num_chips; ++ii ) + { + short res = x1a[ii] ^ x1b[ii] + ^ x2a[4092-sv + ii] ^ x2b[ 4092 ]; + + EXPECT_EQ( dest[ii], res ); + } + + for( ; (ii - sv ) < 37 && ii < num_chips; ++ii ) + { + short res = x1a[ii] ^ x1b[ii] + ^ x2a[ 4091 ] ^ x2b[ 4092 ]; + EXPECT_EQ( dest[ii], res ); + } + + for( ; ii < num_chips; ++ii ) { short res = x1a[ii] - ^ x1b[ii] ^ x2a[4091] - ^ x2b[4092]; + ^ x1b[ii] ^ x2a[ii-37-sv] + ^ x2b[ii-37-sv]; EXPECT_EQ( dest[ii], res ); } @@ -259,7 +393,7 @@ TEST(PCodeGenTest, Prn37Test) GPS_P_Code_Generator pcode_gen; int sv = 37; - unsigned int num_chips = 24+sv-1; + unsigned int num_chips = 24+sv; uint64_t start_ind = 0; @@ -267,13 +401,54 @@ TEST(PCodeGenTest, Prn37Test) EXPECT_EQ( dest.size(), num_chips ); - for( unsigned ii = sv-1; ii < num_chips; ++ii ) + for( unsigned ii = sv; ii < num_chips; ++ii ) { short res = x1a[ii] - ^ x1b[ii] ^ x2a[ii-sv+1] - ^ x2b[ii-sv+1]; + ^ x1b[ii] ^ x2a[ii-sv] + ^ x2b[ii-sv]; EXPECT_EQ( dest[ii], res ); } } +TEST(PCodeGenTest, NewPrnTest) +{ + std::vector< short > dest; + std::vector< short > dest0; + + GPS_P_Code_Generator pcode_gen; + + int sv = 137; + unsigned int num_chips = 24; + uint64_t start_ind = 0; + + int prn0 = (sv-1)%37 + 1; + int day_shift = (sv-1)/37; + + uint64_t start_ind0 = start_ind + day_shift*10230000LL*24LL*3600LL; + + + pcode_gen.get_chips( sv, start_ind, num_chips, dest ); + pcode_gen.get_chips( prn0, start_ind0, num_chips, dest0 ); + + EXPECT_EQ( dest.size(), num_chips ); + EXPECT_EQ( dest0.size(), num_chips ); + + for( unsigned ii = 0; ii < num_chips; ++ii ) + { + EXPECT_EQ( dest[ii], dest0[ii] ); + } + + // From the IS GPS 200H: + // PRN = 137: first 12 chips = o0371 (octal) + // 0 0 0 0 1 1 1 1 1 0 0 1 + std::vector< short > first_12_chips_icd = { + 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1 + }; + + for( unsigned int ii = 0; ii < 12; ++ii ) + { + EXPECT_EQ( dest[ii], first_12_chips_icd[ii] ); + } +} +