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