text: /** These functions are taken from Walter Dal Mut's GPS Library.
   *  We have added parsing of the date and time from the GPRMC
   * data sentence as well as parsing the fix quality indicator 
   * so as to enable the reporting of data valid in a variable. 
   * For details of the NMEA sentence structure please see
   * www.gpsinformation.org/dale/nmea.htm
   */
   
  #include <stdio.h>
  #include <stdlib.h>
  #include <inttypes.h>
  #include <string.h>
  #include <math.h>
  
  #include "nmea.h"
  
  
  void nmea_parse_gpgga(char *nmea, gpgga_t *loc)
  {
      char *p = nmea;
  
      p = strchr(p, ',')+1; //skip time
  
      p = strchr(p, ',')+1;
      loc->latitude = atof(p);
  
      p = strchr(p, ',')+1;
      switch (p[0]) {
          case 'N':
              loc->lat = 'N';
              break;
          case 'S':
              loc->lat = 'S';
              break;
          case ',':
              loc->lat = '\0';
              break;
      }
  
      p = strchr(p, ',')+1;
      loc->longitude = atof(p);
  
      p = strchr(p, ',')+1;
      switch (p[0]) {
          case 'W':
              loc->lon = 'W';
              break;
          case 'E':
              loc->lon = 'E';
              break;
          case ',':
              loc->lon = '\0';
              break;
      }
  
      p = strchr(p, ',')+1;
      loc->quality = (uint8_t)atoi(p);
      if( loc->quality > 0 )	// Fix quality indicator 1 or above shows data is valid
      {
  		loc->dataValid = 1;
  	}
  	else
  	{
  		loc->dataValid = 0;
  	}	
  
      p = strchr(p, ',')+1;
      loc->satellites = (uint8_t)atoi(p);
  
      p = strchr(p, ',')+1;
  
      p = strchr(p, ',')+1;
      loc->altitude = atof(p);
      
      return;
  }
  
  
  void nmea_parse_gprmc(char *nmea, gprmc_t *loc)
  {
      char *p = nmea;
  
      p = strchr(p, ',')+1; 		// Set pointer to the start of the time string
      strncpy(loc->time, p, 6 );	// Copy the characters of the time from the NMEA string to the time string
      loc->time[6] = '\0';  		// Place a string terminating null in the buffer 
     
      p = strchr(p, ',')+1; 		// Set the pointer to the sentence status either A = OK or V = invalid
  	if( p[0] == 'A' )			// Fix quality indicator A or above shows data is valid
      {
  		loc->dataValid = 1;
  	}
  	else
  	{
  		loc->dataValid = 0;
  	}	
  
      p = strchr(p, ',')+1;
      loc->latitude = atof(p);
  
      p = strchr(p, ',')+1;
      switch (p[0]) {
          case 'N':
              loc->lat = 'N';
              break;
          case 'S':
              loc->lat = 'S';
              break;
          case ',':
              loc->lat = '\0';
              break;
      }
  
      p = strchr(p, ',')+1;
      loc->longitude = atof(p);
  
      p = strchr(p, ',')+1;
      switch (p[0]) {
          case 'W':
              loc->lon = 'W';
              break;
          case 'E':
              loc->lon = 'E';
              break;
          case ',':
              loc->lon = '\0';
              break;
      }
  
      p = strchr(p, ',')+1;
      loc->speed = atof(p);
  
      p = strchr(p, ',')+1;
      loc->course = atof(p);
      
  	p = strchr(p, ',')+1;		// Set pointer to the start of the date string
      strncpy(loc->date, p, 6 );	// Copy the characters of the date from the NMEA string to the date string
      loc->date[6] = '\0';  		// Place a string terminating null in the buffer 
  
  	
  	return;
  }
  
  /**
   * Get the message type (GPGGA, GPRMC, etc..)
   *
   * This function filters out also wrong packages (invalid checksum)
   *
   * @param message The NMEA message
   * @return The type of message if it is valid
   */
  uint8_t nmea_get_message_type(const char *message)
  {
      uint8_t checksum = 0;
      if ((checksum = nmea_valid_checksum(message)) != _EMPTY) {
          return checksum;
      }
  
      if (strstr(message, NMEA_GPGGA_STR) != NULL) {
          return NMEA_GPGGA;
      }
  
      if (strstr(message, NMEA_GPRMC_STR) != NULL) {
          return NMEA_GPRMC;
      }
  
      return NMEA_UNKNOWN;
  }
  
  uint8_t nmea_valid_checksum(const char *message) {
      uint8_t checksum= (uint8_t)strtol(strchr(message, '*')+1, NULL, 16);
  
      char p;
      uint8_t sum = 0;
      ++message;
      while ((p = *message++) != '*') {
          sum ^= p;
      }
  
      if (sum != checksum) {
          return NMEA_CHECKSUM_ERR;
      }
  
      return _EMPTY;
  }
  
  
  // Convert lat e lon to decimals (from deg)
  void gps_convert_deg_to_dec(double *latitude, char ns,  double *longitude, char we)
  {
      double lat = (ns == 'N') ? *latitude : -1 * (*latitude);
      double lon = (we == 'E') ? *longitude : -1 * (*longitude);
  
      *latitude = gps_deg_dec(lat);
      *longitude = gps_deg_dec(lon);
  }
  
  double gps_deg_dec(double deg_point)
  {
      double ddeg;
      double sec = modf(deg_point, &ddeg)*60;
      int deg = (int)(ddeg/100);
      int min = (int)(deg_point-(deg*100));
  
      double absdlat = round(deg * 1000000.);
      double absmlat = round(min * 1000000.);
      double absslat = round(sec * 1000000.);
  
      return round(absdlat + (absmlat/60) + (absslat/3600)) /1000000;
  }
  