summaryrefslogtreecommitdiff
path: root/cgps.c
diff options
context:
space:
mode:
Diffstat (limited to 'cgps.c')
-rw-r--r--cgps.c484
1 files changed, 292 insertions, 192 deletions
diff --git a/cgps.c b/cgps.c
index d8338800..03aa1575 100644
--- a/cgps.c
+++ b/cgps.c
@@ -84,7 +84,7 @@
/* This is the maximum ysize we need for the 'satellites' window. */
#define MAX_SATWIN_SIZE (MAX_POSSIBLE_SATS + SATWIN_OVERHEAD)
-/* Minimum xsize to display 3rd window with ECEF's, etc. */
+/* Minimum xsize to display 3rd window with DOPs, etc. */
#define MIN_ERRWIN_SIZE 100
#include <stdio.h>
@@ -122,11 +122,12 @@ static int debug;
static WINDOW *datawin, *satellites, *messages;
static bool raw_flag = false;
-static bool ecef_flag = false; /* tall screen, show ECEF */
+static bool show_ecefs = false; /* taller screen, show ECEFs */
+static bool show_more_dops = false; /* tall screen, show more DOPs */
static bool silent_flag = false;
static bool magnetic_flag = false;
static int window_ysize = 0;
-static int display_sats = 0;
+static int display_sats = 0; /* number of rows of sats to display */
#ifdef TRUENORTH
static bool compass_flag = false;
#endif /* TRUENORTH */
@@ -137,6 +138,61 @@ static bool compass_flag = false;
#define GPS_ERROR -2 /* low-level failure in GPS read */
#define GPS_TIMEOUT -3 /* low-level failure in GPS waiting */
+/* range test an int, return 5 chars + NUL */
+static const char *int_to_str(int val, int min, int max)
+{
+ static char buf[20];
+
+ if (val < min || val > max) {
+ return " n/a";
+ }
+ (void)snprintf(buf, sizeof(buf), "%5d", val);
+ return buf;
+}
+
+/* format a DOP into a 5 char string, handle NAN, INFINITE */
+static char *dop_to_str(double dop)
+{
+ static char buf[20];
+
+ if (isfinite(dop) == 0) {
+ return " n/a ";
+ }
+ (void)snprintf(buf, sizeof(buf), "%5.2f", dop);
+ return buf;
+}
+
+/* format an EP into a string, handle NAN, INFINITE */
+static char *ep_to_str(double ep, double factor, char *units)
+{
+ static char buf[128];
+
+ if (isfinite(ep) == 0) {
+ return " n/a ";
+ }
+ (void)snprintf(buf, sizeof(buf), "+/-%4.1f %.10s", ep * factor, units);
+ return buf;
+}
+
+/* format an ECEF p and v into a string, handle NAN, INFINITE */
+static char *ecef_to_str(double pos, double vel, double factor, char *units)
+{
+ static char buf[128];
+
+ if (isfinite(pos) == 0) {
+ if (isfinite(vel) == 0) {
+ return " n/a n/a ";
+ } else {
+ (void)snprintf(buf, sizeof(buf), " n/a %8.3f%.4s/s",
+ vel * factor, units);
+ }
+ } else {
+ (void)snprintf(buf, sizeof(buf), "% 14.3f%.4s %8.3f%.4s/s",
+ pos * factor, units, vel * factor, units);
+ }
+ return buf;
+}
+
/* Function to call when we're all done. Does a bit of clean-up. */
static void die(int sig)
{
@@ -176,25 +232,6 @@ static void die(int sig)
exit(EXIT_SUCCESS);
}
-/* format an ECEF p and v into a string, handle NAN, INFINITE */
-static char *ecef_to_str(double pos, double vel, double factor, char *units)
-{
- static char buf[128];
-
- if (isfinite(pos) == 0) {
- if (isfinite(vel) == 0) {
- return " n/a n/a ";
- } else {
- (void)snprintf(buf, sizeof(buf), " n/a %8.2f%.4s/s",
- vel * factor, units);
- }
- } else {
- (void)snprintf(buf, sizeof(buf), "% 14.4f%.4s %8.2f%.4s/s",
- pos * factor, units, vel * factor, units);
- }
- return buf;
-}
-
static enum deg_str_type deg_type = deg_dd;
static void windowsetup(void)
@@ -220,8 +257,8 @@ static void windowsetup(void)
* satellites (MAXCHANNELS - 2) with space still left at the bottom,
* add a window at the bottom in which to scroll raw gpsd data.
*
- * 4. If the screen is wide enough to display extra data, add a
- * window on the right for PDOP, etc.
+ * 4. If the screen is tall enough to display extra data, expand
+ * data window down to show DOPs, ECEFs, etc.
*/
int xsize, ysize;
@@ -249,25 +286,35 @@ static void windowsetup(void)
} else
#endif /* TRUENORTH */
{
- if (ysize > MAX_GPS_DATAWIN_YSIZE + 7) {
+ if (ysize > MAX_GPS_DATAWIN_YSIZE + 10) {
+ raw_flag = true;
+ show_ecefs = true;
+ show_more_dops = true;
+ window_ysize = MAX_GPS_DATAWIN_YSIZE + 7;
+ } else if (ysize > MAX_GPS_DATAWIN_YSIZE + 6) {
raw_flag = true;
- ecef_flag = true;
- window_ysize = MAX_GPS_DATAWIN_YSIZE + 3;
+ show_ecefs = false;
+ show_more_dops = true;
+ window_ysize = MAX_GPS_DATAWIN_YSIZE + 4;
} else if (ysize > MAX_GPS_DATAWIN_YSIZE) {
raw_flag = true;
- ecef_flag = false;
+ show_ecefs = false;
+ show_more_dops = false;
window_ysize = MAX_GPS_DATAWIN_YSIZE;
} else if (ysize == MAX_GPS_DATAWIN_YSIZE) {
raw_flag = false;
- ecef_flag = false;
+ show_ecefs = false;
+ show_more_dops = false;
window_ysize = MAX_GPS_DATAWIN_YSIZE;
} else if (ysize > MIN_GPS_DATAWIN_YSIZE) {
raw_flag = true;
- ecef_flag = false;
+ show_ecefs = false;
+ show_more_dops = false;
window_ysize = MIN_GPS_DATAWIN_YSIZE;
} else if (ysize == MIN_GPS_DATAWIN_YSIZE) {
raw_flag = false;
- ecef_flag = false;
+ show_ecefs = false;
+ show_more_dops = false;
window_ysize = MIN_GPS_DATAWIN_YSIZE;
} else {
(void)mvprintw(0, 0,
@@ -284,6 +331,7 @@ static void windowsetup(void)
/* Set up the screen for either a compass or a gps receiver. */
if (compass_flag) {
/* We're a compass, set up accordingly. */
+ int row = 1;
datawin = newwin(window_ysize, DATAWIN_WIDTH, 0, 0);
(void)nodelay(datawin, (bool) TRUE);
@@ -297,18 +345,19 @@ static void windowsetup(void)
(void)refresh();
/* Do the initial field label setup. */
- (void)mvwprintw(datawin, 1, DATAWIN_DESC_OFFSET, "Time:");
- (void)mvwprintw(datawin, 2, DATAWIN_DESC_OFFSET, "Heading:");
- (void)mvwprintw(datawin, 3, DATAWIN_DESC_OFFSET, "Pitch:");
- (void)mvwprintw(datawin, 4, DATAWIN_DESC_OFFSET, "Roll:");
- (void)mvwprintw(datawin, 5, DATAWIN_DESC_OFFSET, "Dip:");
- (void)mvwprintw(datawin, 6, DATAWIN_DESC_OFFSET, "Rcvr Type:");
+ (void)mvwprintw(datawin, row++, DATAWIN_DESC_OFFSET, "Time:");
+ (void)mvwprintw(datawin, row++, DATAWIN_DESC_OFFSET, "Heading:");
+ (void)mvwprintw(datawin, row++, DATAWIN_DESC_OFFSET, "Pitch:");
+ (void)mvwprintw(datawin, row++, DATAWIN_DESC_OFFSET, "Roll:");
+ (void)mvwprintw(datawin, row++, DATAWIN_DESC_OFFSET, "Dip:");
+ (void)mvwprintw(datawin, row++, DATAWIN_DESC_OFFSET, "Rcvr Type:");
(void)wborder(datawin, 0, 0, 0, 0, 0, 0, 0, 0);
} else
#endif /* TRUENORTH */
{
/* We're a GPS, set up accordingly. */
+ int row = 1;
datawin = newwin(window_ysize, DATAWIN_WIDTH, 0, 0);
satellites =
@@ -325,14 +374,14 @@ static void windowsetup(void)
(void)refresh();
/* Do the initial field label setup. */
- (void)mvwprintw(datawin, 1, DATAWIN_DESC_OFFSET, "Time:");
- (void)mvwprintw(datawin, 2, DATAWIN_DESC_OFFSET, "Latitude:");
- (void)mvwprintw(datawin, 3, DATAWIN_DESC_OFFSET, "Longitude:");
- (void)mvwprintw(datawin, 4, DATAWIN_DESC_OFFSET, "Altitude:");
- (void)mvwprintw(datawin, 5, DATAWIN_DESC_OFFSET, "Speed:");
- (void)mvwprintw(datawin, 6, DATAWIN_DESC_OFFSET, "Heading:");
- (void)mvwprintw(datawin, 7, DATAWIN_DESC_OFFSET, "Climb:");
- (void)mvwprintw(datawin, 8, DATAWIN_DESC_OFFSET, "Status:");
+ (void)mvwaddstr(datawin, row++, DATAWIN_DESC_OFFSET, "Time:");
+ (void)mvwaddstr(datawin, row++, DATAWIN_DESC_OFFSET, "Latitude:");
+ (void)mvwaddstr(datawin, row++, DATAWIN_DESC_OFFSET, "Longitude:");
+ (void)mvwaddstr(datawin, row++, DATAWIN_DESC_OFFSET, "Altitude:");
+ (void)mvwaddstr(datawin, row++, DATAWIN_DESC_OFFSET, "Speed:");
+ (void)mvwaddstr(datawin, row++, DATAWIN_DESC_OFFSET, "Heading:");
+ (void)mvwaddstr(datawin, row++, DATAWIN_DESC_OFFSET, "Climb:");
+ (void)mvwaddstr(datawin, row++, DATAWIN_DESC_OFFSET, "Status:");
/* Note that the following fields are exceptions to the
* sizing rule. The minimum window size does not include these
@@ -343,36 +392,58 @@ static void windowsetup(void)
* sounded interesting. ;^) */
if (window_ysize >= MAX_GPS_DATAWIN_YSIZE) {
- int row = 9;
-
- (void)mvwprintw(datawin, row++, DATAWIN_DESC_OFFSET,
- "Longitude Err:");
- (void)mvwprintw(datawin, row++, DATAWIN_DESC_OFFSET,
- "Latitude Err:");
- (void)mvwprintw(datawin, row++, DATAWIN_DESC_OFFSET,
- "Altitude Err:");
+ (void)mvwaddstr(datawin, row++, DATAWIN_DESC_OFFSET,
+ "Long Err (XDOP, EPX):");
+ (void)mvwaddstr(datawin, row++, DATAWIN_DESC_OFFSET,
+ "Lat Err (YDOP, EPY):");
+ (void)mvwaddstr(datawin, row++, DATAWIN_DESC_OFFSET,
+ "Alt Err (VDOP, EPV):");
+
+ if (show_more_dops) {
+ (void)mvwaddstr(datawin, row++, DATAWIN_DESC_OFFSET,
+ "2D Err (HDOP, CEP):");
+ (void)mvwaddstr(datawin, row++, DATAWIN_DESC_OFFSET,
+ "3D Err (PDOP, SEP):");
+ (void)mvwaddstr(datawin, row++, DATAWIN_DESC_OFFSET,
+ "Time Err (TDOP):");
+ (void)mvwaddstr(datawin, row++, DATAWIN_DESC_OFFSET,
+ "Geo Err (GDOP):");
+ }
- if (ecef_flag){
- (void)mvwprintw(datawin, row++, DATAWIN_DESC_OFFSET,
+ if (show_ecefs) {
+ (void)mvwaddstr(datawin, row++, DATAWIN_DESC_OFFSET,
"ECEF X, VX:");
- (void)mvwprintw(datawin, row++, DATAWIN_DESC_OFFSET,
+ (void)mvwaddstr(datawin, row++, DATAWIN_DESC_OFFSET,
"ECEF Y, VY:");
- (void)mvwprintw(datawin, row++, DATAWIN_DESC_OFFSET,
+ (void)mvwaddstr(datawin, row++, DATAWIN_DESC_OFFSET,
"ECEF Z, VZ:");
}
- (void)mvwprintw(datawin, row++, DATAWIN_DESC_OFFSET, "Course Err:");
- (void)mvwprintw(datawin, row++, DATAWIN_DESC_OFFSET, "Speed Err:");
+ (void)mvwaddstr(datawin, row++, DATAWIN_DESC_OFFSET,
+ "Speed Err (EPS):");
+ (void)mvwaddstr(datawin, row++, DATAWIN_DESC_OFFSET,
+ "Head Err (EPD):");
/* it's actually esr that thought *these* were interesting */
- (void)mvwprintw(datawin, row++, DATAWIN_DESC_OFFSET,
+ (void)mvwaddstr(datawin, row++, DATAWIN_DESC_OFFSET,
"Time offset:");
- (void)mvwprintw(datawin, row++, DATAWIN_DESC_OFFSET,
+ (void)mvwaddstr(datawin, row++, DATAWIN_DESC_OFFSET,
"Grid Square:");
}
(void)wborder(datawin, 0, 0, 0, 0, 0, 0, 0, 0);
- /* PRN is not unique, starting at 1, for GPS, GAILEO, etc. */
- (void)mvwprintw(satellites, 1, 1, " PRN Elev Azim SNR Used ");
+ /* PRN is not unique for all GNSS systems.
+ * Each GNSS (GPS, GALILEO, BeiDou, etc.) numbers their PRN from 1.
+ * What we really have here is USI, Universal Sat ID
+ * The USI for each GNSS satellite is unique, starting at 1.
+ * Not all GPS receivers compute the USI the same way. YMMV
+ *
+ * Javad (GREIS) GPS receivers compute USI this way:
+ * GPS is USI 1-37, GLONASS 38-70, GALILEO 71-119, SBAS 120-142,
+ * QZSS 193-197, BeiDou 211-247
+ *
+ * Geostar GPS receivers compute USI this way:
+ * GPS is USI 1 to 32, SBAS is 33 to 64, GLONASS is 65 to 96 */
+ (void)mvwaddstr(satellites, 1, 1, " PRN Elev Azim SNR Used ");
(void)wborder(satellites, 0, 0, 0, 0, 0, 0, 0, 0);
}
}
@@ -393,51 +464,50 @@ static void resize(int sig UNUSED)
static void update_compass_panel(struct gps_data_t *gpsdata)
{
char scr[128];
+ int row = 1;
/* Print time/date. */
if (isfinite(gpsdata->fix.time) != 0) {
(void)unix_to_iso8601(gpsdata->fix.time, scr, sizeof(scr));
} else
- (void)snprintf(scr, sizeof(scr), " n/a");
- (void)mvwprintw(datawin, 1, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);
+ (void)snprintf(scr, sizeof(scr), "n/a");
+ (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);
/* Fill in the heading. */
if (isfinite(gpsdata->fix.track) != 0) {
(void)snprintf(scr, sizeof(scr), "%.1f degrees", gpsdata->fix.track);
} else
- (void)snprintf(scr, sizeof(scr), " n/a");
- (void)mvwprintw(datawin, 2, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);
+ (void)snprintf(scr, sizeof(scr), "n/a");
+ (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);
/* Fill in the climb. */
if (isfinite(gpsdata->fix.climb) != 0) {
(void)snprintf(scr, sizeof(scr), "%.2f", gpsdata->fix.climb);
} else
- (void)snprintf(scr, sizeof(scr), " n/a");
- (void)mvwprintw(datawin, 3, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);
+ (void)snprintf(scr, sizeof(scr), "n/a");
+ (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);
/* Fill in the speed. */
if (isfinite(gpsdata->fix.speed) != 0)
(void)snprintf(scr, sizeof(scr), "%.2f", gpsdata->fix.speed);
else
- (void)snprintf(scr, sizeof(scr), " n/a");
- (void)mvwprintw(datawin, 4, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);
+ (void)snprintf(scr, sizeof(scr), "n/a");
+ (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);
/* Fill in the altitude. */
if (isfinite(gpsdata->fix.altitude) != 0)
(void)snprintf(scr, sizeof(scr), "%.3f", gpsdata->fix.altitude);
else
- (void)snprintf(scr, sizeof(scr), " n/a");
- (void)mvwprintw(datawin, 5, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);
+ (void)snprintf(scr, sizeof(scr), "n/a");
+ (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);
/* When we need to fill in receiver type again, do it here. */
- (void)mvwprintw(datawin, 6, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);
-
- /* Be quiet if the user requests silence. */
- if (!silent_flag && raw_flag) {
- (void)waddstr(messages, message);
- }
+ (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);
(void)wrefresh(datawin);
- if (raw_flag) {
+
+ if (raw_flag && !silent_flag) {
+ /* Be quiet if the user requests silence. */
+ (void)waddstr(messages, message);
(void)wrefresh(messages);
}
}
@@ -457,11 +527,10 @@ static int sat_cmp(const void *p1, const void *p2)
}
-static void update_gps_panel(struct gps_data_t *gpsdata, char * message)
+static void update_gps_panel(struct gps_data_t *gpsdata, char *message)
/* This gets called once for each new GPS sentence. */
{
int newstate;
- int row = 9;
char scr[128], *s;
/* This is for the satellite status display. Originally lifted from
@@ -472,65 +541,59 @@ static void update_gps_panel(struct gps_data_t *gpsdata, char * message)
(void)mvwprintw(satellites, 1, 32, "%2d", gpsdata->satellites_used);
if (gpsdata->satellites_visible != 0) {
- int i;
+ int sat_no;
+ int loop_end = (display_sats < gpsdata->satellites_visible) ? \
+ display_sats : gpsdata->satellites_visible;
+
qsort( gpsdata->skyview, gpsdata->satellites_visible,
sizeof( struct satellite_t), sat_cmp);
- if (display_sats >= MAX_POSSIBLE_SATS) {
- for (i = 0; i < MAX_POSSIBLE_SATS; i++) {
- if (i < gpsdata->satellites_visible) {
- /* allow for 3 digit elevation,
- * ublox uses -91 to signal something undocumented */
- (void)snprintf(scr, sizeof(scr),
- " %3d %3d %3d %2d %c",
- gpsdata->skyview[i].PRN,
- gpsdata->skyview[i].elevation,
- gpsdata->skyview[i].azimuth,
- (int)gpsdata->skyview[i].ss,
- gpsdata->skyview[i].used ? 'Y' : 'N');
- } else {
- (void)strlcpy(scr, "", sizeof(scr));
- }
- (void)mvwprintw(satellites, i + 2, 1, "%-*s",
- SATELLITES_WIDTH - 3, scr);
- }
- } else {
- int n = 0;
- for (i = 0; i < MAX_POSSIBLE_SATS; i++) {
- if (n < display_sats) {
- if ((i < gpsdata->satellites_visible)
- && (gpsdata->skyview[i].used
- || (gpsdata->satellites_visible <= display_sats))) {
- (void)snprintf(scr, sizeof(scr),
- " %3d %2d %3d %2d %c",
- gpsdata->skyview[i].PRN,
- gpsdata->skyview[i].elevation,
- gpsdata->skyview[i].azimuth,
- (int)gpsdata->skyview[i].ss,
- gpsdata->skyview[i].used ? 'Y' : 'N');
- (void)mvwprintw(satellites, n + 2, 1, "%-*s",
- SATELLITES_WIDTH - 3, scr);
- n++;
- }
- }
- }
+ /* displayed all sats that fit, maybe all of them */
+ for (sat_no = 0; sat_no < loop_end; sat_no++) {
+ int column = 1; /* column to write to */
+
+ /* no GPS uses PRN 0, some use 255 for 'unknown'
+ * u-blox uses PRN 1-255, NMEA 4.0 uses 1-437 */
+ (void)mvwaddstr(satellites, sat_no + 2, column,
+ int_to_str(gpsdata->skyview[sat_no].PRN,
+ 1, 438));
+ /* u-blox uses -91 to signal something undocumented */
+ column += 6;
+ (void)mvwaddstr(satellites, sat_no + 2, column,
+ int_to_str(gpsdata->skyview[sat_no].elevation,
+ -90, 90));
+ column += 7;
+ (void)mvwaddstr(satellites, sat_no + 2, column,
+ int_to_str(gpsdata->skyview[sat_no].azimuth,
+ 0, 359));
+ column += 6;
+ (void)mvwaddstr(satellites, sat_no + 2, column,
+ int_to_str((int)round(gpsdata->skyview[sat_no].ss),
+ 0, 254));
+ column += 6;
+ (void)mvwprintw(satellites, sat_no + 2, column, " %c",
+ gpsdata->skyview[sat_no].used ? 'Y' : 'N');
+ }
- if (n < display_sats) {
- for (i = n; i <= display_sats; i++) {
- (void)mvwprintw(satellites, i + 2, 1, "%-*s",
- SATELLITES_WIDTH - 3, "");
- }
+ /* last line is either blank, or More... */
+ if (sat_no < gpsdata->satellites_visible) {
+ /* Too many sats to show them all, tell the user. */
+ (void)mvwprintw(satellites, sat_no + 2, 1, "%-*s",
+ SATELLITES_WIDTH - 3, "More...");
+ } else {
+ /* Clear old data from the unused lines at bottom. */
+ for ( ; sat_no <= display_sats; sat_no++) {
+ (void)mvwprintw(satellites, sat_no + 2, 1, "%-*s",
+ SATELLITES_WIDTH - 3, "");
}
-
}
}
- row = 1;
/* Print time/date. */
if (isfinite(gpsdata->fix.time) != 0) {
(void)unix_to_iso8601(gpsdata->fix.time, scr, sizeof(scr));
} else
- (void)snprintf(scr, sizeof(scr), " n/a");
- (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);
+ (void)snprintf(scr, sizeof(scr), "n/a");
+ (void)mvwprintw(datawin, 1, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);
/* Fill in the latitude. */
@@ -539,8 +602,8 @@ static void update_gps_panel(struct gps_data_t *gpsdata, char * message)
deg_to_str(deg_type, fabs(gpsdata->fix.latitude)),
(gpsdata->fix.latitude < 0) ? 'S' : 'N');
} else
- (void)snprintf(scr, sizeof(scr), " n/a");
- (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);
+ (void)snprintf(scr, sizeof(scr), "n/a");
+ (void)mvwprintw(datawin, 2, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);
/* Fill in the longitude. */
if (gpsdata->fix.mode >= MODE_2D && isfinite(gpsdata->fix.longitude) != 0) {
@@ -548,24 +611,24 @@ static void update_gps_panel(struct gps_data_t *gpsdata, char * message)
deg_to_str(deg_type, fabs(gpsdata->fix.longitude)),
(gpsdata->fix.longitude < 0) ? 'W' : 'E');
} else
- (void)snprintf(scr, sizeof(scr), " n/a");
- (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);
+ (void)snprintf(scr, sizeof(scr), "n/a");
+ (void)mvwprintw(datawin, 3, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);
/* Fill in the altitude. */
if (gpsdata->fix.mode >= MODE_3D && isfinite(gpsdata->fix.altitude) != 0)
(void)snprintf(scr, sizeof(scr), "%9.3f %s",
gpsdata->fix.altitude * altfactor, altunits);
else
- (void)snprintf(scr, sizeof(scr), " n/a");
- (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);
+ (void)snprintf(scr, sizeof(scr), "n/a");
+ (void)mvwprintw(datawin, 4, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);
/* Fill in the speed. */
if (gpsdata->fix.mode >= MODE_2D && isfinite(gpsdata->fix.track) != 0)
(void)snprintf(scr, sizeof(scr), "%8.2f %s",
gpsdata->fix.speed * speedfactor, speedunits);
else
- (void)snprintf(scr, sizeof(scr), " n/a");
- (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);
+ (void)snprintf(scr, sizeof(scr), "n/a");
+ (void)mvwprintw(datawin, 5, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);
/* Fill in the heading. */
if (gpsdata->fix.mode >= MODE_2D && isfinite(gpsdata->fix.track) != 0) {
@@ -580,16 +643,16 @@ static void update_gps_panel(struct gps_data_t *gpsdata, char * message)
magheading);
}
} else
- (void)snprintf(scr, sizeof(scr), " n/a");
- (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET, " %-*s", 25, scr);
+ (void)snprintf(scr, sizeof(scr), "n/a");
+ (void)mvwprintw(datawin, 6, DATAWIN_VALUE_OFFSET, " %-*s", 25, scr);
/* Fill in the rate of climb. */
if (gpsdata->fix.mode >= MODE_3D && isfinite(gpsdata->fix.climb) != 0)
(void)snprintf(scr, sizeof(scr), "%8.2f %s/min",
gpsdata->fix.climb * altfactor * 60, altunits);
else
- (void)snprintf(scr, sizeof(scr), " n/a");
- (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);
+ (void)snprintf(scr, sizeof(scr), "n/a");
+ (void)mvwprintw(datawin, 7, DATAWIN_VALUE_OFFSET, "%-*s", 27, scr);
/* Fill in the GPS status and the time since the last state
* change. */
@@ -617,7 +680,7 @@ static void update_gps_panel(struct gps_data_t *gpsdata, char * message)
break;
}
}
- (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET + 1, "%-*s", 26, scr);
+ (void)mvwprintw(datawin, 8, DATAWIN_VALUE_OFFSET + 1, "%-*s", 26, scr);
/* Note that the following fields are exceptions to the
* sizing rule. The minimum window size does not include these
@@ -628,36 +691,79 @@ static void update_gps_panel(struct gps_data_t *gpsdata, char * message)
* sounded interesting. ;^) */
if (window_ysize >= (MIN_GPS_DATAWIN_YSIZE + 5)) {
- /* Fill in the estimated horizontal position error. */
- if (isfinite(gpsdata->fix.epx) != 0)
- (void)snprintf(scr, sizeof(scr), "+/- %d %s",
- (int)(gpsdata->fix.epx * altfactor), altunits);
- else
- (void)snprintf(scr, sizeof(scr), " n/a");
- (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET + 5, "%-*s", 22,
- scr);
-
- if (isfinite(gpsdata->fix.epy) != 0)
- (void)snprintf(scr, sizeof(scr), "+/- %d %s",
- (int)(gpsdata->fix.epy * altfactor), altunits);
- else
- (void)snprintf(scr, sizeof(scr), " n/a");
- (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET + 5, "%-*s", 22,
- scr);
+ int row = 9;
+ char *ep_str = NULL;
+ char *dop_str = NULL;
+
+ /* Fill in the estimated latitude position error, XDOP. */
+ ep_str = ep_to_str(gpsdata->fix.epx, altfactor, altunits);
+ dop_str = dop_to_str(gpsdata->dop.xdop);
+ (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET + 8, "%s, %-*s",
+ dop_str, 11, ep_str);
+
+ /* Fill in the estimated longitude position error, YDOP. */
+ ep_str = ep_to_str(gpsdata->fix.epy, altfactor, altunits);
+ dop_str = dop_to_str(gpsdata->dop.ydop);
+ (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET + 8, "%s, %-*s",
+ dop_str, 11, ep_str);
+
+ /* Fill in the estimated velocity error, VDOP. */
+ ep_str = ep_to_str(gpsdata->fix.epv, altfactor, altunits);
+ dop_str = dop_to_str(gpsdata->dop.vdop);
+ (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET + 8, "%s, %-*s",
+ dop_str, 11, ep_str);
+
+ /* extra tall screen, show more DOPs */
+ if (show_more_dops) {
+ double cep = NAN; /* 2D EP */
+ double sep = NAN; /* 3D EP */
+
+ /* Calculate estimated 2D circular position error, CEP */
+ if (isfinite(gpsdata->fix.epy) != 0
+ && isfinite(gpsdata->fix.epy) != 0) {
+ /* http://gauss.gge.unb.ca/papers.pdf/gpsworld.may99.pdf */
+ /* CEP is just the hypotenuse of the triangle of epx and epy */
+ cep = sqrt((gpsdata->fix.epx * gpsdata->fix.epx) +
+ (gpsdata->fix.epy * gpsdata->fix.epy));
+ if (isfinite(gpsdata->fix.epv) != 0) {
+ /* SEP is the spherical (3D) error probability.
+ * The square root of the sum of the squares of epx, epy,
+ * and epv */
+ sep = sqrt((gpsdata->fix.epx * gpsdata->fix.epx) +
+ (gpsdata->fix.epy * gpsdata->fix.epy) +
+ (gpsdata->fix.epv * gpsdata->fix.epv));
+ }
+ }
- /* Fill in the estimated vertical position error. */
- if (isfinite(gpsdata->fix.epv) != 0)
- (void)snprintf(scr, sizeof(scr), "+/- %d %s",
- (int)(gpsdata->fix.epv * altfactor), altunits);
- else
- (void)snprintf(scr, sizeof(scr), " n/a");
- (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET + 5, "%-*s", 22,
- scr);
+ /* Fill in the estimated horizontal (2D) error, HDOP */
+ ep_str = ep_to_str(cep, altfactor, altunits);
+ dop_str = dop_to_str(gpsdata->dop.hdop);
+ (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET + 8,
+ "%s, %-*s", dop_str, 11, ep_str);
+
+ /* (spherical) position error, 3D error, PDOP */
+ ep_str = ep_to_str(sep, altfactor, altunits);
+ dop_str = dop_to_str(gpsdata->dop.pdop);
+ (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET + 8,
+ "%s, %-*s", dop_str, 11, ep_str);
+
+ /* time dilution of precision, TDOP */
+ /* FIXME: time ep? */
+ dop_str = dop_to_str(gpsdata->dop.tdop);
+ (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET + 8, "%-*s",
+ 18, dop_str);
+
+ /* geometric dilution of precision, GDOP */
+ /* FIXME: gdop ep? */
+ dop_str = dop_to_str(gpsdata->dop.gdop);
+ (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET + 8, "%-*s",
+ 18, dop_str);
+ }
- /* extra large screen, show more ECEF */
- if (ecef_flag) {
- char *estr;
+ /* extra large screen, show ECEF */
+ if (show_ecefs) {
+ char *estr;
/* Fill in the ECEF's. */
estr = ecef_to_str(gpsdata->fix.ecef.x, gpsdata->fix.ecef.vx,
@@ -674,32 +780,26 @@ static void update_gps_panel(struct gps_data_t *gpsdata, char * message)
1, " m");
(void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET - 3, "%-*s",
27, estr);
- }
+ }
- /* Fill in the estimated track error. */
- if (isfinite(gpsdata->fix.epd) != 0)
- (void)snprintf(scr, sizeof(scr), "+/- %d deg",
- (int)(gpsdata->fix.epd));
- else
- (void)snprintf(scr, sizeof(scr), " n/a");
- (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET + 5, "%-*s", 22,
- scr);
- /* Fill in the estimated speed error. */
- if (isfinite(gpsdata->fix.eps) != 0)
- (void)snprintf(scr, sizeof(scr), "+/- %d %s",
- (int)(gpsdata->fix.eps * speedfactor), speedunits);
- else
- (void)snprintf(scr, sizeof(scr), " n/a");
- (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET + 5, "%-*s", 22,
- scr);
+ /* Fill in the estimated speed error, EPS. */
+ ep_str = ep_to_str(gpsdata->fix.eps, speedfactor, speedunits);
+ (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET + 8,
+ " %-*s", 11,
+ ep_str);
+
+ /* Fill in the estimated track error, EPD. */
+ ep_str = ep_to_str(gpsdata->fix.epd, speedfactor, "deg");
+ (void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET + 8, "%-*s", 18,
+ ep_str);
- /* Fill in the time offset, milli seconds. */
+ /* Fill in the time offset, milliseconds. */
if (isfinite(gpsdata->fix.time) != 0)
(void)snprintf(scr, sizeof(scr), "%6.3f sec",
(double)(timestamp()-gpsdata->fix.time));
else
- (void)snprintf(scr, sizeof(scr), " n/a");
+ (void)snprintf(scr, sizeof(scr), " n/a");
(void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET + 8, "%-*s", 18,
scr);
/* Fill in the grid square (esr thought *this* one was interesting). */
@@ -707,7 +807,7 @@ static void update_gps_panel(struct gps_data_t *gpsdata, char * message)
isfinite(gpsdata->fix.latitude) != 0))
s = maidenhead(gpsdata->fix.latitude,gpsdata->fix.longitude);
else
- s = " n/a";
+ s = "n/a";
(void)mvwprintw(datawin, row++, DATAWIN_VALUE_OFFSET + 9, "%-*s",
18, s);
@@ -890,14 +990,14 @@ int main(int argc, char *argv[])
/* wait 1/2 second for gpsd */
if (!gps_waiting(&gpsdata, 500000)) {
- /* 240 tries at .5 Sec a try is a 2 minute timeout */
+ /* 240 tries at 0.5 seconds a try is a 2 minute timeout */
if ( 240 < wait_clicks++ )
die(GPS_TIMEOUT);
} else {
wait_clicks = 0;
errno = 0;
*message = '\0';
- if (gps_read(&gpsdata, message, sizeof(message)) == -1) {
+ if (gps_read(&gpsdata, message, sizeof(message)) == -1) {
(void)fprintf(stderr, "cgps: socket error 4\n");
die(errno == 0 ? GPS_GONE : GPS_ERROR);
} else {