00001 #pragma ident "$Id: FICData.cpp 2944 2011-10-27 08:04:41Z yanweignss $"
00002
00003
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
00041
00042
00043
00044
00045 #include <vector>
00046 #include <string>
00047
00048 #include <cstring>
00049
00050 #include "StringUtils.hpp"
00051 #include "BinUtils.hpp"
00052 #include "FICData.hpp"
00053 #include "FICStream.hpp"
00054 #include "FICAStream.hpp"
00055
00056 #include <cmath>
00057
00058 #include "gpstkplatform.h"
00059
00060 using namespace gpstk::StringUtils;
00061 using namespace std;
00062 using namespace gpstk::BinUtils;
00063
00064
00065 const int FICBlkHdrSize = 4;
00066
00067 namespace gpstk
00068 {
00069 const string FICData::blockString = "BLK ";
00070
00071 void FICData::reallyPutRecord(FFStream& ffs) const
00072 throw(std::exception, gpstk::StringUtils::StringException,
00073 gpstk::FFStreamError)
00074 {
00075 if (!isValid())
00076 {
00077 FFStreamError e("Tried to write an invalid FIC block");
00078 GPSTK_THROW(e);
00079 }
00080
00081
00082
00083
00084 if (dynamic_cast<FICAStream*>(&ffs))
00085 {
00086 FICAStream& strm = dynamic_cast<FICAStream&>(ffs);
00087
00088 strm << '\n' << blockString;
00089 strm << setw(6) << blockNum
00090 << setw(5) << f.size()
00091 << setw(5) << i.size()
00092 << setw(5) << c.size();
00093 unsigned long index;
00094 for (index = 0; index < f.size(); index++)
00095 {
00096 if ((index % 4) == 0)
00097 strm << '\n';
00098 double l10 = ::log10(::fabs(f[index]));
00099 if ( ((l10 >= 100) || (l10 <= -100)) && (f[index] != 0))
00100 strm << doub2for(f[index], 20, 3);
00101 else
00102 strm << doub2for(f[index], 20, 2);
00103 }
00104 for (index = 0; index < i.size(); index++)
00105 {
00106 if ((index % 6) == 0)
00107 strm << '\n';
00108 strm << setw(12) << i[index];
00109 }
00110 for (index = 0; index < c.size(); index++)
00111 {
00112 if ((index % 8) == 0)
00113 strm << '\n';
00114 strm << setw(8) << c[index];
00115 }
00116 }
00117 else
00118 {
00119 if (dynamic_cast<FICStream*>(&ffs))
00120 {
00121 FICStream& strm = dynamic_cast<FICStream&>(ffs);
00122
00123 strm << blockString;
00124 strm.writeData<int32_t>(hostToIntel(blockNum));
00125 strm.writeData<uint32_t>(hostToIntel(static_cast<uint32_t>(f.size())));
00126 strm.writeData<uint32_t>(hostToIntel(static_cast<uint32_t>(i.size())));
00127 strm.writeData<uint32_t>(hostToIntel(static_cast<uint32_t>(c.size())));
00128 unsigned long index;
00129 for (index = 0; index < f.size(); index++)
00130 strm.writeData<double>(hostToIntel(f[index]));
00131 for (index = 0; index < i.size(); index++)
00132 strm.writeData<int32_t>(hostToIntel(i[index]));
00133 for (index = 0; index < c.size(); index++)
00134 strm.writeData<char>(hostToIntel(c[index]));
00135 }
00136
00137 else
00138 {
00139 FFStreamError e("FICData tried to read from a non-FIC file");
00140 GPSTK_THROW(e);
00141 }
00142 }
00143 }
00144
00145 bool FICData::isValid() const
00146 {
00147 switch(blockNum) {
00148 case 109:
00149 if((f.size() == 0) && (i.size() == 32) && (c.size() == 0))
00150 return true;
00151 break;
00152 case 9:
00153 if((f.size() == 60) && (i.size() == 0) && (c.size() == 0))
00154 return true;
00155 break;
00156 case 162:
00157 if((f.size() == 0) && (i.size() == 15) && (c.size() == 0))
00158 return true;
00159 break;
00160 case 62:
00161 if(( (f.size() == 20) || (f.size() == 32) || (f.size() == 14) ||
00162 (f.size() == 23) || (f.size() == 47) || (f.size() == 29) )
00163 && (i.size() == 6) && (c.size() == 0))
00164 return true;
00165 break;
00166 default:
00167 return false;
00168 break;
00169 }
00170 return false;
00171 }
00172
00173 void FICData::dump(ostream& s) const
00174 {
00175 int n;
00176 s << "FIC BlockNumber: " << blockNum << endl
00177 << " floats: " << flush;
00178 for(n = 0; n< f.size(); n++)
00179 s << f[n] << " " << flush;
00180 s << endl << " integers: " << flush;
00181 for(n = 0; n< i.size(); n++)
00182 s << i[n] << " " << flush;
00183 s << endl << " chars: " << flush;
00184 for(n = 0; n< c.size(); n++)
00185 s << c[n] << " " << flush;
00186 s << endl << endl;
00187 };
00188
00189 void FICData::prettyDump(ostream& os) const
00190 {
00191 switch (blockNum)
00192 {
00193 case 109:
00194 prettyDump109(os);
00195 break;
00196 case 9:
00197 prettyDump9(os);
00198 break;
00199 case 62:
00200 prettyDump62(os);
00201 break;
00202 case 162:
00203 prettyDump162(os);
00204 break;
00205 default:
00206 break;
00207 }
00208 }
00209
00210 bool FICData::getTransmitTime(DayTime& dt) const
00211 {
00212 short week;
00213 double SOW;
00214 switch (blockNum)
00215 {
00216 case 9:
00217 week = (short) f[5];
00218 SOW = f[2];
00219 break;
00220 case 109:
00221 week = i[0];
00222 SOW = ((i[3] & 0x3FFFFFFFL) >> 13) * 6;
00223 break;
00224 case 62:
00225 week = i[5];
00226 SOW = i[1];
00227 break;
00228 case 162:
00229 week = i[14];
00230 SOW = ((i[2] & 0x3FFFFFFFL) >> 13) * 6;
00231 break;
00232 default:
00233 return false;
00234 break;
00235 }
00236 dt.setGPSfullweek(week, SOW);
00237 return true;
00238 }
00239
00240 void FICData::prettyDump9(ostream& os) const
00241 {
00242 short j;
00243 short ndx[3] = { 9, 25, 52 };
00244 short iod;
00245 short itemp;
00246 short epochWeek;
00247 double epochTime, xmitTime, diff;
00248
00249 os << "**************************************";
00250 os << "**************************************\n";
00251 os << " Block Number : ";
00252 os.width(3);
00253 os << blockNum << "\n";
00254 os << "Broadcast Ephemeris (Engineering Units)\n";
00255 os << "\n";
00256 os << "PRN : ";
00257 os.width(2);
00258 os << f[19] << "\n\n";
00259
00260
00261
00262 epochTime = f[12];
00263 xmitTime = f[2];
00264 diff = -1 * (epochTime - xmitTime);
00265 if (diff > DayTime::HALFWEEK) epochWeek = (short) f[5] + 1;
00266 else epochWeek = (short) f[5];
00267 timeDisplay( os, "Clock Epoch:", epochWeek, f[12], 1 );
00268
00269 epochTime = f[33];
00270 xmitTime = f[22];
00271 diff = -1 * (epochTime - xmitTime);
00272 if (diff > DayTime::HALFWEEK) epochWeek = (short) f[5] + 1;
00273 else epochWeek = (short) f[5];
00274 timeDisplay( os, "Eph Epoch:", epochWeek, f[33], 0 );
00275
00276 os << "Transmit Week:";
00277 os.width(4);
00278 os << f[5] << "\n";
00279 os.width(2);
00280 os << "Fit interval flag : " << f[34] << "\n";
00281
00282 os << "\n";
00283 os << " SUBFRAME OVERHEAD\n\n";
00284 os << " SOW DOW:HH:MM:SS IOD ALERT A-S\n";
00285 for (j=0;j<3;j++)
00286 {
00287 os.width(1);
00288 os << "SF" << (j+1) << " HOW: ";
00289 os.width(7);
00290 os << f[2+j*20];
00291
00292
00293 os << " ";
00294 shortcut( os, f[2+j*20]);
00295 if (j==0)os << " ";
00296 else os << " ";
00297 os.setf(ios::uppercase);
00298
00299
00300
00301
00302 iod = (short) (f[ndx[j]] / 2048);
00303 iod = iod;
00304 os << "0x";
00305 os.fill('0');
00306 if (j==0) os.width(3);
00307 else os.width(2);
00308 os << hex << iod << dec << " ";
00309 os.fill(' ');
00310
00311 itemp = (short) f[3+j*20];
00312 if (itemp & 0x0002) os << "1 ";
00313 else os << "0 ";
00314 if (itemp & 0x0001) os << " on\n";
00315 else os << "off\n";
00316 }
00317 os << "\n CLOCK\n\n";
00318 os << "Bias T0: ";
00319 os.setf(ios::scientific, ios::floatfield);
00320 os.setf(ios::right, ios::adjustfield);
00321 os.precision(8);
00322 os.width(16);
00323 os << f[15] << " sec\n";
00324 os << "Drift: ";
00325 os.width(16);
00326 os << f[14] << " sec/sec\n";
00327 os << "Drift rate: ";
00328 os.width(16);
00329 os << f[13] << " sec/(sec**2)\n";
00330 os << "Group delay: ";
00331 os.width(16);
00332 os << f[11] << " sec\n";
00333 os.setf(ios::fixed, ios::floatfield);
00334 os.precision(0);
00335
00336 os << "\n ORBIT PARAMETERS\n\n";
00337 os << "Semi-major axis: ";
00338 os.setf(ios::scientific, ios::floatfield);
00339 os.setf(ios::right, ios::adjustfield);
00340 os.precision(8);
00341 os.width(16);
00342 os << f[32] << " m**.5\n";
00343 os << "Motion correction: ";
00344 os.width(16);
00345 os << f[27] << " rad/sec\n";
00346 os << "Eccentricity: ";
00347 os.width(16);
00348 os << f[30] << "\n";
00349 os << "Arg of perigee: ";
00350 os.width(16);
00351 os << f[50] << " rad\n";
00352 os << "Mean anomaly at epoch: ";
00353 os.width(16);
00354 os << f[28] << " rad\n";
00355 os << "Right ascension: ";
00356 os.width(16);
00357 os << f[46] << " rad ";
00358 os.width(16);
00359 os << f[51] << " rad/sec\n";
00360 os << "Inclination: ";
00361 os.width(16);
00362 os << f[48] << " rad ";
00363 os.width(16);
00364 os << f[53] << " rad/sec\n";
00365 os.setf(ios::fixed, ios::floatfield);
00366 os.precision(0);
00367
00368 os << "\n HARMONIC CORRECTIONS\n\n";
00369 os << "Radial Sine: ";
00370 os.setf(ios::scientific, ios::floatfield);
00371 os.setf(ios::right, ios::adjustfield);
00372 os.precision(8);
00373 os.width(16);
00374 os << f[26] << " m Cosine: ";
00375 os.width(16);
00376 os << f[49] << " m\n";
00377 os << "Inclination Sine: ";
00378 os.width(16);
00379 os << f[47] << " rad Cosine: ";
00380 os.width(16);
00381 os << f[45] << " rad\n";
00382 os << "In-track Sine: ";
00383 os.width(16);
00384 os << f[31] << " rad Cosine: ";
00385 os.width(16);
00386 os << f[29] << " rad\n";
00387 os.setf(ios::fixed, ios::floatfield);
00388 os.precision(0);
00389
00390 os << "\n SV STATUS\n\n";
00391 os << "Health bits: 0x";
00392 os.fill('0');
00393 os.width(2);
00394 os << (short) f[8] << " URA index: ";
00395 os.fill(' ');
00396 os.width(4);
00397 os << f[7] << "\n";
00398 os << "Code on L2: ";
00399 switch ( (short) f[6] )
00400 {
00401 case 0:
00402 os << "reserved";
00403 break;
00404
00405 case 1:
00406 os << " P only";
00407 break;
00408
00409 case 2:
00410 os << " C/A only";
00411 break;
00412
00413 case 3:
00414 os << " P & C/A";
00415 break;
00416
00417 default:
00418 break;
00419
00420 }
00421 os << " L2 P Nav data: ";
00422 if ( (short) f[10]!=0) os << "off";
00423 else os << "on";
00424 os << "\n";
00425 }
00426
00427 void FICData::prettyDump109(ostream & os) const
00428 {
00429 os << "**************************************";
00430 os << "**************************************\n";
00431 os << " Block Number : ";
00432 os.width(3);
00433 os << blockNum << "\n";
00434 os << "Broadcast Ephemeris as Transmitted\n";
00435 os << "\n";
00436 os << "PRN : ";
00437 os.width(2);
00438 os << i[1] << "\n";
00439 timeDisplay( os, "Transmit time:",
00440 i[0],
00441 ((i[3] & 0x3FFFFFFFL) >> 13) * 6,
00442 2 );
00443 os.setf(ios::uppercase);
00444 os << "\n";
00445 os << "Hexadecimal dump of words 1-10";
00446 short j;
00447 for (j=0;j<10;j++)
00448 {
00449 if (j==0 || j ==5 ) os << "\n";
00450 os << " ";
00451 os.width(2);
00452 os << (j+1) << ":";
00453 os.width(8);
00454 os.fill('0');
00455 os << hex << i[j+2] << dec;
00456 os.fill(' ');
00457 }
00458 os << "\n\n";
00459 os << "Hexadecimal dump of words 11-20";
00460 for (j=10;j<20;j++)
00461 {
00462 if (j==10 || j ==15 ) os << "\n";
00463 os << " ";
00464 os.width(2);
00465 os << (j+1) << ":";
00466 os.width(8);
00467 os.fill('0');
00468 os << hex << i[j+2] << dec;
00469 os.fill(' ');
00470 }
00471 os << "\n\n";
00472 os << "Hexadecimal dump of words 21-30";
00473 for (j=20;j<30;j++)
00474 {
00475 if (j==20 || j ==25 ) os << "\n";
00476 os << " ";
00477 os.width(2);
00478 os << (j+1) << ":";
00479 os.width(8);
00480 os.fill('0');
00481 os << hex << i[j+2] << dec;
00482 os.fill(' ');
00483 }
00484 os << "\n\n";
00485 }
00486
00487 void FICData::prettyDump62(ostream & os) const
00488 {
00489 short j,k;
00490 unsigned short btmp;
00491 unsigned long aword;
00492 short rotate;
00493 char ochar;
00494 short almType;
00495
00496 os << "**************************************";
00497 os << "**************************************\n";
00498 os << " Block Number : ";
00499 os.width(3);
00500 os << blockNum << "\n";
00501 os << "Almanac(Engineering Units)\n";
00502 os << "\n";
00503 os << "SV ID : ";
00504 os.setf(ios::right, ios::adjustfield);
00505 os.width(2);
00506 os << i[3] << "\n";
00507 timeDisplay( os, "Transmit time", i[5], i[1], 1 );
00508 os << "Reference Wk ";
00509 os.width(4);
00510 os << i[0] << "\n";
00511 almType = (short) f[6];
00512 if (almType>0&&almType<33)
00513 {
00514
00515 timeDisplay( os, "Epoch time", (short) f[18], f[8], 0);
00516 os << "Health 0x";
00517 os.width(2);
00518 os.fill('0');
00519 os << hex << (short) f[11] << dec;
00520 os.fill(' ');
00521 os << "\n";
00522 os << "\n";
00523 os << "CLOCK\n";
00524 os.setf(ios::scientific, ios::floatfield);
00525 os.setf(ios::right, ios::adjustfield);
00526 os.precision(8);
00527 os << " Bias: ";
00528 os.width(16);
00529 os << f[16] << " sec\n";
00530 os << " Drift: ";
00531 os.width(16);
00532 os << f[17] << " sec/sec\n";
00533
00534 os << "\nORBIT PARAMETERS\n";
00535 os << " Semi-major axis: ";
00536 os.width(16);
00537 os << f[12] << " m**.5\n";
00538 os << " Eccentricity: ";
00539 os.width(16);
00540 os << f[7] << "\n";
00541 os << " Arg of perigee: ";
00542 os.width(16);
00543 os << f[14] << " rad\n";
00544 os << " Mean anamoly of epoch: ";
00545 os.width(16);
00546 os << f[15] << " rad\n";
00547 os << " Right Ascension: ";
00548 os.width(16);
00549 os << f[13] << " rad ";
00550 os.width(16);
00551 os << f[10] << " rad/sec\n";
00552 os << " Inclination: ";
00553 os.width(16);
00554 os << f[9] << " rad (from 54 deg)\n";
00555
00556 os.setf(ios::fixed, ios::floatfield);
00557 os.precision(0);
00558 }
00559 else if (almType>=57 && almType<=62 )
00560 {
00561
00562 os << "\n";
00563 os << "Hexadecimal dump of non-parity bits of words 3-10\n";
00564
00565 os.setf(ios::uppercase);
00566 for (k=2;k<10;k++)
00567 {
00568 if (k==2 || k==6 ) os << "\n";
00569 os << " ";
00570 os.width(2);
00571 os << (k+1) << ":";
00572 os.width(6);
00573 os.fill('0');
00574 aword = (unsigned long) f[k+5];
00575
00576
00577 os << hex << aword << dec;
00578 os.fill(' ');
00579 }
00580
00581 }
00582 else switch (almType)
00583 {
00584 case 51:
00585 os << "\n";
00586 os << "Page Type: SV Health Information\n";
00587 os << "\nAlmanac reference week (8 bit): ";
00588 os.precision(0);
00589 os << f[7] << "\n";
00590 os << "SV Health Information for PRN 1-24\n\n";
00591 os << " --Health--- --Health--- --Health--- --Health---\n";
00592 os << "PRN Hex Binary PRN Hex Binary PRN Hex Binary PRN Hex Binary\n";
00593 os.setf(ios::uppercase);
00594 for (k=1;k<=21;k+=4)
00595 {
00596 for (j=k;j<k+4;j++)
00597 {
00598 if (j!=k) os << " ";
00599 else os << " ";
00600 os.width(2);
00601 os.fill('0');
00602 os << j;
00603 os.fill(' ');
00604 os << " ";
00605 btmp = (unsigned short) f[j+7];
00606 btmp &= 0x003F;
00607 os.fill('0');
00608 os.width(2);
00609 os << hex << btmp << dec;
00610 os.fill(' ');
00611 os << " ";
00612 btmp = (unsigned short) f[j+7];
00613 for (rotate=0;rotate<6;rotate++)
00614 {
00615 if (btmp & 0x20) os << "1";
00616 else os << "0";
00617 btmp <<= 1;
00618 }
00619 }
00620 os << "\n";
00621 }
00622 break;
00623
00624 case 52:
00625 case 53:
00626 case 54:
00627 os << "\n";
00628 if (almType==52) os << "Page Type: Subframe 4 Page 13, Reserved Bits\n";
00629 if (almType==53) os << "Page Type: Subframe 4 Page 14, Reserved Bits\n";
00630 if (almType==54) os << "Page Type: Subframe 4 Page 15, Reserved Bits\n";
00631
00632 os << "Hexadecimal dump of non-parity bits of words 3-10\n";
00633 os << " **This feature under construction.**\n";
00634 os << " **This page is decoded incorrectly in the ";
00635 os << "subframe converter.**\n";
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651 break;
00652
00653 case 55:
00654 os << "\n";
00655 os << "Page Type: Subframe 4 Page 17, Special Message\n";
00656
00657
00658 os << "\n Message : \"";
00659 for (k=1;k<23;k++)
00660 {
00661 aword = (unsigned long) f[k+6];
00662 ochar = (char) aword;
00663 os << ochar;
00664 }
00665 os << "\"\n";
00666 break;
00667
00668 case 56:
00669 os << "\n";
00670 os << "Page Type: UTC and Ionospheric Information\n";
00671 os.setf(ios::scientific, ios::floatfield);
00672 os.setf(ios::right, ios::adjustfield);
00673 os.precision(8);
00674 os << "\n";
00675 os << "IONOSPHERIC PARAMETERS \n";
00676 os << " Alpha 1 : ";
00677 os.width(16);
00678 os << f[7] << " sec Beta 1 : ";
00679 os.width(16);
00680 os << f[11] << "sec\n";
00681 os << " Alpha 2 : ";
00682 os.width(16);
00683 os << f[8] << " sec/rad Beta 2 : ";
00684 os.width(16);
00685 os << f[12] << " sec/rad\n";
00686 os << " Alpha 3 : ";
00687 os.width(16);
00688 os << f[9] << " sec/rad**2 Beta 3 : ";
00689 os.width(16);
00690 os << f[13] << " sec/rad**2\n";
00691 os << " Alpha 4 : ";
00692 os.width(16);
00693 os << f[10] << " sec/rad**3 Beta 4 : ";
00694 os.width(16);
00695 os << f[14] << " sec/rad**3\n\n";
00696
00697 os << "GPS-UTC CORRECTION PARAMETERS\n";
00698 os << " Bias (A0) ";
00699 os.width(16);
00700 os << f[15] << " sec\n";
00701 os << " Drift (A1) ";
00702 os.width(16);
00703 os << f[16] << " sec/sec\n";
00704 os.setf(ios::fixed, ios::floatfield);
00705 os.precision(0);
00706 os << " Reference time (tot) ";
00707 os.width(16);
00708 os << f[17] << " sec of week\n";
00709 os << " Current leap second (dtls) ";
00710 os.width(16);
00711 os << f[19] << " sec\n";
00712 os << " Ref week of current leap second (WNt) ";
00713 os.width(16);
00714 os << f[18] << " weeks\n";
00715 os << " Week of next/last change (WNLSF) ";
00716 os.width(16);
00717 os << f[20] << " weeks\n";
00718 os << " Day number of future change (DN) ";
00719 os.width(16);
00720 os << f[21] << " day of week\n";
00721 os << " Scheduled future time increment due to\n";
00722 os << " lead seconds (dtLSF) ";
00723 os.width(16);
00724 os << f[22] << " sec\n";
00725 break;
00726
00727 case 63:
00728 os << "\n";
00729 os << "Page Type: SV Health and Configuration Information\n\n";
00730 os.precision(0);
00731 os << "SV Health Information for PRN 25-32\n";
00732 os << "-----Health----- -----Health----- -----Health----- -----Health-----\n";
00733 os << "PRN Hex Binary PRN Hex Binary PRN Hex Binary PRN Hex Binary\n";
00734 for (k=25;k<=29;k+=4)
00735 {
00736 for (j=k;j<k+4;j++)
00737 {
00738 if (j!=k) os << " ";
00739 else os << " ";
00740 os.width(2);
00741 os.fill('0');
00742 os << j;
00743 os.fill(' ');
00744 os << " ";
00745 btmp = (unsigned short) f[j+14];
00746 btmp &= 0x003F;
00747 os.fill('0');
00748 os.width(2);
00749 os << hex << btmp << dec;
00750 os.fill(' ');
00751 os << " ";
00752 btmp = (unsigned short) f[j+14];
00753 for (rotate=0;rotate<6;rotate++)
00754 {
00755 if (btmp & 0x20) os << "1";
00756 else os << "0";
00757 btmp <<= 1;
00758 }
00759 }
00760 os << "\n";
00761 }
00762
00763 os << "\nSV Configuration for PRN 1-32 (bit coded)\n";
00764 os << "-----Config----- -----Config----- -----Config----- -----Config-----\n";
00765 os << "PRN Binary PRN Binary PRN Binary PRN Binary\n";
00766 os.fill('0');
00767 for (k=1;k<32;k+=4)
00768 {
00769 for (j=k;j<(k+4);j++)
00770 {
00771 if (j==k) os << " ";
00772 else os << " ";
00773 os.width(2);
00774 os << j << " ";
00775 btmp = (unsigned short) f[j+6];
00776 for (rotate=0;rotate<4;rotate++)
00777 {
00778 if (btmp & 0x08) os << "1";
00779 else os << "0";
00780 btmp <<= 1;
00781 }
00782 }
00783 os << "\n";
00784 }
00785 os.fill(' ');
00786 break;
00787
00788 default:
00789 break;
00790 }
00791 os << "\n\n";
00792 }
00793
00794 void FICData::prettyDump162(ostream & os) const
00795 {
00796 os << "**************************************";
00797 os << "**************************************\n";
00798 os << " Block Number : ";
00799 os.width(3);
00800 os << blockNum << "\n";
00801 os << "As Broadcast Almanac\n";
00802 os << "\n";
00803 os << "SV ID : ";
00804 os.width(2);
00805 os << i[0] << "\n";
00806 timeDisplay( os, "Transmit time",
00807 i[14],
00808 ((i[2] & 0x3FFFFFFFL) >> 13) * 6,
00809 1 );
00810
00811
00812 os << "Reference Wk ";
00813 os.width(4);
00814 os << i[13];
00815 os << "\n";
00816
00817 os.setf(ios::uppercase);
00818 os << "\n";
00819 os << "Hexadecimal dump of words in subframe";
00820 short j;
00821 for (j=0;j<10;j++)
00822 {
00823 if (j==0 || j ==5 ) os << "\n";
00824 os << " ";
00825 os.width(2);
00826 os << (j+1) << ":";
00827 os.width(8);
00828 os.fill('0');
00829 os << hex << i[j+1] << dec;
00830 os.fill(' ');
00831 }
00832 os << "\n\n";
00833 }
00834
00835
00836
00837 void FICData::shortcut(ostream & os, const double HOW ) const
00838 {
00839 short DOW, hour, min, sec;
00840 long SOD, SOW;
00841 short SOH;
00842
00843 SOW = (long) HOW;
00844 DOW = (short) (SOW / DayTime::SEC_DAY);
00845 SOD = SOW - DOW * long(DayTime::SEC_DAY);
00846 hour = (short) (SOD/3600);
00847
00848 SOH = (short) (SOD - (hour*3600));
00849 min = SOH/60;
00850
00851 sec = SOH - min * 60;
00852 switch (DOW)
00853 {
00854 case 0: os << "Sun-0"; break;
00855 case 1: os << "Mon-1"; break;
00856 case 2: os << "Tue-2"; break;
00857 case 3: os << "Wed-3"; break;
00858 case 4: os << "Thu-4"; break;
00859 case 5: os << "Fri-5"; break;
00860 case 6: os << "Sat-6"; break;
00861 default: break;
00862 }
00863 os << ":";
00864 os.fill('0');
00865 os.width(2);
00866 os << hour << ":";
00867 os.width(2);
00868 os << min << ":";
00869 os.width(2);
00870 os << sec;
00871 }
00872
00873
00874
00875
00876
00877
00878
00879 void FICData::timeDisplay( ostream & os, const char * legend,
00880 const short week, const double SOW,
00881 const short headerFlag ) const
00882 {
00883 DayTime dt;
00884 short slen;
00885 short j;
00886
00887 if (headerFlag)
00888 os << " Week(10bt) SOW DOW UTD SOD MM/DD/YYYY HH:MM:SS\n";
00889 os << legend;
00890 slen = std::strlen(legend);
00891 for (j=1;j<(15-slen);j++) os << " ";
00892
00893
00894 dt.setGPSfullweek(week, SOW);
00895
00896 os.width(4);
00897 os << dt.GPSfullweek() << "(";
00898 os.width(4);
00899 os << dt.GPS10bitweek() << ") ";
00900 os.width(6);
00901 os << dt.GPSsecond() << " ";
00902
00903 switch (dt.GPSday())
00904 {
00905 case 0: os << "Sun-0"; break;
00906 case 1: os << "Mon-1"; break;
00907 case 2: os << "Tue-2"; break;
00908 case 3: os << "Wed-3"; break;
00909 case 4: os << "Thu-4"; break;
00910 case 5: os << "Fri-5"; break;
00911 case 6: os << "Sat-6"; break;
00912 default: break;
00913 }
00914 os << " ";
00915 os.fill('0');
00916 os.width(3);
00917 os << dt.DOYday() << " ";
00918 os.width(5);
00919 os << dt.DOYsecond() << " ";
00920 os.width(2);
00921 os << dt.month() << "/";
00922 os.width(2);
00923 os << dt.day() << "/";
00924 os.width(4);
00925 os << dt.year() << " ";
00926 os.width(2);
00927 os << dt.hour() << ":";
00928 os.width(2);
00929 os << dt.minute() << ":";
00930 os.width(2);
00931 os << static_cast<short>(dt.second()) << "\n";
00932 os.fill(' ');
00933 }
00934
00935 void FICData::reallyGetRecord(FFStream& ffs)
00936 throw(std::exception, gpstk::StringUtils::StringException,
00937 gpstk::FFStreamError)
00938 {
00939
00940 if (dynamic_cast<FICAStream*>(&ffs))
00941 {
00942 FICAStream& strm = dynamic_cast<FICAStream&>(ffs);
00943
00944
00945 if (!strm.headerRead)
00946 strm >> strm.header;
00947
00948 f.clear();
00949 i.clear();
00950 c.clear();
00951
00952 string line;
00953 strm.formattedGetLine(line, true);
00954 string blkHdr(line.substr(0,4));
00955
00956 if ( (blkHdr.size() != FICBlkHdrSize) ||
00957 (blkHdr != blockString))
00958 {
00959 FFStreamError e("Bad block header, record=" +
00960 asString(strm.recordNumber) +
00961 " location=" + asString(strm.tellg()));
00962 e.addText(string("blkHdr=[")+string(blkHdr)+string("]"));
00963 GPSTK_THROW(e);
00964 }
00965
00966 blockNum = asInt(line.substr(4, 6));
00967
00968
00969 long numf = asInt(line.substr(10,5)),
00970 numi = asInt(line.substr(15,5)),
00971 numc = asInt(line.substr(20,5));
00972
00973 long n;
00974
00975 for (n = 0; n < numf; n++)
00976 {
00977 if (n%4 == 0)
00978 strm.formattedGetLine(line);
00979 f.push_back(for2doub(line.substr((n%4)*20, 20)));
00980 }
00981
00982 for (n = 0; n < numi; n++)
00983 {
00984 if (n%6 == 0)
00985 strm.formattedGetLine(line);
00986 i.push_back(asInt(line.substr((n%6)*12, 12)));
00987 }
00988
00989 for (n = 0; n < numc; n++)
00990 {
00991 if (n%8 == 0)
00992 strm.formattedGetLine(line);
00993 c.push_back(line.substr((n%8)*8 + 7, 1)[0]);
00994 }
00995
00996 if (!isValid())
00997 {
00998 FFStreamError e("Read an invalid FIC block");
00999 GPSTK_THROW(e);
01000 }
01001 }
01002 else
01003 {
01004 if (dynamic_cast<FICStream*>(&ffs))
01005 {
01006 FICStream& strm = dynamic_cast<FICStream&>(ffs);
01007
01008
01009 if (!strm.headerRead)
01010 strm >> strm.header;
01011
01012 f.clear();
01013 i.clear();
01014 c.clear();
01015
01016 char blkHdr[FICBlkHdrSize + 1];
01017 unsigned location = strm.tellg();
01018
01019 strm.getData(blkHdr, FICBlkHdrSize);
01020 if ((string(blkHdr, FICBlkHdrSize) != blockString))
01021 {
01022 FFStreamError e("Bad block header, record="
01023 + asString(strm.recordNumber)
01024 + " location=" + asString(location));
01025 e.addText(string("blkHdr=[")+string(blkHdr)+string("]"));
01026 GPSTK_THROW(e);
01027 }
01028
01029 blockNum = intelToHost(strm.getData<int32_t>());
01030
01031
01032 int32_t numf = intelToHost(strm.getData<int32_t>());
01033 int32_t numi = intelToHost(strm.getData<int32_t>());
01034 int32_t numc = intelToHost(strm.getData<int32_t>());
01035
01036 long n;
01037
01038 for (n = 0; n < numf; n++)
01039 {
01040 double fl = intelToHost(strm.getData<double>());
01041 f.push_back(fl);
01042 }
01043
01044 for (n = 0; n < numi; n++)
01045 {
01046 long lg = intelToHost(strm.getData<int32_t>());
01047 i.push_back(lg);
01048 }
01049
01050 for (n = 0; n < numc; n++)
01051 {
01052 char ch = intelToHost(strm.getData<char>());
01053 c.push_back(ch);
01054 }
01055 }
01056
01057 else
01058 {
01059 FFStreamError e("FICData tried to read from a non-FIC file");
01060 GPSTK_THROW(e);
01061 }
01062 }
01063 if (!isValid())
01064 {
01065 FFStreamError e("Read an invalid FIC block");
01066 GPSTK_THROW(e);
01067 }
01068 }
01069
01070 FICData::operator EngEphemeris() const
01071 throw(WrongBlockNumber)
01072 {
01073 if(blockNum==9)
01074 {
01075 gpstk::EngEphemeris eph;
01076 unsigned tlm = (unsigned)f[0];
01077 eph.setSF1( ((tlm >> 8) & 0x3fff), (long)f[2], (short)f[3], (short)f[5],
01078 (short)f[6], (short)f[7], (short)f[8], (short)ldexp(f[9],-11),
01079 (short)f[10], f[11], f[12], f[13], f[14], f[15], (short)f[18],
01080 (short)f[19] );
01081 tlm = (unsigned)f[20];
01082 eph.setSF2( ((tlm >> 8) & 0x3fff),(long)f[22], (short)f[23],
01083 (short)ldexp(f[25],-11), f[26], f[27], f[28], f[29], f[30],
01084 f[31], f[32], f[33], (short)f[34] );
01085 tlm = (unsigned)f[40];
01086 eph.setSF3( ((tlm >> 8) & 0x3fff), (long)f[42], (short)f[43], f[45],
01087 f[46], f[47], f[48], f[49], f[50], f[51], f[53] );
01088 return eph;
01089 }
01090 else if(blockNum == 109)
01091 {
01092 gpstk::EngEphemeris eph;
01093
01094 long foo[30];
01095 int count = 0;
01096 for(int count = 2; count < i.size(); count++)
01097 {
01098 foo[count-2] = i[count];
01099 }
01100 eph.addSubframe(foo, i[0], i[1], 0);
01101 eph.addSubframe(foo+10, i[0], i[1], 0);
01102 eph.addSubframe(foo+20, i[0], i[1], 0);
01103 return eph;
01104 }
01105 else
01106 {
01107 WrongBlockNumber wbn( "Block number should be 9, was " +
01108 asString(blockNum) );
01109 GPSTK_THROW(wbn);
01110 }
01111 }
01112
01113
01114 FICData::operator AlmOrbit() const
01115 throw(WrongBlockNumber)
01116 {
01117 if(blockNum == 62)
01118 {
01119 AlmOrbit ao(i[3], f[7], f[9], f[10],
01120 f[12], f[13], f[14], f[15],
01121 f[16], f[17], long(f[8]), i[1],
01122 i[0], short(f[11]));
01123 return ao;
01124 }
01125 else
01126 {
01127 WrongBlockNumber wbn( "Block number should be 62, was " +
01128 asString(blockNum) );
01129 GPSTK_THROW(wbn);
01130 }
01131 }
01132
01133 std::string FICData::generateUniqueKey() const
01134 throw(WrongBlockNumber, WrongBlockFormat)
01135 {
01136 std::ostringstream out;
01137 DayTime transmitTime(0.L), howTime(0.L);
01138 WrongBlockNumber wbn( "Block number should be 9, 109, or 62, was "+
01139 asString(blockNum) );
01140
01141 switch (blockNum)
01142 {
01143 case 9:
01144
01145 out << "EE" << ' '
01146 << f[19] << ' '
01147 << f[5] << ' '
01148
01149
01150 << ldexp(f[9], -11) << ' '
01151
01152 << f[3] << ' '
01153 << f[23] << ' '
01154 << f[43];
01155 break;
01156
01157 case 109:
01158 out << "E" << ' '
01159 << i[1] << ' '
01160 << i[0] << ' '
01161 << (((i[4] & 0xC0)<<2) + ((i[9] & 0x3FC00000)>>22)) << ' '
01162
01163 << ((i[3] & 0x1800)>>11) << ' '
01164 << ((i[13] & 0x1800)>>11) << ' '
01165 << ((i[23] & 0x1800)>>11);
01166 break;
01167
01168 case 62:
01169 transmitTime.setGPSfullweek(i[5], (double)i[1]);
01170 howTime.setGPSfullweek(i[5], f[2]);
01171
01172
01173
01174
01175
01176 if ((i[3] >= 1) && (i[3] <= 32))
01177 {
01178 out << "A" << ' '
01179 << ((short)f[6]) << ' '
01180 << transmitTime.GPSday() << ' '
01181 << transmitTime.GPSfullweek() << ' '
01182 << ((long)f[8]) << ' '
01183 << howTime.DOYday() << ' '
01184 << howTime.DOYyear();
01185 }
01186 else
01187 {
01188 WrongBlockFormat wbf("Format " + asString(i[4]) +
01189 " (page ID " + asString(i[3]) +
01190 ") cannot be used to generate a key.");
01191 GPSTK_THROW(wbf);
01192 }
01193 break;
01194 default:
01195 GPSTK_THROW(wbn);
01196 }
01197
01198 return out.str();
01199
01200 }
01201
01202 bool FICData::operator==(const FICData& rhs)
01203 {
01204 return ( (blockNum == rhs.blockNum) &&
01205 (f == rhs.f) &&
01206 (i == rhs.i) &&
01207 (c == rhs.c) );
01208 }
01209
01210 string FICData::getElementLabel(char type, size_t indx) const
01211 {
01212 string label("Unknown.");
01213
01214
01215
01216
01217
01218
01219 static bool labelsDefined = false;
01220 static map<size_t, string> labels9, labels62i;
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230 static map<long, map<size_t, string> > labels62f;
01231
01232 if (!labelsDefined)
01233 {
01234 labels9[0]="TLM Word (Preamble)";
01235 labels9[1]="TLM Word (Message)";
01236 labels9[2]="HOW Word (Time)";
01237 labels9[3]="Synchronization/Momentum Flag for Block I or Anti-Spoof/\"Alert\" Flag for Block II ";
01238 labels9[4]="Sub-Frame ID";
01239 labels9[5]="Transmit Week Number";
01240 labels9[6]="C/A and/or P Flag, L2 Flag";
01241 labels9[7]="SV Accuracy";
01242 labels9[8]="SV Health";
01243 labels9[9]="Age of Data, Clock";
01244 labels9[10]="L2 P Data Flag";
01245 labels9[11]="Group Delay Differential";
01246 labels9[12]="Clock Epoch";
01247 labels9[13]="Clock Drift Rate";
01248 labels9[14]="Clock Drift";
01249 labels9[15]="Clock Bias";
01250 labels9[16]="(not used)";
01251 labels9[17]="(not used)";
01252 labels9[18]="Tracker";
01253 labels9[19]="SV PRN";
01254 labels9[20]="TLM Word (Preamble)";
01255 labels9[21]="TLM Word (Message)";
01256 labels9[22]="HOW Word (Time)";
01257 labels9[23]="Synchronization/Momentum Flag for Block I or Anti-Spoof/\"Alert\" Flag for Block II ";
01258 labels9[24]="Sub-Frame ID (2)";
01259 labels9[25]="Age of Data Ephemeris";
01260 labels9[26]="Radial Sine Correction (CRS)";
01261 labels9[27]="Correction to Mean Motion";
01262 labels9[28]="Mean Anomaly at Epoch";
01263 labels9[29]="In-Track Cosine Amplitude (CUC)";
01264 labels9[30]="Eccentricity";
01265 labels9[31]="In-track sine amplitude (CUS)";
01266 labels9[32]="Square root of semi-major axis";
01267 labels9[33]="Time of epoch";
01268 labels9[34]="Fit interval flag ";
01269 labels9[35]="(unused)";
01270 labels9[36]="(unused)";
01271 labels9[37]="(unused)";
01272 labels9[38]="(unused)";
01273 labels9[39]="(unused)";
01274 labels9[40]="TLM Word (Preamble)";
01275 labels9[41]="TLM Word (Message)";
01276 labels9[42]="HOW Word (Time)";
01277 labels9[43]="Synchronization/Momentum flag for Block I or Anti-Spoof/\"Alert\" flag for Block II";
01278 labels9[44]="Sub-Frame ID (3)";
01279 labels9[45]="Inclination cosine correction (CIC)";
01280 labels9[46]="Right ascension of ascending node";
01281 labels9[47]="Inclination sine correction (CIS)";
01282 labels9[48]="Inclination";
01283 labels9[49]="Radial cosine adjustment (CRC)";
01284 labels9[50]="Argument of perigee ";
01285 labels9[51]="Right ascension of ascending node time derivative";
01286 labels9[52]="Age of data (Ephemeris)";
01287 labels9[53]="Inclination time derivative";
01288 labels9[54]="(unused)";
01289 labels9[55]="(unused)";
01290 labels9[56]="(unused)";
01291 labels9[57]="(unused)";
01292 labels9[58]="(unused)";
01293 labels9[60]="(unused)";
01294
01295 labels62i[0]="Week of Toa";
01296 labels62i[1]="Time of Transmit";
01297 labels62i[2]="0";
01298 labels62i[3]="SV ID";
01299 labels62i[4]="Format number (ICD-200, Fig 20-1)";
01300 labels62i[5]="Transmit week number";
01301
01302 labels62f[4][0]=labels9[0];
01303 labels62f[4][1]=labels9[1];
01304 labels62f[4][2]=labels9[2];
01305 labels62f[4][3]=labels9[3];
01306 labels62f[4][4]=labels9[4];
01307 labels62f[4][5]="Data Flags";
01308 labels62f[4][6]="Page ID";
01309 labels62f[4][7]="Eccentricity";
01310 labels62f[4][8]="Time of Epoch (Toa)";
01311 labels62f[4][9]="Inclination offset from 54 deg.";
01312 labels62f[4][10]="Right Ascension rate";
01313 labels62f[4][11]="SV Health";
01314 labels62f[4][12]="Square root of semi-major axis";
01315 labels62f[4][13]="Right Ascension of ascending node";
01316 labels62f[4][14]="Argument of Perigee";
01317 labels62f[4][15]="Mean Anomaly";
01318 labels62f[4][16]="AF0 Clock Model Coefficient";
01319 labels62f[4][17]="AF1 Clock Model Coefficient";
01320 labels62f[4][18]="Week of Toa";
01321 labels62f[4][19]="SV PRN";
01322
01323
01324 for (long sheet=5; sheet <= 11; sheet++)
01325 for (size_t k=0; k<7; k++)
01326 labels62f[sheet][k]=labels62f[4][k];
01327
01328
01329 labels62f[5][7]="Almanac Reference Week Number";
01330
01331 long sat=1;
01332 for (size_t k=8; k<32; k++, sat++)
01333 labels62f[5][k]=string("6 bit health info for satellite ")+asString(sat);
01334
01335
01336 short word=3;
01337 for (size_t k=7; k<14; k++, word++)
01338 labels62f[6][k]=string("Reserved bits, word ")+asString(sat);
01339
01340
01341 labels62f[7] = labels62f[6];
01342
01343
01344 labels62f[8][7] = "Alpha 0";
01345 labels62f[8][8] = "Alpha 1";
01346 labels62f[8][9] = "Alpha 2";
01347 labels62f[8][10] = "Alpha 3";
01348 labels62f[8][11] = "Beta 0";
01349 labels62f[8][12] = "Beta 1";
01350 labels62f[8][13] = "Beta 2";
01351 labels62f[8][14] = "Beta 3";
01352 labels62f[8][15] = "Bias term of GPS-UTC (A0) difference polynomial";
01353 labels62f[8][16] = "Drift term of GPS-UTC (A1) difference polynomial";
01354 labels62f[8][17] = "Reference Time";
01355 labels62f[8][18] = "Reference week of current leap seconds";
01356 labels62f[8][19] = "Time increment due to leap seconds";
01357 labels62f[8][20] = "Week number last/next change";
01358 labels62f[8][21] = "Reference day number of future leap second";
01359 labels62f[8][22] = "Scheduled future time increments due to leap seconds";
01360
01361
01362 sat=1;
01363
01364 for (size_t k=7; k<39; k++, sat++)
01365 labels62f[9][k] = string("Anti-Spoofing/SV config for sat ")
01366 +asString(sat);
01367
01368 sat=25;
01369 for (size_t k=39; k<47; k++, sat++)
01370 labels62f[9][k] = string("6 bit health info for satellite ")+asString(sat);
01371
01372
01373
01374
01375
01376 labels62f[11] = labels62f[7];
01377
01378
01379 labelsDefined=true;
01380 }
01381
01382 if ((blockNum==9) && (type=='f'))
01383 return labels9[indx];
01384
01385 if ((blockNum==62) && (type=='i'))
01386 return labels62i[indx];
01387
01388 if ((blockNum==62) && (type=='f'))
01389 {
01390 long thisSheet = i[4];
01391
01392 if (thisSheet==10)
01393 return string("Either NMCT or special message");
01394
01395 string returnValue(labels62f[i[4]][indx]);
01396 if (!returnValue.empty())
01397 return returnValue;
01398 }
01399
01400 if ((blockNum==109) && (type=='i'))
01401 {
01402 int subframe = indx/10;
01403 int word = indx%10;
01404 return "Subframe "+asString(subframe) + ", word "+asString(word);
01405 }
01406
01407 if ((blockNum==162) && (type=='i'))
01408 {
01409 return "Subframe 4 or 5, word "+asString(indx);
01410 }
01411
01412 return label;
01413 }
01414 }
01415