📄 sirf.c
字号:
Here is what Chris Kuethe got from the SiRF folks: Start of message ---------------- Message ID 1 byte 27 Correction Source 1 byte 0=None, 1=SBAS, 2=Serial, 3=Beacon, 4=Software total: 2 bytes Middle part of message varies if using beacon or other: ------------------------------------------------------- If Beacon: Receiver Freq Hz 4 bytes Bit rate BPS 1 byte Status bit map 1 byte 01=Signal Valid, 02=Auto frequency detect 04=Auto bit rate detect Signal Magnitude 4 bytes Note: in internal units Signal Strength dB 2 bytes derived from Signal Magnitude SNR dB 2 bytes total: 14 bytes If Not Beacon: Correction Age[12] 1 byte x 12 Age in seconds in same order as follows Reserved 2 bytes total: 14 bytes End of Message -------------- Repeated 12 times (pad with 0 if less than 12 SV corrections): SVID 1 byte Correction (m) 1 byte total 2 x 12 = 24 bytes ******************************************************************/ return 0; case 0x29: /* Geodetic Navigation Information */ mask = 0; if (session->driver.sirf.driverstate & SIRF_GE_232) { struct tm unpacked_date; double subseconds; /* * Many versions of the SiRF protocol manual don't document * this sentence at all. Those that do may incorrectly * describe UTC Day, Hour, and Minute as 2-byte quantities, * not 1-byte. Chris Kuethe, our SiRF expert, tells us: * * "The Geodetic Navigation packet (0x29) was not fully * implemented in firmware prior to version 2.3.2. So for * anyone running 231.000.000 or earlier (including ES, * SiRFDRive, XTrac trains) you won't get UTC time. I don't * know what's broken in firmwares before 2.3.1..." * * To work around the incomplete implementation of this * packet in 231, we used to assume that only the altitude field * from this packet is valid. But even this doesn't necessarily * seem to be the case. Instead, we do our own computation * of geoid separation now. */ navtype = (unsigned short)getuw(buf, 3); session->gpsdata.status = STATUS_NO_FIX; session->gpsdata.newdata.mode = MODE_NO_FIX; if (navtype & 0x80) session->gpsdata.status = STATUS_DGPS_FIX; else if ((navtype & 0x07) > 0 && (navtype & 0x07) < 7) session->gpsdata.status = STATUS_FIX; session->gpsdata.newdata.mode = MODE_NO_FIX; if ((navtype & 0x07) == 4 || (navtype & 0x07) == 6) session->gpsdata.newdata.mode = MODE_3D; else if (session->gpsdata.status) session->gpsdata.newdata.mode = MODE_2D; gpsd_report(4, "GNI 0x29: Navtype = 0x%0x, Status = %d, mode = %d\n", navtype, session->gpsdata.status, session->gpsdata.newdata.mode); /* * UTC is left all zeros in 231 and older firmware versions, * and misdocumented in the Protocol Reference (version 1.4). * Documented: Real: * UTC year 2 2 * UTC month 1 1 * UTC day 2 1 * UTC hour 2 1 * UTC minute 2 1 * UTC second 2 2 * 11 8 */ unpacked_date.tm_year = (int)getuw(buf, 11); unpacked_date.tm_mon = (int)getub(buf, 13)-1; unpacked_date.tm_mday = (int)getub(buf, 14); unpacked_date.tm_hour = (int)getub(buf, 15); unpacked_date.tm_min = (int)getub(buf, 16); unpacked_date.tm_sec = 0; subseconds = getuw(buf, 17)*1e-3; /*@ -compdef */ session->gpsdata.newdata.time = session->gpsdata.sentence_time = (double)mktime(&unpacked_date)+subseconds; /*@ +compdef */ gpsd_report(5, "MID 41 UTC: %lf\n", session->gpsdata.newdata.time);#ifdef NTPSHM_ENABLE if (session->gpsdata.newdata.mode > MODE_NO_FIX && unpacked_date.tm_year != 0) { if ((session->driver.sirf.time_seen & TIME_SEEN_UTC_1) == 0) gpsd_report(4, "valid time in message 0x29, seen=0x%02x\n", session->driver.sirf.time_seen); session->driver.sirf.time_seen |= TIME_SEEN_UTC_1; if (IS_HIGHEST_BIT(session->driver.sirf.time_seen,TIME_SEEN_UTC_1)) (void)ntpshm_put(session, session->gpsdata.newdata.time + 0.8); }#endif /* NTPSHM_ENABLE */ /* skip 4 bytes of satellite map */ session->gpsdata.newdata.latitude = getsl(buf, 23)*1e-7; session->gpsdata.newdata.longitude = getsl(buf, 27)*1e-7; /* skip 4 bytes of altitude from ellipsoid */ mask = TIME_SET | LATLON_SET | STATUS_SET | MODE_SET; session->gpsdata.newdata.altitude = getsl(buf, 31)*1e-2; /* skip 1 byte of map datum */ session->gpsdata.newdata.speed = getsw(buf, 36)*1e-2; session->gpsdata.newdata.track = getsw(buf, 38)*1e-2; /* skip 2 bytes of magnetic variation */ session->gpsdata.newdata.climb = getsw(buf, 42)*1e-2; /* HDOP should be available at byte 89, but in 231 it's zero. */ mask |= SPEED_SET | TRACK_SET | CLIMB_SET | CYCLE_START_SET; session->gpsdata.sentence_length = 91; strcpy(session->gpsdata.tag, "GND"); } return mask; case 0x32: /* SBAS corrections */ return 0; case 0x34: /* PPS Time */ /* * Carl Carter from SiRF writes: "We do not output on the * second (unless you are using message ID 52). We make * measurements in the receiver in time with an internal * counter that is not slaved to GPS time, so the measurements * are made at a time that wanders around the second. Then, * after the measurements are made (all normalized to the same * point in time) we dispatch the navigation software to make * a solution, and that solution comes out some 200 to 300 ms * after the measurement time. So you may get a message at * 700 ms after the second that uses measurements time tagged * 450 ms after the second. And if some other task jumps up * and delays things, that message may not come out until 900 * ms after the second. Things can get out of sync to the * point that if you try to resolve the GPS time of our 1 PPS * pulses using the navigation messages, you will find it * impossible to be consistent. That is why I added message * ID 52 to our system -- it is tied to the creation of the 1 * PPS and always comes out right around the top of the * second." */ mask = 0; gpsd_report(4, "PPS 0x34: Status = 0x%02x\n", getub(buf, 14)); if (((int)getub(buf, 14) & 0x07) == 0x07) { /* valid UTC time? */ struct tm unpacked_date; unpacked_date.tm_hour = (int)getub(buf, 1); unpacked_date.tm_min = (int)getub(buf, 2); unpacked_date.tm_sec = (int)getub(buf, 3); unpacked_date.tm_mday = (int)getub(buf, 4); unpacked_date.tm_mon = (int)getub(buf, 5) - 1; unpacked_date.tm_year = (int)getuw(buf, 6) - 1900; /*@ -compdef */ session->gpsdata.newdata.time = session->gpsdata.sentence_time = (double)mktime(&unpacked_date); /*@ +compdef */ session->context->leap_seconds = (int)getuw(buf, 8); session->context->valid |= LEAP_SECOND_VALID;#ifdef NTPSHM_ENABLE if ((session->driver.sirf.time_seen & TIME_SEEN_UTC_2) == 0) gpsd_report(4, "valid time in message 0x34, seen=0x%02x\n", session->driver.sirf.time_seen); session->driver.sirf.time_seen |= TIME_SEEN_UTC_2; if (IS_HIGHEST_BIT(session->driver.sirf.time_seen,TIME_SEEN_UTC_2)) (void)ntpshm_put(session, session->gpsdata.newdata.time + 0.3);#endif /* NTPSHM_ENABLE */ mask |= TIME_SET; } return mask; case 0x62: /* uBlox Extended Measured Navigation Data */ /* this packet is only sent by uBlox firmware from version 1.32 */ mask = LATLON_SET | ALTITUDE_SET | SPEED_SET | TRACK_SET | CLIMB_SET | STATUS_SET | MODE_SET | HDOP_SET | VDOP_SET | PDOP_SET; session->gpsdata.newdata.latitude = getsl(buf, 1) * RAD_2_DEG * 1e-8; session->gpsdata.newdata.longitude = getsl(buf, 5) * RAD_2_DEG * 1e-8; session->gpsdata.separation = wgs84_separation(session->gpsdata.newdata.latitude, session->gpsdata.newdata.longitude); session->gpsdata.newdata.altitude = getsl(buf, 9) * 1e-3 - session->gpsdata.separation; session->gpsdata.newdata.speed = getsl(buf, 13) * 1e-3; session->gpsdata.newdata.climb = getsl(buf, 17) * 1e-3; session->gpsdata.newdata.track = getsl(buf, 21) * RAD_2_DEG * 1e-8; navtype = (unsigned short)getub(buf, 25); session->gpsdata.status = STATUS_NO_FIX; session->gpsdata.newdata.mode = MODE_NO_FIX; if (navtype & 0x80) session->gpsdata.status = STATUS_DGPS_FIX; else if ((navtype & 0x07) > 0 && (navtype & 0x07) < 7) session->gpsdata.status = STATUS_FIX; if ((navtype & 0x07) == 4 || (navtype & 0x07) == 6) session->gpsdata.newdata.mode = MODE_3D; else if (session->gpsdata.status) session->gpsdata.newdata.mode = MODE_2D; gpsd_report(4, "EMND 0x62: Navtype = 0x%0x, Status = %d, mode = %d\n", navtype, session->gpsdata.status, session->gpsdata.newdata.mode); if (navtype & 0x40) { /* UTC corrected timestamp? */ struct tm unpacked_date; double subseconds; mask |= TIME_SET; unpacked_date.tm_year = (int)getuw(buf, 26) - 1900; unpacked_date.tm_mon = (int)getub(buf, 28) - 1; unpacked_date.tm_mday = (int)getub(buf, 29); unpacked_date.tm_hour = (int)getub(buf, 30); unpacked_date.tm_min = (int)getub(buf, 31); unpacked_date.tm_sec = 0; subseconds = ((unsigned short)getuw(buf, 32))*1e-3; /*@ -compdef */ session->gpsdata.newdata.time = session->gpsdata.sentence_time = (double)mkgmtime(&unpacked_date)+subseconds; /*@ +compdef */#ifdef NTPSHM_ENABLE if ((session->driver.sirf.time_seen & TIME_SEEN_UTC_2) == 0) gpsd_report(4, "valid time in message 0x62, seen=0x%02x\n", session->driver.sirf.time_seen); session->driver.sirf.time_seen |= TIME_SEEN_UTC_2; if (IS_HIGHEST_BIT(session->driver.sirf.time_seen,TIME_SEEN_UTC_2)) (void)ntpshm_put(session, session->gpsdata.newdata.time + 0.8);#endif /* NTPSHM_ENABLE */ session->context->valid |= LEAP_SECOND_VALID; } session->gpsdata.gdop = (int)getub(buf, 34) / 5.0; session->gpsdata.pdop = (int)getub(buf, 35) / 5.0; session->gpsdata.hdop = (int)getub(buf, 36) / 5.0; session->gpsdata.vdop = (int)getub(buf, 37) / 5.0; session->gpsdata.tdop = (int)getub(buf, 38) / 5.0; session->driver.sirf.driverstate |= UBLOX; return mask; case 0xff: /* Debug messages */ buf2[0] = '\0'; for (i = 1; i < (int)len; i++) if (isprint(buf[i])) (void)snprintf(buf2+strlen(buf2), sizeof(buf2)-strlen(buf2), "%c", buf[i]); else (void)snprintf(buf2+strlen(buf2), sizeof(buf2)-strlen(buf2), "\\x%02x", (unsigned int)buf[i]); gpsd_report(4, "DD 0xff: %s\n", buf2); return 0; default: gpsd_report(3, "Unknown SiRF packet id %d length %d: %s\n", buf[0], len, gpsd_hexdump(buf, len)); return 0; } return 0;}static gps_mask_t sirfbin_parse_input(struct gps_device_t *session){ gps_mask_t st; if (session->packet_type == SIRF_PACKET){ st = sirf_parse(session, session->outbuffer, session->outbuflen); session->gpsdata.driver_mode = 1; return st;#ifdef NMEA_ENABLE } else if (session->packet_type == NMEA_PACKET) { st = nmea_parse((char *)session->outbuffer, session); session->gpsdata.driver_mode = 0; return st;#endif /* NMEA_ENABLE */ } else return 0;}static void sirfbin_initializer(struct gps_device_t *session)/* poll for software version in order to check for old firmware */{ if (session->packet_type == NMEA_PACKET) { gpsd_report(1, "Switching chip mode to SiRF binary.\n"); (void)nmea_send(session->gpsdata.gps_fd, "$PSRF100,0,%d,8,1,0", session->gpsdata.baudrate); } /* do this every time*/ { /*@ +charint @*/ static unsigned char dgpscontrol[] = {0xa0, 0xa2, 0x00, 0x07, 0x85, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xb3}; static unsigned char sbasparams[] = {0xa0, 0xa2, 0x00, 0x06, 0xaa, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xb3}; static unsigned char versionprobe[] = {0xa0, 0xa2, 0x00, 0x02, 0x84, 0x00, 0x00, 0x00, 0xb0, 0xb3}; static unsigned char modecontrol[] = {0xa0, 0xa2, 0x00, 0x0e, 0x88, 0x00, 0x00, /* pad bytes */ 0x00, /* degraded mode off */ 0x00, 0x00, /* pad bytes */ 0x00, 0x00, /* altitude */ 0x00, /* altitude hold auto */ 0x00, /* use last computed alt */ 0x00, /* reserved */ 0x00, /* disable degraded mode */ 0x00, /* disable dead reckoning */ 0x01, /* enable track smoothing */ 0x00, 0x00, 0xb0, 0xb3}; static unsigned char requestecef[] = {0xa0, 0xa2, 0x00, 0x08, 0xa6, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xb3}; static unsigned char requesttracker[] = {0xa0, 0xa2, 0x00, 0x08, 0xa6, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xb3}; /*@ -charint @*/ gpsd_report(4, "Requesting periodic ecef reports...\n"); (void)sirf_write(session->gpsdata.gps_fd, requestecef); gpsd_report(4, "Requesting periodic tracker reports...\n"); (void)sirf_write(session->gpsdata.gps_fd, requesttracker); gpsd_report(4, "Setting DGPS control to use SBAS...\n"); (void)sirf_write(session->gpsdata.gps_fd, dgpscontrol); gpsd_report(4, "Setting SBAS to auto/integrity mode...\n"); (void)sirf_write(session->gpsdata.gps_fd, sbasparams); gpsd_report(4, "Probing for firmware version...\n"); (void)sirf_write(session->gpsdata.gps_fd, versionprobe); gpsd_report(4, "Setting mode...\n"); (void)sirf_write(session->gpsdata.gps_fd, modecontrol); }}static bool sirfbin_speed(struct gps_device_t *session, speed_t speed){ return sirf_speed(session->gpsdata.gps_fd, speed);}/* this is everything we export */struct gps_type_t sirf_binary ={ .typename = "SiRF-II binary", /* full name of type */ .trigger = "$Ack Input105.", /* expected response to SiRF PSRF105 */ .channels = SIRF_CHANNELS, /* consumer-grade GPS */ .probe = NULL, /* no probe */ .initializer = sirfbin_initializer,/* initialize the device */ .get_packet = packet_get, /* use the generic packet getter */ .parse_packet = sirfbin_parse_input,/* parse message packets */ .rtcm_writer = pass_rtcm, /* send RTCM data straight */ .speed_switcher = sirfbin_speed, /* we can change baud rate */ .mode_switcher = sirfbin_mode, /* there's a mode switcher */ .rate_switcher = NULL, /* no sample-rate switcher */ .cycle_chars = -1, /* not relevant, no rate switch */ .wrapup = NULL, /* no close hook */ .cycle = 1, /* updates every second */};#endif /* defined(SIRFII_ENABLE) && defined(BINARY_ENABLE) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -