/* GPS NMEA display on 16x4 LCD connected to 68EZ328 */
/* by Steven J. Merrifield, July 2005 */

#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"

extern char * process(char *);
extern int grid_square(double, double);
extern char * process_date_str(char *);
extern char * process_time_str(char *);
extern float process_lat_decdeg(void);
extern char * process_lat_degminsec(char *);
extern float process_lon_decdeg(void);
extern char * process_lon_degminsec(char *);
extern void LCDWriteStr(char *);
extern void LCDClrScr(void);
extern void LCDLine(int);
extern void LCDScreen0(void);
extern void LCDScreen1(void);
extern void LCDScreen2(void);
extern void LCDScreen3(void);
extern void LCDScreen4(void);
extern void LCDScreen5(void);
extern int CheckButton(void);

int timeout;
int lcdfd;
int state=0;


/*************************************************************/
void DisplayScreen(int i)
{
	if (i)	/* Button was pressed */
	{
		state++;
		if (state == 6)
			state = 0;
	}
	switch(state)
	{
		case 0: LCDScreen0(); break;
		case 1: LCDScreen1(); break;
		case 2: LCDScreen2(); break;
		case 3: LCDScreen3(); break;
		case 4: LCDScreen4(); break;
		case 5: LCDScreen5(); break;
	}
}

/*************************************************************/
void catch_alarm(int dummy)
{
	timeout = 1;
}

/*************************************************************/
int main(int argc, char **argv)
{
	struct termios options;
	char buffer[128];
	char linebuf[NMEA_LINE];
	char GGA[NMEA_LINE];
	char RMC[NMEA_LINE];
	int nbytes;
	int i,j;
	int fd;
	int bounce = 0;	/* Switch debounce counter */
	int flag;	/* Set for duration of switch debounce */

        char LCD_DEVICE[80] = "/dev/lcd";

        if ((lcdfd = open(LCD_DEVICE,O_WRONLY)) < 0) {
                printf("Failed to open %s\n",LCD_DEVICE); exit(-1); }


        if ((fd = open(COMMS_PORT, O_RDWR | O_NOCTTY | O_NDELAY)) == -1)
        {
                fprintf(stderr,"open failed: %s\n",strerror(errno));
                exit(-1);
        }

	fcntl(fd,F_SETFL,FNDELAY);
	tcgetattr(fd,&options);
	options.c_cflag = CLOCAL | CREAD | CS8 | B4800;
	options.c_iflag = IXON | IXOFF | IXANY;
	options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
	options.c_oflag &= ~OPOST;
	options.c_cc[VMIN] = 0;
	options.c_cc[VTIME] = 10;
	tcflush(fd,TCIFLUSH);
	tcsetattr(fd,TCSANOW,&options);

	signal(SIGALRM, catch_alarm);	/* Install the signal handler */
	alarm(SCREEN_TIMEOUT);		/* Start the timer */
	timeout = 0;
	j=0;

	while(1) 
	{
		DisplayScreen(0);	
		/* Clear out structs afer displaying data to avoid false */
		/* info being displayed */
		memset(&gga,0,sizeof(struct gga_struct));
		memset(&rmc,0,sizeof(struct rmc_struct));

		while (!timeout)
		{
			if ((bounce == 0) && (CheckButton()))
			{
				flag = 1;
			}
			if (flag)
				bounce++;

			if (bounce == 500)
			{
				if (CheckButton())
					DisplayScreen(1);
				bounce = 0;
				flag = 0;
			}
			nbytes = read(fd,buffer,sizeof(buffer));
			while (nbytes != -1)
			{
				for (i=0;i<nbytes;i++,j++)
				{
					if (buffer[i]=='$')
					{
						if (linebuf[4]=='G')
						{
							strncpy(GGA,linebuf,j);
//							printf("%s",GGA);
							process(GGA);
						}
	
						if (linebuf[4]=='M')
						{
							strncpy(RMC,linebuf,j);
//							printf("%s",RMC);
							process(RMC);
						}
						j=0;
					}
//					printf("%c",buffer[i]); 
					linebuf[j]=buffer[i];
				}
				nbytes = read(fd,buffer,sizeof(buffer));
			}
		}
		alarm(SCREEN_TIMEOUT);	/* reset timer */
		timeout=0;		/* reset flag */
	}
	close(fd);
	close(lcdfd);

	return(0);
}

