datasourcemodules/bluetoothgpspositioningmodule/btgpspsy/src/BTGPSFix.cpp
changeset 0 9cfd9a3ee49c
equal deleted inserted replaced
-1:000000000000 0:9cfd9a3ee49c
       
     1 // Copyright (c) 2004-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 // INCLUDE FILES
       
    15 //
       
    16 
       
    17 
       
    18 
       
    19 #include <e32std.h>
       
    20 #include <e32math.h>
       
    21 #include <lbspositioninfo.h> 
       
    22 #include <lbssatellite.h>            // TPositionSatelliteInfo
       
    23 #include "BTGPSLogging.h"
       
    24 #include "BTGPSRequestHandler.h"
       
    25 #include "BTGPSConstantsManager.h"
       
    26 #include "BTGPSFix.h"
       
    27 #include "BTGPSLogging.h"
       
    28 #include "BTGPSNmeaParser.h"
       
    29 #include "BTGPSNmeaBuffer.h"
       
    30 
       
    31 // EXTERNAL DATA STRUCTURES
       
    32 
       
    33 // EXTERNAL FUNCTION PROTOTYPES  
       
    34 
       
    35 // CONSTANTS
       
    36 
       
    37 //The knots to m/s conversion multiplier
       
    38 const TReal64 KKnotInMetersPerSecond = 0.5144;
       
    39 
       
    40 //Hardcoded accuracy
       
    41 const TReal32 KHorizontalAccuracy = 10.0;
       
    42 const TReal32 KVerticalAccuracy = 30.0;
       
    43 
       
    44 //Decimal seperator
       
    45 const TUint8 KDecimalSeperator = '.';
       
    46 
       
    47 // MACROS
       
    48 
       
    49 // LOCAL CONSTANTS AND MACROS
       
    50 
       
    51 // MODULE DATA STRUCTURES
       
    52 
       
    53 // LOCAL FUNCTION PROTOTYPES
       
    54 
       
    55 // FORWARD DECLARATIONS
       
    56 
       
    57 // ============================= LOCAL FUNCTIONS ===============================
       
    58 
       
    59 // ============================ MEMBER FUNCTIONS ===============================
       
    60 
       
    61 // -----------------------------------------------------------------------------
       
    62 // CBTGPSFix::CBTGPSFix
       
    63 // C++ default constructor can NOT contain any code, that
       
    64 // might leave.
       
    65 // -----------------------------------------------------------------------------
       
    66 CBTGPSFix::CBTGPSFix()
       
    67     {
       
    68     Reset();
       
    69     }
       
    70 
       
    71 // -----------------------------------------------------------------------------
       
    72 // CBTGPSFix::SetNmeaBuffer
       
    73 // Set NMEA Buffer
       
    74 // -----------------------------------------------------------------------------
       
    75 void CBTGPSFix::SetNmeaBuffer(CBTGPSNmeaBuffer* aNmeaBuffer)
       
    76     {
       
    77     iNmeaBuffer = aNmeaBuffer;
       
    78     }
       
    79 
       
    80 // -----------------------------------------------------------------------------
       
    81 // CBTGPSFix::Reset
       
    82 // Reset the fix parameters.
       
    83 // -----------------------------------------------------------------------------
       
    84 void CBTGPSFix::Reset()
       
    85     {
       
    86     TRACESTRING("CBTGPSFix::Reset")
       
    87     ResetFix();
       
    88     
       
    89     ResetGSVTime();
       
    90     
       
    91     iNumberOfSatellites = 0;
       
    92     iSatelliteArray.Reset();
       
    93     for(TInt i=0; i<KMaxGSVMessageNumber; i++)
       
    94         {
       
    95         iNMEAGSVCache[i].Zero();
       
    96         }
       
    97         
       
    98     //Reset NMEA Buffer
       
    99     if(iNmeaBuffer!=NULL)
       
   100         {
       
   101         iNmeaBuffer->ResetBuffer();
       
   102         }
       
   103     }
       
   104 
       
   105 // -----------------------------------------------------------------------------
       
   106 // CBTGPSFix::ResetFix
       
   107 // -----------------------------------------------------------------------------
       
   108 void CBTGPSFix::ResetFix()
       
   109     {
       
   110     TRACESTRING("CBTGPSFix::ResetFix start...")
       
   111     TRealX nan;
       
   112     nan.SetNaN();
       
   113     
       
   114     ResetPosition();
       
   115     
       
   116     iSpeed=nan;
       
   117     iHeading=nan;
       
   118     
       
   119     iUsedSatellitesArray.Reset();
       
   120     iSatelliteTime = TTime(0);
       
   121     
       
   122     iHorizontalDoP = nan;
       
   123     iVerticalDoP = nan;
       
   124     iPositionDoP = nan;
       
   125     iSatellitesUsed = 0;
       
   126     
       
   127     //Clear the mask
       
   128     iReceivedMsgMask = 0;
       
   129     
       
   130     iGpsMode = EGpsModeSatellite;
       
   131     TRACESTRING("CBTGPSFix::ResetFix end")
       
   132     }
       
   133 
       
   134 // -----------------------------------------------------------------------------
       
   135 // CBTGPSFix::ResetGSVTime
       
   136 // -----------------------------------------------------------------------------
       
   137 void CBTGPSFix::ResetGSVTime()
       
   138     {
       
   139     TRACESTRING("CBTGPSFix::ResetGSVTime start...")
       
   140     iGsvTime = TTime(0);
       
   141     TRACESTRING("CBTGPSFix::ResetGSVTime end");
       
   142     }
       
   143 
       
   144 // -----------------------------------------------------------------------------
       
   145 // CBTGPSFix::ResetPosition
       
   146 // 
       
   147 // -----------------------------------------------------------------------------
       
   148 void CBTGPSFix::ResetPosition()
       
   149     {
       
   150     TRACESTRING("CBTGPSFix::ResetPosition start...")
       
   151     TRealX nan;
       
   152     nan.SetNaN();
       
   153     
       
   154     iLatitude = nan;
       
   155     iLongitude = nan;
       
   156     iAltitude = nan;
       
   157     iTime = TTime(0);
       
   158     
       
   159     iValid = CBTGPSFix::EFixValidityUnkown;
       
   160     TRACESTRING("CBTGPSFix::ResetPosition end")
       
   161     }
       
   162 
       
   163 // -----------------------------------------------------------------------------
       
   164 // CBTGPSFix::FixState
       
   165 // -----------------------------------------------------------------------------
       
   166 CBTGPSFix::TState CBTGPSFix::FixState() const
       
   167     {
       
   168     return iValid;
       
   169     }
       
   170 
       
   171 // -----------------------------------------------------------------------------
       
   172 // CBTGPSFix::IsFixValid
       
   173 // 
       
   174 // -----------------------------------------------------------------------------
       
   175 TBool CBTGPSFix::IsFixValid() const
       
   176     {
       
   177     return (iValid == EFixValid2D || iValid == EFixValid3D);
       
   178     }
       
   179 
       
   180 // -----------------------------------------------------------------------------
       
   181 // CBTGPSFix::IfFullNmeaPatternReceived
       
   182 // 
       
   183 // -----------------------------------------------------------------------------
       
   184 TBool CBTGPSFix::IfFullNmeaPatternReceived() const
       
   185     {
       
   186     return iReceivedMsgMask == (EReceivedGSA|EReceivedGGA|EReceivedRMC);
       
   187     }
       
   188         
       
   189 // -----------------------------------------------------------------------------
       
   190 // CBTGPSFix::FixTime
       
   191 // 
       
   192 // -----------------------------------------------------------------------------
       
   193 TTime CBTGPSFix::FixTime() const
       
   194     {
       
   195     return iTime;
       
   196     }
       
   197 
       
   198 // -----------------------------------------------------------------------------
       
   199 // CBTGPSFix::GsvTime
       
   200 // 
       
   201 // -----------------------------------------------------------------------------
       
   202 TTime CBTGPSFix::GsvTime() const
       
   203     {
       
   204     return iGsvTime;
       
   205     }
       
   206 
       
   207 // -----------------------------------------------------------------------------
       
   208 // CBTGPSFix::ParseMessage
       
   209 // Fills the information available from a command to the fix
       
   210 // -----------------------------------------------------------------------------
       
   211 CBTGPSFix::TParsingStatus CBTGPSFix::ParseMessage(const TBTGPSNmeaParser& aParser)
       
   212     {
       
   213     TRACESTRING("CBTGPSFix::ParseMessage start...")
       
   214     TRAPD(err, ParseMessageL(aParser));
       
   215     TParsingStatus ret = EUnkown;
       
   216     switch(err)
       
   217         {
       
   218         case KErrNone:
       
   219             ret = EInfoUpdated;
       
   220             break;
       
   221         case KErrNotSupported:
       
   222             ret = EUnkown;
       
   223             break;
       
   224         default:
       
   225             ret = EInvalid;
       
   226         }
       
   227     TRACESTRING("CBTGPSFix::ParseMessage end")
       
   228     return ret;
       
   229     }
       
   230 
       
   231 // -----------------------------------------------------------------------------
       
   232 // CBTGPSFix::ParseMessageL
       
   233 // Fills the information available from a command to the fix
       
   234 // -----------------------------------------------------------------------------
       
   235 void CBTGPSFix::ParseMessageL(const TBTGPSNmeaParser& aParser)
       
   236     {
       
   237     if(!aParser.IsValid())
       
   238         {
       
   239         User::Leave(KErrCorrupt);
       
   240         }
       
   241         
       
   242     switch (aParser.MessageId())
       
   243         {
       
   244         case ENmeaGPGSV: 
       
   245             ParseGSVSentenceL(aParser);
       
   246             break;
       
   247             
       
   248         case ENmeaGPRMC:
       
   249             ParseRMCSentenceL(aParser);
       
   250             break;
       
   251             
       
   252         case ENmeaGPGGA:
       
   253             ParseGGASentenceL(aParser);
       
   254             break;
       
   255             
       
   256         case ENmeaGPGSA:
       
   257             ParseGSASentenceL(aParser);
       
   258             break;
       
   259             
       
   260         default:
       
   261             User::Leave(KErrNotSupported);
       
   262             break;
       
   263         }
       
   264     }
       
   265 
       
   266 // -----------------------------------------------------------------------------
       
   267 // CBTGPSFix::ParseGGASentenceL
       
   268 // 
       
   269 // -----------------------------------------------------------------------------
       
   270 void CBTGPSFix::ParseGGASentenceL(
       
   271         const TBTGPSNmeaParser& aParser)
       
   272     {
       
   273     
       
   274     GetLatitudeLongitude(aParser, ENmeaFieldGPGGALatitude);
       
   275     
       
   276     //Get GPS Quality indicator. 
       
   277     //By default, assume GPS works in normal mode
       
   278     TInt gpsQualityIndicator(EGpsQualitySPS); 
       
   279     if(aParser.GetFieldData(ENmeaFieldGPGGAFix, gpsQualityIndicator)==KErrNone)
       
   280         {
       
   281         //Get satellite mode
       
   282         switch(gpsQualityIndicator)
       
   283             {
       
   284             case EGpsQualityManualInput:
       
   285                 iGpsMode = EGpsModeManualInput;
       
   286                 break;
       
   287             case EGpsQualityNotValid:
       
   288                 iGpsMode = EGpsModeInvalid;
       
   289                 break;
       
   290             case EGpsQualityEstimated:
       
   291                 iGpsMode = EGpsModeEstimated;
       
   292                 break;
       
   293             case EGpsQualitySimulation:
       
   294                 iGpsMode = EGpsModeSimulator;
       
   295                 break;
       
   296             case EGpsQualitySPS:
       
   297             case EGpsQualityDGPS:
       
   298             case EGpsQualityPPS:
       
   299             case EGpsQualityRTK:
       
   300             case EGpsQualityFloatRTK:
       
   301             default:
       
   302                 //Specify any value other than those defined in NMEA spec as 
       
   303                 //Satellite mode. This will enable PSY working with mal-functioning
       
   304                 //GPS and future GPS technology.
       
   305                 iGpsMode = EGpsModeSatellite;
       
   306                 break;
       
   307             }
       
   308         }
       
   309         
       
   310     //Get number of satellites in use
       
   311     aParser.GetFieldData(
       
   312         ENmeaFieldGPGGASatellitesUsed,
       
   313         iSatellitesUsed);
       
   314         
       
   315     //Get HDOP
       
   316     aParser.GetFieldData(
       
   317         ENmeaFieldGPGGAHDOP,
       
   318         iHorizontalDoP);
       
   319     
       
   320     //Acquire altitude over msl
       
   321     TReal tempVal32(0); 
       
   322     aParser.GetFieldData(
       
   323         ENmeaFieldGPGGAMSLAltitude,
       
   324         tempVal32);
       
   325 
       
   326     //Get Geoidal seperation
       
   327     aParser.GetFieldData(
       
   328         ENmeaFieldGPGGAGeoidalSeperation,
       
   329         iGeoidalSeperation);
       
   330         
       
   331     //Caculate altitude over WGS84
       
   332     iAltitude = tempVal32+iGeoidalSeperation;
       
   333     
       
   334     //GGA received
       
   335     iReceivedMsgMask = iReceivedMsgMask | EReceivedGGA; 
       
   336     }
       
   337 
       
   338 // -----------------------------------------------------------------------------
       
   339 // CBTGPSFix::ParseGSVSentenceL
       
   340 // 
       
   341 // -----------------------------------------------------------------------------
       
   342 void CBTGPSFix::ParseGSVSentenceL(
       
   343         const TBTGPSNmeaParser& aParser)
       
   344     {
       
   345     //Get message number
       
   346     TInt messageNumber(1);
       
   347     User::LeaveIfError(aParser.GetFieldData(
       
   348         ENmeaFieldGPGSVMessageNumber,
       
   349         messageNumber));
       
   350         
       
   351     //Check validity of message number
       
   352     if(messageNumber>KMaxGSVMessageNumber)
       
   353         {
       
   354         User::Leave(KErrCorrupt);
       
   355         }
       
   356     
       
   357     if(messageNumber == 1)
       
   358         {
       
   359         //Get total number messages
       
   360         TInt totalNumberOfMessages(iGsvTotalNumberOfMessage);
       
   361         User::LeaveIfError(aParser.GetFieldData(
       
   362             ENmeaFieldGPGSVNumberOfMessage,
       
   363             totalNumberOfMessages));
       
   364         iGsvTotalNumberOfMessage = totalNumberOfMessages;
       
   365         
       
   366         //Get satellites in view
       
   367         TInt satellitesInView(iGsvSatelliteInView); 
       
   368         aParser.GetFieldData(
       
   369             ENmeaFieldGPGSVSatellitesInView,
       
   370             satellitesInView);
       
   371     
       
   372         iGsvSatelliteInView = satellitesInView;
       
   373         
       
   374         //Clear cache
       
   375         for(TInt i=0; i<KMaxGSVMessageNumber; i++)
       
   376             {
       
   377             iNMEAGSVCache[i].Zero();
       
   378             }
       
   379         }
       
   380         
       
   381     if(iGsvTotalNumberOfMessage == 0)
       
   382         {
       
   383         //Wait until we get the message number 1
       
   384         return;
       
   385         }
       
   386         
       
   387     //copy NMEA sentence to cache
       
   388     SecureCopy(iNMEAGSVCache[messageNumber-1], aParser.NmeaSentence());
       
   389     if(messageNumber == iGsvTotalNumberOfMessage)
       
   390         {
       
   391         //Extract satellite info from all the cached messages.
       
   392         iNumberOfSatellites = 0;
       
   393         iSatelliteArray.Reset();
       
   394         
       
   395         //Extract sat info from cache
       
   396         for(TInt i=0; i<iGsvTotalNumberOfMessage-1; i++)
       
   397             {
       
   398             TBTGPSNmeaParser cacheMsgParser;
       
   399             cacheMsgParser.SetNmeaSentence(iNMEAGSVCache[i]);
       
   400             if(cacheMsgParser.IsValid())
       
   401                 {
       
   402                 ExtractSatInfoL(cacheMsgParser);
       
   403                 }
       
   404             }
       
   405             
       
   406         //Extract sat info from this message
       
   407         ExtractSatInfoL(aParser);
       
   408         
       
   409         
       
   410         //Reset total number of message and number of sat in view
       
   411         iGsvTotalNumberOfMessage = 0;
       
   412         iGsvSatelliteInView = 0;
       
   413 
       
   414         //Clear cache
       
   415         for(TInt i=0; i<KMaxGSVMessageNumber; i++)
       
   416             {
       
   417             iNMEAGSVCache[i].Zero();
       
   418             }
       
   419             
       
   420         //Set GSV time
       
   421         iGsvTime.UniversalTime();
       
   422         TRACESTRING2("CBTGPSFix:: Set GSV Time=%d", iGsvTime.Int64())
       
   423 
       
   424         }
       
   425     }
       
   426 
       
   427 // -----------------------------------------------------------------------------
       
   428 // CBTGPSFix::ExtractSatInfo
       
   429 // 
       
   430 // -----------------------------------------------------------------------------
       
   431 void CBTGPSFix::ExtractSatInfoL(const TBTGPSNmeaParser& aParser)
       
   432     {
       
   433     //get message number
       
   434     TInt messageNumber(1);
       
   435     User::LeaveIfError(aParser.GetFieldData(
       
   436         ENmeaFieldGPGSVMessageNumber,
       
   437         messageNumber));
       
   438     
       
   439 
       
   440     //Detect the number of satellites in this message
       
   441     if( (((messageNumber - 1) * 4) + 1) <= iGsvSatelliteInView )
       
   442         {
       
   443         ExtractSatelliteDataL(aParser,
       
   444             ENmeaFieldGPGSVSatelliteID1,
       
   445             ENmeaFieldGPGSVElevation1,
       
   446             ENmeaFieldGPGSVAzimuth1,
       
   447             ENmeaFieldGPGSVSNR1);
       
   448         }            
       
   449     
       
   450     //Detect the number of satellites in this message
       
   451     if ( (((messageNumber - 1) * 4) + 2) <= iGsvSatelliteInView )
       
   452         {
       
   453         ExtractSatelliteDataL(aParser,
       
   454             ENmeaFieldGPGSVSatelliteID2,
       
   455             ENmeaFieldGPGSVElevation2,
       
   456             ENmeaFieldGPGSVAzimuth2,
       
   457             ENmeaFieldGPGSVSNR2);
       
   458         }            
       
   459     
       
   460     //Detect the number of satellites in this message
       
   461     if ( (((messageNumber - 1) * 4) + 3) <= iGsvSatelliteInView )
       
   462         {
       
   463         ExtractSatelliteDataL(aParser,
       
   464             ENmeaFieldGPGSVSatelliteID3,
       
   465             ENmeaFieldGPGSVElevation3,
       
   466             ENmeaFieldGPGSVAzimuth3,
       
   467             ENmeaFieldGPGSVSNR3);
       
   468         }            
       
   469     
       
   470     //Detect the number of satellites in this message
       
   471     if ( (((messageNumber - 1) * 4) + 4) <= iGsvSatelliteInView )
       
   472         {
       
   473         ExtractSatelliteDataL(aParser,
       
   474             ENmeaFieldGPGSVSatelliteID4,
       
   475             ENmeaFieldGPGSVElevation4,
       
   476             ENmeaFieldGPGSVAzimuth4,
       
   477             ENmeaFieldGPGSVSNR4);
       
   478         }            
       
   479     }
       
   480 
       
   481 // -----------------------------------------------------------------------------
       
   482 // CBTGPSFix::ParseGSASentenceL
       
   483 // 
       
   484 // -----------------------------------------------------------------------------
       
   485 void CBTGPSFix::ParseGSASentenceL(
       
   486         const TBTGPSNmeaParser& aParser)
       
   487     {
       
   488     TInt err = KErrNone;
       
   489     
       
   490     // Acquire fix status
       
   491     TInt validity(CBTGPSFix::EFixValidityUnkown);
       
   492     aParser.GetFieldData(
       
   493         ENmeaFieldGPGSAMode2,
       
   494         validity);
       
   495 
       
   496     // 2D fix
       
   497     if ( 2 == validity )
       
   498         {
       
   499         iValid = CBTGPSFix::EFixValid2D;
       
   500         }
       
   501     // 3D fix
       
   502     else if ( 3 == validity )
       
   503         {
       
   504         iValid = CBTGPSFix::EFixValid3D;
       
   505         }
       
   506     // No fix
       
   507     else
       
   508         {
       
   509         iValid = CBTGPSFix::EFixNotValid;
       
   510         }   
       
   511     
       
   512     //Get number of used satellites
       
   513     iSatellitesUsed = 0;
       
   514     
       
   515     for ( TInt i = ENmeaFieldGPGSASatellitesUsedCH1; 
       
   516             i <= ENmeaFieldGPGSASatellitesUsedCH12; i++ )
       
   517         {
       
   518         TInt usedSatelliteId=0;
       
   519         err = aParser.GetFieldData(
       
   520             i,
       
   521             usedSatelliteId);
       
   522         if(err==KErrNone && usedSatelliteId !=0)
       
   523             {
       
   524             iUsedSatellitesArray[iSatellitesUsed] = usedSatelliteId;
       
   525             iSatellitesUsed++;
       
   526             }
       
   527         }
       
   528     
       
   529     //Get HDOP
       
   530     aParser.GetFieldData(
       
   531         ENmeaFieldGPGSAHDOP,
       
   532         iHorizontalDoP);
       
   533         
       
   534     //Get VDOP
       
   535     aParser.GetFieldData(
       
   536         ENmeaFieldGPGSAVDOP,
       
   537         iVerticalDoP);
       
   538     
       
   539     //Get PDOP
       
   540     aParser.GetFieldData(
       
   541         ENmeaFieldGPGSAPDOP,
       
   542         iPositionDoP);
       
   543 
       
   544     //GSA received
       
   545     iReceivedMsgMask = iReceivedMsgMask | EReceivedGSA; 
       
   546 
       
   547     }
       
   548 
       
   549 // -----------------------------------------------------------------------------
       
   550 // CBTGPSFix::ParseRMCSentenceL
       
   551 // 
       
   552 // -----------------------------------------------------------------------------
       
   553 void CBTGPSFix::ParseRMCSentenceL(
       
   554         const TBTGPSNmeaParser& aParser)
       
   555     {
       
   556     //Do the hairy time conversion and
       
   557     //add the 2000 to the year
       
   558     
       
   559     //The format for Set YYYYMMDD:HHMMSS.SSSSSS
       
   560     TBuf16<9+10+3> time;
       
   561     
       
   562     //Get date and time field
       
   563     TPtrC8 dateField;
       
   564     aParser.GetFieldBlock(
       
   565         ENmeaFieldGPRMCDate,
       
   566         dateField);
       
   567 
       
   568     //Get time field
       
   569     TPtrC8 timeField;
       
   570     aParser.GetFieldBlock(
       
   571         ENmeaFieldGPRMCUTCTime,
       
   572         timeField);
       
   573     
       
   574     if(dateField.Length()==6 && 
       
   575             timeField.Length()>0 && 
       
   576             timeField.Length()<=10)
       
   577         {
       
   578         //Date consist of DDMMYY
       
   579         TBuf16<6> date;
       
   580         date.Copy(dateField);
       
   581 
       
   582         time.Append(_L("20"));
       
   583         time.Append(date.Mid(4,2));
       
   584 
       
   585         //Take care that the month is indexed from zero
       
   586         TInt tempVal(1);
       
   587         TLex tempLexer = date.Mid(2,2);
       
   588         tempLexer.Val(tempVal); //error ignored
       
   589         tempVal = tempVal - 1;
       
   590         time.AppendNumFixedWidth(tempVal,EDecimal,2);
       
   591     
       
   592         //Take care that the date is indexed from zero
       
   593         tempLexer = date.Mid(0,2);
       
   594         tempVal = 1;
       
   595         tempLexer.Val(tempVal); //error ignored
       
   596         tempVal = tempVal - 1;
       
   597         time.AppendNumFixedWidth(tempVal,EDecimal,2);
       
   598         time.Append(_L(":"));           
       
   599     
       
   600         //Time consist of HHMMSS.SSS
       
   601         TBuf16<10> times;
       
   602     
       
   603         times.Copy(timeField);
       
   604         time.Append(times);
       
   605     
       
   606         iSatelliteTime.Set(time);//error ignored
       
   607         }
       
   608 
       
   609     //Get latitude and longitude
       
   610     GetLatitudeLongitude(aParser, ENmeaFieldGPRMCLatitude);
       
   611     
       
   612     //Get speed
       
   613     TReal32 tempVal32(0);
       
   614     if(aParser.GetFieldData(
       
   615         ENmeaFieldGPRMCSpeedOverGround, 
       
   616         tempVal32)==KErrNone)
       
   617         {
       
   618         iSpeed = KKnotInMetersPerSecond*tempVal32;
       
   619         }
       
   620     
       
   621     //Get heading
       
   622     aParser.GetFieldData(
       
   623         ENmeaFieldGPRMCCourseOverGround,
       
   624         iHeading);
       
   625         
       
   626     //Get GPS Mode
       
   627     TPtrC8 gpsMode;
       
   628     aParser.GetFieldBlock(
       
   629         ENmeaFieldGPRMCModeIndicator,
       
   630         gpsMode);
       
   631     if(gpsMode.Length()!=0)
       
   632         {
       
   633         switch(gpsMode[0])
       
   634             {
       
   635             case 'A':
       
   636             case 'D':
       
   637                 iGpsMode = EGpsModeSatellite;
       
   638                 break;
       
   639             case 'E':
       
   640                 iGpsMode = EGpsModeEstimated;
       
   641                 break;
       
   642             case 'M':
       
   643                 iGpsMode = EGpsModeManualInput;
       
   644                 break;
       
   645             case 'S':
       
   646                 iGpsMode = EGpsModeSimulator;
       
   647                 break;
       
   648             case 'N':
       
   649             default:
       
   650                 iGpsMode = EGpsModeInvalid;
       
   651                 break;
       
   652             }
       
   653         }
       
   654 
       
   655     //RMC received
       
   656     iReceivedMsgMask = iReceivedMsgMask | EReceivedRMC;
       
   657 
       
   658     }
       
   659 
       
   660 
       
   661 // -----------------------------------------------------------------------------
       
   662 // CBTGPSFix::GetLatitudeLongitude
       
   663 // -----------------------------------------------------------------------------
       
   664 void CBTGPSFix::GetLatitudeLongitude(
       
   665             const TBTGPSNmeaParser& aParser,
       
   666             TInt aStartId)
       
   667     {
       
   668     TPtrC8 nsField;
       
   669     TPtrC8 latField;
       
   670     TPtrC8 ewField;
       
   671     TPtrC8 logField;
       
   672     
       
   673     aParser.GetFieldBlock(aStartId, latField);
       
   674     aParser.GetFieldBlock(aStartId+1, nsField);
       
   675     aParser.GetFieldBlock(aStartId+2, logField);
       
   676     aParser.GetFieldBlock(aStartId+3, ewField);
       
   677     
       
   678     //We retrieve position only when all fields are valid
       
   679     if(nsField.Length()!=0 && latField.Length()!=0 &&
       
   680         ewField.Length()!=0 && logField.Length()!=0)
       
   681         {
       
   682         TReal latitude, longitude;
       
   683         if( GetDegrees(nsField, latField, latitude) == KErrNone &&
       
   684             GetDegrees(ewField, logField, longitude) == KErrNone)
       
   685             {
       
   686             iLatitude = latitude;
       
   687             iLongitude = longitude;
       
   688             TRACESTRING2("lat=%f", latitude);
       
   689             TRACESTRING2("lon=%f", longitude);
       
   690             }
       
   691         }
       
   692     //Set fix time
       
   693     iTime.UniversalTime();
       
   694     }
       
   695 
       
   696 
       
   697 // -----------------------------------------------------------------------------
       
   698 // CBTGPSFix::GetDegrees
       
   699 // Transforms from degrees and minutes string to degree float
       
   700 // -----------------------------------------------------------------------------
       
   701 TInt CBTGPSFix::GetDegrees(
       
   702         const TDesC8& aSide,
       
   703         const TDesC8& aDegreesMinutes,
       
   704         TReal64& aDegrees)
       
   705     {
       
   706     TInt err = KErrNone;
       
   707     
       
   708     _LIT8(compNS, "S");
       
   709     _LIT8(compEW, "W");
       
   710     _LIT8(decimalPoint, ".");
       
   711     
       
   712     aDegrees = 0.0;
       
   713     TReal64 sign = 1.0;
       
   714     
       
   715     // Create sign multiplier according to N/S field
       
   716     if ( 0 == aSide.Compare(compNS) || 0 == aSide.Compare(compEW) )
       
   717         {
       
   718         sign = -1;
       
   719         }
       
   720     
       
   721     TInt loop = aDegreesMinutes.Find(decimalPoint);
       
   722     
       
   723     //Check that the decimal point was in right place
       
   724     //There could be 1-3 chars in degrees ([[D]D]DMM.MMMM)
       
   725     if ( (KErrNotFound != loop) && (loop > 2) && (loop < 6) )
       
   726         {
       
   727         loop -= 2;
       
   728         
       
   729         //Get the degrees (MM.MMM)
       
   730         TLex8 numberLexer = aDegreesMinutes.Mid(loop);
       
   731         err = numberLexer.Val(aDegrees, KDecimalSeperator);
       
   732         
       
   733         //Get the minutes (DDD)
       
   734         numberLexer = aDegreesMinutes.Left(loop);
       
   735         TReal64 temp = 0.0;
       
   736         err |= numberLexer.Val( temp, KDecimalSeperator );
       
   737         
       
   738         if(err!=KErrNone)
       
   739             {
       
   740             return err;
       
   741             }
       
   742             
       
   743         //Degrees are calculate as sign*(DD+(MM.MMM/60))
       
   744         aDegrees = (temp) + aDegrees/60;
       
   745         aDegrees = aDegrees * sign;
       
   746         }
       
   747     return err;
       
   748     }
       
   749 
       
   750 
       
   751 // -----------------------------------------------------------------------------
       
   752 // CBTGPSFix::AppendSatelliteData
       
   753 // Fills the internal vector with satellite data
       
   754 // -----------------------------------------------------------------------------
       
   755 void CBTGPSFix::AppendSatelliteData(TSatelliteInfo& aSatInfo)
       
   756     {
       
   757     //Prevent over indexing
       
   758     if ( KMaxNumberOfSatellites > iNumberOfSatellites ) 
       
   759         {
       
   760         iSatelliteArray[iNumberOfSatellites] = aSatInfo;
       
   761         ++iNumberOfSatellites;
       
   762         }
       
   763     }
       
   764 
       
   765 // -----------------------------------------------------------------------------
       
   766 // CBTGPSFix::ExtractSatelliteDataL
       
   767 // ------------------------------------------------------------------------------
       
   768 void CBTGPSFix::ExtractSatelliteDataL (
       
   769         const TBTGPSNmeaParser& aParser,
       
   770         TInt aField1,
       
   771         TInt aField2,
       
   772         TInt aField3,
       
   773         TInt aField4)
       
   774     {
       
   775     TSatelliteInfo satInfo;
       
   776     
       
   777     satInfo.iSatelliteId = -1;
       
   778     satInfo.iElevation = -1;
       
   779     satInfo.iAzimuth = -1;
       
   780     satInfo.iSNR = -1;
       
   781     
       
   782     TInt err = KErrNone;
       
   783     err = aParser.GetFieldData(aField1, satInfo.iSatelliteId);
       
   784     
       
   785     err |= aParser.GetFieldData(aField2, satInfo.iElevation); 
       
   786         
       
   787     err |= aParser.GetFieldData(aField3, satInfo.iAzimuth); 
       
   788     
       
   789     err |= aParser.GetFieldData(aField4, satInfo.iSNR);
       
   790     
       
   791     if(err==KErrNone)
       
   792         {
       
   793         AppendSatelliteData(satInfo);
       
   794         }
       
   795     }
       
   796 
       
   797 // -----------------------------------------------------------------------------
       
   798 // CBTGPSFix::SecureCopy
       
   799 // ------------------------------------------------------------------------------
       
   800 TBool CBTGPSFix::SecureCopy(TDes8& aTo,const TDesC8& aFrom)
       
   801     {
       
   802     //Prevent overflow
       
   803     if ( aFrom.Length() > aTo.MaxLength() )
       
   804         {
       
   805         //Cut the message
       
   806         aTo.Copy(aFrom.Left(aTo.MaxLength()));
       
   807         return EFalse;
       
   808         }
       
   809     else
       
   810         {
       
   811         aTo.Copy(aFrom);
       
   812         return ETrue;
       
   813         }
       
   814     }
       
   815 
       
   816 // -----------------------------------------------------------------------------
       
   817 // CBTGPSFix::FillPositionInfo
       
   818 // ------------------------------------------------------------------------------
       
   819 TInt CBTGPSFix::FillPositionInfo(
       
   820             TPositionInfoBase& aPosInfo,
       
   821             TInt* aNmeaIndex) const
       
   822     {
       
   823     TRAPD(err, FillPositionInfoL(aPosInfo,aNmeaIndex));
       
   824     return err;
       
   825     }
       
   826 
       
   827 // -----------------------------------------------------------------------------
       
   828 // CBTGPSFix::FillPositionInfoL
       
   829 // ------------------------------------------------------------------------------
       
   830 void CBTGPSFix::FillPositionInfoL(
       
   831     TPositionInfoBase& aPosInfo,
       
   832     TInt* aNmeaIndex ) const
       
   833     {
       
   834     TRACESTRING("CBTGPSFix::FillPositionInfo start...")
       
   835     //HPositionGenericInfo
       
   836     //---------------------------------------------------------------
       
   837     if ( aPosInfo.PositionClassType() & EPositionGenericInfoClass )
       
   838         {
       
   839         HPositionGenericInfo* posInfo =
       
   840             static_cast<HPositionGenericInfo*>(&aPosInfo);
       
   841 
       
   842         if ( posInfo->IsRequestedField(EPositionFieldHorizontalSpeed) )
       
   843             {
       
   844             if ( IsFixValid() )
       
   845                 {
       
   846                 User::LeaveIfError(posInfo->SetValue(EPositionFieldHorizontalSpeed,
       
   847                     static_cast<TReal32>(iSpeed)));
       
   848                 }
       
   849             }
       
   850 
       
   851         if ( posInfo->IsRequestedField(EPositionFieldHeading) )
       
   852             {
       
   853             if ( IsFixValid() )
       
   854                 {
       
   855                 User::LeaveIfError(posInfo->SetValue(EPositionFieldHeading,
       
   856                     static_cast<TReal32>(iHeading)));
       
   857                 }
       
   858             }
       
   859 
       
   860         if ( posInfo->IsRequestedField(EPositionFieldNMEASentences) )
       
   861             {
       
   862             TUint8 messageNum=0;
       
   863             if(aNmeaIndex!=NULL)
       
   864                 {
       
   865 				TRACESTRING("CBTGPSFix::FillPositionInfo fill nmea sentences")
       
   866 				TRACESTRING2("begining = %d", *aNmeaIndex)
       
   867 				TRACESTRING2("bottom   = %d", iNmeaBuffer->CurrentIndex())
       
   868                 TInt beginning = *aNmeaIndex;
       
   869                 TBuf8<KMaxNmeaMessageSize> nmeaBuf;
       
   870                 while(iNmeaBuffer->ReadSentences(
       
   871                     nmeaBuf,
       
   872                     beginning) == KErrNone)
       
   873                     {
       
   874                     User::LeaveIfError(posInfo->SetValue(static_cast<TUint16>(
       
   875                         EPositionFieldNMEASentencesStart+messageNum),
       
   876                         nmeaBuf));
       
   877                     ++messageNum;
       
   878                     }
       
   879                     
       
   880                 *aNmeaIndex = beginning;
       
   881                 }
       
   882 
       
   883             User::LeaveIfError(posInfo->SetValue(EPositionFieldNMEASentences,
       
   884                 static_cast<TUint8>(messageNum)));
       
   885             }
       
   886 
       
   887         if ( posInfo->IsRequestedField(EPositionFieldSatelliteNumInView) )
       
   888             {
       
   889             User::LeaveIfError(posInfo->SetValue(EPositionFieldSatelliteNumInView,
       
   890                 static_cast<TInt8>(iNumberOfSatellites)));
       
   891             }
       
   892 
       
   893         if ( posInfo->IsRequestedField(EPositionFieldSatelliteNumUsed) )
       
   894             {
       
   895             User::LeaveIfError(posInfo->SetValue(EPositionFieldSatelliteNumUsed,
       
   896                 static_cast<TInt8>(iSatellitesUsed)));
       
   897             }
       
   898 
       
   899         if ( posInfo->IsRequestedField(EPositionFieldSatelliteTime) )
       
   900             {
       
   901             User::LeaveIfError(
       
   902                 posInfo->SetValue(
       
   903                     EPositionFieldSatelliteTime,
       
   904                     iSatelliteTime));
       
   905             }
       
   906 
       
   907         if ( posInfo->IsRequestedField(EPositionFieldSatelliteHorizontalDoP) )
       
   908             {
       
   909             User::LeaveIfError(
       
   910                 posInfo->SetValue(
       
   911                     EPositionFieldSatelliteHorizontalDoP,
       
   912                     static_cast<TReal32>(iHorizontalDoP)));
       
   913             }
       
   914 
       
   915         if ( posInfo->IsRequestedField(EPositionFieldSatelliteVerticalDoP) )
       
   916             {
       
   917             User::LeaveIfError(
       
   918                 posInfo->SetValue(
       
   919                     EPositionFieldSatelliteVerticalDoP,
       
   920                     static_cast<TReal32>(iVerticalDoP)));
       
   921             }
       
   922 
       
   923         if ( posInfo->IsRequestedField(EPositionFieldSatellitePositionDoP) )
       
   924             {
       
   925             User::LeaveIfError(
       
   926                 posInfo->SetValue(
       
   927                     EPositionFieldSatellitePositionDoP,
       
   928                     static_cast<TReal32>(iPositionDoP)));
       
   929             }
       
   930         }
       
   931 
       
   932     
       
   933     //TpositionSatelliteInfo
       
   934     //---------------------------------------------------------------
       
   935     if ( aPosInfo.PositionClassType() & EPositionSatelliteInfoClass )
       
   936         {
       
   937         TPositionSatelliteInfo* posInfo =
       
   938             static_cast<TPositionSatelliteInfo*>(&aPosInfo);
       
   939         posInfo->ClearSatellitesInView();
       
   940         TSatelliteData satData;
       
   941 
       
   942         //Iterate through the satellites
       
   943         for ( TInt i = 0; i < iNumberOfSatellites;++i )
       
   944             {
       
   945             satData.SetSatelliteId(iSatelliteArray[i].iSatelliteId);
       
   946             satData.SetAzimuth(iSatelliteArray[i].iAzimuth);
       
   947             satData.SetElevation(iSatelliteArray[i].iElevation);
       
   948             satData.SetIsUsed(EFalse);
       
   949 
       
   950             //Find out if the this satellite was used in fix calculation
       
   951             for ( TInt ii = 0; ii < iSatellitesUsed; ii++)
       
   952                 {
       
   953                  if ( iUsedSatellitesArray[ii] == 
       
   954                         iSatelliteArray[i].iSatelliteId )
       
   955                     {
       
   956                     //This satellite is used in solution
       
   957                     satData.SetIsUsed(ETrue);
       
   958                     ii = iSatellitesUsed; //Break the loop
       
   959                     }
       
   960                 }
       
   961 
       
   962             satData.SetSignalStrength(iSatelliteArray[i].iSNR);
       
   963             posInfo->AppendSatelliteData(satData);
       
   964             }
       
   965 
       
   966         posInfo->SetSatelliteTime(iSatelliteTime);
       
   967         posInfo->SetVerticalDoP(iVerticalDoP);
       
   968         posInfo->SetHorizontalDoP(iHorizontalDoP);
       
   969         }
       
   970 
       
   971 
       
   972     //TPositionCourseInfo
       
   973     //---------------------------------------------------------------
       
   974     if ( aPosInfo.PositionClassType() & EPositionCourseInfoClass )
       
   975         {
       
   976         TPositionCourseInfo* posInfo =
       
   977             static_cast<TPositionCourseInfo*>(&aPosInfo);
       
   978         TCourse cos;
       
   979 
       
   980         if ( IsFixValid() )
       
   981             {   
       
   982             cos.SetSpeed(iSpeed);
       
   983             cos.SetHeading(iHeading);
       
   984             }
       
   985 
       
   986         posInfo->SetCourse(cos);
       
   987         }
       
   988 
       
   989 
       
   990 
       
   991     //TPositionInfo
       
   992     //---------------------------------------------------------------
       
   993     if ( aPosInfo.PositionClassType() & EPositionInfoClass )
       
   994         {
       
   995         TPositionInfo * posInfo = static_cast<TPositionInfo*>(&aPosInfo);
       
   996         TPosition pos;
       
   997 
       
   998         if ( IsFixValid() )
       
   999             {
       
  1000             if ( iValid == CBTGPSFix::EFixValid2D ) 
       
  1001                 {
       
  1002                 pos.SetCoordinate(iLatitude,iLongitude);
       
  1003                 }
       
  1004             else
       
  1005                 {
       
  1006                 pos.SetCoordinate(iLatitude,iLongitude,iAltitude);
       
  1007                 }
       
  1008 
       
  1009             //Do a sanity check for the DOP values. If they are not valid,
       
  1010             //use hard coded values instead.
       
  1011             if ( (iHorizontalDoP > 0.0) && (iVerticalDoP > 0.0) )
       
  1012                 {
       
  1013                 pos.SetAccuracy(
       
  1014                     CBTGPSRequestHandler::ConstantsManager().iUserEquivalentRangeError
       
  1015                         * iHorizontalDoP,
       
  1016                     CBTGPSRequestHandler::ConstantsManager().iUserEquivalentRangeError
       
  1017                         * iVerticalDoP);
       
  1018                 }
       
  1019             else
       
  1020                 {
       
  1021                 pos.SetAccuracy(KHorizontalAccuracy,KVerticalAccuracy);
       
  1022                 }
       
  1023             }
       
  1024 
       
  1025         pos.SetTime(iTime);
       
  1026         pos.SetDatum(KPositionDatumWgs84);
       
  1027         posInfo->SetPosition(pos);
       
  1028         }
       
  1029     TRACESTRING("CBTGPSFix::FillPositionInfo end");
       
  1030     }
       
  1031 
       
  1032 // -----------------------------------------------------------------------------
       
  1033 // CBTGPSFix::ValidateNmeaBufferIndex
       
  1034 // ------------------------------------------------------------------------------
       
  1035 void CBTGPSFix::ValidateNmeaBufferIndex(
       
  1036             TInt& aNmeaIndex,
       
  1037             TInt& aBottom) const
       
  1038     {
       
  1039     TRACESTRING("CBTGPSFix::ValidateNmeaBufferIndex: start");
       
  1040     TRACESTRING2("aNmeaIndex: %d", aNmeaIndex);
       
  1041     TRACESTRING2("aBottom   : %d", aBottom);
       
  1042     TRACESTRING2("currentBot: %d", iNmeaBuffer->CurrentIndex());
       
  1043     
       
  1044     TInt currentBottom = iNmeaBuffer->CurrentIndex();
       
  1045     
       
  1046     //when aNmeaIndex==KBTGPSNmeaIndexNotSet, client shall
       
  1047     //get all NMEA data in the buffer
       
  1048 
       
  1049     //aBottom is the bottom of the NMEA buffer that the client
       
  1050     //last time seen. 
       
  1051     //When aBottom==KBTGPSNmeaIndexNotSet, it means the client
       
  1052     //has just constructed. At this time, we don't need to check
       
  1053     //the index
       
  1054 
       
  1055     if(aNmeaIndex != KBTGPSNmeaIndexNotSet 
       
  1056         && aBottom != KBTGPSNmeaIndexNotSet)
       
  1057         {
       
  1058         
       
  1059         //If index falles in the middle of aBottom and currentBottom,
       
  1060         //we shall invalidate the index
       
  1061 
       
  1062         if( ( aNmeaIndex>aBottom && aNmeaIndex<currentBottom ) ||
       
  1063             ( aBottom>currentBottom && aNmeaIndex > aBottom ) ||
       
  1064             ( currentBottom > aNmeaIndex && aBottom > currentBottom ) )
       
  1065             {
       
  1066             //Invalidate aNmeaIndex
       
  1067             aNmeaIndex = KBTGPSNmeaIndexNotSet;
       
  1068             
       
  1069             TRACESTRING("CBTGPSFix::ValidateNmeaBufferIndex: Index reset");
       
  1070             }
       
  1071         }
       
  1072 
       
  1073     //Update aBottom
       
  1074     aBottom = currentBottom;
       
  1075     }
       
  1076 
       
  1077 // -----------------------------------------------------------------------------
       
  1078 // CBTGPSFix::operator =
       
  1079 // ------------------------------------------------------------------------------
       
  1080 void CBTGPSFix::operator =(const CBTGPSFix& aFix)
       
  1081     {
       
  1082     //This class is flat. We can just copy memory
       
  1083     Mem::Copy(this, &aFix, sizeof(CBTGPSFix));
       
  1084     }
       
  1085 
       
  1086 
       
  1087 //  End of File
       
  1088