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 #include <math.h>
00039 #include "gnss_error.h"
00040 #include "gps.h"
00041 #include "constants.h"
00042 #include "geodesy.h"
00043
00044
00045
00046
00047
00048 #ifndef GPS_CLOCK_CORRECTION_RELATIVISTIC_CONSTANT_F
00049 #define GPS_CLOCK_CORRECTION_RELATIVISTIC_CONSTANT_F (-4.442807633e-10)
00050 #endif
00051 #ifndef GPS_UNIVERSAL_GRAVITY_CONSTANT
00052 #define GPS_UNIVERSAL_GRAVITY_CONSTANT (3.986005e14)
00053 #endif
00054 #ifndef GPS_RATIO_OF_SQUARED_FREQUENCIES_L1_OVER_L2
00055 #define GPS_RATIO_OF_SQUARED_FREQUENCIES_L1_OVER_L2 (1.6469444444444444444444444444444)
00056 #endif
00057 #ifndef GPS_WGS84_EARTH_ROTATION_RATE
00058 #define GPS_WGS84_EARTH_ROTATION_RATE (7.2921151467e-05)
00059 #endif
00060
00061 #define TWO_TO_THE_POWER_OF_55 (36028797018963968.0)
00062 #define TWO_TO_THE_POWER_OF_43 (8796093022208.0)
00063 #define TWO_TO_THE_POWER_OF_33 (8589934592.0)
00064 #define TWO_TO_THE_POWER_OF_31 (2147483648.0)
00065 #define TWO_TO_THE_POWER_OF_29 (536870912.0)
00066 #define TWO_TO_THE_POWER_OF_19 (524288.0)
00067
00068
00069
00070
00071
00072
00073 void GPS_ComputeSatelliteClockCorrectionAndDrift(
00074 const unsigned short transmission_gpsweek,
00075 const double transmission_gpstow,
00076 const unsigned short ephem_week,
00077 const unsigned toe,
00078 const unsigned toc,
00079 const double af0,
00080 const double af1,
00081 const double af2,
00082 const double ecc,
00083 const double sqrta,
00084 const double delta_n,
00085 const double m0,
00086 const double tgd,
00087 const unsigned char mode,
00088 double* clock_correction,
00089 double* clock_drift
00090 )
00091 {
00092 unsigned char i;
00093
00094 double tot;
00095 double tk;
00096 double tc;
00097 double d_tr;
00098 double d_tsv;
00099 double a;
00100 double n;
00101 double M;
00102 double E;
00103
00104
00105
00106
00107 tot = transmission_gpsweek*SECONDS_IN_WEEK + transmission_gpstow;
00108 tk = tot - (ephem_week*SECONDS_IN_WEEK + toe);
00109 tc = tot - (ephem_week*SECONDS_IN_WEEK + toc);
00110
00111
00112 a = sqrta*sqrta;
00113 n = sqrt( GPS_UNIVERSAL_GRAVITY_CONSTANT / (a*a*a) );
00114 n += delta_n;
00115
00116
00117 M = m0 + n*tk;
00118 E = M;
00119 for( i = 0; i < 7; i++ )
00120 {
00121 E = M + ecc * sin(E);
00122 }
00123
00124
00125 d_tr = GPS_CLOCK_CORRECTION_RELATIVISTIC_CONSTANT_F * ecc * sqrta * sin(E);
00126 d_tr *= LIGHTSPEED;
00127
00128
00129 d_tsv = af0 + af1*tc + af2*tc*tc;
00130
00131 if( mode == 0 )
00132 {
00133
00134 d_tsv -= tgd;
00135 }
00136 else if( mode == 1 )
00137 {
00138
00139 d_tsv -= tgd*GPS_RATIO_OF_SQUARED_FREQUENCIES_L1_OVER_L2;
00140 }
00141
00142
00143 *clock_correction = d_tsv*LIGHTSPEED + d_tr;
00144
00145
00146 *clock_drift = (af1 + 2.0*af2*tc) * LIGHTSPEED;
00147 }
00148
00149
00150
00151
00152 void GPS_ComputeSatellitePositionAndVelocity(
00153 const unsigned short transmission_gpsweek,
00154 const double transmission_gpstow,
00155 const unsigned short ephem_week,
00156 const unsigned toe,
00157 const double m0,
00158 const double delta_n,
00159 const double ecc,
00160 const double sqrta,
00161 const double omega0,
00162 const double i0,
00163 const double w,
00164 const double omegadot,
00165 const double idot,
00166 const double cuc,
00167 const double cus,
00168 const double crc,
00169 const double crs,
00170 const double cic,
00171 const double cis,
00172 const double estimateOfTrueRange,
00173 const double estimteOfRangeRate,
00174 double* x,
00175 double* y,
00176 double* z,
00177 double* vx,
00178 double* vy,
00179 double* vz
00180 )
00181 {
00182 unsigned char j;
00183
00184 double tot;
00185 double tk;
00186 double a;
00187 double n;
00188 double M;
00189 double E;
00190 double v;
00191 double u;
00192 double r;
00193 double i;
00194 double cos2u;
00195 double sin2u;
00196 double d_u;
00197 double d_r;
00198 double d_i;
00199 double x_op;
00200 double y_op;
00201 double omegak;
00202 double cos_omegak;
00203 double sin_omegak;
00204 double cosu;
00205 double sinu;
00206 double cosi;
00207 double sini;
00208 double cosE;
00209 double sinE;
00210 double omegadotk;
00211 double edot;
00212 double vdot;
00213 double udot;
00214 double idotdot;
00215 double rdot;
00216 double tmpa;
00217 double tmpb;
00218 double vx_op;
00219 double vy_op;
00220
00221
00222
00223
00224
00225 tot = transmission_gpsweek*SECONDS_IN_WEEK + transmission_gpstow;
00226 tk = tot - (ephem_week*SECONDS_IN_WEEK + toe);
00227
00228
00229 a = sqrta*sqrta;
00230 n = sqrt( GPS_UNIVERSAL_GRAVITY_CONSTANT / (a*a*a) );
00231 n += delta_n;
00232
00233
00234 M = m0 + n*tk;
00235 E = M;
00236 for( j = 0; j < 7; j++ )
00237 {
00238 E = M + ecc * sin(E);
00239 }
00240
00241 cosE = cos(E);
00242 sinE = sin(E);
00243
00244
00245 v = atan2( (sqrt(1.0 - ecc*ecc)*sinE), (cosE - ecc) );
00246
00247
00248 u = v + w;
00249
00250 r = a * (1.0 - ecc * cos(E));
00251
00252 i = i0;
00253
00254
00255
00256 cos2u = cos(2.0*u);
00257 sin2u = sin(2.0*u);
00258
00259 d_u = cuc * cos2u + cus * sin2u;
00260
00261 d_r = crc * cos2u + crs * sin2u;
00262
00263 d_i = cic * cos2u + cis * sin2u;
00264
00265
00266 u += d_u;
00267
00268 r += d_r;
00269
00270 i += d_i + idot * tk;
00271
00272
00273 cosu = cos(u);
00274 sinu = sin(u);
00275 x_op = r * cosu;
00276 y_op = r * sinu;
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286 omegak = omega0 + (omegadot - GPS_WGS84_EARTH_ROTATION_RATE)*tk - GPS_WGS84_EARTH_ROTATION_RATE*(toe + estimateOfTrueRange/LIGHTSPEED );
00287
00288
00289
00290 cos_omegak = cos(omegak);
00291 sin_omegak = sin(omegak);
00292 cosi = cos(i);
00293 sini = sin(i);
00294 *x = x_op * cos_omegak - y_op * sin_omegak * cosi;
00295 *y = x_op * sin_omegak + y_op * cos_omegak * cosi;
00296 *z = y_op * sini;
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307 cos2u = cos(2.0*u);
00308 sin2u = sin(2.0*u);
00309
00310 edot = n / (1.0 - ecc*cosE);
00311 vdot = sinE*edot*(1.0 + ecc*cos(v)) / ( sin(v)*(1.0-ecc*cosE) );
00312 udot = vdot + 2.0*(cus*cos2u - cuc*sin2u)*vdot;
00313 rdot = a*ecc*sinE*n/(1.0-ecc*cosE) + 2.0*(crs*cos2u - crc*sin2u)*vdot;
00314 idotdot = idot + (cis*cos2u - cic*sin2u)*2.0*vdot;
00315
00316 vx_op = rdot*cosu - y_op*udot;
00317 vy_op = rdot*sinu + x_op*udot;
00318
00319
00320
00321 omegadotk = omegadot - GPS_WGS84_EARTH_ROTATION_RATE*( 1.0 + estimteOfRangeRate/LIGHTSPEED );
00322
00323 tmpa = vx_op - y_op*cosi*omegadotk;
00324 tmpb = x_op*omegadotk + vy_op*cosi - y_op*sini*idotdot;
00325
00326 *vx = tmpa * cos_omegak - tmpb * sin_omegak;
00327 *vy = tmpa * sin_omegak + tmpb * cos_omegak;
00328 *vz = vy_op*sini + y_op*cosi*idotdot;
00329 }
00330
00331
00332 void GPS_ComputeUserToSatelliteRange(
00333 const double userX,
00334 const double userY,
00335 const double userZ,
00336 const double satX,
00337 const double satY,
00338 const double satZ,
00339 double* range
00340 )
00341 {
00342 double dx;
00343 double dy;
00344 double dz;
00345
00346 dx = satX - userX;
00347 dy = satY - userY;
00348 dz = satZ - userZ;
00349
00350
00351 *range = sqrt( dx*dx + dy*dy + dz*dz );
00352 }
00353
00354
00355 void GPS_ComputeUserToSatelliteRangeAndRangeRate(
00356 const double userX,
00357 const double userY,
00358 const double userZ,
00359 const double userVx,
00360 const double userVy,
00361 const double userVz,
00362 const double satX,
00363 const double satY,
00364 const double satZ,
00365 const double satVx,
00366 const double satVy,
00367 const double satVz,
00368 double* range,
00369 double* range_rate
00370 )
00371 {
00372 double dx;
00373 double dy;
00374 double dz;
00375
00376 dx = satX - userX;
00377 dy = satY - userY;
00378 dz = satZ - userZ;
00379
00380
00381 *range = sqrt( dx*dx + dy*dy + dz*dz );
00382
00383
00384
00385 *range_rate = (userVx - satVx)*dx + (userVy - satVy)*dy + (userVz - satVz)*dz;
00386 *range_rate /= *range;
00387 }
00388
00389
00390
00391 void GPS_ComputeSatellitePositionVelocityAzimuthElevationDoppler_BasedOnAlmanacData(
00392 const double userX,
00393 const double userY,
00394 const double userZ,
00395 const unsigned short gpsweek,
00396 const double gpstow,
00397 const double toa,
00398 const unsigned short almanac_week,
00399 const unsigned short prn,
00400 const double ecc,
00401 const double i0,
00402 const double omegadot,
00403 const double sqrta,
00404 const double omega0,
00405 const double w,
00406 const double m0,
00407 const double af0,
00408 const double af1,
00409 double* clock_correction,
00410 double* clock_drift,
00411 double* satX,
00412 double* satY,
00413 double* satZ,
00414 double* satVx,
00415 double* satVy,
00416 double* satVz,
00417 double* azimuth,
00418 double* elevation,
00419 double* doppler
00420 )
00421 {
00422 double tow;
00423 double range;
00424 double range_rate;
00425 double x;
00426 double y;
00427 double z;
00428 double vx;
00429 double vy;
00430 double vz;
00431
00432 unsigned short week;
00433
00434 unsigned char i;
00435
00436 i = (unsigned char)prn;
00437
00438
00439 x = y = z = vx = vy = vz = 0.0;
00440
00441 GPS_ComputeSatelliteClockCorrectionAndDrift(
00442 gpsweek,
00443 gpstow,
00444 almanac_week,
00445 (unsigned)toa,
00446 (unsigned)toa,
00447 af0,
00448 af1,
00449 0.0,
00450 ecc,
00451 sqrta,
00452 0.0,
00453 m0,
00454 0.0,
00455 0,
00456 clock_correction,
00457 clock_drift );
00458
00459
00460 week = gpsweek;
00461 tow = gpstow + (*clock_correction)/LIGHTSPEED;
00462 if( tow < 0.0 )
00463 {
00464 tow += SECONDS_IN_WEEK;
00465 week--;
00466 }
00467 if( tow > 604800.0 )
00468 {
00469 tow -= SECONDS_IN_WEEK;
00470 week++;
00471 }
00472
00473
00474
00475
00476 range = 0.070*LIGHTSPEED;
00477 range_rate = 0.0;
00478 for( i = 0; i < 2; i++ )
00479 {
00480 GPS_ComputeSatellitePositionAndVelocity(
00481 week,
00482 tow,
00483 almanac_week,
00484 (unsigned)toa,
00485 m0,
00486 0.0,
00487 ecc,
00488 sqrta,
00489 omega0,
00490 i0,
00491 w,
00492 omegadot,
00493 0.0,
00494 0.0,
00495 0.0,
00496 0.0,
00497 0.0,
00498 0.0,
00499 0.0,
00500 range,
00501 range_rate,
00502 &x,
00503 &y,
00504 &z,
00505 &vx,
00506 &vy,
00507 &vz );
00508
00509 GPS_ComputeUserToSatelliteRangeAndRangeRate(
00510 userX,
00511 userY,
00512 userZ,
00513 0.0,
00514 0.0,
00515 0.0,
00516 x,
00517 y,
00518 z,
00519 vx,
00520 vy,
00521 vz,
00522 &range,
00523 &range_rate );
00524 }
00525
00526 GEODESY_ComputeAzimuthAndElevationAnglesBetweenToPointsInTheEarthFixedFrame(
00527 GEODESY_REFERENCE_ELLIPSE_WGS84,
00528 userX,
00529 userY,
00530 userZ,
00531 x,
00532 y,
00533 z,
00534 elevation,
00535 azimuth );
00536
00537 *satX = x;
00538 *satY = y;
00539 *satZ = z;
00540 *satVx = vx;
00541 *satVy = vy;
00542 *satVz = vz;
00543
00544 *doppler = range_rate;
00545
00546 }
00547
00548
00549
00550 void GPS_ComputeSatellitePositionVelocityAzimuthElevationDoppler_BasedOnEphmerisData(
00551 const double userX,
00552 const double userY,
00553 const double userZ,
00554 const unsigned short gpsweek,
00555 const double gpstow,
00556 const unsigned short ephem_week,
00557 const unsigned toe,
00558 const unsigned toc,
00559 const double af0,
00560 const double af1,
00561 const double af2,
00562 const double tgd,
00563 const double m0,
00564 const double delta_n,
00565 const double ecc,
00566 const double sqrta,
00567 const double omega0,
00568 const double i0,
00569 const double w,
00570 const double omegadot,
00571 const double idot,
00572 const double cuc,
00573 const double cus,
00574 const double crc,
00575 const double crs,
00576 const double cic,
00577 const double cis,
00578 double* clock_correction,
00579 double* clock_drift,
00580 double* satX,
00581 double* satY,
00582 double* satZ,
00583 double* satVx,
00584 double* satVy,
00585 double* satVz,
00586 double* azimuth,
00587 double* elevation,
00588 double* doppler
00589 )
00590 {
00591 double tow;
00592 double range;
00593 double range_rate;
00594 double x;
00595 double y;
00596 double z;
00597 double vx;
00598 double vy;
00599 double vz;
00600
00601 unsigned short week;
00602
00603 unsigned char i;
00604
00605
00606 x = y = z = vx = vy = vz = 0.0;
00607
00608 GPS_ComputeSatelliteClockCorrectionAndDrift(
00609 gpsweek,
00610 gpstow,
00611 ephem_week,
00612 toe,
00613 toc,
00614 af0,
00615 af1,
00616 af2,
00617 ecc,
00618 sqrta,
00619 delta_n,
00620 m0,
00621 tgd,
00622 0,
00623 clock_correction,
00624 clock_drift );
00625
00626
00627 week = gpsweek;
00628 tow = gpstow + (*clock_correction)/LIGHTSPEED;
00629 if( tow < 0.0 )
00630 {
00631 tow += SECONDS_IN_WEEK;
00632 week--;
00633 }
00634 if( tow > 604800.0 )
00635 {
00636 tow -= SECONDS_IN_WEEK;
00637 week++;
00638 }
00639
00640
00641
00642
00643 range = 0.070*LIGHTSPEED;
00644 range_rate = 0.0;
00645 for( i = 0; i < 2; i++ )
00646 {
00647 GPS_ComputeSatellitePositionAndVelocity(
00648 week,
00649 tow,
00650 ephem_week,
00651 toe,
00652 m0,
00653 delta_n,
00654 ecc,
00655 sqrta,
00656 omega0,
00657 i0,
00658 w,
00659 omegadot,
00660 idot,
00661 cuc,
00662 cus,
00663 crc,
00664 crs,
00665 cic,
00666 cis,
00667 range,
00668 range_rate,
00669 &x,
00670 &y,
00671 &z,
00672 &vx,
00673 &vy,
00674 &vz );
00675
00676 GPS_ComputeUserToSatelliteRangeAndRangeRate(
00677 userX,
00678 userY,
00679 userZ,
00680 0.0,
00681 0.0,
00682 0.0,
00683 x,
00684 y,
00685 z,
00686 vx,
00687 vy,
00688 vz,
00689 &range,
00690 &range_rate );
00691 }
00692
00693 GEODESY_ComputeAzimuthAndElevationAnglesBetweenToPointsInTheEarthFixedFrame(
00694 GEODESY_REFERENCE_ELLIPSE_WGS84,
00695 userX,
00696 userY,
00697 userZ,
00698 x,
00699 y,
00700 z,
00701 elevation,
00702 azimuth );
00703
00704 *satX = x;
00705 *satY = y;
00706 *satZ = z;
00707 *satVx = vx;
00708 *satVy = vy;
00709 *satVz = vz;
00710
00711 *doppler = range_rate;
00712 }
00713
00714
00715 BOOL GPS_DecodeRawGPSEphemeris(
00716 const unsigned char subframe1[30],
00717 const unsigned char subframe2[30],
00718 const unsigned char subframe3[30],
00719 unsigned short prn,
00720 unsigned* tow,
00721 unsigned short* iodc,
00722 unsigned char* iode,
00723 unsigned* toe,
00724 unsigned* toc,
00725 unsigned short* week,
00726 unsigned char* health,
00727 unsigned char* alert_flag,
00728 unsigned char* anti_spoof,
00729 unsigned char* code_on_L2,
00730 unsigned char* ura,
00731 unsigned char* L2_P_data_flag,
00732 unsigned char* fit_interval_flag,
00733 unsigned short* age_of_data_offset,
00734 double* tgd,
00735 double* af2,
00736 double* af1,
00737 double* af0,
00738 double* m0,
00739 double* delta_n,
00740 double* ecc,
00741 double* sqrta,
00742 double* omega0,
00743 double* i0,
00744 double* w,
00745 double* omegadot,
00746 double* idot,
00747 double* cuc,
00748 double* cus,
00749 double* crc,
00750 double* crs,
00751 double* cic,
00752 double* cis
00753 )
00754 {
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868 unsigned char subframe_id;
00869 unsigned char iode_subframe1;
00870 unsigned char iode_subframe2;
00871 unsigned char iode_subframe3;
00872
00873
00874 char s8;
00875 short s16;
00876 int s32;
00877 unsigned short u16a, u16b;
00878 unsigned u32a, u32b, u32c, u32d;
00879
00880 u16a = prn;
00881
00882
00883
00884
00885
00886
00887 u32a = subframe1[3] << 11;
00888 u32b = subframe1[4] << 3;
00889 u32c = (subframe1[5] & 0x80) >> 5;
00890 *tow = (u32a | u32b | u32c);
00891 *tow = (*tow * 3) / 2;
00892
00893
00894 *alert_flag = (unsigned char)( (subframe1[5] & 0x40) >> 6 );
00895
00896
00897 *anti_spoof = (unsigned char)( (subframe1[5] & 0x20) >> 5 );
00898
00899
00900 subframe_id = (unsigned char)( (subframe1[5] & 0x1C) >> 2 );
00901 if( subframe_id != 1 )
00902 {
00903 GNSS_ERROR_MSG( "if( subframe_id != 1 )" );
00904 return FALSE;
00905 }
00906
00907
00908 u16a = (unsigned short)( subframe1[6] << 2 );
00909 u16b = (unsigned short)( subframe1[7] >> 6 );
00910 *week = (unsigned short)( u16a | u16b );
00911
00912
00913 *code_on_L2 = (unsigned char)( (subframe1[7] & 0x30) >> 4 );
00914
00915
00916 *ura = (unsigned char)( (subframe1[7] & 0x0F) );
00917
00918
00919 *health = (unsigned char)( subframe1[8] >> 2 );
00920
00921
00922 u16a = (unsigned short)( (subframe1[8] & 0x03) << 8 );
00923 u16b = (unsigned short)( subframe1[21] );
00924 *iodc = (unsigned short)( u16a | u16b );
00925
00926
00927 iode_subframe1 = subframe1[21];
00928
00929
00930 *L2_P_data_flag = (unsigned char)( (subframe1[9] & 0x80) >> 7 );
00931
00932
00933 s8 = subframe1[20];
00934 *tgd = s8 / TWO_TO_THE_POWER_OF_31;
00935
00936
00937 u16a = (unsigned short)( subframe1[22] << 8 );
00938 u16b = (unsigned short)( subframe1[23] );
00939 *toc = (unsigned)( (u16a | u16b) ) * 16;
00940
00941
00942 s8 = subframe1[24];
00943 *af2 = s8;
00944 *af2 /= TWO_TO_THE_POWER_OF_55;
00945
00946
00947 u16a = (unsigned short)( subframe1[25] << 8 );
00948 u16b = subframe1[26];
00949 s16 = (unsigned short)( u16a | u16b );
00950 *af1 = s16;
00951 *af1 /= TWO_TO_THE_POWER_OF_43;
00952
00953
00954 u32a = subframe1[27] << 24;
00955 u32b = subframe1[28] << 16;
00956 u32c = subframe1[29] & 0xFC;
00957 u32c <<= 8;
00958 u32d = (u32a | u32b | u32c);
00959 s32 = (int)(u32d);
00960 s32 >>= 10;
00961 *af0 = s32;
00962 *af0 /= TWO_TO_THE_POWER_OF_31;
00963
00964
00965
00966
00967
00968
00969 subframe_id = (unsigned char)( (subframe2[5] & 0x1C) >> 2 );
00970 if( subframe_id != 2 )
00971 {
00972 GNSS_ERROR_MSG( "if( subframe_id != 2 )" );
00973 return FALSE;
00974 }
00975
00976
00977 iode_subframe2 = subframe2[6];
00978
00979
00980 u16a = (unsigned short)( subframe2[7] << 8 );
00981 u16b = subframe2[8];
00982 s16 = (unsigned short)( u16a | u16b );
00983 *crs = s16;
00984 *crs /= 32.0;
00985
00986
00987 u16a = (unsigned short)( subframe2[9] << 8 );
00988 u16b = subframe2[10];
00989 s16 = (short)( u16a | u16b );
00990 *delta_n = s16;
00991 *delta_n *= PI / TWO_TO_THE_POWER_OF_43;
00992
00993
00994 u32a = subframe2[11] << 24;
00995 u32b = subframe2[12] << 16;
00996 u32c = subframe2[13] << 8;
00997 u32d = subframe2[14];
00998 s32 = (u32a | u32b | u32c | u32d);
00999 *m0 = s32;
01000 *m0 *= PI / TWO_TO_THE_POWER_OF_31;
01001
01002
01003 u16a = (unsigned short)( subframe2[15] << 8 );
01004 u16b = subframe2[16];
01005 s16 = (short)( u16a | u16b );
01006 *cuc = s16;
01007 *cuc /= TWO_TO_THE_POWER_OF_29;
01008
01009
01010 u32a = subframe2[17] << 24;
01011 u32b = subframe2[18] << 16;
01012 u32c = subframe2[19] << 8;
01013 u32d = subframe2[20];
01014 *ecc = u32a | u32b | u32c | u32d;
01015 *ecc /= TWO_TO_THE_POWER_OF_33;
01016
01017
01018 u16a = (unsigned short)( subframe2[21] << 8 );
01019 u16b = subframe2[22];
01020 s16 = (short)( u16a | u16b );
01021 *cus = s16;
01022 *cus /= TWO_TO_THE_POWER_OF_29;
01023
01024
01025 u32a = subframe2[23] << 24;
01026 u32b = subframe2[24] << 16;
01027 u32c = subframe2[25] << 8;
01028 u32d = subframe2[26];
01029 *sqrta = u32a | u32b | u32c | u32d;
01030 *sqrta /= TWO_TO_THE_POWER_OF_19;
01031
01032
01033 u16a = (unsigned short)( subframe2[27] << 8 );
01034 u16b = subframe2[28];
01035 *toe = (unsigned)( (u16a | u16b) ) * 16;
01036
01037
01038 *fit_interval_flag = (unsigned char)( subframe2[29] >> 7 );
01039
01040
01041 *age_of_data_offset = (unsigned short)( (subframe2[29] & 0x74) >> 2 );
01042 *age_of_data_offset *= 900;
01043
01044
01045
01046
01047
01048
01049 subframe_id = (unsigned char)( (subframe3[5] & 0x1C) >> 2 );
01050 if( subframe_id != 3 )
01051 {
01052 GNSS_ERROR_MSG( "if( subframe_id != 3 )" );
01053 return FALSE;
01054 }
01055
01056
01057 u16a = (unsigned short)( subframe3[6] << 8 );
01058 u16b = subframe3[7];
01059 s16 = (short)( u16a | u16b );
01060 *cic = s16;
01061 *cic /= TWO_TO_THE_POWER_OF_29;
01062
01063
01064 u32a = subframe3[8] << 24;
01065 u32b = subframe3[9] << 16;
01066 u32c = subframe3[10] << 8;
01067 u32d = subframe3[11];
01068 s32 = u32a | u32b | u32c | u32d;
01069 *omega0 = s32;
01070 *omega0 *= PI / TWO_TO_THE_POWER_OF_31;
01071
01072
01073 u16a = (unsigned short)( subframe3[12] << 8 );
01074 u16b = subframe3[13];
01075 s16 = (short)( u16a | u16b );
01076 *cis = s16;
01077 *cis /= TWO_TO_THE_POWER_OF_29;
01078
01079
01080 u32a = subframe3[14] << 24;
01081 u32b = subframe3[15] << 16;
01082 u32c = subframe3[16] << 8;
01083 u32d = subframe3[17];
01084 s32 = u32a | u32b | u32c | u32d;
01085 *i0 = s32;
01086 *i0 *= PI / TWO_TO_THE_POWER_OF_31;
01087
01088
01089 u16a = (unsigned short)( subframe3[18] << 8 );
01090 u16b = subframe3[19];
01091 s16 = (short)( u16a | u16b );
01092 *crc = s16;
01093 *crc /= 32.0;
01094
01095
01096 u32a = subframe3[20] << 24;
01097 u32b = subframe3[21] << 16;
01098 u32c = subframe3[22] << 8;
01099 u32d = subframe3[23];
01100 s32 = u32a | u32b | u32c | u32d;
01101 *w = s32;
01102 *w *= PI / TWO_TO_THE_POWER_OF_31;
01103
01104
01105 u32a = subframe3[24] << 24;
01106 u32b = subframe3[25] << 16;
01107 u32c = subframe3[26] << 8;
01108 s32 = u32a | u32b | u32c;
01109 s32 = s32 >> 8;
01110 *omegadot = s32;
01111 *omegadot *= PI / TWO_TO_THE_POWER_OF_43;
01112
01113
01114 iode_subframe3 = subframe3[27];
01115
01116
01117 u16a = (unsigned short)( subframe3[28] << 8 );
01118 u16b = (unsigned short)( subframe3[29] & 0xFC );
01119 s16 = (short)( u16a | u16b );
01120 s16 = (short)( s16 >> 2 );
01121 *idot = s16;
01122 *idot *= PI / TWO_TO_THE_POWER_OF_43;
01123
01124
01125 if( (iode_subframe1 == iode_subframe2) && (iode_subframe1 == iode_subframe3) )
01126 {
01127 *iode = iode_subframe1;
01128 return TRUE;
01129 }
01130 else
01131 {
01132 *iode = 0;
01133 GNSS_ERROR_MSG( "inconsistent subframe dataset" );
01134 return FALSE;
01135 }
01136 }
01137
01138