⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tsip.c

📁 gpsd, a popular GPS daemon.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: tsip.c 4661 2008-01-19 22:54:23Z garyemiller $ *//* * Handle the Trimble TSIP packet format * by Rob Janssen, PE1CHL. */#include <sys/types.h>#include <stdio.h>#include <string.h>#include <unistd.h>#include <math.h>#include "gpsd_config.h"#include "gpsd.h"#include "bits.h"#define USE_SUPERPACKET	1			/* use Super Packet mode? */#define SEMI_2_DEG	(180.0 / 2147483647)	/* 2^-31 semicircle to deg */#ifdef TSIP_ENABLE#define TSIP_CHANNELS	12static int tsip_write(int fd, unsigned int id, unsigned char *buf, size_t len){#ifdef ALLOW_RECONFIGURE    char buf2[BUFSIZ];    gpsd_report(LOG_IO, "Sent TSIP packet id 0x%02x: %s\n",id,gpsd_hexdump(buf,len));    /*@ +charint @*/    buf2[0] = '\x10';    buf2[1] = (char)id;    if (write(fd,buf2,2) != 2)	return -1;    while (len-- > 0) {	if (*buf == '\x10')	    if (write(fd,buf2,1) != 1)		return -1;	if (write(fd,buf++,1) != 1)	    return -1;    }    buf2[1] = '\x03';    /*@ -charint @*/    if (write(fd,buf2,2) != 2)	return -1;    return 0;#else    gpsd_report(LOG_IO, "Not sending TSIP packet id 0x%02x: %s\n",id,gpsd_hexdump(buf,len));    return -1;#endif /* ALLOW_RECONFIGURE */}static void tsip_probe_subtype(struct gps_device_t *session, unsigned int seq){    unsigned char buf[100];    switch (seq) {    case 0:	/* TSIP is ODD parity 1 stopbit, save original values and change it */	/* XXX this is not always a good idea; not all receivers are 8O1... */	session->driver.tsip.parity = session->gpsdata.parity;	session->driver.tsip.stopbits = session->gpsdata.stopbits;	gpsd_set_speed(session, session->gpsdata.baudrate, 'O', 1);	break;    case 1:	/* Request Software Versions */	(void)tsip_write(session->gpsdata.gps_fd, 0x1f, NULL, 0);	/* Request Current Time */	(void)tsip_write(session->gpsdata.gps_fd, 0x21, NULL, 0);	/* Request GPS Systems Message */	(void)tsip_write(session->gpsdata.gps_fd, 0x28, NULL, 0);	/* Request Current Datum Values */	putbyte(buf,0,0x15);	(void)tsip_write(session->gpsdata.gps_fd, 0x8e, buf, 1);	/* Request Navigation Configuration */	putbyte(buf,0,0x03);	(void)tsip_write(session->gpsdata.gps_fd, 0xbb, buf, 1);	break;    }}#ifdef ALLOW_RECONFIGUREstatic void tsip_configurator(struct gps_device_t *session, unsigned int seq){    if (seq == 0) {	unsigned char buf[100];	/* I/O Options */	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);    }}#endif /* ALLOW_RECONFIGURE */static void tsip_wrapup(struct gps_device_t *session){    /* restore saved parity and stopbits when leaving TSIP mode */    gpsd_set_speed(session, 		   session->gpsdata.baudrate,		   (unsigned char)session->driver.tsip.parity, 		   session->driver.tsip.stopbits);}static bool tsip_speed_switch(struct gps_device_t *session, unsigned int speed){    unsigned char buf[100];    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 */}static gps_mask_t tsip_analyze(struct gps_device_t *session){    int i, j, len, count;    gps_mask_t mask = 0;    unsigned int id;    u_int8_t u1,u2,u3,u4,u5;    int16_t s1,s2,s3,s4;    int32_t sl1,sl2,sl3;    u_int32_t ul1,ul2;    float f1,f2,f3,f4,f5;    double d1,d2,d3,d4,d5;    union int_float i_f;    union long_double l_d;    time_t now;    unsigned char buf[BUFSIZ];    char buf2[BUFSIZ];    if (session->packet.type != TSIP_PACKET) {	gpsd_report(LOG_INF, "tsip_analyze packet type %d\n",session->packet.type);	return 0;    }    /*@ +charint @*/    if (session->packet.outbuflen < 4 || session->packet.outbuffer[0] != 0x10)	return 0;    /* remove DLE stuffing and put data part of message in buf */    memset(buf, 0, sizeof(buf));    buf2[len = 0] = '\0';    for (i = 2; i < (int)session->packet.outbuflen; i++) {	if (session->packet.outbuffer[i] == 0x10)	    if (session->packet.outbuffer[++i] == 0x03)		break;	(void)snprintf(buf2+strlen(buf2), 		      sizeof(buf2)-strlen(buf2),		      "%02x", buf[len++] = session->packet.outbuffer[i]);    }    /*@ -charint @*/    (void)snprintf(session->gpsdata.tag, sizeof(session->gpsdata.tag), 		   "ID%02x", id = (unsigned)session->packet.outbuffer[1]);    gpsd_report(LOG_IO, "TSIP packet id 0x%02x length %d: %s\n",id,len,buf2);    (void)time(&now);    switch (id) {    case 0x13:		/* Packet Received */	u1 = getub(buf,0);	u2 = getub(buf,1);	gpsd_report(LOG_WARN, "Received packet of type %02x cannot be parsed\n",u1);#if USE_SUPERPACKET	if ((int)u1 == 0x8e && (int)u2 == 0x23) { /* no Compact Super Packet */	    gpsd_report(LOG_WARN, "No Compact Super Packet, use LFwEI\n");	    /* Request LFwEI Super Packet */	    putbyte(buf,0,0x20);	    putbyte(buf,1,0x01);		/* enabled */	    (void)tsip_write(session->gpsdata.gps_fd, 0x8e, buf, 2);	}#endif /* USE_SUPERPACKET */	break;    case 0x41:		/* GPS Time */	if (len != 10)	    break;	session->driver.tsip.last_41 = now;			/* keep timestamp for request */	f1 = getf(buf,0);			/* gpstime */	s1 = getsw(buf,4);			/* week */	f2 = getf(buf,6);			/* leap seconds */	if (f1 >= 0.0 && f2 > 10.0) {	    session->driver.tsip.gps_week = s1;	    session->context->leap_seconds = (int)round(f2);	    session->context->valid |= LEAP_SECOND_VALID;	    session->gpsdata.sentence_time = gpstime_to_unix((int)s1, f1) - f2;#ifdef NTPSHM_ENABLE	    if (session->context->enable_ntpshm)		(void)ntpshm_put(session,session->gpsdata.sentence_time+0.075);#endif	    mask |= TIME_SET;	}	gpsd_report(LOG_INF, "GPS Time %f %d %f\n",f1,s1,f2);	break;    case 0x42:		/* Single-Precision Position Fix, XYZ ECEF */	if (len != 16)	    break;	f1 = getf(buf,0);			/* X */	f2 = getf(buf,4);			/* Y */	f3 = getf(buf,8);			/* Z */	f4 = getf(buf,12);			/* time-of-fix */	gpsd_report(LOG_INF, "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(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(LOG_INF, "GPS Velocity XYZ %f %f %f %f %f\n",f1,f2,f3,f4,f5);	break;    case 0x45:		/* Software Version Information */	if (len != 10)	    break;	/*@ -formattype @*/	(void)snprintf(session->subtype, sizeof(session->subtype), 		       "%d.%d %02d%02d%02d %d.%d %02d%02d%02d",		       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));	/*@ +formattype @*/	gpsd_report(LOG_INF, "Software version: %s\n", session->subtype);	mask |= DEVICEID_SET;	break;    case 0x46:		/* Health of Receiver */	if (len != 2)	    break;	session->driver.tsip.last_46 = now;	u1 = getub(buf,0);			/* Status code */	u2 = getub(buf,1);			/* Antenna/Battery */        if (u1 != (u_int8_t)0) {            session->gpsdata.status = STATUS_NO_FIX;	    mask |= STATUS_SET;        }	else {	    if (session->gpsdata.status < STATUS_FIX) {                session->gpsdata.status = STATUS_FIX;                mask |= STATUS_SET;            }        }	gpsd_report(LOG_PROG, "Receiver health %02x %02x\n",u1,u2);	break;    case 0x47:		/* Signal Levels for all Satellites */	count = (int)getub(buf,0);		/* satellite count */	if (len != (5*count + 1))	    break;	buf2[0] = '\0';	for (i = 0; i < count; i++) {	    u1 = getub(buf,5*i + 1);	    if ((f1 = getf(buf,5*i + 2)) < 0)		f1 = 0.0;	    for (j = 0; j < TSIP_CHANNELS; j++)		if (session->gpsdata.PRN[j] == (int)u1) {		    session->gpsdata.ss[j] = (int)round(f1);		    break;		}	    (void)snprintf(buf2+strlen(buf2), sizeof(buf2)-strlen(buf2),			   " %d=%.1f",(int)u1,f1);	}	gpsd_report(LOG_PROG, "Signal Levels (%d):%s\n",count,buf2);	mask |= SATELLITE_SET;	break;    case 0x48:		/* GPS System Message */	buf[len] = '\0';	gpsd_report(LOG_PROG, "GPS System Message: %s\n",buf);	break;    case 0x4a:		/* Single-Precision Position LLA */	if (len != 20)	    break;	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->driver.tsip.gps_week) {	    session->gpsdata.fix.time = session->gpsdata.sentence_time =		gpstime_to_unix((int)session->driver.tsip.gps_week, f2) - session->context->leap_seconds;	    mask |= TIME_SET;	}	gpsd_report(LOG_PROG, "GPS LLA %f %f %f %f\n",		    session->gpsdata.fix.time,		    session->gpsdata.fix.latitude,		    session->gpsdata.fix.longitude,		    session->gpsdata.fix.altitude);	mask |= LATLON_SET | ALTITUDE_SET | CYCLE_START_SET;	break;    case 0x4b:		/* Machine/Code ID and Additional Status */	if (len != 3)	    break;	u1 = getub(buf,0);			/* Machine ID */	u2 = getub(buf,1);			/* Status 1 */	u3 = getub(buf,2);			/* Status 2 */	gpsd_report(LOG_INF, "Machine ID %02x %02x %02x\n",u1,u2,u3);#if USE_SUPERPACKET	if ((u3 & 0x01) != (u_int8_t)0 && !session->driver.tsip.superpkt) {	    gpsd_report(LOG_PROG, "Switching to Super Packet mode\n");	    /* set new I/O Options for Super Packet output */	    putbyte(buf,0,0x2c);		/* Position: SP, MSL */	    putbyte(buf,1,0x00);		/* Velocity: none (via SP) */	    putbyte(buf,2,0x00);		/* Time: GPS */	    putbyte(buf,3,0x08);		/* Aux: dBHz */	    (void)tsip_write(session->gpsdata.gps_fd, 0x35, buf, 4);	    session->driver.tsip.superpkt = true;	}#endif /* USE_SUPERPACKET */	break;    case 0x55:		/* IO Options */	if (len != 4)	    break;	u1 = getub(buf,0);			/* Position */	u2 = getub(buf,1);			/* Velocity */	u3 = getub(buf,2);			/* Timing */	u4 = getub(buf,3);			/* Aux */	gpsd_report(LOG_INF, "IO Options %02x %02x %02x %02x\n",u1,u2,u3,u4);#if USE_SUPERPACKET	if ((u1 & 0x20) != (u_int8_t)0) {	/* Output Super Packets? */	    /* No LFwEI Super Packet */	    putbyte(buf,0,0x20);	    putbyte(buf,1,0x00);		/* disabled */	    (void)tsip_write(session->gpsdata.gps_fd, 0x8e, buf, 2);	    /* Request Compact Super Packet */	    putbyte(buf,0,0x23);	    putbyte(buf,1,0x01);		/* enabled */	    (void)tsip_write(session->gpsdata.gps_fd, 0x8e, buf, 2);	}#endif /* USE_SUPERPACKET */	break;    case 0x56:		/* Velocity Fix, East-North-Up (ENU) */	if (len != 20)	    break;	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 @*/	if ((session->gpsdata.fix.track = atan2(f1,f2) * RAD_2_DEG) < 0)	    session->gpsdata.fix.track += 360.0;	gpsd_report(LOG_INF, "GPS Velocity ENU %f %f %f %f %f\n",f1,f2,f3,f4,f5);	mask |= SPEED_SET | TRACK_SET | CLIMB_SET; 	break;    case 0x57:		/* Information About Last Computed Fix */	if (len != 8)	    break;	u1 = getub(buf,0);			/* Source of information */	u2 = getub(buf,1);			/* Mfg. diagnostic */	f1 = getf(buf,2);			/* gps_time */	s1 = getsw(buf,6);			/* tsip.gps_week */	/*@ +charint @*/	if (getub(buf,0) == 0x01)		/* good current fix? */	    session->driver.tsip.gps_week = s1;	/*@ -charint @*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -