/*
 * gps.h - defines for gps
 *
 *
 * 
 * $GPBOD Sentence Format (Bearing, Origin to Destination)
 * $GPBOD,<bearing>,T,<bearing>,M,<destination>,<start>,*,<checksum>
 * 
 * $GPGGA Sentence Format (GPS Fix Data)
 * 
 * $GPGGA,HHMMSS.SS,DDMM.MMM,N,DDDMM.MMM,W,X,XX,X.X,XXX,X,XX.X,X,XX.X,XX
 * 
 *     1.   UTC time of position  
 *     2.   Latitude of fix
 *     3.   latitude direction (N=north, S=south)
 *     4.   Longitude of fix
 *     5.   Longitude direction (W=west, E=east)
 *     6.   GPS Quality (0=no fix , 1=GPS fix, 2=DGPS fix)
 *     7.   Number of satellites in use
 *     8.   Horizontal dilution of precision
 *     9.   Antenna altitude mean-sea-level
 *     10.  Unit of antenna altitude, meters
 *     11.  Geoidal\ separation-difference between WGS84 earth ellipsoid & MSL
 *     13.  Age of differential GPS data, time in seconds since last SC104
 *          type 1 or 9 update, null field when DGPS is not used
 *     14.  Differential reference station ID, 0000-1023
 *     15.  Checksum
 * 
 * $GPGLL Sentence Format (Geographical)
 * 
 * $GPGLL,DDMM.MMM,N,DDDMM.MMM,W*XX
 * 
 *     1.   Present latitude (degrees and minutes)
 *     2.   Present latitude direction (N=north, S=south)
 *     3.   Present longitude (degrees and minutes) 
 *     4.   Present longitude direction (E=east, W=west)
 *     5.   Checksum
 * 
 * $GPGSA Sentence Format (GPS DOP and Active satellites) NO CPP
 * 
 * $GPGSA,A,X,XX,XX,,,,,,,,,X.X,X.X,X.X,*XX
 * 
 *     1.   Mode (M=manual, A=automatic)
 *     2.   Mode (1=Fix not available, 2= 2D, 3=3D)
 *     3.   Satellites in view
 *     4,   PDOP
 *     5.   HDOP
 *     6.   VDOP
 *     7.   Checksum
 * 
 * $GPGSV Sentence Format (GPS Satellites in view) NO CPP
 * 
 * $GPGSV,X,X,XX,XX,XX,XXX,XX,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*XX
 * 
 *     1.   Total number of messages, 1 to 3
 *     2.   Message number 1 to 3
 *     3.   Total number of satellites in view
 *     4.   Satellite PRN number
 *     5.   Elevation 90 degrees max
 *     6.   Azimuth degrees true 000-360
 *     7.   SNR  00-99db, null when not tracking
 *     8.   Checksum
 * 
 * $GPRMB Sentence Format (Generic Navigation Information)
 * 
 * $GPRMB,A,X.XX,L,CCCC,CCCC,DDMM.MMM,N,DDDMM.MMM,W,XXX.X,XXX.X,XXX.X,A*XX
 * 
 *     1.  Position valid (A=valid, V=invalid)
 *     2.  Cross Track error (nautical miles)
 *     3.  Direction to steer (L=left, R=right)
 *     4.  Origin waypoint identifier
 *     5.  Destination waypoint identifier
 *     6.  Destination latitude (degrees and minutes)
 *     7.  Destination latitude direction (N=north, S=south)
 *     8.  Destination longitude (degrees and minutes)
 *     9.  Destination longitude direction (E=east, W=-west)
 *     10. Range from present position to destination waypoint (nautical miles)
 *     11. Bearing form present position to destination wypoint (degrees, true)
 *     12. Closing velocity to destination waypoint (knots)
 *     13. Arrival flag (A=arrival, V=not arrival)
 *     14. Checksum
 * 
 * $GPRMC Sentence Format  (GPS and Transit Specific)
 * 
 * $GPRMC,HHMMSS,A,DDMM.MMM,N,DDDMM.MMM,W,XXX.X,XXX.X,DDMMYY,XXX.X,E*XX
 * 
 *     1.   Time (UTC)
 *     2.   Position valid (A=valid,  V=invalid)
 *     3.   Latitude at UTC time (degrees and minutes)
 *     4.   latitude direction (N=north, S=south)
 *     5.   Longitude at UTC time (degrees and minutes)
 *     6.   Longitude direction (E=east, W=west)
 *     7.   Speed over ground (knots)
 *     8.   Course over ground or track (degrees, true)
 *     9.   Date (day, month, year)
 *     10.  Magnetic variation (degrees)
 *     11.  Magnetic variation direction ( E=east, W=west)
 *     12.  Checksum
 * 
 * $PGRME Sentence Format (Proprietary GARMIN Estimated position error)
 * 
 * $PGRME,XXXX.X,M,XXXX.X,M,XXXX.X,M,*XX
 * 
 *     1.   Estimated horizontal position error (HPE).
 *     2.   HPE measure   meters    
 *     3.   Estimated vertical position error (VPE)
 *     4.   VPE measure   meters
 *     5.   Estimated position error (EPE)
 *     6.   EPE measure   meters
 *     7.   Checksum
 * 
 * $PGRMM Sentence Format (Proprietary GARMIN map Datum)
 * 
 * $PGRMM,XXXXXX,*XX
 *              
 *     1.   map Datum
 *     2.   Checksum
 * 
 * $PGRMZ Sentence Format (Proprietary GARMIN Altitude)
 * 
 * $PGRMZ,XXXXX,F,X*XX
 *               
 *     1.   Present altitude (feet)
 *     2.   Units (f=feet)
 *     3.   Position fix dimensions (2=user altitude, 3=GPS altitude)
 *     4.   Checksum
 * 
 * $GPRTE Sentence Format (Routes)
 * 
 * $GPRTE,X.X,X.X,A,CCCC,CCCC,CCCC,CCCC,,,,,,,,,*XX
 * 
 *     1.    Total number of messages transmitted
 *     2.    Message number
 *     3.    Message mode
 *     4.    Route identifier
 *     5.    Waypoint identifier
 *     6-n.  Waypoint identifier
 *     n+1.  Checksum
 * 
 * $GPWPL Sentence Format (Waypoint Location)
 * 
 * $GPWPL,DDMM.MMM,N,DDDMM.MMM,W,CCCC*XX
 * 
 *     1.   Waypoint Latitude (degrees and minutes)
 *     2.   Waypoint Latitude direction (N=north, S=south)
 *     3.   Waypoint Longitude (degrees and minutes)
 *     4.   Waypoint longitude direction (E=east, W=west)
 *     5.   Waypoint identifier
 *     6.   Checksum
 * 
 * Full cycles occur at 20 sec intervals and may look like:
 * $GPRMC,062935,A,4738.363,N,12243.074,W,002.9,303.9,270997,019.6,E*6A
 * $GPRMB,A,3.53,L,BOLNPT,HOME,4739.100,N,12236.600,W,004.4,080.4,-002.1,A*1A
 * $GPGGA,062935,4738.363,N,12243.074,W,1,03,3.1,170.3,M,-18.6,M,,*76
 * $GPGSA,A,2,02,07,,,,27,,,,,,,3.1,3.1,*1D
 * $GPGSV,2,1,07,02,83,354,46,07,43,185,42,15,18,076,00,19,15,125,00*78
 * $GPGSV,2,2,07,26,40,290,00,27,57,126,40,31,06,038,00,,,,*4C
 * $PGRME,72.0,M,,M,166.4,M*30
 * $GPGLL,4738.363,N,12243.070,W,062936,A*3F
 * $PGRMZ,559,f,2*13
 * $PGRMM,WGS 84*06
 * $GPBOD,207.6,T,188.0,M,HOME,BOLNPT*41
 * $GPRTE,2,1,c,0,OAKR2,EASTPT,SNDYPT,PTELLT,BYSF,PTJEFF,AGATR2,AGATR4,BOLNPT*13
 * $GPRTE,2,2,c,0,HOME*24
 * $GPWPL,4815.395,N,12237.640,W,OAKR2*7C
 * $GPRMC,062937,A,4738.363,N,12243.075,W,001.4,297.9,270997,019.6,E*6B
 * $GPRMB,A,3.53,L,BOLNPT,HOME,4739.100,N,12236.600,W,004.4,080.4,000.4,A*30
 * $GPGGA,062937,4738.363,N,12243.075,W,1,03,3.1,170.3,M,-18.6,M,,*75
 * $GPGSA,A,2,02,07,,,,27,,,,,,,3.1,3.1,*1D
 * $GPGSV,2,1,07,02,83,354,46,07,43,185,42,15,18,076,00,19,15,125,00*78
 * $GPGSV,2,2,07,26,40,290,00,27,57,126,39,31,06,038,00,,,,*42
 * $PGRME,72.0,M,,M,166.4,M*30
 * $GPGLL,4738.363,N,12243.075,W,062938,A*34
 * $PGRMZ,559,f,2*13
 * $PGRMM,WGS 84*06
 * $GPBOD,207.6,T,188.0,M,HOME,BOLNPT*41
 * $GPWPL,4805.800,N,12229.400,W,EASTPT*51
 * 
 * Normal cycles occur at 2 second intervals and may look like:
 * $GPRMC,062931,V,,,,,,,270997,,*3C
 * $GPRMB,V,,,,,,,,,,,,V*66
 * $GPGGA,062931,,,,,0,00,,,M,,M,,*69
 * $GPGSA,A,1,,,,,,,,,,,,,,,*1E
 * $GPGSV,2,1,07,02,83,354,46,07,43,185,40,15,18,076,00,19,15,125,00*7A
 * $GPGSV,2,2,07,26,40,291,00,27,57,126,40,31,06,038,00,,,,*4D
 * $PGRME,,M,,M,,M*00
 * $GPGLL,,,,,062931,*5F
 * $PGRMZ,,,*7E
 * $PGRMM,WGS 84*06
 * $GPBOD,,T,,M,,*47
 * $GPWPL,4741.800,N,12234.500,W,BOLNPT*5F
 * $GPRMC,062933,A,4738.358,N,12243.057,W,003.9,315.4,270997,019.6,E*6E
 * $GPRMB,A,,,,,,,,,,,,V*71
 * $GPGGA,062933,4738.358,N,12243.057,W,1,00,3.1,170.3,M,-18.6,M,,*7A
 * $GPGSA,A,2,02,07,,,,27,,,,,,,3.1,3.1,*1D
 * $GPGSV,2,1,07,02,83,354,45,07,43,185,41,15,18,076,00,19,15,125,00*78
 * $GPGSV,2,2,07,26,40,291,00,27,57,126,40,31,06,038,00,,,,*4D
 * $PGRME,72.0,M,,M,166.4,M*30
 * $GPGLL,4738.359,N,12243.058,W,062934,A*3E
 * $PGRMZ,559,f,2*13
 * $PGRMM,WGS 84*06
 * $GPBOD,207.6,T,188.0,M,HOME,BOLNPT*41
 * $GPWPL,4739.100,N,12236.600,W,HOME*5C
 *
 * cat gps45xxx.output | sed 's/,.*$//' | sort | uniq
 * and looking at the strings[2..5] as long's,
 * $G PBOD --> 0x50424F44
 * $G PGGA --> 0x50474741
 * $G PGLL --> 0x50474C4C
 * $G PGSA --> 0x50475341
 * $G PGSV --> 0x50475356
 * $G PRMB --> 0x50524D42
 * $G PRMC --> 0x50524D43
 * $G PRTE --> 0x50525445
 * $G PWPL --> 0x5057504C
 * $P GRME --> 0x47524D45
 * $P GRMM --> 0x47524D4D
 * $P GRMZ --> 0x47524D5A
 *
 * These hex values may be used in a switch statment.
 *
 * $Id: gps.h,v 1.2 2002/08/03 17:52:57 tomdean Exp $
 *
 */

/*
 * specific data to extract from the essage stream
 *
 * $GPBOD
 * $GPBOD,210.3,T,190.7,M,BRWVLE,AGATR6*27
 *     1  5 bearing (t)
 *     2  1   T = true
 *     3  5 bearing (m)
 *     4  1   M = magnetic
 *     6  6 origin          need to xref this to a lat/lon
 *     5  6 destination     need to xref this to a lat/lon
 *        24 bytes
 * 
 * $GPGGA
 * $GPGGA,030754,4738.374,N,12243.120,W,1,03,8.0,70.4,M,-18.6,M,,*42
 *     1  6 UTC time of position
 *     2  8 Latitude of fix
 *     3  1   latitude direction (N=north, S=south)  Use + N, - S
 *     4  9 Longitude of fix
 *     5  1   longitude direction (W=west, E=east)   Use + W, - E
 *        25 bytes
 * 
 * $GPGLL
 * $GPGLL,4738.374,N,12243.121,W,030755,A*30
 *     1  8 Present latitude (degrees and minutes)
 *     2  1 Present latitude direction (N=north, S=south)  Use + N, - S
 *     3  9 Present longitude (degrees and minutes)
 *     4  1 Present longitude direction (E=east, W=west)   Use + W, - E
 *        19 bytes
 * 
 * $GPRMB
 * $GPRMB,A,3.26,L,AGATR6,BRWVLE,4739.139,N,12236.745,W,004.3,079.8,-000.8,A*7F
 *     1   1 Position valid (A=valid, V=invalid)
 *     2   4 Cross Track error (nautical miles)
 *     3   1 Direction to steer (L=left, R=right)
 *     4   6 Origin waypoint identifier
 *     5   6 Destination waypoint identifier
 *     6   8 Destination latitude (degrees and minutes)
 *     7   1 Destination latitude direction (N=north, S=south)  + N, - 
 *     8   9 Destination longitude (degrees and minutes)
 *     9   1 Destination longitude direction (E=east, W=-west)  + W, - E
 *     10  5 Range present position to destination waypoint (nautical miles)
 *     11  5 Bearing present position to destination wapoint (degrees, true)
 *     12  6 Closing velocity to destination waypoint (knots) (signed)
 *         53 bytes
 * 
 * $GPRMC
 * $GPRMC,031506,A,4738.373,N,12242.986,W,000.0,286.7,171198,019.6,E*68
 *     1   6 Time (UTC)
 *     2   1 Position valid (A=valid,  V=invalid)
 *     3   8 Latitude at UTC time (degrees and minutes)
 *     4   1 latitude direction (N=north, S=south)  Use + N, - S
 *     5   9 Longitude at UTC time (degrees and minutes)
 *     6   1 Longitude direction (E=east, W=west)   Use + W, - E
 *     7   5 Speed over ground (knots)
 *     8   5 Course over ground or track (degrees, true)
 *     9   6 Date (day, month, year)
 *     10  5 Magnetic variation (degrees)
 *     11  1 Magnetic variation direction ( E=east, W=west) - W, + E
 *         48 bytes                                      --------
 *  NOTE DIFFERENT CONVENTION --------------------------------^
 *
 * $PGRME
 *     1   6 Estimated horizontal position error (HPE).
 *     2   1 HPE measure   M = meters
 *         7 bytes
 *
 * $GPRTE
 *     1   1 Total number of messages transmitted
 *     2   1 Message number
 *     3   1 Message mode
 *     4   1 Route identifier
 *     5   6 Waypoint identifier  54 char max for 5 and 6-n
 *     6-n 6 Waypoint identifier
 *         16 bytes
 * 
 * $GPWPL
 *     1   8 Waypoint Latitude (degrees and minutes)
 *     2   1 Waypoint Latitude direction (N=north, S=south)  + N, - S
 *     3   9 Waypoint Longitude (degrees and minutes)
 *     4   1 Waypoint longitude direction (E=east, W=west)   + W, - E
 *     5   6 Waypoint identifier
 *         25 bytes
 *
 * row 1: lat lon destination bearing range
 * row 2: dts sog cog vmg cte
 * row 3:
 * row 4: ddmmyy hhmmss 
 *          1111111111222222222233333333334
 * 1234567890123456789012345678901234567890
 * lat       lon        wpt    brg   rng
 * 4827.123N 12245.432W WPTNAM 090.7 004.3
 *  sog   cse   vmg    cterr   date   utc
 * 002.4k 102^ -000.8k 3.20 L ddmmyy 031504
 *
 *  sog   cse   vmg    cterr  steer   utc
 * 002.4k 102^ -000.8k 3.20 L  110m  031504
 *                              ^
 *                              |
 * calculate -------------------+
 *
 * lat   gprmc 3
 *   dir gprmc 4
 * lon   gprmc 5
 *   dir gprmc 6
 * wpt   gprmb 5
 * brg   gprmb 11
 * rng   gprmb 10
 * sog   gprmc 7
 * cse   gprmc 8
 * vmg   gprmb 12
 * cterr gprmb 2
 *  dir  gprmb 3
 * date  gprmc 9
 * steer calc
 * utc   gprmc 1
 */

typedef struct float_t {
  short value;
  short frac;
} float_t;

typedef struct brg_t {
  char  c_brg[5];
  char  dir;
  short b_brg;
} brg_t;

typedef struct posit_t {
  char c_lat[8];
  char lat_dir;
  char c_lon[9];
  char lon_dir;
  float_t lat;
  float_t lon;
} posit_t;

typedef struct gpbod_t {
  brg_t true;
  brg_t mag;
  char orig[6];
  char dest[6];
} gpbod_t;

typedef struct gpgga_t {
  char c_utc[6];
  long utc;
  posit_t fix;
} gpgga_t;

typedef struct gpgll_t {
  posit_t posit;
} gpgll_t;

typedef struct gprmb_t {
  char    valid;
  char    c_cte[6];
  float_t   cte;
  char    cte_dir;
  char    c_orgn[6];
  char    c_dest[6];
  posit_t dest;
  char    c_rng[5];
  float_t   rng;
  char    c_brg[5];
  float_t   brg;
  char    c_vmg[6];
  float_t   vmg;
} gprmb_t;

typedef struct gprmc_t {
  char    c_utc[6];
  long    utc;
  char    valid;
  posit_t posit;
  char    c_sog[5];
  float_t   sog;
  char    c_cog[5];
  float_t   cog;
  char    c_vmg[6];
  float_t   vmg;
} gprmc_t;

typedef struct pgrme_t {
  char  c_err[6];
  float_t err;
  char  measure;
} pgrme_t;

typedef struct gpwpl_t {
  char wpt[6];
  posit_t posit;
} gpwpl_t;

#define NUM_WPT 12

typedef struct gprte_t {
  char msg_num;
  char msg_mode;
  char route;
  gpwpl_t wpts[NUM_WPT];
} gprte_t;

/*
 * gps message variables
 */

extern unsigned short gpbod_count;  /* declared in os.c */
extern unsigned short gpgga_count;  /* declared in os.c */
extern unsigned short gpgll_count;  /* declared in os.c */
extern unsigned short gpgsa_count;  /* declared in os.c */
extern unsigned short gpgsv_count;  /* declared in os.c */
extern unsigned short gprmb_count;  /* declared in os.c */
extern unsigned short gprmc_count;  /* declared in os.c */
extern unsigned short gprte_count;  /* declared in os.c */
extern unsigned short gpwpl_count;  /* declared in os.c */
extern unsigned short pgrme_count;  /* declared in os.c */
extern unsigned short pgrmm_count;  /* declared in os.c */
extern unsigned short pgrmz_count;  /* declared in os.c */
extern unsigned short ignore_count; /* declared in os.c */

/*
 * variables, macros and display locations for ascii data
 */
#define SKIP_FIELD(p) while ( *p != ',' ) p++; p++;
#define COPY_FIELD(p,q) { register unsigned char *ch = q; \
                          while ( *p != ',' ) *ch++ = *p++; \
                          p++; }

extern unsigned char gps_row_1 [];
extern unsigned char gps_row_2 [];
extern unsigned char gps_row_3 [];
extern unsigned char gps_row_4 [];

/* from gprmb record */
#define WPT_LOC       gps_row_2 + 21
#define BRG_LOC       gps_row_2 + 28
#define RNG_LOC       gps_row_2 + 34
#define VMG_LOC       gps_row_4 + 12
#define CTERR_LOC     gps_row_4 + 20
#define CTERR_DIR_LOC gps_row_4 + 25

/* from gprmc record */
#define UTC_LOC       gps_row_4 + 34
#define LAT_LOC       gps_row_2 + 0
#define LAT_DIR_LOC   gps_row_2 + 8
#define LON_LOC       gps_row_2 + 10
#define LON_DIR_LOC   gps_row_2 + 19
#define SOG_LOC       gps_row_4 + 0
#define CSE_LOC       gps_row_4 + 6
#define DATE_LOC      gps_row_4 + 27
 
/*
 * gps parse functions
 */
void parse_gpbod();
void parse_gpgga();
void parse_gpgll();
void parse_gpgsa();
void parse_gpgsv();
void parse_gprmb();
void parse_gprmc();
void parse_gprte();
void parse_gpwpl();
void parse_pgrme();
void parse_pgrmm();
void parse_pgrmz();
