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