"Initial commit to Gerrit"
[profile/ivi/gpsd.git] / monitor_oncore.c
1 /*
2  * OnCore 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 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <math.h>
11 #include <ctype.h>
12 #ifndef S_SPLINT_S
13 #include <unistd.h>
14 #endif /* S_SPLINT_S */
15 #include <stdarg.h>
16 #include <stdbool.h>
17 #include <assert.h>
18
19 #include "gpsd_config.h"
20
21 #ifdef HAVE_NCURSES_H
22 #include <ncurses.h>
23 #else
24 #include <curses.h>
25 #endif /* HAVE_NCURSES_H */
26 #include "gpsd.h"
27
28 #include "bits.h"
29 #include "gpsmon.h"
30
31 #if defined(ONCORE_ENABLE) && defined(BINARY_ENABLE)
32 extern const struct gps_type_t oncore_binary;
33
34 static WINDOW *Ea1win, *Eawin, *Bbwin, *Enwin, *Bowin, *Aywin, *Aswin, *Atwin;
35 static unsigned char EaSVlines[8];
36
37 static const char *antenna[] = {
38     "OK (conn)",
39     "OC (short)",
40     "UC (open)",
41     "OU (short)"
42 };
43
44 static const char *sv_mode[] = {
45     "srch",
46     "acq",
47     "AGCs",
48     "pacq",
49     "bits",
50     "msgs",
51     "satT",
52     "epha",
53     "avl"
54 };
55
56 static const char *pps_ctrl[] = {
57     "off",
58     "on",
59     "on if >= 1 SV",
60     "on if TRAIM ok"
61 };
62
63 static const char *pps_sync[] = {
64     "UTC",
65     "GPS"
66 };
67
68 static const char *traim_sol[] = {
69     "OK",
70     "ALARM",
71     "UNKNOWN"
72 };
73
74 static const char *traim_status[] = {
75     "detect & isolate",
76     "detect",
77     "insufficient"
78 };
79
80 static const char *pos_hold_mode[] = {
81     "off",
82     "on",
83     "survey"
84 };
85
86 #define ONCTYPE(id2,id3) ((((unsigned int)id2)<<8)|(id3))
87
88 #define MAXTRACKSATS    8       /* the most satellites being tracked */
89 #define MAXVISSATS      12      /* the most satellites with known az/el */
90
91 static bool oncore_initialize(void)
92 {
93     unsigned int i;
94
95     /*@ -onlytrans @*/
96     Ea1win = subwin(devicewin, 5, 80, 1, 0);
97     Eawin = subwin(devicewin, MAXTRACKSATS + 3, 27, 6, 0);
98     Bbwin = subwin(devicewin, MAXVISSATS + 3, 22, 6, 28);
99     Enwin = subwin(devicewin, 10, 29, 6, 51);
100     Bowin = subwin(devicewin, 4, 11, 17, 0);
101     Aywin = subwin(devicewin, 4, 15, 17, 12);
102     Atwin = subwin(devicewin, 5, 9, 16, 51);
103     Aswin = subwin(devicewin, 5, 19, 16, 61);
104     /*@ +onlytrans @*/
105
106     if (Ea1win == NULL || Eawin == NULL || Bbwin == NULL || Enwin == NULL
107         || Bowin == NULL || Aswin == NULL || Atwin == NULL)
108         return false;
109
110     (void)syncok(Ea1win, true);
111     (void)syncok(Eawin, true);
112     (void)syncok(Bbwin, true);
113     (void)syncok(Enwin, true);
114     (void)syncok(Bowin, true);
115     (void)syncok(Aywin, true);
116     (void)syncok(Aswin, true);
117     (void)syncok(Atwin, true);
118
119     (void)wborder(Ea1win, 0, 0, 0, 0, 0, 0, 0, 0),
120         (void)wattrset(Ea1win, A_BOLD);
121     (void)mvwaddstr(Ea1win, 1, 1,
122                     "Time:                                     Lat:              Lon:");
123     (void)mvwaddstr(Ea1win, 2, 1,
124                     "Antenna:             DOP:                 Speed:            Course:");
125     (void)mvwaddstr(Ea1win, 3, 1,
126                     "SV/vis:        Status:                                      Alt:");
127     (void)mvwprintw(Ea1win, 4, 4, " @@Ea (pos) ");
128     (void)wattrset(Ea1win, A_NORMAL);
129
130     (void)wborder(Eawin, 0, 0, 0, 0, 0, 0, 0, 0),
131         (void)wattrset(Eawin, A_BOLD);
132     (void)mvwprintw(Eawin, 1, 1, "Ch PRN mode S/N ????????");
133     (void)mvwprintw(Eawin, 10, 4, " @@Ea (sat) ");
134     for (i = 0; i < 8; i++) {
135         (void)mvwprintw(Eawin, (int)(i + 2), 1, "%2d", i);
136     }
137     (void)wattrset(Eawin, A_NORMAL);
138
139     (void)wborder(Bbwin, 0, 0, 0, 0, 0, 0, 0, 0),
140         (void)wattrset(Bbwin, A_BOLD);
141     (void)mvwprintw(Bbwin, 1, 1, "PRN  Az El doppl ??");
142     (void)mvwprintw(Bbwin, 14, 4, " @@Bb ");
143     (void)wattrset(Bbwin, A_NORMAL);
144
145     (void)wborder(Enwin, 0, 0, 0, 0, 0, 0, 0, 0),
146         (void)wattrset(Enwin, A_BOLD);
147     (void)mvwprintw(Enwin, 1, 1, "Time RAIM: ");
148     (void)mvwprintw(Enwin, 2, 1, "Alarm limit:");
149     (void)mvwprintw(Enwin, 3, 1, "PPS ctrl:");
150     (void)mvwprintw(Enwin, 4, 1, "Pulse:");
151     (void)mvwprintw(Enwin, 5, 1, "PPS sync:");
152     (void)mvwprintw(Enwin, 6, 1, "TRAIM sol stat:");
153     (void)mvwprintw(Enwin, 7, 1, "Status:");
154     (void)mvwprintw(Enwin, 8, 1, "Time sol sigma:");
155     (void)mvwprintw(Enwin, 9, 4, " @@En ");
156     (void)wattrset(Enwin, A_NORMAL);
157
158     (void)wborder(Bowin, 0, 0, 0, 0, 0, 0, 0, 0),
159         (void)wattrset(Bowin, A_BOLD);
160     (void)mvwprintw(Bowin, 1, 1, "UTC:");
161     (void)mvwprintw(Bowin, 3, 2, " @@Bo ");
162     (void)wattrset(Bowin, A_NORMAL);
163
164     (void)wborder(Aywin, 0, 0, 0, 0, 0, 0, 0, 0),
165         (void)wattrset(Aywin, A_BOLD);
166     (void)mvwprintw(Aywin, 1, 1, "PPS delay:");
167     (void)mvwprintw(Aywin, 3, 4, " @@Ay ");
168     (void)wattrset(Aywin, A_NORMAL);
169
170     (void)wborder(Atwin, 0, 0, 0, 0, 0, 0, 0, 0),
171         (void)wattrset(Atwin, A_BOLD);
172     (void)mvwprintw(Atwin, 1, 1, "PHold:");
173     (void)mvwprintw(Atwin, 4, 1, " @@At ");
174     (void)wattrset(Atwin, A_NORMAL);
175
176     (void)wborder(Aswin, 0, 0, 0, 0, 0, 0, 0, 0),
177         (void)wattrset(Aswin, A_BOLD);
178     (void)mvwprintw(Aswin, 1, 1, "Lat:");
179     (void)mvwprintw(Aswin, 2, 1, "Lon:");
180     (void)mvwprintw(Aswin, 3, 1, "Alt:");
181     (void)mvwprintw(Aswin, 4, 4, " @@As ");
182     (void)wattrset(Aswin, A_NORMAL);
183
184     memset(EaSVlines, 0, sizeof(EaSVlines));
185
186     return true;
187 }
188
189 static void oncore_update(void)
190 {
191     unsigned int i, j, off;
192     unsigned char *buf;
193     unsigned int type;
194
195     assert(Eawin != NULL);
196     buf = session.packet.outbuffer;
197     type = ONCTYPE(buf[2], buf[3]);
198     switch (type) {
199     case ONCTYPE('E', 'a'):
200     {
201         double lat, lon, alt;
202         float speed, track;
203         float dop;
204         unsigned short year;
205         unsigned char mon, day, hour, min, sec;
206         unsigned int nsec;
207         unsigned char dopt, nvis, nsat, status;
208         char statusbuf[64];     /* 6+9+3+3+10+5+7+12+1=56 */
209
210         mon = (unsigned char)getub(buf, 4);
211         day = (unsigned char)getub(buf, 5);
212         year = (unsigned short)getbeuw(buf, 6);
213         hour = (unsigned char)getub(buf, 8);
214         min = (unsigned char)getub(buf, 9);
215         sec = (unsigned char)getub(buf, 10);
216         nsec = (unsigned int)getbeul(buf, 11);
217
218         lat = getbesl(buf, 15) / 3600000.0;
219         lon = getbesl(buf, 19) / 3600000.0;
220         alt = getbesl(buf, 23) / 100.0;
221         speed = (float)(getbeuw(buf, 31) / 100.0);
222         track = (float)(getbeuw(buf, 33) / 10.0);
223         dop = (float)(getbeuw(buf, 35) / 10.0);
224         dopt = (unsigned char)getub(buf, 37);
225         nvis = (unsigned char)getub(buf, 38);
226         nsat = (unsigned char)getub(buf, 39);
227         status = (unsigned char)getub(buf, 72);
228
229         (void)mvwprintw(Ea1win, 1, 7, "%04d-%02d-%02d %02d:%02d:%02d.%09d",
230                         year, mon, day, hour, min, sec, nsec);
231         (void)mvwprintw(Ea1win, 1, 47, "%10.6lf %c",
232                         fabs(lat), lat < 0 ? 'S' : lat > 0 ? 'N' : ' ');
233         (void)mvwprintw(Ea1win, 1, 66, "%10.6lf %c",
234                         fabs(lon), lat < 0 ? 'W' : lon > 0 ? 'E' : ' ');
235
236         (void)mvwprintw(Ea1win, 2, 50, "%6.2f m/s", speed);
237         (void)mvwprintw(Ea1win, 2, 70, "%5.1f", track);
238         (void)mvwprintw(Ea1win, 3, 68, "%8.2f m", alt);
239
240         /*@ -predboolothers @*/
241         (void)snprintf(statusbuf, sizeof(statusbuf), "%s%s%s%s%s%s%s%s",
242                        status & 0x80 ? "PProp " : "",
243                        status & 0x40 ? "PoorGeom " : "",
244                        status & 0x20 ? "3D " : "",
245                        status & 0x10 ? "2D " : "",
246                        status & 0x08 ? "Acq/PHold " : "",
247                        status & 0x04 ? "Diff " : "",
248                        status & 0x02 ? "Ins (<3 SV) " : "",
249                        status & 0x01 ? "BadAlm " : "");
250         /*@ +predboolothers @*/
251
252         (void)mvwprintw(Ea1win, 3, 24, "%-37s", statusbuf);
253
254         (void)mvwprintw(Ea1win, 2, 10, "%-10s", antenna[dopt >> 6]);
255
256         /*@ -predboolothers @*/
257         (void)mvwprintw(Ea1win, 2, 27, "%s %4.1f",
258                         dopt & 1 ? "hdop" : "pdop", dop);
259         /*@ +predboolothers @*/
260
261         (void)mvwprintw(Ea1win, 3, 10, "%d/%d ", nsat, nvis);
262     }
263
264         for (i = 0; i < 8; i++) {
265             unsigned char sv, mode, sn, status;
266
267             off = 40 + 4 * i;
268             sv = (unsigned char)getub(buf, off);
269             mode = (unsigned char)getub(buf, off + 1);
270             sn = (unsigned char)getub(buf, off + 2);
271             status = (unsigned char)getub(buf, off + 3);
272             (void)wmove(Eawin, (int)(i + 2), 3);
273             (void)wprintw(Eawin, " %3d", sv);
274             EaSVlines[i] = sv;
275             if (mode <= (unsigned char)8)
276                 (void)wprintw(Eawin, " %4s", sv_mode[mode]);
277             else
278                 (void)wprintw(Eawin, "    -");
279             (void)wprintw(Eawin, " %3d", sn);
280             /*@ -predboolothers @*/
281             (void)wprintw(Eawin, " %c%c%c%c%c%c%c%c", (status & 0x80) ? 'p' : ' ',      /* used for pos fix  */
282                           (status & 0x40) ? 'M' : ' ',  /* momentum alert    */
283                           (status & 0x20) ? 's' : ' ',  /* anti-spoof   */
284                           (status & 0x10) ? 'U' : ' ',  /* unhealthy     */
285                           (status & 0x08) ? 'I' : ' ',  /* inaccurate   */
286                           (status & 0x04) ? 'S' : ' ',  /* spare             */
287                           (status & 0x02) ? 't' : ' ',  /* used for time sol */
288                           (status & 0x01) ? 'P' : ' '); /* parity error      */
289             /*@ +predboolothers @*/
290         }
291
292         monitor_log("Ea =");
293         break;
294
295     case ONCTYPE('B', 'b'):
296     {
297         unsigned int Bblines[12];
298         unsigned int Bblines_mask;
299         unsigned int next_line;
300         unsigned char sv;
301         unsigned int ch;
302
303         ch = (unsigned int)getub(buf, 4);
304         if (ch > 12)
305             ch = 12;
306         /* Try to align the entries for each SV of the Bb message at
307          * the same lines as in the Ea message.
308          */
309         memset(Bblines, 0, sizeof(Bblines));
310         Bblines_mask = 0;
311         for (i = 0; i < ch; i++) {
312             off = 5 + 7 * i;
313             sv = (unsigned char)getub(buf, off);
314             /*@ -boolops @*/
315             for (j = 0; j < 8; j++)
316                 if (EaSVlines[j] == sv && !(Bblines_mask & (1 << (j + 2)))) {
317                     Bblines[i] = j + 2;
318                     Bblines_mask |= 1 << Bblines[i];
319                 }
320             /*@ +boolops @*/
321         }
322         /* SVs not seen in Ea fill lines left over. */
323         next_line = 2;
324         for (i = 0; i < ch; i++) {
325             if (Bblines[i] == 0) {
326                 while (Bblines_mask & (1 << next_line))
327                     next_line++;
328                 Bblines[i] = next_line++;
329                 Bblines_mask |= 1 << Bblines[i];
330             }
331         }
332         /* Ready to print on precalculated lines. */
333         for (i = 0; i < ch; i++) {
334             int doppl, el, az, health;
335
336             off = 5 + 7 * i;
337             sv = (unsigned char)getub(buf, off);
338             doppl = (int)getbesw(buf, off + 1);
339             el = (int)getub(buf, off + 3);
340             az = (int)getbeuw(buf, off + 4);
341             health = (int)getub(buf, off + 5);
342
343             (void)wmove(Bbwin, (int)Bblines[i], 1);
344             (void)wprintw(Bbwin, "%3d %3d %2d %5d %c%c", sv, az, el, doppl, (health & 0x02) ? 'U' : ' ',        /* unhealthy */
345                           (health & 0x01) ? 'R' : ' '); /* removed   */
346         }
347
348         for (i = 2; i < 14; i++)
349             /*@ -boolops @*/
350             if (!(Bblines_mask & (1 << i))) {
351                 (void)wmove(Bbwin, (int)i, 1);
352                 (void)wprintw(Bbwin, "                   ");
353             }
354         /*@ +boolops @*/
355     }
356
357         monitor_log("Bb =");
358         break;
359
360     case ONCTYPE('E', 'n'):
361     {
362         unsigned char traim, ctrl, pulse, sync, sol_stat, status;
363         float alarm, sigma;
364
365         traim = (unsigned char)getub(buf, 5);
366         alarm = (float)(getbeuw(buf, 6) / 10.);
367         ctrl = (unsigned char)getub(buf, 8);
368         pulse = (unsigned char)getub(buf, 9);
369         sync = (unsigned char)getub(buf, 10);
370         sol_stat = (unsigned char)getub(buf, 11);
371         status = (unsigned char)getub(buf, 12);
372         sigma = (float)(getbeuw(buf, 13));
373
374         /*@ -predboolothers @*/
375         (void)mvwprintw(Enwin, 1, 24, "%3s", traim ? "on" : "off");
376         (void)mvwprintw(Enwin, 2, 18, "%6.1f us", alarm);
377         (void)mvwprintw(Enwin, 3, 13, "%14s", pps_ctrl[ctrl]);
378         (void)mvwprintw(Enwin, 4, 24, "%3s", pulse ? "on" : "off");
379         (void)mvwprintw(Enwin, 5, 24, "%3s", pps_sync[sync]);
380         (void)mvwprintw(Enwin, 6, 20, "%7s", traim_sol[sol_stat]);
381         (void)mvwprintw(Enwin, 7, 11, "%16s", traim_status[status]);
382         (void)mvwprintw(Enwin, 8, 18, "%6.3f us", sigma);
383         /*@ +predboolothers @*/
384     }
385
386         monitor_log("En =");
387         break;
388
389     case ONCTYPE('B', 'o'):
390     {
391         unsigned char utc_offset;
392
393         utc_offset = (unsigned char)getub(buf, 4);
394
395         if (utc_offset != (unsigned char)0)
396             (void)mvwprintw(Bowin, 2, 2, "GPS%+4d", utc_offset);
397         else
398             (void)mvwprintw(Bowin, 2, 2, "unknown", utc_offset);
399     }
400
401         monitor_log("Bo =");
402         break;
403
404     case ONCTYPE('A', 'y'):
405     {
406         double pps_delay;
407
408         pps_delay = getbesl(buf, 4) / 1000000.0;
409
410         (void)mvwprintw(Aywin, 2, 2, " %7.3f ms", pps_delay);
411     }
412
413         monitor_log("Ay =");
414         break;
415
416     case ONCTYPE('A', 't'):
417     {
418         unsigned char mode;
419
420         mode = (unsigned char)getub(buf, 4);
421
422         (void)mvwprintw(Atwin, 2, 1, "%6s", pos_hold_mode[mode]);
423     }
424
425         monitor_log("At =");
426         break;
427
428     case ONCTYPE('A', 's'):
429     {
430         double lat, lon, alt;
431
432         lat = getbesl(buf, 4) / 3600000.0;
433         lon = getbesl(buf, 8) / 3600000.0;
434         alt = getbesl(buf, 12) / 100.0;
435
436         (void)mvwprintw(Aswin, 1, 5, "%10.6lf %c",
437                         fabs(lat), lat < 0 ? 'S' : lat > 0 ? 'N' : ' ');
438         (void)mvwprintw(Aswin, 2, 5, "%10.6lf %c",
439                         fabs(lon), lat < 0 ? 'W' : lon > 0 ? 'E' : ' ');
440         (void)mvwprintw(Aswin, 3, 7, "%8.2f m", alt);
441     }
442
443         monitor_log("As =");
444         break;
445
446     default:
447         monitor_log("%c%c =", buf[2], buf[3]);
448         break;
449     }
450 }
451
452 static int oncore_command(char line[]UNUSED)
453 {
454     return COMMAND_UNKNOWN;
455 }
456
457 static void oncore_wrap(void)
458 {
459     (void)delwin(Ea1win);
460     (void)delwin(Eawin);
461     (void)delwin(Bbwin);
462     (void)delwin(Enwin);
463     (void)delwin(Bowin);
464     (void)delwin(Aywin);
465     (void)delwin(Atwin);
466     (void)delwin(Aswin);
467 }
468
469 const struct monitor_object_t oncore_mmt = {
470     .initialize = oncore_initialize,
471     .update = oncore_update,
472     .command = oncore_command,
473     .wrap = oncore_wrap,
474     .min_y = 20,.min_x = 80,    /* size of the device window */
475     .driver = &oncore_binary,
476 };
477
478 #endif /* defined(ONCORE_ENABLE) && defined(BINARY_ENABLE) */