18 #define GPS_MAX_NMEA_SENTENCE 128
23 static gpsData_t gpsData;
24 static xSemaphoreHandle semaphore;
29 static void gpsNormalizeNMEA (char *s);
30 static unsigned char gpsChecksumNMEA (char *sz);
31 static void gpsHandlerGGA (char *nmeaSentence);
32 static void gpsHandlerRMC (char *nmeaSentence);
33 static void gpsHandlerRestart (char *nmeaSentence);
34 static void gpsDispatchMessages (char *nmeaSentence);
35 static int gpsProcessByte (unsigned char c, char *nmeaSentence);
40 static void gpsNormalizeNMEA (char *s)
44 while (*s && *s != '*')
46 if (*s == ',' && (*(s + 1) == ',' || *(s + 1) == '*'))
51 memmove (s + 3, s + 1, l);
67 static unsigned char gpsChecksumNMEA (char *sz)
72 for (cs = 0, i = 1; sz [i] && sz [i] != '*'; i++)
73 cs ^= ((unsigned char) sz [i]);
81 static void gpsHandlerGGA (char *nmeaSentence)
85 double latitude = 0.0, longitude = 0.0;
86 char latitudeSign = 0, longitudeSign = 0;
88 if (sscanf (nmeaSentence, "%*f,%lf,%c,%lf,%c,%c,%*d,%*f,%lf", &latitude, &latitudeSign, &longitude, &longitudeSign, &valid, &height) == 6)
90 if (xSemaphoreTake (semaphore, portMAX_DELAY) == pdTRUE)
92 gpsData.valid = (valid - '0');
93 gpsData.height = height;
94 gpsData.latitude = latitude * (latitudeSign == 'N' ? 1.0 : -1.0);
95 gpsData.longitude = longitude * (longitudeSign == 'E' ? 1.0 : -1.0);
97 xSemaphoreGive (semaphore);
102 static void gpsHandlerRMC (char *nmeaSentence)
105 int gpsdate, gpstime;
107 if (sscanf (nmeaSentence, "%d.%*d,%*c,%*f,%*c,%*f,%*c,%f,%f,%d", &gpstime, &speed, &course, &gpsdate) == 4)
109 if (xSemaphoreTake (semaphore, portMAX_DELAY) == pdTRUE)
111 gpsData.utcDay = gpsdate / 10000;
112 gpsData.utcMonth = (gpsdate / 100) % 100;
113 gpsData.utcYear = (gpsdate % 100) + 2000;
114 gpsData.utcHours = gpstime / 10000;
115 gpsData.utcMinutes = (gpstime / 100) % 100;
116 gpsData.utcSeconds = gpstime % 100;
117 gpsData.groundSpeed = speed;
118 gpsData.trueCourse = course;
120 xSemaphoreGive (semaphore);
125 static void gpsHandlerRestart (char *nmeaSentencemea __attribute__ ((unused)))
127 if (xSemaphoreTake (semaphore, portMAX_DELAY) == pdTRUE)
130 xSemaphoreGive (semaphore);
137 typedef struct nmeaDispatch_s
139 const char *sentence;
141 void (*handler) (char *sentence);
146 static const nmeaDispatch_t nmeaDispatch [] =
148 { "$GPGGA", 6, gpsHandlerGGA, 1 },
149 { "$GPRMC", 6, gpsHandlerRMC, 1 },
150 { "$HW Type", 8, gpsHandlerRestart, 0 },
154 static void gpsDispatchMessages (char *nmeaSentence)
158 for (i = 0; nmeaDispatch [i].handler; i++)
160 if (!strncmp (nmeaDispatch [i].sentence, nmeaSentence, nmeaDispatch [i].length))
162 if (nmeaDispatch [i].normalize)
164 gpsNormalizeNMEA (&nmeaSentence [7]);
165 (*nmeaDispatch [i].handler) (&nmeaSentence [7]);
168 (*nmeaDispatch [i].handler) (NULL);
178 static int gpsProcessByte (unsigned char c, char *nmeaSentence)
181 static short state = 0;
182 static short pos = 0;
191 nmeaSentence [pos++] = '$';
192 nmeaSentence [pos] = '\0';
202 if (pos < GPS_MAX_NMEA_SENTENCE)
210 if ((s = strchr (nmeaSentence, '*')))
214 if (sscanf (s + 1, "%x", &cksum) == 1)
216 if (gpsChecksumNMEA (nmeaSentence) == cksum)
220 fprintf (stderr, "NMEA checksum error: got 0x%02x, want %s", cksum, s);
223 fprintf (stderr, "NMEA checksum not found: \"%s\"", nmeaSentence);
227 nmeaSentence [pos++] = c;
228 nmeaSentence [pos] = '\0';
241 // Return 1 if got a copy, 0 if not.
243 int gpsCopyData (gpsData_t *dst)
245 #ifndef CFG_CONSOLE_UART1
246 if (xSemaphoreTake (semaphore, 100 / portTICK_RATE_MS) == pdTRUE)
248 memcpy (dst, &gpsData, sizeof (gpsData_t));
249 xSemaphoreGive (semaphore);
254 memset (dst, 0, sizeof (gpsData_t));
261 portTASK_FUNCTION (vGPSTask, pvParameters __attribute__ ((unused)))
264 static char nmeaSentence [GPS_MAX_NMEA_SENTENCE];
266 memset (&gpsData, 0, sizeof (gpsData));
268 vSemaphoreCreateBinary (semaphore);
270 fd = open ("/dev/uart1", O_RDONLY);
272 if ((fd == -1) || (semaphore == NULL))
280 if (read (fd, &c, sizeof (c)) == sizeof (c))
281 if (gpsProcessByte (c, nmeaSentence))
282 gpsDispatchMessages (nmeaSentence);