~ubuntu-branches/debian/squeeze/ntp/squeeze-201010051545

« back to all changes in this revision

Viewing changes to ntpd/refclock_ripencc.c

  • Committer: Bazaar Package Importer
  • Author(s): Matt Zimmerman
  • Date: 2004-10-11 16:10:27 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20041011161027-icyjbji8ujym633o
Tags: 1:4.2.0a-10ubuntu2
Use ntp.ubuntulinux.org instead of pool.ntp.org

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Id: refclock_ripencc.c,v 1.13 2002/06/18 14:20:55 marks Exp marks $
 
3
 *
 
4
 * Copyright (c) 2002  RIPE NCC
 
5
 *
 
6
 * All Rights Reserved
 
7
 *
 
8
 * Permission to use, copy, modify, and distribute this software and its
 
9
 * documentation for any purpose and without fee is hereby granted,
 
10
 * provided that the above copyright notice appear in all copies and that
 
11
 * both that copyright notice and this permission notice appear in
 
12
 * supporting documentation, and that the name of the author not be
 
13
 * used in advertising or publicity pertaining to distribution of the
 
14
 * software without specific, written prior permission.
 
15
 *
 
16
 * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 
17
 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
 
18
 * AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
 
19
 * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
 
20
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 
21
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
22
 *
 
23
 *
 
24
 *
 
25
 * This driver was developed for use with the RIPE NCC TTM project.
 
26
 *
 
27
 *
 
28
 * The initial driver was developed by Daniel Karrenberg <dfk@ripe.net> 
 
29
 * using the code made available by Trimble. This was for xntpd-3.x.x
 
30
 *
 
31
 * Rewrite of the driver for ntpd-4.x.x by Mark Santcroos <marks@ripe.net>
 
32
 *
 
33
 */
 
34
 
 
35
#ifdef HAVE_CONFIG_H
 
36
#include <config.h>
 
37
#endif /* HAVE_CONFIG_H */
 
38
 
 
39
#if defined(REFCLOCK) && defined(CLOCK_RIPENCC)
 
40
 
 
41
#include "ntp_stdlib.h"
 
42
#include "ntpd.h"
 
43
#include "ntp_refclock.h"
 
44
#include "ntp_unixtime.h"
 
45
#include "ntp_io.h"
 
46
 
 
47
#ifdef HAVE_TIMEPPS_H
 
48
# include <timepps.h>
 
49
#else /* HAVE_TIMEPPS_H */
 
50
# ifdef HAVE_SYS_TIMEPPS_H
 
51
#  include <sys/timepps.h>
 
52
# endif /* HAVE_SYS_TIMEPPS_H */
 
53
#endif /* HAVE_TIMEPPS_H */
 
54
 
 
55
/*
 
56
 * Definitions
 
57
 */
 
58
 
 
59
/* we are on little endian */
 
60
#define BYTESWAP
 
61
 
 
62
/* 
 
63
 * DEBUG statements: uncomment if necessary
 
64
 */
 
65
/* #define DEBUG_NCC */ /* general debug statements */
 
66
/* #define DEBUG_PPS */ /* debug pps */
 
67
/* #define DEBUG_RAW */ /* print raw packets */
 
68
 
 
69
#define TRIMBLE_OUTPUT_FUNC
 
70
#define TSIP_VERNUM "7.12a"
 
71
 
 
72
#ifndef FALSE
 
73
#define FALSE   (0)
 
74
#define TRUE    (!FALSE)
 
75
#endif /* FALSE */
 
76
 
 
77
#define GPS_PI  (3.1415926535898)
 
78
#define GPS_C           (299792458.)
 
79
#define D2R             (GPS_PI/180.0)
 
80
#define R2D             (180.0/GPS_PI)
 
81
#define WEEK    (604800.)
 
82
#define MAXCHAN  (8)
 
83
 
 
84
/* control characters for TSIP packets */
 
85
#define DLE     (0x10)
 
86
#define ETX     (0x03)
 
87
 
 
88
#define MAX_RPTBUF (256)
 
89
 
 
90
/* values of TSIPPKT.status */
 
91
#define TSIP_PARSED_EMPTY       0
 
92
#define TSIP_PARSED_FULL        1
 
93
#define TSIP_PARSED_DLE_1       2
 
94
#define TSIP_PARSED_DATA        3
 
95
#define TSIP_PARSED_DLE_2       4
 
96
 
 
97
#define UTCF_UTC_AVAIL  (unsigned char) (1)             /* UTC available */
 
98
#define UTCF_LEAP_SCHD  (unsigned char) (1<<4)  /* Leap scheduled */
 
99
#define UTCF_LEAP_PNDG  (unsigned char) (1<<5)  /* Leap pending, will occur at end of day */
 
100
 
 
101
#define DEVICE  "/dev/gps%d"    /* name of radio device */
 
102
#define PRECISION       (-9)    /* precision assumed (about 2 ms) */
 
103
#define PPS_PRECISION   (-20)   /* precision assumed (about 1 us) */
 
104
#define REFID           "GPS\0" /* reference id */
 
105
#define REFID_LEN       4
 
106
#define DESCRIPTION     "RIPE NCC GPS (Palisade)"       /* Description */
 
107
#define SPEED232        B9600   /* 9600 baud */
 
108
 
 
109
#define NSAMPLES        3       /* stages of median filter */
 
110
 
 
111
/* Structures */
 
112
 
 
113
/* TSIP packets have the following structure, whether report or command. */
 
114
typedef struct {
 
115
        short 
 
116
                counter,        /* counter */
 
117
                len;            /* size of buf; < MAX_RPTBUF unsigned chars */
 
118
        unsigned char
 
119
                status,         /* TSIP packet format/parse status */
 
120
                code,           /* TSIP code */
 
121
                buf[MAX_RPTBUF];/* report or command string */
 
122
} TSIPPKT;
 
123
 
 
124
/* TSIP binary data structures */
 
125
typedef struct {
 
126
        unsigned char
 
127
                t_oa_raw, SV_health;
 
128
        float
 
129
                e, t_oa, i_0, OMEGADOT, sqrt_A,
 
130
                OMEGA_0, omega, M_0, a_f0, a_f1,
 
131
                Axis, n, OMEGA_n, ODOT_n, t_zc;
 
132
        short
 
133
                weeknum, wn_oa;
 
134
} ALM_INFO;
 
135
 
 
136
typedef struct {     /*  Almanac health page (25) parameters  */
 
137
        unsigned char
 
138
                WN_a, SV_health[32], t_oa;
 
139
} ALH_PARMS;
 
140
 
 
141
typedef struct {     /*  Universal Coordinated Time (UTC) parms */
 
142
        double
 
143
                A_0;
 
144
        float
 
145
                A_1;
 
146
        short
 
147
                delta_t_LS;
 
148
        float
 
149
                t_ot;
 
150
        short
 
151
                WN_t, WN_LSF, DN, delta_t_LSF;
 
152
} UTC_INFO;
 
153
 
 
154
typedef struct {      /*  Ionospheric info (float)  */
 
155
        float
 
156
                alpha_0, alpha_1, alpha_2, alpha_3,
 
157
                beta_0, beta_1, beta_2, beta_3;
 
158
} ION_INFO;
 
159
 
 
160
typedef struct {      /*  Subframe 1 info (float)  */
 
161
        short
 
162
                weeknum;
 
163
        unsigned char
 
164
                codeL2, L2Pdata, SVacc_raw, SV_health;
 
165
        short
 
166
                IODC;
 
167
        float
 
168
                T_GD, t_oc, a_f2, a_f1, a_f0, SVacc;
 
169
} EPHEM_CLOCK;
 
170
 
 
171
typedef struct {     /*  Ephemeris info (float)  */
 
172
        unsigned char
 
173
                IODE, fit_interval;
 
174
        float
 
175
                C_rs, delta_n;
 
176
        double
 
177
                M_0;
 
178
        float
 
179
                C_uc;
 
180
        double
 
181
                e;
 
182
        float
 
183
                C_us;
 
184
        double
 
185
                sqrt_A;
 
186
        float
 
187
                t_oe, C_ic;
 
188
        double
 
189
                OMEGA_0;
 
190
        float
 
191
                C_is;
 
192
        double
 
193
                i_0;
 
194
        float
 
195
                C_rc;
 
196
        double
 
197
                omega;
 
198
        float
 
199
                OMEGADOT, IDOT;
 
200
        double
 
201
                Axis, n, r1me2, OMEGA_n, ODOT_n;
 
202
} EPHEM_ORBIT;
 
203
 
 
204
typedef struct {     /* Navigation data structure */
 
205
        short
 
206
                sv_number;     /* SV number (0 = no entry) */
 
207
        float
 
208
                t_ephem;       /* time of ephemeris collection */
 
209
        EPHEM_CLOCK
 
210
                ephclk;        /* subframe 1 data */
 
211
        EPHEM_ORBIT
 
212
                ephorb;        /* ephemeris data */
 
213
} NAV_INFO;
 
214
 
 
215
typedef struct {
 
216
        unsigned char
 
217
                bSubcode,
 
218
                operating_mode,
 
219
                dgps_mode,
 
220
                dyn_code,
 
221
                trackmode;
 
222
        float
 
223
                elev_mask,
 
224
                cno_mask,
 
225
                dop_mask,
 
226
                dop_switch;
 
227
        unsigned char
 
228
                dgps_age_limit;
 
229
} TSIP_RCVR_CFG;
 
230
 
 
231
 
 
232
#ifdef TRIMBLE_OUTPUT_FUNC
 
233
static char
 
234
        *dayname[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"},
 
235
        old_baudnum[] = {0, 1, 4, 5, 6, 8, 9, 11, 28, 12},
 
236
        *st_baud_text_app [] = {"", "", "  300", "  600", " 1200", " 2400", 
 
237
                " 4800", " 9600", "19200", "38400"},
 
238
        *old_parity_text[] = {"EVEN", "ODD", "", "", "NONE"},
 
239
        *parity_text [] = {"NONE", "ODD", "EVEN"},
 
240
        *old_input_ch[] = { "TSIP", "RTCM (6 of 8 bits)"},
 
241
        *old_output_ch[] = { "TSIP", "No output", "", "", "", "NMEA 0183"},
 
242
        *protocols_in_text[] = { "", "TSIP", "", ""},
 
243
        *protocols_out_text[] = { "", "TSIP", "NMEA"},
 
244
        *rcvr_port_text [] = { "Port A      ", "Port B      ", "Current Port"},
 
245
        *dyn_text [] = {"Unchanged", "Land", "Sea", "Air", "Static"},
 
246
        *NavModeText0xBB[] = {"automatic", "time only (0-D)", "", "2-D",
 
247
                "3-D", "", "", "OverDetermined Time"},
 
248
        *PPSTimeBaseText[] = {"GPS", "UTC", "USER"},
 
249
        *PPSPolarityText[] = {"Positive", "Negative"},
 
250
        *MaskText[] = { "Almanac  ", "Ephemeris", "UTC      ", "Iono     ",
 
251
                "GPS Msg  ", "Alm Hlth ", "Time Fix ", "SV Select",
 
252
                "Ext Event", "Pos Fix  ", "Raw Meas "};
 
253
 
 
254
#endif /* TRIMBLE_OUTPUT_FUNC */
 
255
 
 
256
/*
 
257
 * Unit control structure
 
258
 */
 
259
struct ripencc_unit {                   
 
260
        int unit;                       /* unit number */
 
261
        int     pollcnt;                /* poll message counter */
 
262
        int     polled;                 /* Hand in a sample? */
 
263
        char leapdelta;                 /* delta of next leap event */
 
264
        unsigned char utcflags;         /* delta of next leap event */
 
265
        l_fp    tstamp;                 /* timestamp of last poll */
 
266
        
 
267
        struct timespec ts;             /* last timestamp */
 
268
        pps_params_t pps_params;        /* pps parameters */
 
269
        pps_info_t pps_info;            /* last pps data */
 
270
        pps_handle_t handle;            /* pps handlebars */
 
271
 
 
272
};
 
273
 
 
274
 
 
275
/*******************        PROTOYPES            *****************/
 
276
 
 
277
/*  prototypes for report parsing primitives */
 
278
short rpt_0x3D (TSIPPKT *rpt, unsigned char *tx_baud_index,
 
279
        unsigned char *rx_baud_index, unsigned char *char_format_index,
 
280
        unsigned char *stop_bits, unsigned char *tx_mode_index,
 
281
        unsigned char *rx_mode_index);
 
282
short rpt_0x40 (TSIPPKT *rpt, unsigned char *sv_prn, short *week_num,
 
283
        float *t_zc, float *eccentricity, float *t_oa, float *i_0,
 
284
        float *OMEGA_dot, float *sqrt_A, float *OMEGA_0, float *omega,
 
285
        float *M_0);
 
286
short rpt_0x41 (TSIPPKT *rpt, float *time_of_week, float *UTC_offset,
 
287
        short *week_num);
 
288
short rpt_0x42 (TSIPPKT *rpt, float ECEF_pos[3], float *time_of_fix);
 
289
short rpt_0x43 (TSIPPKT *rpt, float ECEF_vel[3], float *freq_offset,
 
290
        float *time_of_fix);
 
291
short rpt_0x45 (TSIPPKT *rpt, unsigned char *major_nav_version,
 
292
        unsigned char *minor_nav_version, unsigned char *nav_day,
 
293
        unsigned char *nav_month, unsigned char *nav_year,
 
294
        unsigned char *major_dsp_version, unsigned char *minor_dsp_version,
 
295
        unsigned char *dsp_day, unsigned char *dsp_month,
 
296
        unsigned char *dsp_year);
 
297
short rpt_0x46 (TSIPPKT *rpt, unsigned char *status1, unsigned char *status2);
 
298
short rpt_0x47 (TSIPPKT *rpt, unsigned char *nsvs, unsigned char *sv_prn,
 
299
        float *snr);
 
300
short rpt_0x48 (TSIPPKT *rpt, unsigned char *message);
 
301
short rpt_0x49 (TSIPPKT *rpt, unsigned char *sv_health);
 
302
short rpt_0x4A (TSIPPKT *rpt, float *lat, float *lon, float *alt,
 
303
        float *clock_bias, float *time_of_fix);
 
304
short rpt_0x4A_2 (TSIPPKT *rpt, float *alt, float *dummy,
 
305
        unsigned char *alt_flag);
 
306
short rpt_0x4B (TSIPPKT *rpt, unsigned char *machine_id,
 
307
        unsigned char *status3, unsigned char *status4);
 
308
short rpt_0x4C (TSIPPKT *rpt, unsigned char *dyn_code, float *el_mask,
 
309
        float *snr_mask, float *dop_mask, float *dop_switch);
 
310
short rpt_0x4D (TSIPPKT *rpt, float *osc_offset);
 
311
short rpt_0x4E (TSIPPKT *rpt, unsigned char *response);
 
312
short rpt_0x4F (TSIPPKT *rpt, double *a0, float *a1, float *time_of_data,
 
313
        short *dt_ls, short *wn_t, short *wn_lsf, short *dn, short *dt_lsf);
 
314
short rpt_0x54 (TSIPPKT *rpt, float *clock_bias, float *freq_offset,
 
315
        float *time_of_fix);
 
316
short rpt_0x55 (TSIPPKT *rpt, unsigned char *pos_code, unsigned char *vel_code,
 
317
        unsigned char *time_code, unsigned char *aux_code);
 
318
short rpt_0x56 (TSIPPKT *rpt, float vel_ENU[3], float *freq_offset,
 
319
        float *time_of_fix);
 
320
short rpt_0x57 (TSIPPKT *rpt, unsigned char *source_code,
 
321
        unsigned char *diag_code, short *week_num, float *time_of_fix);
 
322
short rpt_0x58 (TSIPPKT *rpt, unsigned char *op_code, unsigned char *data_type,
 
323
        unsigned char *sv_prn, unsigned char *data_length,
 
324
        unsigned char *data_packet);
 
325
short rpt_0x59 (TSIPPKT *rpt, unsigned char *code_type,
 
326
        unsigned char status_code[32]);
 
327
short rpt_0x5A (TSIPPKT *rpt, unsigned char *sv_prn, float *sample_length,
 
328
        float *signal_level, float *code_phase, float *Doppler,
 
329
        double *time_of_fix);
 
330
short rpt_0x5B (TSIPPKT *rpt, unsigned char *sv_prn, unsigned char *sv_health,
 
331
        unsigned char *sv_iode, unsigned char *fit_interval_flag,
 
332
        float *time_of_collection, float *time_of_eph, float *sv_accy);
 
333
short rpt_0x5C (TSIPPKT *rpt, unsigned char *sv_prn, unsigned char *slot,
 
334
        unsigned char *chan, unsigned char *acq_flag, unsigned char *eph_flag,
 
335
        float *signal_level, float *time_of_last_msmt, float *elev,
 
336
        float *azim, unsigned char *old_msmt_flag,
 
337
        unsigned char *integer_msec_flag, unsigned char *bad_data_flag,
 
338
        unsigned char *data_collect_flag);
 
339
short rpt_0x6D (TSIPPKT *rpt, unsigned char *manual_mode, unsigned char *nsvs,
 
340
        unsigned char *ndim, unsigned char sv_prn[], float *pdop,
 
341
        float *hdop, float *vdop, float *tdop);
 
342
short rpt_0x82 (TSIPPKT *rpt, unsigned char *diff_mode);
 
343
short rpt_0x83 (TSIPPKT *rpt, double ECEF_pos[3], double *clock_bias,
 
344
        float *time_of_fix);
 
345
short rpt_0x84 (TSIPPKT *rpt, double *lat, double *lon, double *alt,
 
346
        double *clock_bias, float *time_of_fix);
 
347
short rpt_Paly0xBB(TSIPPKT *rpt, TSIP_RCVR_CFG *TsipxBB);
 
348
short rpt_0xBC   (TSIPPKT *rpt, unsigned char *port_num,
 
349
        unsigned char *in_baud, unsigned char *out_baud,
 
350
        unsigned char *data_bits, unsigned char *parity,
 
351
        unsigned char *stop_bits, unsigned char *flow_control,
 
352
        unsigned char *protocols_in, unsigned char *protocols_out,
 
353
        unsigned char *reserved);
 
354
 
 
355
/* prototypes for superpacket parsers */
 
356
 
 
357
short rpt_0x8F0B (TSIPPKT *rpt, unsigned short *event, double *tow,
 
358
   unsigned char *date, unsigned char *month, short *year,
 
359
   unsigned char *dim_mode, short *utc_offset, double *bias, double *drift,
 
360
   float *bias_unc, float *dr_unc, double *lat, double *lon, double *alt,
 
361
   char sv_id[8]);
 
362
short rpt_0x8F14 (TSIPPKT *rpt, short *datum_idx, double datum_coeffs[5]);
 
363
short rpt_0x8F15 (TSIPPKT *rpt, short *datum_idx, double datum_coeffs[5]);
 
364
short rpt_0x8F20 (TSIPPKT *rpt, unsigned char *info, double *lat,
 
365
        double *lon, double *alt, double vel_enu[], double *time_of_fix,
 
366
        short *week_num, unsigned char *nsvs, unsigned char sv_prn[], 
 
367
        short sv_IODC[], short *datum_index);
 
368
short rpt_0x8F41 (TSIPPKT *rpt, unsigned char *bSearchRange,
 
369
        unsigned char *bBoardOptions, unsigned long *iiSerialNumber,
 
370
        unsigned char *bBuildYear, unsigned char *bBuildMonth,
 
371
        unsigned char *bBuildDay, unsigned char *bBuildHour,
 
372
        float *fOscOffset, unsigned short *iTestCodeId);
 
373
short rpt_0x8F42 (TSIPPKT *rpt, unsigned char *bProdOptionsPre,
 
374
        unsigned char *bProdNumberExt, unsigned short *iCaseSerialNumberPre,
 
375
        unsigned long *iiCaseSerialNumber, unsigned long *iiProdNumber,
 
376
        unsigned short *iPremiumOptions, unsigned short *iMachineID,
 
377
        unsigned short *iKey);
 
378
short rpt_0x8F45 (TSIPPKT *rpt, unsigned char *bSegMask);
 
379
short rpt_0x8F4A_16 (TSIPPKT *rpt, unsigned char *pps_enabled,
 
380
        unsigned char *pps_timebase, unsigned char *pos_polarity,
 
381
        double *pps_offset, float *bias_unc_threshold);
 
382
short rpt_0x8F4B (TSIPPKT *rpt, unsigned long *decorr_max);
 
383
short rpt_0x8F4D (TSIPPKT *rpt, unsigned long *event_mask);
 
384
short rpt_0x8FA5 (TSIPPKT *rpt, unsigned char *spktmask);
 
385
short rpt_0x8FAD (TSIPPKT *rpt, unsigned short *COUNT, double *FracSec,
 
386
    unsigned char *Hour, unsigned char *Minute, unsigned char *Second,
 
387
    unsigned char *Day, unsigned char *Month, unsigned short *Year,
 
388
    unsigned char *Status, unsigned char *Flags);
 
389
 
 
390
/**/
 
391
/* prototypes for command-encode primitives with suffix convention:  */
 
392
/* c = clear, s = set, q = query, e = enable, d = disable            */
 
393
void cmd_0x1F  (TSIPPKT *cmd);
 
394
void cmd_0x26  (TSIPPKT *cmd);
 
395
void cmd_0x2F  (TSIPPKT *cmd);
 
396
void cmd_0x35s (TSIPPKT *cmd, unsigned char pos_code, unsigned char vel_code,
 
397
        unsigned char time_code, unsigned char opts_code);
 
398
void cmd_0x3C  (TSIPPKT *cmd, unsigned char sv_prn);
 
399
void cmd_0x3Ds (TSIPPKT *cmd, unsigned char baud_out, unsigned char baud_inp,
 
400
        unsigned char char_code, unsigned char stopbitcode,
 
401
        unsigned char output_mode, unsigned char input_mode);
 
402
void cmd_0xBBq (TSIPPKT *cmd, unsigned char subcode) ;
 
403
 
 
404
/* prototypes 8E commands */
 
405
void cmd_0x8E0Bq (TSIPPKT *cmd);
 
406
void cmd_0x8E41q (TSIPPKT *cmd);
 
407
void cmd_0x8E42q (TSIPPKT *cmd);
 
408
void cmd_0x8E4Aq (TSIPPKT *cmd);
 
409
void cmd_0x8E4As (TSIPPKT *cmd, unsigned char PPSOnOff, unsigned char TimeBase,
 
410
        unsigned char Polarity, double PPSOffset, float Uncertainty);
 
411
void cmd_0x8E4Bq (TSIPPKT *cmd);
 
412
void cmd_0x8E4Ds (TSIPPKT *cmd, unsigned long AutoOutputMask);
 
413
void cmd_0x8EADq (TSIPPKT *cmd);
 
414
 
 
415
/* header/source border XXXXXXXXXXXXXXXXXXXXXXXXXX */
 
416
 
 
417
/* Trimble parse functions */
 
418
static  int     parse0x8FAD     P((TSIPPKT *, struct peer *));
 
419
static  int     parse0x8F0B     P((TSIPPKT *, struct peer *));
 
420
#ifdef TRIMBLE_OUTPUT_FUNC
 
421
static  int     parseany        P((TSIPPKT *, struct peer *));
 
422
static  void    TranslateTSIPReportToText       P((TSIPPKT *, char *));
 
423
#endif /* TRIMBLE_OUTPUT_FUNC */
 
424
static  int     parse0x5C       P((TSIPPKT *, struct peer *));
 
425
static  int     parse0x4F       P((TSIPPKT *, struct peer *));
 
426
static  void    tsip_input_proc P((TSIPPKT *, int));
 
427
 
 
428
/* Trimble helper functions */
 
429
static  void    bPutFloat       P((float *, unsigned char *));
 
430
static  void    bPutDouble      P((double *, unsigned char *));
 
431
static  void    bPutULong       P((unsigned long *, unsigned char *));
 
432
static  int     print_msg_table_header  P((int rptcode, char *HdrStr, int force));
 
433
static  char *  show_time       P((float time_of_week));
 
434
 
 
435
/* RIPE NCC functions */
 
436
static  void    ripencc_control P((int, struct refclockstat *, struct
 
437
                                refclockstat *, struct peer *));
 
438
static  int     ripencc_ppsapi  P((struct peer *, int, int));
 
439
static  int     ripencc_get_pps_ts      P((struct ripencc_unit *, l_fp *));
 
440
static  int     ripencc_start   P((int, struct peer *));
 
441
static  void    ripencc_shutdown        P((int, struct peer *));
 
442
static  void    ripencc_poll    P((int, struct peer *));
 
443
static  void    ripencc_send    P((struct peer *, TSIPPKT spt));
 
444
static  void    ripencc_receive P((struct recvbuf *));
 
445
 
 
446
/* fill in reflock structure for our clock */
 
447
struct refclock refclock_ripencc = {
 
448
        ripencc_start,          /* start up driver */
 
449
        ripencc_shutdown,       /* shut down driver */
 
450
        ripencc_poll,           /* transmit poll message */
 
451
        ripencc_control,        /* control function */
 
452
        noentry,                /* initialize driver */
 
453
        noentry,                /* debug info */
 
454
        NOFLAGS                 /* clock flags */
 
455
};
 
456
 
 
457
/*
 
458
 *  Tables to compute the ddd of year form icky dd/mm timecode. Viva la
 
459
 *  leap.
 
460
 */
 
461
static int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 
462
static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 
463
 
 
464
 
 
465
/*
 
466
 * ripencc_start - open the GPS devices and initialize data for processing
 
467
 */
 
468
static int
 
469
ripencc_start(int unit, struct peer *peer)
 
470
{
 
471
        register struct ripencc_unit *up;
 
472
        struct refclockproc *pp;
 
473
        char device[40];
 
474
        int fd;
 
475
        struct termios tio;
 
476
        TSIPPKT spt;
 
477
 
 
478
        /*
 
479
         * Open serial port
 
480
         */
 
481
        (void)snprintf(device, sizeof(device), DEVICE, unit);
 
482
        if (!(fd = refclock_open(device, SPEED232, LDISC_RAW)))
 
483
                return (0);
 
484
 
 
485
        /* from refclock_palisade.c */
 
486
        if (tcgetattr(fd, &tio) < 0) {
 
487
                msyslog(LOG_ERR, "Palisade(%d) tcgetattr(fd, &tio): %m",unit);
 
488
                return (0);
 
489
        }
 
490
 
 
491
        /*
 
492
         * set flags
 
493
         */
 
494
        tio.c_cflag |= (PARENB|PARODD);
 
495
        tio.c_iflag &= ~ICRNL;
 
496
        if (tcsetattr(fd, TCSANOW, &tio) == -1) {
 
497
                msyslog(LOG_ERR, "Palisade(%d) tcsetattr(fd, &tio): %m",unit);
 
498
                return (0);
 
499
        }
 
500
 
 
501
        /*
 
502
         * Allocate and initialize unit structure
 
503
         */
 
504
        if (!(up = (struct ripencc_unit *) 
 
505
                                emalloc(sizeof(struct ripencc_unit)))) {
 
506
                (void) close(fd);
 
507
                return (0);
 
508
        }
 
509
        memset((char *)up, 0, sizeof(struct ripencc_unit));
 
510
        pp = peer->procptr;
 
511
        pp->io.clock_recv = ripencc_receive;
 
512
        pp->io.srcclock = (caddr_t)peer;
 
513
        pp->io.datalen = 0;
 
514
        pp->io.fd = fd;
 
515
        if (!io_addclock(&pp->io)) {
 
516
                (void) close(fd);
 
517
                free(up);
 
518
                return (0);
 
519
        }
 
520
        pp->unitptr = (caddr_t)up;
 
521
 
 
522
        /*
 
523
         * Initialize miscellaneous variables
 
524
         */
 
525
        peer->precision = PRECISION;
 
526
        pp->clockdesc = DESCRIPTION;
 
527
        memcpy((char *)&pp->refid, REFID, REFID_LEN);
 
528
        up->pollcnt = 2;
 
529
        up->unit = unit;
 
530
        up->leapdelta = 0;
 
531
        up->utcflags = 0;
 
532
 
 
533
        /*
 
534
         * Initialize the Clock
 
535
         */
 
536
 
 
537
        /* query software versions */
 
538
        cmd_0x1F(&spt);                 
 
539
        ripencc_send(peer, spt);          
 
540
 
 
541
        /* query receiver health */
 
542
        cmd_0x26(&spt);                 
 
543
        ripencc_send(peer, spt);
 
544
 
 
545
        /* query serial numbers */      
 
546
        cmd_0x8E42q(&spt);              
 
547
        ripencc_send(peer, spt);  
 
548
        
 
549
        /* query manuf params */
 
550
        cmd_0x8E41q(&spt);              
 
551
        ripencc_send(peer, spt); 
 
552
 
 
553
        /* i/o opts */ /* trimble manual page A30 */
 
554
        cmd_0x35s(&spt, 
 
555
                0x1C,   /* position */
 
556
                0x00,   /* velocity */
 
557
                0x05,   /* timing */
 
558
                0x0a);  /* auxilary */
 
559
        ripencc_send(peer, spt);
 
560
        
 
561
        /* turn off port A */
 
562
        cmd_0x3Ds (&spt,
 
563
                0x0B, /* baud_out */
 
564
                0x0B, /* baud_inp */
 
565
                0x07, /* char_code */
 
566
                0x07, /* stopbitcode */
 
567
                0x01, /* output_mode */
 
568
                0x00); /* input_mode */
 
569
        ripencc_send(peer, spt);
 
570
 
 
571
        /* set i/o options */
 
572
        cmd_0x8E4As (&spt,
 
573
                0x01,           /* PPS on */
 
574
                0x01,           /* Timebase UTC */
 
575
                0x00,           /* polarity positive */
 
576
                0.,             /* 100 ft. cable XXX make flag */
 
577
                1e-6 * GPS_C);  /* turn of biasuncert. > (1us) */
 
578
        ripencc_send(peer,spt);
 
579
 
 
580
        /* all outomatic packet output off */
 
581
        cmd_0x8E4Ds(&spt,
 
582
                0x00000000); /* AutoOutputMask */
 
583
        ripencc_send(peer, spt);
 
584
 
 
585
        cmd_0xBBq (&spt,
 
586
                0x00); /* query primary configuration */
 
587
        ripencc_send(peer,spt);
 
588
 
 
589
 
 
590
        /* query PPS parameters */
 
591
        cmd_0x8E4Aq (&spt); /* query PPS params */
 
592
        ripencc_send(peer,spt);
 
593
 
 
594
        /* query survey limit */
 
595
        cmd_0x8E4Bq (&spt); /* query survey limit */
 
596
        ripencc_send(peer,spt);
 
597
 
 
598
#ifdef DEBUG_NCC
 
599
        if (debug)
 
600
                printf("ripencc_start: success\n");
 
601
#endif /* DEBUG_NCC */
 
602
 
 
603
        /*
 
604
         * Start the PPSAPI interface if it is there. Default to use
 
605
         * the assert edge and do not enable the kernel hardpps.
 
606
         */
 
607
        if (time_pps_create(fd, &up->handle) < 0) {
 
608
                up->handle = 0;
 
609
                msyslog(LOG_ERR, "refclock_ripencc: time_pps_create failed: %m");
 
610
                return (1);
 
611
        }
 
612
 
 
613
        return(ripencc_ppsapi(peer, 0, 0));
 
614
}
 
615
 
 
616
/*
 
617
 * ripencc_control - fudge control
 
618
 */
 
619
static void
 
620
ripencc_control(
 
621
        int unit,               /* unit (not used) */
 
622
        struct refclockstat *in, /* input parameters (not used) */
 
623
        struct refclockstat *out, /* output parameters (not used) */
 
624
        struct peer *peer       /* peer structure pointer */
 
625
        )
 
626
{
 
627
        struct refclockproc *pp;
 
628
 
 
629
#ifdef DEBUG_NCC
 
630
        msyslog(LOG_INFO,"%s()",__FUNCTION__);
 
631
#endif /* DEBUG_NCC */
 
632
 
 
633
        pp = peer->procptr;
 
634
        ripencc_ppsapi(peer, pp->sloppyclockflag & CLK_FLAG2,
 
635
            pp->sloppyclockflag & CLK_FLAG3);
 
636
}
 
637
 
 
638
 
 
639
/*
 
640
 * Initialize PPSAPI
 
641
 */
 
642
int
 
643
ripencc_ppsapi(
 
644
        struct peer *peer,      /* peer structure pointer */
 
645
        int enb_clear,          /* clear enable */
 
646
        int enb_hardpps         /* hardpps enable */
 
647
        )
 
648
{
 
649
        struct refclockproc *pp;
 
650
        struct ripencc_unit *up;
 
651
        int capability;
 
652
 
 
653
        pp = peer->procptr;
 
654
        up = (struct ripencc_unit *)pp->unitptr;
 
655
        if (time_pps_getcap(up->handle, &capability) < 0) {
 
656
                msyslog(LOG_ERR,
 
657
                    "refclock_ripencc: time_pps_getcap failed: %m");
 
658
                return (0);
 
659
        }
 
660
        memset(&up->pps_params, 0, sizeof(pps_params_t));
 
661
        if (enb_clear)
 
662
                up->pps_params.mode = capability & PPS_CAPTURECLEAR;
 
663
        else
 
664
                up->pps_params.mode = capability & PPS_CAPTUREASSERT;
 
665
        if (!up->pps_params.mode) {
 
666
                msyslog(LOG_ERR,
 
667
                    "refclock_ripencc: invalid capture edge %d",
 
668
                    !enb_clear);
 
669
                return (0);
 
670
        }
 
671
        up->pps_params.mode |= PPS_TSFMT_TSPEC;
 
672
        if (time_pps_setparams(up->handle, &up->pps_params) < 0) {
 
673
                msyslog(LOG_ERR,
 
674
                    "refclock_ripencc: time_pps_setparams failed: %m");
 
675
                return (0);
 
676
        }
 
677
        if (enb_hardpps) {
 
678
                if (time_pps_kcbind(up->handle, PPS_KC_HARDPPS,
 
679
                                    up->pps_params.mode & ~PPS_TSFMT_TSPEC,
 
680
                                    PPS_TSFMT_TSPEC) < 0) {
 
681
                        msyslog(LOG_ERR,
 
682
                            "refclock_ripencc: time_pps_kcbind failed: %m");
 
683
                        return (0);
 
684
                }
 
685
                pps_enable = 1;
 
686
        }
 
687
        peer->precision = PPS_PRECISION;
 
688
 
 
689
#if DEBUG_NCC
 
690
        if (debug) {
 
691
                time_pps_getparams(up->handle, &up->pps_params);
 
692
                printf(
 
693
                    "refclock_ripencc: capability 0x%x version %d mode 0x%x kern %d\n",
 
694
                    capability, up->pps_params.api_version,
 
695
                    up->pps_params.mode, enb_hardpps);
 
696
        }
 
697
#endif /* DEBUG_NCC */
 
698
 
 
699
        return (1);
 
700
}
 
701
 
 
702
/*
 
703
 * This function is called every 64 seconds from ripencc_receive
 
704
 * It will fetch the pps time 
 
705
 *
 
706
 * Return 0 on failure and 1 on success.
 
707
 */
 
708
static int
 
709
ripencc_get_pps_ts(
 
710
        struct ripencc_unit *up,
 
711
        l_fp *tsptr
 
712
        )
 
713
{
 
714
        pps_info_t pps_info;
 
715
        struct timespec timeout, ts;
 
716
        double dtemp;
 
717
        l_fp tstmp;
 
718
 
 
719
#ifdef DEBUG_PPS
 
720
        msyslog(LOG_INFO,"ripencc_get_pps_ts\n");
 
721
#endif /* DEBUG_PPS */
 
722
 
 
723
 
 
724
        /*
 
725
         * Convert the timespec nanoseconds field to ntp l_fp units.
 
726
         */ 
 
727
        if (up->handle == 0)
 
728
                return (0);
 
729
        timeout.tv_sec = 0;
 
730
        timeout.tv_nsec = 0;
 
731
        memcpy(&pps_info, &up->pps_info, sizeof(pps_info_t));
 
732
        if (time_pps_fetch(up->handle, PPS_TSFMT_TSPEC, &up->pps_info,
 
733
            &timeout) < 0)
 
734
                return (0);
 
735
        if (up->pps_params.mode & PPS_CAPTUREASSERT) {
 
736
                if (pps_info.assert_sequence ==
 
737
                    up->pps_info.assert_sequence)
 
738
                        return (0);
 
739
                ts = up->pps_info.assert_timestamp;
 
740
        } else if (up->pps_params.mode & PPS_CAPTURECLEAR) {
 
741
                if (pps_info.clear_sequence ==
 
742
                    up->pps_info.clear_sequence)
 
743
                        return (0);
 
744
                ts = up->pps_info.clear_timestamp;
 
745
        } else {
 
746
                return (0);
 
747
        }
 
748
        if ((up->ts.tv_sec == ts.tv_sec) && (up->ts.tv_nsec == ts.tv_nsec))
 
749
                return (0);
 
750
        up->ts = ts;
 
751
 
 
752
        tstmp.l_ui = ts.tv_sec + JAN_1970;
 
753
        dtemp = ts.tv_nsec * FRAC / 1e9;
 
754
        tstmp.l_uf = (u_int32)dtemp;
 
755
 
 
756
#ifdef DEBUG_PPS
 
757
        msyslog(LOG_INFO,"ts.tv_sec: %d\n",(int)ts.tv_sec);
 
758
        msyslog(LOG_INFO,"ts.tv_nsec: %ld\n",ts.tv_nsec);
 
759
#endif /* DEBUG_PPS */
 
760
 
 
761
        *tsptr = tstmp;
 
762
        return (1);
 
763
}
 
764
 
 
765
/*
 
766
 * ripencc_shutdown - shut down a GPS clock
 
767
 */
 
768
static void
 
769
ripencc_shutdown(int unit, struct peer *peer)
 
770
{
 
771
        register struct ripencc_unit *up;
 
772
        struct refclockproc *pp;
 
773
 
 
774
        pp = peer->procptr;
 
775
        up = (struct ripencc_unit *)pp->unitptr;
 
776
 
 
777
        if (up->handle != 0)
 
778
                time_pps_destroy(up->handle);
 
779
 
 
780
        io_closeclock(&pp->io);
 
781
 
 
782
        free(up);
 
783
}
 
784
 
 
785
/*
 
786
 * ripencc_poll - called by the transmit procedure
 
787
 */
 
788
static void
 
789
ripencc_poll(int unit, struct peer *peer)
 
790
{
 
791
        register struct ripencc_unit *up;
 
792
        struct refclockproc *pp;
 
793
        TSIPPKT spt;
 
794
 
 
795
#ifdef DEBUG_NCC
 
796
        if (debug)
 
797
                fprintf(stderr, "ripencc_poll(%d)\n", unit);
 
798
#endif /* DEBUG_NCC */
 
799
        pp = peer->procptr;
 
800
        up = (struct ripencc_unit *)pp->unitptr;
 
801
        if (up->pollcnt == 0)
 
802
                refclock_report(peer, CEVNT_TIMEOUT);
 
803
        else
 
804
                up->pollcnt--;
 
805
 
 
806
        pp->polls++;
 
807
        up->polled = 1;
 
808
 
 
809
        /* poll for UTC superpacket */
 
810
        cmd_0x8EADq (&spt);
 
811
        ripencc_send(peer,spt);
 
812
}
 
813
 
 
814
/*
 
815
 * ripencc_send - send message to clock
 
816
 * use the structures being created by the trimble functions!
 
817
 * makes the code more readable/clean
 
818
 */
 
819
static void
 
820
ripencc_send(struct peer *peer, TSIPPKT spt)
 
821
{
 
822
        unsigned char *ip, *op;
 
823
        unsigned char obuf[512];
 
824
 
 
825
#ifdef DEBUG_RAW
 
826
        {
 
827
                register struct ripencc_unit *up;
 
828
                register struct refclockproc *pp;       
 
829
 
 
830
                pp = peer->procptr;
 
831
                up = (struct ripencc_unit *)pp->unitptr;
 
832
                if (debug)
 
833
                        printf("ripencc_send(%d, %02X)\n", up->unit, cmd);
 
834
        }
 
835
#endif /* DEBUG_RAW */
 
836
 
 
837
        ip = spt.buf;
 
838
        op = obuf;
 
839
 
 
840
        *op++ = 0x10;
 
841
        *op++ = spt.code;
 
842
 
 
843
        while (spt.len--) {
 
844
                if (op-obuf > sizeof(obuf)-5) {
 
845
                        msyslog(LOG_ERR, "ripencc_send obuf overflow!");
 
846
                        refclock_report(peer, CEVNT_FAULT);
 
847
                        return;
 
848
                }
 
849
                        
 
850
                if (*ip == 0x10)  /* byte stuffing */
 
851
                        *op++ = 0x10;
 
852
                *op++ = *ip++;
 
853
        }
 
854
        
 
855
        *op++ = 0x10;
 
856
        *op++ = 0x03;
 
857
 
 
858
#ifdef DEBUG_RAW
 
859
        if (debug) { /* print raw packet */
 
860
                unsigned char *cp;
 
861
                int i;
 
862
 
 
863
                printf("ripencc_send: len %d\n", op-obuf);
 
864
                for (i=1, cp=obuf; cp<op; i++, cp++) {
 
865
                        printf(" %02X", *cp);
 
866
                        if (i%10 == 0) 
 
867
                                printf("\n");
 
868
                }
 
869
                printf("\n");
 
870
        }
 
871
#endif /* DEBUG_RAW */
 
872
 
 
873
        if (write(peer->procptr->io.fd, obuf, op-obuf) == -1) {
 
874
                        refclock_report(peer, CEVNT_FAULT);
 
875
        }
 
876
}
 
877
 
 
878
/*
 
879
 * ripencc_receive()
 
880
 *
 
881
 * called when a packet is received on the serial port
 
882
 * takes care of further processing
 
883
 *
 
884
 */
 
885
static void
 
886
ripencc_receive(struct recvbuf *rbufp)
 
887
{
 
888
        register struct ripencc_unit *up;
 
889
        register struct refclockproc *pp;       
 
890
        struct peer *peer;
 
891
        static TSIPPKT rpt; /* structure for current incoming TSIP report  */ 
 
892
        TSIPPKT spt; /* send packet */
 
893
        int ns_since_pps;                       
 
894
        int i;
 
895
        char *cp;
 
896
        /* Use these variables to hold data until we decide its worth keeping */
 
897
        char    rd_lastcode[BMAX];
 
898
        l_fp    rd_tmp;
 
899
        u_short rd_lencode;
 
900
 
 
901
        /* msyslog(LOG_INFO, "%s",__FUNCTION__); */
 
902
 
 
903
        /*
 
904
         * Initialize pointers and read the timecode and timestamp
 
905
         */
 
906
        peer = (struct peer *)rbufp->recv_srcclock;
 
907
        pp = peer->procptr;
 
908
        up = (struct ripencc_unit *)pp->unitptr;
 
909
        rd_lencode = refclock_gtlin(rbufp, rd_lastcode, BMAX, &rd_tmp);
 
910
 
 
911
#ifdef DEBUG_RAW
 
912
        if (debug)
 
913
                fprintf(stderr, "ripencc_receive(%d)\n", up->unit);
 
914
#endif /* DEBUG_RAW */
 
915
 
 
916
#ifdef DEBUG_RAW
 
917
        if (debug) { /* print raw packet */
 
918
                int i;
 
919
                unsigned char *cp;
 
920
 
 
921
                printf("ripencc_receive: len %d\n", rbufp->recv_length);
 
922
                for (i=1, cp=(char*)&rbufp->recv_space; i <= rbufp->recv_length; i++, cp++) {
 
923
                        printf(" %02X", *cp);
 
924
                        if (i%10 == 0) 
 
925
                                printf("\n");
 
926
                }
 
927
                printf("\n");
 
928
        }
 
929
#endif /* DEBUG_RAW */
 
930
 
 
931
        cp = (char*) &rbufp->recv_space;
 
932
        i=rbufp->recv_length;
 
933
 
 
934
        while (i--) { /* loop over received chars */
 
935
 
 
936
                tsip_input_proc(&rpt, (unsigned char) *cp++);
 
937
 
 
938
                if (rpt.status != TSIP_PARSED_FULL)
 
939
                        continue;
 
940
 
 
941
                switch (rpt.code) {
 
942
 
 
943
                case 0x8F:      /* superpacket */
 
944
 
 
945
                        switch (rpt.buf[0]) {
 
946
 
 
947
                        case 0xAD:      /* UTC Time */
 
948
                                /*
 
949
                                 * When polling on port B the timecode 
 
950
                                 * is the time of the previous PPS.
 
951
                                 * If we completed receiving the packet 
 
952
                                 * less than 150ms after the turn of the second, 
 
953
                                 * it may have the code of the previous second.
 
954
                                 * We do not trust that and simply poll again
 
955
                                 * without even parsing it.
 
956
                                 *
 
957
                                 * More elegant would be to re-schedule the poll,
 
958
                                 * but I do not know (yet) how to do that cleanly.
 
959
                                 *
 
960
                                 */
 
961
                                /* BLA ns_since_pps = ncc_tstmp(rbufp, &trtmp); */
 
962
/*   if (up->polled && ns_since_pps > -1 && ns_since_pps < 150) { */
 
963
 
 
964
                                ns_since_pps=200;
 
965
                                if (up->polled && ns_since_pps < 150) {
 
966
                                        msyslog(LOG_INFO, "%s(): up->polled",__FUNCTION__);
 
967
                                        ripencc_poll(up->unit, peer);
 
968
                                        break;
 
969
                                }
 
970
 
 
971
                                /*
 
972
                                 * Parse primary utc time packet
 
973
                                 * and fill refclock structure 
 
974
                                 * from results. 
 
975
                                 */
 
976
                                if (parse0x8FAD(&rpt, peer) < 0) {
 
977
                                                msyslog(LOG_INFO, "%s(): parse0x8FAD < 0",__FUNCTION__);
 
978
                                                refclock_report(peer, CEVNT_BADREPLY);
 
979
                                                break;
 
980
                                }
 
981
                                /*
 
982
                                 * If the PPSAPI is working, rather use its 
 
983
                                 * timestamps.
 
984
                                 * assume that the PPS occurs on the second 
 
985
                                 * so blow any msec
 
986
                                 */
 
987
                                if (ripencc_get_pps_ts(up, &rd_tmp) == 1) {
 
988
                                        pp->lastrec = up->tstamp = rd_tmp;
 
989
                                        pp->nsec = 0;
 
990
                                }
 
991
                                else
 
992
                                        msyslog(LOG_INFO, "%s(): ripencc_get_pps_ts returns failure\n",__FUNCTION__);
 
993
 
 
994
 
 
995
                                if (!up->polled) { 
 
996
                                        msyslog(LOG_INFO, "%s(): unrequested packet\n",__FUNCTION__);
 
997
                                        /* unrequested packet */
 
998
                                        break;
 
999
                                }
 
1000
 
 
1001
                                /* we have been polled ! */
 
1002
                                up->polled = 0;
 
1003
                                up->pollcnt = 2;
 
1004
 
 
1005
                                /* poll for next packet */
 
1006
                                cmd_0x8E0Bq(&spt);
 
1007
                                ripencc_send(peer,spt);
 
1008
                                
 
1009
                                if (ns_since_pps < 0) { /* no PPS */
 
1010
                                        msyslog(LOG_INFO, "%s(): ns_since_pps < 0",__FUNCTION__);
 
1011
                                        refclock_report(peer, CEVNT_BADTIME);
 
1012
                                        break;
 
1013
                                }
 
1014
 
 
1015
                                /*
 
1016
                                 * Process the new sample in the median filter and determine the
 
1017
                                 * reference clock offset and dispersion. 
 
1018
                                 */
 
1019
                                if (!refclock_process(pp)) {
 
1020
                                        msyslog(LOG_INFO, "%s(): !refclock_process",__FUNCTION__);
 
1021
                                        refclock_report(peer, CEVNT_BADTIME);
 
1022
                                        break;
 
1023
                                }
 
1024
 
 
1025
                                refclock_receive(peer);
 
1026
                                break;
 
1027
                        
 
1028
                        case 0x0B: /* comprehensive time packet */
 
1029
                                parse0x8F0B(&rpt, peer);
 
1030
                                break;
 
1031
 
 
1032
                        default: /* other superpackets */
 
1033
#ifdef DEBUG_NCC
 
1034
                                msyslog(LOG_INFO, "%s(): calling parseany",__FUNCTION__);
 
1035
#endif /* DEBUG_NCC */
 
1036
#ifdef TRIMBLE_OUTPUT_FUNC
 
1037
                                parseany(&rpt, peer);
 
1038
#endif /* TRIMBLE_OUTPUT_FUNC */
 
1039
                                break;
 
1040
                        }
 
1041
                        break;
 
1042
 
 
1043
                case 0x4F:      /* UTC parameters, for leap info */
 
1044
                        parse0x4F(&rpt, peer);
 
1045
                        break;
 
1046
 
 
1047
                case 0x5C:      /* sat tracking data */
 
1048
                        parse0x5C(&rpt, peer);
 
1049
                        break;
 
1050
 
 
1051
                default: /* other packets */
 
1052
#ifdef TRIMBLE_OUTPUT_FUNC
 
1053
                        parseany(&rpt, peer);
 
1054
#endif /* TRIMBLE_OUTPUT_FUNC */
 
1055
                        break;
 
1056
                }
 
1057
                rpt.status = TSIP_PARSED_EMPTY;
 
1058
        }
 
1059
}
 
1060
 
 
1061
/* 
 
1062
 * All trimble functions that are directly referenced from driver code
 
1063
 * (so not from parseany)
 
1064
 */
 
1065
 
 
1066
void cmd_0x1F (TSIPPKT *cmd)
 
1067
/* request software versions */
 
1068
{
 
1069
        cmd->len = 0;
 
1070
        cmd->code = 0x1F;
 
1071
}
 
1072
 
 
1073
void cmd_0x26 (TSIPPKT *cmd)
 
1074
/* request receiver health */
 
1075
{
 
1076
        cmd->len = 0;
 
1077
        cmd->code = 0x26;
 
1078
}
 
1079
 
 
1080
 
 
1081
 
 
1082
 
 
1083
void cmd_0x2F (TSIPPKT *cmd)
 
1084
/* request UTC params */
 
1085
{
 
1086
        cmd->len = 0;
 
1087
        cmd->code = 0x2F;
 
1088
}
 
1089
 
 
1090
void cmd_0x35s  (TSIPPKT *cmd, unsigned char pos_code, unsigned char vel_code,
 
1091
        unsigned char time_code, unsigned char opts_code)
 
1092
/* set serial I/O options */
 
1093
{
 
1094
        cmd->buf[0] = pos_code;
 
1095
        cmd->buf[1] = vel_code;
 
1096
        cmd->buf[2] = time_code;
 
1097
        cmd->buf[3] = opts_code;
 
1098
        cmd->len = 4;
 
1099
        cmd->code = 0x35;
 
1100
}
 
1101
void cmd_0x3C  (TSIPPKT *cmd, unsigned char sv_prn)
 
1102
/* request tracking status */
 
1103
{
 
1104
        cmd->buf[0] = sv_prn;
 
1105
        cmd->len = 1;
 
1106
        cmd->code = 0x3C;
 
1107
}
 
1108
 
 
1109
 
 
1110
void cmd_0x3Ds (TSIPPKT *cmd,
 
1111
        unsigned char baud_out, unsigned char baud_inp,
 
1112
   unsigned char char_code, unsigned char stopbitcode,
 
1113
   unsigned char output_mode, unsigned char input_mode)
 
1114
/* set Channel A configuration for dual-port operation */
 
1115
{
 
1116
        cmd->buf[0] = baud_out;         /* XMT baud rate */
 
1117
        cmd->buf[1] = baud_inp;         /* RCV baud rate */
 
1118
        cmd->buf[2] = char_code;           /* parity and #bits per byte */
 
1119
        cmd->buf[3] = stopbitcode;      /* number of stop bits code */
 
1120
        cmd->buf[4] = output_mode;      /* Ch. A transmission mode */
 
1121
        cmd->buf[5] = input_mode;       /* Ch. A reception mode */
 
1122
        cmd->len = 6;
 
1123
        cmd->code = 0x3D;
 
1124
}
 
1125
 
 
1126
 
 
1127
/* query primary configuration */
 
1128
void cmd_0xBBq (TSIPPKT *cmd,
 
1129
        unsigned char subcode)
 
1130
{
 
1131
 
 
1132
        cmd->len = 1;
 
1133
        cmd->code = 0xBB;
 
1134
        cmd->buf[0] = subcode;
 
1135
}
 
1136
 
 
1137
 
 
1138
/**** Superpackets ****/
 
1139
void cmd_0x8E0Bq (TSIPPKT *cmd)
 
1140
/* 8E-0B to query 8F-0B controls */
 
1141
{
 
1142
 
 
1143
        cmd->len = 1;
 
1144
        cmd->code = 0x8E;
 
1145
        cmd->buf[0] = 0x0B;
 
1146
}
 
1147
 
 
1148
 
 
1149
void cmd_0x8E41q (TSIPPKT *cmd)
 
1150
/* 8F-41 to query board serial number */
 
1151
{
 
1152
 
 
1153
        cmd->len = 1;
 
1154
        cmd->code = 0x8E;
 
1155
        cmd->buf[0] = 0x41;
 
1156
}
 
1157
 
 
1158
 
 
1159
void cmd_0x8E42q (TSIPPKT *cmd)
 
1160
/* 8F-42 to query product serial number */
 
1161
{
 
1162
 
 
1163
        cmd->len = 1;
 
1164
        cmd->code = 0x8E;
 
1165
        cmd->buf[0] = 0x42;
 
1166
}
 
1167
void cmd_0x8E4Aq (TSIPPKT *cmd)
 
1168
/* 8F-4A to query PPS parameters */
 
1169
{
 
1170
        cmd->len = 1;
 
1171
        cmd->code = 0x8E;
 
1172
        cmd->buf[0] = 0x4A;
 
1173
}
 
1174
 
 
1175
 
 
1176
/* set i/o options */
 
1177
void cmd_0x8E4As (TSIPPKT *cmd,
 
1178
        unsigned char PPSOnOff,
 
1179
        unsigned char TimeBase,
 
1180
        unsigned char Polarity,
 
1181
   double PPSOffset,
 
1182
   float Uncertainty)
 
1183
{
 
1184
        cmd->len = 16;
 
1185
        cmd->code = 0x8E;
 
1186
        cmd->buf[0] = 0x4A;
 
1187
        cmd->buf[1] = PPSOnOff;
 
1188
        cmd->buf[2] = TimeBase;
 
1189
        cmd->buf[3] = Polarity;
 
1190
        bPutDouble (&PPSOffset, &cmd->buf[4]);
 
1191
        bPutFloat (&Uncertainty, &cmd->buf[12]);
 
1192
}
 
1193
void cmd_0x8E4Bq (TSIPPKT *cmd)
 
1194
/* 8F-4B query survey limit */
 
1195
{
 
1196
        cmd->len = 1;
 
1197
        cmd->code = 0x8E;
 
1198
        cmd->buf[0] = 0x4B;
 
1199
}
 
1200
 
 
1201
 
 
1202
/* poll for UTC superpacket */
 
1203
void cmd_0x8EADq (TSIPPKT *cmd)
 
1204
/* 8E-AD to query 8F-AD controls */
 
1205
{
 
1206
        cmd->len = 1;
 
1207
        cmd->code = 0x8E;
 
1208
        cmd->buf[0] = 0xAD;
 
1209
}
 
1210
 
 
1211
/* all outomatic packet output off */
 
1212
void cmd_0x8E4Ds (TSIPPKT *cmd,
 
1213
        unsigned long AutoOutputMask)
 
1214
{
 
1215
        cmd->len = 5;
 
1216
        cmd->code = 0x8E;
 
1217
        cmd->buf[0] = 0x4D;
 
1218
        bPutULong (&AutoOutputMask, &cmd->buf[1]);
 
1219
}
 
1220
 
 
1221
 
 
1222
 
 
1223
 
 
1224
/* for DOS machines, reverse order of bytes as they come through the
 
1225
 * serial port. */
 
1226
#ifdef BYTESWAP
 
1227
static short bGetShort (unsigned char *bp)
 
1228
{
 
1229
        short outval;
 
1230
   unsigned char *optr;
 
1231
 
 
1232
   optr = (unsigned char*)&outval + 1;
 
1233
   *optr-- = *bp++;
 
1234
   *optr = *bp;
 
1235
        return outval;
 
1236
}
 
1237
 
 
1238
#ifdef TRIMBLE_OUTPUT_FUNC
 
1239
static unsigned short bGetUShort (unsigned char *bp)
 
1240
{
 
1241
        unsigned short outval;
 
1242
   unsigned char *optr;
 
1243
 
 
1244
   optr = (unsigned char*)&outval + 1;
 
1245
   *optr-- = *bp++;
 
1246
   *optr = *bp;
 
1247
        return outval;
 
1248
}
 
1249
 
 
1250
static long bGetLong (unsigned char *bp)
 
1251
{
 
1252
        long outval;
 
1253
   unsigned char *optr;
 
1254
 
 
1255
   optr = (unsigned char*)&outval + 3;
 
1256
   *optr-- = *bp++;
 
1257
   *optr-- = *bp++;
 
1258
   *optr-- = *bp++;
 
1259
   *optr = *bp;
 
1260
        return outval;
 
1261
}
 
1262
 
 
1263
static unsigned long bGetULong (unsigned char *bp)
 
1264
{
 
1265
        unsigned long outval;
 
1266
   unsigned char *optr;
 
1267
 
 
1268
   optr = (unsigned char*)&outval + 3;
 
1269
   *optr-- = *bp++;
 
1270
   *optr-- = *bp++;
 
1271
   *optr-- = *bp++;
 
1272
   *optr = *bp;
 
1273
        return outval;
 
1274
}
 
1275
#endif /* TRIMBLE_OUTPUT_FUNC */
 
1276
 
 
1277
static float bGetSingle (unsigned char *bp)
 
1278
{
 
1279
        float outval;
 
1280
   unsigned char *optr;
 
1281
 
 
1282
   optr = (unsigned char*)&outval + 3;
 
1283
   *optr-- = *bp++;
 
1284
   *optr-- = *bp++;
 
1285
   *optr-- = *bp++;
 
1286
   *optr = *bp;
 
1287
        return outval;
 
1288
}
 
1289
 
 
1290
static double bGetDouble (unsigned char *bp)
 
1291
{
 
1292
        double outval;
 
1293
   unsigned char *optr;
 
1294
 
 
1295
   optr = (unsigned char*)&outval + 7;
 
1296
   *optr-- = *bp++;
 
1297
   *optr-- = *bp++;
 
1298
   *optr-- = *bp++;
 
1299
   *optr-- = *bp++;
 
1300
   *optr-- = *bp++;
 
1301
   *optr-- = *bp++;
 
1302
   *optr-- = *bp++;
 
1303
   *optr = *bp;
 
1304
        return outval;
 
1305
}
 
1306
 
 
1307
#else /* not BYTESWAP */
 
1308
 
 
1309
#define bGetShort(bp)   (*(short*)(bp))
 
1310
#define bGetLong(bp)    (*(long*)(bp))
 
1311
#define bGetULong(bp)   (*(unsigned long*)(bp))
 
1312
#define bGetSingle(bp)  (*(float*)(bp))
 
1313
#define bGetDouble(bp)  (*(double*)(bp))
 
1314
 
 
1315
#endif /* BYTESWAP */
 
1316
/*
 
1317
 * Byte-reversal is necessary for little-endian (Intel-based) machines.
 
1318
 * TSIP streams are Big-endian (Motorola-based).
 
1319
 */
 
1320
#ifdef BYTESWAP
 
1321
 
 
1322
void
 
1323
bPutFloat (float *in, unsigned char *out)
 
1324
{
 
1325
        unsigned char *inptr;
 
1326
 
 
1327
   inptr = (unsigned char*)in + 3;
 
1328
   *out++ = *inptr--;
 
1329
   *out++ = *inptr--;
 
1330
   *out++ = *inptr--;
 
1331
   *out = *inptr;
 
1332
}
 
1333
 
 
1334
static void
 
1335
bPutULong (unsigned long *in, unsigned char *out)
 
1336
{
 
1337
        unsigned char *inptr;
 
1338
 
 
1339
   inptr = (unsigned char*)in + 3;
 
1340
   *out++ = *inptr--;
 
1341
   *out++ = *inptr--;
 
1342
   *out++ = *inptr--;
 
1343
   *out = *inptr;
 
1344
}
 
1345
 
 
1346
static void
 
1347
bPutDouble (double *in, unsigned char *out)
 
1348
{
 
1349
        unsigned char *inptr;
 
1350
 
 
1351
   inptr = (unsigned char*)in + 7;
 
1352
   *out++ = *inptr--;
 
1353
   *out++ = *inptr--;
 
1354
   *out++ = *inptr--;
 
1355
   *out++ = *inptr--;
 
1356
   *out++ = *inptr--;
 
1357
   *out++ = *inptr--;
 
1358
   *out++ = *inptr--;
 
1359
   *out = *inptr;
 
1360
}
 
1361
 
 
1362
#else   /* not BYTESWAP */
 
1363
 
 
1364
void bPutShort (short a, unsigned char *cmdbuf) {*(short*) cmdbuf = a;}
 
1365
void bPutULong (long a, unsigned char *cmdbuf)  {*(long*) cmdbuf = a;}
 
1366
void bPutFloat (float a, unsigned char *cmdbuf) {*(float*) cmdbuf = a;}
 
1367
void bPutDouble (double a, unsigned char *cmdbuf){*(double*) cmdbuf = a;}
 
1368
 
 
1369
#endif /* BYTESWAP */
 
1370
 
 
1371
/*
 
1372
 * Parse primary utc time packet
 
1373
 * and fill refclock structure 
 
1374
 * from results. 
 
1375
 *
 
1376
 * 0 = success
 
1377
 * -1 = errors
 
1378
 */
 
1379
 
 
1380
static int
 
1381
parse0x8FAD(rpt, peer)
 
1382
        TSIPPKT *rpt;
 
1383
        struct peer *peer;      
 
1384
{
 
1385
        register struct refclockproc *pp;       
 
1386
        register struct ripencc_unit *up;
 
1387
 
 
1388
        unsigned day, month, year;      /* data derived from received timecode */
 
1389
        unsigned hour, minute, second;
 
1390
        unsigned char trackstat, utcflags;
 
1391
 
 
1392
        static char logbuf[1024];       /* logging string buffer */
 
1393
        int i;
 
1394
        unsigned char *buf;
 
1395
                
 
1396
        buf = rpt->buf;
 
1397
        pp = peer->procptr;
 
1398
 
 
1399
        if (rpt->len != 22) 
 
1400
                return (-1);
 
1401
        
 
1402
        if (bGetShort(&buf[1]) != 0) {
 
1403
#ifdef DEBUG_NCC
 
1404
                if (debug) 
 
1405
                        printf("parse0x8FAD: event count != 0\n");
 
1406
#endif /* DEBUG_NCC */
 
1407
                return(-1);
 
1408
        }
 
1409
 
 
1410
 
 
1411
        if (bGetDouble(&buf[3]) != 0.0) {
 
1412
#ifdef DEBUG_NCC
 
1413
                if (debug) 
 
1414
                        printf("parse0x8FAD: fracsecs != 0\n");
 
1415
#endif /* DEBUG_NCC */
 
1416
                return(-1);
 
1417
        }
 
1418
 
 
1419
        hour = (unsigned int) buf[11];
 
1420
        minute = (unsigned int) buf[12];
 
1421
        second = (unsigned int) buf[13];
 
1422
        day =           (unsigned int) buf[14];
 
1423
        month =         (unsigned int) buf[15];
 
1424
        year =          bGetShort(&buf[16]);
 
1425
        trackstat = buf[18];
 
1426
        utcflags = buf[19];
 
1427
 
 
1428
 
 
1429
        sprintf(logbuf, "U1 %d.%d.%d %02d:%02d:%02d %d %02x",
 
1430
                day, month, year, hour, minute, second, trackstat, utcflags);
 
1431
 
 
1432
#ifdef DEBUG_NCC
 
1433
        if (debug) 
 
1434
                puts(logbuf);
 
1435
#endif /* DEBUG_NCC */
 
1436
 
 
1437
        record_clock_stats(&peer->srcadr, logbuf);
 
1438
 
 
1439
        if (!utcflags & UTCF_UTC_AVAIL)
 
1440
                return(-1);
 
1441
 
 
1442
        /* poll for UTC parameters once and then if UTC flag changed */
 
1443
        up = (struct ripencc_unit *) pp->unitptr;
 
1444
        if (utcflags != up->utcflags) {
 
1445
                TSIPPKT spt; /* local structure for send packet */
 
1446
                cmd_0x2F (&spt); /* request UTC params */
 
1447
                ripencc_send(peer,spt);
 
1448
                up->utcflags = utcflags;
 
1449
        }
 
1450
        
 
1451
        /*
 
1452
         * If we hit the leap second, we choose to skip this sample
 
1453
         * rather than rely on other code to be perfectly correct.
 
1454
         * No offense, just defense ;-).
 
1455
         */
 
1456
        if (second == 60)
 
1457
                return(-1);
 
1458
 
 
1459
        /* now check and convert the time we received */
 
1460
 
 
1461
        pp->year = year;
 
1462
        if (month < 1 || month > 12 || day < 1 || day > 31) 
 
1463
                return(-1);
 
1464
 
 
1465
        if (pp->year % 4) {
 
1466
                if (day > day1tab[month - 1]) 
 
1467
                        return(-1);
 
1468
                for (i = 0; i < month - 1; i++)
 
1469
                        day += day1tab[i];
 
1470
        } else {
 
1471
                if (day > day2tab[month - 1]) 
 
1472
                        return(-1);
 
1473
                for (i = 0; i < month - 1; i++)
 
1474
                        day += day2tab[i];
 
1475
        }
 
1476
        pp->day = day;
 
1477
        pp->hour = hour;
 
1478
        pp->minute = minute;
 
1479
        pp-> second = second;
 
1480
        pp->nsec = 0;
 
1481
 
 
1482
        if ((utcflags&UTCF_LEAP_PNDG) && up->leapdelta != 0) 
 
1483
                pp-> leap = (up->leapdelta > 0 ? LEAP_ADDSECOND : LEAP_DELSECOND); 
 
1484
        else
 
1485
                pp-> leap = LEAP_NOWARNING;  
 
1486
 
 
1487
        return (0);
 
1488
}
 
1489
 
 
1490
/*
 
1491
 * Parse comprehensive time packet 
 
1492
 *
 
1493
 * 0 = success
 
1494
 * -1 = errors
 
1495
 */
 
1496
 
 
1497
int parse0x8F0B(rpt, peer)
 
1498
        TSIPPKT *rpt;
 
1499
        struct peer *peer;      
 
1500
{
 
1501
        register struct refclockproc *pp;       
 
1502
 
 
1503
        unsigned day, month, year;      /* data derived from received timecode */
 
1504
        unsigned hour, minute, second;
 
1505
        unsigned utcoff;
 
1506
        unsigned char mode;
 
1507
        double  bias, rate;
 
1508
        float biasunc, rateunc;
 
1509
        double lat, lon, alt;
 
1510
        short lat_deg, lon_deg;
 
1511
        float lat_min, lon_min;
 
1512
        unsigned char north_south, east_west;
 
1513
        char sv[9];
 
1514
 
 
1515
        static char logbuf[1024];       /* logging string buffer */
 
1516
        unsigned char b;
 
1517
        int i;
 
1518
        unsigned char *buf;
 
1519
        double tow;
 
1520
                
 
1521
        buf = rpt->buf;
 
1522
        pp = peer->procptr;
 
1523
 
 
1524
        if (rpt->len != 74) 
 
1525
                return (-1);
 
1526
        
 
1527
        if (bGetShort(&buf[1]) != 0)
 
1528
                return(-1);;
 
1529
 
 
1530
        tow =  bGetDouble(&buf[3]);
 
1531
 
 
1532
        if (tow == -1.0) {
 
1533
                return(-1);
 
1534
        }
 
1535
        else if ((tow >= 604800.0) || (tow < 0.0)) {
 
1536
                return(-1);
 
1537
        }
 
1538
        else
 
1539
        {
 
1540
                if (tow < 604799.9) tow = tow + .00000001;
 
1541
                second = (unsigned int) fmod(tow, 60.);
 
1542
                minute =  (unsigned int) fmod(tow/60., 60.);
 
1543
                hour = (unsigned int )fmod(tow / 3600., 24.);
 
1544
        } 
 
1545
 
 
1546
 
 
1547
        day =           (unsigned int) buf[11];
 
1548
        month =         (unsigned int) buf[12];
 
1549
        year =          bGetShort(&buf[13]);
 
1550
        mode =          buf[15];
 
1551
        utcoff =        bGetShort(&buf[16]);
 
1552
        bias =          bGetDouble(&buf[18]) / GPS_C * 1e9;     /* ns */
 
1553
        rate =          bGetDouble(&buf[26]) / GPS_C * 1e9;     /* ppb */ 
 
1554
        biasunc =       bGetSingle(&buf[34]) / GPS_C * 1e9;     /* ns */
 
1555
        rateunc =       bGetSingle(&buf[38]) / GPS_C * 1e9;     /* ppb */
 
1556
        lat =           bGetDouble(&buf[42]) * R2D;
 
1557
        lon =           bGetDouble(&buf[50]) * R2D;
 
1558
        alt =           bGetDouble(&buf[58]);
 
1559
 
 
1560
        if (lat < 0.0) {
 
1561
                north_south = 'S';
 
1562
                lat = -lat;
 
1563
        }
 
1564
        else {
 
1565
                north_south = 'N';
 
1566
        }
 
1567
        lat_deg = (short)lat;
 
1568
        lat_min = (lat - lat_deg) * 60.0;
 
1569
 
 
1570
        if (lon < 0.0) {
 
1571
                east_west = 'W';
 
1572
                lon = -lon;
 
1573
        }
 
1574
        else {
 
1575
                east_west = 'E';
 
1576
        }
 
1577
 
 
1578
        lon_deg = (short)lon;
 
1579
        lon_min = (lon - lon_deg) * 60.0;
 
1580
 
 
1581
        for (i=0; i<8; i++) {
 
1582
                sv[i] = buf[i + 66];
 
1583
                if (sv[i]) {
 
1584
                        TSIPPKT spt; /* local structure for sendpacket */
 
1585
                        b = (unsigned char) (sv[i]<0 ? -sv[i] : sv[i]);
 
1586
                        /* request tracking status */
 
1587
                        cmd_0x3C  (&spt, b);
 
1588
                        ripencc_send(peer,spt);
 
1589
                }
 
1590
        }
 
1591
 
 
1592
 
 
1593
        sprintf(logbuf, "C1 %02d%02d%04d %02d%02d%02d %d %7.0f %.1f %.0f %.1f %d %02d%09.6f %c %02d%09.6f %c %.0f  %d %d %d %d %d %d %d %d",
 
1594
                day, month, year, hour, minute, second, mode, bias, biasunc, rate, rateunc, utcoff,
 
1595
                lat_deg, lat_min, north_south, lon_deg, lon_min, east_west, alt,
 
1596
                sv[0], sv[1], sv[2], sv[3], sv[4], sv[5], sv[6], sv[7]);
 
1597
 
 
1598
#ifdef DEBUG_NCC
 
1599
        if (debug) 
 
1600
                puts(logbuf);
 
1601
#endif /* DEBUG_NCC */
 
1602
 
 
1603
        record_clock_stats(&peer->srcadr, logbuf);
 
1604
 
 
1605
        return (0);
 
1606
}
 
1607
 
 
1608
#ifdef TRIMBLE_OUTPUT_FUNC
 
1609
/* 
 
1610
 * Parse any packet using Trimble machinery
 
1611
 */
 
1612
int parseany(rpt, peer) 
 
1613
        TSIPPKT *rpt;
 
1614
        struct peer *peer;      
 
1615
{
 
1616
        static char logbuf[1024];       /* logging string buffer */
 
1617
 
 
1618
        TranslateTSIPReportToText (rpt, logbuf);        /* anything else */
 
1619
#ifdef DEBUG_NCC
 
1620
        if (debug) 
 
1621
                puts(&logbuf[1]);
 
1622
#endif /* DEBUG_NCC */
 
1623
        record_clock_stats(&peer->srcadr, &logbuf[1]);
 
1624
        return(0);
 
1625
}
 
1626
#endif /* TRIMBLE_OUTPUT_FUNC */
 
1627
 
 
1628
 
 
1629
/*
 
1630
 * Parse UTC Parameter Packet
 
1631
 * 
 
1632
 * See the IDE for documentation!
 
1633
 *
 
1634
 * 0 = success
 
1635
 * -1 = errors
 
1636
 */
 
1637
 
 
1638
int parse0x4F(rpt, peer)
 
1639
        TSIPPKT *rpt;
 
1640
        struct peer *peer;      
 
1641
{
 
1642
        register struct ripencc_unit *up;
 
1643
 
 
1644
        double a0;
 
1645
        float a1, tot;
 
1646
        int dt_ls, wn_t, wn_lsf, dn, dt_lsf;
 
1647
 
 
1648
        static char logbuf[1024];       /* logging string buffer */
 
1649
        unsigned char *buf;
 
1650
                
 
1651
        buf = rpt->buf;
 
1652
        
 
1653
        if (rpt->len != 26) 
 
1654
                return (-1);
 
1655
        a0 = bGetDouble (buf);
 
1656
        a1 = bGetSingle (&buf[8]);
 
1657
        dt_ls = bGetShort (&buf[12]);
 
1658
        tot = bGetSingle (&buf[14]);
 
1659
        wn_t = bGetShort (&buf[18]);
 
1660
        wn_lsf = bGetShort (&buf[20]);
 
1661
        dn = bGetShort (&buf[22]);
 
1662
        dt_lsf = bGetShort (&buf[24]);
 
1663
 
 
1664
        sprintf(logbuf, "L1 %d %d %d %g %g %g %d %d %d",
 
1665
                dt_lsf - dt_ls, dt_ls, dt_lsf, a0, a1, tot, wn_t, wn_lsf, dn); 
 
1666
 
 
1667
#ifdef DEBUG_NCC
 
1668
        if (debug) 
 
1669
                puts(logbuf);
 
1670
#endif /* DEBUG_NCC */
 
1671
 
 
1672
        record_clock_stats(&peer->srcadr, logbuf);
 
1673
 
 
1674
        up = (struct ripencc_unit *) peer->procptr->unitptr;
 
1675
        up->leapdelta = dt_lsf - dt_ls;
 
1676
 
 
1677
        return (0);
 
1678
}
 
1679
 
 
1680
/*
 
1681
 * Parse Tracking Status packet
 
1682
 *
 
1683
 * 0 = success
 
1684
 * -1 = errors
 
1685
 */
 
1686
 
 
1687
int parse0x5C(rpt, peer)
 
1688
        TSIPPKT *rpt;
 
1689
        struct peer *peer;      
 
1690
{
 
1691
        unsigned char prn, channel, aqflag, ephstat;
 
1692
        float snr, azinuth, elevation;
 
1693
 
 
1694
        static char logbuf[1024];       /* logging string buffer */
 
1695
        unsigned char *buf;
 
1696
                
 
1697
        buf = rpt->buf;
 
1698
        
 
1699
        if (rpt->len != 24) 
 
1700
                return(-1);
 
1701
 
 
1702
        prn = buf[0];
 
1703
        channel = (unsigned char)(buf[1] >> 3);
 
1704
        if (channel == 0x10) 
 
1705
                channel = 2;
 
1706
        else 
 
1707
                channel++;
 
1708
        aqflag = buf[2];
 
1709
        ephstat = buf[3];
 
1710
        snr = bGetSingle(&buf[4]);
 
1711
        elevation = bGetSingle(&buf[12]) * R2D;
 
1712
        azinuth = bGetSingle(&buf[16]) * R2D;
 
1713
 
 
1714
        sprintf(logbuf, "S1 %02d %d %d %02x %4.1f %5.1f %4.1f",
 
1715
                prn, channel, aqflag, ephstat, snr, azinuth, elevation);
 
1716
 
 
1717
#ifdef DEBUG_NCC
 
1718
        if (debug) 
 
1719
                puts(logbuf);
 
1720
#endif /* DEBUG_NCC */
 
1721
 
 
1722
        record_clock_stats(&peer->srcadr, logbuf);
 
1723
 
 
1724
        return (0);
 
1725
}
 
1726
 
 
1727
/******* Code below is from Trimble Tsipchat *************/
 
1728
 
 
1729
/*
 
1730
 * *************************************************************************
 
1731
 *
 
1732
 * Trimble Navigation, Ltd.
 
1733
 * OEM Products Development Group
 
1734
 * P.O. Box 3642
 
1735
 * 645 North Mary Avenue
 
1736
 * Sunnyvale, California 94088-3642
 
1737
 *
 
1738
 * Corporate Headquarter:
 
1739
 *    Telephone:  (408) 481-8000
 
1740
 *    Fax:        (408) 481-6005
 
1741
 *
 
1742
 * Technical Support Center:
 
1743
 *    Telephone:  (800) 767-4822        (U.S. and Canada)
 
1744
 *                (408) 481-6940    (outside U.S. and Canada)
 
1745
 *    Fax:        (408) 481-6020
 
1746
 *    BBS:        (408) 481-7800
 
1747
 *    e-mail:     trimble_support@trimble.com
 
1748
 *              ftp://ftp.trimble.com/pub/sct/embedded/bin
 
1749
 *
 
1750
 * *************************************************************************
 
1751
 *
 
1752
 * -------  BYTE-SWAPPING  -------
 
1753
 * TSIP is big-endian (Motorola) protocol.  To use on little-endian (Intel)
 
1754
 * systems, the bytes of all multi-byte types (shorts, floats, doubles, etc.)
 
1755
 * must be reversed.  This is controlled by the MACRO BYTESWAP; if defined, it
 
1756
 * assumes little-endian protocol.
 
1757
 * --------------------------------
 
1758
 *
 
1759
 * T_PARSER.C and T_PARSER.H contains primitive functions that interpret
 
1760
 * reports received from the receiver.  A second source file pair,
 
1761
 * T_FORMAT.C and T_FORMAT.H, contin the matching TSIP command formatters.
 
1762
 *
 
1763
 * The module is in very portable, basic C language.  It can be used as is, or
 
1764
 * with minimal changes if a TSIP communications application is needed separate
 
1765
 * from TSIPCHAT. The construction of most argument lists avoid the use of
 
1766
 * structures, but the developer is encouraged to reconstruct them using such
 
1767
 * definitions to meet project requirements.  Declarations of T_PARSER.C
 
1768
 * functions are included in T_PARSER.H to provide prototyping definitions.
 
1769
 *
 
1770
 * There are two types of functions: a serial input processing routine,
 
1771
 *                            tsip_input_proc()
 
1772
 * which assembles incoming bytes into a TSIPPKT structure, and the
 
1773
 * report parsers, rpt_0x??().
 
1774
 *
 
1775
 * 1) The function tsip_input_proc() accumulates bytes from the receiver,
 
1776
 * strips control bytes (DLE), and checks if the report end sequence (DLE ETX)
 
1777
 * has been received.  rpt.status is defined as TSIP_PARSED_FULL (== 1)
 
1778
 * if a complete packet is available.
 
1779
 *
 
1780
 * 2) The functions rpt_0x??() are report string interpreters patterned after
 
1781
 * the document called "Trimble Standard Interface Protocol".  It should be
 
1782
 * noted that if the report buffer is sent into the receiver with the wrong
 
1783
 * length (byte count), the rpt_0x??() returns the Boolean equivalence for
 
1784
 * TRUE.
 
1785
 *
 
1786
 * *************************************************************************
 
1787
 *
 
1788
 */
 
1789
 
 
1790
 
 
1791
/**/
 
1792
static void tsip_input_proc (
 
1793
        TSIPPKT *rpt,
 
1794
        int inbyte)
 
1795
/* reads bytes until serial buffer is empty or a complete report
 
1796
 * has been received; end of report is signified by DLE ETX.
 
1797
 */
 
1798
{
 
1799
        unsigned char newbyte;
 
1800
 
 
1801
        if (inbyte < 0 || inbyte > 0xFF) return;
 
1802
 
 
1803
        newbyte = (unsigned char)(inbyte);
 
1804
        switch (rpt->status)
 
1805
        {
 
1806
        case TSIP_PARSED_DLE_1:
 
1807
                switch (newbyte)
 
1808
                {
 
1809
                case 0:
 
1810
                case ETX:
 
1811
        /* illegal TSIP IDs */
 
1812
         rpt->len = 0;
 
1813
                        rpt->status = TSIP_PARSED_EMPTY;
 
1814
                        break;
 
1815
                case DLE:
 
1816
        /* try normal message start again */
 
1817
                        rpt->len = 0;
 
1818
                        rpt->status = TSIP_PARSED_DLE_1;
 
1819
                        break;
 
1820
                default:
 
1821
        /* legal TSIP ID; start message */
 
1822
                        rpt->code = newbyte;
 
1823
         rpt->len = 0;
 
1824
                        rpt->status = TSIP_PARSED_DATA;
 
1825
                        break;
 
1826
                }
 
1827
                break;
 
1828
        case TSIP_PARSED_DATA:
 
1829
                switch (newbyte) {
 
1830
                case DLE:
 
1831
        /* expect DLE or ETX next */
 
1832
                        rpt->status = TSIP_PARSED_DLE_2;
 
1833
                        break;
 
1834
                default:
 
1835
        /* normal data byte  */
 
1836
                        rpt->buf[rpt->len] = newbyte;
 
1837
                        rpt->len++;
 
1838
         /* no change in rpt->status */
 
1839
                        break;
 
1840
                }
 
1841
                break;
 
1842
        case TSIP_PARSED_DLE_2:
 
1843
                switch (newbyte) {
 
1844
                case DLE:
 
1845
        /* normal data byte */
 
1846
                        rpt->buf[rpt->len] = newbyte;
 
1847
                        rpt->len++;
 
1848
                        rpt->status = TSIP_PARSED_DATA;
 
1849
                        break;
 
1850
                case ETX:
 
1851
                        /* end of message; return TRUE here. */
 
1852
                        rpt->status = TSIP_PARSED_FULL;
 
1853
                        break;
 
1854
                default:
 
1855
                        /* error: treat as TSIP_PARSED_DLE_1; start new report packet */
 
1856
                        rpt->code = newbyte;
 
1857
         rpt->len = 0;
 
1858
                        rpt->status = TSIP_PARSED_DATA;
 
1859
                }
 
1860
                break;
 
1861
        case TSIP_PARSED_FULL:
 
1862
        case TSIP_PARSED_EMPTY:
 
1863
        default:
 
1864
                switch (newbyte) {
 
1865
                case DLE:
 
1866
        /* normal message start */
 
1867
                        rpt->len = 0;
 
1868
                        rpt->status = TSIP_PARSED_DLE_1;
 
1869
                        break;
 
1870
                default:
 
1871
                        /* error: ignore newbyte */
 
1872
                        rpt->len = 0;
 
1873
                        rpt->status = TSIP_PARSED_EMPTY;
 
1874
                }
 
1875
                break;
 
1876
        }
 
1877
        if (rpt->len > MAX_RPTBUF) {
 
1878
                /* error: start new report packet */
 
1879
                rpt->status = TSIP_PARSED_EMPTY;
 
1880
                rpt->len = 0;
 
1881
        }
 
1882
}
 
1883
 
 
1884
#ifdef TRIMBLE_OUTPUT_FUNC
 
1885
 
 
1886
/**/
 
1887
short rpt_0x3D (TSIPPKT *rpt,
 
1888
        unsigned char *tx_baud_index,
 
1889
        unsigned char *rx_baud_index,
 
1890
        unsigned char *char_format_index,
 
1891
        unsigned char *stop_bits,
 
1892
        unsigned char *tx_mode_index,
 
1893
        unsigned char *rx_mode_index)
 
1894
/* Channel A configuration for dual port operation */
 
1895
{
 
1896
        unsigned char *buf;
 
1897
        buf = rpt->buf;
 
1898
 
 
1899
        if (rpt->len != 6) return TRUE;
 
1900
        *tx_baud_index = buf[0];
 
1901
        *rx_baud_index = buf[1];
 
1902
        *char_format_index = buf[2];
 
1903
        *stop_bits = (unsigned char)((buf[3] == 0x07) ? 1 : 2);
 
1904
        *tx_mode_index = buf[4];
 
1905
        *rx_mode_index = buf[5];
 
1906
        return FALSE;
 
1907
}
 
1908
 
 
1909
/**/
 
1910
short rpt_0x40 (TSIPPKT *rpt,
 
1911
        unsigned char *sv_prn,
 
1912
        short *week_num,
 
1913
        float *t_zc,
 
1914
        float *eccentricity,
 
1915
        float *t_oa,
 
1916
        float *i_0,
 
1917
        float *OMEGA_dot,
 
1918
        float *sqrt_A,
 
1919
        float *OMEGA_0,
 
1920
        float *omega,
 
1921
        float *M_0)
 
1922
/* almanac data for specified satellite */
 
1923
{
 
1924
        unsigned char *buf;
 
1925
        buf = rpt->buf;
 
1926
 
 
1927
        if (rpt->len != 39) return TRUE;
 
1928
        *sv_prn = buf[0];
 
1929
        *t_zc = bGetSingle (&buf[1]);
 
1930
        *week_num = bGetShort (&buf[5]);
 
1931
        *eccentricity = bGetSingle (&buf[7]);
 
1932
        *t_oa = bGetSingle (&buf[11]);
 
1933
        *i_0 = bGetSingle (&buf[15]);
 
1934
        *OMEGA_dot = bGetSingle (&buf[19]);
 
1935
        *sqrt_A = bGetSingle (&buf[23]);
 
1936
        *OMEGA_0 = bGetSingle (&buf[27]);
 
1937
        *omega = bGetSingle (&buf[31]);
 
1938
        *M_0 = bGetSingle (&buf[35]);
 
1939
        return FALSE;
 
1940
}
 
1941
 
 
1942
short rpt_0x41 (TSIPPKT *rpt,
 
1943
        float *time_of_week,
 
1944
        float *UTC_offset,
 
1945
        short *week_num)
 
1946
/* GPS time */
 
1947
{
 
1948
        unsigned char *buf;
 
1949
        buf = rpt->buf;
 
1950
        
 
1951
        if (rpt->len != 10) return TRUE;
 
1952
        *time_of_week = bGetSingle (buf);
 
1953
        *week_num = bGetShort (&buf[4]);
 
1954
        *UTC_offset = bGetSingle (&buf[6]);
 
1955
        return FALSE;
 
1956
}
 
1957
 
 
1958
short rpt_0x42 (TSIPPKT *rpt,
 
1959
        float pos_ECEF[3],
 
1960
        float *time_of_fix)
 
1961
/* position in ECEF, single precision */
 
1962
{
 
1963
        unsigned char *buf;
 
1964
        buf = rpt->buf;
 
1965
        
 
1966
        if (rpt->len != 16) return TRUE;
 
1967
        pos_ECEF[0] = bGetSingle (buf);
 
1968
        pos_ECEF[1]= bGetSingle (&buf[4]);
 
1969
        pos_ECEF[2]= bGetSingle (&buf[8]);
 
1970
        *time_of_fix = bGetSingle (&buf[12]);
 
1971
        return FALSE;
 
1972
}
 
1973
 
 
1974
short rpt_0x43 (TSIPPKT *rpt,
 
1975
        float ECEF_vel[3],
 
1976
        float *freq_offset,
 
1977
        float *time_of_fix)
 
1978
/* velocity in ECEF, single precision */
 
1979
{
 
1980
        unsigned char *buf;
 
1981
        buf = rpt->buf;
 
1982
 
 
1983
        if (rpt->len != 20) return TRUE;
 
1984
        ECEF_vel[0] = bGetSingle (buf);
 
1985
        ECEF_vel[1] = bGetSingle (&buf[4]);
 
1986
        ECEF_vel[2] = bGetSingle (&buf[8]);
 
1987
        *freq_offset = bGetSingle (&buf[12]);
 
1988
        *time_of_fix = bGetSingle (&buf[16]);
 
1989
        return FALSE;
 
1990
}
 
1991
 
 
1992
short rpt_0x45 (TSIPPKT *rpt,
 
1993
        unsigned char *major_nav_version,
 
1994
        unsigned char *minor_nav_version,
 
1995
        unsigned char *nav_day,
 
1996
        unsigned char *nav_month,
 
1997
        unsigned char *nav_year,
 
1998
        unsigned char *major_dsp_version,
 
1999
        unsigned char *minor_dsp_version,
 
2000
        unsigned char *dsp_day,
 
2001
        unsigned char *dsp_month,
 
2002
        unsigned char *dsp_year)
 
2003
/* software versions */ 
 
2004
{
 
2005
        unsigned char *buf;
 
2006
        buf = rpt->buf;
 
2007
 
 
2008
        if (rpt->len != 10) return TRUE;
 
2009
        *major_nav_version = buf[0];
 
2010
        *minor_nav_version = buf[1];
 
2011
        *nav_day = buf[2];
 
2012
        *nav_month = buf[3];
 
2013
        *nav_year = buf[4];
 
2014
        *major_dsp_version = buf[5];
 
2015
        *minor_dsp_version = buf[6];
 
2016
        *dsp_day = buf[7];
 
2017
        *dsp_month = buf[8];
 
2018
        *dsp_year = buf[9];
 
2019
        return FALSE;
 
2020
}
 
2021
 
 
2022
short rpt_0x46 (TSIPPKT *rpt,
 
2023
        unsigned char *status1,
 
2024
        unsigned char *status2)
 
2025
/* receiver health and status */
 
2026
{
 
2027
        unsigned char *buf;
 
2028
        buf = rpt->buf;
 
2029
 
 
2030
        if (rpt->len != 2) return TRUE;
 
2031
        *status1 = buf[0];
 
2032
        *status2 = buf[1];
 
2033
        return FALSE;
 
2034
}
 
2035
 
 
2036
short rpt_0x47 (TSIPPKT *rpt,
 
2037
        unsigned char *nsvs, unsigned char *sv_prn,
 
2038
        float *snr)
 
2039
/* signal levels for all satellites tracked */
 
2040
{
 
2041
        short isv;
 
2042
        unsigned char *buf;
 
2043
        buf = rpt->buf;
 
2044
 
 
2045
        if (rpt->len != 1 + 5*buf[0]) return TRUE;
 
2046
        *nsvs = buf[0];
 
2047
        for (isv = 0; isv < (*nsvs); isv++) {
 
2048
                sv_prn[isv] = buf[5*isv + 1];
 
2049
                snr[isv] = bGetSingle (&buf[5*isv + 2]);
 
2050
        }
 
2051
        return FALSE;
 
2052
}
 
2053
 
 
2054
short rpt_0x48 (TSIPPKT *rpt,
 
2055
        unsigned char *message)
 
2056
/* GPS system message */
 
2057
{
 
2058
        unsigned char *buf;
 
2059
        buf = rpt->buf;
 
2060
 
 
2061
        if (rpt->len != 22) return TRUE;
 
2062
        memcpy (message, buf, 22);
 
2063
        message[22] = 0;
 
2064
        return FALSE;
 
2065
}
 
2066
 
 
2067
short rpt_0x49 (TSIPPKT *rpt,
 
2068
        unsigned char *sv_health)
 
2069
/* health for all satellites from almanac health page */
 
2070
{
 
2071
        short i;
 
2072
        unsigned char *buf;
 
2073
        buf = rpt->buf;
 
2074
 
 
2075
        if (rpt->len != 32) return TRUE;
 
2076
        for (i = 0; i < 32; i++) sv_health [i]= buf[i];
 
2077
        return FALSE;
 
2078
}
 
2079
 
 
2080
short rpt_0x4A (TSIPPKT *rpt,
 
2081
        float *lat,
 
2082
        float *lon,
 
2083
        float *alt,
 
2084
        float *clock_bias,
 
2085
        float *time_of_fix)
 
2086
/* position in lat-lon-alt, single precision */
 
2087
{
 
2088
        unsigned char *buf;
 
2089
        buf = rpt->buf;
 
2090
 
 
2091
        if (rpt->len != 20) return TRUE;
 
2092
        *lat = bGetSingle (buf);
 
2093
        *lon = bGetSingle (&buf[4]);
 
2094
        *alt = bGetSingle (&buf[8]);
 
2095
        *clock_bias = bGetSingle (&buf[12]);
 
2096
        *time_of_fix = bGetSingle (&buf[16]);
 
2097
        return FALSE;
 
2098
}
 
2099
 
 
2100
short rpt_0x4A_2 (TSIPPKT *rpt,
 
2101
        float *alt, float *dummy , unsigned char *alt_flag)
 
2102
/* reference altitude parameters */
 
2103
{
 
2104
        unsigned char *buf;
 
2105
 
 
2106
        buf = rpt->buf;
 
2107
 
 
2108
        if (rpt->len != 9) return TRUE;
 
2109
        *alt = bGetSingle (buf);
 
2110
        *dummy = bGetSingle (&buf[4]);
 
2111
        *alt_flag = buf[8];
 
2112
        return FALSE;
 
2113
}
 
2114
 
 
2115
short rpt_0x4B (TSIPPKT *rpt,
 
2116
        unsigned char *machine_id,
 
2117
        unsigned char *status3,
 
2118
        unsigned char *status4)
 
2119
/* machine ID code, status */
 
2120
{
 
2121
        unsigned char *buf;
 
2122
        buf = rpt->buf;
 
2123
 
 
2124
        if (rpt->len != 3) return TRUE;
 
2125
        *machine_id = buf[0];
 
2126
        *status3 = buf[1];
 
2127
        *status4 = buf[2];
 
2128
        return FALSE;
 
2129
}
 
2130
 
 
2131
short rpt_0x4C (TSIPPKT *rpt,
 
2132
        unsigned char *dyn_code,
 
2133
        float *el_mask,
 
2134
        float *snr_mask,
 
2135
        float *dop_mask,
 
2136
        float *dop_switch)
 
2137
/* operating parameters and masks */
 
2138
{
 
2139
        unsigned char *buf;
 
2140
        buf = rpt->buf;
 
2141
 
 
2142
        if (rpt->len != 17) return TRUE;
 
2143
        *dyn_code = buf[0];
 
2144
        *el_mask = bGetSingle (&buf[1]);
 
2145
        *snr_mask = bGetSingle (&buf[5]);
 
2146
        *dop_mask = bGetSingle (&buf[9]);
 
2147
        *dop_switch = bGetSingle (&buf[13]);
 
2148
        return FALSE;
 
2149
}
 
2150
 
 
2151
short rpt_0x4D (TSIPPKT *rpt,
 
2152
        float *osc_offset)
 
2153
/* oscillator offset */
 
2154
{
 
2155
        unsigned char *buf;
 
2156
        buf = rpt->buf;
 
2157
 
 
2158
        if (rpt->len != 4) return TRUE;
 
2159
        *osc_offset = bGetSingle (buf);
 
2160
        return FALSE;
 
2161
}
 
2162
 
 
2163
short rpt_0x4E (TSIPPKT *rpt,
 
2164
        unsigned char *response)
 
2165
/* yes/no response to command to set GPS time */
 
2166
{
 
2167
        unsigned char *buf;
 
2168
        buf = rpt->buf;
 
2169
 
 
2170
        if (rpt->len != 1) return TRUE;
 
2171
        *response = buf[0];
 
2172
        return FALSE;
 
2173
}
 
2174
 
 
2175
short rpt_0x4F (TSIPPKT *rpt,
 
2176
        double *a0,
 
2177
        float *a1,
 
2178
        float *time_of_data,
 
2179
        short *dt_ls,
 
2180
        short *wn_t,
 
2181
        short *wn_lsf,
 
2182
        short *dn,
 
2183
        short *dt_lsf)
 
2184
/* UTC data */
 
2185
{
 
2186
        unsigned char *buf;
 
2187
        buf = rpt->buf;
 
2188
 
 
2189
        if (rpt->len != 26) return TRUE;
 
2190
        *a0 = bGetDouble (buf);
 
2191
        *a1 = bGetSingle (&buf[8]);
 
2192
        *dt_ls = bGetShort (&buf[12]);
 
2193
        *time_of_data = bGetSingle (&buf[14]);
 
2194
        *wn_t = bGetShort (&buf[18]);
 
2195
        *wn_lsf = bGetShort (&buf[20]);
 
2196
        *dn = bGetShort (&buf[22]);
 
2197
        *dt_lsf = bGetShort (&buf[24]);
 
2198
        return FALSE;
 
2199
}
 
2200
 
 
2201
/**/
 
2202
short rpt_0x54 (TSIPPKT *rpt,
 
2203
        float *clock_bias,
 
2204
   float *freq_offset,
 
2205
   float *time_of_fix)
 
2206
/* clock offset and frequency offset in 1-SV (0-D) mode */
 
2207
{
 
2208
        unsigned char *buf;
 
2209
        buf = rpt->buf;
 
2210
 
 
2211
        if (rpt->len != 12) return TRUE;
 
2212
        *clock_bias = bGetSingle (buf);
 
2213
        *freq_offset = bGetSingle (&buf[4]);
 
2214
        *time_of_fix = bGetSingle (&buf[8]);
 
2215
        return FALSE;
 
2216
}
 
2217
 
 
2218
short rpt_0x55 (TSIPPKT *rpt,
 
2219
        unsigned char *pos_code,
 
2220
        unsigned char *vel_code,
 
2221
        unsigned char *time_code,
 
2222
        unsigned char *aux_code)
 
2223
/* I/O serial options */
 
2224
{
 
2225
        unsigned char *buf;
 
2226
        buf = rpt->buf;
 
2227
        
 
2228
        if (rpt->len != 4) return TRUE;
 
2229
        *pos_code = buf[0];
 
2230
        *vel_code = buf[1];
 
2231
        *time_code = buf[2];
 
2232
        *aux_code = buf[3];
 
2233
        return FALSE;
 
2234
}
 
2235
 
 
2236
short rpt_0x56 (TSIPPKT *rpt,
 
2237
        float vel_ENU[3], float *freq_offset, float *time_of_fix)
 
2238
/* velocity in east-north-up coordinates */     
 
2239
{
 
2240
        unsigned char *buf;
 
2241
        buf = rpt->buf;
 
2242
        
 
2243
        if (rpt->len != 20) return TRUE;
 
2244
        /* east */
 
2245
        vel_ENU[0] = bGetSingle (buf);
 
2246
        /* north */
 
2247
        vel_ENU[1] = bGetSingle (&buf[4]);
 
2248
        /* up */
 
2249
        vel_ENU[2] = bGetSingle (&buf[8]);
 
2250
        *freq_offset = bGetSingle (&buf[12]);
 
2251
        *time_of_fix = bGetSingle (&buf[16]);
 
2252
        return FALSE;
 
2253
}
 
2254
 
 
2255
short rpt_0x57 (TSIPPKT *rpt,
 
2256
        unsigned char *source_code, unsigned char *diag_code,
 
2257
        short *week_num,
 
2258
        float *time_of_fix)
 
2259
/* info about last computed fix */
 
2260
{
 
2261
        unsigned char *buf;
 
2262
        buf = rpt->buf;
 
2263
        
 
2264
        if (rpt->len != 8) return TRUE;
 
2265
        *source_code = buf[0];
 
2266
        *diag_code = buf[1];
 
2267
        *time_of_fix = bGetSingle (&buf[2]);
 
2268
        *week_num = bGetShort (&buf[6]);
 
2269
        return FALSE;
 
2270
}
 
2271
 
 
2272
short rpt_0x58 (TSIPPKT *rpt,
 
2273
        unsigned char *op_code, unsigned char *data_type, unsigned char *sv_prn,
 
2274
        unsigned char *data_length, unsigned char *data_packet)
 
2275
/* GPS system data or acknowledgment of GPS system data load */
 
2276
{
 
2277
        unsigned char *buf, *buf4;
 
2278
        short dl;
 
2279
        ALM_INFO* alminfo;
 
2280
        ION_INFO* ioninfo;
 
2281
        UTC_INFO* utcinfo;
 
2282
        NAV_INFO* navinfo;
 
2283
 
 
2284
        buf = rpt->buf;
 
2285
 
 
2286
        if (buf[0] == 2) {
 
2287
                if (rpt->len < 4) return TRUE;
 
2288
                if (rpt->len != 4+buf[3]) return TRUE;
 
2289
        }
 
2290
        else if (rpt->len != 3) {
 
2291
                return TRUE;
 
2292
        }
 
2293
        *op_code = buf[0];
 
2294
        *data_type = buf[1];
 
2295
        *sv_prn = buf[2];
 
2296
        if (*op_code == 2) {
 
2297
                dl = buf[3];
 
2298
                *data_length = (unsigned char)dl;
 
2299
                buf4 = &buf[4];
 
2300
                switch (*data_type) {
 
2301
                case 2:
 
2302
                        /* Almanac */
 
2303
                        if (*data_length != sizeof (ALM_INFO)) return TRUE;
 
2304
                        alminfo = (ALM_INFO*)data_packet;
 
2305
                        alminfo->t_oa_raw  = buf4[0];
 
2306
                        alminfo->SV_health = buf4[1];
 
2307
                        alminfo->e         = bGetSingle(&buf4[2]);
 
2308
                        alminfo->t_oa      = bGetSingle(&buf4[6]);
 
2309
                        alminfo->i_0       = bGetSingle(&buf4[10]);
 
2310
                        alminfo->OMEGADOT  = bGetSingle(&buf4[14]);
 
2311
                        alminfo->sqrt_A    = bGetSingle(&buf4[18]);
 
2312
                        alminfo->OMEGA_0   = bGetSingle(&buf4[22]);
 
2313
                        alminfo->omega     = bGetSingle(&buf4[26]);
 
2314
                        alminfo->M_0       = bGetSingle(&buf4[30]);
 
2315
                        alminfo->a_f0      = bGetSingle(&buf4[34]);
 
2316
                        alminfo->a_f1      = bGetSingle(&buf4[38]);
 
2317
                        alminfo->Axis      = bGetSingle(&buf4[42]);
 
2318
                        alminfo->n         = bGetSingle(&buf4[46]);
 
2319
                        alminfo->OMEGA_n   = bGetSingle(&buf4[50]);
 
2320
                        alminfo->ODOT_n    = bGetSingle(&buf4[54]);
 
2321
                        alminfo->t_zc      = bGetSingle(&buf4[58]);
 
2322
                        alminfo->weeknum   = bGetShort(&buf4[62]);
 
2323
                        alminfo->wn_oa     = bGetShort(&buf4[64]);
 
2324
                        break;
 
2325
 
 
2326
                case 3:
 
2327
                        /* Almanac health page */
 
2328
                        if (*data_length != sizeof (ALH_PARMS) + 3) return TRUE;
 
2329
 
 
2330
                        /* this record is returned raw */
 
2331
                        memcpy (data_packet, buf4, dl);
 
2332
                        break;
 
2333
 
 
2334
                case 4:
 
2335
                        /* Ionosphere */
 
2336
                        if (*data_length != sizeof (ION_INFO) + 8) return TRUE;
 
2337
                        ioninfo = (ION_INFO*)data_packet;
 
2338
                        ioninfo->alpha_0   = bGetSingle (&buf4[8]);
 
2339
                        ioninfo->alpha_1   = bGetSingle (&buf4[12]);
 
2340
                        ioninfo->alpha_2   = bGetSingle (&buf4[16]);
 
2341
                        ioninfo->alpha_3   = bGetSingle (&buf4[20]);
 
2342
                        ioninfo->beta_0    = bGetSingle (&buf4[24]);
 
2343
                        ioninfo->beta_1    = bGetSingle (&buf4[28]);
 
2344
                        ioninfo->beta_2    = bGetSingle (&buf4[32]);
 
2345
                        ioninfo->beta_3    = bGetSingle (&buf4[36]);
 
2346
                        break;
 
2347
 
 
2348
                case 5:
 
2349
                        /* UTC */
 
2350
                        if (*data_length != sizeof (UTC_INFO) + 13) return TRUE;
 
2351
                        utcinfo = (UTC_INFO*)data_packet;
 
2352
                        utcinfo->A_0       = bGetDouble (&buf4[13]);
 
2353
                        utcinfo->A_1       = bGetSingle (&buf4[21]);
 
2354
                        utcinfo->delta_t_LS = bGetShort (&buf4[25]);
 
2355
                        utcinfo->t_ot      = bGetSingle(&buf4[27]);
 
2356
                        utcinfo->WN_t      = bGetShort (&buf4[31]);
 
2357
                        utcinfo->WN_LSF    = bGetShort (&buf4[33]);
 
2358
                        utcinfo->DN        = bGetShort (&buf4[35]);
 
2359
                        utcinfo->delta_t_LSF = bGetShort (&buf4[37]);
 
2360
                        break;
 
2361
 
 
2362
                case 6:
 
2363
                        /* Ephemeris */
 
2364
                        if (*data_length != sizeof (NAV_INFO) - 1) return TRUE;
 
2365
 
 
2366
                        navinfo = (NAV_INFO*)data_packet;
 
2367
 
 
2368
                        navinfo->sv_number = buf4[0];
 
2369
                        navinfo->t_ephem = bGetSingle (&buf4[1]);
 
2370
                        navinfo->ephclk.weeknum = bGetShort (&buf4[5]);
 
2371
 
 
2372
                        navinfo->ephclk.codeL2 = buf4[7];
 
2373
                        navinfo->ephclk.L2Pdata = buf4[8];
 
2374
                        navinfo->ephclk.SVacc_raw = buf4[9];
 
2375
                        navinfo->ephclk.SV_health = buf4[10];
 
2376
                        navinfo->ephclk.IODC = bGetShort (&buf4[11]);
 
2377
                        navinfo->ephclk.T_GD = bGetSingle (&buf4[13]);
 
2378
                        navinfo->ephclk.t_oc = bGetSingle (&buf4[17]);
 
2379
                        navinfo->ephclk.a_f2 = bGetSingle (&buf4[21]);
 
2380
                        navinfo->ephclk.a_f1 = bGetSingle (&buf4[25]);
 
2381
                        navinfo->ephclk.a_f0 = bGetSingle (&buf4[29]);
 
2382
                        navinfo->ephclk.SVacc = bGetSingle (&buf4[33]);
 
2383
 
 
2384
                        navinfo->ephorb.IODE = buf4[37];
 
2385
                        navinfo->ephorb.fit_interval = buf4[38];
 
2386
                        navinfo->ephorb.C_rs = bGetSingle (&buf4[39]);
 
2387
                        navinfo->ephorb.delta_n = bGetSingle (&buf4[43]);
 
2388
                        navinfo->ephorb.M_0 = bGetDouble (&buf4[47]);
 
2389
                        navinfo->ephorb.C_uc = bGetSingle (&buf4[55]);
 
2390
                        navinfo->ephorb.e = bGetDouble (&buf4[59]);
 
2391
                        navinfo->ephorb.C_us = bGetSingle (&buf4[67]);
 
2392
                        navinfo->ephorb.sqrt_A = bGetDouble (&buf4[71]);
 
2393
                        navinfo->ephorb.t_oe = bGetSingle (&buf4[79]);
 
2394
                        navinfo->ephorb.C_ic = bGetSingle (&buf4[83]);
 
2395
                        navinfo->ephorb.OMEGA_0 = bGetDouble (&buf4[87]);
 
2396
                        navinfo->ephorb.C_is = bGetSingle (&buf4[95]);
 
2397
                        navinfo->ephorb.i_0 = bGetDouble (&buf4[99]);
 
2398
                        navinfo->ephorb.C_rc = bGetSingle (&buf4[107]);
 
2399
                        navinfo->ephorb.omega = bGetDouble (&buf4[111]);
 
2400
                        navinfo->ephorb.OMEGADOT=bGetSingle (&buf4[119]);
 
2401
                        navinfo->ephorb.IDOT = bGetSingle (&buf4[123]);
 
2402
                        navinfo->ephorb.Axis = bGetDouble (&buf4[127]);
 
2403
                        navinfo->ephorb.n = bGetDouble (&buf4[135]);
 
2404
                        navinfo->ephorb.r1me2 = bGetDouble (&buf4[143]);
 
2405
                        navinfo->ephorb.OMEGA_n=bGetDouble (&buf4[151]);
 
2406
                        navinfo->ephorb.ODOT_n = bGetDouble (&buf4[159]);
 
2407
                        break;
 
2408
                }
 
2409
        }
 
2410
        return FALSE;
 
2411
}
 
2412
 
 
2413
short rpt_0x59 (TSIPPKT *rpt,
 
2414
        unsigned char *code_type,
 
2415
        unsigned char status_code[32])
 
2416
/* satellite enable/disable or health heed/ignore list */       
 
2417
{
 
2418
        short iprn;
 
2419
        unsigned char *buf;
 
2420
        buf = rpt->buf;
 
2421
        
 
2422
        if (rpt->len != 33) return TRUE;
 
2423
        *code_type = buf[0];
 
2424
        for (iprn = 0; iprn < 32; iprn++)
 
2425
                status_code[iprn] = buf[iprn + 1];
 
2426
        return FALSE;
 
2427
}
 
2428
 
 
2429
short rpt_0x5A (TSIPPKT *rpt,
 
2430
        unsigned char *sv_prn,
 
2431
        float *sample_length,
 
2432
        float *signal_level,
 
2433
        float *code_phase,
 
2434
        float *Doppler,
 
2435
        double *time_of_fix)
 
2436
/* raw measurement data - code phase/Doppler */
 
2437
{
 
2438
        unsigned char *buf;
 
2439
        buf = rpt->buf;
 
2440
 
 
2441
        if (rpt->len != 25) return TRUE;
 
2442
        *sv_prn = buf[0];
 
2443
        *sample_length = bGetSingle (&buf[1]);
 
2444
        *signal_level = bGetSingle (&buf[5]);
 
2445
        *code_phase = bGetSingle (&buf[9]);
 
2446
        *Doppler = bGetSingle (&buf[13]);
 
2447
        *time_of_fix = bGetDouble (&buf[17]);
 
2448
        return FALSE;
 
2449
}
 
2450
 
 
2451
short rpt_0x5B (TSIPPKT *rpt,
 
2452
        unsigned char *sv_prn,
 
2453
        unsigned char *sv_health,
 
2454
        unsigned char *sv_iode,
 
2455
        unsigned char *fit_interval_flag,
 
2456
        float *time_of_collection,
 
2457
        float *time_of_eph,
 
2458
        float *sv_accy)
 
2459
/* satellite ephorb status */   
 
2460
{
 
2461
        unsigned char *buf;
 
2462
        buf = rpt->buf;
 
2463
        
 
2464
        if (rpt->len != 16) return TRUE;
 
2465
        *sv_prn = buf[0];
 
2466
        *time_of_collection = bGetSingle (&buf[1]);
 
2467
        *sv_health = buf[5];
 
2468
        *sv_iode = buf[6];
 
2469
        *time_of_eph = bGetSingle (&buf[7]);
 
2470
        *fit_interval_flag = buf[11];
 
2471
        *sv_accy = bGetSingle (&buf[12]);
 
2472
        return FALSE;
 
2473
}
 
2474
 
 
2475
short rpt_0x5C (TSIPPKT *rpt,
 
2476
        unsigned char *sv_prn,
 
2477
        unsigned char *slot,
 
2478
        unsigned char *chan,
 
2479
        unsigned char *acq_flag,
 
2480
        unsigned char *eph_flag,
 
2481
        float *signal_level,
 
2482
        float *time_of_last_msmt,
 
2483
        float *elev,
 
2484
        float *azim,
 
2485
        unsigned char *old_msmt_flag,
 
2486
        unsigned char *integer_msec_flag,
 
2487
        unsigned char *bad_data_flag,
 
2488
        unsigned char *data_collect_flag)
 
2489
/* satellite tracking status */
 
2490
{
 
2491
        unsigned char *buf;
 
2492
        buf = rpt->buf;
 
2493
        
 
2494
        if (rpt->len != 24) return TRUE;
 
2495
        *sv_prn = buf[0];
 
2496
        *slot = (unsigned char)((buf[1] & 0x07) + 1);
 
2497
        *chan = (unsigned char)(buf[1] >> 3);
 
2498
        if (*chan == 0x10) *chan = 2;
 
2499
        else (*chan)++;
 
2500
        *acq_flag = buf[2];
 
2501
        *eph_flag = buf[3];
 
2502
        *signal_level = bGetSingle (&buf[4]);
 
2503
        *time_of_last_msmt = bGetSingle (&buf[8]);
 
2504
        *elev = bGetSingle (&buf[12]);
 
2505
        *azim = bGetSingle (&buf[16]);
 
2506
        *old_msmt_flag = buf[20];
 
2507
        *integer_msec_flag = buf[21];
 
2508
        *bad_data_flag = buf[22];
 
2509
        *data_collect_flag = buf[23];
 
2510
        return FALSE;
 
2511
}
 
2512
 
 
2513
/**/
 
2514
short rpt_0x6D (TSIPPKT *rpt,
 
2515
        unsigned char *manual_mode,
 
2516
        unsigned char *nsvs,
 
2517
        unsigned char *ndim,
 
2518
        unsigned char sv_prn[],
 
2519
        float *pdop,
 
2520
        float *hdop,
 
2521
        float *vdop,
 
2522
        float *tdop)
 
2523
/* over-determined satellite selection for position fixes, PDOP, fix mode */
 
2524
{
 
2525
        short islot;
 
2526
        unsigned char *buf;
 
2527
        buf = rpt->buf;
 
2528
 
 
2529
        *nsvs = (unsigned char)((buf[0] & 0xF0) >> 4);
 
2530
        if ((*nsvs)>8) return TRUE;
 
2531
        if (rpt->len != 17 + (*nsvs) ) return TRUE;
 
2532
 
 
2533
        *manual_mode = (unsigned char)(buf[0] & 0x08);
 
2534
        *ndim  = (unsigned char)((buf[0] & 0x07));
 
2535
        *pdop = bGetSingle (&buf[1]);
 
2536
        *hdop = bGetSingle (&buf[5]);
 
2537
        *vdop = bGetSingle (&buf[9]);
 
2538
        *tdop = bGetSingle (&buf[13]);
 
2539
        for (islot = 0; islot < (*nsvs); islot++)
 
2540
                sv_prn[islot] = buf[islot + 17];
 
2541
        return FALSE;
 
2542
}
 
2543
 
 
2544
/**/
 
2545
short rpt_0x82 (TSIPPKT *rpt,
 
2546
        unsigned char *diff_mode)
 
2547
/* differential fix mode */
 
2548
{
 
2549
        unsigned char *buf;
 
2550
        buf = rpt->buf;
 
2551
 
 
2552
        if (rpt->len != 1) return TRUE;
 
2553
        *diff_mode = buf[0];
 
2554
        return FALSE;
 
2555
}
 
2556
 
 
2557
short rpt_0x83 (TSIPPKT *rpt,
 
2558
        double ECEF_pos[3],
 
2559
        double *clock_bias,
 
2560
        float *time_of_fix)
 
2561
/* position, ECEF double precision */
 
2562
{
 
2563
        unsigned char *buf;
 
2564
        buf = rpt->buf;
 
2565
 
 
2566
        if (rpt->len != 36) return TRUE;
 
2567
        ECEF_pos[0] = bGetDouble (buf);
 
2568
        ECEF_pos[1] = bGetDouble (&buf[8]);
 
2569
        ECEF_pos[2] = bGetDouble (&buf[16]);
 
2570
        *clock_bias  = bGetDouble (&buf[24]);
 
2571
        *time_of_fix = bGetSingle (&buf[32]);
 
2572
        return FALSE;
 
2573
}
 
2574
 
 
2575
short rpt_0x84 (TSIPPKT *rpt,
 
2576
        double *lat,
 
2577
        double *lon,
 
2578
        double *alt,
 
2579
        double *clock_bias,
 
2580
        float *time_of_fix)
 
2581
/* position, lat-lon-alt double precision */    
 
2582
{
 
2583
        unsigned char *buf;
 
2584
        buf = rpt->buf;
 
2585
 
 
2586
        if (rpt->len != 36) return TRUE;
 
2587
        *lat = bGetDouble (buf);
 
2588
        *lon = bGetDouble (&buf[8]);
 
2589
        *alt = bGetDouble (&buf[16]);
 
2590
        *clock_bias = bGetDouble (&buf[24]);
 
2591
        *time_of_fix = bGetSingle (&buf[32]);
 
2592
        return FALSE;
 
2593
}
 
2594
 
 
2595
short rpt_Paly0xBB(TSIPPKT *rpt,
 
2596
        TSIP_RCVR_CFG *TsipxBB)
 
2597
{
 
2598
 
 
2599
        unsigned char *buf;
 
2600
        buf = rpt->buf;
 
2601
 
 
2602
        /* Palisade is inconsistent with other TSIP, which has a kength of 40 */
 
2603
        /* if (rpt->len != 40) return TRUE; */
 
2604
        if (rpt->len != 43) return TRUE;
 
2605
 
 
2606
        TsipxBB->bSubcode               =       buf[0];
 
2607
        TsipxBB->operating_mode =       buf[1]  ;
 
2608
        TsipxBB->dyn_code                       =       buf[3]  ;
 
2609
        TsipxBB->elev_mask              =  bGetSingle (&buf[5]);
 
2610
        TsipxBB->cno_mask                       =       bGetSingle (&buf[9]);
 
2611
        TsipxBB->dop_mask               =  bGetSingle (&buf[13]);
 
2612
        TsipxBB->dop_switch     =  bGetSingle (&buf[17]);
 
2613
        return FALSE;
 
2614
}
 
2615
 
 
2616
short rpt_0xBC (TSIPPKT *rpt,
 
2617
        unsigned char *port_num,
 
2618
   unsigned char *in_baud,
 
2619
        unsigned char *out_baud,
 
2620
   unsigned char *data_bits,
 
2621
        unsigned char *parity,
 
2622
   unsigned char *stop_bits,
 
2623
   unsigned char *flow_control,
 
2624
        unsigned char *protocols_in,
 
2625
   unsigned char *protocols_out,
 
2626
   unsigned char *reserved)
 
2627
/* Receiver serial port configuration */
 
2628
{
 
2629
        unsigned char *buf;
 
2630
        buf = rpt->buf;
 
2631
 
 
2632
        if (rpt->len != 10) return TRUE;
 
2633
        *port_num = buf[0];
 
2634
        *in_baud = buf[1];
 
2635
        *out_baud = buf[2];
 
2636
        *data_bits = buf[3];
 
2637
        *parity = buf[4];
 
2638
        *stop_bits = buf[5];
 
2639
        *flow_control = buf[6];
 
2640
        *protocols_in = buf[7];
 
2641
        *protocols_out = buf[8];
 
2642
        *reserved = buf[9];
 
2643
 
 
2644
        return FALSE;
 
2645
}
 
2646
 
 
2647
/**** Superpackets ****/
 
2648
 
 
2649
short rpt_0x8F0B(TSIPPKT *rpt,
 
2650
                 unsigned short *event,
 
2651
                 double *tow,
 
2652
                 unsigned char *date,
 
2653
                 unsigned char *month,
 
2654
                 short *year,
 
2655
                 unsigned char *dim_mode,
 
2656
                 short *utc_offset,
 
2657
                 double *bias,
 
2658
                 double *drift,
 
2659
                 float *bias_unc,
 
2660
                 float *dr_unc,
 
2661
                 double *lat,
 
2662
                 double *lon,
 
2663
                 double *alt,
 
2664
                 char sv_id[8])
 
2665
{
 
2666
       short local_index;
 
2667
       unsigned char *buf;
 
2668
 
 
2669
        buf = rpt->buf;
 
2670
       if (rpt->len != 74) return TRUE;
 
2671
       *event = bGetShort(&buf[1]);
 
2672
       *tow = bGetDouble(&buf[3]);
 
2673
       *date = buf[11];
 
2674
       *month = buf[12];
 
2675
       *year = bGetShort(&buf[13]);
 
2676
       *dim_mode = buf[15];
 
2677
       *utc_offset = bGetShort(&buf[16]);
 
2678
       *bias = bGetDouble(&buf[18]);
 
2679
       *drift = bGetDouble(&buf[26]);
 
2680
       *bias_unc = bGetSingle(&buf[34]);
 
2681
       *dr_unc = bGetSingle(&buf[38]);
 
2682
       *lat = bGetDouble(&buf[42]);
 
2683
       *lon = bGetDouble(&buf[50]);
 
2684
       *alt = bGetDouble(&buf[58]);
 
2685
 
 
2686
       for (local_index=0; local_index<8; local_index++) sv_id[local_index] = buf[local_index + 66];
 
2687
       return FALSE;
 
2688
}
 
2689
 
 
2690
short rpt_0x8F14 (TSIPPKT *rpt,
 
2691
        short *datum_idx,
 
2692
        double datum_coeffs[5])
 
2693
/*  datum index and coefficients  */
 
2694
{
 
2695
        unsigned char *buf;
 
2696
        buf = rpt->buf;
 
2697
 
 
2698
        if (rpt->len != 43) return TRUE;
 
2699
        *datum_idx = bGetShort(&buf[1]);
 
2700
        datum_coeffs[0] = bGetDouble (&buf[3]);
 
2701
        datum_coeffs[1] = bGetDouble (&buf[11]);
 
2702
        datum_coeffs[2] = bGetDouble (&buf[19]);
 
2703
        datum_coeffs[3] = bGetDouble (&buf[27]);
 
2704
        datum_coeffs[4] = bGetDouble (&buf[35]);
 
2705
        return FALSE;
 
2706
}
 
2707
 
 
2708
 
 
2709
short rpt_0x8F15 (TSIPPKT *rpt,
 
2710
        short *datum_idx,
 
2711
        double datum_coeffs[5])
 
2712
/*  datum index and coefficients  */
 
2713
{
 
2714
        unsigned char *buf;
 
2715
        buf = rpt->buf;
 
2716
 
 
2717
        if (rpt->len != 43) return TRUE;
 
2718
        *datum_idx = bGetShort(&buf[1]);
 
2719
        datum_coeffs[0] = bGetDouble (&buf[3]);
 
2720
        datum_coeffs[1] = bGetDouble (&buf[11]);
 
2721
        datum_coeffs[2] = bGetDouble (&buf[19]);
 
2722
        datum_coeffs[3] = bGetDouble (&buf[27]);
 
2723
        datum_coeffs[4] = bGetDouble (&buf[35]);
 
2724
        return FALSE;
 
2725
}
 
2726
 
 
2727
 
 
2728
#define MAX_LONG  (2147483648.)   /* 2**31 */
 
2729
 
 
2730
short rpt_0x8F20 (TSIPPKT *rpt,
 
2731
        unsigned char *info,
 
2732
        double *lat,
 
2733
        double *lon,
 
2734
        double *alt,
 
2735
        double vel_enu[],
 
2736
        double *time_of_fix,
 
2737
        short *week_num,
 
2738
        unsigned char *nsvs,
 
2739
        unsigned char sv_prn[],
 
2740
        short sv_IODC[],
 
2741
        short *datum_index)
 
2742
{
 
2743
        short
 
2744
                isv;
 
2745
        unsigned char
 
2746
                *buf, prnx, iode;
 
2747
        unsigned long
 
2748
                ulongtemp;
 
2749
        long
 
2750
                longtemp;
 
2751
        double
 
2752
                vel_scale;
 
2753
 
 
2754
        buf = rpt->buf;
 
2755
 
 
2756
        if (rpt->len != 56) return TRUE;
 
2757
 
 
2758
        vel_scale = (buf[24]&1)? 0.020 : 0.005;
 
2759
        vel_enu[0] = bGetShort (buf+2)*vel_scale;
 
2760
        vel_enu[1] = bGetShort (buf+4)*vel_scale;
 
2761
        vel_enu[2] = bGetShort (buf+6)*vel_scale;
 
2762
 
 
2763
        *time_of_fix = bGetULong (buf+8)*.001;
 
2764
 
 
2765
        longtemp = bGetLong (buf+12);
 
2766
        *lat = longtemp*(GPS_PI/MAX_LONG);
 
2767
 
 
2768
        ulongtemp = bGetULong (buf+16);
 
2769
        *lon = ulongtemp*(GPS_PI/MAX_LONG);
 
2770
        if (*lon > GPS_PI) *lon -= 2.0*GPS_PI;
 
2771
 
 
2772
        *alt = bGetLong (buf+20)*.001;
 
2773
        /* 25 blank; 29 = UTC */
 
2774
        (*datum_index) = (short)((short)buf[26]-1);
 
2775
        *info = buf[27];
 
2776
        *nsvs = buf[28];
 
2777
        *week_num = bGetShort (&buf[30]);
 
2778
        for (isv = 0; isv < 8; isv++) {
 
2779
                prnx = buf[32+2*isv];
 
2780
                sv_prn[isv] = (unsigned char)(prnx&0x3F);
 
2781
      iode = buf[33+2*isv];
 
2782
                sv_IODC[isv] = (short)(iode | ((prnx>>6)<<8));
 
2783
        }
 
2784
        return FALSE;
 
2785
}
 
2786
 
 
2787
short rpt_0x8F41 (TSIPPKT *rpt,
 
2788
        unsigned char *bSearchRange,
 
2789
        unsigned char *bBoardOptions,
 
2790
        unsigned long *iiSerialNumber,
 
2791
        unsigned char *bBuildYear,
 
2792
        unsigned char *bBuildMonth,
 
2793
        unsigned char *bBuildDay,
 
2794
        unsigned char *bBuildHour,
 
2795
        float *fOscOffset,
 
2796
        unsigned short *iTestCodeId)
 
2797
{
 
2798
        if(rpt->len != 17) return FALSE;
 
2799
        *bSearchRange = rpt->buf[1];
 
2800
        *bBoardOptions = rpt->buf[2];
 
2801
        *iiSerialNumber = bGetLong(&rpt->buf[3]);
 
2802
        *bBuildYear = rpt->buf[7];
 
2803
        *bBuildMonth = rpt->buf[8];
 
2804
        *bBuildDay = rpt->buf[9];
 
2805
        *bBuildHour =   rpt->buf[10];
 
2806
        *fOscOffset = bGetSingle(&rpt->buf[11]);
 
2807
        *iTestCodeId = bGetShort(&rpt->buf[15]);
 
2808
/*      Tsipx8E41Data = *Tsipx8E41; */
 
2809
        return TRUE;
 
2810
}
 
2811
 
 
2812
short rpt_0x8F42 (TSIPPKT *rpt,
 
2813
        unsigned char *bProdOptionsPre,
 
2814
        unsigned char *bProdNumberExt,
 
2815
        unsigned short *iCaseSerialNumberPre,
 
2816
        unsigned long *iiCaseSerialNumber,
 
2817
        unsigned long *iiProdNumber,
 
2818
        unsigned short *iPremiumOptions,
 
2819
        unsigned short *iMachineID,
 
2820
        unsigned short *iKey)
 
2821
{
 
2822
        if(rpt->len != 19) return FALSE;
 
2823
        *bProdOptionsPre = rpt->buf[1];
 
2824
        *bProdNumberExt = rpt->buf[2];
 
2825
        *iCaseSerialNumberPre = bGetShort(&rpt->buf[3]);
 
2826
        *iiCaseSerialNumber = bGetLong(&rpt->buf[5]);
 
2827
        *iiProdNumber = bGetLong(&rpt->buf[9]);
 
2828
        *iPremiumOptions = bGetShort(&rpt->buf[13]);
 
2829
        *iMachineID = bGetShort(&rpt->buf[15]);
 
2830
        *iKey = bGetShort(&rpt->buf[17]);
 
2831
        return TRUE;
 
2832
}
 
2833
 
 
2834
short rpt_0x8F45(TSIPPKT *rpt,
 
2835
   unsigned char *bSegMask)
 
2836
{
 
2837
        if(rpt->len != 2) return FALSE;
 
2838
        *bSegMask = rpt->buf[1];
 
2839
        return TRUE;
 
2840
}
 
2841
 
 
2842
short rpt_0x8F4A_16(TSIPPKT *rpt,
 
2843
        unsigned char *pps_enabled,
 
2844
   unsigned char *pps_timebase,
 
2845
   unsigned char *pos_polarity,
 
2846
   double *pps_offset,
 
2847
   float *bias_unc_threshold)
 
2848
/* Stinger PPS definition */
 
2849
{
 
2850
        unsigned char
 
2851
        *buf;
 
2852
 
 
2853
   buf = rpt->buf;
 
2854
   if (rpt->len != 16) return TRUE;
 
2855
   *pps_enabled = buf[1];
 
2856
   *pps_timebase = buf[2];
 
2857
   *pos_polarity = buf[3];
 
2858
   *pps_offset = bGetDouble(&buf[4]);
 
2859
   *bias_unc_threshold = bGetSingle(&buf[12]);
 
2860
        return FALSE;
 
2861
}
 
2862
 
 
2863
short rpt_0x8F4B(TSIPPKT *rpt,
 
2864
                 unsigned long *decorr_max)
 
2865
{
 
2866
        unsigned char
 
2867
        *buf;
 
2868
 
 
2869
   buf = rpt->buf;
 
2870
   if (rpt->len != 5) return TRUE;
 
2871
   *decorr_max = bGetLong(&buf[1]);
 
2872
   return FALSE;
 
2873
}
 
2874
 
 
2875
short rpt_0x8F4D(TSIPPKT *rpt,
 
2876
        unsigned long *event_mask)
 
2877
{
 
2878
        unsigned char
 
2879
        *buf;
 
2880
 
 
2881
   buf = rpt->buf;
 
2882
   if (rpt->len != 5) return TRUE;
 
2883
   *event_mask = bGetULong (&buf[1]);
 
2884
   return FALSE;
 
2885
}
 
2886
 
 
2887
short rpt_0x8FA5(TSIPPKT *rpt,
 
2888
        unsigned char *spktmask)
 
2889
{
 
2890
        unsigned char
 
2891
        *buf;
 
2892
 
 
2893
   buf = rpt->buf;
 
2894
   if (rpt->len != 5) return TRUE;
 
2895
   spktmask[0] = buf[1];
 
2896
   spktmask[1] = buf[2];
 
2897
   spktmask[2] = buf[3];
 
2898
   spktmask[3] = buf[4];
 
2899
   return FALSE;
 
2900
}
 
2901
 
 
2902
short rpt_0x8FAD (TSIPPKT *rpt,
 
2903
    unsigned short *COUNT,
 
2904
    double *FracSec,
 
2905
    unsigned char *Hour,
 
2906
    unsigned char *Minute,
 
2907
    unsigned char *Second,
 
2908
    unsigned char *Day,
 
2909
    unsigned char *Month,
 
2910
    unsigned short *Year,
 
2911
    unsigned char *Status,
 
2912
    unsigned char *Flags)
 
2913
{
 
2914
 
 
2915
        if (rpt->len != 22) return TRUE;
 
2916
 
 
2917
    *COUNT = bGetUShort(&rpt->buf[1]);
 
2918
    *FracSec = bGetDouble(&rpt->buf[3]);
 
2919
    *Hour = rpt->buf[11];
 
2920
    *Minute = rpt->buf[12];
 
2921
    *Second = rpt->buf[13];
 
2922
    *Day = rpt->buf[14];
 
2923
    *Month = rpt->buf[15];
 
2924
    *Year = bGetUShort(&rpt->buf[16]);
 
2925
    *Status = rpt->buf[18];
 
2926
    *Flags = rpt->buf[19];
 
2927
    return FALSE;
 
2928
}
 
2929
 
 
2930
 
 
2931
/*
 
2932
 * *************************************************************************
 
2933
 *
 
2934
 * Trimble Navigation, Ltd.
 
2935
 * OEM Products Development Group
 
2936
 * P.O. Box 3642
 
2937
 * 645 North Mary Avenue
 
2938
 * Sunnyvale, California 94088-3642
 
2939
 *
 
2940
 * Corporate Headquarter:
 
2941
 *    Telephone:  (408) 481-8000
 
2942
 *    Fax:        (408) 481-6005
 
2943
 *
 
2944
 * Technical Support Center:
 
2945
 *    Telephone:  (800) 767-4822        (U.S. and Canada)
 
2946
 *                (408) 481-6940    (outside U.S. and Canada)
 
2947
 *    Fax:        (408) 481-6020
 
2948
 *    BBS:        (408) 481-7800
 
2949
 *    e-mail:     trimble_support@trimble.com
 
2950
 *              ftp://ftp.trimble.com/pub/sct/embedded/bin
 
2951
 *
 
2952
 * *************************************************************************
 
2953
 *
 
2954
 * T_REPORT.C consists of a primary function TranslateTSIPReportToText()
 
2955
 * called by main().
 
2956
 *
 
2957
 * This function takes a character buffer that has been received as a report
 
2958
 * from a TSIP device and interprets it.  The character buffer has been
 
2959
 * assembled using tsip_input_proc() in T_PARSER.C.
 
2960
 *
 
2961
 * A large case statement directs processing to one of many mid-level
 
2962
 * functions.  The mid-level functions specific to the current report
 
2963
 * code passes the report buffer to the appropriate report decoder
 
2964
 * rpt_0x?? () in T_PARSER.C, which converts the byte stream in rpt.buf
 
2965
 * to data values approporaite for use.
 
2966
 *
 
2967
 * *************************************************************************
 
2968
 *
 
2969
 */
 
2970
 
 
2971
 
 
2972
#define GOOD_PARSE 0
 
2973
#define BADID_PARSE 1
 
2974
#define BADLEN_PARSE 2
 
2975
#define BADDATA_PARSE 3
 
2976
 
 
2977
#define B_TSIP  0x02
 
2978
#define B_NMEA  0x04
 
2979
 
 
2980
 
 
2981
/* pbuf is the pointer to the current location of the text output */
 
2982
static char
 
2983
        *pbuf;
 
2984
 
 
2985
/* keep track of whether the message has been successfully parsed */
 
2986
static short
 
2987
        parsed;
 
2988
 
 
2989
 
 
2990
/* convert time of week into day-hour-minute-second and print */
 
2991
char* show_time (float time_of_week)
 
2992
{
 
2993
        short   days, hours, minutes;
 
2994
        float seconds;
 
2995
        double tow = 0;
 
2996
   static char timestring [80];
 
2997
 
 
2998
        if (time_of_week == -1.0)
 
2999
   {
 
3000
                sprintf(timestring, "   <No time yet>   ");
 
3001
        }
 
3002
        else if ((time_of_week >= 604800.0) || (time_of_week < 0.0))
 
3003
   {
 
3004
                sprintf(timestring, "     <Bad time>     ");
 
3005
        }
 
3006
   else
 
3007
   {
 
3008
                if (time_of_week < 604799.9) 
 
3009
                        tow = time_of_week + .00000001;
 
3010
                seconds = (float)fmod(tow, 60.);
 
3011
                minutes =  (short) fmod(tow/60., 60.);
 
3012
                hours = (short)fmod(tow / 3600., 24.);
 
3013
                days = (short)(tow / 86400.0);
 
3014
                sprintf(timestring, " %s %02d:%02d:%05.2f   ",
 
3015
                dayname[days], hours, minutes, seconds);
 
3016
   }
 
3017
   return timestring;
 
3018
}
 
3019
 
 
3020
/**/
 
3021
/* 0x3D */
 
3022
static void rpt_chan_A_config (TSIPPKT *rpt)
 
3023
{
 
3024
        unsigned char
 
3025
                tx_baud_index, rx_baud_index,
 
3026
                char_format_index, stop_bits,
 
3027
      tx_mode_index, rx_mode_index,
 
3028
      databits, parity;
 
3029
        int
 
3030
                i, nbaud;
 
3031
 
 
3032
        /* unload rptbuf */
 
3033
        if (rpt_0x3D (rpt,
 
3034
                &tx_baud_index, &rx_baud_index, &char_format_index,
 
3035
                &stop_bits, &tx_mode_index, &rx_mode_index)) {
 
3036
                parsed = BADLEN_PARSE;
 
3037
                return;
 
3038
        }
 
3039
 
 
3040
        pbuf += sprintf(pbuf, "\nChannel A Configuration");
 
3041
 
 
3042
   nbaud = sizeof(old_baudnum);
 
3043
 
 
3044
        for (i = 0; i < nbaud; ++i) if (tx_baud_index == old_baudnum[i]) break;
 
3045
        pbuf += sprintf(pbuf, "\n   Transmit speed: %s at %s",
 
3046
                old_output_ch[tx_mode_index], st_baud_text_app[i]);
 
3047
 
 
3048
        for (i = 0; i < nbaud; ++i) if (rx_baud_index == old_baudnum[i]) break;
 
3049
        pbuf += sprintf(pbuf, "\n   Receive speed: %s at %s",
 
3050
                old_input_ch[rx_mode_index], st_baud_text_app[i]);
 
3051
 
 
3052
        databits = (unsigned char)((char_format_index & 0x03) + 5);
 
3053
 
 
3054
        parity = (unsigned char)(char_format_index >> 2);
 
3055
        if (parity > 4) parity = 2;
 
3056
 
 
3057
        pbuf += sprintf(pbuf, "\n   Character format (bits/char, parity, stop bits): %d-%s-%d",
 
3058
                databits, old_parity_text[parity], stop_bits);
 
3059
}
 
3060
 
 
3061
/**/
 
3062
/* 0x40 */
 
3063
static void rpt_almanac_data_page (TSIPPKT *rpt)
 
3064
{
 
3065
        unsigned char
 
3066
                sv_prn;
 
3067
        short
 
3068
                week_num;
 
3069
        float
 
3070
                t_zc,
 
3071
                eccentricity,
 
3072
                t_oa,
 
3073
                i_0,
 
3074
                OMEGA_dot,
 
3075
                sqrt_A,
 
3076
                OMEGA_0,
 
3077
                omega,
 
3078
                M_0;
 
3079
 
 
3080
        /* unload rptbuf */
 
3081
        if (rpt_0x40 (rpt,
 
3082
                &sv_prn, &week_num, &t_zc, &eccentricity, &t_oa,
 
3083
                &i_0, &OMEGA_dot, &sqrt_A, &OMEGA_0, &omega, &M_0)) {
 
3084
                parsed = BADLEN_PARSE;
 
3085
                return;
 
3086
        }
 
3087
 
 
3088
        pbuf += sprintf(pbuf, "\nAlmanac for SV %02d", sv_prn);
 
3089
        pbuf += sprintf(pbuf, "\n       Captured:%15.0f %s",
 
3090
        t_zc, show_time (t_zc));
 
3091
        pbuf += sprintf(pbuf, "\n           week:%15d", week_num);
 
3092
        pbuf += sprintf(pbuf, "\n   Eccentricity:%15g", eccentricity);
 
3093
        pbuf += sprintf(pbuf, "\n           T_oa:%15.0f %s",
 
3094
        t_oa, show_time (t_oa));
 
3095
        pbuf += sprintf(pbuf, "\n            i 0:%15g", i_0);
 
3096
        pbuf += sprintf(pbuf, "\n      OMEGA dot:%15g", OMEGA_dot);
 
3097
        pbuf += sprintf(pbuf, "\n         sqrt A:%15g", sqrt_A);
 
3098
        pbuf += sprintf(pbuf, "\n        OMEGA 0:%15g", OMEGA_0);
 
3099
        pbuf += sprintf(pbuf, "\n          omega:%15g", omega);
 
3100
        pbuf += sprintf(pbuf, "\n            M 0:%15g", M_0);
 
3101
}
 
3102
 
 
3103
/* 0x41 */
 
3104
static void rpt_GPS_time (TSIPPKT *rpt)
 
3105
{
 
3106
        float
 
3107
                time_of_week, UTC_offset;
 
3108
        short
 
3109
                week_num;
 
3110
 
 
3111
        /* unload rptbuf */
 
3112
        if (rpt_0x41 (rpt, &time_of_week, &UTC_offset, &week_num)) {
 
3113
                parsed = BADLEN_PARSE;
 
3114
                return;
 
3115
        }
 
3116
 
 
3117
        pbuf += sprintf(pbuf, "\nGPS time:%s GPS week: %d   UTC offset %.1f",
 
3118
        show_time(time_of_week), week_num, UTC_offset);
 
3119
 
 
3120
}
 
3121
 
 
3122
/* 0x42 */
 
3123
static void rpt_single_ECEF_position (TSIPPKT *rpt)
 
3124
{
 
3125
        float
 
3126
                ECEF_pos[3], time_of_fix;
 
3127
 
 
3128
        /* unload rptbuf */
 
3129
        if (rpt_0x42 (rpt, ECEF_pos, &time_of_fix)) {
 
3130
                parsed = BADLEN_PARSE;
 
3131
                return;
 
3132
        }
 
3133
 
 
3134
        pbuf += sprintf(pbuf, "\nSXYZ:  %15.0f  %15.0f  %15.0f    %s",
 
3135
                ECEF_pos[0], ECEF_pos[1], ECEF_pos[2],
 
3136
      show_time(time_of_fix));
 
3137
}
 
3138
 
 
3139
/* 0x43 */
 
3140
static void rpt_single_ECEF_velocity (TSIPPKT *rpt)
 
3141
{
 
3142
 
 
3143
        float
 
3144
                ECEF_vel[3], freq_offset, time_of_fix;
 
3145
 
 
3146
        /* unload rptbuf */
 
3147
        if (rpt_0x43 (rpt, ECEF_vel, &freq_offset, &time_of_fix)) {
 
3148
                parsed = BADLEN_PARSE;
 
3149
                return;
 
3150
        }
 
3151
 
 
3152
        pbuf += sprintf(pbuf, "\nVelECEF: %11.3f  %11.3f  %11.3f  %12.3f%s",
 
3153
                ECEF_vel[0], ECEF_vel[1], ECEF_vel[2], freq_offset,
 
3154
      show_time(time_of_fix));
 
3155
}
 
3156
 
 
3157
/*  0x45  */
 
3158
static void rpt_SW_version (TSIPPKT *rpt) {
 
3159
        unsigned char
 
3160
                major_nav_version, minor_nav_version,
 
3161
                nav_day, nav_month, nav_year,
 
3162
                major_dsp_version, minor_dsp_version,
 
3163
                dsp_day, dsp_month, dsp_year;
 
3164
 
 
3165
        /* unload rptbuf */
 
3166
        if (rpt_0x45 (rpt,
 
3167
                &major_nav_version, &minor_nav_version,
 
3168
                &nav_day, &nav_month, &nav_year,
 
3169
                &major_dsp_version, &minor_dsp_version,
 
3170
                &dsp_day, &dsp_month, &dsp_year)) {
 
3171
                parsed = BADLEN_PARSE;
 
3172
                return;
 
3173
        }
 
3174
 
 
3175
        pbuf += sprintf(pbuf,
 
3176
"\nFW Versions:  Nav Proc %2d.%02d  %2d/%2d/%2d  Sig Proc %2d.%02d  %2d/%2d/%2d",
 
3177
                major_nav_version, minor_nav_version, nav_day, nav_month, nav_year,
 
3178
                major_dsp_version, minor_dsp_version, dsp_day, dsp_month, dsp_year);
 
3179
}
 
3180
 
 
3181
/* 0x46 */
 
3182
static void rpt_rcvr_health (TSIPPKT *rpt)
 
3183
{
 
3184
        unsigned char
 
3185
                status1, status2;
 
3186
        static char
 
3187
                *sc_text[] = {
 
3188
                        "Doing position fixes",
 
3189
                        "Don't have GPS time yet",
 
3190
                        "Waiting for almanac collection",
 
3191
                        "DOP too high          ",
 
3192
                        "No satellites available",
 
3193
                        "Only 1 satellite available",
 
3194
                        "Only 2 satellites available",
 
3195
                        "Only 3 satellites available",
 
3196
                        "No satellites usable   ",
 
3197
                        "Only 1 satellite usable",
 
3198
                        "Only 2 satellites usable",
 
3199
                        "Only 3 satellites usable",
 
3200
                        "Chosen satellite unusable"};
 
3201
 
 
3202
 
 
3203
        /* unload rptbuf */
 
3204
        if (rpt_0x46 (rpt, &status1, &status2))
 
3205
        {
 
3206
                parsed = BADLEN_PARSE;
 
3207
                return;
 
3208
        }
 
3209
 
 
3210
        pbuf += sprintf(pbuf, "\nRcvr status1: %s (%02Xh); ",
 
3211
        sc_text[rpt->buf[0]], status1);
 
3212
 
 
3213
        pbuf += sprintf(pbuf, "status2: %s, %s (%02Xh)",
 
3214
                (status2 & 0x01)?"No BBRAM":"BBRAM OK",
 
3215
                (status2 & 0x10)?"No Ant":"Ant OK",
 
3216
      status2);
 
3217
}
 
3218
 
 
3219
/* 0x47 */
 
3220
static void rpt_SNR_all_SVs (TSIPPKT *rpt)
 
3221
{
 
3222
        unsigned char
 
3223
                nsvs, sv_prn[12];
 
3224
        short
 
3225
                isv;
 
3226
        float
 
3227
                snr[12];
 
3228
 
 
3229
        /* unload rptbuf */
 
3230
        if (rpt_0x47 (rpt, &nsvs, sv_prn, snr))
 
3231
   {
 
3232
                parsed = BADLEN_PARSE;
 
3233
                return;
 
3234
        }
 
3235
 
 
3236
        pbuf += sprintf(pbuf, "\nSNR for satellites: %d", nsvs);
 
3237
        for (isv = 0; isv < nsvs; isv++)
 
3238
   {
 
3239
                pbuf += sprintf(pbuf, "\n    SV %02d   %6.2f",
 
3240
        sv_prn[isv], snr[isv]);
 
3241
        }
 
3242
}
 
3243
 
 
3244
/* 0x48 */
 
3245
static void rpt_GPS_system_message (TSIPPKT *rpt)
 
3246
{
 
3247
        unsigned char
 
3248
                message[23];
 
3249
 
 
3250
        /* unload rptbuf */
 
3251
        if (rpt_0x48 (rpt, message))
 
3252
   {
 
3253
                parsed = BADLEN_PARSE;
 
3254
                return;
 
3255
        }
 
3256
 
 
3257
        pbuf += sprintf(pbuf, "\nGPS message: %s", message);
 
3258
}
 
3259
 
 
3260
/* 0x49 */
 
3261
static void rpt_almanac_health_page (TSIPPKT *rpt)
 
3262
{
 
3263
        short
 
3264
                iprn;
 
3265
        unsigned char
 
3266
                sv_health [32];
 
3267
 
 
3268
        /* unload rptbuf */
 
3269
        if (rpt_0x49 (rpt, sv_health))
 
3270
   {
 
3271
                parsed = BADLEN_PARSE;
 
3272
                return;
 
3273
        }
 
3274
 
 
3275
        pbuf += sprintf(pbuf, "\nAlmanac health page:");
 
3276
        for (iprn = 0; iprn < 32; iprn++)
 
3277
   {
 
3278
                if (!(iprn%5)) *pbuf++ = '\n';
 
3279
                pbuf += sprintf(pbuf, "    SV%02d  %2X",
 
3280
        (iprn+1) , sv_health[iprn]);
 
3281
        }
 
3282
}
 
3283
 
 
3284
/* 0x4A */
 
3285
static void rpt_single_lla_position (TSIPPKT *rpt) {
 
3286
        short
 
3287
                lat_deg, lon_deg;
 
3288
        float
 
3289
                lat, lon,
 
3290
                alt, clock_bias, time_of_fix;
 
3291
        double lat_min, lon_min;
 
3292
        unsigned char
 
3293
                north_south, east_west;
 
3294
 
 
3295
        if (rpt_0x4A (rpt,
 
3296
                &lat, &lon, &alt, &clock_bias, &time_of_fix))
 
3297
   {
 
3298
                parsed = BADLEN_PARSE;
 
3299
                return;
 
3300
        }
 
3301
 
 
3302
        /* convert from radians to degrees */
 
3303
        lat *= (float)R2D;
 
3304
        north_south = 'N';
 
3305
        if (lat < 0.0)
 
3306
   {
 
3307
                north_south = 'S';
 
3308
                lat = -lat;
 
3309
        }
 
3310
        lat_deg = (short)lat;
 
3311
        lat_min = (lat - lat_deg) * 60.0;
 
3312
 
 
3313
        lon *= (float)R2D;
 
3314
        east_west = 'E';
 
3315
        if (lon < 0.0)
 
3316
   {
 
3317
                east_west = 'W';
 
3318
                lon = -lon;
 
3319
        }
 
3320
        lon_deg = (short)lon;
 
3321
        lon_min = (lon - lon_deg) * 60.0;
 
3322
 
 
3323
        pbuf += sprintf(pbuf, "\nSLLA: %4d: %06.3f  %c%5d:%06.3f  %c%10.2f  %12.2f%s",
 
3324
                lat_deg, lat_min, north_south,
 
3325
                lon_deg, lon_min, east_west,
 
3326
                alt, clock_bias,
 
3327
                show_time(time_of_fix));
 
3328
}
 
3329
 
 
3330
/* 0x4A */
 
3331
static void rpt_ref_alt (TSIPPKT *rpt) {
 
3332
 
 
3333
        float
 
3334
                alt, dummy;
 
3335
        unsigned char
 
3336
                alt_flag;
 
3337
 
 
3338
        if (rpt_0x4A_2 (rpt,
 
3339
                &alt, &dummy, &alt_flag))
 
3340
   {
 
3341
                parsed = BADLEN_PARSE;
 
3342
                return;
 
3343
        }
 
3344
 
 
3345
        pbuf += sprintf(pbuf, "\nReference Alt:   %.1f m;    %s",
 
3346
        alt, alt_flag?"ON":"OFF");
 
3347
}
 
3348
 
 
3349
/* 0x4B */
 
3350
static void rpt_rcvr_id_and_status (TSIPPKT *rpt)
 
3351
{
 
3352
 
 
3353
        unsigned char
 
3354
                machine_id, status3, status4;
 
3355
 
 
3356
        /* unload rptbuf */
 
3357
        if (rpt_0x4B (rpt, &machine_id, &status3, &status4))
 
3358
   {
 
3359
                parsed = BADLEN_PARSE;
 
3360
                return;
 
3361
        }
 
3362
 
 
3363
        pbuf += sprintf(pbuf, "\nRcvr Machine ID: %d; Status3 = %s, %s (%02Xh)",
 
3364
        machine_id,
 
3365
                (status3 & 0x02)?"No RTC":"RTC OK",
 
3366
                (status3 & 0x08)?"No Alm":"Alm OK",
 
3367
                status3);
 
3368
}
 
3369
 
 
3370
/* 0x4C */
 
3371
static void rpt_operating_parameters (TSIPPKT *rpt)
 
3372
{
 
3373
        unsigned char
 
3374
                dyn_code;
 
3375
        float
 
3376
                el_mask, snr_mask, dop_mask, dop_switch;
 
3377
 
 
3378
        /* unload rptbuf */
 
3379
        if (rpt_0x4C (rpt, &dyn_code, &el_mask,
 
3380
                &snr_mask, &dop_mask, &dop_switch))
 
3381
   {
 
3382
                parsed = BADLEN_PARSE;
 
3383
                return;
 
3384
        }
 
3385
 
 
3386
        pbuf += sprintf(pbuf, "\nOperating Parameters:");
 
3387
        pbuf += sprintf(pbuf, "\n     Dynamics code = %d %s",
 
3388
        dyn_code, dyn_text[dyn_code]);
 
3389
        pbuf += sprintf(pbuf, "\n     Elevation mask = %.2f�", el_mask * R2D);
 
3390
        pbuf += sprintf(pbuf, "\n     SNR mask = %.2f", snr_mask);
 
3391
        pbuf += sprintf(pbuf, "\n     DOP mask = %.2f", dop_mask);
 
3392
        pbuf += sprintf(pbuf, "\n     DOP switch = %.2f", dop_switch);
 
3393
}
 
3394
 
 
3395
/* 0x4D */
 
3396
static void rpt_oscillator_offset (TSIPPKT *rpt)
 
3397
{
 
3398
        float
 
3399
                osc_offset;
 
3400
 
 
3401
        /* unload rptbuf */
 
3402
        if (rpt_0x4D (rpt, &osc_offset))
 
3403
   {
 
3404
                parsed = BADLEN_PARSE;
 
3405
                return;
 
3406
        }
 
3407
 
 
3408
        pbuf += sprintf(pbuf, "\nOscillator offset: %.2f Hz = %.3f PPM",
 
3409
        osc_offset, osc_offset/1575.42);
 
3410
}
 
3411
 
 
3412
/* 0x4E */
 
3413
static void rpt_GPS_time_set_response (TSIPPKT *rpt)
 
3414
{
 
3415
 
 
3416
        unsigned char
 
3417
                response;
 
3418
 
 
3419
        /* unload rptbuf */
 
3420
        if (rpt_0x4E (rpt, &response))
 
3421
   {
 
3422
                parsed = BADLEN_PARSE;
 
3423
                return;
 
3424
        }
 
3425
 
 
3426
        switch (response)
 
3427
   {
 
3428
        case 'Y':
 
3429
                pbuf += sprintf(pbuf, "\nTime set accepted");
 
3430
                break;
 
3431
 
 
3432
        case 'N':
 
3433
                pbuf += sprintf(pbuf, "\nTime set rejected or not required");
 
3434
                break;
 
3435
 
 
3436
        default:
 
3437
                parsed = BADDATA_PARSE;
 
3438
        }
 
3439
}
 
3440
 
 
3441
/* 0x4F */
 
3442
static void rpt_UTC_offset (TSIPPKT *rpt)
 
3443
{
 
3444
        double
 
3445
                a0;
 
3446
        float
 
3447
                a1, time_of_data;
 
3448
        short
 
3449
                dt_ls, wn_t, wn_lsf, dn, dt_lsf;
 
3450
 
 
3451
        /* unload rptbuf */
 
3452
        if (rpt_0x4F (rpt, &a0, &a1, &time_of_data,
 
3453
                &dt_ls, &wn_t, &wn_lsf, &dn, &dt_lsf)) {
 
3454
                parsed = BADLEN_PARSE;
 
3455
                return;
 
3456
        }
 
3457
 
 
3458
        pbuf += sprintf(pbuf, "\nUTC Correction Data");
 
3459
        pbuf += sprintf(pbuf, "\n   A_0         = %g  ", a0);
 
3460
        pbuf += sprintf(pbuf, "\n   A_1         = %g  ", a1);
 
3461
        pbuf += sprintf(pbuf, "\n   delta_t_LS  = %d  ", dt_ls);
 
3462
        pbuf += sprintf(pbuf, "\n   t_ot        = %.0f  ", time_of_data);
 
3463
        pbuf += sprintf(pbuf, "\n   WN_t        = %d  ", wn_t );
 
3464
        pbuf += sprintf(pbuf, "\n   WN_LSF      = %d  ", wn_lsf );
 
3465
        pbuf += sprintf(pbuf, "\n   DN          = %d  ", dn );
 
3466
        pbuf += sprintf(pbuf, "\n   delta_t_LSF = %d  ", dt_lsf );
 
3467
}
 
3468
 
 
3469
/**/
 
3470
/* 0x54 */
 
3471
static void rpt_1SV_bias (TSIPPKT *rpt)
 
3472
{
 
3473
        float
 
3474
                clock_bias, freq_offset, time_of_fix;
 
3475
 
 
3476
        /* unload rptbuf */
 
3477
        if (rpt_0x54 (rpt, &clock_bias, &freq_offset, &time_of_fix)) {
 
3478
                parsed = BADLEN_PARSE;
 
3479
                return;
 
3480
        }
 
3481
 
 
3482
        pbuf += sprintf (pbuf, "\nTime Fix   Clock Bias: %6.2f m  Freq Bias: %6.2f m/s%s",
 
3483
                clock_bias, freq_offset, show_time (time_of_fix));
 
3484
}
 
3485
 
 
3486
/* 0x55 */
 
3487
static void rpt_io_opt (TSIPPKT *rpt)
 
3488
{
 
3489
        unsigned char
 
3490
                pos_code, vel_code, time_code, aux_code;
 
3491
 
 
3492
        /* unload rptbuf */
 
3493
        if (rpt_0x55 (rpt,
 
3494
                &pos_code, &vel_code, &time_code, &aux_code)) {
 
3495
                parsed = BADLEN_PARSE;
 
3496
                return;
 
3497
        }
 
3498
        /* rptbuf unloaded */
 
3499
 
 
3500
        pbuf += sprintf(pbuf, "\nI/O Options: %2X %2X %2X %2X",
 
3501
                pos_code, vel_code, time_code, aux_code);
 
3502
 
 
3503
        if (pos_code & 0x01) {
 
3504
                pbuf += sprintf(pbuf, "\n    ECEF XYZ position output");
 
3505
        }
 
3506
 
 
3507
        if (pos_code & 0x02) {
 
3508
                pbuf += sprintf(pbuf, "\n    LLA position output");
 
3509
        }
 
3510
 
 
3511
        pbuf += sprintf(pbuf, (pos_code & 0x04)?
 
3512
                "\n    MSL altitude output (Geoid height) ":
 
3513
                "\n    WGS-84 altitude output");
 
3514
 
 
3515
        pbuf += sprintf(pbuf, (pos_code & 0x08)?
 
3516
                "\n    MSL altitude input":
 
3517
      "\n    WGS-84 altitude input");
 
3518
 
 
3519
        pbuf += sprintf(pbuf, (pos_code & 0x10)?
 
3520
                "\n    Double precision":
 
3521
      "\n    Single precision");
 
3522
 
 
3523
        if (pos_code & 0x20) {
 
3524
                pbuf += sprintf(pbuf, "\n    All Enabled Superpackets");
 
3525
        }
 
3526
 
 
3527
        if (vel_code & 0x01) {
 
3528
                pbuf += sprintf(pbuf, "\n    ECEF XYZ velocity output");
 
3529
        }
 
3530
 
 
3531
        if (vel_code & 0x02) {
 
3532
                pbuf += sprintf(pbuf, "\n    ENU velocity output");
 
3533
        }
 
3534
 
 
3535
        pbuf += sprintf(pbuf, (time_code & 0x01)?
 
3536
                  "\n    Time tags in UTC":
 
3537
        "\n    Time tags in GPS time");
 
3538
 
 
3539
        if (time_code & 0x02) {
 
3540
                pbuf += sprintf(pbuf, "\n    Fixes delayed to integer seconds");
 
3541
        }
 
3542
 
 
3543
        if (time_code & 0x04) {
 
3544
                pbuf += sprintf(pbuf, "\n    Fixes sent only on request");
 
3545
        }
 
3546
 
 
3547
        if (time_code & 0x08) {
 
3548
                pbuf += sprintf(pbuf, "\n    Synchronized measurements");
 
3549
        }
 
3550
 
 
3551
        if (time_code & 0x10) {
 
3552
                pbuf += sprintf(pbuf, "\n    Minimize measurement propagation");
 
3553
        }
 
3554
 
 
3555
   pbuf += sprintf(pbuf, (time_code & 0x20) ?
 
3556
                "\n    PPS output at all times" :
 
3557
        "\n    PPS output during fixes");
 
3558
 
 
3559
        if (aux_code & 0x01) {
 
3560
                pbuf += sprintf(pbuf, "\n    Raw measurement output");
 
3561
        }
 
3562
 
 
3563
        if (aux_code & 0x02) {
 
3564
                pbuf += sprintf(pbuf, "\n    Code-phase smoothed before output");
 
3565
        }
 
3566
 
 
3567
        if (aux_code & 0x04) {
 
3568
                pbuf += sprintf(pbuf, "\n    Additional fix status");
 
3569
        }
 
3570
 
 
3571
        pbuf += sprintf(pbuf, (aux_code & 0x08)?
 
3572
        "\n    Signal Strength Output as dBHz" :
 
3573
        "\n    Signal Strength Output as AMU");
 
3574
}
 
3575
 
 
3576
/* 0x56 */
 
3577
static void rpt_ENU_velocity (TSIPPKT *rpt)
 
3578
{
 
3579
        float
 
3580
                vel_ENU[3], freq_offset, time_of_fix;
 
3581
 
 
3582
        /* unload rptbuf */
 
3583
        if (rpt_0x56 (rpt, vel_ENU, &freq_offset, &time_of_fix)) {
 
3584
                parsed = BADLEN_PARSE;
 
3585
                return;
 
3586
        }
 
3587
 
 
3588
        pbuf += sprintf(pbuf, "\nVel ENU: %11.3f  %11.3f  %11.3f  %12.3f%s",
 
3589
                vel_ENU[0], vel_ENU[1], vel_ENU[2], freq_offset,
 
3590
      show_time (time_of_fix));
 
3591
}
 
3592
 
 
3593
/* 0x57 */
 
3594
static void rpt_last_fix_info (TSIPPKT *rpt)
 
3595
{
 
3596
        unsigned char
 
3597
                source_code, diag_code;
 
3598
        short
 
3599
                week_num;
 
3600
        float
 
3601
                time_of_fix;
 
3602
 
 
3603
        /* unload rptbuf */
 
3604
        if (rpt_0x57 (rpt, &source_code, &diag_code, &week_num, &time_of_fix)) {
 
3605
                parsed = BADLEN_PARSE;
 
3606
                return;
 
3607
        }
 
3608
 
 
3609
        pbuf += sprintf(pbuf, "\n source code %d;   diag code: %2Xh",
 
3610
        source_code, diag_code);
 
3611
        pbuf += sprintf(pbuf, "\n    Time of last fix:%s", show_time(time_of_fix));
 
3612
        pbuf += sprintf(pbuf, "\n    Week of last fix: %d", week_num);
 
3613
}
 
3614
 
 
3615
/* 0x58 */
 
3616
static void rpt_GPS_system_data (TSIPPKT *rpt)
 
3617
{
 
3618
        unsigned char
 
3619
        iprn,
 
3620
                op_code, data_type, sv_prn,
 
3621
                data_length, data_packet[250];
 
3622
        ALM_INFO
 
3623
                *almanac;
 
3624
        ALH_PARMS
 
3625
                *almh;
 
3626
        UTC_INFO
 
3627
                *utc;
 
3628
        ION_INFO
 
3629
                *ionosphere;
 
3630
        EPHEM_CLOCK
 
3631
                *cdata;
 
3632
        EPHEM_ORBIT
 
3633
                *edata;
 
3634
        NAV_INFO
 
3635
                *nav_data;
 
3636
        unsigned char
 
3637
                curr_t_oa;
 
3638
        unsigned short
 
3639
                curr_wn_oa;
 
3640
        static char
 
3641
                *datname[] =
 
3642
                {"", "", "Almanac Orbit",
 
3643
                "Health Page & Ref Time", "Ionosphere", "UTC ",
 
3644
                "Ephemeris"};
 
3645
 
 
3646
        /* unload rptbuf */
 
3647
        if (rpt_0x58 (rpt, &op_code, &data_type, &sv_prn,
 
3648
                &data_length, data_packet))
 
3649
   {
 
3650
                parsed = BADLEN_PARSE;
 
3651
                return;
 
3652
        }
 
3653
 
 
3654
        pbuf += sprintf(pbuf, "\nSystem data [%d]:  %s  SV%02d",
 
3655
                data_type, datname[data_type], sv_prn);
 
3656
        switch (op_code)
 
3657
        {
 
3658
        case 1:
 
3659
                pbuf += sprintf(pbuf, "  Acknowledgment");
 
3660
                break;
 
3661
        case 2:
 
3662
                pbuf += sprintf(pbuf, "  length = %d bytes", data_length);
 
3663
                switch (data_type) {
 
3664
                case 2:
 
3665
                        /* Almanac */
 
3666
                        if (sv_prn == 0 || sv_prn > 32) {
 
3667
                                pbuf += sprintf(pbuf, "  Binary PRN invalid");
 
3668
                                return;
 
3669
                        }
 
3670
                        almanac = (ALM_INFO*)data_packet;
 
3671
                        pbuf += sprintf(pbuf, "\n   t_oa_raw = % -12d    SV_hlth  = % -12d  ",
 
3672
                almanac->t_oa_raw , almanac->SV_health );
 
3673
                        pbuf += sprintf(pbuf, "\n   e        = % -12g    t_oa     = % -12g  ",
 
3674
                almanac->e        , almanac->t_oa     );
 
3675
                        pbuf += sprintf(pbuf, "\n   i_0      = % -12g    OMEGADOT = % -12g  ",
 
3676
                almanac->i_0      , almanac->OMEGADOT );
 
3677
                        pbuf += sprintf(pbuf, "\n   sqrt_A   = % -12g    OMEGA_0  = % -12g  ",
 
3678
                almanac->sqrt_A   , almanac->OMEGA_0  );
 
3679
                        pbuf += sprintf(pbuf, "\n   omega    = % -12g    M_0      = % -12g  ",
 
3680
                almanac->omega    , almanac->M_0      );
 
3681
                        pbuf += sprintf(pbuf, "\n   a_f0     = % -12g    a_f1     = % -12g  ",
 
3682
                almanac->a_f0     , almanac->a_f1     );
 
3683
                        pbuf += sprintf(pbuf, "\n   Axis     = % -12g    n        = % -12g  ",
 
3684
                almanac->Axis     , almanac->n        );
 
3685
                        pbuf += sprintf(pbuf, "\n   OMEGA_n  = % -12g    ODOT_n   = % -12g  ",
 
3686
                almanac->OMEGA_n  , almanac->ODOT_n   );
 
3687
                        pbuf += sprintf(pbuf, "\n   t_zc     = % -12g    weeknum  = % -12d  ",
 
3688
                almanac->t_zc     , almanac->weeknum  );
 
3689
                        pbuf += sprintf(pbuf, "\n   wn_oa    = % -12d", almanac->wn_oa    );
 
3690
                        break;
 
3691
 
 
3692
                case 3:
 
3693
                        /* Almanac health page */
 
3694
                        almh = (ALH_PARMS*)data_packet;
 
3695
                        pbuf += sprintf(pbuf, "\n   t_oa = %d, wn_oa&0xFF = %d  ",
 
3696
                almh->t_oa, almh->WN_a);
 
3697
                        pbuf += sprintf(pbuf, "\nAlmanac health page:");
 
3698
                        for (iprn = 0; iprn < 32; iprn++) {
 
3699
                                if (!(iprn%5)) *pbuf++ = '\n';
 
3700
                                pbuf += sprintf(pbuf, "    SV%02d  %2X",
 
3701
                (iprn+1) , almh->SV_health[iprn]);
 
3702
                        }
 
3703
                        curr_t_oa = data_packet[34];
 
3704
                        curr_wn_oa = (unsigned short)((data_packet[35]<<8) + data_packet[36]);
 
3705
                        pbuf += sprintf(pbuf, "\n   current t_oa = %d, wn_oa = %d  ",
 
3706
                curr_t_oa, curr_wn_oa);
 
3707
                        break;
 
3708
 
 
3709
                case 4:
 
3710
                        /* Ionosphere */
 
3711
                        ionosphere = (ION_INFO*)data_packet;
 
3712
                        pbuf += sprintf(pbuf, "\n   alpha_0 = % -12g  alpha_1 = % -12g ",
 
3713
                 ionosphere->alpha_0, ionosphere->alpha_1);
 
3714
                        pbuf += sprintf(pbuf, "\n   alpha_2 = % -12g  alpha_3 = % -12g ",
 
3715
                 ionosphere->alpha_2, ionosphere->alpha_3);
 
3716
                        pbuf += sprintf(pbuf, "\n   beta_0  = % -12g  beta_1  = % -12g  ",
 
3717
                 ionosphere->beta_0, ionosphere->beta_1);
 
3718
                        pbuf += sprintf(pbuf, "\n   beta_2  = % -12g  beta_3  = % -12g  ",
 
3719
                 ionosphere->beta_2, ionosphere->beta_3);
 
3720
                        break;
 
3721
 
 
3722
                case 5:
 
3723
                        /* UTC */
 
3724
                        utc = (UTC_INFO*)data_packet;
 
3725
                        pbuf += sprintf(pbuf, "\n   A_0         = %g  ", utc->A_0);
 
3726
                        pbuf += sprintf(pbuf, "\n   A_1         = %g  ", utc->A_1);
 
3727
                        pbuf += sprintf(pbuf, "\n   delta_t_LS  = %d  ", utc->delta_t_LS);
 
3728
                        pbuf += sprintf(pbuf, "\n   t_ot        = %.0f  ", utc->t_ot );
 
3729
                        pbuf += sprintf(pbuf, "\n   WN_t        = %d  ", utc->WN_t );
 
3730
                        pbuf += sprintf(pbuf, "\n   WN_LSF      = %d  ", utc->WN_LSF );
 
3731
                        pbuf += sprintf(pbuf, "\n   DN          = %d  ", utc->DN );
 
3732
                        pbuf += sprintf(pbuf, "\n   delta_t_LSF = %d  ", utc->delta_t_LSF );
 
3733
                        break;
 
3734
 
 
3735
                case 6: /* Ephemeris */
 
3736
                        if (sv_prn == 0 || sv_prn > 32) {
 
3737
                                pbuf += sprintf(pbuf, "  Binary PRN invalid");
 
3738
                                return;
 
3739
                        }
 
3740
                        nav_data = (NAV_INFO*)data_packet;
 
3741
 
 
3742
                        pbuf += sprintf(pbuf, "\n     SV_PRN = % -12d .  t_ephem = % -12g . ",
 
3743
                nav_data->sv_number , nav_data->t_ephem );
 
3744
                        cdata = &(nav_data->ephclk);
 
3745
                        pbuf += sprintf(pbuf,
 
3746
                "\n    weeknum = % -12d .   codeL2 = % -12d .  L2Pdata = % -12d",
 
3747
                cdata->weeknum , cdata->codeL2 , cdata->L2Pdata );
 
3748
                        pbuf += sprintf(pbuf,
 
3749
                "\n  SVacc_raw = % -12d .SV_health = % -12d .     IODC = % -12d",
 
3750
                cdata->SVacc_raw, cdata->SV_health, cdata->IODC );
 
3751
                        pbuf += sprintf(pbuf,
 
3752
                "\n       T_GD = % -12g .     t_oc = % -12g .     a_f2 = % -12g",
 
3753
                cdata->T_GD, cdata->t_oc, cdata->a_f2 );
 
3754
                        pbuf += sprintf(pbuf,
 
3755
                "\n       a_f1 = % -12g .     a_f0 = % -12g .    SVacc = % -12g",
 
3756
                cdata->a_f1, cdata->a_f0, cdata->SVacc );
 
3757
                        edata = &(nav_data->ephorb);
 
3758
                        pbuf += sprintf(pbuf,
 
3759
                 "\n       IODE = % -12d .fit_intvl = % -12d .     C_rs = % -12g",
 
3760
                 edata->IODE, edata->fit_interval, edata->C_rs );
 
3761
                        pbuf += sprintf(pbuf,
 
3762
                "\n    delta_n = % -12g .      M_0 = % -12g .     C_uc = % -12g",
 
3763
                edata->delta_n, edata->M_0, edata->C_uc );
 
3764
                        pbuf += sprintf(pbuf,
 
3765
                "\n        ecc = % -12g .     C_us = % -12g .   sqrt_A = % -12g",
 
3766
                 edata->e, edata->C_us, edata->sqrt_A );
 
3767
                        pbuf += sprintf(pbuf,
 
3768
                "\n       t_oe = % -12g .     C_ic = % -12g .  OMEGA_0 = % -12g",
 
3769
            edata->t_oe, edata->C_ic, edata->OMEGA_0 );
 
3770
                        pbuf += sprintf(pbuf,
 
3771
                 "\n       C_is = % -12g .      i_0 = % -12g .     C_rc = % -12g",
 
3772
                 edata->C_is, edata->i_0, edata->C_rc );
 
3773
                        pbuf += sprintf(pbuf,
 
3774
                 "\n      omega = % -12g . OMEGADOT = % -12g .     IDOT = % -12g",
 
3775
                edata->omega, edata->OMEGADOT, edata->IDOT );
 
3776
                        pbuf += sprintf(pbuf,
 
3777
              "\n       Axis = % -12g .        n = % -12g .    r1me2 = % -12g",
 
3778
                 edata->Axis, edata->n, edata->r1me2 );
 
3779
                        pbuf += sprintf(pbuf,
 
3780
           "\n    OMEGA_n = % -12g .   ODOT_n = % -12g",
 
3781
                 edata->OMEGA_n, edata->ODOT_n );
 
3782
                        break;
 
3783
                }
 
3784
        }
 
3785
}
 
3786
 
 
3787
 
 
3788
/* 0x59: */
 
3789
static void rpt_SVs_enabled (TSIPPKT *rpt)
 
3790
{
 
3791
        unsigned char
 
3792
        numsvs,
 
3793
                code_type,
 
3794
      status_code[32];
 
3795
        short
 
3796
                iprn;
 
3797
 
 
3798
        /* unload rptbuf */
 
3799
        if (rpt_0x59 (rpt, &code_type, status_code))
 
3800
   {
 
3801
                parsed = BADLEN_PARSE;
 
3802
                return;
 
3803
        }
 
3804
   switch (code_type)
 
3805
   {
 
3806
   case 3: pbuf += sprintf(pbuf, "\nSVs Disabled:\n"); break;
 
3807
   case 6: pbuf += sprintf(pbuf, "\nSVs with Health Ignored:\n"); break;
 
3808
   default: return;
 
3809
   }
 
3810
   numsvs = 0;
 
3811
        for (iprn=0; iprn<32; iprn++)
 
3812
   {
 
3813
        if (status_code[iprn])
 
3814
      {
 
3815
                pbuf += sprintf(pbuf, " %02d", iprn+1);
 
3816
           numsvs++;
 
3817
      }
 
3818
   }
 
3819
   if (numsvs == 0) pbuf += sprintf(pbuf, "None");
 
3820
}
 
3821
 
 
3822
 
 
3823
/* 0x5A */
 
3824
static void rpt_raw_msmt (TSIPPKT *rpt)
 
3825
{
 
3826
        unsigned char
 
3827
                sv_prn;
 
3828
        float
 
3829
                sample_length, signal_level, code_phase, Doppler;
 
3830
        double
 
3831
                time_of_fix;
 
3832
 
 
3833
        /* unload rptbuf */
 
3834
        if (rpt_0x5A (rpt, &sv_prn, &sample_length, &signal_level,
 
3835
                &code_phase, &Doppler, &time_of_fix))
 
3836
   {
 
3837
                parsed = BADLEN_PARSE;
 
3838
                return;
 
3839
        }
 
3840
 
 
3841
        pbuf += sprintf(pbuf, "\n   %02d %5.0f %7.1f %10.2f %10.2f %12.3f %s",
 
3842
                sv_prn, sample_length, signal_level, code_phase, Doppler, time_of_fix,
 
3843
                show_time ((float)time_of_fix));
 
3844
}
 
3845
 
 
3846
/* 0x5B */
 
3847
static void rpt_SV_ephemeris_status (TSIPPKT *rpt)
 
3848
{
 
3849
        unsigned char
 
3850
                sv_prn, sv_health, sv_iode, fit_interval_flag;
 
3851
        float
 
3852
                time_of_collection, time_of_eph, sv_accy;
 
3853
 
 
3854
        /* unload rptbuf */
 
3855
        if (rpt_0x5B (rpt, &sv_prn, &sv_health, &sv_iode, &fit_interval_flag,
 
3856
                &time_of_collection, &time_of_eph, &sv_accy))
 
3857
   {
 
3858
                parsed = BADLEN_PARSE;
 
3859
                return;
 
3860
        }
 
3861
 
 
3862
        pbuf += sprintf(pbuf, "\n  SV%02d  %s   %2Xh     %2Xh ",
 
3863
        sv_prn, show_time (time_of_collection), sv_health, sv_iode);
 
3864
        /* note: cannot use show_time twice in same call */
 
3865
        pbuf += sprintf(pbuf, "%s   %1d   %4.1f",
 
3866
      show_time (time_of_eph), fit_interval_flag, sv_accy);
 
3867
}
 
3868
 
 
3869
/* 0x5C */
 
3870
static void rpt_SV_tracking_status (TSIPPKT *rpt)
 
3871
{
 
3872
        unsigned char
 
3873
                sv_prn, chan, slot, acq_flag, eph_flag,
 
3874
                old_msmt_flag, integer_msec_flag, bad_data_flag,
 
3875
                data_collect_flag;
 
3876
        float
 
3877
                signal_level, time_of_last_msmt,
 
3878
                elev, azim;
 
3879
 
 
3880
        /* unload rptbuf */
 
3881
        if (rpt_0x5C (rpt,
 
3882
                &sv_prn, &slot, &chan, &acq_flag, &eph_flag,
 
3883
                &signal_level, &time_of_last_msmt, &elev, &azim,
 
3884
                &old_msmt_flag, &integer_msec_flag, &bad_data_flag,
 
3885
                &data_collect_flag))
 
3886
   {
 
3887
                parsed = BADLEN_PARSE;
 
3888
                return;
 
3889
        }
 
3890
 
 
3891
        pbuf += sprintf(pbuf,
 
3892
"\n SV%2d  %1d   %1d   %1d   %4.1f  %s  %5.1f  %5.1f",
 
3893
                sv_prn, chan,
 
3894
      acq_flag, eph_flag, signal_level,
 
3895
      show_time(time_of_last_msmt),
 
3896
                elev*R2D, azim*R2D);
 
3897
}
 
3898
 
 
3899
/**/
 
3900
/* 0x6D */
 
3901
static void rpt_allSV_selection (TSIPPKT *rpt)
 
3902
{
 
3903
        unsigned char
 
3904
                manual_mode, nsvs, sv_prn[8], ndim;
 
3905
        short
 
3906
                islot;
 
3907
        float
 
3908
                pdop, hdop, vdop, tdop;
 
3909
 
 
3910
        /* unload rptbuf */
 
3911
        if (rpt_0x6D (rpt,
 
3912
                &manual_mode, &nsvs, &ndim, sv_prn,
 
3913
                &pdop, &hdop, &vdop, &tdop))
 
3914
   {
 
3915
                parsed = BADLEN_PARSE;
 
3916
                return;
 
3917
        }
 
3918
 
 
3919
        switch (ndim)
 
3920
   {
 
3921
   case 0:
 
3922
                pbuf += sprintf(pbuf, "\nMode: Searching, %d-SV:", nsvs);
 
3923
      break;
 
3924
   case 1:
 
3925
                pbuf += sprintf(pbuf, "\nMode: One-SV Timing:");
 
3926
      break;
 
3927
   case 3: case 4:
 
3928
                pbuf += sprintf(pbuf, "\nMode: %c-%dD, %d-SV:",
 
3929
                        manual_mode ? 'M' : 'A', ndim - 1,  nsvs);
 
3930
      break;
 
3931
        case 5:
 
3932
                pbuf += sprintf(pbuf, "\nMode: Timing, %d-SV:", nsvs);
 
3933
      break;
 
3934
   default:
 
3935
                pbuf += sprintf(pbuf, "\nMode: Unknown = %d:", ndim);
 
3936
      break;
 
3937
   }
 
3938
 
 
3939
        for (islot = 0; islot < nsvs; islot++)
 
3940
   {
 
3941
                if (sv_prn[islot]) pbuf += sprintf(pbuf, " %02d", sv_prn[islot]);
 
3942
        }
 
3943
   if (ndim == 3 || ndim == 4)
 
3944
   {
 
3945
                pbuf += sprintf(pbuf, ";  DOPs: P %.1f H %.1f V %.1f T %.1f",
 
3946
                        pdop, hdop, vdop, tdop);
 
3947
   }
 
3948
}
 
3949
 
 
3950
/**/
 
3951
/* 0x82 */
 
3952
static void rpt_DGPS_position_mode (TSIPPKT *rpt)
 
3953
{
 
3954
        unsigned char
 
3955
                diff_mode;
 
3956
 
 
3957
        /* unload rptbuf */
 
3958
        if (rpt_0x82 (rpt, &diff_mode)) {
 
3959
                parsed = BADLEN_PARSE;
 
3960
                return;
 
3961
        }
 
3962
 
 
3963
        pbuf += sprintf(pbuf, "\nFix is%s DGPS-corrected (%s mode)  (%d)",
 
3964
        (diff_mode&1) ? "" : " not",
 
3965
        (diff_mode&2) ? "auto" : "manual",
 
3966
      diff_mode);
 
3967
}
 
3968
 
 
3969
/* 0x83 */
 
3970
static void rpt_double_ECEF_position (TSIPPKT *rpt)
 
3971
{
 
3972
 
 
3973
        double
 
3974
                ECEF_pos[3], clock_bias;
 
3975
        float
 
3976
                time_of_fix;
 
3977
 
 
3978
        /* unload rptbuf */
 
3979
        if (rpt_0x83 (rpt, ECEF_pos, &clock_bias, &time_of_fix))
 
3980
   {
 
3981
                parsed = BADLEN_PARSE;
 
3982
                return;
 
3983
        }
 
3984
 
 
3985
        pbuf += sprintf(pbuf, "\nDXYZ:%12.2f  %13.2f  %13.2f %12.2f%s",
 
3986
                ECEF_pos[0], ECEF_pos[1], ECEF_pos[2], clock_bias,
 
3987
                show_time(time_of_fix));
 
3988
}
 
3989
 
 
3990
/* 0x84 */
 
3991
static void rpt_double_lla_position (TSIPPKT *rpt)
 
3992
{
 
3993
        short
 
3994
                lat_deg, lon_deg;
 
3995
        double
 
3996
                lat, lon, lat_min, lon_min,
 
3997
                alt, clock_bias;
 
3998
        float
 
3999
                time_of_fix;
 
4000
        unsigned char
 
4001
                north_south, east_west;
 
4002
 
 
4003
        /* unload rptbuf */
 
4004
        if (rpt_0x84 (rpt,
 
4005
                &lat, &lon, &alt, &clock_bias, &time_of_fix))
 
4006
   {
 
4007
                parsed = BADLEN_PARSE;
 
4008
                return;
 
4009
        }
 
4010
 
 
4011
        lat *= R2D;
 
4012
        lon *= R2D;
 
4013
        if (lat < 0.0) {
 
4014
                north_south = 'S';
 
4015
                lat = -lat;
 
4016
        } else {
 
4017
                north_south = 'N';
 
4018
        }
 
4019
        lat_deg = (short)lat;
 
4020
        lat_min = (lat - lat_deg) * 60.0;
 
4021
 
 
4022
        if (lon < 0.0) {
 
4023
                east_west = 'W';
 
4024
                lon = -lon;
 
4025
        } else {
 
4026
                east_west = 'E';
 
4027
        }
 
4028
        lon_deg = (short)lon;
 
4029
        lon_min = (lon - lon_deg) * 60.0;
 
4030
        pbuf += sprintf(pbuf, "\nDLLA: %2d:%08.5f %c; %3d:%08.5f %c; %10.2f %12.2f%s",
 
4031
                lat_deg, lat_min, north_south,
 
4032
                lon_deg, lon_min, east_west,
 
4033
                alt, clock_bias,
 
4034
                show_time(time_of_fix));
 
4035
}
 
4036
 
 
4037
/* 0xBB */
 
4038
static void rpt_complete_rcvr_config (TSIPPKT *rpt)
 
4039
{
 
4040
        TSIP_RCVR_CFG TsipxBB ;
 
4041
        /* unload rptbuf */
 
4042
        if (rpt_Paly0xBB (rpt, &TsipxBB))
 
4043
        {
 
4044
                parsed = BADLEN_PARSE;
 
4045
                return;
 
4046
        }
 
4047
 
 
4048
        pbuf += sprintf(pbuf, "\n   operating mode:      %s",
 
4049
                NavModeText0xBB[TsipxBB.operating_mode]);
 
4050
        pbuf += sprintf(pbuf, "\n   dynamics:            %s",
 
4051
                dyn_text[TsipxBB.dyn_code]);
 
4052
        pbuf += sprintf(pbuf, "\n   elev angle mask:     %g deg",
 
4053
                TsipxBB.elev_mask * R2D);
 
4054
        pbuf += sprintf(pbuf, "\n   SNR mask:            %g AMU",
 
4055
                TsipxBB.cno_mask);
 
4056
        pbuf += sprintf(pbuf, "\n   DOP mask:            %g",
 
4057
                TsipxBB.dop_mask);
 
4058
        pbuf += sprintf(pbuf, "\n   DOP switch:          %g",
 
4059
                TsipxBB.dop_switch);
 
4060
        return ;
 
4061
}
 
4062
 
 
4063
/* 0xBC */
 
4064
static void rpt_rcvr_serial_port_config (TSIPPKT *rpt)
 
4065
{
 
4066
        unsigned char
 
4067
                port_num, in_baud, out_baud, data_bits, parity, stop_bits, flow_control,
 
4068
                protocols_in, protocols_out, reserved;
 
4069
        unsigned char known;
 
4070
 
 
4071
        /* unload rptbuf */
 
4072
        if (rpt_0xBC (rpt, &port_num, &in_baud, &out_baud, &data_bits, &parity,
 
4073
                        &stop_bits, &flow_control, &protocols_in, &protocols_out, &reserved)) {
 
4074
                parsed = BADLEN_PARSE;
 
4075
                return;
 
4076
        }
 
4077
        /* rptbuf unloaded */
 
4078
 
 
4079
        pbuf += sprintf(pbuf, "\n   RECEIVER serial port %s config:",
 
4080
                rcvr_port_text[port_num]);
 
4081
 
 
4082
        pbuf += sprintf(pbuf, "\n             I/O Baud %s/%s, %d - %s - %d",
 
4083
                st_baud_text_app[in_baud],
 
4084
                st_baud_text_app[out_baud],
 
4085
                data_bits+5,
 
4086
                parity_text[parity],
 
4087
                stop_bits=1);
 
4088
        pbuf += sprintf(pbuf, "\n             Input protocols: ");
 
4089
        known = FALSE;
 
4090
        if (protocols_in&B_TSIP)
 
4091
   {
 
4092
                pbuf += sprintf(pbuf, "%s ", protocols_in_text[1]);
 
4093
                known = TRUE;
 
4094
        }
 
4095
        if (known == FALSE) pbuf += sprintf(pbuf, "No known");
 
4096
 
 
4097
        pbuf += sprintf(pbuf, "\n             Output protocols: ");
 
4098
        known = FALSE;
 
4099
        if (protocols_out&B_TSIP)
 
4100
   {
 
4101
                pbuf += sprintf(pbuf, "%s ", protocols_out_text[1]);
 
4102
                known = TRUE;
 
4103
        }
 
4104
        if (protocols_out&B_NMEA)
 
4105
   {
 
4106
                pbuf += sprintf(pbuf, "%s ", protocols_out_text[2]);
 
4107
                known = TRUE;
 
4108
        }
 
4109
        if (known == FALSE) pbuf += sprintf(pbuf, "No known");
 
4110
        reserved = reserved;
 
4111
 
 
4112
 }
 
4113
 
 
4114
/* 0x8F */
 
4115
/* 8F0B */
 
4116
static void rpt_8F0B(TSIPPKT *rpt)
 
4117
{
 
4118
        const char
 
4119
        *oprtng_dim[7] = {
 
4120
        "horizontal (2-D)",
 
4121
         "full position (3-D)",
 
4122
         "single satellite (0-D)",
 
4123
         "automatic",
 
4124
         "N/A",
 
4125
         "N/A",
 
4126
         "overdetermined clock"};
 
4127
   char
 
4128
        sv_id[8];
 
4129
   unsigned char
 
4130
        month,
 
4131
      date,
 
4132
      dim_mode,
 
4133
      north_south,
 
4134
      east_west;
 
4135
   unsigned short
 
4136
        event;
 
4137
   short
 
4138
        utc_offset,
 
4139
      year,
 
4140
      local_index;
 
4141
        short
 
4142
        lat_deg,
 
4143
      lon_deg;
 
4144
   float
 
4145
        bias_unc,
 
4146
      dr_unc;
 
4147
   double
 
4148
        tow,
 
4149
      bias,
 
4150
      drift,
 
4151
      lat,
 
4152
      lon,
 
4153
      alt,
 
4154
      lat_min,
 
4155
      lon_min;
 
4156
   int
 
4157
        numfix,
 
4158
      numnotfix;
 
4159
 
 
4160
        if (rpt_0x8F0B(rpt,
 
4161
        &event,
 
4162
      &tow,
 
4163
      &date,
 
4164
      &month,
 
4165
      &year,
 
4166
      &dim_mode,
 
4167
      &utc_offset,
 
4168
      &bias,
 
4169
      &drift,
 
4170
      &bias_unc,
 
4171
      &dr_unc,
 
4172
      &lat,
 
4173
      &lon,
 
4174
      &alt,
 
4175
      sv_id))
 
4176
   {
 
4177
                parsed = BADLEN_PARSE;
 
4178
                return;
 
4179
        }
 
4180
 
 
4181
        if (event == 0)
 
4182
   {
 
4183
        pbuf += sprintf(pbuf, "\nNew partial+full meas");
 
4184
        }
 
4185
   else
 
4186
   {
 
4187
                pbuf += sprintf(pbuf, "\nEvent count: %5d", event);
 
4188
   }
 
4189
 
 
4190
        pbuf += sprintf(pbuf, "\nGPS time  : %s %2d/%2d/%2d (DMY)",
 
4191
        show_time(tow), date, month, year);
 
4192
        pbuf += sprintf(pbuf, "\nMode      : %s", oprtng_dim[dim_mode]);
 
4193
        pbuf += sprintf(pbuf, "\nUTC offset: %2d", utc_offset);
 
4194
        pbuf += sprintf(pbuf, "\nClock Bias: %6.2f m", bias);
 
4195
        pbuf += sprintf(pbuf, "\nFreq bias : %6.2f m/s", drift);
 
4196
        pbuf += sprintf(pbuf, "\nBias unc  : %6.2f m", bias_unc);
 
4197
        pbuf += sprintf(pbuf, "\nFreq unc  : %6.2f m/s", dr_unc);
 
4198
 
 
4199
        lat *= R2D; /* convert from radians to degrees */
 
4200
        lon *= R2D;
 
4201
        if (lat < 0.0)
 
4202
   {
 
4203
                north_south = 'S';
 
4204
                lat = -lat;
 
4205
        }
 
4206
   else
 
4207
   {
 
4208
                north_south = 'N';
 
4209
        }
 
4210
 
 
4211
        lat_deg = (short)lat;
 
4212
        lat_min = (lat - lat_deg) * 60.0;
 
4213
        if (lon < 0.0)
 
4214
   {
 
4215
                east_west = 'W';
 
4216
                lon = -lon;
 
4217
        }
 
4218
   else
 
4219
   {
 
4220
                east_west = 'E';
 
4221
        }
 
4222
 
 
4223
        lon_deg = (short)lon;
 
4224
        lon_min = (lon - lon_deg) * 60.0;
 
4225
        pbuf += sprintf(pbuf, "\nPosition  :");
 
4226
        pbuf += sprintf(pbuf, " %4d %6.3f %c", lat_deg, lat_min, north_south);
 
4227
        pbuf += sprintf(pbuf, " %5d %6.3f %c", lon_deg, lon_min, east_west);
 
4228
        pbuf += sprintf(pbuf, " %10.2f", alt);
 
4229
 
 
4230
   numfix = numnotfix = 0;
 
4231
        for (local_index=0; local_index<8; local_index++)
 
4232
   {
 
4233
                if (sv_id[local_index] < 0) numnotfix++;
 
4234
                if (sv_id[local_index] > 0) numfix++;
 
4235
   }
 
4236
   if (numfix > 0)
 
4237
   {
 
4238
                pbuf += sprintf(pbuf, "\nSVs used in fix  : ");
 
4239
                for (local_index=0; local_index<8; local_index++)
 
4240
           {
 
4241
                        if (sv_id[local_index] > 0)
 
4242
        {
 
4243
                pbuf += sprintf(pbuf, "%2d ", sv_id[local_index]);
 
4244
              }
 
4245
        }
 
4246
   }
 
4247
   if (numnotfix > 0)
 
4248
   {
 
4249
                pbuf += sprintf(pbuf, "\nOther SVs tracked: ");
 
4250
                for (local_index=0; local_index<8; local_index++)
 
4251
           {
 
4252
                        if (sv_id[local_index] < 0)
 
4253
        {
 
4254
                pbuf += sprintf(pbuf, "%2d ", sv_id[local_index]);
 
4255
              }
 
4256
        }
 
4257
   }
 
4258
}
 
4259
 
 
4260
/* 0x8F14 */
 
4261
static void rpt_8F14 (TSIPPKT *rpt)
 
4262
/* Datum parameters */
 
4263
{
 
4264
        double
 
4265
                datum_coeffs[5];
 
4266
        short
 
4267
                datum_idx;
 
4268
 
 
4269
        /* unload rptbuf */
 
4270
        if (rpt_0x8F14 (rpt, &datum_idx, datum_coeffs))
 
4271
   {
 
4272
                parsed = BADLEN_PARSE;
 
4273
                return;
 
4274
        }
 
4275
 
 
4276
        if (datum_idx == -1)
 
4277
   {
 
4278
        pbuf += sprintf(pbuf, "\nUser-Entered Datum:");
 
4279
                pbuf += sprintf(pbuf, "\n   dx        = %6.1f", datum_coeffs[0]);
 
4280
                pbuf += sprintf(pbuf, "\n   dy        = %6.1f", datum_coeffs[1]);
 
4281
                pbuf += sprintf(pbuf, "\n   dz        = %6.1f", datum_coeffs[2]);
 
4282
                pbuf += sprintf(pbuf, "\n   a-axis    = %10.3f", datum_coeffs[3]);
 
4283
                pbuf += sprintf(pbuf, "\n   e-squared = %16.14f", datum_coeffs[4]);
 
4284
   }
 
4285
   else if (datum_idx == 0)
 
4286
   {
 
4287
        pbuf += sprintf(pbuf, "\nWGS-84 datum, Index 0 ");
 
4288
   }
 
4289
   else
 
4290
   {
 
4291
        pbuf += sprintf(pbuf, "\nStandard Datum, Index %3d ", datum_idx);
 
4292
   }
 
4293
}
 
4294
 
 
4295
/* 0x8F15 */
 
4296
static void rpt_8F15 (TSIPPKT *rpt)
 
4297
/* Datum parameters */
 
4298
{
 
4299
        double
 
4300
                datum_coeffs[5];
 
4301
        short
 
4302
                datum_idx;
 
4303
 
 
4304
        /* unload rptbuf */
 
4305
        if (rpt_0x8F15 (rpt, &datum_idx, datum_coeffs)) {
 
4306
                parsed = BADLEN_PARSE;
 
4307
                return;
 
4308
        }
 
4309
 
 
4310
        if (datum_idx == -1)
 
4311
   {
 
4312
        pbuf += sprintf(pbuf, "\nUser-Entered Datum:");
 
4313
                pbuf += sprintf(pbuf, "\n   dx        = %6.1f", datum_coeffs[0]);
 
4314
                pbuf += sprintf(pbuf, "\n   dy        = %6.1f", datum_coeffs[1]);
 
4315
                pbuf += sprintf(pbuf, "\n   dz        = %6.1f", datum_coeffs[2]);
 
4316
                pbuf += sprintf(pbuf, "\n   a-axis    = %10.3f", datum_coeffs[3]);
 
4317
                pbuf += sprintf(pbuf, "\n   e-squared = %16.14f", datum_coeffs[4]);
 
4318
   }
 
4319
   else if (datum_idx == 0)
 
4320
   {
 
4321
        pbuf += sprintf(pbuf, "\nWGS-84 datum, Index 0 ");
 
4322
   }
 
4323
   else
 
4324
   {
 
4325
        pbuf += sprintf(pbuf, "\nStandard Datum, Index %3d ", datum_idx);
 
4326
   }
 
4327
}
 
4328
 
 
4329
/* 0x8F20 */
 
4330
#define INFO_DGPS       0x02
 
4331
#define INFO_2D         0x04
 
4332
#define INFO_ALTSET     0x08
 
4333
#define INFO_FILTERED   0x10
 
4334
static void rpt_8F20 (TSIPPKT *rpt)
 
4335
{
 
4336
        unsigned char
 
4337
                info, nsvs, sv_prn[32];
 
4338
        short
 
4339
                week_num, datum_index, sv_IODC[32];
 
4340
        double
 
4341
                lat, lon, alt, time_of_fix;
 
4342
        double
 
4343
                londeg, latdeg, vel[3];
 
4344
        short
 
4345
                isv;
 
4346
   char
 
4347
        datum_string[20];
 
4348
 
 
4349
        /* unload rptbuf */
 
4350
        if (rpt_0x8F20 (rpt,
 
4351
                &info, &lat, &lon, &alt, vel,
 
4352
                &time_of_fix,
 
4353
                &week_num, &nsvs, sv_prn, sv_IODC, &datum_index))
 
4354
        {
 
4355
                parsed = BADLEN_PARSE;
 
4356
                return;
 
4357
        }
 
4358
        pbuf += sprintf(pbuf,
 
4359
        "\nFix at: %04d:%3s:%02d:%02d:%06.3f GPS (=UTC+%2ds)  FixType: %s%s%s",
 
4360
        week_num,
 
4361
                dayname[(short)(time_of_fix/86400.0)],
 
4362
                (short)fmod(time_of_fix/3600., 24.),
 
4363
                (short)fmod(time_of_fix/60., 60.),
 
4364
                fmod(time_of_fix, 60.),
 
4365
      (char)rpt->buf[29],               /* UTC offset */
 
4366
                (info & INFO_DGPS)?"Diff":"",
 
4367
                (info & INFO_2D)?"2D":"3D",
 
4368
                (info & INFO_FILTERED)?"-Filtrd":"");
 
4369
 
 
4370
   if (datum_index > 0)
 
4371
   {
 
4372
                sprintf(datum_string, "Datum%3d", datum_index);
 
4373
   }
 
4374
   else if (datum_index)
 
4375
   {
 
4376
                sprintf(datum_string, "Unknown ");
 
4377
   }
 
4378
   else
 
4379
   {
 
4380
                sprintf(datum_string, "WGS-84");
 
4381
   }
 
4382
 
 
4383
        /* convert from radians to degrees */
 
4384
        latdeg = R2D * fabs(lat);
 
4385
        londeg = R2D * fabs(lon);
 
4386
        pbuf += sprintf(pbuf,
 
4387
        "\n   Pos: %4d:%09.6f %c %5d:%09.6f %c %10.2f m HAE (%s)",
 
4388
                (short)latdeg, fmod (latdeg, 1.)*60.0,
 
4389
                (lat<0.0)?'S':'N',
 
4390
                (short)londeg, fmod (londeg, 1.)*60.0,
 
4391
                (lon<0.0)?'W':'E',
 
4392
                alt,
 
4393
      datum_string);
 
4394
        pbuf += sprintf(pbuf,
 
4395
        "\n   Vel:    %9.3f E       %9.3f N      %9.3f U   (m/sec)",
 
4396
                vel[0], vel[1], vel[2]);
 
4397
 
 
4398
        pbuf += sprintf(pbuf,
 
4399
        "\n   SVs: ");
 
4400
        for (isv = 0; isv < nsvs; isv++) {
 
4401
                pbuf += sprintf(pbuf, " %02d", sv_prn[isv]);
 
4402
        }
 
4403
        pbuf += sprintf(pbuf, "     (IODEs:");
 
4404
        for (isv = 0; isv < nsvs; isv++) {
 
4405
                pbuf += sprintf(pbuf, " %02X", sv_IODC[isv]&0xFF);
 
4406
        }
 
4407
        pbuf += sprintf(pbuf, ")");
 
4408
}
 
4409
 
 
4410
/* 0x8F41 */
 
4411
static void rpt_8F41(TSIPPKT *rpt)
 
4412
{
 
4413
        unsigned char
 
4414
        bSearchRange,
 
4415
                bBoardOptions,
 
4416
                bBuildYear,
 
4417
                bBuildMonth,
 
4418
                bBuildDay,
 
4419
                bBuildHour;
 
4420
        float
 
4421
        fOscOffset;
 
4422
        unsigned short
 
4423
        iTestCodeId;
 
4424
        unsigned long
 
4425
                iiSerialNumber;
 
4426
 
 
4427
   if (!rpt_0x8F41(rpt,
 
4428
                &bSearchRange,
 
4429
                &bBoardOptions,
 
4430
                &iiSerialNumber,
 
4431
                &bBuildYear,
 
4432
                &bBuildMonth,
 
4433
                &bBuildDay,
 
4434
                &bBuildHour,
 
4435
                &fOscOffset,
 
4436
                &iTestCodeId))
 
4437
   {
 
4438
                parsed = BADLEN_PARSE;
 
4439
      return;
 
4440
   }
 
4441
 
 
4442
   pbuf += sprintf(pbuf, "\n  search range:          %d",
 
4443
        bSearchRange);
 
4444
   pbuf += sprintf(pbuf, "\n  board options:         %d",
 
4445
      bBoardOptions);
 
4446
   pbuf += sprintf(pbuf, "\n  board serial #:        %ld",
 
4447
      iiSerialNumber);
 
4448
   pbuf += sprintf(pbuf, "\n  build date/hour:       %02d/%02d/%02d %02d:00",
 
4449
        bBuildDay, bBuildMonth, bBuildYear, bBuildHour);
 
4450
   pbuf += sprintf(pbuf, "\n  osc offset:            %.3f PPM (%.0f Hz)",
 
4451
        fOscOffset/1575.42, fOscOffset);
 
4452
   pbuf += sprintf(pbuf, "\n  test code:             %d",
 
4453
        iTestCodeId);
 
4454
}
 
4455
 
 
4456
/* 0x8F42 */
 
4457
static void rpt_8F42(TSIPPKT *rpt)
 
4458
{
 
4459
        unsigned char
 
4460
        bProdOptionsPre,
 
4461
      bProdNumberExt;
 
4462
        unsigned short
 
4463
        iCaseSerialNumberPre,
 
4464
      iPremiumOptions,
 
4465
      iMachineID,
 
4466
      iKey;
 
4467
        unsigned long
 
4468
        iiCaseSerialNumber,
 
4469
                iiProdNumber;
 
4470
 
 
4471
   if (!rpt_0x8F42(rpt,
 
4472
                &bProdOptionsPre,
 
4473
                &bProdNumberExt,
 
4474
                &iCaseSerialNumberPre,
 
4475
                &iiCaseSerialNumber,
 
4476
                &iiProdNumber,
 
4477
                &iPremiumOptions,
 
4478
                &iMachineID,
 
4479
                &iKey))
 
4480
   {
 
4481
                parsed = BADLEN_PARSE;
 
4482
      return;
 
4483
   }
 
4484
 
 
4485
        pbuf += sprintf(pbuf, "\nProduct ID 8F42");
 
4486
   pbuf += sprintf(pbuf, "\n   extension:            %d", bProdNumberExt);
 
4487
   pbuf += sprintf(pbuf, "\n   case serial # prefix: %d", iCaseSerialNumberPre);
 
4488
   pbuf += sprintf(pbuf, "\n   case serial #:        %ld", iiCaseSerialNumber);
 
4489
   pbuf += sprintf(pbuf, "\n   prod. #:              %ld", iiProdNumber);
 
4490
        pbuf += sprintf(pbuf, "\n   premium options:      %Xh", iPremiumOptions);
 
4491
   pbuf += sprintf(pbuf, "\n   machine ID:           %d", iMachineID);
 
4492
   pbuf += sprintf(pbuf, "\n   key:                  %Xh", iKey);
 
4493
}
 
4494
 
 
4495
/* 0x8F45 */
 
4496
static void rpt_8F45(TSIPPKT *rpt)
 
4497
{
 
4498
   unsigned char bSegMask;
 
4499
 
 
4500
   if (!rpt_0x8F45(rpt,
 
4501
        &bSegMask))
 
4502
   {
 
4503
                parsed = BADLEN_PARSE;
 
4504
                return;
 
4505
        }
 
4506
        pbuf += sprintf(pbuf, "\nCleared Segment Mask: %Xh", bSegMask);
 
4507
}
 
4508
 
 
4509
static void rpt_8F4A(TSIPPKT *rpt)
 
4510
/* Stinger PPS def */
 
4511
{
 
4512
        unsigned char
 
4513
        pps_enabled,
 
4514
      pps_timebase,
 
4515
      pps_polarity;
 
4516
   float
 
4517
        bias_unc_threshold;
 
4518
   double
 
4519
        pps_offset;
 
4520
 
 
4521
        if (rpt_0x8F4A_16 (rpt,
 
4522
        &pps_enabled,
 
4523
      &pps_timebase,
 
4524
      &pps_polarity,
 
4525
      &pps_offset,
 
4526
      &bias_unc_threshold))
 
4527
   {
 
4528
        parsed = BADLEN_PARSE;
 
4529
           return;
 
4530
   }
 
4531
 
 
4532
        pbuf += sprintf(pbuf, "\nPPS is         %s",    pps_enabled?"enabled":"disabled");
 
4533
   pbuf += sprintf(pbuf, "\n   timebase:   %s", PPSTimeBaseText[pps_timebase]);
 
4534
   pbuf += sprintf(pbuf, "\n   polarity:   %s", PPSPolarityText[pps_polarity]);
 
4535
   pbuf += sprintf(pbuf, "\n   offset:     %.1f ns, ", pps_offset*1.e9);
 
4536
   pbuf += sprintf(pbuf, "\n   biasunc:    %.1f ns", bias_unc_threshold/GPS_C*1.e9);
 
4537
}
 
4538
 
 
4539
static void rpt_8F4B(TSIPPKT *rpt)
 
4540
/* fast-SA decorrolation time for self-survey */
 
4541
{
 
4542
        unsigned long
 
4543
        decorr_max;
 
4544
 
 
4545
   if (rpt_0x8F4B(rpt, &decorr_max))
 
4546
   {
 
4547
                parsed = BADLEN_PARSE;
 
4548
      return;
 
4549
   }
 
4550
 
 
4551
   pbuf += sprintf(pbuf,
 
4552
        "\nMax # of position fixes for self-survey : %ld",
 
4553
      decorr_max);
 
4554
}
 
4555
 
 
4556
static void rpt_8F4D(TSIPPKT *rpt)
 
4557
{
 
4558
        static char
 
4559
        *linestart;
 
4560
        unsigned long
 
4561
        OutputMask;
 
4562
   static unsigned long
 
4563
        MaskBit[] = {
 
4564
        0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020,
 
4565
        0x00000100L, 0x00000800L, 0x00001000L,
 
4566
         0x40000000L, 0x80000000L};
 
4567
   int
 
4568
        ichoice,
 
4569
        numchoices;
 
4570
 
 
4571
   if (rpt_0x8F4D(rpt, &OutputMask))
 
4572
   {
 
4573
                parsed = BADLEN_PARSE;
 
4574
      return;
 
4575
   }
 
4576
 
 
4577
   pbuf += sprintf(pbuf, "\nAuto-Report Mask: %02X %02X %02X %02X",
 
4578
        (unsigned char)(OutputMask>>24),
 
4579
        (unsigned char)(OutputMask>>16),
 
4580
        (unsigned char)(OutputMask>>8),
 
4581
        (unsigned char)OutputMask);
 
4582
 
 
4583
   numchoices = sizeof(MaskText)/sizeof(char*);
 
4584
   pbuf += sprintf(pbuf, "\nAuto-Reports scheduled for Output:");
 
4585
   linestart = pbuf;
 
4586
   for (ichoice=0; ichoice<numchoices; ichoice++)
 
4587
   {
 
4588
        if (OutputMask&MaskBit[ichoice])
 
4589
      {
 
4590
                pbuf += sprintf(pbuf, "%s %s",
 
4591
                (pbuf==linestart)?"\n     ":",",
 
4592
           MaskText[ichoice]);
 
4593
                        if (pbuf-linestart > 60) linestart = pbuf;
 
4594
      }
 
4595
   }
 
4596
 
 
4597
   pbuf += sprintf(pbuf, "\nAuto-Reports NOT scheduled for Output:");
 
4598
   linestart = pbuf;
 
4599
   for (ichoice=0; ichoice<numchoices; ichoice++)
 
4600
   {
 
4601
        if (OutputMask&MaskBit[ichoice]) continue;
 
4602
                pbuf += sprintf(pbuf, "%s %s",
 
4603
                (pbuf==linestart)?"\n     ":",",
 
4604
         MaskText[ichoice]);
 
4605
                if (pbuf-linestart > 60) linestart = pbuf;
 
4606
   }
 
4607
}
 
4608
 
 
4609
static void rpt_8FA5(TSIPPKT *rpt)
 
4610
{
 
4611
        unsigned char
 
4612
        spktmask[4];
 
4613
 
 
4614
   if (rpt_0x8FA5(rpt, spktmask))
 
4615
   {
 
4616
                parsed = BADLEN_PARSE;
 
4617
      return;
 
4618
   }
 
4619
 
 
4620
   pbuf += sprintf(pbuf, "\nSuperpacket auto-output mask: %02X %02X %02X %02X",
 
4621
        spktmask[0], spktmask[1], spktmask[2], spktmask[3]);
 
4622
 
 
4623
   if (spktmask[0]&0x01) pbuf+= sprintf (pbuf, "\n    PPS   8F-0B");
 
4624
   if (spktmask[0]&0x02) pbuf+= sprintf (pbuf, "\n    Event 8F-0B");
 
4625
   if (spktmask[0]&0x10) pbuf+= sprintf (pbuf, "\n    PPS   8F-AD");
 
4626
   if (spktmask[0]&0x20) pbuf+= sprintf (pbuf, "\n    Event 8F-AD");
 
4627
   if (spktmask[2]&0x01) pbuf+= sprintf (pbuf, "\n    ppos Fix 8F-20");
 
4628
}
 
4629
 
 
4630
static void rpt_8FAD (TSIPPKT *rpt)
 
4631
{
 
4632
   unsigned short
 
4633
        Count,
 
4634
        Year;
 
4635
   double
 
4636
        FracSec;
 
4637
   unsigned char
 
4638
        Hour,
 
4639
        Minute,
 
4640
        Second,
 
4641
        Day,
 
4642
        Month,
 
4643
        Status,
 
4644
        Flags;
 
4645
        static char* Status8FADText[] = {
 
4646
      "CODE_DOING_FIXES",
 
4647
      "CODE_GOOD_1_SV",
 
4648
      "CODE_APPX_1SV",
 
4649
      "CODE_NEED_TIME",
 
4650
      "CODE_NEED_INITIALIZATION",
 
4651
      "CODE_PDOP_HIGH",
 
4652
      "CODE_BAD_1SV",
 
4653
      "CODE_0SVS",
 
4654
      "CODE_1SV",
 
4655
      "CODE_2SVS",
 
4656
      "CODE_3SVS",
 
4657
      "CODE_NO_INTEGRITY",
 
4658
      "CODE_DCORR_GEN",
 
4659
      "CODE_OVERDET_CLK",
 
4660
      "Invalid Status"},
 
4661
        *LeapStatusText[] = {
 
4662
        " UTC Avail", " ", " ", " ",
 
4663
      " Scheduled", " Pending", " Warning", " In Progress"};
 
4664
    int i;
 
4665
 
 
4666
        if (rpt_0x8FAD (rpt,
 
4667
        &Count,
 
4668
        &FracSec,
 
4669
        &Hour,
 
4670
        &Minute,
 
4671
        &Second,
 
4672
        &Day,
 
4673
        &Month,
 
4674
        &Year,
 
4675
        &Status,
 
4676
        &Flags))
 
4677
   {
 
4678
                parsed = BADLEN_PARSE;
 
4679
                return;
 
4680
   }
 
4681
 
 
4682
        pbuf += sprintf(pbuf,    "\n8FAD   Count: %d   Status: %s",
 
4683
        Count, Status8FADText[Status]);
 
4684
 
 
4685
        pbuf += sprintf(pbuf, "\n   Leap Flags:");
 
4686
   if (Flags)
 
4687
   {
 
4688
        for (i=0; i<8; i++)
 
4689
      {
 
4690
        if (Flags&(1<<i)) pbuf += sprintf(pbuf, LeapStatusText[i]);
 
4691
      }
 
4692
   }
 
4693
   else
 
4694
   {
 
4695
        pbuf += sprintf(pbuf, "  UTC info not available");
 
4696
   }
 
4697
 
 
4698
        pbuf += sprintf(pbuf,     "\n      %02d/%02d/%04d (DMY)  %02d:%02d:%02d.%09ld UTC",
 
4699
                Day, Month, Year, Hour, Minute, Second, (long)(FracSec*1.e9));
 
4700
}
 
4701
 
 
4702
 
 
4703
int print_msg_table_header (int rptcode, char *HdrStr, int force)
 
4704
{
 
4705
        /* force header is to help auto-output function */
 
4706
        /* last_rptcode is to determine whether to print a header */
 
4707
        /* for the first occurrence of a series of reports */
 
4708
        static int
 
4709
                last_rptcode = 0;
 
4710
   int
 
4711
        numchars;
 
4712
 
 
4713
   numchars = 0;
 
4714
        if (force || rptcode!=last_rptcode)
 
4715
   {
 
4716
                /* supply a header in console output */
 
4717
        switch (rptcode)
 
4718
                {
 
4719
                case 0x5A:
 
4720
                        numchars = sprintf(HdrStr, "\nRaw Measurement Data");
 
4721
                        numchars += sprintf(HdrStr+numchars,
 
4722
                "\n   SV  Sample   SNR  Code Phase   Doppler    Seconds     Time of Meas");
 
4723
                        break;
 
4724
 
 
4725
                case 0x5B:
 
4726
                        numchars = sprintf(HdrStr, "\nEphemeris Status");
 
4727
                        numchars += sprintf(HdrStr+numchars,
 
4728
                                "\n    SV     Time collected     Health  IODE        t oe         Fit   URA");
 
4729
                        break;
 
4730
 
 
4731
                case 0x5C:
 
4732
                        numchars = sprintf(HdrStr, "\nTracking Info");
 
4733
                        numchars += sprintf(HdrStr+numchars,
 
4734
                "\n   SV  C Acq Eph   SNR     Time of Meas       Elev  Azim   ");
 
4735
                        break;
 
4736
 
 
4737
      }
 
4738
        }
 
4739
        last_rptcode = rptcode;
 
4740
   return (short)numchars;
 
4741
}
 
4742
 
 
4743
static void unknown_rpt (TSIPPKT *rpt)
 
4744
{
 
4745
        int i;
 
4746
 
 
4747
        /* app-specific rpt packets */
 
4748
        if (parsed == BADLEN_PARSE)
 
4749
   {
 
4750
                pbuf += sprintf(pbuf, "\nTSIP report packet ID %2Xh, length %d: Bad length",
 
4751
        rpt->code, rpt->len);
 
4752
   }
 
4753
        if (parsed == BADID_PARSE)
 
4754
   {
 
4755
                pbuf += sprintf(pbuf,
 
4756
        "\nTSIP report packet ID %2Xh, length %d: translation not supported",
 
4757
                rpt->code, rpt->len);
 
4758
   }
 
4759
 
 
4760
        if (parsed == BADDATA_PARSE)
 
4761
   {
 
4762
                pbuf += sprintf(pbuf,
 
4763
        "\nTSIP report packet ID %2Xh, length %d: data content incorrect",
 
4764
                rpt->code, rpt->len);
 
4765
   }
 
4766
 
 
4767
        for (i = 0; i < rpt->len; i++) {
 
4768
                if ((i % 20) == 0) *pbuf++ = '\n';
 
4769
                pbuf += sprintf(pbuf, " %02X", rpt->buf[i]);
 
4770
        }
 
4771
}
 
4772
/**/
 
4773
/*
 
4774
** main subroutine, called from ProcessInputBytesWhileWaitingForKBHit()
 
4775
*/
 
4776
void TranslateTSIPReportToText (TSIPPKT *rpt, char *TextOutputBuffer)
 
4777
{
 
4778
 
 
4779
        /* pbuf is the pointer to the current location of the text output */
 
4780
        pbuf = TextOutputBuffer;
 
4781
 
 
4782
   /* keep track of whether the message has been successfully parsed */
 
4783
        parsed = GOOD_PARSE;
 
4784
 
 
4785
        /* print a header if this is the first of a series of messages */
 
4786
        pbuf += print_msg_table_header (rpt->code, pbuf, FALSE);
 
4787
 
 
4788
   /* process incoming TSIP report according to code */
 
4789
        switch (rpt->code)
 
4790
   {
 
4791
        case 0x3D: rpt_chan_A_config (rpt); break;
 
4792
        case 0x40: rpt_almanac_data_page (rpt); break;
 
4793
        case 0x41: rpt_GPS_time (rpt); break;
 
4794
        case 0x42: rpt_single_ECEF_position (rpt); break;
 
4795
        case 0x43: rpt_single_ECEF_velocity (rpt); break;
 
4796
        case 0x45: rpt_SW_version (rpt); break;
 
4797
        case 0x46: rpt_rcvr_health (rpt); break;
 
4798
        case 0x47: rpt_SNR_all_SVs (rpt); break;
 
4799
        case 0x48: rpt_GPS_system_message (rpt); break;
 
4800
        case 0x49: rpt_almanac_health_page (rpt); break;
 
4801
        case 0x4A: switch (rpt->len) {
 
4802
        /*
 
4803
      ** special case (=slip-up) in the TSIP protocol;
 
4804
      ** parsing method depends on length
 
4805
      */
 
4806
        case 20: rpt_single_lla_position (rpt); break;
 
4807
      case  9: rpt_ref_alt (rpt); break;
 
4808
                } break;
 
4809
        case 0x4B: rpt_rcvr_id_and_status (rpt);break;
 
4810
        case 0x4C: rpt_operating_parameters (rpt); break;
 
4811
        case 0x4D: rpt_oscillator_offset (rpt); break;
 
4812
        case 0x4E: rpt_GPS_time_set_response (rpt); break;
 
4813
        case 0x4F: rpt_UTC_offset (rpt); break;
 
4814
   case 0x54: rpt_1SV_bias (rpt); break;
 
4815
        case 0x55: rpt_io_opt (rpt); break;
 
4816
        case 0x56: rpt_ENU_velocity (rpt); break;
 
4817
        case 0x57: rpt_last_fix_info (rpt); break;
 
4818
        case 0x58: rpt_GPS_system_data (rpt); break;
 
4819
        case 0x59: rpt_SVs_enabled (rpt); break;
 
4820
        case 0x5A: rpt_raw_msmt (rpt); break;
 
4821
        case 0x5B: rpt_SV_ephemeris_status (rpt); break;
 
4822
        case 0x5C: rpt_SV_tracking_status (rpt); break;
 
4823
        case 0x6D: rpt_allSV_selection (rpt); break;
 
4824
        case 0x82: rpt_DGPS_position_mode (rpt); break;
 
4825
        case 0x83: rpt_double_ECEF_position (rpt); break;
 
4826
        case 0x84: rpt_double_lla_position (rpt); break;
 
4827
        case 0xBB: rpt_complete_rcvr_config (rpt); break;
 
4828
        case 0xBC: rpt_rcvr_serial_port_config (rpt); break;
 
4829
 
 
4830
        case 0x8F: switch (rpt->buf[0])
 
4831
        {
 
4832
      /* superpackets; parsed according to subcodes */
 
4833
      case 0x0B: rpt_8F0B(rpt); break;
 
4834
      case 0x14: rpt_8F14(rpt); break;
 
4835
      case 0x15: rpt_8F15(rpt); break;
 
4836
                case 0x20: rpt_8F20(rpt); break;
 
4837
      case 0x41: rpt_8F41(rpt); break;
 
4838
      case 0x42: rpt_8F42(rpt); break;
 
4839
      case 0x45: rpt_8F45(rpt); break;
 
4840
      case 0x4A: rpt_8F4A(rpt); break;
 
4841
      case 0x4B: rpt_8F4B(rpt); break;
 
4842
      case 0x4D: rpt_8F4D(rpt); break;
 
4843
      case 0xA5: rpt_8FA5(rpt); break;
 
4844
           case 0xAD: rpt_8FAD(rpt); break;
 
4845
                default: parsed = BADID_PARSE; break;
 
4846
                }
 
4847
                break;
 
4848
 
 
4849
        default: parsed = BADID_PARSE; break;
 
4850
        }
 
4851
 
 
4852
        if (parsed != GOOD_PARSE)
 
4853
        {
 
4854
           /*
 
4855
        **The message has TSIP structure (DLEs, etc.)
 
4856
           ** but could not be parsed by above routines
 
4857
        */
 
4858
                unknown_rpt (rpt);
 
4859
        }
 
4860
 
 
4861
   /* close TextOutputBuffer */
 
4862
   pbuf = '\0';
 
4863
}
 
4864
 
 
4865
#endif /* TRIMBLE_OUTPUT_FUNC */
 
4866
 
 
4867
#else  /* defined(REFCLOCK) && defined(CLOCK_RIPENCC) */
 
4868
int refclock_ripencc_bs;
 
4869
#endif /* defined(REFCLOCK) && defined(CLOCK_RIPENCC) */
 
4870