/* 
  Simple NMEA Parsing routines
  Written by Steven J. Merrifield, July 2005

  Example data:
  $GPRMC,004239,A,3734.4444,S,14441.8229,E,000.0,270.1,250605,,,A*67
  $GPGGA,004240,3734.4443,S,14441.8227,E,1,05,01.4,00306.5,M,-020.0,M,,*7D
*/


#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <math.h>
#include "gps.h" 
#include "lcd.h"

/*************************************************************/
/* Converts NMEA date string into something readable */
/* A string is returned in the parameter that is passed to it */
char * process_date_str(char * date_str)
{
	date_str[0]= rmc.Date[0];	
	date_str[1]= rmc.Date[1];	
	date_str[2]= '/';
	date_str[3]= rmc.Date[2];
	date_str[4]= rmc.Date[3];
	date_str[5]= '/';
	date_str[6]= '2';
	date_str[7]= '0';
	date_str[8]= rmc.Date[4];
	date_str[9]= rmc.Date[5];
	date_str[10]= '\0';	
	return(date_str);
}

/*************************************************************/
/* Converts NMEA time string into something readable */
/* A string is returned in the parameter that is passed to it */
char * process_time_str(char * time_str)
{
	time_str[0]= gga.UTC[0];	
	time_str[1]= gga.UTC[1];	
	time_str[2]= ':';
	time_str[3]= gga.UTC[2];
	time_str[4]= gga.UTC[3];
	time_str[5]= ':';
	time_str[6]= gga.UTC[4];
	time_str[7]= gga.UTC[5];
	time_str[8]= '\0';	
	return(time_str);
}
	
/*************************************************************/
/* Takes a single line of NMEA data (s), and splits it into separate fields according */
/* to the comma delimiters */
int process(char *s)
{
	char *field[25];	// array of individual strings that make up one line
	int index;		// index to the individual field within the line
	int state;

	index=0;
	state=1;

	field[index]=s;		// first field is the data type, eg $GPGGA 
				// assign it the entire line, and cut it when a comma is found

	while (*s != 0)
	{
		switch(state)
		{
			case 0:
				if (*s == ',')
				{
					*s = 0;
					state = 1;
				}
				break;
			case 1:
				field[index++]=s;
				if (*s == ',')
				{
					*s = 0;
				} else
				{
					state = 0;
				}
				break;
			default:	
				state = 0;
				break;
		}
		s++;
	}
/*
	int i;
	for (i=0;i<index;i++)
	{
			printf("%s ",field[i]);
	}
	printf("\n");
*/
	if (strcmp(field[0],"$GPGGA")==0)
	{
		strcpy(gga.UTC,field[1]);
		gga.Lat = atof(field[2]);
		gga.NS = (char) *field[3];
		gga.Lon = atof(field[4]);
		gga.EW = (char) *field[5];
		gga.Fix = atoi(field[6]);
		gga.NumSats = atoi(field[7]);
		gga.Dil = atof(field[8]);
		gga.Alt = atof(field[9]);
		gga.AltMF = (char) *field[10];
		gga.Geo = atof(field[11]);
		gga.GeoMF = (char) *field[12];
		gga.Last = atoi(field[13]);
		gga.ID = atoi(field[14]);
		
	}
	if (strcmp(field[0],"$GPRMC") == 0)
	{
		strcpy(rmc.UTC,field[1]);
		rmc.Status = (char) *field[2];
		rmc.Lat = atof(field[3]);
		rmc.NS = (char) *field[4];
		rmc.Lon = atof(field[5]);
		rmc.EW = (char) *field[6];
		rmc.Speed = atof(field[7]);
		rmc.Heading = atoi(field[8]);
		strcpy(rmc.Date,field[9]);
		strcpy(rmc.Var,field[10]);
	}
	return(0);
}

/*************************************************************/
/* Converts NMEA latitude string to +/- decimal degress */
float process_lat_decdeg(void)
{
	float lat,min;
	int deg;

	lat = gga.Lat;
	deg = (int)(lat / 100.0);
	min = lat - (deg * 100.0);
	lat = deg + (min / 60.0);
	if (gga.NS == 'S')
		lat *= -1;
	return(lat);
}

/*************************************************************/
/* Converts NMEA latitude string to degress, minutes, seconds */
/* A string is returned in the parameter that is passed to it */
char * process_lat_degminsec(char *s)
{
	float lat;
	int deg,min,sec;

	lat = gga.Lat;
	deg = (int)(lat / 100.0);
	min = (int)(lat - (deg * 100.0));
	sec = (int) 60.0*(lat - (deg*100.0) - min); 
	sprintf(s,"%3d%c %2d' %2d\"",deg,DEG,min,sec);
	return(s);
}


/*************************************************************/
/* Converts NMEA longitude string to +/- decimal degress */
float process_lon_decdeg(void)
{
	float lon,min;
	int deg;

	lon = gga.Lon;
	deg = (int)(lon / 100.0);
	min = lon - (deg * 100.0);
	lon = deg + (min / 60.0);
	if (gga.EW == 'W')
		lon *= -1;
	return(lon);
}

/*************************************************************/
/* Converts NMEA longitude string to degress, minutes, seconds */
/* A string is returned in the parameter that is passed to it */
char * process_lon_degminsec(char *s)
{
	float lon;
	int deg,min,sec;

	lon = gga.Lon;
	deg = (int)(lon / 100.0);
	min = (int)(lon - (deg * 100.0));
	sec = (int) 60.0*(lon - (deg*100.0) - min); 
	sprintf(s,"%3d%c %2d' %2d\"",deg,DEG,min,sec);
	return(s);
}

