monitor_oncore.c 16 KB

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