diff options
-rw-r--r-- | bits.h | 4 | ||||
-rw-r--r-- | gpsd.h | 4 | ||||
-rw-r--r-- | tsip.c | 245 |
3 files changed, 131 insertions, 122 deletions
@@ -15,12 +15,12 @@ */ union int_float { - int i; + int32_t i; float f; }; union long_double { - long long l; + int64_t l; double d; }; @@ -115,6 +115,7 @@ struct gps_device_t { unsigned long satcounter; #endif /* SIRFII_ENABLE */ #ifdef TSIP_ENABLE + int16_t gps_week; /* Current GPS week number */ time_t last_request; /* Last time request packets were sent */ #endif /* TSIP_ENABLE */ #ifdef GARMIN_ENABLE /* private housekeeping stuff for the Garmin driver */ @@ -123,9 +124,6 @@ struct gps_device_t { global context and save spave */ size_t GarminBufferLen; /* current GarminBuffer Length */ #endif /* GARMIN_ENABLE */ -#if defined(SIRFII_ENABLE) || defined(TSIP_ENABLE) || defined(GARMIN_ENABLE) - unsigned int gps_week; /* Current GPS week number */ -#endif /*defined(SIRFII_ENABLE)||defined(TSIP_ENABLE)||defined(GARMIN_ENABLE)*/ #ifdef ZODIAC_ENABLE /* private housekeeping stuff for the Zodiac driver */ unsigned short sn; /* packet sequence number */ /* @@ -9,38 +9,10 @@ #define __USE_ISOC99 1 /* needed to get log2() from math.h */ #include <math.h> #include "gpsd.h" +#include "bits.h" #ifdef TSIP_ENABLE -union int_float { - int i; - float f; -}; - -union long_double { - long long l; - double d; -}; - -#define putbyte(off,b) { buf[off] = (unsigned char)(b); } -#define putword(off,w) { putbyte(off,(w) >> 8); putbyte(off+1,w); } -#define putlong(off,l) { putword(off,(l) >> 16); putword(off+2,l); } - -#define getbyte(off) (buf[off]) -#define getword(off) ((short)((getbyte(off) << 8) | getbyte(off+1))) -#define getl(off) ((int)((getbyte(off) << 24) | (getbyte(off+1) << 16) \ - | (getbyte(off+3) << 8) | getbyte(off+4))) -#define getL(off) ((long long)(((unsigned long long)buf[off]<<56) \ - | ((unsigned long long)buf[off+1]<<48) \ - | ((unsigned long long)buf[off+2]<<40) \ - | ((unsigned long long)buf[off+3]<<32) \ - | ((unsigned long long)buf[off+4]<<24) \ - | ((unsigned long long)buf[off+5]<<16) \ - | ((unsigned long long)buf[off+6]<<8) \ - | (unsigned long long)buf[off+7])) -#define getf(off) (i_f.i = getl(off), i_f.f) -#define getd(off) (l_d.l = getL(off), l_d.d) - static int tsip_write(int fd, unsigned int id, unsigned char *buf, int len) { int i; @@ -84,10 +56,10 @@ static void tsip_initializer(struct gps_device_t *session) gpsd_set_speed(session, session->gpsdata.baudrate, 'O', 1); /* I/O Options */ - putbyte(0,0x1e); /* Position: DP, MSL, LLA */ - putbyte(1,0x02); /* Velocity: ENU */ - putbyte(2,0x00); /* Time: GPS */ - putbyte(3,0x08); /* Aux: dBHz */ + putbyte(buf,0,0x1e); /* Position: DP, MSL, LLA */ + putbyte(buf,1,0x02); /* Velocity: ENU */ + putbyte(buf,2,0x00); /* Time: GPS */ + putbyte(buf,3,0x08); /* Aux: dBHz */ (void)tsip_write(session->gpsdata.gps_fd, 0x35, buf, 4); /* Request Software Versions */ @@ -104,16 +76,16 @@ static bool tsip_speed_switch(struct gps_device_t *session, unsigned int speed) { unsigned char buf[100]; - putbyte(0,0xff); /* current port */ - putbyte(1,(round(log((double)speed/300)/M_LN2))+2); /* input baudrate */ - putbyte(2,buf[1]); /* output baudrate */ - putbyte(3,8); /* character width (8 bits) */ - putbyte(4,1); /* parity (odd) */ - putbyte(5,0); /* stop bits (1 stopbit) */ - putbyte(6,0); /* flow control (none) */ - putbyte(7,0x02); /* input protocol (TSIP) */ - putbyte(8,0x02); /* input protocol (TSIP) */ - putbyte(9,0); /* reserved */ + putbyte(buf,0,0xff); /* current port */ + putbyte(buf,1,(round(log((double)speed/300)/M_LN2))+2); /* input baudrate */ + putbyte(buf,2,getub(buf,1)); /* output baudrate */ + putbyte(buf,3,8); /* character width (8 bits) */ + putbyte(buf,4,1); /* parity (odd) */ + putbyte(buf,5,0); /* stop bits (1 stopbit) */ + putbyte(buf,6,0); /* flow control (none) */ + putbyte(buf,7,0x02); /* input protocol (TSIP) */ + putbyte(buf,8,0x02); /* output protocol (TSIP) */ + putbyte(buf,9,0); /* reserved */ (void)tsip_write(session->gpsdata.gps_fd, 0xbc, buf, 10); return true; /* it would be nice to error-check this */ @@ -121,10 +93,11 @@ static bool tsip_speed_switch(struct gps_device_t *session, unsigned int speed) static gps_mask_t tsip_analyze(struct gps_device_t *session) { - int i, len; + int i, len, count; gps_mask_t mask = 0; - unsigned int id, u1; - short s1,s2; + unsigned int id; + u_int8_t u1,u2,u3,u4; + int16_t s1; float f1,f2,f3,f4,f5; double d1,d2,d3,d4; union int_float i_f; @@ -165,20 +138,20 @@ static gps_mask_t tsip_analyze(struct gps_device_t *session) switch (id) { case 0x13: /* Packet Received */ gpsd_report(4, "Received packet of type %02x cannot be parsed\n", - getbyte(0)); + getub(buf,0)); break; case 0x41: /* GPS Time */ if (len != 10) break; - f1 = getf(0); /* gpstime */ - s1 = getword(4); /* week */ - f2 = getf(6); /* leap seconds */ - if (f2 > 10.0) { - session->gps_week = (unsigned)s1; + f1 = getf(buf,0); /* gpstime */ + s1 = getsw(buf,4); /* week */ + f2 = getf(buf,6); /* leap seconds */ + if (f1 >= 0.0 && f2 > 10.0) { + session->gps_week = s1; session->context->leap_seconds = (int)roundf(f2); session->context->valid = LEAP_SECOND_VALID; - session->gpsdata.sentence_time = gpstime_to_unix(s1, f1) - f2; + session->gpsdata.sentence_time = gpstime_to_unix((int)s1, f1) - f2; #ifdef NTPSHM_ENABLE (void)ntpshm_put(session, session->gpsdata.sentence_time + 0.075); @@ -189,49 +162,50 @@ static gps_mask_t tsip_analyze(struct gps_device_t *session) case 0x42: /* Single-Precision Position Fix, XYZ ECEF */ if (len != 16) break; - f1 = getf(0); /* X */ - f2 = getf(4); /* Y */ - f3 = getf(8); /* Z */ - f4 = getf(12); /* time-of-fix */ + f1 = getf(buf,0); /* X */ + f2 = getf(buf,4); /* Y */ + f3 = getf(buf,8); /* Z */ + f4 = getf(buf,12); /* time-of-fix */ gpsd_report(4, "GPS Position XYZ %f %f %f %f\n",f1,f2,f3,f4); break; case 0x43: /* Velocity Fix, XYZ ECEF */ if (len != 20) break; - f1 = getf(0); /* X velocity */ - f2 = getf(4); /* Y velocity */ - f3 = getf(8); /* Z velocity */ - f4 = getf(12); /* bias rate */ - f5 = getf(16); /* time-of-fix */ + f1 = getf(buf,0); /* X velocity */ + f2 = getf(buf,4); /* Y velocity */ + f3 = getf(buf,8); /* Z velocity */ + f4 = getf(buf,12); /* bias rate */ + f5 = getf(buf,16); /* time-of-fix */ gpsd_report(4, "GPS Velocity XYZ %f %f %f %f %f\n",f1,f2,f3,f4,f5); break; case 0x45: /* Software Version Information */ if (len != 10) break; gpsd_report(4, "Software versions %d.%d %02d%02d%02d %d.%d %02d%02d%02d\n", - (int)getbyte(0),(int)getbyte(1),(int)getbyte(4),(int)getbyte(2),(int)getbyte(3), - (int)getbyte(5),(int)getbyte(6),(int)getbyte(9),(int)getbyte(7),(int)getbyte(8)); + getub(buf,0),getub(buf,1),getub(buf,4),getub(buf,2),getub(buf,3), + getub(buf,5),getub(buf,6),getub(buf,9),getub(buf,7),getub(buf,8)); break; case 0x46: /* Health of Receiver */ if (len != 2) break; - gpsd_report(4, "Receiver health %02x %02x\n",getbyte(0),getbyte(1)); + gpsd_report(4, "Receiver health %02x %02x\n",getub(buf,0),getub(buf,1)); break; case 0x47: /* Signal Levels for all Satellites */ - s1 = (short)getbyte(0); /* count */ - if (len != (5*s1 + 1)) + count = (int)getub(buf,0); /* satellite count */ + if (len != (5*count + 1)) break; - gpsd_zero_satellites(&session->gpsdata); - session->gpsdata.satellites = s1; + session->gpsdata.satellites = count; buf2[0] = '\0'; - for (i = 0; i < s1; i++) { - session->gpsdata.PRN[i] = s2 = (short)getbyte(5*i + 1); - f1 = getf(5*i + 2); + for (i = 0; i < count; i++) { + /*@ +charint @*/ + session->gpsdata.PRN[i] = u1 = getub(buf,5*i + 1); + /*@ -charint @*/ + f1 = getf(buf,5*i + 2); session->gpsdata.ss[i] = (int)f1; (void)snprintf(buf2+strlen(buf2), sizeof(buf2)-strlen(buf2), - " %d=%1f",s2,f1); + " %d=%1f",(int)u1,f1); } - gpsd_report(4, "Signal Levels (%d):%s\n",s1,buf2); + gpsd_report(4, "Signal Levels (%d):%s\n",count,buf2); mask |= SATELLITE_SET; break; case 0x48: /* GPS System Message */ @@ -241,11 +215,11 @@ static gps_mask_t tsip_analyze(struct gps_device_t *session) case 0x4a: /* Single-Precision Position LLA */ if (len != 20) break; - session->gpsdata.fix.latitude = getf(0) * RAD_2_DEG; - session->gpsdata.fix.longitude = getf(4) * RAD_2_DEG; - session->gpsdata.fix.altitude = getf(8); - f1 = getf(12); /* clock bias */ - f2 = getf(16); /* time-of-fix */ + session->gpsdata.fix.latitude = getf(buf,0) * RAD_2_DEG; + session->gpsdata.fix.longitude = getf(buf,4) * RAD_2_DEG; + session->gpsdata.fix.altitude = getf(buf,8); + f1 = getf(buf,12); /* clock bias */ + f2 = getf(buf,16); /* time-of-fix */ if (session->gps_week) session->gpsdata.fix.time = session->gpsdata.sentence_time = gpstime_to_unix((int)session->gps_week, f2) - session->context->leap_seconds; @@ -258,22 +232,22 @@ static gps_mask_t tsip_analyze(struct gps_device_t *session) case 0x4b: /* Machine/Code ID and Additional Status */ if (len != 3) break; - gpsd_report(4, "Machine ID %02x %02x %02x\n",getbyte(0),getbyte(1),getbyte(2)); + gpsd_report(4, "Machine ID %02x %02x %02x\n",getub(buf,0),getub(buf,1),getub(buf,2)); break; case 0x55: /* IO Options */ if (len != 4) break; - gpsd_report(4, "IO Options %02x %02x %02x %02x\n",getbyte(0),getbyte(1),getbyte(2),getbyte(4)); + gpsd_report(4, "IO Options %02x %02x %02x %02x\n",getub(buf,0),getub(buf,1),getub(buf,2),getub(buf,3)); break; case 0x56: /* Velocity Fix, East-North-Up (ENU) */ if (len != 20) break; - f1 = getf(0); /* East velocity */ - f2 = getf(4); /* North velocity */ - f3 = getf(8); /* Up velocity */ - f4 = getf(12); /* clock bias rate */ - f5 = getf(16); /* time-of-fix */ - session->gpsdata.fix.climb = f1; + f1 = getf(buf,0); /* East velocity */ + f2 = getf(buf,4); /* North velocity */ + f3 = getf(buf,8); /* Up velocity */ + f4 = getf(buf,12); /* clock bias rate */ + f5 = getf(buf,16); /* time-of-fix */ + session->gpsdata.fix.climb = f3; /*@ -evalorder @*/ session->gpsdata.fix.speed = sqrt(pow(f2,2) + pow(f1,2)); /*@ +evalorder @*/ @@ -285,22 +259,47 @@ static gps_mask_t tsip_analyze(struct gps_device_t *session) case 0x57: /* Information About Last Computed Fix */ if (len != 8) break; - f1 = getf(2); /* gps_time */ - s1 = getword(6); /* gps_weeks */ - if ((int)getbyte(0) != 0) /* good current fix? */ - session->gps_week = (unsigned)s1; - gpsd_report(4, "Fix info %02x %02x %d %f\n",getbyte(0),getbyte(1),s1,f1); + f1 = getf(buf,2); /* gps_time */ + s1 = getsw(buf,6); /* gps_week */ + /*@ +charint @*/ + if (getub(buf,0) == 0x01) /* good current fix? */ + session->gps_week = s1; + /*@ -charint @*/ + gpsd_report(4, "Fix info %02x %02x %d %f\n",getub(buf,0),getub(buf,1),s1,f1); break; case 0x58: /* Satellite System Data/Acknowledge from Receiver */ break; case 0x59: /* Status of Satellite Disable or Ignore Health */ break; case 0x5a: /* Raw Measurement Data */ + if (len != 25) + break; + f1 = getf(buf,5); /* Signal Level */ + f2 = getf(buf,9); /* Code phase */ + f3 = getf(buf,13); /* Doppler */ + d1 = getd(buf,17); /* Time of Measurement */ + gpsd_report(4, "Raw Measurement Data %d %f %f %f %f\n",getub(buf,0),f1,f2,f3,d1); break; case 0x5c: /* Satellite Tracking Status */ + if (len != 24) + break; + u1 = getub(buf,0); /* PRN */ + u2 = getub(buf,1); /* chan */ + u3 = getub(buf,2); /* Acquisition flag */ + u4 = getub(buf,3); /* Ephemeris flag */ + f1 = getf(buf,4); /* Signal level */ + f2 = getf(buf,8); /* time of Last measurement */ + d1 = getf(buf,12) * RAD_2_DEG; /* Elevation */ + d2 = getf(buf,16) * RAD_2_DEG; /* Azimuth */ + id = (unsigned)u2 >> 3; /* channel number */ + session->gpsdata.PRN[id] = (int)u1; + session->gpsdata.ss[id] = (int)roundf(f1); + session->gpsdata.elevation[id] = (int)round(d1); + session->gpsdata.azimuth[id] = (int)round(d2); + gpsd_report(4, "Satellite Tracking Status %d: %d 0x%02x %d %d %f %f %f %f\n",id,u1,u2,u3,u4,f1,f2,d1,d2); break; case 0x6d: /* All-In-View Satellite Selection */ - u1 = (unsigned)getbyte(0); + u1 = getub(buf,0); switch (u1 & 7) /* dimension */ { case 3: @@ -314,19 +313,23 @@ static gps_mask_t tsip_analyze(struct gps_device_t *session) break; } session->gpsdata.satellites_used = (int)((u1 >> 4) & 0x0f); - session->gpsdata.pdop = getf(1); - session->gpsdata.hdop = getf(5); - session->gpsdata.vdop = getf(9); - session->gpsdata.tdop = getf(13); + session->gpsdata.pdop = getf(buf,1); + session->gpsdata.hdop = getf(buf,5); + session->gpsdata.vdop = getf(buf,9); + session->gpsdata.tdop = getf(buf,13); /*@ -evalorder @*/ session->gpsdata.gdop = sqrt(pow(session->gpsdata.pdop,2)+pow(session->gpsdata.tdop,2)); /*@ +evalorder @*/ memset(session->gpsdata.used,0,sizeof(session->gpsdata.used)); + buf2[0] = '\0'; + /*@ +charint @*/ for (i = 0; i < session->gpsdata.satellites_used; i++) - session->gpsdata.used[i] = (int)getbyte(16 + i); + (void)snprintf(buf2+strlen(buf2), sizeof(buf2)-strlen(buf2), + " %d",session->gpsdata.used[i] = getub(buf,17 + i)); + /*@ -charint @*/ - gpsd_report(4, "Sat info: %d %d\n",session->gpsdata.fix.mode,session->gpsdata.satellites_used); + gpsd_report(4, "Sat info: %d %d:%s\n",session->gpsdata.fix.mode,session->gpsdata.satellites_used,buf2); gpsd_binary_quality_dump(session, buf2, sizeof(buf2)); gpsd_report(3, "<= GPS: %s", buf2); mask |= HDOP_SET | VDOP_SET | PDOP_SET | MODE_SET; @@ -334,10 +337,12 @@ static gps_mask_t tsip_analyze(struct gps_device_t *session) case 0x6e: /* Synchronized Measurements */ break; case 0x6f: /* Synchronized Measurements Report */ - if (len < 20 || (int)getbyte(0) != 1 || (int)getbyte(1) != 2) + /*@ +charint @*/ + if (len < 20 || getub(buf,0) != 1 || getub(buf,1) != 2) break; - s1 = getword(2); /* number of bytes */ - s2 = (short)getbyte(20); /* number of SVs */ + /*@ -charint @*/ + s1 = getsw(buf,2); /* number of bytes */ + u1 = getub(buf,20); /* number of SVs */ break; case 0x70: /* Filter Report */ break; @@ -346,31 +351,33 @@ static gps_mask_t tsip_analyze(struct gps_device_t *session) case 0x82: /* Differential Position Fix Mode */ if (len != 1) break; - if (session->gpsdata.status==STATUS_FIX && ((int)getbyte(0) & 0x01)!=0) + /*@ +charint @*/ + if (session->gpsdata.status == STATUS_FIX && (getub(buf,0) & 0x01)!=0) session->gpsdata.status = STATUS_DGPS_FIX; - gpsd_report(4, "DGPS mode %d\n",getbyte(0)); + /*@ -charint @*/ + gpsd_report(4, "DGPS mode %d\n",getub(buf,0)); break; case 0x83: /* Double-Precision XYZ Position Fix and Bias Information */ if (len != 36) break; - d1 = getd(0); /* X */ - d2 = getd(8); /* Y */ - d3 = getd(16); /* Z */ - d4 = getd(24); /* clock bias */ - f1 = getf(32); /* time-of-fix */ + d1 = getd(buf,0); /* X */ + d2 = getd(buf,8); /* Y */ + d3 = getd(buf,16); /* Z */ + d4 = getd(buf,24); /* clock bias */ + f1 = getf(buf,32); /* time-of-fix */ gpsd_report(4, "GPS Position XYZ %f %f %f %f %f\n",d1,d2,d3,d4,f1); break; case 0x84: /* Double-Precision LLA Position Fix and Bias Information */ if (len != 36) break; - session->gpsdata.fix.latitude = getd(0) * RAD_2_DEG; - session->gpsdata.fix.longitude = getd(8) * RAD_2_DEG; - session->gpsdata.fix.altitude = getd(16); - d1 = getd(24); /* clock bias */ - f2 = getf(32); /* time-of-fix */ + session->gpsdata.fix.latitude = getd(buf,0) * RAD_2_DEG; + session->gpsdata.fix.longitude = getd(buf,8) * RAD_2_DEG; + session->gpsdata.fix.altitude = getd(buf,16); + d1 = getd(buf,24); /* clock bias */ + f1 = getf(buf,32); /* time-of-fix */ if (session->gps_week) session->gpsdata.fix.time = session->gpsdata.sentence_time = - gpstime_to_unix((int)session->gps_week, f2) - session->context->leap_seconds; + gpstime_to_unix((int)session->gps_week, f1) - session->context->leap_seconds; session->gpsdata.status = STATUS_FIX; gpsd_report(4, "GPS DP LLA %f %f %f\n",session->gpsdata.fix.latitude,session->gpsdata.fix.longitude,session->gpsdata.fix.altitude); gpsd_binary_fix_dump(session, buf2, sizeof(buf2)); @@ -378,7 +385,7 @@ static gps_mask_t tsip_analyze(struct gps_device_t *session) mask |= LATLON_SET | ALTITUDE_SET; break; case 0x8f: /* Super Packet. Well... */ - switch (getbyte(0)) /* sub-packet ID */ + switch (getub(buf,0)) /* sub-packet ID */ { case 0x20: /* Last Fix with Extra Information (binary fixed point) */ if (len != 56) @@ -389,7 +396,7 @@ static gps_mask_t tsip_analyze(struct gps_device_t *session) break; break; default: - gpsd_report(4,"Unhandled TSIP superpacket type 0x%02x\n",getbyte(0)); + gpsd_report(4,"Unhandled TSIP superpacket type 0x%02x\n",getub(buf,0)); } break; default: @@ -408,6 +415,10 @@ static gps_mask_t tsip_analyze(struct gps_device_t *session) /* Request Signal Levels */ (void)tsip_write(session->gpsdata.gps_fd, 0x27, buf, 0); + /* Request Current Satellite Tracking Status */ + putbyte(buf,0,0x00); /* All satellites */ + (void)tsip_write(session->gpsdata.gps_fd, 0x3c, buf, 1); + session->last_request = t; } |