📄 zodiac.c
字号:
/* * 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 + -