summaryrefslogtreecommitdiff
path: root/cgps.c
diff options
context:
space:
mode:
authorGary E. Miller <gem@rellim.com>2018-07-26 14:18:10 -0700
committerGary E. Miller <gem@rellim.com>2018-07-26 14:28:41 -0700
commit4f28911cecc5c4fb9c6038efb311447ecfbbd3c8 (patch)
tree1222d543fe2b4624f446328cd485ec6ebeae5738 /cgps.c
parent25edf0e836200ee4f6cf86fa4456635ee210484f (diff)
downloadgpsd-4f28911cecc5c4fb9c6038efb311447ecfbbd3c8.tar.gz
cgps: Big clean up of code.
More comments. Range checking of values. Tweaked formatting. More data in tall mode. Thanks to the support of Virgin Orbit for this patch.
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 {