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