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"
49
#else /* HAVE_TIMEPPS_H */
50
# ifdef HAVE_SYS_TIMEPPS_H
51
# include <sys/timepps.h>
52
# endif /* HAVE_SYS_TIMEPPS_H */
53
#endif /* HAVE_TIMEPPS_H */
59
/* we are on little endian */
63
* DEBUG statements: uncomment if necessary
65
/* #define DEBUG_NCC */ /* general debug statements */
66
/* #define DEBUG_PPS */ /* debug pps */
67
/* #define DEBUG_RAW */ /* print raw packets */
69
#define TRIMBLE_OUTPUT_FUNC
70
#define TSIP_VERNUM "7.12a"
77
#define GPS_PI (3.1415926535898)
78
#define GPS_C (299792458.)
79
#define D2R (GPS_PI/180.0)
80
#define R2D (180.0/GPS_PI)
81
#define WEEK (604800.)
84
/* control characters for TSIP packets */
88
#define MAX_RPTBUF (256)
90
/* values of TSIPPKT.status */
91
#define TSIP_PARSED_EMPTY 0
92
#define TSIP_PARSED_FULL 1
93
#define TSIP_PARSED_DLE_1 2
94
#define TSIP_PARSED_DATA 3
95
#define TSIP_PARSED_DLE_2 4
97
#define UTCF_UTC_AVAIL (unsigned char) (1) /* UTC available */
98
#define UTCF_LEAP_SCHD (unsigned char) (1<<4) /* Leap scheduled */
99
#define UTCF_LEAP_PNDG (unsigned char) (1<<5) /* Leap pending, will occur at end of day */
101
#define DEVICE "/dev/gps%d" /* name of radio device */
102
#define PRECISION (-9) /* precision assumed (about 2 ms) */
103
#define PPS_PRECISION (-20) /* precision assumed (about 1 us) */
104
#define REFID "GPS\0" /* reference id */
106
#define DESCRIPTION "RIPE NCC GPS (Palisade)" /* Description */
107
#define SPEED232 B9600 /* 9600 baud */
109
#define NSAMPLES 3 /* stages of median filter */
113
/* TSIP packets have the following structure, whether report or command. */
116
counter, /* counter */
117
len; /* size of buf; < MAX_RPTBUF unsigned chars */
119
status, /* TSIP packet format/parse status */
120
code, /* TSIP code */
121
buf[MAX_RPTBUF];/* report or command string */
124
/* TSIP binary data structures */
129
e, t_oa, i_0, OMEGADOT, sqrt_A,
130
OMEGA_0, omega, M_0, a_f0, a_f1,
131
Axis, n, OMEGA_n, ODOT_n, t_zc;
136
typedef struct { /* Almanac health page (25) parameters */
138
WN_a, SV_health[32], t_oa;
141
typedef struct { /* Universal Coordinated Time (UTC) parms */
151
WN_t, WN_LSF, DN, delta_t_LSF;
154
typedef struct { /* Ionospheric info (float) */
156
alpha_0, alpha_1, alpha_2, alpha_3,
157
beta_0, beta_1, beta_2, beta_3;
160
typedef struct { /* Subframe 1 info (float) */
164
codeL2, L2Pdata, SVacc_raw, SV_health;
168
T_GD, t_oc, a_f2, a_f1, a_f0, SVacc;
171
typedef struct { /* Ephemeris info (float) */
201
Axis, n, r1me2, OMEGA_n, ODOT_n;
204
typedef struct { /* Navigation data structure */
206
sv_number; /* SV number (0 = no entry) */
208
t_ephem; /* time of ephemeris collection */
210
ephclk; /* subframe 1 data */
212
ephorb; /* ephemeris data */
232
#ifdef TRIMBLE_OUTPUT_FUNC
234
*dayname[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"},
235
old_baudnum[] = {0, 1, 4, 5, 6, 8, 9, 11, 28, 12},
236
*st_baud_text_app [] = {"", "", " 300", " 600", " 1200", " 2400",
237
" 4800", " 9600", "19200", "38400"},
238
*old_parity_text[] = {"EVEN", "ODD", "", "", "NONE"},
239
*parity_text [] = {"NONE", "ODD", "EVEN"},
240
*old_input_ch[] = { "TSIP", "RTCM (6 of 8 bits)"},
241
*old_output_ch[] = { "TSIP", "No output", "", "", "", "NMEA 0183"},
242
*protocols_in_text[] = { "", "TSIP", "", ""},
243
*protocols_out_text[] = { "", "TSIP", "NMEA"},
244
*rcvr_port_text [] = { "Port A ", "Port B ", "Current Port"},
245
*dyn_text [] = {"Unchanged", "Land", "Sea", "Air", "Static"},
246
*NavModeText0xBB[] = {"automatic", "time only (0-D)", "", "2-D",
247
"3-D", "", "", "OverDetermined Time"},
248
*PPSTimeBaseText[] = {"GPS", "UTC", "USER"},
249
*PPSPolarityText[] = {"Positive", "Negative"},
250
*MaskText[] = { "Almanac ", "Ephemeris", "UTC ", "Iono ",
251
"GPS Msg ", "Alm Hlth ", "Time Fix ", "SV Select",
252
"Ext Event", "Pos Fix ", "Raw Meas "};
254
#endif /* TRIMBLE_OUTPUT_FUNC */
257
* Unit control structure
259
struct ripencc_unit {
260
int unit; /* unit number */
261
int pollcnt; /* poll message counter */
262
int polled; /* Hand in a sample? */
263
char leapdelta; /* delta of next leap event */
264
unsigned char utcflags; /* delta of next leap event */
265
l_fp tstamp; /* timestamp of last poll */
267
struct timespec ts; /* last timestamp */
268
pps_params_t pps_params; /* pps parameters */
269
pps_info_t pps_info; /* last pps data */
270
pps_handle_t handle; /* pps handlebars */
275
/******************* PROTOYPES *****************/
277
/* prototypes for report parsing primitives */
278
short rpt_0x3D (TSIPPKT *rpt, unsigned char *tx_baud_index,
279
unsigned char *rx_baud_index, unsigned char *char_format_index,
280
unsigned char *stop_bits, unsigned char *tx_mode_index,
281
unsigned char *rx_mode_index);
282
short rpt_0x40 (TSIPPKT *rpt, unsigned char *sv_prn, short *week_num,
283
float *t_zc, float *eccentricity, float *t_oa, float *i_0,
284
float *OMEGA_dot, float *sqrt_A, float *OMEGA_0, float *omega,
286
short rpt_0x41 (TSIPPKT *rpt, float *time_of_week, float *UTC_offset,
288
short rpt_0x42 (TSIPPKT *rpt, float ECEF_pos[3], float *time_of_fix);
289
short rpt_0x43 (TSIPPKT *rpt, float ECEF_vel[3], float *freq_offset,
291
short rpt_0x45 (TSIPPKT *rpt, unsigned char *major_nav_version,
292
unsigned char *minor_nav_version, unsigned char *nav_day,
293
unsigned char *nav_month, unsigned char *nav_year,
294
unsigned char *major_dsp_version, unsigned char *minor_dsp_version,
295
unsigned char *dsp_day, unsigned char *dsp_month,
296
unsigned char *dsp_year);
297
short rpt_0x46 (TSIPPKT *rpt, unsigned char *status1, unsigned char *status2);
298
short rpt_0x47 (TSIPPKT *rpt, unsigned char *nsvs, unsigned char *sv_prn,
300
short rpt_0x48 (TSIPPKT *rpt, unsigned char *message);
301
short rpt_0x49 (TSIPPKT *rpt, unsigned char *sv_health);
302
short rpt_0x4A (TSIPPKT *rpt, float *lat, float *lon, float *alt,
303
float *clock_bias, float *time_of_fix);
304
short rpt_0x4A_2 (TSIPPKT *rpt, float *alt, float *dummy,
305
unsigned char *alt_flag);
306
short rpt_0x4B (TSIPPKT *rpt, unsigned char *machine_id,
307
unsigned char *status3, unsigned char *status4);
308
short rpt_0x4C (TSIPPKT *rpt, unsigned char *dyn_code, float *el_mask,
309
float *snr_mask, float *dop_mask, float *dop_switch);
310
short rpt_0x4D (TSIPPKT *rpt, float *osc_offset);
311
short rpt_0x4E (TSIPPKT *rpt, unsigned char *response);
312
short rpt_0x4F (TSIPPKT *rpt, double *a0, float *a1, float *time_of_data,
313
short *dt_ls, short *wn_t, short *wn_lsf, short *dn, short *dt_lsf);
314
short rpt_0x54 (TSIPPKT *rpt, float *clock_bias, float *freq_offset,
316
short rpt_0x55 (TSIPPKT *rpt, unsigned char *pos_code, unsigned char *vel_code,
317
unsigned char *time_code, unsigned char *aux_code);
318
short rpt_0x56 (TSIPPKT *rpt, float vel_ENU[3], float *freq_offset,
320
short rpt_0x57 (TSIPPKT *rpt, unsigned char *source_code,
321
unsigned char *diag_code, short *week_num, float *time_of_fix);
322
short rpt_0x58 (TSIPPKT *rpt, unsigned char *op_code, unsigned char *data_type,
323
unsigned char *sv_prn, unsigned char *data_length,
324
unsigned char *data_packet);
325
short rpt_0x59 (TSIPPKT *rpt, unsigned char *code_type,
326
unsigned char status_code[32]);
327
short rpt_0x5A (TSIPPKT *rpt, unsigned char *sv_prn, float *sample_length,
328
float *signal_level, float *code_phase, float *Doppler,
329
double *time_of_fix);
330
short rpt_0x5B (TSIPPKT *rpt, unsigned char *sv_prn, unsigned char *sv_health,
331
unsigned char *sv_iode, unsigned char *fit_interval_flag,
332
float *time_of_collection, float *time_of_eph, float *sv_accy);
333
short rpt_0x5C (TSIPPKT *rpt, unsigned char *sv_prn, unsigned char *slot,
334
unsigned char *chan, unsigned char *acq_flag, unsigned char *eph_flag,
335
float *signal_level, float *time_of_last_msmt, float *elev,
336
float *azim, unsigned char *old_msmt_flag,
337
unsigned char *integer_msec_flag, unsigned char *bad_data_flag,
338
unsigned char *data_collect_flag);
339
short rpt_0x6D (TSIPPKT *rpt, unsigned char *manual_mode, unsigned char *nsvs,
340
unsigned char *ndim, unsigned char sv_prn[], float *pdop,
341
float *hdop, float *vdop, float *tdop);
342
short rpt_0x82 (TSIPPKT *rpt, unsigned char *diff_mode);
343
short rpt_0x83 (TSIPPKT *rpt, double ECEF_pos[3], double *clock_bias,
345
short rpt_0x84 (TSIPPKT *rpt, double *lat, double *lon, double *alt,
346
double *clock_bias, float *time_of_fix);
347
short rpt_Paly0xBB(TSIPPKT *rpt, TSIP_RCVR_CFG *TsipxBB);
348
short rpt_0xBC (TSIPPKT *rpt, unsigned char *port_num,
349
unsigned char *in_baud, unsigned char *out_baud,
350
unsigned char *data_bits, unsigned char *parity,
351
unsigned char *stop_bits, unsigned char *flow_control,
352
unsigned char *protocols_in, unsigned char *protocols_out,
353
unsigned char *reserved);
355
/* prototypes for superpacket parsers */
357
short rpt_0x8F0B (TSIPPKT *rpt, unsigned short *event, double *tow,
358
unsigned char *date, unsigned char *month, short *year,
359
unsigned char *dim_mode, short *utc_offset, double *bias, double *drift,
360
float *bias_unc, float *dr_unc, double *lat, double *lon, double *alt,
362
short rpt_0x8F14 (TSIPPKT *rpt, short *datum_idx, double datum_coeffs[5]);
363
short rpt_0x8F15 (TSIPPKT *rpt, short *datum_idx, double datum_coeffs[5]);
364
short rpt_0x8F20 (TSIPPKT *rpt, unsigned char *info, double *lat,
365
double *lon, double *alt, double vel_enu[], double *time_of_fix,
366
short *week_num, unsigned char *nsvs, unsigned char sv_prn[],
367
short sv_IODC[], short *datum_index);
368
short rpt_0x8F41 (TSIPPKT *rpt, unsigned char *bSearchRange,
369
unsigned char *bBoardOptions, unsigned long *iiSerialNumber,
370
unsigned char *bBuildYear, unsigned char *bBuildMonth,
371
unsigned char *bBuildDay, unsigned char *bBuildHour,
372
float *fOscOffset, unsigned short *iTestCodeId);
373
short rpt_0x8F42 (TSIPPKT *rpt, unsigned char *bProdOptionsPre,
374
unsigned char *bProdNumberExt, unsigned short *iCaseSerialNumberPre,
375
unsigned long *iiCaseSerialNumber, unsigned long *iiProdNumber,
376
unsigned short *iPremiumOptions, unsigned short *iMachineID,
377
unsigned short *iKey);
378
short rpt_0x8F45 (TSIPPKT *rpt, unsigned char *bSegMask);
379
short rpt_0x8F4A_16 (TSIPPKT *rpt, unsigned char *pps_enabled,
380
unsigned char *pps_timebase, unsigned char *pos_polarity,
381
double *pps_offset, float *bias_unc_threshold);
382
short rpt_0x8F4B (TSIPPKT *rpt, unsigned long *decorr_max);
383
short rpt_0x8F4D (TSIPPKT *rpt, unsigned long *event_mask);
384
short rpt_0x8FA5 (TSIPPKT *rpt, unsigned char *spktmask);
385
short rpt_0x8FAD (TSIPPKT *rpt, unsigned short *COUNT, double *FracSec,
386
unsigned char *Hour, unsigned char *Minute, unsigned char *Second,
387
unsigned char *Day, unsigned char *Month, unsigned short *Year,
388
unsigned char *Status, unsigned char *Flags);
391
/* prototypes for command-encode primitives with suffix convention: */
392
/* c = clear, s = set, q = query, e = enable, d = disable */
393
void cmd_0x1F (TSIPPKT *cmd);
394
void cmd_0x26 (TSIPPKT *cmd);
395
void cmd_0x2F (TSIPPKT *cmd);
396
void cmd_0x35s (TSIPPKT *cmd, unsigned char pos_code, unsigned char vel_code,
397
unsigned char time_code, unsigned char opts_code);
398
void cmd_0x3C (TSIPPKT *cmd, unsigned char sv_prn);
399
void cmd_0x3Ds (TSIPPKT *cmd, unsigned char baud_out, unsigned char baud_inp,
400
unsigned char char_code, unsigned char stopbitcode,
401
unsigned char output_mode, unsigned char input_mode);
402
void cmd_0xBBq (TSIPPKT *cmd, unsigned char subcode) ;
404
/* prototypes 8E commands */
405
void cmd_0x8E0Bq (TSIPPKT *cmd);
406
void cmd_0x8E41q (TSIPPKT *cmd);
407
void cmd_0x8E42q (TSIPPKT *cmd);
408
void cmd_0x8E4Aq (TSIPPKT *cmd);
409
void cmd_0x8E4As (TSIPPKT *cmd, unsigned char PPSOnOff, unsigned char TimeBase,
410
unsigned char Polarity, double PPSOffset, float Uncertainty);
411
void cmd_0x8E4Bq (TSIPPKT *cmd);
412
void cmd_0x8E4Ds (TSIPPKT *cmd, unsigned long AutoOutputMask);
413
void cmd_0x8EADq (TSIPPKT *cmd);
415
/* header/source border XXXXXXXXXXXXXXXXXXXXXXXXXX */
417
/* Trimble parse functions */
418
static int parse0x8FAD P((TSIPPKT *, struct peer *));
419
static int parse0x8F0B P((TSIPPKT *, struct peer *));
420
#ifdef TRIMBLE_OUTPUT_FUNC
421
static int parseany P((TSIPPKT *, struct peer *));
422
static void TranslateTSIPReportToText P((TSIPPKT *, char *));
423
#endif /* TRIMBLE_OUTPUT_FUNC */
424
static int parse0x5C P((TSIPPKT *, struct peer *));
425
static int parse0x4F P((TSIPPKT *, struct peer *));
426
static void tsip_input_proc P((TSIPPKT *, int));
428
/* Trimble helper functions */
429
static void bPutFloat P((float *, unsigned char *));
430
static void bPutDouble P((double *, unsigned char *));
431
static void bPutULong P((unsigned long *, unsigned char *));
432
static int print_msg_table_header P((int rptcode, char *HdrStr, int force));
433
static char * show_time P((float time_of_week));
435
/* RIPE NCC functions */
436
static void ripencc_control P((int, struct refclockstat *, struct
437
refclockstat *, struct peer *));
438
static int ripencc_ppsapi P((struct peer *, int, int));
439
static int ripencc_get_pps_ts P((struct ripencc_unit *, l_fp *));
440
static int ripencc_start P((int, struct peer *));
441
static void ripencc_shutdown P((int, struct peer *));
442
static void ripencc_poll P((int, struct peer *));
443
static void ripencc_send P((struct peer *, TSIPPKT spt));
444
static void ripencc_receive P((struct recvbuf *));
446
/* fill in reflock structure for our clock */
447
struct refclock refclock_ripencc = {
448
ripencc_start, /* start up driver */
449
ripencc_shutdown, /* shut down driver */
450
ripencc_poll, /* transmit poll message */
451
ripencc_control, /* control function */
452
noentry, /* initialize driver */
453
noentry, /* debug info */
454
NOFLAGS /* clock flags */
458
* Tables to compute the ddd of year form icky dd/mm timecode. Viva la
461
static int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
462
static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
466
* ripencc_start - open the GPS devices and initialize data for processing
469
ripencc_start(int unit, struct peer *peer)
471
register struct ripencc_unit *up;
472
struct refclockproc *pp;
481
(void)snprintf(device, sizeof(device), DEVICE, unit);
482
if (!(fd = refclock_open(device, SPEED232, LDISC_RAW)))
485
/* from refclock_palisade.c */
486
if (tcgetattr(fd, &tio) < 0) {
487
msyslog(LOG_ERR, "Palisade(%d) tcgetattr(fd, &tio): %m",unit);
494
tio.c_cflag |= (PARENB|PARODD);
495
tio.c_iflag &= ~ICRNL;
496
if (tcsetattr(fd, TCSANOW, &tio) == -1) {
497
msyslog(LOG_ERR, "Palisade(%d) tcsetattr(fd, &tio): %m",unit);
502
* Allocate and initialize unit structure
504
if (!(up = (struct ripencc_unit *)
505
emalloc(sizeof(struct ripencc_unit)))) {
509
memset((char *)up, 0, sizeof(struct ripencc_unit));
511
pp->io.clock_recv = ripencc_receive;
512
pp->io.srcclock = (caddr_t)peer;
515
if (!io_addclock(&pp->io)) {
520
pp->unitptr = (caddr_t)up;
523
* Initialize miscellaneous variables
525
peer->precision = PRECISION;
526
pp->clockdesc = DESCRIPTION;
527
memcpy((char *)&pp->refid, REFID, REFID_LEN);
534
* Initialize the Clock
537
/* query software versions */
539
ripencc_send(peer, spt);
541
/* query receiver health */
543
ripencc_send(peer, spt);
545
/* query serial numbers */
547
ripencc_send(peer, spt);
549
/* query manuf params */
551
ripencc_send(peer, spt);
553
/* i/o opts */ /* trimble manual page A30 */
558
0x0a); /* auxilary */
559
ripencc_send(peer, spt);
561
/* turn off port A */
565
0x07, /* char_code */
566
0x07, /* stopbitcode */
567
0x01, /* output_mode */
568
0x00); /* input_mode */
569
ripencc_send(peer, spt);
571
/* set i/o options */
574
0x01, /* Timebase UTC */
575
0x00, /* polarity positive */
576
0., /* 100 ft. cable XXX make flag */
577
1e-6 * GPS_C); /* turn of biasuncert. > (1us) */
578
ripencc_send(peer,spt);
580
/* all outomatic packet output off */
582
0x00000000); /* AutoOutputMask */
583
ripencc_send(peer, spt);
586
0x00); /* query primary configuration */
587
ripencc_send(peer,spt);
590
/* query PPS parameters */
591
cmd_0x8E4Aq (&spt); /* query PPS params */
592
ripencc_send(peer,spt);
594
/* query survey limit */
595
cmd_0x8E4Bq (&spt); /* query survey limit */
596
ripencc_send(peer,spt);
600
printf("ripencc_start: success\n");
601
#endif /* DEBUG_NCC */
604
* Start the PPSAPI interface if it is there. Default to use
605
* the assert edge and do not enable the kernel hardpps.
607
if (time_pps_create(fd, &up->handle) < 0) {
609
msyslog(LOG_ERR, "refclock_ripencc: time_pps_create failed: %m");
613
return(ripencc_ppsapi(peer, 0, 0));
617
* ripencc_control - fudge control
621
int unit, /* unit (not used) */
622
struct refclockstat *in, /* input parameters (not used) */
623
struct refclockstat *out, /* output parameters (not used) */
624
struct peer *peer /* peer structure pointer */
627
struct refclockproc *pp;
630
msyslog(LOG_INFO,"%s()",__FUNCTION__);
631
#endif /* DEBUG_NCC */
634
ripencc_ppsapi(peer, pp->sloppyclockflag & CLK_FLAG2,
635
pp->sloppyclockflag & CLK_FLAG3);
644
struct peer *peer, /* peer structure pointer */
645
int enb_clear, /* clear enable */
646
int enb_hardpps /* hardpps enable */
649
struct refclockproc *pp;
650
struct ripencc_unit *up;
654
up = (struct ripencc_unit *)pp->unitptr;
655
if (time_pps_getcap(up->handle, &capability) < 0) {
657
"refclock_ripencc: time_pps_getcap failed: %m");
660
memset(&up->pps_params, 0, sizeof(pps_params_t));
662
up->pps_params.mode = capability & PPS_CAPTURECLEAR;
664
up->pps_params.mode = capability & PPS_CAPTUREASSERT;
665
if (!up->pps_params.mode) {
667
"refclock_ripencc: invalid capture edge %d",
671
up->pps_params.mode |= PPS_TSFMT_TSPEC;
672
if (time_pps_setparams(up->handle, &up->pps_params) < 0) {
674
"refclock_ripencc: time_pps_setparams failed: %m");
678
if (time_pps_kcbind(up->handle, PPS_KC_HARDPPS,
679
up->pps_params.mode & ~PPS_TSFMT_TSPEC,
680
PPS_TSFMT_TSPEC) < 0) {
682
"refclock_ripencc: time_pps_kcbind failed: %m");
687
peer->precision = PPS_PRECISION;
691
time_pps_getparams(up->handle, &up->pps_params);
693
"refclock_ripencc: capability 0x%x version %d mode 0x%x kern %d\n",
694
capability, up->pps_params.api_version,
695
up->pps_params.mode, enb_hardpps);
697
#endif /* DEBUG_NCC */
703
* This function is called every 64 seconds from ripencc_receive
704
* It will fetch the pps time
706
* Return 0 on failure and 1 on success.
710
struct ripencc_unit *up,
715
struct timespec timeout, ts;
720
msyslog(LOG_INFO,"ripencc_get_pps_ts\n");
721
#endif /* DEBUG_PPS */
725
* Convert the timespec nanoseconds field to ntp l_fp units.
731
memcpy(&pps_info, &up->pps_info, sizeof(pps_info_t));
732
if (time_pps_fetch(up->handle, PPS_TSFMT_TSPEC, &up->pps_info,
735
if (up->pps_params.mode & PPS_CAPTUREASSERT) {
736
if (pps_info.assert_sequence ==
737
up->pps_info.assert_sequence)
739
ts = up->pps_info.assert_timestamp;
740
} else if (up->pps_params.mode & PPS_CAPTURECLEAR) {
741
if (pps_info.clear_sequence ==
742
up->pps_info.clear_sequence)
744
ts = up->pps_info.clear_timestamp;
748
if ((up->ts.tv_sec == ts.tv_sec) && (up->ts.tv_nsec == ts.tv_nsec))
752
tstmp.l_ui = ts.tv_sec + JAN_1970;
753
dtemp = ts.tv_nsec * FRAC / 1e9;
754
tstmp.l_uf = (u_int32)dtemp;
757
msyslog(LOG_INFO,"ts.tv_sec: %d\n",(int)ts.tv_sec);
758
msyslog(LOG_INFO,"ts.tv_nsec: %ld\n",ts.tv_nsec);
759
#endif /* DEBUG_PPS */
766
* ripencc_shutdown - shut down a GPS clock
769
ripencc_shutdown(int unit, struct peer *peer)
771
register struct ripencc_unit *up;
772
struct refclockproc *pp;
775
up = (struct ripencc_unit *)pp->unitptr;
778
time_pps_destroy(up->handle);
780
io_closeclock(&pp->io);
786
* ripencc_poll - called by the transmit procedure
789
ripencc_poll(int unit, struct peer *peer)
791
register struct ripencc_unit *up;
792
struct refclockproc *pp;
797
fprintf(stderr, "ripencc_poll(%d)\n", unit);
798
#endif /* DEBUG_NCC */
800
up = (struct ripencc_unit *)pp->unitptr;
801
if (up->pollcnt == 0)
802
refclock_report(peer, CEVNT_TIMEOUT);
809
/* poll for UTC superpacket */
811
ripencc_send(peer,spt);
815
* ripencc_send - send message to clock
816
* use the structures being created by the trimble functions!
817
* makes the code more readable/clean
820
ripencc_send(struct peer *peer, TSIPPKT spt)
822
unsigned char *ip, *op;
823
unsigned char obuf[512];
827
register struct ripencc_unit *up;
828
register struct refclockproc *pp;
831
up = (struct ripencc_unit *)pp->unitptr;
833
printf("ripencc_send(%d, %02X)\n", up->unit, cmd);
835
#endif /* DEBUG_RAW */
844
if (op-obuf > sizeof(obuf)-5) {
845
msyslog(LOG_ERR, "ripencc_send obuf overflow!");
846
refclock_report(peer, CEVNT_FAULT);
850
if (*ip == 0x10) /* byte stuffing */
859
if (debug) { /* print raw packet */
863
printf("ripencc_send: len %d\n", op-obuf);
864
for (i=1, cp=obuf; cp<op; i++, cp++) {
865
printf(" %02X", *cp);
871
#endif /* DEBUG_RAW */
873
if (write(peer->procptr->io.fd, obuf, op-obuf) == -1) {
874
refclock_report(peer, CEVNT_FAULT);
881
* called when a packet is received on the serial port
882
* takes care of further processing
886
ripencc_receive(struct recvbuf *rbufp)
888
register struct ripencc_unit *up;
889
register struct refclockproc *pp;
891
static TSIPPKT rpt; /* structure for current incoming TSIP report */
892
TSIPPKT spt; /* send packet */
896
/* Use these variables to hold data until we decide its worth keeping */
897
char rd_lastcode[BMAX];
901
/* msyslog(LOG_INFO, "%s",__FUNCTION__); */
904
* Initialize pointers and read the timecode and timestamp
906
peer = (struct peer *)rbufp->recv_srcclock;
908
up = (struct ripencc_unit *)pp->unitptr;
909
rd_lencode = refclock_gtlin(rbufp, rd_lastcode, BMAX, &rd_tmp);
913
fprintf(stderr, "ripencc_receive(%d)\n", up->unit);
914
#endif /* DEBUG_RAW */
917
if (debug) { /* print raw packet */
921
printf("ripencc_receive: len %d\n", rbufp->recv_length);
922
for (i=1, cp=(char*)&rbufp->recv_space; i <= rbufp->recv_length; i++, cp++) {
923
printf(" %02X", *cp);
929
#endif /* DEBUG_RAW */
931
cp = (char*) &rbufp->recv_space;
932
i=rbufp->recv_length;
934
while (i--) { /* loop over received chars */
936
tsip_input_proc(&rpt, (unsigned char) *cp++);
938
if (rpt.status != TSIP_PARSED_FULL)
943
case 0x8F: /* superpacket */
945
switch (rpt.buf[0]) {
947
case 0xAD: /* UTC Time */
949
* When polling on port B the timecode
950
* is the time of the previous PPS.
951
* If we completed receiving the packet
952
* less than 150ms after the turn of the second,
953
* it may have the code of the previous second.
954
* We do not trust that and simply poll again
955
* without even parsing it.
957
* More elegant would be to re-schedule the poll,
958
* but I do not know (yet) how to do that cleanly.
961
/* BLA ns_since_pps = ncc_tstmp(rbufp, &trtmp); */
962
/* if (up->polled && ns_since_pps > -1 && ns_since_pps < 150) { */
965
if (up->polled && ns_since_pps < 150) {
966
msyslog(LOG_INFO, "%s(): up->polled",__FUNCTION__);
967
ripencc_poll(up->unit, peer);
972
* Parse primary utc time packet
973
* and fill refclock structure
976
if (parse0x8FAD(&rpt, peer) < 0) {
977
msyslog(LOG_INFO, "%s(): parse0x8FAD < 0",__FUNCTION__);
978
refclock_report(peer, CEVNT_BADREPLY);
982
* If the PPSAPI is working, rather use its
984
* assume that the PPS occurs on the second
987
if (ripencc_get_pps_ts(up, &rd_tmp) == 1) {
988
pp->lastrec = up->tstamp = rd_tmp;
992
msyslog(LOG_INFO, "%s(): ripencc_get_pps_ts returns failure\n",__FUNCTION__);
996
msyslog(LOG_INFO, "%s(): unrequested packet\n",__FUNCTION__);
997
/* unrequested packet */
1001
/* we have been polled ! */
1005
/* poll for next packet */
1007
ripencc_send(peer,spt);
1009
if (ns_since_pps < 0) { /* no PPS */
1010
msyslog(LOG_INFO, "%s(): ns_since_pps < 0",__FUNCTION__);
1011
refclock_report(peer, CEVNT_BADTIME);
1016
* Process the new sample in the median filter and determine the
1017
* reference clock offset and dispersion.
1019
if (!refclock_process(pp)) {
1020
msyslog(LOG_INFO, "%s(): !refclock_process",__FUNCTION__);
1021
refclock_report(peer, CEVNT_BADTIME);
1025
refclock_receive(peer);
1028
case 0x0B: /* comprehensive time packet */
1029
parse0x8F0B(&rpt, peer);
1032
default: /* other superpackets */
1034
msyslog(LOG_INFO, "%s(): calling parseany",__FUNCTION__);
1035
#endif /* DEBUG_NCC */
1036
#ifdef TRIMBLE_OUTPUT_FUNC
1037
parseany(&rpt, peer);
1038
#endif /* TRIMBLE_OUTPUT_FUNC */
1043
case 0x4F: /* UTC parameters, for leap info */
1044
parse0x4F(&rpt, peer);
1047
case 0x5C: /* sat tracking data */
1048
parse0x5C(&rpt, peer);
1051
default: /* other packets */
1052
#ifdef TRIMBLE_OUTPUT_FUNC
1053
parseany(&rpt, peer);
1054
#endif /* TRIMBLE_OUTPUT_FUNC */
1057
rpt.status = TSIP_PARSED_EMPTY;
1062
* All trimble functions that are directly referenced from driver code
1063
* (so not from parseany)
1066
void cmd_0x1F (TSIPPKT *cmd)
1067
/* request software versions */
1073
void cmd_0x26 (TSIPPKT *cmd)
1074
/* request receiver health */
1083
void cmd_0x2F (TSIPPKT *cmd)
1084
/* request UTC params */
1090
void cmd_0x35s (TSIPPKT *cmd, unsigned char pos_code, unsigned char vel_code,
1091
unsigned char time_code, unsigned char opts_code)
1092
/* set serial I/O options */
1094
cmd->buf[0] = pos_code;
1095
cmd->buf[1] = vel_code;
1096
cmd->buf[2] = time_code;
1097
cmd->buf[3] = opts_code;
1101
void cmd_0x3C (TSIPPKT *cmd, unsigned char sv_prn)
1102
/* request tracking status */
1104
cmd->buf[0] = sv_prn;
1110
void cmd_0x3Ds (TSIPPKT *cmd,
1111
unsigned char baud_out, unsigned char baud_inp,
1112
unsigned char char_code, unsigned char stopbitcode,
1113
unsigned char output_mode, unsigned char input_mode)
1114
/* set Channel A configuration for dual-port operation */
1116
cmd->buf[0] = baud_out; /* XMT baud rate */
1117
cmd->buf[1] = baud_inp; /* RCV baud rate */
1118
cmd->buf[2] = char_code; /* parity and #bits per byte */
1119
cmd->buf[3] = stopbitcode; /* number of stop bits code */
1120
cmd->buf[4] = output_mode; /* Ch. A transmission mode */
1121
cmd->buf[5] = input_mode; /* Ch. A reception mode */
1127
/* query primary configuration */
1128
void cmd_0xBBq (TSIPPKT *cmd,
1129
unsigned char subcode)
1134
cmd->buf[0] = subcode;
1138
/**** Superpackets ****/
1139
void cmd_0x8E0Bq (TSIPPKT *cmd)
1140
/* 8E-0B to query 8F-0B controls */
1149
void cmd_0x8E41q (TSIPPKT *cmd)
1150
/* 8F-41 to query board serial number */
1159
void cmd_0x8E42q (TSIPPKT *cmd)
1160
/* 8F-42 to query product serial number */
1167
void cmd_0x8E4Aq (TSIPPKT *cmd)
1168
/* 8F-4A to query PPS parameters */
1176
/* set i/o options */
1177
void cmd_0x8E4As (TSIPPKT *cmd,
1178
unsigned char PPSOnOff,
1179
unsigned char TimeBase,
1180
unsigned char Polarity,
1187
cmd->buf[1] = PPSOnOff;
1188
cmd->buf[2] = TimeBase;
1189
cmd->buf[3] = Polarity;
1190
bPutDouble (&PPSOffset, &cmd->buf[4]);
1191
bPutFloat (&Uncertainty, &cmd->buf[12]);
1193
void cmd_0x8E4Bq (TSIPPKT *cmd)
1194
/* 8F-4B query survey limit */
1202
/* poll for UTC superpacket */
1203
void cmd_0x8EADq (TSIPPKT *cmd)
1204
/* 8E-AD to query 8F-AD controls */
1211
/* all outomatic packet output off */
1212
void cmd_0x8E4Ds (TSIPPKT *cmd,
1213
unsigned long AutoOutputMask)
1218
bPutULong (&AutoOutputMask, &cmd->buf[1]);
1224
/* for DOS machines, reverse order of bytes as they come through the
1227
static short bGetShort (unsigned char *bp)
1230
unsigned char *optr;
1232
optr = (unsigned char*)&outval + 1;
1238
#ifdef TRIMBLE_OUTPUT_FUNC
1239
static unsigned short bGetUShort (unsigned char *bp)
1241
unsigned short outval;
1242
unsigned char *optr;
1244
optr = (unsigned char*)&outval + 1;
1250
static long bGetLong (unsigned char *bp)
1253
unsigned char *optr;
1255
optr = (unsigned char*)&outval + 3;
1263
static unsigned long bGetULong (unsigned char *bp)
1265
unsigned long outval;
1266
unsigned char *optr;
1268
optr = (unsigned char*)&outval + 3;
1275
#endif /* TRIMBLE_OUTPUT_FUNC */
1277
static float bGetSingle (unsigned char *bp)
1280
unsigned char *optr;
1282
optr = (unsigned char*)&outval + 3;
1290
static double bGetDouble (unsigned char *bp)
1293
unsigned char *optr;
1295
optr = (unsigned char*)&outval + 7;
1307
#else /* not BYTESWAP */
1309
#define bGetShort(bp) (*(short*)(bp))
1310
#define bGetLong(bp) (*(long*)(bp))
1311
#define bGetULong(bp) (*(unsigned long*)(bp))
1312
#define bGetSingle(bp) (*(float*)(bp))
1313
#define bGetDouble(bp) (*(double*)(bp))
1315
#endif /* BYTESWAP */
1317
* Byte-reversal is necessary for little-endian (Intel-based) machines.
1318
* TSIP streams are Big-endian (Motorola-based).
1323
bPutFloat (float *in, unsigned char *out)
1325
unsigned char *inptr;
1327
inptr = (unsigned char*)in + 3;
1335
bPutULong (unsigned long *in, unsigned char *out)
1337
unsigned char *inptr;
1339
inptr = (unsigned char*)in + 3;
1347
bPutDouble (double *in, unsigned char *out)
1349
unsigned char *inptr;
1351
inptr = (unsigned char*)in + 7;
1362
#else /* not BYTESWAP */
1364
void bPutShort (short a, unsigned char *cmdbuf) {*(short*) cmdbuf = a;}
1365
void bPutULong (long a, unsigned char *cmdbuf) {*(long*) cmdbuf = a;}
1366
void bPutFloat (float a, unsigned char *cmdbuf) {*(float*) cmdbuf = a;}
1367
void bPutDouble (double a, unsigned char *cmdbuf){*(double*) cmdbuf = a;}
1369
#endif /* BYTESWAP */
1372
* Parse primary utc time packet
1373
* and fill refclock structure
1381
parse0x8FAD(rpt, peer)
1385
register struct refclockproc *pp;
1386
register struct ripencc_unit *up;
1388
unsigned day, month, year; /* data derived from received timecode */
1389
unsigned hour, minute, second;
1390
unsigned char trackstat, utcflags;
1392
static char logbuf[1024]; /* logging string buffer */
1402
if (bGetShort(&buf[1]) != 0) {
1405
printf("parse0x8FAD: event count != 0\n");
1406
#endif /* DEBUG_NCC */
1411
if (bGetDouble(&buf[3]) != 0.0) {
1414
printf("parse0x8FAD: fracsecs != 0\n");
1415
#endif /* DEBUG_NCC */
1419
hour = (unsigned int) buf[11];
1420
minute = (unsigned int) buf[12];
1421
second = (unsigned int) buf[13];
1422
day = (unsigned int) buf[14];
1423
month = (unsigned int) buf[15];
1424
year = bGetShort(&buf[16]);
1425
trackstat = buf[18];
1429
sprintf(logbuf, "U1 %d.%d.%d %02d:%02d:%02d %d %02x",
1430
day, month, year, hour, minute, second, trackstat, utcflags);
1435
#endif /* DEBUG_NCC */
1437
record_clock_stats(&peer->srcadr, logbuf);
1439
if (!utcflags & UTCF_UTC_AVAIL)
1442
/* poll for UTC parameters once and then if UTC flag changed */
1443
up = (struct ripencc_unit *) pp->unitptr;
1444
if (utcflags != up->utcflags) {
1445
TSIPPKT spt; /* local structure for send packet */
1446
cmd_0x2F (&spt); /* request UTC params */
1447
ripencc_send(peer,spt);
1448
up->utcflags = utcflags;
1452
* If we hit the leap second, we choose to skip this sample
1453
* rather than rely on other code to be perfectly correct.
1454
* No offense, just defense ;-).
1459
/* now check and convert the time we received */
1462
if (month < 1 || month > 12 || day < 1 || day > 31)
1466
if (day > day1tab[month - 1])
1468
for (i = 0; i < month - 1; i++)
1471
if (day > day2tab[month - 1])
1473
for (i = 0; i < month - 1; i++)
1478
pp->minute = minute;
1479
pp-> second = second;
1482
if ((utcflags&UTCF_LEAP_PNDG) && up->leapdelta != 0)
1483
pp-> leap = (up->leapdelta > 0 ? LEAP_ADDSECOND : LEAP_DELSECOND);
1485
pp-> leap = LEAP_NOWARNING;
1491
* Parse comprehensive time packet
1497
int parse0x8F0B(rpt, peer)
1501
register struct refclockproc *pp;
1503
unsigned day, month, year; /* data derived from received timecode */
1504
unsigned hour, minute, second;
1508
float biasunc, rateunc;
1509
double lat, lon, alt;
1510
short lat_deg, lon_deg;
1511
float lat_min, lon_min;
1512
unsigned char north_south, east_west;
1515
static char logbuf[1024]; /* logging string buffer */
1527
if (bGetShort(&buf[1]) != 0)
1530
tow = bGetDouble(&buf[3]);
1535
else if ((tow >= 604800.0) || (tow < 0.0)) {
1540
if (tow < 604799.9) tow = tow + .00000001;
1541
second = (unsigned int) fmod(tow, 60.);
1542
minute = (unsigned int) fmod(tow/60., 60.);
1543
hour = (unsigned int )fmod(tow / 3600., 24.);
1547
day = (unsigned int) buf[11];
1548
month = (unsigned int) buf[12];
1549
year = bGetShort(&buf[13]);
1551
utcoff = bGetShort(&buf[16]);
1552
bias = bGetDouble(&buf[18]) / GPS_C * 1e9; /* ns */
1553
rate = bGetDouble(&buf[26]) / GPS_C * 1e9; /* ppb */
1554
biasunc = bGetSingle(&buf[34]) / GPS_C * 1e9; /* ns */
1555
rateunc = bGetSingle(&buf[38]) / GPS_C * 1e9; /* ppb */
1556
lat = bGetDouble(&buf[42]) * R2D;
1557
lon = bGetDouble(&buf[50]) * R2D;
1558
alt = bGetDouble(&buf[58]);
1567
lat_deg = (short)lat;
1568
lat_min = (lat - lat_deg) * 60.0;
1578
lon_deg = (short)lon;
1579
lon_min = (lon - lon_deg) * 60.0;
1581
for (i=0; i<8; i++) {
1582
sv[i] = buf[i + 66];
1584
TSIPPKT spt; /* local structure for sendpacket */
1585
b = (unsigned char) (sv[i]<0 ? -sv[i] : sv[i]);
1586
/* request tracking status */
1588
ripencc_send(peer,spt);
1593
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",
1594
day, month, year, hour, minute, second, mode, bias, biasunc, rate, rateunc, utcoff,
1595
lat_deg, lat_min, north_south, lon_deg, lon_min, east_west, alt,
1596
sv[0], sv[1], sv[2], sv[3], sv[4], sv[5], sv[6], sv[7]);
1601
#endif /* DEBUG_NCC */
1603
record_clock_stats(&peer->srcadr, logbuf);
1608
#ifdef TRIMBLE_OUTPUT_FUNC
1610
* Parse any packet using Trimble machinery
1612
int parseany(rpt, peer)
1616
static char logbuf[1024]; /* logging string buffer */
1618
TranslateTSIPReportToText (rpt, logbuf); /* anything else */
1622
#endif /* DEBUG_NCC */
1623
record_clock_stats(&peer->srcadr, &logbuf[1]);
1626
#endif /* TRIMBLE_OUTPUT_FUNC */
1630
* Parse UTC Parameter Packet
1632
* See the IDE for documentation!
1638
int parse0x4F(rpt, peer)
1642
register struct ripencc_unit *up;
1646
int dt_ls, wn_t, wn_lsf, dn, dt_lsf;
1648
static char logbuf[1024]; /* logging string buffer */
1655
a0 = bGetDouble (buf);
1656
a1 = bGetSingle (&buf[8]);
1657
dt_ls = bGetShort (&buf[12]);
1658
tot = bGetSingle (&buf[14]);
1659
wn_t = bGetShort (&buf[18]);
1660
wn_lsf = bGetShort (&buf[20]);
1661
dn = bGetShort (&buf[22]);
1662
dt_lsf = bGetShort (&buf[24]);
1664
sprintf(logbuf, "L1 %d %d %d %g %g %g %d %d %d",
1665
dt_lsf - dt_ls, dt_ls, dt_lsf, a0, a1, tot, wn_t, wn_lsf, dn);
1670
#endif /* DEBUG_NCC */
1672
record_clock_stats(&peer->srcadr, logbuf);
1674
up = (struct ripencc_unit *) peer->procptr->unitptr;
1675
up->leapdelta = dt_lsf - dt_ls;
1681
* Parse Tracking Status packet
1687
int parse0x5C(rpt, peer)
1691
unsigned char prn, channel, aqflag, ephstat;
1692
float snr, azinuth, elevation;
1694
static char logbuf[1024]; /* logging string buffer */
1703
channel = (unsigned char)(buf[1] >> 3);
1704
if (channel == 0x10)
1710
snr = bGetSingle(&buf[4]);
1711
elevation = bGetSingle(&buf[12]) * R2D;
1712
azinuth = bGetSingle(&buf[16]) * R2D;
1714
sprintf(logbuf, "S1 %02d %d %d %02x %4.1f %5.1f %4.1f",
1715
prn, channel, aqflag, ephstat, snr, azinuth, elevation);
1720
#endif /* DEBUG_NCC */
1722
record_clock_stats(&peer->srcadr, logbuf);
1727
/******* Code below is from Trimble Tsipchat *************/
1730
* *************************************************************************
1732
* Trimble Navigation, Ltd.
1733
* OEM Products Development Group
1735
* 645 North Mary Avenue
1736
* Sunnyvale, California 94088-3642
1738
* Corporate Headquarter:
1739
* Telephone: (408) 481-8000
1740
* Fax: (408) 481-6005
1742
* Technical Support Center:
1743
* Telephone: (800) 767-4822 (U.S. and Canada)
1744
* (408) 481-6940 (outside U.S. and Canada)
1745
* Fax: (408) 481-6020
1746
* BBS: (408) 481-7800
1747
* e-mail: trimble_support@trimble.com
1748
* ftp://ftp.trimble.com/pub/sct/embedded/bin
1750
* *************************************************************************
1752
* ------- BYTE-SWAPPING -------
1753
* TSIP is big-endian (Motorola) protocol. To use on little-endian (Intel)
1754
* systems, the bytes of all multi-byte types (shorts, floats, doubles, etc.)
1755
* must be reversed. This is controlled by the MACRO BYTESWAP; if defined, it
1756
* assumes little-endian protocol.
1757
* --------------------------------
1759
* T_PARSER.C and T_PARSER.H contains primitive functions that interpret
1760
* reports received from the receiver. A second source file pair,
1761
* T_FORMAT.C and T_FORMAT.H, contin the matching TSIP command formatters.
1763
* The module is in very portable, basic C language. It can be used as is, or
1764
* with minimal changes if a TSIP communications application is needed separate
1765
* from TSIPCHAT. The construction of most argument lists avoid the use of
1766
* structures, but the developer is encouraged to reconstruct them using such
1767
* definitions to meet project requirements. Declarations of T_PARSER.C
1768
* functions are included in T_PARSER.H to provide prototyping definitions.
1770
* There are two types of functions: a serial input processing routine,
1772
* which assembles incoming bytes into a TSIPPKT structure, and the
1773
* report parsers, rpt_0x??().
1775
* 1) The function tsip_input_proc() accumulates bytes from the receiver,
1776
* strips control bytes (DLE), and checks if the report end sequence (DLE ETX)
1777
* has been received. rpt.status is defined as TSIP_PARSED_FULL (== 1)
1778
* if a complete packet is available.
1780
* 2) The functions rpt_0x??() are report string interpreters patterned after
1781
* the document called "Trimble Standard Interface Protocol". It should be
1782
* noted that if the report buffer is sent into the receiver with the wrong
1783
* length (byte count), the rpt_0x??() returns the Boolean equivalence for
1786
* *************************************************************************
1792
static void tsip_input_proc (
1795
/* reads bytes until serial buffer is empty or a complete report
1796
* has been received; end of report is signified by DLE ETX.
1799
unsigned char newbyte;
1801
if (inbyte < 0 || inbyte > 0xFF) return;
1803
newbyte = (unsigned char)(inbyte);
1804
switch (rpt->status)
1806
case TSIP_PARSED_DLE_1:
1811
/* illegal TSIP IDs */
1813
rpt->status = TSIP_PARSED_EMPTY;
1816
/* try normal message start again */
1818
rpt->status = TSIP_PARSED_DLE_1;
1821
/* legal TSIP ID; start message */
1822
rpt->code = newbyte;
1824
rpt->status = TSIP_PARSED_DATA;
1828
case TSIP_PARSED_DATA:
1831
/* expect DLE or ETX next */
1832
rpt->status = TSIP_PARSED_DLE_2;
1835
/* normal data byte */
1836
rpt->buf[rpt->len] = newbyte;
1838
/* no change in rpt->status */
1842
case TSIP_PARSED_DLE_2:
1845
/* normal data byte */
1846
rpt->buf[rpt->len] = newbyte;
1848
rpt->status = TSIP_PARSED_DATA;
1851
/* end of message; return TRUE here. */
1852
rpt->status = TSIP_PARSED_FULL;
1855
/* error: treat as TSIP_PARSED_DLE_1; start new report packet */
1856
rpt->code = newbyte;
1858
rpt->status = TSIP_PARSED_DATA;
1861
case TSIP_PARSED_FULL:
1862
case TSIP_PARSED_EMPTY:
1866
/* normal message start */
1868
rpt->status = TSIP_PARSED_DLE_1;
1871
/* error: ignore newbyte */
1873
rpt->status = TSIP_PARSED_EMPTY;
1877
if (rpt->len > MAX_RPTBUF) {
1878
/* error: start new report packet */
1879
rpt->status = TSIP_PARSED_EMPTY;
1884
#ifdef TRIMBLE_OUTPUT_FUNC
1887
short rpt_0x3D (TSIPPKT *rpt,
1888
unsigned char *tx_baud_index,
1889
unsigned char *rx_baud_index,
1890
unsigned char *char_format_index,
1891
unsigned char *stop_bits,
1892
unsigned char *tx_mode_index,
1893
unsigned char *rx_mode_index)
1894
/* Channel A configuration for dual port operation */
1899
if (rpt->len != 6) return TRUE;
1900
*tx_baud_index = buf[0];
1901
*rx_baud_index = buf[1];
1902
*char_format_index = buf[2];
1903
*stop_bits = (unsigned char)((buf[3] == 0x07) ? 1 : 2);
1904
*tx_mode_index = buf[4];
1905
*rx_mode_index = buf[5];
1910
short rpt_0x40 (TSIPPKT *rpt,
1911
unsigned char *sv_prn,
1914
float *eccentricity,
1922
/* almanac data for specified satellite */
1927
if (rpt->len != 39) return TRUE;
1929
*t_zc = bGetSingle (&buf[1]);
1930
*week_num = bGetShort (&buf[5]);
1931
*eccentricity = bGetSingle (&buf[7]);
1932
*t_oa = bGetSingle (&buf[11]);
1933
*i_0 = bGetSingle (&buf[15]);
1934
*OMEGA_dot = bGetSingle (&buf[19]);
1935
*sqrt_A = bGetSingle (&buf[23]);
1936
*OMEGA_0 = bGetSingle (&buf[27]);
1937
*omega = bGetSingle (&buf[31]);
1938
*M_0 = bGetSingle (&buf[35]);
1942
short rpt_0x41 (TSIPPKT *rpt,
1943
float *time_of_week,
1951
if (rpt->len != 10) return TRUE;
1952
*time_of_week = bGetSingle (buf);
1953
*week_num = bGetShort (&buf[4]);
1954
*UTC_offset = bGetSingle (&buf[6]);
1958
short rpt_0x42 (TSIPPKT *rpt,
1961
/* position in ECEF, single precision */
1966
if (rpt->len != 16) return TRUE;
1967
pos_ECEF[0] = bGetSingle (buf);
1968
pos_ECEF[1]= bGetSingle (&buf[4]);
1969
pos_ECEF[2]= bGetSingle (&buf[8]);
1970
*time_of_fix = bGetSingle (&buf[12]);
1974
short rpt_0x43 (TSIPPKT *rpt,
1978
/* velocity in ECEF, single precision */
1983
if (rpt->len != 20) return TRUE;
1984
ECEF_vel[0] = bGetSingle (buf);
1985
ECEF_vel[1] = bGetSingle (&buf[4]);
1986
ECEF_vel[2] = bGetSingle (&buf[8]);
1987
*freq_offset = bGetSingle (&buf[12]);
1988
*time_of_fix = bGetSingle (&buf[16]);
1992
short rpt_0x45 (TSIPPKT *rpt,
1993
unsigned char *major_nav_version,
1994
unsigned char *minor_nav_version,
1995
unsigned char *nav_day,
1996
unsigned char *nav_month,
1997
unsigned char *nav_year,
1998
unsigned char *major_dsp_version,
1999
unsigned char *minor_dsp_version,
2000
unsigned char *dsp_day,
2001
unsigned char *dsp_month,
2002
unsigned char *dsp_year)
2003
/* software versions */
2008
if (rpt->len != 10) return TRUE;
2009
*major_nav_version = buf[0];
2010
*minor_nav_version = buf[1];
2012
*nav_month = buf[3];
2014
*major_dsp_version = buf[5];
2015
*minor_dsp_version = buf[6];
2017
*dsp_month = buf[8];
2022
short rpt_0x46 (TSIPPKT *rpt,
2023
unsigned char *status1,
2024
unsigned char *status2)
2025
/* receiver health and status */
2030
if (rpt->len != 2) return TRUE;
2036
short rpt_0x47 (TSIPPKT *rpt,
2037
unsigned char *nsvs, unsigned char *sv_prn,
2039
/* signal levels for all satellites tracked */
2045
if (rpt->len != 1 + 5*buf[0]) return TRUE;
2047
for (isv = 0; isv < (*nsvs); isv++) {
2048
sv_prn[isv] = buf[5*isv + 1];
2049
snr[isv] = bGetSingle (&buf[5*isv + 2]);
2054
short rpt_0x48 (TSIPPKT *rpt,
2055
unsigned char *message)
2056
/* GPS system message */
2061
if (rpt->len != 22) return TRUE;
2062
memcpy (message, buf, 22);
2067
short rpt_0x49 (TSIPPKT *rpt,
2068
unsigned char *sv_health)
2069
/* health for all satellites from almanac health page */
2075
if (rpt->len != 32) return TRUE;
2076
for (i = 0; i < 32; i++) sv_health [i]= buf[i];
2080
short rpt_0x4A (TSIPPKT *rpt,
2086
/* position in lat-lon-alt, single precision */
2091
if (rpt->len != 20) return TRUE;
2092
*lat = bGetSingle (buf);
2093
*lon = bGetSingle (&buf[4]);
2094
*alt = bGetSingle (&buf[8]);
2095
*clock_bias = bGetSingle (&buf[12]);
2096
*time_of_fix = bGetSingle (&buf[16]);
2100
short rpt_0x4A_2 (TSIPPKT *rpt,
2101
float *alt, float *dummy , unsigned char *alt_flag)
2102
/* reference altitude parameters */
2108
if (rpt->len != 9) return TRUE;
2109
*alt = bGetSingle (buf);
2110
*dummy = bGetSingle (&buf[4]);
2115
short rpt_0x4B (TSIPPKT *rpt,
2116
unsigned char *machine_id,
2117
unsigned char *status3,
2118
unsigned char *status4)
2119
/* machine ID code, status */
2124
if (rpt->len != 3) return TRUE;
2125
*machine_id = buf[0];
2131
short rpt_0x4C (TSIPPKT *rpt,
2132
unsigned char *dyn_code,
2137
/* operating parameters and masks */
2142
if (rpt->len != 17) return TRUE;
2144
*el_mask = bGetSingle (&buf[1]);
2145
*snr_mask = bGetSingle (&buf[5]);
2146
*dop_mask = bGetSingle (&buf[9]);
2147
*dop_switch = bGetSingle (&buf[13]);
2151
short rpt_0x4D (TSIPPKT *rpt,
2153
/* oscillator offset */
2158
if (rpt->len != 4) return TRUE;
2159
*osc_offset = bGetSingle (buf);
2163
short rpt_0x4E (TSIPPKT *rpt,
2164
unsigned char *response)
2165
/* yes/no response to command to set GPS time */
2170
if (rpt->len != 1) return TRUE;
2175
short rpt_0x4F (TSIPPKT *rpt,
2178
float *time_of_data,
2189
if (rpt->len != 26) return TRUE;
2190
*a0 = bGetDouble (buf);
2191
*a1 = bGetSingle (&buf[8]);
2192
*dt_ls = bGetShort (&buf[12]);
2193
*time_of_data = bGetSingle (&buf[14]);
2194
*wn_t = bGetShort (&buf[18]);
2195
*wn_lsf = bGetShort (&buf[20]);
2196
*dn = bGetShort (&buf[22]);
2197
*dt_lsf = bGetShort (&buf[24]);
2202
short rpt_0x54 (TSIPPKT *rpt,
2206
/* clock offset and frequency offset in 1-SV (0-D) mode */
2211
if (rpt->len != 12) return TRUE;
2212
*clock_bias = bGetSingle (buf);
2213
*freq_offset = bGetSingle (&buf[4]);
2214
*time_of_fix = bGetSingle (&buf[8]);
2218
short rpt_0x55 (TSIPPKT *rpt,
2219
unsigned char *pos_code,
2220
unsigned char *vel_code,
2221
unsigned char *time_code,
2222
unsigned char *aux_code)
2223
/* I/O serial options */
2228
if (rpt->len != 4) return TRUE;
2231
*time_code = buf[2];
2236
short rpt_0x56 (TSIPPKT *rpt,
2237
float vel_ENU[3], float *freq_offset, float *time_of_fix)
2238
/* velocity in east-north-up coordinates */
2243
if (rpt->len != 20) return TRUE;
2245
vel_ENU[0] = bGetSingle (buf);
2247
vel_ENU[1] = bGetSingle (&buf[4]);
2249
vel_ENU[2] = bGetSingle (&buf[8]);
2250
*freq_offset = bGetSingle (&buf[12]);
2251
*time_of_fix = bGetSingle (&buf[16]);
2255
short rpt_0x57 (TSIPPKT *rpt,
2256
unsigned char *source_code, unsigned char *diag_code,
2259
/* info about last computed fix */
2264
if (rpt->len != 8) return TRUE;
2265
*source_code = buf[0];
2266
*diag_code = buf[1];
2267
*time_of_fix = bGetSingle (&buf[2]);
2268
*week_num = bGetShort (&buf[6]);
2272
short rpt_0x58 (TSIPPKT *rpt,
2273
unsigned char *op_code, unsigned char *data_type, unsigned char *sv_prn,
2274
unsigned char *data_length, unsigned char *data_packet)
2275
/* GPS system data or acknowledgment of GPS system data load */
2277
unsigned char *buf, *buf4;
2287
if (rpt->len < 4) return TRUE;
2288
if (rpt->len != 4+buf[3]) return TRUE;
2290
else if (rpt->len != 3) {
2294
*data_type = buf[1];
2296
if (*op_code == 2) {
2298
*data_length = (unsigned char)dl;
2300
switch (*data_type) {
2303
if (*data_length != sizeof (ALM_INFO)) return TRUE;
2304
alminfo = (ALM_INFO*)data_packet;
2305
alminfo->t_oa_raw = buf4[0];
2306
alminfo->SV_health = buf4[1];
2307
alminfo->e = bGetSingle(&buf4[2]);
2308
alminfo->t_oa = bGetSingle(&buf4[6]);
2309
alminfo->i_0 = bGetSingle(&buf4[10]);
2310
alminfo->OMEGADOT = bGetSingle(&buf4[14]);
2311
alminfo->sqrt_A = bGetSingle(&buf4[18]);
2312
alminfo->OMEGA_0 = bGetSingle(&buf4[22]);
2313
alminfo->omega = bGetSingle(&buf4[26]);
2314
alminfo->M_0 = bGetSingle(&buf4[30]);
2315
alminfo->a_f0 = bGetSingle(&buf4[34]);
2316
alminfo->a_f1 = bGetSingle(&buf4[38]);
2317
alminfo->Axis = bGetSingle(&buf4[42]);
2318
alminfo->n = bGetSingle(&buf4[46]);
2319
alminfo->OMEGA_n = bGetSingle(&buf4[50]);
2320
alminfo->ODOT_n = bGetSingle(&buf4[54]);
2321
alminfo->t_zc = bGetSingle(&buf4[58]);
2322
alminfo->weeknum = bGetShort(&buf4[62]);
2323
alminfo->wn_oa = bGetShort(&buf4[64]);
2327
/* Almanac health page */
2328
if (*data_length != sizeof (ALH_PARMS) + 3) return TRUE;
2330
/* this record is returned raw */
2331
memcpy (data_packet, buf4, dl);
2336
if (*data_length != sizeof (ION_INFO) + 8) return TRUE;
2337
ioninfo = (ION_INFO*)data_packet;
2338
ioninfo->alpha_0 = bGetSingle (&buf4[8]);
2339
ioninfo->alpha_1 = bGetSingle (&buf4[12]);
2340
ioninfo->alpha_2 = bGetSingle (&buf4[16]);
2341
ioninfo->alpha_3 = bGetSingle (&buf4[20]);
2342
ioninfo->beta_0 = bGetSingle (&buf4[24]);
2343
ioninfo->beta_1 = bGetSingle (&buf4[28]);
2344
ioninfo->beta_2 = bGetSingle (&buf4[32]);
2345
ioninfo->beta_3 = bGetSingle (&buf4[36]);
2350
if (*data_length != sizeof (UTC_INFO) + 13) return TRUE;
2351
utcinfo = (UTC_INFO*)data_packet;
2352
utcinfo->A_0 = bGetDouble (&buf4[13]);
2353
utcinfo->A_1 = bGetSingle (&buf4[21]);
2354
utcinfo->delta_t_LS = bGetShort (&buf4[25]);
2355
utcinfo->t_ot = bGetSingle(&buf4[27]);
2356
utcinfo->WN_t = bGetShort (&buf4[31]);
2357
utcinfo->WN_LSF = bGetShort (&buf4[33]);
2358
utcinfo->DN = bGetShort (&buf4[35]);
2359
utcinfo->delta_t_LSF = bGetShort (&buf4[37]);
2364
if (*data_length != sizeof (NAV_INFO) - 1) return TRUE;
2366
navinfo = (NAV_INFO*)data_packet;
2368
navinfo->sv_number = buf4[0];
2369
navinfo->t_ephem = bGetSingle (&buf4[1]);
2370
navinfo->ephclk.weeknum = bGetShort (&buf4[5]);
2372
navinfo->ephclk.codeL2 = buf4[7];
2373
navinfo->ephclk.L2Pdata = buf4[8];
2374
navinfo->ephclk.SVacc_raw = buf4[9];
2375
navinfo->ephclk.SV_health = buf4[10];
2376
navinfo->ephclk.IODC = bGetShort (&buf4[11]);
2377
navinfo->ephclk.T_GD = bGetSingle (&buf4[13]);
2378
navinfo->ephclk.t_oc = bGetSingle (&buf4[17]);
2379
navinfo->ephclk.a_f2 = bGetSingle (&buf4[21]);
2380
navinfo->ephclk.a_f1 = bGetSingle (&buf4[25]);
2381
navinfo->ephclk.a_f0 = bGetSingle (&buf4[29]);
2382
navinfo->ephclk.SVacc = bGetSingle (&buf4[33]);
2384
navinfo->ephorb.IODE = buf4[37];
2385
navinfo->ephorb.fit_interval = buf4[38];
2386
navinfo->ephorb.C_rs = bGetSingle (&buf4[39]);
2387
navinfo->ephorb.delta_n = bGetSingle (&buf4[43]);
2388
navinfo->ephorb.M_0 = bGetDouble (&buf4[47]);
2389
navinfo->ephorb.C_uc = bGetSingle (&buf4[55]);
2390
navinfo->ephorb.e = bGetDouble (&buf4[59]);
2391
navinfo->ephorb.C_us = bGetSingle (&buf4[67]);
2392
navinfo->ephorb.sqrt_A = bGetDouble (&buf4[71]);
2393
navinfo->ephorb.t_oe = bGetSingle (&buf4[79]);
2394
navinfo->ephorb.C_ic = bGetSingle (&buf4[83]);
2395
navinfo->ephorb.OMEGA_0 = bGetDouble (&buf4[87]);
2396
navinfo->ephorb.C_is = bGetSingle (&buf4[95]);
2397
navinfo->ephorb.i_0 = bGetDouble (&buf4[99]);
2398
navinfo->ephorb.C_rc = bGetSingle (&buf4[107]);
2399
navinfo->ephorb.omega = bGetDouble (&buf4[111]);
2400
navinfo->ephorb.OMEGADOT=bGetSingle (&buf4[119]);
2401
navinfo->ephorb.IDOT = bGetSingle (&buf4[123]);
2402
navinfo->ephorb.Axis = bGetDouble (&buf4[127]);
2403
navinfo->ephorb.n = bGetDouble (&buf4[135]);
2404
navinfo->ephorb.r1me2 = bGetDouble (&buf4[143]);
2405
navinfo->ephorb.OMEGA_n=bGetDouble (&buf4[151]);
2406
navinfo->ephorb.ODOT_n = bGetDouble (&buf4[159]);
2413
short rpt_0x59 (TSIPPKT *rpt,
2414
unsigned char *code_type,
2415
unsigned char status_code[32])
2416
/* satellite enable/disable or health heed/ignore list */
2422
if (rpt->len != 33) return TRUE;
2423
*code_type = buf[0];
2424
for (iprn = 0; iprn < 32; iprn++)
2425
status_code[iprn] = buf[iprn + 1];
2429
short rpt_0x5A (TSIPPKT *rpt,
2430
unsigned char *sv_prn,
2431
float *sample_length,
2432
float *signal_level,
2435
double *time_of_fix)
2436
/* raw measurement data - code phase/Doppler */
2441
if (rpt->len != 25) return TRUE;
2443
*sample_length = bGetSingle (&buf[1]);
2444
*signal_level = bGetSingle (&buf[5]);
2445
*code_phase = bGetSingle (&buf[9]);
2446
*Doppler = bGetSingle (&buf[13]);
2447
*time_of_fix = bGetDouble (&buf[17]);
2451
short rpt_0x5B (TSIPPKT *rpt,
2452
unsigned char *sv_prn,
2453
unsigned char *sv_health,
2454
unsigned char *sv_iode,
2455
unsigned char *fit_interval_flag,
2456
float *time_of_collection,
2459
/* satellite ephorb status */
2464
if (rpt->len != 16) return TRUE;
2466
*time_of_collection = bGetSingle (&buf[1]);
2467
*sv_health = buf[5];
2469
*time_of_eph = bGetSingle (&buf[7]);
2470
*fit_interval_flag = buf[11];
2471
*sv_accy = bGetSingle (&buf[12]);
2475
short rpt_0x5C (TSIPPKT *rpt,
2476
unsigned char *sv_prn,
2477
unsigned char *slot,
2478
unsigned char *chan,
2479
unsigned char *acq_flag,
2480
unsigned char *eph_flag,
2481
float *signal_level,
2482
float *time_of_last_msmt,
2485
unsigned char *old_msmt_flag,
2486
unsigned char *integer_msec_flag,
2487
unsigned char *bad_data_flag,
2488
unsigned char *data_collect_flag)
2489
/* satellite tracking status */
2494
if (rpt->len != 24) return TRUE;
2496
*slot = (unsigned char)((buf[1] & 0x07) + 1);
2497
*chan = (unsigned char)(buf[1] >> 3);
2498
if (*chan == 0x10) *chan = 2;
2502
*signal_level = bGetSingle (&buf[4]);
2503
*time_of_last_msmt = bGetSingle (&buf[8]);
2504
*elev = bGetSingle (&buf[12]);
2505
*azim = bGetSingle (&buf[16]);
2506
*old_msmt_flag = buf[20];
2507
*integer_msec_flag = buf[21];
2508
*bad_data_flag = buf[22];
2509
*data_collect_flag = buf[23];
2514
short rpt_0x6D (TSIPPKT *rpt,
2515
unsigned char *manual_mode,
2516
unsigned char *nsvs,
2517
unsigned char *ndim,
2518
unsigned char sv_prn[],
2523
/* over-determined satellite selection for position fixes, PDOP, fix mode */
2529
*nsvs = (unsigned char)((buf[0] & 0xF0) >> 4);
2530
if ((*nsvs)>8) return TRUE;
2531
if (rpt->len != 17 + (*nsvs) ) return TRUE;
2533
*manual_mode = (unsigned char)(buf[0] & 0x08);
2534
*ndim = (unsigned char)((buf[0] & 0x07));
2535
*pdop = bGetSingle (&buf[1]);
2536
*hdop = bGetSingle (&buf[5]);
2537
*vdop = bGetSingle (&buf[9]);
2538
*tdop = bGetSingle (&buf[13]);
2539
for (islot = 0; islot < (*nsvs); islot++)
2540
sv_prn[islot] = buf[islot + 17];
2545
short rpt_0x82 (TSIPPKT *rpt,
2546
unsigned char *diff_mode)
2547
/* differential fix mode */
2552
if (rpt->len != 1) return TRUE;
2553
*diff_mode = buf[0];
2557
short rpt_0x83 (TSIPPKT *rpt,
2561
/* position, ECEF double precision */
2566
if (rpt->len != 36) return TRUE;
2567
ECEF_pos[0] = bGetDouble (buf);
2568
ECEF_pos[1] = bGetDouble (&buf[8]);
2569
ECEF_pos[2] = bGetDouble (&buf[16]);
2570
*clock_bias = bGetDouble (&buf[24]);
2571
*time_of_fix = bGetSingle (&buf[32]);
2575
short rpt_0x84 (TSIPPKT *rpt,
2581
/* position, lat-lon-alt double precision */
2586
if (rpt->len != 36) return TRUE;
2587
*lat = bGetDouble (buf);
2588
*lon = bGetDouble (&buf[8]);
2589
*alt = bGetDouble (&buf[16]);
2590
*clock_bias = bGetDouble (&buf[24]);
2591
*time_of_fix = bGetSingle (&buf[32]);
2595
short rpt_Paly0xBB(TSIPPKT *rpt,
2596
TSIP_RCVR_CFG *TsipxBB)
2602
/* Palisade is inconsistent with other TSIP, which has a kength of 40 */
2603
/* if (rpt->len != 40) return TRUE; */
2604
if (rpt->len != 43) return TRUE;
2606
TsipxBB->bSubcode = buf[0];
2607
TsipxBB->operating_mode = buf[1] ;
2608
TsipxBB->dyn_code = buf[3] ;
2609
TsipxBB->elev_mask = bGetSingle (&buf[5]);
2610
TsipxBB->cno_mask = bGetSingle (&buf[9]);
2611
TsipxBB->dop_mask = bGetSingle (&buf[13]);
2612
TsipxBB->dop_switch = bGetSingle (&buf[17]);
2616
short rpt_0xBC (TSIPPKT *rpt,
2617
unsigned char *port_num,
2618
unsigned char *in_baud,
2619
unsigned char *out_baud,
2620
unsigned char *data_bits,
2621
unsigned char *parity,
2622
unsigned char *stop_bits,
2623
unsigned char *flow_control,
2624
unsigned char *protocols_in,
2625
unsigned char *protocols_out,
2626
unsigned char *reserved)
2627
/* Receiver serial port configuration */
2632
if (rpt->len != 10) return TRUE;
2636
*data_bits = buf[3];
2638
*stop_bits = buf[5];
2639
*flow_control = buf[6];
2640
*protocols_in = buf[7];
2641
*protocols_out = buf[8];
2647
/**** Superpackets ****/
2649
short rpt_0x8F0B(TSIPPKT *rpt,
2650
unsigned short *event,
2652
unsigned char *date,
2653
unsigned char *month,
2655
unsigned char *dim_mode,
2670
if (rpt->len != 74) return TRUE;
2671
*event = bGetShort(&buf[1]);
2672
*tow = bGetDouble(&buf[3]);
2675
*year = bGetShort(&buf[13]);
2676
*dim_mode = buf[15];
2677
*utc_offset = bGetShort(&buf[16]);
2678
*bias = bGetDouble(&buf[18]);
2679
*drift = bGetDouble(&buf[26]);
2680
*bias_unc = bGetSingle(&buf[34]);
2681
*dr_unc = bGetSingle(&buf[38]);
2682
*lat = bGetDouble(&buf[42]);
2683
*lon = bGetDouble(&buf[50]);
2684
*alt = bGetDouble(&buf[58]);
2686
for (local_index=0; local_index<8; local_index++) sv_id[local_index] = buf[local_index + 66];
2690
short rpt_0x8F14 (TSIPPKT *rpt,
2692
double datum_coeffs[5])
2693
/* datum index and coefficients */
2698
if (rpt->len != 43) return TRUE;
2699
*datum_idx = bGetShort(&buf[1]);
2700
datum_coeffs[0] = bGetDouble (&buf[3]);
2701
datum_coeffs[1] = bGetDouble (&buf[11]);
2702
datum_coeffs[2] = bGetDouble (&buf[19]);
2703
datum_coeffs[3] = bGetDouble (&buf[27]);
2704
datum_coeffs[4] = bGetDouble (&buf[35]);
2709
short rpt_0x8F15 (TSIPPKT *rpt,
2711
double datum_coeffs[5])
2712
/* datum index and coefficients */
2717
if (rpt->len != 43) return TRUE;
2718
*datum_idx = bGetShort(&buf[1]);
2719
datum_coeffs[0] = bGetDouble (&buf[3]);
2720
datum_coeffs[1] = bGetDouble (&buf[11]);
2721
datum_coeffs[2] = bGetDouble (&buf[19]);
2722
datum_coeffs[3] = bGetDouble (&buf[27]);
2723
datum_coeffs[4] = bGetDouble (&buf[35]);
2728
#define MAX_LONG (2147483648.) /* 2**31 */
2730
short rpt_0x8F20 (TSIPPKT *rpt,
2731
unsigned char *info,
2736
double *time_of_fix,
2738
unsigned char *nsvs,
2739
unsigned char sv_prn[],
2756
if (rpt->len != 56) return TRUE;
2758
vel_scale = (buf[24]&1)? 0.020 : 0.005;
2759
vel_enu[0] = bGetShort (buf+2)*vel_scale;
2760
vel_enu[1] = bGetShort (buf+4)*vel_scale;
2761
vel_enu[2] = bGetShort (buf+6)*vel_scale;
2763
*time_of_fix = bGetULong (buf+8)*.001;
2765
longtemp = bGetLong (buf+12);
2766
*lat = longtemp*(GPS_PI/MAX_LONG);
2768
ulongtemp = bGetULong (buf+16);
2769
*lon = ulongtemp*(GPS_PI/MAX_LONG);
2770
if (*lon > GPS_PI) *lon -= 2.0*GPS_PI;
2772
*alt = bGetLong (buf+20)*.001;
2773
/* 25 blank; 29 = UTC */
2774
(*datum_index) = (short)((short)buf[26]-1);
2777
*week_num = bGetShort (&buf[30]);
2778
for (isv = 0; isv < 8; isv++) {
2779
prnx = buf[32+2*isv];
2780
sv_prn[isv] = (unsigned char)(prnx&0x3F);
2781
iode = buf[33+2*isv];
2782
sv_IODC[isv] = (short)(iode | ((prnx>>6)<<8));
2787
short rpt_0x8F41 (TSIPPKT *rpt,
2788
unsigned char *bSearchRange,
2789
unsigned char *bBoardOptions,
2790
unsigned long *iiSerialNumber,
2791
unsigned char *bBuildYear,
2792
unsigned char *bBuildMonth,
2793
unsigned char *bBuildDay,
2794
unsigned char *bBuildHour,
2796
unsigned short *iTestCodeId)
2798
if(rpt->len != 17) return FALSE;
2799
*bSearchRange = rpt->buf[1];
2800
*bBoardOptions = rpt->buf[2];
2801
*iiSerialNumber = bGetLong(&rpt->buf[3]);
2802
*bBuildYear = rpt->buf[7];
2803
*bBuildMonth = rpt->buf[8];
2804
*bBuildDay = rpt->buf[9];
2805
*bBuildHour = rpt->buf[10];
2806
*fOscOffset = bGetSingle(&rpt->buf[11]);
2807
*iTestCodeId = bGetShort(&rpt->buf[15]);
2808
/* Tsipx8E41Data = *Tsipx8E41; */
2812
short rpt_0x8F42 (TSIPPKT *rpt,
2813
unsigned char *bProdOptionsPre,
2814
unsigned char *bProdNumberExt,
2815
unsigned short *iCaseSerialNumberPre,
2816
unsigned long *iiCaseSerialNumber,
2817
unsigned long *iiProdNumber,
2818
unsigned short *iPremiumOptions,
2819
unsigned short *iMachineID,
2820
unsigned short *iKey)
2822
if(rpt->len != 19) return FALSE;
2823
*bProdOptionsPre = rpt->buf[1];
2824
*bProdNumberExt = rpt->buf[2];
2825
*iCaseSerialNumberPre = bGetShort(&rpt->buf[3]);
2826
*iiCaseSerialNumber = bGetLong(&rpt->buf[5]);
2827
*iiProdNumber = bGetLong(&rpt->buf[9]);
2828
*iPremiumOptions = bGetShort(&rpt->buf[13]);
2829
*iMachineID = bGetShort(&rpt->buf[15]);
2830
*iKey = bGetShort(&rpt->buf[17]);
2834
short rpt_0x8F45(TSIPPKT *rpt,
2835
unsigned char *bSegMask)
2837
if(rpt->len != 2) return FALSE;
2838
*bSegMask = rpt->buf[1];
2842
short rpt_0x8F4A_16(TSIPPKT *rpt,
2843
unsigned char *pps_enabled,
2844
unsigned char *pps_timebase,
2845
unsigned char *pos_polarity,
2847
float *bias_unc_threshold)
2848
/* Stinger PPS definition */
2854
if (rpt->len != 16) return TRUE;
2855
*pps_enabled = buf[1];
2856
*pps_timebase = buf[2];
2857
*pos_polarity = buf[3];
2858
*pps_offset = bGetDouble(&buf[4]);
2859
*bias_unc_threshold = bGetSingle(&buf[12]);
2863
short rpt_0x8F4B(TSIPPKT *rpt,
2864
unsigned long *decorr_max)
2870
if (rpt->len != 5) return TRUE;
2871
*decorr_max = bGetLong(&buf[1]);
2875
short rpt_0x8F4D(TSIPPKT *rpt,
2876
unsigned long *event_mask)
2882
if (rpt->len != 5) return TRUE;
2883
*event_mask = bGetULong (&buf[1]);
2887
short rpt_0x8FA5(TSIPPKT *rpt,
2888
unsigned char *spktmask)
2894
if (rpt->len != 5) return TRUE;
2895
spktmask[0] = buf[1];
2896
spktmask[1] = buf[2];
2897
spktmask[2] = buf[3];
2898
spktmask[3] = buf[4];
2902
short rpt_0x8FAD (TSIPPKT *rpt,
2903
unsigned short *COUNT,
2905
unsigned char *Hour,
2906
unsigned char *Minute,
2907
unsigned char *Second,
2909
unsigned char *Month,
2910
unsigned short *Year,
2911
unsigned char *Status,
2912
unsigned char *Flags)
2915
if (rpt->len != 22) return TRUE;
2917
*COUNT = bGetUShort(&rpt->buf[1]);
2918
*FracSec = bGetDouble(&rpt->buf[3]);
2919
*Hour = rpt->buf[11];
2920
*Minute = rpt->buf[12];
2921
*Second = rpt->buf[13];
2922
*Day = rpt->buf[14];
2923
*Month = rpt->buf[15];
2924
*Year = bGetUShort(&rpt->buf[16]);
2925
*Status = rpt->buf[18];
2926
*Flags = rpt->buf[19];
2932
* *************************************************************************
2934
* Trimble Navigation, Ltd.
2935
* OEM Products Development Group
2937
* 645 North Mary Avenue
2938
* Sunnyvale, California 94088-3642
2940
* Corporate Headquarter:
2941
* Telephone: (408) 481-8000
2942
* Fax: (408) 481-6005
2944
* Technical Support Center:
2945
* Telephone: (800) 767-4822 (U.S. and Canada)
2946
* (408) 481-6940 (outside U.S. and Canada)
2947
* Fax: (408) 481-6020
2948
* BBS: (408) 481-7800
2949
* e-mail: trimble_support@trimble.com
2950
* ftp://ftp.trimble.com/pub/sct/embedded/bin
2952
* *************************************************************************
2954
* T_REPORT.C consists of a primary function TranslateTSIPReportToText()
2957
* This function takes a character buffer that has been received as a report
2958
* from a TSIP device and interprets it. The character buffer has been
2959
* assembled using tsip_input_proc() in T_PARSER.C.
2961
* A large case statement directs processing to one of many mid-level
2962
* functions. The mid-level functions specific to the current report
2963
* code passes the report buffer to the appropriate report decoder
2964
* rpt_0x?? () in T_PARSER.C, which converts the byte stream in rpt.buf
2965
* to data values approporaite for use.
2967
* *************************************************************************
2972
#define GOOD_PARSE 0
2973
#define BADID_PARSE 1
2974
#define BADLEN_PARSE 2
2975
#define BADDATA_PARSE 3
2981
/* pbuf is the pointer to the current location of the text output */
2985
/* keep track of whether the message has been successfully parsed */
2990
/* convert time of week into day-hour-minute-second and print */
2991
char* show_time (float time_of_week)
2993
short days, hours, minutes;
2996
static char timestring [80];
2998
if (time_of_week == -1.0)
3000
sprintf(timestring, " <No time yet> ");
3002
else if ((time_of_week >= 604800.0) || (time_of_week < 0.0))
3004
sprintf(timestring, " <Bad time> ");
3008
if (time_of_week < 604799.9)
3009
tow = time_of_week + .00000001;
3010
seconds = (float)fmod(tow, 60.);
3011
minutes = (short) fmod(tow/60., 60.);
3012
hours = (short)fmod(tow / 3600., 24.);
3013
days = (short)(tow / 86400.0);
3014
sprintf(timestring, " %s %02d:%02d:%05.2f ",
3015
dayname[days], hours, minutes, seconds);
3022
static void rpt_chan_A_config (TSIPPKT *rpt)
3025
tx_baud_index, rx_baud_index,
3026
char_format_index, stop_bits,
3027
tx_mode_index, rx_mode_index,
3034
&tx_baud_index, &rx_baud_index, &char_format_index,
3035
&stop_bits, &tx_mode_index, &rx_mode_index)) {
3036
parsed = BADLEN_PARSE;
3040
pbuf += sprintf(pbuf, "\nChannel A Configuration");
3042
nbaud = sizeof(old_baudnum);
3044
for (i = 0; i < nbaud; ++i) if (tx_baud_index == old_baudnum[i]) break;
3045
pbuf += sprintf(pbuf, "\n Transmit speed: %s at %s",
3046
old_output_ch[tx_mode_index], st_baud_text_app[i]);
3048
for (i = 0; i < nbaud; ++i) if (rx_baud_index == old_baudnum[i]) break;
3049
pbuf += sprintf(pbuf, "\n Receive speed: %s at %s",
3050
old_input_ch[rx_mode_index], st_baud_text_app[i]);
3052
databits = (unsigned char)((char_format_index & 0x03) + 5);
3054
parity = (unsigned char)(char_format_index >> 2);
3055
if (parity > 4) parity = 2;
3057
pbuf += sprintf(pbuf, "\n Character format (bits/char, parity, stop bits): %d-%s-%d",
3058
databits, old_parity_text[parity], stop_bits);
3063
static void rpt_almanac_data_page (TSIPPKT *rpt)
3082
&sv_prn, &week_num, &t_zc, &eccentricity, &t_oa,
3083
&i_0, &OMEGA_dot, &sqrt_A, &OMEGA_0, &omega, &M_0)) {
3084
parsed = BADLEN_PARSE;
3088
pbuf += sprintf(pbuf, "\nAlmanac for SV %02d", sv_prn);
3089
pbuf += sprintf(pbuf, "\n Captured:%15.0f %s",
3090
t_zc, show_time (t_zc));
3091
pbuf += sprintf(pbuf, "\n week:%15d", week_num);
3092
pbuf += sprintf(pbuf, "\n Eccentricity:%15g", eccentricity);
3093
pbuf += sprintf(pbuf, "\n T_oa:%15.0f %s",
3094
t_oa, show_time (t_oa));
3095
pbuf += sprintf(pbuf, "\n i 0:%15g", i_0);
3096
pbuf += sprintf(pbuf, "\n OMEGA dot:%15g", OMEGA_dot);
3097
pbuf += sprintf(pbuf, "\n sqrt A:%15g", sqrt_A);
3098
pbuf += sprintf(pbuf, "\n OMEGA 0:%15g", OMEGA_0);
3099
pbuf += sprintf(pbuf, "\n omega:%15g", omega);
3100
pbuf += sprintf(pbuf, "\n M 0:%15g", M_0);
3104
static void rpt_GPS_time (TSIPPKT *rpt)
3107
time_of_week, UTC_offset;
3112
if (rpt_0x41 (rpt, &time_of_week, &UTC_offset, &week_num)) {
3113
parsed = BADLEN_PARSE;
3117
pbuf += sprintf(pbuf, "\nGPS time:%s GPS week: %d UTC offset %.1f",
3118
show_time(time_of_week), week_num, UTC_offset);
3123
static void rpt_single_ECEF_position (TSIPPKT *rpt)
3126
ECEF_pos[3], time_of_fix;
3129
if (rpt_0x42 (rpt, ECEF_pos, &time_of_fix)) {
3130
parsed = BADLEN_PARSE;
3134
pbuf += sprintf(pbuf, "\nSXYZ: %15.0f %15.0f %15.0f %s",
3135
ECEF_pos[0], ECEF_pos[1], ECEF_pos[2],
3136
show_time(time_of_fix));
3140
static void rpt_single_ECEF_velocity (TSIPPKT *rpt)
3144
ECEF_vel[3], freq_offset, time_of_fix;
3147
if (rpt_0x43 (rpt, ECEF_vel, &freq_offset, &time_of_fix)) {
3148
parsed = BADLEN_PARSE;
3152
pbuf += sprintf(pbuf, "\nVelECEF: %11.3f %11.3f %11.3f %12.3f%s",
3153
ECEF_vel[0], ECEF_vel[1], ECEF_vel[2], freq_offset,
3154
show_time(time_of_fix));
3158
static void rpt_SW_version (TSIPPKT *rpt) {
3160
major_nav_version, minor_nav_version,
3161
nav_day, nav_month, nav_year,
3162
major_dsp_version, minor_dsp_version,
3163
dsp_day, dsp_month, dsp_year;
3167
&major_nav_version, &minor_nav_version,
3168
&nav_day, &nav_month, &nav_year,
3169
&major_dsp_version, &minor_dsp_version,
3170
&dsp_day, &dsp_month, &dsp_year)) {
3171
parsed = BADLEN_PARSE;
3175
pbuf += sprintf(pbuf,
3176
"\nFW Versions: Nav Proc %2d.%02d %2d/%2d/%2d Sig Proc %2d.%02d %2d/%2d/%2d",
3177
major_nav_version, minor_nav_version, nav_day, nav_month, nav_year,
3178
major_dsp_version, minor_dsp_version, dsp_day, dsp_month, dsp_year);
3182
static void rpt_rcvr_health (TSIPPKT *rpt)
3188
"Doing position fixes",
3189
"Don't have GPS time yet",
3190
"Waiting for almanac collection",
3192
"No satellites available",
3193
"Only 1 satellite available",
3194
"Only 2 satellites available",
3195
"Only 3 satellites available",
3196
"No satellites usable ",
3197
"Only 1 satellite usable",
3198
"Only 2 satellites usable",
3199
"Only 3 satellites usable",
3200
"Chosen satellite unusable"};
3204
if (rpt_0x46 (rpt, &status1, &status2))
3206
parsed = BADLEN_PARSE;
3210
pbuf += sprintf(pbuf, "\nRcvr status1: %s (%02Xh); ",
3211
sc_text[rpt->buf[0]], status1);
3213
pbuf += sprintf(pbuf, "status2: %s, %s (%02Xh)",
3214
(status2 & 0x01)?"No BBRAM":"BBRAM OK",
3215
(status2 & 0x10)?"No Ant":"Ant OK",
3220
static void rpt_SNR_all_SVs (TSIPPKT *rpt)
3230
if (rpt_0x47 (rpt, &nsvs, sv_prn, snr))
3232
parsed = BADLEN_PARSE;
3236
pbuf += sprintf(pbuf, "\nSNR for satellites: %d", nsvs);
3237
for (isv = 0; isv < nsvs; isv++)
3239
pbuf += sprintf(pbuf, "\n SV %02d %6.2f",
3240
sv_prn[isv], snr[isv]);
3245
static void rpt_GPS_system_message (TSIPPKT *rpt)
3251
if (rpt_0x48 (rpt, message))
3253
parsed = BADLEN_PARSE;
3257
pbuf += sprintf(pbuf, "\nGPS message: %s", message);
3261
static void rpt_almanac_health_page (TSIPPKT *rpt)
3269
if (rpt_0x49 (rpt, sv_health))
3271
parsed = BADLEN_PARSE;
3275
pbuf += sprintf(pbuf, "\nAlmanac health page:");
3276
for (iprn = 0; iprn < 32; iprn++)
3278
if (!(iprn%5)) *pbuf++ = '\n';
3279
pbuf += sprintf(pbuf, " SV%02d %2X",
3280
(iprn+1) , sv_health[iprn]);
3285
static void rpt_single_lla_position (TSIPPKT *rpt) {
3290
alt, clock_bias, time_of_fix;
3291
double lat_min, lon_min;
3293
north_south, east_west;
3296
&lat, &lon, &alt, &clock_bias, &time_of_fix))
3298
parsed = BADLEN_PARSE;
3302
/* convert from radians to degrees */
3310
lat_deg = (short)lat;
3311
lat_min = (lat - lat_deg) * 60.0;
3320
lon_deg = (short)lon;
3321
lon_min = (lon - lon_deg) * 60.0;
3323
pbuf += sprintf(pbuf, "\nSLLA: %4d: %06.3f %c%5d:%06.3f %c%10.2f %12.2f%s",
3324
lat_deg, lat_min, north_south,
3325
lon_deg, lon_min, east_west,
3327
show_time(time_of_fix));
3331
static void rpt_ref_alt (TSIPPKT *rpt) {
3338
if (rpt_0x4A_2 (rpt,
3339
&alt, &dummy, &alt_flag))
3341
parsed = BADLEN_PARSE;
3345
pbuf += sprintf(pbuf, "\nReference Alt: %.1f m; %s",
3346
alt, alt_flag?"ON":"OFF");
3350
static void rpt_rcvr_id_and_status (TSIPPKT *rpt)
3354
machine_id, status3, status4;
3357
if (rpt_0x4B (rpt, &machine_id, &status3, &status4))
3359
parsed = BADLEN_PARSE;
3363
pbuf += sprintf(pbuf, "\nRcvr Machine ID: %d; Status3 = %s, %s (%02Xh)",
3365
(status3 & 0x02)?"No RTC":"RTC OK",
3366
(status3 & 0x08)?"No Alm":"Alm OK",
3371
static void rpt_operating_parameters (TSIPPKT *rpt)
3376
el_mask, snr_mask, dop_mask, dop_switch;
3379
if (rpt_0x4C (rpt, &dyn_code, &el_mask,
3380
&snr_mask, &dop_mask, &dop_switch))
3382
parsed = BADLEN_PARSE;
3386
pbuf += sprintf(pbuf, "\nOperating Parameters:");
3387
pbuf += sprintf(pbuf, "\n Dynamics code = %d %s",
3388
dyn_code, dyn_text[dyn_code]);
3389
pbuf += sprintf(pbuf, "\n Elevation mask = %.2f�", el_mask * R2D);
3390
pbuf += sprintf(pbuf, "\n SNR mask = %.2f", snr_mask);
3391
pbuf += sprintf(pbuf, "\n DOP mask = %.2f", dop_mask);
3392
pbuf += sprintf(pbuf, "\n DOP switch = %.2f", dop_switch);
3396
static void rpt_oscillator_offset (TSIPPKT *rpt)
3402
if (rpt_0x4D (rpt, &osc_offset))
3404
parsed = BADLEN_PARSE;
3408
pbuf += sprintf(pbuf, "\nOscillator offset: %.2f Hz = %.3f PPM",
3409
osc_offset, osc_offset/1575.42);
3413
static void rpt_GPS_time_set_response (TSIPPKT *rpt)
3420
if (rpt_0x4E (rpt, &response))
3422
parsed = BADLEN_PARSE;
3429
pbuf += sprintf(pbuf, "\nTime set accepted");
3433
pbuf += sprintf(pbuf, "\nTime set rejected or not required");
3437
parsed = BADDATA_PARSE;
3442
static void rpt_UTC_offset (TSIPPKT *rpt)
3449
dt_ls, wn_t, wn_lsf, dn, dt_lsf;
3452
if (rpt_0x4F (rpt, &a0, &a1, &time_of_data,
3453
&dt_ls, &wn_t, &wn_lsf, &dn, &dt_lsf)) {
3454
parsed = BADLEN_PARSE;
3458
pbuf += sprintf(pbuf, "\nUTC Correction Data");
3459
pbuf += sprintf(pbuf, "\n A_0 = %g ", a0);
3460
pbuf += sprintf(pbuf, "\n A_1 = %g ", a1);
3461
pbuf += sprintf(pbuf, "\n delta_t_LS = %d ", dt_ls);
3462
pbuf += sprintf(pbuf, "\n t_ot = %.0f ", time_of_data);
3463
pbuf += sprintf(pbuf, "\n WN_t = %d ", wn_t );
3464
pbuf += sprintf(pbuf, "\n WN_LSF = %d ", wn_lsf );
3465
pbuf += sprintf(pbuf, "\n DN = %d ", dn );
3466
pbuf += sprintf(pbuf, "\n delta_t_LSF = %d ", dt_lsf );
3471
static void rpt_1SV_bias (TSIPPKT *rpt)
3474
clock_bias, freq_offset, time_of_fix;
3477
if (rpt_0x54 (rpt, &clock_bias, &freq_offset, &time_of_fix)) {
3478
parsed = BADLEN_PARSE;
3482
pbuf += sprintf (pbuf, "\nTime Fix Clock Bias: %6.2f m Freq Bias: %6.2f m/s%s",
3483
clock_bias, freq_offset, show_time (time_of_fix));
3487
static void rpt_io_opt (TSIPPKT *rpt)
3490
pos_code, vel_code, time_code, aux_code;
3494
&pos_code, &vel_code, &time_code, &aux_code)) {
3495
parsed = BADLEN_PARSE;
3498
/* rptbuf unloaded */
3500
pbuf += sprintf(pbuf, "\nI/O Options: %2X %2X %2X %2X",
3501
pos_code, vel_code, time_code, aux_code);
3503
if (pos_code & 0x01) {
3504
pbuf += sprintf(pbuf, "\n ECEF XYZ position output");
3507
if (pos_code & 0x02) {
3508
pbuf += sprintf(pbuf, "\n LLA position output");
3511
pbuf += sprintf(pbuf, (pos_code & 0x04)?
3512
"\n MSL altitude output (Geoid height) ":
3513
"\n WGS-84 altitude output");
3515
pbuf += sprintf(pbuf, (pos_code & 0x08)?
3516
"\n MSL altitude input":
3517
"\n WGS-84 altitude input");
3519
pbuf += sprintf(pbuf, (pos_code & 0x10)?
3520
"\n Double precision":
3521
"\n Single precision");
3523
if (pos_code & 0x20) {
3524
pbuf += sprintf(pbuf, "\n All Enabled Superpackets");
3527
if (vel_code & 0x01) {
3528
pbuf += sprintf(pbuf, "\n ECEF XYZ velocity output");
3531
if (vel_code & 0x02) {
3532
pbuf += sprintf(pbuf, "\n ENU velocity output");
3535
pbuf += sprintf(pbuf, (time_code & 0x01)?
3536
"\n Time tags in UTC":
3537
"\n Time tags in GPS time");
3539
if (time_code & 0x02) {
3540
pbuf += sprintf(pbuf, "\n Fixes delayed to integer seconds");
3543
if (time_code & 0x04) {
3544
pbuf += sprintf(pbuf, "\n Fixes sent only on request");
3547
if (time_code & 0x08) {
3548
pbuf += sprintf(pbuf, "\n Synchronized measurements");
3551
if (time_code & 0x10) {
3552
pbuf += sprintf(pbuf, "\n Minimize measurement propagation");
3555
pbuf += sprintf(pbuf, (time_code & 0x20) ?
3556
"\n PPS output at all times" :
3557
"\n PPS output during fixes");
3559
if (aux_code & 0x01) {
3560
pbuf += sprintf(pbuf, "\n Raw measurement output");
3563
if (aux_code & 0x02) {
3564
pbuf += sprintf(pbuf, "\n Code-phase smoothed before output");
3567
if (aux_code & 0x04) {
3568
pbuf += sprintf(pbuf, "\n Additional fix status");
3571
pbuf += sprintf(pbuf, (aux_code & 0x08)?
3572
"\n Signal Strength Output as dBHz" :
3573
"\n Signal Strength Output as AMU");
3577
static void rpt_ENU_velocity (TSIPPKT *rpt)
3580
vel_ENU[3], freq_offset, time_of_fix;
3583
if (rpt_0x56 (rpt, vel_ENU, &freq_offset, &time_of_fix)) {
3584
parsed = BADLEN_PARSE;
3588
pbuf += sprintf(pbuf, "\nVel ENU: %11.3f %11.3f %11.3f %12.3f%s",
3589
vel_ENU[0], vel_ENU[1], vel_ENU[2], freq_offset,
3590
show_time (time_of_fix));
3594
static void rpt_last_fix_info (TSIPPKT *rpt)
3597
source_code, diag_code;
3604
if (rpt_0x57 (rpt, &source_code, &diag_code, &week_num, &time_of_fix)) {
3605
parsed = BADLEN_PARSE;
3609
pbuf += sprintf(pbuf, "\n source code %d; diag code: %2Xh",
3610
source_code, diag_code);
3611
pbuf += sprintf(pbuf, "\n Time of last fix:%s", show_time(time_of_fix));
3612
pbuf += sprintf(pbuf, "\n Week of last fix: %d", week_num);
3616
static void rpt_GPS_system_data (TSIPPKT *rpt)
3620
op_code, data_type, sv_prn,
3621
data_length, data_packet[250];
3642
{"", "", "Almanac Orbit",
3643
"Health Page & Ref Time", "Ionosphere", "UTC ",
3647
if (rpt_0x58 (rpt, &op_code, &data_type, &sv_prn,
3648
&data_length, data_packet))
3650
parsed = BADLEN_PARSE;
3654
pbuf += sprintf(pbuf, "\nSystem data [%d]: %s SV%02d",
3655
data_type, datname[data_type], sv_prn);
3659
pbuf += sprintf(pbuf, " Acknowledgment");
3662
pbuf += sprintf(pbuf, " length = %d bytes", data_length);
3663
switch (data_type) {
3666
if (sv_prn == 0 || sv_prn > 32) {
3667
pbuf += sprintf(pbuf, " Binary PRN invalid");
3670
almanac = (ALM_INFO*)data_packet;
3671
pbuf += sprintf(pbuf, "\n t_oa_raw = % -12d SV_hlth = % -12d ",
3672
almanac->t_oa_raw , almanac->SV_health );
3673
pbuf += sprintf(pbuf, "\n e = % -12g t_oa = % -12g ",
3674
almanac->e , almanac->t_oa );
3675
pbuf += sprintf(pbuf, "\n i_0 = % -12g OMEGADOT = % -12g ",
3676
almanac->i_0 , almanac->OMEGADOT );
3677
pbuf += sprintf(pbuf, "\n sqrt_A = % -12g OMEGA_0 = % -12g ",
3678
almanac->sqrt_A , almanac->OMEGA_0 );
3679
pbuf += sprintf(pbuf, "\n omega = % -12g M_0 = % -12g ",
3680
almanac->omega , almanac->M_0 );
3681
pbuf += sprintf(pbuf, "\n a_f0 = % -12g a_f1 = % -12g ",
3682
almanac->a_f0 , almanac->a_f1 );
3683
pbuf += sprintf(pbuf, "\n Axis = % -12g n = % -12g ",
3684
almanac->Axis , almanac->n );
3685
pbuf += sprintf(pbuf, "\n OMEGA_n = % -12g ODOT_n = % -12g ",
3686
almanac->OMEGA_n , almanac->ODOT_n );
3687
pbuf += sprintf(pbuf, "\n t_zc = % -12g weeknum = % -12d ",
3688
almanac->t_zc , almanac->weeknum );
3689
pbuf += sprintf(pbuf, "\n wn_oa = % -12d", almanac->wn_oa );
3693
/* Almanac health page */
3694
almh = (ALH_PARMS*)data_packet;
3695
pbuf += sprintf(pbuf, "\n t_oa = %d, wn_oa&0xFF = %d ",
3696
almh->t_oa, almh->WN_a);
3697
pbuf += sprintf(pbuf, "\nAlmanac health page:");
3698
for (iprn = 0; iprn < 32; iprn++) {
3699
if (!(iprn%5)) *pbuf++ = '\n';
3700
pbuf += sprintf(pbuf, " SV%02d %2X",
3701
(iprn+1) , almh->SV_health[iprn]);
3703
curr_t_oa = data_packet[34];
3704
curr_wn_oa = (unsigned short)((data_packet[35]<<8) + data_packet[36]);
3705
pbuf += sprintf(pbuf, "\n current t_oa = %d, wn_oa = %d ",
3706
curr_t_oa, curr_wn_oa);
3711
ionosphere = (ION_INFO*)data_packet;
3712
pbuf += sprintf(pbuf, "\n alpha_0 = % -12g alpha_1 = % -12g ",
3713
ionosphere->alpha_0, ionosphere->alpha_1);
3714
pbuf += sprintf(pbuf, "\n alpha_2 = % -12g alpha_3 = % -12g ",
3715
ionosphere->alpha_2, ionosphere->alpha_3);
3716
pbuf += sprintf(pbuf, "\n beta_0 = % -12g beta_1 = % -12g ",
3717
ionosphere->beta_0, ionosphere->beta_1);
3718
pbuf += sprintf(pbuf, "\n beta_2 = % -12g beta_3 = % -12g ",
3719
ionosphere->beta_2, ionosphere->beta_3);
3724
utc = (UTC_INFO*)data_packet;
3725
pbuf += sprintf(pbuf, "\n A_0 = %g ", utc->A_0);
3726
pbuf += sprintf(pbuf, "\n A_1 = %g ", utc->A_1);
3727
pbuf += sprintf(pbuf, "\n delta_t_LS = %d ", utc->delta_t_LS);
3728
pbuf += sprintf(pbuf, "\n t_ot = %.0f ", utc->t_ot );
3729
pbuf += sprintf(pbuf, "\n WN_t = %d ", utc->WN_t );
3730
pbuf += sprintf(pbuf, "\n WN_LSF = %d ", utc->WN_LSF );
3731
pbuf += sprintf(pbuf, "\n DN = %d ", utc->DN );
3732
pbuf += sprintf(pbuf, "\n delta_t_LSF = %d ", utc->delta_t_LSF );
3735
case 6: /* Ephemeris */
3736
if (sv_prn == 0 || sv_prn > 32) {
3737
pbuf += sprintf(pbuf, " Binary PRN invalid");
3740
nav_data = (NAV_INFO*)data_packet;
3742
pbuf += sprintf(pbuf, "\n SV_PRN = % -12d . t_ephem = % -12g . ",
3743
nav_data->sv_number , nav_data->t_ephem );
3744
cdata = &(nav_data->ephclk);
3745
pbuf += sprintf(pbuf,
3746
"\n weeknum = % -12d . codeL2 = % -12d . L2Pdata = % -12d",
3747
cdata->weeknum , cdata->codeL2 , cdata->L2Pdata );
3748
pbuf += sprintf(pbuf,
3749
"\n SVacc_raw = % -12d .SV_health = % -12d . IODC = % -12d",
3750
cdata->SVacc_raw, cdata->SV_health, cdata->IODC );
3751
pbuf += sprintf(pbuf,
3752
"\n T_GD = % -12g . t_oc = % -12g . a_f2 = % -12g",
3753
cdata->T_GD, cdata->t_oc, cdata->a_f2 );
3754
pbuf += sprintf(pbuf,
3755
"\n a_f1 = % -12g . a_f0 = % -12g . SVacc = % -12g",
3756
cdata->a_f1, cdata->a_f0, cdata->SVacc );
3757
edata = &(nav_data->ephorb);
3758
pbuf += sprintf(pbuf,
3759
"\n IODE = % -12d .fit_intvl = % -12d . C_rs = % -12g",
3760
edata->IODE, edata->fit_interval, edata->C_rs );
3761
pbuf += sprintf(pbuf,
3762
"\n delta_n = % -12g . M_0 = % -12g . C_uc = % -12g",
3763
edata->delta_n, edata->M_0, edata->C_uc );
3764
pbuf += sprintf(pbuf,
3765
"\n ecc = % -12g . C_us = % -12g . sqrt_A = % -12g",
3766
edata->e, edata->C_us, edata->sqrt_A );
3767
pbuf += sprintf(pbuf,
3768
"\n t_oe = % -12g . C_ic = % -12g . OMEGA_0 = % -12g",
3769
edata->t_oe, edata->C_ic, edata->OMEGA_0 );
3770
pbuf += sprintf(pbuf,
3771
"\n C_is = % -12g . i_0 = % -12g . C_rc = % -12g",
3772
edata->C_is, edata->i_0, edata->C_rc );
3773
pbuf += sprintf(pbuf,
3774
"\n omega = % -12g . OMEGADOT = % -12g . IDOT = % -12g",
3775
edata->omega, edata->OMEGADOT, edata->IDOT );
3776
pbuf += sprintf(pbuf,
3777
"\n Axis = % -12g . n = % -12g . r1me2 = % -12g",
3778
edata->Axis, edata->n, edata->r1me2 );
3779
pbuf += sprintf(pbuf,
3780
"\n OMEGA_n = % -12g . ODOT_n = % -12g",
3781
edata->OMEGA_n, edata->ODOT_n );
3789
static void rpt_SVs_enabled (TSIPPKT *rpt)
3799
if (rpt_0x59 (rpt, &code_type, status_code))
3801
parsed = BADLEN_PARSE;
3806
case 3: pbuf += sprintf(pbuf, "\nSVs Disabled:\n"); break;
3807
case 6: pbuf += sprintf(pbuf, "\nSVs with Health Ignored:\n"); break;
3811
for (iprn=0; iprn<32; iprn++)
3813
if (status_code[iprn])
3815
pbuf += sprintf(pbuf, " %02d", iprn+1);
3819
if (numsvs == 0) pbuf += sprintf(pbuf, "None");
3824
static void rpt_raw_msmt (TSIPPKT *rpt)
3829
sample_length, signal_level, code_phase, Doppler;
3834
if (rpt_0x5A (rpt, &sv_prn, &sample_length, &signal_level,
3835
&code_phase, &Doppler, &time_of_fix))
3837
parsed = BADLEN_PARSE;
3841
pbuf += sprintf(pbuf, "\n %02d %5.0f %7.1f %10.2f %10.2f %12.3f %s",
3842
sv_prn, sample_length, signal_level, code_phase, Doppler, time_of_fix,
3843
show_time ((float)time_of_fix));
3847
static void rpt_SV_ephemeris_status (TSIPPKT *rpt)
3850
sv_prn, sv_health, sv_iode, fit_interval_flag;
3852
time_of_collection, time_of_eph, sv_accy;
3855
if (rpt_0x5B (rpt, &sv_prn, &sv_health, &sv_iode, &fit_interval_flag,
3856
&time_of_collection, &time_of_eph, &sv_accy))
3858
parsed = BADLEN_PARSE;
3862
pbuf += sprintf(pbuf, "\n SV%02d %s %2Xh %2Xh ",
3863
sv_prn, show_time (time_of_collection), sv_health, sv_iode);
3864
/* note: cannot use show_time twice in same call */
3865
pbuf += sprintf(pbuf, "%s %1d %4.1f",
3866
show_time (time_of_eph), fit_interval_flag, sv_accy);
3870
static void rpt_SV_tracking_status (TSIPPKT *rpt)
3873
sv_prn, chan, slot, acq_flag, eph_flag,
3874
old_msmt_flag, integer_msec_flag, bad_data_flag,
3877
signal_level, time_of_last_msmt,
3882
&sv_prn, &slot, &chan, &acq_flag, &eph_flag,
3883
&signal_level, &time_of_last_msmt, &elev, &azim,
3884
&old_msmt_flag, &integer_msec_flag, &bad_data_flag,
3885
&data_collect_flag))
3887
parsed = BADLEN_PARSE;
3891
pbuf += sprintf(pbuf,
3892
"\n SV%2d %1d %1d %1d %4.1f %s %5.1f %5.1f",
3894
acq_flag, eph_flag, signal_level,
3895
show_time(time_of_last_msmt),
3896
elev*R2D, azim*R2D);
3901
static void rpt_allSV_selection (TSIPPKT *rpt)
3904
manual_mode, nsvs, sv_prn[8], ndim;
3908
pdop, hdop, vdop, tdop;
3912
&manual_mode, &nsvs, &ndim, sv_prn,
3913
&pdop, &hdop, &vdop, &tdop))
3915
parsed = BADLEN_PARSE;
3922
pbuf += sprintf(pbuf, "\nMode: Searching, %d-SV:", nsvs);
3925
pbuf += sprintf(pbuf, "\nMode: One-SV Timing:");
3928
pbuf += sprintf(pbuf, "\nMode: %c-%dD, %d-SV:",
3929
manual_mode ? 'M' : 'A', ndim - 1, nsvs);
3932
pbuf += sprintf(pbuf, "\nMode: Timing, %d-SV:", nsvs);
3935
pbuf += sprintf(pbuf, "\nMode: Unknown = %d:", ndim);
3939
for (islot = 0; islot < nsvs; islot++)
3941
if (sv_prn[islot]) pbuf += sprintf(pbuf, " %02d", sv_prn[islot]);
3943
if (ndim == 3 || ndim == 4)
3945
pbuf += sprintf(pbuf, "; DOPs: P %.1f H %.1f V %.1f T %.1f",
3946
pdop, hdop, vdop, tdop);
3952
static void rpt_DGPS_position_mode (TSIPPKT *rpt)
3958
if (rpt_0x82 (rpt, &diff_mode)) {
3959
parsed = BADLEN_PARSE;
3963
pbuf += sprintf(pbuf, "\nFix is%s DGPS-corrected (%s mode) (%d)",
3964
(diff_mode&1) ? "" : " not",
3965
(diff_mode&2) ? "auto" : "manual",
3970
static void rpt_double_ECEF_position (TSIPPKT *rpt)
3974
ECEF_pos[3], clock_bias;
3979
if (rpt_0x83 (rpt, ECEF_pos, &clock_bias, &time_of_fix))
3981
parsed = BADLEN_PARSE;
3985
pbuf += sprintf(pbuf, "\nDXYZ:%12.2f %13.2f %13.2f %12.2f%s",
3986
ECEF_pos[0], ECEF_pos[1], ECEF_pos[2], clock_bias,
3987
show_time(time_of_fix));
3991
static void rpt_double_lla_position (TSIPPKT *rpt)
3996
lat, lon, lat_min, lon_min,
4001
north_south, east_west;
4005
&lat, &lon, &alt, &clock_bias, &time_of_fix))
4007
parsed = BADLEN_PARSE;
4019
lat_deg = (short)lat;
4020
lat_min = (lat - lat_deg) * 60.0;
4028
lon_deg = (short)lon;
4029
lon_min = (lon - lon_deg) * 60.0;
4030
pbuf += sprintf(pbuf, "\nDLLA: %2d:%08.5f %c; %3d:%08.5f %c; %10.2f %12.2f%s",
4031
lat_deg, lat_min, north_south,
4032
lon_deg, lon_min, east_west,
4034
show_time(time_of_fix));
4038
static void rpt_complete_rcvr_config (TSIPPKT *rpt)
4040
TSIP_RCVR_CFG TsipxBB ;
4042
if (rpt_Paly0xBB (rpt, &TsipxBB))
4044
parsed = BADLEN_PARSE;
4048
pbuf += sprintf(pbuf, "\n operating mode: %s",
4049
NavModeText0xBB[TsipxBB.operating_mode]);
4050
pbuf += sprintf(pbuf, "\n dynamics: %s",
4051
dyn_text[TsipxBB.dyn_code]);
4052
pbuf += sprintf(pbuf, "\n elev angle mask: %g deg",
4053
TsipxBB.elev_mask * R2D);
4054
pbuf += sprintf(pbuf, "\n SNR mask: %g AMU",
4056
pbuf += sprintf(pbuf, "\n DOP mask: %g",
4058
pbuf += sprintf(pbuf, "\n DOP switch: %g",
4059
TsipxBB.dop_switch);
4064
static void rpt_rcvr_serial_port_config (TSIPPKT *rpt)
4067
port_num, in_baud, out_baud, data_bits, parity, stop_bits, flow_control,
4068
protocols_in, protocols_out, reserved;
4069
unsigned char known;
4072
if (rpt_0xBC (rpt, &port_num, &in_baud, &out_baud, &data_bits, &parity,
4073
&stop_bits, &flow_control, &protocols_in, &protocols_out, &reserved)) {
4074
parsed = BADLEN_PARSE;
4077
/* rptbuf unloaded */
4079
pbuf += sprintf(pbuf, "\n RECEIVER serial port %s config:",
4080
rcvr_port_text[port_num]);
4082
pbuf += sprintf(pbuf, "\n I/O Baud %s/%s, %d - %s - %d",
4083
st_baud_text_app[in_baud],
4084
st_baud_text_app[out_baud],
4086
parity_text[parity],
4088
pbuf += sprintf(pbuf, "\n Input protocols: ");
4090
if (protocols_in&B_TSIP)
4092
pbuf += sprintf(pbuf, "%s ", protocols_in_text[1]);
4095
if (known == FALSE) pbuf += sprintf(pbuf, "No known");
4097
pbuf += sprintf(pbuf, "\n Output protocols: ");
4099
if (protocols_out&B_TSIP)
4101
pbuf += sprintf(pbuf, "%s ", protocols_out_text[1]);
4104
if (protocols_out&B_NMEA)
4106
pbuf += sprintf(pbuf, "%s ", protocols_out_text[2]);
4109
if (known == FALSE) pbuf += sprintf(pbuf, "No known");
4110
reserved = reserved;
4116
static void rpt_8F0B(TSIPPKT *rpt)
4121
"full position (3-D)",
4122
"single satellite (0-D)",
4126
"overdetermined clock"};
4177
parsed = BADLEN_PARSE;
4183
pbuf += sprintf(pbuf, "\nNew partial+full meas");
4187
pbuf += sprintf(pbuf, "\nEvent count: %5d", event);
4190
pbuf += sprintf(pbuf, "\nGPS time : %s %2d/%2d/%2d (DMY)",
4191
show_time(tow), date, month, year);
4192
pbuf += sprintf(pbuf, "\nMode : %s", oprtng_dim[dim_mode]);
4193
pbuf += sprintf(pbuf, "\nUTC offset: %2d", utc_offset);
4194
pbuf += sprintf(pbuf, "\nClock Bias: %6.2f m", bias);
4195
pbuf += sprintf(pbuf, "\nFreq bias : %6.2f m/s", drift);
4196
pbuf += sprintf(pbuf, "\nBias unc : %6.2f m", bias_unc);
4197
pbuf += sprintf(pbuf, "\nFreq unc : %6.2f m/s", dr_unc);
4199
lat *= R2D; /* convert from radians to degrees */
4211
lat_deg = (short)lat;
4212
lat_min = (lat - lat_deg) * 60.0;
4223
lon_deg = (short)lon;
4224
lon_min = (lon - lon_deg) * 60.0;
4225
pbuf += sprintf(pbuf, "\nPosition :");
4226
pbuf += sprintf(pbuf, " %4d %6.3f %c", lat_deg, lat_min, north_south);
4227
pbuf += sprintf(pbuf, " %5d %6.3f %c", lon_deg, lon_min, east_west);
4228
pbuf += sprintf(pbuf, " %10.2f", alt);
4230
numfix = numnotfix = 0;
4231
for (local_index=0; local_index<8; local_index++)
4233
if (sv_id[local_index] < 0) numnotfix++;
4234
if (sv_id[local_index] > 0) numfix++;
4238
pbuf += sprintf(pbuf, "\nSVs used in fix : ");
4239
for (local_index=0; local_index<8; local_index++)
4241
if (sv_id[local_index] > 0)
4243
pbuf += sprintf(pbuf, "%2d ", sv_id[local_index]);
4249
pbuf += sprintf(pbuf, "\nOther SVs tracked: ");
4250
for (local_index=0; local_index<8; local_index++)
4252
if (sv_id[local_index] < 0)
4254
pbuf += sprintf(pbuf, "%2d ", sv_id[local_index]);
4261
static void rpt_8F14 (TSIPPKT *rpt)
4262
/* Datum parameters */
4270
if (rpt_0x8F14 (rpt, &datum_idx, datum_coeffs))
4272
parsed = BADLEN_PARSE;
4276
if (datum_idx == -1)
4278
pbuf += sprintf(pbuf, "\nUser-Entered Datum:");
4279
pbuf += sprintf(pbuf, "\n dx = %6.1f", datum_coeffs[0]);
4280
pbuf += sprintf(pbuf, "\n dy = %6.1f", datum_coeffs[1]);
4281
pbuf += sprintf(pbuf, "\n dz = %6.1f", datum_coeffs[2]);
4282
pbuf += sprintf(pbuf, "\n a-axis = %10.3f", datum_coeffs[3]);
4283
pbuf += sprintf(pbuf, "\n e-squared = %16.14f", datum_coeffs[4]);
4285
else if (datum_idx == 0)
4287
pbuf += sprintf(pbuf, "\nWGS-84 datum, Index 0 ");
4291
pbuf += sprintf(pbuf, "\nStandard Datum, Index %3d ", datum_idx);
4296
static void rpt_8F15 (TSIPPKT *rpt)
4297
/* Datum parameters */
4305
if (rpt_0x8F15 (rpt, &datum_idx, datum_coeffs)) {
4306
parsed = BADLEN_PARSE;
4310
if (datum_idx == -1)
4312
pbuf += sprintf(pbuf, "\nUser-Entered Datum:");
4313
pbuf += sprintf(pbuf, "\n dx = %6.1f", datum_coeffs[0]);
4314
pbuf += sprintf(pbuf, "\n dy = %6.1f", datum_coeffs[1]);
4315
pbuf += sprintf(pbuf, "\n dz = %6.1f", datum_coeffs[2]);
4316
pbuf += sprintf(pbuf, "\n a-axis = %10.3f", datum_coeffs[3]);
4317
pbuf += sprintf(pbuf, "\n e-squared = %16.14f", datum_coeffs[4]);
4319
else if (datum_idx == 0)
4321
pbuf += sprintf(pbuf, "\nWGS-84 datum, Index 0 ");
4325
pbuf += sprintf(pbuf, "\nStandard Datum, Index %3d ", datum_idx);
4330
#define INFO_DGPS 0x02
4331
#define INFO_2D 0x04
4332
#define INFO_ALTSET 0x08
4333
#define INFO_FILTERED 0x10
4334
static void rpt_8F20 (TSIPPKT *rpt)
4337
info, nsvs, sv_prn[32];
4339
week_num, datum_index, sv_IODC[32];
4341
lat, lon, alt, time_of_fix;
4343
londeg, latdeg, vel[3];
4350
if (rpt_0x8F20 (rpt,
4351
&info, &lat, &lon, &alt, vel,
4353
&week_num, &nsvs, sv_prn, sv_IODC, &datum_index))
4355
parsed = BADLEN_PARSE;
4358
pbuf += sprintf(pbuf,
4359
"\nFix at: %04d:%3s:%02d:%02d:%06.3f GPS (=UTC+%2ds) FixType: %s%s%s",
4361
dayname[(short)(time_of_fix/86400.0)],
4362
(short)fmod(time_of_fix/3600., 24.),
4363
(short)fmod(time_of_fix/60., 60.),
4364
fmod(time_of_fix, 60.),
4365
(char)rpt->buf[29], /* UTC offset */
4366
(info & INFO_DGPS)?"Diff":"",
4367
(info & INFO_2D)?"2D":"3D",
4368
(info & INFO_FILTERED)?"-Filtrd":"");
4370
if (datum_index > 0)
4372
sprintf(datum_string, "Datum%3d", datum_index);
4374
else if (datum_index)
4376
sprintf(datum_string, "Unknown ");
4380
sprintf(datum_string, "WGS-84");
4383
/* convert from radians to degrees */
4384
latdeg = R2D * fabs(lat);
4385
londeg = R2D * fabs(lon);
4386
pbuf += sprintf(pbuf,
4387
"\n Pos: %4d:%09.6f %c %5d:%09.6f %c %10.2f m HAE (%s)",
4388
(short)latdeg, fmod (latdeg, 1.)*60.0,
4390
(short)londeg, fmod (londeg, 1.)*60.0,
4394
pbuf += sprintf(pbuf,
4395
"\n Vel: %9.3f E %9.3f N %9.3f U (m/sec)",
4396
vel[0], vel[1], vel[2]);
4398
pbuf += sprintf(pbuf,
4400
for (isv = 0; isv < nsvs; isv++) {
4401
pbuf += sprintf(pbuf, " %02d", sv_prn[isv]);
4403
pbuf += sprintf(pbuf, " (IODEs:");
4404
for (isv = 0; isv < nsvs; isv++) {
4405
pbuf += sprintf(pbuf, " %02X", sv_IODC[isv]&0xFF);
4407
pbuf += sprintf(pbuf, ")");
4411
static void rpt_8F41(TSIPPKT *rpt)
4427
if (!rpt_0x8F41(rpt,
4438
parsed = BADLEN_PARSE;
4442
pbuf += sprintf(pbuf, "\n search range: %d",
4444
pbuf += sprintf(pbuf, "\n board options: %d",
4446
pbuf += sprintf(pbuf, "\n board serial #: %ld",
4448
pbuf += sprintf(pbuf, "\n build date/hour: %02d/%02d/%02d %02d:00",
4449
bBuildDay, bBuildMonth, bBuildYear, bBuildHour);
4450
pbuf += sprintf(pbuf, "\n osc offset: %.3f PPM (%.0f Hz)",
4451
fOscOffset/1575.42, fOscOffset);
4452
pbuf += sprintf(pbuf, "\n test code: %d",
4457
static void rpt_8F42(TSIPPKT *rpt)
4463
iCaseSerialNumberPre,
4471
if (!rpt_0x8F42(rpt,
4474
&iCaseSerialNumberPre,
4475
&iiCaseSerialNumber,
4481
parsed = BADLEN_PARSE;
4485
pbuf += sprintf(pbuf, "\nProduct ID 8F42");
4486
pbuf += sprintf(pbuf, "\n extension: %d", bProdNumberExt);
4487
pbuf += sprintf(pbuf, "\n case serial # prefix: %d", iCaseSerialNumberPre);
4488
pbuf += sprintf(pbuf, "\n case serial #: %ld", iiCaseSerialNumber);
4489
pbuf += sprintf(pbuf, "\n prod. #: %ld", iiProdNumber);
4490
pbuf += sprintf(pbuf, "\n premium options: %Xh", iPremiumOptions);
4491
pbuf += sprintf(pbuf, "\n machine ID: %d", iMachineID);
4492
pbuf += sprintf(pbuf, "\n key: %Xh", iKey);
4496
static void rpt_8F45(TSIPPKT *rpt)
4498
unsigned char bSegMask;
4500
if (!rpt_0x8F45(rpt,
4503
parsed = BADLEN_PARSE;
4506
pbuf += sprintf(pbuf, "\nCleared Segment Mask: %Xh", bSegMask);
4509
static void rpt_8F4A(TSIPPKT *rpt)
4510
/* Stinger PPS def */
4521
if (rpt_0x8F4A_16 (rpt,
4526
&bias_unc_threshold))
4528
parsed = BADLEN_PARSE;
4532
pbuf += sprintf(pbuf, "\nPPS is %s", pps_enabled?"enabled":"disabled");
4533
pbuf += sprintf(pbuf, "\n timebase: %s", PPSTimeBaseText[pps_timebase]);
4534
pbuf += sprintf(pbuf, "\n polarity: %s", PPSPolarityText[pps_polarity]);
4535
pbuf += sprintf(pbuf, "\n offset: %.1f ns, ", pps_offset*1.e9);
4536
pbuf += sprintf(pbuf, "\n biasunc: %.1f ns", bias_unc_threshold/GPS_C*1.e9);
4539
static void rpt_8F4B(TSIPPKT *rpt)
4540
/* fast-SA decorrolation time for self-survey */
4545
if (rpt_0x8F4B(rpt, &decorr_max))
4547
parsed = BADLEN_PARSE;
4551
pbuf += sprintf(pbuf,
4552
"\nMax # of position fixes for self-survey : %ld",
4556
static void rpt_8F4D(TSIPPKT *rpt)
4562
static unsigned long
4564
0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020,
4565
0x00000100L, 0x00000800L, 0x00001000L,
4566
0x40000000L, 0x80000000L};
4571
if (rpt_0x8F4D(rpt, &OutputMask))
4573
parsed = BADLEN_PARSE;
4577
pbuf += sprintf(pbuf, "\nAuto-Report Mask: %02X %02X %02X %02X",
4578
(unsigned char)(OutputMask>>24),
4579
(unsigned char)(OutputMask>>16),
4580
(unsigned char)(OutputMask>>8),
4581
(unsigned char)OutputMask);
4583
numchoices = sizeof(MaskText)/sizeof(char*);
4584
pbuf += sprintf(pbuf, "\nAuto-Reports scheduled for Output:");
4586
for (ichoice=0; ichoice<numchoices; ichoice++)
4588
if (OutputMask&MaskBit[ichoice])
4590
pbuf += sprintf(pbuf, "%s %s",
4591
(pbuf==linestart)?"\n ":",",
4593
if (pbuf-linestart > 60) linestart = pbuf;
4597
pbuf += sprintf(pbuf, "\nAuto-Reports NOT scheduled for Output:");
4599
for (ichoice=0; ichoice<numchoices; ichoice++)
4601
if (OutputMask&MaskBit[ichoice]) continue;
4602
pbuf += sprintf(pbuf, "%s %s",
4603
(pbuf==linestart)?"\n ":",",
4605
if (pbuf-linestart > 60) linestart = pbuf;
4609
static void rpt_8FA5(TSIPPKT *rpt)
4614
if (rpt_0x8FA5(rpt, spktmask))
4616
parsed = BADLEN_PARSE;
4620
pbuf += sprintf(pbuf, "\nSuperpacket auto-output mask: %02X %02X %02X %02X",
4621
spktmask[0], spktmask[1], spktmask[2], spktmask[3]);
4623
if (spktmask[0]&0x01) pbuf+= sprintf (pbuf, "\n PPS 8F-0B");
4624
if (spktmask[0]&0x02) pbuf+= sprintf (pbuf, "\n Event 8F-0B");
4625
if (spktmask[0]&0x10) pbuf+= sprintf (pbuf, "\n PPS 8F-AD");
4626
if (spktmask[0]&0x20) pbuf+= sprintf (pbuf, "\n Event 8F-AD");
4627
if (spktmask[2]&0x01) pbuf+= sprintf (pbuf, "\n ppos Fix 8F-20");
4630
static void rpt_8FAD (TSIPPKT *rpt)
4645
static char* Status8FADText[] = {
4650
"CODE_NEED_INITIALIZATION",
4657
"CODE_NO_INTEGRITY",
4661
*LeapStatusText[] = {
4662
" UTC Avail", " ", " ", " ",
4663
" Scheduled", " Pending", " Warning", " In Progress"};
4666
if (rpt_0x8FAD (rpt,
4678
parsed = BADLEN_PARSE;
4682
pbuf += sprintf(pbuf, "\n8FAD Count: %d Status: %s",
4683
Count, Status8FADText[Status]);
4685
pbuf += sprintf(pbuf, "\n Leap Flags:");
4690
if (Flags&(1<<i)) pbuf += sprintf(pbuf, LeapStatusText[i]);
4695
pbuf += sprintf(pbuf, " UTC info not available");
4698
pbuf += sprintf(pbuf, "\n %02d/%02d/%04d (DMY) %02d:%02d:%02d.%09ld UTC",
4699
Day, Month, Year, Hour, Minute, Second, (long)(FracSec*1.e9));
4703
int print_msg_table_header (int rptcode, char *HdrStr, int force)
4705
/* force header is to help auto-output function */
4706
/* last_rptcode is to determine whether to print a header */
4707
/* for the first occurrence of a series of reports */
4714
if (force || rptcode!=last_rptcode)
4716
/* supply a header in console output */
4720
numchars = sprintf(HdrStr, "\nRaw Measurement Data");
4721
numchars += sprintf(HdrStr+numchars,
4722
"\n SV Sample SNR Code Phase Doppler Seconds Time of Meas");
4726
numchars = sprintf(HdrStr, "\nEphemeris Status");
4727
numchars += sprintf(HdrStr+numchars,
4728
"\n SV Time collected Health IODE t oe Fit URA");
4732
numchars = sprintf(HdrStr, "\nTracking Info");
4733
numchars += sprintf(HdrStr+numchars,
4734
"\n SV C Acq Eph SNR Time of Meas Elev Azim ");
4739
last_rptcode = rptcode;
4740
return (short)numchars;
4743
static void unknown_rpt (TSIPPKT *rpt)
4747
/* app-specific rpt packets */
4748
if (parsed == BADLEN_PARSE)
4750
pbuf += sprintf(pbuf, "\nTSIP report packet ID %2Xh, length %d: Bad length",
4751
rpt->code, rpt->len);
4753
if (parsed == BADID_PARSE)
4755
pbuf += sprintf(pbuf,
4756
"\nTSIP report packet ID %2Xh, length %d: translation not supported",
4757
rpt->code, rpt->len);
4760
if (parsed == BADDATA_PARSE)
4762
pbuf += sprintf(pbuf,
4763
"\nTSIP report packet ID %2Xh, length %d: data content incorrect",
4764
rpt->code, rpt->len);
4767
for (i = 0; i < rpt->len; i++) {
4768
if ((i % 20) == 0) *pbuf++ = '\n';
4769
pbuf += sprintf(pbuf, " %02X", rpt->buf[i]);
4774
** main subroutine, called from ProcessInputBytesWhileWaitingForKBHit()
4776
void TranslateTSIPReportToText (TSIPPKT *rpt, char *TextOutputBuffer)
4779
/* pbuf is the pointer to the current location of the text output */
4780
pbuf = TextOutputBuffer;
4782
/* keep track of whether the message has been successfully parsed */
4783
parsed = GOOD_PARSE;
4785
/* print a header if this is the first of a series of messages */
4786
pbuf += print_msg_table_header (rpt->code, pbuf, FALSE);
4788
/* process incoming TSIP report according to code */
4791
case 0x3D: rpt_chan_A_config (rpt); break;
4792
case 0x40: rpt_almanac_data_page (rpt); break;
4793
case 0x41: rpt_GPS_time (rpt); break;
4794
case 0x42: rpt_single_ECEF_position (rpt); break;
4795
case 0x43: rpt_single_ECEF_velocity (rpt); break;
4796
case 0x45: rpt_SW_version (rpt); break;
4797
case 0x46: rpt_rcvr_health (rpt); break;
4798
case 0x47: rpt_SNR_all_SVs (rpt); break;
4799
case 0x48: rpt_GPS_system_message (rpt); break;
4800
case 0x49: rpt_almanac_health_page (rpt); break;
4801
case 0x4A: switch (rpt->len) {
4803
** special case (=slip-up) in the TSIP protocol;
4804
** parsing method depends on length
4806
case 20: rpt_single_lla_position (rpt); break;
4807
case 9: rpt_ref_alt (rpt); break;
4809
case 0x4B: rpt_rcvr_id_and_status (rpt);break;
4810
case 0x4C: rpt_operating_parameters (rpt); break;
4811
case 0x4D: rpt_oscillator_offset (rpt); break;
4812
case 0x4E: rpt_GPS_time_set_response (rpt); break;
4813
case 0x4F: rpt_UTC_offset (rpt); break;
4814
case 0x54: rpt_1SV_bias (rpt); break;
4815
case 0x55: rpt_io_opt (rpt); break;
4816
case 0x56: rpt_ENU_velocity (rpt); break;
4817
case 0x57: rpt_last_fix_info (rpt); break;
4818
case 0x58: rpt_GPS_system_data (rpt); break;
4819
case 0x59: rpt_SVs_enabled (rpt); break;
4820
case 0x5A: rpt_raw_msmt (rpt); break;
4821
case 0x5B: rpt_SV_ephemeris_status (rpt); break;
4822
case 0x5C: rpt_SV_tracking_status (rpt); break;
4823
case 0x6D: rpt_allSV_selection (rpt); break;
4824
case 0x82: rpt_DGPS_position_mode (rpt); break;
4825
case 0x83: rpt_double_ECEF_position (rpt); break;
4826
case 0x84: rpt_double_lla_position (rpt); break;
4827
case 0xBB: rpt_complete_rcvr_config (rpt); break;
4828
case 0xBC: rpt_rcvr_serial_port_config (rpt); break;
4830
case 0x8F: switch (rpt->buf[0])
4832
/* superpackets; parsed according to subcodes */
4833
case 0x0B: rpt_8F0B(rpt); break;
4834
case 0x14: rpt_8F14(rpt); break;
4835
case 0x15: rpt_8F15(rpt); break;
4836
case 0x20: rpt_8F20(rpt); break;
4837
case 0x41: rpt_8F41(rpt); break;
4838
case 0x42: rpt_8F42(rpt); break;
4839
case 0x45: rpt_8F45(rpt); break;
4840
case 0x4A: rpt_8F4A(rpt); break;
4841
case 0x4B: rpt_8F4B(rpt); break;
4842
case 0x4D: rpt_8F4D(rpt); break;
4843
case 0xA5: rpt_8FA5(rpt); break;
4844
case 0xAD: rpt_8FAD(rpt); break;
4845
default: parsed = BADID_PARSE; break;
4849
default: parsed = BADID_PARSE; break;
4852
if (parsed != GOOD_PARSE)
4855
**The message has TSIP structure (DLEs, etc.)
4856
** but could not be parsed by above routines
4861
/* close TextOutputBuffer */
4865
#endif /* TRIMBLE_OUTPUT_FUNC */
4867
#else /* defined(REFCLOCK) && defined(CLOCK_RIPENCC) */
4868
int refclock_ripencc_bs;
4869
#endif /* defined(REFCLOCK) && defined(CLOCK_RIPENCC) */