Devuan fork of gpsd
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

monitor_sirf.c 21 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  1. /*
  2. * SiRF 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. */
  8. #include "gpsd_config.h" /* must be before all includes */
  9. #include <stdlib.h>
  10. #include <stdbool.h>
  11. #include <string.h>
  12. #include <math.h>
  13. #include <stdlib.h> /* for labs() */
  14. #include <assert.h>
  15. #include <time.h>
  16. #include <sys/time.h>
  17. #include "gpsd.h"
  18. #include "bits.h"
  19. #include "gpsmon.h"
  20. #include "strfuncs.h"
  21. #if defined(SIRF_ENABLE) && defined(BINARY_ENABLE)
  22. extern const struct gps_type_t driver_sirf;
  23. static WINDOW *mid2win, *mid4win, *mid6win, *mid7win, *mid9win, *mid13win;
  24. static WINDOW *mid19win, *mid27win;
  25. static bool dispmode = false, subframe_enabled = false, ppstime_enabled = false;
  26. static int leapseconds;
  27. static char *verbpat[] = {
  28. "#Time:",
  29. "@R Time:",
  30. "CSTD: New almanac for",
  31. "NOTICE: DOP Q Boost",
  32. "RTC not set",
  33. "numOfSVs = 0",
  34. "rtcaj tow ",
  35. NULL
  36. };
  37. static char *dgpsvec[] = {
  38. "None",
  39. "SBAS",
  40. "Serial",
  41. "Beacon",
  42. "Software",
  43. };
  44. /* check range of an unsigned quantity */
  45. #define CHECK_RANGE(vec, i) ((i) < sizeof(vec)/sizeof(vec[0]))
  46. /*****************************************************************************
  47. *
  48. * SiRF packet-decoding routines
  49. *
  50. *****************************************************************************/
  51. #define display (void)mvwprintw
  52. #define SIRF_CHANNELS 12 /* max channels allowed in SiRF format */
  53. static bool sirf_initialize(void)
  54. {
  55. unsigned int i;
  56. mid2win = subwin(devicewin, 6, 80, 1, 0);
  57. mid4win = subwin(devicewin, SIRF_CHANNELS + 3, 30, 7, 0);
  58. mid6win = subwin(devicewin, 3, 50, 7, 30);
  59. mid7win = subwin(devicewin, 4, 50, 13, 30);
  60. mid9win = subwin(devicewin, 3, 50, 10, 30);
  61. mid13win = subwin(devicewin, 3, 50, 17, 30);
  62. mid19win = newwin(16, 50, 7, 30);
  63. mid27win = subwin(devicewin, 3, 50, 20, 30);
  64. if (mid2win == NULL || mid4win == NULL || mid6win == NULL
  65. || mid9win == NULL || mid13win == NULL || mid19win == NULL
  66. || mid27win == NULL)
  67. return false;
  68. (void)syncok(mid2win, true);
  69. (void)syncok(mid4win, true);
  70. (void)syncok(mid6win, true);
  71. (void)syncok(mid7win, true);
  72. (void)syncok(mid9win, true);
  73. (void)syncok(mid13win, true);
  74. (void)syncok(mid27win, true);
  75. (void)wborder(mid2win, 0, 0, 0, 0, 0, 0, 0, 0),
  76. (void)wattrset(mid2win, A_BOLD);
  77. (void)wmove(mid2win, 0, 1);
  78. display(mid2win, 0, 12, " X ");
  79. display(mid2win, 0, 21, " Y ");
  80. display(mid2win, 0, 30, " Z ");
  81. display(mid2win, 0, 43, " North ");
  82. display(mid2win, 0, 54, " East ");
  83. display(mid2win, 0, 65, " Alt ");
  84. (void)wmove(mid2win, 1, 1);
  85. (void)wprintw(mid2win,
  86. "Pos: m m");
  87. (void)wmove(mid2win, 2, 1);
  88. (void)wprintw(mid2win,
  89. "Vel: m/s climb m/s");
  90. (void)wmove(mid2win, 3, 1);
  91. (void)wprintw(mid2win,
  92. "Time: Leap: Heading: speed m/s");
  93. (void)wmove(mid2win, 4, 1);
  94. (void)wprintw(mid2win,
  95. "Fix: HDOP: M1: M2: ");
  96. display(mid2win, 5, 24, " Packet type 2 (0x02) ");
  97. (void)wattrset(mid2win, A_NORMAL);
  98. (void)wborder(mid4win, 0, 0, 0, 0, 0, 0, 0, 0),
  99. (void)wattrset(mid4win, A_BOLD);
  100. display(mid4win, 1, 1, "Ch PRN Az El Stat C/N ? SF");
  101. for (i = 0; i < SIRF_CHANNELS; i++) {
  102. display(mid4win, (int)(i + 2), 1, "%2d", i);
  103. }
  104. display(mid4win, 0, 1, " Measured Tracker ");
  105. display(mid4win, 14, 4, " Packet Type 4 (0x04) ");
  106. (void)wattrset(mid4win, A_NORMAL);
  107. (void)wborder(mid19win, 0, 0, 0, 0, 0, 0, 0, 0),
  108. (void)wattrset(mid19win, A_BOLD);
  109. display(mid19win, 1, 1, "Alt. hold mode:");
  110. display(mid19win, 2, 1, "Alt. hold source:");
  111. display(mid19win, 3, 1, "Alt. source input:");
  112. display(mid19win, 4, 1, "Degraded timeout:");
  113. display(mid19win, 5, 1, "DR timeout:");
  114. display(mid19win, 6, 1, "Track smooth mode:");
  115. display(mid19win, 7, 1, "Static Navigation:");
  116. display(mid19win, 8, 1, "3SV Least Squares:");
  117. display(mid19win, 9, 1, "DOP Mask mode:");
  118. display(mid19win, 10, 1, "Nav. Elev. mask:");
  119. display(mid19win, 11, 1, "Nav. Power mask:");
  120. display(mid19win, 12, 1, "DGPS Source:");
  121. display(mid19win, 13, 1, "DGPS Mode:");
  122. display(mid19win, 14, 1, "DGPS Timeout:");
  123. display(mid19win, 1, 26, "LP Push-to-Fix:");
  124. display(mid19win, 2, 26, "LP On Time:");
  125. display(mid19win, 3, 26, "LP Interval:");
  126. display(mid19win, 4, 26, "U. Tasks Enab.:");
  127. display(mid19win, 5, 26, "U. Task Inter.:");
  128. display(mid19win, 6, 26, "LP Pwr Cyc En:");
  129. display(mid19win, 7, 26, "LP Max Acq Srch:");
  130. display(mid19win, 8, 26, "LP Max Off Time:");
  131. display(mid19win, 9, 26, "APM enabled:");
  132. display(mid19win, 10, 26, "# of Fixes:");
  133. display(mid19win, 11, 26, "Time btw Fixes:");
  134. display(mid19win, 12, 26, "H/V Error Max:");
  135. display(mid19win, 13, 26, "Rsp Time Max:");
  136. display(mid19win, 14, 26, "Time/Accu:");
  137. display(mid19win, 15, 8, " Packet type 19 (0x13) ");
  138. (void)wattrset(mid19win, A_NORMAL);
  139. (void)wborder(mid6win, 0, 0, 0, 0, 0, 0, 0, 0),
  140. (void)wattrset(mid6win, A_BOLD);
  141. display(mid6win, 0, 1, " Firmware Version ");
  142. display(mid6win, 2, 8, " Packet Type 6 (0x06) ");
  143. (void)wattrset(mid6win, A_NORMAL);
  144. (void)wborder(mid7win, 0, 0, 0, 0, 0, 0, 0, 0),
  145. (void)wattrset(mid7win, A_BOLD);
  146. display(mid7win, 0, 1, " Clock Status ");
  147. display(mid7win, 1, 1, "SVs: ");
  148. display(mid7win, 1, 9, "Drift: ");
  149. display(mid7win, 1, 23, "Bias: ");
  150. display(mid7win, 2, 1, "GPS Time: ");
  151. display(mid7win, 2, 23, "PPS: ");
  152. (void)syncok(mid7win, true);
  153. (void)mvwaddstr(mid7win, 2, 40, "N/A");
  154. display(mid7win, 3, 8, " Packet type 7 (0x07) ");
  155. (void)wattrset(mid7win, A_NORMAL);
  156. (void)wborder(mid9win, 0, 0, 0, 0, 0, 0, 0, 0),
  157. (void)wattrset(mid9win, A_BOLD);
  158. display(mid9win, 0, 1, " CPU Throughput ");
  159. display(mid9win, 1, 1, "Max: ");
  160. display(mid9win, 1, 13, "Lat: ");
  161. display(mid9win, 1, 25, "Time: ");
  162. display(mid9win, 1, 39, "MS: ");
  163. display(mid9win, 2, 8, " Packet type 9 (0x09) ");
  164. (void)wattrset(mid9win, A_NORMAL);
  165. (void)wborder(mid13win, 0, 0, 0, 0, 0, 0, 0, 0),
  166. (void)wattrset(mid13win, A_BOLD);
  167. display(mid13win, 0, 1, " Visible List ");
  168. display(mid13win, 2, 8, " Packet type 13 (0x0D) ");
  169. (void)wattrset(mid13win, A_NORMAL);
  170. (void)wborder(mid27win, 0, 0, 0, 0, 0, 0, 0, 0),
  171. (void)wattrset(mid27win, A_BOLD);
  172. display(mid27win, 0, 1, " DGPS Status ");
  173. display(mid27win, 2, 8, " Packet type 27 (0x1B) ");
  174. (void)wattrset(mid27win, A_NORMAL);
  175. #ifdef CONTROLSEND_ENABLE
  176. /* probe for version */
  177. (void)monitor_control_send((unsigned char *)"\x84\x00", 2);
  178. #endif /* CONTROLSEND_ENABLE */
  179. /* initialize the GPS context's time fields */
  180. gpsd_time_init(session.context, time(NULL));
  181. return true;
  182. }
  183. static void decode_ecef(double x, double y, double z,
  184. double vx, double vy, double vz)
  185. {
  186. const double a = WGS84A;
  187. const double b = WGS84B;
  188. const double e2 = (a * a - b * b) / (a * a);
  189. const double e_2 = (a * a - b * b) / (b * b);
  190. double lambda, p, theta, phi, n, h, vnorth, veast, vup, speed, heading;
  191. lambda = atan2(y, x);
  192. p = sqrt(pow(x, 2) + pow(y, 2));
  193. theta = atan2(z * a, p * b);
  194. phi =
  195. atan2(z + e_2 * b * pow(sin(theta), 3),
  196. p - e2 * a * pow(cos(theta), 3));
  197. n = a / sqrt(1.0 - e2 * pow(sin(phi), 2));
  198. h = p / cos(phi) - n;
  199. h -= wgs84_separation((double)(RAD_2_DEG * phi),
  200. (double)(RAD_2_DEG * lambda));
  201. vnorth =
  202. -vx * sin(phi) * cos(lambda) - vy * sin(phi) * sin(lambda) +
  203. vz * cos(phi);
  204. veast = -vx * sin(lambda) + vy * cos(lambda);
  205. vup =
  206. vx * cos(phi) * cos(lambda) + vy * cos(phi) * sin(lambda) +
  207. vz * sin(phi);
  208. speed = sqrt(pow(vnorth, 2) + pow(veast, 2));
  209. heading = atan2(veast, vnorth);
  210. if (heading < 0)
  211. heading += 2 * GPS_PI;
  212. /* North and East position fields */
  213. (void)wattrset(mid2win, A_UNDERLINE);
  214. (void)wmove(mid2win, 1, 40);
  215. (void)wprintw(mid2win, "%9.5f %9.5f %9d",
  216. (double)(RAD_2_DEG * phi),
  217. (double)(RAD_2_DEG * lambda),
  218. (int)h);
  219. (void)mvwaddch(mid2win, 1, 49, ACS_DEGREE);
  220. (void)mvwaddch(mid2win, 1, 59, ACS_DEGREE);
  221. /* North and East velocity fields */
  222. (void)wmove(mid2win, 2, 40);
  223. (void)wprintw(mid2win, "%9.1f %9.1f %9.1f", vnorth, veast, vup);
  224. /* heading and speed fields */
  225. (void)wmove(mid2win, 3, 54);
  226. (void)wprintw(mid2win, "%5.1f %9.1f", (double)(RAD_2_DEG * heading), speed);
  227. (void)mvwaddch(mid2win, 3, 59, ACS_DEGREE);
  228. (void)wattrset(mid2win, A_NORMAL);
  229. }
  230. static void sirf_update(void)
  231. {
  232. int i, j, ch, sv;
  233. unsigned char *buf;
  234. size_t len;
  235. uint8_t dgps;
  236. char tbuf[JSON_DATE_MAX+1];
  237. buf = session.lexer.outbuffer + 4;
  238. len = session.lexer.outbuflen - 8;
  239. switch (buf[0]) {
  240. case 0x02: /* Measured Navigation Data */
  241. (void)wmove(mid2win, 1, 6); /* ECEF position */
  242. (void)wprintw(mid2win, "%8d %8d %8d", getbes32(buf, 1),
  243. getbes32(buf, 5), getbes32(buf, 9));
  244. (void)wmove(mid2win, 2, 6); /* ECEF velocity */
  245. (void)wprintw(mid2win, "%8.1f %8.1f %8.1f",
  246. (double)getbes16(buf, 13) / 8, (double)getbes16(buf,
  247. 15) / 8,
  248. (double)getbes16(buf, 17) / 8);
  249. decode_ecef((double)getbes32(buf, 1), (double)getbes32(buf, 5),
  250. (double)getbes32(buf, 9), (double)getbes16(buf, 13) / 8,
  251. (double)getbes16(buf, 15) / 8, (double)getbes16(buf,
  252. 17) / 8);
  253. /* line 3 */
  254. (void)wmove(mid2win, 3, 7);
  255. if (0 < session.gpsdata.fix.time.tv_sec) {
  256. (void)wprintw(mid2win, "%-24s",
  257. timespec_to_iso8601(session.gpsdata.fix.time, tbuf,
  258. sizeof(tbuf)));
  259. }
  260. (void)wmove(mid2win, 3, 38);
  261. (void)wattrset(mid2win, A_UNDERLINE);
  262. if (ppstime_enabled)
  263. (void)wprintw(mid2win, "%02d", leapseconds);
  264. else
  265. (void)wprintw(mid2win, "??");
  266. (void)wattrset(mid2win, A_NORMAL);
  267. /* line 4 */
  268. /* HDOP */
  269. (void)wmove(mid2win, 4, 59);
  270. (void)wprintw(mid2win, "%4.1f", (double)getub(buf, 20) / 5);
  271. /* Mode 1 */
  272. (void)wmove(mid2win, 4, 69);
  273. (void)wprintw(mid2win, "%02x", getub(buf, 19));
  274. /* Mode 2 */
  275. (void)wmove(mid2win, 4, 77);
  276. (void)wprintw(mid2win, "%02x", getub(buf, 21));
  277. /* SVs in fix */
  278. (void)wmove(mid2win, 4, 6);
  279. (void)wprintw(mid2win, "%2d = ",
  280. (int)getub(buf, 28));
  281. /* SV list */
  282. (void)wmove(mid2win, 4, 10);
  283. /* coverity_submit[tainted_data] */
  284. for (i = 0; i < (int)getub(buf, 28); i++)
  285. (void)wprintw(mid2win, " %2d", (int)getub(buf, 29 + i));
  286. monitor_log("MND 0x02=");
  287. break;
  288. case 0x04: /* Measured Tracking Data */
  289. ch = (int)getub(buf, 7);
  290. for (i = 0; i < ch; i++) {
  291. int az, el, state, off;
  292. double cn;
  293. off = 8 + 15 * i;
  294. (void)wmove(mid4win, i + 2, 3);
  295. sv = (int)getub(buf, off);
  296. az = (int)getub(buf, off + 1) * 3 / 2;
  297. el = (int)getub(buf, off + 2) / 2;
  298. state = (int)getbeu16(buf, off + 3);
  299. cn = 0;
  300. for (j = 0; j < 10; j++)
  301. cn += (int)getub(buf, off + 5 + j);
  302. cn /= 10;
  303. (void)wprintw(mid4win, " %3d %3d %2d %04x %4.1f %c",
  304. sv, az, el, state, cn, state == 0xbf ? 'T' : ' ');
  305. }
  306. monitor_log("MTD 0x04=");
  307. break;
  308. #ifdef __UNUSED__
  309. case 0x05: /* raw track data */
  310. for (off = 1; off < len; off += 51) {
  311. ch = getbeu32(buf, off);
  312. (void)wmove(mid4win, ch + 2, 19);
  313. cn = 0;
  314. for (j = 0; j < 10; j++)
  315. cn += getub(buf, off + 34 + j);
  316. printw("%5.1f", (double)cn / 10);
  317. printw("%9d%3d%5d", getbeu32(buf, off + 8),
  318. (int)getbeu16(buf, off + 12), (int)getbeu16(buf, off + 14));
  319. printw("%8.5f %10.5f", (double)getbeu32(buf, off + 16) / 65536,
  320. (double)getbeu32(buf, off + 20) / 1024);
  321. }
  322. monitor_log("RTD 0x05=");
  323. break;
  324. #endif /* __UNUSED */
  325. case 0x06: /* firmware version */
  326. display(mid6win, 1, 1, "%s", buf + 1);
  327. monitor_log("FV 0x06=");
  328. break;
  329. case 0x07: /* Response - Clock Status Data */
  330. display(mid7win, 1, 5, "%2d", getub(buf, 7)); /* SVs */
  331. /* Clock ppstimes */
  332. display(mid7win, 1, 16, "%lu", (unsigned long)getbeu32(buf, 8));
  333. display(mid7win, 1, 29, "%lu", (unsigned long)getbeu32(buf, 12));
  334. /* Clock Bias */
  335. display(mid7win, 2, 11, "%lu", (unsigned long)getbeu32(buf, 16));
  336. /* Estimated Time */
  337. monitor_log("CSD 0x07=");
  338. break;
  339. case 0x08: /* 50 BPS data */
  340. ch = (int)getub(buf, 1);
  341. sv = (int)getub(buf, 2);
  342. display(mid4win, ch + 2, 27, "%2d", sv);
  343. subframe_enabled = true;
  344. monitor_log("50B 0x08=");
  345. break;
  346. case 0x09: /* Throughput */
  347. display(mid9win, 1, 6, "%.3f", (double)getbeu16(buf, 1) / 186); /*SegStatMax */
  348. display(mid9win, 1, 18, "%.3f", (double)getbeu16(buf, 3) / 186); /*SegStatLat */
  349. display(mid9win, 1, 31, "%.3f", (double)getbeu16(buf, 5) / 186); /*SegStatTime */
  350. display(mid9win, 1, 42, "%3d", (int)getbeu16(buf, 7)); /* Last Millisecond */
  351. monitor_log("THR 0x09=");
  352. break;
  353. case 0x0b: /* Command Acknowledgement */
  354. monitor_log("ACK 0x0b=");
  355. break;
  356. case 0x0c: /* Command NAcknowledgement */
  357. monitor_log("NAK 0x0c=");
  358. break;
  359. case 0x0d: /* Visible List */
  360. display(mid13win, 1, 1, "%02d = ",
  361. getub(buf, 1));
  362. (void)wmove(mid13win, 1, 5);
  363. for (i = 0; i < (int)getub(buf, 1); i++)
  364. (void)wprintw(mid13win, " %d", getub(buf, 2 + 5 * i));
  365. monitor_log("VL 0x0d=");
  366. break;
  367. case 0x13:
  368. #define YESNO(n) (((int)getub(buf, n) != 0)?'Y':'N')
  369. display(mid19win, 1, 20, "%d", getub(buf, 5)); /* Alt. hold mode */
  370. display(mid19win, 2, 20, "%d", getub(buf, 6)); /* Alt. hold source */
  371. display(mid19win, 3, 20, "%dm", (int)getbeu16(buf, 7)); /* Alt. source input */
  372. if (getub(buf, 9) != (uint8_t) '\0')
  373. display(mid19win, 4, 20, "%dsec", getub(buf, 10)); /* Degraded timeout */
  374. else
  375. display(mid19win, 4, 20, "N/A ");
  376. display(mid19win, 5, 20, "%dsec", getub(buf, 11)); /* DR timeout */
  377. display(mid19win, 6, 20, "%c", YESNO(12)); /* Track smooth mode */
  378. display(mid19win, 7, 20, "%c", YESNO(13)); /* Static Nav. */
  379. display(mid19win, 8, 20, "0x%x", getub(buf, 14)); /* 3SV Least Squares */
  380. display(mid19win, 9, 20, "0x%x", getub(buf, 19)); /* DOP Mask mode */
  381. display(mid19win, 10, 20, "0x%x", (int)getbeu16(buf, 20)); /* Nav. Elev. mask */
  382. display(mid19win, 11, 20, "0x%x", getub(buf, 22)); /* Nav. Power mask */
  383. display(mid19win, 12, 20, "0x%x", getub(buf, 27)); /* DGPS Source */
  384. display(mid19win, 13, 20, "0x%x", getub(buf, 28)); /* DGPS Mode */
  385. display(mid19win, 14, 20, "%dsec", getub(buf, 29)); /* DGPS Timeout */
  386. display(mid19win, 1, 42, "%c", YESNO(34)); /* LP Push-to-Fix */
  387. display(mid19win, 2, 42, "%dms", getbeu32(buf, 35)); /* LP On Time */
  388. display(mid19win, 3, 42, "%d", getbeu32(buf, 39)); /* LP Interval */
  389. display(mid19win, 4, 42, "%c", YESNO(43)); /* User Tasks enabled */
  390. display(mid19win, 5, 42, "%d", getbeu32(buf, 44)); /* User Task Interval */
  391. display(mid19win, 6, 42, "%c", YESNO(48)); /* LP Power Cycling Enabled */
  392. display(mid19win, 7, 42, "%d", getbeu32(buf, 49)); /* LP Max Acq Search Time */
  393. display(mid19win, 8, 42, "%d", getbeu32(buf, 53)); /* LP Max Off Time */
  394. display(mid19win, 9, 42, "%c", YESNO(57)); /* APM Enabled */
  395. display(mid19win, 10, 42, "%d", (int)getbeu16(buf, 58)); /* # of fixes */
  396. display(mid19win, 11, 42, "%d", (int)getbeu16(buf, 60)); /* Time Between fixes */
  397. display(mid19win, 12, 42, "%d", getub(buf, 62)); /* H/V Error Max */
  398. display(mid19win, 13, 42, "%d", getub(buf, 63)); /* Response Time Max */
  399. display(mid19win, 14, 42, "%d", getub(buf, 64)); /* Time/Accu & Duty Cycle Priority */
  400. #undef YESNO
  401. monitor_log("NP 0x13=");
  402. break;
  403. case 0x1b:
  404. /******************************************************************
  405. Not actually documented in any published materials before the
  406. 1.6 version of the SiRF binary protocol manual.
  407. Here is what Chris Kuethe got from the SiRF folks,
  408. (plus some corrections from the GpsPaSsion forums):
  409. Start of message
  410. ----------------
  411. Message ID 1 byte 27
  412. Correction Source 1 byte 0=None, 1=SBAS, 2=Serial, 3=Beacon,
  413. 4=Software
  414. total: 2 bytes
  415. Middle part of message varies if using beacon or other:
  416. -------------------------------------------------------
  417. If Beacon:
  418. Receiver Freq Hz 4 bytes
  419. Bit rate BPS 1 byte
  420. Status bit map 1 byte 01=Signal Valid,
  421. 02=Auto frequency detect
  422. 04=Auto bit rate detect
  423. Signal Magnitude 4 bytes Note: in internal units
  424. Signal Strength dB 2 bytes derived from Signal Magnitude
  425. SNR dB 2 bytes
  426. total: 14 bytes
  427. If Not Beacon:
  428. Correction Age[12] 1 byte x 12 Age in seconds in same order as follows
  429. Reserved 2 bytes
  430. total: 14 bytes
  431. End of Message
  432. --------------
  433. Repeated 12 times (pad with 0 if less than 12 SV corrections):
  434. SVID 1 byte
  435. Correction (cm) 2 bytes (signed short)
  436. total 3 x 12 = 36 bytes
  437. ******************************************************************/
  438. dgps = getub(buf, 1);
  439. display(mid27win, 1, 1, "%8s = ",
  440. (CHECK_RANGE(dgpsvec, dgps) ? dgpsvec[dgps] : "???"));
  441. (void)wmove(mid27win, 1, 11);
  442. for (ch = 0; ch < SIRF_CHANNELS; ch++)
  443. if (getub(buf, 16 + 3 * ch) != '\0')
  444. (void)wprintw(mid27win, " %d", getub(buf, 16 + 3 * ch));
  445. monitor_log("DST 0x1b=");
  446. break;
  447. case 0x1c: /* NL Measurement Data */
  448. case 0x1d: /* NL DGPS Data */
  449. case 0x1e: /* NL SV State Data */
  450. case 0x1f: /* NL Initialized Data */
  451. subframe_enabled = true;
  452. monitor_log("NL 0x%02x=", buf[0]);
  453. break;
  454. case 0x29: /* Geodetic Navigation Data */
  455. monitor_log("GND 0x29=");
  456. break;
  457. case 0x32: /* SBAS Parameters */
  458. monitor_log("SBP 0x32=");
  459. break;
  460. case 0x34: /* PPS Time */
  461. ppstime_enabled = true;
  462. leapseconds = (int)getbeu16(buf, 8);
  463. monitor_log("PPS 0x34=");
  464. break;
  465. case 0xff: /* Development Data */
  466. while (len > 0 && buf[len - 1] == '\n')
  467. len--;
  468. while (len > 0 && buf[len - 1] == ' ')
  469. len--;
  470. buf[len] = '\0';
  471. j = 1;
  472. for (i = 0; verbpat[i] != NULL; i++)
  473. if (str_starts_with((char *)(buf + 1), verbpat[i])) {
  474. j = 0;
  475. break;
  476. }
  477. if (j != 0)
  478. monitor_log("%s\n", buf + 1);
  479. monitor_log("DD 0xff=");
  480. break;
  481. default:
  482. monitor_log("UNK 0x%02x=", buf[0]);
  483. break;
  484. }
  485. #ifdef CONTROLSEND_ENABLE
  486. /* elicit navigation parameters */
  487. if (dispmode && (time(NULL) % 10 == 0)) {
  488. (void)monitor_control_send((unsigned char *)"\x98\x00", 2);
  489. }
  490. #endif /* CONTROLSEND_ENABLE */
  491. /* clear the 50bps data field every 6 seconds */
  492. if (subframe_enabled && (time(NULL) % 6 == 0)) {
  493. for (ch = 0; ch < SIRF_CHANNELS; ch++)
  494. display(mid4win, ch + 2, 27, " ");
  495. }
  496. if (dispmode) {
  497. (void)touchwin(mid19win);
  498. (void)wnoutrefresh(mid19win);
  499. }
  500. pps_update(mid7win, 2, 32);
  501. }
  502. #ifdef CONTROLSEND_ENABLE
  503. static int sirf_command(char line[])
  504. {
  505. unsigned char buf[BUFSIZ];
  506. int v;
  507. switch (line[0]) {
  508. case 'A': /* toggle 50bps subframe data */
  509. (void)memset(buf, '\0', sizeof(buf));
  510. putbyte(buf, 0, 0x80);
  511. putbyte(buf, 23, 0x0c);
  512. putbyte(buf, 24, subframe_enabled ? 0x00 : 0x10);
  513. (void)monitor_control_send(buf, 25);
  514. /*
  515. * The subframe_enabled off because we're counting on receipt of
  516. * a subframe packet to turn it on if the command succeeds.
  517. */
  518. subframe_enabled = false;
  519. return COMMAND_MATCH;
  520. case 'M': /* static navigation */
  521. putbyte(buf, 0, 0x8f); /* id */
  522. putbyte(buf, 1, atoi(line + 1));
  523. (void)monitor_control_send(buf, 2);
  524. return COMMAND_MATCH;
  525. case 'D': /* MID 4 rate change (undocumented) */
  526. v = atoi(line + 1);
  527. if (v > 30)
  528. return COMMAND_MATCH;
  529. putbyte(buf, 0, 0xa6);
  530. putbyte(buf, 1, 0);
  531. putbyte(buf, 2, 4); /* satellite picture */
  532. putbyte(buf, 3, v);
  533. putbyte(buf, 4, 0);
  534. putbyte(buf, 5, 0);
  535. putbyte(buf, 6, 0);
  536. putbyte(buf, 7, 0);
  537. (void)monitor_control_send(buf, 8);
  538. return COMMAND_MATCH;
  539. case 'P': /* poll navigation params */
  540. dispmode = !dispmode;
  541. if (dispmode) {
  542. (void)syncok(mid6win, false);
  543. (void)syncok(mid7win, false);
  544. (void)syncok(mid9win, false);
  545. (void)syncok(mid13win, false);
  546. (void)syncok(mid27win, false);
  547. } else {
  548. (void)syncok(mid6win, true);
  549. (void)wsyncup(mid6win);
  550. (void)syncok(mid7win, true);
  551. (void)wsyncup(mid7win);
  552. (void)syncok(mid9win, true);
  553. (void)wsyncup(mid9win);
  554. (void)syncok(mid13win, true);
  555. (void)wsyncup(mid13win);
  556. (void)syncok(mid27win, true);
  557. (void)wsyncup(mid27win);
  558. }
  559. return COMMAND_MATCH;
  560. }
  561. return COMMAND_UNKNOWN; /* no match */
  562. }
  563. #endif /* CONTROLSEND_ENABLE */
  564. static void sirf_wrap(void)
  565. {
  566. (void)delwin(mid2win);
  567. (void)delwin(mid4win);
  568. (void)delwin(mid6win);
  569. (void)delwin(mid7win);
  570. (void)delwin(mid9win);
  571. (void)delwin(mid13win);
  572. (void)delwin(mid19win);
  573. (void)delwin(mid27win);
  574. }
  575. const struct monitor_object_t sirf_mmt = {
  576. .initialize = sirf_initialize,
  577. .update = sirf_update,
  578. #ifdef CONTROLSEND_ENABLE
  579. .command = sirf_command,
  580. #else
  581. .command = NULL,
  582. #endif /* CONTROLSEND_ENABLE */
  583. .wrap = sirf_wrap,
  584. .min_y = 22,.min_x = 80,
  585. .driver = &driver_sirf,
  586. };
  587. #endif /* defined(SIRF_ENABLE) && defined(BINARY_ENABLE) */
  588. /* sirfmon.c ends here */