--- /dev/null
+/**
+ * \file
+ * <!--
+ * This file is part of BeRTOS.
+ *
+ * Bertos is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * As a special exception, you may use this file as part of a free software
+ * library without restriction. Specifically, if other files instantiate
+ * templates or use macros or inline functions from this file, or you compile
+ * this file and link it with other files to produce an executable, this
+ * file does not by itself cause the resulting executable to be covered by
+ * the GNU General Public License. This exception does not however
+ * invalidate any other reasons why the executable file might be covered by
+ * the GNU General Public License.
+ *
+ * Copyright 2009 Develer S.r.l. (http://www.develer.com/)
+ *
+ * -->
+ * \brief NMEA implementation.
+ *
+ * \author Daniele Basile <asterix@develer.com>
+ *
+ */
+
+#include "nmea.h"
+
+#include "cfg/cfg_nmea.h"
+
+#include <cfg/debug.h>
+
+#define LOG_LEVEL NMEA_LOG_LEVEL
+#define LOG_FORMAT NMEA_LOG_FORMAT
+#include <cfg/log.h>
+
+#include <net/nmeap/inc/nmeap.h>
+
+#include <ctype.h>
+
+
+static uint32_t tokenToInt(const char *s)
+{
+ uint32_t num = 0;
+ int i;
+
+ ASSERT(s);
+
+ for(i = 0; i < NMEAP_MAX_TOKENS; i++)
+ {
+ char c = *s++;
+
+ if (c == '.')
+ continue;
+
+ if (c == '\0' || !isdigit(c))
+ break;
+
+ num *= 10;
+ num += c - '0';
+ }
+
+ return num;
+}
+
+
+static udegree_t nmea_latitude(const char *plat, const char *phem)
+{
+ int ns;
+ uint32_t lat;
+ uint32_t deg;
+ uint32_t min;
+
+ if (*plat == 0)
+ {
+ return 0;
+ }
+ if (*phem == 0)
+ {
+ return 0;
+ }
+
+ /* north lat is +, south lat is - */
+ if (*phem == 'N')
+ {
+ ns = 1;
+ }
+ else
+ {
+ ns = -1;
+ }
+
+ lat = tokenToInt(plat);
+ deg = lat / 1000000;
+ min = lat - deg * 1000000;
+ lat = deg * 1000000 + ((min * 5) + 1) / 3;
+
+ return ns * lat;
+}
+
+static udegree_t nmea_longitude(const char *plot, const char *phem)
+{
+ int ew;
+ uint32_t lot;
+ uint32_t deg;
+ uint32_t min;
+
+ if (*plot == 0)
+ {
+ return 0;
+ }
+ if (*phem == 0)
+ {
+ return 0;
+ }
+
+ /* west long is negative, east long is positive */
+ if (*phem == 'E')
+ {
+ ew = 1;
+ }
+ else {
+ ew = -1;
+ }
+
+ lot = tokenToInt(plot);
+ deg = lot / 1000000;
+ min = lot - deg * 1000000;
+ lot = deg * 1000000 + ((min * 5) + 1) / 3;
+
+ return ew * lot;
+}
+
+static cm_t nmea_altitude(const char *palt, const char *punits)
+{
+ uint32_t alt;
+
+ if (*palt == 0)
+ {
+ return 0;
+ }
+
+ alt = tokenToInt(palt);
+
+ if (*punits == 'F')
+ {
+ /* convert to feet */
+ /* alt = alt * 3.2808399 */
+ alt = alt * 3 + /* 3.0 */
+ (alt >> 2) + /* 0.25 */
+ (alt >> 6) + /* 0.015625 */
+ (alt >> 7) + /* 0.0078125 */
+ (alt >> 8); /* 0,00390625 */
+
+ }
+
+ return alt;
+}
+
+/**
+ * standard GPGGA sentence parser
+ */
+int nmea_gpgga(nmeap_context_t *context, nmeap_sentence_t *sentence)
+{
+ /*
+ * get pointer to sentence data
+ */
+ NmeaGga *gga = (NmeaGga *)sentence->data;
+
+ /*
+ * if there is a data element, extract data from the tokens
+ */
+ if (gga != 0)
+ {
+ gga->latitude = nmea_latitude(context->token[2],context->token[3]);
+ gga->longitude = nmea_longitude(context->token[4],context->token[5]);
+ gga->altitude = nmea_altitude(context->token[9],context->token[10]);
+ gga->time = tokenToInt(context->token[1]);
+ gga->satellites = tokenToInt(context->token[7]);
+ gga->quality = tokenToInt(context->token[6]);
+ gga->hdop = tokenToInt(context->token[8]);
+ gga->geoid = nmea_altitude(context->token[11],context->token[12]);
+
+ }
+
+
+ /*
+ * if the sentence has a callout, call it
+ */
+ if (sentence->callout != 0)
+ (*sentence->callout)(context,gga,context->user_data);
+
+ return NMEA_GPGGA;
+}
+
+/**
+ * standard GPRMCntence parser
+ */
+int nmea_gprmc(nmeap_context_t *context, nmeap_sentence_t *sentence)
+{
+
+ /*
+ * get pointer to sentence data
+ */
+ NmeaRmc *rmc = (NmeaRmc *)sentence->data;
+
+ /*
+ * if there is a data element, use it
+ */
+ if (rmc != 0)
+ {
+ /*
+ * extract data from the tokens
+ */
+ rmc->time = tokenToInt(context->token[1]);
+ rmc->warn = *context->token[2];
+ rmc->latitude = nmea_latitude(context->token[3],context->token[4]);
+ rmc->longitude = nmea_longitude(context->token[5],context->token[6]);
+ rmc->speed = tokenToInt(context->token[7]) * 100;
+ rmc->course = tokenToInt(context->token[8]) * 100;
+ rmc->date = tokenToInt(context->token[9]);
+ rmc->mag_var = tokenToInt(context->token[10]);
+ }
+
+ /*
+ * if the sentence has a callout, call it
+ */
+ if (sentence->callout != 0)
+ (*sentence->callout)(context,rmc,context->user_data);
+
+ return NMEA_GPRMC;
+}
+
+
+/**
+ * standard GPVTG sentence parser
+ */
+int nmea_gpvtg(nmeap_context_t *context, nmeap_sentence_t *sentence)
+{
+
+ /*
+ * get pointer to sentence data
+ */
+ NmeaVtg *vtg = (NmeaVtg *)sentence->data;
+
+ /*
+ * if there is a data element, use it
+ */
+ if (vtg != 0)
+ {
+ /*
+ * extract data from the tokens
+ */
+ vtg->track_good = tokenToInt(context->token[1]) * 100;
+ vtg->knot_speed = tokenToInt(context->token[5]) * 100;
+ vtg->km_speed = tokenToInt(context->token[7]) * 100;
+ }
+
+ /*
+ * if the sentence has a callout, call it
+ */
+ if (sentence->callout != 0)
+ (*sentence->callout)(context,vtg,context->user_data);
+
+ return NMEA_GPVTG;
+}
+
+/**
+ * standard GPGDSV sentence parser
+ */
+int nmea_gpgsv(nmeap_context_t *context, nmeap_sentence_t *sentence)
+{
+
+ /*
+ * get pointer to sentence data
+ */
+ NmeaGsv *gsv = (NmeaGsv *)sentence->data;
+
+ /*
+ * if there is a data element, use it
+ */
+ if (gsv != 0)
+ {
+ /*
+ * extract data from the tokens
+ */
+ gsv->tot_message = tokenToInt(context->token[1]);
+ gsv->message_num = tokenToInt(context->token[2]);
+ gsv->tot_svv = tokenToInt(context->token[3]);
+ gsv->sv_prn = tokenToInt(context->token[4]);
+ gsv->elevation = tokenToInt(context->token[5]);
+ gsv->azimut = tokenToInt(context->token[6]);
+ gsv->snr = tokenToInt(context->token[7]);
+ gsv->sv_prn2 = tokenToInt(context->token[8]);
+ gsv->elevation2 = tokenToInt(context->token[9]);
+ gsv->azimut2 = tokenToInt(context->token[10]);
+ gsv->snr2 = tokenToInt(context->token[11]);
+ gsv->sv_prn3 = tokenToInt(context->token[12]);
+ gsv->elevation3 = tokenToInt(context->token[13]);
+ gsv->azimut3 = tokenToInt(context->token[14]);
+ gsv->snr3 = tokenToInt(context->token[15]);
+ gsv->sv_prn4 = tokenToInt(context->token[16]);
+ gsv->elevation4 = tokenToInt(context->token[17]);
+ gsv->azimut4 = tokenToInt(context->token[18]);
+ gsv->snr4 = tokenToInt(context->token[19]);
+ }
+
+
+ /*
+ * if the sentence has a callout, call it
+ */
+ if (sentence->callout != 0)
+ (*sentence->callout)(context,gsv,context->user_data);
+
+ return NMEA_GPGSV;
+}
+
+void nmea_poll(nmeap_context_t *context, KFile *channel)
+{
+ int c;
+ while ((c = kfile_getc(channel)) != EOF)
+ {
+ if (nmeap_parse(context, c) == -1)
+ break;
+ }
+}
+
--- /dev/null
+/**
+ * \file
+ * <!--
+ * This file is part of BeRTOS.
+ *
+ * Bertos is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * As a special exception, you may use this file as part of a free software
+ * library without restriction. Specifically, if other files instantiate
+ * templates or use macros or inline functions from this file, or you compile
+ * this file and link it with other files to produce an executable, this
+ * file does not by itself cause the resulting executable to be covered by
+ * the GNU General Public License. This exception does not however
+ * invalidate any other reasons why the executable file might be covered by
+ * the GNU General Public License.
+ *
+ * Copyright 2009 Develer S.r.l. (http://www.develer.com/)
+ *
+ * -->
+ * \brief NMEA Parser
+ *
+ * \author Daniele Basile <asterix@develer.com>
+ *
+ * $WIZ$ module_name = "nmea"
+ * $WIZ$ module_configuration = "bertos/cfg/cfg_nmea.h"
+ * $WIZ$ module_depends = "kfile"
+ */
+
+#ifndef NET_NMEA_H
+#define NET_NMEA_H
+
+#include "cfg/cfg_nmea.h"
+
+#include <net/nmeap/inc/nmeap.h>
+
+#include <kern/kfile.h>
+
+/*
+ * Implemented NMEA parser strings.
+ */
+#define NMEA_GPGGA 1 // GGA MESSAGE ID
+#define NMEA_GPRMC 2 // RMC MESSAGE ID
+#define NMEA_GPVTG 3 // VTG MESSAGE ID
+#define NMEA_GPGSV 4 // GSV MESSAGE ID
+
+// Standart type to rappresent fiels.
+typedef uint32_t udegree_t; // Micro degrees
+typedef uint32_t mdegree_t; // Milli degrees
+typedef uint16_t degree_t; // Degrees
+typedef uint16_t cm_t; // Centimeter
+typedef uint32_t sec_t; // Seconds
+typedef uint32_t str_time_t; // Time format HH:MM:SS
+typedef uint32_t mknots_t; // Milli knots
+typedef uint32_t mkh_t; // Milli kilometers/hour
+typedef uint16_t number_t; // Pure number
+
+
+/**
+ * Extracted data from a GGA message
+ */
+typedef struct NmeaGga
+{
+ udegree_t latitude;
+ udegree_t longitude;
+ cm_t altitude;
+ sec_t time;
+ number_t satellites;
+ number_t quality;
+ udegree_t hdop;
+ udegree_t geoid;
+} NmeaGga;
+
+/**
+ * Extracted data from an RMC message
+ */
+typedef struct NmeaRmc
+{
+ str_time_t time;
+ char warn;
+ udegree_t latitude;
+ udegree_t longitude;
+ mknots_t speed;
+ mdegree_t course;
+ str_time_t date;
+ mdegree_t mag_var;
+} NmeaRmc;
+
+/**
+ * Extracted data from an vtg message
+ */
+typedef struct NmeaVtg
+{
+ mdegree_t track_good;
+ mknots_t knot_speed;
+ mkh_t km_speed;
+} NmeaVtg;
+
+/**
+ * Extracted data from an gsv message
+ */
+typedef struct NmeaGsv
+{
+ number_t tot_message;
+ number_t message_num;
+ number_t tot_svv;
+ number_t sv_prn;
+ degree_t elevation;
+ degree_t azimut;
+ number_t snr;
+ number_t sv_prn2;
+ degree_t elevation2;
+ degree_t azimut2;
+ number_t snr2;
+ number_t sv_prn3;
+ degree_t elevation3;
+ degree_t azimut3;
+ number_t snr3;
+ number_t sv_prn4;
+ degree_t elevation4;
+ degree_t azimut4;
+ number_t snr4;
+} NmeaGsv;
+
+void nmea_poll(nmeap_context_t *context, KFile *channel);
+
+int nmea_gpgsv(nmeap_context_t *context, nmeap_sentence_t *sentence);
+int nmea_gpvtg(nmeap_context_t *context, nmeap_sentence_t *sentence);
+int nmea_gprmc(nmeap_context_t *context, nmeap_sentence_t *sentence);
+int nmea_gpgga(nmeap_context_t *context, nmeap_sentence_t *sentence);
+
+#endif /* NET_NMEA_H */