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 "novatel.h"
00042 #include "gps.h"
00043 #include "constants.h"
00044
00045
00046
00047 static unsigned NOVATEL_CalculateCRC32(
00048 unsigned char *crcData,
00049 const unsigned short dataLength
00050 );
00051
00052
00053
00054
00055 static BOOL NOVATEL_CheckCRC32(
00056 unsigned char *message,
00057 const unsigned short messageLength,
00058 const unsigned messageCRC,
00059 BOOL *isCRCValid
00060 );
00061
00062
00063 static const unsigned NOVATEL_CRC32_Table[256] =
00064 {
00065 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL,
00066 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L,
00067 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L,
00068 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
00069 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
00070 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L,
00071 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 0x35b5a8faL, 0x42b2986cL,
00072 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
00073 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L,
00074 0xcfba9599L, 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
00075 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, 0x01db7106L,
00076 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
00077 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL,
00078 0x91646c97L, 0xe6635c01L, 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL,
00079 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
00080 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
00081 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L,
00082 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L,
00083 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL,
00084 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
00085 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L,
00086 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL,
00087 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, 0xe3630b12L, 0x94643b84L,
00088 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
00089 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
00090 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL,
00091 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 0xd6d6a3e8L, 0xa1d1937eL,
00092 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
00093 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L,
00094 0x316e8eefL, 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
00095 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, 0xb2bd0b28L,
00096 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
00097 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL,
00098 0x72076785L, 0x05005713L, 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L,
00099 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
00100 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
00101 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L,
00102 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L,
00103 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL,
00104 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
00105 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L,
00106 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L,
00107 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL
00108 };
00109
00110
00111
00112 unsigned NOVATEL_CalculateCRC32(
00113 unsigned char *crcData,
00114 const unsigned short dataLength
00115 )
00116 {
00117 unsigned i;
00118 unsigned crc = 0;
00119 for( i = 0; i < dataLength; i++ )
00120 crc = NOVATEL_CRC32_Table[(crc ^ crcData[i]) & 0xFF] ^ (crc >> 8);
00121 return crc;
00122 }
00123
00124
00125
00126 BOOL NOVATEL_CheckCRC32(
00127 unsigned char *message,
00128 const unsigned short messageLength,
00129 const unsigned messageCRC,
00130 BOOL *isCRCValid
00131 )
00132 {
00133 unsigned crc = 0;
00134
00135 if( message == NULL )
00136 return FALSE;
00137
00138
00139 crc = NOVATEL_CalculateCRC32( message, messageLength-4 );
00140
00141 *isCRCValid = FALSE;
00142
00143 if( messageCRC != crc )
00144 *isCRCValid = FALSE;
00145 else
00146 *isCRCValid = TRUE;
00147
00148 return TRUE;
00149 }
00150
00151
00152 BOOL NOVATELOEM4_FindNextMessageInFile(
00153 FILE *fid,
00154 unsigned char *message,
00155 const unsigned maxMessageLength,
00156 BOOL *wasEndOfFileReached,
00157 BOOL *wasMessageFound,
00158 unsigned *filePosition,
00159 unsigned short *messageLength,
00160 unsigned short *messageID,
00161 unsigned *numberBadCRC
00162 )
00163 {
00164 unsigned i = 0;
00165 unsigned char sync[3];
00166 unsigned char headerLength = 0;
00167 unsigned byteCount = 0;
00168 unsigned short dataLength = 0;
00169 unsigned short msgLength = 0;
00170 int fpos = 0;
00171 unsigned messageCRC = 0;
00172 BOOL startSearch = TRUE;
00173 BOOL isCRCValid = FALSE;
00174
00175
00176
00177 *wasEndOfFileReached = FALSE;
00178 *wasMessageFound = 0;
00179 *filePosition = 0;
00180 *messageLength = 0;
00181 *messageID = 0;
00182 *numberBadCRC = 0;
00183
00184
00185 if( fid == NULL )
00186 return FALSE;
00187
00188
00189 if( maxMessageLength < 32 )
00190 {
00191 return FALSE;
00192 }
00193
00194
00195 if( feof(fid) )
00196 {
00197 *wasEndOfFileReached = TRUE;
00198 return TRUE;
00199 }
00200
00201 while( !(*wasEndOfFileReached) && !(*wasMessageFound) )
00202 {
00203 if( startSearch )
00204 {
00205
00206 sync[0] = (unsigned char)fgetc( fid );
00207 if( feof( fid ) )
00208 {
00209 *wasEndOfFileReached = TRUE;
00210 return TRUE;
00211 }
00212
00213 sync[1] = (unsigned char)fgetc( fid );
00214 if( feof( fid ) )
00215 {
00216 *wasEndOfFileReached = TRUE;
00217 return TRUE;
00218 }
00219
00220 startSearch = FALSE;
00221 }
00222
00223
00224 sync[2] = (unsigned char)fgetc( fid );
00225 if( feof( fid ) )
00226 {
00227 *wasEndOfFileReached = TRUE;
00228 return TRUE;
00229 }
00230
00231
00232 if( sync[0] == 0xAA && sync[1] == 0x44 && sync[2] == 0x12 )
00233 {
00234
00235 i = 0;
00236 message[i] = sync[0]; i++;
00237 message[i] = sync[1]; i++;
00238 message[i] = sync[2]; i++;
00239
00240
00241 fpos = ftell(fid);
00242 if( fpos < 2 )
00243 {
00244 return FALSE;
00245 }
00246 *filePosition = fpos - 3;
00247
00248
00249 headerLength = (unsigned char)fgetc( fid );
00250 if( feof( fid ) )
00251 {
00252 *wasEndOfFileReached = TRUE;
00253 return TRUE;
00254 }
00255 message[i] = headerLength;
00256 i++;
00257
00258
00259 byteCount = (int)fread( &(message[i]), sizeof(unsigned char), headerLength-4, fid );
00260 if( byteCount+4 != headerLength )
00261 {
00262 *wasEndOfFileReached = TRUE;
00263 return TRUE;
00264 }
00265
00266
00267 *messageID = message[i];
00268 i++;
00269 *messageID |= message[i] << 8;
00270 i++;
00271
00272
00273 i += 2;
00274
00275
00276 dataLength = message[i];
00277 i++;
00278 dataLength |= message[i] << 8;
00279 i++;
00280
00281
00282 msgLength = headerLength + dataLength + 4;
00283 if( msgLength > maxMessageLength )
00284 {
00285
00286
00287
00288 if( fseek( fid, fpos, SEEK_SET ) != 0 )
00289 {
00290
00291 return FALSE;
00292 }
00293 startSearch = TRUE;
00294 continue;
00295 }
00296
00297
00298
00299 i = headerLength;
00300 byteCount = (int)fread( &(message[i]), sizeof(unsigned char), dataLength, fid );
00301 if( byteCount != dataLength )
00302 {
00303
00304
00305
00306
00307 if( fseek( fid, fpos, SEEK_SET ) != 0 )
00308 {
00309
00310 return FALSE;
00311 }
00312 startSearch = TRUE;
00313 continue;
00314 }
00315 i += dataLength;
00316
00317
00318 byteCount = (int)fread( &(message[i]), sizeof(unsigned char), 4, fid );
00319 if( byteCount != 4 )
00320 {
00321 *wasEndOfFileReached = TRUE;
00322 return TRUE;
00323 }
00324 messageCRC = message[i];
00325 i++;
00326 messageCRC |= message[i] << 8;
00327 i++;
00328 messageCRC |= message[i] << 16;
00329 i++;
00330 messageCRC |= message[i] << 24;
00331 i++;
00332
00333
00334 if( !NOVATEL_CheckCRC32( message, msgLength, messageCRC, &isCRCValid ) )
00335 {
00336 return FALSE;
00337 }
00338 if( !isCRCValid )
00339 {
00340 *numberBadCRC += 1;
00341
00342
00343
00344 if( fseek( fid, fpos, SEEK_SET ) != 0 )
00345 {
00346
00347 return FALSE;
00348 }
00349 startSearch = TRUE;
00350 continue;
00351 }
00352
00353 *wasMessageFound = TRUE;
00354 *messageLength = msgLength;
00355 break;
00356 }
00357 else
00358 {
00359
00360 sync[0] = sync[1];
00361 sync[1] = sync[2];
00362 }
00363 }
00364 return TRUE;
00365 }
00366
00367
00368 BOOL NOVATELOEM4_DecodeBinaryMessageHeader(
00369 const unsigned char *message,
00370 const unsigned short messageLength,
00371 NOVATELOEM4_structBinaryHeader *header
00372 )
00373 {
00374 unsigned u32 = 0;
00375 NOVATELOEM4_structRxStatusBitField* ptrRxStatusBitField = NULL;
00376
00377
00378 if( message == NULL )
00379 return FALSE;
00380 if( header == NULL )
00381 return FALSE;
00382
00383 if( messageLength < 4 )
00384 return FALSE;
00385
00386
00387
00388 header->headerLength = message[3];
00389 if( messageLength < header->headerLength )
00390 return FALSE;
00391
00392 header->messageID = message[4];
00393 header->messageID |= message[5] << 8;
00394
00395 header->messageType = message[6];
00396
00397 header->portAddress = message[7];
00398
00399 header->dataLength = message[8];
00400 header->dataLength |= message[9] << 8;
00401
00402 header->sequenceNr = message[10];
00403 header->sequenceNr |= message[11] << 8;
00404
00405 header->idleTime = message[12];
00406
00407 header->eTimeStatus = (NOVATELOEM4_enumTimeStatus)message[13];
00408
00409 header->gpsWeek = message[14];
00410 header->gpsWeek |= message[15] << 8;
00411
00412 header->gpsMilliSeconds = message[16];
00413 header->gpsMilliSeconds |= message[17] << 8;
00414 header->gpsMilliSeconds |= message[18] << 16;
00415 header->gpsMilliSeconds |= message[19] << 24;
00416
00417 u32 = message[20];
00418 u32 |= message[21] << 8;
00419 u32 |= message[22] << 16;
00420 u32 |= message[23] << 24;
00421 ptrRxStatusBitField = (NOVATELOEM4_structRxStatusBitField *)&u32;
00422 header->receiverStatus = *ptrRxStatusBitField;
00423
00424 header->reserved = message[24];
00425 header->reserved |= message[25] << 8;
00426
00427 header->receiverVersion = message[26];
00428 header->receiverVersion |= message[27] << 8;
00429
00430 return TRUE;
00431 }
00432
00433
00434 BOOL NOVATELOEM4_DecodeRANGECMPB(
00435 const unsigned char *message,
00436 const unsigned short messageLength,
00437 NOVATELOEM4_structBinaryHeader* header,
00438 NOVATELOEM4_structObservation* obsArray,
00439 const unsigned char maxNrObs,
00440 unsigned *nrObs
00441 )
00442 {
00443 unsigned i = 0;
00444 unsigned index = 0;
00445 unsigned char headerLength = 0;
00446 unsigned short dataLength = 0;
00447 unsigned short msgLength = 0;
00448 unsigned short testLength = 0;
00449
00450
00451 if( message == NULL )
00452 return FALSE;
00453 if( obsArray == NULL )
00454 return FALSE;
00455 if( message[0] != 0xAA || message[1] != 0x44 || message[2] != 0x12 )
00456 return FALSE;
00457
00458
00459 if( !NOVATELOEM4_DecodeBinaryMessageHeader( message, messageLength, header ) )
00460 return FALSE;
00461
00462
00463 headerLength = message[3];
00464
00465
00466 dataLength = message[8];
00467 dataLength |= message[9] << 8;
00468
00469
00470 msgLength = dataLength + headerLength + 4;
00471 if( msgLength != messageLength )
00472 return FALSE;
00473
00474
00475 index = headerLength;
00476 *nrObs = message[index];
00477 index++;
00478 *nrObs |= message[index] << 8;
00479 index++;
00480 *nrObs |= message[index] << 16;
00481 index++;
00482 *nrObs |= message[index] << 24;
00483
00484
00485 if( maxNrObs < *nrObs )
00486 return FALSE;
00487
00488
00489 testLength = (unsigned short)(*nrObs*24 + 4);
00490 if( testLength != dataLength )
00491 return FALSE;
00492
00493
00494 index = headerLength+4;
00495 for( i = 0; i < *nrObs; i++ )
00496 {
00497 long long int rangecmp_psr = 0;
00498 long rangecmp_adr = 0;
00499 double adr_rolls = 0;
00500 long rangecmp_doppler_freq = 0;
00501 unsigned char rangecmp_stdev_psr = 0;
00502 unsigned char rangecmp_stdev_adr = 0;
00503 unsigned long rangecmp_lock_time = 0;
00504 unsigned long rangecmp_cno = 0;
00505 double dtmp = 0;
00506
00507
00508 obsArray[i].rawTrackingStatus = message[index]; index++;
00509 obsArray[i].rawTrackingStatus |= message[index] << 8; index++;
00510 obsArray[i].rawTrackingStatus |= message[index] << 16; index++;
00511 obsArray[i].rawTrackingStatus |= message[index] << 24; index++;
00512
00513 if( !NOVATELOEM4_DecodeTrackingStatus( obsArray[i].rawTrackingStatus, &obsArray[i].trackingStatus ) )
00514 return FALSE;
00515
00516
00517 rangecmp_doppler_freq |= message[index]; index++;
00518 rangecmp_doppler_freq |= message[index] << 8; index++;
00519 rangecmp_doppler_freq |= message[index] << 16; index++;
00520 rangecmp_doppler_freq |= (message[index] & 0x0F) << 24;
00521
00522 if( (rangecmp_doppler_freq >> 27) > 0 )
00523 {
00524 rangecmp_doppler_freq |= 0xF0000000;
00525 }
00526 dtmp = (double)(rangecmp_doppler_freq);
00527 dtmp /= 256.0;
00528 obsArray[i].doppler = (float)dtmp;
00529
00530
00531 rangecmp_psr |= (message[index]&0xF0)>>4; index++;
00532 rangecmp_psr |= message[index]<<4; index++;
00533 rangecmp_psr |= message[index]<<12; index++;
00534 rangecmp_psr |= message[index]<<20; index++;
00535 rangecmp_psr |= (long long int)(message[index])<<28; index++;
00536
00537 if( ((long long int)(rangecmp_psr)>>35) > 0 )
00538 {
00539
00540 unsigned long int checkneg = 0xFFFFFFF0;
00541 checkneg *= (unsigned long int)(1<<31);
00542 checkneg *= 2;
00543 rangecmp_psr |= checkneg;
00544 }
00545 obsArray[i].psr = (double)rangecmp_psr;
00546 obsArray[i].psr /= 128.0;
00547
00548
00549 rangecmp_adr = message[index]; index++;
00550 rangecmp_adr |= message[index] << 8; index++;
00551 rangecmp_adr |= message[index] << 16; index++;
00552 rangecmp_adr |= message[index] << 24; index++;
00553 obsArray[i].adr = (double) rangecmp_adr;
00554 obsArray[i].adr /= 256.0;
00555
00556
00557 if (obsArray[i].trackingStatus.eFrequency == NOVATELOEM4_L1)
00558 adr_rolls =(obsArray[i].psr / GPS_WAVELENGTHL1 + obsArray[i].adr) / 8388608.0;
00559 else
00560 adr_rolls =(obsArray[i].psr / GPS_WAVELENGTHL2 + obsArray[i].adr) / 8388608.0;
00561
00562 if ( adr_rolls <= 0)
00563 adr_rolls = adr_rolls - 0.5;
00564 else
00565 adr_rolls = adr_rolls + 0.5;
00566
00567 obsArray[i].adr = obsArray[i].adr - (8388608.0 * (int)adr_rolls);
00568
00569
00570 rangecmp_stdev_psr = ((message[index] & 0x0F));
00571
00572
00573
00574 switch(rangecmp_stdev_psr)
00575 {
00576 case 0 : obsArray[i].psrstd = 0.050f; break;
00577 case 1 : obsArray[i].psrstd = 0.075f; break;
00578 case 2 : obsArray[i].psrstd = 0.113f; break;
00579 case 3 : obsArray[i].psrstd = 0.169f; break;
00580 case 4 : obsArray[i].psrstd = 0.253f; break;
00581 case 5 : obsArray[i].psrstd = 0.380f; break;
00582 case 6 : obsArray[i].psrstd = 0.570f; break;
00583 case 7 : obsArray[i].psrstd = 0.854f; break;
00584 case 8 : obsArray[i].psrstd = 1.281f; break;
00585 case 9 : obsArray[i].psrstd = 2.375f; break;
00586 case 10 : obsArray[i].psrstd = 4.750f; break;
00587 case 11 : obsArray[i].psrstd = 9.500f; break;
00588 case 12 : obsArray[i].psrstd = 19.000f; break;
00589 case 13 : obsArray[i].psrstd = 38.000f; break;
00590 case 14 : obsArray[i].psrstd = 76.000f; break;
00591 case 15 : obsArray[i].psrstd = 152.000f; break;
00592 };
00593
00594
00595 rangecmp_stdev_adr = message[index] >> 4 ;
00596 index++;
00597 obsArray[i].adrstd = (float)(rangecmp_stdev_adr+1)/512;
00598
00599
00600 obsArray[i].prn = (unsigned short)message[index];
00601 index++;
00602
00603
00604 rangecmp_lock_time |= message[index]; index++;
00605 rangecmp_lock_time |= message[index] << 8; index++;
00606 rangecmp_lock_time |= ((message[index] & 0x1F)) << 16;
00607
00608 obsArray[i].locktime = (float)(rangecmp_lock_time);
00609 obsArray[i].locktime /= 32.0;
00610
00611
00612 rangecmp_cno = (message[index] & 0xE0 ) >> 5; index++;
00613 rangecmp_cno |= (message[index] & 0x03 ) << 3;
00614
00615 obsArray[i].cno = (float)rangecmp_cno + 20;
00616
00617
00618 obsArray[i].reserved = (message[index] & 0xFC )>> 5; index ++ ;
00619 obsArray[i].reserved |= message[index] << 8; index ++ ;
00620 obsArray[i].reserved |= message[index] << 16; index ++ ;
00621 }
00622
00623 return TRUE;
00624 }
00625
00626 BOOL NOVATELOEM4_DecodeRANGEB(
00627 const unsigned char *message,
00628 const unsigned short messageLength,
00629 NOVATELOEM4_structBinaryHeader* header,
00630 NOVATELOEM4_structObservation* obsArray,
00631 const unsigned char maxNrObs,
00632 unsigned *nrObs
00633 )
00634 {
00635 unsigned i = 0;
00636 unsigned j = 0;
00637 unsigned index = 0;
00638 unsigned char headerLength = 0;
00639 unsigned short dataLength = 0;
00640 unsigned short msgLength = 0;
00641 unsigned short testLength = 0;
00642 unsigned char dbytes[8];
00643 unsigned char fbytes[4];
00644 double *dptr;
00645 float *fptr;
00646
00647
00648 if( message == NULL )
00649 return FALSE;
00650 if( obsArray == NULL )
00651 return FALSE;
00652 if( message[0] != 0xAA || message[1] != 0x44 || message[2] != 0x12 )
00653 return FALSE;
00654
00655
00656 if( !NOVATELOEM4_DecodeBinaryMessageHeader( message, messageLength, header ) )
00657 return FALSE;
00658
00659
00660 headerLength = message[3];
00661
00662
00663 dataLength = message[8];
00664 dataLength |= message[9] << 8;
00665
00666
00667 msgLength = dataLength + headerLength + 4;
00668 if( msgLength != messageLength )
00669 return FALSE;
00670
00671
00672 index = headerLength;
00673 *nrObs = message[index];
00674 index++;
00675 *nrObs |= message[index] << 8;
00676 index++;
00677 *nrObs |= message[index] << 16;
00678 index++;
00679 *nrObs |= message[index] << 24;
00680
00681
00682 if( maxNrObs < *nrObs )
00683 return FALSE;
00684
00685
00686 testLength = (unsigned short)(*nrObs*44 + 4);
00687 if( testLength != dataLength )
00688 return FALSE;
00689
00690
00691 index = headerLength+4;
00692 for( i = 0; i < *nrObs; i++ )
00693 {
00694 obsArray[i].prn = message[index]; index++;
00695 obsArray[i].prn |= message[index] << 8; index++;
00696 obsArray[i].reserved = message[index]; index++;
00697 obsArray[i].reserved |= message[index] << 8; index++;
00698
00699 for( j=0; j<8; j++ ){ dbytes[j] = message[index]; index++; }
00700 dptr = (double*)&dbytes;
00701 obsArray[i].psr = *dptr;
00702
00703 for( j=0; j<4; j++ ){ fbytes[j] = message[index]; index++; }
00704 fptr = (float*)&fbytes;
00705 obsArray[i].psrstd = *fptr;
00706
00707 for( j=0; j<8; j++ ){ dbytes[j] = message[index]; index++; }
00708 dptr = (double*)&dbytes;
00709 obsArray[i].adr = *dptr;
00710
00711 for( j=0; j<4; j++ ){ fbytes[j] = message[index]; index++; }
00712 fptr = (float*)&fbytes;
00713 obsArray[i].adrstd = *fptr;
00714
00715 for( j=0; j<4; j++ ){ fbytes[j] = message[index]; index++; }
00716 fptr = (float*)&fbytes;
00717 obsArray[i].doppler = *fptr;
00718
00719 for( j=0; j<4; j++ ){ fbytes[j] = message[index]; index++; }
00720 fptr = (float*)&fbytes;
00721 obsArray[i].cno = *fptr;
00722
00723 for( j=0; j<4; j++ ){ fbytes[j] = message[index]; index++; }
00724 fptr = (float*)&fbytes;
00725 obsArray[i].locktime = *fptr;
00726
00727 obsArray[i].rawTrackingStatus = message[index]; index++;
00728 obsArray[i].rawTrackingStatus |= message[index] << 8; index++;
00729 obsArray[i].rawTrackingStatus |= message[index] << 16; index++;
00730 obsArray[i].rawTrackingStatus |= message[index] << 24; index++;
00731
00732 if( !NOVATELOEM4_DecodeTrackingStatus( obsArray[i].rawTrackingStatus, &obsArray[i].trackingStatus ) )
00733 return FALSE;
00734 }
00735
00736 return TRUE;
00737 }
00738
00739
00740 BOOL NOVATELOEM4_DecodeTrackingStatus(
00741 const unsigned rawTrackingStatus,
00742 NOVATELOEM4_structTrackingStatus *trackingStatus
00743 )
00744 {
00745
00746 typedef struct
00747 {
00748 unsigned trackingState :5;
00749 unsigned channelNumber :5;
00750 unsigned phaseLockFlag :1;
00751 unsigned parityKnownFlag :1;
00752 unsigned codeLockedFlag :1;
00753 unsigned correlatorSpacing :3;
00754 unsigned satelliteSystem :3;
00755 unsigned reserved1 :1;
00756 unsigned grouping :1;
00757 unsigned frequency :2;
00758 unsigned codeType :3;
00759 unsigned forwardErrorCorrection :1;
00760 unsigned primaryL1Channel :1;
00761 unsigned halfCycleFlag :1;
00762 unsigned reserved3 :1;
00763 unsigned prnLockFlag :1;
00764 unsigned channelAssignment :1;
00765 } NOVATELOEM4_channelStatusBitField;
00766
00767 NOVATELOEM4_channelStatusBitField bitField;
00768 NOVATELOEM4_channelStatusBitField *ptrBitField;
00769
00770 if( trackingStatus == NULL )
00771 return FALSE;
00772
00773 ptrBitField = (NOVATELOEM4_channelStatusBitField *)&rawTrackingStatus;
00774 bitField = *ptrBitField;
00775
00776 trackingStatus->eTrackingState = (NOVATELOEM4_enumTrackingState)bitField.trackingState;
00777 trackingStatus->channelNumber = bitField.channelNumber;
00778 trackingStatus->isPhaseLocked = bitField.phaseLockFlag;
00779 trackingStatus->isParityKnown = bitField.parityKnownFlag;
00780 trackingStatus->isCodeLocked = bitField.codeLockedFlag;
00781 trackingStatus->eCorrelatorSpacing = (NOVATELOEM4_enumCorrelatorSpacing)bitField.correlatorSpacing;
00782 trackingStatus->eSatelliteSystem = (NOVATELOEM4_enumSatelliteSystem)bitField.satelliteSystem;
00783 trackingStatus->isGrouped = bitField.grouping;
00784 trackingStatus->eFrequency = (NOVATELOEM4_enumFrequency)bitField.frequency;
00785 trackingStatus->eCodeType = (NOVATELOEM4_enumCodeType)bitField.codeType;
00786 trackingStatus->isFECEnabled = bitField.forwardErrorCorrection;
00787 trackingStatus->isPrimaryL1Channel = bitField.primaryL1Channel;
00788 trackingStatus->isHalfCycleAdded = bitField.halfCycleFlag;
00789 trackingStatus->isForcedAssignment = bitField.channelAssignment;
00790
00791 return TRUE;
00792 }
00793
00794
00795 BOOL NOVATELOEM4_DecodeRAWEPHEMB(
00796 const unsigned char *message,
00797 const unsigned short messageLength,
00798 NOVATELOEM4_structBinaryHeader* header,
00799 unsigned *prn,
00800 unsigned *reference_week,
00801 unsigned *reference_time,
00802 unsigned *tow,
00803 unsigned short *iodc,
00804 unsigned char *iode,
00805 unsigned *toe,
00806 unsigned *toc,
00807 unsigned short *week,
00808 unsigned char *health,
00809 unsigned char *alert_flag,
00810 unsigned char *anti_spoof,
00811 unsigned char *code_on_L2,
00812 unsigned char *ura,
00813 unsigned char *L2_P_data_flag,
00814 unsigned char *fit_interval_flag,
00815 unsigned short *age_of_data_offset,
00816 double *tgd,
00817 double *af2,
00818 double *af1,
00819 double *af0,
00820 double *m0,
00821 double *delta_n,
00822 double *ecc,
00823 double *sqrta,
00824 double *omega0,
00825 double *i0,
00826 double *w,
00827 double *omegadot,
00828 double *idot,
00829 double *cuc,
00830 double *cus,
00831 double *crc,
00832 double *crs,
00833 double *cic,
00834 double *cis
00835 )
00836 {
00837 unsigned short msgLength;
00838 unsigned index = 0;
00839 BOOL result = FALSE;
00840
00841
00842 if( message == NULL )
00843 return FALSE;
00844 if( message[0] != 0xAA || message[1] != 0x44 || message[2] != 0x12 )
00845 return FALSE;
00846
00847
00848 if( !NOVATELOEM4_DecodeBinaryMessageHeader( message, messageLength, header ) )
00849 return FALSE;
00850
00851
00852 msgLength = header->headerLength + header->dataLength + 4;
00853 if( msgLength != messageLength )
00854 return FALSE;
00855
00856 index = header->headerLength;
00857 *prn = message[index]; index++;
00858 *prn |= message[index] << 8; index++;
00859 *prn |= message[index] << 16; index++;
00860 *prn |= message[index] << 24; index++;
00861
00862 *reference_week = message[index]; index++;
00863 *reference_week |= message[index] << 8; index++;
00864 *reference_week |= message[index] << 16; index++;
00865 *reference_week |= message[index] << 24; index++;
00866
00867 *reference_time = message[index]; index++;
00868 *reference_time |= message[index] << 8; index++;
00869 *reference_time |= message[index] << 16; index++;
00870 *reference_time |= message[index] << 24; index++;
00871
00872 result = GPS_DecodeRawGPSEphemeris(
00873 &message[index],
00874 &message[index+30],
00875 &message[index+60],
00876 (unsigned short)(*prn),
00877 tow,
00878 iodc,
00879 iode,
00880 toe,
00881 toc,
00882 week,
00883 health,
00884 alert_flag,
00885 anti_spoof,
00886 code_on_L2,
00887 ura,
00888 L2_P_data_flag,
00889 fit_interval_flag,
00890 age_of_data_offset,
00891 tgd,
00892 af2,
00893 af1,
00894 af0,
00895 m0,
00896 delta_n,
00897 ecc,
00898 sqrta,
00899 omega0,
00900 i0,
00901 w,
00902 omegadot,
00903 idot,
00904 cuc,
00905 cus,
00906 crc,
00907 crs,
00908 cic,
00909 cis
00910 );
00911 if( !result )
00912 return FALSE;
00913
00914 return TRUE;
00915 }