|
@@ -26,6 +26,7 @@
|
|
#include "display.h"
|
|
#include "display.h"
|
|
#include "working_modes.h"
|
|
#include "working_modes.h"
|
|
#include "timec.h"
|
|
#include "timec.h"
|
|
|
|
+#include "nmea.h"
|
|
|
|
|
|
/*FUSES = {0xFF, 0x11, 0xFE};*/ /* ATmega644PA fuses: Low, High, Extended.
|
|
/*FUSES = {0xFF, 0x11, 0xFE};*/ /* ATmega644PA fuses: Low, High, Extended.
|
|
This is the fuse settings for this project. The fuse bits will be included
|
|
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() == ' '){
|
|
if (uart1_test() && uart1_get() == '0' && uart1_get() == ' '){
|
|
LEDB_ON();
|
|
LEDB_ON();
|
|
start_bootloader();
|
|
start_bootloader();
|
|
- LEDR_ON();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/* keyboard */
|
|
/* keyboard */
|
|
@@ -167,53 +167,13 @@ ISR(ADC_vect)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-static void sleep(void) {
|
|
|
|
|
|
+void sleep(void) {
|
|
set_sleep_mode(SLEEP_MODE_IDLE);
|
|
set_sleep_mode(SLEEP_MODE_IDLE);
|
|
sleep_enable();
|
|
sleep_enable();
|
|
sleep_cpu();
|
|
sleep_cpu();
|
|
sleep_disable();
|
|
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 */
|
|
/* 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
|
|
#define LOG_SIZE 300
|
|
|
|
|
|
struct {
|
|
struct {
|