datasourcemodules/simulationpositioningmodule/src/EPos_TNmeaSentenceParser.cpp
changeset 0 9cfd9a3ee49c
equal deleted inserted replaced
-1:000000000000 0:9cfd9a3ee49c
       
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 
       
    17 
       
    18 // INCLUDE FILES
       
    19 #include "EPos_TNmeaSentenceParser.h"
       
    20 
       
    21 // CONSTANTS
       
    22 const signed int KCoordTokenS = 'S';
       
    23 const signed int KCoordTokenW = 'W';
       
    24 const signed int KCoordTokenDot = '.';
       
    25 
       
    26 const TReal32 KPosUERE = 10.0;
       
    27 
       
    28 const TNmeaSentence KPosUnknownSentence = 0;
       
    29 const TNmeaSentence KPosGGASentence = ('G'<<16) + ('G'<<8) + 'A';
       
    30 const TNmeaSentence KPosGSASentence = ('G'<<16) + ('S'<<8) + 'A';
       
    31 const TNmeaSentence KPosGSVSentence = ('G'<<16) + ('S'<<8) + 'V';
       
    32 const TNmeaSentence KPosRMCSentence = ('R'<<16) + ('M'<<8) + 'C';
       
    33 const TNmeaSentence KPosGLLSentence = ('G'<<16) + ('L'<<8) + 'L';
       
    34 
       
    35 // PGRMM - propriatary GARMIN sentence
       
    36 const TNmeaSentence KPosPGRMMSentence = ('G'<<24) + ('R'<<16) + ('M'<<8) + 'M';
       
    37 
       
    38 const TInt KPosMinSentenceLength = 7;
       
    39 const TUint KPosNMEASentenceStartToken = '$';
       
    40 const TInt KPosNofSatelliteSlotsInGSA = 12;
       
    41 
       
    42 const TReal32 KKnotsToMetrePerSecFactor = 1.852F / 3.6F;
       
    43 
       
    44 const TInt KMaxSatellitesPerSentence = 4;
       
    45 
       
    46 // ================= MEMBER FUNCTIONS =======================
       
    47 
       
    48 TNmeaSentenceParser::TNmeaSentenceParser() :
       
    49     iProgress(KPosNotParsed),
       
    50     iGSVIndex(1),
       
    51     iNumNmeaSentences(0)
       
    52     {
       
    53     }
       
    54 
       
    55 // ----------------------------------------------------------------------------
       
    56 // TNmeaSentenceParser::ParseSentenceL
       
    57 //
       
    58 // (other items were commented in a header).
       
    59 // ----------------------------------------------------------------------------
       
    60 //
       
    61 TInt TNmeaSentenceParser::ParseSentence(
       
    62     const TDesC8& aSentence,
       
    63     TPositionInfo& aPosInfo, TBool aConst)
       
    64     {
       
    65     if (aSentence.Length() == 0 ||
       
    66         !(aSentence[0] == KPosNMEASentenceStartToken) ||
       
    67         !VerifyChecksum(aSentence))
       
    68         {
       
    69         // Return KPosErrorNotValidNMEASentence since this
       
    70         // sentence won't be set as parsed
       
    71         // and therefore PSY should make another try to get a full fix.
       
    72         return KPosErrorNotValidNMEASentence;
       
    73         }
       
    74 
       
    75     TNmeaSentence type = SentenceType(aSentence);
       
    76 
       
    77     // Do not permit duplicate sentences of the types GLL, GGA, GSA and RMC
       
    78     if(!aConst)
       
    79     	{
       
    80 		if (type == KPosGLLSentence && (iProgress & KPosGLLParsed) ||
       
    81 			type == KPosGGASentence && (iProgress & KPosGGAParsed) ||
       
    82 			type == KPosGSASentence && (iProgress & KPosGSAParsed) ||
       
    83 			type == KPosRMCSentence && (iProgress & KPosRMCParsed))
       
    84 			{
       
    85 			return KPosErrorAlreadyParsed;
       
    86 			}
       
    87     	}
       
    88     
       
    89     if (aPosInfo.PositionClassType() & EPositionGenericInfoClass)
       
    90         {
       
    91         // Store raw NMEA sentence in position info
       
    92         HPositionGenericInfo& genInfo =
       
    93             static_cast<HPositionGenericInfo&> (aPosInfo);
       
    94         AddNmeaSentence(genInfo, aSentence);
       
    95         }
       
    96 
       
    97     switch (type)
       
    98         {
       
    99         case KPosGLLSentence:
       
   100             iProgress |= KPosGLLParsed;
       
   101             return KErrNone;
       
   102         case KPosGGASentence:
       
   103             return ParseGGA(aSentence, aPosInfo);
       
   104         case KPosRMCSentence:
       
   105             return ParseRMC(aSentence, aPosInfo);
       
   106         case KPosGSASentence:
       
   107             return ParseGSA(aSentence, aPosInfo);
       
   108         case KPosGSVSentence:
       
   109             return ParseGSV(aSentence, aPosInfo, aConst);
       
   110         case KPosPGRMMSentence:
       
   111             return ParsePGRMM(aSentence, aPosInfo);
       
   112         default:
       
   113             return KErrNone;
       
   114         }
       
   115     }
       
   116 
       
   117 // ----------------------------------------------------------------------------
       
   118 // TNmeaSentenceParser::Progress
       
   119 //
       
   120 // (other items were commented in a header).
       
   121 // ----------------------------------------------------------------------------
       
   122 //
       
   123 TInt TNmeaSentenceParser::Progress()
       
   124     {
       
   125     return iProgress;
       
   126     }
       
   127 
       
   128 // ----------------------------------------------------------------------------
       
   129 // TNmeaSentenceParser::Reset
       
   130 //
       
   131 // (other items were commented in a header).
       
   132 // ----------------------------------------------------------------------------
       
   133 //
       
   134 void TNmeaSentenceParser::Reset()
       
   135     {
       
   136     iProgress = KPosNotParsed;
       
   137     iGSVIndex = 1;
       
   138     iNumNmeaSentences = 0;
       
   139     }
       
   140 
       
   141 // ----------------------------------------------------------------------------
       
   142 // TNmeaSentenceParser::SentenceType
       
   143 //
       
   144 // (other items were commented in a header).
       
   145 // ----------------------------------------------------------------------------
       
   146 //
       
   147 TNmeaSentence TNmeaSentenceParser::SentenceType(const TDesC8& aSentence)
       
   148     {
       
   149     if (aSentence.Length() <= KPosMinSentenceLength)
       
   150         {
       
   151         return KPosUnknownSentence;
       
   152         }
       
   153 
       
   154     TInt type = (aSentence[3]<<16) + (aSentence[4]<<8) + aSentence[5];
       
   155 
       
   156     if (aSentence[1] == 'P')
       
   157         {
       
   158         type += (aSentence[2]<<24);
       
   159         }
       
   160 
       
   161     return type;
       
   162     }
       
   163 
       
   164 // ----------------------------------------------------------------------------
       
   165 // TNmeaSentenceParser::ParseGGA
       
   166 //
       
   167 // (other items were commented in a header).
       
   168 // ----------------------------------------------------------------------------
       
   169 //
       
   170 TInt TNmeaSentenceParser::ParseGGA(
       
   171     const TDesC8& aSentence,
       
   172     TPositionInfo& aPositionInfo)
       
   173     {
       
   174     TDesTokeniser tokeniser(aSentence);
       
   175 
       
   176     tokeniser.SkipToken(2); // Initial token, timestamp
       
   177 
       
   178     TPtrC8 latitude = tokeniser.NextToken();
       
   179     TPtrC8 dLat = tokeniser.NextToken();
       
   180 
       
   181     TPtrC8 longitude = tokeniser.NextToken();
       
   182     TPtrC8 dLong = tokeniser.NextToken();
       
   183 
       
   184     TInt quality = DesToInt(tokeniser.NextToken());
       
   185 
       
   186     if (quality == 0)
       
   187         {
       
   188         // Return KPosErrorNotValidNMEASentence since this
       
   189         // sentence won't be set as parsed
       
   190         // and therefore PSY should make another try to get a full fix.
       
   191         return KPosErrorNotValidNMEASentence;
       
   192         }
       
   193 
       
   194     TRealX nan;
       
   195     nan.SetNaN();
       
   196 
       
   197     // Number of tracked satellites, Horizontal dilution
       
   198     tokeniser.SkipToken(2);
       
   199 
       
   200     TPtrC8 altitudeC = tokeniser.NextToken(); // // Mean-sea altitude
       
   201     TReal32 altitude = nan;
       
   202     if (altitudeC.Length() > 0)
       
   203         {
       
   204         altitude = DesToFloat(altitudeC);
       
   205         }
       
   206 
       
   207     TReal latCoord = nan;
       
   208     ToCoordinate(latitude, dLat, latCoord);
       
   209     TReal longCoord = nan;
       
   210     ToCoordinate(longitude, dLong, longCoord);
       
   211 
       
   212     tokeniser.SkipToken();  // Unit (meters)
       
   213 
       
   214     TPtrC8 gsValueC = tokeniser.NextToken(); // Geoidal Separation
       
   215     TReal32 gsValue = nan;
       
   216     if (gsValueC.Length() > 0)
       
   217         {
       
   218         gsValue = DesToFloat(gsValueC);
       
   219         }
       
   220 
       
   221     TReal32 wgs84alt = nan;
       
   222     if (!Math::IsNaN(TRealX(altitude)) && !Math::IsNaN(TRealX(gsValue)))
       
   223         {
       
   224         // Wgs84-altitude = Mean-sea level altitude + Geoidal separation
       
   225         wgs84alt = altitude + gsValue;
       
   226         }
       
   227     else
       
   228         {
       
   229         // If there is no altitude, there should not be a vertical accuracy.
       
   230         TPosition pos;
       
   231         aPositionInfo.GetPosition(pos);
       
   232         pos.SetVerticalAccuracy(nan);
       
   233         aPositionInfo.SetPosition(pos);
       
   234         }
       
   235 
       
   236     // Set position
       
   237     TPosition pos;
       
   238     aPositionInfo.GetPosition(pos);
       
   239     pos.SetCoordinate(latCoord, longCoord, wgs84alt);
       
   240     if (!Math::IsNaN(latCoord) || !Math::IsNaN(longCoord))
       
   241         {
       
   242         pos.SetCurrentTime();
       
   243         }
       
   244     aPositionInfo.SetPosition(pos);
       
   245 
       
   246     // Check if generic info class
       
   247     if (aPositionInfo.PositionClassType() & EPositionGenericInfoClass)
       
   248         {
       
   249         HPositionGenericInfo& genInfo =
       
   250             static_cast<HPositionGenericInfo&> (aPositionInfo);
       
   251         TInt err = KErrNone;
       
   252         if (genInfo.IsRequestedField(
       
   253                 EPositionFieldSatelliteGeoidalSeparation) &&
       
   254                 !Math::IsNaN(TRealX(gsValue)))
       
   255             {
       
   256             err = genInfo.SetValue(EPositionFieldSatelliteGeoidalSeparation,
       
   257                 gsValue);
       
   258             }
       
   259         if (genInfo.IsRequestedField(
       
   260                 EPositionFieldSatelliteSeaLevelAltitude) &&
       
   261                 !Math::IsNaN(TRealX(altitude)))
       
   262             {
       
   263             err = genInfo.SetValue(EPositionFieldSatelliteSeaLevelAltitude,
       
   264                 altitude);
       
   265             }
       
   266         if (err != KErrNone)
       
   267             {
       
   268             return err;
       
   269             }
       
   270         }
       
   271 
       
   272     iProgress |= KPosGGAParsed;
       
   273     return KErrNone;
       
   274     }
       
   275 
       
   276 // ----------------------------------------------------------------------------
       
   277 // TNmeaSentenceParser::ParseRMC
       
   278 //
       
   279 // (other items were commented in a header).
       
   280 // ----------------------------------------------------------------------------
       
   281 //
       
   282 TInt TNmeaSentenceParser::ParseRMC(
       
   283     const TDesC8& aSentence,
       
   284     TPositionInfo& aPositionInfo)
       
   285     {
       
   286     // Check if generic, course or satellite info class
       
   287     if (aPositionInfo.PositionClassType() & (EPositionGenericInfoClass |
       
   288             EPositionCourseInfoClass | EPositionSatelliteInfoClass))
       
   289         {
       
   290         TDesTokeniser tokeniser(aSentence);
       
   291 
       
   292         tokeniser.SkipToken(); // Initial token
       
   293 
       
   294         TReal timestamp = DesToReal(tokeniser.NextToken()); // Timestamp
       
   295         tokeniser.SkipToken(5); // status, latitude * 2, longitude * 2
       
   296 
       
   297         TRealX nan;
       
   298         nan.SetNaN();
       
   299 
       
   300         TPtrC8 speedC = tokeniser.NextToken(); // Speed
       
   301         TReal32 speed = nan;
       
   302         if (speedC.Length() > 0)
       
   303             {
       
   304             speed = DesToFloat(speedC);
       
   305             // Speed is in knots. Transform to metres/sec
       
   306             speed *= KKnotsToMetrePerSecFactor;
       
   307             }
       
   308 
       
   309         TPtrC8 trueCourseC = tokeniser.NextToken(); // True course
       
   310         TReal32 trueCourse = nan;
       
   311         if (trueCourseC.Length() > 0)
       
   312             {
       
   313             trueCourse = DesToFloat(trueCourseC);
       
   314             }
       
   315 
       
   316         TInt date = DesToInt(tokeniser.NextToken()); // Date
       
   317 
       
   318         TPtrC8 magVarC = tokeniser.NextToken(); // Magnetic variation
       
   319         TReal32 magVar = nan;
       
   320         if (magVarC.Length() > 0)
       
   321             {
       
   322             magVar = DesToFloat(magVarC);
       
   323             }
       
   324         TPtrC8 dirMagVar = tokeniser.NextToken(); // Magnetic direction
       
   325         TPtrC8 modeIndicator = tokeniser.NextToken('*'); // Mode indicator
       
   326 
       
   327         _LIT8(KDataNotValid, "N");
       
   328         if (modeIndicator.Compare(KDataNotValid) == 0)
       
   329             {
       
   330             return KPosErrorNotValidNMEASentence;
       
   331             }
       
   332 
       
   333         if (dirMagVar.Length() && dirMagVar[0] == 'E' && !Math::IsNaN(TRealX(magVar)))
       
   334             {
       
   335             magVar = -magVar;
       
   336             }
       
   337 
       
   338         TInt hours = static_cast<TInt> (timestamp / 10000);
       
   339         TInt minutes = (static_cast<TInt> (timestamp / 100)) % 100;
       
   340         TInt seconds = (static_cast<TInt> (timestamp)) % 100;
       
   341         TInt microSeconds =
       
   342             ((static_cast<TInt> (timestamp * 100)) % 100) * 10000;
       
   343 
       
   344         const TInt KInitialYear = 2000;
       
   345         TInt days = (date / 10000) % 100;
       
   346         TInt months = (date / 100) % 100;
       
   347         TInt years = date % 100 + KInitialYear;
       
   348 
       
   349         if (timestamp < 0 || hours > 23 || minutes > 59 || seconds > 59 ||
       
   350             date < 0 || days < 1 || days > 31 || months < 1 ||
       
   351             months > 12 || years > 2099)
       
   352             {
       
   353             return KErrCorrupt;
       
   354             }
       
   355 
       
   356         TDateTime time =  TDateTime
       
   357             (years, static_cast<TMonth> (months - 1), days, hours, minutes,
       
   358             seconds, microSeconds);
       
   359 
       
   360         // Check if generic info class
       
   361         if (aPositionInfo.PositionClassType() & EPositionGenericInfoClass)
       
   362             {
       
   363             HPositionGenericInfo& genInfo =
       
   364                 static_cast<HPositionGenericInfo&> (aPositionInfo);
       
   365             TInt err = KErrNone;
       
   366             if (genInfo.IsRequestedField(EPositionFieldTrueCourse) &&
       
   367                 !Math::IsNaN(TRealX(trueCourse)))
       
   368                 {
       
   369                 err = genInfo.SetValue(EPositionFieldTrueCourse, trueCourse);
       
   370                 }
       
   371             if (genInfo.IsRequestedField(EPositionFieldHorizontalSpeed) &&
       
   372                 !Math::IsNaN(TRealX(speed)))
       
   373                 {
       
   374                 err = genInfo.SetValue(EPositionFieldHorizontalSpeed, speed);
       
   375                 }
       
   376             if (genInfo.IsRequestedField(EPositionFieldMagneticCourse) &&
       
   377                 !Math::IsNaN(TRealX(magVar)) &&
       
   378                 !Math::IsNaN(TRealX(trueCourse)))
       
   379                 {
       
   380                 err = genInfo.SetValue(EPositionFieldMagneticCourse,
       
   381                     magVar + trueCourse);
       
   382                 }
       
   383             if (genInfo.IsRequestedField(EPositionFieldSatelliteTime))
       
   384                 {
       
   385                 err = genInfo.SetValue(EPositionFieldSatelliteTime,
       
   386                     TTime(time));
       
   387                 }
       
   388             if (err != KErrNone)
       
   389                 {
       
   390                 return err;
       
   391                 }
       
   392             }
       
   393         // course info, sat info
       
   394         else
       
   395             {
       
   396             TPositionCourseInfo& courseInfo =
       
   397                 static_cast<TPositionCourseInfo&> (aPositionInfo);
       
   398             TCourse course;
       
   399             course.SetHeading(trueCourse);
       
   400             course.SetSpeed(speed);
       
   401             courseInfo.SetCourse(course);
       
   402             // satellite info
       
   403             if (aPositionInfo.PositionClassType() &
       
   404                 EPositionSatelliteInfoClass)
       
   405                 {
       
   406                 TPositionSatelliteInfo& satInfo =
       
   407                     static_cast<TPositionSatelliteInfo&> (aPositionInfo);
       
   408                 satInfo.SetSatelliteTime(TTime(time));
       
   409                 }
       
   410             }
       
   411         }
       
   412     iProgress |= KPosRMCParsed;
       
   413     return KErrNone;
       
   414     }
       
   415 
       
   416 // ----------------------------------------------------------------------------
       
   417 // TNmeaSentenceParser::ParseGSA
       
   418 //
       
   419 // (other items were commented in a header).
       
   420 // ----------------------------------------------------------------------------
       
   421 //
       
   422 TInt TNmeaSentenceParser::ParseGSA(
       
   423     const TDesC8& aSentence,
       
   424     TPositionInfo& aPositionInfo)
       
   425     {
       
   426     TDesTokeniser tokeniser(aSentence);
       
   427 
       
   428     tokeniser.SkipToken(2); // Initial token, Selection
       
   429 
       
   430     TInt twoDthreeD = DesToInt(tokeniser.NextToken());
       
   431     if (twoDthreeD == 1)
       
   432         {
       
   433         // Return KPosErrorNotValidNMEASentence since this
       
   434         // sentence won't be set as parsed
       
   435         // and therefore PSY should make another try to get a full fix.
       
   436         return KPosErrorNotValidNMEASentence;
       
   437         }
       
   438 
       
   439     TInt8 numUsedSatellites = 0;
       
   440     for (TInt i = 0; i < KPosNofSatelliteSlotsInGSA; i++)
       
   441         {
       
   442         // Satelite Id nr used for fix
       
   443         TPtrC8 satIdNrC = tokeniser.NextToken();
       
   444         if (satIdNrC.Length() > 0)
       
   445             {
       
   446             // Check if satellite info class
       
   447             if (aPositionInfo.PositionClassType() &
       
   448                 EPositionSatelliteInfoClass)
       
   449                 {
       
   450                 TPositionSatelliteInfo& satInfo =
       
   451                     static_cast<TPositionSatelliteInfo&> (aPositionInfo);
       
   452 
       
   453                 TSatelliteData satData;
       
   454                 TInt satIndex = 0;
       
   455                 TInt satId = DesToInt(satIdNrC);
       
   456                 TInt err = GetSatelliteListIndex(satInfo, satId, satIndex);
       
   457                 if (err == KErrNotFound)
       
   458                     {
       
   459                     satData.SetSatelliteId(satId);
       
   460                     satData.SetIsUsed(ETrue);
       
   461                     err = satInfo.AppendSatelliteData(satData);
       
   462                     if (err != KErrNone)
       
   463                         {
       
   464                         return err;
       
   465                         }
       
   466                     }
       
   467                 else // Satellite already exists
       
   468                     {
       
   469                     satInfo.GetSatelliteData(satIndex, satData);
       
   470                     satData.SetIsUsed(ETrue);
       
   471                     err = UpdateSatDataInList(satInfo, satData, satIndex);
       
   472                     if (err != KErrNone)
       
   473                         {
       
   474                         return err;
       
   475                         }
       
   476                     }
       
   477                 }
       
   478             numUsedSatellites++;
       
   479             }
       
   480         }
       
   481 
       
   482     TRealX nan;
       
   483     nan.SetNaN();
       
   484     TPtrC8 pdopC = tokeniser.NextToken(); // PDop
       
   485     TReal32 pdop = nan;
       
   486     TPtrC8 hdopC = tokeniser.NextToken(); // HDop
       
   487     TReal32 hdop = nan;
       
   488     TPtrC8 vdopC = tokeniser.NextToken('*'); // VDop
       
   489     TReal32 vdop = nan;
       
   490 
       
   491     if (pdopC.Length() > 0)
       
   492         {
       
   493         pdop = DesToFloat(pdopC);
       
   494         }
       
   495 
       
   496     if (hdopC.Length() > 0)
       
   497         {
       
   498         hdop = DesToFloat(hdopC);
       
   499         // Set basic info
       
   500         TPosition pos;
       
   501         aPositionInfo.GetPosition(pos);
       
   502         pos.SetHorizontalAccuracy(KPosUERE * hdop);
       
   503 
       
   504         // Set vertical accuracy, but only if we have altitude, or if we may get
       
   505         // altitude in later NMEA sentences.
       
   506         if (twoDthreeD == 3 &&
       
   507             !((iProgress & KPosGGAParsed) &&
       
   508             Math::IsNaN(TRealX(pos.Altitude()))))
       
   509             {
       
   510             pos.SetVerticalAccuracy(1.5f * KPosUERE * hdop);
       
   511             }
       
   512         aPositionInfo.SetPosition(pos);
       
   513         }
       
   514 
       
   515     if (vdopC.Length() > 0)
       
   516         {
       
   517         vdop = DesToFloat(vdopC);
       
   518         }
       
   519 
       
   520     // Check if generic info class
       
   521     if (aPositionInfo.PositionClassType() & EPositionGenericInfoClass)
       
   522         {
       
   523         HPositionGenericInfo& genInfo =
       
   524                     static_cast<HPositionGenericInfo&> (aPositionInfo);
       
   525         TInt err = KErrNone;
       
   526 
       
   527         if (TRealX(pdop).IsNaN() &&
       
   528             !TRealX(vdop).IsNaN() &&
       
   529             !TRealX(hdop).IsNaN())
       
   530             {
       
   531             TReal trg(pdop);
       
   532             err = Math::Sqrt(trg, TReal(hdop * hdop + vdop * vdop));
       
   533             pdop = TReal32(trg);
       
   534             }
       
   535 
       
   536         if (genInfo.IsRequestedField(EPositionFieldSatelliteHorizontalDoP) &&
       
   537             !Math::IsNaN(TRealX(hdop)))
       
   538             {
       
   539             err = genInfo.SetValue(EPositionFieldSatelliteHorizontalDoP, hdop);
       
   540             }
       
   541         if (genInfo.IsRequestedField(EPositionFieldSatelliteVerticalDoP) &&
       
   542             !Math::IsNaN(TRealX(vdop)))
       
   543             {
       
   544             err = genInfo.SetValue(EPositionFieldSatelliteVerticalDoP, vdop);
       
   545             }
       
   546         if (genInfo.IsRequestedField(EPositionFieldSatellitePositionDoP) &&
       
   547             !Math::IsNaN(TRealX(pdop)))
       
   548             {
       
   549             err = genInfo.SetValue(EPositionFieldSatellitePositionDoP, pdop);
       
   550             }
       
   551         if (genInfo.IsRequestedField(EPositionFieldSatelliteNumUsed))
       
   552             {
       
   553             err = genInfo.SetValue(EPositionFieldSatelliteNumUsed,
       
   554                 numUsedSatellites);
       
   555             }
       
   556         if (err != KErrNone)
       
   557             {
       
   558             return err;
       
   559             }
       
   560         }
       
   561     // satellite info
       
   562     else if (aPositionInfo.PositionClassType() & EPositionSatelliteInfoClass)
       
   563         {
       
   564         TPositionSatelliteInfo& satInfo =
       
   565                 static_cast<TPositionSatelliteInfo&> (aPositionInfo);
       
   566         satInfo.SetHorizontalDoP(hdop);
       
   567         satInfo.SetVerticalDoP(vdop);
       
   568         }
       
   569 
       
   570     iProgress |= KPosGSAParsed;
       
   571     return KErrNone;
       
   572     }
       
   573 
       
   574 // ----------------------------------------------------------------------------
       
   575 // TNmeaSentenceParser::ParseGSV
       
   576 //
       
   577 // Must be called in sequence for each GSV sentence
       
   578 // otherwise an error code will be returned.
       
   579 // (other items were commented in a header).
       
   580 // ----------------------------------------------------------------------------
       
   581 //
       
   582 TInt TNmeaSentenceParser::ParseGSV(
       
   583     const TDesC8& aSentence,
       
   584     TPositionInfo& aPositionInfo,
       
   585     TBool aConst)
       
   586     {
       
   587     TDesTokeniser tokeniser(aSentence);
       
   588 
       
   589     tokeniser.SkipToken(2); // Initial token, Number of sentences
       
   590 
       
   591     TInt sentenceIndex = DesToInt(tokeniser.NextToken()); // Message number
       
   592 
       
   593     // OK to try to parse a sentence with the wrong index, but progress
       
   594     // will not be updated.
       
   595     //
       
   596     // Because iGSVIndex is incremented each time function is called with aConst = EFalse
       
   597     // then to get same result like for previous read we have to temporary decrement
       
   598     // this value. Then if aConst is ETrue we are decrementing iGSVIndex
       
   599     TInt tempGSVIndex = iGSVIndex;
       
   600     if(aConst)
       
   601     	{
       
   602     	tempGSVIndex--;
       
   603     	}
       
   604     if (sentenceIndex != tempGSVIndex)
       
   605         {
       
   606         iGSVIndex = 1;
       
   607         return KErrNone;
       
   608         }
       
   609     if(!aConst)
       
   610     	{
       
   611     	iGSVIndex++;
       
   612     	}
       
   613 
       
   614     // Number of satellites in view
       
   615     TInt8 satInView = static_cast<TInt8> (DesToInt(tokeniser.NextToken()));
       
   616 
       
   617     // Check if generic info class
       
   618     if (aPositionInfo.PositionClassType() & EPositionGenericInfoClass)
       
   619         {
       
   620         HPositionGenericInfo& genInfo =
       
   621                     static_cast<HPositionGenericInfo&> (aPositionInfo);
       
   622         TInt err = KErrNone;
       
   623         if (genInfo.IsRequestedField(EPositionFieldSatelliteNumInView))
       
   624             {
       
   625             err = genInfo.SetValue(EPositionFieldSatelliteNumInView,
       
   626                 satInView);
       
   627             if (err != KErrNone)
       
   628                 {
       
   629                 return err;
       
   630                 }
       
   631             }
       
   632         }
       
   633     // satellite info
       
   634     else if (aPositionInfo.PositionClassType() & EPositionSatelliteInfoClass)
       
   635         {
       
   636         TPositionSatelliteInfo& satInfo =
       
   637                 static_cast<TPositionSatelliteInfo&> (aPositionInfo);
       
   638 
       
   639         for (TInt n = 0; n < KMaxSatellitesPerSentence; n++)
       
   640             {
       
   641             TPtrC8 prnPtrC = tokeniser.NextToken(); // PRN
       
   642             TPtrC8 elevationPtrC = tokeniser.NextToken(); // Elevation
       
   643             TPtrC8 azimuthPtrC = tokeniser.NextToken(); // Azimuth
       
   644 
       
   645             if (prnPtrC.Length() > 0)
       
   646                 {
       
   647                 TPtrC8 signalStrengtPtrC;
       
   648                 // Last satellite in sentence
       
   649                 if (n == (KMaxSatellitesPerSentence - 1))
       
   650                     {
       
   651                     signalStrengtPtrC.Set(tokeniser.NextToken('*')); // SNR
       
   652                     }
       
   653                 else
       
   654                     {
       
   655                     signalStrengtPtrC.Set(tokeniser.NextToken()); // SNR
       
   656                     }
       
   657 
       
   658                 TSatelliteData satSata;
       
   659                 TInt satIndex;
       
   660                 TInt satId = DesToInt(prnPtrC);
       
   661                 TInt err = GetSatelliteListIndex(satInfo, satId, satIndex);
       
   662                 if (err == KErrNotFound)
       
   663                     {
       
   664                     satSata.SetSatelliteId(satId);
       
   665                     if (elevationPtrC.Length() > 0)
       
   666                         {
       
   667                         satSata.SetElevation(DesToFloat(elevationPtrC));
       
   668                         }
       
   669                     if (azimuthPtrC.Length() > 0)
       
   670                         {
       
   671                         satSata.SetAzimuth(DesToFloat(azimuthPtrC));
       
   672                         }
       
   673                     if (signalStrengtPtrC.Length() > 0)
       
   674                         {
       
   675                          satSata.SetSignalStrength(DesToInt(signalStrengtPtrC));
       
   676                         }
       
   677                     err = satInfo.AppendSatelliteData(satSata);
       
   678                     if (err != KErrNone)
       
   679                         {
       
   680                         return err;
       
   681                         }
       
   682                     }
       
   683                 else // Satellite already exists
       
   684                     {
       
   685                     satInfo.GetSatelliteData(satIndex, satSata);
       
   686                     satSata.SetSatelliteId(DesToInt(prnPtrC));
       
   687                     if (elevationPtrC.Length() > 0)
       
   688                         {
       
   689                         satSata.SetElevation(DesToFloat(elevationPtrC));
       
   690                         }
       
   691                     if (azimuthPtrC.Length() > 0)
       
   692                         {
       
   693                         satSata.SetAzimuth(DesToFloat(azimuthPtrC));
       
   694                         }
       
   695                     if (signalStrengtPtrC.Length() > 0)
       
   696                         {
       
   697                         satSata.SetSignalStrength(DesToInt(signalStrengtPtrC));
       
   698                         }
       
   699                     err = UpdateSatDataInList(satInfo, satSata, satIndex);
       
   700                     if (err != KErrNone)
       
   701                         {
       
   702                         return err;
       
   703                         }
       
   704                     }
       
   705                 }
       
   706             }
       
   707         }
       
   708 
       
   709     return KErrNone;
       
   710     }
       
   711 
       
   712 // ----------------------------------------------------------------------------
       
   713 // TNmeaSentenceParser::ParsePGRMM
       
   714 //
       
   715 // (other items were commented in a header).
       
   716 // ----------------------------------------------------------------------------
       
   717 //
       
   718 TInt TNmeaSentenceParser::ParsePGRMM(
       
   719     const TDesC8& aSentence,
       
   720     TPositionInfo& /*aPositionInfo*/)
       
   721     {
       
   722     _LIT8(KWgs84, "WGS 84");
       
   723     TDesTokeniser tokeniser(aSentence);
       
   724 
       
   725     tokeniser.SkipToken(); // initial token
       
   726 
       
   727     TPtrC8 datum = tokeniser.NextToken('*');
       
   728     if (datum.Compare(KWgs84) != 0)
       
   729         {
       
   730         return KErrNotSupported;
       
   731         }
       
   732 
       
   733     return KErrNone;
       
   734     }
       
   735 
       
   736 // ----------------------------------------------------------------------------
       
   737 // TNmeaSentenceParser::AddNmeaSentence
       
   738 //
       
   739 // (other items were commented in a header).
       
   740 // ----------------------------------------------------------------------------
       
   741 //
       
   742 TInt TNmeaSentenceParser::AddNmeaSentence(
       
   743     HPositionGenericInfo& aPositionGenericInfo,
       
   744     const TDesC8& aSentence, TBool aConst)
       
   745     {
       
   746     TInt err = KErrNone;
       
   747 
       
   748     // Check if NMEA data is requested
       
   749     if (aPositionGenericInfo.IsRequestedField(EPositionFieldNMEASentences))
       
   750         {
       
   751         TUint16 sentenceNumber =
       
   752             static_cast<TUint16> (EPositionFieldNMEASentencesStart +
       
   753             iNumNmeaSentences);
       
   754         err = aPositionGenericInfo.SetValue(sentenceNumber, aSentence);
       
   755         if(!aConst)
       
   756         	++iNumNmeaSentences;
       
   757         TUint8 sentences = static_cast<TUint8> (iNumNmeaSentences);
       
   758         err = aPositionGenericInfo.SetValue(EPositionFieldNMEASentences,
       
   759             sentences);
       
   760         }
       
   761     return err;
       
   762     }
       
   763 
       
   764 // ----------------------------------------------------------------------------
       
   765 // TNmeaSentenceParser::ToCoordinate
       
   766 //
       
   767 // (other items were commented in a header).
       
   768 // ----------------------------------------------------------------------------
       
   769 //
       
   770 void TNmeaSentenceParser::ToCoordinate(
       
   771     const TDesC8& aDes,
       
   772     const TDesC8& aDir,
       
   773     TReal& aCoordinate)
       
   774     {
       
   775     const TInt  KPosMinutesIntegerLength = 2;
       
   776     const TReal KPosMinutesPerDegree = 60.0;
       
   777 
       
   778     TInt point = aDes.Locate(KCoordTokenDot);
       
   779 
       
   780     if (point >= KPosMinutesIntegerLength)
       
   781         {
       
   782         TInt deg = DesToInt(aDes.Left(point - KPosMinutesIntegerLength));
       
   783         TReal min = DesToReal(aDes.Mid(point - KPosMinutesIntegerLength));
       
   784         aCoordinate = TReal(deg) + min / KPosMinutesPerDegree;
       
   785 
       
   786         if (aDir.Length() && (aDir[0] == KCoordTokenS || aDir[0] == KCoordTokenW))
       
   787             {
       
   788             aCoordinate = - aCoordinate;
       
   789             }
       
   790         }
       
   791     }
       
   792 
       
   793 // ----------------------------------------------------------------------------
       
   794 // TNmeaSentenceParser::DesToInt
       
   795 //
       
   796 // (other items were commented in a header).
       
   797 // ----------------------------------------------------------------------------
       
   798 //
       
   799 TInt TNmeaSentenceParser::DesToInt(const TPtrC8& aDes)
       
   800     {
       
   801     TLex8 lexer(aDes);
       
   802     TInt integer;
       
   803 
       
   804     lexer.Val(integer);
       
   805     return integer;
       
   806     }
       
   807 
       
   808 // ----------------------------------------------------------------------------
       
   809 // TNmeaSentenceParser::DesToFloat
       
   810 //
       
   811 // (other items were commented in a header).
       
   812 // ----------------------------------------------------------------------------
       
   813 //
       
   814 TReal32 TNmeaSentenceParser::DesToFloat(const TPtrC8& aDes)
       
   815     {
       
   816     TLex8 lexer(aDes);
       
   817     TReal32 floatNumber;
       
   818 
       
   819     lexer.Val(floatNumber, TChar(KCoordTokenDot));
       
   820     return floatNumber;
       
   821     }
       
   822 
       
   823 // ----------------------------------------------------------------------------
       
   824 // TNmeaSentenceParser::DesToReal
       
   825 //
       
   826 // (other items were commented in a header).
       
   827 // ----------------------------------------------------------------------------
       
   828 //
       
   829 TReal TNmeaSentenceParser::DesToReal(const TPtrC8& aDes)
       
   830     {
       
   831     TLex8 lexer(aDes);
       
   832     TReal realNumber;
       
   833 
       
   834     lexer.Val(realNumber, TChar('.'));
       
   835     return realNumber;
       
   836     }
       
   837 
       
   838 // ----------------------------------------------------------------------------
       
   839 // TNmeaSentenceParser::VerifyChecksum
       
   840 //
       
   841 // (other items were commented in a header).
       
   842 // ----------------------------------------------------------------------------
       
   843 //
       
   844 TBool TNmeaSentenceParser::VerifyChecksum(const TDesC8& aSentence)
       
   845     {
       
   846     TUint8 checksum = 0;
       
   847     TInt i;
       
   848     for (i = 1; i < aSentence.Length() && aSentence[i] != '*'; i++)
       
   849         {
       
   850         checksum ^= aSentence[i];
       
   851         }
       
   852 
       
   853     if (++i + 1 < aSentence.Length())
       
   854         {
       
   855         TUint8 sum = TUint8((CharToNibble(aSentence[i]) << 4) +
       
   856             CharToNibble(aSentence[i+1]));
       
   857         if (sum == checksum)
       
   858             {
       
   859             return ETrue;
       
   860             }
       
   861         }
       
   862 
       
   863     return EFalse;
       
   864     }
       
   865 
       
   866 // ----------------------------------------------------------------------------
       
   867 // TNmeaSentenceParser::CharToNibble
       
   868 //
       
   869 // (other items were commented in a header).
       
   870 // ----------------------------------------------------------------------------
       
   871 //
       
   872 TUint8 TNmeaSentenceParser::CharToNibble(const TUint8 aChar)
       
   873     {
       
   874     if (aChar <= '9')
       
   875         {
       
   876         return TUint8(aChar - '0');
       
   877         }
       
   878     else
       
   879         {
       
   880         return TUint8(aChar - 'A' + 10);
       
   881         }
       
   882     }
       
   883 
       
   884 // ----------------------------------------------------------------------------
       
   885 // TNmeaSentenceParser::GetSatelliteListIndex
       
   886 //
       
   887 // (other items were commented in a header).
       
   888 // ----------------------------------------------------------------------------
       
   889 //
       
   890 TInt TNmeaSentenceParser::GetSatelliteListIndex(
       
   891     const TPositionSatelliteInfo& aSatInfo,
       
   892     TInt aPrnNumber,
       
   893     TInt& aIndex)
       
   894     {
       
   895     TSatelliteData satData;
       
   896 
       
   897     for (TInt i = 0; i < aSatInfo.NumSatellitesInView(); i++)
       
   898         {
       
   899         aSatInfo.GetSatelliteData(i, satData);
       
   900         if (satData.SatelliteId() == aPrnNumber)
       
   901             {
       
   902             aIndex = i;
       
   903             return KErrNone;
       
   904             }
       
   905         }
       
   906     return KErrNotFound;
       
   907     }
       
   908 
       
   909 // ----------------------------------------------------------------------------
       
   910 // TNmeaSentenceParser::UpdateSatDataInList
       
   911 //
       
   912 // (other items were commented in a header).
       
   913 // ----------------------------------------------------------------------------
       
   914 //
       
   915 TInt TNmeaSentenceParser::UpdateSatDataInList(
       
   916     TPositionSatelliteInfo& aSatInfo,
       
   917     TSatelliteData aSatData,
       
   918     TInt aIndex)
       
   919     {
       
   920     TInt nrOfSat = aSatInfo.NumSatellitesInView();
       
   921     RArray<TSatelliteData> satList;
       
   922     TInt i;
       
   923     TInt err;
       
   924     for (i = 0; i < nrOfSat; i++)
       
   925         {
       
   926         TSatelliteData satData;
       
   927         aSatInfo.GetSatelliteData(i,satData);
       
   928         err = satList.Append(satData);
       
   929         if (err != KErrNone)
       
   930             {
       
   931             satList.Close();
       
   932             return err;
       
   933             }
       
   934         }
       
   935 
       
   936     if (aIndex < nrOfSat)
       
   937         {
       
   938         satList[aIndex] = aSatData;
       
   939         }
       
   940 
       
   941     // Re-create satellite list in SatelliteInfo
       
   942     aSatInfo.ClearSatellitesInView();
       
   943     for (i = 0; i < satList.Count(); i++)
       
   944         {
       
   945         err = aSatInfo.AppendSatelliteData(satList[i]);
       
   946         if (err != KErrNone)
       
   947             {
       
   948             satList.Close();
       
   949             return err;
       
   950             }
       
   951         }
       
   952     satList.Close();
       
   953     return KErrNone;
       
   954     }
       
   955 
       
   956 //  End of File