2 * $Id: refclock_ripencc.c,v 1.13 2002/06/18 14:20:55 marks Exp marks $
4 * Copyright (c) 2002 RIPE NCC
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.
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.
25 * This driver was developed for use with the RIPE NCC TTM project.
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
31 * Rewrite of the driver for ntpd-4.x.x by Mark Santcroos <marks@ripe.net>
37 #endif /* HAVE_CONFIG_H */
39 #if defined(REFCLOCK) && defined(CLOCK_RIPENCC)
41 #include "ntp_stdlib.h"
43 #include "ntp_refclock.h"
44 #include "ntp_unixtime.h"
48 # include "ppsapi_timepps.h"
55 /* we are on little endian */
59 * DEBUG statements: uncomment if necessary
61 /* #define DEBUG_NCC */ /* general debug statements */
62 /* #define DEBUG_PPS */ /* debug pps */
63 /* #define DEBUG_RAW */ /* print raw packets */
65 #define TRIMBLE_OUTPUT_FUNC
66 #define TSIP_VERNUM "7.12a"
73 #define GPS_PI (3.1415926535898)
74 #define GPS_C (299792458.)
75 #define D2R (GPS_PI/180.0)
76 #define R2D (180.0/GPS_PI)
77 #define WEEK (604800.)
80 /* control characters for TSIP packets */
84 #define MAX_RPTBUF (256)
86 /* values of TSIPPKT.status */
87 #define TSIP_PARSED_EMPTY 0
88 #define TSIP_PARSED_FULL 1
89 #define TSIP_PARSED_DLE_1 2
90 #define TSIP_PARSED_DATA 3
91 #define TSIP_PARSED_DLE_2 4
93 #define UTCF_UTC_AVAIL (unsigned char) (1) /* UTC available */
94 #define UTCF_LEAP_SCHD (unsigned char) (1<<4) /* Leap scheduled */
95 #define UTCF_LEAP_PNDG (unsigned char) (1<<5) /* Leap pending, will occur at end of day */
97 #define DEVICE "/dev/gps%d" /* name of radio device */
98 #define PRECISION (-9) /* precision assumed (about 2 ms) */
99 #define PPS_PRECISION (-20) /* precision assumed (about 1 us) */
100 #define REFID "GPS\0" /* reference id */
102 #define DESCRIPTION "RIPE NCC GPS (Palisade)" /* Description */
103 #define SPEED232 B9600 /* 9600 baud */
105 #define NSAMPLES 3 /* stages of median filter */
109 /* TSIP packets have the following structure, whether report or command. */
112 counter, /* counter */
113 len; /* size of buf; < MAX_RPTBUF unsigned chars */
115 status, /* TSIP packet format/parse status */
116 code, /* TSIP code */
117 buf[MAX_RPTBUF]; /* report or command string */
120 /* TSIP binary data structures */
125 e, t_oa, i_0, OMEGADOT, sqrt_A,
126 OMEGA_0, omega, M_0, a_f0, a_f1,
127 Axis, n, OMEGA_n, ODOT_n, t_zc;
132 typedef struct { /* Almanac health page (25) parameters */
134 WN_a, SV_health[32], t_oa;
137 typedef struct { /* Universal Coordinated Time (UTC) parms */
147 WN_t, WN_LSF, DN, delta_t_LSF;
150 typedef struct { /* Ionospheric info (float) */
152 alpha_0, alpha_1, alpha_2, alpha_3,
153 beta_0, beta_1, beta_2, beta_3;
156 typedef struct { /* Subframe 1 info (float) */
160 codeL2, L2Pdata, SVacc_raw, SV_health;
164 T_GD, t_oc, a_f2, a_f1, a_f0, SVacc;
167 typedef struct { /* Ephemeris info (float) */
197 Axis, n, r1me2, OMEGA_n, ODOT_n;
200 typedef struct { /* Navigation data structure */
202 sv_number; /* SV number (0 = no entry) */
204 t_ephem; /* time of ephemeris collection */
206 ephclk; /* subframe 1 data */
208 ephorb; /* ephemeris data */
228 #ifdef TRIMBLE_OUTPUT_FUNC
230 *dayname[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"},
231 old_baudnum[] = {0, 1, 4, 5, 6, 8, 9, 11, 28, 12},
232 *st_baud_text_app [] = {"", "", " 300", " 600", " 1200", " 2400",
233 " 4800", " 9600", "19200", "38400"},
234 *old_parity_text[] = {"EVEN", "ODD", "", "", "NONE"},
235 *parity_text [] = {"NONE", "ODD", "EVEN"},
236 *old_input_ch[] = { "TSIP", "RTCM (6 of 8 bits)"},
237 *old_output_ch[] = { "TSIP", "No output", "", "", "", "NMEA 0183"},
238 *protocols_in_text[] = { "", "TSIP", "", ""},
239 *protocols_out_text[] = { "", "TSIP", "NMEA"},
240 *rcvr_port_text [] = { "Port A ", "Port B ", "Current Port"},
241 *dyn_text [] = {"Unchanged", "Land", "Sea", "Air", "Static"},
242 *NavModeText0xBB[] = {"automatic", "time only (0-D)", "", "2-D",
243 "3-D", "", "", "OverDetermined Time"},
244 *PPSTimeBaseText[] = {"GPS", "UTC", "USER"},
245 *PPSPolarityText[] = {"Positive", "Negative"},
246 *MaskText[] = { "Almanac ", "Ephemeris", "UTC ", "Iono ",
247 "GPS Msg ", "Alm Hlth ", "Time Fix ", "SV Select",
248 "Ext Event", "Pos Fix ", "Raw Meas "};
250 #endif /* TRIMBLE_OUTPUT_FUNC */
253 * Unit control structure
255 struct ripencc_unit {
256 int unit; /* unit number */
257 int pollcnt; /* poll message counter */
258 int polled; /* Hand in a sample? */
259 char leapdelta; /* delta of next leap event */
260 unsigned char utcflags; /* delta of next leap event */
261 l_fp tstamp; /* timestamp of last poll */
263 struct timespec ts; /* last timestamp */
264 pps_params_t pps_params; /* pps parameters */
265 pps_info_t pps_info; /* last pps data */
266 pps_handle_t handle; /* pps handlebars */
271 /******************* PROTOYPES *****************/
273 /* prototypes for report parsing primitives */
274 short rpt_0x3D (TSIPPKT *rpt, unsigned char *tx_baud_index,
275 unsigned char *rx_baud_index, unsigned char *char_format_index,
276 unsigned char *stop_bits, unsigned char *tx_mode_index,
277 unsigned char *rx_mode_index);
278 short rpt_0x40 (TSIPPKT *rpt, unsigned char *sv_prn, short *week_num,
279 float *t_zc, float *eccentricity, float *t_oa, float *i_0,
280 float *OMEGA_dot, float *sqrt_A, float *OMEGA_0, float *omega,
282 short rpt_0x41 (TSIPPKT *rpt, float *time_of_week, float *UTC_offset,
284 short rpt_0x42 (TSIPPKT *rpt, float ECEF_pos[3], float *time_of_fix);
285 short rpt_0x43 (TSIPPKT *rpt, float ECEF_vel[3], float *freq_offset,
287 short rpt_0x45 (TSIPPKT *rpt, unsigned char *major_nav_version,
288 unsigned char *minor_nav_version, unsigned char *nav_day,
289 unsigned char *nav_month, unsigned char *nav_year,
290 unsigned char *major_dsp_version, unsigned char *minor_dsp_version,
291 unsigned char *dsp_day, unsigned char *dsp_month,
292 unsigned char *dsp_year);
293 short rpt_0x46 (TSIPPKT *rpt, unsigned char *status1, unsigned char *status2);
294 short rpt_0x47 (TSIPPKT *rpt, unsigned char *nsvs, unsigned char *sv_prn,
296 short rpt_0x48 (TSIPPKT *rpt, unsigned char *message);
297 short rpt_0x49 (TSIPPKT *rpt, unsigned char *sv_health);
298 short rpt_0x4A (TSIPPKT *rpt, float *lat, float *lon, float *alt,
299 float *clock_bias, float *time_of_fix);
300 short rpt_0x4A_2 (TSIPPKT *rpt, float *alt, float *dummy,
301 unsigned char *alt_flag);
302 short rpt_0x4B (TSIPPKT *rpt, unsigned char *machine_id,
303 unsigned char *status3, unsigned char *status4);
304 short rpt_0x4C (TSIPPKT *rpt, unsigned char *dyn_code, float *el_mask,
305 float *snr_mask, float *dop_mask, float *dop_switch);
306 short rpt_0x4D (TSIPPKT *rpt, float *osc_offset);
307 short rpt_0x4E (TSIPPKT *rpt, unsigned char *response);
308 short rpt_0x4F (TSIPPKT *rpt, double *a0, float *a1, float *time_of_data,
309 short *dt_ls, short *wn_t, short *wn_lsf, short *dn, short *dt_lsf);
310 short rpt_0x54 (TSIPPKT *rpt, float *clock_bias, float *freq_offset,
312 short rpt_0x55 (TSIPPKT *rpt, unsigned char *pos_code, unsigned char *vel_code,
313 unsigned char *time_code, unsigned char *aux_code);
314 short rpt_0x56 (TSIPPKT *rpt, float vel_ENU[3], float *freq_offset,
316 short rpt_0x57 (TSIPPKT *rpt, unsigned char *source_code,
317 unsigned char *diag_code, short *week_num, float *time_of_fix);
318 short rpt_0x58 (TSIPPKT *rpt, unsigned char *op_code, unsigned char *data_type,
319 unsigned char *sv_prn, unsigned char *data_length,
320 unsigned char *data_packet);
321 short rpt_0x59 (TSIPPKT *rpt, unsigned char *code_type,
322 unsigned char status_code[32]);
323 short rpt_0x5A (TSIPPKT *rpt, unsigned char *sv_prn, float *sample_length,
324 float *signal_level, float *code_phase, float *Doppler,
325 double *time_of_fix);
326 short rpt_0x5B (TSIPPKT *rpt, unsigned char *sv_prn, unsigned char *sv_health,
327 unsigned char *sv_iode, unsigned char *fit_interval_flag,
328 float *time_of_collection, float *time_of_eph, float *sv_accy);
329 short rpt_0x5C (TSIPPKT *rpt, unsigned char *sv_prn, unsigned char *slot,
330 unsigned char *chan, unsigned char *acq_flag, unsigned char *eph_flag,
331 float *signal_level, float *time_of_last_msmt, float *elev,
332 float *azim, unsigned char *old_msmt_flag,
333 unsigned char *integer_msec_flag, unsigned char *bad_data_flag,
334 unsigned char *data_collect_flag);
335 short rpt_0x6D (TSIPPKT *rpt, unsigned char *manual_mode, unsigned char *nsvs,
336 unsigned char *ndim, unsigned char sv_prn[], float *pdop,
337 float *hdop, float *vdop, float *tdop);
338 short rpt_0x82 (TSIPPKT *rpt, unsigned char *diff_mode);
339 short rpt_0x83 (TSIPPKT *rpt, double ECEF_pos[3], double *clock_bias,
341 short rpt_0x84 (TSIPPKT *rpt, double *lat, double *lon, double *alt,
342 double *clock_bias, float *time_of_fix);
343 short rpt_Paly0xBB(TSIPPKT *rpt, TSIP_RCVR_CFG *TsipxBB);
344 short rpt_0xBC (TSIPPKT *rpt, unsigned char *port_num,
345 unsigned char *in_baud, unsigned char *out_baud,
346 unsigned char *data_bits, unsigned char *parity,
347 unsigned char *stop_bits, unsigned char *flow_control,
348 unsigned char *protocols_in, unsigned char *protocols_out,
349 unsigned char *reserved);
351 /* prototypes for superpacket parsers */
353 short rpt_0x8F0B (TSIPPKT *rpt, unsigned short *event, double *tow,
354 unsigned char *date, unsigned char *month, short *year,
355 unsigned char *dim_mode, short *utc_offset, double *bias, double *drift,
356 float *bias_unc, float *dr_unc, double *lat, double *lon, double *alt,
358 short rpt_0x8F14 (TSIPPKT *rpt, short *datum_idx, double datum_coeffs[5]);
359 short rpt_0x8F15 (TSIPPKT *rpt, short *datum_idx, double datum_coeffs[5]);
360 short rpt_0x8F20 (TSIPPKT *rpt, unsigned char *info, double *lat,
361 double *lon, double *alt, double vel_enu[], double *time_of_fix,
362 short *week_num, unsigned char *nsvs, unsigned char sv_prn[],
363 short sv_IODC[], short *datum_index);
364 short rpt_0x8F41 (TSIPPKT *rpt, unsigned char *bSearchRange,
365 unsigned char *bBoardOptions, unsigned long *iiSerialNumber,
366 unsigned char *bBuildYear, unsigned char *bBuildMonth,
367 unsigned char *bBuildDay, unsigned char *bBuildHour,
368 float *fOscOffset, unsigned short *iTestCodeId);
369 short rpt_0x8F42 (TSIPPKT *rpt, unsigned char *bProdOptionsPre,
370 unsigned char *bProdNumberExt, unsigned short *iCaseSerialNumberPre,
371 unsigned long *iiCaseSerialNumber, unsigned long *iiProdNumber,
372 unsigned short *iPremiumOptions, unsigned short *iMachineID,
373 unsigned short *iKey);
374 short rpt_0x8F45 (TSIPPKT *rpt, unsigned char *bSegMask);
375 short rpt_0x8F4A_16 (TSIPPKT *rpt, unsigned char *pps_enabled,
376 unsigned char *pps_timebase, unsigned char *pos_polarity,
377 double *pps_offset, float *bias_unc_threshold);
378 short rpt_0x8F4B (TSIPPKT *rpt, unsigned long *decorr_max);
379 short rpt_0x8F4D (TSIPPKT *rpt, unsigned long *event_mask);
380 short rpt_0x8FA5 (TSIPPKT *rpt, unsigned char *spktmask);
381 short rpt_0x8FAD (TSIPPKT *rpt, unsigned short *COUNT, double *FracSec,
382 unsigned char *Hour, unsigned char *Minute, unsigned char *Second,
383 unsigned char *Day, unsigned char *Month, unsigned short *Year,
384 unsigned char *Status, unsigned char *Flags);
387 /* prototypes for command-encode primitives with suffix convention: */
388 /* c = clear, s = set, q = query, e = enable, d = disable */
389 void cmd_0x1F (TSIPPKT *cmd);
390 void cmd_0x26 (TSIPPKT *cmd);
391 void cmd_0x2F (TSIPPKT *cmd);
392 void cmd_0x35s (TSIPPKT *cmd, unsigned char pos_code, unsigned char vel_code,
393 unsigned char time_code, unsigned char opts_code);
394 void cmd_0x3C (TSIPPKT *cmd, unsigned char sv_prn);
395 void cmd_0x3Ds (TSIPPKT *cmd, unsigned char baud_out, unsigned char baud_inp,
396 unsigned char char_code, unsigned char stopbitcode,
397 unsigned char output_mode, unsigned char input_mode);
398 void cmd_0xBBq (TSIPPKT *cmd, unsigned char subcode) ;
400 /* prototypes 8E commands */
401 void cmd_0x8E0Bq (TSIPPKT *cmd);
402 void cmd_0x8E41q (TSIPPKT *cmd);
403 void cmd_0x8E42q (TSIPPKT *cmd);
404 void cmd_0x8E4Aq (TSIPPKT *cmd);
405 void cmd_0x8E4As (TSIPPKT *cmd, unsigned char PPSOnOff, unsigned char TimeBase,
406 unsigned char Polarity, double PPSOffset, float Uncertainty);
407 void cmd_0x8E4Bq (TSIPPKT *cmd);
408 void cmd_0x8E4Ds (TSIPPKT *cmd, unsigned long AutoOutputMask);
409 void cmd_0x8EADq (TSIPPKT *cmd);
411 /* header/source border XXXXXXXXXXXXXXXXXXXXXXXXXX */
413 /* Trimble parse functions */
414 static int parse0x8FAD (TSIPPKT *, struct peer *);
415 static int parse0x8F0B (TSIPPKT *, struct peer *);
416 #ifdef TRIMBLE_OUTPUT_FUNC
417 static int parseany (TSIPPKT *, struct peer *);
418 static void TranslateTSIPReportToText (TSIPPKT *, char *);
419 #endif /* TRIMBLE_OUTPUT_FUNC */
420 static int parse0x5C (TSIPPKT *, struct peer *);
421 static int parse0x4F (TSIPPKT *, struct peer *);
422 static void tsip_input_proc (TSIPPKT *, int);
424 /* Trimble helper functions */
425 static void bPutFloat (float *, unsigned char *);
426 static void bPutDouble (double *, unsigned char *);
427 static void bPutULong (unsigned long *, unsigned char *);
428 static int print_msg_table_header (int rptcode, char *HdrStr, int force);
429 static char * show_time (float time_of_week);
431 /* RIPE NCC functions */
432 static void ripencc_control (int, const struct refclockstat *,
433 struct refclockstat *, struct peer *);
434 static int ripencc_ppsapi (struct peer *, int, int);
435 static int ripencc_get_pps_ts (struct ripencc_unit *, l_fp *);
436 static int ripencc_start (int, struct peer *);
437 static void ripencc_shutdown (int, struct peer *);
438 static void ripencc_poll (int, struct peer *);
439 static void ripencc_send (struct peer *, TSIPPKT spt);
440 static void ripencc_receive (struct recvbuf *);
442 /* fill in reflock structure for our clock */
443 struct refclock refclock_ripencc = {
444 ripencc_start, /* start up driver */
445 ripencc_shutdown, /* shut down driver */
446 ripencc_poll, /* transmit poll message */
447 ripencc_control, /* control function */
448 noentry, /* initialize driver */
449 noentry, /* debug info */
450 NOFLAGS /* clock flags */
454 * Tables to compute the ddd of year form icky dd/mm timecode. Viva la
457 static int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
458 static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
462 * ripencc_start - open the GPS devices and initialize data for processing
465 ripencc_start(int unit, struct peer *peer)
467 register struct ripencc_unit *up;
468 struct refclockproc *pp;
479 (void)snprintf(device, sizeof(device), DEVICE, unit);
480 if (!(fd = refclock_open(device, SPEED232, LDISC_RAW))) {
487 /* from refclock_palisade.c */
488 if (tcgetattr(fd, &tio) < 0) {
489 msyslog(LOG_ERR, "Palisade(%d) tcgetattr(fd, &tio): %m",unit);
496 tio.c_cflag |= (PARENB|PARODD);
497 tio.c_iflag &= ~ICRNL;
498 if (tcsetattr(fd, TCSANOW, &tio) == -1) {
499 msyslog(LOG_ERR, "Palisade(%d) tcsetattr(fd, &tio): %m",unit);
504 * Allocate and initialize unit structure
506 if (!(up = (struct ripencc_unit *)
507 emalloc(sizeof(struct ripencc_unit)))) {
511 memset((char *)up, 0, sizeof(struct ripencc_unit));
513 pp->io.clock_recv = ripencc_receive;
514 pp->io.srcclock = (caddr_t)peer;
516 if (!io_addclock(&pp->io)) {
522 pp->unitptr = (caddr_t)up;
525 * Initialize miscellaneous variables
527 peer->precision = PRECISION;
528 pp->clockdesc = DESCRIPTION;
529 memcpy((char *)&pp->refid, REFID, REFID_LEN);
536 * Initialize the Clock
539 /* query software versions */
541 ripencc_send(peer, spt);
543 /* query receiver health */
545 ripencc_send(peer, spt);
547 /* query serial numbers */
549 ripencc_send(peer, spt);
551 /* query manuf params */
553 ripencc_send(peer, spt);
555 /* i/o opts */ /* trimble manual page A30 */
560 0x0a); /* auxilary */
561 ripencc_send(peer, spt);
563 /* turn off port A */
567 0x07, /* char_code */
568 0x07, /* stopbitcode */
569 0x01, /* output_mode */
570 0x00); /* input_mode */
571 ripencc_send(peer, spt);
573 /* set i/o options */
576 0x01, /* Timebase UTC */
577 0x00, /* polarity positive */
578 0., /* 100 ft. cable XXX make flag */
579 1e-6 * GPS_C); /* turn of biasuncert. > (1us) */
580 ripencc_send(peer,spt);
582 /* all outomatic packet output off */
584 0x00000000); /* AutoOutputMask */
585 ripencc_send(peer, spt);
588 0x00); /* query primary configuration */
589 ripencc_send(peer,spt);
592 /* query PPS parameters */
593 cmd_0x8E4Aq (&spt); /* query PPS params */
594 ripencc_send(peer,spt);
596 /* query survey limit */
597 cmd_0x8E4Bq (&spt); /* query survey limit */
598 ripencc_send(peer,spt);
602 printf("ripencc_start: success\n");
603 #endif /* DEBUG_NCC */
606 * Start the PPSAPI interface if it is there. Default to use
607 * the assert edge and do not enable the kernel hardpps.
609 if (time_pps_create(fd, &up->handle) < 0) {
611 msyslog(LOG_ERR, "refclock_ripencc: time_pps_create failed: %m");
615 return(ripencc_ppsapi(peer, 0, 0));
619 * ripencc_control - fudge control
623 int unit, /* unit (not used) */
624 const struct refclockstat *in, /* input parameters (not used) */
625 struct refclockstat *out, /* output parameters (not used) */
626 struct peer *peer /* peer structure pointer */
629 struct refclockproc *pp;
632 msyslog(LOG_INFO,"%s()",__FUNCTION__);
633 #endif /* DEBUG_NCC */
636 ripencc_ppsapi(peer, pp->sloppyclockflag & CLK_FLAG2,
637 pp->sloppyclockflag & CLK_FLAG3);
646 struct peer *peer, /* peer structure pointer */
647 int enb_clear, /* clear enable */
648 int enb_hardpps /* hardpps enable */
651 struct refclockproc *pp;
652 struct ripencc_unit *up;
656 up = (struct ripencc_unit *)pp->unitptr;
657 if (time_pps_getcap(up->handle, &capability) < 0) {
659 "refclock_ripencc: time_pps_getcap failed: %m");
662 memset(&up->pps_params, 0, sizeof(pps_params_t));
664 up->pps_params.mode = capability & PPS_CAPTURECLEAR;
666 up->pps_params.mode = capability & PPS_CAPTUREASSERT;
667 if (!up->pps_params.mode) {
669 "refclock_ripencc: invalid capture edge %d",
673 up->pps_params.mode |= PPS_TSFMT_TSPEC;
674 if (time_pps_setparams(up->handle, &up->pps_params) < 0) {
676 "refclock_ripencc: time_pps_setparams failed: %m");
680 if (time_pps_kcbind(up->handle, PPS_KC_HARDPPS,
681 up->pps_params.mode & ~PPS_TSFMT_TSPEC,
682 PPS_TSFMT_TSPEC) < 0) {
684 "refclock_ripencc: time_pps_kcbind failed: %m");
689 peer->precision = PPS_PRECISION;
693 time_pps_getparams(up->handle, &up->pps_params);
695 "refclock_ripencc: capability 0x%x version %d mode 0x%x kern %d\n",
696 capability, up->pps_params.api_version,
697 up->pps_params.mode, enb_hardpps);
699 #endif /* DEBUG_NCC */
705 * This function is called every 64 seconds from ripencc_receive
706 * It will fetch the pps time
708 * Return 0 on failure and 1 on success.
712 struct ripencc_unit *up,
717 struct timespec timeout, ts;
722 msyslog(LOG_INFO,"ripencc_get_pps_ts\n");
723 #endif /* DEBUG_PPS */
727 * Convert the timespec nanoseconds field to ntp l_fp units.
733 memcpy(&pps_info, &up->pps_info, sizeof(pps_info_t));
734 if (time_pps_fetch(up->handle, PPS_TSFMT_TSPEC, &up->pps_info,
737 if (up->pps_params.mode & PPS_CAPTUREASSERT) {
738 if (pps_info.assert_sequence ==
739 up->pps_info.assert_sequence)
741 ts = up->pps_info.assert_timestamp;
742 } else if (up->pps_params.mode & PPS_CAPTURECLEAR) {
743 if (pps_info.clear_sequence ==
744 up->pps_info.clear_sequence)
746 ts = up->pps_info.clear_timestamp;
750 if ((up->ts.tv_sec == ts.tv_sec) && (up->ts.tv_nsec == ts.tv_nsec))
754 tstmp.l_ui = ts.tv_sec + JAN_1970;
755 dtemp = ts.tv_nsec * FRAC / 1e9;
756 tstmp.l_uf = (u_int32)dtemp;
759 msyslog(LOG_INFO,"ts.tv_sec: %d\n",(int)ts.tv_sec);
760 msyslog(LOG_INFO,"ts.tv_nsec: %ld\n",ts.tv_nsec);
761 #endif /* DEBUG_PPS */
768 * ripencc_shutdown - shut down a GPS clock
771 ripencc_shutdown(int unit, struct peer *peer)
773 register struct ripencc_unit *up;
774 struct refclockproc *pp;
777 up = (struct ripencc_unit *)pp->unitptr;
781 time_pps_destroy(up->handle);
785 io_closeclock(&pp->io);
791 * ripencc_poll - called by the transmit procedure
794 ripencc_poll(int unit, struct peer *peer)
796 register struct ripencc_unit *up;
797 struct refclockproc *pp;
802 fprintf(stderr, "ripencc_poll(%d)\n", unit);
803 #endif /* DEBUG_NCC */
805 up = (struct ripencc_unit *)pp->unitptr;
806 if (up->pollcnt == 0)
807 refclock_report(peer, CEVNT_TIMEOUT);
814 /* poll for UTC superpacket */
816 ripencc_send(peer,spt);
820 * ripencc_send - send message to clock
821 * use the structures being created by the trimble functions!
822 * makes the code more readable/clean
825 ripencc_send(struct peer *peer, TSIPPKT spt)
827 unsigned char *ip, *op;
828 unsigned char obuf[512];
832 register struct ripencc_unit *up;
833 register struct refclockproc *pp;
836 up = (struct ripencc_unit *)pp->unitptr;
838 printf("ripencc_send(%d, %02X)\n", up->unit, cmd);
840 #endif /* DEBUG_RAW */
849 if (op-obuf > sizeof(obuf)-5) {
850 msyslog(LOG_ERR, "ripencc_send obuf overflow!");
851 refclock_report(peer, CEVNT_FAULT);
855 if (*ip == 0x10) /* byte stuffing */
864 if (debug) { /* print raw packet */
868 printf("ripencc_send: len %d\n", op-obuf);
869 for (i=1, cp=obuf; cp<op; i++, cp++) {
870 printf(" %02X", *cp);
876 #endif /* DEBUG_RAW */
878 if (write(peer->procptr->io.fd, obuf, op-obuf) == -1) {
879 refclock_report(peer, CEVNT_FAULT);
886 * called when a packet is received on the serial port
887 * takes care of further processing
891 ripencc_receive(struct recvbuf *rbufp)
893 register struct ripencc_unit *up;
894 register struct refclockproc *pp;
896 static TSIPPKT rpt; /* for current incoming TSIP report */
897 TSIPPKT spt; /* send packet */
901 /* these variables hold data until we decide it's worth keeping */
902 char rd_lastcode[BMAX];
906 /* msyslog(LOG_INFO, "%s",__FUNCTION__); */
909 * Initialize pointers and read the timecode and timestamp
911 peer = (struct peer *)rbufp->recv_srcclock;
913 up = (struct ripencc_unit *)pp->unitptr;
914 rd_lencode = refclock_gtlin(rbufp, rd_lastcode, BMAX, &rd_tmp);
918 fprintf(stderr, "ripencc_receive(%d)\n", up->unit);
919 #endif /* DEBUG_RAW */
922 if (debug) { /* print raw packet */
926 printf("ripencc_receive: len %d\n", rbufp->recv_length);
927 for (i=1, cp=(char*)&rbufp->recv_space;
928 i <= rbufp->recv_length;
930 printf(" %02X", *cp);
936 #endif /* DEBUG_RAW */
938 cp = (char*) &rbufp->recv_space;
939 i=rbufp->recv_length;
941 while (i--) { /* loop over received chars */
943 tsip_input_proc(&rpt, (unsigned char) *cp++);
945 if (rpt.status != TSIP_PARSED_FULL)
950 case 0x8F: /* superpacket */
952 switch (rpt.buf[0]) {
954 case 0xAD: /* UTC Time */
956 ** When polling on port B the timecode is
957 ** the time of the previous PPS. If we
958 ** completed receiving the packet less than
959 ** 150ms after the turn of the second, it
960 ** may have the code of the previous second.
961 ** We do not trust that and simply poll
962 ** again without even parsing it.
964 ** More elegant would be to re-schedule the
965 ** poll, but I do not know (yet) how to do
969 /* BLA ns_since_pps = ncc_tstmp(rbufp, &trtmp); */
970 /* if (up->polled && ns_since_pps > -1 && ns_since_pps < 150) { */
973 if (up->polled && ns_since_pps < 150) {
974 msyslog(LOG_INFO, "%s(): up->polled",
976 ripencc_poll(up->unit, peer);
981 * Parse primary utc time packet
982 * and fill refclock structure
985 if (parse0x8FAD(&rpt, peer) < 0) {
986 msyslog(LOG_INFO, "%s(): parse0x8FAD < 0",__FUNCTION__);
987 refclock_report(peer, CEVNT_BADREPLY);
991 * If the PPSAPI is working, rather use its
993 * assume that the PPS occurs on the second
996 if (ripencc_get_pps_ts(up, &rd_tmp) == 1) {
997 pp->lastrec = up->tstamp = rd_tmp;
1001 msyslog(LOG_INFO, "%s(): ripencc_get_pps_ts returns failure\n",__FUNCTION__);
1005 msyslog(LOG_INFO, "%s(): unrequested packet\n",__FUNCTION__);
1006 /* unrequested packet */
1010 /* we have been polled ! */
1014 /* poll for next packet */
1016 ripencc_send(peer,spt);
1018 if (ns_since_pps < 0) { /* no PPS */
1019 msyslog(LOG_INFO, "%s(): ns_since_pps < 0",__FUNCTION__);
1020 refclock_report(peer, CEVNT_BADTIME);
1025 ** Process the new sample in the median
1026 ** filter and determine the reference clock
1027 ** offset and dispersion.
1029 if (!refclock_process(pp)) {
1030 msyslog(LOG_INFO, "%s(): !refclock_process",__FUNCTION__);
1031 refclock_report(peer, CEVNT_BADTIME);
1035 refclock_receive(peer);
1038 case 0x0B: /* comprehensive time packet */
1039 parse0x8F0B(&rpt, peer);
1042 default: /* other superpackets */
1044 msyslog(LOG_INFO, "%s(): calling parseany",
1046 #endif /* DEBUG_NCC */
1047 #ifdef TRIMBLE_OUTPUT_FUNC
1048 parseany(&rpt, peer);
1049 #endif /* TRIMBLE_OUTPUT_FUNC */
1054 case 0x4F: /* UTC parameters, for leap info */
1055 parse0x4F(&rpt, peer);
1058 case 0x5C: /* sat tracking data */
1059 parse0x5C(&rpt, peer);
1062 default: /* other packets */
1063 #ifdef TRIMBLE_OUTPUT_FUNC
1064 parseany(&rpt, peer);
1065 #endif /* TRIMBLE_OUTPUT_FUNC */
1068 rpt.status = TSIP_PARSED_EMPTY;
1073 * All trimble functions that are directly referenced from driver code
1074 * (so not from parseany)
1077 /* request software versions */
1087 /* request receiver health */
1097 /* request UTC params */
1107 /* set serial I/O options */
1111 unsigned char pos_code,
1112 unsigned char vel_code,
1113 unsigned char time_code,
1114 unsigned char opts_code
1117 cmd->buf[0] = pos_code;
1118 cmd->buf[1] = vel_code;
1119 cmd->buf[2] = time_code;
1120 cmd->buf[3] = opts_code;
1125 /* request tracking status */
1129 unsigned char sv_prn
1132 cmd->buf[0] = sv_prn;
1137 /* set Channel A configuration for dual-port operation */
1141 unsigned char baud_out,
1142 unsigned char baud_inp,
1143 unsigned char char_code,
1144 unsigned char stopbitcode,
1145 unsigned char output_mode,
1146 unsigned char input_mode
1149 cmd->buf[0] = baud_out; /* XMT baud rate */
1150 cmd->buf[1] = baud_inp; /* RCV baud rate */
1151 cmd->buf[2] = char_code; /* parity and #bits per byte */
1152 cmd->buf[3] = stopbitcode; /* number of stop bits code */
1153 cmd->buf[4] = output_mode; /* Ch. A transmission mode */
1154 cmd->buf[5] = input_mode; /* Ch. A reception mode */
1160 /* query primary configuration */
1164 unsigned char subcode
1169 cmd->buf[0] = subcode;
1173 /**** Superpackets ****/
1174 /* 8E-0B to query 8F-0B controls */
1186 /* 8F-41 to query board serial number */
1198 /* 8F-42 to query product serial number */
1210 /* 8F-4A to query PPS parameters */
1222 /* set i/o options */
1226 unsigned char PPSOnOff,
1227 unsigned char TimeBase,
1228 unsigned char Polarity,
1236 cmd->buf[1] = PPSOnOff;
1237 cmd->buf[2] = TimeBase;
1238 cmd->buf[3] = Polarity;
1239 bPutDouble (&PPSOffset, &cmd->buf[4]);
1240 bPutFloat (&Uncertainty, &cmd->buf[12]);
1243 /* 8F-4B query survey limit */
1254 /* poll for UTC superpacket */
1255 /* 8E-AD to query 8F-AD controls */
1266 /* all outomatic packet output off */
1270 unsigned long AutoOutputMask
1276 bPutULong (&AutoOutputMask, &cmd->buf[1]);
1281 * for DOS machines, reverse order of bytes as they come through the
1291 unsigned char *optr;
1293 optr = (unsigned char*)&outval + 1;
1299 #ifdef TRIMBLE_OUTPUT_FUNC
1300 static unsigned short
1305 unsigned short outval;
1306 unsigned char *optr;
1308 optr = (unsigned char*)&outval + 1;
1320 unsigned char *optr;
1322 optr = (unsigned char*)&outval + 3;
1330 static unsigned long
1335 unsigned long outval;
1336 unsigned char *optr;
1338 optr = (unsigned char*)&outval + 3;
1345 #endif /* TRIMBLE_OUTPUT_FUNC */
1353 unsigned char *optr;
1355 optr = (unsigned char*)&outval + 3;
1369 unsigned char *optr;
1371 optr = (unsigned char*)&outval + 7;
1383 #else /* not BYTESWAP */
1385 #define bGetShort(bp) (*(short*)(bp))
1386 #define bGetLong(bp) (*(long*)(bp))
1387 #define bGetULong(bp) (*(unsigned long*)(bp))
1388 #define bGetSingle(bp) (*(float*)(bp))
1389 #define bGetDouble(bp) (*(double*)(bp))
1391 #endif /* BYTESWAP */
1393 * Byte-reversal is necessary for little-endian (Intel-based) machines.
1394 * TSIP streams are Big-endian (Motorola-based).
1404 unsigned char *inptr;
1406 inptr = (unsigned char*)in + 3;
1419 unsigned char *inptr;
1421 inptr = (unsigned char*)in + 3;
1434 unsigned char *inptr;
1436 inptr = (unsigned char*)in + 7;
1447 #else /* not BYTESWAP */
1449 void bPutShort (short a, unsigned char *cmdbuf) {*(short*) cmdbuf = a;}
1450 void bPutULong (long a, unsigned char *cmdbuf) {*(long*) cmdbuf = a;}
1451 void bPutFloat (float a, unsigned char *cmdbuf) {*(float*) cmdbuf = a;}
1452 void bPutDouble (double a, unsigned char *cmdbuf){*(double*) cmdbuf = a;}
1454 #endif /* BYTESWAP */
1457 * Parse primary utc time packet
1458 * and fill refclock structure
1471 register struct refclockproc *pp;
1472 register struct ripencc_unit *up;
1474 unsigned day, month, year; /* data derived from received timecode */
1475 unsigned hour, minute, second;
1476 unsigned char trackstat, utcflags;
1478 static char logbuf[1024]; /* logging string buffer */
1488 if (bGetShort(&buf[1]) != 0) {
1491 printf("parse0x8FAD: event count != 0\n");
1492 #endif /* DEBUG_NCC */
1496 if (bGetDouble(&buf[3]) != 0.0) {
1499 printf("parse0x8FAD: fracsecs != 0\n");
1500 #endif /* DEBUG_NCC */
1504 hour = (unsigned int) buf[11];
1505 minute = (unsigned int) buf[12];
1506 second = (unsigned int) buf[13];
1507 day = (unsigned int) buf[14];
1508 month = (unsigned int) buf[15];
1509 year = bGetShort(&buf[16]);
1510 trackstat = buf[18];
1514 sprintf(logbuf, "U1 %d.%d.%d %02d:%02d:%02d %d %02x",
1515 day, month, year, hour, minute, second, trackstat, utcflags);
1520 #endif /* DEBUG_NCC */
1522 record_clock_stats(&peer->srcadr, logbuf);
1524 if (!utcflags & UTCF_UTC_AVAIL)
1527 /* poll for UTC parameters once and then if UTC flag changed */
1528 up = (struct ripencc_unit *) pp->unitptr;
1529 if (utcflags != up->utcflags) {
1530 TSIPPKT spt; /* local structure for send packet */
1531 cmd_0x2F (&spt); /* request UTC params */
1532 ripencc_send(peer,spt);
1533 up->utcflags = utcflags;
1537 * If we hit the leap second, we choose to skip this sample
1538 * rather than rely on other code to be perfectly correct.
1539 * No offense, just defense ;-).
1544 /* now check and convert the time we received */
1547 if (month < 1 || month > 12 || day < 1 || day > 31)
1550 if (pp->year % 4) { /* XXX: use is_leapyear() ? */
1551 if (day > day1tab[month - 1])
1553 for (i = 0; i < month - 1; i++)
1556 if (day > day2tab[month - 1])
1558 for (i = 0; i < month - 1; i++)
1563 pp->minute = minute;
1564 pp-> second = second;
1567 if ((utcflags&UTCF_LEAP_PNDG) && up->leapdelta != 0)
1568 pp-> leap = (up->leapdelta > 0)
1572 pp-> leap = LEAP_NOWARNING;
1578 * Parse comprehensive time packet
1590 register struct refclockproc *pp;
1592 unsigned day, month, year; /* data derived from received timecode */
1593 unsigned hour, minute, second;
1597 float biasunc, rateunc;
1598 double lat, lon, alt;
1599 short lat_deg, lon_deg;
1600 float lat_min, lon_min;
1601 unsigned char north_south, east_west;
1604 static char logbuf[1024]; /* logging string buffer */
1616 if (bGetShort(&buf[1]) != 0)
1619 tow = bGetDouble(&buf[3]);
1624 else if ((tow >= 604800.0) || (tow < 0.0)) {
1629 if (tow < 604799.9) tow = tow + .00000001;
1630 second = (unsigned int) fmod(tow, 60.);
1631 minute = (unsigned int) fmod(tow/60., 60.);
1632 hour = (unsigned int )fmod(tow / 3600., 24.);
1635 day = (unsigned int) buf[11];
1636 month = (unsigned int) buf[12];
1637 year = bGetShort(&buf[13]);
1639 utcoff = bGetShort(&buf[16]);
1640 bias = bGetDouble(&buf[18]) / GPS_C * 1e9; /* ns */
1641 rate = bGetDouble(&buf[26]) / GPS_C * 1e9; /* ppb */
1642 biasunc = bGetSingle(&buf[34]) / GPS_C * 1e9; /* ns */
1643 rateunc = bGetSingle(&buf[38]) / GPS_C * 1e9; /* ppb */
1644 lat = bGetDouble(&buf[42]) * R2D;
1645 lon = bGetDouble(&buf[50]) * R2D;
1646 alt = bGetDouble(&buf[58]);
1655 lat_deg = (short)lat;
1656 lat_min = (lat - lat_deg) * 60.0;
1666 lon_deg = (short)lon;
1667 lon_min = (lon - lon_deg) * 60.0;
1669 for (i=0; i<8; i++) {
1670 sv[i] = buf[i + 66];
1672 TSIPPKT spt; /* local structure for sendpacket */
1673 b = (unsigned char) (sv[i]<0 ? -sv[i] : sv[i]);
1674 /* request tracking status */
1676 ripencc_send(peer,spt);
1681 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",
1682 day, month, year, hour, minute, second, mode, bias, biasunc,
1683 rate, rateunc, utcoff, lat_deg, lat_min, north_south, lon_deg,
1684 lon_min, east_west, alt, sv[0], sv[1], sv[2], sv[3], sv[4],
1685 sv[5], sv[6], sv[7]);
1690 #endif /* DEBUG_NCC */
1692 record_clock_stats(&peer->srcadr, logbuf);
1697 #ifdef TRIMBLE_OUTPUT_FUNC
1699 * Parse any packet using Trimble machinery
1707 static char logbuf[1024]; /* logging string buffer */
1709 TranslateTSIPReportToText (rpt, logbuf); /* anything else */
1713 #endif /* DEBUG_NCC */
1714 record_clock_stats(&peer->srcadr, &logbuf[1]);
1717 #endif /* TRIMBLE_OUTPUT_FUNC */
1721 * Parse UTC Parameter Packet
1723 * See the IDE for documentation!
1735 register struct ripencc_unit *up;
1739 int dt_ls, wn_t, wn_lsf, dn, dt_lsf;
1741 static char logbuf[1024]; /* logging string buffer */
1748 a0 = bGetDouble (buf);
1749 a1 = bGetSingle (&buf[8]);
1750 dt_ls = bGetShort (&buf[12]);
1751 tot = bGetSingle (&buf[14]);
1752 wn_t = bGetShort (&buf[18]);
1753 wn_lsf = bGetShort (&buf[20]);
1754 dn = bGetShort (&buf[22]);
1755 dt_lsf = bGetShort (&buf[24]);
1757 sprintf(logbuf, "L1 %d %d %d %g %g %g %d %d %d",
1758 dt_lsf - dt_ls, dt_ls, dt_lsf, a0, a1, tot, wn_t, wn_lsf, dn);
1763 #endif /* DEBUG_NCC */
1765 record_clock_stats(&peer->srcadr, logbuf);
1767 up = (struct ripencc_unit *) peer->procptr->unitptr;
1768 up->leapdelta = dt_lsf - dt_ls;
1774 * Parse Tracking Status packet
1786 unsigned char prn, channel, aqflag, ephstat;
1787 float snr, azinuth, elevation;
1789 static char logbuf[1024]; /* logging string buffer */
1798 channel = (unsigned char)(buf[1] >> 3);
1799 if (channel == 0x10)
1805 snr = bGetSingle(&buf[4]);
1806 elevation = bGetSingle(&buf[12]) * R2D;
1807 azinuth = bGetSingle(&buf[16]) * R2D;
1809 sprintf(logbuf, "S1 %02d %d %d %02x %4.1f %5.1f %4.1f",
1810 prn, channel, aqflag, ephstat, snr, azinuth, elevation);
1815 #endif /* DEBUG_NCC */
1817 record_clock_stats(&peer->srcadr, logbuf);
1822 /******* Code below is from Trimble Tsipchat *************/
1825 * *************************************************************************
1827 * Trimble Navigation, Ltd.
1828 * OEM Products Development Group
1830 * 645 North Mary Avenue
1831 * Sunnyvale, California 94088-3642
1833 * Corporate Headquarter:
1834 * Telephone: (408) 481-8000
1835 * Fax: (408) 481-6005
1837 * Technical Support Center:
1838 * Telephone: (800) 767-4822 (U.S. and Canada)
1839 * (408) 481-6940 (outside U.S. and Canada)
1840 * Fax: (408) 481-6020
1841 * BBS: (408) 481-7800
1842 * e-mail: trimble_support@trimble.com
1843 * ftp://ftp.trimble.com/pub/sct/embedded/bin
1845 * *************************************************************************
1847 * ------- BYTE-SWAPPING -------
1848 * TSIP is big-endian (Motorola) protocol. To use on little-endian (Intel)
1849 * systems, the bytes of all multi-byte types (shorts, floats, doubles, etc.)
1850 * must be reversed. This is controlled by the MACRO BYTESWAP; if defined, it
1851 * assumes little-endian protocol.
1852 * --------------------------------
1854 * T_PARSER.C and T_PARSER.H contains primitive functions that interpret
1855 * reports received from the receiver. A second source file pair,
1856 * T_FORMAT.C and T_FORMAT.H, contin the matching TSIP command formatters.
1858 * The module is in very portable, basic C language. It can be used as is, or
1859 * with minimal changes if a TSIP communications application is needed separate
1860 * from TSIPCHAT. The construction of most argument lists avoid the use of
1861 * structures, but the developer is encouraged to reconstruct them using such
1862 * definitions to meet project requirements. Declarations of T_PARSER.C
1863 * functions are included in T_PARSER.H to provide prototyping definitions.
1865 * There are two types of functions: a serial input processing routine,
1867 * which assembles incoming bytes into a TSIPPKT structure, and the
1868 * report parsers, rpt_0x??().
1870 * 1) The function tsip_input_proc() accumulates bytes from the receiver,
1871 * strips control bytes (DLE), and checks if the report end sequence (DLE ETX)
1872 * has been received. rpt.status is defined as TSIP_PARSED_FULL (== 1)
1873 * if a complete packet is available.
1875 * 2) The functions rpt_0x??() are report string interpreters patterned after
1876 * the document called "Trimble Standard Interface Protocol". It should be
1877 * noted that if the report buffer is sent into the receiver with the wrong
1878 * length (byte count), the rpt_0x??() returns the Boolean equivalence for
1881 * *************************************************************************
1887 * reads bytes until serial buffer is empty or a complete report
1888 * has been received; end of report is signified by DLE ETX.
1896 unsigned char newbyte;
1898 if (inbyte < 0 || inbyte > 0xFF) return;
1900 newbyte = (unsigned char)(inbyte);
1901 switch (rpt->status)
1903 case TSIP_PARSED_DLE_1:
1908 /* illegal TSIP IDs */
1910 rpt->status = TSIP_PARSED_EMPTY;
1913 /* try normal message start again */
1915 rpt->status = TSIP_PARSED_DLE_1;
1918 /* legal TSIP ID; start message */
1919 rpt->code = newbyte;
1921 rpt->status = TSIP_PARSED_DATA;
1925 case TSIP_PARSED_DATA:
1928 /* expect DLE or ETX next */
1929 rpt->status = TSIP_PARSED_DLE_2;
1932 /* normal data byte */
1933 rpt->buf[rpt->len] = newbyte;
1935 /* no change in rpt->status */
1939 case TSIP_PARSED_DLE_2:
1942 /* normal data byte */
1943 rpt->buf[rpt->len] = newbyte;
1945 rpt->status = TSIP_PARSED_DATA;
1948 /* end of message; return TRUE here. */
1949 rpt->status = TSIP_PARSED_FULL;
1952 /* error: treat as TSIP_PARSED_DLE_1; start new report packet */
1953 rpt->code = newbyte;
1955 rpt->status = TSIP_PARSED_DATA;
1958 case TSIP_PARSED_FULL:
1959 case TSIP_PARSED_EMPTY:
1963 /* normal message start */
1965 rpt->status = TSIP_PARSED_DLE_1;
1968 /* error: ignore newbyte */
1970 rpt->status = TSIP_PARSED_EMPTY;
1974 if (rpt->len > MAX_RPTBUF) {
1975 /* error: start new report packet */
1976 rpt->status = TSIP_PARSED_EMPTY;
1981 #ifdef TRIMBLE_OUTPUT_FUNC
1984 /* Channel A configuration for dual port operation */
1988 unsigned char *tx_baud_index,
1989 unsigned char *rx_baud_index,
1990 unsigned char *char_format_index,
1991 unsigned char *stop_bits,
1992 unsigned char *tx_mode_index,
1993 unsigned char *rx_mode_index
1999 if (rpt->len != 6) return TRUE;
2000 *tx_baud_index = buf[0];
2001 *rx_baud_index = buf[1];
2002 *char_format_index = buf[2];
2003 *stop_bits = (unsigned char)((buf[3] == 0x07) ? 1 : 2);
2004 *tx_mode_index = buf[4];
2005 *rx_mode_index = buf[5];
2010 /* almanac data for specified satellite */
2014 unsigned char *sv_prn,
2017 float *eccentricity,
2030 if (rpt->len != 39) return TRUE;
2032 *t_zc = bGetSingle (&buf[1]);
2033 *week_num = bGetShort (&buf[5]);
2034 *eccentricity = bGetSingle (&buf[7]);
2035 *t_oa = bGetSingle (&buf[11]);
2036 *i_0 = bGetSingle (&buf[15]);
2037 *OMEGA_dot = bGetSingle (&buf[19]);
2038 *sqrt_A = bGetSingle (&buf[23]);
2039 *OMEGA_0 = bGetSingle (&buf[27]);
2040 *omega = bGetSingle (&buf[31]);
2041 *M_0 = bGetSingle (&buf[35]);
2049 float *time_of_week,
2057 if (rpt->len != 10) return TRUE;
2058 *time_of_week = bGetSingle (buf);
2059 *week_num = bGetShort (&buf[4]);
2060 *UTC_offset = bGetSingle (&buf[6]);
2064 /* position in ECEF, single precision */
2075 if (rpt->len != 16) return TRUE;
2076 pos_ECEF[0] = bGetSingle (buf);
2077 pos_ECEF[1]= bGetSingle (&buf[4]);
2078 pos_ECEF[2]= bGetSingle (&buf[8]);
2079 *time_of_fix = bGetSingle (&buf[12]);
2083 /* velocity in ECEF, single precision */
2095 if (rpt->len != 20) return TRUE;
2096 ECEF_vel[0] = bGetSingle (buf);
2097 ECEF_vel[1] = bGetSingle (&buf[4]);
2098 ECEF_vel[2] = bGetSingle (&buf[8]);
2099 *freq_offset = bGetSingle (&buf[12]);
2100 *time_of_fix = bGetSingle (&buf[16]);
2104 /* software versions */
2108 unsigned char *major_nav_version,
2109 unsigned char *minor_nav_version,
2110 unsigned char *nav_day,
2111 unsigned char *nav_month,
2112 unsigned char *nav_year,
2113 unsigned char *major_dsp_version,
2114 unsigned char *minor_dsp_version,
2115 unsigned char *dsp_day,
2116 unsigned char *dsp_month,
2117 unsigned char *dsp_year
2123 if (rpt->len != 10) return TRUE;
2124 *major_nav_version = buf[0];
2125 *minor_nav_version = buf[1];
2127 *nav_month = buf[3];
2129 *major_dsp_version = buf[5];
2130 *minor_dsp_version = buf[6];
2132 *dsp_month = buf[8];
2137 /* receiver health and status */
2141 unsigned char *status1,
2142 unsigned char *status2
2148 if (rpt->len != 2) return TRUE;
2154 /* signal levels for all satellites tracked */
2158 unsigned char *nsvs,
2159 unsigned char *sv_prn,
2167 if (rpt->len != 1 + 5*buf[0]) return TRUE;
2169 for (isv = 0; isv < (*nsvs); isv++) {
2170 sv_prn[isv] = buf[5*isv + 1];
2171 snr[isv] = bGetSingle (&buf[5*isv + 2]);
2176 /* GPS system message */
2180 unsigned char *message
2186 if (rpt->len != 22) return TRUE;
2187 memcpy (message, buf, 22);
2192 /* health for all satellites from almanac health page */
2196 unsigned char *sv_health
2203 if (rpt->len != 32) return TRUE;
2204 for (i = 0; i < 32; i++) sv_health [i]= buf[i];
2208 /* position in lat-lon-alt, single precision */
2222 if (rpt->len != 20) return TRUE;
2223 *lat = bGetSingle (buf);
2224 *lon = bGetSingle (&buf[4]);
2225 *alt = bGetSingle (&buf[8]);
2226 *clock_bias = bGetSingle (&buf[12]);
2227 *time_of_fix = bGetSingle (&buf[16]);
2231 /* reference altitude parameters */
2237 unsigned char *alt_flag
2244 if (rpt->len != 9) return TRUE;
2245 *alt = bGetSingle (buf);
2246 *dummy = bGetSingle (&buf[4]);
2251 /* machine ID code, status */
2255 unsigned char *machine_id,
2256 unsigned char *status3,
2257 unsigned char *status4
2263 if (rpt->len != 3) return TRUE;
2264 *machine_id = buf[0];
2270 /* operating parameters and masks */
2274 unsigned char *dyn_code,
2284 if (rpt->len != 17) return TRUE;
2286 *el_mask = bGetSingle (&buf[1]);
2287 *snr_mask = bGetSingle (&buf[5]);
2288 *dop_mask = bGetSingle (&buf[9]);
2289 *dop_switch = bGetSingle (&buf[13]);
2293 /* oscillator offset */
2303 if (rpt->len != 4) return TRUE;
2304 *osc_offset = bGetSingle (buf);
2308 /* yes/no response to command to set GPS time */
2312 unsigned char *response
2318 if (rpt->len != 1) return TRUE;
2329 float *time_of_data,
2340 if (rpt->len != 26) return TRUE;
2341 *a0 = bGetDouble (buf);
2342 *a1 = bGetSingle (&buf[8]);
2343 *dt_ls = bGetShort (&buf[12]);
2344 *time_of_data = bGetSingle (&buf[14]);
2345 *wn_t = bGetShort (&buf[18]);
2346 *wn_lsf = bGetShort (&buf[20]);
2347 *dn = bGetShort (&buf[22]);
2348 *dt_lsf = bGetShort (&buf[24]);
2353 /* clock offset and frequency offset in 1-SV (0-D) mode */
2365 if (rpt->len != 12) return TRUE;
2366 *clock_bias = bGetSingle (buf);
2367 *freq_offset = bGetSingle (&buf[4]);
2368 *time_of_fix = bGetSingle (&buf[8]);
2372 /* I/O serial options */
2376 unsigned char *pos_code,
2377 unsigned char *vel_code,
2378 unsigned char *time_code,
2379 unsigned char *aux_code
2385 if (rpt->len != 4) return TRUE;
2388 *time_code = buf[2];
2393 /* velocity in east-north-up coordinates */
2405 if (rpt->len != 20) return TRUE;
2407 vel_ENU[0] = bGetSingle (buf);
2409 vel_ENU[1] = bGetSingle (&buf[4]);
2411 vel_ENU[2] = bGetSingle (&buf[8]);
2412 *freq_offset = bGetSingle (&buf[12]);
2413 *time_of_fix = bGetSingle (&buf[16]);
2417 /* info about last computed fix */
2421 unsigned char *source_code,
2422 unsigned char *diag_code,
2430 if (rpt->len != 8) return TRUE;
2431 *source_code = buf[0];
2432 *diag_code = buf[1];
2433 *time_of_fix = bGetSingle (&buf[2]);
2434 *week_num = bGetShort (&buf[6]);
2438 /* GPS system data or acknowledgment of GPS system data load */
2442 unsigned char *op_code,
2443 unsigned char *data_type,
2444 unsigned char *sv_prn,
2445 unsigned char *data_length,
2446 unsigned char *data_packet
2449 unsigned char *buf, *buf4;
2459 if (rpt->len < 4) return TRUE;
2460 if (rpt->len != 4+buf[3]) return TRUE;
2462 else if (rpt->len != 3) {
2466 *data_type = buf[1];
2468 if (*op_code == 2) {
2470 *data_length = (unsigned char)dl;
2472 switch (*data_type) {
2475 if (*data_length != sizeof (ALM_INFO)) return TRUE;
2476 alminfo = (ALM_INFO*)data_packet;
2477 alminfo->t_oa_raw = buf4[0];
2478 alminfo->SV_health = buf4[1];
2479 alminfo->e = bGetSingle(&buf4[2]);
2480 alminfo->t_oa = bGetSingle(&buf4[6]);
2481 alminfo->i_0 = bGetSingle(&buf4[10]);
2482 alminfo->OMEGADOT = bGetSingle(&buf4[14]);
2483 alminfo->sqrt_A = bGetSingle(&buf4[18]);
2484 alminfo->OMEGA_0 = bGetSingle(&buf4[22]);
2485 alminfo->omega = bGetSingle(&buf4[26]);
2486 alminfo->M_0 = bGetSingle(&buf4[30]);
2487 alminfo->a_f0 = bGetSingle(&buf4[34]);
2488 alminfo->a_f1 = bGetSingle(&buf4[38]);
2489 alminfo->Axis = bGetSingle(&buf4[42]);
2490 alminfo->n = bGetSingle(&buf4[46]);
2491 alminfo->OMEGA_n = bGetSingle(&buf4[50]);
2492 alminfo->ODOT_n = bGetSingle(&buf4[54]);
2493 alminfo->t_zc = bGetSingle(&buf4[58]);
2494 alminfo->weeknum = bGetShort(&buf4[62]);
2495 alminfo->wn_oa = bGetShort(&buf4[64]);
2499 /* Almanac health page */
2500 if (*data_length != sizeof (ALH_PARMS) + 3) return TRUE;
2502 /* this record is returned raw */
2503 memcpy (data_packet, buf4, dl);
2508 if (*data_length != sizeof (ION_INFO) + 8) return TRUE;
2509 ioninfo = (ION_INFO*)data_packet;
2510 ioninfo->alpha_0 = bGetSingle (&buf4[8]);
2511 ioninfo->alpha_1 = bGetSingle (&buf4[12]);
2512 ioninfo->alpha_2 = bGetSingle (&buf4[16]);
2513 ioninfo->alpha_3 = bGetSingle (&buf4[20]);
2514 ioninfo->beta_0 = bGetSingle (&buf4[24]);
2515 ioninfo->beta_1 = bGetSingle (&buf4[28]);
2516 ioninfo->beta_2 = bGetSingle (&buf4[32]);
2517 ioninfo->beta_3 = bGetSingle (&buf4[36]);
2522 if (*data_length != sizeof (UTC_INFO) + 13) return TRUE;
2523 utcinfo = (UTC_INFO*)data_packet;
2524 utcinfo->A_0 = bGetDouble (&buf4[13]);
2525 utcinfo->A_1 = bGetSingle (&buf4[21]);
2526 utcinfo->delta_t_LS = bGetShort (&buf4[25]);
2527 utcinfo->t_ot = bGetSingle(&buf4[27]);
2528 utcinfo->WN_t = bGetShort (&buf4[31]);
2529 utcinfo->WN_LSF = bGetShort (&buf4[33]);
2530 utcinfo->DN = bGetShort (&buf4[35]);
2531 utcinfo->delta_t_LSF = bGetShort (&buf4[37]);
2536 if (*data_length != sizeof (NAV_INFO) - 1) return TRUE;
2538 navinfo = (NAV_INFO*)data_packet;
2540 navinfo->sv_number = buf4[0];
2541 navinfo->t_ephem = bGetSingle (&buf4[1]);
2542 navinfo->ephclk.weeknum = bGetShort (&buf4[5]);
2544 navinfo->ephclk.codeL2 = buf4[7];
2545 navinfo->ephclk.L2Pdata = buf4[8];
2546 navinfo->ephclk.SVacc_raw = buf4[9];
2547 navinfo->ephclk.SV_health = buf4[10];
2548 navinfo->ephclk.IODC = bGetShort (&buf4[11]);
2549 navinfo->ephclk.T_GD = bGetSingle (&buf4[13]);
2550 navinfo->ephclk.t_oc = bGetSingle (&buf4[17]);
2551 navinfo->ephclk.a_f2 = bGetSingle (&buf4[21]);
2552 navinfo->ephclk.a_f1 = bGetSingle (&buf4[25]);
2553 navinfo->ephclk.a_f0 = bGetSingle (&buf4[29]);
2554 navinfo->ephclk.SVacc = bGetSingle (&buf4[33]);
2556 navinfo->ephorb.IODE = buf4[37];
2557 navinfo->ephorb.fit_interval = buf4[38];
2558 navinfo->ephorb.C_rs = bGetSingle (&buf4[39]);
2559 navinfo->ephorb.delta_n = bGetSingle (&buf4[43]);
2560 navinfo->ephorb.M_0 = bGetDouble (&buf4[47]);
2561 navinfo->ephorb.C_uc = bGetSingle (&buf4[55]);
2562 navinfo->ephorb.e = bGetDouble (&buf4[59]);
2563 navinfo->ephorb.C_us = bGetSingle (&buf4[67]);
2564 navinfo->ephorb.sqrt_A = bGetDouble (&buf4[71]);
2565 navinfo->ephorb.t_oe = bGetSingle (&buf4[79]);
2566 navinfo->ephorb.C_ic = bGetSingle (&buf4[83]);
2567 navinfo->ephorb.OMEGA_0 = bGetDouble (&buf4[87]);
2568 navinfo->ephorb.C_is = bGetSingle (&buf4[95]);
2569 navinfo->ephorb.i_0 = bGetDouble (&buf4[99]);
2570 navinfo->ephorb.C_rc = bGetSingle (&buf4[107]);
2571 navinfo->ephorb.omega = bGetDouble (&buf4[111]);
2572 navinfo->ephorb.OMEGADOT=bGetSingle (&buf4[119]);
2573 navinfo->ephorb.IDOT = bGetSingle (&buf4[123]);
2574 navinfo->ephorb.Axis = bGetDouble (&buf4[127]);
2575 navinfo->ephorb.n = bGetDouble (&buf4[135]);
2576 navinfo->ephorb.r1me2 = bGetDouble (&buf4[143]);
2577 navinfo->ephorb.OMEGA_n=bGetDouble (&buf4[151]);
2578 navinfo->ephorb.ODOT_n = bGetDouble (&buf4[159]);
2585 /* satellite enable/disable or health heed/ignore list */
2589 unsigned char *code_type,
2590 unsigned char status_code[32]
2597 if (rpt->len != 33) return TRUE;
2598 *code_type = buf[0];
2599 for (iprn = 0; iprn < 32; iprn++)
2600 status_code[iprn] = buf[iprn + 1];
2604 /* raw measurement data - code phase/Doppler */
2608 unsigned char *sv_prn,
2609 float *sample_length,
2610 float *signal_level,
2619 if (rpt->len != 25) return TRUE;
2621 *sample_length = bGetSingle (&buf[1]);
2622 *signal_level = bGetSingle (&buf[5]);
2623 *code_phase = bGetSingle (&buf[9]);
2624 *Doppler = bGetSingle (&buf[13]);
2625 *time_of_fix = bGetDouble (&buf[17]);
2629 /* satellite ephorb status */
2633 unsigned char *sv_prn,
2634 unsigned char *sv_health,
2635 unsigned char *sv_iode,
2636 unsigned char *fit_interval_flag,
2637 float *time_of_collection,
2645 if (rpt->len != 16) return TRUE;
2647 *time_of_collection = bGetSingle (&buf[1]);
2648 *sv_health = buf[5];
2650 *time_of_eph = bGetSingle (&buf[7]);
2651 *fit_interval_flag = buf[11];
2652 *sv_accy = bGetSingle (&buf[12]);
2656 /* satellite tracking status */
2660 unsigned char *sv_prn,
2661 unsigned char *slot,
2662 unsigned char *chan,
2663 unsigned char *acq_flag,
2664 unsigned char *eph_flag,
2665 float *signal_level,
2666 float *time_of_last_msmt,
2669 unsigned char *old_msmt_flag,
2670 unsigned char *integer_msec_flag,
2671 unsigned char *bad_data_flag,
2672 unsigned char *data_collect_flag
2678 if (rpt->len != 24) return TRUE;
2680 *slot = (unsigned char)((buf[1] & 0x07) + 1);
2681 *chan = (unsigned char)(buf[1] >> 3);
2682 if (*chan == 0x10) *chan = 2;
2686 *signal_level = bGetSingle (&buf[4]);
2687 *time_of_last_msmt = bGetSingle (&buf[8]);
2688 *elev = bGetSingle (&buf[12]);
2689 *azim = bGetSingle (&buf[16]);
2690 *old_msmt_flag = buf[20];
2691 *integer_msec_flag = buf[21];
2692 *bad_data_flag = buf[22];
2693 *data_collect_flag = buf[23];
2698 /* over-determined satellite selection for position fixes, PDOP, fix mode */
2702 unsigned char *manual_mode,
2703 unsigned char *nsvs,
2704 unsigned char *ndim,
2705 unsigned char sv_prn[],
2716 *nsvs = (unsigned char)((buf[0] & 0xF0) >> 4);
2717 if ((*nsvs)>8) return TRUE;
2718 if (rpt->len != 17 + (*nsvs) ) return TRUE;
2720 *manual_mode = (unsigned char)(buf[0] & 0x08);
2721 *ndim = (unsigned char)((buf[0] & 0x07));
2722 *pdop = bGetSingle (&buf[1]);
2723 *hdop = bGetSingle (&buf[5]);
2724 *vdop = bGetSingle (&buf[9]);
2725 *tdop = bGetSingle (&buf[13]);
2726 for (islot = 0; islot < (*nsvs); islot++)
2727 sv_prn[islot] = buf[islot + 17];
2732 /* differential fix mode */
2736 unsigned char *diff_mode
2742 if (rpt->len != 1) return TRUE;
2743 *diff_mode = buf[0];
2747 /* position, ECEF double precision */
2759 if (rpt->len != 36) return TRUE;
2760 ECEF_pos[0] = bGetDouble (buf);
2761 ECEF_pos[1] = bGetDouble (&buf[8]);
2762 ECEF_pos[2] = bGetDouble (&buf[16]);
2763 *clock_bias = bGetDouble (&buf[24]);
2764 *time_of_fix = bGetSingle (&buf[32]);
2768 /* position, lat-lon-alt double precision */
2782 if (rpt->len != 36) return TRUE;
2783 *lat = bGetDouble (buf);
2784 *lon = bGetDouble (&buf[8]);
2785 *alt = bGetDouble (&buf[16]);
2786 *clock_bias = bGetDouble (&buf[24]);
2787 *time_of_fix = bGetSingle (&buf[32]);
2794 TSIP_RCVR_CFG *TsipxBB
2800 /* Palisade is inconsistent with other TSIP, which has a length of 40 */
2801 /* if (rpt->len != 40) return TRUE; */
2802 if (rpt->len != 43) return TRUE;
2804 TsipxBB->bSubcode = buf[0];
2805 TsipxBB->operating_mode = buf[1];
2806 TsipxBB->dyn_code = buf[3];
2807 TsipxBB->elev_mask = bGetSingle (&buf[5]);
2808 TsipxBB->cno_mask = bGetSingle (&buf[9]);
2809 TsipxBB->dop_mask = bGetSingle (&buf[13]);
2810 TsipxBB->dop_switch = bGetSingle (&buf[17]);
2814 /* Receiver serial port configuration */
2818 unsigned char *port_num,
2819 unsigned char *in_baud,
2820 unsigned char *out_baud,
2821 unsigned char *data_bits,
2822 unsigned char *parity,
2823 unsigned char *stop_bits,
2824 unsigned char *flow_control,
2825 unsigned char *protocols_in,
2826 unsigned char *protocols_out,
2827 unsigned char *reserved
2833 if (rpt->len != 10) return TRUE;
2837 *data_bits = buf[3];
2839 *stop_bits = buf[5];
2840 *flow_control = buf[6];
2841 *protocols_in = buf[7];
2842 *protocols_out = buf[8];
2848 /**** Superpackets ****/
2853 unsigned short *event,
2855 unsigned char *date,
2856 unsigned char *month,
2858 unsigned char *dim_mode,
2874 if (rpt->len != 74) return TRUE;
2875 *event = bGetShort(&buf[1]);
2876 *tow = bGetDouble(&buf[3]);
2879 *year = bGetShort(&buf[13]);
2880 *dim_mode = buf[15];
2881 *utc_offset = bGetShort(&buf[16]);
2882 *bias = bGetDouble(&buf[18]);
2883 *drift = bGetDouble(&buf[26]);
2884 *bias_unc = bGetSingle(&buf[34]);
2885 *dr_unc = bGetSingle(&buf[38]);
2886 *lat = bGetDouble(&buf[42]);
2887 *lon = bGetDouble(&buf[50]);
2888 *alt = bGetDouble(&buf[58]);
2890 for (local_index=0; local_index<8; local_index++) sv_id[local_index] = buf[local_index + 66];
2894 /* datum index and coefficients */
2899 double datum_coeffs[5]
2905 if (rpt->len != 43) return TRUE;
2906 *datum_idx = bGetShort(&buf[1]);
2907 datum_coeffs[0] = bGetDouble (&buf[3]);
2908 datum_coeffs[1] = bGetDouble (&buf[11]);
2909 datum_coeffs[2] = bGetDouble (&buf[19]);
2910 datum_coeffs[3] = bGetDouble (&buf[27]);
2911 datum_coeffs[4] = bGetDouble (&buf[35]);
2916 /* datum index and coefficients */
2921 double datum_coeffs[5]
2927 if (rpt->len != 43) return TRUE;
2928 *datum_idx = bGetShort(&buf[1]);
2929 datum_coeffs[0] = bGetDouble (&buf[3]);
2930 datum_coeffs[1] = bGetDouble (&buf[11]);
2931 datum_coeffs[2] = bGetDouble (&buf[19]);
2932 datum_coeffs[3] = bGetDouble (&buf[27]);
2933 datum_coeffs[4] = bGetDouble (&buf[35]);
2938 #define MAX_LONG (2147483648.) /* 2**31 */
2943 unsigned char *info,
2948 double *time_of_fix,
2950 unsigned char *nsvs,
2951 unsigned char sv_prn[],
2969 if (rpt->len != 56) return TRUE;
2971 vel_scale = (buf[24]&1)? 0.020 : 0.005;
2972 vel_enu[0] = bGetShort (buf+2)*vel_scale;
2973 vel_enu[1] = bGetShort (buf+4)*vel_scale;
2974 vel_enu[2] = bGetShort (buf+6)*vel_scale;
2976 *time_of_fix = bGetULong (buf+8)*.001;
2978 longtemp = bGetLong (buf+12);
2979 *lat = longtemp*(GPS_PI/MAX_LONG);
2981 ulongtemp = bGetULong (buf+16);
2982 *lon = ulongtemp*(GPS_PI/MAX_LONG);
2983 if (*lon > GPS_PI) *lon -= 2.0*GPS_PI;
2985 *alt = bGetLong (buf+20)*.001;
2986 /* 25 blank; 29 = UTC */
2987 (*datum_index) = (short)((short)buf[26]-1);
2990 *week_num = bGetShort (&buf[30]);
2991 for (isv = 0; isv < 8; isv++) {
2992 prnx = buf[32+2*isv];
2993 sv_prn[isv] = (unsigned char)(prnx&0x3F);
2994 iode = buf[33+2*isv];
2995 sv_IODC[isv] = (short)(iode | ((prnx>>6)<<8));
3003 unsigned char *bSearchRange,
3004 unsigned char *bBoardOptions,
3005 unsigned long *iiSerialNumber,
3006 unsigned char *bBuildYear,
3007 unsigned char *bBuildMonth,
3008 unsigned char *bBuildDay,
3009 unsigned char *bBuildHour,
3011 unsigned short *iTestCodeId
3014 if (rpt->len != 17) return FALSE;
3015 *bSearchRange = rpt->buf[1];
3016 *bBoardOptions = rpt->buf[2];
3017 *iiSerialNumber = bGetLong(&rpt->buf[3]);
3018 *bBuildYear = rpt->buf[7];
3019 *bBuildMonth = rpt->buf[8];
3020 *bBuildDay = rpt->buf[9];
3021 *bBuildHour = rpt->buf[10];
3022 *fOscOffset = bGetSingle(&rpt->buf[11]);
3023 *iTestCodeId = bGetShort(&rpt->buf[15]);
3024 /* Tsipx8E41Data = *Tsipx8E41; */
3031 unsigned char *bProdOptionsPre,
3032 unsigned char *bProdNumberExt,
3033 unsigned short *iCaseSerialNumberPre,
3034 unsigned long *iiCaseSerialNumber,
3035 unsigned long *iiProdNumber,
3036 unsigned short *iPremiumOptions,
3037 unsigned short *iMachineID,
3038 unsigned short *iKey
3041 if (rpt->len != 19) return FALSE;
3042 *bProdOptionsPre = rpt->buf[1];
3043 *bProdNumberExt = rpt->buf[2];
3044 *iCaseSerialNumberPre = bGetShort(&rpt->buf[3]);
3045 *iiCaseSerialNumber = bGetLong(&rpt->buf[5]);
3046 *iiProdNumber = bGetLong(&rpt->buf[9]);
3047 *iPremiumOptions = bGetShort(&rpt->buf[13]);
3048 *iMachineID = bGetShort(&rpt->buf[15]);
3049 *iKey = bGetShort(&rpt->buf[17]);
3056 unsigned char *bSegMask
3059 if (rpt->len != 2) return FALSE;
3060 *bSegMask = rpt->buf[1];
3064 /* Stinger PPS definition */
3068 unsigned char *pps_enabled,
3069 unsigned char *pps_timebase,
3070 unsigned char *pos_polarity,
3072 float *bias_unc_threshold
3079 if (rpt->len != 16) return TRUE;
3080 *pps_enabled = buf[1];
3081 *pps_timebase = buf[2];
3082 *pos_polarity = buf[3];
3083 *pps_offset = bGetDouble(&buf[4]);
3084 *bias_unc_threshold = bGetSingle(&buf[12]);
3091 unsigned long *decorr_max
3098 if (rpt->len != 5) return TRUE;
3099 *decorr_max = bGetLong(&buf[1]);
3106 unsigned long *event_mask
3113 if (rpt->len != 5) return TRUE;
3114 *event_mask = bGetULong (&buf[1]);
3121 unsigned char *spktmask
3128 if (rpt->len != 5) return TRUE;
3129 spktmask[0] = buf[1];
3130 spktmask[1] = buf[2];
3131 spktmask[2] = buf[3];
3132 spktmask[3] = buf[4];
3139 unsigned short *COUNT,
3141 unsigned char *Hour,
3142 unsigned char *Minute,
3143 unsigned char *Second,
3145 unsigned char *Month,
3146 unsigned short *Year,
3147 unsigned char *Status,
3148 unsigned char *Flags
3151 if (rpt->len != 22) return TRUE;
3153 *COUNT = bGetUShort(&rpt->buf[1]);
3154 *FracSec = bGetDouble(&rpt->buf[3]);
3155 *Hour = rpt->buf[11];
3156 *Minute = rpt->buf[12];
3157 *Second = rpt->buf[13];
3158 *Day = rpt->buf[14];
3159 *Month = rpt->buf[15];
3160 *Year = bGetUShort(&rpt->buf[16]);
3161 *Status = rpt->buf[18];
3162 *Flags = rpt->buf[19];
3168 * *************************************************************************
3170 * Trimble Navigation, Ltd.
3171 * OEM Products Development Group
3173 * 645 North Mary Avenue
3174 * Sunnyvale, California 94088-3642
3176 * Corporate Headquarter:
3177 * Telephone: (408) 481-8000
3178 * Fax: (408) 481-6005
3180 * Technical Support Center:
3181 * Telephone: (800) 767-4822 (U.S. and Canada)
3182 * (408) 481-6940 (outside U.S. and Canada)
3183 * Fax: (408) 481-6020
3184 * BBS: (408) 481-7800
3185 * e-mail: trimble_support@trimble.com
3186 * ftp://ftp.trimble.com/pub/sct/embedded/bin
3188 * *************************************************************************
3190 * T_REPORT.C consists of a primary function TranslateTSIPReportToText()
3193 * This function takes a character buffer that has been received as a report
3194 * from a TSIP device and interprets it. The character buffer has been
3195 * assembled using tsip_input_proc() in T_PARSER.C.
3197 * A large case statement directs processing to one of many mid-level
3198 * functions. The mid-level functions specific to the current report
3199 * code passes the report buffer to the appropriate report decoder
3200 * rpt_0x?? () in T_PARSER.C, which converts the byte stream in rpt.buf
3201 * to data values approporaite for use.
3203 * *************************************************************************
3208 #define GOOD_PARSE 0
3209 #define BADID_PARSE 1
3210 #define BADLEN_PARSE 2
3211 #define BADDATA_PARSE 3
3217 /* pbuf is the pointer to the current location of the text output */
3221 /* keep track of whether the message has been successfully parsed */
3226 /* convert time of week into day-hour-minute-second and print */
3232 short days, hours, minutes;
3235 static char timestring [80];
3237 if (time_of_week == -1.0)
3239 sprintf(timestring, " <No time yet> ");
3241 else if ((time_of_week >= 604800.0) || (time_of_week < 0.0))
3243 sprintf(timestring, " <Bad time> ");
3247 if (time_of_week < 604799.9)
3248 tow = time_of_week + .00000001;
3249 seconds = (float)fmod(tow, 60.);
3250 minutes = (short) fmod(tow/60., 60.);
3251 hours = (short)fmod(tow / 3600., 24.);
3252 days = (short)(tow / 86400.0);
3253 sprintf(timestring, " %s %02d:%02d:%05.2f ",
3254 dayname[days], hours, minutes, seconds);
3267 tx_baud_index, rx_baud_index,
3268 char_format_index, stop_bits,
3269 tx_mode_index, rx_mode_index,
3276 &tx_baud_index, &rx_baud_index, &char_format_index,
3277 &stop_bits, &tx_mode_index, &rx_mode_index)) {
3278 parsed = BADLEN_PARSE;
3282 pbuf += sprintf(pbuf, "\nChannel A Configuration");
3284 nbaud = sizeof(old_baudnum);
3286 for (i = 0; i < nbaud; ++i) if (tx_baud_index == old_baudnum[i]) break;
3287 pbuf += sprintf(pbuf, "\n Transmit speed: %s at %s",
3288 old_output_ch[tx_mode_index], st_baud_text_app[i]);
3290 for (i = 0; i < nbaud; ++i) if (rx_baud_index == old_baudnum[i]) break;
3291 pbuf += sprintf(pbuf, "\n Receive speed: %s at %s",
3292 old_input_ch[rx_mode_index], st_baud_text_app[i]);
3294 databits = (unsigned char)((char_format_index & 0x03) + 5);
3296 parity = (unsigned char)(char_format_index >> 2);
3297 if (parity > 4) parity = 2;
3299 pbuf += sprintf(pbuf, "\n Character format (bits/char, parity, stop bits): %d-%s-%d",
3300 databits, old_parity_text[parity], stop_bits);
3306 rpt_almanac_data_page(
3327 &sv_prn, &week_num, &t_zc, &eccentricity, &t_oa,
3328 &i_0, &OMEGA_dot, &sqrt_A, &OMEGA_0, &omega, &M_0)) {
3329 parsed = BADLEN_PARSE;
3333 pbuf += sprintf(pbuf, "\nAlmanac for SV %02d", sv_prn);
3334 pbuf += sprintf(pbuf, "\n Captured:%15.0f %s",
3335 t_zc, show_time (t_zc));
3336 pbuf += sprintf(pbuf, "\n week:%15d", week_num);
3337 pbuf += sprintf(pbuf, "\n Eccentricity:%15g", eccentricity);
3338 pbuf += sprintf(pbuf, "\n T_oa:%15.0f %s",
3339 t_oa, show_time (t_oa));
3340 pbuf += sprintf(pbuf, "\n i 0:%15g", i_0);
3341 pbuf += sprintf(pbuf, "\n OMEGA dot:%15g", OMEGA_dot);
3342 pbuf += sprintf(pbuf, "\n sqrt A:%15g", sqrt_A);
3343 pbuf += sprintf(pbuf, "\n OMEGA 0:%15g", OMEGA_0);
3344 pbuf += sprintf(pbuf, "\n omega:%15g", omega);
3345 pbuf += sprintf(pbuf, "\n M 0:%15g", M_0);
3355 time_of_week, UTC_offset;
3360 if (rpt_0x41 (rpt, &time_of_week, &UTC_offset, &week_num)) {
3361 parsed = BADLEN_PARSE;
3365 pbuf += sprintf(pbuf, "\nGPS time:%s GPS week: %d UTC offset %.1f",
3366 show_time(time_of_week), week_num, UTC_offset);
3372 rpt_single_ECEF_position(
3377 ECEF_pos[3], time_of_fix;
3380 if (rpt_0x42 (rpt, ECEF_pos, &time_of_fix)) {
3381 parsed = BADLEN_PARSE;
3385 pbuf += sprintf(pbuf, "\nSXYZ: %15.0f %15.0f %15.0f %s",
3386 ECEF_pos[0], ECEF_pos[1], ECEF_pos[2],
3387 show_time(time_of_fix));
3392 rpt_single_ECEF_velocity(
3398 ECEF_vel[3], freq_offset, time_of_fix;
3401 if (rpt_0x43 (rpt, ECEF_vel, &freq_offset, &time_of_fix)) {
3402 parsed = BADLEN_PARSE;
3406 pbuf += sprintf(pbuf, "\nVelECEF: %11.3f %11.3f %11.3f %12.3f%s",
3407 ECEF_vel[0], ECEF_vel[1], ECEF_vel[2], freq_offset,
3408 show_time(time_of_fix));
3418 major_nav_version, minor_nav_version,
3419 nav_day, nav_month, nav_year,
3420 major_dsp_version, minor_dsp_version,
3421 dsp_day, dsp_month, dsp_year;
3425 &major_nav_version, &minor_nav_version,
3426 &nav_day, &nav_month, &nav_year,
3427 &major_dsp_version, &minor_dsp_version,
3428 &dsp_day, &dsp_month, &dsp_year)) {
3429 parsed = BADLEN_PARSE;
3433 pbuf += sprintf(pbuf,
3434 "\nFW Versions: Nav Proc %2d.%02d %2d/%2d/%2d Sig Proc %2d.%02d %2d/%2d/%2d",
3435 major_nav_version, minor_nav_version, nav_day, nav_month, nav_year,
3436 major_dsp_version, minor_dsp_version, dsp_day, dsp_month, dsp_year);
3449 static const char const
3451 "Doing position fixes",
3452 "Don't have GPS time yet",
3453 "Waiting for almanac collection",
3455 "No satellites available",
3456 "Only 1 satellite available",
3457 "Only 2 satellites available",
3458 "Only 3 satellites available",
3459 "No satellites usable ",
3460 "Only 1 satellite usable",
3461 "Only 2 satellites usable",
3462 "Only 3 satellites usable",
3463 "Chosen satellite unusable"};
3467 if (rpt_0x46 (rpt, &status1, &status2))
3469 parsed = BADLEN_PARSE;
3473 text = (status1 < COUNTOF(sc_text))
3476 pbuf += sprintf(pbuf, "\nRcvr status1: %s (%02Xh); ",
3479 pbuf += sprintf(pbuf, "status2: %s, %s (%02Xh)",
3480 (status2 & 0x01)?"No BBRAM":"BBRAM OK",
3481 (status2 & 0x10)?"No Ant":"Ant OK",
3499 if (rpt_0x47 (rpt, &nsvs, sv_prn, snr))
3501 parsed = BADLEN_PARSE;
3505 pbuf += sprintf(pbuf, "\nSNR for satellites: %d", nsvs);
3506 for (isv = 0; isv < nsvs; isv++)
3508 pbuf += sprintf(pbuf, "\n SV %02d %6.2f",
3509 sv_prn[isv], snr[isv]);
3515 rpt_GPS_system_message(
3523 if (rpt_0x48 (rpt, message))
3525 parsed = BADLEN_PARSE;
3529 pbuf += sprintf(pbuf, "\nGPS message: %s", message);
3534 rpt_almanac_health_page(
3544 if (rpt_0x49 (rpt, sv_health))
3546 parsed = BADLEN_PARSE;
3550 pbuf += sprintf(pbuf, "\nAlmanac health page:");
3551 for (iprn = 0; iprn < 32; iprn++)
3553 if (!(iprn%5)) *pbuf++ = '\n';
3554 pbuf += sprintf(pbuf, " SV%02d %2X",
3555 (iprn+1) , sv_health[iprn]);
3561 rpt_single_lla_position(
3569 alt, clock_bias, time_of_fix;
3570 double lat_min, lon_min;
3572 north_south, east_west;
3575 &lat, &lon, &alt, &clock_bias, &time_of_fix))
3577 parsed = BADLEN_PARSE;
3581 /* convert from radians to degrees */
3589 lat_deg = (short)lat;
3590 lat_min = (lat - lat_deg) * 60.0;
3599 lon_deg = (short)lon;
3600 lon_min = (lon - lon_deg) * 60.0;
3602 pbuf += sprintf(pbuf, "\nSLLA: %4d: %06.3f %c%5d:%06.3f %c%10.2f %12.2f%s",
3603 lat_deg, lat_min, north_south,
3604 lon_deg, lon_min, east_west,
3606 show_time(time_of_fix));
3620 if (rpt_0x4A_2 (rpt, &alt, &dummy, &alt_flag))
3622 parsed = BADLEN_PARSE;
3626 pbuf += sprintf(pbuf, "\nReference Alt: %.1f m; %s",
3627 alt, alt_flag?"ON":"OFF");
3632 rpt_rcvr_id_and_status(
3638 machine_id, status3, status4;
3641 if (rpt_0x4B (rpt, &machine_id, &status3, &status4))
3643 parsed = BADLEN_PARSE;
3647 pbuf += sprintf(pbuf, "\nRcvr Machine ID: %d; Status3 = %s, %s (%02Xh)",
3649 (status3 & 0x02)?"No RTC":"RTC OK",
3650 (status3 & 0x08)?"No Alm":"Alm OK",
3656 rpt_operating_parameters(
3663 el_mask, snr_mask, dop_mask, dop_switch;
3666 if (rpt_0x4C (rpt, &dyn_code, &el_mask,
3667 &snr_mask, &dop_mask, &dop_switch))
3669 parsed = BADLEN_PARSE;
3673 pbuf += sprintf(pbuf, "\nOperating Parameters:");
3674 pbuf += sprintf(pbuf, "\n Dynamics code = %d %s",
3675 dyn_code, dyn_text[dyn_code]);
3676 pbuf += sprintf(pbuf, "\n Elevation mask = %.2f", el_mask * R2D);
3677 pbuf += sprintf(pbuf, "\n SNR mask = %.2f", snr_mask);
3678 pbuf += sprintf(pbuf, "\n DOP mask = %.2f", dop_mask);
3679 pbuf += sprintf(pbuf, "\n DOP switch = %.2f", dop_switch);
3684 rpt_oscillator_offset(
3692 if (rpt_0x4D (rpt, &osc_offset))
3694 parsed = BADLEN_PARSE;
3698 pbuf += sprintf(pbuf, "\nOscillator offset: %.2f Hz = %.3f PPM",
3699 osc_offset, osc_offset/1575.42);
3704 rpt_GPS_time_set_response(
3712 if (rpt_0x4E (rpt, &response))
3714 parsed = BADLEN_PARSE;
3721 pbuf += sprintf(pbuf, "\nTime set accepted");
3725 pbuf += sprintf(pbuf, "\nTime set rejected or not required");
3729 parsed = BADDATA_PARSE;
3744 dt_ls, wn_t, wn_lsf, dn, dt_lsf;
3747 if (rpt_0x4F (rpt, &a0, &a1, &time_of_data,
3748 &dt_ls, &wn_t, &wn_lsf, &dn, &dt_lsf)) {
3749 parsed = BADLEN_PARSE;
3753 pbuf += sprintf(pbuf, "\nUTC Correction Data");
3754 pbuf += sprintf(pbuf, "\n A_0 = %g ", a0);
3755 pbuf += sprintf(pbuf, "\n A_1 = %g ", a1);
3756 pbuf += sprintf(pbuf, "\n delta_t_LS = %d ", dt_ls);
3757 pbuf += sprintf(pbuf, "\n t_ot = %.0f ", time_of_data);
3758 pbuf += sprintf(pbuf, "\n WN_t = %d ", wn_t );
3759 pbuf += sprintf(pbuf, "\n WN_LSF = %d ", wn_lsf );
3760 pbuf += sprintf(pbuf, "\n DN = %d ", dn );
3761 pbuf += sprintf(pbuf, "\n delta_t_LSF = %d ", dt_lsf );
3772 clock_bias, freq_offset, time_of_fix;
3775 if (rpt_0x54 (rpt, &clock_bias, &freq_offset, &time_of_fix)) {
3776 parsed = BADLEN_PARSE;
3780 pbuf += sprintf (pbuf, "\nTime Fix Clock Bias: %6.2f m Freq Bias: %6.2f m/s%s",
3781 clock_bias, freq_offset, show_time (time_of_fix));
3791 pos_code, vel_code, time_code, aux_code;
3795 &pos_code, &vel_code, &time_code, &aux_code)) {
3796 parsed = BADLEN_PARSE;
3799 /* rptbuf unloaded */
3801 pbuf += sprintf(pbuf, "\nI/O Options: %2X %2X %2X %2X",
3802 pos_code, vel_code, time_code, aux_code);
3804 if (pos_code & 0x01) {
3805 pbuf += sprintf(pbuf, "\n ECEF XYZ position output");
3808 if (pos_code & 0x02) {
3809 pbuf += sprintf(pbuf, "\n LLA position output");
3812 pbuf += sprintf(pbuf, (pos_code & 0x04)?
3813 "\n MSL altitude output (Geoid height) ":
3814 "\n WGS-84 altitude output");
3816 pbuf += sprintf(pbuf, (pos_code & 0x08)?
3817 "\n MSL altitude input":
3818 "\n WGS-84 altitude input");
3820 pbuf += sprintf(pbuf, (pos_code & 0x10)?
3821 "\n Double precision":
3822 "\n Single precision");
3824 if (pos_code & 0x20) {
3825 pbuf += sprintf(pbuf, "\n All Enabled Superpackets");
3828 if (vel_code & 0x01) {
3829 pbuf += sprintf(pbuf, "\n ECEF XYZ velocity output");
3832 if (vel_code & 0x02) {
3833 pbuf += sprintf(pbuf, "\n ENU velocity output");
3836 pbuf += sprintf(pbuf, (time_code & 0x01)?
3837 "\n Time tags in UTC":
3838 "\n Time tags in GPS time");
3840 if (time_code & 0x02) {
3841 pbuf += sprintf(pbuf, "\n Fixes delayed to integer seconds");
3844 if (time_code & 0x04) {
3845 pbuf += sprintf(pbuf, "\n Fixes sent only on request");
3848 if (time_code & 0x08) {
3849 pbuf += sprintf(pbuf, "\n Synchronized measurements");
3852 if (time_code & 0x10) {
3853 pbuf += sprintf(pbuf, "\n Minimize measurement propagation");
3856 pbuf += sprintf(pbuf, (time_code & 0x20) ?
3857 "\n PPS output at all times" :
3858 "\n PPS output during fixes");
3860 if (aux_code & 0x01) {
3861 pbuf += sprintf(pbuf, "\n Raw measurement output");
3864 if (aux_code & 0x02) {
3865 pbuf += sprintf(pbuf, "\n Code-phase smoothed before output");
3868 if (aux_code & 0x04) {
3869 pbuf += sprintf(pbuf, "\n Additional fix status");
3872 pbuf += sprintf(pbuf, (aux_code & 0x08)?
3873 "\n Signal Strength Output as dBHz" :
3874 "\n Signal Strength Output as AMU");
3884 vel_ENU[3], freq_offset, time_of_fix;
3887 if (rpt_0x56 (rpt, vel_ENU, &freq_offset, &time_of_fix)) {
3888 parsed = BADLEN_PARSE;
3892 pbuf += sprintf(pbuf, "\nVel ENU: %11.3f %11.3f %11.3f %12.3f%s",
3893 vel_ENU[0], vel_ENU[1], vel_ENU[2], freq_offset,
3894 show_time (time_of_fix));
3904 source_code, diag_code;
3911 if (rpt_0x57 (rpt, &source_code, &diag_code, &week_num, &time_of_fix)) {
3912 parsed = BADLEN_PARSE;
3916 pbuf += sprintf(pbuf, "\n source code %d; diag code: %2Xh",
3917 source_code, diag_code);
3918 pbuf += sprintf(pbuf, "\n Time of last fix:%s", show_time(time_of_fix));
3919 pbuf += sprintf(pbuf, "\n Week of last fix: %d", week_num);
3924 rpt_GPS_system_data(
3930 op_code, data_type, sv_prn,
3931 data_length, data_packet[250];
3952 {"", "", "Almanac Orbit",
3953 "Health Page & Ref Time", "Ionosphere", "UTC ",
3957 if (rpt_0x58 (rpt, &op_code, &data_type, &sv_prn,
3958 &data_length, data_packet))
3960 parsed = BADLEN_PARSE;
3964 pbuf += sprintf(pbuf, "\nSystem data [%d]: %s SV%02d",
3965 data_type, datname[data_type], sv_prn);
3969 pbuf += sprintf(pbuf, " Acknowledgment");
3972 pbuf += sprintf(pbuf, " length = %d bytes", data_length);
3973 switch (data_type) {
3976 if (sv_prn == 0 || sv_prn > 32) {
3977 pbuf += sprintf(pbuf, " Binary PRN invalid");
3980 almanac = (ALM_INFO*)data_packet;
3981 pbuf += sprintf(pbuf, "\n t_oa_raw = % -12d SV_hlth = % -12d ",
3982 almanac->t_oa_raw , almanac->SV_health );
3983 pbuf += sprintf(pbuf, "\n e = % -12g t_oa = % -12g ",
3984 almanac->e , almanac->t_oa );
3985 pbuf += sprintf(pbuf, "\n i_0 = % -12g OMEGADOT = % -12g ",
3986 almanac->i_0 , almanac->OMEGADOT );
3987 pbuf += sprintf(pbuf, "\n sqrt_A = % -12g OMEGA_0 = % -12g ",
3988 almanac->sqrt_A , almanac->OMEGA_0 );
3989 pbuf += sprintf(pbuf, "\n omega = % -12g M_0 = % -12g ",
3990 almanac->omega , almanac->M_0 );
3991 pbuf += sprintf(pbuf, "\n a_f0 = % -12g a_f1 = % -12g ",
3992 almanac->a_f0 , almanac->a_f1 );
3993 pbuf += sprintf(pbuf, "\n Axis = % -12g n = % -12g ",
3994 almanac->Axis , almanac->n );
3995 pbuf += sprintf(pbuf, "\n OMEGA_n = % -12g ODOT_n = % -12g ",
3996 almanac->OMEGA_n , almanac->ODOT_n );
3997 pbuf += sprintf(pbuf, "\n t_zc = % -12g weeknum = % -12d ",
3998 almanac->t_zc , almanac->weeknum );
3999 pbuf += sprintf(pbuf, "\n wn_oa = % -12d", almanac->wn_oa );
4003 /* Almanac health page */
4004 almh = (ALH_PARMS*)data_packet;
4005 pbuf += sprintf(pbuf, "\n t_oa = %d, wn_oa&0xFF = %d ",
4006 almh->t_oa, almh->WN_a);
4007 pbuf += sprintf(pbuf, "\nAlmanac health page:");
4008 for (iprn = 0; iprn < 32; iprn++) {
4009 if (!(iprn%5)) *pbuf++ = '\n';
4010 pbuf += sprintf(pbuf, " SV%02d %2X",
4011 (iprn+1) , almh->SV_health[iprn]);
4013 curr_t_oa = data_packet[34];
4014 curr_wn_oa = (unsigned short)((data_packet[35]<<8) + data_packet[36]);
4015 pbuf += sprintf(pbuf, "\n current t_oa = %d, wn_oa = %d ",
4016 curr_t_oa, curr_wn_oa);
4021 ionosphere = (ION_INFO*)data_packet;
4022 pbuf += sprintf(pbuf, "\n alpha_0 = % -12g alpha_1 = % -12g ",
4023 ionosphere->alpha_0, ionosphere->alpha_1);
4024 pbuf += sprintf(pbuf, "\n alpha_2 = % -12g alpha_3 = % -12g ",
4025 ionosphere->alpha_2, ionosphere->alpha_3);
4026 pbuf += sprintf(pbuf, "\n beta_0 = % -12g beta_1 = % -12g ",
4027 ionosphere->beta_0, ionosphere->beta_1);
4028 pbuf += sprintf(pbuf, "\n beta_2 = % -12g beta_3 = % -12g ",
4029 ionosphere->beta_2, ionosphere->beta_3);
4034 utc = (UTC_INFO*)data_packet;
4035 pbuf += sprintf(pbuf, "\n A_0 = %g ", utc->A_0);
4036 pbuf += sprintf(pbuf, "\n A_1 = %g ", utc->A_1);
4037 pbuf += sprintf(pbuf, "\n delta_t_LS = %d ", utc->delta_t_LS);
4038 pbuf += sprintf(pbuf, "\n t_ot = %.0f ", utc->t_ot );
4039 pbuf += sprintf(pbuf, "\n WN_t = %d ", utc->WN_t );
4040 pbuf += sprintf(pbuf, "\n WN_LSF = %d ", utc->WN_LSF );
4041 pbuf += sprintf(pbuf, "\n DN = %d ", utc->DN );
4042 pbuf += sprintf(pbuf, "\n delta_t_LSF = %d ", utc->delta_t_LSF );
4045 case 6: /* Ephemeris */
4046 if (sv_prn == 0 || sv_prn > 32) {
4047 pbuf += sprintf(pbuf, " Binary PRN invalid");
4050 nav_data = (NAV_INFO*)data_packet;
4052 pbuf += sprintf(pbuf, "\n SV_PRN = % -12d . t_ephem = % -12g . ",
4053 nav_data->sv_number , nav_data->t_ephem );
4054 cdata = &(nav_data->ephclk);
4055 pbuf += sprintf(pbuf,
4056 "\n weeknum = % -12d . codeL2 = % -12d . L2Pdata = % -12d",
4057 cdata->weeknum , cdata->codeL2 , cdata->L2Pdata );
4058 pbuf += sprintf(pbuf,
4059 "\n SVacc_raw = % -12d .SV_health = % -12d . IODC = % -12d",
4060 cdata->SVacc_raw, cdata->SV_health, cdata->IODC );
4061 pbuf += sprintf(pbuf,
4062 "\n T_GD = % -12g . t_oc = % -12g . a_f2 = % -12g",
4063 cdata->T_GD, cdata->t_oc, cdata->a_f2 );
4064 pbuf += sprintf(pbuf,
4065 "\n a_f1 = % -12g . a_f0 = % -12g . SVacc = % -12g",
4066 cdata->a_f1, cdata->a_f0, cdata->SVacc );
4067 edata = &(nav_data->ephorb);
4068 pbuf += sprintf(pbuf,
4069 "\n IODE = % -12d .fit_intvl = % -12d . C_rs = % -12g",
4070 edata->IODE, edata->fit_interval, edata->C_rs );
4071 pbuf += sprintf(pbuf,
4072 "\n delta_n = % -12g . M_0 = % -12g . C_uc = % -12g",
4073 edata->delta_n, edata->M_0, edata->C_uc );
4074 pbuf += sprintf(pbuf,
4075 "\n ecc = % -12g . C_us = % -12g . sqrt_A = % -12g",
4076 edata->e, edata->C_us, edata->sqrt_A );
4077 pbuf += sprintf(pbuf,
4078 "\n t_oe = % -12g . C_ic = % -12g . OMEGA_0 = % -12g",
4079 edata->t_oe, edata->C_ic, edata->OMEGA_0 );
4080 pbuf += sprintf(pbuf,
4081 "\n C_is = % -12g . i_0 = % -12g . C_rc = % -12g",
4082 edata->C_is, edata->i_0, edata->C_rc );
4083 pbuf += sprintf(pbuf,
4084 "\n omega = % -12g . OMEGADOT = % -12g . IDOT = % -12g",
4085 edata->omega, edata->OMEGADOT, edata->IDOT );
4086 pbuf += sprintf(pbuf,
4087 "\n Axis = % -12g . n = % -12g . r1me2 = % -12g",
4088 edata->Axis, edata->n, edata->r1me2 );
4089 pbuf += sprintf(pbuf,
4090 "\n OMEGA_n = % -12g . ODOT_n = % -12g",
4091 edata->OMEGA_n, edata->ODOT_n );
4112 if (rpt_0x59 (rpt, &code_type, status_code))
4114 parsed = BADLEN_PARSE;
4119 case 3: pbuf += sprintf(pbuf, "\nSVs Disabled:\n"); break;
4120 case 6: pbuf += sprintf(pbuf, "\nSVs with Health Ignored:\n"); break;
4124 for (iprn = 0; iprn < 32; iprn++)
4126 if (status_code[iprn])
4128 pbuf += sprintf(pbuf, " %02d", iprn+1);
4132 if (numsvs == 0) pbuf += sprintf(pbuf, "None");
4145 sample_length, signal_level, code_phase, Doppler;
4150 if (rpt_0x5A (rpt, &sv_prn, &sample_length, &signal_level,
4151 &code_phase, &Doppler, &time_of_fix))
4153 parsed = BADLEN_PARSE;
4157 pbuf += sprintf(pbuf, "\n %02d %5.0f %7.1f %10.2f %10.2f %12.3f %s",
4158 sv_prn, sample_length, signal_level, code_phase, Doppler, time_of_fix,
4159 show_time ((float)time_of_fix));
4164 rpt_SV_ephemeris_status(
4169 sv_prn, sv_health, sv_iode, fit_interval_flag;
4171 time_of_collection, time_of_eph, sv_accy;
4174 if (rpt_0x5B (rpt, &sv_prn, &sv_health, &sv_iode, &fit_interval_flag,
4175 &time_of_collection, &time_of_eph, &sv_accy))
4177 parsed = BADLEN_PARSE;
4181 pbuf += sprintf(pbuf, "\n SV%02d %s %2Xh %2Xh ",
4182 sv_prn, show_time (time_of_collection), sv_health, sv_iode);
4183 /* note: cannot use show_time twice in same call */
4184 pbuf += sprintf(pbuf, "%s %1d %4.1f",
4185 show_time (time_of_eph), fit_interval_flag, sv_accy);
4190 rpt_SV_tracking_status(
4195 sv_prn, chan, slot, acq_flag, eph_flag,
4196 old_msmt_flag, integer_msec_flag, bad_data_flag,
4199 signal_level, time_of_last_msmt,
4204 &sv_prn, &slot, &chan, &acq_flag, &eph_flag,
4205 &signal_level, &time_of_last_msmt, &elev, &azim,
4206 &old_msmt_flag, &integer_msec_flag, &bad_data_flag,
4207 &data_collect_flag))
4209 parsed = BADLEN_PARSE;
4213 pbuf += sprintf(pbuf,
4214 "\n SV%2d %1d %1d %1d %4.1f %s %5.1f %5.1f",
4216 acq_flag, eph_flag, signal_level,
4217 show_time(time_of_last_msmt),
4218 elev*R2D, azim*R2D);
4224 rpt_allSV_selection(
4229 manual_mode, nsvs, sv_prn[8], ndim;
4233 pdop, hdop, vdop, tdop;
4237 &manual_mode, &nsvs, &ndim, sv_prn,
4238 &pdop, &hdop, &vdop, &tdop))
4240 parsed = BADLEN_PARSE;
4247 pbuf += sprintf(pbuf, "\nMode: Searching, %d-SV:", nsvs);
4250 pbuf += sprintf(pbuf, "\nMode: One-SV Timing:");
4253 pbuf += sprintf(pbuf, "\nMode: %c-%dD, %d-SV:",
4254 manual_mode ? 'M' : 'A', ndim - 1, nsvs);
4257 pbuf += sprintf(pbuf, "\nMode: Timing, %d-SV:", nsvs);
4260 pbuf += sprintf(pbuf, "\nMode: Unknown = %d:", ndim);
4264 for (islot = 0; islot < nsvs; islot++)
4266 if (sv_prn[islot]) pbuf += sprintf(pbuf, " %02d", sv_prn[islot]);
4268 if (ndim == 3 || ndim == 4)
4270 pbuf += sprintf(pbuf, "; DOPs: P %.1f H %.1f V %.1f T %.1f",
4271 pdop, hdop, vdop, tdop);
4278 rpt_DGPS_position_mode(
4286 if (rpt_0x82 (rpt, &diff_mode)) {
4287 parsed = BADLEN_PARSE;
4291 pbuf += sprintf(pbuf, "\nFix is%s DGPS-corrected (%s mode) (%d)",
4292 (diff_mode&1) ? "" : " not",
4293 (diff_mode&2) ? "auto" : "manual",
4299 rpt_double_ECEF_position(
4304 ECEF_pos[3], clock_bias;
4309 if (rpt_0x83 (rpt, ECEF_pos, &clock_bias, &time_of_fix))
4311 parsed = BADLEN_PARSE;
4315 pbuf += sprintf(pbuf, "\nDXYZ:%12.2f %13.2f %13.2f %12.2f%s",
4316 ECEF_pos[0], ECEF_pos[1], ECEF_pos[2], clock_bias,
4317 show_time(time_of_fix));
4322 rpt_double_lla_position(
4329 lat, lon, lat_min, lon_min,
4334 north_south, east_west;
4338 &lat, &lon, &alt, &clock_bias, &time_of_fix))
4340 parsed = BADLEN_PARSE;
4352 lat_deg = (short)lat;
4353 lat_min = (lat - lat_deg) * 60.0;
4361 lon_deg = (short)lon;
4362 lon_min = (lon - lon_deg) * 60.0;
4363 pbuf += sprintf(pbuf, "\nDLLA: %2d:%08.5f %c; %3d:%08.5f %c; %10.2f %12.2f%s",
4364 lat_deg, lat_min, north_south,
4365 lon_deg, lon_min, east_west,
4367 show_time(time_of_fix));
4372 rpt_complete_rcvr_config(
4376 TSIP_RCVR_CFG TsipxBB ;
4378 if (rpt_Paly0xBB (rpt, &TsipxBB))
4380 parsed = BADLEN_PARSE;
4384 pbuf += sprintf(pbuf, "\n operating mode: %s",
4385 NavModeText0xBB[TsipxBB.operating_mode]);
4386 pbuf += sprintf(pbuf, "\n dynamics: %s",
4387 dyn_text[TsipxBB.dyn_code]);
4388 pbuf += sprintf(pbuf, "\n elev angle mask: %g deg",
4389 TsipxBB.elev_mask * R2D);
4390 pbuf += sprintf(pbuf, "\n SNR mask: %g AMU",
4392 pbuf += sprintf(pbuf, "\n DOP mask: %g",
4394 pbuf += sprintf(pbuf, "\n DOP switch: %g",
4395 TsipxBB.dop_switch);
4401 rpt_rcvr_serial_port_config(
4406 port_num, in_baud, out_baud, data_bits, parity, stop_bits, flow_control,
4407 protocols_in, protocols_out, reserved;
4408 unsigned char known;
4411 if (rpt_0xBC (rpt, &port_num, &in_baud, &out_baud, &data_bits, &parity,
4412 &stop_bits, &flow_control, &protocols_in, &protocols_out, &reserved)) {
4413 parsed = BADLEN_PARSE;
4416 /* rptbuf unloaded */
4418 pbuf += sprintf(pbuf, "\n RECEIVER serial port %s config:",
4419 rcvr_port_text[port_num]);
4421 pbuf += sprintf(pbuf, "\n I/O Baud %s/%s, %d - %s - %d",
4422 st_baud_text_app[in_baud],
4423 st_baud_text_app[out_baud],
4425 parity_text[parity],
4427 pbuf += sprintf(pbuf, "\n Input protocols: ");
4429 if (protocols_in&B_TSIP)
4431 pbuf += sprintf(pbuf, "%s ", protocols_in_text[1]);
4434 if (known == FALSE) pbuf += sprintf(pbuf, "No known");
4436 pbuf += sprintf(pbuf, "\n Output protocols: ");
4438 if (protocols_out&B_TSIP)
4440 pbuf += sprintf(pbuf, "%s ", protocols_out_text[1]);
4443 if (protocols_out&B_NMEA)
4445 pbuf += sprintf(pbuf, "%s ", protocols_out_text[2]);
4448 if (known == FALSE) pbuf += sprintf(pbuf, "No known");
4449 reserved = reserved;
4463 "full position (3-D)",
4464 "single satellite (0-D)",
4468 "overdetermined clock"};
4519 parsed = BADLEN_PARSE;
4525 pbuf += sprintf(pbuf, "\nNew partial+full meas");
4529 pbuf += sprintf(pbuf, "\nEvent count: %5d", event);
4532 pbuf += sprintf(pbuf, "\nGPS time : %s %2d/%2d/%2d (DMY)",
4533 show_time(tow), date, month, year);
4534 pbuf += sprintf(pbuf, "\nMode : %s", oprtng_dim[dim_mode]);
4535 pbuf += sprintf(pbuf, "\nUTC offset: %2d", utc_offset);
4536 pbuf += sprintf(pbuf, "\nClock Bias: %6.2f m", bias);
4537 pbuf += sprintf(pbuf, "\nFreq bias : %6.2f m/s", drift);
4538 pbuf += sprintf(pbuf, "\nBias unc : %6.2f m", bias_unc);
4539 pbuf += sprintf(pbuf, "\nFreq unc : %6.2f m/s", dr_unc);
4541 lat *= R2D; /* convert from radians to degrees */
4553 lat_deg = (short)lat;
4554 lat_min = (lat - lat_deg) * 60.0;
4565 lon_deg = (short)lon;
4566 lon_min = (lon - lon_deg) * 60.0;
4567 pbuf += sprintf(pbuf, "\nPosition :");
4568 pbuf += sprintf(pbuf, " %4d %6.3f %c", lat_deg, lat_min, north_south);
4569 pbuf += sprintf(pbuf, " %5d %6.3f %c", lon_deg, lon_min, east_west);
4570 pbuf += sprintf(pbuf, " %10.2f", alt);
4572 numfix = numnotfix = 0;
4573 for (local_index=0; local_index<8; local_index++)
4575 if (sv_id[local_index] < 0) numnotfix++;
4576 if (sv_id[local_index] > 0) numfix++;
4580 pbuf += sprintf(pbuf, "\nSVs used in fix : ");
4581 for (local_index=0; local_index<8; local_index++)
4583 if (sv_id[local_index] > 0)
4585 pbuf += sprintf(pbuf, "%2d ", sv_id[local_index]);
4591 pbuf += sprintf(pbuf, "\nOther SVs tracked: ");
4592 for (local_index=0; local_index<8; local_index++)
4594 if (sv_id[local_index] < 0)
4596 pbuf += sprintf(pbuf, "%2d ", sv_id[local_index]);
4603 /* Datum parameters */
4615 if (rpt_0x8F14 (rpt, &datum_idx, datum_coeffs))
4617 parsed = BADLEN_PARSE;
4621 if (datum_idx == -1)
4623 pbuf += sprintf(pbuf, "\nUser-Entered Datum:");
4624 pbuf += sprintf(pbuf, "\n dx = %6.1f", datum_coeffs[0]);
4625 pbuf += sprintf(pbuf, "\n dy = %6.1f", datum_coeffs[1]);
4626 pbuf += sprintf(pbuf, "\n dz = %6.1f", datum_coeffs[2]);
4627 pbuf += sprintf(pbuf, "\n a-axis = %10.3f", datum_coeffs[3]);
4628 pbuf += sprintf(pbuf, "\n e-squared = %16.14f", datum_coeffs[4]);
4630 else if (datum_idx == 0)
4632 pbuf += sprintf(pbuf, "\nWGS-84 datum, Index 0 ");
4636 pbuf += sprintf(pbuf, "\nStandard Datum, Index %3d ", datum_idx);
4641 /* Datum parameters */
4653 if (rpt_0x8F15 (rpt, &datum_idx, datum_coeffs)) {
4654 parsed = BADLEN_PARSE;
4658 if (datum_idx == -1)
4660 pbuf += sprintf(pbuf, "\nUser-Entered Datum:");
4661 pbuf += sprintf(pbuf, "\n dx = %6.1f", datum_coeffs[0]);
4662 pbuf += sprintf(pbuf, "\n dy = %6.1f", datum_coeffs[1]);
4663 pbuf += sprintf(pbuf, "\n dz = %6.1f", datum_coeffs[2]);
4664 pbuf += sprintf(pbuf, "\n a-axis = %10.3f", datum_coeffs[3]);
4665 pbuf += sprintf(pbuf, "\n e-squared = %16.14f", datum_coeffs[4]);
4667 else if (datum_idx == 0)
4669 pbuf += sprintf(pbuf, "\nWGS-84 datum, Index 0 ");
4673 pbuf += sprintf(pbuf, "\nStandard Datum, Index %3d ", datum_idx);
4678 #define INFO_DGPS 0x02
4679 #define INFO_2D 0x04
4680 #define INFO_ALTSET 0x08
4681 #define INFO_FILTERED 0x10
4688 info, nsvs, sv_prn[32];
4690 week_num, datum_index, sv_IODC[32];
4692 lat, lon, alt, time_of_fix;
4694 londeg, latdeg, vel[3];
4701 if (rpt_0x8F20 (rpt,
4702 &info, &lat, &lon, &alt, vel,
4704 &week_num, &nsvs, sv_prn, sv_IODC, &datum_index))
4706 parsed = BADLEN_PARSE;
4709 pbuf += sprintf(pbuf,
4710 "\nFix at: %04d:%3s:%02d:%02d:%06.3f GPS (=UTC+%2ds) FixType: %s%s%s",
4712 dayname[(short)(time_of_fix/86400.0)],
4713 (short)fmod(time_of_fix/3600., 24.),
4714 (short)fmod(time_of_fix/60., 60.),
4715 fmod(time_of_fix, 60.),
4716 (char)rpt->buf[29], /* UTC offset */
4717 (info & INFO_DGPS)?"Diff":"",
4718 (info & INFO_2D)?"2D":"3D",
4719 (info & INFO_FILTERED)?"-Filtrd":"");
4721 if (datum_index > 0)
4723 sprintf(datum_string, "Datum%3d", datum_index);
4725 else if (datum_index)
4727 sprintf(datum_string, "Unknown ");
4731 sprintf(datum_string, "WGS-84");
4734 /* convert from radians to degrees */
4735 latdeg = R2D * fabs(lat);
4736 londeg = R2D * fabs(lon);
4737 pbuf += sprintf(pbuf,
4738 "\n Pos: %4d:%09.6f %c %5d:%09.6f %c %10.2f m HAE (%s)",
4739 (short)latdeg, fmod (latdeg, 1.)*60.0,
4741 (short)londeg, fmod (londeg, 1.)*60.0,
4745 pbuf += sprintf(pbuf,
4746 "\n Vel: %9.3f E %9.3f N %9.3f U (m/sec)",
4747 vel[0], vel[1], vel[2]);
4749 pbuf += sprintf(pbuf,
4751 for (isv = 0; isv < nsvs; isv++) {
4752 pbuf += sprintf(pbuf, " %02d", sv_prn[isv]);
4754 pbuf += sprintf(pbuf, " (IODEs:");
4755 for (isv = 0; isv < nsvs; isv++) {
4756 pbuf += sprintf(pbuf, " %02X", sv_IODC[isv]&0xFF);
4758 pbuf += sprintf(pbuf, ")");
4781 if (!rpt_0x8F41(rpt,
4792 parsed = BADLEN_PARSE;
4796 pbuf += sprintf(pbuf, "\n search range: %d",
4798 pbuf += sprintf(pbuf, "\n board options: %d",
4800 pbuf += sprintf(pbuf, "\n board serial #: %ld",
4802 pbuf += sprintf(pbuf, "\n build date/hour: %02d/%02d/%02d %02d:00",
4803 bBuildDay, bBuildMonth, bBuildYear, bBuildHour);
4804 pbuf += sprintf(pbuf, "\n osc offset: %.3f PPM (%.0f Hz)",
4805 fOscOffset/1575.42, fOscOffset);
4806 pbuf += sprintf(pbuf, "\n test code: %d",
4820 iCaseSerialNumberPre,
4828 if (!rpt_0x8F42(rpt,
4831 &iCaseSerialNumberPre,
4832 &iiCaseSerialNumber,
4838 parsed = BADLEN_PARSE;
4842 pbuf += sprintf(pbuf, "\nProduct ID 8F42");
4843 pbuf += sprintf(pbuf, "\n extension: %d", bProdNumberExt);
4844 pbuf += sprintf(pbuf, "\n case serial # prefix: %d", iCaseSerialNumberPre);
4845 pbuf += sprintf(pbuf, "\n case serial #: %ld", iiCaseSerialNumber);
4846 pbuf += sprintf(pbuf, "\n prod. #: %ld", iiProdNumber);
4847 pbuf += sprintf(pbuf, "\n premium options: %Xh", iPremiumOptions);
4848 pbuf += sprintf(pbuf, "\n machine ID: %d", iMachineID);
4849 pbuf += sprintf(pbuf, "\n key: %Xh", iKey);
4858 unsigned char bSegMask;
4860 if (!rpt_0x8F45(rpt,
4863 parsed = BADLEN_PARSE;
4866 pbuf += sprintf(pbuf, "\nCleared Segment Mask: %Xh", bSegMask);
4869 /* Stinger PPS def */
4884 if (rpt_0x8F4A_16 (rpt,
4889 &bias_unc_threshold))
4891 parsed = BADLEN_PARSE;
4895 pbuf += sprintf(pbuf, "\nPPS is %s", pps_enabled?"enabled":"disabled");
4896 pbuf += sprintf(pbuf, "\n timebase: %s", PPSTimeBaseText[pps_timebase]);
4897 pbuf += sprintf(pbuf, "\n polarity: %s", PPSPolarityText[pps_polarity]);
4898 pbuf += sprintf(pbuf, "\n offset: %.1f ns, ", pps_offset*1.e9);
4899 pbuf += sprintf(pbuf, "\n biasunc: %.1f ns", bias_unc_threshold/GPS_C*1.e9);
4902 /* fast-SA decorrolation time for self-survey */
4911 if (rpt_0x8F4B(rpt, &decorr_max))
4913 parsed = BADLEN_PARSE;
4917 pbuf += sprintf(pbuf,
4918 "\nMax # of position fixes for self-survey : %ld",
4931 static unsigned long
4933 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010,
4935 0x00000100L, 0x00000800L, 0x00001000L,
4936 0x40000000L, 0x80000000L};
4941 if (rpt_0x8F4D(rpt, &OutputMask))
4943 parsed = BADLEN_PARSE;
4947 pbuf += sprintf(pbuf, "\nAuto-Report Mask: %02X %02X %02X %02X",
4948 (unsigned char)(OutputMask>>24),
4949 (unsigned char)(OutputMask>>16),
4950 (unsigned char)(OutputMask>>8),
4951 (unsigned char)OutputMask);
4953 numchoices = sizeof(MaskText)/sizeof(char*);
4954 pbuf += sprintf(pbuf, "\nAuto-Reports scheduled for Output:");
4956 for (ichoice = 0; ichoice < numchoices; ichoice++)
4958 if (OutputMask&MaskBit[ichoice])
4960 pbuf += sprintf(pbuf, "%s %s",
4961 (pbuf==linestart)?"\n ":",",
4963 if (pbuf-linestart > 60) linestart = pbuf;
4967 pbuf += sprintf(pbuf, "\nAuto-Reports NOT scheduled for Output:");
4969 for (ichoice = 0; ichoice < numchoices; ichoice++)
4971 if (OutputMask&MaskBit[ichoice]) continue;
4972 pbuf += sprintf(pbuf, "%s %s",
4973 (pbuf==linestart)?"\n ":",",
4975 if (pbuf-linestart > 60) linestart = pbuf;
4987 if (rpt_0x8FA5(rpt, spktmask))
4989 parsed = BADLEN_PARSE;
4993 pbuf += sprintf(pbuf, "\nSuperpacket auto-output mask: %02X %02X %02X %02X",
4994 spktmask[0], spktmask[1], spktmask[2], spktmask[3]);
4996 if (spktmask[0]&0x01) pbuf+= sprintf (pbuf, "\n PPS 8F-0B");
4997 if (spktmask[0]&0x02) pbuf+= sprintf (pbuf, "\n Event 8F-0B");
4998 if (spktmask[0]&0x10) pbuf+= sprintf (pbuf, "\n PPS 8F-AD");
4999 if (spktmask[0]&0x20) pbuf+= sprintf (pbuf, "\n Event 8F-AD");
5000 if (spktmask[2]&0x01) pbuf+= sprintf (pbuf, "\n ppos Fix 8F-20");
5021 static char* Status8FADText[] = {
5026 "CODE_NEED_INITIALIZATION",
5033 "CODE_NO_INTEGRITY",
5037 *LeapStatusText[] = {
5038 " UTC Avail", " ", " ", " ",
5039 " Scheduled", " Pending", " Warning", " In Progress"};
5042 if (rpt_0x8FAD (rpt,
5054 parsed = BADLEN_PARSE;
5058 pbuf += sprintf(pbuf, "\n8FAD Count: %d Status: %s",
5059 Count, Status8FADText[Status]);
5061 pbuf += sprintf(pbuf, "\n Leap Flags:");
5066 if (Flags&(1<<i)) pbuf += sprintf(pbuf, LeapStatusText[i]);
5071 pbuf += sprintf(pbuf, " UTC info not available");
5074 pbuf += sprintf(pbuf, "\n %02d/%02d/%04d (DMY) %02d:%02d:%02d.%09ld UTC",
5075 Day, Month, Year, Hour, Minute, Second, (long)(FracSec*1.e9));
5080 print_msg_table_header(
5086 /* force header is to help auto-output function */
5087 /* last_rptcode is to determine whether to print a header */
5088 /* for the first occurrence of a series of reports */
5095 if (force || rptcode!=last_rptcode)
5097 /* supply a header in console output */
5101 numchars = sprintf(HdrStr, "\nRaw Measurement Data");
5102 numchars += sprintf(HdrStr+numchars,
5103 "\n SV Sample SNR Code Phase Doppler Seconds Time of Meas");
5107 numchars = sprintf(HdrStr, "\nEphemeris Status");
5108 numchars += sprintf(HdrStr+numchars,
5109 "\n SV Time collected Health IODE t oe Fit URA");
5113 numchars = sprintf(HdrStr, "\nTracking Info");
5114 numchars += sprintf(HdrStr+numchars,
5115 "\n SV C Acq Eph SNR Time of Meas Elev Azim ");
5120 last_rptcode = rptcode;
5121 return (short)numchars;
5131 /* app-specific rpt packets */
5132 if (parsed == BADLEN_PARSE)
5134 pbuf += sprintf(pbuf, "\nTSIP report packet ID %2Xh, length %d: Bad length",
5135 rpt->code, rpt->len);
5137 if (parsed == BADID_PARSE)
5139 pbuf += sprintf(pbuf,
5140 "\nTSIP report packet ID %2Xh, length %d: translation not supported",
5141 rpt->code, rpt->len);
5144 if (parsed == BADDATA_PARSE)
5146 pbuf += sprintf(pbuf,
5147 "\nTSIP report packet ID %2Xh, length %d: data content incorrect",
5148 rpt->code, rpt->len);
5151 for (i = 0; i < rpt->len; i++) {
5152 if ((i % 20) == 0) *pbuf++ = '\n';
5153 pbuf += sprintf(pbuf, " %02X", rpt->buf[i]);
5159 ** main subroutine, called from ProcessInputBytesWhileWaitingForKBHit()
5162 TranslateTSIPReportToText(
5164 char *TextOutputBuffer
5168 /* pbuf is the pointer to the current location of the text output */
5169 pbuf = TextOutputBuffer;
5171 /* keep track of whether the message has been successfully parsed */
5172 parsed = GOOD_PARSE;
5174 /* print a header if this is the first of a series of messages */
5175 pbuf += print_msg_table_header (rpt->code, pbuf, FALSE);
5177 /* process incoming TSIP report according to code */
5180 case 0x3D: rpt_chan_A_config (rpt); break;
5181 case 0x40: rpt_almanac_data_page (rpt); break;
5182 case 0x41: rpt_GPS_time (rpt); break;
5183 case 0x42: rpt_single_ECEF_position (rpt); break;
5184 case 0x43: rpt_single_ECEF_velocity (rpt); break;
5185 case 0x45: rpt_SW_version (rpt); break;
5186 case 0x46: rpt_rcvr_health (rpt); break;
5187 case 0x47: rpt_SNR_all_SVs (rpt); break;
5188 case 0x48: rpt_GPS_system_message (rpt); break;
5189 case 0x49: rpt_almanac_health_page (rpt); break;
5190 case 0x4A: switch (rpt->len) {
5192 ** special case (=slip-up) in the TSIP protocol;
5193 ** parsing method depends on length
5195 case 20: rpt_single_lla_position (rpt); break;
5196 case 9: rpt_ref_alt (rpt); break;
5198 case 0x4B: rpt_rcvr_id_and_status (rpt);break;
5199 case 0x4C: rpt_operating_parameters (rpt); break;
5200 case 0x4D: rpt_oscillator_offset (rpt); break;
5201 case 0x4E: rpt_GPS_time_set_response (rpt); break;
5202 case 0x4F: rpt_UTC_offset (rpt); break;
5203 case 0x54: rpt_1SV_bias (rpt); break;
5204 case 0x55: rpt_io_opt (rpt); break;
5205 case 0x56: rpt_ENU_velocity (rpt); break;
5206 case 0x57: rpt_last_fix_info (rpt); break;
5207 case 0x58: rpt_GPS_system_data (rpt); break;
5208 case 0x59: rpt_SVs_enabled (rpt); break;
5209 case 0x5A: rpt_raw_msmt (rpt); break;
5210 case 0x5B: rpt_SV_ephemeris_status (rpt); break;
5211 case 0x5C: rpt_SV_tracking_status (rpt); break;
5212 case 0x6D: rpt_allSV_selection (rpt); break;
5213 case 0x82: rpt_DGPS_position_mode (rpt); break;
5214 case 0x83: rpt_double_ECEF_position (rpt); break;
5215 case 0x84: rpt_double_lla_position (rpt); break;
5216 case 0xBB: rpt_complete_rcvr_config (rpt); break;
5217 case 0xBC: rpt_rcvr_serial_port_config (rpt); break;
5219 case 0x8F: switch (rpt->buf[0])
5221 /* superpackets; parsed according to subcodes */
5222 case 0x0B: rpt_8F0B(rpt); break;
5223 case 0x14: rpt_8F14(rpt); break;
5224 case 0x15: rpt_8F15(rpt); break;
5225 case 0x20: rpt_8F20(rpt); break;
5226 case 0x41: rpt_8F41(rpt); break;
5227 case 0x42: rpt_8F42(rpt); break;
5228 case 0x45: rpt_8F45(rpt); break;
5229 case 0x4A: rpt_8F4A(rpt); break;
5230 case 0x4B: rpt_8F4B(rpt); break;
5231 case 0x4D: rpt_8F4D(rpt); break;
5232 case 0xA5: rpt_8FA5(rpt); break;
5233 case 0xAD: rpt_8FAD(rpt); break;
5234 default: parsed = BADID_PARSE; break;
5238 default: parsed = BADID_PARSE; break;
5241 if (parsed != GOOD_PARSE)
5244 **The message has TSIP structure (DLEs, etc.)
5245 ** but could not be parsed by above routines
5250 /* close TextOutputBuffer */
5254 #endif /* TRIMBLE_OUTPUT_FUNC */
5256 #else /* defined(REFCLOCK) && defined(CLOCK_RIPENCC) */
5257 int refclock_ripencc_bs;
5258 #endif /* defined(REFCLOCK) && defined(CLOCK_RIPENCC) */