1 /***************************************************************************
2  *
3  * Project:  OpenCPN
4  * Purpose:  NMEA0183 Support Classes
5  * Author:   Samuel R. Blackburn, David S. Register
6  *
7  ***************************************************************************
8  *   Copyright (C) 2010 by Samuel R. Blackburn, David S Register           *
9  *                                                                         *
10  *   This program is free software; you can redistribute it and/or modify  *
11  *   it under the terms of the GNU General Public License as published by  *
12  *   the Free Software Foundation; either version 2 of the License, or     *
13  *   (at your option) any later version.                                   *
14  *                                                                         *
15  *   This program is distributed in the hope that it will be useful,       *
16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  *   GNU General Public License for more details.                          *
19  *                                                                         *
20  *   You should have received a copy of the GNU General Public License     *
21  *   along with this program; if not, write to the                         *
22  *   Free Software Foundation, Inc.,                                       *
23  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,  USA.             *
24  ***************************************************************************
25  *
26  *   S Blackburn's original source license:                                *
27  *         "You can use it any way you like."                              *
28  *   More recent (2010) license statement:                                 *
29  *         "It is BSD license, do with it what you will"                   *
30  */
31 
32 
33 #include "nmea0183.h"
34 //#pragma hdrstop
35 
36 /*
37 ** Author: Samuel R. Blackburn
38 ** CI$: 76300,326
39 ** Internet: sammy@sed.csc.com
40 **
41 ** You can use it any way you like.
42 */
43 
44 //IMPLEMENT_DYNAMIC( GLL, RESPONSE )
45 
GLL()46 GLL::GLL()
47 {
48    Mnemonic = _T("GLL");
49    Empty();
50 }
51 
~GLL()52 GLL::~GLL()
53 {
54    Mnemonic.Empty();
55    Empty();
56 }
57 
Empty(void)58 void GLL::Empty( void )
59 {
60 //   ASSERT_VALID( this );
61 
62    Position.Empty();
63    UTCTime.Empty();
64    IsDataValid = Unknown0183;
65 }
66 
Parse(const SENTENCE & sentence)67 bool GLL::Parse( const SENTENCE& sentence )
68 {
69 //   ASSERT_VALID( this );
70 
71    /*
72    ** GLL - Geographic Position - Latitude/Longitude
73    ** Latitude, N/S, Longitude, E/W, UTC, Status
74    **
75    **        +-------------------------------- 1) Latitude
76    **        |       +------------------------ 2) N or S (North or South)
77    **        |       | +---------------------- 3) Longitude
78    **        |       | |        +------------- 4) E or W (East or West)
79    **        |       | |        | +----------- 5) Universal Time Coordinated (UTC)
80    **        |       | |        | |         +- 6) Status A - Data Valid, V - Data Invalid
81    **        |       | |        | |         | +7) Checksum
82    ** $--GLL,llll.ll,a,yyyyy.yy,a,hhmmss.ss,A*hh<CR><LF>
83    */
84 
85    /*
86    ** First we check the checksum...
87    */
88 
89       int target_field_count = 6;
90 
91       NMEA0183_BOOLEAN check = sentence.IsChecksumBad( 7 );
92 
93       if ( check == NTrue )
94       {
95 
96   /*
97             ** This may be an NMEA Version 2.3 sentence, with "Mode" field
98   */
99             wxString checksum_in_sentence = sentence.Field( 7 );
100             if(checksum_in_sentence.StartsWith(_T("*")))       // Field is a valid erroneous checksum
101             {
102                   SetErrorMessage( _T("Invalid Checksum") );
103                   return( FALSE );
104             }
105 
106             else
107             {
108                   target_field_count = 7;
109                   check = sentence.IsChecksumBad( 8 );
110                   if( check == NTrue)
111                   {
112                         SetErrorMessage( _T("Invalid Checksum") );
113                         return( FALSE );
114                   }
115             }
116       }
117 
118 
119       if ( sentence.GetNumberOfDataFields() == target_field_count )
120       {
121             Position.Parse( 1, 2, 3, 4, sentence );
122             UTCTime     = sentence.Field( 5 );
123             IsDataValid = sentence.Boolean( 6 );
124 
125             return( TRUE );
126       }
127 
128       //    May be old style GLL sentence
129       if ( sentence.GetNumberOfDataFields() == 4 )
130       {
131             Position.Parse( 1, 2, 3, 4, sentence );
132             IsDataValid = NTrue;
133 
134             return( TRUE );
135       }
136 
137       //    A real error...
138       SetErrorMessage( _T("Invalid FieldCount") );
139       return( FALSE );
140 }
141 
142 
PlainEnglish(void)143 const wxString& GLL::PlainEnglish( void )
144 {
145 //   ASSERT_VALID( this );
146 
147    static wxString return_string;
148 
149    return_string.Empty();
150 /*
151    char temp_string[ 128 ];
152 
153    sprintf( temp_string, "At %d, you were at Latitude %ld %s, Longitude %ld %s.",
154             (const char *) UTCTime,
155             Position.Latitude.Latitude,
156             ( Position.Latitude.Northing == North ) ? "North" : "South",
157             Position.Longitude.Longitude,
158             ( Position.Longitude.Easting == East ) ? "East" : "West" );
159 
160    return_string = temp_string;
161 */
162    return( return_string );
163 }
164 
165 
Write(SENTENCE & sentence)166 bool GLL::Write( SENTENCE& sentence )
167 {
168 //   ASSERT_VALID( this );
169 
170    /*
171    ** Let the parent do its thing
172    */
173 
174    RESPONSE::Write( sentence );
175 
176    sentence += Position;
177    sentence += UTCTime;
178    sentence += IsDataValid;
179 
180    sentence.Finish();
181 
182    return( TRUE );
183 }
184 
operator =(const GLL & source)185 const GLL& GLL::operator = ( const GLL& source )
186 {
187 //   ASSERT_VALID( this );
188 
189    Position    = source.Position;
190    UTCTime     = source.UTCTime;
191    IsDataValid = source.IsDataValid;
192 
193    return( *this );
194 }
195