monitor_ubx.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. /*
  2. * This file is Copyright 2010 by the GPSD project
  3. * SPDX-License-Identifier: BSD-2-clause
  4. */
  5. #include "../include/gpsd_config.h" /* must be before all includes */
  6. #include <math.h>
  7. #include <stdlib.h> /* for labs() */
  8. #include <time.h>
  9. #include "../include/gpsd.h"
  10. #include "../include/bits.h"
  11. #include "../include/gpsmon.h"
  12. #ifdef UBLOX_ENABLE
  13. #include "../include/driver_ubx.h"
  14. extern const struct gps_type_t driver_ubx;
  15. static WINDOW *satwin, *navsolwin, *dopwin, *ppswin;
  16. #define display (void)mvwprintw
  17. static bool ubx_initialize(void)
  18. {
  19. int i;
  20. /* "heavily inspired" by monitor_nmea.c */
  21. if ((satwin = derwin(devicewin, 19, 28, 0, 0)) == NULL)
  22. return false;
  23. (void)wborder(satwin, 0, 0, 0, 0, 0, 0, 0, 0), (void)syncok(satwin, true);
  24. (void)wattrset(satwin, A_BOLD);
  25. display(satwin, 1, 1, "Ch PRN Az El S/N Flag U");
  26. for (i = 0; i < 16; i++)
  27. display(satwin, (int)(i + 2), 1, "%2d", i);
  28. display(satwin, 18, 7, " NAV_SVINFO ");
  29. (void)wattrset(satwin, A_NORMAL);
  30. /* "heavily inspired" by monitor_nmea.c */
  31. if ((navsolwin = derwin(devicewin, 13, 51, 0, 28)) == NULL)
  32. return false;
  33. (void)wborder(navsolwin, 0, 0, 0, 0, 0, 0, 0, 0),
  34. (void)wattrset(navsolwin, A_BOLD);
  35. (void)wmove(navsolwin, 1, 1);
  36. (void)wprintw(navsolwin, "ECEF Pos:");
  37. (void)wmove(navsolwin, 2, 1);
  38. (void)wprintw(navsolwin, "ECEF Vel:");
  39. (void)wmove(navsolwin, 4, 1);
  40. (void)wprintw(navsolwin, "LTP Pos:");
  41. (void)wmove(navsolwin, 5, 1);
  42. (void)wprintw(navsolwin, "LTP Vel:");
  43. (void)wmove(navsolwin, 7, 1);
  44. (void)wprintw(navsolwin, "Time:");
  45. (void)wmove(navsolwin, 8, 1);
  46. (void)wprintw(navsolwin, "Time GPS: Day:");
  47. (void)wmove(navsolwin, 10, 1);
  48. (void)wprintw(navsolwin, "Est Pos Err m Est Vel Err m/s");
  49. (void)wmove(navsolwin, 11, 1);
  50. (void)wprintw(navsolwin, "PRNs: ## PDOP: xx.x Fix 0x.. Flags 0x..");
  51. display(navsolwin, 12, 20, " NAV_SOL ");
  52. (void)wattrset(navsolwin, A_NORMAL);
  53. if ((dopwin = derwin(devicewin, 3, 51, 13, 28)) == NULL)
  54. return false;
  55. (void)wborder(dopwin, 0, 0, 0, 0, 0, 0, 0, 0);
  56. (void)wattrset(dopwin, A_BOLD);
  57. (void)wmove(dopwin, 1, 1);
  58. (void)wprintw(dopwin, "DOP [H] [V] [P] [T] [G]");
  59. display(dopwin, 2, 20, " NAV_DOP ");
  60. (void)wattrset(dopwin, A_NORMAL);
  61. if ((ppswin = derwin(devicewin, 3, 51, 16, 28)) == NULL)
  62. return false;
  63. (void)wborder(ppswin, 0, 0, 0, 0, 0, 0, 0, 0);
  64. (void)syncok(ppswin, true);
  65. (void)wattrset(ppswin, A_BOLD);
  66. #define TOFF_LINE 1
  67. #define TOFF_COLUMN 1
  68. (void)mvwaddstr(ppswin, TOFF_LINE, TOFF_COLUMN, "TOFF: ");
  69. (void)mvwaddstr(ppswin, TOFF_LINE, TOFF_COLUMN + 10, "N/A");
  70. #define PPS_LINE 1
  71. #define PPS_COLUMN 26
  72. (void)mvwaddstr(ppswin, PPS_LINE, PPS_COLUMN, "PPS: ");
  73. (void)mvwaddstr(ppswin, PPS_LINE, PPS_COLUMN + 10, "N/A");
  74. (void)wattrset(ppswin, A_NORMAL);
  75. return true;
  76. }
  77. static void display_nav_svinfo(unsigned char *buf, size_t data_len)
  78. {
  79. unsigned i, j, nchan;
  80. /* very coarse sanity check (minimal length for valid message reached?) */
  81. if (data_len < 8)
  82. return;
  83. nchan = getub(buf, 4);
  84. if (nchan > 16)
  85. nchan = 16;
  86. for (i = 0; i < nchan; i++) {
  87. unsigned off = 8 + 12 * i;
  88. unsigned ss, prn;
  89. int el;
  90. int az;
  91. unsigned fl;
  92. prn = getub(buf, off + 1);
  93. fl = getleu16(buf, off + 2);
  94. ss = getub(buf, off + 4);
  95. el = getsb(buf, off + 5);
  96. az = getles16(buf, off + 6);
  97. (void)wmove(satwin, (int)(i + 2), 4);
  98. (void)wprintw(satwin, "%3d %3d %3d %2d %04x %c",
  99. prn, az, el, ss, fl, (fl & UBX_SAT_USED) ? 'Y' : ' ');
  100. }
  101. /* clear potentially stale sat lines unconditionally */
  102. for (j = i; j < 16; j++) {
  103. (void)wmove(satwin, (int)(j + 2), 4);
  104. (void)wprintw(satwin, "%22s", " ");
  105. }
  106. /* update pane label, in case NAV-SAT was previously displayed */
  107. (void)wattrset(satwin, A_BOLD);
  108. display(satwin, 18, 13, "VINFO ");
  109. (void)wattrset(satwin, A_NORMAL);
  110. (void)wnoutrefresh(satwin);
  111. return;
  112. }
  113. static void display_nav_sat(unsigned char *buf, size_t data_len)
  114. {
  115. unsigned i, j, nchan;
  116. /* very coarse sanity check (minimal length for valid message reached?) */
  117. if (data_len < 8)
  118. return;
  119. nchan = getub(buf, 5);
  120. if (nchan > 16)
  121. nchan = 16;
  122. for (i = 0; i < nchan; i++) {
  123. unsigned off = 8 + 12 * i;
  124. unsigned ss, prn, gnss;
  125. int el;
  126. int az;
  127. unsigned fl;
  128. gnss = getub(buf, off);
  129. prn = getub(buf, off + 1);
  130. fl = getleu16(buf, off + 8);
  131. ss = getub(buf, off + 2);
  132. el = getsb(buf, off + 3);
  133. az = getles16(buf, off + 4);
  134. /* Translate sat numbering to the one used in UBX-NAV-SVINFO */
  135. if (gnss == 2) {
  136. prn += 210; // Galileo
  137. } else if (gnss == 3 && prn <= 5) {
  138. prn += 158; // BeiDou
  139. } else if (gnss == 3 && prn >= 6) {
  140. prn += 27; // BeiDou (continued)
  141. } else if (gnss == 4) {
  142. prn += 172; // IMES
  143. } else if (gnss == 5) {
  144. prn += 192; // QZSS
  145. } else if (gnss == 6 && prn != 255) {
  146. prn += 64; // GLONASS
  147. }
  148. (void)wmove(satwin, (int)(i + 2), 4);
  149. (void)wprintw(satwin, "%3d %3d %3d %2d %04x %c",
  150. prn, az, el, ss, fl,
  151. (fl & (UBX_SAT_USED << 3)) ? 'Y' : ' ');
  152. }
  153. /* clear potentially stale sat lines unconditionally */
  154. for (j = i; j < 16; j++) {
  155. (void)wmove(satwin, (int)(j + 2), 4);
  156. (void)wprintw(satwin, "%22s", " ");
  157. }
  158. /* redraw frame to close gap to shorter label */
  159. (void)wborder(satwin, 0, 0, 0, 0, 0, 0, 0, 0), (void)syncok(satwin, true);
  160. /* update pane label */
  161. (void)wattrset(satwin, A_BOLD);
  162. display(satwin, 18, 7, " NAV-SAT ");
  163. (void)wattrset(satwin, A_NORMAL);
  164. (void)wnoutrefresh(satwin);
  165. return;
  166. }
  167. static void display_nav_sol(unsigned char *buf, size_t data_len)
  168. {
  169. unsigned short gw = 0;
  170. unsigned int tow = 0, flags;
  171. double epx, epy, epz, evx, evy, evz;
  172. unsigned char navmode;
  173. struct gps_data_t g;
  174. if (data_len != 52)
  175. return;
  176. navmode = (unsigned char)getub(buf, 10);
  177. flags = (unsigned int)getub(buf, 11);
  178. if ((flags & (UBX_SOL_VALID_WEEK | UBX_SOL_VALID_TIME)) != 0) {
  179. tow = (unsigned int)getleu32(buf, 0);
  180. gw = (unsigned short)getles16(buf, 8);
  181. }
  182. epx = (double)(getles32(buf, 12) / 100.0);
  183. epy = (double)(getles32(buf, 16) / 100.0);
  184. epz = (double)(getles32(buf, 20) / 100.0);
  185. evx = (double)(getles32(buf, 28) / 100.0);
  186. evy = (double)(getles32(buf, 32) / 100.0);
  187. evz = (double)(getles32(buf, 36) / 100.0);
  188. (void)ecef_to_wgs84fix(&g.fix, epx, epy, epz, evx, evy, evz);
  189. /* maybe should check the ecef_to_wgs84fix() return code? */
  190. g.fix.epx = g.fix.epy = (double)(getles32(buf, 24) / 100.0);
  191. g.fix.eps = (double)(getles32(buf, 40) / 100.0);
  192. g.dop.pdop = (double)(getleu16(buf, 44) / 100.0);
  193. g.satellites_used = (int)getub(buf, 47);
  194. (void)wmove(navsolwin, 1, 11);
  195. (void)wprintw(navsolwin, "%+10.2fm %+10.2fm %+10.2fm", epx, epy, epz);
  196. (void)wmove(navsolwin, 2, 11);
  197. (void)wprintw(navsolwin, "%+9.2fm/s %+9.2fm/s %+9.2fm/s", evx, evy, evz);
  198. (void)wmove(navsolwin, 4, 11);
  199. (void)wattrset(navsolwin, A_UNDERLINE);
  200. (void)wprintw(navsolwin, "%12.9f %13.9f %8.2fm",
  201. g.fix.latitude, g.fix.longitude, g.fix.altHAE);
  202. (void)mvwaddch(navsolwin, 4, 23, ACS_DEGREE);
  203. (void)mvwaddch(navsolwin, 4, 38, ACS_DEGREE);
  204. (void)wmove(navsolwin, 5, 11);
  205. (void)wprintw(navsolwin, "%6.2fm/s %5.1fo %6.2fm/s",
  206. g.fix.speed, g.fix.track, g.fix.climb);
  207. (void)mvwaddch(navsolwin, 5, 26, ACS_DEGREE);
  208. (void)wattrset(navsolwin, A_NORMAL);
  209. (void)wmove(navsolwin, 7, 7);
  210. {
  211. unsigned int day = tow / 86400000;
  212. unsigned int tod = tow % 86400000;
  213. unsigned int h = tod / 3600000;
  214. unsigned int m = tod % 3600000;
  215. unsigned int s = m % 60000;
  216. m = (m - s) / 60000;
  217. (void)wattrset(navsolwin, A_UNDERLINE);
  218. (void)wprintw(navsolwin, "%u %02u:%02u:%05.2f",
  219. day, h, m, (double)s / 1000);
  220. (void)wattrset(navsolwin, A_NORMAL);
  221. }
  222. (void)wmove(navsolwin, 8, 11);
  223. if ((flags & (UBX_SOL_VALID_WEEK | UBX_SOL_VALID_TIME)) != 0) {
  224. (void)wprintw(navsolwin, "%d+%10.3lf", gw, (double)(tow / 1000.0));
  225. (void)wmove(navsolwin, 8, 36);
  226. (void)wprintw(navsolwin, "%d", (tow / 86400000));
  227. }
  228. /* relies on the fact that epx and epy are set to same value */
  229. (void)wmove(navsolwin, 10, 12);
  230. (void)wprintw(navsolwin, "%7.2f", g.fix.epx);
  231. (void)wmove(navsolwin, 10, 33);
  232. (void)wprintw(navsolwin, "%6.2f", g.fix.epv);
  233. (void)wmove(navsolwin, 11, 7);
  234. (void)wprintw(navsolwin, "%2d", g.satellites_used);
  235. (void)wmove(navsolwin, 11, 15);
  236. (void)wprintw(navsolwin, "%5.1f", g.dop.pdop);
  237. (void)wmove(navsolwin, 11, 25);
  238. (void)wprintw(navsolwin, "0x%02x", navmode);
  239. (void)wmove(navsolwin, 11, 36);
  240. (void)wprintw(navsolwin, "0x%02x", flags);
  241. (void)wnoutrefresh(navsolwin);
  242. }
  243. static void display_nav_dop(unsigned char *buf, size_t data_len)
  244. {
  245. if (data_len != 18)
  246. return;
  247. (void)wmove(dopwin, 1, 9);
  248. (void)wprintw(dopwin, "%4.1f", getleu16(buf, 12) / 100.0);
  249. (void)wmove(dopwin, 1, 18);
  250. (void)wprintw(dopwin, "%4.1f", getleu16(buf, 10) / 100.0);
  251. (void)wmove(dopwin, 1, 27);
  252. (void)wprintw(dopwin, "%4.1f", getleu16(buf, 6) / 100.0);
  253. (void)wmove(dopwin, 1, 36);
  254. (void)wprintw(dopwin, "%4.1f", getleu16(buf, 8) / 100.0);
  255. (void)wmove(dopwin, 1, 45);
  256. (void)wprintw(dopwin, "%4.1f", getleu16(buf, 4) / 100.0);
  257. (void)wnoutrefresh(dopwin);
  258. }
  259. static void ubx_update(void)
  260. {
  261. unsigned char *buf;
  262. size_t data_len;
  263. unsigned short msgid;
  264. buf = session.lexer.outbuffer;
  265. msgid = (unsigned short)((buf[2] << 8) | buf[3]);
  266. data_len = (size_t) getles16(buf, 4);
  267. switch (msgid) {
  268. case UBX_NAV_SVINFO:
  269. display_nav_svinfo(&buf[6], data_len);
  270. break;
  271. case UBX_NAV_SAT:
  272. display_nav_sat(&buf[6], data_len);
  273. break;
  274. case UBX_NAV_DOP:
  275. display_nav_dop(&buf[6], data_len);
  276. break;
  277. case UBX_NAV_SOL:
  278. display_nav_sol(&buf[6], data_len);
  279. break;
  280. default:
  281. break;
  282. }
  283. toff_update(ppswin, TOFF_LINE, TOFF_COLUMN + 6);
  284. pps_update(ppswin, PPS_LINE, PPS_COLUMN + 5);
  285. }
  286. static int ubx_command(char line[]UNUSED)
  287. {
  288. return COMMAND_UNKNOWN;
  289. }
  290. static void ubx_wrap(void)
  291. {
  292. (void)delwin(satwin);
  293. return;
  294. }
  295. const struct monitor_object_t ubx_mmt = {
  296. .initialize = ubx_initialize,
  297. .update = ubx_update,
  298. .command = ubx_command,
  299. .wrap = ubx_wrap,
  300. .min_y = 19,.min_x = 80, /* size of the device window */
  301. .driver = &driver_ubx,
  302. };
  303. #endif
  304. // vim: set expandtab shiftwidth=4