datasourceadaptation/gpsdatasourceadaptation/common/src/nmeafunctions.cpp
changeset 0 9cfd9a3ee49c
equal deleted inserted replaced
-1:000000000000 0:9cfd9a3ee49c
       
     1 // Copyright (c) 2008-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 // utility fucntions, and odds and sods for various bits of the location server
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file
       
    20  @internalComponent
       
    21  @deprecated
       
    22 */
       
    23 
       
    24 #include <lbssatellite.h>
       
    25 #include "nmeafunctions.h"
       
    26 
       
    27 
       
    28 // $GPGGA,hhmmss.sss,llll.lllll,a,yyyyy.yyyyy,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx
       
    29 // $GPGGA size < 90 
       
    30 // In the NMEA standard the time is in hundreth of a second, but in previous code miliseconds are used
       
    31 // In the NMEA standard latitude and longitude are specified with 2 decimals, but in previous code 5 decimals were used
       
    32 _LIT8(KNmeaGga, "$GPGGA,%S,%S,%S,%d,%02d,%S,%S,%S,,");
       
    33 // hhmmss.ss
       
    34 _LIT8(KLbsNmeaUtcTimeFormat, "%02d%02d%02d.%03d");
       
    35 // llll.ll,a
       
    36 _LIT8(KLbsNmeaLatFormat, "%02u%08.5lf,%S");
       
    37 // yyyyy.yy,a
       
    38 _LIT8(KLbsNmeaLonFormat, "%03u%08.5lf,%S");
       
    39 // x.x
       
    40 _LIT8(KLbsNmeaOneDecimalFormat, "%.1f");
       
    41 // x.x,M
       
    42 _LIT8(KLbsNmeaOneDecimalMFormat, "%.1f,M");
       
    43 _LIT8(KDefaultLatLongAltBuf, ",");
       
    44 _LIT8(KLbsNmeaNorth, "N");
       
    45 _LIT8(KLbsNmeaSouth, "S");
       
    46 _LIT8(KLbsNmeaEast, "E");
       
    47 _LIT8(KLbsNmeaWest, "W");
       
    48 
       
    49 const TInt KMicrosecondToMiliseconds = 1000;
       
    50 const TInt KMinutesToADegree = 60;
       
    51 
       
    52 // $GPGLL,llll.lllll,a,yyyyy.yyyyy,a,hhmmss.sss,A,a
       
    53 // size < 50
       
    54 // In the NMEA standard the time is in hundreth of a second, but in previous code miliseconds are used
       
    55 // In the NMEA standard latitude and longitude are specified with 2 decimals, but in previous code 5 decimals were used
       
    56 _LIT8(KNmeaGll, "$GPGLL,%S,%S,%S,%S,%S");
       
    57 
       
    58 _LIT8(KLbsNmeaValidStatus, "A");
       
    59 _LIT8(KLbsNmeaValidModeIndicator, "A");
       
    60 _LIT8(KLbsNmeaInvalidStatus, "V");
       
    61 _LIT8(KLbsNmeaInvalidModeIndicator, "N");
       
    62 
       
    63 // $GPGSA,a,x,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,x.x,x.x,x.x
       
    64 // size < 60
       
    65 _LIT8(KLbsNmeaGsa, "$GPGSA,A,%d,%S,%S,%S,%S");
       
    66 
       
    67 // $GPGST,hhmmss.sss,x.x,x.x,x.x,x.x,x.x,x.x,x.x
       
    68 // size < 100
       
    69 _LIT8(KNmeaGst, "$GPGST,%S,%S,%S,%S,%S,%S,%S,%S");
       
    70 
       
    71 // $GPGSV,x,x,xx,xx,xx,xxx,xx,...,xx,xx,xxx,xx
       
    72 // size < 64
       
    73 _LIT8(KLbsNmeaGsv, "$GPGSV,%d,%d,%02d,");
       
    74 _LIT8(KLbsNmeaGsvSatInfo, "%02d,%S,%S,%02d");
       
    75 _LIT8(KLbsNmeaGsvEmptySatInfo, ",,,");
       
    76 _LIT8(KLbsNmeaElevationFormat, "%02.0f");
       
    77 _LIT8(KLbsNmeaAzimuthFormat, "%03.0f");
       
    78 
       
    79 // $GPRMC,hhmmss.sss,A,llll.lllll,a,yyyyy.yyyyy,a,x.x,x.x,ddmmyy,x.x,a,a
       
    80 // size < 50
       
    81 _LIT8(KNmeaRmc, "$GPRMC,%S,%S,%S,%S,%S,%S,%S,%S,%S");
       
    82 _LIT8(KLbsNmeaDateFormat, "%02d%02d%02d");
       
    83 _LIT8(KLbsNmeaMagneticVariationFormat, "%.1f,%S");
       
    84 
       
    85 // $GPVTG,x.x,T,x.x,M,x.x,N,x.x,K,a
       
    86 // size < 45
       
    87 _LIT8(KLbsNmeaVtg, "$GPVTG,%S,T,%S,M,%S,N,%S,K,%S");
       
    88 
       
    89 /**
       
    90   Creates an NMEA GGA string:
       
    91   $GPGGA,hhmmss.sss,llll.lllll,a,yyyyy.yyyyy,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx
       
    92   size < 90
       
    93   
       
    94   @param aTo The descriptor where the string gets written (anything inside is overwritten)
       
    95   @param aFrom The structure from which the information is taken
       
    96  */ 
       
    97 void CreateGga(TDes8& aTo, const TPositionExtendedSatelliteInfo& aFrom)
       
    98     {
       
    99     aTo.Zero();
       
   100     TPosition pos;
       
   101     aFrom.GetPosition(pos);
       
   102     
       
   103     TBuf8<10> utcTimeBuf;
       
   104     CreateUtcTimeBuffer(utcTimeBuf, pos);
       
   105     
       
   106     TBuf8<20> latBuf;
       
   107     CreateLatitudeBuffer(latBuf, pos);
       
   108     
       
   109     TBuf8<20> lonBuf;
       
   110     CreateLongitudeBuffer(lonBuf, pos);
       
   111     
       
   112     TInt quality = (!Math::IsNaN(pos.Latitude()) && !Math::IsNaN(pos.Longitude()) && !Math::IsNaN(pos.Altitude())) ? 1 : 0;
       
   113     
       
   114     TInt numSatsUsed = aFrom.NumSatellitesUsed();
       
   115     
       
   116     TBuf8<4> hdopBuf;
       
   117     CreateDoPBuffer(hdopBuf, aFrom.HorizontalDoP(), quality == 1);
       
   118     
       
   119     TReal32 geoid = aFrom.GeoidalSeparation();    
       
   120     TBuf8<9> altBuf;
       
   121     TBuf8<9> geoidBuf;
       
   122     TReal32 altitude = pos.Altitude();
       
   123     if(!Math::IsNaN(altitude) && !Math::IsNaN(geoid))
       
   124         {
       
   125         altBuf.AppendFormat(KLbsNmeaOneDecimalMFormat, altitude + geoid);
       
   126         geoidBuf.AppendFormat(KLbsNmeaOneDecimalMFormat, -geoid);
       
   127         }
       
   128     else
       
   129         {
       
   130         altBuf = KDefaultLatLongAltBuf;
       
   131         geoidBuf = KDefaultLatLongAltBuf;
       
   132         }
       
   133 
       
   134     aTo.AppendFormat(KNmeaGga, &utcTimeBuf, &latBuf, &lonBuf, quality, numSatsUsed, &hdopBuf, &altBuf, &geoidBuf);
       
   135     }
       
   136 
       
   137 /**
       
   138   Creates an NMEA GLL string:
       
   139   $GPGLL,llll.lllll,a,yyyyy.yyyyy,a,hhmmss.sss,A,a
       
   140   size < 50
       
   141   
       
   142   @param aTo The descriptor where the string gets written (anything inside is overwritten)
       
   143   @param aFrom The structure from which the information is taken
       
   144  */ 
       
   145 void CreateGll(TDes8& aTo, const TPositionExtendedSatelliteInfo& aFrom)
       
   146     {
       
   147     aTo.Zero();
       
   148     TPosition pos;
       
   149     aFrom.GetPosition(pos);
       
   150     
       
   151     TBuf8<10> utcTimeBuf;
       
   152     CreateUtcTimeBuffer(utcTimeBuf, pos);
       
   153     
       
   154     TBuf8<20> latBuf;
       
   155     CreateLatitudeBuffer(latBuf, pos);
       
   156     
       
   157     TBuf8<20> lonBuf;
       
   158     CreateLongitudeBuffer(lonBuf, pos);
       
   159 
       
   160     TBuf8<1> status;
       
   161     TBuf8<1> modeIndicator;
       
   162     
       
   163     if((!Math::IsNaN(pos.Latitude()) && !Math::IsNaN(pos.Longitude()) && !Math::IsNaN(pos.Altitude())))
       
   164         {
       
   165         status = KLbsNmeaValidStatus;
       
   166         modeIndicator = KLbsNmeaValidModeIndicator;
       
   167         }
       
   168     else
       
   169         {
       
   170         status = KLbsNmeaInvalidStatus;
       
   171         modeIndicator = KLbsNmeaInvalidModeIndicator;
       
   172         }
       
   173     
       
   174     aTo.AppendFormat(KNmeaGll, &latBuf, &lonBuf, &utcTimeBuf, &status, &modeIndicator);
       
   175     }
       
   176 
       
   177 /**
       
   178   Creates an NMEA GSA string:
       
   179   $GPGSA,a,x,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,x.x,x.x,x.x
       
   180   size < 60
       
   181   
       
   182   @param aTo The descriptor where the string gets written (anything inside is overwritten)
       
   183   @param aFrom The structure from which the information is taken
       
   184  */ 
       
   185 void CreateGsa(TDes8& aTo, const TPositionExtendedSatelliteInfo& aFrom)
       
   186     {
       
   187     aTo.Zero();
       
   188     TPosition pos;
       
   189     aFrom.GetPosition(pos);
       
   190     
       
   191     TInt fixType = 1;
       
   192     
       
   193     if(!Math::IsNaN(pos.Latitude()) && !Math::IsNaN(pos.Longitude()))
       
   194             {
       
   195             if(!Math::IsNaN(pos.Altitude()))
       
   196                 {
       
   197                 fixType = 3;
       
   198                 }
       
   199             else
       
   200                 {
       
   201                 fixType = 2;
       
   202                 }
       
   203             }
       
   204     
       
   205     TBuf8<36> usedSatsBuffer;
       
   206     // because there can be more than 12 satellites in view we want to make sure the ones used
       
   207     // are being recorded
       
   208     // so the spaces left to fill will be checked against the remaining satellites in view
       
   209     // in order to decide if an empty field will be added
       
   210     TInt spacesLeft = 12;
       
   211     TInt satsInView = aFrom.NumSatellitesInView();
       
   212     // add sattelite data only if the fix is avaialable. Make sure exactly 12 spaces get filled
       
   213     TSatelliteData satData;
       
   214     for(TInt index = 0; (index < satsInView) && (fixType > 1) && (spacesLeft > 0); ++index)
       
   215         {
       
   216         aFrom.GetSatelliteData(index, satData);
       
   217         // add satellite data if satellite is used, otherwise insert blank field
       
   218         if(satData.IsUsed())
       
   219             {
       
   220             usedSatsBuffer.AppendNumFixedWidth(satData.SatelliteId(), EDecimal, 2);
       
   221             --spacesLeft;
       
   222             if(spacesLeft > 0)
       
   223                 {
       
   224                 // only add , if it's not the last element to be added
       
   225                 usedSatsBuffer.Append(',');
       
   226                 }
       
   227             }
       
   228         else if(spacesLeft >= satsInView - index)
       
   229             {
       
   230             --spacesLeft;
       
   231             if(spacesLeft > 0)
       
   232                 {
       
   233                 // only add , if it's not the last element to be added
       
   234                 usedSatsBuffer.Append(',');
       
   235                 }
       
   236             }
       
   237         }
       
   238     // fill the rest of the fields
       
   239     while(spacesLeft > 0)
       
   240         {
       
   241         --spacesLeft;
       
   242         if(spacesLeft > 0)
       
   243             {
       
   244             // only add , if it's not the last element to be added
       
   245             usedSatsBuffer.Append(',');
       
   246             }
       
   247         }
       
   248 
       
   249     TBuf8<4> pdopBuf;
       
   250     TReal64 pdop;
       
   251     TReal64 hdop = aFrom.HorizontalDoP();
       
   252     TReal64 vdop = aFrom.VerticalDoP();
       
   253     if(!Math::IsNaN(hdop) && !Math::IsNaN(vdop))
       
   254         {
       
   255         Math::Sqrt(pdop, hdop*hdop + vdop*vdop);
       
   256         }
       
   257     else
       
   258         {
       
   259         TRealX nan;
       
   260         nan.SetNaN();
       
   261         pdop = nan;
       
   262         }
       
   263     CreateDoPBuffer(pdopBuf, pdop, fixType > 1);
       
   264 
       
   265     TBuf8<4> hdopBuf;
       
   266     CreateDoPBuffer(hdopBuf, hdop, fixType > 1);
       
   267 
       
   268     TBuf8<4> vdopBuf;
       
   269     CreateDoPBuffer(vdopBuf, vdop, fixType > 1);
       
   270 
       
   271     aTo.AppendFormat(KLbsNmeaGsa, fixType, &usedSatsBuffer, &pdopBuf, &hdopBuf, &vdopBuf);
       
   272     }
       
   273 
       
   274 /**
       
   275   Creates an NMEA GST string:
       
   276   $GPGST,hhmmss.sss,x.x,x.x,x.x,x.x,x.x,x.x,x.x
       
   277   size < 100
       
   278   
       
   279   @param aTo The descriptor where the string gets written (anything inside is overwritten)
       
   280   @param aFrom The structure from which the information is taken
       
   281  */ 
       
   282 void CreateGst(TDes8& aTo, const TPositionExtendedSatelliteInfo& aFrom)
       
   283     {
       
   284     aTo.Zero();
       
   285     TPosition pos;
       
   286     aFrom.GetPosition(pos);
       
   287     
       
   288     TBuf8<10> utcTimeBuf;
       
   289     CreateUtcTimeBuffer(utcTimeBuf, pos);
       
   290     
       
   291     TDetailedErrorReport errorReport;
       
   292     aFrom.GetDetailedErrorReport(errorReport);
       
   293     
       
   294     TBuf8<10> rmsValueBuffer;
       
   295     TReal32 value = errorReport.RmsValOfStanDeviOfRange();
       
   296     if(!Math::IsNaN(value))
       
   297         {
       
   298         rmsValueBuffer.AppendFormat(KLbsNmeaOneDecimalMFormat, value);
       
   299         }
       
   300     else
       
   301         {
       
   302         rmsValueBuffer = KNullDesC8;
       
   303         }
       
   304 
       
   305     TBuf8<10> deviSemiMajorAxisBuffer;
       
   306     value = errorReport.StanDeviOfSemiMajorAxisError();
       
   307     if(!Math::IsNaN(value))
       
   308         {
       
   309         deviSemiMajorAxisBuffer.AppendFormat(KLbsNmeaOneDecimalMFormat, value);
       
   310         }
       
   311     else
       
   312         {
       
   313         deviSemiMajorAxisBuffer = KNullDesC8;
       
   314         }
       
   315 
       
   316     TBuf8<10> deviSemiMinorAxisBuffer;
       
   317     value = errorReport.StanDeviOfSemiMinorAxisError();
       
   318     if(!Math::IsNaN(value))
       
   319         {
       
   320         deviSemiMinorAxisBuffer.AppendFormat(KLbsNmeaOneDecimalMFormat, value);
       
   321         }
       
   322     else
       
   323         {
       
   324         deviSemiMinorAxisBuffer = KNullDesC8;
       
   325         }
       
   326 
       
   327     TBuf8<10> orientationSemiMjorAxisBuffer;
       
   328     value = errorReport.OrientationOfSemiMajorAxisError();
       
   329     if(!Math::IsNaN(value))
       
   330         {
       
   331         orientationSemiMjorAxisBuffer.AppendFormat(KLbsNmeaOneDecimalMFormat, value);
       
   332         }
       
   333     else
       
   334         {
       
   335         orientationSemiMjorAxisBuffer = KNullDesC8;
       
   336         }
       
   337 
       
   338     TBuf8<10> deviLatitudeBuffer;
       
   339     value = errorReport.StanDeviOfLatiitudeError();
       
   340     if(!Math::IsNaN(value))
       
   341         {
       
   342         deviLatitudeBuffer.AppendFormat(KLbsNmeaOneDecimalMFormat, value);
       
   343         }
       
   344     else
       
   345         {
       
   346         deviLatitudeBuffer = KNullDesC8;
       
   347         }
       
   348 
       
   349     TBuf8<10> deviLongitudeBuffer;
       
   350     value = errorReport.StanDeviOfLongitudeError();
       
   351     if(!Math::IsNaN(value))
       
   352         {
       
   353         deviLongitudeBuffer.AppendFormat(KLbsNmeaOneDecimalMFormat, value);
       
   354         }
       
   355     else
       
   356         {
       
   357         deviLongitudeBuffer = KNullDesC8;
       
   358         }
       
   359 
       
   360     TBuf8<10> deviAltitudeBuffer;
       
   361     value = errorReport.StanDeviOfAltitudeError();
       
   362     if(!Math::IsNaN(value))
       
   363         {
       
   364         deviAltitudeBuffer.AppendFormat(KLbsNmeaOneDecimalMFormat, value);
       
   365         }
       
   366     else
       
   367         {
       
   368         deviAltitudeBuffer = KNullDesC8;
       
   369         }
       
   370 
       
   371 
       
   372     aTo.AppendFormat(KNmeaGst, &utcTimeBuf, &rmsValueBuffer, &deviSemiMajorAxisBuffer, 
       
   373             &deviSemiMinorAxisBuffer, &orientationSemiMjorAxisBuffer, &deviLatitudeBuffer, 
       
   374             &deviLongitudeBuffer, &deviAltitudeBuffer);
       
   375     }
       
   376 
       
   377 
       
   378 /**
       
   379   Creates an NMEA GSV string (next one in sequence based on the sentences done so far. This 
       
   380   method should be called repeatedly, until all sentences have been written.
       
   381   $GPGSV,x,x,xx,xx,xx,xxx,xx,...,xx,xx,xxx,xx
       
   382   size < 64
       
   383   
       
   384   @param aTo The descriptor where the string gets written (anything inside is overwritten)
       
   385   @param aFrom The structure from which the information is taken
       
   386   @param aTotalSentences This is where the method writes the total number of sentences required
       
   387   @param aLastSentence This is where the method writes the value of the latest created sentence
       
   388  */ 
       
   389 void CreateGsv(TDes8& aTo, const TPositionExtendedSatelliteInfo& aFrom, TInt& aTotalSentences, TInt& aLastSentence)
       
   390     {
       
   391     aTo.Zero();
       
   392     TInt satsInView = aFrom.NumSatellitesInView();
       
   393     aTotalSentences = (satsInView+3)/4;
       
   394     ++aLastSentence;
       
   395     aTo.AppendFormat(KLbsNmeaGsv, aTotalSentences, aLastSentence, satsInView);
       
   396     
       
   397     for(TInt index = (aLastSentence-1)*4; index < aLastSentence*4; ++index)
       
   398         {
       
   399         if(index < satsInView)
       
   400             {
       
   401             TSatelliteData satData;
       
   402             aFrom.GetSatelliteData(index, satData);
       
   403             TBuf8<2> elevationBuffer;
       
   404             if(!Math::IsNaN(satData.Elevation()))
       
   405                 {
       
   406                 elevationBuffer.AppendFormat(KLbsNmeaElevationFormat, satData.Elevation());
       
   407                 }
       
   408             else
       
   409                 {
       
   410                 elevationBuffer = KNullDesC8;
       
   411                 }
       
   412 
       
   413             TBuf8<3> azimuthBuffer;
       
   414             if(!Math::IsNaN(satData.Azimuth()))
       
   415                 {
       
   416                 azimuthBuffer.AppendFormat(KLbsNmeaAzimuthFormat, satData.Azimuth());
       
   417                 }
       
   418             else
       
   419                 {
       
   420                 azimuthBuffer = KNullDesC8;
       
   421                 }
       
   422             TBuf8<12> satInfoBuffer;
       
   423             satInfoBuffer.AppendFormat(KLbsNmeaGsvSatInfo, satData.SatelliteId(), 
       
   424                     &elevationBuffer, &azimuthBuffer, satData.SignalStrength());
       
   425             aTo.Append(satInfoBuffer);
       
   426             }
       
   427         else
       
   428             {
       
   429             aTo.Append(KLbsNmeaGsvEmptySatInfo);
       
   430             }
       
   431         if(index < aLastSentence*4 - 1)
       
   432             {
       
   433             aTo.Append(',');
       
   434             }
       
   435         }
       
   436     }
       
   437 
       
   438 /**
       
   439   Creates an NMEA RMC string:
       
   440   $GPRMC,hhmmss.sss,A,llll.lllll,a,yyyyy.yyyyy,a,x.x,x.x,ddmmyy,x.x,a,a
       
   441   size < 50
       
   442   
       
   443   @param aTo The descriptor where the string gets written (anything inside is overwritten)
       
   444   @param aFrom The structure from which the information is taken
       
   445  */ 
       
   446 void CreateRmc(TDes8& aTo, const TPositionExtendedSatelliteInfo& aFrom)
       
   447     {
       
   448     aTo.Zero();
       
   449     TPosition pos;
       
   450     aFrom.GetPosition(pos);
       
   451     
       
   452     TBuf8<10> utcTimeBuf;
       
   453     CreateUtcTimeBuffer(utcTimeBuf, pos);
       
   454     
       
   455     TBuf8<20> latBuf;
       
   456     CreateLatitudeBuffer(latBuf, pos);
       
   457     
       
   458     TBuf8<20> lonBuf;
       
   459     CreateLongitudeBuffer(lonBuf, pos);
       
   460     
       
   461     TBuf8<1> status;
       
   462     TBuf8<1> modeIndicator;
       
   463     if((!Math::IsNaN(pos.Latitude()) && !Math::IsNaN(pos.Longitude()) && !Math::IsNaN(pos.Altitude())))
       
   464         {
       
   465         status = KLbsNmeaValidStatus;
       
   466         modeIndicator = KLbsNmeaValidModeIndicator;
       
   467         }
       
   468     else
       
   469         {
       
   470         status = KLbsNmeaInvalidStatus;
       
   471         modeIndicator = KLbsNmeaInvalidModeIndicator;
       
   472         }
       
   473     
       
   474     TCourse course;
       
   475     aFrom.GetCourse(course);
       
   476     
       
   477     TBuf8<10> speedBuf;
       
   478     CreateSpeedBuffer(speedBuf, course);
       
   479     
       
   480     TBuf8<10> headingBuf;
       
   481     CreateHeadingBuffer(headingBuf, course);
       
   482 
       
   483     TBuf8<6> dateBuf;
       
   484     TDateTime date(pos.Time().DateTime());
       
   485     dateBuf.AppendFormat(KLbsNmeaDateFormat, date.Day(), date.Month()+1, date.Year() % 100);
       
   486     
       
   487     TBuf8<6> magneticVariationBuf;
       
   488     TReal32 magneticVariation = aFrom.MagneticVariation();
       
   489     if(!Math::IsNaN(magneticVariation))
       
   490         {
       
   491         TBuf8<1> direction;
       
   492         if(magneticVariation >= 0)
       
   493             {
       
   494             direction = KLbsNmeaEast;
       
   495             }
       
   496         else
       
   497             {
       
   498             direction = KLbsNmeaWest;
       
   499             magneticVariation = -magneticVariation;
       
   500             }
       
   501         magneticVariationBuf.AppendFormat(KLbsNmeaMagneticVariationFormat, magneticVariation, &direction);
       
   502         }
       
   503     else
       
   504         {
       
   505         magneticVariationBuf = KDefaultLatLongAltBuf;
       
   506         }    
       
   507     
       
   508     aTo.AppendFormat(KNmeaRmc, &utcTimeBuf, &status, &latBuf, &lonBuf, &speedBuf, 
       
   509             &headingBuf, &dateBuf, &magneticVariationBuf, &modeIndicator);
       
   510     }
       
   511 
       
   512 /**
       
   513   Creates an NMEA VTG string:
       
   514   $GPVTG,x.x,T,x.x,M,x.x,N,x.x,K,a
       
   515   size < 45
       
   516   
       
   517   @param aTo The descriptor where the string gets written (anything inside is overwritten)
       
   518   @param aFrom The structure from which the information is taken
       
   519  */ 
       
   520 void CreateVtg(TDes8& aTo, const TPositionExtendedSatelliteInfo& aFrom)
       
   521     {
       
   522     aTo.Zero();
       
   523     TCourse course;
       
   524     aFrom.GetCourse(course);
       
   525     
       
   526     TBuf8<10> headingBuf;
       
   527     CreateHeadingBuffer(headingBuf, course);
       
   528     
       
   529     TBuf8<10> courseDegreesMagneticBuf;
       
   530     if(!Math::IsNaN(aFrom.CourseOverGroundMagnetic()))
       
   531         {
       
   532         courseDegreesMagneticBuf.AppendFormat(KLbsNmeaOneDecimalFormat, aFrom.CourseOverGroundMagnetic());
       
   533         }
       
   534     else
       
   535         {
       
   536         courseDegreesMagneticBuf = KNullDesC8;
       
   537         }
       
   538 
       
   539     TBuf8<10> speedBuf;
       
   540     CreateSpeedBuffer(speedBuf, course);
       
   541     
       
   542     TBuf8<10> speedKmHBuf;
       
   543     if(!Math::IsNaN(course.Speed()))
       
   544         {
       
   545         speedKmHBuf.AppendFormat(KLbsNmeaOneDecimalFormat, course.Speed()*3.6);
       
   546         }
       
   547     else
       
   548         {
       
   549         speedKmHBuf = KNullDesC8;
       
   550         }
       
   551     TBuf8<1> modeIndicator;
       
   552     if(!Math::IsNaN(course.Speed()) && !Math::IsNaN(course.Heading()))
       
   553         {
       
   554         modeIndicator = KLbsNmeaValidModeIndicator;
       
   555         }
       
   556     else
       
   557         {
       
   558         modeIndicator = KLbsNmeaInvalidModeIndicator;
       
   559         }
       
   560     
       
   561     aTo.AppendFormat(KLbsNmeaVtg, &headingBuf, &courseDegreesMagneticBuf, &speedBuf, &speedKmHBuf, &modeIndicator);
       
   562     }
       
   563 
       
   564 /**
       
   565   Helper for creating part of an NMEA string: UTC time
       
   566   
       
   567   @param aBuffer The descriptor where the string gets written
       
   568   @param aPos The structure from which the information is taken
       
   569  */ 
       
   570 void CreateUtcTimeBuffer(TDes8& aBuffer, const TPosition& aPos)
       
   571     {
       
   572     TDateTime utcDateTime(aPos.Time().DateTime());
       
   573     aBuffer.AppendFormat(KLbsNmeaUtcTimeFormat, utcDateTime.Hour(), utcDateTime.Minute(), utcDateTime.Second(), utcDateTime.MicroSecond()/KMicrosecondToMiliseconds);
       
   574     }
       
   575 
       
   576 /**
       
   577   Helper for creating part of an NMEA string: Latitude
       
   578   
       
   579   @param aBuffer The descriptor where the string gets written
       
   580   @param aPos The structure from which the information is taken
       
   581  */ 
       
   582 void CreateLatitudeBuffer(TDes8& aBuffer, const TPosition& aPos)
       
   583     {
       
   584     TReal64 latitude = aPos.Latitude();
       
   585     if(!Math::IsNaN(latitude))
       
   586         {
       
   587         TBuf8<1> latDirection;
       
   588         if(latitude >= 0)
       
   589             {
       
   590             latDirection = KLbsNmeaNorth;
       
   591             }
       
   592         else
       
   593             {
       
   594             latDirection = KLbsNmeaSouth;
       
   595             latitude = -latitude;
       
   596             }
       
   597         TInt latDegrees = latitude;
       
   598         TReal64 latMinutes = (latitude - latDegrees) * KMinutesToADegree;
       
   599         __ASSERT_DEBUG((latDegrees >= 0) && (latDegrees <= 90) && (latMinutes >= 0) && (latMinutes < 60), User::Invariant());
       
   600         aBuffer.AppendFormat(KLbsNmeaLatFormat, latDegrees, latMinutes, &latDirection);
       
   601         }
       
   602     else
       
   603         {
       
   604         aBuffer = KDefaultLatLongAltBuf;
       
   605         }    
       
   606     }
       
   607 
       
   608 /**
       
   609   Helper for creating part of an NMEA string: Longitude
       
   610   
       
   611   @param aBuffer The descriptor where the string gets written
       
   612   @param aPos The structure from which the information is taken
       
   613  */ 
       
   614 void CreateLongitudeBuffer(TDes8& aBuffer, const TPosition& aPos)
       
   615     {
       
   616     TReal64 longitude = aPos.Longitude();
       
   617     if(!Math::IsNaN(longitude))
       
   618         {
       
   619         TBuf8<1> lonDirection;
       
   620         if(longitude >= 0)
       
   621             {
       
   622             lonDirection = KLbsNmeaEast;
       
   623             }
       
   624         else
       
   625             {
       
   626             lonDirection = KLbsNmeaWest;
       
   627             longitude = -longitude;
       
   628             }
       
   629         TInt lonDegrees = longitude;
       
   630         TReal64 lonMinutes = (longitude - lonDegrees) * KMinutesToADegree;
       
   631         __ASSERT_DEBUG((lonDegrees >= 0) && (lonDegrees <= 180) && (lonMinutes >= 0) && (lonMinutes < 60), User::Invariant());
       
   632         aBuffer.AppendFormat(KLbsNmeaLonFormat, lonDegrees, lonMinutes, &lonDirection);
       
   633         }
       
   634     else
       
   635         {
       
   636         aBuffer = KDefaultLatLongAltBuf;
       
   637         }    
       
   638     }
       
   639 
       
   640 /**
       
   641   Helper for creating part of an NMEA string: Dilution of Precision
       
   642   
       
   643   @param aBuffer The descriptor where the string gets written
       
   644   @param aDop The structure from which the information is taken
       
   645   @param aValidFix Specifies if the fix is valid or not
       
   646  */ 
       
   647 void CreateDoPBuffer(TDes8& aBuffer, TReal32 aDop, TBool aValidFix)
       
   648     {
       
   649     if(aValidFix && !Math::IsNaN(aDop))
       
   650         {
       
   651         aBuffer.AppendFormat(KLbsNmeaOneDecimalFormat, aDop);
       
   652         }
       
   653     else
       
   654         {
       
   655         aBuffer = KNullDesC8;
       
   656         }    
       
   657     }
       
   658 
       
   659 /**
       
   660   Helper for creating part of an NMEA string: speed
       
   661   
       
   662   @param aBuffer The descriptor where the string gets written
       
   663   @param aCourse The structure from which the information is taken
       
   664  */ 
       
   665 void CreateSpeedBuffer(TDes8& aBuffer, const TCourse& aCourse)
       
   666     {
       
   667     if(!Math::IsNaN(aCourse.Speed()))
       
   668         {
       
   669         aBuffer.AppendFormat(KLbsNmeaOneDecimalFormat, aCourse.Speed()*1.94384);
       
   670         }
       
   671     else
       
   672         {
       
   673         aBuffer = KNullDesC8;
       
   674         }    
       
   675     }
       
   676 
       
   677 /**
       
   678   Helper for creating part of an NMEA string: heading
       
   679   
       
   680   @param aBuffer The descriptor where the string gets written
       
   681   @param aCourse The structure from which the information is taken
       
   682  */ 
       
   683 void CreateHeadingBuffer(TDes8& aBuffer, const TCourse& aCourse)
       
   684     {
       
   685     if(!Math::IsNaN(aCourse.Heading()))
       
   686         {
       
   687         aBuffer.AppendFormat(KLbsNmeaOneDecimalFormat, aCourse.Heading());
       
   688         }
       
   689     else
       
   690         {
       
   691         aBuffer = KNullDesC8;
       
   692         }
       
   693     }
       
   694 //