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

📄 zodiac.c

📁 很好的一个gps daemon驱动,简单实用
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Handle the Rockwell binary packet format supported by the old Zodiac chipset */#include <stdio.h>#include <stdlib.h>#include <math.h>#include <string.h>#include <unistd.h>#include "config.h"#include "gpsd.h"#ifdef ZODIAC_ENABLEenum {    ZODIAC_HUNT_FF, ZODIAC_HUNT_81, ZODIAC_HUNT_ID, ZODIAC_HUNT_WC,    ZODIAC_HUNT_FLAGS, ZODIAC_HUNT_CS, ZODIAC_HUNT_DATA, ZODIAC_HUNT_A};#define O(x) (x-6)struct header {    unsigned short sync;    unsigned short id;    unsigned short ndata;    unsigned short flags;    unsigned short csum;};static unsigned short zodiac_checksum(unsigned short *w, int n){    unsigned short csum = 0;    while (n--)	csum += *(w++);    return -csum;}/* zodiac_spew - Takes a message type, an array of data words, and a length   for the array, and prepends a 5 word header (including nmea_checksum).   The data words are expected to be nmea_checksummed */#if defined (WORDS_BIGENDIAN)/* data is assumed to contain len/2 unsigned short words * we change the endianness to little, when needed. */static int end_write(int fd, void *d, int len){    char buf[BUFSIZE];    char *p = buf;    char *data = (char *)d;    while (len>0) {	*p++ = *(data+1); *p++ = *data;	data += 2; len -= 2;    }    return write(fd, buf, len);}#else#define end_write write#endifstatic void zodiac_spew(struct gps_session_t *session, int type, unsigned short *dat, int dlen){    struct header h;    h.flags = 0;    h.sync = 0x81ff;    h.id = type;    h.ndata = dlen - 1;    h.csum = zodiac_checksum((unsigned short *) &h, 4);    if (session->gNMEAdata.gps_fd != -1) {	end_write(session->gNMEAdata.gps_fd, &h, sizeof(h));	end_write(session->gNMEAdata.gps_fd, dat, sizeof(unsigned short) * dlen);    }}static long putlong(char *dm, int sign){    double tmpl;    long rad;    tmpl = fabs(atof(dm));    rad = (floor(tmpl/100) + (fmod(tmpl, 100.0)/60)) * 100000000*PI/180;    if (sign)	rad = -rad;    return rad;}static void zodiac_init(struct gps_session_t *session){    unsigned short data[22];    time_t t;    struct tm *tm;    if (session->latitude && session->longitude) {      t = time(NULL);      tm = gmtime(&t);      if (session->sn++ > 32767)	  session->sn = 0;            memset(data, 0, sizeof(data));      data[0] = session->sn;		/* sequence number */      data[1] = (1 << 2) | (1 << 3);      data[2] = data[3] = data[4] = 0;      data[5] = tm->tm_mday; data[6] = tm->tm_mon+1; data[7]= tm->tm_year+1900;       data[8] = tm->tm_hour; data[9] = tm->tm_min; data[10] = tm->tm_sec;      *(long *) (data + 11) = putlong(session->latitude, (session->latd == 'S') ? 1 : 0);      *(long *) (data + 13) = putlong(session->longitude, (session->lond == 'W') ? 1 : 0);      data[15] = data[16] = 0;      data[17] = data[18] = data[19] = data[20] = 0;      data[21] = zodiac_checksum(data, 21);      zodiac_spew(session, 1200, data, 22);    }}static void send_rtcm(struct gps_session_t *session, 		      char *rtcmbuf, int rtcmbytes){    unsigned short data[34];    int n = 1 + (rtcmbytes/2 + rtcmbytes%2);    if (session->sn++ > 32767)	session->sn = 0;    memset(data, 0, sizeof(data));    data[0] = session->sn;		/* sequence number */    memcpy(&data[1], rtcmbuf, rtcmbytes);    data[n] = zodiac_checksum(data, n);    zodiac_spew(session, 1351, data, n+1);}static int zodiac_send_rtcm(struct gps_session_t *session,			char *rtcmbuf, int rtcmbytes){    int len;    while (rtcmbytes) {	len = rtcmbytes>64?64:rtcmbytes;	send_rtcm(session, rtcmbuf, len);	rtcmbytes -= len;	rtcmbuf += len;    }    return 1;}static long getlong(void *p){    return *(long *) p;}static unsigned long getulong(void *p){    return *(unsigned long *) p;}static double degtodm(double a){    double m, t;    m = modf(a, &t);    t = floor(a) * 100 + m * 60;    return t;}static void handle1000(struct gps_session_t *session, unsigned short *p){    sprintf(session->gNMEAdata.utc, "%04d/%02d/%dT%02d:%02d:%02dZ",	    p[O(19)], p[O(20)], p[O(21)], p[O(22)], p[O(23)], p[O(24)]);#if 0    gpsd_report(1, "date: %s\n", session->gNMEAdata.utc);    gpsd_report(1, "  solution invalid:\n");    gpsd_report(1, "    altitude: %d\n", (p[O(10)] & 1) ? 1 : 0);    gpsd_report(1, "    no diff gps: %d\n", (p[O(10)] & 2) ? 1 : 0);    gpsd_report(1, "    not enough satellites: %d\n", (p[O(10)] & 4) ? 1 : 0);    gpsd_report(1, "    exceed max EHPE: %d\n", (p[O(10)] & 8) ? 1 : 0);    gpsd_report(1, "    exceed max EVPE: %d\n", (p[O(10)] & 16) ? 1 : 0);    gpsd_report(1, "  solution type:\n");    gpsd_report(1, "    propagated: %d\n", (p[O(11)] & 1) ? 1 : 0);    gpsd_report(1, "    altitude: %d\n", (p[O(11)] & 2) ? 1 : 0);    gpsd_report(1, "    differential: %d\n", (p[O(11)] & 4) ? 1 : 0);    gpsd_report(1, "Number of measurements in solution: %d\n", p[O(12)]);    gpsd_report(1, "Lat: %f\n", 180.0 / (PI / ((double) getlong(p + O(27)) / 100000000)));    gpsd_report(1, "Lon: %f\n", 180.0 / (PI / ((double) getlong(p + O(29)) / 100000000)));    gpsd_report(1, "Alt: %f\n", (double) getlong(p + O(31)) / 100.0);    gpsd_report(1, "Speed: %f\n", (double) getlong(p + O(34)) / 100.0) * 1.94387;    gpsd_report(1, "Map datum: %d\n", p[O(39)]);    gpsd_report(1, "Magnetic variation: %f\n", p[O(37)] * 180 / (PI * 10000));    gpsd_report(1, "Course: %f\n", (p[O(36)] * 180 / (PI * 1000)));    gpsd_report(1, "Separation: %f\n", (p[O(33)] / 100));#endif    session->mag_var = p[O(37)] * 180 / (PI * 10000);	/* degrees */    session->gNMEAdata.track = p[O(36)] * 180 / (PI * 1000);	/* degrees */    session->gNMEAdata.satellites_used = p[O(12)];    session->hours = p[O(22)];     session->minutes = p[O(23)];     session->seconds = p[O(24)];    session->year = p[O(21)];    session->month = p[O(20)];    session->day = p[O(19)];    session->gNMEAdata.latitude = 180.0 / (PI / ((double) getlong(p + O(27)) / 100000000));    session->gNMEAdata.longitude = 180.0 / (PI / ((double) getlong(p + O(29)) / 100000000));    session->gNMEAdata.speed = ((double) getulong(p + O(34)) / 100.0) * 1.94387;    session->gNMEAdata.altitude = (double) getlong(p + O(31)) / 100.0;    session->gNMEAdata.status = (p[O(10)] & 0x1c) ? 0 : 1;    if (session->gNMEAdata.status)	session->gNMEAdata.mode = (p[O(10)] & 1) ? 2 : 3;    else	session->gNMEAdata.mode = 1;    REFRESH(session->gNMEAdata.status_stamp);    REFRESH(session->gNMEAdata.mode_stamp);    session->separation = p[O(33)] / 100;	/* meters */}static void handle1002(struct gps_session_t *session, unsigned short *p){    int i, j;    for (j = 0; j < MAXCHANNELS; j++)	session->gNMEAdata.used[j] = 0;    session->gNMEAdata.satellites_used = 0;    for (i = 0; i < MAXCHANNELS; i++) {	session->Zs[i] = p[O(16 + (3 * i))];	session->Zv[i] = (p[O(15 + (3 * i))] & 0xf);#if 0	gpsd_report(1, "Sat%02d:", i);	gpsd_report(1, " used:%d", (p[O(15 + (3 * i))] & 1) ? 1 : 0);	gpsd_report(1, " eph:%d", (p[O(15 + (3 * i))] & 2) ? 1 : 0);	gpsd_report(1, " val:%d", (p[O(15 + (3 * i))] & 4) ? 1 : 0);	gpsd_report(1, " dgps:%d", (p[O(15 + (3 * i))] & 8) ? 1 : 0);	gpsd_report(1, " PRN:%d", p[O(16 + (3 * i))]);	gpsd_report(1, " C/No:%d\n", p[O(17 + (3 * i))]);#endif	if (p[O(15 + (3 * i))] & 1)	    session->gNMEAdata.used[session->gNMEAdata.satellites_used++] = i;	for (j = 0; j < MAXCHANNELS; j++) {	    if (session->gNMEAdata.PRN[j] != p[O(16 + (3 * i))])		continue;	    session->gNMEAdata.ss[j] = p[O(17 + (3 * i))];	    break;	}    }

⌨️ 快捷键说明

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