"Initial commit to Gerrit"
[profile/ivi/gpsd.git] / monitor_sirf.c
1 /*
2  * SiRF object for the GPS packet monitor.
3  *
4  * This file is Copyright (c) 2010 by the GPSD project
5  * BSD terms apply: see the file COPYING in the distribution root for details.
6  *
7  */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <math.h>
12 #include <ctype.h>
13 #ifndef S_SPLINT_S
14 #include <unistd.h>
15 #endif /* S_SPLINT_S */
16 #include <stdarg.h>
17 #include <stdbool.h>
18 #include <assert.h>
19
20 #include "gpsd_config.h"
21
22 #ifdef HAVE_NCURSES_H
23 #include <ncurses.h>
24 #else
25 #include <curses.h>
26 #endif /* HAVE_NCURSES_H */
27 #include "gpsd.h"
28
29 #include "bits.h"
30 #include "gpsmon.h"
31
32 #if defined(SIRF_ENABLE) && defined(BINARY_ENABLE)
33 extern const struct gps_type_t sirf_binary;
34
35 static WINDOW *mid2win, *mid4win, *mid6win, *mid7win, *mid9win, *mid13win;
36 static WINDOW *mid19win, *mid27win;
37 static bool dispmode = false, subframe_enabled = false;
38 static int nfix, fix[20];
39
40 /*@ -nullassign @*/
41 static char *verbpat[] = {
42     "#Time:",
43     "@R Time:",
44     "CSTD: New almanac for",
45     "NOTICE: DOP Q Boost",
46     "RTC not set",
47     "numOfSVs = 0",
48     "rtcaj tow ",
49     NULL
50 };
51
52 /*@ +nullassign @*/
53
54 static char *dgpsvec[] = {
55     "None",
56     "SBAS",
57     "Serial",
58     "Beacon",
59     "Software",
60 };
61
62 /* check range of an unsigned quantity */
63 #define CHECK_RANGE(vec, i) ((i) < sizeof(vec)/sizeof(vec[0]))
64
65 /*****************************************************************************
66  *
67  * SiRF packet-decoding routines
68  *
69  *****************************************************************************/
70
71 #define display (void)mvwprintw
72
73 #define MAXSATS         12      /* the most satellites we can dump data on */
74
75 static bool sirf_initialize(void)
76 {
77     unsigned int i;
78
79     /*@ -onlytrans @*/
80     mid2win = subwin(devicewin, 7, 80, 1, 0);
81     mid4win = subwin(devicewin, MAXSATS + 3, 30, 8, 0);
82     mid6win = subwin(devicewin, 3, 50, 8, 30);
83     mid7win = subwin(devicewin, 4, 50, 11, 30);
84     mid9win = subwin(devicewin, 3, 50, 15, 30);
85     mid13win = subwin(devicewin, 3, 50, 18, 30);
86     mid19win = newwin(16, 50, 8, 30);
87     mid27win = subwin(devicewin, 3, 50, 21, 30);
88     if (mid2win == NULL || mid4win == NULL || mid6win == NULL
89         || mid9win == NULL || mid13win == NULL || mid19win == NULL
90         || mid27win == NULL)
91         return false;
92
93     (void)syncok(mid2win, true);
94     (void)syncok(mid4win, true);
95     (void)syncok(mid6win, true);
96     (void)syncok(mid7win, true);
97     (void)syncok(mid9win, true);
98     (void)syncok(mid13win, true);
99     (void)syncok(mid27win, true);
100
101     /*@ -nullpass @*/
102     (void)wborder(mid2win, 0, 0, 0, 0, 0, 0, 0, 0),
103         (void)wattrset(mid2win, A_BOLD);
104     (void)wmove(mid2win, 0, 1);
105     display(mid2win, 0, 12, " X ");
106     display(mid2win, 0, 21, " Y ");
107     display(mid2win, 0, 30, " Z ");
108     display(mid2win, 0, 43, " North ");
109     display(mid2win, 0, 54, " East ");
110     display(mid2win, 0, 65, " Alt ");
111
112     (void)wmove(mid2win, 1, 1);
113     (void)wprintw(mid2win,
114                   "Pos:                            m                                    m");
115     (void)wmove(mid2win, 2, 1);
116     (void)wprintw(mid2win,
117                   "Vel:                            m/s                                  climb m/s");
118     (void)wmove(mid2win, 3, 1);
119     (void)wprintw(mid2win,
120                   "Week+TOW:               Day:                Heading:                 speed m/s");
121     (void)wmove(mid2win, 4, 1);
122     (void)wprintw(mid2win,
123                   "Skew:                   TZ:                HDOP:      M1:        M2:    ");
124     (void)wmove(mid2win, 5, 1);
125     (void)wprintw(mid2win, "Fix:");
126     display(mid2win, 6, 24, " Packet type 2 (0x02) ");
127     (void)wattrset(mid2win, A_NORMAL);
128
129     (void)wborder(mid4win, 0, 0, 0, 0, 0, 0, 0, 0),
130         (void)wattrset(mid4win, A_BOLD);
131     display(mid4win, 1, 1, "Ch PRN  Az El Stat  C/N ? A");
132     for (i = 0; i < MAXSATS; i++) {
133         display(mid4win, (int)(i + 2), 1, "%2d", i);
134     }
135     display(mid4win, 14, 4, " Packet Type 4 (0x04) ");
136     (void)wattrset(mid4win, A_NORMAL);
137
138     (void)wborder(mid19win, 0, 0, 0, 0, 0, 0, 0, 0),
139         (void)wattrset(mid19win, A_BOLD);
140     display(mid19win, 1, 1, "Alt. hold mode:");
141     display(mid19win, 2, 1, "Alt. hold source:");
142     display(mid19win, 3, 1, "Alt. source input:");
143     display(mid19win, 4, 1, "Degraded timeout:");
144     display(mid19win, 5, 1, "DR timeout:");
145     display(mid19win, 6, 1, "Track smooth mode:");
146     display(mid19win, 7, 1, "Static Navigation:");
147     display(mid19win, 8, 1, "3SV Least Squares:");
148     display(mid19win, 9, 1, "DOP Mask mode:");
149     display(mid19win, 10, 1, "Nav. Elev. mask:");
150     display(mid19win, 11, 1, "Nav. Power mask:");
151     display(mid19win, 12, 1, "DGPS Source:");
152     display(mid19win, 13, 1, "DGPS Mode:");
153     display(mid19win, 14, 1, "DGPS Timeout:");
154     display(mid19win, 1, 26, "LP Push-to-Fix:");
155     display(mid19win, 2, 26, "LP On Time:");
156     display(mid19win, 3, 26, "LP Interval:");
157     display(mid19win, 4, 26, "U. Tasks Enab.:");
158     display(mid19win, 5, 26, "U. Task Inter.:");
159     display(mid19win, 6, 26, "LP Pwr Cyc En:");
160     display(mid19win, 7, 26, "LP Max Acq Srch:");
161     display(mid19win, 8, 26, "LP Max Off Time:");
162     display(mid19win, 9, 26, "APM enabled:");
163     display(mid19win, 10, 26, "# of Fixes:");
164     display(mid19win, 11, 26, "Time btw Fixes:");
165     display(mid19win, 12, 26, "H/V Error Max:");
166     display(mid19win, 13, 26, "Rsp Time Max:");
167     display(mid19win, 14, 26, "Time/Accu:");
168
169     display(mid19win, 15, 8, " Packet type 19 (0x13) ");
170     (void)wattrset(mid19win, A_NORMAL);
171
172     (void)wborder(mid6win, 0, 0, 0, 0, 0, 0, 0, 0),
173         (void)wattrset(mid6win, A_BOLD);
174     display(mid6win, 1, 1, "Version:");
175     display(mid6win, 2, 8, " Packet Type 6 (0x06) ");
176     (void)wattrset(mid6win, A_NORMAL);
177
178     (void)wborder(mid7win, 0, 0, 0, 0, 0, 0, 0, 0),
179         (void)wattrset(mid7win, A_BOLD);
180     display(mid7win, 1, 1, "SVs: ");
181     display(mid7win, 1, 9, "Drift: ");
182     display(mid7win, 1, 23, "Bias: ");
183     display(mid7win, 2, 1, "Estimated GPS Time: ");
184     display(mid7win, 3, 8, " Packet type 7 (0x07) ");
185     (void)wattrset(mid7win, A_NORMAL);
186
187     (void)wborder(mid9win, 0, 0, 0, 0, 0, 0, 0, 0),
188         (void)wattrset(mid9win, A_BOLD);
189     display(mid9win, 1, 1, "Max: ");
190     display(mid9win, 1, 13, "Lat: ");
191     display(mid9win, 1, 25, "Time: ");
192     display(mid9win, 1, 39, "MS: ");
193     display(mid9win, 2, 8, " Packet type 9 (0x09) ");
194     (void)wattrset(mid9win, A_NORMAL);
195
196     (void)wborder(mid13win, 0, 0, 0, 0, 0, 0, 0, 0),
197         (void)wattrset(mid13win, A_BOLD);
198     display(mid13win, 1, 1, "SVs: ");
199     display(mid13win, 1, 9, "=");
200     display(mid13win, 2, 8, " Packet type 13 (0x0D) ");
201     (void)wattrset(mid13win, A_NORMAL);
202
203     (void)wborder(mid27win, 0, 0, 0, 0, 0, 0, 0, 0),
204         (void)wattrset(mid27win, A_BOLD);
205     display(mid27win, 1, 1, "DGPS source: ");
206     display(mid27win, 1, 31, "Corrections: ");
207     display(mid27win, 2, 8, " Packet type 27 (0x1B) ");
208     (void)wattrset(mid27win, A_NORMAL);
209     /*@ +nullpass @*/
210     /*@ -onlytrans @*/
211
212 #ifdef ALLOW_CONTROLSEND
213     /* probe for version */
214     /*@ -compdef @*/
215     (void)monitor_control_send((unsigned char *)"\x84\x00", 2);
216     /*@ +compdef @*/
217 #endif /* ALLOW_CONTROLSEND */
218
219     return true;
220 }
221
222 static void decode_time(int week, int tow)
223 {
224     int day = tow / 8640000;
225     int tod = tow % 8640000;
226     int h = tod / 360000;
227     int m = tod % 360000;
228     int s = m % 6000;
229
230     m = (m - s) / 6000;
231
232     (void)wmove(mid2win, 3, 10);
233     (void)wprintw(mid2win, "%4d+%9.2f", week, (double)tow / 100);
234     (void)wmove(mid2win, 3, 30);
235     (void)wprintw(mid2win, "%d %02d:%02d:%05.2f", day, h, m, (double)s / 100);
236     (void)wmove(mid2win, 4, 8);
237     (void)wattrset(mid2win, A_UNDERLINE);
238     (void)wprintw(mid2win, "%f",
239                   timestamp() - gpstime_to_unix(week, tow / 100.0));
240     (void)wmove(mid2win, 4, 29);
241     (void)wprintw(mid2win, "%d", gmt_offset);
242     (void)wattrset(mid2win, A_NORMAL);
243 }
244
245 static void decode_ecef(double x, double y, double z,
246                         double vx, double vy, double vz)
247 {
248     const double a = WGS84A;
249     const double b = WGS84B;
250     const double e2 = (a * a - b * b) / (a * a);
251     const double e_2 = (a * a - b * b) / (b * b);
252     double lambda, p, theta, phi, n, h, vnorth, veast, vup, speed, heading;
253
254     lambda = atan2(y, x);
255     /*@ -evalorder @*/
256     p = sqrt(pow(x, 2) + pow(y, 2));
257     theta = atan2(z * a, p * b);
258     phi =
259         atan2(z + e_2 * b * pow(sin(theta), 3),
260               p - e2 * a * pow(cos(theta), 3));
261     n = a / sqrt(1.0 - e2 * pow(sin(phi), 2));
262     h = p / cos(phi) - n;
263     h -= wgs84_separation((double)(RAD_2_DEG * phi),
264                           (double)(RAD_2_DEG * lambda));
265     vnorth =
266         -vx * sin(phi) * cos(lambda) - vy * sin(phi) * sin(lambda) +
267         vz * cos(phi);
268     veast = -vx * sin(lambda) + vy * cos(lambda);
269     vup =
270         vx * cos(phi) * cos(lambda) + vy * cos(phi) * sin(lambda) +
271         vz * sin(phi);
272     speed = sqrt(pow(vnorth, 2) + pow(veast, 2));
273     heading = atan2(veast, vnorth);
274     /*@ +evalorder @*/
275     if (heading < 0)
276         heading += 2 * GPS_PI;
277
278     (void)wattrset(mid2win, A_UNDERLINE);
279     (void)wmove(mid2win, 1, 40);
280     (void)wprintw(mid2win, "%9.5f %9.5f", (double)(RAD_2_DEG * phi),
281                   (double)(RAD_2_DEG * lambda));
282     (void)mvwaddch(mid2win, 1, 49, ACS_DEGREE);
283     (void)mvwaddch(mid2win, 1, 59, ACS_DEGREE);
284     (void)wmove(mid2win, 1, 61);
285     (void)wprintw(mid2win, "%8d", (int)h);
286
287     (void)wmove(mid2win, 2, 40);
288     (void)wprintw(mid2win, "%9.1f %9.1f", vnorth, veast);
289     (void)wmove(mid2win, 2, 61);
290     (void)wprintw(mid2win, "%8.1f", vup);
291
292     (void)wmove(mid2win, 3, 54);
293     (void)wprintw(mid2win, "%5.1f", (double)(RAD_2_DEG * heading));
294     (void)mvwaddch(mid2win, 3, 59, ACS_DEGREE);
295     (void)wmove(mid2win, 3, 61);
296     (void)wprintw(mid2win, "%8.1f", speed);
297     (void)wattrset(mid2win, A_NORMAL);
298 }
299
300 /*@ -globstate */
301 static void sirf_update(void)
302 {
303     int i, j, ch, off, cn;
304     unsigned char *buf;
305     size_t len;
306     uint8_t dgps;
307
308     assert(mid27win != NULL);
309     buf = session.packet.outbuffer + 4;
310     len = session.packet.outbuflen - 8;
311     switch (buf[0]) {
312     case 0x02:                  /* Measured Navigation Data */
313         (void)wmove(mid2win, 1, 6);     /* ECEF position */
314         (void)wprintw(mid2win, "%8d %8d %8d", getbesl(buf, 1),
315                       getbesl(buf, 5), getbesl(buf, 9));
316         (void)wmove(mid2win, 2, 6);     /* ECEF velocity */
317         (void)wprintw(mid2win, "%8.1f %8.1f %8.1f",
318                       (double)getbesw(buf, 13) / 8, (double)getbesw(buf,
319                                                                     15) / 8,
320                       (double)getbesw(buf, 17) / 8);
321         decode_ecef((double)getbesl(buf, 1), (double)getbesl(buf, 5),
322                     (double)getbesl(buf, 9), (double)getbesw(buf, 13) / 8,
323                     (double)getbesw(buf, 15) / 8, (double)getbesw(buf,
324                                                                   17) / 8);
325         decode_time((int)getbeuw(buf, 22), getbesl(buf, 24));
326         /* line 4 */
327         (void)wmove(mid2win, 4, 49);
328         (void)wprintw(mid2win, "%4.1f", (double)getub(buf, 20) / 5);    /* HDOP */
329         (void)wmove(mid2win, 4, 58);
330         (void)wprintw(mid2win, "%02x", getub(buf, 19)); /* Mode 1 */
331         (void)wmove(mid2win, 4, 70);
332         (void)wprintw(mid2win, "%02x", getub(buf, 21)); /* Mode 2 */
333         (void)wmove(mid2win, 5, 7);
334         nfix = (int)getub(buf, 28);
335         (void)wprintw(mid2win, "%d = ", nfix);  /* SVs in fix */
336         for (i = 0; i < MAXSATS; i++) { /* SV list */
337             if (i < nfix)
338                 (void)wprintw(mid2win, "%3d", fix[i] =
339                               (int)getub(buf, 29 + i));
340             else
341                 (void)wprintw(mid2win, "   ");
342         }
343         monitor_log("MND 0x02=");
344         break;
345
346     case 0x04:                  /* Measured Tracking Data */
347         decode_time((int)getbeuw(buf, 1), getbesl(buf, 3));
348         ch = (int)getub(buf, 7);
349         for (i = 0; i < ch; i++) {
350             int sv, st;
351
352             off = 8 + 15 * i;
353             (void)wmove(mid4win, i + 2, 3);
354             sv = (int)getub(buf, off);
355             (void)wprintw(mid4win, " %3d", sv);
356
357             (void)wprintw(mid4win, " %3d%3d %04x",
358                           ((int)getub(buf, off + 1) * 3) / 2, (int)getub(buf,
359                                                                          off +
360                                                                          2) /
361                           2, (int)getbesw(buf, off + 3));
362
363             st = ' ';
364             if ((int)getbeuw(buf, off + 3) == 0xbf)
365                 st = 'T';
366             for (j = 0; j < nfix; j++)
367                 if (sv == fix[j]) {
368                     st = 'N';
369                     break;
370                 }
371
372             cn = 0;
373
374             for (j = 0; j < 10; j++)
375                 cn += (int)getub(buf, off + 5 + j);
376
377             (void)wprintw(mid4win, "%5.1f %c", (double)cn / 10, st);
378
379             if (sv == 0)        /* not tracking? */
380                 (void)wprintw(mid4win, "   ");  /* clear other info */
381         }
382         monitor_log("MTD 0x04=");
383         break;
384
385 #ifdef __UNUSED__
386     case 0x05:                  /* raw track data */
387         for (off = 1; off < len; off += 51) {
388             ch = getbeul(buf, off);
389             (void)wmove(mid4win, ch + 2, 19);
390             cn = 0;
391
392             for (j = 0; j < 10; j++)
393                 cn += getub(buf, off + 34 + j);
394
395             printw("%5.1f", (double)cn / 10);
396
397             printw("%9d%3d%5d", getbeul(buf, off + 8),
398                    (int)getbeuw(buf, off + 12), (int)getbeuw(buf, off + 14));
399             printw("%8.5f %10.5f", (double)getbeul(buf, off + 16) / 65536,
400                    (double)getbeul(buf, off + 20) / 1024);
401         }
402         monitor_log("RTD 0x05=");
403         break;
404 #endif /* __UNUSED */
405
406     case 0x06:                  /* firmware version */
407         display(mid6win, 1, 10, "%s", buf + 1);
408         monitor_log("FV  0x06=");
409         break;
410
411     case 0x07:                  /* Response - Clock Status Data */
412         decode_time((int)getbeuw(buf, 1), getbesl(buf, 3));
413         display(mid7win, 1, 5, "%2d", getub(buf, 7));   /* SVs */
414         display(mid7win, 1, 16, "%lu", getbeul(buf, 8));        /* Clock drift */
415         display(mid7win, 1, 29, "%lu", getbeul(buf, 12));       /* Clock Bias */
416         display(mid7win, 2, 21, "%lu", getbeul(buf, 16));       /* Estimated Time */
417         monitor_log("CSD 0x07=");
418         break;
419
420     case 0x08:                  /* 50 BPS data */
421         ch = (int)getub(buf, 1);
422         display(mid4win, ch + 2, 27, "Y");
423         monitor_log("50B 0x08=");
424         subframe_enabled = true;
425         break;
426
427     case 0x09:                  /* Throughput */
428         display(mid9win, 1, 6, "%.3f", (double)getbeuw(buf, 1) / 186);  /*SegStatMax */
429         display(mid9win, 1, 18, "%.3f", (double)getbeuw(buf, 3) / 186); /*SegStatLat */
430         display(mid9win, 1, 31, "%.3f", (double)getbeuw(buf, 5) / 186); /*SegStatTime */
431         display(mid9win, 1, 42, "%3d", (int)getbeuw(buf, 7));   /* Last Millisecond */
432         monitor_log("THR 0x09=");
433         break;
434
435     case 0x0b:                  /* Command Acknowledgement */
436         monitor_log("ACK 0x0b=");
437         break;
438
439     case 0x0c:                  /* Command NAcknowledgement */
440         monitor_log("NAK 0x0c=");
441         break;
442
443     case 0x0d:                  /* Visible List */
444         display(mid13win, 1, 6, "%02d", getub(buf, 1));
445         (void)wmove(mid13win, 1, 10);
446         for (i = 0; i < MAXSATS; i++) {
447             if (i < (int)getub(buf, 1))
448                 (void)wprintw(mid13win, " %2d", getub(buf, 2 + 5 * i));
449             else
450                 (void)wprintw(mid13win, "   ");
451         }
452         monitor_log("VL  0x0d=");
453         break;
454
455     case 0x13:
456 #define YESNO(n)        (((int)getub(buf, n) != 0)?'Y':'N')
457         display(mid19win, 1, 20, "%d", getub(buf, 5));  /* Alt. hold mode */
458         display(mid19win, 2, 20, "%d", getub(buf, 6));  /* Alt. hold source */
459         display(mid19win, 3, 20, "%dm", (int)getbeuw(buf, 7));  /* Alt. source input */
460         if (getub(buf, 9) != (uint8_t) '\0')
461             display(mid19win, 4, 20, "%dsec", getub(buf, 10));  /* Degraded timeout */
462         else
463             display(mid19win, 4, 20, "N/A   ");
464         display(mid19win, 5, 20, "%dsec", getub(buf, 11));      /* DR timeout */
465         display(mid19win, 6, 20, "%c", YESNO(12));      /* Track smooth mode */
466         display(mid19win, 7, 20, "%c", YESNO(13));      /* Static Nav. */
467         display(mid19win, 8, 20, "0x%x", getub(buf, 14));       /* 3SV Least Squares */
468         display(mid19win, 9, 20, "0x%x", getub(buf, 19));       /* DOP Mask mode */
469         display(mid19win, 10, 20, "0x%x", (int)getbeuw(buf, 20));       /* Nav. Elev. mask */
470         display(mid19win, 11, 20, "0x%x", getub(buf, 22));      /* Nav. Power mask */
471         display(mid19win, 12, 20, "0x%x", getub(buf, 27));      /* DGPS Source */
472         display(mid19win, 13, 20, "0x%x", getub(buf, 28));      /* DGPS Mode */
473         display(mid19win, 14, 20, "%dsec", getub(buf, 29));     /* DGPS Timeout */
474         display(mid19win, 1, 42, "%c", YESNO(34));      /* LP Push-to-Fix */
475         display(mid19win, 2, 42, "%dms", getbeul(buf, 35));     /* LP On Time */
476         display(mid19win, 3, 42, "%d", getbeul(buf, 39));       /* LP Interval */
477         display(mid19win, 4, 42, "%c", YESNO(43));      /* User Tasks enabled */
478         display(mid19win, 5, 42, "%d", getbeul(buf, 44));       /* User Task Interval */
479         display(mid19win, 6, 42, "%c", YESNO(48));      /* LP Power Cycling Enabled */
480         display(mid19win, 7, 42, "%d", getbeul(buf, 49));       /* LP Max Acq Search Time */
481         display(mid19win, 8, 42, "%d", getbeul(buf, 53));       /* LP Max Off Time */
482         display(mid19win, 9, 42, "%c", YESNO(57));      /* APM Enabled */
483         display(mid19win, 10, 42, "%d", (int)getbeuw(buf, 58)); /* # of fixes */
484         display(mid19win, 11, 42, "%d", (int)getbeuw(buf, 60)); /* Time Between fixes */
485         display(mid19win, 12, 42, "%d", getub(buf, 62));        /* H/V Error Max */
486         display(mid19win, 13, 42, "%d", getub(buf, 63));        /* Response Time Max */
487         display(mid19win, 14, 42, "%d", getub(buf, 64));        /* Time/Accu & Duty Cycle Priority */
488 #undef YESNO
489         break;
490
491     case 0x1b:
492         /******************************************************************
493          Not actually documented in any published materials.
494          Here is what Chris Kuethe got from the SiRF folks,
495          (plus some corrections from the GpsPaSsion forums):
496
497         Start of message
498         ----------------
499         Message ID          1 byte    27
500         Correction Source   1 byte    0=None, 1=SBAS, 2=Serial, 3=Beacon,
501         4=Software
502
503         total:              2 bytes
504
505         Middle part of message varies if using beacon or other:
506         -------------------------------------------------------
507         If Beacon:
508         Receiver Freq Hz    4 bytes
509         Bit rate BPS        1 byte
510         Status bit map      1 byte    01=Signal Valid,
511                                       02=Auto frequency detect
512                                       04=Auto bit rate detect
513         Signal Magnitude    4 bytes   Note: in internal units
514         Signal Strength dB  2 bytes   derived from Signal Magnitude
515         SNR  dB             2 bytes
516
517         total:             14 bytes
518
519         If Not Beacon:
520         Correction Age[12]  1 byte x 12  Age in seconds in same order as follows
521         Reserved            2 bytes
522
523         total:             14 bytes
524
525         End of Message
526         --------------
527         Repeated 12 times (pad with 0 if less than 12 SV corrections):
528         SVID                1 byte
529         Correction (cm)     2 bytes (signed short)
530
531         total               3 x 12 = 36 bytes
532         ******************************************************************/
533         dgps = getub(buf, 1);
534         display(mid27win, 1, 14, "%d (%s)",
535                 dgps, (CHECK_RANGE(dgpsvec, dgps) ? dgpsvec[dgps] : "???"));
536         /*@ -type @*/
537         //(void) wmove(mid27win, 2, 0);
538         for (i = j = 0; i < 12; i++) {
539             if (getub(buf, 16 + 3 * i) != '\0') {
540                 //(void)wprintw(mid27win, " %d=%d", getub(buf, 16+3*i), getbesw(buf, 16+3*i+1));
541                 j++;
542             }
543         }
544         /*@ +type @*/
545         display(mid27win, 1, 44, "%d", j);
546         monitor_log("DST 0x1b=");
547         break;
548
549     case 0x1C:                  /* NL Measurement Data */
550     case 0x1D:                  /* DGPS Data */
551     case 0x1E:                  /* SV State Data */
552     case 0x1F:                  /* NL Initialized Data */
553         subframe_enabled = true;
554         break;
555     case 0x29:                  /* Geodetic Navigation Message */
556         monitor_log("GNM 0x29=");
557         break;
558     case 0x32:                  /* SBAS Parameters */
559         monitor_log("SBP 0x32=");
560         break;
561     case 0x34:                  /* PPS Time */
562         monitor_log("PPS 0x34=");
563         break;
564
565 #ifdef __UNUSED__
566     case 0x62:
567         attrset(A_BOLD);
568         move(2, 40);
569         printw("%9.5f %9.5f", (double)(RAD_2_DEG * 1e8 * getbesl(buf, 1)),
570                (double)(RAD_2_DEG * 1e8 * getbesl(buf, 5)));
571         move(2, 63);
572         printw("%8d", getbesl(buf, 9) / 1000);
573
574         move(3, 63);
575
576         printw("%8.1f", (double)getbesl(buf, 17) / 1000);
577
578         move(4, 54);
579         if (getbeul(buf, 13) > 50) {
580             double heading = RAD_2_DEG * 1e8 * getbesl(buf, 21);
581             if (heading < 0)
582                 heading += 360;
583             printw("%5.1f", heading);
584         } else
585             printw("  0.0");
586
587         move(4, 63);
588         printw("%8.1f", (double)getbesl(buf, 13) / 1000);
589         attrset(A_NORMAL);
590
591         move(5, 13);
592         printw("%04d-%02d-%02d %02d:%02d:%02d.%02d",
593                (int)getbeuw(buf, 26), getub(buf, 28), getub(buf, 29),
594                getub(buf, 30), getub(buf, 31), (unsigned short)getbeuw(buf,
595                                                                        32) /
596                1000, ((unsigned short)getbeuw(buf, 32) % 1000) / 10);
597         {
598             struct timeval clk, gps;
599             struct tm tm;
600
601             gettimeofday(&clk, NULL);
602
603             memset(&tm, 0, sizeof(tm));
604             tm.tm_sec = (unsigned short)getbeuw(buf, 32) / 1000;
605             tm.tm_min = (int)getub(buf, 31);
606             tm.tm_hour = (int)getub(buf, 30);
607             tm.tm_mday = (int)getub(buf, 29);
608             tm.tm_mon = (int)getub(buf, 28) - 1;
609             tm.tm_year = (int)getbeuw(buf, 26) - 1900;
610
611             gps.tv_sec = mkgmtime(&tm);
612             gps.tv_usec =
613                 (((unsigned short)getbeuw(buf, 32) % 1000) / 10) * 10000;
614
615             move(5, 2);
616             printw("           ");
617             move(5, 2);
618 #if 1
619             printw("%ld", (gps.tv_usec - clk.tv_usec) +
620                    ((gps.tv_sec - clk.tv_sec) % 3600) * 1000000);
621 #else
622             printw("%ld %ld %ld %ld", gps.tv_sec % 3600, gps.tv_usec,
623                    clk.tv_sec % 3600, clk.tv_usec);
624 #endif
625         }
626         monitor_log("??? 0x62=");
627         break;
628 #endif /* __UNUSED__ */
629
630     case 0xff:                  /* Development Data */
631         /*@ +ignoresigns @*/
632         while (len > 0 && buf[len - 1] == '\n')
633             len--;
634         while (len > 0 && buf[len - 1] == ' ')
635             len--;
636         /*@ -ignoresigns @*/
637         buf[len] = '\0';
638         j = 1;
639         for (i = 0; verbpat[i] != NULL; i++)
640             if (strncmp((char *)(buf + 1), verbpat[i], strlen(verbpat[i])) ==
641                 0) {
642                 j = 0;
643                 break;
644             }
645         if (j != 0)
646             monitor_log("%s\n", buf + 1);
647         monitor_log("DD  0xff=");
648         break;
649
650     default:
651         monitor_log("    0x%02x=", buf[4]);
652         break;
653     }
654
655 #ifdef ALLOW_CONTROLSEND
656     /* elicit navigation parameters */
657     if (dispmode && (time(NULL) % 10 == 0)) {
658         (void)monitor_control_send((unsigned char *)"\x98\x00", 2);
659     }
660 #endif /* ALLOW_CONTROLSEND */
661
662     /*@ -nullpass -nullderef @*/
663     if (dispmode) {
664         (void)touchwin(mid19win);
665         (void)wnoutrefresh(mid19win);
666     }
667     /*@ +nullpass -nullderef @*/
668 }
669
670 /*@ +globstate */
671
672 #ifdef ALLOW_CONTROLSEND
673 static int sirf_command(char line[])
674 {
675     unsigned char buf[BUFSIZ];
676     int v;
677
678     switch (line[0]) {
679     case 'A':                   /* toggle 50bps subframe data */
680         (void)memset(buf, '\0', sizeof(buf));
681         putbyte(buf, 0, 0x80);
682         putbyte(buf, 23, 12);
683         putbyte(buf, 24, subframe_enabled ? 0x00 : 0x10);
684         (void)monitor_control_send(buf, 25);
685         return COMMAND_MATCH;
686
687     case 'M':                   /* static navigation */
688         putbyte(buf, 0, 0x8f);  /* id */
689         putbyte(buf, 1, atoi(line + 1));
690         (void)monitor_control_send(buf, 2);
691         return COMMAND_MATCH;
692
693     case 'D':                   /* MID 4 rate change (undocumented) */
694         v = atoi(line + 1);
695         if (v > 30)
696             return COMMAND_MATCH;
697         putbyte(buf, 0, 0xa6);
698         putbyte(buf, 1, 0);
699         putbyte(buf, 2, 4);     /* satellite picture */
700         putbyte(buf, 3, v);
701         putbyte(buf, 4, 0);
702         putbyte(buf, 5, 0);
703         putbyte(buf, 6, 0);
704         putbyte(buf, 7, 0);
705         (void)monitor_control_send(buf, 8);
706         return COMMAND_MATCH;
707
708     case 'P':                   /* poll navigation params */
709         dispmode = !dispmode;
710         return COMMAND_MATCH;
711     }
712
713     return COMMAND_UNKNOWN;     /* no match */
714 }
715 #endif /* ALLOW_CONTROLSEND */
716
717 static void sirf_wrap(void)
718 {
719     (void)delwin(mid2win);
720     (void)delwin(mid4win);
721     (void)delwin(mid6win);
722     (void)delwin(mid7win);
723     (void)delwin(mid9win);
724     (void)delwin(mid13win);
725     (void)delwin(mid19win);
726     (void)delwin(mid27win);
727 }
728
729 const struct monitor_object_t sirf_mmt = {
730     .initialize = sirf_initialize,
731     .update = sirf_update,
732 #ifdef ALLOW_CONTROLSEND
733     .command = sirf_command,
734 #else
735     .command = NULL,
736 #endif /* ALLOW_CONTROLSEND */
737     .wrap = sirf_wrap,
738     .min_y = 23,.min_x = 80,
739     .driver = &sirf_binary,
740 };
741 #endif /* defined(SIRF_ENABLE) && defined(BINARY_ENABLE) */
742
743 /* sirfmon.c ends here */