00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <stdio.h>
00014 #include <string.h>
00015 #include <math.h>
00016
00017 #include "constants.h"
00018 #include "nav_msg.h"
00019
00020 #define NAV_MSG_BIT_PHASE_THRES 5
00021
00022 void nav_msg_init(nav_msg_t *n)
00023 {
00024
00025 n->subframe_bit_index = 0;
00026 n->bit_phase = 0;
00027 n->bit_phase_ref = 0;
00028 n->bit_phase_count = 0;
00029 n->nav_bit_integrate = 0;
00030 n->subframe_start_index = 0;
00031 memset(n->subframe_bits, 0, sizeof(n->subframe_bits));
00032 n->next_subframe_id = 1;
00033 }
00034
00035 u32 extract_word(nav_msg_t *n, u16 bit_index, u8 n_bits, u8 invert)
00036 {
00037
00038
00039
00040
00041
00042 if (n->subframe_start_index) {
00043 if (n->subframe_start_index > 0)
00044 bit_index += n->subframe_start_index;
00045 else {
00046 bit_index -= n->subframe_start_index;
00047 invert = !invert;
00048 }
00049
00050 bit_index--;
00051 }
00052
00053
00054 if (bit_index > NAV_MSG_SUBFRAME_BITS_LEN*32)
00055 bit_index -= NAV_MSG_SUBFRAME_BITS_LEN*32;
00056
00057 u8 bix_hi = bit_index >> 5;
00058 u8 bix_lo = bit_index & 0x1F;
00059 u32 word = n->subframe_bits[bix_hi] << bix_lo;
00060
00061 if (bix_lo) {
00062 bix_hi++;
00063 if (bix_hi == NAV_MSG_SUBFRAME_BITS_LEN)
00064 bix_hi = 0;
00065 word |= n->subframe_bits[bix_hi] >> (32 - bix_lo);
00066 }
00067
00068 if (invert)
00069 word = ~word;
00070
00071 return word >> (32 - n_bits);
00072 }
00073
00074
00075 s32 nav_msg_update(nav_msg_t *n, s32 corr_prompt_real)
00076 {
00077
00078
00079
00080
00081 s32 TOW_ms = -1;
00082
00083
00084
00085 n->bit_phase++;
00086 n->bit_phase %= 20;
00087
00088 if (n->bit_phase_count < NAV_MSG_BIT_PHASE_THRES) {
00089
00090
00091 if ((n->nav_bit_integrate > 0) != (corr_prompt_real > 0)) {
00092
00093 if (n->bit_phase == n->bit_phase_ref)
00094
00095 n->bit_phase_count++;
00096 else {
00097
00098 n->bit_phase_ref = n->bit_phase;
00099 n->bit_phase_count = 1;
00100 }
00101 }
00102
00103 n->nav_bit_integrate = corr_prompt_real;
00104
00105 } else {
00106
00107
00108 if (n->bit_phase != n->bit_phase_ref) {
00109
00110 n->nav_bit_integrate += corr_prompt_real;
00111 } else {
00112
00113
00114
00115
00116 if (n->nav_bit_integrate > 0) {
00117 n->subframe_bits[n->subframe_bit_index >> 5] |= \
00118 1 << (31 - (n->subframe_bit_index & 0x1F));
00119 } else {
00120
00121 n->subframe_bits[n->subframe_bit_index >> 5] &= \
00122 ~(1 << (31 - (n->subframe_bit_index & 0x1F)));
00123 }
00124
00125
00126 n->nav_bit_integrate = 0;
00127
00128 n->subframe_bit_index++;
00129 if (n->subframe_bit_index == NAV_MSG_SUBFRAME_BITS_LEN*32)
00130 n->subframe_bit_index = 0;
00131
00132
00133 if (!n->subframe_start_index) {
00134
00135
00136 #define SUBFRAME_START_BUFFER_OFFSET (NAV_MSG_SUBFRAME_BITS_LEN*32 - 360)
00137
00138
00139
00140 u8 preamble_candidate = extract_word(n, n->subframe_bit_index + SUBFRAME_START_BUFFER_OFFSET, 8, 0);
00141
00142 if (preamble_candidate == 0x8B) {
00143 n->subframe_start_index = n->subframe_bit_index + SUBFRAME_START_BUFFER_OFFSET + 1;
00144 }
00145 else if (preamble_candidate == 0x74) {
00146 n->subframe_start_index = -(n->subframe_bit_index + SUBFRAME_START_BUFFER_OFFSET + 1);
00147 }
00148
00149 if (n->subframe_start_index) {
00150
00151 if (extract_word(n, 300, 8, 0) == 0x8B) {
00152
00153
00154
00155 unsigned int TOW_trunc = extract_word(n,30,17,extract_word(n,29,1,0));
00156 TOW_trunc++;
00157 if (TOW_trunc >= 7*24*60*10)
00158 TOW_trunc = 0;
00159
00160 if (TOW_trunc == extract_word(n,330,17,extract_word(n,329,1,0))) {
00161
00162
00163
00164
00165 if (TOW_trunc)
00166 TOW_ms = TOW_trunc * 6000 - (300-60)*20;
00167 else
00168 TOW_ms = 7*24*60*60*1000 - (300-60)*20;
00169
00170
00171 } else
00172 n->subframe_start_index = 0;
00173 } else
00174 n->subframe_start_index = 0;
00175 }
00176 }
00177 }
00178 }
00179 return TOW_ms;
00180 }
00181
00182
00183 int parity(u32 x)
00184 {
00185
00186 x ^= x >> 1;
00187 x ^= x >> 2;
00188 x ^= x >> 4;
00189 x ^= x >> 8;
00190 x ^= x >> 16;
00191 return (x & 1);
00192 }
00193
00194 int nav_parity(u32 *word) {
00195
00196
00197
00198
00199 if (*word & 1<<30)
00200 *word ^= 0x3FFFFFC0;
00201
00202
00203
00204 if (parity(*word & 0xBB1F34A0 ))
00205 return 25;
00206
00207 if (parity(*word & 0x5D8F9A50 ))
00208 return 26;
00209
00210 if (parity(*word & 0xAEC7CD08 ))
00211 return 27;
00212
00213 if (parity(*word & 0x5763E684 ))
00214 return 28;
00215
00216 if (parity(*word & 0x6BB1F342 ))
00217 return 29;
00218
00219 if (parity(*word & 0x8B7A89C1 ))
00220 return 30;
00221
00222 return 0;
00223 }
00224
00225 bool subframe_ready(nav_msg_t *n) {
00226 return (n->subframe_start_index != 0);
00227 }
00228
00229 s8 process_subframe(nav_msg_t *n, ephemeris_t *e) {
00230
00231
00232
00233
00234
00235
00236
00237
00238 if (n->inverted != (n->subframe_start_index < 0))
00239 printf("Nav phase flip\n");
00240 n->inverted = (n->subframe_start_index < 0);
00241
00242 if (!e) {
00243 printf(" process_subframe: CALLED WITH e = NULL!\n");
00244 n->subframe_start_index = 0;
00245 n->next_subframe_id = 1;
00246 return -1;
00247 }
00248 u32 sf_word2 = extract_word(n, 28, 32, 0);
00249 if (nav_parity(&sf_word2)) {
00250 printf("SUBFRAME PARITY ERROR (word 2)\n");
00251 n->subframe_start_index = 0;
00252 n->next_subframe_id = 1;
00253 return -2;
00254 }
00255
00256 u8 sf_id = sf_word2 >> 8 & 0x07;
00257
00258
00259
00260 if (sf_id <= 3 && sf_id == n->next_subframe_id) {
00261
00262 for (int w = 0; w < 8; w++) {
00263 n->frame_words[sf_id-1][w] = extract_word(n, 30*(w+2) - 2, 32, 0);
00264
00265 if (nav_parity(&n->frame_words[sf_id-1][w])) {
00266 printf("SUBFRAME PARITY ERROR (word %d)\n", w+3);
00267 n->next_subframe_id = 1;
00268 n->subframe_start_index = 0;
00269 return -3;
00270 }
00271 }
00272 n->subframe_start_index = 0;
00273 n->next_subframe_id++;
00274
00275 if (sf_id == 3) {
00276
00277 n->next_subframe_id = 1;
00278
00279
00280
00281
00282 union {
00283 s8 s8;
00284 u8 u8;
00285 } onebyte;
00286
00287 union
00288 {
00289 s16 s16;
00290 u16 u16;
00291 } twobyte;
00292
00293 union
00294 {
00295 s32 s32;
00296 u32 u32;
00297 } fourbyte;
00298
00299
00300
00301 e->toe.wn = (n->frame_words[0][3-3] >> (30-10) & 0x3FF);
00302 e->toe.wn += GPS_WEEK_CYCLE*1024;
00303 e->toc.wn = e->toe.wn;
00304
00305 e->healthy = !(n->frame_words[0][3-3] >> (30-17) & 1);
00306
00307 onebyte.u8 = n->frame_words[0][7-3] >> (30-24) & 0xFF;
00308 e->tgd = onebyte.s8 * pow(2,-31);
00309
00310 e->toc.tow = (n->frame_words[0][8-3] >> (30-24) & 0xFFFF) * 16;
00311
00312 onebyte.u8 = n->frame_words[0][9-3] >> (30-8) & 0xFF;
00313 e->af2 = onebyte.s8 * pow(2,-55);
00314
00315 twobyte.u16 = n->frame_words[0][9-3] >> (30-24) & 0xFFFF;
00316 e->af1 = twobyte.s16 * pow(2,-43);
00317
00318 fourbyte.u32 = n->frame_words[0][10-3] >> (30-22) & 0x3FFFFF;
00319 fourbyte.u32 <<= 10;
00320 fourbyte.s32 >>= 10;
00321 e->af0 = fourbyte.s32 * pow(2,-31);
00322
00323
00324
00325
00326 twobyte.u16 = n->frame_words[1][3-3] >> (30-24) & 0xFFFF;
00327 e->crs = twobyte.s16 * pow(2,-5);
00328
00329 twobyte.u16 = n->frame_words[1][4-3] >> (30-16) & 0xFFFF;
00330 e->dn = twobyte.s16 * pow(2,-43) * GPS_PI;
00331
00332 fourbyte.u32 = ((n->frame_words[1][4-3] >> (30-24) & 0xFF) << 24)
00333 | (n->frame_words[1][5-3] >> (30-24) & 0xFFFFFF);
00334 e->m0 = fourbyte.s32 * pow(2,-31) * GPS_PI;
00335
00336 twobyte.u16 = n->frame_words[1][6-3] >> (30-16) & 0xFFFF;
00337 e->cuc = twobyte.s16 * pow(2,-29);
00338
00339 fourbyte.u32 = ((n->frame_words[1][6-3] >> (30-24) & 0xFF) << 24)
00340 | (n->frame_words[1][7-3] >> (30-24) & 0xFFFFFF);
00341 e->ecc = fourbyte.u32 * pow(2,-33);
00342
00343
00344 twobyte.u16 = n->frame_words[1][8-3] >> (30-16) & 0xFFFF;
00345 e->cus = twobyte.s16 * pow(2,-29);
00346
00347
00348 fourbyte.u32 = ((n->frame_words[1][8-3] >> (30-24) & 0xFF) << 24)
00349 | (n->frame_words[1][9-3] >> (30-24) & 0xFFFFFF);
00350 e->sqrta = fourbyte.u32 * pow(2,-19);
00351
00352 e->toe.tow = (n->frame_words[1][10-3] >> (30-16) & 0xFFFF) * 16;
00353
00354
00355
00356
00357 twobyte.u16 = n->frame_words[2][3-3] >> (30-16) & 0xFFFF;
00358 e->cic = twobyte.s16 * pow(2,-29);
00359
00360 fourbyte.u32 = ((n->frame_words[2][3-3] >> (30-24) & 0xFF) << 24)
00361 | (n->frame_words[2][4-3] >> (30-24) & 0xFFFFFF);
00362 e->omega0 = fourbyte.s32 * pow(2,-31) * GPS_PI;
00363
00364 twobyte.u16 = n->frame_words[2][5-3] >> (30-16) & 0xFFFF;
00365 e->cis = twobyte.s16 * pow(2,-29);
00366
00367 fourbyte.u32 = ((n->frame_words[2][5-3] >> (30-24) & 0xFF) << 24)
00368 | (n->frame_words[2][6-3] >> (30-24) & 0xFFFFFF);
00369 e->inc = fourbyte.s32 * pow(2,-31) * GPS_PI;
00370
00371 twobyte.u16 = n->frame_words[2][7-3] >> (30-16) & 0xFFFF;
00372 e->crc = twobyte.s16 * pow(2,-5);
00373
00374 fourbyte.u32 = ((n->frame_words[2][7-3] >> (30-24) & 0xFF) << 24)
00375 | (n->frame_words[2][8-3] >> (30-24) & 0xFFFFFF);
00376 e->w = fourbyte.s32 * pow(2,-31) * GPS_PI;
00377
00378 fourbyte.u32 = n->frame_words[2][9-3] >> (30-24) & 0xFFFFFF;
00379 fourbyte.u32 <<= 8;
00380 fourbyte.s32 >>= 8;
00381 e->omegadot = fourbyte.s32 * pow(2,-43) * GPS_PI;
00382
00383
00384 twobyte.u16 = n->frame_words[2][10-3] >> (30-22) & 0x3FFF;
00385 twobyte.u16 <<= 2;
00386 twobyte.s16 >>= 2;
00387 e->inc_dot = twobyte.s16 * pow(2,-43) * GPS_PI;
00388
00389
00390 e->valid = 1;
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414 return 1;
00415
00416 }
00417 } else {
00418 n->next_subframe_id = 1;
00419 n->subframe_start_index = 0;
00420 }
00421
00422 return 0;
00423
00424
00425 }
00426