From 3edad8812e3ce1ec93e4f3be779283c5ea0ec22d Mon Sep 17 00:00:00 2001 From: Cillian O'Driscoll Date: Wed, 4 Nov 2015 09:30:33 +0000 Subject: [PATCH] Working version of p-code plus tests Note that there is an error in IS GPS 200 H, which is where we get the testvectors from. This commit passes against test vectors from the proposed modification: IS GPS 200 H PIRN 001 --- src/algorithms/libs/gps_pcode.cc | 36 +++- src/tests/arithmetic/pcode_generation_test.cc | 203 ++++++++++++++++-- 2 files changed, 214 insertions(+), 25 deletions(-) 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] ); + } +} +