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

📄 gpsfs.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <u.h>#include <libc.h>#include <fcall.h>#include <thread.h>#include <ctype.h>#include <9p.h>#include "dat.h"enum{	Numsize=	12,	Vlnumsize=	22,	Rawbuf=		0x10000,	Rawmask=	Rawbuf-1,};#define	nsecperchar	((int)(1000000000.0 * 10.0 / baud))typedef struct Fix Fix;typedef struct Satellite Satellite;typedef struct GPSfile GPSfile;typedef struct Gpsmsg Gpsmsg;struct Satellite {	int		prn;	int		elevation;	int		azimuth;	int		snr;};struct Fix {	int		messages;	/* bitmap of types seen */	Place;	/*	 * The following are in Plan 9 time format:	 * seconds or nanoseconds since the epoch.	 */	vlong		localtime;	/* nsec() value when first byte was read */	vlong		gpstime;	/* nsec() value from GPS */	long		time;		/* time() value from GPS */	double		zulu;	int		date;	char		valid;	uchar		quality;	ushort		satellites;	double		pdop;	double		hdop;	double		vdop;	double		altitude;	double		sealevel;	double		groundspeed;	double		kmh;	double		course;	double		heading;	double		magvar;	Satellite	s[12];};struct GPSfile {	char	*name;	char*	(*rread)(Req*);	int	mode;	vlong	offset;		/* for raw: rawout - read-offset */};enum {	ASTRAL,	GPGGA,	GPGLL,	GPGSA,	GPGSV,	GPRMC,	GPVTG,	PRWIRID,	PRWIZCH};struct Gpsmsg {	char *name;	int tokens;	ulong errors;};char	raw[Rawbuf];vlong	rawin;vlong	rawout;ulong	badlat, goodlat, suspectlat;ulong	badlon, goodlon, suspectlon;ulong	suspecttime, goodtime;ulong histo[32];char *serial = "/dev/eia0";Gpsmsg gpsmsg[] = {[ASTRAL]	= { "ASTRAL",	 0,	0},[GPGGA]		= { "$GPGGA",	15,	0},[GPGLL]		= { "$GPGLL",	 7,	0},[GPGSA]		= { "$GPGSA",	18,	0},[GPGSV]		= { "$GPGSV",	0,	0},[GPRMC]		= { "$GPRMC",	0,	0},[GPVTG]		= { "$GPVTG",	0,	0},[PRWIRID]	= { "$PRWIRID",	0,	0},[PRWIZCH]	= { "$PRWIZCH",	0,	0},};int ttyfd, ctlfd, debug;int setrtc;int baud = Baud;char *baudstr = "b%dd1r1pns1l8i9";ulong seconds;ulong starttime;ulong checksumerrors;int gpsplayback;	/* If set, return times and positions with `invalid' marker set */Place where = {-(74.0 + 23.9191/60.0), 40.0 + 41.1346/60.0};Fix curfix;Lock fixlock;int	type(char*);void	setline(void);int	getonechar(vlong*);void	getline(char*, int, vlong*);void	putline(char*);int	gettime(Fix*);int	getzulu(char *, Fix*);int	getalt(char*, char*, Fix*);int	getsea(char*, char*, Fix*);int	getlat(char*, char*, Fix*);int	getlon(char*, char*, Fix*);int	getgs(char*, Fix *);int	getkmh(char*, Fix*);int	getcrs(char*, Fix*);int	gethdg(char*, Fix*);int	getdate(char*, Fix*);int	getmagvar(char*, char*, Fix*);void	printfix(int, Fix*);void	ropen(Req *r);void	rread(Req *r);void	rend(Srv *s);void	gpsinit(void);char*	readposn(Req*);char*	readtime(Req*);char*	readsats(Req*);char*	readstats(Req*);char*	readraw(Req*);GPSfile files[] = {	{ "time",	readtime,	0444,	0 },	{ "position",	readposn,	0444,	0 },	{ "satellites",	readsats,	0444,	0 },	{ "stats",	readstats,	0444,	0 },	{ "raw",	readraw,	DMEXCL|0444, 0 },};Srv s = {	.open	= ropen,	.read	= rread,	.end = rend,};File *root;File *gpsdir;voidrend(Srv *){	sysfatal("gpsfs demised");}voidropen(Req *r){	respond(r, nil);}voidrread(Req *r){	GPSfile *f;	r->ofcall.count = 0;	f = r->fid->file->aux;	respond(r, f->rread(r));}voidfsinit(void){	char* user;	int i;	user = getuser();	s.tree = alloctree(user, user, 0555, nil);	if(s.tree == nil)		sysfatal("fsinit: alloctree: %r");	root = s.tree->root;	if((gpsdir = createfile(root, "gps", user, DMDIR|0555, nil)) == nil)		sysfatal("fsinit: createfile: gps: %r");	for(i = 0; i < nelem(files); i++)		if(createfile(gpsdir, files[i].name, user, files[i].mode, files + i) == nil)			sysfatal("fsinit: createfile: %s: %r", files[i].name);}voidthreadmain(int argc, char*argv[]){	char *srvname, *mntpt;	srvname = "gps";	mntpt = "/mnt";	ARGBEGIN {	default:		fprint(2, "usage: %s [-b baud] [-d device] [-l logfile] [-m mntpt] [-r] [-s postname]\n", argv0);		exits("usage");	case 'D':		debug++;		break;	case 'b':		baud = strtol(ARGF(), nil, 0);		break;	case 'd':		serial = ARGF();		break;	case 'r':		setrtc = 1;		break;	case 's':		srvname = ARGF();		break;	case 'm':		mntpt = ARGF();		break;	} ARGEND	fmtinstall('L', placeconv);		rfork(RFNOTEG);	fsinit();	gpsinit();	threadpostmountsrv(&s, srvname, mntpt, MBEFORE);	threadexits(nil);}static voidgpstrack(void *){	Fix fix;	static char buf[256], *t[32];	int n, i, k, tp;	vlong localtime;	double d;	setline();	fix.messages = 0;	fix.lon = 181.0;	fix.lat = 91.0;	fix.zulu = 0;	fix.date = 0;	fix.valid = 0;	fix.quality = 0;	fix.satellites = 0;	fix.pdop = 0.0;	fix.hdop = 0.0;	fix.vdop = 0.0;	fix.altitude = 0.0;	fix.sealevel = 0.0;	fix.groundspeed = 0.0;	fix.kmh = 0.0;	fix.course = 0.0;	fix.heading = 0.0;	fix.magvar = 0.0;	for(;;){		getline(buf, sizeof buf, &localtime);		n = getfields(buf, t, nelem(t), 0,",\r\n");		if(n == 0)			continue;		tp = type(t[0]);		if(tp >= 0 && tp < nelem(gpsmsg) && gpsmsg[tp].tokens && gpsmsg[tp].tokens != n){			gpsmsg[tp].errors++;			if(debug)				fprint(2, "%s: Expect %d tokens, got %d\n",					gpsmsg[tp].name, gpsmsg[tp].tokens, n);			continue;		}		switch(tp){		case ASTRAL:			putline("$IIGPQ,ASTRAL*73");			putline("$PRWIILOG,GGA,A,T,10,0");			putline("$PRWIILOG,RMC,A,T,10,0");			putline("$PRWIILOG,GSA,A,T,10,0");			putline("$PRWIILOG,GSV,V,,,");			fprint(2, "Reply: %s\n", "$IIGPQ,ASTRAL*73");			break;		case PRWIRID:		case PRWIZCH:			for(i = 0; i < n; i++) fprint(2, "%s,", t[i]);			fprint(2, "(%d tokens)\n", n);			break;		case GPGGA:			if(getlat(t[2], t[3], &fix))				break;			if(getlon(t[4], t[5], &fix))				break;			getzulu(t[1], &fix);			if(fix.date && gettime(&fix))				break;			if(isdigit(*t[7]))				fix.satellites = strtol(t[7], nil, 10);			if(isdigit(*t[8])){				d = strtod(t[8], nil);				if(!isNaN(d))					fix.hdop = d;			}			getalt(t[9], t[10], &fix);			getsea(t[11], t[12], &fix);			fix.localtime = localtime;			fix.quality = strtol(t[6], nil, 10);			fix.messages |= 1 << tp;			break;		case GPRMC:			fix.valid = *t[2];			getgs(t[7], &fix);			getcrs(t[8], &fix);			getdate(t[9], &fix);			getmagvar(t[10], t[11], &fix);			if((fix.messages & (1 << GPGGA)) == 0){				if(getlat(t[3], t[4], &fix))					break;				if(getlon(t[5], t[6], &fix))					break;				fix.localtime = localtime;				getzulu(t[1], &fix);				if(fix.date)					gettime(&fix);			}			fix.messages |= 1 << tp;			break;		case GPGSA:			if(*t[15]){				d = strtod(t[15], nil);				if(!isNaN(d))					fix.pdop = d;			}			if(*t[16]){				d = strtod(t[16], nil);				if(!isNaN(d))					fix.hdop = d;			}			if(*t[17]){				d = strtod(t[17], nil);				if(!isNaN(d))					fix.vdop = d;			}			fix.messages |= 1 << tp;			break;		case GPGLL:			if(getlat(t[1], t[2], &fix))				break;			if(getlon(t[3], t[4], &fix))				break;			getzulu(t[5], &fix);			fix.messages |= 1 << tp;			break;		case GPGSV:			if(n < 8){				gpsmsg[tp].errors++;				if(debug)					fprint(2, "%s: Expect at least 8 tokens, got %d\n",						gpsmsg[tp].name, n);				break;			}			i = 4*(strtol(t[2], nil, 10)-1);	/* starting entry in satellite table */			fix.satellites = strtol(t[3], nil, 10);			k = 4;			while(i < nelem(fix.s) && k + 3 < n){				fix.s[i].prn = strtol(t[k++], nil, 10);				fix.s[i].elevation = strtol(t[k++], nil, 10);				fix.s[i].azimuth = strtol(t[k++], nil, 10);				fix.s[i].snr = strtol(t[k++], nil, 10);				k += 4;				i++;			} 			fix.messages |= 1 << tp;			break;		case GPVTG:			if(n < 8){				gpsmsg[tp].errors++;				if(debug)					fprint(2, "%s: Expect at least 8 tokens, got %d\n",						gpsmsg[tp].name, n);				break;			}			getcrs(t[2], &fix);			gethdg(t[4], &fix);			getgs(t[6], &fix);			if(n > 8)				getkmh(t[8], &fix);			fix.messages |= 1 << tp;			break;		default:			if(debug && fix.date)				fprint(2, "Don't know %s\n", t[0]);			break;		}		if(fix.valid){			seconds++;			lock(&fixlock);			memmove(&curfix, &fix, sizeof fix);			unlock(&fixlock);			if(debug)				printfix(2, &fix);			fix.valid = 0;			fix.messages = 0;			for(i = 0; i < nelem(fix.s); i++)				fix.s[i].prn = 0;			if(gpsplayback)				sleep(100);		}	}}voidgpsinit(void){	proccreate(gpstrack, nil, 4096);}voidprintfix(int f, Fix *fix){	int i;	fprint(f, "%L, ", fix->Place);	fprint(f, "%g, ", fix->magvar);	fprint(f, "%gm - %gm = %gm, ", fix->altitude, fix->sealevel, fix->altitude - fix->sealevel);	fprint(f, "%06dZ(%g)-", (int)fix->zulu, fix->zulu);	fprint(f, "%06d\n", fix->date);	if(fix->lat >= 0)		fprint(f, "%11.8fN, ", fix->lat);	else		fprint(f, "%11.8fS, ", -fix->lat);			if(fix->lon >= 0)		fprint(f, "%12.8fE, ", fix->lon);	else		fprint(f, "%12.8fW, ", -fix->lon);	fprint(f, "%g@%g, ", fix->course, fix->groundspeed);	fprint(f, "(%c, %ds)\n", fix->valid, fix->satellites);	for(i = 0; i < nelem(fix->s); i++){		if(fix->s[i].prn == 0)			continue;		fprint(f, "[%d, %d°, %d°, %d]\n",			fix->s[i].prn, fix->s[i].elevation, fix->s[i].azimuth, fix->s[i].snr);	}}char*readposn(Req *r){	Fix f;	char buf[256];	lock(&fixlock);	memmove(&f, &curfix, sizeof f);	unlock(&fixlock);	snprint(buf, sizeof buf, "%x	%06dZ	%lud	%g	%g	%g	%g	%g	%g",		gpsplayback|f.quality, (int)f.zulu, f.time, f.lon, f.lat, f.altitude - f.sealevel,		f.course, f.groundspeed, f.magvar);	readstr(r, buf);	return nil;}char*readtime(Req *r){	Fix f;	char buf[Numsize+Vlnumsize+Vlnumsize+8];

⌨️ 快捷键说明

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