00001 #pragma ident "$Id: MDPNavSubframe.cpp 1416 2008-10-15 02:31:52Z ocibu $"
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 #include <sstream>
00040 #include <BinUtils.hpp>
00041 #include <StringUtils.hpp>
00042 #include <gps_constants.hpp>
00043 #include <EngNav.hpp>
00044
00045 #include "miscenum.hpp"
00046 #include "MDPNavSubframe.hpp"
00047 #include "MDPStream.hpp"
00048
00049 using gpstk::StringUtils::asString;
00050 using gpstk::BinUtils::netToHost;
00051 using gpstk::BinUtils::hostToNet;
00052 using gpstk::BinUtils::encodeVar;
00053 using gpstk::BinUtils::decodeVar;
00054 using namespace std;
00055
00056 namespace gpstk
00057 {
00058
00059 MDPNavSubframe::MDPNavSubframe()
00060 throw()
00061 : subframe(11), cooked(false), inverted(false),
00062 neededCooking(false), parityGood(false)
00063 {
00064 id = myId;
00065 }
00066
00067
00068
00069 string MDPNavSubframe::encode() const
00070 throw()
00071 {
00072 string str;
00073 str += encodeVar<int8_t>(prn);
00074 str += encodeVar<int8_t>(carrier);
00075 str += encodeVar<int8_t>(range);
00076 str += encodeVar<int8_t>(nav);
00077
00078 for(int i=1; i<11; i++)
00079 str += encodeVar<uint32_t>(subframe[i]);
00080
00081 return str;
00082 }
00083
00084
00085
00086 void MDPNavSubframe::decode(string str)
00087 throw()
00088 {
00089 if (str.length() != myLength)
00090 return;
00091
00092 clearstate(lenbit);
00093
00094 prn = static_cast<int> (decodeVar<int8_t>(str));
00095 carrier = static_cast<CarrierCode>(decodeVar<int8_t>(str));
00096 range = static_cast<RangeCode> (decodeVar<int8_t>(str));
00097 nav = static_cast<NavCode> (decodeVar<int8_t>(str));
00098
00099 for (int i=1; i<11; i++)
00100 subframe[i] = decodeVar<uint32_t>(str);
00101
00102 if (prn > gpstk::MAX_PRN ||
00103 carrier >= ccMax ||
00104 range >= rcMax ||
00105 nav >= ncMax)
00106 return;
00107
00108 clearstate(fmtbit);
00109 }
00110
00111
00112
00113
00114 unsigned long MDPNavSubframe::getHOWTime() const throw()
00115 {
00116 uint32_t itemp,iret;
00117 itemp = subframe[2];
00118 itemp >>= 13;
00119 itemp &= 0x0001FFFFL;
00120 iret = itemp;
00121 iret = iret * 6;
00122
00123 return iret;
00124 }
00125
00126
00127
00128 unsigned int MDPNavSubframe::getSFID() const throw()
00129 {
00130 uint32_t itemp;
00131 short iret;
00132 itemp = subframe[2];
00133 itemp >>= 8;
00134 itemp &= 0x00000007L;
00135 iret = ( short) itemp;
00136 return iret;
00137 }
00138
00139
00140
00141 unsigned int MDPNavSubframe::getSVID() const throw()
00142 {
00143 if (getSFID() <4)
00144 return 0;
00145 else
00146 return (subframe[3] >> 22) & 0x3F;
00147 }
00148
00150 inline uint32_t getd30(uint32_t sfword)
00151 {
00152 return (sfword & 0x01);
00153 }
00154
00156 inline uint32_t getd29(uint32_t sfword)
00157 {
00158 return ((sfword & 0x02) >> 1);
00159 }
00160
00161
00162
00163 void MDPNavSubframe::cookSubframe() throw()
00164 {
00165 if (cooked)
00166 return;
00167
00168 cooked = true;
00169 uint32_t preamble = subframe[1] >> 22;
00170 if (preamble == 0x74)
00171 {
00172 neededCooking = inverted = true;
00173 for (int i = 1; i<=10; i++)
00174 subframe[i] = ~subframe[i] & 0x3fffffff;
00175 }
00176
00177
00178 parityGood = checkParity();
00179 if (parityGood)
00180 return;
00181
00182 preamble = subframe[1] >> 22;
00183 if (preamble != 0x8b)
00184 return;
00185
00186
00187
00188 for (int i=2; i<=10; i++)
00189 if (getd30(subframe[i-1]))
00190 {
00191 subframe[i] = subframe[i] ^ 0x3fffffc0;
00192 neededCooking = true;
00193 }
00194
00195 parityGood = checkParity();
00196 }
00197
00198
00199 string asBin(unsigned v, const unsigned n)
00200 {
00201 char *s = new char[n+1];
00202 for (int i=0; i<n; i++,v=v>>1)
00203 if (v&1)
00204 s[i] = '1';
00205 else
00206 s[i] = '0';
00207 s[n] = 0;
00208 string ns(s);
00209 delete[] s;
00210 return ns;
00211 }
00212
00213
00214 bool MDPNavSubframe::checkParity() const throw()
00215 {
00216 uint32_t preamble = subframe[1] >> 22;
00217 bool needsInversion = (preamble == 0x74);
00218 if (debugLevel>2)
00219 cout << "preamble:" << hex << preamble << dec
00220 << " cooked:" << cooked
00221 << " inverted:" << inverted
00222 << " needsInversion:" << needsInversion
00223 << " parities:"
00224 << endl;
00225
00226 bool goodParity = true;
00227 for (int i=1; i<=10; i++)
00228 {
00229 uint32_t prev = i==1 ? 0 : subframe[i-1];
00230 uint32_t curr = subframe[i];
00231 if (needsInversion)
00232 {
00233 if (i>1)
00234 prev = ~prev & 0x3fffffff;
00235 curr = ~curr & 0x3fffffff;
00236 }
00237 bool D30 = getd30(prev);
00238 unsigned receivedParity = curr & 0x3f;
00239 unsigned computedParity = EngNav::computeParity(curr, prev, cooked);
00240 if (debugLevel>3)
00241 cout << i << ":" << asBin(receivedParity,6)
00242 << "-" << asBin(computedParity,6) << " ";
00243 if (i==5 && debugLevel>3)
00244 cout << endl;
00245 if (receivedParity != computedParity)
00246 goodParity = false;
00247
00248
00249
00250 if (i == 1 && receivedParity == (~computedParity & 0x3f))
00251 goodParity = true;
00252 }
00253 if (debugLevel>3)
00254 cout << endl;
00255 return goodParity;
00256 }
00257
00258
00259
00260 void MDPNavSubframe::dump(ostream& out) const
00261 throw()
00262 {
00263 ostringstream oss;
00264 MDPHeader::dump(oss);
00265
00266 short page = getSFID() > 3 ? ((getHOWTime()-6) / 30) % 25 + 1 : 0;
00267
00268 oss << getName() << 0 <<":"
00269 << " PRN:" << prn
00270 << " CC:" << static_cast<int>(carrier)
00271 << " RC:" << static_cast<int>(range)
00272 << " NC:" << static_cast<int>(nav)
00273 << " SF:" << getSFID()
00274 << " PG:" << page
00275 << " I:" << inverted
00276 << " C:" << cooked
00277 << endl;
00278
00279 oss << setfill('0') << hex;
00280 for(int i = 1; i < subframe.size(); i++)
00281 {
00282 if ((i % 5) == 1)
00283 oss << getName() << i << ": ";
00284 oss << setw(8) << uppercase << subframe[i] << " ";
00285 if ((i % 5) == 0)
00286 oss << endl;
00287 }
00288 out << oss.str() << flush;
00289 }
00290
00291
00292
00293 void dump(std::ostream& out, const EphemerisPages& pages) throw()
00294 {
00295 for (int sf=1; sf<=3; sf++)
00296 {
00297 EphemerisPages::const_iterator i = pages.find(sf);
00298 if (i == pages.end())
00299 out << "Missing subframe " << sf << endl;
00300 else
00301 i->second.dump(out);
00302 }
00303 }
00304
00305
00306
00307 void dump(std::ostream& out, const AlmanacPages& pages) throw()
00308 {
00309 for (int p=1; p<=25; p++)
00310 {
00311 for (int sf=4; sf<=5; sf++)
00312 {
00313 AlmanacPages::const_iterator i = pages.find(SubframePage(sf, p));
00314 if (i == pages.end())
00315 out << "Missing subframe " << sf << " page " << p << endl;
00316 else
00317 i->second.dump(out);
00318
00319 }
00320 }
00321 }
00322 }