/contrib/ntp/ntpd/refclock_ripencc.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 4866 lines · 3751 code · 591 blank · 524 comment · 411 complexity · 262eb696cb696d14c100f9b876355fbe MD5 · raw file

Large files are truncated click here to view the full file

  1. /*
  2. * $Id: refclock_ripencc.c,v 1.13 2002/06/18 14:20:55 marks Exp marks $
  3. *
  4. * Copyright (c) 2002 RIPE NCC
  5. *
  6. * All Rights Reserved
  7. *
  8. * Permission to use, copy, modify, and distribute this software and its
  9. * documentation for any purpose and without fee is hereby granted,
  10. * provided that the above copyright notice appear in all copies and that
  11. * both that copyright notice and this permission notice appear in
  12. * supporting documentation, and that the name of the author not be
  13. * used in advertising or publicity pertaining to distribution of the
  14. * software without specific, written prior permission.
  15. *
  16. * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  17. * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  18. * AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  19. * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  20. * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  21. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22. *
  23. *
  24. *
  25. * This driver was developed for use with the RIPE NCC TTM project.
  26. *
  27. *
  28. * The initial driver was developed by Daniel Karrenberg <dfk@ripe.net>
  29. * using the code made available by Trimble. This was for xntpd-3.x.x
  30. *
  31. * Rewrite of the driver for ntpd-4.x.x by Mark Santcroos <marks@ripe.net>
  32. *
  33. */
  34. #ifdef HAVE_CONFIG_H
  35. #include <config.h>
  36. #endif /* HAVE_CONFIG_H */
  37. #if defined(REFCLOCK) && defined(CLOCK_RIPENCC)
  38. #include "ntp_stdlib.h"
  39. #include "ntpd.h"
  40. #include "ntp_refclock.h"
  41. #include "ntp_unixtime.h"
  42. #include "ntp_io.h"
  43. #ifdef HAVE_PPSAPI
  44. # include "ppsapi_timepps.h"
  45. #endif
  46. /*
  47. * Definitions
  48. */
  49. /* we are on little endian */
  50. #define BYTESWAP
  51. /*
  52. * DEBUG statements: uncomment if necessary
  53. */
  54. /* #define DEBUG_NCC */ /* general debug statements */
  55. /* #define DEBUG_PPS */ /* debug pps */
  56. /* #define DEBUG_RAW */ /* print raw packets */
  57. #define TRIMBLE_OUTPUT_FUNC
  58. #define TSIP_VERNUM "7.12a"
  59. #ifndef FALSE
  60. #define FALSE (0)
  61. #define TRUE (!FALSE)
  62. #endif /* FALSE */
  63. #define GPS_PI (3.1415926535898)
  64. #define GPS_C (299792458.)
  65. #define D2R (GPS_PI/180.0)
  66. #define R2D (180.0/GPS_PI)
  67. #define WEEK (604800.)
  68. #define MAXCHAN (8)
  69. /* control characters for TSIP packets */
  70. #define DLE (0x10)
  71. #define ETX (0x03)
  72. #define MAX_RPTBUF (256)
  73. /* values of TSIPPKT.status */
  74. #define TSIP_PARSED_EMPTY 0
  75. #define TSIP_PARSED_FULL 1
  76. #define TSIP_PARSED_DLE_1 2
  77. #define TSIP_PARSED_DATA 3
  78. #define TSIP_PARSED_DLE_2 4
  79. #define UTCF_UTC_AVAIL (unsigned char) (1) /* UTC available */
  80. #define UTCF_LEAP_SCHD (unsigned char) (1<<4) /* Leap scheduled */
  81. #define UTCF_LEAP_PNDG (unsigned char) (1<<5) /* Leap pending, will occur at end of day */
  82. #define DEVICE "/dev/gps%d" /* name of radio device */
  83. #define PRECISION (-9) /* precision assumed (about 2 ms) */
  84. #define PPS_PRECISION (-20) /* precision assumed (about 1 us) */
  85. #define REFID "GPS\0" /* reference id */
  86. #define REFID_LEN 4
  87. #define DESCRIPTION "RIPE NCC GPS (Palisade)" /* Description */
  88. #define SPEED232 B9600 /* 9600 baud */
  89. #define NSAMPLES 3 /* stages of median filter */
  90. /* Structures */
  91. /* TSIP packets have the following structure, whether report or command. */
  92. typedef struct {
  93. short
  94. counter, /* counter */
  95. len; /* size of buf; < MAX_RPTBUF unsigned chars */
  96. unsigned char
  97. status, /* TSIP packet format/parse status */
  98. code, /* TSIP code */
  99. buf[MAX_RPTBUF];/* report or command string */
  100. } TSIPPKT;
  101. /* TSIP binary data structures */
  102. typedef struct {
  103. unsigned char
  104. t_oa_raw, SV_health;
  105. float
  106. e, t_oa, i_0, OMEGADOT, sqrt_A,
  107. OMEGA_0, omega, M_0, a_f0, a_f1,
  108. Axis, n, OMEGA_n, ODOT_n, t_zc;
  109. short
  110. weeknum, wn_oa;
  111. } ALM_INFO;
  112. typedef struct { /* Almanac health page (25) parameters */
  113. unsigned char
  114. WN_a, SV_health[32], t_oa;
  115. } ALH_PARMS;
  116. typedef struct { /* Universal Coordinated Time (UTC) parms */
  117. double
  118. A_0;
  119. float
  120. A_1;
  121. short
  122. delta_t_LS;
  123. float
  124. t_ot;
  125. short
  126. WN_t, WN_LSF, DN, delta_t_LSF;
  127. } UTC_INFO;
  128. typedef struct { /* Ionospheric info (float) */
  129. float
  130. alpha_0, alpha_1, alpha_2, alpha_3,
  131. beta_0, beta_1, beta_2, beta_3;
  132. } ION_INFO;
  133. typedef struct { /* Subframe 1 info (float) */
  134. short
  135. weeknum;
  136. unsigned char
  137. codeL2, L2Pdata, SVacc_raw, SV_health;
  138. short
  139. IODC;
  140. float
  141. T_GD, t_oc, a_f2, a_f1, a_f0, SVacc;
  142. } EPHEM_CLOCK;
  143. typedef struct { /* Ephemeris info (float) */
  144. unsigned char
  145. IODE, fit_interval;
  146. float
  147. C_rs, delta_n;
  148. double
  149. M_0;
  150. float
  151. C_uc;
  152. double
  153. e;
  154. float
  155. C_us;
  156. double
  157. sqrt_A;
  158. float
  159. t_oe, C_ic;
  160. double
  161. OMEGA_0;
  162. float
  163. C_is;
  164. double
  165. i_0;
  166. float
  167. C_rc;
  168. double
  169. omega;
  170. float
  171. OMEGADOT, IDOT;
  172. double
  173. Axis, n, r1me2, OMEGA_n, ODOT_n;
  174. } EPHEM_ORBIT;
  175. typedef struct { /* Navigation data structure */
  176. short
  177. sv_number; /* SV number (0 = no entry) */
  178. float
  179. t_ephem; /* time of ephemeris collection */
  180. EPHEM_CLOCK
  181. ephclk; /* subframe 1 data */
  182. EPHEM_ORBIT
  183. ephorb; /* ephemeris data */
  184. } NAV_INFO;
  185. typedef struct {
  186. unsigned char
  187. bSubcode,
  188. operating_mode,
  189. dgps_mode,
  190. dyn_code,
  191. trackmode;
  192. float
  193. elev_mask,
  194. cno_mask,
  195. dop_mask,
  196. dop_switch;
  197. unsigned char
  198. dgps_age_limit;
  199. } TSIP_RCVR_CFG;
  200. #ifdef TRIMBLE_OUTPUT_FUNC
  201. static char
  202. *dayname[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"},
  203. old_baudnum[] = {0, 1, 4, 5, 6, 8, 9, 11, 28, 12},
  204. *st_baud_text_app [] = {"", "", " 300", " 600", " 1200", " 2400",
  205. " 4800", " 9600", "19200", "38400"},
  206. *old_parity_text[] = {"EVEN", "ODD", "", "", "NONE"},
  207. *parity_text [] = {"NONE", "ODD", "EVEN"},
  208. *old_input_ch[] = { "TSIP", "RTCM (6 of 8 bits)"},
  209. *old_output_ch[] = { "TSIP", "No output", "", "", "", "NMEA 0183"},
  210. *protocols_in_text[] = { "", "TSIP", "", ""},
  211. *protocols_out_text[] = { "", "TSIP", "NMEA"},
  212. *rcvr_port_text [] = { "Port A ", "Port B ", "Current Port"},
  213. *dyn_text [] = {"Unchanged", "Land", "Sea", "Air", "Static"},
  214. *NavModeText0xBB[] = {"automatic", "time only (0-D)", "", "2-D",
  215. "3-D", "", "", "OverDetermined Time"},
  216. *PPSTimeBaseText[] = {"GPS", "UTC", "USER"},
  217. *PPSPolarityText[] = {"Positive", "Negative"},
  218. *MaskText[] = { "Almanac ", "Ephemeris", "UTC ", "Iono ",
  219. "GPS Msg ", "Alm Hlth ", "Time Fix ", "SV Select",
  220. "Ext Event", "Pos Fix ", "Raw Meas "};
  221. #endif /* TRIMBLE_OUTPUT_FUNC */
  222. /*
  223. * Unit control structure
  224. */
  225. struct ripencc_unit {
  226. int unit; /* unit number */
  227. int pollcnt; /* poll message counter */
  228. int polled; /* Hand in a sample? */
  229. char leapdelta; /* delta of next leap event */
  230. unsigned char utcflags; /* delta of next leap event */
  231. l_fp tstamp; /* timestamp of last poll */
  232. struct timespec ts; /* last timestamp */
  233. pps_params_t pps_params; /* pps parameters */
  234. pps_info_t pps_info; /* last pps data */
  235. pps_handle_t handle; /* pps handlebars */
  236. };
  237. /******************* PROTOYPES *****************/
  238. /* prototypes for report parsing primitives */
  239. short rpt_0x3D (TSIPPKT *rpt, unsigned char *tx_baud_index,
  240. unsigned char *rx_baud_index, unsigned char *char_format_index,
  241. unsigned char *stop_bits, unsigned char *tx_mode_index,
  242. unsigned char *rx_mode_index);
  243. short rpt_0x40 (TSIPPKT *rpt, unsigned char *sv_prn, short *week_num,
  244. float *t_zc, float *eccentricity, float *t_oa, float *i_0,
  245. float *OMEGA_dot, float *sqrt_A, float *OMEGA_0, float *omega,
  246. float *M_0);
  247. short rpt_0x41 (TSIPPKT *rpt, float *time_of_week, float *UTC_offset,
  248. short *week_num);
  249. short rpt_0x42 (TSIPPKT *rpt, float ECEF_pos[3], float *time_of_fix);
  250. short rpt_0x43 (TSIPPKT *rpt, float ECEF_vel[3], float *freq_offset,
  251. float *time_of_fix);
  252. short rpt_0x45 (TSIPPKT *rpt, unsigned char *major_nav_version,
  253. unsigned char *minor_nav_version, unsigned char *nav_day,
  254. unsigned char *nav_month, unsigned char *nav_year,
  255. unsigned char *major_dsp_version, unsigned char *minor_dsp_version,
  256. unsigned char *dsp_day, unsigned char *dsp_month,
  257. unsigned char *dsp_year);
  258. short rpt_0x46 (TSIPPKT *rpt, unsigned char *status1, unsigned char *status2);
  259. short rpt_0x47 (TSIPPKT *rpt, unsigned char *nsvs, unsigned char *sv_prn,
  260. float *snr);
  261. short rpt_0x48 (TSIPPKT *rpt, unsigned char *message);
  262. short rpt_0x49 (TSIPPKT *rpt, unsigned char *sv_health);
  263. short rpt_0x4A (TSIPPKT *rpt, float *lat, float *lon, float *alt,
  264. float *clock_bias, float *time_of_fix);
  265. short rpt_0x4A_2 (TSIPPKT *rpt, float *alt, float *dummy,
  266. unsigned char *alt_flag);
  267. short rpt_0x4B (TSIPPKT *rpt, unsigned char *machine_id,
  268. unsigned char *status3, unsigned char *status4);
  269. short rpt_0x4C (TSIPPKT *rpt, unsigned char *dyn_code, float *el_mask,
  270. float *snr_mask, float *dop_mask, float *dop_switch);
  271. short rpt_0x4D (TSIPPKT *rpt, float *osc_offset);
  272. short rpt_0x4E (TSIPPKT *rpt, unsigned char *response);
  273. short rpt_0x4F (TSIPPKT *rpt, double *a0, float *a1, float *time_of_data,
  274. short *dt_ls, short *wn_t, short *wn_lsf, short *dn, short *dt_lsf);
  275. short rpt_0x54 (TSIPPKT *rpt, float *clock_bias, float *freq_offset,
  276. float *time_of_fix);
  277. short rpt_0x55 (TSIPPKT *rpt, unsigned char *pos_code, unsigned char *vel_code,
  278. unsigned char *time_code, unsigned char *aux_code);
  279. short rpt_0x56 (TSIPPKT *rpt, float vel_ENU[3], float *freq_offset,
  280. float *time_of_fix);
  281. short rpt_0x57 (TSIPPKT *rpt, unsigned char *source_code,
  282. unsigned char *diag_code, short *week_num, float *time_of_fix);
  283. short rpt_0x58 (TSIPPKT *rpt, unsigned char *op_code, unsigned char *data_type,
  284. unsigned char *sv_prn, unsigned char *data_length,
  285. unsigned char *data_packet);
  286. short rpt_0x59 (TSIPPKT *rpt, unsigned char *code_type,
  287. unsigned char status_code[32]);
  288. short rpt_0x5A (TSIPPKT *rpt, unsigned char *sv_prn, float *sample_length,
  289. float *signal_level, float *code_phase, float *Doppler,
  290. double *time_of_fix);
  291. short rpt_0x5B (TSIPPKT *rpt, unsigned char *sv_prn, unsigned char *sv_health,
  292. unsigned char *sv_iode, unsigned char *fit_interval_flag,
  293. float *time_of_collection, float *time_of_eph, float *sv_accy);
  294. short rpt_0x5C (TSIPPKT *rpt, unsigned char *sv_prn, unsigned char *slot,
  295. unsigned char *chan, unsigned char *acq_flag, unsigned char *eph_flag,
  296. float *signal_level, float *time_of_last_msmt, float *elev,
  297. float *azim, unsigned char *old_msmt_flag,
  298. unsigned char *integer_msec_flag, unsigned char *bad_data_flag,
  299. unsigned char *data_collect_flag);
  300. short rpt_0x6D (TSIPPKT *rpt, unsigned char *manual_mode, unsigned char *nsvs,
  301. unsigned char *ndim, unsigned char sv_prn[], float *pdop,
  302. float *hdop, float *vdop, float *tdop);
  303. short rpt_0x82 (TSIPPKT *rpt, unsigned char *diff_mode);
  304. short rpt_0x83 (TSIPPKT *rpt, double ECEF_pos[3], double *clock_bias,
  305. float *time_of_fix);
  306. short rpt_0x84 (TSIPPKT *rpt, double *lat, double *lon, double *alt,
  307. double *clock_bias, float *time_of_fix);
  308. short rpt_Paly0xBB(TSIPPKT *rpt, TSIP_RCVR_CFG *TsipxBB);
  309. short rpt_0xBC (TSIPPKT *rpt, unsigned char *port_num,
  310. unsigned char *in_baud, unsigned char *out_baud,
  311. unsigned char *data_bits, unsigned char *parity,
  312. unsigned char *stop_bits, unsigned char *flow_control,
  313. unsigned char *protocols_in, unsigned char *protocols_out,
  314. unsigned char *reserved);
  315. /* prototypes for superpacket parsers */
  316. short rpt_0x8F0B (TSIPPKT *rpt, unsigned short *event, double *tow,
  317. unsigned char *date, unsigned char *month, short *year,
  318. unsigned char *dim_mode, short *utc_offset, double *bias, double *drift,
  319. float *bias_unc, float *dr_unc, double *lat, double *lon, double *alt,
  320. char sv_id[8]);
  321. short rpt_0x8F14 (TSIPPKT *rpt, short *datum_idx, double datum_coeffs[5]);
  322. short rpt_0x8F15 (TSIPPKT *rpt, short *datum_idx, double datum_coeffs[5]);
  323. short rpt_0x8F20 (TSIPPKT *rpt, unsigned char *info, double *lat,
  324. double *lon, double *alt, double vel_enu[], double *time_of_fix,
  325. short *week_num, unsigned char *nsvs, unsigned char sv_prn[],
  326. short sv_IODC[], short *datum_index);
  327. short rpt_0x8F41 (TSIPPKT *rpt, unsigned char *bSearchRange,
  328. unsigned char *bBoardOptions, unsigned long *iiSerialNumber,
  329. unsigned char *bBuildYear, unsigned char *bBuildMonth,
  330. unsigned char *bBuildDay, unsigned char *bBuildHour,
  331. float *fOscOffset, unsigned short *iTestCodeId);
  332. short rpt_0x8F42 (TSIPPKT *rpt, unsigned char *bProdOptionsPre,
  333. unsigned char *bProdNumberExt, unsigned short *iCaseSerialNumberPre,
  334. unsigned long *iiCaseSerialNumber, unsigned long *iiProdNumber,
  335. unsigned short *iPremiumOptions, unsigned short *iMachineID,
  336. unsigned short *iKey);
  337. short rpt_0x8F45 (TSIPPKT *rpt, unsigned char *bSegMask);
  338. short rpt_0x8F4A_16 (TSIPPKT *rpt, unsigned char *pps_enabled,
  339. unsigned char *pps_timebase, unsigned char *pos_polarity,
  340. double *pps_offset, float *bias_unc_threshold);
  341. short rpt_0x8F4B (TSIPPKT *rpt, unsigned long *decorr_max);
  342. short rpt_0x8F4D (TSIPPKT *rpt, unsigned long *event_mask);
  343. short rpt_0x8FA5 (TSIPPKT *rpt, unsigned char *spktmask);
  344. short rpt_0x8FAD (TSIPPKT *rpt, unsigned short *COUNT, double *FracSec,
  345. unsigned char *Hour, unsigned char *Minute, unsigned char *Second,
  346. unsigned char *Day, unsigned char *Month, unsigned short *Year,
  347. unsigned char *Status, unsigned char *Flags);
  348. /**/
  349. /* prototypes for command-encode primitives with suffix convention: */
  350. /* c = clear, s = set, q = query, e = enable, d = disable */
  351. void cmd_0x1F (TSIPPKT *cmd);
  352. void cmd_0x26 (TSIPPKT *cmd);
  353. void cmd_0x2F (TSIPPKT *cmd);
  354. void cmd_0x35s (TSIPPKT *cmd, unsigned char pos_code, unsigned char vel_code,
  355. unsigned char time_code, unsigned char opts_code);
  356. void cmd_0x3C (TSIPPKT *cmd, unsigned char sv_prn);
  357. void cmd_0x3Ds (TSIPPKT *cmd, unsigned char baud_out, unsigned char baud_inp,
  358. unsigned char char_code, unsigned char stopbitcode,
  359. unsigned char output_mode, unsigned char input_mode);
  360. void cmd_0xBBq (TSIPPKT *cmd, unsigned char subcode) ;
  361. /* prototypes 8E commands */
  362. void cmd_0x8E0Bq (TSIPPKT *cmd);
  363. void cmd_0x8E41q (TSIPPKT *cmd);
  364. void cmd_0x8E42q (TSIPPKT *cmd);
  365. void cmd_0x8E4Aq (TSIPPKT *cmd);
  366. void cmd_0x8E4As (TSIPPKT *cmd, unsigned char PPSOnOff, unsigned char TimeBase,
  367. unsigned char Polarity, double PPSOffset, float Uncertainty);
  368. void cmd_0x8E4Bq (TSIPPKT *cmd);
  369. void cmd_0x8E4Ds (TSIPPKT *cmd, unsigned long AutoOutputMask);
  370. void cmd_0x8EADq (TSIPPKT *cmd);
  371. /* header/source border XXXXXXXXXXXXXXXXXXXXXXXXXX */
  372. /* Trimble parse functions */
  373. static int parse0x8FAD P((TSIPPKT *, struct peer *));
  374. static int parse0x8F0B P((TSIPPKT *, struct peer *));
  375. #ifdef TRIMBLE_OUTPUT_FUNC
  376. static int parseany P((TSIPPKT *, struct peer *));
  377. static void TranslateTSIPReportToText P((TSIPPKT *, char *));
  378. #endif /* TRIMBLE_OUTPUT_FUNC */
  379. static int parse0x5C P((TSIPPKT *, struct peer *));
  380. static int parse0x4F P((TSIPPKT *, struct peer *));
  381. static void tsip_input_proc P((TSIPPKT *, int));
  382. /* Trimble helper functions */
  383. static void bPutFloat P((float *, unsigned char *));
  384. static void bPutDouble P((double *, unsigned char *));
  385. static void bPutULong P((unsigned long *, unsigned char *));
  386. static int print_msg_table_header P((int rptcode, char *HdrStr, int force));
  387. static char * show_time P((float time_of_week));
  388. /* RIPE NCC functions */
  389. static void ripencc_control P((int, struct refclockstat *, struct
  390. refclockstat *, struct peer *));
  391. static int ripencc_ppsapi P((struct peer *, int, int));
  392. static int ripencc_get_pps_ts P((struct ripencc_unit *, l_fp *));
  393. static int ripencc_start P((int, struct peer *));
  394. static void ripencc_shutdown P((int, struct peer *));
  395. static void ripencc_poll P((int, struct peer *));
  396. static void ripencc_send P((struct peer *, TSIPPKT spt));
  397. static void ripencc_receive P((struct recvbuf *));
  398. /* fill in reflock structure for our clock */
  399. struct refclock refclock_ripencc = {
  400. ripencc_start, /* start up driver */
  401. ripencc_shutdown, /* shut down driver */
  402. ripencc_poll, /* transmit poll message */
  403. ripencc_control, /* control function */
  404. noentry, /* initialize driver */
  405. noentry, /* debug info */
  406. NOFLAGS /* clock flags */
  407. };
  408. /*
  409. * Tables to compute the ddd of year form icky dd/mm timecode. Viva la
  410. * leap.
  411. */
  412. static int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  413. static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  414. /*
  415. * ripencc_start - open the GPS devices and initialize data for processing
  416. */
  417. static int
  418. ripencc_start(int unit, struct peer *peer)
  419. {
  420. register struct ripencc_unit *up;
  421. struct refclockproc *pp;
  422. char device[40];
  423. int fd;
  424. struct termios tio;
  425. TSIPPKT spt;
  426. /*
  427. * Open serial port
  428. */
  429. (void)snprintf(device, sizeof(device), DEVICE, unit);
  430. if (!(fd = refclock_open(device, SPEED232, LDISC_RAW)))
  431. return (0);
  432. /* from refclock_palisade.c */
  433. if (tcgetattr(fd, &tio) < 0) {
  434. msyslog(LOG_ERR, "Palisade(%d) tcgetattr(fd, &tio): %m",unit);
  435. return (0);
  436. }
  437. /*
  438. * set flags
  439. */
  440. tio.c_cflag |= (PARENB|PARODD);
  441. tio.c_iflag &= ~ICRNL;
  442. if (tcsetattr(fd, TCSANOW, &tio) == -1) {
  443. msyslog(LOG_ERR, "Palisade(%d) tcsetattr(fd, &tio): %m",unit);
  444. return (0);
  445. }
  446. /*
  447. * Allocate and initialize unit structure
  448. */
  449. if (!(up = (struct ripencc_unit *)
  450. emalloc(sizeof(struct ripencc_unit)))) {
  451. (void) close(fd);
  452. return (0);
  453. }
  454. memset((char *)up, 0, sizeof(struct ripencc_unit));
  455. pp = peer->procptr;
  456. pp->io.clock_recv = ripencc_receive;
  457. pp->io.srcclock = (caddr_t)peer;
  458. pp->io.datalen = 0;
  459. pp->io.fd = fd;
  460. if (!io_addclock(&pp->io)) {
  461. (void) close(fd);
  462. free(up);
  463. return (0);
  464. }
  465. pp->unitptr = (caddr_t)up;
  466. /*
  467. * Initialize miscellaneous variables
  468. */
  469. peer->precision = PRECISION;
  470. pp->clockdesc = DESCRIPTION;
  471. memcpy((char *)&pp->refid, REFID, REFID_LEN);
  472. up->pollcnt = 2;
  473. up->unit = unit;
  474. up->leapdelta = 0;
  475. up->utcflags = 0;
  476. /*
  477. * Initialize the Clock
  478. */
  479. /* query software versions */
  480. cmd_0x1F(&spt);
  481. ripencc_send(peer, spt);
  482. /* query receiver health */
  483. cmd_0x26(&spt);
  484. ripencc_send(peer, spt);
  485. /* query serial numbers */
  486. cmd_0x8E42q(&spt);
  487. ripencc_send(peer, spt);
  488. /* query manuf params */
  489. cmd_0x8E41q(&spt);
  490. ripencc_send(peer, spt);
  491. /* i/o opts */ /* trimble manual page A30 */
  492. cmd_0x35s(&spt,
  493. 0x1C, /* position */
  494. 0x00, /* velocity */
  495. 0x05, /* timing */
  496. 0x0a); /* auxilary */
  497. ripencc_send(peer, spt);
  498. /* turn off port A */
  499. cmd_0x3Ds (&spt,
  500. 0x0B, /* baud_out */
  501. 0x0B, /* baud_inp */
  502. 0x07, /* char_code */
  503. 0x07, /* stopbitcode */
  504. 0x01, /* output_mode */
  505. 0x00); /* input_mode */
  506. ripencc_send(peer, spt);
  507. /* set i/o options */
  508. cmd_0x8E4As (&spt,
  509. 0x01, /* PPS on */
  510. 0x01, /* Timebase UTC */
  511. 0x00, /* polarity positive */
  512. 0., /* 100 ft. cable XXX make flag */
  513. 1e-6 * GPS_C); /* turn of biasuncert. > (1us) */
  514. ripencc_send(peer,spt);
  515. /* all outomatic packet output off */
  516. cmd_0x8E4Ds(&spt,
  517. 0x00000000); /* AutoOutputMask */
  518. ripencc_send(peer, spt);
  519. cmd_0xBBq (&spt,
  520. 0x00); /* query primary configuration */
  521. ripencc_send(peer,spt);
  522. /* query PPS parameters */
  523. cmd_0x8E4Aq (&spt); /* query PPS params */
  524. ripencc_send(peer,spt);
  525. /* query survey limit */
  526. cmd_0x8E4Bq (&spt); /* query survey limit */
  527. ripencc_send(peer,spt);
  528. #ifdef DEBUG_NCC
  529. if (debug)
  530. printf("ripencc_start: success\n");
  531. #endif /* DEBUG_NCC */
  532. /*
  533. * Start the PPSAPI interface if it is there. Default to use
  534. * the assert edge and do not enable the kernel hardpps.
  535. */
  536. if (time_pps_create(fd, &up->handle) < 0) {
  537. up->handle = 0;
  538. msyslog(LOG_ERR, "refclock_ripencc: time_pps_create failed: %m");
  539. return (1);
  540. }
  541. return(ripencc_ppsapi(peer, 0, 0));
  542. }
  543. /*
  544. * ripencc_control - fudge control
  545. */
  546. static void
  547. ripencc_control(
  548. int unit, /* unit (not used) */
  549. struct refclockstat *in, /* input parameters (not used) */
  550. struct refclockstat *out, /* output parameters (not used) */
  551. struct peer *peer /* peer structure pointer */
  552. )
  553. {
  554. struct refclockproc *pp;
  555. #ifdef DEBUG_NCC
  556. msyslog(LOG_INFO,"%s()",__FUNCTION__);
  557. #endif /* DEBUG_NCC */
  558. pp = peer->procptr;
  559. ripencc_ppsapi(peer, pp->sloppyclockflag & CLK_FLAG2,
  560. pp->sloppyclockflag & CLK_FLAG3);
  561. }
  562. /*
  563. * Initialize PPSAPI
  564. */
  565. int
  566. ripencc_ppsapi(
  567. struct peer *peer, /* peer structure pointer */
  568. int enb_clear, /* clear enable */
  569. int enb_hardpps /* hardpps enable */
  570. )
  571. {
  572. struct refclockproc *pp;
  573. struct ripencc_unit *up;
  574. int capability;
  575. pp = peer->procptr;
  576. up = (struct ripencc_unit *)pp->unitptr;
  577. if (time_pps_getcap(up->handle, &capability) < 0) {
  578. msyslog(LOG_ERR,
  579. "refclock_ripencc: time_pps_getcap failed: %m");
  580. return (0);
  581. }
  582. memset(&up->pps_params, 0, sizeof(pps_params_t));
  583. if (enb_clear)
  584. up->pps_params.mode = capability & PPS_CAPTURECLEAR;
  585. else
  586. up->pps_params.mode = capability & PPS_CAPTUREASSERT;
  587. if (!up->pps_params.mode) {
  588. msyslog(LOG_ERR,
  589. "refclock_ripencc: invalid capture edge %d",
  590. !enb_clear);
  591. return (0);
  592. }
  593. up->pps_params.mode |= PPS_TSFMT_TSPEC;
  594. if (time_pps_setparams(up->handle, &up->pps_params) < 0) {
  595. msyslog(LOG_ERR,
  596. "refclock_ripencc: time_pps_setparams failed: %m");
  597. return (0);
  598. }
  599. if (enb_hardpps) {
  600. if (time_pps_kcbind(up->handle, PPS_KC_HARDPPS,
  601. up->pps_params.mode & ~PPS_TSFMT_TSPEC,
  602. PPS_TSFMT_TSPEC) < 0) {
  603. msyslog(LOG_ERR,
  604. "refclock_ripencc: time_pps_kcbind failed: %m");
  605. return (0);
  606. }
  607. pps_enable = 1;
  608. }
  609. peer->precision = PPS_PRECISION;
  610. #if DEBUG_NCC
  611. if (debug) {
  612. time_pps_getparams(up->handle, &up->pps_params);
  613. printf(
  614. "refclock_ripencc: capability 0x%x version %d mode 0x%x kern %d\n",
  615. capability, up->pps_params.api_version,
  616. up->pps_params.mode, enb_hardpps);
  617. }
  618. #endif /* DEBUG_NCC */
  619. return (1);
  620. }
  621. /*
  622. * This function is called every 64 seconds from ripencc_receive
  623. * It will fetch the pps time
  624. *
  625. * Return 0 on failure and 1 on success.
  626. */
  627. static int
  628. ripencc_get_pps_ts(
  629. struct ripencc_unit *up,
  630. l_fp *tsptr
  631. )
  632. {
  633. pps_info_t pps_info;
  634. struct timespec timeout, ts;
  635. double dtemp;
  636. l_fp tstmp;
  637. #ifdef DEBUG_PPS
  638. msyslog(LOG_INFO,"ripencc_get_pps_ts\n");
  639. #endif /* DEBUG_PPS */
  640. /*
  641. * Convert the timespec nanoseconds field to ntp l_fp units.
  642. */
  643. if (up->handle == 0)
  644. return (0);
  645. timeout.tv_sec = 0;
  646. timeout.tv_nsec = 0;
  647. memcpy(&pps_info, &up->pps_info, sizeof(pps_info_t));
  648. if (time_pps_fetch(up->handle, PPS_TSFMT_TSPEC, &up->pps_info,
  649. &timeout) < 0)
  650. return (0);
  651. if (up->pps_params.mode & PPS_CAPTUREASSERT) {
  652. if (pps_info.assert_sequence ==
  653. up->pps_info.assert_sequence)
  654. return (0);
  655. ts = up->pps_info.assert_timestamp;
  656. } else if (up->pps_params.mode & PPS_CAPTURECLEAR) {
  657. if (pps_info.clear_sequence ==
  658. up->pps_info.clear_sequence)
  659. return (0);
  660. ts = up->pps_info.clear_timestamp;
  661. } else {
  662. return (0);
  663. }
  664. if ((up->ts.tv_sec == ts.tv_sec) && (up->ts.tv_nsec == ts.tv_nsec))
  665. return (0);
  666. up->ts = ts;
  667. tstmp.l_ui = ts.tv_sec + JAN_1970;
  668. dtemp = ts.tv_nsec * FRAC / 1e9;
  669. tstmp.l_uf = (u_int32)dtemp;
  670. #ifdef DEBUG_PPS
  671. msyslog(LOG_INFO,"ts.tv_sec: %d\n",(int)ts.tv_sec);
  672. msyslog(LOG_INFO,"ts.tv_nsec: %ld\n",ts.tv_nsec);
  673. #endif /* DEBUG_PPS */
  674. *tsptr = tstmp;
  675. return (1);
  676. }
  677. /*
  678. * ripencc_shutdown - shut down a GPS clock
  679. */
  680. static void
  681. ripencc_shutdown(int unit, struct peer *peer)
  682. {
  683. register struct ripencc_unit *up;
  684. struct refclockproc *pp;
  685. pp = peer->procptr;
  686. up = (struct ripencc_unit *)pp->unitptr;
  687. if (up->handle != 0)
  688. time_pps_destroy(up->handle);
  689. io_closeclock(&pp->io);
  690. free(up);
  691. }
  692. /*
  693. * ripencc_poll - called by the transmit procedure
  694. */
  695. static void
  696. ripencc_poll(int unit, struct peer *peer)
  697. {
  698. register struct ripencc_unit *up;
  699. struct refclockproc *pp;
  700. TSIPPKT spt;
  701. #ifdef DEBUG_NCC
  702. if (debug)
  703. fprintf(stderr, "ripencc_poll(%d)\n", unit);
  704. #endif /* DEBUG_NCC */
  705. pp = peer->procptr;
  706. up = (struct ripencc_unit *)pp->unitptr;
  707. if (up->pollcnt == 0)
  708. refclock_report(peer, CEVNT_TIMEOUT);
  709. else
  710. up->pollcnt--;
  711. pp->polls++;
  712. up->polled = 1;
  713. /* poll for UTC superpacket */
  714. cmd_0x8EADq (&spt);
  715. ripencc_send(peer,spt);
  716. }
  717. /*
  718. * ripencc_send - send message to clock
  719. * use the structures being created by the trimble functions!
  720. * makes the code more readable/clean
  721. */
  722. static void
  723. ripencc_send(struct peer *peer, TSIPPKT spt)
  724. {
  725. unsigned char *ip, *op;
  726. unsigned char obuf[512];
  727. #ifdef DEBUG_RAW
  728. {
  729. register struct ripencc_unit *up;
  730. register struct refclockproc *pp;
  731. pp = peer->procptr;
  732. up = (struct ripencc_unit *)pp->unitptr;
  733. if (debug)
  734. printf("ripencc_send(%d, %02X)\n", up->unit, cmd);
  735. }
  736. #endif /* DEBUG_RAW */
  737. ip = spt.buf;
  738. op = obuf;
  739. *op++ = 0x10;
  740. *op++ = spt.code;
  741. while (spt.len--) {
  742. if (op-obuf > sizeof(obuf)-5) {
  743. msyslog(LOG_ERR, "ripencc_send obuf overflow!");
  744. refclock_report(peer, CEVNT_FAULT);
  745. return;
  746. }
  747. if (*ip == 0x10) /* byte stuffing */
  748. *op++ = 0x10;
  749. *op++ = *ip++;
  750. }
  751. *op++ = 0x10;
  752. *op++ = 0x03;
  753. #ifdef DEBUG_RAW
  754. if (debug) { /* print raw packet */
  755. unsigned char *cp;
  756. int i;
  757. printf("ripencc_send: len %d\n", op-obuf);
  758. for (i=1, cp=obuf; cp<op; i++, cp++) {
  759. printf(" %02X", *cp);
  760. if (i%10 == 0)
  761. printf("\n");
  762. }
  763. printf("\n");
  764. }
  765. #endif /* DEBUG_RAW */
  766. if (write(peer->procptr->io.fd, obuf, op-obuf) == -1) {
  767. refclock_report(peer, CEVNT_FAULT);
  768. }
  769. }
  770. /*
  771. * ripencc_receive()
  772. *
  773. * called when a packet is received on the serial port
  774. * takes care of further processing
  775. *
  776. */
  777. static void
  778. ripencc_receive(struct recvbuf *rbufp)
  779. {
  780. register struct ripencc_unit *up;
  781. register struct refclockproc *pp;
  782. struct peer *peer;
  783. static TSIPPKT rpt; /* structure for current incoming TSIP report */
  784. TSIPPKT spt; /* send packet */
  785. int ns_since_pps;
  786. int i;
  787. char *cp;
  788. /* Use these variables to hold data until we decide its worth keeping */
  789. char rd_lastcode[BMAX];
  790. l_fp rd_tmp;
  791. u_short rd_lencode;
  792. /* msyslog(LOG_INFO, "%s",__FUNCTION__); */
  793. /*
  794. * Initialize pointers and read the timecode and timestamp
  795. */
  796. peer = (struct peer *)rbufp->recv_srcclock;
  797. pp = peer->procptr;
  798. up = (struct ripencc_unit *)pp->unitptr;
  799. rd_lencode = refclock_gtlin(rbufp, rd_lastcode, BMAX, &rd_tmp);
  800. #ifdef DEBUG_RAW
  801. if (debug)
  802. fprintf(stderr, "ripencc_receive(%d)\n", up->unit);
  803. #endif /* DEBUG_RAW */
  804. #ifdef DEBUG_RAW
  805. if (debug) { /* print raw packet */
  806. int i;
  807. unsigned char *cp;
  808. printf("ripencc_receive: len %d\n", rbufp->recv_length);
  809. for (i=1, cp=(char*)&rbufp->recv_space; i <= rbufp->recv_length; i++, cp++) {
  810. printf(" %02X", *cp);
  811. if (i%10 == 0)
  812. printf("\n");
  813. }
  814. printf("\n");
  815. }
  816. #endif /* DEBUG_RAW */
  817. cp = (char*) &rbufp->recv_space;
  818. i=rbufp->recv_length;
  819. while (i--) { /* loop over received chars */
  820. tsip_input_proc(&rpt, (unsigned char) *cp++);
  821. if (rpt.status != TSIP_PARSED_FULL)
  822. continue;
  823. switch (rpt.code) {
  824. case 0x8F: /* superpacket */
  825. switch (rpt.buf[0]) {
  826. case 0xAD: /* UTC Time */
  827. /*
  828. * When polling on port B the timecode
  829. * is the time of the previous PPS.
  830. * If we completed receiving the packet
  831. * less than 150ms after the turn of the second,
  832. * it may have the code of the previous second.
  833. * We do not trust that and simply poll again
  834. * without even parsing it.
  835. *
  836. * More elegant would be to re-schedule the poll,
  837. * but I do not know (yet) how to do that cleanly.
  838. *
  839. */
  840. /* BLA ns_since_pps = ncc_tstmp(rbufp, &trtmp); */
  841. /* if (up->polled && ns_since_pps > -1 && ns_since_pps < 150) { */
  842. ns_since_pps=200;
  843. if (up->polled && ns_since_pps < 150) {
  844. msyslog(LOG_INFO, "%s(): up->polled",__FUNCTION__);
  845. ripencc_poll(up->unit, peer);
  846. break;
  847. }
  848. /*
  849. * Parse primary utc time packet
  850. * and fill refclock structure
  851. * from results.
  852. */
  853. if (parse0x8FAD(&rpt, peer) < 0) {
  854. msyslog(LOG_INFO, "%s(): parse0x8FAD < 0",__FUNCTION__);
  855. refclock_report(peer, CEVNT_BADREPLY);
  856. break;
  857. }
  858. /*
  859. * If the PPSAPI is working, rather use its
  860. * timestamps.
  861. * assume that the PPS occurs on the second
  862. * so blow any msec
  863. */
  864. if (ripencc_get_pps_ts(up, &rd_tmp) == 1) {
  865. pp->lastrec = up->tstamp = rd_tmp;
  866. pp->nsec = 0;
  867. }
  868. else
  869. msyslog(LOG_INFO, "%s(): ripencc_get_pps_ts returns failure\n",__FUNCTION__);
  870. if (!up->polled) {
  871. msyslog(LOG_INFO, "%s(): unrequested packet\n",__FUNCTION__);
  872. /* unrequested packet */
  873. break;
  874. }
  875. /* we have been polled ! */
  876. up->polled = 0;
  877. up->pollcnt = 2;
  878. /* poll for next packet */
  879. cmd_0x8E0Bq(&spt);
  880. ripencc_send(peer,spt);
  881. if (ns_since_pps < 0) { /* no PPS */
  882. msyslog(LOG_INFO, "%s(): ns_since_pps < 0",__FUNCTION__);
  883. refclock_report(peer, CEVNT_BADTIME);
  884. break;
  885. }
  886. /*
  887. * Process the new sample in the median filter and determine the
  888. * reference clock offset and dispersion.
  889. */
  890. if (!refclock_process(pp)) {
  891. msyslog(LOG_INFO, "%s(): !refclock_process",__FUNCTION__);
  892. refclock_report(peer, CEVNT_BADTIME);
  893. break;
  894. }
  895. refclock_receive(peer);
  896. break;
  897. case 0x0B: /* comprehensive time packet */
  898. parse0x8F0B(&rpt, peer);
  899. break;
  900. default: /* other superpackets */
  901. #ifdef DEBUG_NCC
  902. msyslog(LOG_INFO, "%s(): calling parseany",__FUNCTION__);
  903. #endif /* DEBUG_NCC */
  904. #ifdef TRIMBLE_OUTPUT_FUNC
  905. parseany(&rpt, peer);
  906. #endif /* TRIMBLE_OUTPUT_FUNC */
  907. break;
  908. }
  909. break;
  910. case 0x4F: /* UTC parameters, for leap info */
  911. parse0x4F(&rpt, peer);
  912. break;
  913. case 0x5C: /* sat tracking data */
  914. parse0x5C(&rpt, peer);
  915. break;
  916. default: /* other packets */
  917. #ifdef TRIMBLE_OUTPUT_FUNC
  918. parseany(&rpt, peer);
  919. #endif /* TRIMBLE_OUTPUT_FUNC */
  920. break;
  921. }
  922. rpt.status = TSIP_PARSED_EMPTY;
  923. }
  924. }
  925. /*
  926. * All trimble functions that are directly referenced from driver code
  927. * (so not from parseany)
  928. */
  929. void cmd_0x1F (TSIPPKT *cmd)
  930. /* request software versions */
  931. {
  932. cmd->len = 0;
  933. cmd->code = 0x1F;
  934. }
  935. void cmd_0x26 (TSIPPKT *cmd)
  936. /* request receiver health */
  937. {
  938. cmd->len = 0;
  939. cmd->code = 0x26;
  940. }
  941. void cmd_0x2F (TSIPPKT *cmd)
  942. /* request UTC params */
  943. {
  944. cmd->len = 0;
  945. cmd->code = 0x2F;
  946. }
  947. void cmd_0x35s (TSIPPKT *cmd, unsigned char pos_code, unsigned char vel_code,
  948. unsigned char time_code, unsigned char opts_code)
  949. /* set serial I/O options */
  950. {
  951. cmd->buf[0] = pos_code;
  952. cmd->buf[1] = vel_code;
  953. cmd->buf[2] = time_code;
  954. cmd->buf[3] = opts_code;
  955. cmd->len = 4;
  956. cmd->code = 0x35;
  957. }
  958. void cmd_0x3C (TSIPPKT *cmd, unsigned char sv_prn)
  959. /* request tracking status */
  960. {
  961. cmd->buf[0] = sv_prn;
  962. cmd->len = 1;
  963. cmd->code = 0x3C;
  964. }
  965. void cmd_0x3Ds (TSIPPKT *cmd,
  966. unsigned char baud_out, unsigned char baud_inp,
  967. unsigned char char_code, unsigned char stopbitcode,
  968. unsigned char output_mode, unsigned char input_mode)
  969. /* set Channel A configuration for dual-port operation */
  970. {
  971. cmd->buf[0] = baud_out; /* XMT baud rate */
  972. cmd->buf[1] = baud_inp; /* RCV baud rate */
  973. cmd->buf[2] = char_code; /* parity and #bits per byte */
  974. cmd->buf[3] = stopbitcode; /* number of stop bits code */
  975. cmd->buf[4] = output_mode; /* Ch. A transmission mode */
  976. cmd->buf[5] = input_mode; /* Ch. A reception mode */
  977. cmd->len = 6;
  978. cmd->code = 0x3D;
  979. }
  980. /* query primary configuration */
  981. void cmd_0xBBq (TSIPPKT *cmd,
  982. unsigned char subcode)
  983. {
  984. cmd->len = 1;
  985. cmd->code = 0xBB;
  986. cmd->buf[0] = subcode;
  987. }
  988. /**** Superpackets ****/
  989. void cmd_0x8E0Bq (TSIPPKT *cmd)
  990. /* 8E-0B to query 8F-0B controls */
  991. {
  992. cmd->len = 1;
  993. cmd->code = 0x8E;
  994. cmd->buf[0] = 0x0B;
  995. }
  996. void cmd_0x8E41q (TSIPPKT *cmd)
  997. /* 8F-41 to query board serial number */
  998. {
  999. cmd->len = 1;
  1000. cmd->code = 0x8E;
  1001. cmd->buf[0] = 0x41;
  1002. }
  1003. void cmd_0x8E42q (TSIPPKT *cmd)
  1004. /* 8F-42 to query product serial number */
  1005. {
  1006. cmd->len = 1;
  1007. cmd->code = 0x8E;
  1008. cmd->buf[0] = 0x42;
  1009. }
  1010. void cmd_0x8E4Aq (TSIPPKT *cmd)
  1011. /* 8F-4A to query PPS parameters */
  1012. {
  1013. cmd->len = 1;
  1014. cmd->code = 0x8E;
  1015. cmd->buf[0] = 0x4A;
  1016. }
  1017. /* set i/o options */
  1018. void cmd_0x8E4As (TSIPPKT *cmd,
  1019. unsigned char PPSOnOff,
  1020. unsigned char TimeBase,
  1021. unsigned char Polarity,
  1022. double PPSOffset,
  1023. float Uncertainty)
  1024. {
  1025. cmd->len = 16;
  1026. cmd->code = 0x8E;
  1027. cmd->buf[0] = 0x4A;
  1028. cmd->buf[1] = PPSOnOff;
  1029. cmd->buf[2] = TimeBase;
  1030. cmd->buf[3] = Polarity;
  1031. bPutDouble (&PPSOffset, &cmd->buf[4]);
  1032. bPutFloat (&Uncertainty, &cmd->buf[12]);
  1033. }
  1034. void cmd_0x8E4Bq (TSIPPKT *cmd)
  1035. /* 8F-4B query survey limit */
  1036. {
  1037. cmd->len = 1;
  1038. cmd->code = 0x8E;
  1039. cmd->buf[0] = 0x4B;
  1040. }
  1041. /* poll for UTC superpacket */
  1042. void cmd_0x8EADq (TSIPPKT *cmd)
  1043. /* 8E-AD to query 8F-AD controls */
  1044. {
  1045. cmd->len = 1;
  1046. cmd->code = 0x8E;
  1047. cmd->buf[0] = 0xAD;
  1048. }
  1049. /* all outomatic packet output off */
  1050. void cmd_0x8E4Ds (TSIPPKT *cmd,
  1051. unsigned long AutoOutputMask)
  1052. {
  1053. cmd->len = 5;
  1054. cmd->code = 0x8E;
  1055. cmd->buf[0] = 0x4D;
  1056. bPutULong (&AutoOutputMask, &cmd->buf[1]);
  1057. }
  1058. /* for DOS machines, reverse order of bytes as they come through the
  1059. * serial port. */
  1060. #ifdef BYTESWAP
  1061. static short bGetShort (unsigned char *bp)
  1062. {
  1063. short outval;
  1064. unsigned char *optr;
  1065. optr = (unsigned char*)&outval + 1;
  1066. *optr-- = *bp++;
  1067. *optr = *bp;
  1068. return outval;
  1069. }
  1070. #ifdef TRIMBLE_OUTPUT_FUNC
  1071. static unsigned short bGetUShort (unsigned char *bp)
  1072. {
  1073. unsigned short outval;
  1074. unsigned char *optr;
  1075. optr = (unsigned char*)&outval + 1;
  1076. *optr-- = *bp++;
  1077. *optr = *bp;
  1078. return outval;
  1079. }
  1080. static long bGetLong (unsigned char *bp)
  1081. {
  1082. long outval;
  1083. unsigned char *optr;
  1084. optr = (unsigned char*)&outval + 3;
  1085. *optr-- = *bp++;
  1086. *optr-- = *bp++;
  1087. *optr-- = *bp++;
  1088. *optr = *bp;
  1089. return outval;
  1090. }
  1091. static unsigned long bGetULong (unsigned char *bp)
  1092. {
  1093. unsigned long outval;
  1094. unsigned char *optr;
  1095. optr = (unsigned char*)&outval + 3;
  1096. *optr-- = *bp++;
  1097. *optr-- = *bp++;
  1098. *optr-- = *bp++;
  1099. *optr = *bp;
  1100. return outval;
  1101. }
  1102. #endif /* TRIMBLE_OUTPUT_FUNC */
  1103. static float bGetSingle (unsigned char *bp)
  1104. {
  1105. float outval;
  1106. unsigned char *optr;
  1107. optr = (unsigned char*)&outval + 3;
  1108. *optr-- = *bp++;
  1109. *optr-- = *bp++;
  1110. *optr-- = *bp++;
  1111. *optr = *bp;
  1112. return outval;
  1113. }
  1114. static double bGetDouble (unsigned char *bp)
  1115. {
  1116. double outval;
  1117. unsigned char *optr;
  1118. optr = (unsigned char*)&outval + 7;
  1119. *optr-- = *bp++;
  1120. *optr-- = *bp++;
  1121. *optr-- = *bp++;
  1122. *optr-- = *bp++;
  1123. *optr-- = *bp++;
  1124. *optr-- = *bp++;
  1125. *optr-- = *bp++;
  1126. *optr = *bp;
  1127. return outval;
  1128. }
  1129. #else /* not BYTESWAP */
  1130. #define bGetShort(bp) (*(short*)(bp))
  1131. #define bGetLong(bp) (*(long*)(bp))
  1132. #define bGetULong(bp) (*(unsigned long*)(bp))
  1133. #define bGetSingle(bp) (*(float*)(bp))
  1134. #define bGetDouble(bp) (*(double*)(bp))
  1135. #endif /* BYTESWAP */
  1136. /*
  1137. * Byte-reversal is necessary for little-endian (Intel-based) machines.
  1138. * TSIP streams are Big-endian (Motorola-based).
  1139. */
  1140. #ifdef BYTESWAP
  1141. void
  1142. bPutFloat (float *in, unsigned char *out)
  1143. {
  1144. unsigned char *inptr;
  1145. inptr = (unsigned char*)in + 3;
  1146. *out++ = *inptr--;
  1147. *out++ = *inptr--;
  1148. *out++ = *inptr--;
  1149. *out = *inptr;
  1150. }
  1151. static void
  1152. bPutULong (unsigned long *in, unsigned char *out)
  1153. {
  1154. unsigned char *inptr;
  1155. inptr = (unsigned char*)in + 3;
  1156. *out++ = *inptr--;
  1157. *out++ = *inptr--;
  1158. *out++ = *inptr--;
  1159. *out = *inptr;
  1160. }
  1161. static void
  1162. bPutDouble (double *in, unsigned char *out)
  1163. {
  1164. unsigned char *inptr;
  1165. inptr = (unsigned char*)in + 7;
  1166. *out++ = *inptr--;
  1167. *out++ = *inptr--;
  1168. *out++ = *inptr--;
  1169. *out++ = *inptr--;
  1170. *out++ = *inptr--;
  1171. *out++ = *inptr--;
  1172. *out++ = *inptr--;
  1173. *out = *inptr;
  1174. }
  1175. #else /* not BYTESWAP */
  1176. void bPutShort (short a, unsigned char *cmdbuf) {*(short*) cmdbuf = a;}
  1177. void bPutULong (long a, unsigned char *cmdbuf) {*(long*) cmdbuf = a;}
  1178. void bPutFloat (float a, unsigned char *cmdbuf) {*(float*) cmdbuf = a;}
  1179. void bPutDouble (double a, unsigned char *cmdbuf){*(double*) cmdbuf = a;}
  1180. #endif /* BYTESWAP */
  1181. /*
  1182. * Parse primary utc time packet
  1183. * and fill refclock structure
  1184. * from results.
  1185. *
  1186. * 0 = success
  1187. * -1 = errors
  1188. */
  1189. static int
  1190. parse0x8FAD(rpt, peer)
  1191. TSIPPKT *rpt;
  1192. struct peer *peer;
  1193. {
  1194. register struct refclockproc *pp;
  1195. register struct ripencc_unit *up;
  1196. unsigned day, month, year; /* data derived from received timecode */
  1197. unsigned hour, minute, second;
  1198. unsigned char trackstat, utcflags;
  1199. static char logbuf[1024]; /* logging string buffer */
  1200. int i;
  1201. unsigned char *buf;
  1202. buf = rpt->buf;
  1203. pp = peer->procptr;
  1204. if (rpt->len != 22)
  1205. return (-1);
  1206. if (bGetShort(&buf[1]) != 0) {
  1207. #ifdef DEBUG_NCC
  1208. if (debug)
  1209. printf("parse0x8FAD: event count != 0\n");
  1210. #endif /* DEBUG_NCC */
  1211. return(-1);
  1212. }
  1213. if (bGetDouble(&buf[3]) != 0.0) {
  1214. #ifdef DEBUG_NCC
  1215. if (debug)
  1216. printf("parse0x8FAD: fracsecs != 0\n");
  1217. #endif /* DEBUG_NCC */
  1218. return(-1);
  1219. }
  1220. hour = (unsigned int) buf[11];
  1221. minute = (unsigned int) buf[12];
  1222. second = (unsigned int) buf[13];
  1223. day = (unsigned int) buf[14];
  1224. month = (unsigned int) buf[15];
  1225. year = bGetShort(&buf[16]);
  1226. trackstat = buf[18];
  1227. utcflags = buf[19];
  1228. sprintf(logbuf, "U1 %d.%d.%d %02d:%02d:%02d %d %02x",
  1229. day, month, year, hour, minute, second, trackstat, utcflags);
  1230. #ifdef DEBUG_NCC
  1231. if (debug)
  1232. puts(logbuf);
  1233. #endif /* DEBUG_NCC */
  1234. record_clock_stats(&peer->srcadr, logbuf);
  1235. if (!utcflags & UTCF_UTC_AVAIL)
  1236. return(-1);
  1237. /* poll for UTC parameters once and then if UTC flag changed */
  1238. up = (struct ripencc_unit *) pp->unitptr;
  1239. if (utcflags != up->utcflags) {
  1240. TSIPPKT spt; /* local structure for send packet */
  1241. cmd_0x2F (&spt); /* request UTC params */
  1242. ripencc_send(peer,spt);
  1243. up->utcflags = utcflags;
  1244. }
  1245. /*
  1246. * If we hit the leap second, we choose to skip this sample
  1247. * rather than rely on other code to be perfectly correct.
  1248. * No offense, just defense ;-).
  1249. */
  1250. if (second == 60)
  1251. return(-1);
  1252. /* now check and convert the time we received */
  1253. pp->year = year;
  1254. if (month < 1 || month > 12 || day < 1 || day > 31)
  1255. return(-1);
  1256. if (pp->year % 4) {
  1257. if (day > day1tab[month - 1])
  1258. return(-1);
  1259. for (i = 0; i < month - 1; i++)
  1260. day += day1tab[i];
  1261. } else {
  1262. if (day > day2tab[month - 1])
  1263. return(-1);
  1264. for (i = 0; i < month - 1; i++)
  1265. day += day2tab[i];
  1266. }
  1267. pp->day = day;
  1268. pp->hour = hour;
  1269. pp->minute = minute;
  1270. pp-> second = second;
  1271. pp->nsec = 0;
  1272. if ((utcflags&UTCF_LEAP_PNDG) && up->leapdelta != 0)
  1273. pp-> leap = (up->leapdelta > 0 ? LEAP_ADDSECOND : LEAP_DELSECOND);
  1274. else
  1275. pp-> leap = LEAP_NOWARNING;
  1276. return (0);
  1277. }
  1278. /*
  1279. * Parse comprehensive time packet
  1280. *
  1281. * 0 = success
  1282. * -1 = errors
  1283. */
  1284. int parse0x8F0B(rpt, peer)
  1285. TSIPPKT *rpt;
  1286. struct peer *peer;
  1287. {
  1288. register struct refclockproc *pp;
  1289. unsigned day, month, year; /* data derived from received timecode */
  1290. unsigned hour, minute, second;
  1291. unsigned utcoff;
  1292. unsigned char mode;
  1293. double bias, rate;
  1294. float biasunc, rateunc;
  1295. double lat, lon, alt;
  1296. short lat_deg, lon_deg;
  1297. float lat_min, lon_min;
  1298. unsigned char north_south, east_west;
  1299. char sv[9];
  1300. static char logbuf[1024]; /* logging string buffer */
  1301. unsigned char b;
  1302. int i;
  1303. unsigned char *buf;
  1304. double tow;
  1305. buf = rpt->buf;
  1306. pp = peer->procptr;
  1307. if (rpt->len != 74)
  1308. return (-1);
  1309. if (bGetShort(&buf[1]) != 0)
  1310. return(-1);;
  1311. tow = bGetDouble(&buf[3]);
  1312. if (tow == -1.0) {
  1313. return(-1);
  1314. }
  1315. else if ((tow >= 604800.0) || (tow < 0.0)) {
  1316. return(-1);
  1317. }
  1318. else
  1319. {
  1320. if (tow < 604799.9) tow = tow + .00000001;
  1321. second = (unsigned int) fmod(tow, 60.);
  1322. minute = (unsigned int) fmod(tow/60., 60.);
  1323. hour = (unsigned int )fmod(tow / 3600., 24.);
  1324. }
  1325. day = (unsigned int) buf[11];
  1326. month = (unsigned int) buf[12];
  1327. year = bGetShort(&buf[13]);
  1328. mode = buf[15];
  1329. utcoff = bGetShort(&buf[16]);
  1330. bias = bGetDouble(&buf[18]) / GPS_C * 1e9; /* ns */
  1331. rate = bGetDouble(&buf[26]) / GPS_C * 1e9; /* ppb */
  1332. biasunc = bGetSingle(&buf[34]) / GPS_C * 1e9; /* ns */
  1333. rateunc = bGetSingle(&buf[38]) / GPS_C * 1e9; /* ppb */
  1334. lat = bGetDouble(&buf[42]) * R2D;
  1335. lon = bGetDouble(&buf[50]) * R2D;
  1336. alt = bGetDouble(&buf[58]);
  1337. if (lat < 0.0) {
  1338. north_south = 'S';
  1339. lat = -lat;
  1340. }
  1341. else {
  1342. north_south = 'N';
  1343. }
  1344. lat_deg = (short)lat;
  1345. lat_min = (lat - lat_deg) * 60.0;
  1346. if (lon < 0.0) {
  1347. east_west = 'W';
  1348. lon = -lon;
  1349. }
  1350. else {
  1351. east_west = 'E';
  1352. }
  1353. lon_deg = (short)lon;
  1354. lon_min = (lon - lon_deg) * 60.0;
  1355. for (i=0; i<8; i++) {
  1356. sv[i] = buf[i + 66];
  1357. if (sv[i]) {
  1358. TSIPPKT spt; /* local structure for sendpacket */
  1359. b = (unsigned char) (sv[i]<0 ? -sv[i] : sv[i]);
  1360. /* request tracking status */
  1361. cmd_0x3C (&spt, b);
  1362. ripencc_send(peer,spt);
  1363. }
  1364. }
  1365. sprintf(logbuf, "C1 %02d%02d%04d %02d%02d%02d %d %7.0f %.1f %.0f %.1f %d %02d%09.6f %c %02d%09.6f %c %.0f %d %d %d %d %d %d %d %d",
  1366. day, month, year, hour, minute, second, mode, bias, biasunc, rate, rateunc, utcoff,
  1367. lat_deg, lat_min, north_south, lon_deg, lon_min, east_west, alt,
  1368. sv[0], sv[1], sv[2], sv[3], sv[4], sv[5], sv[6], sv[7]);
  1369. #ifdef DEBUG_NCC
  1370. if (debug)
  1371. puts(logbuf);
  1372. #endif /* DEBUG_NCC */
  1373. record_clock_stats(&peer->srcadr, logbuf);
  1374. return (0);
  1375. }
  1376. #ifdef TRIMBLE_OUTPUT_FUNC
  1377. /*
  1378. * Parse any packet using Trimble machinery
  1379. */
  1380. int parseany(rpt, peer)
  1381. TSIPPKT *rpt;
  1382. struct peer *peer;
  1383. {
  1384. static char logbuf[1024]; /* logging string buffer */
  1385. TranslateTSIPReportToText (rpt, logbuf); /* anything else */
  1386. #ifdef DEBUG_NCC
  1387. if (debug)
  1388. puts(&logbuf[1]);
  1389. #endif /* DEBUG_NCC */
  1390. record_clock_stats(&peer->srcadr, &logbuf[1]);
  1391. return(0);
  1392. }
  1393. #endif /* TRIMBLE_OUTPUT_FUNC */
  1394. /*
  1395. * Parse UTC Parameter Packet
  1396. *
  1397. * See the IDE for documentation!
  1398. *
  1399. * 0 = success
  1400. * -1 = errors
  1401. */
  1402. int parse0x4F(rpt, peer)
  1403. TSIPPKT *rpt;
  1404. struct peer *peer;
  1405. {
  1406. register struct ripencc_unit *up;
  1407. double a0;
  1408. float a1, tot;
  1409. int dt_ls, wn_t, wn_lsf, dn, dt_lsf;
  1410. static char logbuf[1024]; /* logging string buffer */
  1411. unsigned char *buf;
  1412. buf = rpt->buf;
  1413. if (rpt->len != 26)
  1414. return (-1);
  1415. a0 = bGetDouble (buf);
  1416. a1 = bGetSingle (&buf[8]);
  1417. dt_ls = bGetShort (&buf[12]);
  1418. tot = bGetSingle (&buf[14]);
  1419. wn_t = bGetShort (&buf[18]);
  1420. wn_lsf = bGetShort (&buf[20]);
  1421. dn = bGetShort (&buf[22]);
  1422. dt_lsf = bGetShort (&buf[24]);
  1423. sprintf(logbuf, "L1 %d %d %d %g %g %g %d %d %d",
  1424. dt_lsf - dt_ls, dt_ls, dt_lsf, a0, a1, tot, wn_t, wn_lsf, dn);
  1425. #ifdef DEBUG_NCC
  1426. if (debug)
  1427. puts(logbuf);
  1428. #endif /* DEBUG_NCC */
  1429. record_clock_stats(&peer->srcadr, logbuf);
  1430. up = (struct ripencc_unit *) peer->procptr->unitptr;
  1431. up->leapdelta = dt_lsf - dt_ls;
  1432. return (0);
  1433. }
  1434. /*
  1435. * Parse Tracking Status packet
  1436. *
  1437. * 0 = success
  1438. * -1 = errors
  1439. */
  1440. int parse0x5C(rpt, peer)
  1441. TSIPPKT *rpt;
  1442. struct peer *peer;
  1443. {
  1444. unsigned char prn, channel, aqflag, ephstat;
  1445. float snr, azinuth, elevation;
  1446. static char logbuf[1024]; /* logging string buffer */
  1447. unsigned char *buf;
  1448. buf = rpt->buf;
  1449. if (rpt->len != 24)
  1450. return(-1);
  1451. prn = buf[0];
  1452. channel = (unsigned char)(buf[1] >> 3);
  1453. if (channel == 0x10)
  1454. channel = 2;
  1455. else
  1456. channel++;
  1457. aqflag = buf[2];
  1458. ephstat = buf[3];
  1459. snr = bGetSingle(&buf[4]);
  1460. elevation = bGetSingle(&buf[12]) * R2D;
  1461. azinuth = bGetSingle(&buf[16]) * R2D;
  1462. sprintf(logbuf, "S1 %02d %d %d %02x %4.1f %5.1f %4.1f",
  1463. prn, channel, aqflag, ephstat, snr, azinuth, elevation);
  1464. #ifdef DEBUG_NCC
  1465. if (debug)
  1466. puts(logbuf);
  1467. #endif /* DEBUG_NCC */
  1468. record_clock_stats(&peer->srcadr, logbuf);
  1469. return (0);
  1470. }
  1471. /******* Code below is from Trimble Tsipchat *************/
  1472. /*
  1473. * *************************************************************************
  1474. *
  1475. * Trimble Navigation, Ltd.
  1476. * OEM Products Development Group
  1477. * P.O. Box 3642
  1478. * 645 North Mary Avenue
  1479. * Sunnyvale, California 94088-3642
  1480. *
  1481. * Corporate Headquarter:
  1482. * Telephone: (408) 481-8000
  1483. * Fax: (408) 481-6005
  1484. *
  1485. * Technical Support Center:
  1486. * Telephone: (800) 767-4822 (U.S. and Canada)
  1487. * (408) 481-6940 (outside U.S. and Canada)
  1488. * Fax: (408) 481-6020
  1489. * BBS: (408) 481-7800
  1490. * e-mail: trimble_support@trimble.com
  1491. * ftp://ftp.trimble.com/pub/sct/embedded/bin
  1492. *
  1493. * *************************************************************************
  1494. *
  1495. * ------- BYTE-SWAPPING -------
  1496. * TSIP is big-endian (Motorola) protocol. To use on little-endian (Intel)
  1497. * systems, the bytes of all multi-byte types (shorts, floats, doubles, etc.)
  1498. * must be reversed. This is controlled by the MACRO BYTESWAP; if defined, it
  1499. * assumes little-endian protocol.
  1500. * --------------------------------
  1501. *
  1502. * T_PARSER.C and T_PARSER.H contains primitive functions that interpret
  1503. * reports received from the receiver. A second source file pair,
  1504. * T_FORMAT.C and T_FORMAT.H, contin the matching TSIP command formatters.
  1505. *
  1506. * The module is in very portable, basic C language. It can be used as is, or
  1507. * with minimal changes if a TSIP communications application is needed separate
  1508. * from TSIPCHAT. The construction of most argument lists avoid the use of
  1509. * structures, but the developer is encouraged to reconstruct them using such
  1510. * definitions to meet project requirements. Declarations of T_PARSER.C
  1511. * functions are included in T_PARSER.H to provide prototyping definitions.
  1512. *
  1513. * There are two types of functions: a serial input processing routine,
  1514. * tsip_input_proc()
  1515. * which assembles incoming bytes into a TSIPPKT structure, and the
  1516. * report parsers, rpt_0x??().
  1517. *
  1518. * 1) The function tsip_input_proc() accumulates bytes from the receiver,
  1519. * strips control bytes (DLE), and checks if the report end sequence (DLE ETX)
  1520. * has been received. rpt.status is defined as TSIP_PARSED_FULL (== 1)
  1521. * if a complete packet is available.
  1522. *
  1523. * 2) The functions rpt_0x??() are report string interpreters patterned after
  1524. * the document called "Trimble Standard Interface Protocol". It should be
  1525. * noted that if the report buffer is sent into the receiver with the wrong
  1526. * length (byte count), the rpt_0x??() returns the Boolean equivalence for
  1527. * TRUE.
  1528. *
  1529. * *************************************************************************
  1530. *
  1531. */
  1532. /**/
  1533. static void tsip_input_proc (
  1534. TSIPPKT *rpt,
  1535. int inbyte)
  1536. /* reads bytes until serial buffer is empty or a complete report
  1537. * has been received; end of report is signified by DLE ETX.
  1538. */
  1539. {
  1540. unsigned char newbyte;
  1541. if (inbyte < 0 || inbyte > 0xFF) return;
  1542. newbyte = (unsigned char)(inbyte);
  1543. switch (rpt->status)
  1544. {
  1545. case TSIP_PARSED_DLE_1:
  1546. switch (newbyte)
  1547. {
  1548. case 0:
  1549. case ETX:
  1550. /* illegal TSIP IDs */
  1551. rpt->len = 0;
  1552. rpt->status = TSIP_PARSED_EMPTY;
  1553. break;
  1554. case DLE:
  1555. /* try normal message start again */
  1556. rpt->len = 0;
  1557. rpt->status = TSIP_PARSED_DLE_1;
  1558. break;
  1559. default:
  1560. /* legal TSIP ID; start message */
  1561. rpt->code = newbyte;
  1562. rpt->len = 0;
  1563. rpt->status = TSIP_PARSED_DATA;
  1564. break;
  1565. }
  1566. break;
  1567. case TSIP_PARSED_DATA:
  1568. switch (newbyte) {
  1569. case DLE:
  1570. /* expect DLE or ETX next */
  1571. rpt->status = TSIP_PARSED_DLE_2;
  1572. break;
  1573. default:
  1574. /* normal data byte */
  1575. rpt->buf[rpt->len] = newbyte;
  1576. rpt->len++;
  1577. /* no change in rpt->status */
  1578. break;
  1579. }
  1580. break;
  1581. case TSIP_PARSED_DLE_2:
  1582. switch (newbyte) {
  1583. case DLE:
  1584. /* normal data byte */
  1585. rpt->buf[rpt->len] = newbyte;
  1586. rpt->len++;
  1587. rpt->status = TSIP_PARSED_DATA;
  1588. break;
  1589. case ETX:
  1590. /* end of message; return TRUE here. */
  1591. rpt->status = TSIP_PARSED_FULL;
  1592. break;
  1593. default:
  1594. /* error: treat as TSIP_PARSED_DLE_1; start new report packet */
  1595. rpt->code = newbyte;
  1596. rpt->len = 0;
  1597. rpt->status = TSIP_PARSED_DATA;
  1598. }
  1599. break;
  1600. case TSIP_PARSED_FULL:
  1601. case TSIP_PARSED_EMPTY:
  1602. default:
  1603. switch (newbyte) {
  1604. case DLE:
  1605. /* normal message start */
  1606. rpt->len = 0;
  1607. rpt->status = TSIP_PARSED_DLE_1;
  1608. break;
  1609. default:
  1610. /* error: ignore newbyte */
  1611. rpt->len = 0;
  1612. rpt->status = TSIP_PARSED_EMPTY;
  1613. }
  1614. break;
  1615. }
  1616. if (rpt->len > MAX_RPTBUF) {
  1617. /* error: start new report packet */
  1618. rpt->status = TSIP_PARSED_EMPTY;
  1619. rpt->len = 0;
  1620. }
  1621. }
  1622. #ifdef TRIMBLE_OUTPUT_FUNC
  1623. /**/
  1624. short rpt_0x3D (TSIPPKT *rpt,
  1625. unsigned char *tx_baud_index,
  1626. unsigned char *rx_baud_index,
  1627. unsigned char *char_format_index,
  1628. unsigned char *stop_bits,
  1629. unsigned char *tx_mode_index,
  1630. unsigned char *rx_mode_index)
  1631. /* Channel A configuration for dual port operation */
  1632. {
  1633. unsigned char *buf;
  1634. buf = rpt->buf;
  1635. if (rpt->len != 6) return TRUE;
  1636. *tx_baud_index = buf[0];
  1637. *rx_baud_index = buf[1];
  1638. *char_format_index = buf[2];
  1639. *stop_bits = (unsigned char)((buf[3] == 0x07) ? 1 : 2);
  1640. *tx_mode_index = buf[4];
  1641. *rx_mode_index = buf[5];
  1642. return FALSE;
  1643. }
  1644. /**/
  1645. short rpt_0x40 (TSIPPKT *rpt,
  1646. unsigned char *sv_prn,
  1647. short *week_num,
  1648. float *t_zc,
  1649. float *eccentricity,
  1650. float *t_oa,
  1651. float *i_0,
  1652. float *OMEGA_dot,
  1653. float *sqrt_A,
  1654. float *OMEGA_0,
  1655. float *omega,
  1656. float *M_0)
  1657. /* almanac data for specified satellite */
  1658. {
  1659. unsigned char *buf;
  1660. buf = rpt->buf;
  1661. if (rpt->len != 39) return TRUE;
  1662. *sv_prn = buf[0];
  1663. *t_zc = bGetSingle (&buf[1]);
  1664. *week_num = bGetShort (&buf[5]);
  1665. *eccentricity = bGetSingle (&buf[7]);
  1666. *t_oa = bGetSingle (&buf[11]);
  1667. *i_0 = bGetSingle (&buf[15]);
  1668. *OMEGA_dot = bGetSingle (&buf[19]);
  1669. *sqrt_A = bGetSingle (&buf[23]);
  1670. *OMEGA_0 = bGetSingle (&buf[27]);
  1671. *omega = bGetSingle (&buf[31]);
  1672. *M_0 = bGetSingle (&buf[35]);
  1673. return FALSE;
  1674. }
  1675. short rpt_0x41 (TSIPPKT *rpt,
  1676. float *time_of_week,
  1677. float *UTC_offset,
  1678. short *week_num)
  1679. /* GPS time */
  1680. {
  1681. unsigned char *buf;
  1682. buf = rpt->buf;
  1683. if (rpt->len != 10) return TRUE;
  1684. *time_of_week = bGetSingle (buf);
  1685. *week_num = bGetShort (&buf[4]);
  1686. *UTC_offset = bGetSingle (&buf[6]);
  1687. return FALSE;
  1688. }
  1689. short rpt_0x42 (TSIPPKT *rpt,
  1690. float pos_ECEF[3],
  1691. float *time_of_fix)
  1692. /* position in ECEF, single precision */
  1693. {
  1694. unsigned char *buf;
  1695. buf = rpt->buf;
  1696. if (rpt->len != 16) return TRUE;
  1697. pos_ECEF[0] = bGetSingle (buf);
  1698. pos_ECEF[1]= bGetSingle (&buf[4]);
  1699. pos_ECEF[2]= bGetSingle (&buf[8]);
  1700. *time_of_fix = bGetSingle (&buf[12]);
  1701. return FALSE;
  1702. }
  1703. short rpt_0x43 (TSIPPKT *rpt,
  1704. float ECEF_vel[3],
  1705. float *freq_offset,
  1706. float *time_of_fix)
  1707. /* velocity in ECEF, single precision */
  1708. {
  1709. unsigned char *buf;
  1710. buf = rpt->bu