00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include <stdio.h>
00041 #include <memory.h>
00042 #include "gnss_error.h"
00043 #include "novatel.h"
00044 #include "gps.h"
00045 #include "constants.h"
00046
00047
00048
00049 static BOOL NOVATELOEM3_CompareChecksums(
00050 unsigned char *message,
00051 const unsigned messageLength,
00052 const unsigned messageChecksum,
00053 BOOL *isChecksumValid
00054 );
00055
00056
00057
00058 static unsigned NOVATEL_CalculateCRC32(
00059 unsigned char *crcData,
00060 const unsigned short dataLength
00061 );
00062
00063
00064
00065
00066 static BOOL NOVATEL_CheckCRC32(
00067 unsigned char *message,
00068 const unsigned short messageLength,
00069 const unsigned messageCRC,
00070 BOOL *isCRCValid
00071 );
00072
00073
00074 static const unsigned NOVATEL_CRC32_Table[256] =
00075 {
00076 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL,
00077 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L,
00078 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L,
00079 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
00080 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
00081 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L,
00082 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 0x35b5a8faL, 0x42b2986cL,
00083 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
00084 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L,
00085 0xcfba9599L, 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
00086 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, 0x01db7106L,
00087 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
00088 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL,
00089 0x91646c97L, 0xe6635c01L, 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL,
00090 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
00091 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
00092 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L,
00093 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L,
00094 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL,
00095 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
00096 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L,
00097 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL,
00098 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, 0xe3630b12L, 0x94643b84L,
00099 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
00100 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
00101 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL,
00102 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 0xd6d6a3e8L, 0xa1d1937eL,
00103 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
00104 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L,
00105 0x316e8eefL, 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
00106 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, 0xb2bd0b28L,
00107 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
00108 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL,
00109 0x72076785L, 0x05005713L, 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L,
00110 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
00111 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
00112 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L,
00113 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L,
00114 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL,
00115 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
00116 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L,
00117 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L,
00118 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL
00119 };
00120
00121
00122 BOOL NOVATELOEM3_CompareChecksums(
00123 unsigned char *message,
00124 const unsigned messageLength,
00125 const unsigned messageChecksum,
00126 BOOL *isChecksumValid
00127 )
00128 {
00129 unsigned char tmpc;
00130 unsigned char xorVal = 0;
00131 unsigned i = 0;
00132
00133 if( messageLength < 12 )
00134 return FALSE;
00135
00136 tmpc = message[3];
00137 message[3] = 0;
00138
00139
00140 for( xorVal = 0; i < messageLength; i++ )
00141 {
00142 xorVal ^= message[i];
00143 }
00144
00145
00146 message[3] = tmpc;
00147
00148 if( xorVal == messageChecksum )
00149 *isChecksumValid = TRUE;
00150 else
00151 *isChecksumValid = FALSE;
00152
00153 return TRUE;
00154 }
00155
00156
00157
00158 unsigned NOVATEL_CalculateCRC32(
00159 unsigned char *crcData,
00160 const unsigned short dataLength
00161 )
00162 {
00163 unsigned i;
00164 unsigned crc = 0;
00165 for( i = 0; i < dataLength; i++ )
00166 crc = NOVATEL_CRC32_Table[(crc ^ crcData[i]) & 0xFF] ^ (crc >> 8);
00167 return crc;
00168 }
00169
00170
00171
00172 BOOL NOVATEL_CheckCRC32(
00173 unsigned char *message,
00174 const unsigned short messageLength,
00175 const unsigned messageCRC,
00176 BOOL *isCRCValid
00177 )
00178 {
00179 unsigned crc = 0;
00180
00181 if( message == NULL )
00182 {
00183 GNSS_ERROR_MSG( "if( message == NULL )" );
00184 return FALSE;
00185 }
00186
00187
00188 crc = NOVATEL_CalculateCRC32( message, messageLength-4 );
00189
00190 *isCRCValid = FALSE;
00191
00192 if( messageCRC != crc )
00193 *isCRCValid = FALSE;
00194 else
00195 *isCRCValid = TRUE;
00196
00197 return TRUE;
00198 }
00199
00200
00201
00202
00203 BOOL NOVATELOEM3_FindNextMessageInFile(
00204 FILE *fid,
00205 unsigned char *message,
00206 const unsigned maxMessageLength,
00207 BOOL *wasEndOfFileReached,
00208 BOOL *wasMessageFound,
00209 unsigned *filePosition,
00210 unsigned *messageLength,
00211 unsigned *messageID,
00212 unsigned *numberBadChecksums
00213 )
00214 {
00215 unsigned i = 0;
00216 unsigned char sync[3];
00217 unsigned byteCount = 0;
00218 unsigned dataLength = 0;
00219 unsigned msgLength = 0;
00220 int fpos = 0;
00221 unsigned char rx_checksum = 0;
00222 BOOL startSearch = TRUE;
00223 BOOL isChecksumValid = FALSE;
00224
00225 const unsigned char headerLength = 12;
00226
00227
00228 *wasEndOfFileReached = FALSE;
00229 *wasMessageFound = 0;
00230 *filePosition = 0;
00231 *messageLength = 0;
00232 *messageID = 0;
00233 *numberBadChecksums = 0;
00234
00235
00236 if( fid == NULL )
00237 {
00238 GNSS_ERROR_MSG( "if( fid == NULL )" );
00239 return FALSE;
00240 }
00241
00242 if( message == NULL )
00243 {
00244 GNSS_ERROR_MSG( "if( message == NULL )" );
00245 return FALSE;
00246 }
00247
00248
00249 if( maxMessageLength < 12 )
00250 {
00251 GNSS_ERROR_MSG( "if( maxMessageLength < 12 )" );
00252 return FALSE;
00253 }
00254
00255
00256 if( feof(fid) )
00257 {
00258 *wasEndOfFileReached = TRUE;
00259 return TRUE;
00260 }
00261
00262 while( !(*wasEndOfFileReached) && !(*wasMessageFound) )
00263 {
00264 if( startSearch )
00265 {
00266
00267 sync[0] = (unsigned char)fgetc( fid );
00268 if( feof( fid ) )
00269 {
00270 *wasEndOfFileReached = TRUE;
00271 return TRUE;
00272 }
00273
00274 sync[1] = (unsigned char)fgetc( fid );
00275 if( feof( fid ) )
00276 {
00277 *wasEndOfFileReached = TRUE;
00278 return TRUE;
00279 }
00280
00281 startSearch = FALSE;
00282 }
00283
00284
00285 sync[2] = (unsigned char)fgetc( fid );
00286 if( feof( fid ) )
00287 {
00288 *wasEndOfFileReached = TRUE;
00289 return TRUE;
00290 }
00291
00292
00293 if( sync[0] == 0xAA && sync[1] == 0x44 && sync[2] == 0x11 )
00294 {
00295
00296 i = 0;
00297 message[i] = sync[0]; i++;
00298 message[i] = sync[1]; i++;
00299 message[i] = sync[2]; i++;
00300
00301
00302 fpos = ftell(fid);
00303 if( fpos < 2 )
00304 {
00305 GNSS_ERROR_MSG( "if( fpos < 2 )" );
00306 return FALSE;
00307 }
00308 *filePosition = fpos - 3;
00309
00310
00311 rx_checksum = (unsigned char)fgetc( fid );
00312 if( feof( fid ) )
00313 {
00314 *wasEndOfFileReached = TRUE;
00315 return TRUE;
00316 }
00317 message[i] = rx_checksum;
00318 i++;
00319
00320
00321 byteCount = (int)fread( &(message[i]), sizeof(unsigned char), 4, fid );
00322 if( byteCount != 4 )
00323 {
00324 *wasEndOfFileReached = TRUE;
00325 return TRUE;
00326 }
00327
00328 *messageID = message[i]; i++;
00329 *messageID |= message[i] << 8; i++;
00330 *messageID |= message[i] << 16; i++;
00331 *messageID |= message[i] << 24; i++;
00332
00333
00334 byteCount = (int)fread( &(message[i]), sizeof(unsigned char), 4, fid );
00335 if( byteCount != 4 )
00336 {
00337 *wasEndOfFileReached = TRUE;
00338 return TRUE;
00339 }
00340
00341 msgLength = message[i]; i++;
00342 msgLength |= message[i] << 8; i++;
00343 msgLength |= message[i] << 16; i++;
00344 msgLength |= message[i] << 24; i++;
00345
00346
00347 dataLength = msgLength - headerLength;
00348
00349
00350 if( msgLength > maxMessageLength )
00351 {
00352
00353
00354
00355 if( fseek( fid, fpos, SEEK_SET ) != 0 )
00356 {
00357
00358 GNSS_ERROR_MSG( "fseek failed." );
00359 return FALSE;
00360 }
00361 startSearch = TRUE;
00362 continue;
00363 }
00364
00365
00366
00367 i = headerLength;
00368 byteCount = (int)fread( &(message[i]), sizeof(unsigned char), dataLength, fid );
00369 if( byteCount != dataLength )
00370 {
00371
00372
00373
00374
00375 if( fseek( fid, fpos, SEEK_SET ) != 0 )
00376 {
00377
00378 GNSS_ERROR_MSG( "fseek failed." );
00379 return FALSE;
00380 }
00381 startSearch = TRUE;
00382 continue;
00383 }
00384 i += dataLength;
00385
00386
00387 if( !NOVATELOEM3_CompareChecksums( message, msgLength, rx_checksum, &isChecksumValid ) )
00388 {
00389 GNSS_ERROR_MSG( "NOVATELOEM3_CompareChecksums returned FALSE." );
00390 return FALSE;
00391 }
00392 if( !isChecksumValid )
00393 {
00394 *numberBadChecksums += 1;
00395
00396
00397
00398 if( fseek( fid, fpos, SEEK_SET ) != 0 )
00399 {
00400
00401 GNSS_ERROR_MSG( "fseek failed." );
00402 return FALSE;
00403 }
00404 startSearch = TRUE;
00405 continue;
00406 }
00407
00408 *wasMessageFound = TRUE;
00409 *messageLength = msgLength;
00410 break;
00411 }
00412 else
00413 {
00414
00415 sync[0] = sync[1];
00416 sync[1] = sync[2];
00417 }
00418 }
00419 return TRUE;
00420 }
00421
00422
00423
00424 BOOL NOVATELOEM3_FindNextMessageInBuffer(
00425 unsigned char *buffer,
00426 const unsigned bufferLength,
00427 unsigned char *message,
00428 const unsigned maxMessageLength,
00429 BOOL *wasEndOfBufferReached,
00430 BOOL *wasMessageFound,
00431 unsigned *startPosition,
00432 unsigned *messageLength,
00433 unsigned *messageID,
00434 unsigned *numberBadChecksums
00435 )
00436 {
00437 unsigned bi = 0;
00438 unsigned i = 0;
00439 unsigned char sync[3];
00440 unsigned dataLength = 0;
00441 unsigned msgLength = 0;
00442 int bpos = 0;
00443 unsigned char rx_checksum = 0;
00444 BOOL startSearch = TRUE;
00445 BOOL isChecksumValid = FALSE;
00446
00447 const unsigned char headerLength = 12;
00448
00449
00450 *wasEndOfBufferReached = FALSE;
00451 *wasMessageFound = 0;
00452 *startPosition = 0;
00453 *messageLength = 0;
00454 *messageID = 0;
00455 *numberBadChecksums = 0;
00456
00457
00458 if( buffer == NULL )
00459 {
00460 GNSS_ERROR_MSG( "if( fid == NULL )" );
00461 return FALSE;
00462 }
00463
00464 if( message == NULL )
00465 {
00466 GNSS_ERROR_MSG( "if( message == NULL )" );
00467 return FALSE;
00468 }
00469
00470
00471 if( maxMessageLength < 12 )
00472 {
00473 GNSS_ERROR_MSG( "if( maxMessageLength < 12 )" );
00474 return FALSE;
00475 }
00476
00477 while( !(*wasEndOfBufferReached) && !(*wasMessageFound) )
00478 {
00479 if( startSearch )
00480 {
00481
00482 sync[0] = buffer[bi]; bi++;
00483 if( bi >= bufferLength )
00484 {
00485 *wasEndOfBufferReached = TRUE;
00486 return TRUE;
00487 }
00488
00489 sync[1] = buffer[bi]; bi++;
00490 if( bi >= bufferLength )
00491 {
00492 *wasEndOfBufferReached = TRUE;
00493 return TRUE;
00494 }
00495 startSearch = FALSE;
00496 }
00497
00498
00499 sync[2] = buffer[bi]; bi++;
00500 if( bi >= bufferLength )
00501 {
00502 *wasEndOfBufferReached = TRUE;
00503 return TRUE;
00504 }
00505
00506
00507 if( sync[0] == 0xAA && sync[1] == 0x44 && sync[2] == 0x11 )
00508 {
00509
00510 i = 0;
00511 message[i] = sync[0]; i++;
00512 message[i] = sync[1]; i++;
00513 message[i] = sync[2]; i++;
00514
00515
00516 bpos = bi;
00517 *startPosition = bi - 3;
00518
00519
00520 rx_checksum = buffer[bi]; bi++;
00521 if( bi > bufferLength )
00522 {
00523 *wasEndOfBufferReached = TRUE;
00524 return TRUE;
00525 }
00526 message[i] = rx_checksum;
00527 i++;
00528
00529
00530 if( bi+4 > bufferLength )
00531 {
00532 *wasEndOfBufferReached = TRUE;
00533 return TRUE;
00534 }
00535 memcpy( &message[i], buffer+bi, 4 );
00536 bi+=4;
00537
00538
00539 *messageID = message[i]; i++;
00540 *messageID |= message[i] << 8; i++;
00541 *messageID |= message[i] << 16; i++;
00542 *messageID |= message[i] << 24; i++;
00543
00544
00545 if( bi+4 > bufferLength )
00546 {
00547 *wasEndOfBufferReached = TRUE;
00548 return TRUE;
00549 }
00550 memcpy( &message[i], buffer+bi, 4 );
00551 bi+=4;
00552
00553
00554 msgLength = message[i]; i++;
00555 msgLength |= message[i] << 8; i++;
00556 msgLength |= message[i] << 16; i++;
00557 msgLength |= message[i] << 24; i++;
00558
00559
00560 dataLength = msgLength - headerLength;
00561
00562
00563 if( msgLength > maxMessageLength )
00564 {
00565
00566
00567
00568 bi = bpos;
00569 startSearch = TRUE;
00570 continue;
00571 }
00572
00573
00574
00575 i = headerLength;
00576
00577 if( bi+dataLength > bufferLength )
00578 {
00579 *wasEndOfBufferReached = TRUE;
00580 return TRUE;
00581 }
00582 memcpy( &message[i], buffer+bi, dataLength );
00583 bi+=dataLength;
00584 i += dataLength;
00585
00586
00587 if( !NOVATELOEM3_CompareChecksums( message, msgLength, rx_checksum, &isChecksumValid ) )
00588 {
00589 GNSS_ERROR_MSG( "NOVATELOEM3_CompareChecksums returned FALSE." );
00590 return FALSE;
00591 }
00592 if( !isChecksumValid )
00593 {
00594 *numberBadChecksums += 1;
00595
00596
00597
00598 bi = bpos;
00599 startSearch = TRUE;
00600 continue;
00601 }
00602
00603 *wasMessageFound = TRUE;
00604 *messageLength = msgLength;
00605 break;
00606 }
00607 else
00608 {
00609
00610 sync[0] = sync[1];
00611 sync[1] = sync[2];
00612 }
00613 }
00614 return TRUE;
00615 }
00616
00617
00618 BOOL NOVATELOEM3_DecodeREPB(
00619 const unsigned char *message,
00620 const unsigned messageLength,
00621 unsigned *prn,
00622 unsigned *tow,
00623 unsigned short *iodc,
00624 unsigned char *iode,
00625 unsigned *toe,
00626 unsigned *toc,
00627 unsigned short *week,
00628 unsigned char *health,
00629 unsigned char *alert_flag,
00630 unsigned char *anti_spoof,
00631 unsigned char *code_on_L2,
00632 unsigned char *ura,
00633 unsigned char *L2_P_data_flag,
00634 unsigned char *fit_interval_flag,
00635 unsigned short *age_of_data_offset,
00636 double *tgd,
00637 double *af2,
00638 double *af1,
00639 double *af0,
00640 double *m0,
00641 double *delta_n,
00642 double *ecc,
00643 double *sqrta,
00644 double *omega0,
00645 double *i0,
00646 double *w,
00647 double *omegadot,
00648 double *idot,
00649 double *cuc,
00650 double *cus,
00651 double *crc,
00652 double *crs,
00653 double *cic,
00654 double *cis
00655 )
00656 {
00657 unsigned msgLength = 0;
00658 unsigned index = 0;
00659 BOOL result = FALSE;
00660
00661
00662 if( message == NULL )
00663 {
00664 GNSS_ERROR_MSG( "if( message == NULL )" );
00665 return FALSE;
00666 }
00667 if( message[0] != 0xAA || message[1] != 0x44 || message[2] != 0x11 )
00668 {
00669 GNSS_ERROR_MSG( "sync not present" );
00670 return FALSE;
00671 }
00672
00673
00674 if( messageLength != 108 )
00675 {
00676 GNSS_ERROR_MSG( "if( messageLength != 108 )" );
00677 return FALSE;
00678 }
00679
00680
00681 index = 8;
00682 msgLength = message[index]; index++;
00683 msgLength |= message[index] << 8; index++;
00684 msgLength |= message[index] << 16; index++;
00685 msgLength |= message[index] << 24; index++;
00686
00687
00688 if( messageLength != msgLength )
00689 {
00690 GNSS_ERROR_MSG( "if( messageLength != msgLength )" );
00691 return FALSE;
00692 }
00693
00694 index = 12;
00695 *prn = message[index]; index++;
00696 *prn |= message[index] << 8; index++;
00697 *prn |= message[index] << 16; index++;
00698 *prn |= message[index] << 24; index++;
00699
00700 result = GPS_DecodeRawGPSEphemeris(
00701 &message[index],
00702 &message[index+30],
00703 &message[index+60],
00704 (unsigned short)(*prn),
00705 tow,
00706 iodc,
00707 iode,
00708 toe,
00709 toc,
00710 week,
00711 health,
00712 alert_flag,
00713 anti_spoof,
00714 code_on_L2,
00715 ura,
00716 L2_P_data_flag,
00717 fit_interval_flag,
00718 age_of_data_offset,
00719 tgd,
00720 af2,
00721 af1,
00722 af0,
00723 m0,
00724 delta_n,
00725 ecc,
00726 sqrta,
00727 omega0,
00728 i0,
00729 w,
00730 omegadot,
00731 idot,
00732 cuc,
00733 cus,
00734 crc,
00735 crs,
00736 cic,
00737 cis
00738 );
00739 if( !result )
00740 {
00741 GNSS_ERROR_MSG( "GPS_DecodeRawGPSEphemeris returned FALSE." );
00742 return FALSE;
00743 }
00744
00745 return TRUE;
00746 }
00747
00748 BOOL NOVATELOEM3_DecodeRGEB(
00749 const unsigned char *message,
00750 const unsigned messageLength,
00751 NOVATELOEM3_structObservationHeader* obsHeader,
00752 NOVATELOEM3_structObservation* obsArray,
00753 const unsigned char maxNrObs,
00754 unsigned *nrObs
00755 )
00756 {
00757 unsigned nrObsInMessage = 0;
00758 unsigned messageID = 0;
00759 unsigned utmp = 0;
00760 unsigned i = 0;
00761 unsigned j = 0;
00762 unsigned obsIndex = 0;
00763 unsigned char dbytes[8];
00764 unsigned char fbytes[4];
00765 double *dptr;
00766 float *fptr;
00767
00768 NOVATELOEM3_bitfieldTrackingStatus* ptrTrackStatus = NULL;
00769 NOVATELOEM3_bitfieldSelfTestStatus* ptrSelfStatus = NULL;
00770
00771 if( message == NULL )
00772 {
00773 GNSS_ERROR_MSG( "if( message == NULL )" );
00774 return FALSE;
00775 }
00776 if( messageLength < 12+20 )
00777 {
00778 GNSS_ERROR_MSG( "if( messageLength < 12+20 )" );
00779 return FALSE;
00780 }
00781 if( message[0] != 0xAA || message[1] != 0x44 || message[2] != 0x11 )
00782 {
00783 GNSS_ERROR_MSG( "sync not present" );
00784 return FALSE;
00785 }
00786
00787 if( obsHeader == NULL )
00788 {
00789 GNSS_ERROR_MSG( "if( obsHeader == NULL )" );
00790 return FALSE;
00791 }
00792 if( obsArray == NULL )
00793 {
00794 GNSS_ERROR_MSG( "if( obsArray == NULL )" );
00795 return FALSE;
00796 }
00797 if( nrObs == NULL )
00798 {
00799 GNSS_ERROR_MSG( "if( nrObs == NULL )" );
00800 return FALSE;
00801 }
00802
00803 memset( obsHeader, 0, sizeof(NOVATELOEM3_structObservationHeader) );
00804
00805 i = 4;
00806 messageID = message[i]; i++;
00807 messageID |= message[i] << 8; i++;
00808 messageID |= message[i] << 16; i++;
00809 messageID |= message[i] << 24; i++;
00810
00811 if( messageID != NOVATELOEM3_RGEB )
00812 {
00813 GNSS_ERROR_MSG( "if( messageID != NOVATELOEM3_RGEB )" );
00814 return FALSE;
00815 }
00816
00817 i = 24;
00818 nrObsInMessage = message[i]; i++;
00819 nrObsInMessage |= message[i] << 8; i++;
00820 nrObsInMessage |= message[i] << 16; i++;
00821 nrObsInMessage |= message[i] << 24; i++;
00822
00823 if( nrObsInMessage > maxNrObs )
00824 {
00825 GNSS_ERROR_MSG( "if( nrObsInMessage > maxNrObs )" );
00826 return FALSE;
00827 }
00828
00829 obsHeader->nrObs = nrObsInMessage;
00830
00831 i = 12;
00832 obsHeader->week = message[i]; i++;
00833 obsHeader->week |= message[i] << 8; i++;
00834 obsHeader->week |= message[i] << 16; i++;
00835 obsHeader->week |= message[i] << 24; i++;
00836
00837
00838 for( j=0; j<8; j++ ){ dbytes[j] = message[i]; i++; }
00839 dptr = (double*)&dbytes;
00840 obsHeader->tow = *dptr;
00841
00842
00843 i = 28;
00844 utmp = message[i]; i++;
00845 utmp |= message[i] << 8; i++;
00846 utmp |= message[i] << 16; i++;
00847 utmp |= message[i] << 24; i++;
00848
00849 ptrSelfStatus = (NOVATELOEM3_bitfieldSelfTestStatus*)&utmp;
00850 obsHeader->status = *ptrSelfStatus;
00851
00852 for( obsIndex = 0; obsIndex < nrObsInMessage; obsIndex++ )
00853 {
00854 utmp = message[i]; i++;
00855 utmp |= message[i] << 8; i++;
00856 utmp |= message[i] << 16; i++;
00857 utmp |= message[i] << 24; i++;
00858
00859
00860 obsArray[obsIndex].prn = utmp;
00861
00862
00863 for( j=0; j<8; j++ ){ dbytes[j] = message[i]; i++; }
00864 dptr = (double*)&dbytes;
00865 obsArray[obsIndex].psr = *dptr;
00866
00867
00868 for( j=0; j<4; j++ ){ fbytes[j] = message[i]; i++; }
00869 fptr = (float*)&fbytes;
00870 obsArray[obsIndex].psrstd = *fptr;
00871
00872
00873 for( j=0; j<8; j++ ){ dbytes[j] = message[i]; i++; }
00874 dptr = (double*)&dbytes;
00875 obsArray[obsIndex].adr = *dptr;
00876
00877
00878 for( j=0; j<4; j++ ){ fbytes[j] = message[i]; i++; }
00879 fptr = (float*)&fbytes;
00880 obsArray[obsIndex].adrstd = *fptr;
00881
00882
00883 for( j=0; j<4; j++ ){ fbytes[j] = message[i]; i++; }
00884 fptr = (float*)&fbytes;
00885 obsArray[obsIndex].doppler = *fptr;
00886
00887
00888 for( j=0; j<4; j++ ){ fbytes[j] = message[i]; i++; }
00889 fptr = (float*)&fbytes;
00890 obsArray[obsIndex].cno = *fptr;
00891
00892
00893 for( j=0; j<4; j++ ){ fbytes[j] = message[i]; i++; }
00894 fptr = (float*)&fbytes;
00895 obsArray[obsIndex].locktime = *fptr;
00896
00897
00898 utmp = message[i]; i++;
00899 utmp |= message[i] << 8; i++;
00900 utmp |= message[i] << 16; i++;
00901 utmp |= message[i] << 24; i++;
00902
00903 ptrTrackStatus = (NOVATELOEM3_bitfieldTrackingStatus*)&utmp;
00904 obsArray[obsIndex].status = *ptrTrackStatus;
00905 }
00906
00907 *nrObs = obsHeader->nrObs;
00908
00909 return TRUE;
00910 }
00911
00912
00913 BOOL NOVATELOEM3_DecodePOSB(
00914 const unsigned char *message,
00915 const unsigned messageLength,
00916 unsigned short* gps_week,
00917 double* gps_tow,
00918 double* latitude_degs,
00919 double* longitude_degs,
00920 double* height_msl,
00921 double* undulation,
00922 unsigned int* datum_id,
00923 double* lat_std,
00924 double* lon_std,
00925 double* hgt_std,
00926 NOVATELOEM3_enumSolutionStatus* status
00927 )
00928 {
00929 unsigned messageID = 0;
00930 unsigned utmp = 0;
00931 unsigned i = 0;
00932 unsigned j = 0;
00933 unsigned obsIndex = 0;
00934 unsigned char dbytes[8];
00935 double *dptr;
00936
00937 if( message == NULL )
00938 {
00939 GNSS_ERROR_MSG( "if( message == NULL )" );
00940 return FALSE;
00941 }
00942 if( messageLength != 88 )
00943 {
00944 GNSS_ERROR_MSG( "if( messageLength != 88 )" );
00945 return FALSE;
00946 }
00947 if( message[0] != 0xAA || message[1] != 0x44 || message[2] != 0x11 )
00948 {
00949 GNSS_ERROR_MSG( "sync not present" );
00950 return FALSE;
00951 }
00952
00953 if( gps_week == NULL ||
00954 gps_tow == NULL ||
00955 latitude_degs == NULL ||
00956 longitude_degs == NULL ||
00957 height_msl == NULL ||
00958 undulation == NULL ||
00959 datum_id == NULL ||
00960 lat_std == NULL ||
00961 lon_std == NULL ||
00962 hgt_std == NULL ||
00963 status == NULL )
00964 {
00965 GNSS_ERROR_MSG( "NULL parameter not allowed." );
00966 return FALSE;
00967 }
00968
00969 i = 4;
00970 messageID = message[i]; i++;
00971 messageID |= message[i] << 8; i++;
00972 messageID |= message[i] << 16; i++;
00973 messageID |= message[i] << 24; i++;
00974
00975 if( messageID != NOVATELOEM3_POSB )
00976 {
00977 GNSS_ERROR_MSG( "if( messageID != NOVATELOEM3_POSB )" );
00978 return FALSE;
00979 }
00980
00981 i = 12;
00982
00983 utmp = message[i]; i++;
00984 utmp |= message[i] << 8; i++;
00985 utmp |= message[i] << 16; i++;
00986 utmp |= message[i] << 24; i++;
00987
00988 *gps_week = (unsigned short)utmp;
00989
00990
00991 for( j=0; j<8; j++ ){ dbytes[j] = message[i]; i++; }
00992 dptr = (double*)&dbytes;
00993 *gps_tow = *dptr;
00994
00995
00996 for( j=0; j<8; j++ ){ dbytes[j] = message[i]; i++; }
00997 dptr = (double*)&dbytes;
00998 *latitude_degs = *dptr;
00999
01000
01001 for( j=0; j<8; j++ ){ dbytes[j] = message[i]; i++; }
01002 dptr = (double*)&dbytes;
01003 *longitude_degs = *dptr;
01004
01005
01006 for( j=0; j<8; j++ ){ dbytes[j] = message[i]; i++; }
01007 dptr = (double*)&dbytes;
01008 *height_msl = *dptr;
01009
01010
01011 for( j=0; j<8; j++ ){ dbytes[j] = message[i]; i++; }
01012 dptr = (double*)&dbytes;
01013 *undulation = *dptr;
01014
01015
01016 utmp = message[i]; i++;
01017 utmp |= message[i] << 8; i++;
01018 utmp |= message[i] << 16; i++;
01019 utmp |= message[i] << 24; i++;
01020 *datum_id = utmp;
01021
01022
01023 for( j=0; j<8; j++ ){ dbytes[j] = message[i]; i++; }
01024 dptr = (double*)&dbytes;
01025 *lat_std = *dptr;
01026
01027
01028 for( j=0; j<8; j++ ){ dbytes[j] = message[i]; i++; }
01029 dptr = (double*)&dbytes;
01030 *lon_std = *dptr;
01031
01032
01033 for( j=0; j<8; j++ ){ dbytes[j] = message[i]; i++; }
01034 dptr = (double*)&dbytes;
01035 *hgt_std = *dptr;
01036
01037
01038 utmp = message[i]; i++;
01039 utmp |= message[i] << 8; i++;
01040 utmp |= message[i] << 16; i++;
01041 utmp |= message[i] << 24; i++;
01042 *status = (NOVATELOEM3_enumSolutionStatus)utmp;
01043
01044 return TRUE;
01045 }
01046
01047
01048 BOOL NOVATELOEM3_DecodeTM1B(
01049 const unsigned char *message,
01050 const unsigned messageLength,
01051 unsigned short* gps_week,
01052 double* gps_tow,
01053 double* clk_offset,
01054 double* clk_offset_std,
01055 double* utc_offset,
01056 BOOL* is_clk_stabilized
01057 )
01058 {
01059 unsigned messageID = 0;
01060 unsigned utmp = 0;
01061 unsigned i = 0;
01062 unsigned j = 0;
01063 unsigned obsIndex = 0;
01064 unsigned char dbytes[8];
01065 double *dptr;
01066
01067 if( message == NULL )
01068 {
01069 GNSS_ERROR_MSG( "if( message == NULL )" );
01070 return FALSE;
01071 }
01072 if( messageLength != 52 )
01073 {
01074 GNSS_ERROR_MSG( "if( messageLength != 52 )" );
01075 return FALSE;
01076 }
01077 if( message[0] != 0xAA || message[1] != 0x44 || message[2] != 0x11 )
01078 {
01079 GNSS_ERROR_MSG( "sync not present" );
01080 return FALSE;
01081 }
01082
01083 if( gps_week == NULL ||
01084 gps_tow == NULL ||
01085 clk_offset == NULL ||
01086 clk_offset_std == NULL ||
01087 utc_offset == NULL ||
01088 is_clk_stabilized == NULL )
01089 {
01090 GNSS_ERROR_MSG( "NULL parameter not allowed." );
01091 return FALSE;
01092 }
01093
01094 i = 4;
01095 messageID = message[i]; i++;
01096 messageID |= message[i] << 8; i++;
01097 messageID |= message[i] << 16; i++;
01098 messageID |= message[i] << 24; i++;
01099
01100 if( messageID != NOVATELOEM3_TM1B )
01101 {
01102 GNSS_ERROR_MSG( "if( messageID != NOVATELOEM3_TM1B )" );
01103 return FALSE;
01104 }
01105
01106 i = 12;
01107
01108 utmp = message[i]; i++;
01109 utmp |= message[i] << 8; i++;
01110 utmp |= message[i] << 16; i++;
01111 utmp |= message[i] << 24; i++;
01112
01113 *gps_week = (unsigned short)utmp;
01114
01115
01116 for( j=0; j<8; j++ ){ dbytes[j] = message[i]; i++; }
01117 dptr = (double*)&dbytes;
01118 *gps_tow = *dptr;
01119
01120
01121 for( j=0; j<8; j++ ){ dbytes[j] = message[i]; i++; }
01122 dptr = (double*)&dbytes;
01123 *clk_offset = *dptr;
01124
01125
01126 for( j=0; j<8; j++ ){ dbytes[j] = message[i]; i++; }
01127 dptr = (double*)&dbytes;
01128 *clk_offset_std = *dptr;
01129
01130
01131 for( j=0; j<8; j++ ){ dbytes[j] = message[i]; i++; }
01132 dptr = (double*)&dbytes;
01133 *utc_offset = *dptr;
01134
01135
01136 utmp = message[i]; i++;
01137 utmp |= message[i] << 8; i++;
01138 utmp |= message[i] << 16; i++;
01139 utmp |= message[i] << 24; i++;
01140
01141 if( utmp == 0 )
01142 {
01143 *is_clk_stabilized = TRUE;
01144 }
01145 else
01146 {
01147 *is_clk_stabilized = FALSE;
01148 }
01149
01150 return TRUE;
01151 }
01152
01153
01154
01155 BOOL NOVATELOEM3_DecodeIONB(
01156 const unsigned char *message,
01157 const unsigned messageLength,
01158 double *alpha0,
01159 double *alpha1,
01160 double *alpha2,
01161 double *alpha3,
01162 double *beta0,
01163 double *beta1,
01164 double *beta2,
01165 double *beta3
01166 )
01167 {
01168 unsigned messageID = 0;
01169 unsigned i = 0;
01170 unsigned j = 0;
01171 unsigned char dbytes[8];
01172 double *dptr = NULL;
01173
01174 if( message == NULL )
01175 {
01176 GNSS_ERROR_MSG( "if( message == NULL )");
01177 return FALSE;
01178 }
01179 if( messageLength != 76 )
01180 {
01181 GNSS_ERROR_MSG( "if( messageLength != 76 )");
01182 return FALSE;
01183 }
01184
01185 if( message[0] != 0xAA || message[1] != 0x44 || message[2] != 0x11 )
01186 {
01187 GNSS_ERROR_MSG( "sync not present" );
01188 return FALSE;
01189 }
01190 if( alpha0 == NULL ||
01191 alpha1 == NULL ||
01192 alpha2 == NULL ||
01193 alpha3 == NULL ||
01194 beta0 == NULL ||
01195 beta1 == NULL ||
01196 beta2 == NULL ||
01197 beta3 == NULL )
01198 {
01199 GNSS_ERROR_MSG( "NULL alpha or beta parameters.");
01200 return FALSE;
01201 }
01202
01203 i = 4;
01204 messageID = message[i]; i++;
01205 messageID |= message[i] << 8; i++;
01206 messageID |= message[i] << 16; i++;
01207 messageID |= message[i] << 24; i++;
01208
01209 if( messageID != NOVATELOEM3_IONB )
01210 {
01211 GNSS_ERROR_MSG( "if( messageID != NOVATELOEM3_IONB )");
01212 return FALSE;
01213 }
01214
01215 i = 12;
01216 for( j=0; j<8; j++ ){ dbytes[j] = message[i]; i++; }
01217 dptr = (double*)&dbytes;
01218 *alpha0 = *dptr;
01219
01220 for( j=0; j<8; j++ ){ dbytes[j] = message[i]; i++; }
01221 dptr = (double*)&dbytes;
01222 *alpha1 = *dptr;
01223
01224 for( j=0; j<8; j++ ){ dbytes[j] = message[i]; i++; }
01225 dptr = (double*)&dbytes;
01226 *alpha2 = *dptr;
01227
01228 for( j=0; j<8; j++ ){ dbytes[j] = message[i]; i++; }
01229 dptr = (double*)&dbytes;
01230 *alpha3 = *dptr;
01231
01232 for( j=0; j<8; j++ ){ dbytes[j] = message[i]; i++; }
01233 dptr = (double*)&dbytes;
01234 *beta0 = *dptr;
01235
01236 for( j=0; j<8; j++ ){ dbytes[j] = message[i]; i++; }
01237 dptr = (double*)&dbytes;
01238 *beta1 = *dptr;
01239
01240 for( j=0; j<8; j++ ){ dbytes[j] = message[i]; i++; }
01241 dptr = (double*)&dbytes;
01242 *beta2 = *dptr;
01243
01244 for( j=0; j<8; j++ ){ dbytes[j] = message[i]; i++; }
01245 dptr = (double*)&dbytes;
01246 *beta3 = *dptr;
01247
01248 return TRUE;
01249 }
01250
01251
01252
01253 BOOL NOVATELOEM4_FindNextMessageInFile(
01254 FILE *fid,
01255 unsigned char *message,
01256 const unsigned maxMessageLength,
01257 BOOL *wasEndOfFileReached,
01258 BOOL *wasMessageFound,
01259 unsigned *filePosition,
01260 unsigned short *messageLength,
01261 unsigned short *messageID,
01262 unsigned *numberBadCRC
01263 )
01264 {
01265 unsigned i = 0;
01266 unsigned char sync[3];
01267 unsigned char headerLength = 0;
01268 unsigned byteCount = 0;
01269 unsigned short dataLength = 0;
01270 unsigned short msgLength = 0;
01271 int fpos = 0;
01272 unsigned messageCRC = 0;
01273 BOOL startSearch = TRUE;
01274 BOOL isCRCValid = FALSE;
01275
01276
01277
01278 *wasEndOfFileReached = FALSE;
01279 *wasMessageFound = 0;
01280 *filePosition = 0;
01281 *messageLength = 0;
01282 *messageID = 0;
01283 *numberBadCRC = 0;
01284
01285
01286 if( fid == NULL )
01287 {
01288 GNSS_ERROR_MSG( "if( fid == NULL )" );
01289 return FALSE;
01290 }
01291
01292
01293 if( maxMessageLength < 32 )
01294 {
01295 GNSS_ERROR_MSG( "if( maxMessageLength < 32 )" );
01296 return FALSE;
01297 }
01298
01299
01300 if( feof(fid) )
01301 {
01302 *wasEndOfFileReached = TRUE;
01303 return TRUE;
01304 }
01305
01306 while( !(*wasEndOfFileReached) && !(*wasMessageFound) )
01307 {
01308 if( startSearch )
01309 {
01310
01311 sync[0] = (unsigned char)fgetc( fid );
01312 if( feof( fid ) )
01313 {
01314 *wasEndOfFileReached = TRUE;
01315 return TRUE;
01316 }
01317
01318 sync[1] = (unsigned char)fgetc( fid );
01319 if( feof( fid ) )
01320 {
01321 *wasEndOfFileReached = TRUE;
01322 return TRUE;
01323 }
01324
01325 startSearch = FALSE;
01326 }
01327
01328
01329 sync[2] = (unsigned char)fgetc( fid );
01330 if( feof( fid ) )
01331 {
01332 *wasEndOfFileReached = TRUE;
01333 return TRUE;
01334 }
01335
01336
01337 if( sync[0] == 0xAA && sync[1] == 0x44 && sync[2] == 0x12 )
01338 {
01339
01340 i = 0;
01341 message[i] = sync[0]; i++;
01342 message[i] = sync[1]; i++;
01343 message[i] = sync[2]; i++;
01344
01345
01346 fpos = ftell(fid);
01347 if( fpos < 2 )
01348 {
01349 GNSS_ERROR_MSG( "if( fpos < 2 )" );
01350 return FALSE;
01351 }
01352 *filePosition = fpos - 3;
01353
01354
01355 headerLength = (unsigned char)fgetc( fid );
01356 if( feof( fid ) )
01357 {
01358 *wasEndOfFileReached = TRUE;
01359 return TRUE;
01360 }
01361 message[i] = headerLength;
01362 i++;
01363
01364
01365 byteCount = (int)fread( &(message[i]), sizeof(unsigned char), headerLength-4, fid );
01366 if( byteCount+4 != headerLength )
01367 {
01368 *wasEndOfFileReached = TRUE;
01369 return TRUE;
01370 }
01371
01372
01373 *messageID = message[i];
01374 i++;
01375 *messageID |= message[i] << 8;
01376 i++;
01377
01378
01379 i += 2;
01380
01381
01382 dataLength = message[i];
01383 i++;
01384 dataLength |= message[i] << 8;
01385 i++;
01386
01387
01388 msgLength = headerLength + dataLength + 4;
01389 if( msgLength > maxMessageLength )
01390 {
01391
01392
01393
01394 if( fseek( fid, fpos, SEEK_SET ) != 0 )
01395 {
01396
01397 GNSS_ERROR_MSG( "fseek failed." );
01398 return FALSE;
01399 }
01400 startSearch = TRUE;
01401 continue;
01402 }
01403
01404
01405
01406 i = headerLength;
01407 byteCount = (int)fread( &(message[i]), sizeof(unsigned char), dataLength, fid );
01408 if( byteCount != dataLength )
01409 {
01410
01411
01412
01413
01414 if( fseek( fid, fpos, SEEK_SET ) != 0 )
01415 {
01416
01417 GNSS_ERROR_MSG( "fseek failed." );
01418 return FALSE;
01419 }
01420 startSearch = TRUE;
01421 continue;
01422 }
01423 i += dataLength;
01424
01425
01426 byteCount = (int)fread( &(message[i]), sizeof(unsigned char), 4, fid );
01427 if( byteCount != 4 )
01428 {
01429 *wasEndOfFileReached = TRUE;
01430 return TRUE;
01431 }
01432 messageCRC = message[i];
01433 i++;
01434 messageCRC |= message[i] << 8;
01435 i++;
01436 messageCRC |= message[i] << 16;
01437 i++;
01438 messageCRC |= message[i] << 24;
01439 i++;
01440
01441
01442 if( !NOVATEL_CheckCRC32( message, msgLength, messageCRC, &isCRCValid ) )
01443 {
01444 GNSS_ERROR_MSG( "NOVATEL_CheckCRC32 returned FALSE." );
01445 return FALSE;
01446 }
01447 if( !isCRCValid )
01448 {
01449 *numberBadCRC += 1;
01450
01451
01452
01453 if( fseek( fid, fpos, SEEK_SET ) != 0 )
01454 {
01455
01456 GNSS_ERROR_MSG( "fseek failed." );
01457 return FALSE;
01458 }
01459 startSearch = TRUE;
01460 continue;
01461 }
01462
01463 *wasMessageFound = TRUE;
01464 *messageLength = msgLength;
01465 break;
01466 }
01467 else
01468 {
01469
01470 sync[0] = sync[1];
01471 sync[1] = sync[2];
01472 }
01473 }
01474 return TRUE;
01475 }
01476
01477
01478
01479 BOOL NOVATELOEM4_FindNextMessageInBuffer(
01480 unsigned char *buffer,
01481 const unsigned bufferLength,
01482 unsigned char *message,
01483 const unsigned maxMessageLength,
01484 BOOL *wasEndOfBufferReached,
01485 BOOL *wasMessageFound,
01486 unsigned *startPosition,
01487 unsigned short *messageLength,
01488 unsigned short *messageID,
01489 unsigned *numberBadCRC
01490 )
01491 {
01492 unsigned bi = 0;
01493 unsigned i = 0;
01494 unsigned char sync[3];
01495 unsigned dataLength = 0;
01496 unsigned msgLength = 0;
01497 int bpos = 0;
01498 unsigned messageCRC = 0;
01499 BOOL startSearch = TRUE;
01500 BOOL isCRCValid = FALSE;
01501 unsigned char headerLength = 0;
01502
01503
01504 *wasEndOfBufferReached = FALSE;
01505 *wasMessageFound = 0;
01506 *startPosition = 0;
01507 *messageLength = 0;
01508 *messageID = 0;
01509 *numberBadCRC = 0;
01510
01511
01512 if( buffer == NULL )
01513 {
01514 GNSS_ERROR_MSG( "if( fid == NULL )" );
01515 return FALSE;
01516 }
01517 if( message == NULL )
01518 {
01519 GNSS_ERROR_MSG( "if( message == NULL )" );
01520 return FALSE;
01521 }
01522
01523
01524 if( maxMessageLength < 32 )
01525 {
01526 GNSS_ERROR_MSG( "if( maxMessageLength < 32 )" );
01527 return FALSE;
01528 }
01529
01530 while( !(*wasEndOfBufferReached) && !(*wasMessageFound) )
01531 {
01532 if( startSearch )
01533 {
01534
01535 sync[0] = buffer[bi]; bi++;
01536 if( bi >= bufferLength )
01537 {
01538 *wasEndOfBufferReached = TRUE;
01539 return TRUE;
01540 }
01541
01542 sync[1] = buffer[bi]; bi++;
01543 if( bi >= bufferLength )
01544 {
01545 *wasEndOfBufferReached = TRUE;
01546 return TRUE;
01547 }
01548 startSearch = FALSE;
01549 }
01550
01551
01552 sync[2] = buffer[bi]; bi++;
01553 if( bi >= bufferLength )
01554 {
01555 *wasEndOfBufferReached = TRUE;
01556 return TRUE;
01557 }
01558
01559
01560 if( sync[0] == 0xAA && sync[1] == 0x44 && sync[2] == 0x12 )
01561 {
01562
01563 i = 0;
01564 message[i] = sync[0]; i++;
01565 message[i] = sync[1]; i++;
01566 message[i] = sync[2]; i++;
01567
01568
01569 bpos = bi;
01570 *startPosition = bi - 3;
01571
01572
01573
01574 headerLength = buffer[bi]; bi++;
01575 if( bi > bufferLength )
01576 {
01577 *wasEndOfBufferReached = TRUE;
01578 return TRUE;
01579 }
01580 message[i] = headerLength;
01581 i++;
01582
01583
01584 if( bi+headerLength-4 > bufferLength )
01585 {
01586 *wasEndOfBufferReached = TRUE;
01587 return TRUE;
01588 }
01589 memcpy( &(message[i]), (buffer+bi), (headerLength-4) );
01590 bi += headerLength-4;
01591
01592
01593 *messageID = message[i];
01594 i++;
01595 *messageID |= message[i] << 8;
01596 i++;
01597
01598
01599 i += 2;
01600
01601
01602 dataLength = message[i];
01603 i++;
01604 dataLength |= message[i] << 8;
01605 i++;
01606
01607
01608 msgLength = headerLength + dataLength + 4;
01609 if( msgLength > maxMessageLength )
01610 {
01611
01612
01613
01614 bi = bpos;
01615 startSearch = TRUE;
01616 continue;
01617 }
01618
01619
01620
01621 i = headerLength;
01622 if( bi+dataLength > bufferLength )
01623 {
01624
01625 *wasEndOfBufferReached = TRUE;
01626 return TRUE;
01627 }
01628 memcpy( &(message[i]), (buffer+bi), dataLength );
01629 bi += dataLength;
01630 i += dataLength;
01631
01632
01633 if( bi + 4 > bufferLength )
01634 {
01635
01636 *wasEndOfBufferReached = TRUE;
01637 return TRUE;
01638 }
01639 message[i] = buffer[bi]; i++; bi++;
01640 message[i] = buffer[bi]; i++; bi++;
01641 message[i] = buffer[bi]; i++; bi++;
01642 message[i] = buffer[bi]; i++; bi++;
01643
01644 i -= 4;
01645 messageCRC = message[i]; i++;
01646 messageCRC |= message[i] << 8; i++;
01647 messageCRC |= message[i] << 16; i++;
01648 messageCRC |= message[i] << 24; i++;
01649
01650
01651 if( !NOVATEL_CheckCRC32( message, msgLength, messageCRC, &isCRCValid ) )
01652 {
01653 GNSS_ERROR_MSG( "NOVATEL_CheckCRC32 returned FALSE." );
01654 return FALSE;
01655 }
01656 if( !isCRCValid )
01657 {
01658 *numberBadCRC += 1;
01659
01660
01661
01662 bi = bpos;
01663 startSearch = TRUE;
01664 continue;
01665 }
01666
01667 *wasMessageFound = TRUE;
01668 *messageLength = msgLength;
01669 break;
01670 }
01671 else
01672 {
01673
01674 sync[0] = sync[1];
01675 sync[1] = sync[2];
01676 }
01677 }
01678 return TRUE;
01679 }
01680
01681
01682
01683 BOOL NOVATELOEM4_DecodeBinaryMessageHeader(
01684 const unsigned char *message,
01685 const unsigned short messageLength,
01686 NOVATELOEM4_structBinaryHeader *header
01687 )
01688 {
01689 unsigned u32 = 0;
01690 NOVATELOEM4_structRxStatusBitField* ptrRxStatusBitField = NULL;
01691
01692
01693 if( message == NULL )
01694 {
01695 GNSS_ERROR_MSG( "if( message == NULL )" );
01696 return FALSE;
01697 }
01698 if( header == NULL )
01699 {
01700 GNSS_ERROR_MSG( "if( header == NULL )" );
01701 return FALSE;
01702 }
01703
01704 if( messageLength < 4 )
01705 {
01706 GNSS_ERROR_MSG( "if( messageLength < 4 )" );
01707 return FALSE;
01708 }
01709
01710
01711 header->headerLength = message[3];
01712 if( messageLength < header->headerLength )
01713 {
01714 GNSS_ERROR_MSG( "if( messageLength < header->headerLength )" );
01715 return FALSE;
01716 }
01717
01718 header->messageID = message[4];
01719 header->messageID |= message[5] << 8;
01720
01721 header->messageType = message[6];
01722
01723 header->portAddress = message[7];
01724
01725 header->dataLength = message[8];
01726 header->dataLength |= message[9] << 8;
01727
01728 header->sequenceNr = message[10];
01729 header->sequenceNr |= message[11] << 8;
01730
01731 header->idleTime = message[12];
01732
01733 header->eTimeStatus = (NOVATELOEM4_enumTimeStatus)message[13];
01734
01735 header->gpsWeek = message[14];
01736 header->gpsWeek |= message[15] << 8;
01737
01738 header->gpsMilliSeconds = message[16];
01739 header->gpsMilliSeconds |= message[17] << 8;
01740 header->gpsMilliSeconds |= message[18] << 16;
01741 header->gpsMilliSeconds |= message[19] << 24;
01742
01743 u32 = message[20];
01744 u32 |= message[21] << 8;
01745 u32 |= message[22] << 16;
01746 u32 |= message[23] << 24;
01747 ptrRxStatusBitField = (NOVATELOEM4_structRxStatusBitField *)&u32;
01748 header->receiverStatus = *ptrRxStatusBitField;
01749
01750 header->reserved = message[24];
01751 header->reserved |= message[25] << 8;
01752
01753 header->receiverVersion = message[26];
01754 header->receiverVersion |= message[27] << 8;
01755
01756 return TRUE;
01757 }
01758
01759
01760 BOOL NOVATELOEM4_DecodeRANGECMPB(
01761 const unsigned char *message,
01762 const unsigned short messageLength,
01763 NOVATELOEM4_structBinaryHeader* header,
01764 NOVATELOEM4_structObservation* obsArray,
01765 const unsigned char maxNrObs,
01766 unsigned *nrObs
01767 )
01768 {
01769 unsigned i = 0;
01770 unsigned index = 0;
01771 unsigned char headerLength = 0;
01772 unsigned short dataLength = 0;
01773 unsigned short msgLength = 0;
01774 unsigned short testLength = 0;
01775
01776
01777 if( message == NULL )
01778 {
01779 GNSS_ERROR_MSG( "if( message == NULL )" );
01780 return FALSE;
01781 }
01782 if( obsArray == NULL )
01783 {
01784 GNSS_ERROR_MSG( "if( obsArray == NULL )" );
01785 return FALSE;
01786 }
01787 if( message[0] != 0xAA || message[1] != 0x44 || message[2] != 0x12 )
01788 {
01789 GNSS_ERROR_MSG( "sync is not present" );
01790 return FALSE;
01791 }
01792
01793
01794 if( !NOVATELOEM4_DecodeBinaryMessageHeader( message, messageLength, header ) )
01795 {
01796 GNSS_ERROR_MSG( "NOVATELOEM4_DecodeBinaryMessageHeader returned FALSE." );
01797 return FALSE;
01798 }
01799
01800
01801 headerLength = message[3];
01802
01803
01804 dataLength = message[8];
01805 dataLength |= message[9] << 8;
01806
01807
01808 msgLength = dataLength + headerLength + 4;
01809 if( msgLength != messageLength )
01810 {
01811 GNSS_ERROR_MSG( "if( msgLength != messageLength )" );
01812 return FALSE;
01813 }
01814
01815
01816 index = headerLength;
01817 *nrObs = message[index];
01818 index++;
01819 *nrObs |= message[index] << 8;
01820 index++;
01821 *nrObs |= message[index] << 16;
01822 index++;
01823 *nrObs |= message[index] << 24;
01824
01825
01826 if( maxNrObs < *nrObs )
01827 {
01828 GNSS_ERROR_MSG( "if( maxNrObs < *nrObs )" );
01829 return FALSE;
01830 }
01831
01832
01833 testLength = (unsigned short)(*nrObs*24 + 4);
01834 if( testLength != dataLength )
01835 {
01836 GNSS_ERROR_MSG( "if( testLength != dataLength )" );
01837 return FALSE;
01838 }
01839
01840
01841 index = headerLength+4;
01842 for( i = 0; i < *nrObs; i++ )
01843 {
01844 long long int rangecmp_psr = 0;
01845 long rangecmp_adr = 0;
01846 double adr_rolls = 0;
01847 long rangecmp_doppler_freq = 0;
01848 unsigned char rangecmp_stdev_psr = 0;
01849 unsigned char rangecmp_stdev_adr = 0;
01850 unsigned long rangecmp_lock_time = 0;
01851 unsigned long rangecmp_cno = 0;
01852 double dtmp = 0;
01853
01854
01855 obsArray[i].rawTrackingStatus = message[index]; index++;
01856 obsArray[i].rawTrackingStatus |= message[index] << 8; index++;
01857 obsArray[i].rawTrackingStatus |= message[index] << 16; index++;
01858 obsArray[i].rawTrackingStatus |= message[index] << 24; index++;
01859
01860 if( !NOVATELOEM4_DecodeTrackingStatus( obsArray[i].rawTrackingStatus, &obsArray[i].trackingStatus ) )
01861 {
01862 GNSS_ERROR_MSG( "NOVATELOEM4_DecodeTrackingStatus returned FALSE." );
01863 return FALSE;
01864 }
01865
01866
01867 rangecmp_doppler_freq |= message[index]; index++;
01868 rangecmp_doppler_freq |= message[index] << 8; index++;
01869 rangecmp_doppler_freq |= message[index] << 16; index++;
01870 rangecmp_doppler_freq |= (message[index] & 0x0F) << 24;
01871
01872 if( (rangecmp_doppler_freq >> 27) > 0 )
01873 {
01874 rangecmp_doppler_freq |= 0xF0000000;
01875 }
01876 dtmp = (double)(rangecmp_doppler_freq);
01877 dtmp /= 256.0;
01878 obsArray[i].doppler = (float)dtmp;
01879
01880
01881 rangecmp_psr |= (message[index]&0xF0)>>4; index++;
01882 rangecmp_psr |= message[index]<<4; index++;
01883 rangecmp_psr |= message[index]<<12; index++;
01884 rangecmp_psr |= message[index]<<20; index++;
01885 rangecmp_psr |= (long long int)(message[index])<<28; index++;
01886
01887 if( ((long long int)(rangecmp_psr)>>35) > 0 )
01888 {
01889
01890 unsigned long int checkneg = 0xFFFFFFF0;
01891 checkneg *= (unsigned long int)(1<<31);
01892 checkneg *= 2;
01893 rangecmp_psr |= checkneg;
01894 }
01895 obsArray[i].psr = (double)rangecmp_psr;
01896 obsArray[i].psr /= 128.0;
01897
01898
01899 rangecmp_adr = message[index]; index++;
01900 rangecmp_adr |= message[index] << 8; index++;
01901 rangecmp_adr |= message[index] << 16; index++;
01902 rangecmp_adr |= message[index] << 24; index++;
01903 obsArray[i].adr = (double) rangecmp_adr;
01904 obsArray[i].adr /= 256.0;
01905
01906
01907 if (obsArray[i].trackingStatus.eFrequency == NOVATELOEM4_L1)
01908 adr_rolls =(obsArray[i].psr / GPS_WAVELENGTHL1 + obsArray[i].adr) / 8388608.0;
01909 else
01910 adr_rolls =(obsArray[i].psr / GPS_WAVELENGTHL2 + obsArray[i].adr) / 8388608.0;
01911
01912 if ( adr_rolls <= 0)
01913 adr_rolls = adr_rolls - 0.5;
01914 else
01915 adr_rolls = adr_rolls + 0.5;
01916
01917 obsArray[i].adr = obsArray[i].adr - (8388608.0 * (int)adr_rolls);
01918
01919
01920 rangecmp_stdev_psr = ((message[index] & 0x0F));
01921
01922
01923
01924 switch(rangecmp_stdev_psr)
01925 {
01926 case 0 : obsArray[i].psrstd = 0.050f; break;
01927 case 1 : obsArray[i].psrstd = 0.075f; break;
01928 case 2 : obsArray[i].psrstd = 0.113f; break;
01929 case 3 : obsArray[i].psrstd = 0.169f; break;
01930 case 4 : obsArray[i].psrstd = 0.253f; break;
01931 case 5 : obsArray[i].psrstd = 0.380f; break;
01932 case 6 : obsArray[i].psrstd = 0.570f; break;
01933 case 7 : obsArray[i].psrstd = 0.854f; break;
01934 case 8 : obsArray[i].psrstd = 1.281f; break;
01935 case 9 : obsArray[i].psrstd = 2.375f; break;
01936 case 10 : obsArray[i].psrstd = 4.750f; break;
01937 case 11 : obsArray[i].psrstd = 9.500f; break;
01938 case 12 : obsArray[i].psrstd = 19.000f; break;
01939 case 13 : obsArray[i].psrstd = 38.000f; break;
01940 case 14 : obsArray[i].psrstd = 76.000f; break;
01941 case 15 : obsArray[i].psrstd = 152.000f; break;
01942 };
01943
01944
01945 rangecmp_stdev_adr = message[index] >> 4 ;
01946 index++;
01947 obsArray[i].adrstd = (float)(rangecmp_stdev_adr+1)/512;
01948
01949
01950 obsArray[i].prn = (unsigned short)message[index];
01951 index++;
01952
01953
01954 rangecmp_lock_time |= message[index]; index++;
01955 rangecmp_lock_time |= message[index] << 8; index++;
01956 rangecmp_lock_time |= ((message[index] & 0x1F)) << 16;
01957
01958 obsArray[i].locktime = (float)(rangecmp_lock_time);
01959 obsArray[i].locktime /= 32.0;
01960
01961
01962 rangecmp_cno = (message[index] & 0xE0 ) >> 5; index++;
01963 rangecmp_cno |= (message[index] & 0x03 ) << 3;
01964
01965 obsArray[i].cno = (float)rangecmp_cno + 20;
01966
01967
01968 obsArray[i].reserved = (message[index] & 0xFC )>> 5; index ++ ;
01969 obsArray[i].reserved |= message[index] << 8; index ++ ;
01970 obsArray[i].reserved |= message[index] << 16; index ++ ;
01971 }
01972
01973 return TRUE;
01974 }
01975
01976 BOOL NOVATELOEM4_DecodeRANGEB(
01977 const unsigned char *message,
01978 const unsigned short messageLength,
01979 NOVATELOEM4_structBinaryHeader* header,
01980 NOVATELOEM4_structObservation* obsArray,
01981 const unsigned char maxNrObs,
01982 unsigned *nrObs
01983 )
01984 {
01985 unsigned i = 0;
01986 unsigned j = 0;
01987 unsigned index = 0;
01988 unsigned char headerLength = 0;
01989 unsigned short dataLength = 0;
01990 unsigned short msgLength = 0;
01991 unsigned short testLength = 0;
01992 unsigned char dbytes[8];
01993 unsigned char fbytes[4];
01994 double *dptr;
01995 float *fptr;
01996
01997
01998 if( message == NULL )
01999 {
02000 GNSS_ERROR_MSG( "if( message == NULL )" );
02001 return FALSE;
02002 }
02003 if( obsArray == NULL )
02004 {
02005 GNSS_ERROR_MSG( "if( obsArray == NULL )" );
02006 return FALSE;
02007 }
02008 if( message[0] != 0xAA || message[1] != 0x44 || message[2] != 0x12 )
02009 {
02010 GNSS_ERROR_MSG( "sync not present" );
02011 return FALSE;
02012 }
02013
02014
02015 if( !NOVATELOEM4_DecodeBinaryMessageHeader( message, messageLength, header ) )
02016 {
02017 GNSS_ERROR_MSG( "NOVATELOEM4_DecodeBinaryMessageHeader returned FALSE." );
02018 return FALSE;
02019 }
02020
02021
02022 headerLength = message[3];
02023
02024
02025 dataLength = message[8];
02026 dataLength |= message[9] << 8;
02027
02028
02029 msgLength = dataLength + headerLength + 4;
02030 if( msgLength != messageLength )
02031 {
02032 GNSS_ERROR_MSG( "if( msgLength != messageLength )" );
02033 return FALSE;
02034 }
02035
02036
02037 index = headerLength;
02038 *nrObs = message[index];
02039 index++;
02040 *nrObs |= message[index] << 8;
02041 index++;
02042 *nrObs |= message[index] << 16;
02043 index++;
02044 *nrObs |= message[index] << 24;
02045
02046
02047 if( maxNrObs < *nrObs )
02048 {
02049 GNSS_ERROR_MSG( "if( maxNrObs < *nrObs )" );
02050 return FALSE;
02051 }
02052
02053
02054 testLength = (unsigned short)(*nrObs*44 + 4);
02055 if( testLength != dataLength )
02056 {
02057 GNSS_ERROR_MSG( "if( testLength != dataLength )" );
02058 return FALSE;
02059 }
02060
02061
02062 index = headerLength+4;
02063 for( i = 0; i < *nrObs; i++ )
02064 {
02065 obsArray[i].prn = message[index]; index++;
02066 obsArray[i].prn |= message[index] << 8; index++;
02067 obsArray[i].reserved = message[index]; index++;
02068 obsArray[i].reserved |= message[index] << 8; index++;
02069
02070 for( j=0; j<8; j++ ){ dbytes[j] = message[index]; index++; }
02071 dptr = (double*)&dbytes;
02072 obsArray[i].psr = *dptr;
02073
02074 for( j=0; j<4; j++ ){ fbytes[j] = message[index]; index++; }
02075 fptr = (float*)&fbytes;
02076 obsArray[i].psrstd = *fptr;
02077
02078 for( j=0; j<8; j++ ){ dbytes[j] = message[index]; index++; }
02079 dptr = (double*)&dbytes;
02080 obsArray[i].adr = *dptr;
02081
02082 for( j=0; j<4; j++ ){ fbytes[j] = message[index]; index++; }
02083 fptr = (float*)&fbytes;
02084 obsArray[i].adrstd = *fptr;
02085
02086 for( j=0; j<4; j++ ){ fbytes[j] = message[index]; index++; }
02087 fptr = (float*)&fbytes;
02088 obsArray[i].doppler = *fptr;
02089
02090 for( j=0; j<4; j++ ){ fbytes[j] = message[index]; index++; }
02091 fptr = (float*)&fbytes;
02092 obsArray[i].cno = *fptr;
02093
02094 for( j=0; j<4; j++ ){ fbytes[j] = message[index]; index++; }
02095 fptr = (float*)&fbytes;
02096 obsArray[i].locktime = *fptr;
02097
02098 obsArray[i].rawTrackingStatus = message[index]; index++;
02099 obsArray[i].rawTrackingStatus |= message[index] << 8; index++;
02100 obsArray[i].rawTrackingStatus |= message[index] << 16; index++;
02101 obsArray[i].rawTrackingStatus |= message[index] << 24; index++;
02102
02103 if( !NOVATELOEM4_DecodeTrackingStatus( obsArray[i].rawTrackingStatus, &obsArray[i].trackingStatus ) )
02104 {
02105 GNSS_ERROR_MSG( "NOVATELOEM4_DecodeTrackingStatus returned FALSE." );
02106 return FALSE;
02107 }
02108 }
02109
02110 return TRUE;
02111 }
02112
02113
02114 BOOL NOVATELOEM4_DecodeBESTPOSB(
02115 const unsigned char *message,
02116 const unsigned short messageLength,
02117 NOVATELOEM4_structBinaryHeader* header,
02118 NOVATELOEM4_structBestPosition* bestpos
02119 )
02120 {
02121 unsigned i = 0;
02122 unsigned j = 0;
02123 unsigned index = 0;
02124 unsigned char headerLength = 0;
02125 unsigned short dataLength = 0;
02126 unsigned short msgLength = 0;
02127 unsigned char dbytes[8];
02128 unsigned char fbytes[4];
02129 double *dptr;
02130 float *fptr;
02131 unsigned utmp = 0;
02132
02133
02134 if( message == NULL )
02135 {
02136 GNSS_ERROR_MSG( "if( message == NULL )" );
02137 return FALSE;
02138 }
02139 if( header == NULL || bestpos == NULL )
02140 {
02141 GNSS_ERROR_MSG( "if( header == NULL || bestpos == NULL )" );
02142 return FALSE;
02143 }
02144 if( message[0] != 0xAA || message[1] != 0x44 || message[2] != 0x12 )
02145 {
02146 GNSS_ERROR_MSG( "sync not present" );
02147 return FALSE;
02148 }
02149
02150
02151 if( !NOVATELOEM4_DecodeBinaryMessageHeader( message, messageLength, header ) )
02152 {
02153 GNSS_ERROR_MSG( "NOVATELOEM4_DecodeBinaryMessageHeader returned FALSE." );
02154 return FALSE;
02155 }
02156
02157
02158 headerLength = message[3];
02159
02160
02161 dataLength = message[8];
02162 dataLength |= message[9] << 8;
02163
02164
02165 msgLength = dataLength + headerLength + 4;
02166 if( msgLength != messageLength )
02167 {
02168 GNSS_ERROR_MSG( "if( msgLength != messageLength )" );
02169 return FALSE;
02170 }
02171
02172
02173 index = headerLength;
02174 utmp = message[index]; index++;
02175 utmp |= message[index] << 8; index++;
02176 utmp |= message[index] << 16; index++;
02177 utmp |= message[index] << 24; index++;
02178 bestpos->solution_status = (NOVATELOEM4_enumSolutionStatus)(utmp);
02179
02180
02181 utmp = message[index]; index++;
02182 utmp |= message[index] << 8; index++;
02183 utmp |= message[index] << 16; index++;
02184 utmp |= message[index] << 24; index++;
02185 bestpos->solution_type = (NOVATELOEM4_enumSolutionType)(utmp);
02186
02187
02188 for( j=0; j<8; j++ ){ dbytes[j] = message[index]; index++; }
02189 dptr = (double*)&dbytes;
02190 bestpos->latitude_in_deg = *dptr;
02191
02192
02193 for( j=0; j<8; j++ ){ dbytes[j] = message[index]; index++; }
02194 dptr = (double*)&dbytes;
02195 bestpos->longitude_in_deg = *dptr;
02196
02197
02198 for( j=0; j<8; j++ ){ dbytes[j] = message[index]; index++; }
02199 dptr = (double*)&dbytes;
02200 bestpos->height_msl = *dptr;
02201
02202
02203 for( j=0; j<4; j++ ){ fbytes[j] = message[index]; index++; }
02204 fptr = (float*)&fbytes;
02205 bestpos->undulation = *fptr;
02206
02207
02208 utmp = message[index]; index++;
02209 utmp |= message[index] << 8; index++;
02210 utmp |= message[index] << 16; index++;
02211 utmp |= message[index] << 24; index++;
02212 bestpos->datum_id = utmp;
02213
02214
02215 for( j=0; j<4; j++ ){ fbytes[j] = message[index]; index++; }
02216 fptr = (float*)&fbytes;
02217 bestpos->lat_std = *fptr;
02218
02219
02220 for( j=0; j<4; j++ ){ fbytes[j] = message[index]; index++; }
02221 fptr = (float*)&fbytes;
02222 bestpos->lon_std = *fptr;
02223
02224
02225 for( j=0; j<4; j++ ){ fbytes[j] = message[index]; index++; }
02226 fptr = (float*)&fbytes;
02227 bestpos->hgt_std = *fptr;
02228
02229
02230 bestpos->station_id[0] = message[index]; index++;
02231 bestpos->station_id[1] = message[index]; index++;
02232 bestpos->station_id[2] = message[index]; index++;
02233 bestpos->station_id[3] = message[index]; index++;
02234
02235
02236 for( j=0; j<4; j++ ){ fbytes[j] = message[index]; index++; }
02237 fptr = (float*)&fbytes;
02238 bestpos->diff_age = *fptr;
02239
02240
02241 for( j=0; j<4; j++ ){ fbytes[j] = message[index]; index++; }
02242 fptr = (float*)&fbytes;
02243 bestpos->sol_age = *fptr;
02244
02245 bestpos->nr_obs_tracked = message[index]; index++;
02246 bestpos->nr_GPS_L1_ranges = message[index]; index++;
02247 bestpos->nr_GPS_L1_ranges_above_RTK_mask_angle = message[index]; index++;
02248 bestpos->nr_GPS_L2_ranges_above_RTK_mask_angle = message[index]; index++;
02249
02250 bestpos->reserved[0] = message[index]; index++;
02251 bestpos->reserved[1] = message[index]; index++;
02252 bestpos->reserved[2] = message[index]; index++;
02253 bestpos->reserved[3] = message[index]; index++;
02254
02255 return TRUE;
02256 }
02257
02258
02259 BOOL NOVATELOEM4_DecodeTIMEB(
02260 const unsigned char *message,
02261 const unsigned short messageLength,
02262 NOVATELOEM4_structBinaryHeader* header,
02263 NOVATELOEM4_structTime* time_data
02264 )
02265 {
02266 unsigned i = 0;
02267 unsigned j = 0;
02268 unsigned index = 0;
02269 unsigned char headerLength = 0;
02270 unsigned short dataLength = 0;
02271 unsigned short msgLength = 0;
02272 unsigned char dbytes[8];
02273 double *dptr;
02274 unsigned utmp = 0;
02275
02276
02277 if( message == NULL )
02278 {
02279 GNSS_ERROR_MSG( "if( message == NULL )" );
02280 return FALSE;
02281 }
02282 if( header == NULL || time_data == NULL )
02283 {
02284 GNSS_ERROR_MSG( "if( header == NULL || time_data == NULL )" );
02285 return FALSE;
02286 }
02287 if( message[0] != 0xAA || message[1] != 0x44 || message[2] != 0x12 )
02288 {
02289 GNSS_ERROR_MSG( "sync not present" );
02290 return FALSE;
02291 }
02292
02293
02294 if( !NOVATELOEM4_DecodeBinaryMessageHeader( message, messageLength, header ) )
02295 {
02296 GNSS_ERROR_MSG( "NOVATELOEM4_DecodeBinaryMessageHeader returned FALSE." );
02297 return FALSE;
02298 }
02299
02300
02301 headerLength = message[3];
02302
02303
02304 dataLength = message[8];
02305 dataLength |= message[9] << 8;
02306
02307
02308 msgLength = dataLength + headerLength + 4;
02309 if( msgLength != messageLength )
02310 {
02311 GNSS_ERROR_MSG( "if( msgLength != messageLength )" );
02312 return FALSE;
02313 }
02314
02315
02316 index = headerLength;
02317 utmp = message[index]; index++;
02318 utmp |= message[index] << 8; index++;
02319 utmp |= message[index] << 16; index++;
02320 utmp |= message[index] << 24; index++;
02321 time_data->clock_status = (NOVATELOEM4_enumClockStatus)(utmp);
02322
02323
02324 for( j=0; j<8; j++ ){ dbytes[j] = message[index]; index++; }
02325 dptr = (double*)&dbytes;
02326 time_data->receiver_clock_offset = *dptr;
02327
02328
02329 for( j=0; j<8; j++ ){ dbytes[j] = message[index]; index++; }
02330 dptr = (double*)&dbytes;
02331 time_data->receiver_clock_offset_std = *dptr;
02332
02333
02334 for( j=0; j<8; j++ ){ dbytes[j] = message[index]; index++; }
02335 dptr = (double*)&dbytes;
02336 time_data->utc_offset = *dptr;
02337
02338
02339 utmp = message[index]; index++;
02340 utmp |= message[index] << 8; index++;
02341 utmp |= message[index] << 16; index++;
02342 utmp |= message[index] << 24; index++;
02343 time_data->utc_year = utmp;
02344
02345 time_data->utc_month = message[index]; index++;
02346 time_data->utc_day = message[index]; index++;
02347 time_data->utc_hour = message[index]; index++;
02348 time_data->utc_minute = message[index]; index++;
02349
02350 utmp = message[index]; index++;
02351 utmp |= message[index] << 8; index++;
02352 utmp |= message[index] << 16; index++;
02353 utmp |= message[index] << 24; index++;
02354 time_data->utc_milliseconds = utmp;
02355
02356 utmp = message[index]; index++;
02357 utmp |= message[index] << 8; index++;
02358 utmp |= message[index] << 16; index++;
02359 utmp |= message[index] << 24; index++;
02360 if( utmp == 0 )
02361 time_data->isUTCValid = FALSE;
02362 else
02363 time_data->isUTCValid = TRUE;
02364
02365 return TRUE;
02366 }
02367
02368
02369
02370
02371 BOOL NOVATELOEM4_DecodeTrackingStatus(
02372 const unsigned rawTrackingStatus,
02373 NOVATELOEM4_structTrackingStatus *trackingStatus
02374 )
02375 {
02376
02377 typedef struct
02378 {
02379 unsigned trackingState :5;
02380 unsigned channelNumber :5;
02381 unsigned phaseLockFlag :1;
02382 unsigned parityKnownFlag :1;
02383 unsigned codeLockedFlag :1;
02384 unsigned correlatorSpacing :3;
02385 unsigned satelliteSystem :3;
02386 unsigned reserved1 :1;
02387 unsigned grouping :1;
02388 unsigned frequency :2;
02389 unsigned codeType :3;
02390 unsigned forwardErrorCorrection :1;
02391 unsigned primaryL1Channel :1;
02392 unsigned halfCycleFlag :1;
02393 unsigned reserved3 :1;
02394 unsigned prnLockFlag :1;
02395 unsigned channelAssignment :1;
02396 } NOVATELOEM4_channelStatusBitField;
02397
02398 NOVATELOEM4_channelStatusBitField bitField;
02399 NOVATELOEM4_channelStatusBitField *ptrBitField;
02400
02401 if( trackingStatus == NULL )
02402 {
02403 GNSS_ERROR_MSG( "if( trackingStatus == NULL )" );
02404 return FALSE;
02405 }
02406
02407 ptrBitField = (NOVATELOEM4_channelStatusBitField *)&rawTrackingStatus;
02408 bitField = *ptrBitField;
02409
02410 trackingStatus->eTrackingState = (NOVATELOEM4_enumTrackingState)bitField.trackingState;
02411 trackingStatus->channelNumber = bitField.channelNumber;
02412 trackingStatus->isPhaseLocked = bitField.phaseLockFlag;
02413 trackingStatus->isParityKnown = bitField.parityKnownFlag;
02414 trackingStatus->isCodeLocked = bitField.codeLockedFlag;
02415 trackingStatus->eCorrelatorSpacing = (NOVATELOEM4_enumCorrelatorSpacing)bitField.correlatorSpacing;
02416 trackingStatus->eSatelliteSystem = (NOVATELOEM4_enumSatelliteSystem)bitField.satelliteSystem;
02417 trackingStatus->isGrouped = bitField.grouping;
02418 trackingStatus->eFrequency = (NOVATELOEM4_enumFrequency)bitField.frequency;
02419 trackingStatus->eCodeType = (NOVATELOEM4_enumCodeType)bitField.codeType;
02420 trackingStatus->isFECEnabled = bitField.forwardErrorCorrection;
02421 trackingStatus->isPrimaryL1Channel = bitField.primaryL1Channel;
02422 trackingStatus->isHalfCycleAdded = bitField.halfCycleFlag;
02423 trackingStatus->isForcedAssignment = bitField.channelAssignment;
02424
02425 return TRUE;
02426 }
02427
02428
02429 BOOL NOVATELOEM4_DecodeRAWEPHEMB(
02430 const unsigned char *message,
02431 const unsigned short messageLength,
02432 NOVATELOEM4_structBinaryHeader* header,
02433 unsigned *prn,
02434 unsigned *reference_week,
02435 unsigned *reference_time,
02436 unsigned *tow,
02437 unsigned short *iodc,
02438 unsigned char *iode,
02439 unsigned *toe,
02440 unsigned *toc,
02441 unsigned short *week,
02442 unsigned char *health,
02443 unsigned char *alert_flag,
02444 unsigned char *anti_spoof,
02445 unsigned char *code_on_L2,
02446 unsigned char *ura,
02447 unsigned char *L2_P_data_flag,
02448 unsigned char *fit_interval_flag,
02449 unsigned short *age_of_data_offset,
02450 double *tgd,
02451 double *af2,
02452 double *af1,
02453 double *af0,
02454 double *m0,
02455 double *delta_n,
02456 double *ecc,
02457 double *sqrta,
02458 double *omega0,
02459 double *i0,
02460 double *w,
02461 double *omegadot,
02462 double *idot,
02463 double *cuc,
02464 double *cus,
02465 double *crc,
02466 double *crs,
02467 double *cic,
02468 double *cis
02469 )
02470 {
02471 unsigned short msgLength;
02472 unsigned index = 0;
02473 BOOL result = FALSE;
02474
02475
02476 if( message == NULL )
02477 {
02478 GNSS_ERROR_MSG( "if( message == NULL )" );
02479 return FALSE;
02480 }
02481 if( message[0] != 0xAA || message[1] != 0x44 || message[2] != 0x12 )
02482 {
02483 GNSS_ERROR_MSG( "sync not present" );
02484 return FALSE;
02485 }
02486
02487
02488 if( !NOVATELOEM4_DecodeBinaryMessageHeader( message, messageLength, header ) )
02489 {
02490 GNSS_ERROR_MSG( "NOVATELOEM4_DecodeBinaryMessageHeader returned FALSE." );
02491 return FALSE;
02492 }
02493
02494
02495 msgLength = header->headerLength + header->dataLength + 4;
02496 if( msgLength != messageLength )
02497 {
02498 GNSS_ERROR_MSG( "if( msgLength != messageLength )" );
02499 return FALSE;
02500 }
02501
02502 index = header->headerLength;
02503 *prn = message[index]; index++;
02504 *prn |= message[index] << 8; index++;
02505 *prn |= message[index] << 16; index++;
02506 *prn |= message[index] << 24; index++;
02507
02508 *reference_week = message[index]; index++;
02509 *reference_week |= message[index] << 8; index++;
02510 *reference_week |= message[index] << 16; index++;
02511 *reference_week |= message[index] << 24; index++;
02512
02513 *reference_time = message[index]; index++;
02514 *reference_time |= message[index] << 8; index++;
02515 *reference_time |= message[index] << 16; index++;
02516 *reference_time |= message[index] << 24; index++;
02517
02518 result = GPS_DecodeRawGPSEphemeris(
02519 &message[index],
02520 &message[index+30],
02521 &message[index+60],
02522 (unsigned short)(*prn),
02523 tow,
02524 iodc,
02525 iode,
02526 toe,
02527 toc,
02528 week,
02529 health,
02530 alert_flag,
02531 anti_spoof,
02532 code_on_L2,
02533 ura,
02534 L2_P_data_flag,
02535 fit_interval_flag,
02536 age_of_data_offset,
02537 tgd,
02538 af2,
02539 af1,
02540 af0,
02541 m0,
02542 delta_n,
02543 ecc,
02544 sqrta,
02545 omega0,
02546 i0,
02547 w,
02548 omegadot,
02549 idot,
02550 cuc,
02551 cus,
02552 crc,
02553 crs,
02554 cic,
02555 cis
02556 );
02557 if( !result )
02558 {
02559 GNSS_ERROR_MSG( "GPS_DecodeRawGPSEphemeris returned FALSE." );
02560 return FALSE;
02561 }
02562
02563 return TRUE;
02564 }