Add date to GPS data, captured from GPRMC packet.
authorKeith Packard <keithp@keithp.com>
Mon, 16 Nov 2009 00:04:41 +0000 (16:04 -0800)
committerKeith Packard <keithp@keithp.com>
Mon, 16 Nov 2009 00:19:52 +0000 (16:19 -0800)
Pull the date out of the GPS stream and send it over the telemetry
link and write it to the eeprom.

Signed-off-by: Keith Packard <keithp@keithp.com>
ao-tools/ao-view/aoview_state.c
ao-tools/lib/cc-telem.c
ao-tools/lib/cc.h
src/ao.h
src/ao_gps_print.c
src/ao_gps_report.c
src/ao_gps_skytraq.c
src/ao_gps_test.c
src/ao_gps_test_skytraq.c

index 2f613d44c835c2f29893d22cf3f9bd253490e99f..21cea99add4451dfb462ac3ea48f23c3568b9a00 100644 (file)
@@ -315,6 +315,10 @@ aoview_state_notify(struct cc_telem *data)
                aoview_state_add_deg(1, "Longitude", state->gps.lon, 'E', 'W');
                aoview_table_add_row(1, "GPS altitude", "%d", state->gps.alt);
                aoview_table_add_row(1, "GPS height", "%d", state->gps_height);
+               aoview_table_add_row(1, "GPS date", "%04d-%02d-%02d",
+                                    state->gps.gps_time.year,
+                                    state->gps.gps_time.month,
+                                    state->gps.gps_time.day);
                aoview_table_add_row(1, "GPS time", "%02d:%02d:%02d",
                                     state->gps.gps_time.hour,
                                     state->gps.gps_time.minute,
index 0e1483f7aa17934e2648a05d37d71c6bd9cc62c0..9a2f6155a4345ce12bd22e022a83a89dc590237f 100644 (file)
@@ -127,6 +127,7 @@ cc_telem_parse(const char *input_line, struct cc_telem *telem)
        if (strcmp (words[36], "unlocked") == 0) {
                telem->gps.gps_connected = 1;
                telem->gps.gps_locked = 0;
+               telem->gps.gps_time.year = telem->gps.gps_time.month = telem->gps.gps_time.day = 0;
                telem->gps.gps_time.hour = telem->gps.gps_time.minute = telem->gps.gps_time.second = 0;
                telem->gps.lat = telem->gps.lon = 0;
                telem->gps.alt = 0;
@@ -134,6 +135,16 @@ cc_telem_parse(const char *input_line, struct cc_telem *telem)
        } else if (nword >= 40) {
                telem->gps.gps_locked = 1;
                telem->gps.gps_connected = 1;
+               if (version >= 2) {
+                       sscanf(words[36], "%d-%d-%d",
+                              &telem->gps.gps_time.year,
+                              &telem->gps.gps_time.month,
+                              &telem->gps.gps_time.day);
+                       words += 1;
+                       nword -= 1;
+               } else {
+                       telem->gps.gps_time.year = telem->gps.gps_time.month = telem->gps.gps_time.day = 0;
+               }
                sscanf(words[36], "%d:%d:%d", &telem->gps.gps_time.hour, &telem->gps.gps_time.minute, &telem->gps.gps_time.second);
                cc_parse_pos(&telem->gps.lat, words[37]);
                cc_parse_pos(&telem->gps.lon, words[38]);
@@ -142,6 +153,7 @@ cc_telem_parse(const char *input_line, struct cc_telem *telem)
        } else {
                telem->gps.gps_connected = 0;
                telem->gps.gps_locked = 0;
+               telem->gps.gps_time.year = telem->gps.gps_time.month = telem->gps.gps_time.day = 0;
                telem->gps.gps_time.hour = telem->gps.gps_time.minute = telem->gps.gps_time.second = 0;
                telem->gps.lat = telem->gps.lon = 0;
                telem->gps.alt = 0;
index b8e3c061140f764699174cda0ba92fd55323d9c7..ebc0db7d9ee22a90e8aff73cd71c21c13524bc4e 100644 (file)
@@ -192,6 +192,9 @@ struct cc_flightcooked {
 
 
 struct cc_gps_time {
+       int year;
+       int month;
+       int day;
        int hour;
        int minute;
        int second;
index f266ac64844e4808033b67263d195080c6c509bc..c1a0f6e396228906e7b4942240a1a0049c9cf82f 100644 (file)
--- a/src/ao.h
+++ b/src/ao.h
@@ -493,6 +493,7 @@ ao_ee_init(void);
 #define AO_LOG_GPS_LON         'W'
 #define AO_LOG_GPS_ALT         'H'
 #define AO_LOG_GPS_SAT         'V'
+#define AO_LOG_GPS_DATE                'Y'
 
 #define AO_LOG_POS_NONE                (~0UL)
 
@@ -538,6 +539,11 @@ struct ao_log_record {
                        uint8_t         state;
                        uint8_t         c_n;
                } gps_sat;
+               struct {
+                       uint8_t         year;
+                       uint8_t         month;
+                       uint8_t         day;
+               } gps_date;
                struct {
                        uint16_t        d0;
                        uint16_t        d1;
@@ -720,8 +726,12 @@ ao_serial_init(void);
 
 #define AO_GPS_VALID           (1 << 4)
 #define AO_GPS_RUNNING         (1 << 5)
+#define AO_GPS_DATE_VALID      (1 << 6)
 
 struct ao_gps_data {
+       uint8_t                 year;
+       uint8_t                 month;
+       uint8_t                 day;
        uint8_t                 hour;
        uint8_t                 minute;
        uint8_t                 second;
index cc75133728884550d1e092c8992ecfb6527cbb00..95439ec709c6eb9542ed70e1c274a93a08a4c20c 100644 (file)
@@ -53,6 +53,10 @@ ao_gps_print(__xdata struct ao_gps_data *gps_data) __reentrant
 
                ao_gps_split(gps_data->latitude, &lat);
                ao_gps_split(gps_data->longitude, &lon);
+               printf(" 20%02d-%02d-%02d",
+                      gps_data->year,
+                      gps_data->month,
+                      gps_data->day);
                printf(" %2d:%02d:%02d",
                       gps_data->hour,
                       gps_data->minute,
index 75c944f55378afa601e60464a4246cdb07d31f09..e3e275238bd7f54c2c8b2fabe1e232345a536be4 100644 (file)
@@ -22,6 +22,7 @@ ao_gps_report(void)
 {
        static __xdata struct ao_log_record     gps_log;
        static __xdata struct ao_gps_data       gps_data;
+       uint8_t date_reported = 0;
 
        for (;;) {
                ao_sleep(&ao_gps_data);
@@ -49,6 +50,14 @@ ao_gps_report(void)
                gps_log.u.gps_altitude.altitude = gps_data.altitude;
                gps_log.u.gps_altitude.unused = 0xffff;
                ao_log_data(&gps_log);
+               if (!date_reported && (gps_data.flags & AO_GPS_DATE_VALID)) {
+                       date_reported = 1;
+                       gps_log.type = AO_LOG_GPS_DATE;
+                       gps_log.u.gps_date.year = gps_data.year;
+                       gps_log.u.gps_date.month = gps_data.month;
+                       gps_log.u.gps_date.day = gps_data.day;
+                       ao_log_data(&gps_log);
+               }
        }
 }
 
@@ -71,8 +80,7 @@ ao_gps_tracking_report(void)
                gps_log.tick = ao_time();
                gps_log.type = AO_LOG_GPS_SAT;
                for (c = 0; c < n; c++)
-                       if ((gps_log.u.gps_sat.svid = gps_tracking_data.sats[c].svid) &&
-                           (gps_log.u.gps_sat.state = gps_tracking_data.sats[c].state))
+                       if ((gps_log.u.gps_sat.svid = gps_tracking_data.sats[c].svid))
                        {
                                gps_log.u.gps_sat.c_n = gps_tracking_data.sats[c].c_n_1;
                                ao_log_data(&gps_log);
index cd5f78b923c4a437671fdeb77f5c45af008bfc13..b2eef04bfd24521ef884f877ecc2a92089216816 100644 (file)
@@ -19,9 +19,9 @@
 #include "ao.h"
 #endif
 
-#define AO_GPS_LEADER          3
+#define AO_GPS_LEADER          2
 
-static const char ao_gps_header[] = "GPG";
+static const char ao_gps_header[] = "GP";
 
 __xdata uint8_t ao_gps_mutex;
 static __xdata char ao_gps_char;
@@ -32,6 +32,7 @@ __xdata struct ao_gps_data    ao_gps_data;
 __xdata struct ao_gps_tracking_data    ao_gps_tracking_data;
 
 static __xdata struct ao_gps_data              ao_gps_next;
+static __xdata uint8_t                         ao_gps_date_flags;
 static __xdata struct ao_gps_tracking_data     ao_gps_tracking_next;
 
 static const char ao_gps_config[] = {
@@ -181,7 +182,7 @@ ao_gps_parse_flag(char no_c, char yes_c) __reentrant
 void
 ao_gps(void) __reentrant
 {
-       char    c;
+       char    a, c;
        uint8_t i;
 
        ao_serial_set_speed(AO_SERIAL_SPEED_9600);
@@ -198,7 +199,7 @@ ao_gps(void) __reentrant
                ao_gps_cksum = 0;
                ao_gps_error = 0;
 
-               /* Skip anything other than GPG */
+               /* Skip anything other than GP */
                for (i = 0; i < AO_GPS_LEADER; i++) {
                        ao_gps_lexchar();
                        if (ao_gps_char != ao_gps_header[i])
@@ -209,6 +210,8 @@ ao_gps(void) __reentrant
 
                /* pull the record identifier characters off the link */
                ao_gps_lexchar();
+               a = ao_gps_char;
+               ao_gps_lexchar();
                c = ao_gps_char;
                ao_gps_lexchar();
                i = ao_gps_char;
@@ -216,7 +219,7 @@ ao_gps(void) __reentrant
                if (ao_gps_char != ',')
                        continue;
 
-               if (c == (uint8_t) 'G' && i == (uint8_t) 'A') {
+               if (a == (uint8_t) 'G' && c == (uint8_t) 'G' && i == (uint8_t) 'A') {
                        /* Now read the data into the gps data record
                         *
                         * $GPGGA,025149.000,4528.1723,N,12244.2480,W,1,05,2.0,103.5,M,-19.5,M,,0000*66
@@ -245,7 +248,7 @@ ao_gps(void) __reentrant
                         *         *66          checksum
                         */
 
-                       ao_gps_next.flags = AO_GPS_RUNNING;
+                       ao_gps_next.flags = AO_GPS_RUNNING | ao_gps_date_flags;
                        ao_gps_next.hour = ao_gps_decimal(2);
                        ao_gps_next.minute = ao_gps_decimal(2);
                        ao_gps_next.second = ao_gps_decimal(2);
@@ -290,7 +293,7 @@ ao_gps(void) __reentrant
                                ao_mutex_put(&ao_gps_mutex);
                                ao_wakeup(&ao_gps_data);
                        }
-               } else if (c == (uint8_t) 'S' && i == (uint8_t) 'V') {
+               } else if (a == (uint8_t) 'G' && c == (uint8_t) 'S' && i == (uint8_t) 'V') {
                        uint8_t done;
                        /* Now read the data into the GPS tracking data record
                         *
@@ -345,6 +348,56 @@ ao_gps(void) __reentrant
                                ao_mutex_put(&ao_gps_mutex);
                                ao_wakeup(&ao_gps_tracking_data);
                        }
+               } else if (a == (uint8_t) 'R' && c == (uint8_t) 'M' && i == (uint8_t) 'C') {
+                       /* Parse the RMC record to read out the current date */
+
+                       /* $GPRMC,111636.932,A,2447.0949,N,12100.5223,E,000.0,000.0,030407,,,A*61
+                        *
+                        * Recommended Minimum Specific GNSS Data
+                        *
+                        *      111636.932      UTC time 11:16:36.932
+                        *      A               Data Valid (V = receiver warning)
+                        *      2447.0949       Latitude
+                        *      N               North/south indicator
+                        *      12100.5223      Longitude
+                        *      E               East/west indicator
+                        *      000.0           Speed over ground
+                        *      000.0           Course over ground
+                        *      030407          UTC date (ddmmyy format)
+                        *      A               Mode indicator:
+                        *                      N = data not valid
+                        *                      A = autonomous mode
+                        *                      D = differential mode
+                        *                      E = estimated (dead reckoning) mode
+                        *                      M = manual input mode
+                        *                      S = simulator mode
+                        *      61              checksum
+                        */
+                       ao_gps_skip_field();
+                       for (i = 0; i < 8; i++) {
+                               ao_gps_lexchar();
+                               ao_gps_skip_field();
+                       }
+                       a = ao_gps_decimal(2);
+                       c = ao_gps_decimal(2);
+                       i = ao_gps_decimal(2);
+                       /* Skip remaining fields */
+                       while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') {
+                               ao_gps_lexchar();
+                               ao_gps_skip_field();
+                       }
+                       if (ao_gps_char == '*') {
+                               uint8_t cksum = ao_gps_cksum ^ '*';
+                               if (cksum != ao_gps_hex(2))
+                                       ao_gps_error = 1;
+                       } else
+                               ao_gps_error = 1;
+                       if (!ao_gps_error) {
+                               ao_gps_next.year = i;
+                               ao_gps_next.month = c;
+                               ao_gps_next.day = a;
+                               ao_gps_date_flags = AO_GPS_DATE_VALID;
+                       }
                }
        }
 }
index 366bca718a76851a31c26434a124b794324f3d10..3692f0e53b0cc5865d76c76eaf8c21a2ab808e61 100644 (file)
 
 #define AO_GPS_VALID           (1 << 4)
 #define AO_GPS_RUNNING         (1 << 5)
+#define AO_GPS_DATE_VALID      (1 << 6)
 
 struct ao_gps_data {
+       uint8_t                 year;
+       uint8_t                 month;
+       uint8_t                 day;
        uint8_t                 hour;
        uint8_t                 minute;
        uint8_t                 second;
index 510bc41916532aa3b53f4ec2037226af62c20f39..ccf963785d74b44adaf4c7da06a1f7d491a14d37 100644 (file)
 
 #define AO_GPS_VALID           (1 << 4)
 #define AO_GPS_RUNNING         (1 << 5)
+#define AO_GPS_DATE_VALID      (1 << 6)
 
 struct ao_gps_data {
+       uint8_t                 year;
+       uint8_t                 month;
+       uint8_t                 day;
        uint8_t                 hour;
        uint8_t                 minute;
        uint8_t                 second;