static gps_mask_t decode_itk_navfix(struct gps_device_t *session, unsigned char *buf, size_t len) { unsigned short flags, pflags; gps_mask_t mask = 0; double epx, epy, epz, evx, evy, evz, eph; if (len != 296) { gpsd_report(LOG_PROG, "ITALK: bad NAV_FIX (len %zu, should be 296)\n", len); return -1; } flags = (ushort) getleu16(buf, 7 + 4); //cflags = (ushort) getleu16(buf, 7 + 6); pflags = (ushort) getleu16(buf, 7 + 8); session->gpsdata.status = STATUS_NO_FIX; session->newdata.mode = MODE_NO_FIX; mask = ONLINE_SET | MODE_SET | STATUS_SET | CLEAR_IS; /* just bail out if this fix is not marked valid */ if (0 != (pflags & FIX_FLAG_MASK_INVALID) || 0 == (flags & FIXINFO_FLAG_VALID)) return mask; session->newdata.time = gpsd_gpstime_resolve(session, (unsigned short) getles16(buf, 7 + 82), (unsigned int)getleu32(buf, 7 + 84) / 1000.0); mask |= TIME_SET | PPSTIME_IS; epx = (double)(getles32(buf, 7 + 96) / 100.0); epy = (double)(getles32(buf, 7 + 100) / 100.0); epz = (double)(getles32(buf, 7 + 104) / 100.0); evx = (double)(getles32(buf, 7 + 186) / 1000.0); evy = (double)(getles32(buf, 7 + 190) / 1000.0); evz = (double)(getles32(buf, 7 + 194) / 1000.0); ecef_to_wgs84fix(&session->newdata, &session->gpsdata.separation, epx, epy, epz, evx, evy, evz); mask |= LATLON_SET | ALTITUDE_SET | SPEED_SET | TRACK_SET | CLIMB_SET; eph = (double)(getles32(buf, 7 + 252) / 100.0); /* eph is a circular error, sqrt(epx**2 + epy**2) */ session->newdata.epx = session->newdata.epy = eph / sqrt(2); session->newdata.eps = (double)(getles32(buf, 7 + 254) / 100.0); #define MAX(a,b) (((a) > (b)) ? (a) : (b)) session->gpsdata.satellites_used = (int)MAX(getleu16(buf, 7 + 12), getleu16(buf, 7 + 14)); mask |= USED_IS; if (flags & FIX_CONV_DOP_VALID) { session->gpsdata.dop.hdop = (double)(getleu16(buf, 7 + 56) / 100.0); session->gpsdata.dop.gdop = (double)(getleu16(buf, 7 + 58) / 100.0); session->gpsdata.dop.pdop = (double)(getleu16(buf, 7 + 60) / 100.0); session->gpsdata.dop.vdop = (double)(getleu16(buf, 7 + 62) / 100.0); session->gpsdata.dop.tdop = (double)(getleu16(buf, 7 + 64) / 100.0); mask |= DOP_SET; } if ((pflags & FIX_FLAG_MASK_INVALID) == 0 && (flags & FIXINFO_FLAG_VALID) != 0) { if (pflags & FIX_FLAG_3DFIX) session->newdata.mode = MODE_3D; else session->newdata.mode = MODE_2D; if (pflags & FIX_FLAG_DGPS_CORRECTION) session->gpsdata.status = STATUS_DGPS_FIX; else session->gpsdata.status = STATUS_FIX; } gpsd_report(LOG_DATA, "NAV_FIX: time=%.2f, lat=%.2f lon=%.2f alt=%.f speed=%.2f track=%.2f climb=%.2f mode=%d status=%d gdop=%.2f pdop=%.2f hdop=%.2f vdop=%.2f tdop=%.2f\n", session->newdata.time, session->newdata.latitude, session->newdata.longitude, session->newdata.altitude, session->newdata.speed, session->newdata.track, session->newdata.climb, session->newdata.mode, session->gpsdata.status, session->gpsdata.dop.gdop, session->gpsdata.dop.pdop, session->gpsdata.dop.hdop, session->gpsdata.dop.vdop, session->gpsdata.dop.tdop); return mask; }
/*@ +charint @*/ gps_mask_t evermore_parse(struct gps_device_t *session, unsigned char *buf, size_t len) { unsigned char buf2[MAX_PACKET_LENGTH], *cp, *tp; size_t i, datalen; unsigned int used, visible, satcnt; double version; gps_mask_t mask = 0; if (len == 0) return 0; /* time to unstuff it and discard the header and footer */ cp = buf + 2; tp = buf2; if (*cp == 0x10) cp++; datalen = (size_t)*cp++; gpsd_report(LOG_RAW, "raw EverMore packet type 0x%02x, length %d: %s\n", *cp, len, gpsd_hexdump(buf, len)); datalen -= 2; for (i = 0; i < (size_t)datalen; i++) { *tp = *cp++; if (*tp == 0x10) cp++; tp++; } /*@ -usedef -compdef @*/ gpsd_report(LOG_RAW, "EverMore packet type 0x%02x, length %d: %s\n", buf2[0], datalen, gpsd_hexdump(buf2, datalen)); /*@ +usedef +compdef @*/ (void)snprintf(session->gpsdata.tag, sizeof(session->gpsdata.tag), "EID%d",(int)buf2[0]); switch (getub(buf2, 1)) { case 0x02: /* Navigation Data Output */ session->gpsdata.fix.time = session->gpsdata.sentence_time = gpstime_to_unix((int)getuw(buf2, 2), getul(buf2, 4)*0.01) - session->context->leap_seconds; ecef_to_wgs84fix(&session->gpsdata, getsl(buf2, 8)*1.0, getsl(buf2, 12)*1.0, getsl(buf2, 16)*1.0, getsw(buf2, 20)/10.0, getsw(buf2, 22)/10.0, getsw(buf2, 24)/10.0); used = getub(buf2, 26) & 0x0f; visible = (getub(buf2, 26) & 0xf0) >> 4; version = getuw(buf2, 27)/100.0; /* that's all the information in this packet */ if (used < 3) session->gpsdata.fix.mode = MODE_NO_FIX; else if (used == 3) session->gpsdata.fix.mode = MODE_2D; else { session->gpsdata.fix.mode = MODE_3D; mask |= ALTITUDE_SET | CLIMB_SET; } gpsd_report(LOG_PROG, "NDO 0x02: version %3.2f, mode=%d, status=%d, visible=%d, used=%d\n", version, session->gpsdata.fix.mode, session->gpsdata.status, visible, used); mask |= TIME_SET | LATLON_SET | TRACK_SET | SPEED_SET | MODE_SET | CYCLE_START_SET; if (session->subtype[0] == '\0') { (void)snprintf(session->subtype, sizeof(session->subtype), "%3.2f", version); mask |= DEVICEID_SET; } return mask; case 0x04: /* DOP Data Output */ session->gpsdata.fix.time = session->gpsdata.sentence_time = gpstime_to_unix((int)getuw(buf2, 2), getul(buf2, 4)*0.01) - session->context->leap_seconds; session->gpsdata.gdop = (double)getub(buf2, 8)*0.1; session->gpsdata.pdop = (double)getub(buf2, 9)*0.1; session->gpsdata.hdop = (double)getub(buf2, 10)*0.1; session->gpsdata.vdop = (double)getub(buf2, 11)*0.1; session->gpsdata.tdop = (double)getub(buf2, 12)*0.1; switch (getub(buf2, 13)) { case 0: /* no position fix */ case 1: /* manual calls this "1D navigation" */ session->gpsdata.status = STATUS_NO_FIX; session->gpsdata.fix.mode = MODE_NO_FIX; break; case 2: /* 2D navigation */ session->gpsdata.status = STATUS_FIX; session->gpsdata.fix.mode = MODE_2D; break; case 3: /* 3D navigation */ session->gpsdata.status = STATUS_FIX; session->gpsdata.fix.mode = MODE_3D; break; case 4: /* 3D navigation with DGPS */ session->gpsdata.status = STATUS_DGPS_FIX; session->gpsdata.fix.mode = MODE_3D; break; } /* that's all the information in this packet */ gpsd_report(LOG_PROG, "DDO 0x04: mode=%d, status=%d\n", session->gpsdata.fix.mode, session->gpsdata.status); return TIME_SET | DOP_SET | MODE_SET | STATUS_SET; case 0x06: /* Channel Status Output */ session->gpsdata.fix.time = session->gpsdata.sentence_time = gpstime_to_unix((int)getuw(buf2, 2), getul(buf2, 4)*0.01) - session->context->leap_seconds; session->gpsdata.satellites = (int)getub(buf2, 8); session->gpsdata.satellites_used = 0; memset(session->gpsdata.used, 0, sizeof(session->gpsdata.used)); if (session->gpsdata.satellites > 12) { gpsd_report(LOG_WARN, "Warning: EverMore packet has information about %d satellites!\n", session->gpsdata.satellites); } if (session->gpsdata.satellites > EVERMORE_CHANNELS) session->gpsdata.satellites = EVERMORE_CHANNELS; satcnt = 0; for (i = 0; i < (size_t)session->gpsdata.satellites; i++) { int prn; // channel = getub(buf2, 7*i+7+2) prn = (int)getub(buf2, 7*i+7+3); if (prn == 0) continue; /* satellite record is not valid */ session->gpsdata.PRN[satcnt] = prn; session->gpsdata.azimuth[satcnt] = (int)getuw(buf2, 7*i+7+4); session->gpsdata.elevation[satcnt] = (int)getub(buf2, 7*i+7+6); session->gpsdata.ss[satcnt] = (int)getub(buf2, 7*i+7+7); /* * Status bits at offset 8: * bit0 = 1 satellite acquired * bit1 = 1 code-tracking loop locked * bit2 = 1 carrier-tracking loop locked * bit3 = 1 data-bit synchronization done * bit4 = 1 frame synchronization done * bit5 = 1 ephemeris data collected * bit6 = 1 used for position fix */ if (getub(buf2, 7*i+7+8) & 0x40) { session->gpsdata.used[session->gpsdata.satellites_used++]=prn; } satcnt++; } session->gpsdata.satellites = (int)satcnt; /* that's all the information in this packet */ gpsd_report(LOG_PROG, "CSO 0x04: %d satellites used\n", session->gpsdata.satellites_used); return TIME_SET | SATELLITE_SET | USED_SET; case 0x08: /* Measurement Data Output */ /* clock offset is a manufacturer diagnostic */ /* (int)getuw(buf2, 8); clock offset, 29000..29850 ?? */ session->gpsdata.fix.time = session->gpsdata.sentence_time = gpstime_to_unix((int)getuw(buf2, 2), getul(buf2, 4)*0.01) - session->context->leap_seconds; visible = getub(buf2, 10); /* FIXME: read full statellite status for each channel */ /* we can get pseudo range (m), delta-range (m/s), doppler (Hz) and status for each channel */ /* gpsd_report(LOG_PROG, "MDO 0x04: visible=%d\n", visible); */ gpsd_report(LOG_PROG, "MDO 0x04:\n"); return TIME_SET; case 0x20: /* LogConfig Info, could be used as a probe for EverMore GPS */ gpsd_report(LOG_IO, "LogConfig EverMore packet, length %d: %s\n", datalen, gpsd_hexdump(buf2, datalen)); return ONLINE_SET; case 0x22: /* LogData */ gpsd_report(LOG_IO, "LogData EverMore packet, length %d: %s\n", datalen, gpsd_hexdump(buf2, datalen)); return ONLINE_SET; case 0x38: /* ACK */ gpsd_report(LOG_PROG, "EverMore command %02X ACK\n", getub(buf2, 2)); return ONLINE_SET; default: gpsd_report(LOG_WARN, "unknown EverMore packet id 0x%02x, length %d: %s\n", buf2[0], datalen, gpsd_hexdump(buf2, datalen)); return 0; } }
/* * decode MID 0xDF, Nav status (PVT) * * 81 bytes */ static gps_mask_t sky_msg_DF(struct gps_device_t *session, unsigned char *buf, size_t len) { unsigned int iod; /* Issue of data 0 - 255 */ unsigned short navstat; unsigned int wn; /* week number 0 - 65535 */ double f_tow; /* receiver tow Sec */ double clock_bias; double clock_drift; gps_mask_t mask = 0; if ( 81 != len) return 0; iod = (unsigned int)getub(buf, 1); /* fix status is byte 2 */ navstat = (unsigned short)getub(buf, 2); session->gpsdata.status = STATUS_NO_FIX; session->newdata.mode = MODE_NO_FIX; switch ( navstat ) { case 1: /* fix prediction, ignore */ break; case 2: session->gpsdata.status = STATUS_FIX; session->newdata.mode = MODE_2D; break; case 3: session->gpsdata.status = STATUS_FIX; session->newdata.mode = MODE_3D; mask |= ALTITUDE_SET | CLIMB_SET; break; case 4: session->gpsdata.status = STATUS_DGPS_FIX; session->newdata.mode = MODE_3D; mask |= ALTITUDE_SET | CLIMB_SET; break; default: break; } wn = getbeu16(buf, 3); f_tow = getbed64((const char *)buf, 5); /* position/velocity is bytes 13-48, meters and m/s */ ecef_to_wgs84fix(&session->newdata, &session->gpsdata.separation, (double)getbed64((const char *)buf, 13), (double)getbed64((const char *)buf, 21), (double)getbed64((const char *)buf, 29), (double)getbef32((const char *)buf, 37), (double)getbef32((const char *)buf, 41), (double)getbef32((const char *)buf, 46)); clock_bias = getbed64((const char *)buf, 49); clock_drift = getbes32(buf, 57); session->gpsdata.dop.gdop = getbef32((const char *)buf, 61); session->gpsdata.dop.pdop = getbef32((const char *)buf, 65); session->gpsdata.dop.hdop = getbef32((const char *)buf, 69); session->gpsdata.dop.vdop = getbef32((const char *)buf, 73); session->gpsdata.dop.tdop = getbef32((const char *)buf, 77); session->newdata.time = gpsd_gpstime_resolve(session, wn, f_tow ); gpsd_log(&session->context->errout, LOG_DATA, "Skytraq: MID 0xDF: iod=%u, stat=%u, wn=%u, tow=%f, t=%.6f " "cb: %f, cd: %f " "gdop: %.2f, pdop: %.2f, hdop: %.2f, vdop: %.2f, tdop: %.2f\n", iod, navstat, wn, f_tow, session->newdata.time, clock_bias, clock_drift, session->gpsdata.dop.gdop, session->gpsdata.dop.pdop, session->gpsdata.dop.hdop, session->gpsdata.dop.vdop, session->gpsdata.dop.tdop); mask |= TIME_SET | LATLON_SET | TRACK_SET | SPEED_SET | STATUS_SET | MODE_SET | DOP_SET | CLEAR_IS | REPORT_IS; return mask; }
/*@ +charint @*/ gps_mask_t evermore_parse(struct gps_device_t * session, unsigned char *buf, size_t len) { unsigned char buf2[MAX_PACKET_LENGTH], *cp, *tp; size_t i, datalen; unsigned int type, used, visible, satcnt, j, k; double version; gps_mask_t mask = 0; if (len == 0) return 0; /* time to unstuff it and discard the header and footer */ cp = buf + 2; tp = buf2; if (*cp == 0x10) cp++; datalen = (size_t) * cp++; gpsd_report(LOG_RAW, "raw EverMore packet type 0x%02x, length %zd: %s\n", *cp, len, gpsd_hexdump_wrapper(buf, len, LOG_RAW)); datalen -= 2; /*@ -usedef @*/ for (i = 0; i < (size_t) datalen; i++) { *tp = *cp++; if (*tp == 0x10) cp++; tp++; } type = (unsigned char)getub(buf2, 1); /*@ +usedef @*/ /*@ -usedef -compdef @*/ gpsd_report(LOG_RAW, "EverMore packet type 0x%02x, length %zd: %s\n", type, datalen, gpsd_hexdump_wrapper(buf2, datalen, LOG_RAW)); /*@ +usedef +compdef @*/ (void)snprintf(session->gpsdata.tag, sizeof(session->gpsdata.tag), "EID%u", type); session->cycle_end_reliable = true; switch (type) { case 0x02: /* Navigation Data Output */ session->context->gps_week = (unsigned short)getleuw(buf2, 2); session->context->gps_tow = (double)getleul(buf2, 4) * 0.01; /*@ ignore @*//*@ splint is confused @ */ session->newdata.time = gpstime_to_unix(session->context->gps_week, session->context->gps_tow) - session->context->leap_seconds; /*@ end @*/ ecef_to_wgs84fix(&session->newdata, &session->gpsdata.separation, getlesl(buf2, 8) * 1.0, getlesl(buf2, 12) * 1.0, getlesl(buf2, 16) * 1.0, getlesw(buf2, 20) / 10.0, getlesw(buf2, 22) / 10.0, getlesw(buf2, 24) / 10.0); used = (unsigned char)getub(buf2, 26) & 0x0f; //visible = (getub(buf2, 26) & 0xf0) >> 4; version = (uint) getleuw(buf2, 27) / 100.0; /* that's all the information in this packet */ if (used < 3) session->newdata.mode = MODE_NO_FIX; else if (used == 3) session->newdata.mode = MODE_2D; else { session->newdata.mode = MODE_3D; mask |= ALTITUDE_IS | CLIMB_IS; } mask |= TIME_IS | LATLON_IS | TRACK_IS | SPEED_IS | MODE_IS; if (session->subtype[0] == '\0') { (void)snprintf(session->subtype, sizeof(session->subtype), "%3.2f", version); mask |= DEVICEID_IS; } gpsd_report(LOG_DATA, "NDO 0x02: time=%.2f, lat=%.2f lon=%.2f alt=%.2f speed=%.2f track=%.2f climb=%.2f mode=%d subtype='%s' mask=%s\n", session->newdata.time, session->newdata.latitude, session->newdata.longitude, session->newdata.altitude, session->newdata.speed, session->newdata.track, session->newdata.climb, session->newdata.mode, session->gpsdata.dev.subtype, gpsd_maskdump(mask)); return mask | CLEAR_IS | REPORT_IS; case 0x04: /* DOP Data Output */ session->context->gps_week = (unsigned short)getleuw(buf2, 2); session->context->gps_tow = (double)getleul(buf2, 4) * 0.01; /*@ ignore @*//*@ splint is confused @ */ session->newdata.time = gpstime_to_unix(session->context->gps_week, session->context->gps_tow) - session->context->leap_seconds; /*@ end @*/ /* * We make a deliberate choice not to clear DOPs from the * last skyview here, but rather to treat this as a supplement * to our calculations from the visiniolity matrix, trusting * the firmware algorithms over ours. */ session->gpsdata.dop.gdop = (double)getub(buf2, 8) * 0.1; session->gpsdata.dop.pdop = (double)getub(buf2, 9) * 0.1; session->gpsdata.dop.hdop = (double)getub(buf2, 10) * 0.1; session->gpsdata.dop.vdop = (double)getub(buf2, 11) * 0.1; session->gpsdata.dop.tdop = (double)getub(buf2, 12) * 0.1; switch (getub(buf2, 13)) { case 0: /* no position fix */ case 1: /* manual calls this "1D navigation" */ session->gpsdata.status = STATUS_NO_FIX; session->newdata.mode = MODE_NO_FIX; break; case 2: /* 2D navigation */ session->gpsdata.status = STATUS_FIX; session->newdata.mode = MODE_2D; break; case 3: /* 3D navigation */ session->gpsdata.status = STATUS_FIX; session->newdata.mode = MODE_3D; break; case 4: /* 3D navigation with DGPS */ session->gpsdata.status = STATUS_DGPS_FIX; session->newdata.mode = MODE_3D; break; } /* that's all the information in this packet */ mask = TIME_IS | DOP_IS | MODE_IS | STATUS_IS; gpsd_report(LOG_DATA, "DDO 0x04: gdop=%.2f pdop=%.2f hdop=%.2f vdop=%.2f tdop=%.2f mode=%d, status=%d mask={TIME| DOP|MODE|STATUS}\n", session->gpsdata.dop.gdop, session->gpsdata.dop.pdop, session->gpsdata.dop.hdop, session->gpsdata.dop.vdop, session->gpsdata.dop.tdop, session->newdata.mode, session->gpsdata.status); return mask; case 0x06: /* Channel Status Output */ session->context->gps_week = (unsigned short)getleuw(buf2, 2); session->context->gps_tow = (double)getleul(buf2, 4) * 0.01; /*@ ignore @*//*@ splint is confused @ */ session->gpsdata.skyview_time = gpstime_to_unix(session->context->gps_week, session->context->gps_tow) - session->context->leap_seconds; /*@ end @*/ session->gpsdata.satellites_visible = (int)getub(buf2, 8); gpsd_zero_satellites(&session->gpsdata); memset(session->gpsdata.used, 0, sizeof(session->gpsdata.used)); if (session->gpsdata.satellites_visible > 12) { gpsd_report(LOG_WARN, "Warning: EverMore packet has information about %d satellites!\n", session->gpsdata.satellites_visible); } if (session->gpsdata.satellites_visible > EVERMORE_CHANNELS) session->gpsdata.satellites_visible = EVERMORE_CHANNELS; satcnt = 0; for (i = 0; i < (size_t) session->gpsdata.satellites_visible; i++) { int prn; // channel = getub(buf2, 7*i+7+2) prn = (int)getub(buf2, 7 * i + 7 + 3); if (prn == 0) continue; /* satellite record is not valid */ session->gpsdata.PRN[satcnt] = prn; session->gpsdata.azimuth[satcnt] = (int)getleuw(buf2, 7 * i + 7 + 4); session->gpsdata.elevation[satcnt] = (int)getub(buf2, 7 * i + 7 + 6); session->gpsdata.ss[satcnt] = (float)getub(buf2, 7 * i + 7 + 7); /* * Status bits at offset 8: * bit0 = 1 satellite acquired * bit1 = 1 code-tracking loop locked * bit2 = 1 carrier-tracking loop locked * bit3 = 1 data-bit synchronization done * bit4 = 1 frame synchronization done * bit5 = 1 ephemeris data collected * bit6 = 1 used for position fix */ if (getub(buf2, 7 * i + 7 + 8) & 0x40) { session->gpsdata.used[session->gpsdata.satellites_used++] = prn; } satcnt++; } session->gpsdata.satellites_visible = (int)satcnt; /* that's all the information in this packet */ mask = SATELLITE_IS | USED_IS; gpsd_report(LOG_DATA, "CSO 0x06: time=%.2f used=%d visible=%d mask={TIME|SATELLITE|USED}\n", session->newdata.time, session->gpsdata.satellites_used, session->gpsdata.satellites_visible); return mask; case 0x08: /* Measurement Data Output */ /* clock offset is a manufacturer diagnostic */ /* (int)getleuw(buf2, 8); clock offset, 29000..29850 ?? */ session->context->gps_week = (unsigned short)getleuw(buf2, 2); session->context->gps_tow = (double)getleul(buf2, 4) * 0.01; /*@ ignore @*//*@ splint is confused @ */ session->newdata.time = gpstime_to_unix(session->context->gps_week, session->context->gps_tow) - session->context->leap_seconds; /*@ end @*/ visible = (unsigned char)getub(buf2, 10); /* * Note: This code is untested. It was written from the manual. * The results need to be sanity-checked against a GPS with * known-good raw decoding and the same skyview. * * We can get pseudo range (m), delta-range (m/s), doppler (Hz) * and status for each channel from the chip. We cannot get * codephase or carrierphase. */ #define SBITS(sat, s, l) sbits((char *)buf, 10 + (sat*14) + s, l) #define UBITS(sat, s, l) ubits((char *)buf, 10 + (sat*14) + s, l) for (k = 0; k < visible; k++) { int prn = (int)UBITS(k, 4, 5); /* this is so we can tell which never got set */ for (j = 0; j < MAXCHANNELS; j++) session->gpsdata.raw.mtime[j] = 0; for (j = 0; j < MAXCHANNELS; j++) { if (session->gpsdata.PRN[j] == prn) { session->gpsdata.raw.codephase[j] = NAN; session->gpsdata.raw.carrierphase[j] = NAN; session->gpsdata.raw.mtime[j] = session->newdata.time; session->gpsdata.raw.satstat[j] = (unsigned)UBITS(k, 24, 8); session->gpsdata.raw.pseudorange[j] = (double)SBITS(k,40,32); session->gpsdata.raw.deltarange[j] = (double)SBITS(k,72,32); session->gpsdata.raw.doppler[j] = (double)SBITS(k, 104, 16); } } } #undef SBITS #undef UBITS gpsd_report(LOG_DATA, "MDO 0x04: time=%.2f mask={TIME|RAW}\n", session->newdata.time); return TIME_IS | RAW_IS; case 0x20: /* LogConfig Info, could be used as a probe for EverMore GPS */ gpsd_report(LOG_IO, "LogConfig EverMore packet, length %zd: %s\n", datalen, gpsd_hexdump_wrapper(buf2, datalen, LOG_IO)); return ONLINE_IS; case 0x22: /* LogData */ gpsd_report(LOG_IO, "LogData EverMore packet, length %zd: %s\n", datalen, gpsd_hexdump_wrapper(buf2, datalen, LOG_IO)); return ONLINE_IS; case 0x38: /* ACK */ gpsd_report(LOG_PROG, "EverMore command %02X ACK\n", getub(buf2, 2)); return ONLINE_IS; default: gpsd_report(LOG_WARN, "unknown EverMore packet EID 0x%02x, length %zd: %s\n", buf2[0], datalen, gpsd_hexdump_wrapper(buf2, datalen, LOG_IO)); return 0; } }
static void display_nav_sol(unsigned char *buf, size_t data_len) { unsigned short gw = 0; unsigned int tow = 0, flags; double epx, epy, epz, evx, evy, evz; unsigned char navmode; struct gps_data_t g; double separation; if (data_len != 52) return; navmode = (unsigned char)getub(buf, 10); flags = (unsigned int)getub(buf, 11); if ((flags & (UBX_SOL_VALID_WEEK | UBX_SOL_VALID_TIME)) != 0) { tow = (unsigned int)getleu32(buf, 0); gw = (unsigned short)getles16(buf, 8); } epx = (double)(getles32(buf, 12) / 100.0); epy = (double)(getles32(buf, 16) / 100.0); epz = (double)(getles32(buf, 20) / 100.0); evx = (double)(getles32(buf, 28) / 100.0); evy = (double)(getles32(buf, 32) / 100.0); evz = (double)(getles32(buf, 36) / 100.0); ecef_to_wgs84fix(&g.fix, &separation, epx, epy, epz, evx, evy, evz); g.fix.epx = g.fix.epy = (double)(getles32(buf, 24) / 100.0); g.fix.eps = (double)(getles32(buf, 40) / 100.0); g.dop.pdop = (double)(getleu16(buf, 44) / 100.0); g.satellites_used = (int)getub(buf, 47); (void)wmove(navsolwin, 1, 11); (void)wprintw(navsolwin, "%+10.2fm %+10.2fm %+10.2fm", epx, epy, epz); (void)wmove(navsolwin, 2, 11); (void)wprintw(navsolwin, "%+9.2fm/s %+9.2fm/s %+9.2fm/s", evx, evy, evz); (void)wmove(navsolwin, 4, 11); (void)wattrset(navsolwin, A_UNDERLINE); (void)wprintw(navsolwin, "%12.9f %13.9f %8.2fm", g.fix.latitude, g.fix.longitude, g.fix.altitude); (void)mvwaddch(navsolwin, 4, 23, ACS_DEGREE); (void)mvwaddch(navsolwin, 4, 38, ACS_DEGREE); (void)wmove(navsolwin, 5, 11); (void)wprintw(navsolwin, "%6.2fm/s %5.1fo %6.2fm/s", g.fix.speed, g.fix.track, g.fix.climb); (void)mvwaddch(navsolwin, 5, 26, ACS_DEGREE); (void)wattrset(navsolwin, A_NORMAL); (void)wmove(navsolwin, 7, 7); { unsigned int day = tow / 8640000; unsigned int tod = tow % 8640000; unsigned int h = tod / 360000; unsigned int m = tod % 360000; unsigned int s = m % 6000; m = (m - s) / 6000; (void)wattrset(navsolwin, A_UNDERLINE); (void)wprintw(navsolwin, "%u %02u:%02u:%05.2f", day, h, m, (double)s / 100); (void)wattrset(navsolwin, A_NORMAL); } (void)wmove(navsolwin, 8, 11); if ((flags & (UBX_SOL_VALID_WEEK | UBX_SOL_VALID_TIME)) != 0) { (void)wprintw(navsolwin, "%d+%10.3lf", gw, (double)(tow / 1000.0)); (void)wmove(navsolwin, 8, 36); (void)wprintw(navsolwin, "%d", (tow / 86400000)); } /* relies on the fact that epx and epy are set to same value */ (void)wmove(navsolwin, 10, 12); (void)wprintw(navsolwin, "%7.2f", g.fix.epx); (void)wmove(navsolwin, 10, 33); (void)wprintw(navsolwin, "%6.2f", g.fix.epv); (void)wmove(navsolwin, 11, 7); (void)wprintw(navsolwin, "%2d", g.satellites_used); (void)wmove(navsolwin, 11, 15); (void)wprintw(navsolwin, "%5.1f", g.dop.pdop); (void)wmove(navsolwin, 11, 25); (void)wprintw(navsolwin, "0x%02x", navmode); (void)wmove(navsolwin, 11, 36); (void)wprintw(navsolwin, "0x%02x", flags); (void)wnoutrefresh(navsolwin); }