monitor_oncore.c 13 KB

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