datasourcemodules/bluetoothgpspositioningmodule/btgpspsy/src/Nmea/BTGPSNmeaParser.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 //
       
    15 
       
    16 
       
    17 
       
    18 // INCLUDE FILES
       
    19 #include <e32std.h>
       
    20 
       
    21 #include "BTGPSNmeaParser.h"
       
    22 #include "BTGPSMessageDef.h"
       
    23 #include "BTGPSPanic.h"
       
    24 
       
    25 // EXTERNAL DATA STRUCTURES
       
    26 
       
    27 // EXTERNAL FUNCTION PROTOTYPES  
       
    28 
       
    29 // CONSTANTS
       
    30 //NMEA sentence field delimiter
       
    31 const TUint8 KNmeaFieldDelimiter = ',';
       
    32 
       
    33 //NMEA sentecne checksum delimiter
       
    34 const TUint8 KNmeaChecksumDelimiter = '*';
       
    35 
       
    36 //Data start postion of NMEA sentence
       
    37 const TInt KNmeaDataStartPos = 1; 
       
    38 
       
    39 //Minimum length of NMEA sentence(starter and check sum)
       
    40 const TInt KNmeaMininumLength = 4;
       
    41 
       
    42 //Checksum field length
       
    43 const TInt KNmeaChecksumFieldLength = 2;
       
    44 
       
    45 //Maximum length of address field length
       
    46 const TInt KNmeaMaxAddressFieldLength = 32;
       
    47 
       
    48 //Decimal seperator
       
    49 const TUint8 KDecimalSeperator = '.';
       
    50 
       
    51 /** 
       
    52 * Structure for address field Id map
       
    53 */
       
    54 struct TAddressFieldMessageIdMap
       
    55     {
       
    56     TText8 iField[KNmeaMaxAddressFieldLength];  //Field text
       
    57     TInt iId;                                   //Field id
       
    58     };
       
    59 
       
    60 /**
       
    61 * NMEA and Sirf specific NMEA sentence sId field text and 
       
    62 * id mapping defination
       
    63 */
       
    64 const struct TAddressFieldMessageIdMap KNmeaAddressIdMap[]=
       
    65     {
       
    66         {"GPGSV", ENmeaGPGSV},
       
    67         {"GPGLL", ENmeaGPGLL},
       
    68         {"GPRMC", ENmeaGPRMC},
       
    69         {"GPVTG", ENmeaGPVTG},
       
    70         {"GPGGA", ENmeaGPGGA},
       
    71         {"GPGSA", ENmeaGPGSA},
       
    72         {"PSRF107", ENmeaPSRF107},
       
    73         {"PSRF103", ENmeaPSRF103},
       
    74         {"PSRF101", ENmeaPSRF101},
       
    75         {"PSRF105", ENmeaPSRF105},
       
    76         {"PSRF201", ENmeaPSRF201},
       
    77         {"PNOK",    ENmeaProprietaryNok}
       
    78     };
       
    79 
       
    80 /**
       
    81 * PNOK message id field text and id mapping defination
       
    82 */
       
    83 const struct TAddressFieldMessageIdMap KNmeaPNokAddressIdMap[]=
       
    84     {
       
    85         {"OK",          ENmeaPNokOk},
       
    86         {"RESET",       ENmeaPNokReset},
       
    87         {"MSGS",        ENmeaPNokPeriodicMsgs},
       
    88         {"LOWPWR",      ENmeaPNokLowPwrMode},
       
    89         {"NIGHTMODE",   ENmeaPNokNightMode},
       
    90         {"VER",         ENmeaPNokVersionInfo},
       
    91         {"STAT",        ENmeaPNokPeriodicEvents},
       
    92         {"TIME",        ENmeaPNokReferenceTime}
       
    93      };
       
    94 
       
    95 
       
    96 
       
    97 // MACROS
       
    98 
       
    99 // LOCAL CONSTANTS AND MACROS
       
   100 
       
   101 // MODULE DATA STRUCTURES
       
   102 
       
   103 // LOCAL FUNCTION PROTOTYPES
       
   104 
       
   105 // FORWARD DECLARATIONS
       
   106 
       
   107 // ============================= LOCAL FUNCTIONS ===============================
       
   108 
       
   109 // ============================ MEMBER FUNCTIONS ===============================
       
   110 
       
   111 
       
   112 // -----------------------------------------------------------------------------
       
   113 // TBTGPSNmeaParser::TBTGPSNmeaParser
       
   114 // -----------------------------------------------------------------------------
       
   115 TBTGPSNmeaParser::TBTGPSNmeaParser() : TDelimitedParserBase8()
       
   116     {
       
   117     SetDelimiter(KNmeaFieldDelimiter);
       
   118     }
       
   119 
       
   120 // -----------------------------------------------------------------------------
       
   121 // TBTGPSNmeaParser::SetNmeaSentence
       
   122 // -----------------------------------------------------------------------------
       
   123 void TBTGPSNmeaParser::SetNmeaSentence(const TDesC8& aNmea)
       
   124     {
       
   125     iNmea.Set(aNmea);
       
   126     iId = ENmeaNull;
       
   127     if(CheckValidity())
       
   128         {
       
   129         Parse(TrimSentence());
       
   130         GetMessageId();
       
   131         }
       
   132     }
       
   133 
       
   134 // -----------------------------------------------------------------------------
       
   135 // TBTGPSNmeaParser::NmeaSentence
       
   136 // -----------------------------------------------------------------------------
       
   137 const TDesC8& TBTGPSNmeaParser::NmeaSentence() const
       
   138     {
       
   139     return iNmea;
       
   140     }
       
   141 
       
   142 // -----------------------------------------------------------------------------
       
   143 // TBTGPSNmeaParser::IsValid
       
   144 // -----------------------------------------------------------------------------
       
   145 TBool TBTGPSNmeaParser::IsValid() const
       
   146     {
       
   147     return iId!=ENmeaNull;
       
   148     }
       
   149 
       
   150 // -----------------------------------------------------------------------------
       
   151 // TBTGPSNmeaParser::MessageId
       
   152 // -----------------------------------------------------------------------------
       
   153 TInt TBTGPSNmeaParser::MessageId() const
       
   154     {
       
   155     return iId;
       
   156     }
       
   157 
       
   158 // -----------------------------------------------------------------------------
       
   159 // TBTGPSNmeaParser::GetMessageId
       
   160 // -----------------------------------------------------------------------------
       
   161 void TBTGPSNmeaParser::GetMessageId()
       
   162     {
       
   163     iId = ENmeaUnknown;
       
   164     Reset();
       
   165     TPtrC8 address;
       
   166     if(GetFieldBlock(ENmeaFieldAddressField,address)==KErrNone)
       
   167         {
       
   168         for(TInt i=0; 
       
   169             i<sizeof(KNmeaAddressIdMap)/sizeof(TAddressFieldMessageIdMap);i++)
       
   170             {
       
   171             TPtrC8 knownAddress(KNmeaAddressIdMap[i].iField);
       
   172             if(address.Compare(knownAddress)==KErrNone)
       
   173                 {
       
   174                 TInt messageId = KNmeaAddressIdMap[i].iId;
       
   175                 //If message if Nokia proprietary message, we have to check next field
       
   176                 if(messageId == ENmeaProprietaryNok)
       
   177                     {
       
   178                     Reset();
       
   179                     Inc();Inc();
       
   180                     if(GetNext(address)==KErrNone)
       
   181                         {
       
   182                         for(TInt j=0; 
       
   183                             j<sizeof(KNmeaPNokAddressIdMap)/sizeof(TAddressFieldMessageIdMap); 
       
   184                             j++)
       
   185                             {
       
   186                             TPtrC8 nokAddress(KNmeaPNokAddressIdMap[j].iField);
       
   187                             if(address.Compare(nokAddress)==KErrNone)
       
   188                                 {
       
   189                                 iId = KNmeaPNokAddressIdMap[j].iId;
       
   190                                 return;
       
   191                                 }
       
   192                             }
       
   193                         }
       
   194                     }
       
   195                 iId = messageId;
       
   196                 return;
       
   197                 }
       
   198             }
       
   199         }
       
   200     }
       
   201 
       
   202 // -----------------------------------------------------------------------------
       
   203 // TBTGPSNmeaParser::GetFieldBlock
       
   204 // -----------------------------------------------------------------------------
       
   205 TInt TBTGPSNmeaParser::GetFieldBlock(TInt aFieldId, TPtrC8& aField) const
       
   206     {
       
   207     Reset();
       
   208     if(aFieldId != ENmeaFieldAddressField)
       
   209         {
       
   210         TInt messageId = MessageId();
       
   211         //Check fieldId matches message Id
       
   212         if(aFieldId<messageId || aFieldId>=messageId+KNmeaMessageIdSkip)
       
   213             {
       
   214             return KErrNotFound;
       
   215             }
       
   216 
       
   217         //Skip address field and other fields
       
   218         if(messageId != ENmeaNull)
       
   219             {
       
   220             for(TInt i=0; i<aFieldId-messageId+2; i++)
       
   221                 {
       
   222                 Inc();
       
   223                 }
       
   224             }
       
   225         }
       
   226     return GetNext(aField);
       
   227     }
       
   228 
       
   229 // -----------------------------------------------------------------------------
       
   230 // TBTGPSNmeaParser::IsNullField
       
   231 // -----------------------------------------------------------------------------
       
   232 TBool TBTGPSNmeaParser::IsNullField(TInt aFieldId) const
       
   233     {
       
   234     TPtrC8 fieldBlock;
       
   235     if(GetFieldBlock(aFieldId, fieldBlock)==KErrNone)
       
   236         {
       
   237         return fieldBlock.Length()==0;
       
   238         }
       
   239     //error case
       
   240     return ETrue;
       
   241     }
       
   242 
       
   243 
       
   244 // -----------------------------------------------------------------------------
       
   245 // TBTGPSNmeaParser::GetFieldData
       
   246 // -----------------------------------------------------------------------------
       
   247 template  <>
       
   248 TInt TBTGPSNmeaParser::GetFieldData<TReal32>(TInt aFieldId, TReal32& aData) const
       
   249     {
       
   250     TPtrC8 fieldBlock;
       
   251     TInt err = GetFieldBlock(aFieldId, fieldBlock);
       
   252     if(err==KErrNone && fieldBlock.Length()>0)
       
   253         {
       
   254         TLex8 lex(fieldBlock);
       
   255         return lex.Val(aData, KDecimalSeperator);
       
   256         }
       
   257     return err;
       
   258     }
       
   259 
       
   260 // -----------------------------------------------------------------------------
       
   261 // TBTGPSNmeaParser::GetFieldData
       
   262 // -----------------------------------------------------------------------------
       
   263 template  <>
       
   264 TInt TBTGPSNmeaParser::GetFieldData<TReal>(TInt aFieldId, TReal& aData) const
       
   265     {
       
   266     TPtrC8 fieldBlock;
       
   267     TInt err = GetFieldBlock(aFieldId, fieldBlock);
       
   268     if(err==KErrNone && fieldBlock.Length()>0)
       
   269         {
       
   270         TLex8 lex(fieldBlock);
       
   271         return lex.Val(aData, KDecimalSeperator);
       
   272         }
       
   273     return err;
       
   274     }
       
   275 
       
   276 // -----------------------------------------------------------------------------
       
   277 // TBTGPSNmeaParser::GetFieldData
       
   278 // -----------------------------------------------------------------------------
       
   279 template  <>
       
   280 TInt TBTGPSNmeaParser::GetFieldData<TInt>(TInt aFieldId, TInt& aData) const
       
   281     {
       
   282     TPtrC8 fieldBlock;
       
   283     TInt err = GetFieldBlock(aFieldId, fieldBlock);
       
   284     if(err==KErrNone && fieldBlock.Length()>0)
       
   285         {
       
   286         TLex8 lex(fieldBlock);
       
   287         return lex.Val(aData);
       
   288         }
       
   289     return err;
       
   290     }
       
   291 
       
   292 // -----------------------------------------------------------------------------
       
   293 // TBTGPSNmeaParser::GetFieldData<TInt>
       
   294 // -----------------------------------------------------------------------------
       
   295 #define GetFieldDataImplementation(s) \
       
   296 template <> TInt TBTGPSNmeaParser::GetFieldData<s>(TInt aFieldId, s& aData) const \
       
   297     { \
       
   298     TPtrC8 fieldBlock; \
       
   299     TInt err = GetFieldBlock(aFieldId, fieldBlock); \
       
   300     if(err==KErrNone && fieldBlock.Length()>0) \
       
   301         { \
       
   302         TLex8 lex(fieldBlock); \
       
   303         return lex.Val(aData); \
       
   304         } \
       
   305     return err; \
       
   306     }
       
   307 
       
   308 // -----------------------------------------------------------------------------
       
   309 // TBTGPSNmeaParser::NextFieldData
       
   310 // -----------------------------------------------------------------------------
       
   311 template <class T>
       
   312 TInt TBTGPSNmeaParser::NextFieldData(T& aData) const
       
   313     {
       
   314     //This function must be called when the sentence is valid
       
   315     __ASSERT_DEBUG(IsValid(), Panic(EPanicInvalidNmeaSentence));
       
   316 
       
   317     TBuf8<KNmeaMaxAddressFieldLength> fieldBuf;
       
   318     TPtrC8 fieldBlock(fieldBuf);
       
   319     TInt err = GetNext(fieldBlock);
       
   320     if(err==KErrNone)
       
   321         {
       
   322         TLex8 lex(fieldBlock);
       
   323         return lex.Val(aData);
       
   324         }
       
   325     return err;
       
   326     }
       
   327 
       
   328 // -----------------------------------------------------------------------------
       
   329 // TBTGPSNmeaParser::CheckValidity
       
   330 // -----------------------------------------------------------------------------
       
   331 TBool TBTGPSNmeaParser::CheckValidity() const
       
   332     {
       
   333     TInt length = iNmea.Length();
       
   334     
       
   335     //Check the length of the NMEA sentence
       
   336     if(length<KNmeaMininumLength)
       
   337         {
       
   338         return EFalse;
       
   339         }
       
   340 
       
   341     //Check checksum
       
   342     TInt checksumDelimiterPos = iNmea.LocateReverse(KNmeaChecksumDelimiter);
       
   343     if((checksumDelimiterPos == KErrNotFound) || (checksumDelimiterPos + KNmeaChecksumFieldLength > length))
       
   344         {
       
   345         return EFalse;
       
   346         }
       
   347 
       
   348     //Get checsum field
       
   349     TLex8 lex(iNmea.Mid(checksumDelimiterPos, KNmeaChecksumFieldLength));
       
   350 
       
   351     //Check checksum 
       
   352     return VerifyChecksum(iNmea);
       
   353     }
       
   354 
       
   355 // -----------------------------------------------------------------------------
       
   356 // TBTGPSNmeaParser::TrimSentence
       
   357 // -----------------------------------------------------------------------------
       
   358 const TPtrC8 TBTGPSNmeaParser::TrimSentence() const
       
   359     {
       
   360     //Check checksum
       
   361     TInt checksumDelimiterPos = iNmea.LocateReverse(KNmeaChecksumDelimiter);
       
   362 
       
   363     return iNmea.Mid(
       
   364         KNmeaDataStartPos,
       
   365         checksumDelimiterPos-KNmeaDataStartPos);
       
   366     }
       
   367 
       
   368 
       
   369 // ----------------------------------------------------------------------------
       
   370 // TBTGPSNmeaParser::VerifyChecksum
       
   371 // ----------------------------------------------------------------------------
       
   372 //
       
   373 TBool TBTGPSNmeaParser::VerifyChecksum(const TDesC8& aSentence) const
       
   374     {
       
   375     TUint8 checksum = 0;
       
   376     TInt i;
       
   377     TInt length = aSentence.Length();
       
   378     for (i = KNmeaDataStartPos; 
       
   379         i < length && aSentence[i] != KNmeaChecksumDelimiter; i++)
       
   380         {
       
   381         checksum ^= aSentence[i];
       
   382         }
       
   383 
       
   384     if (++i + KNmeaDataStartPos < aSentence.Length())
       
   385         {
       
   386         TUint8 sum = TUint8((CharToNibble(aSentence[i]) << 4) +
       
   387             CharToNibble(aSentence[i+1]));
       
   388         if (sum == checksum)
       
   389             {
       
   390             return ETrue;
       
   391             }
       
   392         }
       
   393 
       
   394     return EFalse;
       
   395     }
       
   396 
       
   397 // ----------------------------------------------------------------------------
       
   398 // TBTGPSNmeaParser::CharToNibble
       
   399 // ----------------------------------------------------------------------------
       
   400 //
       
   401 TUint8 TBTGPSNmeaParser::CharToNibble(const TUint8 aChar) const
       
   402     {
       
   403     if (aChar <= '9')
       
   404         {
       
   405         return TUint8(aChar - '0');
       
   406         }
       
   407     else
       
   408         {
       
   409         return TUint8(aChar - 'A' + 10);
       
   410         }
       
   411     }
       
   412 
       
   413 //  End of File
       
   414 
       
   415 
       
   416