| 
					
				 | 
			
			
				@@ -26,6 +26,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "display.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "working_modes.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "timec.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "nmea.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /*FUSES = {0xFF, 0x11, 0xFE};*/		/* ATmega644PA fuses: Low, High, Extended. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 This is the fuse settings for this project. The fuse bits will be included 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -113,7 +114,6 @@ ISR(TIMER1_COMPA_vect) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	if (uart1_test() && uart1_get() == '0' && uart1_get() == ' '){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		LEDB_ON(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		start_bootloader(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		LEDR_ON(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	/* keyboard */ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -167,53 +167,13 @@ ISR(ADC_vect) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void sleep(void) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void sleep(void) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	set_sleep_mode(SLEEP_MODE_IDLE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	sleep_enable(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	sleep_cpu(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	sleep_disable(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-/*----------------------------------------------------*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-/*  Get a line received from GPS module               */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-/*----------------------------------------------------*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-UINT get_line (		/* 0:Brownout or timeout, >0: Number of bytes received. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	char *buff, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	UINT sz_buf 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	char c; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	UINT i = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	set_timer(recv_timeout, 1000); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	for (;;) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		wdt_reset(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if (FLAGS & (F_LVD | F_POWEROFF)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			return 0;	/* A brownout is detected */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if (timer_expired(recv_timeout)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			return 0; /* timeout; continue the main loop */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if (!uart0_test()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			sleep(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		c = (char)uart0_get(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		uart1_put(c); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if (i == 0 && c != '$') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			continue;	/* Find start of line */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		buff[i++] = c; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if (c == '\n') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			break;	/* EOL */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if (i >= sz_buf) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			i = 0;	/* Buffer overflow (abort this line) */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /*--------------------------------------------------------------------------*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /* Controls                                                                 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -229,178 +189,6 @@ void beep (UINT len, BYTE cnt) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-/* Compare sentence header string */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-BYTE gp_comp (const char *str1, __flash const char *str2) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	char c; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	do { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		c = pgm_read_byte(str2++); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} while (c && c == *str1++); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return c; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#define FIELD_BUF_LEN	32 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-/* Get a column item */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const char* gp_col (	/* Returns pointer to the item (returns a NULL when not found) */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const char* buf,	/* Pointer to the sentence */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	BYTE col			/* Column number (0 is the 1st item) */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	BYTE c; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	static char field_buf[FIELD_BUF_LEN]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	unsigned char length = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	while (col) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		do { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			c = *buf++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			if (c <= ' ') return NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		} while (c != ','); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		col--; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	while (*buf && *buf != ',' && length < FIELD_BUF_LEN-1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		field_buf[length++] = *buf++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	field_buf[length] = '\0'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return field_buf; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-BYTE gp_val2 ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const char *db 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	BYTE n, m; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	n = db[0] - '0'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if (n >= 10) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	m = db[1] - '0'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if (m >= 10) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return n * 10 + m; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-UINT gp_val3 ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const char *db 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	BYTE n, m, l; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	n = db[0] - '0'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if (n >= 10) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	m = db[1] - '0'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if (m >= 10) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	l = db[2] - '0'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if (l >= 10) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return n * 100 + m * 10 + l; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static time_t gp_rmc_parse(const char *str) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const char *p; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	struct tm tmc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	p = gp_col(str, 1);		/* Get h:m:s */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if (!p) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	tmc.tm_hour = gp_val2(p); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	tmc.tm_min = gp_val2(p+2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	tmc.tm_sec = gp_val2(p+4); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	p = gp_col(str, 9);		/* Get y:m:d */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if (!p) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	tmc.tm_mday = gp_val2(p); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	tmc.tm_mon = gp_val2(p+2) - 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	tmc.tm_year = gp_val2(p+4) + 100; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	utc = mktime(&tmc);				/* Check time validity */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if (utc == -1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	p = gp_col(str, 2);		/* Get status */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if (!p || *p != 'A') { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		System.location_valid = LOC_INVALID; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		FLAGS &= ~F_GPSOK; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return 0;			/* Return 0 even is time is valid (comes from module's internal RTC) */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	FLAGS |= F_GPSOK; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return utc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void gp_gga_parse(const char *str) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const char *p; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	double tmp; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	/* check validity */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	p = gp_col(str, 6); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if (*p == '0') { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		System.location_valid = LOC_INVALID; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	System.location_valid = LOC_VALID_NEW; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	/* parse location */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	p = gp_col(str, 2);		/* latitude */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	location.lat = gp_val2(p);	/* degrees */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	p += 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	xatof(&p, &tmp);	/* minutes */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	tmp /= 60;			/* convert minutes to degrees */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	location.lat += tmp; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	p = gp_col(str, 3);	/* N/S */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if (*p != 'N') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		location.lat = -location.lat; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	p = gp_col(str, 4);		/* longitude */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	location.lon = gp_val3(p);	/* degrees */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	p += 3; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	xatof(&p, &tmp);	/* minutes */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	tmp /= 60;			/* convert minutes to degrees */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	location.lon += tmp; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	p = gp_col(str, 5); /* E/W */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if (*p != 'E') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		location.lon = -location.lon; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	p = gp_col(str, 7); /* satellites used */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	System.satellites_used = atoi(p); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	p = gp_col(str, 9); /* MSL altitude */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	xatof(&p, &tmp); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	location.alt = tmp; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	location.time = utc; /* parsed from RMC */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static time_t gps_parse(const char *str) {	/* Get all required data from NMEA sentences */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if (!gp_comp(str, PSTR("$GPRMC"))) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return gp_rmc_parse(str); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if (!gp_comp(str, PSTR("$GPGGA"))) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		gp_gga_parse(str); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define LOG_SIZE	300 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 struct { 
			 |