xref: /freebsd/contrib/ntp/ntpd/refclock_ripencc.c (revision f5f40dd63bc7acbb5312b26ac1ea1103c12352a6)
1ba371819SOllivier Robert /*
2ba371819SOllivier Robert  * $Id: refclock_ripencc.c,v 1.13 2002/06/18 14:20:55 marks Exp marks $
3ba371819SOllivier Robert  *
4ba371819SOllivier Robert  * Copyright (c) 2002  RIPE NCC
5ba371819SOllivier Robert  *
6ba371819SOllivier Robert  * All Rights Reserved
7ba371819SOllivier Robert  *
8ba371819SOllivier Robert  * Permission to use, copy, modify, and distribute this software and its
9ba371819SOllivier Robert  * documentation for any purpose and without fee is hereby granted,
10ba371819SOllivier Robert  * provided that the above copyright notice appear in all copies and that
11ba371819SOllivier Robert  * both that copyright notice and this permission notice appear in
12ba371819SOllivier Robert  * supporting documentation, and that the name of the author not be
13ba371819SOllivier Robert  * used in advertising or publicity pertaining to distribution of the
14ba371819SOllivier Robert  * software without specific, written prior permission.
15ba371819SOllivier Robert  *
16ba371819SOllivier Robert  * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
17ba371819SOllivier Robert  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
18ba371819SOllivier Robert  * AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
19ba371819SOllivier Robert  * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
20ba371819SOllivier Robert  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
21ba371819SOllivier Robert  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22ba371819SOllivier Robert  *
23ba371819SOllivier Robert  *
24ba371819SOllivier Robert  *
25ba371819SOllivier Robert  * This driver was developed for use with the RIPE NCC TTM project.
26ba371819SOllivier Robert  *
27ba371819SOllivier Robert  *
28ba371819SOllivier Robert  * The initial driver was developed by Daniel Karrenberg <dfk@ripe.net>
29ba371819SOllivier Robert  * using the code made available by Trimble. This was for xntpd-3.x.x
30ba371819SOllivier Robert  *
31ba371819SOllivier Robert  * Rewrite of the driver for ntpd-4.x.x by Mark Santcroos <marks@ripe.net>
32ba371819SOllivier Robert  *
33ba371819SOllivier Robert  */
34ba371819SOllivier Robert 
35ba371819SOllivier Robert #ifdef HAVE_CONFIG_H
36ba371819SOllivier Robert #include <config.h>
37ba371819SOllivier Robert #endif /* HAVE_CONFIG_H */
38ba371819SOllivier Robert 
39ba371819SOllivier Robert #if defined(REFCLOCK) && defined(CLOCK_RIPENCC)
40ba371819SOllivier Robert 
41ba371819SOllivier Robert #include "ntp_stdlib.h"
42ba371819SOllivier Robert #include "ntpd.h"
43ba371819SOllivier Robert #include "ntp_refclock.h"
44ba371819SOllivier Robert #include "ntp_unixtime.h"
45ba371819SOllivier Robert #include "ntp_io.h"
46ba371819SOllivier Robert 
47ea906c41SOllivier Robert #ifdef HAVE_PPSAPI
48ea906c41SOllivier Robert # include "ppsapi_timepps.h"
49ea906c41SOllivier Robert #endif
50ba371819SOllivier Robert 
51ba371819SOllivier Robert /*
52ba371819SOllivier Robert  * Definitions
53ba371819SOllivier Robert  */
54ba371819SOllivier Robert 
55ba371819SOllivier Robert /* we are on little endian */
56ba371819SOllivier Robert #define BYTESWAP
57ba371819SOllivier Robert 
58ba371819SOllivier Robert /*
59ba371819SOllivier Robert  * DEBUG statements: uncomment if necessary
60ba371819SOllivier Robert  */
61ba371819SOllivier Robert /* #define DEBUG_NCC */ /* general debug statements */
62ba371819SOllivier Robert /* #define DEBUG_PPS */ /* debug pps */
63ba371819SOllivier Robert /* #define DEBUG_RAW */ /* print raw packets */
64ba371819SOllivier Robert 
65ba371819SOllivier Robert #define TRIMBLE_OUTPUT_FUNC
66ba371819SOllivier Robert #define TSIP_VERNUM "7.12a"
67ba371819SOllivier Robert 
68ba371819SOllivier Robert #ifndef FALSE
69ba371819SOllivier Robert #define FALSE 	(0)
70ba371819SOllivier Robert #define TRUE 	(!FALSE)
71ba371819SOllivier Robert #endif /* FALSE */
72ba371819SOllivier Robert 
73ba371819SOllivier Robert #define GPS_PI 	(3.1415926535898)
74ba371819SOllivier Robert #define GPS_C 		(299792458.)
75ba371819SOllivier Robert #define	D2R		(GPS_PI/180.0)
76ba371819SOllivier Robert #define	R2D		(180.0/GPS_PI)
77ba371819SOllivier Robert #define WEEK 	(604800.)
78ba371819SOllivier Robert #define MAXCHAN  (8)
79ba371819SOllivier Robert 
80ba371819SOllivier Robert /* control characters for TSIP packets */
81ba371819SOllivier Robert #define DLE 	(0x10)
82ba371819SOllivier Robert #define ETX 	(0x03)
83ba371819SOllivier Robert 
84ba371819SOllivier Robert #define MAX_RPTBUF (256)
85ba371819SOllivier Robert 
86ba371819SOllivier Robert /* values of TSIPPKT.status */
87ba371819SOllivier Robert #define TSIP_PARSED_EMPTY 	0
88ba371819SOllivier Robert #define TSIP_PARSED_FULL 	1
89ba371819SOllivier Robert #define TSIP_PARSED_DLE_1 	2
90ba371819SOllivier Robert #define TSIP_PARSED_DATA 	3
91ba371819SOllivier Robert #define TSIP_PARSED_DLE_2 	4
92ba371819SOllivier Robert 
93ba371819SOllivier Robert #define UTCF_UTC_AVAIL  (unsigned char) (1)     /* UTC available */
94ba371819SOllivier Robert #define UTCF_LEAP_SCHD  (unsigned char) (1<<4)  /* Leap scheduled */
95ba371819SOllivier Robert #define UTCF_LEAP_PNDG  (unsigned char) (1<<5)  /* Leap pending, will occur at end of day */
96ba371819SOllivier Robert 
97ba371819SOllivier Robert #define DEVICE  "/dev/gps%d"	/* name of radio device */
98ba371819SOllivier Robert #define PRECISION       (-9)    /* precision assumed (about 2 ms) */
99ba371819SOllivier Robert #define PPS_PRECISION   (-20)	/* precision assumed (about 1 us) */
100ba371819SOllivier Robert #define REFID           "GPS\0" /* reference id */
101ba371819SOllivier Robert #define REFID_LEN	4
102ba371819SOllivier Robert #define DESCRIPTION     "RIPE NCC GPS (Palisade)"	/* Description */
103ba371819SOllivier Robert #define SPEED232        B9600   /* 9600 baud */
104ba371819SOllivier Robert 
105ba371819SOllivier Robert #define NSAMPLES        3       /* stages of median filter */
106ba371819SOllivier Robert 
107ba371819SOllivier Robert /* Structures */
108ba371819SOllivier Robert 
109ba371819SOllivier Robert /* TSIP packets have the following structure, whether report or command. */
110ba371819SOllivier Robert typedef struct {
111ba371819SOllivier Robert 	short
112ba371819SOllivier Robert 	    counter,		/* counter */
113ba371819SOllivier Robert 	    len;		/* size of buf; < MAX_RPTBUF unsigned chars */
114ba371819SOllivier Robert 	unsigned char
115ba371819SOllivier Robert 	    status,		/* TSIP packet format/parse status */
116ba371819SOllivier Robert 	    code,		/* TSIP code */
117ba371819SOllivier Robert 	    buf[MAX_RPTBUF];	/* report or command string */
118ba371819SOllivier Robert } TSIPPKT;
119ba371819SOllivier Robert 
120ba371819SOllivier Robert /* TSIP binary data structures */
121ba371819SOllivier Robert typedef struct {
122ba371819SOllivier Robert 	unsigned char
123ba371819SOllivier Robert 	    t_oa_raw, SV_health;
124ba371819SOllivier Robert 	float
125ba371819SOllivier Robert 	    e, t_oa, i_0, OMEGADOT, sqrt_A,
126ba371819SOllivier Robert 	    OMEGA_0, omega, M_0, a_f0, a_f1,
127ba371819SOllivier Robert 	    Axis, n, OMEGA_n, ODOT_n, t_zc;
128ba371819SOllivier Robert 	short
129ba371819SOllivier Robert 	    weeknum, wn_oa;
130ba371819SOllivier Robert } ALM_INFO;
131ba371819SOllivier Robert 
132ba371819SOllivier Robert typedef struct {		/*  Almanac health page (25) parameters  */
133ba371819SOllivier Robert 	unsigned char
134ba371819SOllivier Robert 	    WN_a, SV_health[32], t_oa;
135ba371819SOllivier Robert } ALH_PARMS;
136ba371819SOllivier Robert 
137ba371819SOllivier Robert typedef struct {		/*  Universal Coordinated Time (UTC) parms */
138ba371819SOllivier Robert 	double
139ba371819SOllivier Robert 	    A_0;
140ba371819SOllivier Robert 	float
141ba371819SOllivier Robert 	    A_1;
142ba371819SOllivier Robert 	short
143ba371819SOllivier Robert 	    delta_t_LS;
144ba371819SOllivier Robert 	float
145ba371819SOllivier Robert 	    t_ot;
146ba371819SOllivier Robert 	short
147ba371819SOllivier Robert 	    WN_t, WN_LSF, DN, delta_t_LSF;
148ba371819SOllivier Robert } UTC_INFO;
149ba371819SOllivier Robert 
150ba371819SOllivier Robert typedef struct {		/*  Ionospheric info (float)  */
151ba371819SOllivier Robert 	float
152ba371819SOllivier Robert 	    alpha_0, alpha_1, alpha_2, alpha_3,
153ba371819SOllivier Robert 	    beta_0, beta_1, beta_2, beta_3;
154ba371819SOllivier Robert } ION_INFO;
155ba371819SOllivier Robert 
156ba371819SOllivier Robert typedef struct {		/*  Subframe 1 info (float)  */
157ba371819SOllivier Robert 	short
158ba371819SOllivier Robert 	    weeknum;
159ba371819SOllivier Robert 	unsigned char
160ba371819SOllivier Robert 	    codeL2, L2Pdata, SVacc_raw, SV_health;
161ba371819SOllivier Robert 	short
162ba371819SOllivier Robert 	    IODC;
163ba371819SOllivier Robert 	float
164ba371819SOllivier Robert 	    T_GD, t_oc, a_f2, a_f1, a_f0, SVacc;
165ba371819SOllivier Robert } EPHEM_CLOCK;
166ba371819SOllivier Robert 
167ba371819SOllivier Robert typedef	struct {		/*  Ephemeris info (float)  */
168ba371819SOllivier Robert 	unsigned char
169ba371819SOllivier Robert 	    IODE, fit_interval;
170ba371819SOllivier Robert 	float
171ba371819SOllivier Robert 	    C_rs, delta_n;
172ba371819SOllivier Robert 	double
173ba371819SOllivier Robert 	    M_0;
174ba371819SOllivier Robert 	float
175ba371819SOllivier Robert 	    C_uc;
176ba371819SOllivier Robert 	double
177ba371819SOllivier Robert 	    e;
178ba371819SOllivier Robert 	float
179ba371819SOllivier Robert 	    C_us;
180ba371819SOllivier Robert 	double
181ba371819SOllivier Robert 	    sqrt_A;
182ba371819SOllivier Robert 	float
183ba371819SOllivier Robert 	    t_oe, C_ic;
184ba371819SOllivier Robert 	double
185ba371819SOllivier Robert 	    OMEGA_0;
186ba371819SOllivier Robert 	float
187ba371819SOllivier Robert 	    C_is;
188ba371819SOllivier Robert 	double
189ba371819SOllivier Robert 	    i_0;
190ba371819SOllivier Robert 	float
191ba371819SOllivier Robert 	    C_rc;
192ba371819SOllivier Robert 	double
193ba371819SOllivier Robert 	    omega;
194ba371819SOllivier Robert 	float
195ba371819SOllivier Robert 	    OMEGADOT, IDOT;
196ba371819SOllivier Robert 	double
197ba371819SOllivier Robert 	    Axis, n, r1me2, OMEGA_n, ODOT_n;
198ba371819SOllivier Robert } EPHEM_ORBIT;
199ba371819SOllivier Robert 
200ba371819SOllivier Robert typedef struct {		/* Navigation data structure */
201ba371819SOllivier Robert 	short
202ba371819SOllivier Robert 	    sv_number;		/* SV number (0 = no entry) */
203ba371819SOllivier Robert 	float
204ba371819SOllivier Robert 	    t_ephem;		/* time of ephemeris collection */
205ba371819SOllivier Robert 	EPHEM_CLOCK
206ba371819SOllivier Robert 	    ephclk;		/* subframe 1 data */
207ba371819SOllivier Robert 	EPHEM_ORBIT
208ba371819SOllivier Robert 	    ephorb;		/* ephemeris data */
209ba371819SOllivier Robert } NAV_INFO;
210ba371819SOllivier Robert 
211ba371819SOllivier Robert typedef struct {
212ba371819SOllivier Robert 	unsigned char
213ba371819SOllivier Robert 	    bSubcode,
214ba371819SOllivier Robert 	    operating_mode,
215ba371819SOllivier Robert 	    dgps_mode,
216ba371819SOllivier Robert 	    dyn_code,
217ba371819SOllivier Robert 	    trackmode;
218ba371819SOllivier Robert 	float
219ba371819SOllivier Robert 	    elev_mask,
220ba371819SOllivier Robert 	    cno_mask,
221ba371819SOllivier Robert 	    dop_mask,
222ba371819SOllivier Robert 	    dop_switch;
223ba371819SOllivier Robert 	unsigned char
224ba371819SOllivier Robert 	    dgps_age_limit;
225ba371819SOllivier Robert } TSIP_RCVR_CFG;
226ba371819SOllivier Robert 
227ba371819SOllivier Robert 
228ba371819SOllivier Robert #ifdef TRIMBLE_OUTPUT_FUNC
229ba371819SOllivier Robert static char
230ba371819SOllivier Robert         *dayname[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"},
231ba371819SOllivier Robert 	old_baudnum[] = {0, 1, 4, 5, 6, 8, 9, 11, 28, 12},
232ba371819SOllivier Robert         *st_baud_text_app [] = {"", "", "  300", "  600", " 1200", " 2400",
233ba371819SOllivier Robert 				" 4800", " 9600", "19200", "38400"},
234ba371819SOllivier Robert 	*old_parity_text[] = {"EVEN", "ODD", "", "", "NONE"},
235ba371819SOllivier Robert 	*parity_text [] = {"NONE", "ODD", "EVEN"},
236ba371819SOllivier Robert 	*old_input_ch[] = { "TSIP", "RTCM (6 of 8 bits)"},
237ba371819SOllivier Robert 	*old_output_ch[] = { "TSIP", "No output", "", "", "", "NMEA 0183"},
238ba371819SOllivier Robert 	*protocols_in_text[] = { "", "TSIP", "", ""},
239ba371819SOllivier Robert 	*protocols_out_text[] =	{ "", "TSIP", "NMEA"},
240ba371819SOllivier Robert 	*rcvr_port_text [] = { "Port A      ", "Port B      ", "Current Port"},
241ba371819SOllivier Robert 	*dyn_text [] = {"Unchanged", "Land", "Sea", "Air", "Static"},
242ba371819SOllivier Robert 	*NavModeText0xBB[] = {"automatic", "time only (0-D)", "", "2-D",
243ba371819SOllivier Robert 			      "3-D", "", "", "OverDetermined Time"},
244ba371819SOllivier Robert 	*PPSTimeBaseText[] = {"GPS", "UTC", "USER"},
245ba371819SOllivier Robert 	*PPSPolarityText[] = {"Positive", "Negative"},
246ba371819SOllivier Robert   	*MaskText[] = { "Almanac  ", "Ephemeris", "UTC      ", "Iono     ",
247ba371819SOllivier Robert 			"GPS Msg  ", "Alm Hlth ", "Time Fix ", "SV Select",
248ba371819SOllivier Robert 			"Ext Event", "Pos Fix  ", "Raw Meas "};
249ba371819SOllivier Robert 
250ba371819SOllivier Robert #endif /* TRIMBLE_OUTPUT_FUNC */
251ba371819SOllivier Robert 
252ba371819SOllivier Robert /*
253ba371819SOllivier Robert  * Unit control structure
254ba371819SOllivier Robert  */
255ba371819SOllivier Robert struct ripencc_unit {
256ba371819SOllivier Robert         int unit;                       /* unit number */
257ba371819SOllivier Robert         int     pollcnt;                /* poll message counter */
258ba371819SOllivier Robert         int     polled;                 /* Hand in a sample? */
259ba371819SOllivier Robert         char leapdelta;                 /* delta of next leap event */
260ba371819SOllivier Robert         unsigned char utcflags;         /* delta of next leap event */
261ba371819SOllivier Robert         l_fp    tstamp;                 /* timestamp of last poll */
262ba371819SOllivier Robert 
263ba371819SOllivier Robert         struct timespec ts;             /* last timestamp */
264ba371819SOllivier Robert         pps_params_t pps_params;        /* pps parameters */
265ba371819SOllivier Robert         pps_info_t pps_info;            /* last pps data */
266ba371819SOllivier Robert         pps_handle_t handle;            /* pps handlebars */
267ba371819SOllivier Robert 
268ba371819SOllivier Robert };
269ba371819SOllivier Robert 
270ba371819SOllivier Robert 
271ba371819SOllivier Robert /*******************        PROTOYPES            *****************/
272ba371819SOllivier Robert 
273ba371819SOllivier Robert /*  prototypes for report parsing primitives */
274ba371819SOllivier Robert short rpt_0x3D (TSIPPKT *rpt, unsigned char *tx_baud_index,
275ba371819SOllivier Robert 		unsigned char *rx_baud_index, unsigned char *char_format_index,
276ba371819SOllivier Robert 		unsigned char *stop_bits, unsigned char *tx_mode_index,
277ba371819SOllivier Robert 		unsigned char *rx_mode_index);
278ba371819SOllivier Robert short rpt_0x40 (TSIPPKT *rpt, unsigned char *sv_prn, short *week_num,
279ba371819SOllivier Robert 		float *t_zc, float *eccentricity, float *t_oa, float *i_0,
280ba371819SOllivier Robert 		float *OMEGA_dot, float *sqrt_A, float *OMEGA_0, float *omega,
281ba371819SOllivier Robert 		float *M_0);
282ba371819SOllivier Robert short rpt_0x41 (TSIPPKT *rpt, float *time_of_week, float *UTC_offset,
283ba371819SOllivier Robert 		short *week_num);
284ba371819SOllivier Robert short rpt_0x42 (TSIPPKT *rpt, float ECEF_pos[3], float *time_of_fix);
285ba371819SOllivier Robert short rpt_0x43 (TSIPPKT *rpt, float ECEF_vel[3], float *freq_offset,
286ba371819SOllivier Robert 		float *time_of_fix);
287ba371819SOllivier Robert short rpt_0x45 (TSIPPKT *rpt, unsigned char *major_nav_version,
288ba371819SOllivier Robert 		unsigned char *minor_nav_version, unsigned char *nav_day,
289ba371819SOllivier Robert 		unsigned char *nav_month, unsigned char *nav_year,
290ba371819SOllivier Robert 		unsigned char *major_dsp_version, unsigned char *minor_dsp_version,
291ba371819SOllivier Robert 		unsigned char *dsp_day, unsigned char *dsp_month,
292ba371819SOllivier Robert 		unsigned char *dsp_year);
293ba371819SOllivier Robert short rpt_0x46 (TSIPPKT *rpt, unsigned char *status1, unsigned char *status2);
294ba371819SOllivier Robert short rpt_0x47 (TSIPPKT *rpt, unsigned char *nsvs, unsigned char *sv_prn,
295ba371819SOllivier Robert 		float *snr);
296ba371819SOllivier Robert short rpt_0x48 (TSIPPKT *rpt, unsigned char *message);
297ba371819SOllivier Robert short rpt_0x49 (TSIPPKT *rpt, unsigned char *sv_health);
298ba371819SOllivier Robert short rpt_0x4A (TSIPPKT *rpt, float *lat, float *lon, float *alt,
299ba371819SOllivier Robert 		float *clock_bias, float *time_of_fix);
300ba371819SOllivier Robert short rpt_0x4A_2 (TSIPPKT *rpt, float *alt, float *dummy,
301ba371819SOllivier Robert 		  unsigned char *alt_flag);
302ba371819SOllivier Robert short rpt_0x4B (TSIPPKT *rpt, unsigned char *machine_id,
303ba371819SOllivier Robert 		unsigned char *status3, unsigned char *status4);
304ba371819SOllivier Robert short rpt_0x4C (TSIPPKT *rpt, unsigned char *dyn_code, float *el_mask,
305ba371819SOllivier Robert 		float *snr_mask, float *dop_mask, float *dop_switch);
306ba371819SOllivier Robert short rpt_0x4D (TSIPPKT *rpt, float *osc_offset);
307ba371819SOllivier Robert short rpt_0x4E (TSIPPKT *rpt, unsigned char *response);
308ba371819SOllivier Robert short rpt_0x4F (TSIPPKT *rpt, double *a0, float *a1, float *time_of_data,
309ba371819SOllivier Robert 		short *dt_ls, short *wn_t, short *wn_lsf, short *dn, short *dt_lsf);
310ba371819SOllivier Robert short rpt_0x54 (TSIPPKT *rpt, float *clock_bias, float *freq_offset,
311ba371819SOllivier Robert 		float *time_of_fix);
312ba371819SOllivier Robert short rpt_0x55 (TSIPPKT *rpt, unsigned char *pos_code, unsigned char *vel_code,
313ba371819SOllivier Robert 		unsigned char *time_code, unsigned char *aux_code);
314ba371819SOllivier Robert short rpt_0x56 (TSIPPKT *rpt, float vel_ENU[3], float *freq_offset,
315ba371819SOllivier Robert 		float *time_of_fix);
316ba371819SOllivier Robert short rpt_0x57 (TSIPPKT *rpt, unsigned char *source_code,
317ba371819SOllivier Robert 		unsigned char *diag_code, short *week_num, float *time_of_fix);
318ba371819SOllivier Robert short rpt_0x58 (TSIPPKT *rpt, unsigned char *op_code, unsigned char *data_type,
319ba371819SOllivier Robert 		unsigned char *sv_prn, unsigned char *data_length,
320ba371819SOllivier Robert 		unsigned char *data_packet);
321ba371819SOllivier Robert short rpt_0x59 (TSIPPKT *rpt, unsigned char *code_type,
322ba371819SOllivier Robert 		unsigned char status_code[32]);
323ba371819SOllivier Robert short rpt_0x5A (TSIPPKT *rpt, unsigned char *sv_prn, float *sample_length,
324ba371819SOllivier Robert 		float *signal_level, float *code_phase, float *Doppler,
325ba371819SOllivier Robert 		double *time_of_fix);
326ba371819SOllivier Robert short rpt_0x5B (TSIPPKT *rpt, unsigned char *sv_prn, unsigned char *sv_health,
327ba371819SOllivier Robert 		unsigned char *sv_iode, unsigned char *fit_interval_flag,
328ba371819SOllivier Robert 		float *time_of_collection, float *time_of_eph, float *sv_accy);
329ba371819SOllivier Robert short rpt_0x5C (TSIPPKT *rpt, unsigned char *sv_prn, unsigned char *slot,
330ba371819SOllivier Robert 		unsigned char *chan, unsigned char *acq_flag, unsigned char *eph_flag,
331ba371819SOllivier Robert 		float *signal_level, float *time_of_last_msmt, float *elev,
332ba371819SOllivier Robert 		float *azim, unsigned char *old_msmt_flag,
333ba371819SOllivier Robert 		unsigned char *integer_msec_flag, unsigned char *bad_data_flag,
334ba371819SOllivier Robert 		unsigned char *data_collect_flag);
335ba371819SOllivier Robert short rpt_0x6D (TSIPPKT *rpt, unsigned char *manual_mode, unsigned char *nsvs,
336ba371819SOllivier Robert 		unsigned char *ndim, unsigned char sv_prn[], float *pdop,
337ba371819SOllivier Robert 		float *hdop, float *vdop, float *tdop);
338ba371819SOllivier Robert short rpt_0x82 (TSIPPKT *rpt, unsigned char *diff_mode);
339ba371819SOllivier Robert short rpt_0x83 (TSIPPKT *rpt, double ECEF_pos[3], double *clock_bias,
340ba371819SOllivier Robert 		float *time_of_fix);
341ba371819SOllivier Robert short rpt_0x84 (TSIPPKT *rpt, double *lat, double *lon, double *alt,
342ba371819SOllivier Robert 		double *clock_bias, float *time_of_fix);
343ba371819SOllivier Robert short rpt_Paly0xBB(TSIPPKT *rpt, TSIP_RCVR_CFG *TsipxBB);
344ba371819SOllivier Robert short rpt_0xBC   (TSIPPKT *rpt, unsigned char *port_num,
345ba371819SOllivier Robert 		  unsigned char *in_baud, unsigned char *out_baud,
346ba371819SOllivier Robert 		  unsigned char *data_bits, unsigned char *parity,
347ba371819SOllivier Robert 		  unsigned char *stop_bits, unsigned char *flow_control,
348ba371819SOllivier Robert 		  unsigned char *protocols_in, unsigned char *protocols_out,
349ba371819SOllivier Robert 		  unsigned char *reserved);
350ba371819SOllivier Robert 
351ba371819SOllivier Robert /* prototypes for superpacket parsers */
352ba371819SOllivier Robert 
353ba371819SOllivier Robert short rpt_0x8F0B (TSIPPKT *rpt, unsigned short *event, double *tow,
354ba371819SOllivier Robert 		  unsigned char *date, unsigned char *month, short *year,
355ba371819SOllivier Robert 		  unsigned char *dim_mode, short *utc_offset, double *bias, double *drift,
356ba371819SOllivier Robert 		  float *bias_unc, float *dr_unc, double *lat, double *lon, double *alt,
357ba371819SOllivier Robert 		  char sv_id[8]);
358ba371819SOllivier Robert short rpt_0x8F14 (TSIPPKT *rpt, short *datum_idx, double datum_coeffs[5]);
359ba371819SOllivier Robert short rpt_0x8F15 (TSIPPKT *rpt, short *datum_idx, double datum_coeffs[5]);
360ba371819SOllivier Robert short rpt_0x8F20 (TSIPPKT *rpt, unsigned char *info, double *lat,
361ba371819SOllivier Robert 		  double *lon, double *alt, double vel_enu[], double *time_of_fix,
362ba371819SOllivier Robert 		  short *week_num, unsigned char *nsvs, unsigned char sv_prn[],
363ba371819SOllivier Robert 		  short sv_IODC[], short *datum_index);
364ba371819SOllivier Robert short rpt_0x8F41 (TSIPPKT *rpt, unsigned char *bSearchRange,
365ba371819SOllivier Robert 		  unsigned char *bBoardOptions, unsigned long *iiSerialNumber,
366ba371819SOllivier Robert 		  unsigned char *bBuildYear, unsigned char *bBuildMonth,
367ba371819SOllivier Robert 		  unsigned char *bBuildDay, unsigned char *bBuildHour,
368ba371819SOllivier Robert 		  float *fOscOffset, unsigned short *iTestCodeId);
369ba371819SOllivier Robert short rpt_0x8F42 (TSIPPKT *rpt, unsigned char *bProdOptionsPre,
370ba371819SOllivier Robert 		  unsigned char *bProdNumberExt, unsigned short *iCaseSerialNumberPre,
371ba371819SOllivier Robert 		  unsigned long *iiCaseSerialNumber, unsigned long *iiProdNumber,
372ba371819SOllivier Robert 		  unsigned short *iPremiumOptions, unsigned short *iMachineID,
373ba371819SOllivier Robert 		  unsigned short *iKey);
374ba371819SOllivier Robert short rpt_0x8F45 (TSIPPKT *rpt, unsigned char *bSegMask);
375ba371819SOllivier Robert short rpt_0x8F4A_16 (TSIPPKT *rpt, unsigned char *pps_enabled,
376ba371819SOllivier Robert 		     unsigned char *pps_timebase, unsigned char *pos_polarity,
377ba371819SOllivier Robert 		     double *pps_offset, float *bias_unc_threshold);
378ba371819SOllivier Robert short rpt_0x8F4B (TSIPPKT *rpt, unsigned long *decorr_max);
379ba371819SOllivier Robert short rpt_0x8F4D (TSIPPKT *rpt, unsigned long *event_mask);
380ba371819SOllivier Robert short rpt_0x8FA5 (TSIPPKT *rpt, unsigned char *spktmask);
381ba371819SOllivier Robert short rpt_0x8FAD (TSIPPKT *rpt, unsigned short *COUNT, double *FracSec,
382ba371819SOllivier Robert 		  unsigned char *Hour, unsigned char *Minute, unsigned char *Second,
383ba371819SOllivier Robert 		  unsigned char *Day, unsigned char *Month, unsigned short *Year,
384ba371819SOllivier Robert 		  unsigned char *Status, unsigned char *Flags);
385ba371819SOllivier Robert 
386ba371819SOllivier Robert /**/
387ba371819SOllivier Robert /* prototypes for command-encode primitives with suffix convention:  */
388ba371819SOllivier Robert /* c = clear, s = set, q = query, e = enable, d = disable            */
389ba371819SOllivier Robert void cmd_0x1F  (TSIPPKT *cmd);
390ba371819SOllivier Robert void cmd_0x26  (TSIPPKT *cmd);
391ba371819SOllivier Robert void cmd_0x2F  (TSIPPKT *cmd);
392ba371819SOllivier Robert void cmd_0x35s (TSIPPKT *cmd, unsigned char pos_code, unsigned char vel_code,
393ba371819SOllivier Robert 		unsigned char time_code, unsigned char opts_code);
394ba371819SOllivier Robert void cmd_0x3C  (TSIPPKT *cmd, unsigned char sv_prn);
395ba371819SOllivier Robert void cmd_0x3Ds (TSIPPKT *cmd, unsigned char baud_out, unsigned char baud_inp,
396ba371819SOllivier Robert 		unsigned char char_code, unsigned char stopbitcode,
397ba371819SOllivier Robert 		unsigned char output_mode, unsigned char input_mode);
398ba371819SOllivier Robert void cmd_0xBBq (TSIPPKT *cmd, unsigned char subcode) ;
399ba371819SOllivier Robert 
400ba371819SOllivier Robert /* prototypes 8E commands */
401ba371819SOllivier Robert void cmd_0x8E0Bq (TSIPPKT *cmd);
402ba371819SOllivier Robert void cmd_0x8E41q (TSIPPKT *cmd);
403ba371819SOllivier Robert void cmd_0x8E42q (TSIPPKT *cmd);
404ba371819SOllivier Robert void cmd_0x8E4Aq (TSIPPKT *cmd);
405ba371819SOllivier Robert void cmd_0x8E4As (TSIPPKT *cmd, unsigned char PPSOnOff, unsigned char TimeBase,
406ba371819SOllivier Robert 		  unsigned char Polarity, double PPSOffset, float Uncertainty);
407ba371819SOllivier Robert void cmd_0x8E4Bq (TSIPPKT *cmd);
408ba371819SOllivier Robert void cmd_0x8E4Ds (TSIPPKT *cmd, unsigned long AutoOutputMask);
409ba371819SOllivier Robert void cmd_0x8EADq (TSIPPKT *cmd);
410ba371819SOllivier Robert 
411ba371819SOllivier Robert /* header/source border XXXXXXXXXXXXXXXXXXXXXXXXXX */
412ba371819SOllivier Robert 
413ba371819SOllivier Robert /* Trimble parse functions */
4142b15cb3dSCy Schubert static 	int	parse0x8FAD	(TSIPPKT *, struct peer *);
4152b15cb3dSCy Schubert static 	int	parse0x8F0B	(TSIPPKT *, struct peer *);
416ba371819SOllivier Robert #ifdef TRIMBLE_OUTPUT_FUNC
4172b15cb3dSCy Schubert static 	int	parseany	(TSIPPKT *, struct peer *);
4182b15cb3dSCy Schubert static 	void	TranslateTSIPReportToText	(TSIPPKT *, char *);
419ba371819SOllivier Robert #endif /* TRIMBLE_OUTPUT_FUNC */
4202b15cb3dSCy Schubert static 	int	parse0x5C	(TSIPPKT *, struct peer *);
4212b15cb3dSCy Schubert static 	int	parse0x4F	(TSIPPKT *, struct peer *);
4222b15cb3dSCy Schubert static	void	tsip_input_proc	(TSIPPKT *, int);
423ba371819SOllivier Robert 
424ba371819SOllivier Robert /* Trimble helper functions */
4252b15cb3dSCy Schubert static	void	bPutFloat 	(float *, unsigned char *);
4262b15cb3dSCy Schubert static	void	bPutDouble 	(double *, unsigned char *);
4272b15cb3dSCy Schubert static	void	bPutULong 	(unsigned long *, unsigned char *);
4282b15cb3dSCy Schubert static	int	print_msg_table_header	(int rptcode, char *HdrStr, int force);
4292b15cb3dSCy Schubert static	char *	show_time	(float time_of_week);
430ba371819SOllivier Robert 
431ba371819SOllivier Robert /* RIPE NCC functions */
4322b15cb3dSCy Schubert static	void	ripencc_control	(int, const struct refclockstat *,
4332b15cb3dSCy Schubert 				 struct refclockstat *, struct peer *);
4342b15cb3dSCy Schubert static	int	ripencc_ppsapi	(struct peer *, int, int);
4352b15cb3dSCy Schubert static	int	ripencc_get_pps_ts	(struct ripencc_unit *, l_fp *);
4362b15cb3dSCy Schubert static	int	ripencc_start	(int, struct peer *);
4372b15cb3dSCy Schubert static 	void	ripencc_shutdown	(int, struct peer *);
4382b15cb3dSCy Schubert static 	void	ripencc_poll	(int, struct peer *);
4392b15cb3dSCy Schubert static 	void	ripencc_send	(struct peer *, TSIPPKT spt);
4402b15cb3dSCy Schubert static 	void	ripencc_receive	(struct recvbuf *);
441ba371819SOllivier Robert 
442ba371819SOllivier Robert /* fill in reflock structure for our clock */
443ba371819SOllivier Robert struct refclock refclock_ripencc = {
444ba371819SOllivier Robert 	ripencc_start,		/* start up driver */
445ba371819SOllivier Robert 	ripencc_shutdown,	/* shut down driver */
446ba371819SOllivier Robert 	ripencc_poll,		/* transmit poll message */
447ba371819SOllivier Robert 	ripencc_control,	/* control function */
448ba371819SOllivier Robert 	noentry,		/* initialize driver */
449ba371819SOllivier Robert 	noentry,		/* debug info */
450ba371819SOllivier Robert 	NOFLAGS			/* clock flags */
451ba371819SOllivier Robert };
452ba371819SOllivier Robert 
453ba371819SOllivier Robert /*
454ba371819SOllivier Robert  *  Tables to compute the ddd of year form icky dd/mm timecode. Viva la
455ba371819SOllivier Robert  *  leap.
456ba371819SOllivier Robert  */
457ba371819SOllivier Robert static int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
458ba371819SOllivier Robert static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
459ba371819SOllivier Robert 
460ba371819SOllivier Robert 
461ba371819SOllivier Robert /*
462ba371819SOllivier Robert  * ripencc_start - open the GPS devices and initialize data for processing
463ba371819SOllivier Robert  */
464ba371819SOllivier Robert static int
465ba371819SOllivier Robert ripencc_start(int unit, struct peer *peer)
466ba371819SOllivier Robert {
467ba371819SOllivier Robert 	register struct ripencc_unit *up;
468ba371819SOllivier Robert 	struct refclockproc *pp;
469ba371819SOllivier Robert 	char device[40];
470ba371819SOllivier Robert 	int fd;
471ba371819SOllivier Robert 	struct termios tio;
472ba371819SOllivier Robert 	TSIPPKT spt;
473ba371819SOllivier Robert 
4742b15cb3dSCy Schubert 	pp = peer->procptr;
4752b15cb3dSCy Schubert 
476ba371819SOllivier Robert 	/*
477ba371819SOllivier Robert 	 * Open serial port
478ba371819SOllivier Robert 	 */
479ba371819SOllivier Robert 	(void)snprintf(device, sizeof(device), DEVICE, unit);
480a466cc55SCy Schubert 	fd = refclock_open(&peer->srcadr, device, SPEED232, LDISC_RAW);
4812b15cb3dSCy Schubert 	if (fd <= 0) {
4822b15cb3dSCy Schubert 		pp->io.fd = -1;
483ba371819SOllivier Robert 		return (0);
4842b15cb3dSCy Schubert 	}
4852b15cb3dSCy Schubert 
4862b15cb3dSCy Schubert 	pp->io.fd = fd;
487ba371819SOllivier Robert 
488ba371819SOllivier Robert 	/* from refclock_palisade.c */
489ba371819SOllivier Robert 	if (tcgetattr(fd, &tio) < 0) {
490ba371819SOllivier Robert 		msyslog(LOG_ERR, "Palisade(%d) tcgetattr(fd, &tio): %m",unit);
491ba371819SOllivier Robert 		return (0);
492ba371819SOllivier Robert 	}
493ba371819SOllivier Robert 
494ba371819SOllivier Robert 	/*
495ba371819SOllivier Robert 	 * set flags
496ba371819SOllivier Robert 	 */
497ba371819SOllivier Robert 	tio.c_cflag |= (PARENB|PARODD);
498ba371819SOllivier Robert 	tio.c_iflag &= ~ICRNL;
499ba371819SOllivier Robert 	if (tcsetattr(fd, TCSANOW, &tio) == -1) {
500ba371819SOllivier Robert 		msyslog(LOG_ERR, "Palisade(%d) tcsetattr(fd, &tio): %m",unit);
501ba371819SOllivier Robert 		return (0);
502ba371819SOllivier Robert 	}
503ba371819SOllivier Robert 
504ba371819SOllivier Robert 	/*
505ba371819SOllivier Robert 	 * Allocate and initialize unit structure
506ba371819SOllivier Robert 	 */
5072b15cb3dSCy Schubert 	up = emalloc_zero(sizeof(*up));
5082b15cb3dSCy Schubert 
509ba371819SOllivier Robert 	pp->io.clock_recv = ripencc_receive;
5102b15cb3dSCy Schubert 	pp->io.srcclock = peer;
511ba371819SOllivier Robert 	pp->io.datalen = 0;
512ba371819SOllivier Robert 	if (!io_addclock(&pp->io)) {
5132b15cb3dSCy Schubert 		pp->io.fd = -1;
5142b15cb3dSCy Schubert 		close(fd);
515ba371819SOllivier Robert 		free(up);
516ba371819SOllivier Robert 		return (0);
517ba371819SOllivier Robert 	}
5182b15cb3dSCy Schubert 	pp->unitptr = up;
519ba371819SOllivier Robert 
520ba371819SOllivier Robert 	/*
521ba371819SOllivier Robert 	 * Initialize miscellaneous variables
522ba371819SOllivier Robert 	 */
523ba371819SOllivier Robert 	peer->precision = PRECISION;
524ba371819SOllivier Robert 	pp->clockdesc = DESCRIPTION;
525ba371819SOllivier Robert 	memcpy((char *)&pp->refid, REFID, REFID_LEN);
526ba371819SOllivier Robert 	up->pollcnt = 2;
527ba371819SOllivier Robert 	up->unit = unit;
528ba371819SOllivier Robert 	up->leapdelta = 0;
529ba371819SOllivier Robert 	up->utcflags = 0;
530ba371819SOllivier Robert 
531ba371819SOllivier Robert 	/*
532ba371819SOllivier Robert 	 * Initialize the Clock
533ba371819SOllivier Robert 	 */
534ba371819SOllivier Robert 
535ba371819SOllivier Robert 	/* query software versions */
536ba371819SOllivier Robert 	cmd_0x1F(&spt);
537ba371819SOllivier Robert 	ripencc_send(peer, spt);
538ba371819SOllivier Robert 
539ba371819SOllivier Robert 	/* query receiver health */
540ba371819SOllivier Robert 	cmd_0x26(&spt);
541ba371819SOllivier Robert 	ripencc_send(peer, spt);
542ba371819SOllivier Robert 
543ba371819SOllivier Robert 	/* query serial numbers */
544ba371819SOllivier Robert 	cmd_0x8E42q(&spt);
545ba371819SOllivier Robert 	ripencc_send(peer, spt);
546ba371819SOllivier Robert 
547ba371819SOllivier Robert 	/* query manuf params */
548ba371819SOllivier Robert 	cmd_0x8E41q(&spt);
549ba371819SOllivier Robert 	ripencc_send(peer, spt);
550ba371819SOllivier Robert 
551ba371819SOllivier Robert 	/* i/o opts */ /* trimble manual page A30 */
552ba371819SOllivier Robert 	cmd_0x35s(&spt,
553ba371819SOllivier Robert 		  0x1C, 	/* position */
554ba371819SOllivier Robert 		  0x00, 	/* velocity */
555ba371819SOllivier Robert 		  0x05, 	/* timing */
556ba371819SOllivier Robert 		  0x0a); 	/* auxilary */
557ba371819SOllivier Robert 	ripencc_send(peer, spt);
558ba371819SOllivier Robert 
559ba371819SOllivier Robert 	/* turn off port A */
560ba371819SOllivier Robert 	cmd_0x3Ds (&spt,
561ba371819SOllivier Robert 		   0x0B,	/* baud_out */
562ba371819SOllivier Robert 		   0x0B,	/* baud_inp */
563ba371819SOllivier Robert 		   0x07,	/* char_code */
564ba371819SOllivier Robert 		   0x07,	/* stopbitcode */
565ba371819SOllivier Robert 		   0x01,	/* output_mode */
566ba371819SOllivier Robert 		   0x00);	/* input_mode */
567ba371819SOllivier Robert 	ripencc_send(peer, spt);
568ba371819SOllivier Robert 
569ba371819SOllivier Robert 	/* set i/o options */
570ba371819SOllivier Robert 	cmd_0x8E4As (&spt,
571ba371819SOllivier Robert 		     0x01,	/* PPS on */
572ba371819SOllivier Robert 		     0x01,	/* Timebase UTC */
573ba371819SOllivier Robert 		     0x00,	/* polarity positive */
574ba371819SOllivier Robert 		     0.,	/* 100 ft. cable XXX make flag */
575ba371819SOllivier Robert 		     1e-6 * GPS_C); 	/* turn of biasuncert. > (1us) */
576ba371819SOllivier Robert 	ripencc_send(peer,spt);
577ba371819SOllivier Robert 
578ba371819SOllivier Robert 	/* all outomatic packet output off */
579ba371819SOllivier Robert 	cmd_0x8E4Ds(&spt,
580ba371819SOllivier Robert 		    0x00000000); /* AutoOutputMask */
581ba371819SOllivier Robert 	ripencc_send(peer, spt);
582ba371819SOllivier Robert 
583ba371819SOllivier Robert 	cmd_0xBBq (&spt,
584ba371819SOllivier Robert 		   0x00);	/* query primary configuration */
585ba371819SOllivier Robert 	ripencc_send(peer,spt);
586ba371819SOllivier Robert 
587ba371819SOllivier Robert 
588ba371819SOllivier Robert 	/* query PPS parameters */
589ba371819SOllivier Robert 	cmd_0x8E4Aq (&spt);	/* query PPS params */
590ba371819SOllivier Robert 	ripencc_send(peer,spt);
591ba371819SOllivier Robert 
592ba371819SOllivier Robert 	/* query survey limit */
593ba371819SOllivier Robert 	cmd_0x8E4Bq (&spt);	/* query survey limit */
594ba371819SOllivier Robert 	ripencc_send(peer,spt);
595ba371819SOllivier Robert 
596ba371819SOllivier Robert #ifdef DEBUG_NCC
597ba371819SOllivier Robert 	if (debug)
598ba371819SOllivier Robert 		printf("ripencc_start: success\n");
599ba371819SOllivier Robert #endif /* DEBUG_NCC */
600ba371819SOllivier Robert 
601ba371819SOllivier Robert 	/*
602ba371819SOllivier Robert 	 * Start the PPSAPI interface if it is there. Default to use
603ba371819SOllivier Robert 	 * the assert edge and do not enable the kernel hardpps.
604ba371819SOllivier Robert 	 */
605ba371819SOllivier Robert 	if (time_pps_create(fd, &up->handle) < 0) {
606ba371819SOllivier Robert 		up->handle = 0;
607ba371819SOllivier Robert 		msyslog(LOG_ERR, "refclock_ripencc: time_pps_create failed: %m");
608ba371819SOllivier Robert 		return (1);
609ba371819SOllivier Robert 	}
610ba371819SOllivier Robert 
6119c2daa00SOllivier Robert 	return(ripencc_ppsapi(peer, 0, 0));
612ba371819SOllivier Robert }
613ba371819SOllivier Robert 
614ba371819SOllivier Robert /*
615ba371819SOllivier Robert  * ripencc_control - fudge control
616ba371819SOllivier Robert  */
617ba371819SOllivier Robert static void
618ba371819SOllivier Robert ripencc_control(
619ba371819SOllivier Robert 	int unit,		/* unit (not used) */
6202b15cb3dSCy Schubert 	const struct refclockstat *in, /* input parameters (not used) */
621ba371819SOllivier Robert 	struct refclockstat *out, /* output parameters (not used) */
622ba371819SOllivier Robert 	struct peer *peer	/* peer structure pointer */
623ba371819SOllivier Robert 	)
624ba371819SOllivier Robert {
625ba371819SOllivier Robert 	struct refclockproc *pp;
626ba371819SOllivier Robert 
627ba371819SOllivier Robert #ifdef DEBUG_NCC
628ba371819SOllivier Robert 	msyslog(LOG_INFO,"%s()",__FUNCTION__);
629ba371819SOllivier Robert #endif /* DEBUG_NCC */
630ba371819SOllivier Robert 
631ba371819SOllivier Robert 	pp = peer->procptr;
632ba371819SOllivier Robert 	ripencc_ppsapi(peer, pp->sloppyclockflag & CLK_FLAG2,
633ba371819SOllivier Robert 		       pp->sloppyclockflag & CLK_FLAG3);
634ba371819SOllivier Robert }
635ba371819SOllivier Robert 
636ba371819SOllivier Robert 
637ba371819SOllivier Robert /*
638ba371819SOllivier Robert  * Initialize PPSAPI
639ba371819SOllivier Robert  */
640ba371819SOllivier Robert int
641ba371819SOllivier Robert ripencc_ppsapi(
642ba371819SOllivier Robert 	struct peer *peer,	/* peer structure pointer */
643ba371819SOllivier Robert 	int enb_clear,		/* clear enable */
644ba371819SOllivier Robert 	int enb_hardpps		/* hardpps enable */
645ba371819SOllivier Robert 	)
646ba371819SOllivier Robert {
647ba371819SOllivier Robert 	struct refclockproc *pp;
648ba371819SOllivier Robert 	struct ripencc_unit *up;
649ba371819SOllivier Robert 	int capability;
650ba371819SOllivier Robert 
651ba371819SOllivier Robert 	pp = peer->procptr;
6522b15cb3dSCy Schubert 	up = pp->unitptr;
653ba371819SOllivier Robert 	if (time_pps_getcap(up->handle, &capability) < 0) {
654ba371819SOllivier Robert 		msyslog(LOG_ERR,
655ba371819SOllivier Robert 			"refclock_ripencc: time_pps_getcap failed: %m");
656ba371819SOllivier Robert 		return (0);
657ba371819SOllivier Robert 	}
658ba371819SOllivier Robert 	memset(&up->pps_params, 0, sizeof(pps_params_t));
659ba371819SOllivier Robert 	if (enb_clear)
660ba371819SOllivier Robert 		up->pps_params.mode = capability & PPS_CAPTURECLEAR;
661ba371819SOllivier Robert 	else
662ba371819SOllivier Robert 		up->pps_params.mode = capability & PPS_CAPTUREASSERT;
663ba371819SOllivier Robert 	if (!up->pps_params.mode) {
664ba371819SOllivier Robert 		msyslog(LOG_ERR,
665ba371819SOllivier Robert 			"refclock_ripencc: invalid capture edge %d",
666ba371819SOllivier Robert 			!enb_clear);
667ba371819SOllivier Robert 		return (0);
668ba371819SOllivier Robert 	}
669ba371819SOllivier Robert 	up->pps_params.mode |= PPS_TSFMT_TSPEC;
670ba371819SOllivier Robert 	if (time_pps_setparams(up->handle, &up->pps_params) < 0) {
671ba371819SOllivier Robert 		msyslog(LOG_ERR,
672ba371819SOllivier Robert 			"refclock_ripencc: time_pps_setparams failed: %m");
673ba371819SOllivier Robert 		return (0);
674ba371819SOllivier Robert 	}
675ba371819SOllivier Robert 	if (enb_hardpps) {
676ba371819SOllivier Robert 		if (time_pps_kcbind(up->handle, PPS_KC_HARDPPS,
677ba371819SOllivier Robert 				    up->pps_params.mode & ~PPS_TSFMT_TSPEC,
678ba371819SOllivier Robert 				    PPS_TSFMT_TSPEC) < 0) {
679ba371819SOllivier Robert 			msyslog(LOG_ERR,
680ba371819SOllivier Robert 				"refclock_ripencc: time_pps_kcbind failed: %m");
681ba371819SOllivier Robert 			return (0);
682ba371819SOllivier Robert 		}
6832b15cb3dSCy Schubert 		hardpps_enable = 1;
684ba371819SOllivier Robert 	}
685ba371819SOllivier Robert 	peer->precision = PPS_PRECISION;
686ba371819SOllivier Robert 
687ba371819SOllivier Robert #if DEBUG_NCC
688ba371819SOllivier Robert 	if (debug) {
689ba371819SOllivier Robert 		time_pps_getparams(up->handle, &up->pps_params);
690ba371819SOllivier Robert 		printf(
691ba371819SOllivier Robert 			"refclock_ripencc: capability 0x%x version %d mode 0x%x kern %d\n",
692ba371819SOllivier Robert 			capability, up->pps_params.api_version,
693ba371819SOllivier Robert 			up->pps_params.mode, enb_hardpps);
694ba371819SOllivier Robert 	}
695ba371819SOllivier Robert #endif /* DEBUG_NCC */
696ba371819SOllivier Robert 
697ba371819SOllivier Robert 	return (1);
698ba371819SOllivier Robert }
699ba371819SOllivier Robert 
700ba371819SOllivier Robert /*
701ba371819SOllivier Robert  * This function is called every 64 seconds from ripencc_receive
702ba371819SOllivier Robert  * It will fetch the pps time
703ba371819SOllivier Robert  *
704ba371819SOllivier Robert  * Return 0 on failure and 1 on success.
705ba371819SOllivier Robert  */
706ba371819SOllivier Robert static int
707ba371819SOllivier Robert ripencc_get_pps_ts(
708ba371819SOllivier Robert 	struct ripencc_unit *up,
709ba371819SOllivier Robert 	l_fp *tsptr
710ba371819SOllivier Robert 	)
711ba371819SOllivier Robert {
712ba371819SOllivier Robert 	pps_info_t pps_info;
713ba371819SOllivier Robert 	struct timespec timeout, ts;
714ba371819SOllivier Robert 	double dtemp;
715ba371819SOllivier Robert 	l_fp tstmp;
716ba371819SOllivier Robert 
717ba371819SOllivier Robert #ifdef DEBUG_PPS
7182b15cb3dSCy Schubert 	msyslog(LOG_INFO,"ripencc_get_pps_ts");
719ba371819SOllivier Robert #endif /* DEBUG_PPS */
720ba371819SOllivier Robert 
721ba371819SOllivier Robert 
722ba371819SOllivier Robert 	/*
723ba371819SOllivier Robert 	 * Convert the timespec nanoseconds field to ntp l_fp units.
724ba371819SOllivier Robert 	 */
725ba371819SOllivier Robert 	if (up->handle == 0)
726ba371819SOllivier Robert 		return (0);
727ba371819SOllivier Robert 	timeout.tv_sec = 0;
728ba371819SOllivier Robert 	timeout.tv_nsec = 0;
729ba371819SOllivier Robert 	memcpy(&pps_info, &up->pps_info, sizeof(pps_info_t));
730ba371819SOllivier Robert 	if (time_pps_fetch(up->handle, PPS_TSFMT_TSPEC, &up->pps_info,
731ba371819SOllivier Robert 			   &timeout) < 0)
732ba371819SOllivier Robert 		return (0);
733ba371819SOllivier Robert 	if (up->pps_params.mode & PPS_CAPTUREASSERT) {
734ba371819SOllivier Robert 		if (pps_info.assert_sequence ==
735ba371819SOllivier Robert 		    up->pps_info.assert_sequence)
736ba371819SOllivier Robert 			return (0);
737ba371819SOllivier Robert 		ts = up->pps_info.assert_timestamp;
738ba371819SOllivier Robert 	} else if (up->pps_params.mode & PPS_CAPTURECLEAR) {
739ba371819SOllivier Robert 		if (pps_info.clear_sequence ==
740ba371819SOllivier Robert 		    up->pps_info.clear_sequence)
741ba371819SOllivier Robert 			return (0);
742ba371819SOllivier Robert 		ts = up->pps_info.clear_timestamp;
743ba371819SOllivier Robert 	} else {
744ba371819SOllivier Robert 		return (0);
745ba371819SOllivier Robert 	}
746ba371819SOllivier Robert 	if ((up->ts.tv_sec == ts.tv_sec) && (up->ts.tv_nsec == ts.tv_nsec))
747ba371819SOllivier Robert 		return (0);
748ba371819SOllivier Robert 	up->ts = ts;
749ba371819SOllivier Robert 
750ba371819SOllivier Robert 	tstmp.l_ui = ts.tv_sec + JAN_1970;
751ba371819SOllivier Robert 	dtemp = ts.tv_nsec * FRAC / 1e9;
752ba371819SOllivier Robert 	tstmp.l_uf = (u_int32)dtemp;
753ba371819SOllivier Robert 
754ba371819SOllivier Robert #ifdef DEBUG_PPS
7552b15cb3dSCy Schubert 	msyslog(LOG_INFO,"ts.tv_sec: %d",(int)ts.tv_sec);
7562b15cb3dSCy Schubert 	msyslog(LOG_INFO,"ts.tv_nsec: %ld",ts.tv_nsec);
757ba371819SOllivier Robert #endif /* DEBUG_PPS */
758ba371819SOllivier Robert 
759ba371819SOllivier Robert 	*tsptr = tstmp;
760ba371819SOllivier Robert 	return (1);
761ba371819SOllivier Robert }
762ba371819SOllivier Robert 
763ba371819SOllivier Robert /*
764ba371819SOllivier Robert  * ripencc_shutdown - shut down a GPS clock
765ba371819SOllivier Robert  */
766ba371819SOllivier Robert static void
767ba371819SOllivier Robert ripencc_shutdown(int unit, struct peer *peer)
768ba371819SOllivier Robert {
769ba371819SOllivier Robert 	register struct ripencc_unit *up;
770ba371819SOllivier Robert 	struct refclockproc *pp;
771ba371819SOllivier Robert 
772ba371819SOllivier Robert 	pp = peer->procptr;
7732b15cb3dSCy Schubert 	up = pp->unitptr;
774ba371819SOllivier Robert 
7752b15cb3dSCy Schubert 	if (up != NULL) {
776ba371819SOllivier Robert 		if (up->handle != 0)
777ba371819SOllivier Robert 			time_pps_destroy(up->handle);
7782b15cb3dSCy Schubert 		free(up);
7792b15cb3dSCy Schubert 	}
7802b15cb3dSCy Schubert 	if (-1 != pp->io.fd)
781ba371819SOllivier Robert 		io_closeclock(&pp->io);
782ba371819SOllivier Robert 
7832b15cb3dSCy Schubert 	return;
784ba371819SOllivier Robert }
785ba371819SOllivier Robert 
786ba371819SOllivier Robert /*
787ba371819SOllivier Robert  * ripencc_poll - called by the transmit procedure
788ba371819SOllivier Robert  */
789ba371819SOllivier Robert static void
790ba371819SOllivier Robert ripencc_poll(int unit, struct peer *peer)
791ba371819SOllivier Robert {
792ba371819SOllivier Robert 	register struct ripencc_unit *up;
793ba371819SOllivier Robert 	struct refclockproc *pp;
794ba371819SOllivier Robert 	TSIPPKT spt;
795ba371819SOllivier Robert 
796ba371819SOllivier Robert #ifdef DEBUG_NCC
797ba371819SOllivier Robert 	if (debug)
798ba371819SOllivier Robert 		fprintf(stderr, "ripencc_poll(%d)\n", unit);
799ba371819SOllivier Robert #endif /* DEBUG_NCC */
800ba371819SOllivier Robert 	pp = peer->procptr;
8012b15cb3dSCy Schubert 	up = pp->unitptr;
802ba371819SOllivier Robert 	if (up->pollcnt == 0)
803ba371819SOllivier Robert 		refclock_report(peer, CEVNT_TIMEOUT);
804ba371819SOllivier Robert 	else
805ba371819SOllivier Robert 		up->pollcnt--;
806ba371819SOllivier Robert 
807ba371819SOllivier Robert 	pp->polls++;
808ba371819SOllivier Robert 	up->polled = 1;
809ba371819SOllivier Robert 
810ba371819SOllivier Robert 	/* poll for UTC superpacket */
811ba371819SOllivier Robert 	cmd_0x8EADq (&spt);
812ba371819SOllivier Robert 	ripencc_send(peer,spt);
813ba371819SOllivier Robert }
814ba371819SOllivier Robert 
815ba371819SOllivier Robert /*
816ba371819SOllivier Robert  * ripencc_send - send message to clock
817ba371819SOllivier Robert  * use the structures being created by the trimble functions!
818ba371819SOllivier Robert  * makes the code more readable/clean
819ba371819SOllivier Robert  */
820ba371819SOllivier Robert static void
821ba371819SOllivier Robert ripencc_send(struct peer *peer, TSIPPKT spt)
822ba371819SOllivier Robert {
823ba371819SOllivier Robert 	unsigned char *ip, *op;
824ba371819SOllivier Robert 	unsigned char obuf[512];
825ba371819SOllivier Robert 
826ba371819SOllivier Robert #ifdef DEBUG_RAW
827ba371819SOllivier Robert 	{
828ba371819SOllivier Robert 		register struct ripencc_unit *up;
829ba371819SOllivier Robert 		register struct refclockproc *pp;
830ba371819SOllivier Robert 
831ba371819SOllivier Robert 		pp = peer->procptr;
8322b15cb3dSCy Schubert 		up = pp->unitptr;
833ba371819SOllivier Robert 		if (debug)
834ba371819SOllivier Robert 			printf("ripencc_send(%d, %02X)\n", up->unit, cmd);
835ba371819SOllivier Robert 	}
836ba371819SOllivier Robert #endif /* DEBUG_RAW */
837ba371819SOllivier Robert 
838ba371819SOllivier Robert 	ip = spt.buf;
839ba371819SOllivier Robert 	op = obuf;
840ba371819SOllivier Robert 
841ba371819SOllivier Robert 	*op++ = 0x10;
842ba371819SOllivier Robert 	*op++ = spt.code;
843ba371819SOllivier Robert 
844ba371819SOllivier Robert 	while (spt.len--) {
845ba371819SOllivier Robert 		if (op-obuf > sizeof(obuf)-5) {
846ba371819SOllivier Robert 			msyslog(LOG_ERR, "ripencc_send obuf overflow!");
847ba371819SOllivier Robert 			refclock_report(peer, CEVNT_FAULT);
848ba371819SOllivier Robert 			return;
849ba371819SOllivier Robert 		}
850ba371819SOllivier Robert 
851ba371819SOllivier Robert 		if (*ip == 0x10) /* byte stuffing */
852ba371819SOllivier Robert 			*op++ = 0x10;
853ba371819SOllivier Robert 		*op++ = *ip++;
854ba371819SOllivier Robert 	}
855ba371819SOllivier Robert 
856ba371819SOllivier Robert 	*op++ = 0x10;
857ba371819SOllivier Robert 	*op++ = 0x03;
858ba371819SOllivier Robert 
859ba371819SOllivier Robert #ifdef DEBUG_RAW
860ba371819SOllivier Robert 	if (debug) { /* print raw packet */
861ba371819SOllivier Robert 		unsigned char *cp;
862ba371819SOllivier Robert 		int i;
863ba371819SOllivier Robert 
864ba371819SOllivier Robert 		printf("ripencc_send: len %d\n", op-obuf);
865ba371819SOllivier Robert 		for (i=1, cp=obuf; cp<op; i++, cp++) {
866ba371819SOllivier Robert 			printf(" %02X", *cp);
867ba371819SOllivier Robert 			if (i%10 == 0)
868ba371819SOllivier Robert 				printf("\n");
869ba371819SOllivier Robert 		}
870ba371819SOllivier Robert 		printf("\n");
871ba371819SOllivier Robert 	}
872ba371819SOllivier Robert #endif /* DEBUG_RAW */
873ba371819SOllivier Robert 
874ba371819SOllivier Robert 	if (write(peer->procptr->io.fd, obuf, op-obuf) == -1) {
875ba371819SOllivier Robert 		refclock_report(peer, CEVNT_FAULT);
876ba371819SOllivier Robert 	}
877ba371819SOllivier Robert }
878ba371819SOllivier Robert 
879ba371819SOllivier Robert /*
880ba371819SOllivier Robert  * ripencc_receive()
881ba371819SOllivier Robert  *
882ba371819SOllivier Robert  * called when a packet is received on the serial port
883ba371819SOllivier Robert  * takes care of further processing
884ba371819SOllivier Robert  *
885ba371819SOllivier Robert  */
886ba371819SOllivier Robert static void
887ba371819SOllivier Robert ripencc_receive(struct recvbuf *rbufp)
888ba371819SOllivier Robert {
889ba371819SOllivier Robert 	register struct ripencc_unit *up;
890ba371819SOllivier Robert 	register struct refclockproc *pp;
891ba371819SOllivier Robert 	struct peer *peer;
8922b15cb3dSCy Schubert 	static TSIPPKT rpt;	/* for current incoming TSIP report */
893ba371819SOllivier Robert 	TSIPPKT spt;		/* send packet */
894ba371819SOllivier Robert 	int ns_since_pps;
895ba371819SOllivier Robert 	int i;
896ba371819SOllivier Robert 	char *cp;
8972b15cb3dSCy Schubert 	/* these variables hold data until we decide it's worth keeping */
898ba371819SOllivier Robert 	char    rd_lastcode[BMAX];
899ba371819SOllivier Robert 	l_fp    rd_tmp;
900ba371819SOllivier Robert 	u_short rd_lencode;
901ba371819SOllivier Robert 
902ba371819SOllivier Robert 	/* msyslog(LOG_INFO, "%s",__FUNCTION__); */
903ba371819SOllivier Robert 
904ba371819SOllivier Robert 	/*
905ba371819SOllivier Robert 	 * Initialize pointers and read the timecode and timestamp
906ba371819SOllivier Robert 	 */
9072b15cb3dSCy Schubert 	peer = rbufp->recv_peer;
908ba371819SOllivier Robert 	pp = peer->procptr;
9092b15cb3dSCy Schubert 	up = pp->unitptr;
910ba371819SOllivier Robert 	rd_lencode = refclock_gtlin(rbufp, rd_lastcode, BMAX, &rd_tmp);
911ba371819SOllivier Robert 
912ba371819SOllivier Robert #ifdef DEBUG_RAW
913ba371819SOllivier Robert 	if (debug)
914ba371819SOllivier Robert 		fprintf(stderr, "ripencc_receive(%d)\n", up->unit);
915ba371819SOllivier Robert #endif /* DEBUG_RAW */
916ba371819SOllivier Robert 
917ba371819SOllivier Robert #ifdef DEBUG_RAW
918ba371819SOllivier Robert 	if (debug) {		/* print raw packet */
919ba371819SOllivier Robert 		int i;
920ba371819SOllivier Robert 		unsigned char *cp;
921ba371819SOllivier Robert 
922ba371819SOllivier Robert 		printf("ripencc_receive: len %d\n", rbufp->recv_length);
9232b15cb3dSCy Schubert 		for (i=1, cp=(char*)&rbufp->recv_space;
9242b15cb3dSCy Schubert 		     i <= rbufp->recv_length;
9252b15cb3dSCy Schubert 		     i++, cp++) {
926ba371819SOllivier Robert 			printf(" %02X", *cp);
927ba371819SOllivier Robert 			if (i%10 == 0)
928ba371819SOllivier Robert 				printf("\n");
929ba371819SOllivier Robert 		}
930ba371819SOllivier Robert 		printf("\n");
931ba371819SOllivier Robert 	}
932ba371819SOllivier Robert #endif /* DEBUG_RAW */
933ba371819SOllivier Robert 
934ba371819SOllivier Robert 	cp = (char*) &rbufp->recv_space;
935ba371819SOllivier Robert 	i=rbufp->recv_length;
936ba371819SOllivier Robert 
937ba371819SOllivier Robert 	while (i--) {		/* loop over received chars */
938ba371819SOllivier Robert 
939ba371819SOllivier Robert 		tsip_input_proc(&rpt, (unsigned char) *cp++);
940ba371819SOllivier Robert 
941ba371819SOllivier Robert 		if (rpt.status != TSIP_PARSED_FULL)
942ba371819SOllivier Robert 			continue;
943ba371819SOllivier Robert 
944ba371819SOllivier Robert 		switch (rpt.code) {
945ba371819SOllivier Robert 
946ba371819SOllivier Robert 		    case 0x8F:	/* superpacket */
947ba371819SOllivier Robert 
948ba371819SOllivier Robert 			switch (rpt.buf[0]) {
949ba371819SOllivier Robert 
950ba371819SOllivier Robert 			    case 0xAD:	/* UTC Time */
951ba371819SOllivier Robert 				/*
9522b15cb3dSCy Schubert 				** When polling on port B the timecode is
9532b15cb3dSCy Schubert 				** the time of the previous PPS.  If we
9542b15cb3dSCy Schubert 				** completed receiving the packet less than
9552b15cb3dSCy Schubert 				** 150ms after the turn of the second, it
9562b15cb3dSCy Schubert 				** may have the code of the previous second.
9572b15cb3dSCy Schubert 				** We do not trust that and simply poll
9582b15cb3dSCy Schubert 				** again without even parsing it.
9592b15cb3dSCy Schubert 				**
9602b15cb3dSCy Schubert 				** More elegant would be to re-schedule the
9612b15cb3dSCy Schubert 				** poll, but I do not know (yet) how to do
9622b15cb3dSCy Schubert 				** that cleanly.
9632b15cb3dSCy Schubert 				**
964ba371819SOllivier Robert 				*/
965ba371819SOllivier Robert 				/* BLA ns_since_pps = ncc_tstmp(rbufp, &trtmp); */
966ba371819SOllivier Robert /*   if (up->polled && ns_since_pps > -1 && ns_since_pps < 150) { */
967ba371819SOllivier Robert 
968ba371819SOllivier Robert 				ns_since_pps = 200;
969ba371819SOllivier Robert 				if (up->polled && ns_since_pps < 150) {
9702b15cb3dSCy Schubert 					msyslog(LOG_INFO, "%s(): up->polled",
9712b15cb3dSCy Schubert 						__FUNCTION__);
972ba371819SOllivier Robert 					ripencc_poll(up->unit, peer);
973ba371819SOllivier Robert 					break;
974ba371819SOllivier Robert 				}
975ba371819SOllivier Robert 
976ba371819SOllivier Robert 			        /*
977ba371819SOllivier Robert  				 * Parse primary utc time packet
978ba371819SOllivier Robert 				 * and fill refclock structure
979ba371819SOllivier Robert 				 * from results.
980ba371819SOllivier Robert 				 */
981ba371819SOllivier Robert 				if (parse0x8FAD(&rpt, peer) < 0) {
982ba371819SOllivier Robert 					msyslog(LOG_INFO, "%s(): parse0x8FAD < 0",__FUNCTION__);
983ba371819SOllivier Robert 					refclock_report(peer, CEVNT_BADREPLY);
984ba371819SOllivier Robert 					break;
985ba371819SOllivier Robert 				}
986ba371819SOllivier Robert 				/*
987ba371819SOllivier Robert 				 * If the PPSAPI is working, rather use its
988ba371819SOllivier Robert 				 * timestamps.
989ba371819SOllivier Robert 				 * assume that the PPS occurs on the second
990ba371819SOllivier Robert 				 * so blow any msec
991ba371819SOllivier Robert 				 */
992ba371819SOllivier Robert 				if (ripencc_get_pps_ts(up, &rd_tmp) == 1) {
993ba371819SOllivier Robert 					pp->lastrec = up->tstamp = rd_tmp;
9949c2daa00SOllivier Robert 					pp->nsec = 0;
995ba371819SOllivier Robert 				}
996ba371819SOllivier Robert 				else
9972b15cb3dSCy Schubert 					msyslog(LOG_INFO, "%s(): ripencc_get_pps_ts returns failure",__FUNCTION__);
998ba371819SOllivier Robert 
999ba371819SOllivier Robert 
1000ba371819SOllivier Robert 				if (!up->polled) {
10012b15cb3dSCy Schubert 					msyslog(LOG_INFO, "%s(): unrequested packet",__FUNCTION__);
1002ba371819SOllivier Robert 					/* unrequested packet */
1003ba371819SOllivier Robert 					break;
1004ba371819SOllivier Robert 				}
1005ba371819SOllivier Robert 
1006ba371819SOllivier Robert 				/* we have been polled ! */
1007ba371819SOllivier Robert 				up->polled = 0;
1008ba371819SOllivier Robert 				up->pollcnt = 2;
1009ba371819SOllivier Robert 
1010ba371819SOllivier Robert 				/* poll for next packet */
1011ba371819SOllivier Robert 				cmd_0x8E0Bq(&spt);
1012ba371819SOllivier Robert 				ripencc_send(peer,spt);
1013ba371819SOllivier Robert 
1014ba371819SOllivier Robert 				if (ns_since_pps < 0) { /* no PPS */
1015ba371819SOllivier Robert 					msyslog(LOG_INFO, "%s(): ns_since_pps < 0",__FUNCTION__);
1016ba371819SOllivier Robert 					refclock_report(peer, CEVNT_BADTIME);
1017ba371819SOllivier Robert 					break;
1018ba371819SOllivier Robert 				}
1019ba371819SOllivier Robert 
1020ba371819SOllivier Robert 				/*
10212b15cb3dSCy Schubert 				** Process the new sample in the median
10222b15cb3dSCy Schubert 				** filter and determine the reference clock
10232b15cb3dSCy Schubert 				** offset and dispersion.
1024ba371819SOllivier Robert 				*/
1025ba371819SOllivier Robert 				if (!refclock_process(pp)) {
1026ba371819SOllivier Robert 					msyslog(LOG_INFO, "%s(): !refclock_process",__FUNCTION__);
1027ba371819SOllivier Robert 					refclock_report(peer, CEVNT_BADTIME);
1028ba371819SOllivier Robert 					break;
1029ba371819SOllivier Robert 				}
1030ba371819SOllivier Robert 
1031ba371819SOllivier Robert 				refclock_receive(peer);
1032ba371819SOllivier Robert 				break;
1033ba371819SOllivier Robert 
1034ba371819SOllivier Robert 			    case 0x0B: /* comprehensive time packet */
1035ba371819SOllivier Robert 				parse0x8F0B(&rpt, peer);
1036ba371819SOllivier Robert 				break;
1037ba371819SOllivier Robert 
1038ba371819SOllivier Robert 			    default: /* other superpackets */
1039ba371819SOllivier Robert #ifdef DEBUG_NCC
10402b15cb3dSCy Schubert 				msyslog(LOG_INFO, "%s(): calling parseany",
10412b15cb3dSCy Schubert 					__FUNCTION__);
1042ba371819SOllivier Robert #endif /* DEBUG_NCC */
1043ba371819SOllivier Robert #ifdef TRIMBLE_OUTPUT_FUNC
1044ba371819SOllivier Robert 				parseany(&rpt, peer);
1045ba371819SOllivier Robert #endif /* TRIMBLE_OUTPUT_FUNC */
1046ba371819SOllivier Robert 				break;
1047ba371819SOllivier Robert 			}
1048ba371819SOllivier Robert 			break;
1049ba371819SOllivier Robert 
1050ba371819SOllivier Robert 		    case 0x4F:	/* UTC parameters, for leap info */
1051ba371819SOllivier Robert 			parse0x4F(&rpt, peer);
1052ba371819SOllivier Robert 			break;
1053ba371819SOllivier Robert 
1054ba371819SOllivier Robert 		    case 0x5C:	/* sat tracking data */
1055ba371819SOllivier Robert 			parse0x5C(&rpt, peer);
1056ba371819SOllivier Robert 			break;
1057ba371819SOllivier Robert 
1058ba371819SOllivier Robert 		    default:	/* other packets */
1059ba371819SOllivier Robert #ifdef TRIMBLE_OUTPUT_FUNC
1060ba371819SOllivier Robert 			parseany(&rpt, peer);
1061ba371819SOllivier Robert #endif /* TRIMBLE_OUTPUT_FUNC */
1062ba371819SOllivier Robert 			break;
1063ba371819SOllivier Robert 		}
1064ba371819SOllivier Robert    		rpt.status = TSIP_PARSED_EMPTY;
1065ba371819SOllivier Robert 	}
1066ba371819SOllivier Robert }
1067ba371819SOllivier Robert 
1068ba371819SOllivier Robert /*
1069ba371819SOllivier Robert  * All trimble functions that are directly referenced from driver code
1070ba371819SOllivier Robert  * (so not from parseany)
1071ba371819SOllivier Robert  */
1072ba371819SOllivier Robert 
1073ba371819SOllivier Robert /* request software versions */
10742b15cb3dSCy Schubert void
10752b15cb3dSCy Schubert cmd_0x1F(
10762b15cb3dSCy Schubert 	 TSIPPKT *cmd
10772b15cb3dSCy Schubert 	 )
1078ba371819SOllivier Robert {
1079ba371819SOllivier Robert 	cmd->len = 0;
1080ba371819SOllivier Robert 	cmd->code = 0x1F;
1081ba371819SOllivier Robert }
1082ba371819SOllivier Robert 
1083ba371819SOllivier Robert /* request receiver health */
10842b15cb3dSCy Schubert void
10852b15cb3dSCy Schubert cmd_0x26(
10862b15cb3dSCy Schubert 	 TSIPPKT *cmd
10872b15cb3dSCy Schubert 	 )
1088ba371819SOllivier Robert {
1089ba371819SOllivier Robert 	cmd->len = 0;
1090ba371819SOllivier Robert 	cmd->code = 0x26;
1091ba371819SOllivier Robert }
1092ba371819SOllivier Robert 
1093ba371819SOllivier Robert /* request UTC params */
10942b15cb3dSCy Schubert void
10952b15cb3dSCy Schubert cmd_0x2F(
10962b15cb3dSCy Schubert 	 TSIPPKT *cmd
10972b15cb3dSCy Schubert 	 )
1098ba371819SOllivier Robert {
1099ba371819SOllivier Robert 	cmd->len = 0;
1100ba371819SOllivier Robert 	cmd->code = 0x2F;
1101ba371819SOllivier Robert }
1102ba371819SOllivier Robert 
1103ba371819SOllivier Robert /* set serial I/O options */
11042b15cb3dSCy Schubert void
11052b15cb3dSCy Schubert cmd_0x35s(
11062b15cb3dSCy Schubert 	 TSIPPKT *cmd,
11072b15cb3dSCy Schubert 	 unsigned char pos_code,
11082b15cb3dSCy Schubert 	 unsigned char vel_code,
11092b15cb3dSCy Schubert 	 unsigned char time_code,
11102b15cb3dSCy Schubert 	 unsigned char opts_code
11112b15cb3dSCy Schubert 	 )
1112ba371819SOllivier Robert {
1113ba371819SOllivier Robert 	cmd->buf[0] = pos_code;
1114ba371819SOllivier Robert 	cmd->buf[1] = vel_code;
1115ba371819SOllivier Robert 	cmd->buf[2] = time_code;
1116ba371819SOllivier Robert 	cmd->buf[3] = opts_code;
1117ba371819SOllivier Robert 	cmd->len = 4;
1118ba371819SOllivier Robert 	cmd->code = 0x35;
1119ba371819SOllivier Robert }
11202b15cb3dSCy Schubert 
1121ba371819SOllivier Robert /* request tracking status */
11222b15cb3dSCy Schubert void
11232b15cb3dSCy Schubert cmd_0x3C(
11242b15cb3dSCy Schubert 	 TSIPPKT *cmd,
11252b15cb3dSCy Schubert 	 unsigned char sv_prn
11262b15cb3dSCy Schubert 	 )
1127ba371819SOllivier Robert {
1128ba371819SOllivier Robert 	cmd->buf[0] = sv_prn;
1129ba371819SOllivier Robert 	cmd->len = 1;
1130ba371819SOllivier Robert 	cmd->code = 0x3C;
1131ba371819SOllivier Robert }
1132ba371819SOllivier Robert 
1133ba371819SOllivier Robert /* set Channel A configuration for dual-port operation */
11342b15cb3dSCy Schubert void
11352b15cb3dSCy Schubert cmd_0x3Ds(
11362b15cb3dSCy Schubert 	  TSIPPKT *cmd,
11372b15cb3dSCy Schubert 	  unsigned char baud_out,
11382b15cb3dSCy Schubert 	  unsigned char baud_inp,
11392b15cb3dSCy Schubert 	  unsigned char char_code,
11402b15cb3dSCy Schubert 	  unsigned char stopbitcode,
11412b15cb3dSCy Schubert 	  unsigned char output_mode,
11422b15cb3dSCy Schubert 	  unsigned char input_mode
11432b15cb3dSCy Schubert 	  )
1144ba371819SOllivier Robert {
1145ba371819SOllivier Robert 	cmd->buf[0] = baud_out;		/* XMT baud rate */
1146ba371819SOllivier Robert 	cmd->buf[1] = baud_inp;		/* RCV baud rate */
1147ba371819SOllivier Robert 	cmd->buf[2] = char_code;	/* parity and #bits per byte */
1148ba371819SOllivier Robert 	cmd->buf[3] = stopbitcode;	/* number of stop bits code */
1149ba371819SOllivier Robert 	cmd->buf[4] = output_mode;	/* Ch. A transmission mode */
1150ba371819SOllivier Robert 	cmd->buf[5] = input_mode;	/* Ch. A reception mode */
1151ba371819SOllivier Robert 	cmd->len = 6;
1152ba371819SOllivier Robert 	cmd->code = 0x3D;
1153ba371819SOllivier Robert }
1154ba371819SOllivier Robert 
1155ba371819SOllivier Robert 
1156ba371819SOllivier Robert /* query primary configuration */
11572b15cb3dSCy Schubert void
11582b15cb3dSCy Schubert cmd_0xBBq(
11592b15cb3dSCy Schubert 	  TSIPPKT *cmd,
11602b15cb3dSCy Schubert 	  unsigned char subcode
11612b15cb3dSCy Schubert 	  )
1162ba371819SOllivier Robert {
1163ba371819SOllivier Robert 	cmd->len = 1;
1164ba371819SOllivier Robert 	cmd->code = 0xBB;
1165ba371819SOllivier Robert 	cmd->buf[0] = subcode;
1166ba371819SOllivier Robert }
1167ba371819SOllivier Robert 
1168ba371819SOllivier Robert 
1169ba371819SOllivier Robert /**** Superpackets ****/
1170ba371819SOllivier Robert /* 8E-0B to query 8F-0B controls */
11712b15cb3dSCy Schubert void
11722b15cb3dSCy Schubert cmd_0x8E0Bq(
11732b15cb3dSCy Schubert 	    TSIPPKT *cmd
11742b15cb3dSCy Schubert 	    )
1175ba371819SOllivier Robert {
1176ba371819SOllivier Robert 	cmd->len = 1;
1177ba371819SOllivier Robert 	cmd->code = 0x8E;
1178ba371819SOllivier Robert 	cmd->buf[0] = 0x0B;
1179ba371819SOllivier Robert }
1180ba371819SOllivier Robert 
1181ba371819SOllivier Robert 
1182ba371819SOllivier Robert /* 8F-41 to query board serial number */
11832b15cb3dSCy Schubert void
11842b15cb3dSCy Schubert cmd_0x8E41q(
11852b15cb3dSCy Schubert 	    TSIPPKT *cmd
11862b15cb3dSCy Schubert 	    )
1187ba371819SOllivier Robert {
1188ba371819SOllivier Robert 	cmd->len = 1;
1189ba371819SOllivier Robert 	cmd->code = 0x8E;
1190ba371819SOllivier Robert 	cmd->buf[0] = 0x41;
1191ba371819SOllivier Robert }
1192ba371819SOllivier Robert 
1193ba371819SOllivier Robert 
1194ba371819SOllivier Robert /* 8F-42 to query product serial number */
11952b15cb3dSCy Schubert void
11962b15cb3dSCy Schubert cmd_0x8E42q(
11972b15cb3dSCy Schubert 	    TSIPPKT *cmd
11982b15cb3dSCy Schubert 	    )
1199ba371819SOllivier Robert {
1200ba371819SOllivier Robert 	cmd->len = 1;
1201ba371819SOllivier Robert 	cmd->code = 0x8E;
1202ba371819SOllivier Robert 	cmd->buf[0] = 0x42;
1203ba371819SOllivier Robert }
12042b15cb3dSCy Schubert 
12052b15cb3dSCy Schubert 
1206ba371819SOllivier Robert /* 8F-4A to query PPS parameters */
12072b15cb3dSCy Schubert void
12082b15cb3dSCy Schubert cmd_0x8E4Aq(
12092b15cb3dSCy Schubert 	    TSIPPKT *cmd
12102b15cb3dSCy Schubert 	    )
1211ba371819SOllivier Robert {
1212ba371819SOllivier Robert 	cmd->len = 1;
1213ba371819SOllivier Robert 	cmd->code = 0x8E;
1214ba371819SOllivier Robert 	cmd->buf[0] = 0x4A;
1215ba371819SOllivier Robert }
1216ba371819SOllivier Robert 
1217ba371819SOllivier Robert 
1218ba371819SOllivier Robert /* set i/o options */
12192b15cb3dSCy Schubert void
12202b15cb3dSCy Schubert cmd_0x8E4As(
12212b15cb3dSCy Schubert 	    TSIPPKT *cmd,
1222ba371819SOllivier Robert 	    unsigned char PPSOnOff,
1223ba371819SOllivier Robert 	    unsigned char TimeBase,
1224ba371819SOllivier Robert 	    unsigned char Polarity,
1225ba371819SOllivier Robert 	    double PPSOffset,
12262b15cb3dSCy Schubert 	    float Uncertainty
12272b15cb3dSCy Schubert 	    )
1228ba371819SOllivier Robert {
1229ba371819SOllivier Robert 	cmd->len = 16;
1230ba371819SOllivier Robert 	cmd->code = 0x8E;
1231ba371819SOllivier Robert 	cmd->buf[0] = 0x4A;
1232ba371819SOllivier Robert 	cmd->buf[1] = PPSOnOff;
1233ba371819SOllivier Robert 	cmd->buf[2] = TimeBase;
1234ba371819SOllivier Robert 	cmd->buf[3] = Polarity;
1235ba371819SOllivier Robert 	bPutDouble (&PPSOffset, &cmd->buf[4]);
1236ba371819SOllivier Robert 	bPutFloat (&Uncertainty, &cmd->buf[12]);
1237ba371819SOllivier Robert }
12382b15cb3dSCy Schubert 
1239ba371819SOllivier Robert /* 8F-4B query survey limit */
12402b15cb3dSCy Schubert void
12412b15cb3dSCy Schubert cmd_0x8E4Bq(
12422b15cb3dSCy Schubert 	    TSIPPKT *cmd
12432b15cb3dSCy Schubert 	    )
1244ba371819SOllivier Robert {
1245ba371819SOllivier Robert 	cmd->len = 1;
1246ba371819SOllivier Robert 	cmd->code = 0x8E;
1247ba371819SOllivier Robert 	cmd->buf[0] = 0x4B;
1248ba371819SOllivier Robert }
1249ba371819SOllivier Robert 
1250ba371819SOllivier Robert /* poll for UTC superpacket */
1251ba371819SOllivier Robert /* 8E-AD to query 8F-AD controls */
12522b15cb3dSCy Schubert void
12532b15cb3dSCy Schubert cmd_0x8EADq(
12542b15cb3dSCy Schubert 	    TSIPPKT *cmd
12552b15cb3dSCy Schubert 	    )
1256ba371819SOllivier Robert {
1257ba371819SOllivier Robert 	cmd->len = 1;
1258ba371819SOllivier Robert 	cmd->code = 0x8E;
1259ba371819SOllivier Robert 	cmd->buf[0] = 0xAD;
1260ba371819SOllivier Robert }
1261ba371819SOllivier Robert 
1262ba371819SOllivier Robert /* all outomatic packet output off */
12632b15cb3dSCy Schubert void
12642b15cb3dSCy Schubert cmd_0x8E4Ds(
12652b15cb3dSCy Schubert 	    TSIPPKT *cmd,
12662b15cb3dSCy Schubert 	    unsigned long AutoOutputMask
12672b15cb3dSCy Schubert 	    )
1268ba371819SOllivier Robert {
1269ba371819SOllivier Robert 	cmd->len = 5;
1270ba371819SOllivier Robert 	cmd->code = 0x8E;
1271ba371819SOllivier Robert 	cmd->buf[0] = 0x4D;
1272ba371819SOllivier Robert 	bPutULong (&AutoOutputMask, &cmd->buf[1]);
1273ba371819SOllivier Robert }
1274ba371819SOllivier Robert 
1275ba371819SOllivier Robert 
12762b15cb3dSCy Schubert /*
12772b15cb3dSCy Schubert  * for DOS machines, reverse order of bytes as they come through the
12782b15cb3dSCy Schubert  * serial port.
12792b15cb3dSCy Schubert  */
1280ba371819SOllivier Robert #ifdef BYTESWAP
12812b15cb3dSCy Schubert static short
12822b15cb3dSCy Schubert bGetShort(
12832b15cb3dSCy Schubert 	  unsigned char *bp
12842b15cb3dSCy Schubert 	  )
1285ba371819SOllivier Robert {
1286ba371819SOllivier Robert 	short outval;
1287ba371819SOllivier Robert 	unsigned char *optr;
1288ba371819SOllivier Robert 
1289ba371819SOllivier Robert 	optr = (unsigned char*)&outval + 1;
1290ba371819SOllivier Robert 	*optr-- = *bp++;
1291ba371819SOllivier Robert 	*optr = *bp;
1292ba371819SOllivier Robert 	return outval;
1293ba371819SOllivier Robert }
1294ba371819SOllivier Robert 
1295ba371819SOllivier Robert #ifdef TRIMBLE_OUTPUT_FUNC
12962b15cb3dSCy Schubert static unsigned short
12972b15cb3dSCy Schubert bGetUShort(
12982b15cb3dSCy Schubert 	   unsigned char *bp
12992b15cb3dSCy Schubert 	   )
1300ba371819SOllivier Robert {
1301ba371819SOllivier Robert 	unsigned short outval;
1302ba371819SOllivier Robert 	unsigned char *optr;
1303ba371819SOllivier Robert 
1304ba371819SOllivier Robert 	optr = (unsigned char*)&outval + 1;
1305ba371819SOllivier Robert 	*optr-- = *bp++;
1306ba371819SOllivier Robert 	*optr = *bp;
1307ba371819SOllivier Robert 	return outval;
1308ba371819SOllivier Robert }
1309ba371819SOllivier Robert 
13102b15cb3dSCy Schubert static long
13112b15cb3dSCy Schubert bGetLong(
13122b15cb3dSCy Schubert 	 unsigned char *bp
13132b15cb3dSCy Schubert 	 )
1314ba371819SOllivier Robert {
1315ba371819SOllivier Robert 	long outval;
1316ba371819SOllivier Robert 	unsigned char *optr;
1317ba371819SOllivier Robert 
1318ba371819SOllivier Robert 	optr = (unsigned char*)&outval + 3;
1319ba371819SOllivier Robert 	*optr-- = *bp++;
1320ba371819SOllivier Robert 	*optr-- = *bp++;
1321ba371819SOllivier Robert 	*optr-- = *bp++;
1322ba371819SOllivier Robert 	*optr = *bp;
1323ba371819SOllivier Robert 	return outval;
1324ba371819SOllivier Robert }
1325ba371819SOllivier Robert 
13262b15cb3dSCy Schubert static unsigned long
13272b15cb3dSCy Schubert bGetULong(
13282b15cb3dSCy Schubert 	  unsigned char *bp
13292b15cb3dSCy Schubert 	  )
1330ba371819SOllivier Robert {
1331ba371819SOllivier Robert 	unsigned long outval;
1332ba371819SOllivier Robert 	unsigned char *optr;
1333ba371819SOllivier Robert 
1334ba371819SOllivier Robert 	optr = (unsigned char*)&outval + 3;
1335ba371819SOllivier Robert 	*optr-- = *bp++;
1336ba371819SOllivier Robert 	*optr-- = *bp++;
1337ba371819SOllivier Robert 	*optr-- = *bp++;
1338ba371819SOllivier Robert 	*optr = *bp;
1339ba371819SOllivier Robert 	return outval;
1340ba371819SOllivier Robert }
1341ba371819SOllivier Robert #endif /* TRIMBLE_OUTPUT_FUNC */
1342ba371819SOllivier Robert 
13432b15cb3dSCy Schubert static float
13442b15cb3dSCy Schubert bGetSingle(
13452b15cb3dSCy Schubert 	   unsigned char *bp
13462b15cb3dSCy Schubert 	   )
1347ba371819SOllivier Robert {
1348ba371819SOllivier Robert 	float outval;
1349ba371819SOllivier Robert 	unsigned char *optr;
1350ba371819SOllivier Robert 
1351ba371819SOllivier Robert 	optr = (unsigned char*)&outval + 3;
1352ba371819SOllivier Robert 	*optr-- = *bp++;
1353ba371819SOllivier Robert 	*optr-- = *bp++;
1354ba371819SOllivier Robert 	*optr-- = *bp++;
1355ba371819SOllivier Robert 	*optr = *bp;
1356ba371819SOllivier Robert 	return outval;
1357ba371819SOllivier Robert }
1358ba371819SOllivier Robert 
13592b15cb3dSCy Schubert static double
13602b15cb3dSCy Schubert bGetDouble(
13612b15cb3dSCy Schubert 	   unsigned char *bp
13622b15cb3dSCy Schubert 	   )
1363ba371819SOllivier Robert {
1364ba371819SOllivier Robert 	double outval;
1365ba371819SOllivier Robert 	unsigned char *optr;
1366ba371819SOllivier Robert 
1367ba371819SOllivier Robert 	optr = (unsigned char*)&outval + 7;
1368ba371819SOllivier Robert 	*optr-- = *bp++;
1369ba371819SOllivier Robert 	*optr-- = *bp++;
1370ba371819SOllivier Robert 	*optr-- = *bp++;
1371ba371819SOllivier Robert 	*optr-- = *bp++;
1372ba371819SOllivier Robert 	*optr-- = *bp++;
1373ba371819SOllivier Robert 	*optr-- = *bp++;
1374ba371819SOllivier Robert 	*optr-- = *bp++;
1375ba371819SOllivier Robert 	*optr = *bp;
1376ba371819SOllivier Robert 	return outval;
1377ba371819SOllivier Robert }
1378ba371819SOllivier Robert 
1379ba371819SOllivier Robert #else /* not BYTESWAP */
1380ba371819SOllivier Robert 
1381ba371819SOllivier Robert #define bGetShort(bp) 	(*(short*)(bp))
1382ba371819SOllivier Robert #define bGetLong(bp) 	(*(long*)(bp))
1383ba371819SOllivier Robert #define bGetULong(bp) 	(*(unsigned long*)(bp))
1384ba371819SOllivier Robert #define bGetSingle(bp) 	(*(float*)(bp))
1385ba371819SOllivier Robert #define bGetDouble(bp)	(*(double*)(bp))
1386ba371819SOllivier Robert 
1387ba371819SOllivier Robert #endif /* BYTESWAP */
1388ba371819SOllivier Robert /*
1389ba371819SOllivier Robert  * Byte-reversal is necessary for little-endian (Intel-based) machines.
1390ba371819SOllivier Robert  * TSIP streams are Big-endian (Motorola-based).
1391ba371819SOllivier Robert  */
1392ba371819SOllivier Robert #ifdef BYTESWAP
1393ba371819SOllivier Robert 
1394ba371819SOllivier Robert void
13952b15cb3dSCy Schubert bPutFloat(
13962b15cb3dSCy Schubert 	  float *in,
13972b15cb3dSCy Schubert 	  unsigned char *out
13982b15cb3dSCy Schubert 	  )
1399ba371819SOllivier Robert {
1400ba371819SOllivier Robert 	unsigned char *inptr;
1401ba371819SOllivier Robert 
1402ba371819SOllivier Robert 	inptr = (unsigned char*)in + 3;
1403ba371819SOllivier Robert 	*out++ = *inptr--;
1404ba371819SOllivier Robert 	*out++ = *inptr--;
1405ba371819SOllivier Robert 	*out++ = *inptr--;
1406ba371819SOllivier Robert 	*out = *inptr;
1407ba371819SOllivier Robert }
1408ba371819SOllivier Robert 
1409ba371819SOllivier Robert static void
14102b15cb3dSCy Schubert bPutULong(
14112b15cb3dSCy Schubert 	  unsigned long *in,
14122b15cb3dSCy Schubert 	  unsigned char *out
14132b15cb3dSCy Schubert 	  )
1414ba371819SOllivier Robert {
1415ba371819SOllivier Robert 	unsigned char *inptr;
1416ba371819SOllivier Robert 
1417ba371819SOllivier Robert 	inptr = (unsigned char*)in + 3;
1418ba371819SOllivier Robert 	*out++ = *inptr--;
1419ba371819SOllivier Robert 	*out++ = *inptr--;
1420ba371819SOllivier Robert 	*out++ = *inptr--;
1421ba371819SOllivier Robert 	*out = *inptr;
1422ba371819SOllivier Robert }
1423ba371819SOllivier Robert 
1424ba371819SOllivier Robert static void
14252b15cb3dSCy Schubert bPutDouble(
14262b15cb3dSCy Schubert 	   double *in,
14272b15cb3dSCy Schubert 	   unsigned char *out
14282b15cb3dSCy Schubert 	   )
1429ba371819SOllivier Robert {
1430ba371819SOllivier Robert 	unsigned char *inptr;
1431ba371819SOllivier Robert 
1432ba371819SOllivier Robert 	inptr = (unsigned char*)in + 7;
1433ba371819SOllivier Robert 	*out++ = *inptr--;
1434ba371819SOllivier Robert 	*out++ = *inptr--;
1435ba371819SOllivier Robert 	*out++ = *inptr--;
1436ba371819SOllivier Robert 	*out++ = *inptr--;
1437ba371819SOllivier Robert 	*out++ = *inptr--;
1438ba371819SOllivier Robert 	*out++ = *inptr--;
1439ba371819SOllivier Robert 	*out++ = *inptr--;
1440ba371819SOllivier Robert 	*out = *inptr;
1441ba371819SOllivier Robert }
1442ba371819SOllivier Robert 
1443ba371819SOllivier Robert #else	/* not BYTESWAP */
1444ba371819SOllivier Robert 
1445ba371819SOllivier Robert void bPutShort (short a, unsigned char *cmdbuf) {*(short*) cmdbuf = a;}
1446ba371819SOllivier Robert void bPutULong (long a, unsigned char *cmdbuf) 	{*(long*) cmdbuf = a;}
1447ba371819SOllivier Robert void bPutFloat (float a, unsigned char *cmdbuf) {*(float*) cmdbuf = a;}
1448ba371819SOllivier Robert void bPutDouble (double a, unsigned char *cmdbuf){*(double*) cmdbuf = a;}
1449ba371819SOllivier Robert 
1450ba371819SOllivier Robert #endif /* BYTESWAP */
1451ba371819SOllivier Robert 
1452ba371819SOllivier Robert /*
1453ba371819SOllivier Robert  * Parse primary utc time packet
1454ba371819SOllivier Robert  * and fill refclock structure
1455ba371819SOllivier Robert  * from results.
1456ba371819SOllivier Robert  *
1457ba371819SOllivier Robert  * 0 = success
1458ba371819SOllivier Robert  * -1 = errors
1459ba371819SOllivier Robert  */
1460ba371819SOllivier Robert 
1461ba371819SOllivier Robert static int
14622b15cb3dSCy Schubert parse0x8FAD(
14632b15cb3dSCy Schubert 	    TSIPPKT *rpt,
14642b15cb3dSCy Schubert 	    struct peer *peer
14652b15cb3dSCy Schubert 	    )
1466ba371819SOllivier Robert {
1467ba371819SOllivier Robert 	register struct refclockproc *pp;
1468ba371819SOllivier Robert 	register struct ripencc_unit *up;
1469ba371819SOllivier Robert 
1470ba371819SOllivier Robert 	unsigned day, month, year;	/* data derived from received timecode */
1471ba371819SOllivier Robert 	unsigned hour, minute, second;
1472ba371819SOllivier Robert 	unsigned char trackstat, utcflags;
1473ba371819SOllivier Robert 
1474ba371819SOllivier Robert    	static char logbuf[1024];	/* logging string buffer */
1475ba371819SOllivier Robert 	int i;
1476ba371819SOllivier Robert 	unsigned char *buf;
1477ba371819SOllivier Robert 
1478ba371819SOllivier Robert 	buf = rpt->buf;
1479ba371819SOllivier Robert 	pp = peer->procptr;
1480ba371819SOllivier Robert 
1481ba371819SOllivier Robert 	if (rpt->len != 22)
1482ba371819SOllivier Robert 		return (-1);
1483ba371819SOllivier Robert 
1484ba371819SOllivier Robert 	if (bGetShort(&buf[1]) != 0) {
1485ba371819SOllivier Robert #ifdef DEBUG_NCC
1486ba371819SOllivier Robert 		if (debug)
1487ba371819SOllivier Robert 			printf("parse0x8FAD: event count != 0\n");
1488ba371819SOllivier Robert #endif /* DEBUG_NCC */
1489ba371819SOllivier Robert 		return(-1);
1490ba371819SOllivier Robert 	}
1491ba371819SOllivier Robert 
1492ba371819SOllivier Robert 	if (bGetDouble(&buf[3]) != 0.0) {
1493ba371819SOllivier Robert #ifdef DEBUG_NCC
1494ba371819SOllivier Robert 		if (debug)
1495ba371819SOllivier Robert 			printf("parse0x8FAD: fracsecs != 0\n");
1496ba371819SOllivier Robert #endif /* DEBUG_NCC */
1497ba371819SOllivier Robert 		return(-1);
1498ba371819SOllivier Robert 	}
1499ba371819SOllivier Robert 
1500ba371819SOllivier Robert 	hour =		(unsigned int) buf[11];
1501ba371819SOllivier Robert 	minute =	(unsigned int) buf[12];
1502ba371819SOllivier Robert 	second =	(unsigned int) buf[13];
1503ba371819SOllivier Robert 	day =		(unsigned int) buf[14];
1504ba371819SOllivier Robert 	month =		(unsigned int) buf[15];
1505ba371819SOllivier Robert 	year =		bGetShort(&buf[16]);
1506ba371819SOllivier Robert 	trackstat =	buf[18];
1507ba371819SOllivier Robert 	utcflags =	buf[19];
1508ba371819SOllivier Robert 
1509ba371819SOllivier Robert 
1510ba371819SOllivier Robert 	sprintf(logbuf, "U1 %d.%d.%d %02d:%02d:%02d %d %02x",
1511ba371819SOllivier Robert 		day, month, year, hour, minute, second, trackstat, utcflags);
1512ba371819SOllivier Robert 
1513ba371819SOllivier Robert #ifdef DEBUG_NCC
1514ba371819SOllivier Robert 	if (debug)
1515ba371819SOllivier Robert    		puts(logbuf);
1516ba371819SOllivier Robert #endif /* DEBUG_NCC */
1517ba371819SOllivier Robert 
1518ba371819SOllivier Robert 	record_clock_stats(&peer->srcadr, logbuf);
1519ba371819SOllivier Robert 
1520ba371819SOllivier Robert 	if (!utcflags & UTCF_UTC_AVAIL)
1521ba371819SOllivier Robert 		return(-1);
1522ba371819SOllivier Robert 
1523ba371819SOllivier Robert 	/* poll for UTC parameters once and then if UTC flag changed */
1524ba371819SOllivier Robert 	up = (struct ripencc_unit *) pp->unitptr;
1525ba371819SOllivier Robert 	if (utcflags != up->utcflags) {
1526ba371819SOllivier Robert 		TSIPPKT spt;	/* local structure for send packet */
1527ba371819SOllivier Robert 		cmd_0x2F (&spt); /* request UTC params */
1528ba371819SOllivier Robert 		ripencc_send(peer,spt);
1529ba371819SOllivier Robert 		up->utcflags = utcflags;
1530ba371819SOllivier Robert 	}
1531ba371819SOllivier Robert 
1532ba371819SOllivier Robert 	/*
1533ba371819SOllivier Robert 	 * If we hit the leap second, we choose to skip this sample
1534ba371819SOllivier Robert 	 * rather than rely on other code to be perfectly correct.
1535ba371819SOllivier Robert 	 * No offense, just defense ;-).
1536ba371819SOllivier Robert 	 */
1537ba371819SOllivier Robert 	if (second == 60)
1538ba371819SOllivier Robert 		return(-1);
1539ba371819SOllivier Robert 
1540ba371819SOllivier Robert 	/* now check and convert the time we received */
1541ba371819SOllivier Robert 
1542ba371819SOllivier Robert 	pp->year = year;
1543ba371819SOllivier Robert 	if (month < 1 || month > 12 || day < 1 || day > 31)
1544ba371819SOllivier Robert 		return(-1);
1545ba371819SOllivier Robert 
15462b15cb3dSCy Schubert 	if (pp->year % 4) {	/* XXX: use is_leapyear() ? */
1547ba371819SOllivier Robert 		if (day > day1tab[month - 1])
1548ba371819SOllivier Robert 			return(-1);
1549ba371819SOllivier Robert 		for (i = 0; i < month - 1; i++)
1550ba371819SOllivier Robert 			day += day1tab[i];
1551ba371819SOllivier Robert 	} else {
1552ba371819SOllivier Robert 		if (day > day2tab[month - 1])
1553ba371819SOllivier Robert 			return(-1);
1554ba371819SOllivier Robert 		for (i = 0; i < month - 1; i++)
1555ba371819SOllivier Robert 			day += day2tab[i];
1556ba371819SOllivier Robert 	}
1557ba371819SOllivier Robert 	pp->day = day;
1558ba371819SOllivier Robert 	pp->hour = hour;
1559ba371819SOllivier Robert 	pp->minute = minute;
1560ba371819SOllivier Robert 	pp-> second = second;
15619c2daa00SOllivier Robert 	pp->nsec = 0;
1562ba371819SOllivier Robert 
1563ba371819SOllivier Robert 	if ((utcflags&UTCF_LEAP_PNDG) && up->leapdelta != 0)
15642b15cb3dSCy Schubert 		pp-> leap = (up->leapdelta > 0)
15652b15cb3dSCy Schubert 		    ? LEAP_ADDSECOND
15662b15cb3dSCy Schubert 		    : LEAP_DELSECOND;
1567ba371819SOllivier Robert 	else
1568ba371819SOllivier Robert 		pp-> leap = LEAP_NOWARNING;
1569ba371819SOllivier Robert 
1570ba371819SOllivier Robert 	return (0);
1571ba371819SOllivier Robert }
1572ba371819SOllivier Robert 
1573ba371819SOllivier Robert /*
1574ba371819SOllivier Robert  * Parse comprehensive time packet
1575ba371819SOllivier Robert  *
1576ba371819SOllivier Robert  *  0 = success
1577ba371819SOllivier Robert  * -1 = errors
1578ba371819SOllivier Robert  */
1579ba371819SOllivier Robert 
15802b15cb3dSCy Schubert int
15812b15cb3dSCy Schubert parse0x8F0B(
15822b15cb3dSCy Schubert 	    TSIPPKT *rpt,
15832b15cb3dSCy Schubert 	    struct peer *peer
15842b15cb3dSCy Schubert 	    )
1585ba371819SOllivier Robert {
1586ba371819SOllivier Robert 	register struct refclockproc *pp;
1587ba371819SOllivier Robert 
1588ba371819SOllivier Robert 	unsigned day, month, year;	/* data derived from received timecode */
1589ba371819SOllivier Robert 	unsigned hour, minute, second;
1590ba371819SOllivier Robert 	unsigned utcoff;
1591ba371819SOllivier Robert 	unsigned char mode;
1592ba371819SOllivier Robert 	double  bias, rate;
1593ba371819SOllivier Robert 	float biasunc, rateunc;
1594ba371819SOllivier Robert 	double lat, lon, alt;
1595ba371819SOllivier Robert 	short lat_deg, lon_deg;
1596ba371819SOllivier Robert 	float lat_min, lon_min;
1597ba371819SOllivier Robert 	unsigned char north_south, east_west;
1598ba371819SOllivier Robert 	char sv[9];
1599ba371819SOllivier Robert 
1600ba371819SOllivier Robert    	static char logbuf[1024];	/* logging string buffer */
1601ba371819SOllivier Robert 	unsigned char b;
1602ba371819SOllivier Robert 	int i;
1603ba371819SOllivier Robert 	unsigned char *buf;
1604ba371819SOllivier Robert 	double tow;
1605ba371819SOllivier Robert 
1606ba371819SOllivier Robert 	buf = rpt->buf;
1607ba371819SOllivier Robert 	pp = peer->procptr;
1608ba371819SOllivier Robert 
1609ba371819SOllivier Robert 	if (rpt->len != 74)
1610ba371819SOllivier Robert 		return (-1);
1611ba371819SOllivier Robert 
1612ba371819SOllivier Robert 	if (bGetShort(&buf[1]) != 0)
1613ba371819SOllivier Robert 		return(-1);;
1614ba371819SOllivier Robert 
1615ba371819SOllivier Robert 	tow =  bGetDouble(&buf[3]);
1616ba371819SOllivier Robert 
1617ba371819SOllivier Robert 	if (tow == -1.0) {
1618ba371819SOllivier Robert 		return(-1);
1619ba371819SOllivier Robert 	}
1620ba371819SOllivier Robert 	else if ((tow >= 604800.0) || (tow < 0.0)) {
1621ba371819SOllivier Robert 		return(-1);
1622ba371819SOllivier Robert 	}
1623ba371819SOllivier Robert 	else
1624ba371819SOllivier Robert 	{
1625ba371819SOllivier Robert 		if (tow < 604799.9) tow = tow + .00000001;
1626ba371819SOllivier Robert 		second = (unsigned int) fmod(tow, 60.);
1627ba371819SOllivier Robert 		minute =  (unsigned int) fmod(tow/60., 60.);
1628ba371819SOllivier Robert 		hour = (unsigned int )fmod(tow / 3600., 24.);
1629ba371819SOllivier Robert 	}
1630ba371819SOllivier Robert 
1631ba371819SOllivier Robert 	day =		(unsigned int) buf[11];
1632ba371819SOllivier Robert 	month =		(unsigned int) buf[12];
1633ba371819SOllivier Robert 	year =		bGetShort(&buf[13]);
1634ba371819SOllivier Robert 	mode =		buf[15];
1635ba371819SOllivier Robert 	utcoff =	bGetShort(&buf[16]);
1636ba371819SOllivier Robert 	bias = 		bGetDouble(&buf[18]) / GPS_C * 1e9;	/* ns */
1637ba371819SOllivier Robert 	rate = 		bGetDouble(&buf[26]) / GPS_C * 1e9;	/* ppb */
1638ba371819SOllivier Robert 	biasunc = 	bGetSingle(&buf[34]) / GPS_C * 1e9;	/* ns */
1639ba371819SOllivier Robert 	rateunc = 	bGetSingle(&buf[38]) / GPS_C * 1e9;	/* ppb */
1640ba371819SOllivier Robert 	lat = 		bGetDouble(&buf[42]) * R2D;
1641ba371819SOllivier Robert 	lon = 		bGetDouble(&buf[50]) * R2D;
1642ba371819SOllivier Robert 	alt = 		bGetDouble(&buf[58]);
1643ba371819SOllivier Robert 
1644ba371819SOllivier Robert 	if (lat < 0.0) {
1645ba371819SOllivier Robert 		north_south = 'S';
1646ba371819SOllivier Robert 		lat = -lat;
1647ba371819SOllivier Robert 	}
1648ba371819SOllivier Robert 	else {
1649ba371819SOllivier Robert 		north_south = 'N';
1650ba371819SOllivier Robert 	}
1651ba371819SOllivier Robert 	lat_deg = (short)lat;
1652ba371819SOllivier Robert 	lat_min = (lat - lat_deg) * 60.0;
1653ba371819SOllivier Robert 
1654ba371819SOllivier Robert 	if (lon < 0.0) {
1655ba371819SOllivier Robert 		east_west = 'W';
1656ba371819SOllivier Robert 		lon = -lon;
1657ba371819SOllivier Robert 	}
1658ba371819SOllivier Robert 	else {
1659ba371819SOllivier Robert 		east_west = 'E';
1660ba371819SOllivier Robert 	}
1661ba371819SOllivier Robert 
1662ba371819SOllivier Robert 	lon_deg = (short)lon;
1663ba371819SOllivier Robert 	lon_min = (lon - lon_deg) * 60.0;
1664ba371819SOllivier Robert 
1665ba371819SOllivier Robert 	for (i=0; i<8; i++) {
1666ba371819SOllivier Robert 		sv[i] = buf[i + 66];
1667ba371819SOllivier Robert 		if (sv[i]) {
1668ba371819SOllivier Robert 			TSIPPKT spt; /* local structure for sendpacket */
1669ba371819SOllivier Robert 			b = (unsigned char) (sv[i]<0 ? -sv[i] : sv[i]);
1670ba371819SOllivier Robert 			/* request tracking status */
1671ba371819SOllivier Robert 			cmd_0x3C  (&spt, b);
1672ba371819SOllivier Robert 			ripencc_send(peer,spt);
1673ba371819SOllivier Robert 		}
1674ba371819SOllivier Robert 	}
1675ba371819SOllivier Robert 
1676ba371819SOllivier Robert 
1677ba371819SOllivier Robert 	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",
16782b15cb3dSCy Schubert 		day, month, year, hour, minute, second, mode, bias, biasunc,
16792b15cb3dSCy Schubert 		rate, rateunc, utcoff, lat_deg, lat_min, north_south, lon_deg,
16802b15cb3dSCy Schubert 		lon_min, east_west, alt, sv[0], sv[1], sv[2], sv[3], sv[4],
16812b15cb3dSCy Schubert 		sv[5], sv[6], sv[7]);
1682ba371819SOllivier Robert 
1683ba371819SOllivier Robert #ifdef DEBUG_NCC
1684ba371819SOllivier Robert 	if (debug)
1685ba371819SOllivier Robert    		puts(logbuf);
1686ba371819SOllivier Robert #endif /* DEBUG_NCC */
1687ba371819SOllivier Robert 
1688ba371819SOllivier Robert 	record_clock_stats(&peer->srcadr, logbuf);
1689ba371819SOllivier Robert 
1690ba371819SOllivier Robert 	return (0);
1691ba371819SOllivier Robert }
1692ba371819SOllivier Robert 
1693ba371819SOllivier Robert #ifdef TRIMBLE_OUTPUT_FUNC
1694ba371819SOllivier Robert /*
1695ba371819SOllivier Robert  * Parse any packet using Trimble machinery
1696ba371819SOllivier Robert  */
16972b15cb3dSCy Schubert int
16982b15cb3dSCy Schubert parseany(
16992b15cb3dSCy Schubert 	 TSIPPKT *rpt,
17002b15cb3dSCy Schubert 	 struct peer *peer
17012b15cb3dSCy Schubert 	 )
1702ba371819SOllivier Robert {
1703ba371819SOllivier Robert    	static char logbuf[1024];	/* logging string buffer */
1704ba371819SOllivier Robert 
1705ba371819SOllivier Robert    	TranslateTSIPReportToText (rpt, logbuf);	/* anything else */
1706ba371819SOllivier Robert #ifdef DEBUG_NCC
1707ba371819SOllivier Robert 	if (debug)
1708ba371819SOllivier Robert    		puts(&logbuf[1]);
1709ba371819SOllivier Robert #endif /* DEBUG_NCC */
1710ba371819SOllivier Robert 	record_clock_stats(&peer->srcadr, &logbuf[1]);
1711ba371819SOllivier Robert 	return(0);
1712ba371819SOllivier Robert }
1713ba371819SOllivier Robert #endif /* TRIMBLE_OUTPUT_FUNC */
1714ba371819SOllivier Robert 
1715ba371819SOllivier Robert 
1716ba371819SOllivier Robert /*
1717ba371819SOllivier Robert  * Parse UTC Parameter Packet
1718ba371819SOllivier Robert  *
1719ba371819SOllivier Robert  * See the IDE for documentation!
1720ba371819SOllivier Robert  *
1721ba371819SOllivier Robert  * 0 = success
1722ba371819SOllivier Robert  * -1 = errors
1723ba371819SOllivier Robert  */
1724ba371819SOllivier Robert 
17252b15cb3dSCy Schubert int
17262b15cb3dSCy Schubert parse0x4F(
17272b15cb3dSCy Schubert 	  TSIPPKT *rpt,
17282b15cb3dSCy Schubert 	  struct peer *peer
17292b15cb3dSCy Schubert 	  )
1730ba371819SOllivier Robert {
1731ba371819SOllivier Robert 	register struct ripencc_unit *up;
1732ba371819SOllivier Robert 
1733ba371819SOllivier Robert 	double a0;
1734ba371819SOllivier Robert 	float a1, tot;
1735ba371819SOllivier Robert 	int dt_ls, wn_t, wn_lsf, dn, dt_lsf;
1736ba371819SOllivier Robert 
1737ba371819SOllivier Robert    	static char logbuf[1024];	/* logging string buffer */
1738ba371819SOllivier Robert 	unsigned char *buf;
1739ba371819SOllivier Robert 
1740ba371819SOllivier Robert 	buf = rpt->buf;
1741ba371819SOllivier Robert 
1742ba371819SOllivier Robert 	if (rpt->len != 26)
1743ba371819SOllivier Robert 		return (-1);
1744ba371819SOllivier Robert 	a0 = bGetDouble (buf);
1745ba371819SOllivier Robert 	a1 = bGetSingle (&buf[8]);
1746ba371819SOllivier Robert 	dt_ls = bGetShort (&buf[12]);
1747ba371819SOllivier Robert 	tot = bGetSingle (&buf[14]);
1748ba371819SOllivier Robert 	wn_t = bGetShort (&buf[18]);
1749ba371819SOllivier Robert 	wn_lsf = bGetShort (&buf[20]);
1750ba371819SOllivier Robert 	dn = bGetShort (&buf[22]);
1751ba371819SOllivier Robert 	dt_lsf = bGetShort (&buf[24]);
1752ba371819SOllivier Robert 
1753ba371819SOllivier Robert 	sprintf(logbuf, "L1 %d %d %d %g %g %g %d %d %d",
1754ba371819SOllivier Robert 		dt_lsf - dt_ls, dt_ls, dt_lsf, a0, a1, tot, wn_t, wn_lsf, dn);
1755ba371819SOllivier Robert 
1756ba371819SOllivier Robert #ifdef DEBUG_NCC
1757ba371819SOllivier Robert 	if (debug)
1758ba371819SOllivier Robert    		puts(logbuf);
1759ba371819SOllivier Robert #endif /* DEBUG_NCC */
1760ba371819SOllivier Robert 
1761ba371819SOllivier Robert 	record_clock_stats(&peer->srcadr, logbuf);
1762ba371819SOllivier Robert 
1763ba371819SOllivier Robert 	up = (struct ripencc_unit *) peer->procptr->unitptr;
1764ba371819SOllivier Robert 	up->leapdelta = dt_lsf - dt_ls;
1765ba371819SOllivier Robert 
1766ba371819SOllivier Robert 	return (0);
1767ba371819SOllivier Robert }
1768ba371819SOllivier Robert 
1769ba371819SOllivier Robert /*
1770ba371819SOllivier Robert  * Parse Tracking Status packet
1771ba371819SOllivier Robert  *
1772ba371819SOllivier Robert  * 0 = success
1773ba371819SOllivier Robert  * -1 = errors
1774ba371819SOllivier Robert  */
1775ba371819SOllivier Robert 
17762b15cb3dSCy Schubert int
17772b15cb3dSCy Schubert parse0x5C(
17782b15cb3dSCy Schubert 	  TSIPPKT *rpt,
17792b15cb3dSCy Schubert 	  struct peer *peer
17802b15cb3dSCy Schubert 	  )
1781ba371819SOllivier Robert {
1782ba371819SOllivier Robert 	unsigned char prn, channel, aqflag, ephstat;
1783ba371819SOllivier Robert 	float snr, azinuth, elevation;
1784ba371819SOllivier Robert 
1785ba371819SOllivier Robert    	static char logbuf[1024];	/* logging string buffer */
1786ba371819SOllivier Robert 	unsigned char *buf;
1787ba371819SOllivier Robert 
1788ba371819SOllivier Robert 	buf = rpt->buf;
1789ba371819SOllivier Robert 
1790ba371819SOllivier Robert 	if (rpt->len != 24)
1791ba371819SOllivier Robert 		return(-1);
1792ba371819SOllivier Robert 
1793ba371819SOllivier Robert 	prn = buf[0];
1794ba371819SOllivier Robert 	channel = (unsigned char)(buf[1] >> 3);
1795ba371819SOllivier Robert 	if (channel == 0x10)
1796ba371819SOllivier Robert 		channel = 2;
1797ba371819SOllivier Robert 	else
1798ba371819SOllivier Robert 		channel++;
1799ba371819SOllivier Robert 	aqflag = buf[2];
1800ba371819SOllivier Robert 	ephstat = buf[3];
1801ba371819SOllivier Robert 	snr = bGetSingle(&buf[4]);
1802ba371819SOllivier Robert 	elevation = bGetSingle(&buf[12]) * R2D;
1803ba371819SOllivier Robert 	azinuth = bGetSingle(&buf[16]) * R2D;
1804ba371819SOllivier Robert 
1805ba371819SOllivier Robert 	sprintf(logbuf, "S1 %02d %d %d %02x %4.1f %5.1f %4.1f",
1806ba371819SOllivier Robert 		prn, channel, aqflag, ephstat, snr, azinuth, elevation);
1807ba371819SOllivier Robert 
1808ba371819SOllivier Robert #ifdef DEBUG_NCC
1809ba371819SOllivier Robert 	if (debug)
1810ba371819SOllivier Robert    		puts(logbuf);
1811ba371819SOllivier Robert #endif /* DEBUG_NCC */
1812ba371819SOllivier Robert 
1813ba371819SOllivier Robert 	record_clock_stats(&peer->srcadr, logbuf);
1814ba371819SOllivier Robert 
1815ba371819SOllivier Robert 	return (0);
1816ba371819SOllivier Robert }
1817ba371819SOllivier Robert 
1818ba371819SOllivier Robert /******* Code below is from Trimble Tsipchat *************/
1819ba371819SOllivier Robert 
1820ba371819SOllivier Robert /*
1821ba371819SOllivier Robert  * *************************************************************************
1822ba371819SOllivier Robert  *
1823ba371819SOllivier Robert  * Trimble Navigation, Ltd.
1824ba371819SOllivier Robert  * OEM Products Development Group
1825ba371819SOllivier Robert  * P.O. Box 3642
1826ba371819SOllivier Robert  * 645 North Mary Avenue
1827ba371819SOllivier Robert  * Sunnyvale, California 94088-3642
1828ba371819SOllivier Robert  *
1829ba371819SOllivier Robert  * Corporate Headquarter:
1830ba371819SOllivier Robert  *    Telephone:  (408) 481-8000
1831ba371819SOllivier Robert  *    Fax:        (408) 481-6005
1832ba371819SOllivier Robert  *
1833ba371819SOllivier Robert  * Technical Support Center:
1834ba371819SOllivier Robert  *    Telephone:  (800) 767-4822	(U.S. and Canada)
1835ba371819SOllivier Robert  *                (408) 481-6940    (outside U.S. and Canada)
1836ba371819SOllivier Robert  *    Fax:        (408) 481-6020
1837ba371819SOllivier Robert  *    BBS:        (408) 481-7800
1838ba371819SOllivier Robert  *    e-mail:     trimble_support@trimble.com
1839ba371819SOllivier Robert  *		ftp://ftp.trimble.com/pub/sct/embedded/bin
1840ba371819SOllivier Robert  *
1841ba371819SOllivier Robert  * *************************************************************************
1842ba371819SOllivier Robert  *
1843ba371819SOllivier Robert  * -------  BYTE-SWAPPING  -------
1844ba371819SOllivier Robert  * TSIP is big-endian (Motorola) protocol.  To use on little-endian (Intel)
1845ba371819SOllivier Robert  * systems, the bytes of all multi-byte types (shorts, floats, doubles, etc.)
1846ba371819SOllivier Robert  * must be reversed.  This is controlled by the MACRO BYTESWAP; if defined, it
1847ba371819SOllivier Robert  * assumes little-endian protocol.
1848ba371819SOllivier Robert  * --------------------------------
1849ba371819SOllivier Robert  *
1850ba371819SOllivier Robert  * T_PARSER.C and T_PARSER.H contains primitive functions that interpret
1851ba371819SOllivier Robert  * reports received from the receiver.  A second source file pair,
1852ba371819SOllivier Robert  * T_FORMAT.C and T_FORMAT.H, contin the matching TSIP command formatters.
1853ba371819SOllivier Robert  *
1854ba371819SOllivier Robert  * The module is in very portable, basic C language.  It can be used as is, or
1855ba371819SOllivier Robert  * with minimal changes if a TSIP communications application is needed separate
1856ba371819SOllivier Robert  * from TSIPCHAT. The construction of most argument lists avoid the use of
1857ba371819SOllivier Robert  * structures, but the developer is encouraged to reconstruct them using such
1858ba371819SOllivier Robert  * definitions to meet project requirements.  Declarations of T_PARSER.C
1859ba371819SOllivier Robert  * functions are included in T_PARSER.H to provide prototyping definitions.
1860ba371819SOllivier Robert  *
1861ba371819SOllivier Robert  * There are two types of functions: a serial input processing routine,
1862ba371819SOllivier Robert  *                            tsip_input_proc()
1863ba371819SOllivier Robert  * which assembles incoming bytes into a TSIPPKT structure, and the
1864ba371819SOllivier Robert  * report parsers, rpt_0x??().
1865ba371819SOllivier Robert  *
1866ba371819SOllivier Robert  * 1) The function tsip_input_proc() accumulates bytes from the receiver,
1867ba371819SOllivier Robert  * strips control bytes (DLE), and checks if the report end sequence (DLE ETX)
1868ba371819SOllivier Robert  * has been received.  rpt.status is defined as TSIP_PARSED_FULL (== 1)
1869ba371819SOllivier Robert  * if a complete packet is available.
1870ba371819SOllivier Robert  *
1871ba371819SOllivier Robert  * 2) The functions rpt_0x??() are report string interpreters patterned after
1872ba371819SOllivier Robert  * the document called "Trimble Standard Interface Protocol".  It should be
1873ba371819SOllivier Robert  * noted that if the report buffer is sent into the receiver with the wrong
1874ba371819SOllivier Robert  * length (byte count), the rpt_0x??() returns the Boolean equivalence for
1875ba371819SOllivier Robert  * TRUE.
1876ba371819SOllivier Robert  *
1877ba371819SOllivier Robert  * *************************************************************************
1878ba371819SOllivier Robert  *
1879ba371819SOllivier Robert  */
1880ba371819SOllivier Robert 
1881ba371819SOllivier Robert 
18822b15cb3dSCy Schubert /*
18832b15cb3dSCy Schubert  * reads bytes until serial buffer is empty or a complete report
1884ba371819SOllivier Robert  * has been received; end of report is signified by DLE ETX.
1885ba371819SOllivier Robert  */
18862b15cb3dSCy Schubert static void
18872b15cb3dSCy Schubert tsip_input_proc(
18882b15cb3dSCy Schubert 		TSIPPKT *rpt,
18892b15cb3dSCy Schubert 		int inbyte
18902b15cb3dSCy Schubert 		)
1891ba371819SOllivier Robert {
1892ba371819SOllivier Robert 	unsigned char newbyte;
1893ba371819SOllivier Robert 
1894ba371819SOllivier Robert 	if (inbyte < 0 || inbyte > 0xFF) return;
1895ba371819SOllivier Robert 
1896ba371819SOllivier Robert 	newbyte = (unsigned char)(inbyte);
1897ba371819SOllivier Robert 	switch (rpt->status)
1898ba371819SOllivier Robert 	{
1899ba371819SOllivier Robert 	    case TSIP_PARSED_DLE_1:
1900ba371819SOllivier Robert 		switch (newbyte)
1901ba371819SOllivier Robert 		{
1902ba371819SOllivier Robert 		    case 0:
1903ba371819SOllivier Robert 		    case ETX:
1904ba371819SOllivier Robert 			/* illegal TSIP IDs */
1905ba371819SOllivier Robert 			rpt->len = 0;
1906ba371819SOllivier Robert 			rpt->status = TSIP_PARSED_EMPTY;
1907ba371819SOllivier Robert 			break;
1908ba371819SOllivier Robert 		    case DLE:
1909ba371819SOllivier Robert 			/* try normal message start again */
1910ba371819SOllivier Robert 			rpt->len = 0;
1911ba371819SOllivier Robert 			rpt->status = TSIP_PARSED_DLE_1;
1912ba371819SOllivier Robert 			break;
1913ba371819SOllivier Robert 		    default:
1914ba371819SOllivier Robert 			/* legal TSIP ID; start message */
1915ba371819SOllivier Robert 			rpt->code = newbyte;
1916ba371819SOllivier Robert 			rpt->len = 0;
1917ba371819SOllivier Robert 			rpt->status = TSIP_PARSED_DATA;
1918ba371819SOllivier Robert 			break;
1919ba371819SOllivier Robert 		}
1920ba371819SOllivier Robert 		break;
1921ba371819SOllivier Robert 	    case TSIP_PARSED_DATA:
1922ba371819SOllivier Robert 		switch (newbyte) {
1923ba371819SOllivier Robert 		    case DLE:
1924ba371819SOllivier Robert 			/* expect DLE or ETX next */
1925ba371819SOllivier Robert 			rpt->status = TSIP_PARSED_DLE_2;
1926ba371819SOllivier Robert 			break;
1927ba371819SOllivier Robert 		    default:
1928ba371819SOllivier Robert 			/* normal data byte  */
1929ba371819SOllivier Robert 			rpt->buf[rpt->len] = newbyte;
1930ba371819SOllivier Robert 			rpt->len++;
1931ba371819SOllivier Robert 			/* no change in rpt->status */
1932ba371819SOllivier Robert 			break;
1933ba371819SOllivier Robert 		}
1934ba371819SOllivier Robert 		break;
1935ba371819SOllivier Robert 	    case TSIP_PARSED_DLE_2:
1936ba371819SOllivier Robert 		switch (newbyte) {
1937ba371819SOllivier Robert 		    case DLE:
1938ba371819SOllivier Robert 			/* normal data byte */
1939ba371819SOllivier Robert 			rpt->buf[rpt->len] = newbyte;
1940ba371819SOllivier Robert 			rpt->len++;
1941ba371819SOllivier Robert 			rpt->status = TSIP_PARSED_DATA;
1942ba371819SOllivier Robert 			break;
1943ba371819SOllivier Robert 		    case ETX:
1944ba371819SOllivier Robert 			/* end of message; return TRUE here. */
1945ba371819SOllivier Robert 			rpt->status = TSIP_PARSED_FULL;
1946ba371819SOllivier Robert 			break;
1947ba371819SOllivier Robert 		    default:
1948ba371819SOllivier Robert 			/* error: treat as TSIP_PARSED_DLE_1; start new report packet */
1949ba371819SOllivier Robert 			rpt->code = newbyte;
1950ba371819SOllivier Robert 			rpt->len = 0;
1951ba371819SOllivier Robert 			rpt->status = TSIP_PARSED_DATA;
1952ba371819SOllivier Robert 		}
1953ba371819SOllivier Robert 		break;
1954ba371819SOllivier Robert 	    case TSIP_PARSED_FULL:
1955ba371819SOllivier Robert 	    case TSIP_PARSED_EMPTY:
1956ba371819SOllivier Robert 	    default:
1957ba371819SOllivier Robert 		switch (newbyte) {
1958ba371819SOllivier Robert 		    case DLE:
1959ba371819SOllivier Robert 			/* normal message start */
1960ba371819SOllivier Robert 			rpt->len = 0;
1961ba371819SOllivier Robert 			rpt->status = TSIP_PARSED_DLE_1;
1962ba371819SOllivier Robert 			break;
1963ba371819SOllivier Robert 		    default:
1964ba371819SOllivier Robert 			/* error: ignore newbyte */
1965ba371819SOllivier Robert 			rpt->len = 0;
1966ba371819SOllivier Robert 			rpt->status = TSIP_PARSED_EMPTY;
1967ba371819SOllivier Robert 		}
1968ba371819SOllivier Robert 		break;
1969ba371819SOllivier Robert 	}
1970ba371819SOllivier Robert 	if (rpt->len > MAX_RPTBUF) {
1971ba371819SOllivier Robert 		/* error: start new report packet */
1972ba371819SOllivier Robert 		rpt->status = TSIP_PARSED_EMPTY;
1973ba371819SOllivier Robert 		rpt->len = 0;
1974ba371819SOllivier Robert 	}
1975ba371819SOllivier Robert }
1976ba371819SOllivier Robert 
1977ba371819SOllivier Robert #ifdef TRIMBLE_OUTPUT_FUNC
1978ba371819SOllivier Robert 
1979ba371819SOllivier Robert /**/
19802b15cb3dSCy Schubert /* Channel A configuration for dual port operation */
19812b15cb3dSCy Schubert short
19822b15cb3dSCy Schubert rpt_0x3D(
19832b15cb3dSCy Schubert 	 TSIPPKT *rpt,
1984ba371819SOllivier Robert 	 unsigned char *tx_baud_index,
1985ba371819SOllivier Robert 	 unsigned char *rx_baud_index,
1986ba371819SOllivier Robert 	 unsigned char *char_format_index,
1987ba371819SOllivier Robert 	 unsigned char *stop_bits,
1988ba371819SOllivier Robert 	 unsigned char *tx_mode_index,
19892b15cb3dSCy Schubert 	 unsigned char *rx_mode_index
19902b15cb3dSCy Schubert 	 )
1991ba371819SOllivier Robert {
1992ba371819SOllivier Robert 	unsigned char *buf;
1993ba371819SOllivier Robert 	buf = rpt->buf;
1994ba371819SOllivier Robert 
1995ba371819SOllivier Robert 	if (rpt->len != 6) return TRUE;
1996ba371819SOllivier Robert 	*tx_baud_index = buf[0];
1997ba371819SOllivier Robert 	*rx_baud_index = buf[1];
1998ba371819SOllivier Robert 	*char_format_index = buf[2];
1999ba371819SOllivier Robert 	*stop_bits = (unsigned char)((buf[3] == 0x07) ? 1 : 2);
2000ba371819SOllivier Robert 	*tx_mode_index = buf[4];
2001ba371819SOllivier Robert 	*rx_mode_index = buf[5];
2002ba371819SOllivier Robert 	return FALSE;
2003ba371819SOllivier Robert }
2004ba371819SOllivier Robert 
2005ba371819SOllivier Robert /**/
20062b15cb3dSCy Schubert /* almanac data for specified satellite */
20072b15cb3dSCy Schubert short
20082b15cb3dSCy Schubert rpt_0x40(
20092b15cb3dSCy Schubert 	 TSIPPKT *rpt,
2010ba371819SOllivier Robert 	 unsigned char *sv_prn,
2011ba371819SOllivier Robert 	 short *week_num,
2012ba371819SOllivier Robert 	 float *t_zc,
2013ba371819SOllivier Robert 	 float *eccentricity,
2014ba371819SOllivier Robert 	 float *t_oa,
2015ba371819SOllivier Robert 	 float *i_0,
2016ba371819SOllivier Robert 	 float *OMEGA_dot,
2017ba371819SOllivier Robert 	 float *sqrt_A,
2018ba371819SOllivier Robert 	 float *OMEGA_0,
2019ba371819SOllivier Robert 	 float *omega,
20202b15cb3dSCy Schubert 	 float *M_0
20212b15cb3dSCy Schubert 	 )
2022ba371819SOllivier Robert {
2023ba371819SOllivier Robert 	unsigned char *buf;
2024ba371819SOllivier Robert 	buf = rpt->buf;
2025ba371819SOllivier Robert 
2026ba371819SOllivier Robert 	if (rpt->len != 39) return TRUE;
2027ba371819SOllivier Robert 	*sv_prn = buf[0];
2028ba371819SOllivier Robert 	*t_zc = bGetSingle (&buf[1]);
2029ba371819SOllivier Robert 	*week_num = bGetShort (&buf[5]);
2030ba371819SOllivier Robert 	*eccentricity = bGetSingle (&buf[7]);
2031ba371819SOllivier Robert 	*t_oa = bGetSingle (&buf[11]);
2032ba371819SOllivier Robert 	*i_0 = bGetSingle (&buf[15]);
2033ba371819SOllivier Robert 	*OMEGA_dot = bGetSingle (&buf[19]);
2034ba371819SOllivier Robert 	*sqrt_A = bGetSingle (&buf[23]);
2035ba371819SOllivier Robert 	*OMEGA_0 = bGetSingle (&buf[27]);
2036ba371819SOllivier Robert 	*omega = bGetSingle (&buf[31]);
2037ba371819SOllivier Robert 	*M_0 = bGetSingle (&buf[35]);
2038ba371819SOllivier Robert 	return FALSE;
2039ba371819SOllivier Robert }
2040ba371819SOllivier Robert 
20412b15cb3dSCy Schubert /* GPS time */
20422b15cb3dSCy Schubert short
20432b15cb3dSCy Schubert rpt_0x41(
20442b15cb3dSCy Schubert 	 TSIPPKT *rpt,
2045ba371819SOllivier Robert 	 float *time_of_week,
2046ba371819SOllivier Robert 	 float *UTC_offset,
20472b15cb3dSCy Schubert 	 short *week_num
20482b15cb3dSCy Schubert 	 )
2049ba371819SOllivier Robert {
2050ba371819SOllivier Robert 	unsigned char *buf;
2051ba371819SOllivier Robert 	buf = rpt->buf;
2052ba371819SOllivier Robert 
2053ba371819SOllivier Robert 	if (rpt->len != 10) return TRUE;
2054ba371819SOllivier Robert 	*time_of_week = bGetSingle (buf);
2055ba371819SOllivier Robert 	*week_num = bGetShort (&buf[4]);
2056ba371819SOllivier Robert 	*UTC_offset = bGetSingle (&buf[6]);
2057ba371819SOllivier Robert 	return FALSE;
2058ba371819SOllivier Robert }
2059ba371819SOllivier Robert 
2060ba371819SOllivier Robert /* position in ECEF, single precision */
20612b15cb3dSCy Schubert short
20622b15cb3dSCy Schubert rpt_0x42(
20632b15cb3dSCy Schubert 	 TSIPPKT *rpt,
20642b15cb3dSCy Schubert 	 float pos_ECEF[3],
20652b15cb3dSCy Schubert 	 float *time_of_fix
20662b15cb3dSCy Schubert 	 )
2067ba371819SOllivier Robert {
2068ba371819SOllivier Robert 	unsigned char *buf;
2069ba371819SOllivier Robert 	buf = rpt->buf;
2070ba371819SOllivier Robert 
2071ba371819SOllivier Robert 	if (rpt->len != 16) return TRUE;
2072ba371819SOllivier Robert 	pos_ECEF[0] = bGetSingle (buf);
2073ba371819SOllivier Robert 	pos_ECEF[1]= bGetSingle (&buf[4]);
2074ba371819SOllivier Robert 	pos_ECEF[2]= bGetSingle (&buf[8]);
2075ba371819SOllivier Robert 	*time_of_fix = bGetSingle (&buf[12]);
2076ba371819SOllivier Robert 	return FALSE;
2077ba371819SOllivier Robert }
2078ba371819SOllivier Robert 
20792b15cb3dSCy Schubert /* velocity in ECEF, single precision */
20802b15cb3dSCy Schubert short
20812b15cb3dSCy Schubert rpt_0x43(
20822b15cb3dSCy Schubert 	 TSIPPKT *rpt,
2083ba371819SOllivier Robert 	 float ECEF_vel[3],
2084ba371819SOllivier Robert 	 float *freq_offset,
20852b15cb3dSCy Schubert 	 float *time_of_fix
20862b15cb3dSCy Schubert 	 )
2087ba371819SOllivier Robert {
2088ba371819SOllivier Robert 	unsigned char *buf;
2089ba371819SOllivier Robert 	buf = rpt->buf;
2090ba371819SOllivier Robert 
2091ba371819SOllivier Robert 	if (rpt->len != 20) return TRUE;
2092ba371819SOllivier Robert 	ECEF_vel[0] = bGetSingle (buf);
2093ba371819SOllivier Robert 	ECEF_vel[1] = bGetSingle (&buf[4]);
2094ba371819SOllivier Robert 	ECEF_vel[2] = bGetSingle (&buf[8]);
2095ba371819SOllivier Robert 	*freq_offset = bGetSingle (&buf[12]);
2096ba371819SOllivier Robert 	*time_of_fix = bGetSingle (&buf[16]);
2097ba371819SOllivier Robert 	return FALSE;
2098ba371819SOllivier Robert }
2099ba371819SOllivier Robert 
21002b15cb3dSCy Schubert /* software versions */
21012b15cb3dSCy Schubert short
21022b15cb3dSCy Schubert rpt_0x45(
21032b15cb3dSCy Schubert 	 TSIPPKT *rpt,
2104ba371819SOllivier Robert 	 unsigned char *major_nav_version,
2105ba371819SOllivier Robert 	 unsigned char *minor_nav_version,
2106ba371819SOllivier Robert 	 unsigned char *nav_day,
2107ba371819SOllivier Robert 	 unsigned char *nav_month,
2108ba371819SOllivier Robert 	 unsigned char *nav_year,
2109ba371819SOllivier Robert 	 unsigned char *major_dsp_version,
2110ba371819SOllivier Robert 	 unsigned char *minor_dsp_version,
2111ba371819SOllivier Robert 	 unsigned char *dsp_day,
2112ba371819SOllivier Robert 	 unsigned char *dsp_month,
21132b15cb3dSCy Schubert 	 unsigned char *dsp_year
21142b15cb3dSCy Schubert 	 )
2115ba371819SOllivier Robert {
2116ba371819SOllivier Robert 	unsigned char *buf;
2117ba371819SOllivier Robert 	buf = rpt->buf;
2118ba371819SOllivier Robert 
2119ba371819SOllivier Robert 	if (rpt->len != 10) return TRUE;
2120ba371819SOllivier Robert 	*major_nav_version = buf[0];
2121ba371819SOllivier Robert 	*minor_nav_version = buf[1];
2122ba371819SOllivier Robert 	*nav_day = buf[2];
2123ba371819SOllivier Robert 	*nav_month = buf[3];
2124ba371819SOllivier Robert 	*nav_year = buf[4];
2125ba371819SOllivier Robert 	*major_dsp_version = buf[5];
2126ba371819SOllivier Robert 	*minor_dsp_version = buf[6];
2127ba371819SOllivier Robert 	*dsp_day = buf[7];
2128ba371819SOllivier Robert 	*dsp_month = buf[8];
2129ba371819SOllivier Robert 	*dsp_year = buf[9];
2130ba371819SOllivier Robert 	return FALSE;
2131ba371819SOllivier Robert }
2132ba371819SOllivier Robert 
2133ba371819SOllivier Robert /* receiver health and status */
21342b15cb3dSCy Schubert short
21352b15cb3dSCy Schubert rpt_0x46(
21362b15cb3dSCy Schubert 	 TSIPPKT *rpt,
21372b15cb3dSCy Schubert 	 unsigned char *status1,
21382b15cb3dSCy Schubert 	 unsigned char *status2
21392b15cb3dSCy Schubert 	 )
2140ba371819SOllivier Robert {
2141ba371819SOllivier Robert 	unsigned char *buf;
2142ba371819SOllivier Robert 	buf = rpt->buf;
2143ba371819SOllivier Robert 
2144ba371819SOllivier Robert 	if (rpt->len != 2) return TRUE;
2145ba371819SOllivier Robert 	*status1 = buf[0];
2146ba371819SOllivier Robert 	*status2 = buf[1];
2147ba371819SOllivier Robert 	return FALSE;
2148ba371819SOllivier Robert }
2149ba371819SOllivier Robert 
2150ba371819SOllivier Robert /* signal levels for all satellites tracked */
21512b15cb3dSCy Schubert short
21522b15cb3dSCy Schubert rpt_0x47(
21532b15cb3dSCy Schubert 	 TSIPPKT *rpt,
21542b15cb3dSCy Schubert 	 unsigned char *nsvs,
21552b15cb3dSCy Schubert 	 unsigned char *sv_prn,
21562b15cb3dSCy Schubert 	 float *snr
21572b15cb3dSCy Schubert 	 )
2158ba371819SOllivier Robert {
2159ba371819SOllivier Robert 	short isv;
2160ba371819SOllivier Robert 	unsigned char *buf;
2161ba371819SOllivier Robert 	buf = rpt->buf;
2162ba371819SOllivier Robert 
2163ba371819SOllivier Robert 	if (rpt->len != 1 + 5*buf[0]) return TRUE;
2164ba371819SOllivier Robert 	*nsvs = buf[0];
2165ba371819SOllivier Robert 	for (isv = 0; isv < (*nsvs); isv++) {
2166ba371819SOllivier Robert 		sv_prn[isv] = buf[5*isv + 1];
2167ba371819SOllivier Robert 		snr[isv] = bGetSingle (&buf[5*isv + 2]);
2168ba371819SOllivier Robert 	}
2169ba371819SOllivier Robert 	return FALSE;
2170ba371819SOllivier Robert }
2171ba371819SOllivier Robert 
2172ba371819SOllivier Robert /* GPS system message */
21732b15cb3dSCy Schubert short
21742b15cb3dSCy Schubert rpt_0x48(
21752b15cb3dSCy Schubert 	 TSIPPKT *rpt,
21762b15cb3dSCy Schubert 	 unsigned char *message
21772b15cb3dSCy Schubert 	 )
2178ba371819SOllivier Robert {
2179ba371819SOllivier Robert 	unsigned char *buf;
2180ba371819SOllivier Robert 	buf = rpt->buf;
2181ba371819SOllivier Robert 
2182ba371819SOllivier Robert 	if (rpt->len != 22) return TRUE;
2183ba371819SOllivier Robert 	memcpy (message, buf, 22);
2184ba371819SOllivier Robert 	message[22] = 0;
2185ba371819SOllivier Robert 	return FALSE;
2186ba371819SOllivier Robert }
2187ba371819SOllivier Robert 
2188ba371819SOllivier Robert /* health for all satellites from almanac health page */
21892b15cb3dSCy Schubert short
21902b15cb3dSCy Schubert rpt_0x49(
21912b15cb3dSCy Schubert 	 TSIPPKT *rpt,
21922b15cb3dSCy Schubert 	 unsigned char *sv_health
21932b15cb3dSCy Schubert 	 )
2194ba371819SOllivier Robert {
2195ba371819SOllivier Robert 	short i;
2196ba371819SOllivier Robert 	unsigned char *buf;
2197ba371819SOllivier Robert 	buf = rpt->buf;
2198ba371819SOllivier Robert 
2199ba371819SOllivier Robert 	if (rpt->len != 32) return TRUE;
2200ba371819SOllivier Robert 	for (i = 0; i < 32; i++) sv_health [i]= buf[i];
2201ba371819SOllivier Robert 	return FALSE;
2202ba371819SOllivier Robert }
2203ba371819SOllivier Robert 
22042b15cb3dSCy Schubert /* position in lat-lon-alt, single precision */
22052b15cb3dSCy Schubert short
22062b15cb3dSCy Schubert rpt_0x4A(
22072b15cb3dSCy Schubert 	 TSIPPKT *rpt,
2208ba371819SOllivier Robert 	 float *lat,
2209ba371819SOllivier Robert 	 float *lon,
2210ba371819SOllivier Robert 	 float *alt,
2211ba371819SOllivier Robert 	 float *clock_bias,
22122b15cb3dSCy Schubert 	 float *time_of_fix
22132b15cb3dSCy Schubert 	 )
2214ba371819SOllivier Robert {
2215ba371819SOllivier Robert 	unsigned char *buf;
2216ba371819SOllivier Robert 	buf = rpt->buf;
2217ba371819SOllivier Robert 
2218ba371819SOllivier Robert 	if (rpt->len != 20) return TRUE;
2219ba371819SOllivier Robert 	*lat = bGetSingle (buf);
2220ba371819SOllivier Robert 	*lon = bGetSingle (&buf[4]);
2221ba371819SOllivier Robert 	*alt = bGetSingle (&buf[8]);
2222ba371819SOllivier Robert 	*clock_bias = bGetSingle (&buf[12]);
2223ba371819SOllivier Robert 	*time_of_fix = bGetSingle (&buf[16]);
2224ba371819SOllivier Robert 	return FALSE;
2225ba371819SOllivier Robert }
2226ba371819SOllivier Robert 
2227ba371819SOllivier Robert /* reference altitude parameters */
22282b15cb3dSCy Schubert short
22292b15cb3dSCy Schubert rpt_0x4A_2(
22302b15cb3dSCy Schubert 	   TSIPPKT *rpt,
22312b15cb3dSCy Schubert 	   float *alt,
22322b15cb3dSCy Schubert 	   float *dummy,
22332b15cb3dSCy Schubert 	   unsigned char *alt_flag
22342b15cb3dSCy Schubert 	   )
2235ba371819SOllivier Robert {
2236ba371819SOllivier Robert 	unsigned char *buf;
2237ba371819SOllivier Robert 
2238ba371819SOllivier Robert 	buf = rpt->buf;
2239ba371819SOllivier Robert 
2240ba371819SOllivier Robert 	if (rpt->len != 9) return TRUE;
2241ba371819SOllivier Robert 	*alt = bGetSingle (buf);
2242ba371819SOllivier Robert 	*dummy = bGetSingle (&buf[4]);
2243ba371819SOllivier Robert 	*alt_flag = buf[8];
2244ba371819SOllivier Robert 	return FALSE;
2245ba371819SOllivier Robert }
2246ba371819SOllivier Robert 
22472b15cb3dSCy Schubert /* machine ID code, status */
22482b15cb3dSCy Schubert short
22492b15cb3dSCy Schubert rpt_0x4B(
22502b15cb3dSCy Schubert 	 TSIPPKT *rpt,
2251ba371819SOllivier Robert 	 unsigned char *machine_id,
2252ba371819SOllivier Robert 	 unsigned char *status3,
22532b15cb3dSCy Schubert 	 unsigned char *status4
22542b15cb3dSCy Schubert 	 )
2255ba371819SOllivier Robert {
2256ba371819SOllivier Robert 	unsigned char *buf;
2257ba371819SOllivier Robert 	buf = rpt->buf;
2258ba371819SOllivier Robert 
2259ba371819SOllivier Robert 	if (rpt->len != 3) return TRUE;
2260ba371819SOllivier Robert 	*machine_id = buf[0];
2261ba371819SOllivier Robert 	*status3 = buf[1];
2262ba371819SOllivier Robert 	*status4 = buf[2];
2263ba371819SOllivier Robert 	return FALSE;
2264ba371819SOllivier Robert }
2265ba371819SOllivier Robert 
22662b15cb3dSCy Schubert /* operating parameters and masks */
22672b15cb3dSCy Schubert short
22682b15cb3dSCy Schubert rpt_0x4C(
22692b15cb3dSCy Schubert 	 TSIPPKT *rpt,
2270ba371819SOllivier Robert 	 unsigned char *dyn_code,
2271ba371819SOllivier Robert 	 float *el_mask,
2272ba371819SOllivier Robert 	 float *snr_mask,
2273ba371819SOllivier Robert 	 float *dop_mask,
22742b15cb3dSCy Schubert 	 float *dop_switch
22752b15cb3dSCy Schubert 	 )
2276ba371819SOllivier Robert {
2277ba371819SOllivier Robert 	unsigned char *buf;
2278ba371819SOllivier Robert 	buf = rpt->buf;
2279ba371819SOllivier Robert 
2280ba371819SOllivier Robert 	if (rpt->len != 17) return TRUE;
2281ba371819SOllivier Robert 	*dyn_code = buf[0];
2282ba371819SOllivier Robert 	*el_mask = bGetSingle (&buf[1]);
2283ba371819SOllivier Robert 	*snr_mask = bGetSingle (&buf[5]);
2284ba371819SOllivier Robert 	*dop_mask = bGetSingle (&buf[9]);
2285ba371819SOllivier Robert 	*dop_switch = bGetSingle (&buf[13]);
2286ba371819SOllivier Robert 	return FALSE;
2287ba371819SOllivier Robert }
2288ba371819SOllivier Robert 
2289ba371819SOllivier Robert /* oscillator offset */
22902b15cb3dSCy Schubert short
22912b15cb3dSCy Schubert rpt_0x4D(
22922b15cb3dSCy Schubert 	 TSIPPKT *rpt,
22932b15cb3dSCy Schubert 	 float *osc_offset
22942b15cb3dSCy Schubert 	 )
2295ba371819SOllivier Robert {
2296ba371819SOllivier Robert 	unsigned char *buf;
2297ba371819SOllivier Robert 	buf = rpt->buf;
2298ba371819SOllivier Robert 
2299ba371819SOllivier Robert 	if (rpt->len != 4) return TRUE;
2300ba371819SOllivier Robert 	*osc_offset = bGetSingle (buf);
2301ba371819SOllivier Robert 	return FALSE;
2302ba371819SOllivier Robert }
2303ba371819SOllivier Robert 
2304ba371819SOllivier Robert /* yes/no response to command to set GPS time */
23052b15cb3dSCy Schubert short
23062b15cb3dSCy Schubert rpt_0x4E(
23072b15cb3dSCy Schubert 	 TSIPPKT *rpt,
23082b15cb3dSCy Schubert 	 unsigned char *response
23092b15cb3dSCy Schubert 	 )
2310ba371819SOllivier Robert {
2311ba371819SOllivier Robert 	unsigned char *buf;
2312ba371819SOllivier Robert 	buf = rpt->buf;
2313ba371819SOllivier Robert 
2314ba371819SOllivier Robert 	if (rpt->len != 1) return TRUE;
2315ba371819SOllivier Robert 	*response = buf[0];
2316ba371819SOllivier Robert 	return FALSE;
2317ba371819SOllivier Robert }
2318ba371819SOllivier Robert 
23192b15cb3dSCy Schubert /* UTC data */
23202b15cb3dSCy Schubert short
23212b15cb3dSCy Schubert rpt_0x4F(
23222b15cb3dSCy Schubert 	 TSIPPKT *rpt,
2323ba371819SOllivier Robert 	 double *a0,
2324ba371819SOllivier Robert 	 float *a1,
2325ba371819SOllivier Robert 	 float *time_of_data,
2326ba371819SOllivier Robert 	 short *dt_ls,
2327ba371819SOllivier Robert 	 short *wn_t,
2328ba371819SOllivier Robert 	 short *wn_lsf,
2329ba371819SOllivier Robert 	 short *dn,
23302b15cb3dSCy Schubert 	 short *dt_lsf
23312b15cb3dSCy Schubert 	 )
2332ba371819SOllivier Robert {
2333ba371819SOllivier Robert 	unsigned char *buf;
2334ba371819SOllivier Robert 	buf = rpt->buf;
2335ba371819SOllivier Robert 
2336ba371819SOllivier Robert 	if (rpt->len != 26) return TRUE;
2337ba371819SOllivier Robert 	*a0 = bGetDouble (buf);
2338ba371819SOllivier Robert 	*a1 = bGetSingle (&buf[8]);
2339ba371819SOllivier Robert 	*dt_ls = bGetShort (&buf[12]);
2340ba371819SOllivier Robert 	*time_of_data = bGetSingle (&buf[14]);
2341ba371819SOllivier Robert 	*wn_t = bGetShort (&buf[18]);
2342ba371819SOllivier Robert 	*wn_lsf = bGetShort (&buf[20]);
2343ba371819SOllivier Robert 	*dn = bGetShort (&buf[22]);
2344ba371819SOllivier Robert 	*dt_lsf = bGetShort (&buf[24]);
2345ba371819SOllivier Robert 	return FALSE;
2346ba371819SOllivier Robert }
2347ba371819SOllivier Robert 
2348ba371819SOllivier Robert /**/
23492b15cb3dSCy Schubert /* clock offset and frequency offset in 1-SV (0-D) mode */
23502b15cb3dSCy Schubert short
23512b15cb3dSCy Schubert rpt_0x54(
23522b15cb3dSCy Schubert 	 TSIPPKT *rpt,
2353ba371819SOllivier Robert 	 float *clock_bias,
2354ba371819SOllivier Robert 	 float *freq_offset,
23552b15cb3dSCy Schubert 	 float *time_of_fix
23562b15cb3dSCy Schubert 	 )
2357ba371819SOllivier Robert {
2358ba371819SOllivier Robert 	unsigned char *buf;
2359ba371819SOllivier Robert 	buf = rpt->buf;
2360ba371819SOllivier Robert 
2361ba371819SOllivier Robert 	if (rpt->len != 12) return TRUE;
2362ba371819SOllivier Robert 	*clock_bias = bGetSingle (buf);
2363ba371819SOllivier Robert 	*freq_offset = bGetSingle (&buf[4]);
2364ba371819SOllivier Robert 	*time_of_fix = bGetSingle (&buf[8]);
2365ba371819SOllivier Robert 	return FALSE;
2366ba371819SOllivier Robert }
2367ba371819SOllivier Robert 
23682b15cb3dSCy Schubert /* I/O serial options */
23692b15cb3dSCy Schubert short
23702b15cb3dSCy Schubert rpt_0x55(
23712b15cb3dSCy Schubert 	 TSIPPKT *rpt,
2372ba371819SOllivier Robert 	 unsigned char *pos_code,
2373ba371819SOllivier Robert 	 unsigned char *vel_code,
2374ba371819SOllivier Robert 	 unsigned char *time_code,
23752b15cb3dSCy Schubert 	 unsigned char *aux_code
23762b15cb3dSCy Schubert 	 )
2377ba371819SOllivier Robert {
2378ba371819SOllivier Robert 	unsigned char *buf;
2379ba371819SOllivier Robert 	buf = rpt->buf;
2380ba371819SOllivier Robert 
2381ba371819SOllivier Robert 	if (rpt->len != 4) return TRUE;
2382ba371819SOllivier Robert 	*pos_code = buf[0];
2383ba371819SOllivier Robert 	*vel_code = buf[1];
2384ba371819SOllivier Robert 	*time_code = buf[2];
2385ba371819SOllivier Robert 	*aux_code = buf[3];
2386ba371819SOllivier Robert 	return FALSE;
2387ba371819SOllivier Robert }
2388ba371819SOllivier Robert 
2389ba371819SOllivier Robert /* velocity in east-north-up coordinates */
23902b15cb3dSCy Schubert short
23912b15cb3dSCy Schubert rpt_0x56(
23922b15cb3dSCy Schubert 	 TSIPPKT *rpt,
23932b15cb3dSCy Schubert 	 float vel_ENU[3],
23942b15cb3dSCy Schubert 	 float *freq_offset,
23952b15cb3dSCy Schubert 	 float *time_of_fix
23962b15cb3dSCy Schubert 	 )
2397ba371819SOllivier Robert {
2398ba371819SOllivier Robert 	unsigned char *buf;
2399ba371819SOllivier Robert 	buf = rpt->buf;
2400ba371819SOllivier Robert 
2401ba371819SOllivier Robert 	if (rpt->len != 20) return TRUE;
2402ba371819SOllivier Robert 	/* east */
2403ba371819SOllivier Robert 	vel_ENU[0] = bGetSingle (buf);
2404ba371819SOllivier Robert 	/* north */
2405ba371819SOllivier Robert 	vel_ENU[1] = bGetSingle (&buf[4]);
2406ba371819SOllivier Robert 	/* up */
2407ba371819SOllivier Robert 	vel_ENU[2] = bGetSingle (&buf[8]);
2408ba371819SOllivier Robert 	*freq_offset = bGetSingle (&buf[12]);
2409ba371819SOllivier Robert 	*time_of_fix = bGetSingle (&buf[16]);
2410ba371819SOllivier Robert 	return FALSE;
2411ba371819SOllivier Robert }
2412ba371819SOllivier Robert 
2413ba371819SOllivier Robert /* info about last computed fix */
24142b15cb3dSCy Schubert short
24152b15cb3dSCy Schubert rpt_0x57(
24162b15cb3dSCy Schubert 	 TSIPPKT *rpt,
24172b15cb3dSCy Schubert 	 unsigned char *source_code,
24182b15cb3dSCy Schubert 	 unsigned char *diag_code,
24192b15cb3dSCy Schubert 	 short *week_num,
24202b15cb3dSCy Schubert 	 float *time_of_fix
24212b15cb3dSCy Schubert 	 )
2422ba371819SOllivier Robert {
2423ba371819SOllivier Robert 	unsigned char *buf;
2424ba371819SOllivier Robert 	buf = rpt->buf;
2425ba371819SOllivier Robert 
2426ba371819SOllivier Robert 	if (rpt->len != 8) return TRUE;
2427ba371819SOllivier Robert 	*source_code = buf[0];
2428ba371819SOllivier Robert 	*diag_code = buf[1];
2429ba371819SOllivier Robert 	*time_of_fix = bGetSingle (&buf[2]);
2430ba371819SOllivier Robert 	*week_num = bGetShort (&buf[6]);
2431ba371819SOllivier Robert 	return FALSE;
2432ba371819SOllivier Robert }
2433ba371819SOllivier Robert 
2434ba371819SOllivier Robert /* GPS system data or acknowledgment of GPS system data load */
24352b15cb3dSCy Schubert short
24362b15cb3dSCy Schubert rpt_0x58(
24372b15cb3dSCy Schubert 	 TSIPPKT *rpt,
24382b15cb3dSCy Schubert 	 unsigned char *op_code,
24392b15cb3dSCy Schubert 	 unsigned char *data_type,
24402b15cb3dSCy Schubert 	 unsigned char *sv_prn,
24412b15cb3dSCy Schubert 	 unsigned char *data_length,
24422b15cb3dSCy Schubert 	 unsigned char *data_packet
24432b15cb3dSCy Schubert 	 )
2444ba371819SOllivier Robert {
2445ba371819SOllivier Robert 	unsigned char *buf, *buf4;
2446ba371819SOllivier Robert 	short dl;
2447ba371819SOllivier Robert 	ALM_INFO* alminfo;
2448ba371819SOllivier Robert 	ION_INFO* ioninfo;
2449ba371819SOllivier Robert 	UTC_INFO* utcinfo;
2450ba371819SOllivier Robert 	NAV_INFO* navinfo;
2451ba371819SOllivier Robert 
2452ba371819SOllivier Robert 	buf = rpt->buf;
2453ba371819SOllivier Robert 
2454ba371819SOllivier Robert 	if (buf[0] == 2) {
2455ba371819SOllivier Robert 		if (rpt->len < 4) return TRUE;
2456ba371819SOllivier Robert 		if (rpt->len != 4+buf[3]) return TRUE;
2457ba371819SOllivier Robert 	}
2458ba371819SOllivier Robert 	else if (rpt->len != 3) {
2459ba371819SOllivier Robert 		return TRUE;
2460ba371819SOllivier Robert 	}
2461ba371819SOllivier Robert 	*op_code = buf[0];
2462ba371819SOllivier Robert 	*data_type = buf[1];
2463ba371819SOllivier Robert 	*sv_prn = buf[2];
2464ba371819SOllivier Robert 	if (*op_code == 2) {
2465ba371819SOllivier Robert 		dl = buf[3];
2466ba371819SOllivier Robert 		*data_length = (unsigned char)dl;
2467ba371819SOllivier Robert 		buf4 = &buf[4];
2468ba371819SOllivier Robert 		switch (*data_type) {
2469ba371819SOllivier Robert 		    case 2:
2470ba371819SOllivier Robert 			/* Almanac */
2471ba371819SOllivier Robert 			if (*data_length != sizeof (ALM_INFO)) return TRUE;
2472ba371819SOllivier Robert 			alminfo = (ALM_INFO*)data_packet;
2473ba371819SOllivier Robert 			alminfo->t_oa_raw  = buf4[0];
2474ba371819SOllivier Robert 			alminfo->SV_health = buf4[1];
2475ba371819SOllivier Robert 			alminfo->e         = bGetSingle(&buf4[2]);
2476ba371819SOllivier Robert 			alminfo->t_oa      = bGetSingle(&buf4[6]);
2477ba371819SOllivier Robert 			alminfo->i_0       = bGetSingle(&buf4[10]);
2478ba371819SOllivier Robert 			alminfo->OMEGADOT  = bGetSingle(&buf4[14]);
2479ba371819SOllivier Robert 			alminfo->sqrt_A    = bGetSingle(&buf4[18]);
2480ba371819SOllivier Robert 			alminfo->OMEGA_0   = bGetSingle(&buf4[22]);
2481ba371819SOllivier Robert 			alminfo->omega     = bGetSingle(&buf4[26]);
2482ba371819SOllivier Robert 			alminfo->M_0       = bGetSingle(&buf4[30]);
2483ba371819SOllivier Robert 			alminfo->a_f0      = bGetSingle(&buf4[34]);
2484ba371819SOllivier Robert 			alminfo->a_f1      = bGetSingle(&buf4[38]);
2485ba371819SOllivier Robert 			alminfo->Axis      = bGetSingle(&buf4[42]);
2486ba371819SOllivier Robert 			alminfo->n         = bGetSingle(&buf4[46]);
2487ba371819SOllivier Robert 			alminfo->OMEGA_n   = bGetSingle(&buf4[50]);
2488ba371819SOllivier Robert 			alminfo->ODOT_n    = bGetSingle(&buf4[54]);
2489ba371819SOllivier Robert 			alminfo->t_zc      = bGetSingle(&buf4[58]);
2490ba371819SOllivier Robert 			alminfo->weeknum   = bGetShort(&buf4[62]);
2491ba371819SOllivier Robert 			alminfo->wn_oa     = bGetShort(&buf4[64]);
2492ba371819SOllivier Robert 			break;
2493ba371819SOllivier Robert 
2494ba371819SOllivier Robert 		    case 3:
2495ba371819SOllivier Robert 			/* Almanac health page */
2496ba371819SOllivier Robert 			if (*data_length != sizeof (ALH_PARMS) + 3) return TRUE;
2497ba371819SOllivier Robert 
2498ba371819SOllivier Robert 			/* this record is returned raw */
2499ba371819SOllivier Robert 			memcpy (data_packet, buf4, dl);
2500ba371819SOllivier Robert 			break;
2501ba371819SOllivier Robert 
2502ba371819SOllivier Robert 		    case 4:
2503ba371819SOllivier Robert 			/* Ionosphere */
2504ba371819SOllivier Robert 			if (*data_length != sizeof (ION_INFO) + 8) return TRUE;
2505ba371819SOllivier Robert 			ioninfo = (ION_INFO*)data_packet;
2506ba371819SOllivier Robert 			ioninfo->alpha_0   = bGetSingle (&buf4[8]);
2507ba371819SOllivier Robert 			ioninfo->alpha_1   = bGetSingle (&buf4[12]);
2508ba371819SOllivier Robert 			ioninfo->alpha_2   = bGetSingle (&buf4[16]);
2509ba371819SOllivier Robert 			ioninfo->alpha_3   = bGetSingle (&buf4[20]);
2510ba371819SOllivier Robert 			ioninfo->beta_0    = bGetSingle (&buf4[24]);
2511ba371819SOllivier Robert 			ioninfo->beta_1    = bGetSingle (&buf4[28]);
2512ba371819SOllivier Robert 			ioninfo->beta_2    = bGetSingle (&buf4[32]);
2513ba371819SOllivier Robert 			ioninfo->beta_3    = bGetSingle (&buf4[36]);
2514ba371819SOllivier Robert 			break;
2515ba371819SOllivier Robert 
2516ba371819SOllivier Robert 		    case 5:
2517ba371819SOllivier Robert 			/* UTC */
2518ba371819SOllivier Robert 			if (*data_length != sizeof (UTC_INFO) + 13) return TRUE;
2519ba371819SOllivier Robert 			utcinfo = (UTC_INFO*)data_packet;
2520ba371819SOllivier Robert 			utcinfo->A_0       = bGetDouble (&buf4[13]);
2521ba371819SOllivier Robert 			utcinfo->A_1       = bGetSingle (&buf4[21]);
2522ba371819SOllivier Robert 			utcinfo->delta_t_LS = bGetShort (&buf4[25]);
2523ba371819SOllivier Robert 			utcinfo->t_ot      = bGetSingle(&buf4[27]);
2524ba371819SOllivier Robert 			utcinfo->WN_t      = bGetShort (&buf4[31]);
2525ba371819SOllivier Robert 			utcinfo->WN_LSF    = bGetShort (&buf4[33]);
2526ba371819SOllivier Robert 			utcinfo->DN        = bGetShort (&buf4[35]);
2527ba371819SOllivier Robert 			utcinfo->delta_t_LSF = bGetShort (&buf4[37]);
2528ba371819SOllivier Robert 			break;
2529ba371819SOllivier Robert 
2530ba371819SOllivier Robert 		    case 6:
2531ba371819SOllivier Robert 			/* Ephemeris */
2532ba371819SOllivier Robert 			if (*data_length != sizeof (NAV_INFO) - 1) return TRUE;
2533ba371819SOllivier Robert 
2534ba371819SOllivier Robert 			navinfo = (NAV_INFO*)data_packet;
2535ba371819SOllivier Robert 
2536ba371819SOllivier Robert 			navinfo->sv_number = buf4[0];
2537ba371819SOllivier Robert 			navinfo->t_ephem = bGetSingle (&buf4[1]);
2538ba371819SOllivier Robert 			navinfo->ephclk.weeknum = bGetShort (&buf4[5]);
2539ba371819SOllivier Robert 
2540ba371819SOllivier Robert 			navinfo->ephclk.codeL2 = buf4[7];
2541ba371819SOllivier Robert 			navinfo->ephclk.L2Pdata = buf4[8];
2542ba371819SOllivier Robert 			navinfo->ephclk.SVacc_raw = buf4[9];
2543ba371819SOllivier Robert 			navinfo->ephclk.SV_health = buf4[10];
2544ba371819SOllivier Robert 			navinfo->ephclk.IODC = bGetShort (&buf4[11]);
2545ba371819SOllivier Robert 			navinfo->ephclk.T_GD = bGetSingle (&buf4[13]);
2546ba371819SOllivier Robert 			navinfo->ephclk.t_oc = bGetSingle (&buf4[17]);
2547ba371819SOllivier Robert 			navinfo->ephclk.a_f2 = bGetSingle (&buf4[21]);
2548ba371819SOllivier Robert 			navinfo->ephclk.a_f1 = bGetSingle (&buf4[25]);
2549ba371819SOllivier Robert 			navinfo->ephclk.a_f0 = bGetSingle (&buf4[29]);
2550ba371819SOllivier Robert 			navinfo->ephclk.SVacc = bGetSingle (&buf4[33]);
2551ba371819SOllivier Robert 
2552ba371819SOllivier Robert 			navinfo->ephorb.IODE = buf4[37];
2553ba371819SOllivier Robert 			navinfo->ephorb.fit_interval = buf4[38];
2554ba371819SOllivier Robert 			navinfo->ephorb.C_rs = bGetSingle (&buf4[39]);
2555ba371819SOllivier Robert 			navinfo->ephorb.delta_n = bGetSingle (&buf4[43]);
2556ba371819SOllivier Robert 			navinfo->ephorb.M_0 = bGetDouble (&buf4[47]);
2557ba371819SOllivier Robert 			navinfo->ephorb.C_uc = bGetSingle (&buf4[55]);
2558ba371819SOllivier Robert 			navinfo->ephorb.e = bGetDouble (&buf4[59]);
2559ba371819SOllivier Robert 			navinfo->ephorb.C_us = bGetSingle (&buf4[67]);
2560ba371819SOllivier Robert 			navinfo->ephorb.sqrt_A = bGetDouble (&buf4[71]);
2561ba371819SOllivier Robert 			navinfo->ephorb.t_oe = bGetSingle (&buf4[79]);
2562ba371819SOllivier Robert 			navinfo->ephorb.C_ic = bGetSingle (&buf4[83]);
2563ba371819SOllivier Robert 			navinfo->ephorb.OMEGA_0 = bGetDouble (&buf4[87]);
2564ba371819SOllivier Robert 			navinfo->ephorb.C_is = bGetSingle (&buf4[95]);
2565ba371819SOllivier Robert 			navinfo->ephorb.i_0 = bGetDouble (&buf4[99]);
2566ba371819SOllivier Robert 			navinfo->ephorb.C_rc = bGetSingle (&buf4[107]);
2567ba371819SOllivier Robert 			navinfo->ephorb.omega = bGetDouble (&buf4[111]);
2568ba371819SOllivier Robert 			navinfo->ephorb.OMEGADOT=bGetSingle (&buf4[119]);
2569ba371819SOllivier Robert 			navinfo->ephorb.IDOT = bGetSingle (&buf4[123]);
2570ba371819SOllivier Robert 			navinfo->ephorb.Axis = bGetDouble (&buf4[127]);
2571ba371819SOllivier Robert 			navinfo->ephorb.n = bGetDouble (&buf4[135]);
2572ba371819SOllivier Robert 			navinfo->ephorb.r1me2 = bGetDouble (&buf4[143]);
2573ba371819SOllivier Robert 			navinfo->ephorb.OMEGA_n=bGetDouble (&buf4[151]);
2574ba371819SOllivier Robert 			navinfo->ephorb.ODOT_n = bGetDouble (&buf4[159]);
2575ba371819SOllivier Robert 			break;
2576ba371819SOllivier Robert 		}
2577ba371819SOllivier Robert 	}
2578ba371819SOllivier Robert 	return FALSE;
2579ba371819SOllivier Robert }
2580ba371819SOllivier Robert 
2581ba371819SOllivier Robert /* satellite enable/disable or health heed/ignore list */
25822b15cb3dSCy Schubert short
25832b15cb3dSCy Schubert rpt_0x59(
25842b15cb3dSCy Schubert 	 TSIPPKT *rpt,
25852b15cb3dSCy Schubert 	 unsigned char *code_type,
25862b15cb3dSCy Schubert 	 unsigned char status_code[32]
25872b15cb3dSCy Schubert 	 )
2588ba371819SOllivier Robert {
2589ba371819SOllivier Robert 	short iprn;
2590ba371819SOllivier Robert 	unsigned char *buf;
2591ba371819SOllivier Robert 	buf = rpt->buf;
2592ba371819SOllivier Robert 
2593ba371819SOllivier Robert 	if (rpt->len != 33) return TRUE;
2594ba371819SOllivier Robert 	*code_type = buf[0];
2595ba371819SOllivier Robert 	for (iprn = 0; iprn < 32; iprn++)
2596ba371819SOllivier Robert 		status_code[iprn] = buf[iprn + 1];
2597ba371819SOllivier Robert 	return FALSE;
2598ba371819SOllivier Robert }
2599ba371819SOllivier Robert 
26002b15cb3dSCy Schubert /* raw measurement data - code phase/Doppler */
26012b15cb3dSCy Schubert short
26022b15cb3dSCy Schubert rpt_0x5A(
26032b15cb3dSCy Schubert 	 TSIPPKT *rpt,
2604ba371819SOllivier Robert 	 unsigned char *sv_prn,
2605ba371819SOllivier Robert 	 float *sample_length,
2606ba371819SOllivier Robert 	 float *signal_level,
2607ba371819SOllivier Robert 	 float *code_phase,
2608ba371819SOllivier Robert 	 float *Doppler,
26092b15cb3dSCy Schubert 	 double *time_of_fix
26102b15cb3dSCy Schubert 	 )
2611ba371819SOllivier Robert {
2612ba371819SOllivier Robert 	unsigned char *buf;
2613ba371819SOllivier Robert 	buf = rpt->buf;
2614ba371819SOllivier Robert 
2615ba371819SOllivier Robert 	if (rpt->len != 25) return TRUE;
2616ba371819SOllivier Robert 	*sv_prn = buf[0];
2617ba371819SOllivier Robert 	*sample_length = bGetSingle (&buf[1]);
2618ba371819SOllivier Robert 	*signal_level = bGetSingle (&buf[5]);
2619ba371819SOllivier Robert 	*code_phase = bGetSingle (&buf[9]);
2620ba371819SOllivier Robert 	*Doppler = bGetSingle (&buf[13]);
2621ba371819SOllivier Robert 	*time_of_fix = bGetDouble (&buf[17]);
2622ba371819SOllivier Robert 	return FALSE;
2623ba371819SOllivier Robert }
2624ba371819SOllivier Robert 
26252b15cb3dSCy Schubert /* satellite ephorb status */
26262b15cb3dSCy Schubert short
26272b15cb3dSCy Schubert rpt_0x5B(
26282b15cb3dSCy Schubert 	 TSIPPKT *rpt,
2629ba371819SOllivier Robert 	 unsigned char *sv_prn,
2630ba371819SOllivier Robert 	 unsigned char *sv_health,
2631ba371819SOllivier Robert 	 unsigned char *sv_iode,
2632ba371819SOllivier Robert 	 unsigned char *fit_interval_flag,
2633ba371819SOllivier Robert 	 float *time_of_collection,
2634ba371819SOllivier Robert 	 float *time_of_eph,
26352b15cb3dSCy Schubert 	 float *sv_accy
26362b15cb3dSCy Schubert 	 )
2637ba371819SOllivier Robert {
2638ba371819SOllivier Robert 	unsigned char *buf;
2639ba371819SOllivier Robert 	buf = rpt->buf;
2640ba371819SOllivier Robert 
2641ba371819SOllivier Robert 	if (rpt->len != 16) return TRUE;
2642ba371819SOllivier Robert 	*sv_prn = buf[0];
2643ba371819SOllivier Robert 	*time_of_collection = bGetSingle (&buf[1]);
2644ba371819SOllivier Robert 	*sv_health = buf[5];
2645ba371819SOllivier Robert 	*sv_iode = buf[6];
2646ba371819SOllivier Robert 	*time_of_eph = bGetSingle (&buf[7]);
2647ba371819SOllivier Robert 	*fit_interval_flag = buf[11];
2648ba371819SOllivier Robert 	*sv_accy = bGetSingle (&buf[12]);
2649ba371819SOllivier Robert 	return FALSE;
2650ba371819SOllivier Robert }
2651ba371819SOllivier Robert 
26522b15cb3dSCy Schubert /* satellite tracking status */
26532b15cb3dSCy Schubert short
26542b15cb3dSCy Schubert rpt_0x5C(
26552b15cb3dSCy Schubert 	 TSIPPKT *rpt,
2656ba371819SOllivier Robert 	 unsigned char *sv_prn,
2657ba371819SOllivier Robert 	 unsigned char *slot,
2658ba371819SOllivier Robert 	 unsigned char *chan,
2659ba371819SOllivier Robert 	 unsigned char *acq_flag,
2660ba371819SOllivier Robert 	 unsigned char *eph_flag,
2661ba371819SOllivier Robert 	 float *signal_level,
2662ba371819SOllivier Robert 	 float *time_of_last_msmt,
2663ba371819SOllivier Robert 	 float *elev,
2664ba371819SOllivier Robert 	 float *azim,
2665ba371819SOllivier Robert 	 unsigned char *old_msmt_flag,
2666ba371819SOllivier Robert 	 unsigned char *integer_msec_flag,
2667ba371819SOllivier Robert 	 unsigned char *bad_data_flag,
26682b15cb3dSCy Schubert 	 unsigned char *data_collect_flag
26692b15cb3dSCy Schubert 	 )
2670ba371819SOllivier Robert {
2671ba371819SOllivier Robert 	unsigned char *buf;
2672ba371819SOllivier Robert 	buf = rpt->buf;
2673ba371819SOllivier Robert 
2674ba371819SOllivier Robert 	if (rpt->len != 24) return TRUE;
2675ba371819SOllivier Robert 	*sv_prn = buf[0];
2676ba371819SOllivier Robert 	*slot = (unsigned char)((buf[1] & 0x07) + 1);
2677ba371819SOllivier Robert 	*chan = (unsigned char)(buf[1] >> 3);
2678ba371819SOllivier Robert 	if (*chan == 0x10) *chan = 2;
2679ba371819SOllivier Robert 	else (*chan)++;
2680ba371819SOllivier Robert 	*acq_flag = buf[2];
2681ba371819SOllivier Robert 	*eph_flag = buf[3];
2682ba371819SOllivier Robert 	*signal_level = bGetSingle (&buf[4]);
2683ba371819SOllivier Robert 	*time_of_last_msmt = bGetSingle (&buf[8]);
2684ba371819SOllivier Robert 	*elev = bGetSingle (&buf[12]);
2685ba371819SOllivier Robert 	*azim = bGetSingle (&buf[16]);
2686ba371819SOllivier Robert 	*old_msmt_flag = buf[20];
2687ba371819SOllivier Robert 	*integer_msec_flag = buf[21];
2688ba371819SOllivier Robert 	*bad_data_flag = buf[22];
2689ba371819SOllivier Robert 	*data_collect_flag = buf[23];
2690ba371819SOllivier Robert 	return FALSE;
2691ba371819SOllivier Robert }
2692ba371819SOllivier Robert 
2693ba371819SOllivier Robert /**/
26942b15cb3dSCy Schubert /* over-determined satellite selection for position fixes, PDOP, fix mode */
26952b15cb3dSCy Schubert short
26962b15cb3dSCy Schubert rpt_0x6D(
26972b15cb3dSCy Schubert 	 TSIPPKT *rpt,
2698ba371819SOllivier Robert 	 unsigned char *manual_mode,
2699ba371819SOllivier Robert 	 unsigned char *nsvs,
2700ba371819SOllivier Robert 	 unsigned char *ndim,
2701ba371819SOllivier Robert 	 unsigned char sv_prn[],
2702ba371819SOllivier Robert 	 float *pdop,
2703ba371819SOllivier Robert 	 float *hdop,
2704ba371819SOllivier Robert 	 float *vdop,
27052b15cb3dSCy Schubert 	 float *tdop
27062b15cb3dSCy Schubert 	 )
2707ba371819SOllivier Robert {
2708ba371819SOllivier Robert 	short islot;
2709ba371819SOllivier Robert 	unsigned char *buf;
2710ba371819SOllivier Robert 	buf = rpt->buf;
2711ba371819SOllivier Robert 
2712ba371819SOllivier Robert 	*nsvs = (unsigned char)((buf[0] & 0xF0) >> 4);
2713ba371819SOllivier Robert 	if ((*nsvs)>8) return TRUE;
2714ba371819SOllivier Robert 	if (rpt->len != 17 + (*nsvs) ) return TRUE;
2715ba371819SOllivier Robert 
2716ba371819SOllivier Robert 	*manual_mode = (unsigned char)(buf[0] & 0x08);
2717ba371819SOllivier Robert 	*ndim  = (unsigned char)((buf[0] & 0x07));
2718ba371819SOllivier Robert 	*pdop = bGetSingle (&buf[1]);
2719ba371819SOllivier Robert 	*hdop = bGetSingle (&buf[5]);
2720ba371819SOllivier Robert 	*vdop = bGetSingle (&buf[9]);
2721ba371819SOllivier Robert 	*tdop = bGetSingle (&buf[13]);
2722ba371819SOllivier Robert 	for (islot = 0; islot < (*nsvs); islot++)
2723ba371819SOllivier Robert 		sv_prn[islot] = buf[islot + 17];
2724ba371819SOllivier Robert 	return FALSE;
2725ba371819SOllivier Robert }
2726ba371819SOllivier Robert 
2727ba371819SOllivier Robert /**/
2728ba371819SOllivier Robert /* differential fix mode */
27292b15cb3dSCy Schubert short
27302b15cb3dSCy Schubert rpt_0x82(
27312b15cb3dSCy Schubert 	 TSIPPKT *rpt,
27322b15cb3dSCy Schubert 	 unsigned char *diff_mode
27332b15cb3dSCy Schubert 	 )
2734ba371819SOllivier Robert {
2735ba371819SOllivier Robert 	unsigned char *buf;
2736ba371819SOllivier Robert 	buf = rpt->buf;
2737ba371819SOllivier Robert 
2738ba371819SOllivier Robert 	if (rpt->len != 1) return TRUE;
2739ba371819SOllivier Robert 	*diff_mode = buf[0];
2740ba371819SOllivier Robert 	return FALSE;
2741ba371819SOllivier Robert }
2742ba371819SOllivier Robert 
27432b15cb3dSCy Schubert /* position, ECEF double precision */
27442b15cb3dSCy Schubert short
27452b15cb3dSCy Schubert rpt_0x83(
27462b15cb3dSCy Schubert 	 TSIPPKT *rpt,
2747ba371819SOllivier Robert 	 double ECEF_pos[3],
2748ba371819SOllivier Robert 	 double *clock_bias,
27492b15cb3dSCy Schubert 	 float *time_of_fix
27502b15cb3dSCy Schubert 	 )
2751ba371819SOllivier Robert {
2752ba371819SOllivier Robert 	unsigned char *buf;
2753ba371819SOllivier Robert 	buf = rpt->buf;
2754ba371819SOllivier Robert 
2755ba371819SOllivier Robert 	if (rpt->len != 36) return TRUE;
2756ba371819SOllivier Robert 	ECEF_pos[0] = bGetDouble (buf);
2757ba371819SOllivier Robert 	ECEF_pos[1] = bGetDouble (&buf[8]);
2758ba371819SOllivier Robert 	ECEF_pos[2] = bGetDouble (&buf[16]);
2759ba371819SOllivier Robert 	*clock_bias  = bGetDouble (&buf[24]);
2760ba371819SOllivier Robert 	*time_of_fix = bGetSingle (&buf[32]);
2761ba371819SOllivier Robert 	return FALSE;
2762ba371819SOllivier Robert }
2763ba371819SOllivier Robert 
27642b15cb3dSCy Schubert /* position, lat-lon-alt double precision */
27652b15cb3dSCy Schubert short
27662b15cb3dSCy Schubert rpt_0x84(
27672b15cb3dSCy Schubert 	 TSIPPKT *rpt,
2768ba371819SOllivier Robert 	 double *lat,
2769ba371819SOllivier Robert 	 double *lon,
2770ba371819SOllivier Robert 	 double *alt,
2771ba371819SOllivier Robert 	 double *clock_bias,
27722b15cb3dSCy Schubert 	 float *time_of_fix
27732b15cb3dSCy Schubert 	 )
2774ba371819SOllivier Robert {
2775ba371819SOllivier Robert 	unsigned char *buf;
2776ba371819SOllivier Robert 	buf = rpt->buf;
2777ba371819SOllivier Robert 
2778ba371819SOllivier Robert 	if (rpt->len != 36) return TRUE;
2779ba371819SOllivier Robert 	*lat = bGetDouble (buf);
2780ba371819SOllivier Robert 	*lon = bGetDouble (&buf[8]);
2781ba371819SOllivier Robert 	*alt = bGetDouble (&buf[16]);
2782ba371819SOllivier Robert 	*clock_bias = bGetDouble (&buf[24]);
2783ba371819SOllivier Robert 	*time_of_fix = bGetSingle (&buf[32]);
2784ba371819SOllivier Robert 	return FALSE;
2785ba371819SOllivier Robert }
2786ba371819SOllivier Robert 
27872b15cb3dSCy Schubert short
27882b15cb3dSCy Schubert rpt_Paly0xBB(
27892b15cb3dSCy Schubert 	     TSIPPKT *rpt,
27902b15cb3dSCy Schubert 	     TSIP_RCVR_CFG *TsipxBB
27912b15cb3dSCy Schubert 	     )
2792ba371819SOllivier Robert {
2793ba371819SOllivier Robert 	unsigned char *buf;
2794ba371819SOllivier Robert 	buf = rpt->buf;
2795ba371819SOllivier Robert 
27962b15cb3dSCy Schubert 	/* Palisade is inconsistent with other TSIP, which has a length of 40 */
2797ba371819SOllivier Robert 	/* if (rpt->len != 40) return TRUE; */
2798ba371819SOllivier Robert 	if (rpt->len != 43) return TRUE;
2799ba371819SOllivier Robert 
2800ba371819SOllivier Robert 	TsipxBB->bSubcode	=  buf[0];
2801ba371819SOllivier Robert 	TsipxBB->operating_mode	=  buf[1];
2802ba371819SOllivier Robert 	TsipxBB->dyn_code	=  buf[3];
2803ba371819SOllivier Robert 	TsipxBB->elev_mask	=  bGetSingle (&buf[5]);
2804ba371819SOllivier Robert 	TsipxBB->cno_mask	=  bGetSingle (&buf[9]);
2805ba371819SOllivier Robert 	TsipxBB->dop_mask 	=  bGetSingle (&buf[13]);
2806ba371819SOllivier Robert 	TsipxBB->dop_switch 	=  bGetSingle (&buf[17]);
2807ba371819SOllivier Robert 	return FALSE;
2808ba371819SOllivier Robert }
2809ba371819SOllivier Robert 
28102b15cb3dSCy Schubert /* Receiver serial port configuration */
28112b15cb3dSCy Schubert short
28122b15cb3dSCy Schubert rpt_0xBC(
28132b15cb3dSCy Schubert 	 TSIPPKT *rpt,
2814ba371819SOllivier Robert 	 unsigned char *port_num,
2815ba371819SOllivier Robert 	 unsigned char *in_baud,
2816ba371819SOllivier Robert 	 unsigned char *out_baud,
2817ba371819SOllivier Robert 	 unsigned char *data_bits,
2818ba371819SOllivier Robert 	 unsigned char *parity,
2819ba371819SOllivier Robert 	 unsigned char *stop_bits,
2820ba371819SOllivier Robert 	 unsigned char *flow_control,
2821ba371819SOllivier Robert 	 unsigned char *protocols_in,
2822ba371819SOllivier Robert 	 unsigned char *protocols_out,
28232b15cb3dSCy Schubert 	 unsigned char *reserved
28242b15cb3dSCy Schubert 	 )
2825ba371819SOllivier Robert {
2826ba371819SOllivier Robert 	unsigned char *buf;
2827ba371819SOllivier Robert 	buf = rpt->buf;
2828ba371819SOllivier Robert 
2829ba371819SOllivier Robert 	if (rpt->len != 10) return TRUE;
2830ba371819SOllivier Robert 	*port_num = buf[0];
2831ba371819SOllivier Robert 	*in_baud = buf[1];
2832ba371819SOllivier Robert 	*out_baud = buf[2];
2833ba371819SOllivier Robert 	*data_bits = buf[3];
2834ba371819SOllivier Robert 	*parity = buf[4];
2835ba371819SOllivier Robert 	*stop_bits = buf[5];
2836ba371819SOllivier Robert 	*flow_control = buf[6];
2837ba371819SOllivier Robert 	*protocols_in = buf[7];
2838ba371819SOllivier Robert 	*protocols_out = buf[8];
2839ba371819SOllivier Robert 	*reserved = buf[9];
2840ba371819SOllivier Robert 
2841ba371819SOllivier Robert 	return FALSE;
2842ba371819SOllivier Robert }
2843ba371819SOllivier Robert 
2844ba371819SOllivier Robert /**** Superpackets ****/
2845ba371819SOllivier Robert 
28462b15cb3dSCy Schubert short
28472b15cb3dSCy Schubert rpt_0x8F0B(
28482b15cb3dSCy Schubert 	   TSIPPKT *rpt,
2849ba371819SOllivier Robert 	   unsigned short *event,
2850ba371819SOllivier Robert 	   double *tow,
2851ba371819SOllivier Robert 	   unsigned char *date,
2852ba371819SOllivier Robert 	   unsigned char *month,
2853ba371819SOllivier Robert 	   short *year,
2854ba371819SOllivier Robert 	   unsigned char *dim_mode,
2855ba371819SOllivier Robert 	   short *utc_offset,
2856ba371819SOllivier Robert 	   double *bias,
2857ba371819SOllivier Robert 	   double *drift,
2858ba371819SOllivier Robert 	   float *bias_unc,
2859ba371819SOllivier Robert 	   float *dr_unc,
2860ba371819SOllivier Robert 	   double *lat,
2861ba371819SOllivier Robert 	   double *lon,
2862ba371819SOllivier Robert 	   double *alt,
28632b15cb3dSCy Schubert 	   char sv_id[8]
28642b15cb3dSCy Schubert 	   )
2865ba371819SOllivier Robert {
2866ba371819SOllivier Robert 	short local_index;
2867ba371819SOllivier Robert 	unsigned char *buf;
2868ba371819SOllivier Robert 
2869ba371819SOllivier Robert 	buf = rpt->buf;
2870ba371819SOllivier Robert 	if (rpt->len != 74) return TRUE;
2871ba371819SOllivier Robert 	*event = bGetShort(&buf[1]);
2872ba371819SOllivier Robert 	*tow = bGetDouble(&buf[3]);
2873ba371819SOllivier Robert 	*date = buf[11];
2874ba371819SOllivier Robert 	*month = buf[12];
2875ba371819SOllivier Robert 	*year = bGetShort(&buf[13]);
2876ba371819SOllivier Robert 	*dim_mode = buf[15];
2877ba371819SOllivier Robert 	*utc_offset = bGetShort(&buf[16]);
2878ba371819SOllivier Robert 	*bias = bGetDouble(&buf[18]);
2879ba371819SOllivier Robert 	*drift = bGetDouble(&buf[26]);
2880ba371819SOllivier Robert 	*bias_unc = bGetSingle(&buf[34]);
2881ba371819SOllivier Robert 	*dr_unc = bGetSingle(&buf[38]);
2882ba371819SOllivier Robert 	*lat = bGetDouble(&buf[42]);
2883ba371819SOllivier Robert 	*lon = bGetDouble(&buf[50]);
2884ba371819SOllivier Robert 	*alt = bGetDouble(&buf[58]);
2885ba371819SOllivier Robert 
2886ba371819SOllivier Robert 	for (local_index=0; local_index<8; local_index++) sv_id[local_index] = buf[local_index + 66];
2887ba371819SOllivier Robert 	return FALSE;
2888ba371819SOllivier Robert }
2889ba371819SOllivier Robert 
2890ba371819SOllivier Robert /* datum index and coefficients  */
28912b15cb3dSCy Schubert short
28922b15cb3dSCy Schubert rpt_0x8F14(
28932b15cb3dSCy Schubert 	   TSIPPKT *rpt,
28942b15cb3dSCy Schubert 	   short *datum_idx,
28952b15cb3dSCy Schubert 	   double datum_coeffs[5]
28962b15cb3dSCy Schubert 	   )
2897ba371819SOllivier Robert {
2898ba371819SOllivier Robert 	unsigned char *buf;
2899ba371819SOllivier Robert 	buf = rpt->buf;
2900ba371819SOllivier Robert 
2901ba371819SOllivier Robert 	if (rpt->len != 43) return TRUE;
2902ba371819SOllivier Robert 	*datum_idx = bGetShort(&buf[1]);
2903ba371819SOllivier Robert 	datum_coeffs[0] = bGetDouble (&buf[3]);
2904ba371819SOllivier Robert 	datum_coeffs[1] = bGetDouble (&buf[11]);
2905ba371819SOllivier Robert 	datum_coeffs[2] = bGetDouble (&buf[19]);
2906ba371819SOllivier Robert 	datum_coeffs[3] = bGetDouble (&buf[27]);
2907ba371819SOllivier Robert 	datum_coeffs[4] = bGetDouble (&buf[35]);
2908ba371819SOllivier Robert 	return FALSE;
2909ba371819SOllivier Robert }
2910ba371819SOllivier Robert 
2911ba371819SOllivier Robert 
2912ba371819SOllivier Robert /* datum index and coefficients  */
29132b15cb3dSCy Schubert short
29142b15cb3dSCy Schubert rpt_0x8F15(
29152b15cb3dSCy Schubert 	   TSIPPKT *rpt,
29162b15cb3dSCy Schubert 	   short *datum_idx,
29172b15cb3dSCy Schubert 	   double datum_coeffs[5]
29182b15cb3dSCy Schubert 	   )
2919ba371819SOllivier Robert {
2920ba371819SOllivier Robert 	unsigned char *buf;
2921ba371819SOllivier Robert 	buf = rpt->buf;
2922ba371819SOllivier Robert 
2923ba371819SOllivier Robert 	if (rpt->len != 43) return TRUE;
2924ba371819SOllivier Robert 	*datum_idx = bGetShort(&buf[1]);
2925ba371819SOllivier Robert 	datum_coeffs[0] = bGetDouble (&buf[3]);
2926ba371819SOllivier Robert 	datum_coeffs[1] = bGetDouble (&buf[11]);
2927ba371819SOllivier Robert 	datum_coeffs[2] = bGetDouble (&buf[19]);
2928ba371819SOllivier Robert 	datum_coeffs[3] = bGetDouble (&buf[27]);
2929ba371819SOllivier Robert 	datum_coeffs[4] = bGetDouble (&buf[35]);
2930ba371819SOllivier Robert 	return FALSE;
2931ba371819SOllivier Robert }
2932ba371819SOllivier Robert 
2933ba371819SOllivier Robert 
2934ba371819SOllivier Robert #define MAX_LONG  (2147483648.)   /* 2**31 */
2935ba371819SOllivier Robert 
29362b15cb3dSCy Schubert short
29372b15cb3dSCy Schubert rpt_0x8F20(
29382b15cb3dSCy Schubert 	   TSIPPKT *rpt,
2939ba371819SOllivier Robert 	   unsigned char *info,
2940ba371819SOllivier Robert 	   double *lat,
2941ba371819SOllivier Robert 	   double *lon,
2942ba371819SOllivier Robert 	   double *alt,
2943ba371819SOllivier Robert 	   double vel_enu[],
2944ba371819SOllivier Robert 	   double *time_of_fix,
2945ba371819SOllivier Robert 	   short *week_num,
2946ba371819SOllivier Robert 	   unsigned char *nsvs,
2947ba371819SOllivier Robert 	   unsigned char sv_prn[],
2948ba371819SOllivier Robert 	   short sv_IODC[],
29492b15cb3dSCy Schubert 	   short *datum_index
29502b15cb3dSCy Schubert 	   )
2951ba371819SOllivier Robert {
2952ba371819SOllivier Robert 	short
2953ba371819SOllivier Robert 	    isv;
2954ba371819SOllivier Robert 	unsigned char
2955ba371819SOllivier Robert 	    *buf, prnx, iode;
2956ba371819SOllivier Robert 	unsigned long
2957ba371819SOllivier Robert 	    ulongtemp;
2958ba371819SOllivier Robert 	long
2959ba371819SOllivier Robert 	    longtemp;
2960ba371819SOllivier Robert 	double
2961ba371819SOllivier Robert 	    vel_scale;
2962ba371819SOllivier Robert 
2963ba371819SOllivier Robert 	buf = rpt->buf;
2964ba371819SOllivier Robert 
2965ba371819SOllivier Robert 	if (rpt->len != 56) return TRUE;
2966ba371819SOllivier Robert 
2967ba371819SOllivier Robert 	vel_scale = (buf[24]&1)? 0.020 : 0.005;
2968ba371819SOllivier Robert 	vel_enu[0] = bGetShort (buf+2)*vel_scale;
2969ba371819SOllivier Robert 	vel_enu[1] = bGetShort (buf+4)*vel_scale;
2970ba371819SOllivier Robert 	vel_enu[2] = bGetShort (buf+6)*vel_scale;
2971ba371819SOllivier Robert 
2972ba371819SOllivier Robert 	*time_of_fix = bGetULong (buf+8)*.001;
2973ba371819SOllivier Robert 
2974ba371819SOllivier Robert 	longtemp = bGetLong (buf+12);
2975ba371819SOllivier Robert 	*lat = longtemp*(GPS_PI/MAX_LONG);
2976ba371819SOllivier Robert 
2977ba371819SOllivier Robert 	ulongtemp = bGetULong (buf+16);
2978ba371819SOllivier Robert 	*lon = ulongtemp*(GPS_PI/MAX_LONG);
2979ba371819SOllivier Robert 	if (*lon > GPS_PI) *lon -= 2.0*GPS_PI;
2980ba371819SOllivier Robert 
2981ba371819SOllivier Robert 	*alt = bGetLong (buf+20)*.001;
2982ba371819SOllivier Robert 	/* 25 blank; 29 = UTC */
2983ba371819SOllivier Robert 	(*datum_index) = (short)((short)buf[26]-1);
2984ba371819SOllivier Robert 	*info = buf[27];
2985ba371819SOllivier Robert 	*nsvs = buf[28];
2986ba371819SOllivier Robert 	*week_num = bGetShort (&buf[30]);
2987ba371819SOllivier Robert 	for (isv = 0; isv < 8; isv++) {
2988ba371819SOllivier Robert 		prnx = buf[32+2*isv];
2989ba371819SOllivier Robert 		sv_prn[isv] = (unsigned char)(prnx&0x3F);
2990ba371819SOllivier Robert 		iode = buf[33+2*isv];
2991ba371819SOllivier Robert 		sv_IODC[isv] = (short)(iode | ((prnx>>6)<<8));
2992ba371819SOllivier Robert 	}
2993ba371819SOllivier Robert 	return FALSE;
2994ba371819SOllivier Robert }
2995ba371819SOllivier Robert 
29962b15cb3dSCy Schubert short
29972b15cb3dSCy Schubert rpt_0x8F41(
29982b15cb3dSCy Schubert 	   TSIPPKT *rpt,
2999ba371819SOllivier Robert 	   unsigned char *bSearchRange,
3000ba371819SOllivier Robert 	   unsigned char *bBoardOptions,
3001ba371819SOllivier Robert 	   unsigned long *iiSerialNumber,
3002ba371819SOllivier Robert 	   unsigned char *bBuildYear,
3003ba371819SOllivier Robert 	   unsigned char *bBuildMonth,
3004ba371819SOllivier Robert 	   unsigned char *bBuildDay,
3005ba371819SOllivier Robert 	   unsigned char *bBuildHour,
3006ba371819SOllivier Robert 	   float *fOscOffset,
30072b15cb3dSCy Schubert 	   unsigned short *iTestCodeId
30082b15cb3dSCy Schubert 	   )
3009ba371819SOllivier Robert {
3010ba371819SOllivier Robert 	if (rpt->len != 17) return FALSE;
3011ba371819SOllivier Robert 	*bSearchRange = rpt->buf[1];
3012ba371819SOllivier Robert 	*bBoardOptions = rpt->buf[2];
3013ba371819SOllivier Robert 	*iiSerialNumber = bGetLong(&rpt->buf[3]);
3014ba371819SOllivier Robert 	*bBuildYear = rpt->buf[7];
3015ba371819SOllivier Robert 	*bBuildMonth = rpt->buf[8];
3016ba371819SOllivier Robert 	*bBuildDay = rpt->buf[9];
3017ba371819SOllivier Robert 	*bBuildHour =	rpt->buf[10];
3018ba371819SOllivier Robert 	*fOscOffset = bGetSingle(&rpt->buf[11]);
3019ba371819SOllivier Robert 	*iTestCodeId = bGetShort(&rpt->buf[15]);
3020ba371819SOllivier Robert /*	Tsipx8E41Data = *Tsipx8E41; */
3021ba371819SOllivier Robert 	return TRUE;
3022ba371819SOllivier Robert }
3023ba371819SOllivier Robert 
30242b15cb3dSCy Schubert short
30252b15cb3dSCy Schubert rpt_0x8F42(
30262b15cb3dSCy Schubert 	   TSIPPKT *rpt,
3027ba371819SOllivier Robert 	   unsigned char *bProdOptionsPre,
3028ba371819SOllivier Robert 	   unsigned char *bProdNumberExt,
3029ba371819SOllivier Robert 	   unsigned short *iCaseSerialNumberPre,
3030ba371819SOllivier Robert 	   unsigned long *iiCaseSerialNumber,
3031ba371819SOllivier Robert 	   unsigned long *iiProdNumber,
3032ba371819SOllivier Robert 	   unsigned short *iPremiumOptions,
3033ba371819SOllivier Robert 	   unsigned short *iMachineID,
30342b15cb3dSCy Schubert 	   unsigned short *iKey
30352b15cb3dSCy Schubert 	   )
3036ba371819SOllivier Robert {
3037ba371819SOllivier Robert 	if (rpt->len != 19) return FALSE;
3038ba371819SOllivier Robert 	*bProdOptionsPre = rpt->buf[1];
3039ba371819SOllivier Robert 	*bProdNumberExt = rpt->buf[2];
3040ba371819SOllivier Robert 	*iCaseSerialNumberPre = bGetShort(&rpt->buf[3]);
3041ba371819SOllivier Robert 	*iiCaseSerialNumber = bGetLong(&rpt->buf[5]);
3042ba371819SOllivier Robert 	*iiProdNumber = bGetLong(&rpt->buf[9]);
3043ba371819SOllivier Robert 	*iPremiumOptions = bGetShort(&rpt->buf[13]);
3044ba371819SOllivier Robert 	*iMachineID = bGetShort(&rpt->buf[15]);
3045ba371819SOllivier Robert 	*iKey = bGetShort(&rpt->buf[17]);
3046ba371819SOllivier Robert 	return TRUE;
3047ba371819SOllivier Robert }
3048ba371819SOllivier Robert 
30492b15cb3dSCy Schubert short
30502b15cb3dSCy Schubert rpt_0x8F45(
30512b15cb3dSCy Schubert 	   TSIPPKT *rpt,
30522b15cb3dSCy Schubert 	   unsigned char *bSegMask
30532b15cb3dSCy Schubert 	   )
3054ba371819SOllivier Robert {
3055ba371819SOllivier Robert 	if (rpt->len != 2) return FALSE;
3056ba371819SOllivier Robert 	*bSegMask = rpt->buf[1];
3057ba371819SOllivier Robert 	return TRUE;
3058ba371819SOllivier Robert }
3059ba371819SOllivier Robert 
30602b15cb3dSCy Schubert /* Stinger PPS definition */
30612b15cb3dSCy Schubert short
30622b15cb3dSCy Schubert rpt_0x8F4A_16(
30632b15cb3dSCy Schubert 	      TSIPPKT *rpt,
3064ba371819SOllivier Robert 	      unsigned char *pps_enabled,
3065ba371819SOllivier Robert 	      unsigned char *pps_timebase,
3066ba371819SOllivier Robert 	      unsigned char *pos_polarity,
3067ba371819SOllivier Robert 	      double *pps_offset,
30682b15cb3dSCy Schubert 	      float *bias_unc_threshold
30692b15cb3dSCy Schubert 	      )
3070ba371819SOllivier Robert {
3071ba371819SOllivier Robert 	unsigned char
3072ba371819SOllivier Robert 	    *buf;
3073ba371819SOllivier Robert 
3074ba371819SOllivier Robert 	buf = rpt->buf;
3075ba371819SOllivier Robert 	if (rpt->len != 16) return TRUE;
3076ba371819SOllivier Robert 	*pps_enabled = buf[1];
3077ba371819SOllivier Robert 	*pps_timebase = buf[2];
3078ba371819SOllivier Robert 	*pos_polarity = buf[3];
3079ba371819SOllivier Robert 	*pps_offset = bGetDouble(&buf[4]);
3080ba371819SOllivier Robert 	*bias_unc_threshold = bGetSingle(&buf[12]);
3081ba371819SOllivier Robert 	return FALSE;
3082ba371819SOllivier Robert }
3083ba371819SOllivier Robert 
30842b15cb3dSCy Schubert short
30852b15cb3dSCy Schubert rpt_0x8F4B(
30862b15cb3dSCy Schubert 	   TSIPPKT *rpt,
30872b15cb3dSCy Schubert 	   unsigned long *decorr_max
30882b15cb3dSCy Schubert 	   )
3089ba371819SOllivier Robert {
3090ba371819SOllivier Robert 	unsigned char
3091ba371819SOllivier Robert 	    *buf;
3092ba371819SOllivier Robert 
3093ba371819SOllivier Robert 	buf = rpt->buf;
3094ba371819SOllivier Robert 	if (rpt->len != 5) return TRUE;
3095ba371819SOllivier Robert 	*decorr_max = bGetLong(&buf[1]);
3096ba371819SOllivier Robert 	return FALSE;
3097ba371819SOllivier Robert }
3098ba371819SOllivier Robert 
30992b15cb3dSCy Schubert short
31002b15cb3dSCy Schubert rpt_0x8F4D(
31012b15cb3dSCy Schubert 	   TSIPPKT *rpt,
31022b15cb3dSCy Schubert 	   unsigned long *event_mask
31032b15cb3dSCy Schubert 	   )
3104ba371819SOllivier Robert {
3105ba371819SOllivier Robert 	unsigned char
3106ba371819SOllivier Robert 	    *buf;
3107ba371819SOllivier Robert 
3108ba371819SOllivier Robert 	buf = rpt->buf;
3109ba371819SOllivier Robert 	if (rpt->len != 5) return TRUE;
3110ba371819SOllivier Robert 	*event_mask = bGetULong (&buf[1]);
3111ba371819SOllivier Robert 	return FALSE;
3112ba371819SOllivier Robert }
3113ba371819SOllivier Robert 
31142b15cb3dSCy Schubert short
31152b15cb3dSCy Schubert rpt_0x8FA5(
31162b15cb3dSCy Schubert 	   TSIPPKT *rpt,
31172b15cb3dSCy Schubert 	   unsigned char *spktmask
31182b15cb3dSCy Schubert 	   )
3119ba371819SOllivier Robert {
3120ba371819SOllivier Robert 	unsigned char
3121ba371819SOllivier Robert 	    *buf;
3122ba371819SOllivier Robert 
3123ba371819SOllivier Robert 	buf = rpt->buf;
3124ba371819SOllivier Robert 	if (rpt->len != 5) return TRUE;
3125ba371819SOllivier Robert 	spktmask[0] = buf[1];
3126ba371819SOllivier Robert 	spktmask[1] = buf[2];
3127ba371819SOllivier Robert 	spktmask[2] = buf[3];
3128ba371819SOllivier Robert 	spktmask[3] = buf[4];
3129ba371819SOllivier Robert 	return FALSE;
3130ba371819SOllivier Robert }
3131ba371819SOllivier Robert 
31322b15cb3dSCy Schubert short
31332b15cb3dSCy Schubert rpt_0x8FAD(
31342b15cb3dSCy Schubert 	   TSIPPKT *rpt,
3135ba371819SOllivier Robert 	   unsigned short *COUNT,
3136ba371819SOllivier Robert 	   double *FracSec,
3137ba371819SOllivier Robert 	   unsigned char *Hour,
3138ba371819SOllivier Robert 	   unsigned char *Minute,
3139ba371819SOllivier Robert 	   unsigned char *Second,
3140ba371819SOllivier Robert 	   unsigned char *Day,
3141ba371819SOllivier Robert 	   unsigned char *Month,
3142ba371819SOllivier Robert 	   unsigned short *Year,
3143ba371819SOllivier Robert 	   unsigned char *Status,
31442b15cb3dSCy Schubert 	   unsigned char *Flags
31452b15cb3dSCy Schubert 	   )
3146ba371819SOllivier Robert {
3147ba371819SOllivier Robert 	if (rpt->len != 22) return TRUE;
3148ba371819SOllivier Robert 
3149ba371819SOllivier Robert 	*COUNT = bGetUShort(&rpt->buf[1]);
3150ba371819SOllivier Robert 	*FracSec = bGetDouble(&rpt->buf[3]);
3151ba371819SOllivier Robert 	*Hour = rpt->buf[11];
3152ba371819SOllivier Robert 	*Minute = rpt->buf[12];
3153ba371819SOllivier Robert 	*Second = rpt->buf[13];
3154ba371819SOllivier Robert 	*Day = rpt->buf[14];
3155ba371819SOllivier Robert 	*Month = rpt->buf[15];
3156ba371819SOllivier Robert 	*Year = bGetUShort(&rpt->buf[16]);
3157ba371819SOllivier Robert 	*Status = rpt->buf[18];
3158ba371819SOllivier Robert 	*Flags = rpt->buf[19];
3159ba371819SOllivier Robert 	return FALSE;
3160ba371819SOllivier Robert }
3161ba371819SOllivier Robert 
3162ba371819SOllivier Robert 
3163ba371819SOllivier Robert /*
3164ba371819SOllivier Robert  * *************************************************************************
3165ba371819SOllivier Robert  *
3166ba371819SOllivier Robert  * Trimble Navigation, Ltd.
3167ba371819SOllivier Robert  * OEM Products Development Group
3168ba371819SOllivier Robert  * P.O. Box 3642
3169ba371819SOllivier Robert  * 645 North Mary Avenue
3170ba371819SOllivier Robert  * Sunnyvale, California 94088-3642
3171ba371819SOllivier Robert  *
3172ba371819SOllivier Robert  * Corporate Headquarter:
3173ba371819SOllivier Robert  *    Telephone:  (408) 481-8000
3174ba371819SOllivier Robert  *    Fax:        (408) 481-6005
3175ba371819SOllivier Robert  *
3176ba371819SOllivier Robert  * Technical Support Center:
3177ba371819SOllivier Robert  *    Telephone:  (800) 767-4822	(U.S. and Canada)
3178ba371819SOllivier Robert  *                (408) 481-6940    (outside U.S. and Canada)
3179ba371819SOllivier Robert  *    Fax:        (408) 481-6020
3180ba371819SOllivier Robert  *    BBS:        (408) 481-7800
3181ba371819SOllivier Robert  *    e-mail:     trimble_support@trimble.com
3182ba371819SOllivier Robert  *		ftp://ftp.trimble.com/pub/sct/embedded/bin
3183ba371819SOllivier Robert  *
3184ba371819SOllivier Robert  * *************************************************************************
3185ba371819SOllivier Robert  *
3186ba371819SOllivier Robert  * T_REPORT.C consists of a primary function TranslateTSIPReportToText()
3187ba371819SOllivier Robert  * called by main().
3188ba371819SOllivier Robert  *
3189ba371819SOllivier Robert  * This function takes a character buffer that has been received as a report
3190ba371819SOllivier Robert  * from a TSIP device and interprets it.  The character buffer has been
3191ba371819SOllivier Robert  * assembled using tsip_input_proc() in T_PARSER.C.
3192ba371819SOllivier Robert  *
3193ba371819SOllivier Robert  * A large case statement directs processing to one of many mid-level
3194ba371819SOllivier Robert  * functions.  The mid-level functions specific to the current report
3195ba371819SOllivier Robert  * code passes the report buffer to the appropriate report decoder
3196ba371819SOllivier Robert  * rpt_0x?? () in T_PARSER.C, which converts the byte stream in rpt.buf
3197ba371819SOllivier Robert  * to data values approporaite for use.
3198ba371819SOllivier Robert  *
3199ba371819SOllivier Robert  * *************************************************************************
3200ba371819SOllivier Robert  *
3201ba371819SOllivier Robert  */
3202ba371819SOllivier Robert 
3203ba371819SOllivier Robert 
3204ba371819SOllivier Robert #define GOOD_PARSE 0
3205ba371819SOllivier Robert #define BADID_PARSE 1
3206ba371819SOllivier Robert #define BADLEN_PARSE 2
3207ba371819SOllivier Robert #define BADDATA_PARSE 3
3208ba371819SOllivier Robert 
3209ba371819SOllivier Robert #define B_TSIP	0x02
3210ba371819SOllivier Robert #define B_NMEA	0x04
3211ba371819SOllivier Robert 
3212ba371819SOllivier Robert 
3213ba371819SOllivier Robert /* pbuf is the pointer to the current location of the text output */
3214ba371819SOllivier Robert static char
3215ba371819SOllivier Robert *pbuf;
3216ba371819SOllivier Robert 
3217ba371819SOllivier Robert /* keep track of whether the message has been successfully parsed */
3218ba371819SOllivier Robert static short
3219ba371819SOllivier Robert parsed;
3220ba371819SOllivier Robert 
3221ba371819SOllivier Robert 
3222ba371819SOllivier Robert /* convert time of week into day-hour-minute-second and print */
32232b15cb3dSCy Schubert char *
32242b15cb3dSCy Schubert show_time(
32252b15cb3dSCy Schubert 	  float time_of_week
32262b15cb3dSCy Schubert 	  )
3227ba371819SOllivier Robert {
3228ba371819SOllivier Robert 	short	days, hours, minutes;
3229ba371819SOllivier Robert 	float seconds;
3230ba371819SOllivier Robert 	double tow = 0;
3231ba371819SOllivier Robert 	static char timestring [80];
3232ba371819SOllivier Robert 
3233ba371819SOllivier Robert 	if (time_of_week == -1.0)
3234ba371819SOllivier Robert 	{
3235ba371819SOllivier Robert 		sprintf(timestring, "   <No time yet>   ");
3236ba371819SOllivier Robert 	}
3237ba371819SOllivier Robert 	else if ((time_of_week >= 604800.0) || (time_of_week < 0.0))
3238ba371819SOllivier Robert 	{
3239ba371819SOllivier Robert 		sprintf(timestring, "     <Bad time>     ");
3240ba371819SOllivier Robert 	}
3241ba371819SOllivier Robert 	else
3242ba371819SOllivier Robert 	{
3243ba371819SOllivier Robert 		if (time_of_week < 604799.9)
3244ba371819SOllivier Robert 			tow = time_of_week + .00000001;
3245ba371819SOllivier Robert 		seconds = (float)fmod(tow, 60.);
3246ba371819SOllivier Robert 		minutes =  (short) fmod(tow/60., 60.);
3247ba371819SOllivier Robert 		hours = (short)fmod(tow / 3600., 24.);
3248ba371819SOllivier Robert 		days = (short)(tow / 86400.0);
3249ba371819SOllivier Robert 		sprintf(timestring, " %s %02d:%02d:%05.2f   ",
3250ba371819SOllivier Robert 			dayname[days], hours, minutes, seconds);
3251ba371819SOllivier Robert 	}
3252ba371819SOllivier Robert 	return timestring;
3253ba371819SOllivier Robert }
3254ba371819SOllivier Robert 
3255ba371819SOllivier Robert /**/
3256ba371819SOllivier Robert /* 0x3D */
32572b15cb3dSCy Schubert static void
32582b15cb3dSCy Schubert rpt_chan_A_config(
32592b15cb3dSCy Schubert 		  TSIPPKT *rpt
32602b15cb3dSCy Schubert 		  )
3261ba371819SOllivier Robert {
3262ba371819SOllivier Robert 	unsigned char
3263ba371819SOllivier Robert 	    tx_baud_index, rx_baud_index,
3264ba371819SOllivier Robert 	    char_format_index, stop_bits,
3265ba371819SOllivier Robert 	    tx_mode_index, rx_mode_index,
3266ba371819SOllivier Robert 	    databits, parity;
3267ba371819SOllivier Robert 	int
3268ba371819SOllivier Robert 	    i, nbaud;
3269ba371819SOllivier Robert 
3270ba371819SOllivier Robert 	/* unload rptbuf */
3271ba371819SOllivier Robert 	if (rpt_0x3D (rpt,
3272ba371819SOllivier Robert 		      &tx_baud_index, &rx_baud_index, &char_format_index,
3273ba371819SOllivier Robert 		      &stop_bits, &tx_mode_index, &rx_mode_index)) {
3274ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
3275ba371819SOllivier Robert 		return;
3276ba371819SOllivier Robert 	}
3277ba371819SOllivier Robert 
3278ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nChannel A Configuration");
3279ba371819SOllivier Robert 
3280ba371819SOllivier Robert 	nbaud = sizeof(old_baudnum);
3281ba371819SOllivier Robert 
3282ba371819SOllivier Robert 	for (i = 0; i < nbaud; ++i) if (tx_baud_index == old_baudnum[i]) break;
3283ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   Transmit speed: %s at %s",
3284ba371819SOllivier Robert 			old_output_ch[tx_mode_index], st_baud_text_app[i]);
3285ba371819SOllivier Robert 
3286ba371819SOllivier Robert 	for (i = 0; i < nbaud; ++i) if (rx_baud_index == old_baudnum[i]) break;
3287ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   Receive speed: %s at %s",
3288ba371819SOllivier Robert 			old_input_ch[rx_mode_index], st_baud_text_app[i]);
3289ba371819SOllivier Robert 
3290ba371819SOllivier Robert 	databits = (unsigned char)((char_format_index & 0x03) + 5);
3291ba371819SOllivier Robert 
3292ba371819SOllivier Robert 	parity = (unsigned char)(char_format_index >> 2);
3293ba371819SOllivier Robert 	if (parity > 4) parity = 2;
3294ba371819SOllivier Robert 
3295ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   Character format (bits/char, parity, stop bits): %d-%s-%d",
3296ba371819SOllivier Robert 			databits, old_parity_text[parity], stop_bits);
3297ba371819SOllivier Robert }
3298ba371819SOllivier Robert 
3299ba371819SOllivier Robert /**/
3300ba371819SOllivier Robert /* 0x40 */
33012b15cb3dSCy Schubert static void
33022b15cb3dSCy Schubert rpt_almanac_data_page(
33032b15cb3dSCy Schubert 		      TSIPPKT *rpt
33042b15cb3dSCy Schubert 		      )
3305ba371819SOllivier Robert {
3306ba371819SOllivier Robert 	unsigned char
3307ba371819SOllivier Robert 	    sv_prn;
3308ba371819SOllivier Robert 	short
3309ba371819SOllivier Robert 	    week_num;
3310ba371819SOllivier Robert 	float
3311ba371819SOllivier Robert 	    t_zc,
3312ba371819SOllivier Robert 	    eccentricity,
3313ba371819SOllivier Robert 	    t_oa,
3314ba371819SOllivier Robert 	    i_0,
3315ba371819SOllivier Robert 	    OMEGA_dot,
3316ba371819SOllivier Robert 	    sqrt_A,
3317ba371819SOllivier Robert 	    OMEGA_0,
3318ba371819SOllivier Robert 	    omega,
3319ba371819SOllivier Robert 	    M_0;
3320ba371819SOllivier Robert 
3321ba371819SOllivier Robert 	/* unload rptbuf */
3322ba371819SOllivier Robert 	if (rpt_0x40 (rpt,
3323ba371819SOllivier Robert 		      &sv_prn, &week_num, &t_zc, &eccentricity, &t_oa,
3324ba371819SOllivier Robert 		      &i_0, &OMEGA_dot, &sqrt_A, &OMEGA_0, &omega, &M_0)) {
3325ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
3326ba371819SOllivier Robert 		return;
3327ba371819SOllivier Robert 	}
3328ba371819SOllivier Robert 
3329ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nAlmanac for SV %02d", sv_prn);
3330ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n       Captured:%15.0f %s",
3331ba371819SOllivier Robert 			t_zc, show_time (t_zc));
3332ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n           week:%15d", week_num);
3333ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   Eccentricity:%15g", eccentricity);
3334ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n           T_oa:%15.0f %s",
3335ba371819SOllivier Robert 			t_oa, show_time (t_oa));
3336ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n            i 0:%15g", i_0);
3337ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n      OMEGA dot:%15g", OMEGA_dot);
3338ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n         sqrt A:%15g", sqrt_A);
3339ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n        OMEGA 0:%15g", OMEGA_0);
3340ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n          omega:%15g", omega);
3341ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n            M 0:%15g", M_0);
3342ba371819SOllivier Robert }
3343ba371819SOllivier Robert 
3344ba371819SOllivier Robert /* 0x41 */
33452b15cb3dSCy Schubert static void
33462b15cb3dSCy Schubert rpt_GPS_time(
33472b15cb3dSCy Schubert 	     TSIPPKT *rpt
33482b15cb3dSCy Schubert 	     )
3349ba371819SOllivier Robert {
3350ba371819SOllivier Robert 	float
3351ba371819SOllivier Robert 	    time_of_week, UTC_offset;
3352ba371819SOllivier Robert 	short
3353ba371819SOllivier Robert 	    week_num;
3354ba371819SOllivier Robert 
3355ba371819SOllivier Robert 	/* unload rptbuf */
3356ba371819SOllivier Robert 	if (rpt_0x41 (rpt, &time_of_week, &UTC_offset, &week_num)) {
3357ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
3358ba371819SOllivier Robert 		return;
3359ba371819SOllivier Robert 	}
3360ba371819SOllivier Robert 
3361ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nGPS time:%s GPS week: %d   UTC offset %.1f",
3362ba371819SOllivier Robert 			show_time(time_of_week), week_num, UTC_offset);
3363ba371819SOllivier Robert 
3364ba371819SOllivier Robert }
3365ba371819SOllivier Robert 
3366ba371819SOllivier Robert /* 0x42 */
33672b15cb3dSCy Schubert static void
33682b15cb3dSCy Schubert rpt_single_ECEF_position(
33692b15cb3dSCy Schubert 			 TSIPPKT *rpt
33702b15cb3dSCy Schubert 			 )
3371ba371819SOllivier Robert {
3372ba371819SOllivier Robert 	float
3373ba371819SOllivier Robert 	    ECEF_pos[3], time_of_fix;
3374ba371819SOllivier Robert 
3375ba371819SOllivier Robert 	/* unload rptbuf */
3376ba371819SOllivier Robert 	if (rpt_0x42 (rpt, ECEF_pos, &time_of_fix)) {
3377ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
3378ba371819SOllivier Robert 		return;
3379ba371819SOllivier Robert 	}
3380ba371819SOllivier Robert 
3381ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nSXYZ:  %15.0f  %15.0f  %15.0f    %s",
3382ba371819SOllivier Robert 			ECEF_pos[0], ECEF_pos[1], ECEF_pos[2],
3383ba371819SOllivier Robert 			show_time(time_of_fix));
3384ba371819SOllivier Robert }
3385ba371819SOllivier Robert 
3386ba371819SOllivier Robert /* 0x43 */
33872b15cb3dSCy Schubert static void
33882b15cb3dSCy Schubert rpt_single_ECEF_velocity(
33892b15cb3dSCy Schubert 			 TSIPPKT *rpt
33902b15cb3dSCy Schubert 			 )
3391ba371819SOllivier Robert {
3392ba371819SOllivier Robert 
3393ba371819SOllivier Robert 	float
3394ba371819SOllivier Robert 	    ECEF_vel[3], freq_offset, time_of_fix;
3395ba371819SOllivier Robert 
3396ba371819SOllivier Robert 	/* unload rptbuf */
3397ba371819SOllivier Robert 	if (rpt_0x43 (rpt, ECEF_vel, &freq_offset, &time_of_fix)) {
3398ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
3399ba371819SOllivier Robert 		return;
3400ba371819SOllivier Robert 	}
3401ba371819SOllivier Robert 
3402ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nVelECEF: %11.3f  %11.3f  %11.3f  %12.3f%s",
3403ba371819SOllivier Robert 			ECEF_vel[0], ECEF_vel[1], ECEF_vel[2], freq_offset,
3404ba371819SOllivier Robert 			show_time(time_of_fix));
3405ba371819SOllivier Robert }
3406ba371819SOllivier Robert 
3407ba371819SOllivier Robert /*  0x45  */
34082b15cb3dSCy Schubert static void
34092b15cb3dSCy Schubert rpt_SW_version(
34102b15cb3dSCy Schubert 	       TSIPPKT *rpt
34112b15cb3dSCy Schubert 	       )
34122b15cb3dSCy Schubert {
3413ba371819SOllivier Robert 	unsigned char
3414ba371819SOllivier Robert 	    major_nav_version, minor_nav_version,
3415ba371819SOllivier Robert 	    nav_day, nav_month, nav_year,
3416ba371819SOllivier Robert 	    major_dsp_version, minor_dsp_version,
3417ba371819SOllivier Robert 	    dsp_day, dsp_month, dsp_year;
3418ba371819SOllivier Robert 
3419ba371819SOllivier Robert 	/* unload rptbuf */
3420ba371819SOllivier Robert 	if (rpt_0x45 (rpt,
3421ba371819SOllivier Robert 		      &major_nav_version, &minor_nav_version,
3422ba371819SOllivier Robert 		      &nav_day, &nav_month, &nav_year,
3423ba371819SOllivier Robert 		      &major_dsp_version, &minor_dsp_version,
3424ba371819SOllivier Robert 		      &dsp_day, &dsp_month, &dsp_year)) {
3425ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
3426ba371819SOllivier Robert 		return;
3427ba371819SOllivier Robert 	}
3428ba371819SOllivier Robert 
3429ba371819SOllivier Robert 	pbuf += sprintf(pbuf,
3430ba371819SOllivier Robert 			"\nFW Versions:  Nav Proc %2d.%02d  %2d/%2d/%2d  Sig Proc %2d.%02d  %2d/%2d/%2d",
3431ba371819SOllivier Robert 			major_nav_version, minor_nav_version, nav_day, nav_month, nav_year,
3432ba371819SOllivier Robert 			major_dsp_version, minor_dsp_version, dsp_day, dsp_month, dsp_year);
3433ba371819SOllivier Robert }
3434ba371819SOllivier Robert 
3435ba371819SOllivier Robert /* 0x46 */
34362b15cb3dSCy Schubert static void
34372b15cb3dSCy Schubert rpt_rcvr_health(
34382b15cb3dSCy Schubert 		TSIPPKT *rpt
34392b15cb3dSCy Schubert 		)
3440ba371819SOllivier Robert {
3441ba371819SOllivier Robert 	unsigned char
3442ba371819SOllivier Robert 	    status1, status2;
34432b15cb3dSCy Schubert 	const char
34442b15cb3dSCy Schubert 	    *text;
34452b15cb3dSCy Schubert 	static const char const
3446ba371819SOllivier Robert 	    *sc_text[] = {
3447ba371819SOllivier Robert 		"Doing position fixes",
3448ba371819SOllivier Robert 		"Don't have GPS time yet",
3449ba371819SOllivier Robert 		"Waiting for almanac collection",
3450ba371819SOllivier Robert 		"DOP too high          ",
3451ba371819SOllivier Robert 		"No satellites available",
3452ba371819SOllivier Robert 		"Only 1 satellite available",
3453ba371819SOllivier Robert 		"Only 2 satellites available",
3454ba371819SOllivier Robert 		"Only 3 satellites available",
3455ba371819SOllivier Robert 		"No satellites usable   ",
3456ba371819SOllivier Robert 		"Only 1 satellite usable",
3457ba371819SOllivier Robert 		"Only 2 satellites usable",
3458ba371819SOllivier Robert 		"Only 3 satellites usable",
3459ba371819SOllivier Robert 		"Chosen satellite unusable"};
3460ba371819SOllivier Robert 
3461ba371819SOllivier Robert 
3462ba371819SOllivier Robert 	/* unload rptbuf */
3463ba371819SOllivier Robert 	if (rpt_0x46 (rpt, &status1, &status2))
3464ba371819SOllivier Robert 	{
3465ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
3466ba371819SOllivier Robert 		return;
3467ba371819SOllivier Robert 	}
3468ba371819SOllivier Robert 
34692b15cb3dSCy Schubert 	text = (status1 < COUNTOF(sc_text))
34702b15cb3dSCy Schubert 	    ? sc_text[status1]
34712b15cb3dSCy Schubert 	    : "(out of range)";
3472ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nRcvr status1: %s (%02Xh); ",
34732b15cb3dSCy Schubert 			text, status1);
3474ba371819SOllivier Robert 
3475ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "status2: %s, %s (%02Xh)",
3476ba371819SOllivier Robert 			(status2 & 0x01)?"No BBRAM":"BBRAM OK",
3477ba371819SOllivier Robert 			(status2 & 0x10)?"No Ant":"Ant OK",
3478ba371819SOllivier Robert 			status2);
3479ba371819SOllivier Robert }
3480ba371819SOllivier Robert 
3481ba371819SOllivier Robert /* 0x47 */
34822b15cb3dSCy Schubert static void
34832b15cb3dSCy Schubert rpt_SNR_all_SVs(
34842b15cb3dSCy Schubert 		TSIPPKT *rpt
34852b15cb3dSCy Schubert 		)
3486ba371819SOllivier Robert {
3487ba371819SOllivier Robert 	unsigned char
3488ba371819SOllivier Robert 	    nsvs, sv_prn[12];
3489ba371819SOllivier Robert 	short
3490ba371819SOllivier Robert 	    isv;
3491ba371819SOllivier Robert 	float
3492ba371819SOllivier Robert 	    snr[12];
3493ba371819SOllivier Robert 
3494ba371819SOllivier Robert 	/* unload rptbuf */
3495ba371819SOllivier Robert 	if (rpt_0x47 (rpt, &nsvs, sv_prn, snr))
3496ba371819SOllivier Robert 	{
3497ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
3498ba371819SOllivier Robert 		return;
3499ba371819SOllivier Robert 	}
3500ba371819SOllivier Robert 
3501ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nSNR for satellites: %d", nsvs);
3502ba371819SOllivier Robert 	for (isv = 0; isv < nsvs; isv++)
3503ba371819SOllivier Robert 	{
3504ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\n    SV %02d   %6.2f",
3505ba371819SOllivier Robert 				sv_prn[isv], snr[isv]);
3506ba371819SOllivier Robert 	}
3507ba371819SOllivier Robert }
3508ba371819SOllivier Robert 
3509ba371819SOllivier Robert /* 0x48 */
35102b15cb3dSCy Schubert static void
35112b15cb3dSCy Schubert rpt_GPS_system_message(
35122b15cb3dSCy Schubert 		       TSIPPKT *rpt
35132b15cb3dSCy Schubert 		       )
3514ba371819SOllivier Robert {
3515ba371819SOllivier Robert 	unsigned char
3516ba371819SOllivier Robert 	    message[23];
3517ba371819SOllivier Robert 
3518ba371819SOllivier Robert 	/* unload rptbuf */
3519ba371819SOllivier Robert 	if (rpt_0x48 (rpt, message))
3520ba371819SOllivier Robert 	{
3521ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
3522ba371819SOllivier Robert 		return;
3523ba371819SOllivier Robert 	}
3524ba371819SOllivier Robert 
3525ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nGPS message: %s", message);
3526ba371819SOllivier Robert }
3527ba371819SOllivier Robert 
3528ba371819SOllivier Robert /* 0x49 */
35292b15cb3dSCy Schubert static void
35302b15cb3dSCy Schubert rpt_almanac_health_page(
35312b15cb3dSCy Schubert 			TSIPPKT *rpt
35322b15cb3dSCy Schubert 			)
3533ba371819SOllivier Robert {
3534ba371819SOllivier Robert 	short
3535ba371819SOllivier Robert 	    iprn;
3536ba371819SOllivier Robert 	unsigned char
3537ba371819SOllivier Robert 	    sv_health [32];
3538ba371819SOllivier Robert 
3539ba371819SOllivier Robert 	/* unload rptbuf */
3540ba371819SOllivier Robert 	if (rpt_0x49 (rpt, sv_health))
3541ba371819SOllivier Robert 	{
3542ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
3543ba371819SOllivier Robert 		return;
3544ba371819SOllivier Robert 	}
3545ba371819SOllivier Robert 
3546ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nAlmanac health page:");
3547ba371819SOllivier Robert 	for (iprn = 0; iprn < 32; iprn++)
3548ba371819SOllivier Robert 	{
3549ba371819SOllivier Robert 		if (!(iprn%5)) *pbuf++ = '\n';
3550ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "    SV%02d  %2X",
3551ba371819SOllivier Robert 				(iprn+1) , sv_health[iprn]);
3552ba371819SOllivier Robert 	}
3553ba371819SOllivier Robert }
3554ba371819SOllivier Robert 
3555ba371819SOllivier Robert /* 0x4A */
35562b15cb3dSCy Schubert static void
35572b15cb3dSCy Schubert rpt_single_lla_position(
35582b15cb3dSCy Schubert 			TSIPPKT *rpt
35592b15cb3dSCy Schubert 			)
35602b15cb3dSCy Schubert {
3561ba371819SOllivier Robert 	short
3562ba371819SOllivier Robert 	    lat_deg, lon_deg;
3563ba371819SOllivier Robert 	float
3564ba371819SOllivier Robert 	    lat, lon,
3565ba371819SOllivier Robert 	    alt, clock_bias, time_of_fix;
3566ba371819SOllivier Robert 	double lat_min, lon_min;
3567ba371819SOllivier Robert 	unsigned char
3568ba371819SOllivier Robert 	    north_south, east_west;
3569ba371819SOllivier Robert 
3570ba371819SOllivier Robert 	if (rpt_0x4A (rpt,
3571ba371819SOllivier Robert 		      &lat, &lon, &alt, &clock_bias, &time_of_fix))
3572ba371819SOllivier Robert 	{
3573ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
3574ba371819SOllivier Robert 		return;
3575ba371819SOllivier Robert 	}
3576ba371819SOllivier Robert 
3577ba371819SOllivier Robert 	/* convert from radians to degrees */
3578ba371819SOllivier Robert 	lat *= (float)R2D;
3579ba371819SOllivier Robert 	north_south = 'N';
3580ba371819SOllivier Robert 	if (lat < 0.0)
3581ba371819SOllivier Robert 	{
3582ba371819SOllivier Robert 		north_south = 'S';
3583ba371819SOllivier Robert 		lat = -lat;
3584ba371819SOllivier Robert 	}
3585ba371819SOllivier Robert 	lat_deg = (short)lat;
3586ba371819SOllivier Robert 	lat_min = (lat - lat_deg) * 60.0;
3587ba371819SOllivier Robert 
3588ba371819SOllivier Robert 	lon *= (float)R2D;
3589ba371819SOllivier Robert 	east_west = 'E';
3590ba371819SOllivier Robert 	if (lon < 0.0)
3591ba371819SOllivier Robert 	{
3592ba371819SOllivier Robert 		east_west = 'W';
3593ba371819SOllivier Robert 		lon = -lon;
3594ba371819SOllivier Robert 	}
3595ba371819SOllivier Robert 	lon_deg = (short)lon;
3596ba371819SOllivier Robert 	lon_min = (lon - lon_deg) * 60.0;
3597ba371819SOllivier Robert 
3598ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nSLLA: %4d: %06.3f  %c%5d:%06.3f  %c%10.2f  %12.2f%s",
3599ba371819SOllivier Robert 			lat_deg, lat_min, north_south,
3600ba371819SOllivier Robert 			lon_deg, lon_min, east_west,
3601ba371819SOllivier Robert 			alt, clock_bias,
3602ba371819SOllivier Robert 			show_time(time_of_fix));
3603ba371819SOllivier Robert }
3604ba371819SOllivier Robert 
3605ba371819SOllivier Robert /* 0x4A */
36062b15cb3dSCy Schubert static void
36072b15cb3dSCy Schubert rpt_ref_alt(
36082b15cb3dSCy Schubert 	    TSIPPKT *rpt
36092b15cb3dSCy Schubert 	    )
36102b15cb3dSCy Schubert {
3611ba371819SOllivier Robert 	float
3612ba371819SOllivier Robert 	    alt, dummy;
3613ba371819SOllivier Robert 	unsigned char
3614ba371819SOllivier Robert 	    alt_flag;
3615ba371819SOllivier Robert 
36162b15cb3dSCy Schubert 	if (rpt_0x4A_2 (rpt, &alt, &dummy, &alt_flag))
3617ba371819SOllivier Robert 	{
3618ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
3619ba371819SOllivier Robert 		return;
3620ba371819SOllivier Robert 	}
3621ba371819SOllivier Robert 
3622ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nReference Alt:   %.1f m;    %s",
3623ba371819SOllivier Robert 			alt, alt_flag?"ON":"OFF");
3624ba371819SOllivier Robert }
3625ba371819SOllivier Robert 
3626ba371819SOllivier Robert /* 0x4B */
36272b15cb3dSCy Schubert static void
36282b15cb3dSCy Schubert rpt_rcvr_id_and_status(
36292b15cb3dSCy Schubert 		       TSIPPKT *rpt
36302b15cb3dSCy Schubert 		       )
3631ba371819SOllivier Robert {
3632ba371819SOllivier Robert 
3633ba371819SOllivier Robert 	unsigned char
3634ba371819SOllivier Robert 	    machine_id, status3, status4;
3635ba371819SOllivier Robert 
3636ba371819SOllivier Robert 	/* unload rptbuf */
3637ba371819SOllivier Robert 	if (rpt_0x4B (rpt, &machine_id, &status3, &status4))
3638ba371819SOllivier Robert 	{
3639ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
3640ba371819SOllivier Robert 		return;
3641ba371819SOllivier Robert 	}
3642ba371819SOllivier Robert 
3643ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nRcvr Machine ID: %d; Status3 = %s, %s (%02Xh)",
3644ba371819SOllivier Robert 			machine_id,
3645ba371819SOllivier Robert 			(status3 & 0x02)?"No RTC":"RTC OK",
3646ba371819SOllivier Robert 			(status3 & 0x08)?"No Alm":"Alm OK",
3647ba371819SOllivier Robert 			status3);
3648ba371819SOllivier Robert }
3649ba371819SOllivier Robert 
3650ba371819SOllivier Robert /* 0x4C */
36512b15cb3dSCy Schubert static void
36522b15cb3dSCy Schubert rpt_operating_parameters(
36532b15cb3dSCy Schubert 			 TSIPPKT *rpt
36542b15cb3dSCy Schubert 			 )
3655ba371819SOllivier Robert {
3656ba371819SOllivier Robert 	unsigned char
3657ba371819SOllivier Robert 	    dyn_code;
3658ba371819SOllivier Robert 	float
3659ba371819SOllivier Robert 	    el_mask, snr_mask, dop_mask, dop_switch;
3660ba371819SOllivier Robert 
3661ba371819SOllivier Robert 	/* unload rptbuf */
3662ba371819SOllivier Robert 	if (rpt_0x4C (rpt, &dyn_code, &el_mask,
3663ba371819SOllivier Robert 		      &snr_mask, &dop_mask, &dop_switch))
3664ba371819SOllivier Robert 	{
3665ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
3666ba371819SOllivier Robert 		return;
3667ba371819SOllivier Robert 	}
3668ba371819SOllivier Robert 
3669ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nOperating Parameters:");
3670ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n     Dynamics code = %d %s",
3671ba371819SOllivier Robert 			dyn_code, dyn_text[dyn_code]);
36722b15cb3dSCy Schubert 	pbuf += sprintf(pbuf, "\n     Elevation mask = %.2f", el_mask * R2D);
3673ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n     SNR mask = %.2f", snr_mask);
3674ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n     DOP mask = %.2f", dop_mask);
3675ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n     DOP switch = %.2f", dop_switch);
3676ba371819SOllivier Robert }
3677ba371819SOllivier Robert 
3678ba371819SOllivier Robert /* 0x4D */
36792b15cb3dSCy Schubert static void
36802b15cb3dSCy Schubert rpt_oscillator_offset(
36812b15cb3dSCy Schubert 		      TSIPPKT *rpt
36822b15cb3dSCy Schubert 		      )
3683ba371819SOllivier Robert {
3684ba371819SOllivier Robert 	float
3685ba371819SOllivier Robert 	    osc_offset;
3686ba371819SOllivier Robert 
3687ba371819SOllivier Robert 	/* unload rptbuf */
3688ba371819SOllivier Robert 	if (rpt_0x4D (rpt, &osc_offset))
3689ba371819SOllivier Robert 	{
3690ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
3691ba371819SOllivier Robert 		return;
3692ba371819SOllivier Robert 	}
3693ba371819SOllivier Robert 
3694ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nOscillator offset: %.2f Hz = %.3f PPM",
3695ba371819SOllivier Robert 			osc_offset, osc_offset/1575.42);
3696ba371819SOllivier Robert }
3697ba371819SOllivier Robert 
3698ba371819SOllivier Robert /* 0x4E */
36992b15cb3dSCy Schubert static void
37002b15cb3dSCy Schubert rpt_GPS_time_set_response(
37012b15cb3dSCy Schubert 			  TSIPPKT *rpt
37022b15cb3dSCy Schubert 			  )
3703ba371819SOllivier Robert {
3704ba371819SOllivier Robert 	unsigned char
3705ba371819SOllivier Robert 	    response;
3706ba371819SOllivier Robert 
3707ba371819SOllivier Robert 	/* unload rptbuf */
3708ba371819SOllivier Robert 	if (rpt_0x4E (rpt, &response))
3709ba371819SOllivier Robert 	{
3710ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
3711ba371819SOllivier Robert 		return;
3712ba371819SOllivier Robert 	}
3713ba371819SOllivier Robert 
3714ba371819SOllivier Robert 	switch (response)
3715ba371819SOllivier Robert 	{
3716ba371819SOllivier Robert 	    case 'Y':
3717ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\nTime set accepted");
3718ba371819SOllivier Robert 		break;
3719ba371819SOllivier Robert 
3720ba371819SOllivier Robert 	    case 'N':
3721ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\nTime set rejected or not required");
3722ba371819SOllivier Robert 		break;
3723ba371819SOllivier Robert 
3724ba371819SOllivier Robert 	    default:
3725ba371819SOllivier Robert 		parsed = BADDATA_PARSE;
3726ba371819SOllivier Robert 	}
3727ba371819SOllivier Robert }
3728ba371819SOllivier Robert 
3729ba371819SOllivier Robert /* 0x4F */
37302b15cb3dSCy Schubert static void
37312b15cb3dSCy Schubert rpt_UTC_offset(
37322b15cb3dSCy Schubert 	       TSIPPKT *rpt
37332b15cb3dSCy Schubert 	       )
3734ba371819SOllivier Robert {
3735ba371819SOllivier Robert 	double
3736ba371819SOllivier Robert 	    a0;
3737ba371819SOllivier Robert 	float
3738ba371819SOllivier Robert 	    a1, time_of_data;
3739ba371819SOllivier Robert 	short
3740ba371819SOllivier Robert 	    dt_ls, wn_t, wn_lsf, dn, dt_lsf;
3741ba371819SOllivier Robert 
3742ba371819SOllivier Robert 	/* unload rptbuf */
3743ba371819SOllivier Robert 	if (rpt_0x4F (rpt, &a0, &a1, &time_of_data,
3744ba371819SOllivier Robert 		      &dt_ls, &wn_t, &wn_lsf, &dn, &dt_lsf)) {
3745ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
3746ba371819SOllivier Robert 		return;
3747ba371819SOllivier Robert 	}
3748ba371819SOllivier Robert 
3749ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nUTC Correction Data");
3750ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   A_0         = %g  ", a0);
3751ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   A_1         = %g  ", a1);
3752ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   delta_t_LS  = %d  ", dt_ls);
3753ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   t_ot        = %.0f  ", time_of_data);
3754ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   WN_t        = %d  ", wn_t );
3755ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   WN_LSF      = %d  ", wn_lsf );
3756ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   DN          = %d  ", dn );
3757ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   delta_t_LSF = %d  ", dt_lsf );
3758ba371819SOllivier Robert }
3759ba371819SOllivier Robert 
3760ba371819SOllivier Robert /**/
3761ba371819SOllivier Robert /* 0x54 */
37622b15cb3dSCy Schubert static void
37632b15cb3dSCy Schubert rpt_1SV_bias(
37642b15cb3dSCy Schubert 	     TSIPPKT *rpt
37652b15cb3dSCy Schubert 	     )
3766ba371819SOllivier Robert {
3767ba371819SOllivier Robert 	float
3768ba371819SOllivier Robert 	    clock_bias, freq_offset, time_of_fix;
3769ba371819SOllivier Robert 
3770ba371819SOllivier Robert 	/* unload rptbuf */
3771ba371819SOllivier Robert 	if (rpt_0x54 (rpt, &clock_bias, &freq_offset, &time_of_fix)) {
3772ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
3773ba371819SOllivier Robert 		return;
3774ba371819SOllivier Robert 	}
3775ba371819SOllivier Robert 
3776ba371819SOllivier Robert 	pbuf += sprintf (pbuf, "\nTime Fix   Clock Bias: %6.2f m  Freq Bias: %6.2f m/s%s",
3777ba371819SOllivier Robert 			 clock_bias, freq_offset, show_time (time_of_fix));
3778ba371819SOllivier Robert }
3779ba371819SOllivier Robert 
3780ba371819SOllivier Robert /* 0x55 */
37812b15cb3dSCy Schubert static void
37822b15cb3dSCy Schubert rpt_io_opt(
37832b15cb3dSCy Schubert 	   TSIPPKT *rpt
37842b15cb3dSCy Schubert 	   )
3785ba371819SOllivier Robert {
3786ba371819SOllivier Robert 	unsigned char
3787ba371819SOllivier Robert 	    pos_code, vel_code, time_code, aux_code;
3788ba371819SOllivier Robert 
3789ba371819SOllivier Robert 	/* unload rptbuf */
3790ba371819SOllivier Robert 	if (rpt_0x55 (rpt,
3791ba371819SOllivier Robert 		      &pos_code, &vel_code, &time_code, &aux_code)) {
3792ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
3793ba371819SOllivier Robert 		return;
3794ba371819SOllivier Robert 	}
3795ba371819SOllivier Robert 	/* rptbuf unloaded */
3796ba371819SOllivier Robert 
3797ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nI/O Options: %2X %2X %2X %2X",
3798ba371819SOllivier Robert 			pos_code, vel_code, time_code, aux_code);
3799ba371819SOllivier Robert 
3800ba371819SOllivier Robert 	if (pos_code & 0x01) {
3801ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\n    ECEF XYZ position output");
3802ba371819SOllivier Robert 	}
3803ba371819SOllivier Robert 
3804ba371819SOllivier Robert 	if (pos_code & 0x02) {
3805ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\n    LLA position output");
3806ba371819SOllivier Robert 	}
3807ba371819SOllivier Robert 
3808ba371819SOllivier Robert 	pbuf += sprintf(pbuf, (pos_code & 0x04)?
3809ba371819SOllivier Robert 			"\n    MSL altitude output (Geoid height) ":
3810ba371819SOllivier Robert 			"\n    WGS-84 altitude output");
3811ba371819SOllivier Robert 
3812ba371819SOllivier Robert 	pbuf += sprintf(pbuf, (pos_code & 0x08)?
3813ba371819SOllivier Robert 			"\n    MSL altitude input":
3814ba371819SOllivier Robert 			"\n    WGS-84 altitude input");
3815ba371819SOllivier Robert 
3816ba371819SOllivier Robert 	pbuf += sprintf(pbuf, (pos_code & 0x10)?
3817ba371819SOllivier Robert 			"\n    Double precision":
3818ba371819SOllivier Robert 			"\n    Single precision");
3819ba371819SOllivier Robert 
3820ba371819SOllivier Robert 	if (pos_code & 0x20) {
3821ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\n    All Enabled Superpackets");
3822ba371819SOllivier Robert 	}
3823ba371819SOllivier Robert 
3824ba371819SOllivier Robert 	if (vel_code & 0x01) {
3825ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\n    ECEF XYZ velocity output");
3826ba371819SOllivier Robert 	}
3827ba371819SOllivier Robert 
3828ba371819SOllivier Robert 	if (vel_code & 0x02) {
3829ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\n    ENU velocity output");
3830ba371819SOllivier Robert 	}
3831ba371819SOllivier Robert 
3832ba371819SOllivier Robert 	pbuf += sprintf(pbuf, (time_code & 0x01)?
3833ba371819SOllivier Robert 			"\n    Time tags in UTC":
3834ba371819SOllivier Robert 			"\n    Time tags in GPS time");
3835ba371819SOllivier Robert 
3836ba371819SOllivier Robert 	if (time_code & 0x02) {
3837ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\n    Fixes delayed to integer seconds");
3838ba371819SOllivier Robert 	}
3839ba371819SOllivier Robert 
3840ba371819SOllivier Robert 	if (time_code & 0x04) {
3841ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\n    Fixes sent only on request");
3842ba371819SOllivier Robert 	}
3843ba371819SOllivier Robert 
3844ba371819SOllivier Robert 	if (time_code & 0x08) {
3845ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\n    Synchronized measurements");
3846ba371819SOllivier Robert 	}
3847ba371819SOllivier Robert 
3848ba371819SOllivier Robert 	if (time_code & 0x10) {
3849ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\n    Minimize measurement propagation");
3850ba371819SOllivier Robert 	}
3851ba371819SOllivier Robert 
3852ba371819SOllivier Robert 	pbuf += sprintf(pbuf, (time_code & 0x20) ?
3853ba371819SOllivier Robert 			"\n    PPS output at all times" :
3854ba371819SOllivier Robert 			"\n    PPS output during fixes");
3855ba371819SOllivier Robert 
3856ba371819SOllivier Robert 	if (aux_code & 0x01) {
3857ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\n    Raw measurement output");
3858ba371819SOllivier Robert 	}
3859ba371819SOllivier Robert 
3860ba371819SOllivier Robert 	if (aux_code & 0x02) {
3861ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\n    Code-phase smoothed before output");
3862ba371819SOllivier Robert 	}
3863ba371819SOllivier Robert 
3864ba371819SOllivier Robert 	if (aux_code & 0x04) {
3865ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\n    Additional fix status");
3866ba371819SOllivier Robert 	}
3867ba371819SOllivier Robert 
3868ba371819SOllivier Robert 	pbuf += sprintf(pbuf, (aux_code & 0x08)?
3869ba371819SOllivier Robert 			"\n    Signal Strength Output as dBHz" :
3870ba371819SOllivier Robert 			"\n    Signal Strength Output as AMU");
3871ba371819SOllivier Robert }
3872ba371819SOllivier Robert 
3873ba371819SOllivier Robert /* 0x56 */
38742b15cb3dSCy Schubert static void
38752b15cb3dSCy Schubert rpt_ENU_velocity(
38762b15cb3dSCy Schubert 		 TSIPPKT *rpt
38772b15cb3dSCy Schubert 		 )
3878ba371819SOllivier Robert {
3879ba371819SOllivier Robert 	float
3880ba371819SOllivier Robert 	    vel_ENU[3], freq_offset, time_of_fix;
3881ba371819SOllivier Robert 
3882ba371819SOllivier Robert 	/* unload rptbuf */
3883ba371819SOllivier Robert 	if (rpt_0x56 (rpt, vel_ENU, &freq_offset, &time_of_fix)) {
3884ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
3885ba371819SOllivier Robert 		return;
3886ba371819SOllivier Robert 	}
3887ba371819SOllivier Robert 
3888ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nVel ENU: %11.3f  %11.3f  %11.3f  %12.3f%s",
3889ba371819SOllivier Robert 			vel_ENU[0], vel_ENU[1], vel_ENU[2], freq_offset,
3890ba371819SOllivier Robert 			show_time (time_of_fix));
3891ba371819SOllivier Robert }
3892ba371819SOllivier Robert 
3893ba371819SOllivier Robert /* 0x57 */
38942b15cb3dSCy Schubert static void
38952b15cb3dSCy Schubert rpt_last_fix_info(
38962b15cb3dSCy Schubert 		  TSIPPKT *rpt
38972b15cb3dSCy Schubert 		  )
3898ba371819SOllivier Robert {
3899ba371819SOllivier Robert 	unsigned char
3900ba371819SOllivier Robert 	    source_code, diag_code;
3901ba371819SOllivier Robert 	short
3902ba371819SOllivier Robert 	    week_num;
3903ba371819SOllivier Robert 	float
3904ba371819SOllivier Robert 	    time_of_fix;
3905ba371819SOllivier Robert 
3906ba371819SOllivier Robert 	/* unload rptbuf */
3907ba371819SOllivier Robert 	if (rpt_0x57 (rpt, &source_code, &diag_code, &week_num, &time_of_fix)) {
3908ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
3909ba371819SOllivier Robert 		return;
3910ba371819SOllivier Robert 	}
3911ba371819SOllivier Robert 
3912ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n source code %d;   diag code: %2Xh",
3913ba371819SOllivier Robert 			source_code, diag_code);
3914ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n    Time of last fix:%s", show_time(time_of_fix));
3915ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n    Week of last fix: %d", week_num);
3916ba371819SOllivier Robert }
3917ba371819SOllivier Robert 
3918ba371819SOllivier Robert /* 0x58 */
39192b15cb3dSCy Schubert static void
39202b15cb3dSCy Schubert rpt_GPS_system_data(
39212b15cb3dSCy Schubert 		    TSIPPKT *rpt
39222b15cb3dSCy Schubert 		    )
3923ba371819SOllivier Robert {
3924ba371819SOllivier Robert 	unsigned char
3925ba371819SOllivier Robert 	    iprn,
3926ba371819SOllivier Robert 	    op_code, data_type, sv_prn,
3927ba371819SOllivier Robert 	    data_length, data_packet[250];
3928ba371819SOllivier Robert 	ALM_INFO
3929ba371819SOllivier Robert 	    *almanac;
3930ba371819SOllivier Robert 	ALH_PARMS
3931ba371819SOllivier Robert 	    *almh;
3932ba371819SOllivier Robert 	UTC_INFO
3933ba371819SOllivier Robert 	    *utc;
3934ba371819SOllivier Robert 	ION_INFO
3935ba371819SOllivier Robert 	    *ionosphere;
3936ba371819SOllivier Robert 	EPHEM_CLOCK
3937ba371819SOllivier Robert 	    *cdata;
3938ba371819SOllivier Robert 	EPHEM_ORBIT
3939ba371819SOllivier Robert 	    *edata;
3940ba371819SOllivier Robert 	NAV_INFO
3941ba371819SOllivier Robert 	    *nav_data;
3942ba371819SOllivier Robert 	unsigned char
3943ba371819SOllivier Robert 	    curr_t_oa;
3944ba371819SOllivier Robert 	unsigned short
3945ba371819SOllivier Robert 	    curr_wn_oa;
3946ba371819SOllivier Robert 	static char
3947ba371819SOllivier Robert 	    *datname[] =
3948ba371819SOllivier Robert 	    {"", "", "Almanac Orbit",
3949ba371819SOllivier Robert 	     "Health Page & Ref Time", "Ionosphere", "UTC ",
3950ba371819SOllivier Robert 	     "Ephemeris"};
3951ba371819SOllivier Robert 
3952ba371819SOllivier Robert 	/* unload rptbuf */
3953ba371819SOllivier Robert 	if (rpt_0x58 (rpt, &op_code, &data_type, &sv_prn,
3954ba371819SOllivier Robert 		      &data_length, data_packet))
3955ba371819SOllivier Robert 	{
3956ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
3957ba371819SOllivier Robert 		return;
3958ba371819SOllivier Robert 	}
3959ba371819SOllivier Robert 
3960ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nSystem data [%d]:  %s  SV%02d",
3961ba371819SOllivier Robert 			data_type, datname[data_type], sv_prn);
3962ba371819SOllivier Robert 	switch (op_code)
3963ba371819SOllivier Robert 	{
3964ba371819SOllivier Robert 	    case 1:
3965ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "  Acknowledgment");
3966ba371819SOllivier Robert 		break;
3967ba371819SOllivier Robert 	    case 2:
3968ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "  length = %d bytes", data_length);
3969ba371819SOllivier Robert 		switch (data_type) {
3970ba371819SOllivier Robert 		    case 2:
3971ba371819SOllivier Robert 			/* Almanac */
3972ba371819SOllivier Robert 			if (sv_prn == 0 || sv_prn > 32) {
3973ba371819SOllivier Robert 				pbuf += sprintf(pbuf, "  Binary PRN invalid");
3974ba371819SOllivier Robert 				return;
3975ba371819SOllivier Robert 			}
3976ba371819SOllivier Robert 			almanac = (ALM_INFO*)data_packet;
3977ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\n   t_oa_raw = % -12d    SV_hlth  = % -12d  ",
3978ba371819SOllivier Robert 					almanac->t_oa_raw , almanac->SV_health );
3979ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\n   e        = % -12g    t_oa     = % -12g  ",
3980ba371819SOllivier Robert 					almanac->e        , almanac->t_oa     );
3981ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\n   i_0      = % -12g    OMEGADOT = % -12g  ",
3982ba371819SOllivier Robert 					almanac->i_0      , almanac->OMEGADOT );
3983ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\n   sqrt_A   = % -12g    OMEGA_0  = % -12g  ",
3984ba371819SOllivier Robert 					almanac->sqrt_A   , almanac->OMEGA_0  );
3985ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\n   omega    = % -12g    M_0      = % -12g  ",
3986ba371819SOllivier Robert 					almanac->omega    , almanac->M_0      );
3987ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\n   a_f0     = % -12g    a_f1     = % -12g  ",
3988ba371819SOllivier Robert 					almanac->a_f0     , almanac->a_f1     );
3989ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\n   Axis     = % -12g    n        = % -12g  ",
3990ba371819SOllivier Robert 					almanac->Axis     , almanac->n        );
3991ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\n   OMEGA_n  = % -12g    ODOT_n   = % -12g  ",
3992ba371819SOllivier Robert 					almanac->OMEGA_n  , almanac->ODOT_n   );
3993ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\n   t_zc     = % -12g    weeknum  = % -12d  ",
3994ba371819SOllivier Robert 					almanac->t_zc     , almanac->weeknum  );
3995ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\n   wn_oa    = % -12d", almanac->wn_oa    );
3996ba371819SOllivier Robert 			break;
3997ba371819SOllivier Robert 
3998ba371819SOllivier Robert 		    case 3:
3999ba371819SOllivier Robert 			/* Almanac health page */
4000ba371819SOllivier Robert 			almh = (ALH_PARMS*)data_packet;
4001ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\n   t_oa = %d, wn_oa&0xFF = %d  ",
4002ba371819SOllivier Robert 					almh->t_oa, almh->WN_a);
4003ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\nAlmanac health page:");
4004ba371819SOllivier Robert 			for (iprn = 0; iprn < 32; iprn++) {
4005ba371819SOllivier Robert 				if (!(iprn%5)) *pbuf++ = '\n';
4006ba371819SOllivier Robert 				pbuf += sprintf(pbuf, "    SV%02d  %2X",
4007ba371819SOllivier Robert 						(iprn+1) , almh->SV_health[iprn]);
4008ba371819SOllivier Robert 			}
4009ba371819SOllivier Robert 			curr_t_oa = data_packet[34];
4010ba371819SOllivier Robert 			curr_wn_oa = (unsigned short)((data_packet[35]<<8) + data_packet[36]);
4011ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\n   current t_oa = %d, wn_oa = %d  ",
4012ba371819SOllivier Robert 					curr_t_oa, curr_wn_oa);
4013ba371819SOllivier Robert 			break;
4014ba371819SOllivier Robert 
4015ba371819SOllivier Robert 		    case 4:
4016ba371819SOllivier Robert 			/* Ionosphere */
4017ba371819SOllivier Robert 			ionosphere = (ION_INFO*)data_packet;
4018ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\n   alpha_0 = % -12g  alpha_1 = % -12g ",
4019ba371819SOllivier Robert 					ionosphere->alpha_0, ionosphere->alpha_1);
4020ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\n   alpha_2 = % -12g  alpha_3 = % -12g ",
4021ba371819SOllivier Robert 					ionosphere->alpha_2, ionosphere->alpha_3);
4022ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\n   beta_0  = % -12g  beta_1  = % -12g  ",
4023ba371819SOllivier Robert 					ionosphere->beta_0, ionosphere->beta_1);
4024ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\n   beta_2  = % -12g  beta_3  = % -12g  ",
4025ba371819SOllivier Robert 					ionosphere->beta_2, ionosphere->beta_3);
4026ba371819SOllivier Robert 			break;
4027ba371819SOllivier Robert 
4028ba371819SOllivier Robert 		    case 5:
4029ba371819SOllivier Robert 			/* UTC */
4030ba371819SOllivier Robert 			utc = (UTC_INFO*)data_packet;
4031ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\n   A_0         = %g  ", utc->A_0);
4032ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\n   A_1         = %g  ", utc->A_1);
4033ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\n   delta_t_LS  = %d  ", utc->delta_t_LS);
4034ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\n   t_ot        = %.0f  ", utc->t_ot );
4035ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\n   WN_t        = %d  ", utc->WN_t );
4036ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\n   WN_LSF      = %d  ", utc->WN_LSF );
4037ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\n   DN          = %d  ", utc->DN );
4038ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\n   delta_t_LSF = %d  ", utc->delta_t_LSF );
4039ba371819SOllivier Robert 			break;
4040ba371819SOllivier Robert 
4041ba371819SOllivier Robert 		    case 6: /* Ephemeris */
4042ba371819SOllivier Robert 			if (sv_prn == 0 || sv_prn > 32) {
4043ba371819SOllivier Robert 				pbuf += sprintf(pbuf, "  Binary PRN invalid");
4044ba371819SOllivier Robert 				return;
4045ba371819SOllivier Robert 			}
4046ba371819SOllivier Robert 			nav_data = (NAV_INFO*)data_packet;
4047ba371819SOllivier Robert 
4048ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "\n     SV_PRN = % -12d .  t_ephem = % -12g . ",
4049ba371819SOllivier Robert 					nav_data->sv_number , nav_data->t_ephem );
4050ba371819SOllivier Robert 			cdata = &(nav_data->ephclk);
4051ba371819SOllivier Robert 			pbuf += sprintf(pbuf,
4052ba371819SOllivier Robert 					"\n    weeknum = % -12d .   codeL2 = % -12d .  L2Pdata = % -12d",
4053ba371819SOllivier Robert 					cdata->weeknum , cdata->codeL2 , cdata->L2Pdata );
4054ba371819SOllivier Robert 			pbuf += sprintf(pbuf,
4055ba371819SOllivier Robert 					"\n  SVacc_raw = % -12d .SV_health = % -12d .     IODC = % -12d",
4056ba371819SOllivier Robert 					cdata->SVacc_raw, cdata->SV_health, cdata->IODC );
4057ba371819SOllivier Robert 			pbuf += sprintf(pbuf,
4058ba371819SOllivier Robert 					"\n       T_GD = % -12g .     t_oc = % -12g .     a_f2 = % -12g",
4059ba371819SOllivier Robert 					cdata->T_GD, cdata->t_oc, cdata->a_f2 );
4060ba371819SOllivier Robert 			pbuf += sprintf(pbuf,
4061ba371819SOllivier Robert 					"\n       a_f1 = % -12g .     a_f0 = % -12g .    SVacc = % -12g",
4062ba371819SOllivier Robert 					cdata->a_f1, cdata->a_f0, cdata->SVacc );
4063ba371819SOllivier Robert 			edata = &(nav_data->ephorb);
4064ba371819SOllivier Robert 			pbuf += sprintf(pbuf,
4065ba371819SOllivier Robert 					"\n       IODE = % -12d .fit_intvl = % -12d .     C_rs = % -12g",
4066ba371819SOllivier Robert 					edata->IODE, edata->fit_interval, edata->C_rs );
4067ba371819SOllivier Robert 			pbuf += sprintf(pbuf,
4068ba371819SOllivier Robert 					"\n    delta_n = % -12g .      M_0 = % -12g .     C_uc = % -12g",
4069ba371819SOllivier Robert 					edata->delta_n, edata->M_0, edata->C_uc );
4070ba371819SOllivier Robert 			pbuf += sprintf(pbuf,
4071ba371819SOllivier Robert 					"\n        ecc = % -12g .     C_us = % -12g .   sqrt_A = % -12g",
4072ba371819SOllivier Robert 					edata->e, edata->C_us, edata->sqrt_A );
4073ba371819SOllivier Robert 			pbuf += sprintf(pbuf,
4074ba371819SOllivier Robert 					"\n       t_oe = % -12g .     C_ic = % -12g .  OMEGA_0 = % -12g",
4075ba371819SOllivier Robert 					edata->t_oe, edata->C_ic, edata->OMEGA_0 );
4076ba371819SOllivier Robert 			pbuf += sprintf(pbuf,
4077ba371819SOllivier Robert 					"\n       C_is = % -12g .      i_0 = % -12g .     C_rc = % -12g",
4078ba371819SOllivier Robert 					edata->C_is, edata->i_0, edata->C_rc );
4079ba371819SOllivier Robert 			pbuf += sprintf(pbuf,
4080ba371819SOllivier Robert 					"\n      omega = % -12g . OMEGADOT = % -12g .     IDOT = % -12g",
4081ba371819SOllivier Robert 					edata->omega, edata->OMEGADOT, edata->IDOT );
4082ba371819SOllivier Robert 			pbuf += sprintf(pbuf,
4083ba371819SOllivier Robert 					"\n       Axis = % -12g .        n = % -12g .    r1me2 = % -12g",
4084ba371819SOllivier Robert 					edata->Axis, edata->n, edata->r1me2 );
4085ba371819SOllivier Robert 			pbuf += sprintf(pbuf,
4086ba371819SOllivier Robert 					"\n    OMEGA_n = % -12g .   ODOT_n = % -12g",
4087ba371819SOllivier Robert 					edata->OMEGA_n, edata->ODOT_n );
4088ba371819SOllivier Robert 			break;
4089ba371819SOllivier Robert 		}
4090ba371819SOllivier Robert 	}
4091ba371819SOllivier Robert }
4092ba371819SOllivier Robert 
4093ba371819SOllivier Robert 
4094ba371819SOllivier Robert /* 0x59: */
40952b15cb3dSCy Schubert static void
40962b15cb3dSCy Schubert rpt_SVs_enabled(
40972b15cb3dSCy Schubert 		TSIPPKT *rpt
40982b15cb3dSCy Schubert 		)
4099ba371819SOllivier Robert {
4100ba371819SOllivier Robert 	unsigned char
4101ba371819SOllivier Robert 	    numsvs,
4102ba371819SOllivier Robert 	    code_type,
4103ba371819SOllivier Robert 	    status_code[32];
4104ba371819SOllivier Robert 	short
4105ba371819SOllivier Robert 	    iprn;
4106ba371819SOllivier Robert 
4107ba371819SOllivier Robert 	/* unload rptbuf */
4108ba371819SOllivier Robert 	if (rpt_0x59 (rpt, &code_type, status_code))
4109ba371819SOllivier Robert 	{
4110ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
4111ba371819SOllivier Robert 		return;
4112ba371819SOllivier Robert 	}
4113ba371819SOllivier Robert 	switch (code_type)
4114ba371819SOllivier Robert 	{
4115ba371819SOllivier Robert 	    case 3: pbuf += sprintf(pbuf, "\nSVs Disabled:\n"); break;
4116ba371819SOllivier Robert 	    case 6: pbuf += sprintf(pbuf, "\nSVs with Health Ignored:\n"); break;
4117ba371819SOllivier Robert 	    default: return;
4118ba371819SOllivier Robert 	}
4119ba371819SOllivier Robert 	numsvs = 0;
4120ba371819SOllivier Robert 	for (iprn = 0; iprn < 32; iprn++)
4121ba371819SOllivier Robert 	{
4122ba371819SOllivier Robert 		if (status_code[iprn])
4123ba371819SOllivier Robert 		{
4124ba371819SOllivier Robert 			pbuf += sprintf(pbuf, " %02d", iprn+1);
4125ba371819SOllivier Robert 			numsvs++;
4126ba371819SOllivier Robert 		}
4127ba371819SOllivier Robert 	}
4128ba371819SOllivier Robert 	if (numsvs == 0) pbuf += sprintf(pbuf, "None");
4129ba371819SOllivier Robert }
4130ba371819SOllivier Robert 
4131ba371819SOllivier Robert 
4132ba371819SOllivier Robert /* 0x5A */
41332b15cb3dSCy Schubert static void
41342b15cb3dSCy Schubert rpt_raw_msmt(
41352b15cb3dSCy Schubert 	     TSIPPKT *rpt
41362b15cb3dSCy Schubert 	     )
4137ba371819SOllivier Robert {
4138ba371819SOllivier Robert 	unsigned char
4139ba371819SOllivier Robert 	    sv_prn;
4140ba371819SOllivier Robert 	float
4141ba371819SOllivier Robert 	    sample_length, signal_level, code_phase, Doppler;
4142ba371819SOllivier Robert 	double
4143ba371819SOllivier Robert 	    time_of_fix;
4144ba371819SOllivier Robert 
4145ba371819SOllivier Robert 	/* unload rptbuf */
4146ba371819SOllivier Robert 	if (rpt_0x5A (rpt, &sv_prn, &sample_length, &signal_level,
4147ba371819SOllivier Robert 		      &code_phase, &Doppler, &time_of_fix))
4148ba371819SOllivier Robert 	{
4149ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
4150ba371819SOllivier Robert 		return;
4151ba371819SOllivier Robert 	}
4152ba371819SOllivier Robert 
4153ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   %02d %5.0f %7.1f %10.2f %10.2f %12.3f %s",
4154ba371819SOllivier Robert 			sv_prn, sample_length, signal_level, code_phase, Doppler, time_of_fix,
4155ba371819SOllivier Robert 			show_time ((float)time_of_fix));
4156ba371819SOllivier Robert }
4157ba371819SOllivier Robert 
4158ba371819SOllivier Robert /* 0x5B */
41592b15cb3dSCy Schubert static void
41602b15cb3dSCy Schubert rpt_SV_ephemeris_status(
41612b15cb3dSCy Schubert 			TSIPPKT *rpt
41622b15cb3dSCy Schubert 			)
4163ba371819SOllivier Robert {
4164ba371819SOllivier Robert 	unsigned char
4165ba371819SOllivier Robert 	    sv_prn, sv_health, sv_iode, fit_interval_flag;
4166ba371819SOllivier Robert 	float
4167ba371819SOllivier Robert 	    time_of_collection, time_of_eph, sv_accy;
4168ba371819SOllivier Robert 
4169ba371819SOllivier Robert 	/* unload rptbuf */
4170ba371819SOllivier Robert 	if (rpt_0x5B (rpt, &sv_prn, &sv_health, &sv_iode, &fit_interval_flag,
4171ba371819SOllivier Robert 		      &time_of_collection, &time_of_eph, &sv_accy))
4172ba371819SOllivier Robert 	{
4173ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
4174ba371819SOllivier Robert 		return;
4175ba371819SOllivier Robert 	}
4176ba371819SOllivier Robert 
4177ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n  SV%02d  %s   %2Xh     %2Xh ",
4178ba371819SOllivier Robert 			sv_prn, show_time (time_of_collection), sv_health, sv_iode);
4179ba371819SOllivier Robert 	/* note: cannot use show_time twice in same call */
4180ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "%s   %1d   %4.1f",
4181ba371819SOllivier Robert 			show_time (time_of_eph), fit_interval_flag, sv_accy);
4182ba371819SOllivier Robert }
4183ba371819SOllivier Robert 
4184ba371819SOllivier Robert /* 0x5C */
41852b15cb3dSCy Schubert static void
41862b15cb3dSCy Schubert rpt_SV_tracking_status(
41872b15cb3dSCy Schubert 		       TSIPPKT *rpt
41882b15cb3dSCy Schubert 		       )
4189ba371819SOllivier Robert {
4190ba371819SOllivier Robert 	unsigned char
4191ba371819SOllivier Robert 	    sv_prn, chan, slot, acq_flag, eph_flag,
4192ba371819SOllivier Robert 	    old_msmt_flag, integer_msec_flag, bad_data_flag,
4193ba371819SOllivier Robert 	    data_collect_flag;
4194ba371819SOllivier Robert 	float
4195ba371819SOllivier Robert 	    signal_level, time_of_last_msmt,
4196ba371819SOllivier Robert 	    elev, azim;
4197ba371819SOllivier Robert 
4198ba371819SOllivier Robert 	/* unload rptbuf */
4199ba371819SOllivier Robert 	if (rpt_0x5C (rpt,
4200ba371819SOllivier Robert 		      &sv_prn, &slot, &chan, &acq_flag, &eph_flag,
4201ba371819SOllivier Robert 		      &signal_level, &time_of_last_msmt, &elev, &azim,
4202ba371819SOllivier Robert 		      &old_msmt_flag, &integer_msec_flag, &bad_data_flag,
4203ba371819SOllivier Robert 		      &data_collect_flag))
4204ba371819SOllivier Robert 	{
4205ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
4206ba371819SOllivier Robert 		return;
4207ba371819SOllivier Robert 	}
4208ba371819SOllivier Robert 
4209ba371819SOllivier Robert 	pbuf += sprintf(pbuf,
4210ba371819SOllivier Robert 			"\n SV%2d  %1d   %1d   %1d   %4.1f  %s  %5.1f  %5.1f",
4211ba371819SOllivier Robert 			sv_prn, chan,
4212ba371819SOllivier Robert 			acq_flag, eph_flag, signal_level,
4213ba371819SOllivier Robert 			show_time(time_of_last_msmt),
4214ba371819SOllivier Robert 			elev*R2D, azim*R2D);
4215ba371819SOllivier Robert }
4216ba371819SOllivier Robert 
4217ba371819SOllivier Robert /**/
4218ba371819SOllivier Robert /* 0x6D */
42192b15cb3dSCy Schubert static void
42202b15cb3dSCy Schubert rpt_allSV_selection(
42212b15cb3dSCy Schubert 		    TSIPPKT *rpt
42222b15cb3dSCy Schubert 		    )
4223ba371819SOllivier Robert {
4224ba371819SOllivier Robert 	unsigned char
4225ba371819SOllivier Robert 	    manual_mode, nsvs, sv_prn[8], ndim;
4226ba371819SOllivier Robert 	short
4227ba371819SOllivier Robert 	    islot;
4228ba371819SOllivier Robert 	float
4229ba371819SOllivier Robert 	    pdop, hdop, vdop, tdop;
4230ba371819SOllivier Robert 
4231ba371819SOllivier Robert 	/* unload rptbuf */
4232ba371819SOllivier Robert 	if (rpt_0x6D (rpt,
4233ba371819SOllivier Robert 		      &manual_mode, &nsvs, &ndim, sv_prn,
4234ba371819SOllivier Robert 		      &pdop, &hdop, &vdop, &tdop))
4235ba371819SOllivier Robert 	{
4236ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
4237ba371819SOllivier Robert 		return;
4238ba371819SOllivier Robert 	}
4239ba371819SOllivier Robert 
4240ba371819SOllivier Robert 	switch (ndim)
4241ba371819SOllivier Robert 	{
4242ba371819SOllivier Robert 	    case 0:
4243ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\nMode: Searching, %d-SV:", nsvs);
4244ba371819SOllivier Robert 		break;
4245ba371819SOllivier Robert 	    case 1:
4246ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\nMode: One-SV Timing:");
4247ba371819SOllivier Robert 		break;
4248ba371819SOllivier Robert 	    case 3: case 4:
4249ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\nMode: %c-%dD, %d-SV:",
4250ba371819SOllivier Robert 				manual_mode ? 'M' : 'A', ndim - 1,  nsvs);
4251ba371819SOllivier Robert 		break;
4252ba371819SOllivier Robert 	    case 5:
4253ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\nMode: Timing, %d-SV:", nsvs);
4254ba371819SOllivier Robert 		break;
4255ba371819SOllivier Robert 	    default:
4256ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\nMode: Unknown = %d:", ndim);
4257ba371819SOllivier Robert 		break;
4258ba371819SOllivier Robert 	}
4259ba371819SOllivier Robert 
4260ba371819SOllivier Robert 	for (islot = 0; islot < nsvs; islot++)
4261ba371819SOllivier Robert 	{
4262ba371819SOllivier Robert 		if (sv_prn[islot]) pbuf += sprintf(pbuf, " %02d", sv_prn[islot]);
4263ba371819SOllivier Robert 	}
4264ba371819SOllivier Robert 	if (ndim == 3 || ndim == 4)
4265ba371819SOllivier Robert 	{
4266ba371819SOllivier Robert 		pbuf += sprintf(pbuf, ";  DOPs: P %.1f H %.1f V %.1f T %.1f",
4267ba371819SOllivier Robert 				pdop, hdop, vdop, tdop);
4268ba371819SOllivier Robert 	}
4269ba371819SOllivier Robert }
4270ba371819SOllivier Robert 
4271ba371819SOllivier Robert /**/
4272ba371819SOllivier Robert /* 0x82 */
42732b15cb3dSCy Schubert static void
42742b15cb3dSCy Schubert rpt_DGPS_position_mode(
42752b15cb3dSCy Schubert 		       TSIPPKT *rpt
42762b15cb3dSCy Schubert 		       )
4277ba371819SOllivier Robert {
4278ba371819SOllivier Robert 	unsigned char
4279ba371819SOllivier Robert 	    diff_mode;
4280ba371819SOllivier Robert 
4281ba371819SOllivier Robert 	/* unload rptbuf */
4282ba371819SOllivier Robert 	if (rpt_0x82 (rpt, &diff_mode)) {
4283ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
4284ba371819SOllivier Robert 		return;
4285ba371819SOllivier Robert 	}
4286ba371819SOllivier Robert 
4287ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nFix is%s DGPS-corrected (%s mode)  (%d)",
4288ba371819SOllivier Robert 			(diff_mode&1) ? "" : " not",
4289ba371819SOllivier Robert 			(diff_mode&2) ? "auto" : "manual",
4290ba371819SOllivier Robert 			diff_mode);
4291ba371819SOllivier Robert }
4292ba371819SOllivier Robert 
4293ba371819SOllivier Robert /* 0x83 */
42942b15cb3dSCy Schubert static void
42952b15cb3dSCy Schubert rpt_double_ECEF_position(
42962b15cb3dSCy Schubert 			 TSIPPKT *rpt
42972b15cb3dSCy Schubert 			 )
4298ba371819SOllivier Robert {
4299ba371819SOllivier Robert 	double
4300ba371819SOllivier Robert 	    ECEF_pos[3], clock_bias;
4301ba371819SOllivier Robert 	float
4302ba371819SOllivier Robert 	    time_of_fix;
4303ba371819SOllivier Robert 
4304ba371819SOllivier Robert 	/* unload rptbuf */
4305ba371819SOllivier Robert 	if (rpt_0x83 (rpt, ECEF_pos, &clock_bias, &time_of_fix))
4306ba371819SOllivier Robert 	{
4307ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
4308ba371819SOllivier Robert 		return;
4309ba371819SOllivier Robert 	}
4310ba371819SOllivier Robert 
4311ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nDXYZ:%12.2f  %13.2f  %13.2f %12.2f%s",
4312ba371819SOllivier Robert 			ECEF_pos[0], ECEF_pos[1], ECEF_pos[2], clock_bias,
4313ba371819SOllivier Robert 			show_time(time_of_fix));
4314ba371819SOllivier Robert }
4315ba371819SOllivier Robert 
4316ba371819SOllivier Robert /* 0x84 */
43172b15cb3dSCy Schubert static void
43182b15cb3dSCy Schubert rpt_double_lla_position(
43192b15cb3dSCy Schubert 			TSIPPKT *rpt
43202b15cb3dSCy Schubert 			)
4321ba371819SOllivier Robert {
4322ba371819SOllivier Robert 	short
4323ba371819SOllivier Robert 	    lat_deg, lon_deg;
4324ba371819SOllivier Robert 	double
4325ba371819SOllivier Robert 	    lat, lon, lat_min, lon_min,
4326ba371819SOllivier Robert 	    alt, clock_bias;
4327ba371819SOllivier Robert 	float
4328ba371819SOllivier Robert 	    time_of_fix;
4329ba371819SOllivier Robert 	unsigned char
4330ba371819SOllivier Robert 	    north_south, east_west;
4331ba371819SOllivier Robert 
4332ba371819SOllivier Robert 	/* unload rptbuf */
4333ba371819SOllivier Robert 	if (rpt_0x84 (rpt,
4334ba371819SOllivier Robert 		      &lat, &lon, &alt, &clock_bias, &time_of_fix))
4335ba371819SOllivier Robert 	{
4336ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
4337ba371819SOllivier Robert 		return;
4338ba371819SOllivier Robert 	}
4339ba371819SOllivier Robert 
4340ba371819SOllivier Robert 	lat *= R2D;
4341ba371819SOllivier Robert 	lon *= R2D;
4342ba371819SOllivier Robert 	if (lat < 0.0) {
4343ba371819SOllivier Robert 		north_south = 'S';
4344ba371819SOllivier Robert 		lat = -lat;
4345ba371819SOllivier Robert 	} else {
4346ba371819SOllivier Robert 		north_south = 'N';
4347ba371819SOllivier Robert 	}
4348ba371819SOllivier Robert 	lat_deg = (short)lat;
4349ba371819SOllivier Robert 	lat_min = (lat - lat_deg) * 60.0;
4350ba371819SOllivier Robert 
4351ba371819SOllivier Robert 	if (lon < 0.0) {
4352ba371819SOllivier Robert 		east_west = 'W';
4353ba371819SOllivier Robert 		lon = -lon;
4354ba371819SOllivier Robert 	} else {
4355ba371819SOllivier Robert 		east_west = 'E';
4356ba371819SOllivier Robert 	}
4357ba371819SOllivier Robert 	lon_deg = (short)lon;
4358ba371819SOllivier Robert 	lon_min = (lon - lon_deg) * 60.0;
4359ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nDLLA: %2d:%08.5f %c; %3d:%08.5f %c; %10.2f %12.2f%s",
4360ba371819SOllivier Robert 			lat_deg, lat_min, north_south,
4361ba371819SOllivier Robert 			lon_deg, lon_min, east_west,
4362ba371819SOllivier Robert 			alt, clock_bias,
4363ba371819SOllivier Robert 			show_time(time_of_fix));
4364ba371819SOllivier Robert }
4365ba371819SOllivier Robert 
4366ba371819SOllivier Robert /* 0xBB */
43672b15cb3dSCy Schubert static void
43682b15cb3dSCy Schubert rpt_complete_rcvr_config(
43692b15cb3dSCy Schubert 			 TSIPPKT *rpt
43702b15cb3dSCy Schubert 			 )
4371ba371819SOllivier Robert {
4372ba371819SOllivier Robert 	TSIP_RCVR_CFG TsipxBB ;
4373ba371819SOllivier Robert 	/* unload rptbuf */
4374ba371819SOllivier Robert 	if (rpt_Paly0xBB (rpt, &TsipxBB))
4375ba371819SOllivier Robert 	{
4376ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
4377ba371819SOllivier Robert 		return;
4378ba371819SOllivier Robert 	}
4379ba371819SOllivier Robert 
4380ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   operating mode:      %s",
4381ba371819SOllivier Robert 			NavModeText0xBB[TsipxBB.operating_mode]);
4382ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   dynamics:            %s",
4383ba371819SOllivier Robert 			dyn_text[TsipxBB.dyn_code]);
4384ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   elev angle mask:     %g deg",
4385ba371819SOllivier Robert 			TsipxBB.elev_mask * R2D);
4386ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   SNR mask:            %g AMU",
4387ba371819SOllivier Robert 			TsipxBB.cno_mask);
4388ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   DOP mask:            %g",
4389ba371819SOllivier Robert 			TsipxBB.dop_mask);
4390ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   DOP switch:          %g",
4391ba371819SOllivier Robert 			TsipxBB.dop_switch);
4392ba371819SOllivier Robert 	return ;
4393ba371819SOllivier Robert }
4394ba371819SOllivier Robert 
4395ba371819SOllivier Robert /* 0xBC */
43962b15cb3dSCy Schubert static void
43972b15cb3dSCy Schubert rpt_rcvr_serial_port_config(
43982b15cb3dSCy Schubert 			    TSIPPKT *rpt
43992b15cb3dSCy Schubert 			    )
4400ba371819SOllivier Robert {
4401ba371819SOllivier Robert 	unsigned char
4402ba371819SOllivier Robert 	    port_num, in_baud, out_baud, data_bits, parity, stop_bits, flow_control,
4403ba371819SOllivier Robert 	    protocols_in, protocols_out, reserved;
4404ba371819SOllivier Robert 	unsigned char known;
4405ba371819SOllivier Robert 
4406ba371819SOllivier Robert 	/* unload rptbuf */
4407ba371819SOllivier Robert 	if (rpt_0xBC (rpt, &port_num, &in_baud, &out_baud, &data_bits, &parity,
4408ba371819SOllivier Robert 		      &stop_bits, &flow_control, &protocols_in, &protocols_out, &reserved)) {
4409ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
4410ba371819SOllivier Robert 		return;
4411ba371819SOllivier Robert 	}
4412ba371819SOllivier Robert 	/* rptbuf unloaded */
4413ba371819SOllivier Robert 
4414ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   RECEIVER serial port %s config:",
4415ba371819SOllivier Robert 			rcvr_port_text[port_num]);
4416ba371819SOllivier Robert 
4417ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n             I/O Baud %s/%s, %d - %s - %d",
4418ba371819SOllivier Robert 			st_baud_text_app[in_baud],
4419ba371819SOllivier Robert 			st_baud_text_app[out_baud],
4420ba371819SOllivier Robert 			data_bits+5,
4421ba371819SOllivier Robert 			parity_text[parity],
4422ba371819SOllivier Robert 			stop_bits=1);
4423ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n             Input protocols: ");
4424ba371819SOllivier Robert 	known = FALSE;
4425ba371819SOllivier Robert 	if (protocols_in&B_TSIP)
4426ba371819SOllivier Robert 	{
4427ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "%s ", protocols_in_text[1]);
4428ba371819SOllivier Robert 		known = TRUE;
4429ba371819SOllivier Robert 	}
4430ba371819SOllivier Robert 	if (known == FALSE) pbuf += sprintf(pbuf, "No known");
4431ba371819SOllivier Robert 
4432ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n             Output protocols: ");
4433ba371819SOllivier Robert 	known = FALSE;
4434ba371819SOllivier Robert 	if (protocols_out&B_TSIP)
4435ba371819SOllivier Robert 	{
4436ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "%s ", protocols_out_text[1]);
4437ba371819SOllivier Robert 		known = TRUE;
4438ba371819SOllivier Robert 	}
4439ba371819SOllivier Robert 	if (protocols_out&B_NMEA)
4440ba371819SOllivier Robert 	{
4441ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "%s ", protocols_out_text[2]);
4442ba371819SOllivier Robert 		known = TRUE;
4443ba371819SOllivier Robert 	}
4444ba371819SOllivier Robert 	if (known == FALSE) pbuf += sprintf(pbuf, "No known");
4445ba371819SOllivier Robert 	reserved = reserved;
4446ba371819SOllivier Robert 
4447ba371819SOllivier Robert }
4448ba371819SOllivier Robert 
4449ba371819SOllivier Robert /* 0x8F */
4450ba371819SOllivier Robert /* 8F0B */
44512b15cb3dSCy Schubert static void
44522b15cb3dSCy Schubert rpt_8F0B(
44532b15cb3dSCy Schubert 	 TSIPPKT *rpt
44542b15cb3dSCy Schubert 	 )
4455ba371819SOllivier Robert {
4456ba371819SOllivier Robert 	const char
4457ba371819SOllivier Robert 	    *oprtng_dim[7] = {
4458ba371819SOllivier Robert 		"horizontal (2-D)",
4459ba371819SOllivier Robert 		"full position (3-D)",
4460ba371819SOllivier Robert 		"single satellite (0-D)",
4461ba371819SOllivier Robert 		"automatic",
4462ba371819SOllivier Robert 		"N/A",
4463ba371819SOllivier Robert 		"N/A",
4464ba371819SOllivier Robert 		"overdetermined clock"};
4465ba371819SOllivier Robert 	char
4466ba371819SOllivier Robert 	    sv_id[8];
4467ba371819SOllivier Robert 	unsigned char
4468ba371819SOllivier Robert 	    month,
4469ba371819SOllivier Robert 	    date,
4470ba371819SOllivier Robert 	    dim_mode,
4471ba371819SOllivier Robert 	    north_south,
4472ba371819SOllivier Robert 	    east_west;
4473ba371819SOllivier Robert 	unsigned short
4474ba371819SOllivier Robert 	    event;
4475ba371819SOllivier Robert 	short
4476ba371819SOllivier Robert 	    utc_offset,
4477ba371819SOllivier Robert 	    year,
4478ba371819SOllivier Robert 	    local_index;
4479ba371819SOllivier Robert 	short
4480ba371819SOllivier Robert 	    lat_deg,
4481ba371819SOllivier Robert 	    lon_deg;
4482ba371819SOllivier Robert 	float
4483ba371819SOllivier Robert 	    bias_unc,
4484ba371819SOllivier Robert 	    dr_unc;
4485ba371819SOllivier Robert 	double
4486ba371819SOllivier Robert 	    tow,
4487ba371819SOllivier Robert 	    bias,
4488ba371819SOllivier Robert 	    drift,
4489ba371819SOllivier Robert 	    lat,
4490ba371819SOllivier Robert 	    lon,
4491ba371819SOllivier Robert 	    alt,
4492ba371819SOllivier Robert 	    lat_min,
4493ba371819SOllivier Robert 	    lon_min;
4494ba371819SOllivier Robert 	int
4495ba371819SOllivier Robert 	    numfix,
4496ba371819SOllivier Robert 	    numnotfix;
4497ba371819SOllivier Robert 
4498ba371819SOllivier Robert 	if (rpt_0x8F0B(rpt,
4499ba371819SOllivier Robert 		       &event,
4500ba371819SOllivier Robert 		       &tow,
4501ba371819SOllivier Robert 		       &date,
4502ba371819SOllivier Robert 		       &month,
4503ba371819SOllivier Robert 		       &year,
4504ba371819SOllivier Robert 		       &dim_mode,
4505ba371819SOllivier Robert 		       &utc_offset,
4506ba371819SOllivier Robert 		       &bias,
4507ba371819SOllivier Robert 		       &drift,
4508ba371819SOllivier Robert 		       &bias_unc,
4509ba371819SOllivier Robert 		       &dr_unc,
4510ba371819SOllivier Robert 		       &lat,
4511ba371819SOllivier Robert 		       &lon,
4512ba371819SOllivier Robert 		       &alt,
4513ba371819SOllivier Robert 		       sv_id))
4514ba371819SOllivier Robert 	{
4515ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
4516ba371819SOllivier Robert 		return;
4517ba371819SOllivier Robert 	}
4518ba371819SOllivier Robert 
4519ba371819SOllivier Robert 	if (event == 0)
4520ba371819SOllivier Robert 	{
4521ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\nNew partial+full meas");
4522ba371819SOllivier Robert 	}
4523ba371819SOllivier Robert 	else
4524ba371819SOllivier Robert 	{
4525ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\nEvent count: %5d", event);
4526ba371819SOllivier Robert 	}
4527ba371819SOllivier Robert 
4528ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nGPS time  : %s %2d/%2d/%2d (DMY)",
4529ba371819SOllivier Robert 			show_time(tow), date, month, year);
4530ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nMode      : %s", oprtng_dim[dim_mode]);
4531ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nUTC offset: %2d", utc_offset);
4532ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nClock Bias: %6.2f m", bias);
4533ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nFreq bias : %6.2f m/s", drift);
4534ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nBias unc  : %6.2f m", bias_unc);
4535ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nFreq unc  : %6.2f m/s", dr_unc);
4536ba371819SOllivier Robert 
4537ba371819SOllivier Robert 	lat *= R2D; /* convert from radians to degrees */
4538ba371819SOllivier Robert 	lon *= R2D;
4539ba371819SOllivier Robert 	if (lat < 0.0)
4540ba371819SOllivier Robert 	{
4541ba371819SOllivier Robert 		north_south = 'S';
4542ba371819SOllivier Robert 		lat = -lat;
4543ba371819SOllivier Robert 	}
4544ba371819SOllivier Robert 	else
4545ba371819SOllivier Robert 	{
4546ba371819SOllivier Robert 		north_south = 'N';
4547ba371819SOllivier Robert 	}
4548ba371819SOllivier Robert 
4549ba371819SOllivier Robert 	lat_deg = (short)lat;
4550ba371819SOllivier Robert 	lat_min = (lat - lat_deg) * 60.0;
4551ba371819SOllivier Robert 	if (lon < 0.0)
4552ba371819SOllivier Robert 	{
4553ba371819SOllivier Robert 		east_west = 'W';
4554ba371819SOllivier Robert 		lon = -lon;
4555ba371819SOllivier Robert 	}
4556ba371819SOllivier Robert 	else
4557ba371819SOllivier Robert 	{
4558ba371819SOllivier Robert 		east_west = 'E';
4559ba371819SOllivier Robert 	}
4560ba371819SOllivier Robert 
4561ba371819SOllivier Robert 	lon_deg = (short)lon;
4562ba371819SOllivier Robert 	lon_min = (lon - lon_deg) * 60.0;
4563ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nPosition  :");
4564ba371819SOllivier Robert 	pbuf += sprintf(pbuf, " %4d %6.3f %c", lat_deg, lat_min, north_south);
4565ba371819SOllivier Robert 	pbuf += sprintf(pbuf, " %5d %6.3f %c", lon_deg, lon_min, east_west);
4566ba371819SOllivier Robert 	pbuf += sprintf(pbuf, " %10.2f", alt);
4567ba371819SOllivier Robert 
4568ba371819SOllivier Robert 	numfix = numnotfix = 0;
4569ba371819SOllivier Robert 	for (local_index=0; local_index<8; local_index++)
4570ba371819SOllivier Robert 	{
4571ba371819SOllivier Robert 		if (sv_id[local_index] < 0) numnotfix++;
4572ba371819SOllivier Robert 		if (sv_id[local_index] > 0) numfix++;
4573ba371819SOllivier Robert 	}
4574ba371819SOllivier Robert 	if (numfix > 0)
4575ba371819SOllivier Robert 	{
4576ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\nSVs used in fix  : ");
4577ba371819SOllivier Robert 		for (local_index=0; local_index<8; local_index++)
4578ba371819SOllivier Robert 		{
4579ba371819SOllivier Robert 			if (sv_id[local_index] > 0)
4580ba371819SOllivier Robert 			{
4581ba371819SOllivier Robert 				pbuf += sprintf(pbuf, "%2d ", sv_id[local_index]);
4582ba371819SOllivier Robert 			}
4583ba371819SOllivier Robert 		}
4584ba371819SOllivier Robert 	}
4585ba371819SOllivier Robert 	if (numnotfix > 0)
4586ba371819SOllivier Robert 	{
4587ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\nOther SVs tracked: ");
4588ba371819SOllivier Robert 		for (local_index=0; local_index<8; local_index++)
4589ba371819SOllivier Robert 		{
4590ba371819SOllivier Robert 			if (sv_id[local_index] < 0)
4591ba371819SOllivier Robert 			{
4592ba371819SOllivier Robert 				pbuf += sprintf(pbuf, "%2d ", sv_id[local_index]);
4593ba371819SOllivier Robert 			}
4594ba371819SOllivier Robert 		}
4595ba371819SOllivier Robert 	}
4596ba371819SOllivier Robert }
4597ba371819SOllivier Robert 
4598ba371819SOllivier Robert /* 0x8F14 */
4599ba371819SOllivier Robert /* Datum parameters */
46002b15cb3dSCy Schubert static void
46012b15cb3dSCy Schubert rpt_8F14(
46022b15cb3dSCy Schubert 	 TSIPPKT *rpt
46032b15cb3dSCy Schubert 	 )
4604ba371819SOllivier Robert {
4605ba371819SOllivier Robert 	double
4606ba371819SOllivier Robert 	    datum_coeffs[5];
4607ba371819SOllivier Robert 	short
4608ba371819SOllivier Robert 	    datum_idx;
4609ba371819SOllivier Robert 
4610ba371819SOllivier Robert 	/* unload rptbuf */
4611ba371819SOllivier Robert 	if (rpt_0x8F14 (rpt, &datum_idx, datum_coeffs))
4612ba371819SOllivier Robert 	{
4613ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
4614ba371819SOllivier Robert 		return;
4615ba371819SOllivier Robert 	}
4616ba371819SOllivier Robert 
4617ba371819SOllivier Robert 	if (datum_idx == -1)
4618ba371819SOllivier Robert 	{
4619ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\nUser-Entered Datum:");
4620ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\n   dx        = %6.1f", datum_coeffs[0]);
4621ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\n   dy        = %6.1f", datum_coeffs[1]);
4622ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\n   dz        = %6.1f", datum_coeffs[2]);
4623ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\n   a-axis    = %10.3f", datum_coeffs[3]);
4624ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\n   e-squared = %16.14f", datum_coeffs[4]);
4625ba371819SOllivier Robert 	}
4626ba371819SOllivier Robert 	else if (datum_idx == 0)
4627ba371819SOllivier Robert 	{
4628ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\nWGS-84 datum, Index 0 ");
4629ba371819SOllivier Robert 	}
4630ba371819SOllivier Robert 	else
4631ba371819SOllivier Robert 	{
4632ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\nStandard Datum, Index %3d ", datum_idx);
4633ba371819SOllivier Robert 	}
4634ba371819SOllivier Robert }
4635ba371819SOllivier Robert 
4636ba371819SOllivier Robert /* 0x8F15 */
4637ba371819SOllivier Robert /* Datum parameters */
46382b15cb3dSCy Schubert static void
46392b15cb3dSCy Schubert rpt_8F15(
46402b15cb3dSCy Schubert 	 TSIPPKT *rpt
46412b15cb3dSCy Schubert 	 )
4642ba371819SOllivier Robert {
4643ba371819SOllivier Robert 	double
4644ba371819SOllivier Robert 	    datum_coeffs[5];
4645ba371819SOllivier Robert 	short
4646ba371819SOllivier Robert 	    datum_idx;
4647ba371819SOllivier Robert 
4648ba371819SOllivier Robert 	/* unload rptbuf */
4649ba371819SOllivier Robert 	if (rpt_0x8F15 (rpt, &datum_idx, datum_coeffs)) {
4650ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
4651ba371819SOllivier Robert 		return;
4652ba371819SOllivier Robert 	}
4653ba371819SOllivier Robert 
4654ba371819SOllivier Robert 	if (datum_idx == -1)
4655ba371819SOllivier Robert 	{
4656ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\nUser-Entered Datum:");
4657ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\n   dx        = %6.1f", datum_coeffs[0]);
4658ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\n   dy        = %6.1f", datum_coeffs[1]);
4659ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\n   dz        = %6.1f", datum_coeffs[2]);
4660ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\n   a-axis    = %10.3f", datum_coeffs[3]);
4661ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\n   e-squared = %16.14f", datum_coeffs[4]);
4662ba371819SOllivier Robert 	}
4663ba371819SOllivier Robert 	else if (datum_idx == 0)
4664ba371819SOllivier Robert 	{
4665ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\nWGS-84 datum, Index 0 ");
4666ba371819SOllivier Robert 	}
4667ba371819SOllivier Robert 	else
4668ba371819SOllivier Robert 	{
4669ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\nStandard Datum, Index %3d ", datum_idx);
4670ba371819SOllivier Robert 	}
4671ba371819SOllivier Robert }
4672ba371819SOllivier Robert 
4673ba371819SOllivier Robert /* 0x8F20 */
4674ba371819SOllivier Robert #define INFO_DGPS       0x02
4675ba371819SOllivier Robert #define INFO_2D         0x04
4676ba371819SOllivier Robert #define INFO_ALTSET     0x08
4677ba371819SOllivier Robert #define INFO_FILTERED   0x10
46782b15cb3dSCy Schubert static void
46792b15cb3dSCy Schubert rpt_8F20(
46802b15cb3dSCy Schubert 	 TSIPPKT *rpt
46812b15cb3dSCy Schubert 	 )
4682ba371819SOllivier Robert {
4683ba371819SOllivier Robert 	unsigned char
4684ba371819SOllivier Robert 	    info, nsvs, sv_prn[32];
4685ba371819SOllivier Robert 	short
4686ba371819SOllivier Robert 	    week_num, datum_index, sv_IODC[32];
4687ba371819SOllivier Robert 	double
4688ba371819SOllivier Robert 	    lat, lon, alt, time_of_fix;
4689ba371819SOllivier Robert 	double
4690ba371819SOllivier Robert 	    londeg, latdeg, vel[3];
4691ba371819SOllivier Robert 	short
4692ba371819SOllivier Robert 	    isv;
4693ba371819SOllivier Robert 	char
4694ba371819SOllivier Robert 	    datum_string[20];
4695ba371819SOllivier Robert 
4696ba371819SOllivier Robert 	/* unload rptbuf */
4697ba371819SOllivier Robert 	if (rpt_0x8F20 (rpt,
4698ba371819SOllivier Robert 			&info, &lat, &lon, &alt, vel,
4699ba371819SOllivier Robert 			&time_of_fix,
4700ba371819SOllivier Robert 			&week_num, &nsvs, sv_prn, sv_IODC, &datum_index))
4701ba371819SOllivier Robert 	{
4702ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
4703ba371819SOllivier Robert 		return;
4704ba371819SOllivier Robert 	}
4705ba371819SOllivier Robert 	pbuf += sprintf(pbuf,
4706ba371819SOllivier Robert 			"\nFix at: %04d:%3s:%02d:%02d:%06.3f GPS (=UTC+%2ds)  FixType: %s%s%s",
4707ba371819SOllivier Robert 			week_num,
4708ba371819SOllivier Robert 			dayname[(short)(time_of_fix/86400.0)],
4709ba371819SOllivier Robert 			(short)fmod(time_of_fix/3600., 24.),
4710ba371819SOllivier Robert 			(short)fmod(time_of_fix/60., 60.),
4711ba371819SOllivier Robert 			fmod(time_of_fix, 60.),
4712ba371819SOllivier Robert 			(char)rpt->buf[29],		/* UTC offset */
4713ba371819SOllivier Robert 			(info & INFO_DGPS)?"Diff":"",
4714ba371819SOllivier Robert 			(info & INFO_2D)?"2D":"3D",
4715ba371819SOllivier Robert 			(info & INFO_FILTERED)?"-Filtrd":"");
4716ba371819SOllivier Robert 
4717ba371819SOllivier Robert 	if (datum_index > 0)
4718ba371819SOllivier Robert 	{
4719ba371819SOllivier Robert 		sprintf(datum_string, "Datum%3d", datum_index);
4720ba371819SOllivier Robert 	}
4721ba371819SOllivier Robert 	else if (datum_index)
4722ba371819SOllivier Robert 	{
4723ba371819SOllivier Robert 		sprintf(datum_string, "Unknown ");
4724ba371819SOllivier Robert 	}
4725ba371819SOllivier Robert 	else
4726ba371819SOllivier Robert 	{
4727ba371819SOllivier Robert 		sprintf(datum_string, "WGS-84");
4728ba371819SOllivier Robert 	}
4729ba371819SOllivier Robert 
4730ba371819SOllivier Robert 	/* convert from radians to degrees */
4731ba371819SOllivier Robert 	latdeg = R2D * fabs(lat);
4732ba371819SOllivier Robert 	londeg = R2D * fabs(lon);
4733ba371819SOllivier Robert 	pbuf += sprintf(pbuf,
4734ba371819SOllivier Robert 			"\n   Pos: %4d:%09.6f %c %5d:%09.6f %c %10.2f m HAE (%s)",
4735ba371819SOllivier Robert 			(short)latdeg, fmod (latdeg, 1.)*60.0,
4736ba371819SOllivier Robert 			(lat<0.0)?'S':'N',
4737ba371819SOllivier Robert 			(short)londeg, fmod (londeg, 1.)*60.0,
4738ba371819SOllivier Robert 			(lon<0.0)?'W':'E',
4739ba371819SOllivier Robert 			alt,
4740ba371819SOllivier Robert 			datum_string);
4741ba371819SOllivier Robert 	pbuf += sprintf(pbuf,
4742ba371819SOllivier Robert 			"\n   Vel:    %9.3f E       %9.3f N      %9.3f U   (m/sec)",
4743ba371819SOllivier Robert 			vel[0], vel[1], vel[2]);
4744ba371819SOllivier Robert 
4745ba371819SOllivier Robert 	pbuf += sprintf(pbuf,
4746ba371819SOllivier Robert 			"\n   SVs: ");
4747ba371819SOllivier Robert 	for (isv = 0; isv < nsvs; isv++) {
4748ba371819SOllivier Robert 		pbuf += sprintf(pbuf, " %02d", sv_prn[isv]);
4749ba371819SOllivier Robert 	}
4750ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "     (IODEs:");
4751ba371819SOllivier Robert 	for (isv = 0; isv < nsvs; isv++) {
4752ba371819SOllivier Robert 		pbuf += sprintf(pbuf, " %02X", sv_IODC[isv]&0xFF);
4753ba371819SOllivier Robert 	}
4754ba371819SOllivier Robert 	pbuf += sprintf(pbuf, ")");
4755ba371819SOllivier Robert }
4756ba371819SOllivier Robert 
4757ba371819SOllivier Robert /* 0x8F41 */
47582b15cb3dSCy Schubert static void
47592b15cb3dSCy Schubert rpt_8F41(
47602b15cb3dSCy Schubert 	 TSIPPKT *rpt
47612b15cb3dSCy Schubert 	 )
4762ba371819SOllivier Robert {
4763ba371819SOllivier Robert 	unsigned char
4764ba371819SOllivier Robert 	    bSearchRange,
4765ba371819SOllivier Robert 	    bBoardOptions,
4766ba371819SOllivier Robert 	    bBuildYear,
4767ba371819SOllivier Robert 	    bBuildMonth,
4768ba371819SOllivier Robert 	    bBuildDay,
4769ba371819SOllivier Robert 	    bBuildHour;
4770ba371819SOllivier Robert 	float
4771ba371819SOllivier Robert 	    fOscOffset;
4772ba371819SOllivier Robert 	unsigned short
4773ba371819SOllivier Robert 	    iTestCodeId;
4774ba371819SOllivier Robert 	unsigned long
4775ba371819SOllivier Robert 	    iiSerialNumber;
4776ba371819SOllivier Robert 
4777ba371819SOllivier Robert 	if (!rpt_0x8F41(rpt,
4778ba371819SOllivier Robert 			&bSearchRange,
4779ba371819SOllivier Robert 			&bBoardOptions,
4780ba371819SOllivier Robert 			&iiSerialNumber,
4781ba371819SOllivier Robert 			&bBuildYear,
4782ba371819SOllivier Robert 			&bBuildMonth,
4783ba371819SOllivier Robert 			&bBuildDay,
4784ba371819SOllivier Robert 			&bBuildHour,
4785ba371819SOllivier Robert 			&fOscOffset,
4786ba371819SOllivier Robert 			&iTestCodeId))
4787ba371819SOllivier Robert 	{
4788ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
4789ba371819SOllivier Robert 		return;
4790ba371819SOllivier Robert 	}
4791ba371819SOllivier Robert 
4792ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n  search range:          %d",
4793ba371819SOllivier Robert 			bSearchRange);
4794ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n  board options:         %d",
4795ba371819SOllivier Robert 			bBoardOptions);
4796ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n  board serial #:        %ld",
4797ba371819SOllivier Robert 			iiSerialNumber);
4798ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n  build date/hour:       %02d/%02d/%02d %02d:00",
4799ba371819SOllivier Robert 			bBuildDay, bBuildMonth, bBuildYear, bBuildHour);
4800ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n  osc offset:            %.3f PPM (%.0f Hz)",
4801ba371819SOllivier Robert 			fOscOffset/1575.42, fOscOffset);
4802ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n  test code:             %d",
4803ba371819SOllivier Robert 			iTestCodeId);
4804ba371819SOllivier Robert }
4805ba371819SOllivier Robert 
4806ba371819SOllivier Robert /* 0x8F42 */
48072b15cb3dSCy Schubert static void
48082b15cb3dSCy Schubert rpt_8F42(
48092b15cb3dSCy Schubert 	 TSIPPKT *rpt
48102b15cb3dSCy Schubert 	 )
4811ba371819SOllivier Robert {
4812ba371819SOllivier Robert 	unsigned char
4813ba371819SOllivier Robert 	    bProdOptionsPre,
4814ba371819SOllivier Robert 	    bProdNumberExt;
4815ba371819SOllivier Robert 	unsigned short
4816ba371819SOllivier Robert 	    iCaseSerialNumberPre,
4817ba371819SOllivier Robert 	    iPremiumOptions,
4818ba371819SOllivier Robert 	    iMachineID,
4819ba371819SOllivier Robert 	    iKey;
4820ba371819SOllivier Robert 	unsigned long
4821ba371819SOllivier Robert 	    iiCaseSerialNumber,
4822ba371819SOllivier Robert 	    iiProdNumber;
4823ba371819SOllivier Robert 
4824ba371819SOllivier Robert 	if (!rpt_0x8F42(rpt,
4825ba371819SOllivier Robert 			&bProdOptionsPre,
4826ba371819SOllivier Robert 			&bProdNumberExt,
4827ba371819SOllivier Robert 			&iCaseSerialNumberPre,
4828ba371819SOllivier Robert 			&iiCaseSerialNumber,
4829ba371819SOllivier Robert 			&iiProdNumber,
4830ba371819SOllivier Robert 			&iPremiumOptions,
4831ba371819SOllivier Robert 			&iMachineID,
4832ba371819SOllivier Robert 			&iKey))
4833ba371819SOllivier Robert 	{
4834ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
4835ba371819SOllivier Robert 		return;
4836ba371819SOllivier Robert 	}
4837ba371819SOllivier Robert 
4838ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nProduct ID 8F42");
4839ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   extension:            %d", bProdNumberExt);
4840ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   case serial # prefix: %d", iCaseSerialNumberPre);
4841ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   case serial #:        %ld", iiCaseSerialNumber);
4842ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   prod. #:              %ld", iiProdNumber);
4843ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   premium options:      %Xh", iPremiumOptions);
4844ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   machine ID:           %d", iMachineID);
4845ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   key:                  %Xh", iKey);
4846ba371819SOllivier Robert }
4847ba371819SOllivier Robert 
4848ba371819SOllivier Robert /* 0x8F45 */
48492b15cb3dSCy Schubert static void
48502b15cb3dSCy Schubert rpt_8F45(
48512b15cb3dSCy Schubert 	 TSIPPKT *rpt
48522b15cb3dSCy Schubert 	 )
4853ba371819SOllivier Robert {
4854ba371819SOllivier Robert 	unsigned char bSegMask;
4855ba371819SOllivier Robert 
4856ba371819SOllivier Robert 	if (!rpt_0x8F45(rpt,
4857ba371819SOllivier Robert 			&bSegMask))
4858ba371819SOllivier Robert 	{
4859ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
4860ba371819SOllivier Robert 		return;
4861ba371819SOllivier Robert 	}
4862ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nCleared Segment Mask: %Xh", bSegMask);
4863ba371819SOllivier Robert }
4864ba371819SOllivier Robert 
4865ba371819SOllivier Robert /* Stinger PPS def */
48662b15cb3dSCy Schubert static void
48672b15cb3dSCy Schubert rpt_8F4A(
48682b15cb3dSCy Schubert 	 TSIPPKT *rpt
48692b15cb3dSCy Schubert 	 )
4870ba371819SOllivier Robert {
4871ba371819SOllivier Robert 	unsigned char
4872ba371819SOllivier Robert 	    pps_enabled,
4873ba371819SOllivier Robert 	    pps_timebase,
4874ba371819SOllivier Robert 	    pps_polarity;
4875ba371819SOllivier Robert 	float
4876ba371819SOllivier Robert 	    bias_unc_threshold;
4877ba371819SOllivier Robert 	double
4878ba371819SOllivier Robert 	    pps_offset;
4879ba371819SOllivier Robert 
4880ba371819SOllivier Robert   	if (rpt_0x8F4A_16 (rpt,
4881ba371819SOllivier Robert 			   &pps_enabled,
4882ba371819SOllivier Robert 			   &pps_timebase,
4883ba371819SOllivier Robert 			   &pps_polarity,
4884ba371819SOllivier Robert 			   &pps_offset,
4885ba371819SOllivier Robert 			   &bias_unc_threshold))
4886ba371819SOllivier Robert 	{
4887ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
4888ba371819SOllivier Robert 		return;
4889ba371819SOllivier Robert 	}
4890ba371819SOllivier Robert 
4891ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nPPS is         %s",	pps_enabled?"enabled":"disabled");
4892ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   timebase:   %s", PPSTimeBaseText[pps_timebase]);
4893ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   polarity:   %s", PPSPolarityText[pps_polarity]);
4894ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   offset:     %.1f ns, ", pps_offset*1.e9);
4895ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   biasunc:    %.1f ns", bias_unc_threshold/GPS_C*1.e9);
4896ba371819SOllivier Robert }
4897ba371819SOllivier Robert 
4898ba371819SOllivier Robert /* fast-SA decorrolation time for self-survey */
48992b15cb3dSCy Schubert static void
49002b15cb3dSCy Schubert rpt_8F4B(
49012b15cb3dSCy Schubert 	 TSIPPKT *rpt
49022b15cb3dSCy Schubert 	 )
4903ba371819SOllivier Robert {
4904ba371819SOllivier Robert 	unsigned long
4905ba371819SOllivier Robert 	    decorr_max;
4906ba371819SOllivier Robert 
4907ba371819SOllivier Robert 	if (rpt_0x8F4B(rpt, &decorr_max))
4908ba371819SOllivier Robert 	{
4909ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
4910ba371819SOllivier Robert 		return;
4911ba371819SOllivier Robert 	}
4912ba371819SOllivier Robert 
4913ba371819SOllivier Robert 	pbuf += sprintf(pbuf,
4914ba371819SOllivier Robert 			"\nMax # of position fixes for self-survey : %ld",
4915ba371819SOllivier Robert 			decorr_max);
4916ba371819SOllivier Robert }
4917ba371819SOllivier Robert 
49182b15cb3dSCy Schubert static void
49192b15cb3dSCy Schubert rpt_8F4D(
49202b15cb3dSCy Schubert 	 TSIPPKT *rpt
49212b15cb3dSCy Schubert 	 )
4922ba371819SOllivier Robert {
4923ba371819SOllivier Robert 	static char
4924ba371819SOllivier Robert 	    *linestart;
4925ba371819SOllivier Robert 	unsigned long
4926ba371819SOllivier Robert 	    OutputMask;
4927ba371819SOllivier Robert 	static unsigned long
4928ba371819SOllivier Robert 	    MaskBit[] = {
49292b15cb3dSCy Schubert 		0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010,
49302b15cb3dSCy Schubert 		0x00000020,
4931ba371819SOllivier Robert 		0x00000100L, 0x00000800L, 0x00001000L,
4932ba371819SOllivier Robert 		0x40000000L, 0x80000000L};
4933ba371819SOllivier Robert 	int
4934ba371819SOllivier Robert 	    ichoice,
4935ba371819SOllivier Robert 	    numchoices;
4936ba371819SOllivier Robert 
4937ba371819SOllivier Robert 	if (rpt_0x8F4D(rpt, &OutputMask))
4938ba371819SOllivier Robert 	{
4939ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
4940ba371819SOllivier Robert 		return;
4941ba371819SOllivier Robert 	}
4942ba371819SOllivier Robert 
4943ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nAuto-Report Mask: %02X %02X %02X %02X",
4944ba371819SOllivier Robert 			(unsigned char)(OutputMask>>24),
4945ba371819SOllivier Robert 			(unsigned char)(OutputMask>>16),
4946ba371819SOllivier Robert 			(unsigned char)(OutputMask>>8),
4947ba371819SOllivier Robert 			(unsigned char)OutputMask);
4948ba371819SOllivier Robert 
4949ba371819SOllivier Robert 	numchoices = sizeof(MaskText)/sizeof(char*);
4950ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nAuto-Reports scheduled for Output:");
4951ba371819SOllivier Robert 	linestart = pbuf;
4952ba371819SOllivier Robert 	for (ichoice = 0; ichoice < numchoices; ichoice++)
4953ba371819SOllivier Robert 	{
4954ba371819SOllivier Robert 		if (OutputMask&MaskBit[ichoice])
4955ba371819SOllivier Robert 		{
4956ba371819SOllivier Robert 			pbuf += sprintf(pbuf, "%s %s",
4957ba371819SOllivier Robert 					(pbuf==linestart)?"\n     ":",",
4958ba371819SOllivier Robert 					MaskText[ichoice]);
4959ba371819SOllivier Robert 			if (pbuf-linestart > 60) linestart = pbuf;
4960ba371819SOllivier Robert 		}
4961ba371819SOllivier Robert 	}
4962ba371819SOllivier Robert 
4963ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nAuto-Reports NOT scheduled for Output:");
4964ba371819SOllivier Robert 	linestart = pbuf;
4965ba371819SOllivier Robert 	for (ichoice = 0; ichoice < numchoices; ichoice++)
4966ba371819SOllivier Robert 	{
4967ba371819SOllivier Robert 		if (OutputMask&MaskBit[ichoice]) continue;
4968ba371819SOllivier Robert 	     	pbuf += sprintf(pbuf, "%s %s",
4969ba371819SOllivier Robert 				(pbuf==linestart)?"\n     ":",",
4970ba371819SOllivier Robert 				MaskText[ichoice]);
4971ba371819SOllivier Robert 		if (pbuf-linestart > 60) linestart = pbuf;
4972ba371819SOllivier Robert 	}
4973ba371819SOllivier Robert }
4974ba371819SOllivier Robert 
49752b15cb3dSCy Schubert static void
49762b15cb3dSCy Schubert rpt_8FA5(
49772b15cb3dSCy Schubert 	 TSIPPKT *rpt
49782b15cb3dSCy Schubert 	 )
4979ba371819SOllivier Robert {
4980ba371819SOllivier Robert 	unsigned char
4981ba371819SOllivier Robert 	    spktmask[4];
4982ba371819SOllivier Robert 
4983ba371819SOllivier Robert 	if (rpt_0x8FA5(rpt, spktmask))
4984ba371819SOllivier Robert 	{
4985ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
4986ba371819SOllivier Robert 		return;
4987ba371819SOllivier Robert 	}
4988ba371819SOllivier Robert 
4989ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\nSuperpacket auto-output mask: %02X %02X %02X %02X",
4990ba371819SOllivier Robert 			spktmask[0], spktmask[1], spktmask[2], spktmask[3]);
4991ba371819SOllivier Robert 
4992ba371819SOllivier Robert 	if (spktmask[0]&0x01) pbuf+= sprintf (pbuf, "\n    PPS   8F-0B");
4993ba371819SOllivier Robert 	if (spktmask[0]&0x02) pbuf+= sprintf (pbuf, "\n    Event 8F-0B");
4994ba371819SOllivier Robert 	if (spktmask[0]&0x10) pbuf+= sprintf (pbuf, "\n    PPS   8F-AD");
4995ba371819SOllivier Robert 	if (spktmask[0]&0x20) pbuf+= sprintf (pbuf, "\n    Event 8F-AD");
4996ba371819SOllivier Robert 	if (spktmask[2]&0x01) pbuf+= sprintf (pbuf, "\n    ppos Fix 8F-20");
4997ba371819SOllivier Robert }
4998ba371819SOllivier Robert 
49992b15cb3dSCy Schubert static void
50002b15cb3dSCy Schubert rpt_8FAD(
50012b15cb3dSCy Schubert 	 TSIPPKT *rpt
50022b15cb3dSCy Schubert 	 )
5003ba371819SOllivier Robert {
5004ba371819SOllivier Robert 	unsigned short
5005ba371819SOllivier Robert 	    Count,
5006ba371819SOllivier Robert 	    Year;
5007ba371819SOllivier Robert 	double
5008ba371819SOllivier Robert 	    FracSec;
5009ba371819SOllivier Robert 	unsigned char
5010ba371819SOllivier Robert 	    Hour,
5011ba371819SOllivier Robert 	    Minute,
5012ba371819SOllivier Robert 	    Second,
5013ba371819SOllivier Robert 	    Day,
5014ba371819SOllivier Robert 	    Month,
5015ba371819SOllivier Robert 	    Status,
5016ba371819SOllivier Robert 	    Flags;
5017ba371819SOllivier Robert 	static char* Status8FADText[] = {
5018ba371819SOllivier Robert 		"CODE_DOING_FIXES",
5019ba371819SOllivier Robert 		"CODE_GOOD_1_SV",
5020ba371819SOllivier Robert 		"CODE_APPX_1SV",
5021ba371819SOllivier Robert 		"CODE_NEED_TIME",
5022ba371819SOllivier Robert 		"CODE_NEED_INITIALIZATION",
5023ba371819SOllivier Robert 		"CODE_PDOP_HIGH",
5024ba371819SOllivier Robert 		"CODE_BAD_1SV",
5025ba371819SOllivier Robert 		"CODE_0SVS",
5026ba371819SOllivier Robert 		"CODE_1SV",
5027ba371819SOllivier Robert 		"CODE_2SVS",
5028ba371819SOllivier Robert 		"CODE_3SVS",
5029ba371819SOllivier Robert 		"CODE_NO_INTEGRITY",
5030ba371819SOllivier Robert 		"CODE_DCORR_GEN",
5031ba371819SOllivier Robert 		"CODE_OVERDET_CLK",
5032ba371819SOllivier Robert 		"Invalid Status"},
5033ba371819SOllivier Robert 	    *LeapStatusText[] = {
5034ba371819SOllivier Robert 		    " UTC Avail", " ", " ", " ",
5035ba371819SOllivier Robert 		    " Scheduled", " Pending", " Warning", " In Progress"};
5036ba371819SOllivier Robert 	int i;
5037ba371819SOllivier Robert 
5038ba371819SOllivier Robert 	if (rpt_0x8FAD (rpt,
5039ba371819SOllivier Robert 			&Count,
5040ba371819SOllivier Robert 			&FracSec,
5041ba371819SOllivier Robert 			&Hour,
5042ba371819SOllivier Robert 			&Minute,
5043ba371819SOllivier Robert 			&Second,
5044ba371819SOllivier Robert 			&Day,
5045ba371819SOllivier Robert 			&Month,
5046ba371819SOllivier Robert 			&Year,
5047ba371819SOllivier Robert 			&Status,
5048ba371819SOllivier Robert 			&Flags))
5049ba371819SOllivier Robert 	{
5050ba371819SOllivier Robert 		parsed = BADLEN_PARSE;
5051ba371819SOllivier Robert 		return;
5052ba371819SOllivier Robert 	}
5053ba371819SOllivier Robert 
5054ba371819SOllivier Robert 	pbuf += sprintf(pbuf,    "\n8FAD   Count: %d   Status: %s",
5055ba371819SOllivier Robert 			Count, Status8FADText[Status]);
5056ba371819SOllivier Robert 
5057ba371819SOllivier Robert 	pbuf += sprintf(pbuf, "\n   Leap Flags:");
5058ba371819SOllivier Robert 	if (Flags)
5059ba371819SOllivier Robert 	{
5060ba371819SOllivier Robert 		for (i=0; i<8; i++)
5061ba371819SOllivier Robert 		{
5062ba371819SOllivier Robert 			if (Flags&(1<<i)) pbuf += sprintf(pbuf, LeapStatusText[i]);
5063ba371819SOllivier Robert 		}
5064ba371819SOllivier Robert 	}
5065ba371819SOllivier Robert 	else
5066ba371819SOllivier Robert 	{
5067ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "  UTC info not available");
5068ba371819SOllivier Robert 	}
5069ba371819SOllivier Robert 
5070ba371819SOllivier Robert 	pbuf += sprintf(pbuf,     "\n      %02d/%02d/%04d (DMY)  %02d:%02d:%02d.%09ld UTC",
5071ba371819SOllivier Robert 			Day, Month, Year, Hour, Minute, Second, (long)(FracSec*1.e9));
5072ba371819SOllivier Robert }
5073ba371819SOllivier Robert 
5074ba371819SOllivier Robert 
50752b15cb3dSCy Schubert int
50762b15cb3dSCy Schubert print_msg_table_header(
50772b15cb3dSCy Schubert 		       int rptcode,
50782b15cb3dSCy Schubert 		       char *HdrStr,
50792b15cb3dSCy Schubert 		       int force
50802b15cb3dSCy Schubert 		       )
5081ba371819SOllivier Robert {
5082ba371819SOllivier Robert 	/* force header is to help auto-output function */
5083ba371819SOllivier Robert 	/* last_rptcode is to determine whether to print a header */
50849c2daa00SOllivier Robert 	/* for the first occurrence of a series of reports */
5085ba371819SOllivier Robert 	static int
5086ba371819SOllivier Robert 	    last_rptcode = 0;
5087ba371819SOllivier Robert 	int
5088ba371819SOllivier Robert 	    numchars;
5089ba371819SOllivier Robert 
5090ba371819SOllivier Robert 	numchars = 0;
5091ba371819SOllivier Robert 	if (force || rptcode!=last_rptcode)
5092ba371819SOllivier Robert 	{
5093ba371819SOllivier Robert 		/* supply a header in console output */
5094ba371819SOllivier Robert 		switch (rptcode)
5095ba371819SOllivier Robert 		{
5096ba371819SOllivier Robert 		    case 0x5A:
5097ba371819SOllivier Robert 			numchars = sprintf(HdrStr, "\nRaw Measurement Data");
5098ba371819SOllivier Robert 			numchars += sprintf(HdrStr+numchars,
5099ba371819SOllivier Robert 					    "\n   SV  Sample   SNR  Code Phase   Doppler    Seconds     Time of Meas");
5100ba371819SOllivier Robert 			break;
5101ba371819SOllivier Robert 
5102ba371819SOllivier Robert 		    case 0x5B:
5103ba371819SOllivier Robert 			numchars = sprintf(HdrStr, "\nEphemeris Status");
5104ba371819SOllivier Robert 			numchars += sprintf(HdrStr+numchars,
5105ba371819SOllivier Robert 					    "\n    SV     Time collected     Health  IODE        t oe         Fit   URA");
5106ba371819SOllivier Robert 			break;
5107ba371819SOllivier Robert 
5108ba371819SOllivier Robert 		    case 0x5C:
5109ba371819SOllivier Robert 			numchars = sprintf(HdrStr, "\nTracking Info");
5110ba371819SOllivier Robert 			numchars += sprintf(HdrStr+numchars,
5111ba371819SOllivier Robert 					    "\n   SV  C Acq Eph   SNR     Time of Meas       Elev  Azim   ");
5112ba371819SOllivier Robert 			break;
5113ba371819SOllivier Robert 
5114ba371819SOllivier Robert 		}
5115ba371819SOllivier Robert 	}
5116ba371819SOllivier Robert 	last_rptcode = rptcode;
5117ba371819SOllivier Robert 	return (short)numchars;
5118ba371819SOllivier Robert }
5119ba371819SOllivier Robert 
51202b15cb3dSCy Schubert static void
51212b15cb3dSCy Schubert unknown_rpt(
51222b15cb3dSCy Schubert 	    TSIPPKT *rpt
51232b15cb3dSCy Schubert 	    )
5124ba371819SOllivier Robert {
5125ba371819SOllivier Robert 	int i;
5126ba371819SOllivier Robert 
5127ba371819SOllivier Robert 	/* app-specific rpt packets */
5128ba371819SOllivier Robert 	if (parsed == BADLEN_PARSE)
5129ba371819SOllivier Robert 	{
5130ba371819SOllivier Robert 		pbuf += sprintf(pbuf, "\nTSIP report packet ID %2Xh, length %d: Bad length",
5131ba371819SOllivier Robert 				rpt->code, rpt->len);
5132ba371819SOllivier Robert 	}
5133ba371819SOllivier Robert 	if (parsed == BADID_PARSE)
5134ba371819SOllivier Robert 	{
5135ba371819SOllivier Robert 		pbuf += sprintf(pbuf,
5136ba371819SOllivier Robert 				"\nTSIP report packet ID %2Xh, length %d: translation not supported",
5137ba371819SOllivier Robert 				rpt->code, rpt->len);
5138ba371819SOllivier Robert 	}
5139ba371819SOllivier Robert 
5140ba371819SOllivier Robert 	if (parsed == BADDATA_PARSE)
5141ba371819SOllivier Robert 	{
5142ba371819SOllivier Robert 		pbuf += sprintf(pbuf,
5143ba371819SOllivier Robert 				"\nTSIP report packet ID %2Xh, length %d: data content incorrect",
5144ba371819SOllivier Robert 				rpt->code, rpt->len);
5145ba371819SOllivier Robert 	}
5146ba371819SOllivier Robert 
5147ba371819SOllivier Robert 	for (i = 0; i < rpt->len; i++) {
5148ba371819SOllivier Robert 		if ((i % 20) == 0) *pbuf++ = '\n';
5149ba371819SOllivier Robert 		pbuf += sprintf(pbuf, " %02X", rpt->buf[i]);
5150ba371819SOllivier Robert 	}
5151ba371819SOllivier Robert }
5152ba371819SOllivier Robert /**/
51532b15cb3dSCy Schubert 
5154ba371819SOllivier Robert /*
5155ba371819SOllivier Robert ** main subroutine, called from ProcessInputBytesWhileWaitingForKBHit()
5156ba371819SOllivier Robert */
51572b15cb3dSCy Schubert void
51582b15cb3dSCy Schubert TranslateTSIPReportToText(
51592b15cb3dSCy Schubert 			  TSIPPKT *rpt,
51602b15cb3dSCy Schubert 			  char *TextOutputBuffer
51612b15cb3dSCy Schubert 			  )
5162ba371819SOllivier Robert {
5163ba371819SOllivier Robert 
5164ba371819SOllivier Robert 	/* pbuf is the pointer to the current location of the text output */
5165ba371819SOllivier Robert 	pbuf = TextOutputBuffer;
5166ba371819SOllivier Robert 
5167ba371819SOllivier Robert 	/* keep track of whether the message has been successfully parsed */
5168ba371819SOllivier Robert 	parsed = GOOD_PARSE;
5169ba371819SOllivier Robert 
5170ba371819SOllivier Robert 	/* print a header if this is the first of a series of messages */
5171ba371819SOllivier Robert 	pbuf += print_msg_table_header (rpt->code, pbuf, FALSE);
5172ba371819SOllivier Robert 
5173ba371819SOllivier Robert 	/* process incoming TSIP report according to code */
5174ba371819SOllivier Robert 	switch (rpt->code)
5175ba371819SOllivier Robert 	{
5176ba371819SOllivier Robert 	    case 0x3D: rpt_chan_A_config (rpt); break;
5177ba371819SOllivier Robert 	    case 0x40: rpt_almanac_data_page (rpt); break;
5178ba371819SOllivier Robert 	    case 0x41: rpt_GPS_time (rpt); break;
5179ba371819SOllivier Robert 	    case 0x42: rpt_single_ECEF_position (rpt); break;
5180ba371819SOllivier Robert 	    case 0x43: rpt_single_ECEF_velocity (rpt); break;
5181ba371819SOllivier Robert 	    case 0x45: rpt_SW_version (rpt); break;
5182ba371819SOllivier Robert 	    case 0x46: rpt_rcvr_health (rpt); break;
5183ba371819SOllivier Robert 	    case 0x47: rpt_SNR_all_SVs (rpt); break;
5184ba371819SOllivier Robert 	    case 0x48: rpt_GPS_system_message (rpt); break;
5185ba371819SOllivier Robert 	    case 0x49: rpt_almanac_health_page (rpt); break;
5186ba371819SOllivier Robert 	    case 0x4A: switch (rpt->len) {
5187ba371819SOllivier Robert 			/*
5188ba371819SOllivier Robert 			** special case (=slip-up) in the TSIP protocol;
5189ba371819SOllivier Robert 			** parsing method depends on length
5190ba371819SOllivier Robert 			*/
5191ba371819SOllivier Robert 		    case 20: rpt_single_lla_position (rpt); break;
5192ba371819SOllivier Robert 		    case  9: rpt_ref_alt (rpt); break;
5193ba371819SOllivier Robert 		} break;
5194ba371819SOllivier Robert 	    case 0x4B: rpt_rcvr_id_and_status (rpt);break;
5195ba371819SOllivier Robert 	    case 0x4C: rpt_operating_parameters (rpt); break;
5196ba371819SOllivier Robert 	    case 0x4D: rpt_oscillator_offset (rpt); break;
5197ba371819SOllivier Robert 	    case 0x4E: rpt_GPS_time_set_response (rpt); break;
5198ba371819SOllivier Robert 	    case 0x4F: rpt_UTC_offset (rpt); break;
5199ba371819SOllivier Robert 	    case 0x54: rpt_1SV_bias (rpt); break;
5200ba371819SOllivier Robert 	    case 0x55: rpt_io_opt (rpt); break;
5201ba371819SOllivier Robert 	    case 0x56: rpt_ENU_velocity (rpt); break;
5202ba371819SOllivier Robert 	    case 0x57: rpt_last_fix_info (rpt); break;
5203ba371819SOllivier Robert 	    case 0x58: rpt_GPS_system_data (rpt); break;
5204ba371819SOllivier Robert 	    case 0x59: rpt_SVs_enabled (rpt); break;
5205ba371819SOllivier Robert 	    case 0x5A: rpt_raw_msmt (rpt); break;
5206ba371819SOllivier Robert 	    case 0x5B: rpt_SV_ephemeris_status (rpt); break;
5207ba371819SOllivier Robert 	    case 0x5C: rpt_SV_tracking_status (rpt); break;
5208ba371819SOllivier Robert 	    case 0x6D: rpt_allSV_selection (rpt); break;
5209ba371819SOllivier Robert 	    case 0x82: rpt_DGPS_position_mode (rpt); break;
5210ba371819SOllivier Robert 	    case 0x83: rpt_double_ECEF_position (rpt); break;
5211ba371819SOllivier Robert 	    case 0x84: rpt_double_lla_position (rpt); break;
5212ba371819SOllivier Robert 	    case 0xBB: rpt_complete_rcvr_config (rpt); break;
5213ba371819SOllivier Robert 	    case 0xBC: rpt_rcvr_serial_port_config (rpt); break;
5214ba371819SOllivier Robert 
5215ba371819SOllivier Robert 	    case 0x8F: switch (rpt->buf[0])
5216ba371819SOllivier Robert 		{
5217ba371819SOllivier Robert 			/* superpackets; parsed according to subcodes */
5218ba371819SOllivier Robert 		    case 0x0B: rpt_8F0B(rpt); break;
5219ba371819SOllivier Robert 		    case 0x14: rpt_8F14(rpt); break;
5220ba371819SOllivier Robert 		    case 0x15: rpt_8F15(rpt); break;
5221ba371819SOllivier Robert 		    case 0x20: rpt_8F20(rpt); break;
5222ba371819SOllivier Robert 		    case 0x41: rpt_8F41(rpt); break;
5223ba371819SOllivier Robert 		    case 0x42: rpt_8F42(rpt); break;
5224ba371819SOllivier Robert 		    case 0x45: rpt_8F45(rpt); break;
5225ba371819SOllivier Robert 		    case 0x4A: rpt_8F4A(rpt); break;
5226ba371819SOllivier Robert 		    case 0x4B: rpt_8F4B(rpt); break;
5227ba371819SOllivier Robert 		    case 0x4D: rpt_8F4D(rpt); break;
5228ba371819SOllivier Robert 		    case 0xA5: rpt_8FA5(rpt); break;
5229ba371819SOllivier Robert 		    case 0xAD: rpt_8FAD(rpt); break;
5230ba371819SOllivier Robert 		    default: parsed = BADID_PARSE; break;
5231ba371819SOllivier Robert 		}
5232ba371819SOllivier Robert 		break;
5233ba371819SOllivier Robert 
5234ba371819SOllivier Robert 	    default: parsed = BADID_PARSE; break;
5235ba371819SOllivier Robert 	}
5236ba371819SOllivier Robert 
5237ba371819SOllivier Robert 	if (parsed != GOOD_PARSE)
5238ba371819SOllivier Robert 	{
5239ba371819SOllivier Robert 		/*
5240ba371819SOllivier Robert 		**The message has TSIP structure (DLEs, etc.)
5241ba371819SOllivier Robert 		** but could not be parsed by above routines
5242ba371819SOllivier Robert 		*/
5243ba371819SOllivier Robert 		unknown_rpt (rpt);
5244ba371819SOllivier Robert 	}
5245ba371819SOllivier Robert 
5246ba371819SOllivier Robert 	/* close TextOutputBuffer */
5247ba371819SOllivier Robert 	pbuf = '\0';
5248ba371819SOllivier Robert }
5249ba371819SOllivier Robert 
5250ba371819SOllivier Robert #endif /* TRIMBLE_OUTPUT_FUNC */
5251ba371819SOllivier Robert 
5252ba371819SOllivier Robert #else  /* defined(REFCLOCK) && defined(CLOCK_RIPENCC) */
5253*f5f40dd6SCy Schubert NONEMPTY_TRANSLATION_UNIT
5254ba371819SOllivier Robert #endif /* defined(REFCLOCK) && defined(CLOCK_RIPENCC) */
5255ba371819SOllivier Robert 
5256