MDPNavSubframe.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: MDPNavSubframe.cpp 1416 2008-10-15 02:31:52Z ocibu $"
00002 
00003 //============================================================================
00004 //
00005 //  This file is part of GPSTk, the GPS Toolkit.
00006 //
00007 //  The GPSTk is free software; you can redistribute it and/or modify
00008 //  it under the terms of the GNU Lesser General Public License as published
00009 //  by the Free Software Foundation; either version 2.1 of the License, or
00010 //  any later version.
00011 //
00012 //  The GPSTk is distributed in the hope that it will be useful,
00013 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 //  GNU Lesser General Public License for more details.
00016 //
00017 //  You should have received a copy of the GNU Lesser General Public
00018 //  License along with GPSTk; if not, write to the Free Software Foundation,
00019 //  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 //  
00021 //  Copyright 2004, The University of Texas at Austin
00022 //
00023 //============================================================================
00024 
00025 //============================================================================
00026 //
00027 //This software developed by Applied Research Laboratories at the University of
00028 //Texas at Austin, under contract to an agency or agencies within the U.S. 
00029 //Department of Defense. The U.S. Government retains all rights to use,
00030 //duplicate, distribute, disclose, or release this software. 
00031 //
00032 //Pursuant to DoD Directive 523024 
00033 //
00034 // DISTRIBUTION STATEMENT A: This software has been approved for public 
00035 //                           release, distribution is unlimited.
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    } // MDPNavSubframe::encode()
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    } // MDPNavSubframe::decode()
00110 
00111 
00112    //--------------------------------------------------------------------------
00113    // This cracks the sow from the handover word
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    // This cracks the subframe ID from the handover word
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    // This cracks the SV (page) ID from an almanac subframe
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       // First try the data assuming it is already upright
00178       parityGood = checkParity();
00179       if (parityGood)
00180          return;
00181 
00182       preamble = subframe[1] >> 22;
00183       if (preamble != 0x8b)
00184          return;
00185 
00186       // note that this routine assumes that D30 from the previous subframe
00187       // is zero. That is why we start with the second word in the array
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    // Print as a string of 1/0
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          // This seems to be required for pre-cooked bits but I don't
00249          // understand why...
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 } // namespace gpstk

Generated on Fri Feb 3 03:31:02 2012 for GPS ToolKit Software Library by  doxygen 1.3.9.1