1106424Sroberto/* 2106424Sroberto * $Id: refclock_ripencc.c,v 1.13 2002/06/18 14:20:55 marks Exp marks $ 3106424Sroberto * 4106424Sroberto * Copyright (c) 2002 RIPE NCC 5106424Sroberto * 6106424Sroberto * All Rights Reserved 7106424Sroberto * 8106424Sroberto * Permission to use, copy, modify, and distribute this software and its 9106424Sroberto * documentation for any purpose and without fee is hereby granted, 10106424Sroberto * provided that the above copyright notice appear in all copies and that 11106424Sroberto * both that copyright notice and this permission notice appear in 12106424Sroberto * supporting documentation, and that the name of the author not be 13106424Sroberto * used in advertising or publicity pertaining to distribution of the 14106424Sroberto * software without specific, written prior permission. 15106424Sroberto * 16106424Sroberto * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 17106424Sroberto * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL 18106424Sroberto * AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 19106424Sroberto * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 20106424Sroberto * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 21106424Sroberto * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22106424Sroberto * 23106424Sroberto * 24106424Sroberto * 25106424Sroberto * This driver was developed for use with the RIPE NCC TTM project. 26106424Sroberto * 27106424Sroberto * 28106424Sroberto * The initial driver was developed by Daniel Karrenberg <dfk@ripe.net> 29106424Sroberto * using the code made available by Trimble. This was for xntpd-3.x.x 30106424Sroberto * 31106424Sroberto * Rewrite of the driver for ntpd-4.x.x by Mark Santcroos <marks@ripe.net> 32106424Sroberto * 33106424Sroberto */ 34106424Sroberto 35106424Sroberto#ifdef HAVE_CONFIG_H 36106424Sroberto#include <config.h> 37106424Sroberto#endif /* HAVE_CONFIG_H */ 38106424Sroberto 39106424Sroberto#if defined(REFCLOCK) && defined(CLOCK_RIPENCC) 40106424Sroberto 41106424Sroberto#include "ntp_stdlib.h" 42106424Sroberto#include "ntpd.h" 43106424Sroberto#include "ntp_refclock.h" 44106424Sroberto#include "ntp_unixtime.h" 45106424Sroberto#include "ntp_io.h" 46106424Sroberto 47182007Sroberto#ifdef HAVE_PPSAPI 48182007Sroberto# include "ppsapi_timepps.h" 49182007Sroberto#endif 50106424Sroberto 51106424Sroberto/* 52106424Sroberto * Definitions 53106424Sroberto */ 54106424Sroberto 55106424Sroberto/* we are on little endian */ 56106424Sroberto#define BYTESWAP 57106424Sroberto 58106424Sroberto/* 59106424Sroberto * DEBUG statements: uncomment if necessary 60106424Sroberto */ 61106424Sroberto/* #define DEBUG_NCC */ /* general debug statements */ 62106424Sroberto/* #define DEBUG_PPS */ /* debug pps */ 63106424Sroberto/* #define DEBUG_RAW */ /* print raw packets */ 64106424Sroberto 65106424Sroberto#define TRIMBLE_OUTPUT_FUNC 66106424Sroberto#define TSIP_VERNUM "7.12a" 67106424Sroberto 68106424Sroberto#ifndef FALSE 69106424Sroberto#define FALSE (0) 70106424Sroberto#define TRUE (!FALSE) 71106424Sroberto#endif /* FALSE */ 72106424Sroberto 73106424Sroberto#define GPS_PI (3.1415926535898) 74106424Sroberto#define GPS_C (299792458.) 75106424Sroberto#define D2R (GPS_PI/180.0) 76106424Sroberto#define R2D (180.0/GPS_PI) 77106424Sroberto#define WEEK (604800.) 78106424Sroberto#define MAXCHAN (8) 79106424Sroberto 80106424Sroberto/* control characters for TSIP packets */ 81106424Sroberto#define DLE (0x10) 82106424Sroberto#define ETX (0x03) 83106424Sroberto 84106424Sroberto#define MAX_RPTBUF (256) 85106424Sroberto 86106424Sroberto/* values of TSIPPKT.status */ 87106424Sroberto#define TSIP_PARSED_EMPTY 0 88106424Sroberto#define TSIP_PARSED_FULL 1 89106424Sroberto#define TSIP_PARSED_DLE_1 2 90106424Sroberto#define TSIP_PARSED_DATA 3 91106424Sroberto#define TSIP_PARSED_DLE_2 4 92106424Sroberto 93290001Sglebius#define UTCF_UTC_AVAIL (unsigned char) (1) /* UTC available */ 94106424Sroberto#define UTCF_LEAP_SCHD (unsigned char) (1<<4) /* Leap scheduled */ 95106424Sroberto#define UTCF_LEAP_PNDG (unsigned char) (1<<5) /* Leap pending, will occur at end of day */ 96106424Sroberto 97106424Sroberto#define DEVICE "/dev/gps%d" /* name of radio device */ 98106424Sroberto#define PRECISION (-9) /* precision assumed (about 2 ms) */ 99106424Sroberto#define PPS_PRECISION (-20) /* precision assumed (about 1 us) */ 100106424Sroberto#define REFID "GPS\0" /* reference id */ 101106424Sroberto#define REFID_LEN 4 102106424Sroberto#define DESCRIPTION "RIPE NCC GPS (Palisade)" /* Description */ 103106424Sroberto#define SPEED232 B9600 /* 9600 baud */ 104106424Sroberto 105106424Sroberto#define NSAMPLES 3 /* stages of median filter */ 106106424Sroberto 107106424Sroberto/* Structures */ 108106424Sroberto 109106424Sroberto/* TSIP packets have the following structure, whether report or command. */ 110106424Srobertotypedef struct { 111106424Sroberto short 112290001Sglebius counter, /* counter */ 113290001Sglebius len; /* size of buf; < MAX_RPTBUF unsigned chars */ 114106424Sroberto unsigned char 115290001Sglebius status, /* TSIP packet format/parse status */ 116290001Sglebius code, /* TSIP code */ 117290001Sglebius buf[MAX_RPTBUF]; /* report or command string */ 118106424Sroberto} TSIPPKT; 119106424Sroberto 120106424Sroberto/* TSIP binary data structures */ 121106424Srobertotypedef struct { 122106424Sroberto unsigned char 123290001Sglebius t_oa_raw, SV_health; 124106424Sroberto float 125290001Sglebius e, t_oa, i_0, OMEGADOT, sqrt_A, 126290001Sglebius OMEGA_0, omega, M_0, a_f0, a_f1, 127290001Sglebius Axis, n, OMEGA_n, ODOT_n, t_zc; 128106424Sroberto short 129290001Sglebius weeknum, wn_oa; 130106424Sroberto} ALM_INFO; 131106424Sroberto 132290001Sglebiustypedef struct { /* Almanac health page (25) parameters */ 133106424Sroberto unsigned char 134290001Sglebius WN_a, SV_health[32], t_oa; 135106424Sroberto} ALH_PARMS; 136106424Sroberto 137290001Sglebiustypedef struct { /* Universal Coordinated Time (UTC) parms */ 138106424Sroberto double 139290001Sglebius A_0; 140106424Sroberto float 141290001Sglebius A_1; 142106424Sroberto short 143290001Sglebius delta_t_LS; 144106424Sroberto float 145290001Sglebius t_ot; 146106424Sroberto short 147290001Sglebius WN_t, WN_LSF, DN, delta_t_LSF; 148106424Sroberto} UTC_INFO; 149106424Sroberto 150290001Sglebiustypedef struct { /* Ionospheric info (float) */ 151106424Sroberto float 152290001Sglebius alpha_0, alpha_1, alpha_2, alpha_3, 153290001Sglebius beta_0, beta_1, beta_2, beta_3; 154106424Sroberto} ION_INFO; 155106424Sroberto 156290001Sglebiustypedef struct { /* Subframe 1 info (float) */ 157106424Sroberto short 158290001Sglebius weeknum; 159106424Sroberto unsigned char 160290001Sglebius codeL2, L2Pdata, SVacc_raw, SV_health; 161106424Sroberto short 162290001Sglebius IODC; 163106424Sroberto float 164290001Sglebius T_GD, t_oc, a_f2, a_f1, a_f0, SVacc; 165106424Sroberto} EPHEM_CLOCK; 166106424Sroberto 167290001Sglebiustypedef struct { /* Ephemeris info (float) */ 168106424Sroberto unsigned char 169290001Sglebius IODE, fit_interval; 170106424Sroberto float 171290001Sglebius C_rs, delta_n; 172106424Sroberto double 173290001Sglebius M_0; 174106424Sroberto float 175290001Sglebius C_uc; 176106424Sroberto double 177290001Sglebius e; 178106424Sroberto float 179290001Sglebius C_us; 180106424Sroberto double 181290001Sglebius sqrt_A; 182106424Sroberto float 183290001Sglebius t_oe, C_ic; 184106424Sroberto double 185290001Sglebius OMEGA_0; 186106424Sroberto float 187290001Sglebius C_is; 188106424Sroberto double 189290001Sglebius i_0; 190106424Sroberto float 191290001Sglebius C_rc; 192106424Sroberto double 193290001Sglebius omega; 194106424Sroberto float 195290001Sglebius OMEGADOT, IDOT; 196106424Sroberto double 197290001Sglebius Axis, n, r1me2, OMEGA_n, ODOT_n; 198106424Sroberto} EPHEM_ORBIT; 199106424Sroberto 200290001Sglebiustypedef struct { /* Navigation data structure */ 201106424Sroberto short 202290001Sglebius sv_number; /* SV number (0 = no entry) */ 203106424Sroberto float 204290001Sglebius t_ephem; /* time of ephemeris collection */ 205106424Sroberto EPHEM_CLOCK 206290001Sglebius ephclk; /* subframe 1 data */ 207106424Sroberto EPHEM_ORBIT 208290001Sglebius ephorb; /* ephemeris data */ 209106424Sroberto} NAV_INFO; 210106424Sroberto 211106424Srobertotypedef struct { 212106424Sroberto unsigned char 213290001Sglebius bSubcode, 214290001Sglebius operating_mode, 215290001Sglebius dgps_mode, 216290001Sglebius dyn_code, 217290001Sglebius trackmode; 218106424Sroberto float 219290001Sglebius elev_mask, 220290001Sglebius cno_mask, 221290001Sglebius dop_mask, 222290001Sglebius dop_switch; 223106424Sroberto unsigned char 224290001Sglebius dgps_age_limit; 225106424Sroberto} TSIP_RCVR_CFG; 226106424Sroberto 227106424Sroberto 228106424Sroberto#ifdef TRIMBLE_OUTPUT_FUNC 229106424Srobertostatic char 230290001Sglebius *dayname[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}, 231106424Sroberto old_baudnum[] = {0, 1, 4, 5, 6, 8, 9, 11, 28, 12}, 232106424Sroberto *st_baud_text_app [] = {"", "", " 300", " 600", " 1200", " 2400", 233290001Sglebius " 4800", " 9600", "19200", "38400"}, 234106424Sroberto *old_parity_text[] = {"EVEN", "ODD", "", "", "NONE"}, 235106424Sroberto *parity_text [] = {"NONE", "ODD", "EVEN"}, 236106424Sroberto *old_input_ch[] = { "TSIP", "RTCM (6 of 8 bits)"}, 237106424Sroberto *old_output_ch[] = { "TSIP", "No output", "", "", "", "NMEA 0183"}, 238106424Sroberto *protocols_in_text[] = { "", "TSIP", "", ""}, 239106424Sroberto *protocols_out_text[] = { "", "TSIP", "NMEA"}, 240106424Sroberto *rcvr_port_text [] = { "Port A ", "Port B ", "Current Port"}, 241106424Sroberto *dyn_text [] = {"Unchanged", "Land", "Sea", "Air", "Static"}, 242106424Sroberto *NavModeText0xBB[] = {"automatic", "time only (0-D)", "", "2-D", 243290001Sglebius "3-D", "", "", "OverDetermined Time"}, 244106424Sroberto *PPSTimeBaseText[] = {"GPS", "UTC", "USER"}, 245106424Sroberto *PPSPolarityText[] = {"Positive", "Negative"}, 246106424Sroberto *MaskText[] = { "Almanac ", "Ephemeris", "UTC ", "Iono ", 247290001Sglebius "GPS Msg ", "Alm Hlth ", "Time Fix ", "SV Select", 248290001Sglebius "Ext Event", "Pos Fix ", "Raw Meas "}; 249106424Sroberto 250106424Sroberto#endif /* TRIMBLE_OUTPUT_FUNC */ 251106424Sroberto 252106424Sroberto/* 253106424Sroberto * Unit control structure 254106424Sroberto */ 255106424Srobertostruct ripencc_unit { 256106424Sroberto int unit; /* unit number */ 257106424Sroberto int pollcnt; /* poll message counter */ 258106424Sroberto int polled; /* Hand in a sample? */ 259106424Sroberto char leapdelta; /* delta of next leap event */ 260106424Sroberto unsigned char utcflags; /* delta of next leap event */ 261106424Sroberto l_fp tstamp; /* timestamp of last poll */ 262106424Sroberto 263106424Sroberto struct timespec ts; /* last timestamp */ 264106424Sroberto pps_params_t pps_params; /* pps parameters */ 265106424Sroberto pps_info_t pps_info; /* last pps data */ 266106424Sroberto pps_handle_t handle; /* pps handlebars */ 267106424Sroberto 268106424Sroberto}; 269106424Sroberto 270106424Sroberto 271106424Sroberto/******************* PROTOYPES *****************/ 272106424Sroberto 273106424Sroberto/* prototypes for report parsing primitives */ 274106424Srobertoshort rpt_0x3D (TSIPPKT *rpt, unsigned char *tx_baud_index, 275290001Sglebius unsigned char *rx_baud_index, unsigned char *char_format_index, 276290001Sglebius unsigned char *stop_bits, unsigned char *tx_mode_index, 277290001Sglebius unsigned char *rx_mode_index); 278106424Srobertoshort rpt_0x40 (TSIPPKT *rpt, unsigned char *sv_prn, short *week_num, 279290001Sglebius float *t_zc, float *eccentricity, float *t_oa, float *i_0, 280290001Sglebius float *OMEGA_dot, float *sqrt_A, float *OMEGA_0, float *omega, 281290001Sglebius float *M_0); 282106424Srobertoshort rpt_0x41 (TSIPPKT *rpt, float *time_of_week, float *UTC_offset, 283290001Sglebius short *week_num); 284106424Srobertoshort rpt_0x42 (TSIPPKT *rpt, float ECEF_pos[3], float *time_of_fix); 285106424Srobertoshort rpt_0x43 (TSIPPKT *rpt, float ECEF_vel[3], float *freq_offset, 286290001Sglebius float *time_of_fix); 287106424Srobertoshort rpt_0x45 (TSIPPKT *rpt, unsigned char *major_nav_version, 288290001Sglebius unsigned char *minor_nav_version, unsigned char *nav_day, 289290001Sglebius unsigned char *nav_month, unsigned char *nav_year, 290290001Sglebius unsigned char *major_dsp_version, unsigned char *minor_dsp_version, 291290001Sglebius unsigned char *dsp_day, unsigned char *dsp_month, 292290001Sglebius unsigned char *dsp_year); 293106424Srobertoshort rpt_0x46 (TSIPPKT *rpt, unsigned char *status1, unsigned char *status2); 294106424Srobertoshort rpt_0x47 (TSIPPKT *rpt, unsigned char *nsvs, unsigned char *sv_prn, 295290001Sglebius float *snr); 296106424Srobertoshort rpt_0x48 (TSIPPKT *rpt, unsigned char *message); 297106424Srobertoshort rpt_0x49 (TSIPPKT *rpt, unsigned char *sv_health); 298106424Srobertoshort rpt_0x4A (TSIPPKT *rpt, float *lat, float *lon, float *alt, 299290001Sglebius float *clock_bias, float *time_of_fix); 300106424Srobertoshort rpt_0x4A_2 (TSIPPKT *rpt, float *alt, float *dummy, 301290001Sglebius unsigned char *alt_flag); 302106424Srobertoshort rpt_0x4B (TSIPPKT *rpt, unsigned char *machine_id, 303290001Sglebius unsigned char *status3, unsigned char *status4); 304106424Srobertoshort rpt_0x4C (TSIPPKT *rpt, unsigned char *dyn_code, float *el_mask, 305290001Sglebius float *snr_mask, float *dop_mask, float *dop_switch); 306106424Srobertoshort rpt_0x4D (TSIPPKT *rpt, float *osc_offset); 307106424Srobertoshort rpt_0x4E (TSIPPKT *rpt, unsigned char *response); 308106424Srobertoshort rpt_0x4F (TSIPPKT *rpt, double *a0, float *a1, float *time_of_data, 309290001Sglebius short *dt_ls, short *wn_t, short *wn_lsf, short *dn, short *dt_lsf); 310106424Srobertoshort rpt_0x54 (TSIPPKT *rpt, float *clock_bias, float *freq_offset, 311290001Sglebius float *time_of_fix); 312106424Srobertoshort rpt_0x55 (TSIPPKT *rpt, unsigned char *pos_code, unsigned char *vel_code, 313290001Sglebius unsigned char *time_code, unsigned char *aux_code); 314106424Srobertoshort rpt_0x56 (TSIPPKT *rpt, float vel_ENU[3], float *freq_offset, 315290001Sglebius float *time_of_fix); 316106424Srobertoshort rpt_0x57 (TSIPPKT *rpt, unsigned char *source_code, 317290001Sglebius unsigned char *diag_code, short *week_num, float *time_of_fix); 318106424Srobertoshort rpt_0x58 (TSIPPKT *rpt, unsigned char *op_code, unsigned char *data_type, 319290001Sglebius unsigned char *sv_prn, unsigned char *data_length, 320290001Sglebius unsigned char *data_packet); 321106424Srobertoshort rpt_0x59 (TSIPPKT *rpt, unsigned char *code_type, 322290001Sglebius unsigned char status_code[32]); 323106424Srobertoshort rpt_0x5A (TSIPPKT *rpt, unsigned char *sv_prn, float *sample_length, 324290001Sglebius float *signal_level, float *code_phase, float *Doppler, 325290001Sglebius double *time_of_fix); 326106424Srobertoshort rpt_0x5B (TSIPPKT *rpt, unsigned char *sv_prn, unsigned char *sv_health, 327290001Sglebius unsigned char *sv_iode, unsigned char *fit_interval_flag, 328290001Sglebius float *time_of_collection, float *time_of_eph, float *sv_accy); 329106424Srobertoshort rpt_0x5C (TSIPPKT *rpt, unsigned char *sv_prn, unsigned char *slot, 330290001Sglebius unsigned char *chan, unsigned char *acq_flag, unsigned char *eph_flag, 331290001Sglebius float *signal_level, float *time_of_last_msmt, float *elev, 332290001Sglebius float *azim, unsigned char *old_msmt_flag, 333290001Sglebius unsigned char *integer_msec_flag, unsigned char *bad_data_flag, 334290001Sglebius unsigned char *data_collect_flag); 335106424Srobertoshort rpt_0x6D (TSIPPKT *rpt, unsigned char *manual_mode, unsigned char *nsvs, 336290001Sglebius unsigned char *ndim, unsigned char sv_prn[], float *pdop, 337290001Sglebius float *hdop, float *vdop, float *tdop); 338106424Srobertoshort rpt_0x82 (TSIPPKT *rpt, unsigned char *diff_mode); 339106424Srobertoshort rpt_0x83 (TSIPPKT *rpt, double ECEF_pos[3], double *clock_bias, 340290001Sglebius float *time_of_fix); 341106424Srobertoshort rpt_0x84 (TSIPPKT *rpt, double *lat, double *lon, double *alt, 342290001Sglebius double *clock_bias, float *time_of_fix); 343106424Srobertoshort rpt_Paly0xBB(TSIPPKT *rpt, TSIP_RCVR_CFG *TsipxBB); 344106424Srobertoshort rpt_0xBC (TSIPPKT *rpt, unsigned char *port_num, 345290001Sglebius unsigned char *in_baud, unsigned char *out_baud, 346290001Sglebius unsigned char *data_bits, unsigned char *parity, 347290001Sglebius unsigned char *stop_bits, unsigned char *flow_control, 348290001Sglebius unsigned char *protocols_in, unsigned char *protocols_out, 349290001Sglebius unsigned char *reserved); 350106424Sroberto 351106424Sroberto/* prototypes for superpacket parsers */ 352106424Sroberto 353106424Srobertoshort rpt_0x8F0B (TSIPPKT *rpt, unsigned short *event, double *tow, 354290001Sglebius unsigned char *date, unsigned char *month, short *year, 355290001Sglebius unsigned char *dim_mode, short *utc_offset, double *bias, double *drift, 356290001Sglebius float *bias_unc, float *dr_unc, double *lat, double *lon, double *alt, 357290001Sglebius char sv_id[8]); 358106424Srobertoshort rpt_0x8F14 (TSIPPKT *rpt, short *datum_idx, double datum_coeffs[5]); 359106424Srobertoshort rpt_0x8F15 (TSIPPKT *rpt, short *datum_idx, double datum_coeffs[5]); 360106424Srobertoshort rpt_0x8F20 (TSIPPKT *rpt, unsigned char *info, double *lat, 361290001Sglebius double *lon, double *alt, double vel_enu[], double *time_of_fix, 362290001Sglebius short *week_num, unsigned char *nsvs, unsigned char sv_prn[], 363290001Sglebius short sv_IODC[], short *datum_index); 364106424Srobertoshort rpt_0x8F41 (TSIPPKT *rpt, unsigned char *bSearchRange, 365290001Sglebius unsigned char *bBoardOptions, unsigned long *iiSerialNumber, 366290001Sglebius unsigned char *bBuildYear, unsigned char *bBuildMonth, 367290001Sglebius unsigned char *bBuildDay, unsigned char *bBuildHour, 368290001Sglebius float *fOscOffset, unsigned short *iTestCodeId); 369106424Srobertoshort rpt_0x8F42 (TSIPPKT *rpt, unsigned char *bProdOptionsPre, 370290001Sglebius unsigned char *bProdNumberExt, unsigned short *iCaseSerialNumberPre, 371290001Sglebius unsigned long *iiCaseSerialNumber, unsigned long *iiProdNumber, 372290001Sglebius unsigned short *iPremiumOptions, unsigned short *iMachineID, 373290001Sglebius unsigned short *iKey); 374106424Srobertoshort rpt_0x8F45 (TSIPPKT *rpt, unsigned char *bSegMask); 375106424Srobertoshort rpt_0x8F4A_16 (TSIPPKT *rpt, unsigned char *pps_enabled, 376290001Sglebius unsigned char *pps_timebase, unsigned char *pos_polarity, 377290001Sglebius double *pps_offset, float *bias_unc_threshold); 378106424Srobertoshort rpt_0x8F4B (TSIPPKT *rpt, unsigned long *decorr_max); 379106424Srobertoshort rpt_0x8F4D (TSIPPKT *rpt, unsigned long *event_mask); 380106424Srobertoshort rpt_0x8FA5 (TSIPPKT *rpt, unsigned char *spktmask); 381106424Srobertoshort rpt_0x8FAD (TSIPPKT *rpt, unsigned short *COUNT, double *FracSec, 382290001Sglebius unsigned char *Hour, unsigned char *Minute, unsigned char *Second, 383290001Sglebius unsigned char *Day, unsigned char *Month, unsigned short *Year, 384290001Sglebius unsigned char *Status, unsigned char *Flags); 385106424Sroberto 386106424Sroberto/**/ 387106424Sroberto/* prototypes for command-encode primitives with suffix convention: */ 388106424Sroberto/* c = clear, s = set, q = query, e = enable, d = disable */ 389106424Srobertovoid cmd_0x1F (TSIPPKT *cmd); 390106424Srobertovoid cmd_0x26 (TSIPPKT *cmd); 391106424Srobertovoid cmd_0x2F (TSIPPKT *cmd); 392106424Srobertovoid cmd_0x35s (TSIPPKT *cmd, unsigned char pos_code, unsigned char vel_code, 393290001Sglebius unsigned char time_code, unsigned char opts_code); 394106424Srobertovoid cmd_0x3C (TSIPPKT *cmd, unsigned char sv_prn); 395106424Srobertovoid cmd_0x3Ds (TSIPPKT *cmd, unsigned char baud_out, unsigned char baud_inp, 396290001Sglebius unsigned char char_code, unsigned char stopbitcode, 397290001Sglebius unsigned char output_mode, unsigned char input_mode); 398106424Srobertovoid cmd_0xBBq (TSIPPKT *cmd, unsigned char subcode) ; 399106424Sroberto 400106424Sroberto/* prototypes 8E commands */ 401106424Srobertovoid cmd_0x8E0Bq (TSIPPKT *cmd); 402106424Srobertovoid cmd_0x8E41q (TSIPPKT *cmd); 403106424Srobertovoid cmd_0x8E42q (TSIPPKT *cmd); 404106424Srobertovoid cmd_0x8E4Aq (TSIPPKT *cmd); 405106424Srobertovoid cmd_0x8E4As (TSIPPKT *cmd, unsigned char PPSOnOff, unsigned char TimeBase, 406290001Sglebius unsigned char Polarity, double PPSOffset, float Uncertainty); 407106424Srobertovoid cmd_0x8E4Bq (TSIPPKT *cmd); 408106424Srobertovoid cmd_0x8E4Ds (TSIPPKT *cmd, unsigned long AutoOutputMask); 409106424Srobertovoid cmd_0x8EADq (TSIPPKT *cmd); 410106424Sroberto 411106424Sroberto/* header/source border XXXXXXXXXXXXXXXXXXXXXXXXXX */ 412106424Sroberto 413106424Sroberto/* Trimble parse functions */ 414290001Sglebiusstatic int parse0x8FAD (TSIPPKT *, struct peer *); 415290001Sglebiusstatic int parse0x8F0B (TSIPPKT *, struct peer *); 416106424Sroberto#ifdef TRIMBLE_OUTPUT_FUNC 417290001Sglebiusstatic int parseany (TSIPPKT *, struct peer *); 418290001Sglebiusstatic void TranslateTSIPReportToText (TSIPPKT *, char *); 419106424Sroberto#endif /* TRIMBLE_OUTPUT_FUNC */ 420290001Sglebiusstatic int parse0x5C (TSIPPKT *, struct peer *); 421290001Sglebiusstatic int parse0x4F (TSIPPKT *, struct peer *); 422290001Sglebiusstatic void tsip_input_proc (TSIPPKT *, int); 423106424Sroberto 424106424Sroberto/* Trimble helper functions */ 425290001Sglebiusstatic void bPutFloat (float *, unsigned char *); 426290001Sglebiusstatic void bPutDouble (double *, unsigned char *); 427290001Sglebiusstatic void bPutULong (unsigned long *, unsigned char *); 428290001Sglebiusstatic int print_msg_table_header (int rptcode, char *HdrStr, int force); 429290001Sglebiusstatic char * show_time (float time_of_week); 430106424Sroberto 431106424Sroberto/* RIPE NCC functions */ 432290001Sglebiusstatic void ripencc_control (int, const struct refclockstat *, 433290001Sglebius struct refclockstat *, struct peer *); 434290001Sglebiusstatic int ripencc_ppsapi (struct peer *, int, int); 435290001Sglebiusstatic int ripencc_get_pps_ts (struct ripencc_unit *, l_fp *); 436290001Sglebiusstatic int ripencc_start (int, struct peer *); 437290001Sglebiusstatic void ripencc_shutdown (int, struct peer *); 438290001Sglebiusstatic void ripencc_poll (int, struct peer *); 439290001Sglebiusstatic void ripencc_send (struct peer *, TSIPPKT spt); 440290001Sglebiusstatic void ripencc_receive (struct recvbuf *); 441106424Sroberto 442106424Sroberto/* fill in reflock structure for our clock */ 443106424Srobertostruct refclock refclock_ripencc = { 444106424Sroberto ripencc_start, /* start up driver */ 445106424Sroberto ripencc_shutdown, /* shut down driver */ 446106424Sroberto ripencc_poll, /* transmit poll message */ 447106424Sroberto ripencc_control, /* control function */ 448106424Sroberto noentry, /* initialize driver */ 449106424Sroberto noentry, /* debug info */ 450106424Sroberto NOFLAGS /* clock flags */ 451106424Sroberto}; 452106424Sroberto 453106424Sroberto/* 454106424Sroberto * Tables to compute the ddd of year form icky dd/mm timecode. Viva la 455106424Sroberto * leap. 456106424Sroberto */ 457106424Srobertostatic int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 458106424Srobertostatic int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 459106424Sroberto 460106424Sroberto 461106424Sroberto/* 462106424Sroberto * ripencc_start - open the GPS devices and initialize data for processing 463106424Sroberto */ 464106424Srobertostatic int 465106424Srobertoripencc_start(int unit, struct peer *peer) 466106424Sroberto{ 467106424Sroberto register struct ripencc_unit *up; 468106424Sroberto struct refclockproc *pp; 469106424Sroberto char device[40]; 470106424Sroberto int fd; 471106424Sroberto struct termios tio; 472106424Sroberto TSIPPKT spt; 473106424Sroberto 474290001Sglebius pp = peer->procptr; 475290001Sglebius 476106424Sroberto /* 477106424Sroberto * Open serial port 478106424Sroberto */ 479106424Sroberto (void)snprintf(device, sizeof(device), DEVICE, unit); 480290001Sglebius fd = refclock_open(device, SPEED232, LDISC_RAW); 481290001Sglebius if (fd <= 0) { 482290001Sglebius pp->io.fd = -1; 483106424Sroberto return (0); 484290001Sglebius } 485106424Sroberto 486290001Sglebius pp->io.fd = fd; 487290001Sglebius 488106424Sroberto /* from refclock_palisade.c */ 489106424Sroberto if (tcgetattr(fd, &tio) < 0) { 490106424Sroberto msyslog(LOG_ERR, "Palisade(%d) tcgetattr(fd, &tio): %m",unit); 491106424Sroberto return (0); 492106424Sroberto } 493106424Sroberto 494106424Sroberto /* 495106424Sroberto * set flags 496106424Sroberto */ 497106424Sroberto tio.c_cflag |= (PARENB|PARODD); 498106424Sroberto tio.c_iflag &= ~ICRNL; 499106424Sroberto if (tcsetattr(fd, TCSANOW, &tio) == -1) { 500106424Sroberto msyslog(LOG_ERR, "Palisade(%d) tcsetattr(fd, &tio): %m",unit); 501106424Sroberto return (0); 502106424Sroberto } 503106424Sroberto 504106424Sroberto /* 505106424Sroberto * Allocate and initialize unit structure 506106424Sroberto */ 507290001Sglebius up = emalloc_zero(sizeof(*up)); 508290001Sglebius 509106424Sroberto pp->io.clock_recv = ripencc_receive; 510290001Sglebius pp->io.srcclock = peer; 511106424Sroberto pp->io.datalen = 0; 512106424Sroberto if (!io_addclock(&pp->io)) { 513290001Sglebius pp->io.fd = -1; 514290001Sglebius close(fd); 515106424Sroberto free(up); 516106424Sroberto return (0); 517106424Sroberto } 518290001Sglebius pp->unitptr = up; 519106424Sroberto 520106424Sroberto /* 521106424Sroberto * Initialize miscellaneous variables 522106424Sroberto */ 523106424Sroberto peer->precision = PRECISION; 524106424Sroberto pp->clockdesc = DESCRIPTION; 525106424Sroberto memcpy((char *)&pp->refid, REFID, REFID_LEN); 526106424Sroberto up->pollcnt = 2; 527106424Sroberto up->unit = unit; 528106424Sroberto up->leapdelta = 0; 529106424Sroberto up->utcflags = 0; 530106424Sroberto 531106424Sroberto /* 532106424Sroberto * Initialize the Clock 533106424Sroberto */ 534106424Sroberto 535106424Sroberto /* query software versions */ 536106424Sroberto cmd_0x1F(&spt); 537106424Sroberto ripencc_send(peer, spt); 538106424Sroberto 539106424Sroberto /* query receiver health */ 540106424Sroberto cmd_0x26(&spt); 541106424Sroberto ripencc_send(peer, spt); 542106424Sroberto 543106424Sroberto /* query serial numbers */ 544106424Sroberto cmd_0x8E42q(&spt); 545106424Sroberto ripencc_send(peer, spt); 546106424Sroberto 547106424Sroberto /* query manuf params */ 548106424Sroberto cmd_0x8E41q(&spt); 549106424Sroberto ripencc_send(peer, spt); 550106424Sroberto 551106424Sroberto /* i/o opts */ /* trimble manual page A30 */ 552106424Sroberto cmd_0x35s(&spt, 553290001Sglebius 0x1C, /* position */ 554290001Sglebius 0x00, /* velocity */ 555290001Sglebius 0x05, /* timing */ 556290001Sglebius 0x0a); /* auxilary */ 557106424Sroberto ripencc_send(peer, spt); 558106424Sroberto 559106424Sroberto /* turn off port A */ 560106424Sroberto cmd_0x3Ds (&spt, 561290001Sglebius 0x0B, /* baud_out */ 562290001Sglebius 0x0B, /* baud_inp */ 563290001Sglebius 0x07, /* char_code */ 564290001Sglebius 0x07, /* stopbitcode */ 565290001Sglebius 0x01, /* output_mode */ 566290001Sglebius 0x00); /* input_mode */ 567106424Sroberto ripencc_send(peer, spt); 568106424Sroberto 569106424Sroberto /* set i/o options */ 570106424Sroberto cmd_0x8E4As (&spt, 571290001Sglebius 0x01, /* PPS on */ 572290001Sglebius 0x01, /* Timebase UTC */ 573290001Sglebius 0x00, /* polarity positive */ 574290001Sglebius 0., /* 100 ft. cable XXX make flag */ 575290001Sglebius 1e-6 * GPS_C); /* turn of biasuncert. > (1us) */ 576106424Sroberto ripencc_send(peer,spt); 577106424Sroberto 578106424Sroberto /* all outomatic packet output off */ 579106424Sroberto cmd_0x8E4Ds(&spt, 580290001Sglebius 0x00000000); /* AutoOutputMask */ 581106424Sroberto ripencc_send(peer, spt); 582106424Sroberto 583106424Sroberto cmd_0xBBq (&spt, 584290001Sglebius 0x00); /* query primary configuration */ 585106424Sroberto ripencc_send(peer,spt); 586106424Sroberto 587106424Sroberto 588106424Sroberto /* query PPS parameters */ 589290001Sglebius cmd_0x8E4Aq (&spt); /* query PPS params */ 590106424Sroberto ripencc_send(peer,spt); 591106424Sroberto 592106424Sroberto /* query survey limit */ 593290001Sglebius cmd_0x8E4Bq (&spt); /* query survey limit */ 594106424Sroberto ripencc_send(peer,spt); 595106424Sroberto 596106424Sroberto#ifdef DEBUG_NCC 597106424Sroberto if (debug) 598106424Sroberto printf("ripencc_start: success\n"); 599106424Sroberto#endif /* DEBUG_NCC */ 600106424Sroberto 601106424Sroberto /* 602106424Sroberto * Start the PPSAPI interface if it is there. Default to use 603106424Sroberto * the assert edge and do not enable the kernel hardpps. 604106424Sroberto */ 605106424Sroberto if (time_pps_create(fd, &up->handle) < 0) { 606106424Sroberto up->handle = 0; 607106424Sroberto msyslog(LOG_ERR, "refclock_ripencc: time_pps_create failed: %m"); 608106424Sroberto return (1); 609106424Sroberto } 610106424Sroberto 611132451Sroberto return(ripencc_ppsapi(peer, 0, 0)); 612106424Sroberto} 613106424Sroberto 614106424Sroberto/* 615106424Sroberto * ripencc_control - fudge control 616106424Sroberto */ 617106424Srobertostatic void 618106424Srobertoripencc_control( 619106424Sroberto int unit, /* unit (not used) */ 620290001Sglebius const struct refclockstat *in, /* input parameters (not used) */ 621106424Sroberto struct refclockstat *out, /* output parameters (not used) */ 622106424Sroberto struct peer *peer /* peer structure pointer */ 623106424Sroberto ) 624106424Sroberto{ 625106424Sroberto struct refclockproc *pp; 626106424Sroberto 627106424Sroberto#ifdef DEBUG_NCC 628106424Sroberto msyslog(LOG_INFO,"%s()",__FUNCTION__); 629106424Sroberto#endif /* DEBUG_NCC */ 630106424Sroberto 631106424Sroberto pp = peer->procptr; 632106424Sroberto ripencc_ppsapi(peer, pp->sloppyclockflag & CLK_FLAG2, 633290001Sglebius pp->sloppyclockflag & CLK_FLAG3); 634106424Sroberto} 635106424Sroberto 636106424Sroberto 637106424Sroberto/* 638106424Sroberto * Initialize PPSAPI 639106424Sroberto */ 640106424Srobertoint 641106424Srobertoripencc_ppsapi( 642106424Sroberto struct peer *peer, /* peer structure pointer */ 643106424Sroberto int enb_clear, /* clear enable */ 644106424Sroberto int enb_hardpps /* hardpps enable */ 645106424Sroberto ) 646106424Sroberto{ 647106424Sroberto struct refclockproc *pp; 648106424Sroberto struct ripencc_unit *up; 649106424Sroberto int capability; 650106424Sroberto 651106424Sroberto pp = peer->procptr; 652290001Sglebius up = pp->unitptr; 653106424Sroberto if (time_pps_getcap(up->handle, &capability) < 0) { 654106424Sroberto msyslog(LOG_ERR, 655290001Sglebius "refclock_ripencc: time_pps_getcap failed: %m"); 656106424Sroberto return (0); 657106424Sroberto } 658106424Sroberto memset(&up->pps_params, 0, sizeof(pps_params_t)); 659106424Sroberto if (enb_clear) 660106424Sroberto up->pps_params.mode = capability & PPS_CAPTURECLEAR; 661106424Sroberto else 662106424Sroberto up->pps_params.mode = capability & PPS_CAPTUREASSERT; 663106424Sroberto if (!up->pps_params.mode) { 664106424Sroberto msyslog(LOG_ERR, 665290001Sglebius "refclock_ripencc: invalid capture edge %d", 666290001Sglebius !enb_clear); 667106424Sroberto return (0); 668106424Sroberto } 669106424Sroberto up->pps_params.mode |= PPS_TSFMT_TSPEC; 670106424Sroberto if (time_pps_setparams(up->handle, &up->pps_params) < 0) { 671106424Sroberto msyslog(LOG_ERR, 672290001Sglebius "refclock_ripencc: time_pps_setparams failed: %m"); 673106424Sroberto return (0); 674106424Sroberto } 675106424Sroberto if (enb_hardpps) { 676106424Sroberto if (time_pps_kcbind(up->handle, PPS_KC_HARDPPS, 677106424Sroberto up->pps_params.mode & ~PPS_TSFMT_TSPEC, 678106424Sroberto PPS_TSFMT_TSPEC) < 0) { 679106424Sroberto msyslog(LOG_ERR, 680290001Sglebius "refclock_ripencc: time_pps_kcbind failed: %m"); 681106424Sroberto return (0); 682106424Sroberto } 683290001Sglebius hardpps_enable = 1; 684106424Sroberto } 685106424Sroberto peer->precision = PPS_PRECISION; 686106424Sroberto 687106424Sroberto#if DEBUG_NCC 688106424Sroberto if (debug) { 689106424Sroberto time_pps_getparams(up->handle, &up->pps_params); 690106424Sroberto printf( 691290001Sglebius "refclock_ripencc: capability 0x%x version %d mode 0x%x kern %d\n", 692290001Sglebius capability, up->pps_params.api_version, 693290001Sglebius up->pps_params.mode, enb_hardpps); 694106424Sroberto } 695106424Sroberto#endif /* DEBUG_NCC */ 696106424Sroberto 697106424Sroberto return (1); 698106424Sroberto} 699106424Sroberto 700106424Sroberto/* 701106424Sroberto * This function is called every 64 seconds from ripencc_receive 702106424Sroberto * It will fetch the pps time 703106424Sroberto * 704106424Sroberto * Return 0 on failure and 1 on success. 705106424Sroberto */ 706106424Srobertostatic int 707106424Srobertoripencc_get_pps_ts( 708106424Sroberto struct ripencc_unit *up, 709106424Sroberto l_fp *tsptr 710106424Sroberto ) 711106424Sroberto{ 712106424Sroberto pps_info_t pps_info; 713106424Sroberto struct timespec timeout, ts; 714106424Sroberto double dtemp; 715106424Sroberto l_fp tstmp; 716106424Sroberto 717106424Sroberto#ifdef DEBUG_PPS 718290001Sglebius msyslog(LOG_INFO,"ripencc_get_pps_ts"); 719106424Sroberto#endif /* DEBUG_PPS */ 720106424Sroberto 721106424Sroberto 722106424Sroberto /* 723106424Sroberto * Convert the timespec nanoseconds field to ntp l_fp units. 724106424Sroberto */ 725106424Sroberto if (up->handle == 0) 726106424Sroberto return (0); 727106424Sroberto timeout.tv_sec = 0; 728106424Sroberto timeout.tv_nsec = 0; 729106424Sroberto memcpy(&pps_info, &up->pps_info, sizeof(pps_info_t)); 730106424Sroberto if (time_pps_fetch(up->handle, PPS_TSFMT_TSPEC, &up->pps_info, 731290001Sglebius &timeout) < 0) 732106424Sroberto return (0); 733106424Sroberto if (up->pps_params.mode & PPS_CAPTUREASSERT) { 734106424Sroberto if (pps_info.assert_sequence == 735106424Sroberto up->pps_info.assert_sequence) 736106424Sroberto return (0); 737106424Sroberto ts = up->pps_info.assert_timestamp; 738106424Sroberto } else if (up->pps_params.mode & PPS_CAPTURECLEAR) { 739106424Sroberto if (pps_info.clear_sequence == 740106424Sroberto up->pps_info.clear_sequence) 741106424Sroberto return (0); 742106424Sroberto ts = up->pps_info.clear_timestamp; 743106424Sroberto } else { 744106424Sroberto return (0); 745106424Sroberto } 746106424Sroberto if ((up->ts.tv_sec == ts.tv_sec) && (up->ts.tv_nsec == ts.tv_nsec)) 747106424Sroberto return (0); 748106424Sroberto up->ts = ts; 749106424Sroberto 750106424Sroberto tstmp.l_ui = ts.tv_sec + JAN_1970; 751106424Sroberto dtemp = ts.tv_nsec * FRAC / 1e9; 752106424Sroberto tstmp.l_uf = (u_int32)dtemp; 753106424Sroberto 754106424Sroberto#ifdef DEBUG_PPS 755290001Sglebius msyslog(LOG_INFO,"ts.tv_sec: %d",(int)ts.tv_sec); 756290001Sglebius msyslog(LOG_INFO,"ts.tv_nsec: %ld",ts.tv_nsec); 757106424Sroberto#endif /* DEBUG_PPS */ 758106424Sroberto 759106424Sroberto *tsptr = tstmp; 760106424Sroberto return (1); 761106424Sroberto} 762106424Sroberto 763106424Sroberto/* 764106424Sroberto * ripencc_shutdown - shut down a GPS clock 765106424Sroberto */ 766106424Srobertostatic void 767106424Srobertoripencc_shutdown(int unit, struct peer *peer) 768106424Sroberto{ 769106424Sroberto register struct ripencc_unit *up; 770106424Sroberto struct refclockproc *pp; 771106424Sroberto 772106424Sroberto pp = peer->procptr; 773290001Sglebius up = pp->unitptr; 774106424Sroberto 775290001Sglebius if (up != NULL) { 776290001Sglebius if (up->handle != 0) 777290001Sglebius time_pps_destroy(up->handle); 778290001Sglebius free(up); 779290001Sglebius } 780290001Sglebius if (-1 != pp->io.fd) 781290001Sglebius io_closeclock(&pp->io); 782106424Sroberto 783290001Sglebius return; 784106424Sroberto} 785106424Sroberto 786106424Sroberto/* 787106424Sroberto * ripencc_poll - called by the transmit procedure 788106424Sroberto */ 789106424Srobertostatic void 790106424Srobertoripencc_poll(int unit, struct peer *peer) 791106424Sroberto{ 792106424Sroberto register struct ripencc_unit *up; 793106424Sroberto struct refclockproc *pp; 794106424Sroberto TSIPPKT spt; 795106424Sroberto 796106424Sroberto#ifdef DEBUG_NCC 797106424Sroberto if (debug) 798106424Sroberto fprintf(stderr, "ripencc_poll(%d)\n", unit); 799106424Sroberto#endif /* DEBUG_NCC */ 800106424Sroberto pp = peer->procptr; 801290001Sglebius up = pp->unitptr; 802106424Sroberto if (up->pollcnt == 0) 803106424Sroberto refclock_report(peer, CEVNT_TIMEOUT); 804106424Sroberto else 805106424Sroberto up->pollcnt--; 806106424Sroberto 807106424Sroberto pp->polls++; 808106424Sroberto up->polled = 1; 809106424Sroberto 810106424Sroberto /* poll for UTC superpacket */ 811106424Sroberto cmd_0x8EADq (&spt); 812106424Sroberto ripencc_send(peer,spt); 813106424Sroberto} 814106424Sroberto 815106424Sroberto/* 816106424Sroberto * ripencc_send - send message to clock 817106424Sroberto * use the structures being created by the trimble functions! 818106424Sroberto * makes the code more readable/clean 819106424Sroberto */ 820106424Srobertostatic void 821106424Srobertoripencc_send(struct peer *peer, TSIPPKT spt) 822106424Sroberto{ 823106424Sroberto unsigned char *ip, *op; 824106424Sroberto unsigned char obuf[512]; 825106424Sroberto 826106424Sroberto#ifdef DEBUG_RAW 827106424Sroberto { 828106424Sroberto register struct ripencc_unit *up; 829106424Sroberto register struct refclockproc *pp; 830106424Sroberto 831106424Sroberto pp = peer->procptr; 832290001Sglebius up = pp->unitptr; 833106424Sroberto if (debug) 834106424Sroberto printf("ripencc_send(%d, %02X)\n", up->unit, cmd); 835106424Sroberto } 836106424Sroberto#endif /* DEBUG_RAW */ 837106424Sroberto 838106424Sroberto ip = spt.buf; 839106424Sroberto op = obuf; 840106424Sroberto 841106424Sroberto *op++ = 0x10; 842106424Sroberto *op++ = spt.code; 843106424Sroberto 844106424Sroberto while (spt.len--) { 845106424Sroberto if (op-obuf > sizeof(obuf)-5) { 846106424Sroberto msyslog(LOG_ERR, "ripencc_send obuf overflow!"); 847106424Sroberto refclock_report(peer, CEVNT_FAULT); 848106424Sroberto return; 849106424Sroberto } 850106424Sroberto 851290001Sglebius if (*ip == 0x10) /* byte stuffing */ 852106424Sroberto *op++ = 0x10; 853106424Sroberto *op++ = *ip++; 854106424Sroberto } 855106424Sroberto 856106424Sroberto *op++ = 0x10; 857106424Sroberto *op++ = 0x03; 858106424Sroberto 859106424Sroberto#ifdef DEBUG_RAW 860106424Sroberto if (debug) { /* print raw packet */ 861106424Sroberto unsigned char *cp; 862106424Sroberto int i; 863106424Sroberto 864106424Sroberto printf("ripencc_send: len %d\n", op-obuf); 865106424Sroberto for (i=1, cp=obuf; cp<op; i++, cp++) { 866106424Sroberto printf(" %02X", *cp); 867106424Sroberto if (i%10 == 0) 868106424Sroberto printf("\n"); 869106424Sroberto } 870106424Sroberto printf("\n"); 871106424Sroberto } 872106424Sroberto#endif /* DEBUG_RAW */ 873106424Sroberto 874106424Sroberto if (write(peer->procptr->io.fd, obuf, op-obuf) == -1) { 875290001Sglebius refclock_report(peer, CEVNT_FAULT); 876106424Sroberto } 877106424Sroberto} 878106424Sroberto 879106424Sroberto/* 880106424Sroberto * ripencc_receive() 881106424Sroberto * 882106424Sroberto * called when a packet is received on the serial port 883106424Sroberto * takes care of further processing 884106424Sroberto * 885106424Sroberto */ 886106424Srobertostatic void 887106424Srobertoripencc_receive(struct recvbuf *rbufp) 888106424Sroberto{ 889106424Sroberto register struct ripencc_unit *up; 890106424Sroberto register struct refclockproc *pp; 891106424Sroberto struct peer *peer; 892290001Sglebius static TSIPPKT rpt; /* for current incoming TSIP report */ 893290001Sglebius TSIPPKT spt; /* send packet */ 894106424Sroberto int ns_since_pps; 895106424Sroberto int i; 896106424Sroberto char *cp; 897290001Sglebius /* these variables hold data until we decide it's worth keeping */ 898106424Sroberto char rd_lastcode[BMAX]; 899106424Sroberto l_fp rd_tmp; 900106424Sroberto u_short rd_lencode; 901106424Sroberto 902106424Sroberto /* msyslog(LOG_INFO, "%s",__FUNCTION__); */ 903106424Sroberto 904106424Sroberto /* 905106424Sroberto * Initialize pointers and read the timecode and timestamp 906106424Sroberto */ 907290001Sglebius peer = rbufp->recv_peer; 908106424Sroberto pp = peer->procptr; 909290001Sglebius up = pp->unitptr; 910106424Sroberto rd_lencode = refclock_gtlin(rbufp, rd_lastcode, BMAX, &rd_tmp); 911106424Sroberto 912106424Sroberto#ifdef DEBUG_RAW 913106424Sroberto if (debug) 914106424Sroberto fprintf(stderr, "ripencc_receive(%d)\n", up->unit); 915106424Sroberto#endif /* DEBUG_RAW */ 916106424Sroberto 917106424Sroberto#ifdef DEBUG_RAW 918290001Sglebius if (debug) { /* print raw packet */ 919106424Sroberto int i; 920106424Sroberto unsigned char *cp; 921106424Sroberto 922106424Sroberto printf("ripencc_receive: len %d\n", rbufp->recv_length); 923290001Sglebius for (i=1, cp=(char*)&rbufp->recv_space; 924290001Sglebius i <= rbufp->recv_length; 925290001Sglebius i++, cp++) { 926106424Sroberto printf(" %02X", *cp); 927106424Sroberto if (i%10 == 0) 928106424Sroberto printf("\n"); 929106424Sroberto } 930106424Sroberto printf("\n"); 931106424Sroberto } 932106424Sroberto#endif /* DEBUG_RAW */ 933106424Sroberto 934106424Sroberto cp = (char*) &rbufp->recv_space; 935106424Sroberto i=rbufp->recv_length; 936106424Sroberto 937290001Sglebius while (i--) { /* loop over received chars */ 938106424Sroberto 939106424Sroberto tsip_input_proc(&rpt, (unsigned char) *cp++); 940106424Sroberto 941106424Sroberto if (rpt.status != TSIP_PARSED_FULL) 942106424Sroberto continue; 943106424Sroberto 944106424Sroberto switch (rpt.code) { 945106424Sroberto 946290001Sglebius case 0x8F: /* superpacket */ 947106424Sroberto 948106424Sroberto switch (rpt.buf[0]) { 949106424Sroberto 950290001Sglebius case 0xAD: /* UTC Time */ 951106424Sroberto /* 952290001Sglebius ** When polling on port B the timecode is 953290001Sglebius ** the time of the previous PPS. If we 954290001Sglebius ** completed receiving the packet less than 955290001Sglebius ** 150ms after the turn of the second, it 956290001Sglebius ** may have the code of the previous second. 957290001Sglebius ** We do not trust that and simply poll 958290001Sglebius ** again without even parsing it. 959290001Sglebius ** 960290001Sglebius ** More elegant would be to re-schedule the 961290001Sglebius ** poll, but I do not know (yet) how to do 962290001Sglebius ** that cleanly. 963290001Sglebius ** 964290001Sglebius */ 965106424Sroberto /* BLA ns_since_pps = ncc_tstmp(rbufp, &trtmp); */ 966106424Sroberto/* if (up->polled && ns_since_pps > -1 && ns_since_pps < 150) { */ 967106424Sroberto 968290001Sglebius ns_since_pps = 200; 969106424Sroberto if (up->polled && ns_since_pps < 150) { 970290001Sglebius msyslog(LOG_INFO, "%s(): up->polled", 971290001Sglebius __FUNCTION__); 972106424Sroberto ripencc_poll(up->unit, peer); 973106424Sroberto break; 974106424Sroberto } 975106424Sroberto 976106424Sroberto /* 977106424Sroberto * Parse primary utc time packet 978106424Sroberto * and fill refclock structure 979106424Sroberto * from results. 980106424Sroberto */ 981106424Sroberto if (parse0x8FAD(&rpt, peer) < 0) { 982290001Sglebius msyslog(LOG_INFO, "%s(): parse0x8FAD < 0",__FUNCTION__); 983290001Sglebius refclock_report(peer, CEVNT_BADREPLY); 984290001Sglebius break; 985106424Sroberto } 986106424Sroberto /* 987106424Sroberto * If the PPSAPI is working, rather use its 988106424Sroberto * timestamps. 989106424Sroberto * assume that the PPS occurs on the second 990106424Sroberto * so blow any msec 991106424Sroberto */ 992106424Sroberto if (ripencc_get_pps_ts(up, &rd_tmp) == 1) { 993106424Sroberto pp->lastrec = up->tstamp = rd_tmp; 994132451Sroberto pp->nsec = 0; 995106424Sroberto } 996106424Sroberto else 997290001Sglebius msyslog(LOG_INFO, "%s(): ripencc_get_pps_ts returns failure",__FUNCTION__); 998106424Sroberto 999106424Sroberto 1000106424Sroberto if (!up->polled) { 1001290001Sglebius msyslog(LOG_INFO, "%s(): unrequested packet",__FUNCTION__); 1002106424Sroberto /* unrequested packet */ 1003106424Sroberto break; 1004106424Sroberto } 1005106424Sroberto 1006106424Sroberto /* we have been polled ! */ 1007106424Sroberto up->polled = 0; 1008106424Sroberto up->pollcnt = 2; 1009106424Sroberto 1010106424Sroberto /* poll for next packet */ 1011106424Sroberto cmd_0x8E0Bq(&spt); 1012106424Sroberto ripencc_send(peer,spt); 1013106424Sroberto 1014106424Sroberto if (ns_since_pps < 0) { /* no PPS */ 1015106424Sroberto msyslog(LOG_INFO, "%s(): ns_since_pps < 0",__FUNCTION__); 1016106424Sroberto refclock_report(peer, CEVNT_BADTIME); 1017106424Sroberto break; 1018106424Sroberto } 1019106424Sroberto 1020106424Sroberto /* 1021290001Sglebius ** Process the new sample in the median 1022290001Sglebius ** filter and determine the reference clock 1023290001Sglebius ** offset and dispersion. 1024290001Sglebius */ 1025106424Sroberto if (!refclock_process(pp)) { 1026106424Sroberto msyslog(LOG_INFO, "%s(): !refclock_process",__FUNCTION__); 1027106424Sroberto refclock_report(peer, CEVNT_BADTIME); 1028106424Sroberto break; 1029106424Sroberto } 1030106424Sroberto 1031106424Sroberto refclock_receive(peer); 1032106424Sroberto break; 1033106424Sroberto 1034290001Sglebius case 0x0B: /* comprehensive time packet */ 1035106424Sroberto parse0x8F0B(&rpt, peer); 1036106424Sroberto break; 1037106424Sroberto 1038290001Sglebius default: /* other superpackets */ 1039106424Sroberto#ifdef DEBUG_NCC 1040290001Sglebius msyslog(LOG_INFO, "%s(): calling parseany", 1041290001Sglebius __FUNCTION__); 1042106424Sroberto#endif /* DEBUG_NCC */ 1043106424Sroberto#ifdef TRIMBLE_OUTPUT_FUNC 1044106424Sroberto parseany(&rpt, peer); 1045106424Sroberto#endif /* TRIMBLE_OUTPUT_FUNC */ 1046106424Sroberto break; 1047106424Sroberto } 1048106424Sroberto break; 1049106424Sroberto 1050290001Sglebius case 0x4F: /* UTC parameters, for leap info */ 1051106424Sroberto parse0x4F(&rpt, peer); 1052106424Sroberto break; 1053106424Sroberto 1054290001Sglebius case 0x5C: /* sat tracking data */ 1055106424Sroberto parse0x5C(&rpt, peer); 1056106424Sroberto break; 1057106424Sroberto 1058290001Sglebius default: /* other packets */ 1059106424Sroberto#ifdef TRIMBLE_OUTPUT_FUNC 1060106424Sroberto parseany(&rpt, peer); 1061106424Sroberto#endif /* TRIMBLE_OUTPUT_FUNC */ 1062106424Sroberto break; 1063106424Sroberto } 1064106424Sroberto rpt.status = TSIP_PARSED_EMPTY; 1065106424Sroberto } 1066106424Sroberto} 1067106424Sroberto 1068106424Sroberto/* 1069106424Sroberto * All trimble functions that are directly referenced from driver code 1070106424Sroberto * (so not from parseany) 1071106424Sroberto */ 1072106424Sroberto 1073106424Sroberto/* request software versions */ 1074290001Sglebiusvoid 1075290001Sglebiuscmd_0x1F( 1076290001Sglebius TSIPPKT *cmd 1077290001Sglebius ) 1078106424Sroberto{ 1079106424Sroberto cmd->len = 0; 1080106424Sroberto cmd->code = 0x1F; 1081106424Sroberto} 1082106424Sroberto 1083106424Sroberto/* request receiver health */ 1084290001Sglebiusvoid 1085290001Sglebiuscmd_0x26( 1086290001Sglebius TSIPPKT *cmd 1087290001Sglebius ) 1088106424Sroberto{ 1089106424Sroberto cmd->len = 0; 1090106424Sroberto cmd->code = 0x26; 1091106424Sroberto} 1092106424Sroberto 1093106424Sroberto/* request UTC params */ 1094290001Sglebiusvoid 1095290001Sglebiuscmd_0x2F( 1096290001Sglebius TSIPPKT *cmd 1097290001Sglebius ) 1098106424Sroberto{ 1099106424Sroberto cmd->len = 0; 1100106424Sroberto cmd->code = 0x2F; 1101106424Sroberto} 1102106424Sroberto 1103106424Sroberto/* set serial I/O options */ 1104290001Sglebiusvoid 1105290001Sglebiuscmd_0x35s( 1106290001Sglebius TSIPPKT *cmd, 1107290001Sglebius unsigned char pos_code, 1108290001Sglebius unsigned char vel_code, 1109290001Sglebius unsigned char time_code, 1110290001Sglebius unsigned char opts_code 1111290001Sglebius ) 1112106424Sroberto{ 1113106424Sroberto cmd->buf[0] = pos_code; 1114106424Sroberto cmd->buf[1] = vel_code; 1115106424Sroberto cmd->buf[2] = time_code; 1116106424Sroberto cmd->buf[3] = opts_code; 1117106424Sroberto cmd->len = 4; 1118106424Sroberto cmd->code = 0x35; 1119106424Sroberto} 1120290001Sglebius 1121106424Sroberto/* request tracking status */ 1122290001Sglebiusvoid 1123290001Sglebiuscmd_0x3C( 1124290001Sglebius TSIPPKT *cmd, 1125290001Sglebius unsigned char sv_prn 1126290001Sglebius ) 1127106424Sroberto{ 1128106424Sroberto cmd->buf[0] = sv_prn; 1129106424Sroberto cmd->len = 1; 1130106424Sroberto cmd->code = 0x3C; 1131106424Sroberto} 1132106424Sroberto 1133106424Sroberto/* set Channel A configuration for dual-port operation */ 1134290001Sglebiusvoid 1135290001Sglebiuscmd_0x3Ds( 1136290001Sglebius TSIPPKT *cmd, 1137290001Sglebius unsigned char baud_out, 1138290001Sglebius unsigned char baud_inp, 1139290001Sglebius unsigned char char_code, 1140290001Sglebius unsigned char stopbitcode, 1141290001Sglebius unsigned char output_mode, 1142290001Sglebius unsigned char input_mode 1143290001Sglebius ) 1144106424Sroberto{ 1145106424Sroberto cmd->buf[0] = baud_out; /* XMT baud rate */ 1146106424Sroberto cmd->buf[1] = baud_inp; /* RCV baud rate */ 1147290001Sglebius cmd->buf[2] = char_code; /* parity and #bits per byte */ 1148106424Sroberto cmd->buf[3] = stopbitcode; /* number of stop bits code */ 1149106424Sroberto cmd->buf[4] = output_mode; /* Ch. A transmission mode */ 1150106424Sroberto cmd->buf[5] = input_mode; /* Ch. A reception mode */ 1151106424Sroberto cmd->len = 6; 1152106424Sroberto cmd->code = 0x3D; 1153106424Sroberto} 1154106424Sroberto 1155106424Sroberto 1156106424Sroberto/* query primary configuration */ 1157290001Sglebiusvoid 1158290001Sglebiuscmd_0xBBq( 1159290001Sglebius TSIPPKT *cmd, 1160290001Sglebius unsigned char subcode 1161290001Sglebius ) 1162106424Sroberto{ 1163106424Sroberto cmd->len = 1; 1164106424Sroberto cmd->code = 0xBB; 1165106424Sroberto cmd->buf[0] = subcode; 1166106424Sroberto} 1167106424Sroberto 1168106424Sroberto 1169106424Sroberto/**** Superpackets ****/ 1170106424Sroberto/* 8E-0B to query 8F-0B controls */ 1171290001Sglebiusvoid 1172290001Sglebiuscmd_0x8E0Bq( 1173290001Sglebius TSIPPKT *cmd 1174290001Sglebius ) 1175106424Sroberto{ 1176106424Sroberto cmd->len = 1; 1177106424Sroberto cmd->code = 0x8E; 1178106424Sroberto cmd->buf[0] = 0x0B; 1179106424Sroberto} 1180106424Sroberto 1181106424Sroberto 1182106424Sroberto/* 8F-41 to query board serial number */ 1183290001Sglebiusvoid 1184290001Sglebiuscmd_0x8E41q( 1185290001Sglebius TSIPPKT *cmd 1186290001Sglebius ) 1187106424Sroberto{ 1188106424Sroberto cmd->len = 1; 1189106424Sroberto cmd->code = 0x8E; 1190106424Sroberto cmd->buf[0] = 0x41; 1191106424Sroberto} 1192106424Sroberto 1193106424Sroberto 1194106424Sroberto/* 8F-42 to query product serial number */ 1195290001Sglebiusvoid 1196290001Sglebiuscmd_0x8E42q( 1197290001Sglebius TSIPPKT *cmd 1198290001Sglebius ) 1199106424Sroberto{ 1200106424Sroberto cmd->len = 1; 1201106424Sroberto cmd->code = 0x8E; 1202106424Sroberto cmd->buf[0] = 0x42; 1203106424Sroberto} 1204290001Sglebius 1205290001Sglebius 1206106424Sroberto/* 8F-4A to query PPS parameters */ 1207290001Sglebiusvoid 1208290001Sglebiuscmd_0x8E4Aq( 1209290001Sglebius TSIPPKT *cmd 1210290001Sglebius ) 1211106424Sroberto{ 1212106424Sroberto cmd->len = 1; 1213106424Sroberto cmd->code = 0x8E; 1214106424Sroberto cmd->buf[0] = 0x4A; 1215106424Sroberto} 1216106424Sroberto 1217106424Sroberto 1218106424Sroberto/* set i/o options */ 1219290001Sglebiusvoid 1220290001Sglebiuscmd_0x8E4As( 1221290001Sglebius TSIPPKT *cmd, 1222290001Sglebius unsigned char PPSOnOff, 1223290001Sglebius unsigned char TimeBase, 1224290001Sglebius unsigned char Polarity, 1225290001Sglebius double PPSOffset, 1226290001Sglebius float Uncertainty 1227290001Sglebius ) 1228106424Sroberto{ 1229106424Sroberto cmd->len = 16; 1230106424Sroberto cmd->code = 0x8E; 1231106424Sroberto cmd->buf[0] = 0x4A; 1232106424Sroberto cmd->buf[1] = PPSOnOff; 1233106424Sroberto cmd->buf[2] = TimeBase; 1234106424Sroberto cmd->buf[3] = Polarity; 1235106424Sroberto bPutDouble (&PPSOffset, &cmd->buf[4]); 1236106424Sroberto bPutFloat (&Uncertainty, &cmd->buf[12]); 1237106424Sroberto} 1238290001Sglebius 1239106424Sroberto/* 8F-4B query survey limit */ 1240290001Sglebiusvoid 1241290001Sglebiuscmd_0x8E4Bq( 1242290001Sglebius TSIPPKT *cmd 1243290001Sglebius ) 1244106424Sroberto{ 1245106424Sroberto cmd->len = 1; 1246106424Sroberto cmd->code = 0x8E; 1247106424Sroberto cmd->buf[0] = 0x4B; 1248106424Sroberto} 1249106424Sroberto 1250106424Sroberto/* poll for UTC superpacket */ 1251106424Sroberto/* 8E-AD to query 8F-AD controls */ 1252290001Sglebiusvoid 1253290001Sglebiuscmd_0x8EADq( 1254290001Sglebius TSIPPKT *cmd 1255290001Sglebius ) 1256106424Sroberto{ 1257106424Sroberto cmd->len = 1; 1258106424Sroberto cmd->code = 0x8E; 1259106424Sroberto cmd->buf[0] = 0xAD; 1260106424Sroberto} 1261106424Sroberto 1262106424Sroberto/* all outomatic packet output off */ 1263290001Sglebiusvoid 1264290001Sglebiuscmd_0x8E4Ds( 1265290001Sglebius TSIPPKT *cmd, 1266290001Sglebius unsigned long AutoOutputMask 1267290001Sglebius ) 1268106424Sroberto{ 1269106424Sroberto cmd->len = 5; 1270106424Sroberto cmd->code = 0x8E; 1271106424Sroberto cmd->buf[0] = 0x4D; 1272106424Sroberto bPutULong (&AutoOutputMask, &cmd->buf[1]); 1273106424Sroberto} 1274106424Sroberto 1275106424Sroberto 1276290001Sglebius/* 1277290001Sglebius * for DOS machines, reverse order of bytes as they come through the 1278290001Sglebius * serial port. 1279290001Sglebius */ 1280106424Sroberto#ifdef BYTESWAP 1281290001Sglebiusstatic short 1282290001SglebiusbGetShort( 1283290001Sglebius unsigned char *bp 1284290001Sglebius ) 1285106424Sroberto{ 1286106424Sroberto short outval; 1287290001Sglebius unsigned char *optr; 1288106424Sroberto 1289290001Sglebius optr = (unsigned char*)&outval + 1; 1290290001Sglebius *optr-- = *bp++; 1291290001Sglebius *optr = *bp; 1292106424Sroberto return outval; 1293106424Sroberto} 1294106424Sroberto 1295106424Sroberto#ifdef TRIMBLE_OUTPUT_FUNC 1296290001Sglebiusstatic unsigned short 1297290001SglebiusbGetUShort( 1298290001Sglebius unsigned char *bp 1299290001Sglebius ) 1300106424Sroberto{ 1301106424Sroberto unsigned short outval; 1302290001Sglebius unsigned char *optr; 1303106424Sroberto 1304290001Sglebius optr = (unsigned char*)&outval + 1; 1305290001Sglebius *optr-- = *bp++; 1306290001Sglebius *optr = *bp; 1307106424Sroberto return outval; 1308106424Sroberto} 1309106424Sroberto 1310290001Sglebiusstatic long 1311290001SglebiusbGetLong( 1312290001Sglebius unsigned char *bp 1313290001Sglebius ) 1314106424Sroberto{ 1315106424Sroberto long outval; 1316290001Sglebius unsigned char *optr; 1317106424Sroberto 1318290001Sglebius optr = (unsigned char*)&outval + 3; 1319290001Sglebius *optr-- = *bp++; 1320290001Sglebius *optr-- = *bp++; 1321290001Sglebius *optr-- = *bp++; 1322290001Sglebius *optr = *bp; 1323106424Sroberto return outval; 1324106424Sroberto} 1325106424Sroberto 1326290001Sglebiusstatic unsigned long 1327290001SglebiusbGetULong( 1328290001Sglebius unsigned char *bp 1329290001Sglebius ) 1330106424Sroberto{ 1331106424Sroberto unsigned long outval; 1332290001Sglebius unsigned char *optr; 1333106424Sroberto 1334290001Sglebius optr = (unsigned char*)&outval + 3; 1335290001Sglebius *optr-- = *bp++; 1336290001Sglebius *optr-- = *bp++; 1337290001Sglebius *optr-- = *bp++; 1338290001Sglebius *optr = *bp; 1339106424Sroberto return outval; 1340106424Sroberto} 1341106424Sroberto#endif /* TRIMBLE_OUTPUT_FUNC */ 1342106424Sroberto 1343290001Sglebiusstatic float 1344290001SglebiusbGetSingle( 1345290001Sglebius unsigned char *bp 1346290001Sglebius ) 1347106424Sroberto{ 1348106424Sroberto float outval; 1349290001Sglebius unsigned char *optr; 1350106424Sroberto 1351290001Sglebius optr = (unsigned char*)&outval + 3; 1352290001Sglebius *optr-- = *bp++; 1353290001Sglebius *optr-- = *bp++; 1354290001Sglebius *optr-- = *bp++; 1355290001Sglebius *optr = *bp; 1356106424Sroberto return outval; 1357106424Sroberto} 1358106424Sroberto 1359290001Sglebiusstatic double 1360290001SglebiusbGetDouble( 1361290001Sglebius unsigned char *bp 1362290001Sglebius ) 1363106424Sroberto{ 1364106424Sroberto double outval; 1365290001Sglebius unsigned char *optr; 1366106424Sroberto 1367290001Sglebius optr = (unsigned char*)&outval + 7; 1368290001Sglebius *optr-- = *bp++; 1369290001Sglebius *optr-- = *bp++; 1370290001Sglebius *optr-- = *bp++; 1371290001Sglebius *optr-- = *bp++; 1372290001Sglebius *optr-- = *bp++; 1373290001Sglebius *optr-- = *bp++; 1374290001Sglebius *optr-- = *bp++; 1375290001Sglebius *optr = *bp; 1376106424Sroberto return outval; 1377106424Sroberto} 1378106424Sroberto 1379106424Sroberto#else /* not BYTESWAP */ 1380106424Sroberto 1381106424Sroberto#define bGetShort(bp) (*(short*)(bp)) 1382106424Sroberto#define bGetLong(bp) (*(long*)(bp)) 1383106424Sroberto#define bGetULong(bp) (*(unsigned long*)(bp)) 1384106424Sroberto#define bGetSingle(bp) (*(float*)(bp)) 1385106424Sroberto#define bGetDouble(bp) (*(double*)(bp)) 1386106424Sroberto 1387106424Sroberto#endif /* BYTESWAP */ 1388106424Sroberto/* 1389106424Sroberto * Byte-reversal is necessary for little-endian (Intel-based) machines. 1390106424Sroberto * TSIP streams are Big-endian (Motorola-based). 1391106424Sroberto */ 1392106424Sroberto#ifdef BYTESWAP 1393106424Sroberto 1394106424Srobertovoid 1395290001SglebiusbPutFloat( 1396290001Sglebius float *in, 1397290001Sglebius unsigned char *out 1398290001Sglebius ) 1399106424Sroberto{ 1400106424Sroberto unsigned char *inptr; 1401106424Sroberto 1402290001Sglebius inptr = (unsigned char*)in + 3; 1403290001Sglebius *out++ = *inptr--; 1404290001Sglebius *out++ = *inptr--; 1405290001Sglebius *out++ = *inptr--; 1406290001Sglebius *out = *inptr; 1407106424Sroberto} 1408106424Sroberto 1409106424Srobertostatic void 1410290001SglebiusbPutULong( 1411290001Sglebius unsigned long *in, 1412290001Sglebius unsigned char *out 1413290001Sglebius ) 1414106424Sroberto{ 1415106424Sroberto unsigned char *inptr; 1416106424Sroberto 1417290001Sglebius inptr = (unsigned char*)in + 3; 1418290001Sglebius *out++ = *inptr--; 1419290001Sglebius *out++ = *inptr--; 1420290001Sglebius *out++ = *inptr--; 1421290001Sglebius *out = *inptr; 1422106424Sroberto} 1423106424Sroberto 1424106424Srobertostatic void 1425290001SglebiusbPutDouble( 1426290001Sglebius double *in, 1427290001Sglebius unsigned char *out 1428290001Sglebius ) 1429106424Sroberto{ 1430106424Sroberto unsigned char *inptr; 1431106424Sroberto 1432290001Sglebius inptr = (unsigned char*)in + 7; 1433290001Sglebius *out++ = *inptr--; 1434290001Sglebius *out++ = *inptr--; 1435290001Sglebius *out++ = *inptr--; 1436290001Sglebius *out++ = *inptr--; 1437290001Sglebius *out++ = *inptr--; 1438290001Sglebius *out++ = *inptr--; 1439290001Sglebius *out++ = *inptr--; 1440290001Sglebius *out = *inptr; 1441106424Sroberto} 1442106424Sroberto 1443106424Sroberto#else /* not BYTESWAP */ 1444106424Sroberto 1445106424Srobertovoid bPutShort (short a, unsigned char *cmdbuf) {*(short*) cmdbuf = a;} 1446106424Srobertovoid bPutULong (long a, unsigned char *cmdbuf) {*(long*) cmdbuf = a;} 1447106424Srobertovoid bPutFloat (float a, unsigned char *cmdbuf) {*(float*) cmdbuf = a;} 1448106424Srobertovoid bPutDouble (double a, unsigned char *cmdbuf){*(double*) cmdbuf = a;} 1449106424Sroberto 1450106424Sroberto#endif /* BYTESWAP */ 1451106424Sroberto 1452106424Sroberto/* 1453106424Sroberto * Parse primary utc time packet 1454106424Sroberto * and fill refclock structure 1455106424Sroberto * from results. 1456106424Sroberto * 1457106424Sroberto * 0 = success 1458106424Sroberto * -1 = errors 1459106424Sroberto */ 1460106424Sroberto 1461106424Srobertostatic int 1462290001Sglebiusparse0x8FAD( 1463290001Sglebius TSIPPKT *rpt, 1464290001Sglebius struct peer *peer 1465290001Sglebius ) 1466106424Sroberto{ 1467106424Sroberto register struct refclockproc *pp; 1468106424Sroberto register struct ripencc_unit *up; 1469106424Sroberto 1470106424Sroberto unsigned day, month, year; /* data derived from received timecode */ 1471106424Sroberto unsigned hour, minute, second; 1472106424Sroberto unsigned char trackstat, utcflags; 1473106424Sroberto 1474106424Sroberto static char logbuf[1024]; /* logging string buffer */ 1475106424Sroberto int i; 1476106424Sroberto unsigned char *buf; 1477106424Sroberto 1478106424Sroberto buf = rpt->buf; 1479106424Sroberto pp = peer->procptr; 1480106424Sroberto 1481106424Sroberto if (rpt->len != 22) 1482106424Sroberto return (-1); 1483106424Sroberto 1484106424Sroberto if (bGetShort(&buf[1]) != 0) { 1485106424Sroberto#ifdef DEBUG_NCC 1486106424Sroberto if (debug) 1487106424Sroberto printf("parse0x8FAD: event count != 0\n"); 1488106424Sroberto#endif /* DEBUG_NCC */ 1489106424Sroberto return(-1); 1490106424Sroberto } 1491106424Sroberto 1492106424Sroberto if (bGetDouble(&buf[3]) != 0.0) { 1493106424Sroberto#ifdef DEBUG_NCC 1494106424Sroberto if (debug) 1495106424Sroberto printf("parse0x8FAD: fracsecs != 0\n"); 1496106424Sroberto#endif /* DEBUG_NCC */ 1497106424Sroberto return(-1); 1498106424Sroberto } 1499106424Sroberto 1500290001Sglebius hour = (unsigned int) buf[11]; 1501290001Sglebius minute = (unsigned int) buf[12]; 1502290001Sglebius second = (unsigned int) buf[13]; 1503106424Sroberto day = (unsigned int) buf[14]; 1504106424Sroberto month = (unsigned int) buf[15]; 1505106424Sroberto year = bGetShort(&buf[16]); 1506290001Sglebius trackstat = buf[18]; 1507290001Sglebius utcflags = buf[19]; 1508106424Sroberto 1509106424Sroberto 1510106424Sroberto sprintf(logbuf, "U1 %d.%d.%d %02d:%02d:%02d %d %02x", 1511106424Sroberto day, month, year, hour, minute, second, trackstat, utcflags); 1512106424Sroberto 1513106424Sroberto#ifdef DEBUG_NCC 1514106424Sroberto if (debug) 1515106424Sroberto puts(logbuf); 1516106424Sroberto#endif /* DEBUG_NCC */ 1517106424Sroberto 1518106424Sroberto record_clock_stats(&peer->srcadr, logbuf); 1519106424Sroberto 1520106424Sroberto if (!utcflags & UTCF_UTC_AVAIL) 1521106424Sroberto return(-1); 1522106424Sroberto 1523106424Sroberto /* poll for UTC parameters once and then if UTC flag changed */ 1524106424Sroberto up = (struct ripencc_unit *) pp->unitptr; 1525106424Sroberto if (utcflags != up->utcflags) { 1526290001Sglebius TSIPPKT spt; /* local structure for send packet */ 1527106424Sroberto cmd_0x2F (&spt); /* request UTC params */ 1528106424Sroberto ripencc_send(peer,spt); 1529106424Sroberto up->utcflags = utcflags; 1530106424Sroberto } 1531106424Sroberto 1532106424Sroberto /* 1533106424Sroberto * If we hit the leap second, we choose to skip this sample 1534106424Sroberto * rather than rely on other code to be perfectly correct. 1535106424Sroberto * No offense, just defense ;-). 1536106424Sroberto */ 1537106424Sroberto if (second == 60) 1538106424Sroberto return(-1); 1539106424Sroberto 1540106424Sroberto /* now check and convert the time we received */ 1541106424Sroberto 1542106424Sroberto pp->year = year; 1543106424Sroberto if (month < 1 || month > 12 || day < 1 || day > 31) 1544106424Sroberto return(-1); 1545106424Sroberto 1546290001Sglebius if (pp->year % 4) { /* XXX: use is_leapyear() ? */ 1547106424Sroberto if (day > day1tab[month - 1]) 1548106424Sroberto return(-1); 1549106424Sroberto for (i = 0; i < month - 1; i++) 1550106424Sroberto day += day1tab[i]; 1551106424Sroberto } else { 1552106424Sroberto if (day > day2tab[month - 1]) 1553106424Sroberto return(-1); 1554106424Sroberto for (i = 0; i < month - 1; i++) 1555106424Sroberto day += day2tab[i]; 1556106424Sroberto } 1557106424Sroberto pp->day = day; 1558106424Sroberto pp->hour = hour; 1559106424Sroberto pp->minute = minute; 1560106424Sroberto pp-> second = second; 1561132451Sroberto pp->nsec = 0; 1562106424Sroberto 1563106424Sroberto if ((utcflags&UTCF_LEAP_PNDG) && up->leapdelta != 0) 1564290001Sglebius pp-> leap = (up->leapdelta > 0) 1565290001Sglebius ? LEAP_ADDSECOND 1566290001Sglebius : LEAP_DELSECOND; 1567106424Sroberto else 1568106424Sroberto pp-> leap = LEAP_NOWARNING; 1569106424Sroberto 1570106424Sroberto return (0); 1571106424Sroberto} 1572106424Sroberto 1573106424Sroberto/* 1574106424Sroberto * Parse comprehensive time packet 1575106424Sroberto * 1576290001Sglebius * 0 = success 1577106424Sroberto * -1 = errors 1578106424Sroberto */ 1579106424Sroberto 1580290001Sglebiusint 1581290001Sglebiusparse0x8F0B( 1582290001Sglebius TSIPPKT *rpt, 1583290001Sglebius struct peer *peer 1584290001Sglebius ) 1585106424Sroberto{ 1586106424Sroberto register struct refclockproc *pp; 1587106424Sroberto 1588106424Sroberto unsigned day, month, year; /* data derived from received timecode */ 1589106424Sroberto unsigned hour, minute, second; 1590106424Sroberto unsigned utcoff; 1591106424Sroberto unsigned char mode; 1592106424Sroberto double bias, rate; 1593106424Sroberto float biasunc, rateunc; 1594106424Sroberto double lat, lon, alt; 1595106424Sroberto short lat_deg, lon_deg; 1596106424Sroberto float lat_min, lon_min; 1597106424Sroberto unsigned char north_south, east_west; 1598106424Sroberto char sv[9]; 1599106424Sroberto 1600106424Sroberto static char logbuf[1024]; /* logging string buffer */ 1601106424Sroberto unsigned char b; 1602106424Sroberto int i; 1603106424Sroberto unsigned char *buf; 1604106424Sroberto double tow; 1605106424Sroberto 1606106424Sroberto buf = rpt->buf; 1607106424Sroberto pp = peer->procptr; 1608106424Sroberto 1609106424Sroberto if (rpt->len != 74) 1610106424Sroberto return (-1); 1611106424Sroberto 1612106424Sroberto if (bGetShort(&buf[1]) != 0) 1613106424Sroberto return(-1);; 1614106424Sroberto 1615106424Sroberto tow = bGetDouble(&buf[3]); 1616106424Sroberto 1617106424Sroberto if (tow == -1.0) { 1618106424Sroberto return(-1); 1619106424Sroberto } 1620106424Sroberto else if ((tow >= 604800.0) || (tow < 0.0)) { 1621106424Sroberto return(-1); 1622106424Sroberto } 1623106424Sroberto else 1624106424Sroberto { 1625106424Sroberto if (tow < 604799.9) tow = tow + .00000001; 1626106424Sroberto second = (unsigned int) fmod(tow, 60.); 1627106424Sroberto minute = (unsigned int) fmod(tow/60., 60.); 1628106424Sroberto hour = (unsigned int )fmod(tow / 3600., 24.); 1629106424Sroberto } 1630106424Sroberto 1631106424Sroberto day = (unsigned int) buf[11]; 1632106424Sroberto month = (unsigned int) buf[12]; 1633106424Sroberto year = bGetShort(&buf[13]); 1634106424Sroberto mode = buf[15]; 1635106424Sroberto utcoff = bGetShort(&buf[16]); 1636106424Sroberto bias = bGetDouble(&buf[18]) / GPS_C * 1e9; /* ns */ 1637106424Sroberto rate = bGetDouble(&buf[26]) / GPS_C * 1e9; /* ppb */ 1638106424Sroberto biasunc = bGetSingle(&buf[34]) / GPS_C * 1e9; /* ns */ 1639106424Sroberto rateunc = bGetSingle(&buf[38]) / GPS_C * 1e9; /* ppb */ 1640106424Sroberto lat = bGetDouble(&buf[42]) * R2D; 1641106424Sroberto lon = bGetDouble(&buf[50]) * R2D; 1642106424Sroberto alt = bGetDouble(&buf[58]); 1643106424Sroberto 1644106424Sroberto if (lat < 0.0) { 1645106424Sroberto north_south = 'S'; 1646106424Sroberto lat = -lat; 1647106424Sroberto } 1648106424Sroberto else { 1649106424Sroberto north_south = 'N'; 1650106424Sroberto } 1651106424Sroberto lat_deg = (short)lat; 1652106424Sroberto lat_min = (lat - lat_deg) * 60.0; 1653106424Sroberto 1654106424Sroberto if (lon < 0.0) { 1655106424Sroberto east_west = 'W'; 1656106424Sroberto lon = -lon; 1657106424Sroberto } 1658106424Sroberto else { 1659106424Sroberto east_west = 'E'; 1660106424Sroberto } 1661106424Sroberto 1662106424Sroberto lon_deg = (short)lon; 1663106424Sroberto lon_min = (lon - lon_deg) * 60.0; 1664106424Sroberto 1665106424Sroberto for (i=0; i<8; i++) { 1666106424Sroberto sv[i] = buf[i + 66]; 1667106424Sroberto if (sv[i]) { 1668106424Sroberto TSIPPKT spt; /* local structure for sendpacket */ 1669106424Sroberto b = (unsigned char) (sv[i]<0 ? -sv[i] : sv[i]); 1670106424Sroberto /* request tracking status */ 1671106424Sroberto cmd_0x3C (&spt, b); 1672106424Sroberto ripencc_send(peer,spt); 1673106424Sroberto } 1674106424Sroberto } 1675106424Sroberto 1676106424Sroberto 1677106424Sroberto 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", 1678290001Sglebius day, month, year, hour, minute, second, mode, bias, biasunc, 1679290001Sglebius rate, rateunc, utcoff, lat_deg, lat_min, north_south, lon_deg, 1680290001Sglebius lon_min, east_west, alt, sv[0], sv[1], sv[2], sv[3], sv[4], 1681290001Sglebius sv[5], sv[6], sv[7]); 1682106424Sroberto 1683106424Sroberto#ifdef DEBUG_NCC 1684106424Sroberto if (debug) 1685106424Sroberto puts(logbuf); 1686106424Sroberto#endif /* DEBUG_NCC */ 1687106424Sroberto 1688106424Sroberto record_clock_stats(&peer->srcadr, logbuf); 1689106424Sroberto 1690106424Sroberto return (0); 1691106424Sroberto} 1692106424Sroberto 1693106424Sroberto#ifdef TRIMBLE_OUTPUT_FUNC 1694106424Sroberto/* 1695106424Sroberto * Parse any packet using Trimble machinery 1696106424Sroberto */ 1697290001Sglebiusint 1698290001Sglebiusparseany( 1699290001Sglebius TSIPPKT *rpt, 1700290001Sglebius struct peer *peer 1701290001Sglebius ) 1702106424Sroberto{ 1703106424Sroberto static char logbuf[1024]; /* logging string buffer */ 1704106424Sroberto 1705106424Sroberto TranslateTSIPReportToText (rpt, logbuf); /* anything else */ 1706106424Sroberto#ifdef DEBUG_NCC 1707106424Sroberto if (debug) 1708106424Sroberto puts(&logbuf[1]); 1709106424Sroberto#endif /* DEBUG_NCC */ 1710106424Sroberto record_clock_stats(&peer->srcadr, &logbuf[1]); 1711106424Sroberto return(0); 1712106424Sroberto} 1713106424Sroberto#endif /* TRIMBLE_OUTPUT_FUNC */ 1714106424Sroberto 1715106424Sroberto 1716106424Sroberto/* 1717106424Sroberto * Parse UTC Parameter Packet 1718106424Sroberto * 1719106424Sroberto * See the IDE for documentation! 1720106424Sroberto * 1721106424Sroberto * 0 = success 1722106424Sroberto * -1 = errors 1723106424Sroberto */ 1724106424Sroberto 1725290001Sglebiusint 1726290001Sglebiusparse0x4F( 1727290001Sglebius TSIPPKT *rpt, 1728290001Sglebius struct peer *peer 1729290001Sglebius ) 1730106424Sroberto{ 1731106424Sroberto register struct ripencc_unit *up; 1732106424Sroberto 1733106424Sroberto double a0; 1734106424Sroberto float a1, tot; 1735106424Sroberto int dt_ls, wn_t, wn_lsf, dn, dt_lsf; 1736106424Sroberto 1737106424Sroberto static char logbuf[1024]; /* logging string buffer */ 1738106424Sroberto unsigned char *buf; 1739106424Sroberto 1740106424Sroberto buf = rpt->buf; 1741106424Sroberto 1742106424Sroberto if (rpt->len != 26) 1743106424Sroberto return (-1); 1744106424Sroberto a0 = bGetDouble (buf); 1745106424Sroberto a1 = bGetSingle (&buf[8]); 1746106424Sroberto dt_ls = bGetShort (&buf[12]); 1747106424Sroberto tot = bGetSingle (&buf[14]); 1748106424Sroberto wn_t = bGetShort (&buf[18]); 1749106424Sroberto wn_lsf = bGetShort (&buf[20]); 1750106424Sroberto dn = bGetShort (&buf[22]); 1751106424Sroberto dt_lsf = bGetShort (&buf[24]); 1752106424Sroberto 1753106424Sroberto sprintf(logbuf, "L1 %d %d %d %g %g %g %d %d %d", 1754106424Sroberto dt_lsf - dt_ls, dt_ls, dt_lsf, a0, a1, tot, wn_t, wn_lsf, dn); 1755106424Sroberto 1756106424Sroberto#ifdef DEBUG_NCC 1757106424Sroberto if (debug) 1758106424Sroberto puts(logbuf); 1759106424Sroberto#endif /* DEBUG_NCC */ 1760106424Sroberto 1761106424Sroberto record_clock_stats(&peer->srcadr, logbuf); 1762106424Sroberto 1763106424Sroberto up = (struct ripencc_unit *) peer->procptr->unitptr; 1764106424Sroberto up->leapdelta = dt_lsf - dt_ls; 1765106424Sroberto 1766106424Sroberto return (0); 1767106424Sroberto} 1768106424Sroberto 1769106424Sroberto/* 1770106424Sroberto * Parse Tracking Status packet 1771106424Sroberto * 1772106424Sroberto * 0 = success 1773106424Sroberto * -1 = errors 1774106424Sroberto */ 1775106424Sroberto 1776290001Sglebiusint 1777290001Sglebiusparse0x5C( 1778290001Sglebius TSIPPKT *rpt, 1779290001Sglebius struct peer *peer 1780290001Sglebius ) 1781106424Sroberto{ 1782106424Sroberto unsigned char prn, channel, aqflag, ephstat; 1783106424Sroberto float snr, azinuth, elevation; 1784106424Sroberto 1785106424Sroberto static char logbuf[1024]; /* logging string buffer */ 1786106424Sroberto unsigned char *buf; 1787106424Sroberto 1788106424Sroberto buf = rpt->buf; 1789106424Sroberto 1790106424Sroberto if (rpt->len != 24) 1791106424Sroberto return(-1); 1792106424Sroberto 1793106424Sroberto prn = buf[0]; 1794106424Sroberto channel = (unsigned char)(buf[1] >> 3); 1795106424Sroberto if (channel == 0x10) 1796106424Sroberto channel = 2; 1797106424Sroberto else 1798106424Sroberto channel++; 1799106424Sroberto aqflag = buf[2]; 1800106424Sroberto ephstat = buf[3]; 1801106424Sroberto snr = bGetSingle(&buf[4]); 1802106424Sroberto elevation = bGetSingle(&buf[12]) * R2D; 1803106424Sroberto azinuth = bGetSingle(&buf[16]) * R2D; 1804106424Sroberto 1805106424Sroberto sprintf(logbuf, "S1 %02d %d %d %02x %4.1f %5.1f %4.1f", 1806106424Sroberto prn, channel, aqflag, ephstat, snr, azinuth, elevation); 1807106424Sroberto 1808106424Sroberto#ifdef DEBUG_NCC 1809106424Sroberto if (debug) 1810106424Sroberto puts(logbuf); 1811106424Sroberto#endif /* DEBUG_NCC */ 1812106424Sroberto 1813106424Sroberto record_clock_stats(&peer->srcadr, logbuf); 1814106424Sroberto 1815106424Sroberto return (0); 1816106424Sroberto} 1817106424Sroberto 1818106424Sroberto/******* Code below is from Trimble Tsipchat *************/ 1819106424Sroberto 1820106424Sroberto/* 1821106424Sroberto * ************************************************************************* 1822106424Sroberto * 1823106424Sroberto * Trimble Navigation, Ltd. 1824106424Sroberto * OEM Products Development Group 1825106424Sroberto * P.O. Box 3642 1826106424Sroberto * 645 North Mary Avenue 1827106424Sroberto * Sunnyvale, California 94088-3642 1828106424Sroberto * 1829106424Sroberto * Corporate Headquarter: 1830106424Sroberto * Telephone: (408) 481-8000 1831106424Sroberto * Fax: (408) 481-6005 1832106424Sroberto * 1833106424Sroberto * Technical Support Center: 1834106424Sroberto * Telephone: (800) 767-4822 (U.S. and Canada) 1835106424Sroberto * (408) 481-6940 (outside U.S. and Canada) 1836106424Sroberto * Fax: (408) 481-6020 1837106424Sroberto * BBS: (408) 481-7800 1838106424Sroberto * e-mail: trimble_support@trimble.com 1839106424Sroberto * ftp://ftp.trimble.com/pub/sct/embedded/bin 1840106424Sroberto * 1841106424Sroberto * ************************************************************************* 1842106424Sroberto * 1843106424Sroberto * ------- BYTE-SWAPPING ------- 1844106424Sroberto * TSIP is big-endian (Motorola) protocol. To use on little-endian (Intel) 1845106424Sroberto * systems, the bytes of all multi-byte types (shorts, floats, doubles, etc.) 1846106424Sroberto * must be reversed. This is controlled by the MACRO BYTESWAP; if defined, it 1847106424Sroberto * assumes little-endian protocol. 1848106424Sroberto * -------------------------------- 1849106424Sroberto * 1850106424Sroberto * T_PARSER.C and T_PARSER.H contains primitive functions that interpret 1851106424Sroberto * reports received from the receiver. A second source file pair, 1852106424Sroberto * T_FORMAT.C and T_FORMAT.H, contin the matching TSIP command formatters. 1853106424Sroberto * 1854106424Sroberto * The module is in very portable, basic C language. It can be used as is, or 1855106424Sroberto * with minimal changes if a TSIP communications application is needed separate 1856106424Sroberto * from TSIPCHAT. The construction of most argument lists avoid the use of 1857106424Sroberto * structures, but the developer is encouraged to reconstruct them using such 1858106424Sroberto * definitions to meet project requirements. Declarations of T_PARSER.C 1859106424Sroberto * functions are included in T_PARSER.H to provide prototyping definitions. 1860106424Sroberto * 1861106424Sroberto * There are two types of functions: a serial input processing routine, 1862106424Sroberto * tsip_input_proc() 1863106424Sroberto * which assembles incoming bytes into a TSIPPKT structure, and the 1864106424Sroberto * report parsers, rpt_0x??(). 1865106424Sroberto * 1866106424Sroberto * 1) The function tsip_input_proc() accumulates bytes from the receiver, 1867106424Sroberto * strips control bytes (DLE), and checks if the report end sequence (DLE ETX) 1868106424Sroberto * has been received. rpt.status is defined as TSIP_PARSED_FULL (== 1) 1869106424Sroberto * if a complete packet is available. 1870106424Sroberto * 1871106424Sroberto * 2) The functions rpt_0x??() are report string interpreters patterned after 1872106424Sroberto * the document called "Trimble Standard Interface Protocol". It should be 1873106424Sroberto * noted that if the report buffer is sent into the receiver with the wrong 1874106424Sroberto * length (byte count), the rpt_0x??() returns the Boolean equivalence for 1875106424Sroberto * TRUE. 1876106424Sroberto * 1877106424Sroberto * ************************************************************************* 1878106424Sroberto * 1879106424Sroberto */ 1880106424Sroberto 1881106424Sroberto 1882290001Sglebius/* 1883290001Sglebius * reads bytes until serial buffer is empty or a complete report 1884106424Sroberto * has been received; end of report is signified by DLE ETX. 1885106424Sroberto */ 1886290001Sglebiusstatic void 1887290001Sglebiustsip_input_proc( 1888290001Sglebius TSIPPKT *rpt, 1889290001Sglebius int inbyte 1890290001Sglebius ) 1891106424Sroberto{ 1892106424Sroberto unsigned char newbyte; 1893106424Sroberto 1894106424Sroberto if (inbyte < 0 || inbyte > 0xFF) return; 1895106424Sroberto 1896106424Sroberto newbyte = (unsigned char)(inbyte); 1897106424Sroberto switch (rpt->status) 1898106424Sroberto { 1899290001Sglebius case TSIP_PARSED_DLE_1: 1900106424Sroberto switch (newbyte) 1901106424Sroberto { 1902290001Sglebius case 0: 1903290001Sglebius case ETX: 1904290001Sglebius /* illegal TSIP IDs */ 1905290001Sglebius rpt->len = 0; 1906106424Sroberto rpt->status = TSIP_PARSED_EMPTY; 1907106424Sroberto break; 1908290001Sglebius case DLE: 1909290001Sglebius /* try normal message start again */ 1910106424Sroberto rpt->len = 0; 1911106424Sroberto rpt->status = TSIP_PARSED_DLE_1; 1912106424Sroberto break; 1913290001Sglebius default: 1914290001Sglebius /* legal TSIP ID; start message */ 1915106424Sroberto rpt->code = newbyte; 1916290001Sglebius rpt->len = 0; 1917106424Sroberto rpt->status = TSIP_PARSED_DATA; 1918106424Sroberto break; 1919106424Sroberto } 1920106424Sroberto break; 1921290001Sglebius case TSIP_PARSED_DATA: 1922106424Sroberto switch (newbyte) { 1923290001Sglebius case DLE: 1924290001Sglebius /* expect DLE or ETX next */ 1925106424Sroberto rpt->status = TSIP_PARSED_DLE_2; 1926106424Sroberto break; 1927290001Sglebius default: 1928290001Sglebius /* normal data byte */ 1929106424Sroberto rpt->buf[rpt->len] = newbyte; 1930106424Sroberto rpt->len++; 1931290001Sglebius /* no change in rpt->status */ 1932106424Sroberto break; 1933106424Sroberto } 1934106424Sroberto break; 1935290001Sglebius case TSIP_PARSED_DLE_2: 1936106424Sroberto switch (newbyte) { 1937290001Sglebius case DLE: 1938290001Sglebius /* normal data byte */ 1939106424Sroberto rpt->buf[rpt->len] = newbyte; 1940106424Sroberto rpt->len++; 1941106424Sroberto rpt->status = TSIP_PARSED_DATA; 1942106424Sroberto break; 1943290001Sglebius case ETX: 1944106424Sroberto /* end of message; return TRUE here. */ 1945106424Sroberto rpt->status = TSIP_PARSED_FULL; 1946106424Sroberto break; 1947290001Sglebius default: 1948106424Sroberto /* error: treat as TSIP_PARSED_DLE_1; start new report packet */ 1949106424Sroberto rpt->code = newbyte; 1950290001Sglebius rpt->len = 0; 1951106424Sroberto rpt->status = TSIP_PARSED_DATA; 1952106424Sroberto } 1953106424Sroberto break; 1954290001Sglebius case TSIP_PARSED_FULL: 1955290001Sglebius case TSIP_PARSED_EMPTY: 1956290001Sglebius default: 1957106424Sroberto switch (newbyte) { 1958290001Sglebius case DLE: 1959290001Sglebius /* normal message start */ 1960106424Sroberto rpt->len = 0; 1961106424Sroberto rpt->status = TSIP_PARSED_DLE_1; 1962106424Sroberto break; 1963290001Sglebius default: 1964106424Sroberto /* error: ignore newbyte */ 1965106424Sroberto rpt->len = 0; 1966106424Sroberto rpt->status = TSIP_PARSED_EMPTY; 1967106424Sroberto } 1968106424Sroberto break; 1969106424Sroberto } 1970106424Sroberto if (rpt->len > MAX_RPTBUF) { 1971106424Sroberto /* error: start new report packet */ 1972106424Sroberto rpt->status = TSIP_PARSED_EMPTY; 1973106424Sroberto rpt->len = 0; 1974106424Sroberto } 1975106424Sroberto} 1976106424Sroberto 1977106424Sroberto#ifdef TRIMBLE_OUTPUT_FUNC 1978106424Sroberto 1979106424Sroberto/**/ 1980106424Sroberto/* Channel A configuration for dual port operation */ 1981290001Sglebiusshort 1982290001Sglebiusrpt_0x3D( 1983290001Sglebius TSIPPKT *rpt, 1984290001Sglebius unsigned char *tx_baud_index, 1985290001Sglebius unsigned char *rx_baud_index, 1986290001Sglebius unsigned char *char_format_index, 1987290001Sglebius unsigned char *stop_bits, 1988290001Sglebius unsigned char *tx_mode_index, 1989290001Sglebius unsigned char *rx_mode_index 1990290001Sglebius ) 1991106424Sroberto{ 1992106424Sroberto unsigned char *buf; 1993106424Sroberto buf = rpt->buf; 1994106424Sroberto 1995106424Sroberto if (rpt->len != 6) return TRUE; 1996106424Sroberto *tx_baud_index = buf[0]; 1997106424Sroberto *rx_baud_index = buf[1]; 1998106424Sroberto *char_format_index = buf[2]; 1999106424Sroberto *stop_bits = (unsigned char)((buf[3] == 0x07) ? 1 : 2); 2000106424Sroberto *tx_mode_index = buf[4]; 2001106424Sroberto *rx_mode_index = buf[5]; 2002106424Sroberto return FALSE; 2003106424Sroberto} 2004106424Sroberto 2005106424Sroberto/**/ 2006106424Sroberto/* almanac data for specified satellite */ 2007290001Sglebiusshort 2008290001Sglebiusrpt_0x40( 2009290001Sglebius TSIPPKT *rpt, 2010290001Sglebius unsigned char *sv_prn, 2011290001Sglebius short *week_num, 2012290001Sglebius float *t_zc, 2013290001Sglebius float *eccentricity, 2014290001Sglebius float *t_oa, 2015290001Sglebius float *i_0, 2016290001Sglebius float *OMEGA_dot, 2017290001Sglebius float *sqrt_A, 2018290001Sglebius float *OMEGA_0, 2019290001Sglebius float *omega, 2020290001Sglebius float *M_0 2021290001Sglebius ) 2022106424Sroberto{ 2023106424Sroberto unsigned char *buf; 2024106424Sroberto buf = rpt->buf; 2025106424Sroberto 2026106424Sroberto if (rpt->len != 39) return TRUE; 2027106424Sroberto *sv_prn = buf[0]; 2028106424Sroberto *t_zc = bGetSingle (&buf[1]); 2029106424Sroberto *week_num = bGetShort (&buf[5]); 2030106424Sroberto *eccentricity = bGetSingle (&buf[7]); 2031106424Sroberto *t_oa = bGetSingle (&buf[11]); 2032106424Sroberto *i_0 = bGetSingle (&buf[15]); 2033106424Sroberto *OMEGA_dot = bGetSingle (&buf[19]); 2034106424Sroberto *sqrt_A = bGetSingle (&buf[23]); 2035106424Sroberto *OMEGA_0 = bGetSingle (&buf[27]); 2036106424Sroberto *omega = bGetSingle (&buf[31]); 2037106424Sroberto *M_0 = bGetSingle (&buf[35]); 2038106424Sroberto return FALSE; 2039106424Sroberto} 2040106424Sroberto 2041106424Sroberto/* GPS time */ 2042290001Sglebiusshort 2043290001Sglebiusrpt_0x41( 2044290001Sglebius TSIPPKT *rpt, 2045290001Sglebius float *time_of_week, 2046290001Sglebius float *UTC_offset, 2047290001Sglebius short *week_num 2048290001Sglebius ) 2049106424Sroberto{ 2050106424Sroberto unsigned char *buf; 2051106424Sroberto buf = rpt->buf; 2052106424Sroberto 2053106424Sroberto if (rpt->len != 10) return TRUE; 2054106424Sroberto *time_of_week = bGetSingle (buf); 2055106424Sroberto *week_num = bGetShort (&buf[4]); 2056106424Sroberto *UTC_offset = bGetSingle (&buf[6]); 2057106424Sroberto return FALSE; 2058106424Sroberto} 2059106424Sroberto 2060106424Sroberto/* position in ECEF, single precision */ 2061290001Sglebiusshort 2062290001Sglebiusrpt_0x42( 2063290001Sglebius TSIPPKT *rpt, 2064290001Sglebius float pos_ECEF[3], 2065290001Sglebius float *time_of_fix 2066290001Sglebius ) 2067106424Sroberto{ 2068106424Sroberto unsigned char *buf; 2069106424Sroberto buf = rpt->buf; 2070106424Sroberto 2071106424Sroberto if (rpt->len != 16) return TRUE; 2072106424Sroberto pos_ECEF[0] = bGetSingle (buf); 2073106424Sroberto pos_ECEF[1]= bGetSingle (&buf[4]); 2074106424Sroberto pos_ECEF[2]= bGetSingle (&buf[8]); 2075106424Sroberto *time_of_fix = bGetSingle (&buf[12]); 2076106424Sroberto return FALSE; 2077106424Sroberto} 2078106424Sroberto 2079106424Sroberto/* velocity in ECEF, single precision */ 2080290001Sglebiusshort 2081290001Sglebiusrpt_0x43( 2082290001Sglebius TSIPPKT *rpt, 2083290001Sglebius float ECEF_vel[3], 2084290001Sglebius float *freq_offset, 2085290001Sglebius float *time_of_fix 2086290001Sglebius ) 2087106424Sroberto{ 2088106424Sroberto unsigned char *buf; 2089106424Sroberto buf = rpt->buf; 2090106424Sroberto 2091106424Sroberto if (rpt->len != 20) return TRUE; 2092106424Sroberto ECEF_vel[0] = bGetSingle (buf); 2093106424Sroberto ECEF_vel[1] = bGetSingle (&buf[4]); 2094106424Sroberto ECEF_vel[2] = bGetSingle (&buf[8]); 2095106424Sroberto *freq_offset = bGetSingle (&buf[12]); 2096106424Sroberto *time_of_fix = bGetSingle (&buf[16]); 2097106424Sroberto return FALSE; 2098106424Sroberto} 2099106424Sroberto 2100106424Sroberto/* software versions */ 2101290001Sglebiusshort 2102290001Sglebiusrpt_0x45( 2103290001Sglebius TSIPPKT *rpt, 2104290001Sglebius unsigned char *major_nav_version, 2105290001Sglebius unsigned char *minor_nav_version, 2106290001Sglebius unsigned char *nav_day, 2107290001Sglebius unsigned char *nav_month, 2108290001Sglebius unsigned char *nav_year, 2109290001Sglebius unsigned char *major_dsp_version, 2110290001Sglebius unsigned char *minor_dsp_version, 2111290001Sglebius unsigned char *dsp_day, 2112290001Sglebius unsigned char *dsp_month, 2113290001Sglebius unsigned char *dsp_year 2114290001Sglebius ) 2115106424Sroberto{ 2116106424Sroberto unsigned char *buf; 2117106424Sroberto buf = rpt->buf; 2118106424Sroberto 2119106424Sroberto if (rpt->len != 10) return TRUE; 2120106424Sroberto *major_nav_version = buf[0]; 2121106424Sroberto *minor_nav_version = buf[1]; 2122106424Sroberto *nav_day = buf[2]; 2123106424Sroberto *nav_month = buf[3]; 2124106424Sroberto *nav_year = buf[4]; 2125106424Sroberto *major_dsp_version = buf[5]; 2126106424Sroberto *minor_dsp_version = buf[6]; 2127106424Sroberto *dsp_day = buf[7]; 2128106424Sroberto *dsp_month = buf[8]; 2129106424Sroberto *dsp_year = buf[9]; 2130106424Sroberto return FALSE; 2131106424Sroberto} 2132106424Sroberto 2133106424Sroberto/* receiver health and status */ 2134290001Sglebiusshort 2135290001Sglebiusrpt_0x46( 2136290001Sglebius TSIPPKT *rpt, 2137290001Sglebius unsigned char *status1, 2138290001Sglebius unsigned char *status2 2139290001Sglebius ) 2140106424Sroberto{ 2141106424Sroberto unsigned char *buf; 2142106424Sroberto buf = rpt->buf; 2143106424Sroberto 2144106424Sroberto if (rpt->len != 2) return TRUE; 2145106424Sroberto *status1 = buf[0]; 2146106424Sroberto *status2 = buf[1]; 2147106424Sroberto return FALSE; 2148106424Sroberto} 2149106424Sroberto 2150106424Sroberto/* signal levels for all satellites tracked */ 2151290001Sglebiusshort 2152290001Sglebiusrpt_0x47( 2153290001Sglebius TSIPPKT *rpt, 2154290001Sglebius unsigned char *nsvs, 2155290001Sglebius unsigned char *sv_prn, 2156290001Sglebius float *snr 2157290001Sglebius ) 2158106424Sroberto{ 2159106424Sroberto short isv; 2160106424Sroberto unsigned char *buf; 2161106424Sroberto buf = rpt->buf; 2162106424Sroberto 2163106424Sroberto if (rpt->len != 1 + 5*buf[0]) return TRUE; 2164106424Sroberto *nsvs = buf[0]; 2165106424Sroberto for (isv = 0; isv < (*nsvs); isv++) { 2166106424Sroberto sv_prn[isv] = buf[5*isv + 1]; 2167106424Sroberto snr[isv] = bGetSingle (&buf[5*isv + 2]); 2168106424Sroberto } 2169106424Sroberto return FALSE; 2170106424Sroberto} 2171106424Sroberto 2172106424Sroberto/* GPS system message */ 2173290001Sglebiusshort 2174290001Sglebiusrpt_0x48( 2175290001Sglebius TSIPPKT *rpt, 2176290001Sglebius unsigned char *message 2177290001Sglebius ) 2178106424Sroberto{ 2179106424Sroberto unsigned char *buf; 2180106424Sroberto buf = rpt->buf; 2181106424Sroberto 2182106424Sroberto if (rpt->len != 22) return TRUE; 2183106424Sroberto memcpy (message, buf, 22); 2184106424Sroberto message[22] = 0; 2185106424Sroberto return FALSE; 2186106424Sroberto} 2187106424Sroberto 2188106424Sroberto/* health for all satellites from almanac health page */ 2189290001Sglebiusshort 2190290001Sglebiusrpt_0x49( 2191290001Sglebius TSIPPKT *rpt, 2192290001Sglebius unsigned char *sv_health 2193290001Sglebius ) 2194106424Sroberto{ 2195106424Sroberto short i; 2196106424Sroberto unsigned char *buf; 2197106424Sroberto buf = rpt->buf; 2198106424Sroberto 2199106424Sroberto if (rpt->len != 32) return TRUE; 2200106424Sroberto for (i = 0; i < 32; i++) sv_health [i]= buf[i]; 2201106424Sroberto return FALSE; 2202106424Sroberto} 2203106424Sroberto 2204106424Sroberto/* position in lat-lon-alt, single precision */ 2205290001Sglebiusshort 2206290001Sglebiusrpt_0x4A( 2207290001Sglebius TSIPPKT *rpt, 2208290001Sglebius float *lat, 2209290001Sglebius float *lon, 2210290001Sglebius float *alt, 2211290001Sglebius float *clock_bias, 2212290001Sglebius float *time_of_fix 2213290001Sglebius ) 2214106424Sroberto{ 2215106424Sroberto unsigned char *buf; 2216106424Sroberto buf = rpt->buf; 2217106424Sroberto 2218106424Sroberto if (rpt->len != 20) return TRUE; 2219106424Sroberto *lat = bGetSingle (buf); 2220106424Sroberto *lon = bGetSingle (&buf[4]); 2221106424Sroberto *alt = bGetSingle (&buf[8]); 2222106424Sroberto *clock_bias = bGetSingle (&buf[12]); 2223106424Sroberto *time_of_fix = bGetSingle (&buf[16]); 2224106424Sroberto return FALSE; 2225106424Sroberto} 2226106424Sroberto 2227106424Sroberto/* reference altitude parameters */ 2228290001Sglebiusshort 2229290001Sglebiusrpt_0x4A_2( 2230290001Sglebius TSIPPKT *rpt, 2231290001Sglebius float *alt, 2232290001Sglebius float *dummy, 2233290001Sglebius unsigned char *alt_flag 2234290001Sglebius ) 2235106424Sroberto{ 2236106424Sroberto unsigned char *buf; 2237106424Sroberto 2238106424Sroberto buf = rpt->buf; 2239106424Sroberto 2240106424Sroberto if (rpt->len != 9) return TRUE; 2241106424Sroberto *alt = bGetSingle (buf); 2242106424Sroberto *dummy = bGetSingle (&buf[4]); 2243106424Sroberto *alt_flag = buf[8]; 2244106424Sroberto return FALSE; 2245106424Sroberto} 2246106424Sroberto 2247106424Sroberto/* machine ID code, status */ 2248290001Sglebiusshort 2249290001Sglebiusrpt_0x4B( 2250290001Sglebius TSIPPKT *rpt, 2251290001Sglebius unsigned char *machine_id, 2252290001Sglebius unsigned char *status3, 2253290001Sglebius unsigned char *status4 2254290001Sglebius ) 2255106424Sroberto{ 2256106424Sroberto unsigned char *buf; 2257106424Sroberto buf = rpt->buf; 2258106424Sroberto 2259106424Sroberto if (rpt->len != 3) return TRUE; 2260106424Sroberto *machine_id = buf[0]; 2261106424Sroberto *status3 = buf[1]; 2262106424Sroberto *status4 = buf[2]; 2263106424Sroberto return FALSE; 2264106424Sroberto} 2265106424Sroberto 2266106424Sroberto/* operating parameters and masks */ 2267290001Sglebiusshort 2268290001Sglebiusrpt_0x4C( 2269290001Sglebius TSIPPKT *rpt, 2270290001Sglebius unsigned char *dyn_code, 2271290001Sglebius float *el_mask, 2272290001Sglebius float *snr_mask, 2273290001Sglebius float *dop_mask, 2274290001Sglebius float *dop_switch 2275290001Sglebius ) 2276106424Sroberto{ 2277106424Sroberto unsigned char *buf; 2278106424Sroberto buf = rpt->buf; 2279106424Sroberto 2280106424Sroberto if (rpt->len != 17) return TRUE; 2281106424Sroberto *dyn_code = buf[0]; 2282106424Sroberto *el_mask = bGetSingle (&buf[1]); 2283106424Sroberto *snr_mask = bGetSingle (&buf[5]); 2284106424Sroberto *dop_mask = bGetSingle (&buf[9]); 2285106424Sroberto *dop_switch = bGetSingle (&buf[13]); 2286106424Sroberto return FALSE; 2287106424Sroberto} 2288106424Sroberto 2289106424Sroberto/* oscillator offset */ 2290290001Sglebiusshort 2291290001Sglebiusrpt_0x4D( 2292290001Sglebius TSIPPKT *rpt, 2293290001Sglebius float *osc_offset 2294290001Sglebius ) 2295106424Sroberto{ 2296106424Sroberto unsigned char *buf; 2297106424Sroberto buf = rpt->buf; 2298106424Sroberto 2299106424Sroberto if (rpt->len != 4) return TRUE; 2300106424Sroberto *osc_offset = bGetSingle (buf); 2301106424Sroberto return FALSE; 2302106424Sroberto} 2303106424Sroberto 2304106424Sroberto/* yes/no response to command to set GPS time */ 2305290001Sglebiusshort 2306290001Sglebiusrpt_0x4E( 2307290001Sglebius TSIPPKT *rpt, 2308290001Sglebius unsigned char *response 2309290001Sglebius ) 2310106424Sroberto{ 2311106424Sroberto unsigned char *buf; 2312106424Sroberto buf = rpt->buf; 2313106424Sroberto 2314106424Sroberto if (rpt->len != 1) return TRUE; 2315106424Sroberto *response = buf[0]; 2316106424Sroberto return FALSE; 2317106424Sroberto} 2318106424Sroberto 2319106424Sroberto/* UTC data */ 2320290001Sglebiusshort 2321290001Sglebiusrpt_0x4F( 2322290001Sglebius TSIPPKT *rpt, 2323290001Sglebius double *a0, 2324290001Sglebius float *a1, 2325290001Sglebius float *time_of_data, 2326290001Sglebius short *dt_ls, 2327290001Sglebius short *wn_t, 2328290001Sglebius short *wn_lsf, 2329290001Sglebius short *dn, 2330290001Sglebius short *dt_lsf 2331290001Sglebius ) 2332106424Sroberto{ 2333106424Sroberto unsigned char *buf; 2334106424Sroberto buf = rpt->buf; 2335106424Sroberto 2336106424Sroberto if (rpt->len != 26) return TRUE; 2337106424Sroberto *a0 = bGetDouble (buf); 2338106424Sroberto *a1 = bGetSingle (&buf[8]); 2339106424Sroberto *dt_ls = bGetShort (&buf[12]); 2340106424Sroberto *time_of_data = bGetSingle (&buf[14]); 2341106424Sroberto *wn_t = bGetShort (&buf[18]); 2342106424Sroberto *wn_lsf = bGetShort (&buf[20]); 2343106424Sroberto *dn = bGetShort (&buf[22]); 2344106424Sroberto *dt_lsf = bGetShort (&buf[24]); 2345106424Sroberto return FALSE; 2346106424Sroberto} 2347106424Sroberto 2348106424Sroberto/**/ 2349106424Sroberto/* clock offset and frequency offset in 1-SV (0-D) mode */ 2350290001Sglebiusshort 2351290001Sglebiusrpt_0x54( 2352290001Sglebius TSIPPKT *rpt, 2353290001Sglebius float *clock_bias, 2354290001Sglebius float *freq_offset, 2355290001Sglebius float *time_of_fix 2356290001Sglebius ) 2357106424Sroberto{ 2358106424Sroberto unsigned char *buf; 2359106424Sroberto buf = rpt->buf; 2360106424Sroberto 2361106424Sroberto if (rpt->len != 12) return TRUE; 2362106424Sroberto *clock_bias = bGetSingle (buf); 2363106424Sroberto *freq_offset = bGetSingle (&buf[4]); 2364106424Sroberto *time_of_fix = bGetSingle (&buf[8]); 2365106424Sroberto return FALSE; 2366106424Sroberto} 2367106424Sroberto 2368106424Sroberto/* I/O serial options */ 2369290001Sglebiusshort 2370290001Sglebiusrpt_0x55( 2371290001Sglebius TSIPPKT *rpt, 2372290001Sglebius unsigned char *pos_code, 2373290001Sglebius unsigned char *vel_code, 2374290001Sglebius unsigned char *time_code, 2375290001Sglebius unsigned char *aux_code 2376290001Sglebius ) 2377106424Sroberto{ 2378106424Sroberto unsigned char *buf; 2379106424Sroberto buf = rpt->buf; 2380106424Sroberto 2381106424Sroberto if (rpt->len != 4) return TRUE; 2382106424Sroberto *pos_code = buf[0]; 2383106424Sroberto *vel_code = buf[1]; 2384106424Sroberto *time_code = buf[2]; 2385106424Sroberto *aux_code = buf[3]; 2386106424Sroberto return FALSE; 2387106424Sroberto} 2388106424Sroberto 2389106424Sroberto/* velocity in east-north-up coordinates */ 2390290001Sglebiusshort 2391290001Sglebiusrpt_0x56( 2392290001Sglebius TSIPPKT *rpt, 2393290001Sglebius float vel_ENU[3], 2394290001Sglebius float *freq_offset, 2395290001Sglebius float *time_of_fix 2396290001Sglebius ) 2397106424Sroberto{ 2398106424Sroberto unsigned char *buf; 2399106424Sroberto buf = rpt->buf; 2400106424Sroberto 2401106424Sroberto if (rpt->len != 20) return TRUE; 2402106424Sroberto /* east */ 2403106424Sroberto vel_ENU[0] = bGetSingle (buf); 2404106424Sroberto /* north */ 2405106424Sroberto vel_ENU[1] = bGetSingle (&buf[4]); 2406106424Sroberto /* up */ 2407106424Sroberto vel_ENU[2] = bGetSingle (&buf[8]); 2408106424Sroberto *freq_offset = bGetSingle (&buf[12]); 2409106424Sroberto *time_of_fix = bGetSingle (&buf[16]); 2410106424Sroberto return FALSE; 2411106424Sroberto} 2412106424Sroberto 2413106424Sroberto/* info about last computed fix */ 2414290001Sglebiusshort 2415290001Sglebiusrpt_0x57( 2416290001Sglebius TSIPPKT *rpt, 2417290001Sglebius unsigned char *source_code, 2418290001Sglebius unsigned char *diag_code, 2419290001Sglebius short *week_num, 2420290001Sglebius float *time_of_fix 2421290001Sglebius ) 2422106424Sroberto{ 2423106424Sroberto unsigned char *buf; 2424106424Sroberto buf = rpt->buf; 2425106424Sroberto 2426106424Sroberto if (rpt->len != 8) return TRUE; 2427106424Sroberto *source_code = buf[0]; 2428106424Sroberto *diag_code = buf[1]; 2429106424Sroberto *time_of_fix = bGetSingle (&buf[2]); 2430106424Sroberto *week_num = bGetShort (&buf[6]); 2431106424Sroberto return FALSE; 2432106424Sroberto} 2433106424Sroberto 2434106424Sroberto/* GPS system data or acknowledgment of GPS system data load */ 2435290001Sglebiusshort 2436290001Sglebiusrpt_0x58( 2437290001Sglebius TSIPPKT *rpt, 2438290001Sglebius unsigned char *op_code, 2439290001Sglebius unsigned char *data_type, 2440290001Sglebius unsigned char *sv_prn, 2441290001Sglebius unsigned char *data_length, 2442290001Sglebius unsigned char *data_packet 2443290001Sglebius ) 2444106424Sroberto{ 2445106424Sroberto unsigned char *buf, *buf4; 2446106424Sroberto short dl; 2447106424Sroberto ALM_INFO* alminfo; 2448106424Sroberto ION_INFO* ioninfo; 2449106424Sroberto UTC_INFO* utcinfo; 2450106424Sroberto NAV_INFO* navinfo; 2451106424Sroberto 2452106424Sroberto buf = rpt->buf; 2453106424Sroberto 2454106424Sroberto if (buf[0] == 2) { 2455106424Sroberto if (rpt->len < 4) return TRUE; 2456106424Sroberto if (rpt->len != 4+buf[3]) return TRUE; 2457106424Sroberto } 2458106424Sroberto else if (rpt->len != 3) { 2459106424Sroberto return TRUE; 2460106424Sroberto } 2461106424Sroberto *op_code = buf[0]; 2462106424Sroberto *data_type = buf[1]; 2463106424Sroberto *sv_prn = buf[2]; 2464106424Sroberto if (*op_code == 2) { 2465106424Sroberto dl = buf[3]; 2466106424Sroberto *data_length = (unsigned char)dl; 2467106424Sroberto buf4 = &buf[4]; 2468106424Sroberto switch (*data_type) { 2469290001Sglebius case 2: 2470106424Sroberto /* Almanac */ 2471106424Sroberto if (*data_length != sizeof (ALM_INFO)) return TRUE; 2472106424Sroberto alminfo = (ALM_INFO*)data_packet; 2473106424Sroberto alminfo->t_oa_raw = buf4[0]; 2474106424Sroberto alminfo->SV_health = buf4[1]; 2475106424Sroberto alminfo->e = bGetSingle(&buf4[2]); 2476106424Sroberto alminfo->t_oa = bGetSingle(&buf4[6]); 2477106424Sroberto alminfo->i_0 = bGetSingle(&buf4[10]); 2478106424Sroberto alminfo->OMEGADOT = bGetSingle(&buf4[14]); 2479106424Sroberto alminfo->sqrt_A = bGetSingle(&buf4[18]); 2480106424Sroberto alminfo->OMEGA_0 = bGetSingle(&buf4[22]); 2481106424Sroberto alminfo->omega = bGetSingle(&buf4[26]); 2482106424Sroberto alminfo->M_0 = bGetSingle(&buf4[30]); 2483106424Sroberto alminfo->a_f0 = bGetSingle(&buf4[34]); 2484106424Sroberto alminfo->a_f1 = bGetSingle(&buf4[38]); 2485106424Sroberto alminfo->Axis = bGetSingle(&buf4[42]); 2486106424Sroberto alminfo->n = bGetSingle(&buf4[46]); 2487106424Sroberto alminfo->OMEGA_n = bGetSingle(&buf4[50]); 2488106424Sroberto alminfo->ODOT_n = bGetSingle(&buf4[54]); 2489106424Sroberto alminfo->t_zc = bGetSingle(&buf4[58]); 2490106424Sroberto alminfo->weeknum = bGetShort(&buf4[62]); 2491106424Sroberto alminfo->wn_oa = bGetShort(&buf4[64]); 2492106424Sroberto break; 2493106424Sroberto 2494290001Sglebius case 3: 2495106424Sroberto /* Almanac health page */ 2496106424Sroberto if (*data_length != sizeof (ALH_PARMS) + 3) return TRUE; 2497106424Sroberto 2498106424Sroberto /* this record is returned raw */ 2499106424Sroberto memcpy (data_packet, buf4, dl); 2500106424Sroberto break; 2501106424Sroberto 2502290001Sglebius case 4: 2503106424Sroberto /* Ionosphere */ 2504106424Sroberto if (*data_length != sizeof (ION_INFO) + 8) return TRUE; 2505106424Sroberto ioninfo = (ION_INFO*)data_packet; 2506106424Sroberto ioninfo->alpha_0 = bGetSingle (&buf4[8]); 2507106424Sroberto ioninfo->alpha_1 = bGetSingle (&buf4[12]); 2508106424Sroberto ioninfo->alpha_2 = bGetSingle (&buf4[16]); 2509106424Sroberto ioninfo->alpha_3 = bGetSingle (&buf4[20]); 2510106424Sroberto ioninfo->beta_0 = bGetSingle (&buf4[24]); 2511106424Sroberto ioninfo->beta_1 = bGetSingle (&buf4[28]); 2512106424Sroberto ioninfo->beta_2 = bGetSingle (&buf4[32]); 2513106424Sroberto ioninfo->beta_3 = bGetSingle (&buf4[36]); 2514106424Sroberto break; 2515106424Sroberto 2516290001Sglebius case 5: 2517106424Sroberto /* UTC */ 2518106424Sroberto if (*data_length != sizeof (UTC_INFO) + 13) return TRUE; 2519106424Sroberto utcinfo = (UTC_INFO*)data_packet; 2520106424Sroberto utcinfo->A_0 = bGetDouble (&buf4[13]); 2521106424Sroberto utcinfo->A_1 = bGetSingle (&buf4[21]); 2522106424Sroberto utcinfo->delta_t_LS = bGetShort (&buf4[25]); 2523106424Sroberto utcinfo->t_ot = bGetSingle(&buf4[27]); 2524106424Sroberto utcinfo->WN_t = bGetShort (&buf4[31]); 2525106424Sroberto utcinfo->WN_LSF = bGetShort (&buf4[33]); 2526106424Sroberto utcinfo->DN = bGetShort (&buf4[35]); 2527106424Sroberto utcinfo->delta_t_LSF = bGetShort (&buf4[37]); 2528106424Sroberto break; 2529106424Sroberto 2530290001Sglebius case 6: 2531106424Sroberto /* Ephemeris */ 2532106424Sroberto if (*data_length != sizeof (NAV_INFO) - 1) return TRUE; 2533106424Sroberto 2534106424Sroberto navinfo = (NAV_INFO*)data_packet; 2535106424Sroberto 2536106424Sroberto navinfo->sv_number = buf4[0]; 2537106424Sroberto navinfo->t_ephem = bGetSingle (&buf4[1]); 2538106424Sroberto navinfo->ephclk.weeknum = bGetShort (&buf4[5]); 2539106424Sroberto 2540106424Sroberto navinfo->ephclk.codeL2 = buf4[7]; 2541106424Sroberto navinfo->ephclk.L2Pdata = buf4[8]; 2542106424Sroberto navinfo->ephclk.SVacc_raw = buf4[9]; 2543106424Sroberto navinfo->ephclk.SV_health = buf4[10]; 2544106424Sroberto navinfo->ephclk.IODC = bGetShort (&buf4[11]); 2545106424Sroberto navinfo->ephclk.T_GD = bGetSingle (&buf4[13]); 2546106424Sroberto navinfo->ephclk.t_oc = bGetSingle (&buf4[17]); 2547106424Sroberto navinfo->ephclk.a_f2 = bGetSingle (&buf4[21]); 2548106424Sroberto navinfo->ephclk.a_f1 = bGetSingle (&buf4[25]); 2549106424Sroberto navinfo->ephclk.a_f0 = bGetSingle (&buf4[29]); 2550106424Sroberto navinfo->ephclk.SVacc = bGetSingle (&buf4[33]); 2551106424Sroberto 2552106424Sroberto navinfo->ephorb.IODE = buf4[37]; 2553106424Sroberto navinfo->ephorb.fit_interval = buf4[38]; 2554106424Sroberto navinfo->ephorb.C_rs = bGetSingle (&buf4[39]); 2555106424Sroberto navinfo->ephorb.delta_n = bGetSingle (&buf4[43]); 2556106424Sroberto navinfo->ephorb.M_0 = bGetDouble (&buf4[47]); 2557106424Sroberto navinfo->ephorb.C_uc = bGetSingle (&buf4[55]); 2558106424Sroberto navinfo->ephorb.e = bGetDouble (&buf4[59]); 2559106424Sroberto navinfo->ephorb.C_us = bGetSingle (&buf4[67]); 2560106424Sroberto navinfo->ephorb.sqrt_A = bGetDouble (&buf4[71]); 2561106424Sroberto navinfo->ephorb.t_oe = bGetSingle (&buf4[79]); 2562106424Sroberto navinfo->ephorb.C_ic = bGetSingle (&buf4[83]); 2563106424Sroberto navinfo->ephorb.OMEGA_0 = bGetDouble (&buf4[87]); 2564106424Sroberto navinfo->ephorb.C_is = bGetSingle (&buf4[95]); 2565106424Sroberto navinfo->ephorb.i_0 = bGetDouble (&buf4[99]); 2566106424Sroberto navinfo->ephorb.C_rc = bGetSingle (&buf4[107]); 2567106424Sroberto navinfo->ephorb.omega = bGetDouble (&buf4[111]); 2568106424Sroberto navinfo->ephorb.OMEGADOT=bGetSingle (&buf4[119]); 2569106424Sroberto navinfo->ephorb.IDOT = bGetSingle (&buf4[123]); 2570106424Sroberto navinfo->ephorb.Axis = bGetDouble (&buf4[127]); 2571106424Sroberto navinfo->ephorb.n = bGetDouble (&buf4[135]); 2572106424Sroberto navinfo->ephorb.r1me2 = bGetDouble (&buf4[143]); 2573106424Sroberto navinfo->ephorb.OMEGA_n=bGetDouble (&buf4[151]); 2574106424Sroberto navinfo->ephorb.ODOT_n = bGetDouble (&buf4[159]); 2575106424Sroberto break; 2576106424Sroberto } 2577106424Sroberto } 2578106424Sroberto return FALSE; 2579106424Sroberto} 2580106424Sroberto 2581106424Sroberto/* satellite enable/disable or health heed/ignore list */ 2582290001Sglebiusshort 2583290001Sglebiusrpt_0x59( 2584290001Sglebius TSIPPKT *rpt, 2585290001Sglebius unsigned char *code_type, 2586290001Sglebius unsigned char status_code[32] 2587290001Sglebius ) 2588106424Sroberto{ 2589106424Sroberto short iprn; 2590106424Sroberto unsigned char *buf; 2591106424Sroberto buf = rpt->buf; 2592106424Sroberto 2593106424Sroberto if (rpt->len != 33) return TRUE; 2594106424Sroberto *code_type = buf[0]; 2595106424Sroberto for (iprn = 0; iprn < 32; iprn++) 2596106424Sroberto status_code[iprn] = buf[iprn + 1]; 2597106424Sroberto return FALSE; 2598106424Sroberto} 2599106424Sroberto 2600106424Sroberto/* raw measurement data - code phase/Doppler */ 2601290001Sglebiusshort 2602290001Sglebiusrpt_0x5A( 2603290001Sglebius TSIPPKT *rpt, 2604290001Sglebius unsigned char *sv_prn, 2605290001Sglebius float *sample_length, 2606290001Sglebius float *signal_level, 2607290001Sglebius float *code_phase, 2608290001Sglebius float *Doppler, 2609290001Sglebius double *time_of_fix 2610290001Sglebius ) 2611106424Sroberto{ 2612106424Sroberto unsigned char *buf; 2613106424Sroberto buf = rpt->buf; 2614106424Sroberto 2615106424Sroberto if (rpt->len != 25) return TRUE; 2616106424Sroberto *sv_prn = buf[0]; 2617106424Sroberto *sample_length = bGetSingle (&buf[1]); 2618106424Sroberto *signal_level = bGetSingle (&buf[5]); 2619106424Sroberto *code_phase = bGetSingle (&buf[9]); 2620106424Sroberto *Doppler = bGetSingle (&buf[13]); 2621106424Sroberto *time_of_fix = bGetDouble (&buf[17]); 2622106424Sroberto return FALSE; 2623106424Sroberto} 2624106424Sroberto 2625106424Sroberto/* satellite ephorb status */ 2626290001Sglebiusshort 2627290001Sglebiusrpt_0x5B( 2628290001Sglebius TSIPPKT *rpt, 2629290001Sglebius unsigned char *sv_prn, 2630290001Sglebius unsigned char *sv_health, 2631290001Sglebius unsigned char *sv_iode, 2632290001Sglebius unsigned char *fit_interval_flag, 2633290001Sglebius float *time_of_collection, 2634290001Sglebius float *time_of_eph, 2635290001Sglebius float *sv_accy 2636290001Sglebius ) 2637106424Sroberto{ 2638106424Sroberto unsigned char *buf; 2639106424Sroberto buf = rpt->buf; 2640106424Sroberto 2641106424Sroberto if (rpt->len != 16) return TRUE; 2642106424Sroberto *sv_prn = buf[0]; 2643106424Sroberto *time_of_collection = bGetSingle (&buf[1]); 2644106424Sroberto *sv_health = buf[5]; 2645106424Sroberto *sv_iode = buf[6]; 2646106424Sroberto *time_of_eph = bGetSingle (&buf[7]); 2647106424Sroberto *fit_interval_flag = buf[11]; 2648106424Sroberto *sv_accy = bGetSingle (&buf[12]); 2649106424Sroberto return FALSE; 2650106424Sroberto} 2651106424Sroberto 2652106424Sroberto/* satellite tracking status */ 2653290001Sglebiusshort 2654290001Sglebiusrpt_0x5C( 2655290001Sglebius TSIPPKT *rpt, 2656290001Sglebius unsigned char *sv_prn, 2657290001Sglebius unsigned char *slot, 2658290001Sglebius unsigned char *chan, 2659290001Sglebius unsigned char *acq_flag, 2660290001Sglebius unsigned char *eph_flag, 2661290001Sglebius float *signal_level, 2662290001Sglebius float *time_of_last_msmt, 2663290001Sglebius float *elev, 2664290001Sglebius float *azim, 2665290001Sglebius unsigned char *old_msmt_flag, 2666290001Sglebius unsigned char *integer_msec_flag, 2667290001Sglebius unsigned char *bad_data_flag, 2668290001Sglebius unsigned char *data_collect_flag 2669290001Sglebius ) 2670106424Sroberto{ 2671106424Sroberto unsigned char *buf; 2672106424Sroberto buf = rpt->buf; 2673106424Sroberto 2674106424Sroberto if (rpt->len != 24) return TRUE; 2675106424Sroberto *sv_prn = buf[0]; 2676106424Sroberto *slot = (unsigned char)((buf[1] & 0x07) + 1); 2677106424Sroberto *chan = (unsigned char)(buf[1] >> 3); 2678106424Sroberto if (*chan == 0x10) *chan = 2; 2679106424Sroberto else (*chan)++; 2680106424Sroberto *acq_flag = buf[2]; 2681106424Sroberto *eph_flag = buf[3]; 2682106424Sroberto *signal_level = bGetSingle (&buf[4]); 2683106424Sroberto *time_of_last_msmt = bGetSingle (&buf[8]); 2684106424Sroberto *elev = bGetSingle (&buf[12]); 2685106424Sroberto *azim = bGetSingle (&buf[16]); 2686106424Sroberto *old_msmt_flag = buf[20]; 2687106424Sroberto *integer_msec_flag = buf[21]; 2688106424Sroberto *bad_data_flag = buf[22]; 2689106424Sroberto *data_collect_flag = buf[23]; 2690106424Sroberto return FALSE; 2691106424Sroberto} 2692106424Sroberto 2693106424Sroberto/**/ 2694106424Sroberto/* over-determined satellite selection for position fixes, PDOP, fix mode */ 2695290001Sglebiusshort 2696290001Sglebiusrpt_0x6D( 2697290001Sglebius TSIPPKT *rpt, 2698290001Sglebius unsigned char *manual_mode, 2699290001Sglebius unsigned char *nsvs, 2700290001Sglebius unsigned char *ndim, 2701290001Sglebius unsigned char sv_prn[], 2702290001Sglebius float *pdop, 2703290001Sglebius float *hdop, 2704290001Sglebius float *vdop, 2705290001Sglebius float *tdop 2706290001Sglebius ) 2707106424Sroberto{ 2708106424Sroberto short islot; 2709106424Sroberto unsigned char *buf; 2710106424Sroberto buf = rpt->buf; 2711106424Sroberto 2712106424Sroberto *nsvs = (unsigned char)((buf[0] & 0xF0) >> 4); 2713106424Sroberto if ((*nsvs)>8) return TRUE; 2714106424Sroberto if (rpt->len != 17 + (*nsvs) ) return TRUE; 2715106424Sroberto 2716106424Sroberto *manual_mode = (unsigned char)(buf[0] & 0x08); 2717106424Sroberto *ndim = (unsigned char)((buf[0] & 0x07)); 2718106424Sroberto *pdop = bGetSingle (&buf[1]); 2719106424Sroberto *hdop = bGetSingle (&buf[5]); 2720106424Sroberto *vdop = bGetSingle (&buf[9]); 2721106424Sroberto *tdop = bGetSingle (&buf[13]); 2722106424Sroberto for (islot = 0; islot < (*nsvs); islot++) 2723106424Sroberto sv_prn[islot] = buf[islot + 17]; 2724106424Sroberto return FALSE; 2725106424Sroberto} 2726106424Sroberto 2727106424Sroberto/**/ 2728106424Sroberto/* differential fix mode */ 2729290001Sglebiusshort 2730290001Sglebiusrpt_0x82( 2731290001Sglebius TSIPPKT *rpt, 2732290001Sglebius unsigned char *diff_mode 2733290001Sglebius ) 2734106424Sroberto{ 2735106424Sroberto unsigned char *buf; 2736106424Sroberto buf = rpt->buf; 2737106424Sroberto 2738106424Sroberto if (rpt->len != 1) return TRUE; 2739106424Sroberto *diff_mode = buf[0]; 2740106424Sroberto return FALSE; 2741106424Sroberto} 2742106424Sroberto 2743106424Sroberto/* position, ECEF double precision */ 2744290001Sglebiusshort 2745290001Sglebiusrpt_0x83( 2746290001Sglebius TSIPPKT *rpt, 2747290001Sglebius double ECEF_pos[3], 2748290001Sglebius double *clock_bias, 2749290001Sglebius float *time_of_fix 2750290001Sglebius ) 2751106424Sroberto{ 2752106424Sroberto unsigned char *buf; 2753106424Sroberto buf = rpt->buf; 2754106424Sroberto 2755106424Sroberto if (rpt->len != 36) return TRUE; 2756106424Sroberto ECEF_pos[0] = bGetDouble (buf); 2757106424Sroberto ECEF_pos[1] = bGetDouble (&buf[8]); 2758106424Sroberto ECEF_pos[2] = bGetDouble (&buf[16]); 2759106424Sroberto *clock_bias = bGetDouble (&buf[24]); 2760106424Sroberto *time_of_fix = bGetSingle (&buf[32]); 2761106424Sroberto return FALSE; 2762106424Sroberto} 2763106424Sroberto 2764106424Sroberto/* position, lat-lon-alt double precision */ 2765290001Sglebiusshort 2766290001Sglebiusrpt_0x84( 2767290001Sglebius TSIPPKT *rpt, 2768290001Sglebius double *lat, 2769290001Sglebius double *lon, 2770290001Sglebius double *alt, 2771290001Sglebius double *clock_bias, 2772290001Sglebius float *time_of_fix 2773290001Sglebius ) 2774106424Sroberto{ 2775106424Sroberto unsigned char *buf; 2776106424Sroberto buf = rpt->buf; 2777106424Sroberto 2778106424Sroberto if (rpt->len != 36) return TRUE; 2779106424Sroberto *lat = bGetDouble (buf); 2780106424Sroberto *lon = bGetDouble (&buf[8]); 2781106424Sroberto *alt = bGetDouble (&buf[16]); 2782106424Sroberto *clock_bias = bGetDouble (&buf[24]); 2783106424Sroberto *time_of_fix = bGetSingle (&buf[32]); 2784106424Sroberto return FALSE; 2785106424Sroberto} 2786106424Sroberto 2787290001Sglebiusshort 2788290001Sglebiusrpt_Paly0xBB( 2789290001Sglebius TSIPPKT *rpt, 2790290001Sglebius TSIP_RCVR_CFG *TsipxBB 2791290001Sglebius ) 2792106424Sroberto{ 2793106424Sroberto unsigned char *buf; 2794106424Sroberto buf = rpt->buf; 2795106424Sroberto 2796290001Sglebius /* Palisade is inconsistent with other TSIP, which has a length of 40 */ 2797106424Sroberto /* if (rpt->len != 40) return TRUE; */ 2798106424Sroberto if (rpt->len != 43) return TRUE; 2799106424Sroberto 2800290001Sglebius TsipxBB->bSubcode = buf[0]; 2801290001Sglebius TsipxBB->operating_mode = buf[1]; 2802290001Sglebius TsipxBB->dyn_code = buf[3]; 2803290001Sglebius TsipxBB->elev_mask = bGetSingle (&buf[5]); 2804290001Sglebius TsipxBB->cno_mask = bGetSingle (&buf[9]); 2805290001Sglebius TsipxBB->dop_mask = bGetSingle (&buf[13]); 2806106424Sroberto TsipxBB->dop_switch = bGetSingle (&buf[17]); 2807106424Sroberto return FALSE; 2808106424Sroberto} 2809106424Sroberto 2810106424Sroberto/* Receiver serial port configuration */ 2811290001Sglebiusshort 2812290001Sglebiusrpt_0xBC( 2813290001Sglebius TSIPPKT *rpt, 2814290001Sglebius unsigned char *port_num, 2815290001Sglebius unsigned char *in_baud, 2816290001Sglebius unsigned char *out_baud, 2817290001Sglebius unsigned char *data_bits, 2818290001Sglebius unsigned char *parity, 2819290001Sglebius unsigned char *stop_bits, 2820290001Sglebius unsigned char *flow_control, 2821290001Sglebius unsigned char *protocols_in, 2822290001Sglebius unsigned char *protocols_out, 2823290001Sglebius unsigned char *reserved 2824290001Sglebius ) 2825106424Sroberto{ 2826106424Sroberto unsigned char *buf; 2827106424Sroberto buf = rpt->buf; 2828106424Sroberto 2829106424Sroberto if (rpt->len != 10) return TRUE; 2830106424Sroberto *port_num = buf[0]; 2831106424Sroberto *in_baud = buf[1]; 2832106424Sroberto *out_baud = buf[2]; 2833106424Sroberto *data_bits = buf[3]; 2834106424Sroberto *parity = buf[4]; 2835106424Sroberto *stop_bits = buf[5]; 2836106424Sroberto *flow_control = buf[6]; 2837106424Sroberto *protocols_in = buf[7]; 2838106424Sroberto *protocols_out = buf[8]; 2839106424Sroberto *reserved = buf[9]; 2840106424Sroberto 2841106424Sroberto return FALSE; 2842106424Sroberto} 2843106424Sroberto 2844106424Sroberto/**** Superpackets ****/ 2845106424Sroberto 2846290001Sglebiusshort 2847290001Sglebiusrpt_0x8F0B( 2848290001Sglebius TSIPPKT *rpt, 2849290001Sglebius unsigned short *event, 2850290001Sglebius double *tow, 2851290001Sglebius unsigned char *date, 2852290001Sglebius unsigned char *month, 2853290001Sglebius short *year, 2854290001Sglebius unsigned char *dim_mode, 2855290001Sglebius short *utc_offset, 2856290001Sglebius double *bias, 2857290001Sglebius double *drift, 2858290001Sglebius float *bias_unc, 2859290001Sglebius float *dr_unc, 2860290001Sglebius double *lat, 2861290001Sglebius double *lon, 2862290001Sglebius double *alt, 2863290001Sglebius char sv_id[8] 2864290001Sglebius ) 2865106424Sroberto{ 2866290001Sglebius short local_index; 2867290001Sglebius unsigned char *buf; 2868106424Sroberto 2869106424Sroberto buf = rpt->buf; 2870290001Sglebius if (rpt->len != 74) return TRUE; 2871290001Sglebius *event = bGetShort(&buf[1]); 2872290001Sglebius *tow = bGetDouble(&buf[3]); 2873290001Sglebius *date = buf[11]; 2874290001Sglebius *month = buf[12]; 2875290001Sglebius *year = bGetShort(&buf[13]); 2876290001Sglebius *dim_mode = buf[15]; 2877290001Sglebius *utc_offset = bGetShort(&buf[16]); 2878290001Sglebius *bias = bGetDouble(&buf[18]); 2879290001Sglebius *drift = bGetDouble(&buf[26]); 2880290001Sglebius *bias_unc = bGetSingle(&buf[34]); 2881290001Sglebius *dr_unc = bGetSingle(&buf[38]); 2882290001Sglebius *lat = bGetDouble(&buf[42]); 2883290001Sglebius *lon = bGetDouble(&buf[50]); 2884290001Sglebius *alt = bGetDouble(&buf[58]); 2885106424Sroberto 2886290001Sglebius for (local_index=0; local_index<8; local_index++) sv_id[local_index] = buf[local_index + 66]; 2887290001Sglebius return FALSE; 2888106424Sroberto} 2889106424Sroberto 2890290001Sglebius/* datum index and coefficients */ 2891290001Sglebiusshort 2892290001Sglebiusrpt_0x8F14( 2893290001Sglebius TSIPPKT *rpt, 2894290001Sglebius short *datum_idx, 2895290001Sglebius double datum_coeffs[5] 2896290001Sglebius ) 2897106424Sroberto{ 2898106424Sroberto unsigned char *buf; 2899106424Sroberto buf = rpt->buf; 2900106424Sroberto 2901106424Sroberto if (rpt->len != 43) return TRUE; 2902106424Sroberto *datum_idx = bGetShort(&buf[1]); 2903106424Sroberto datum_coeffs[0] = bGetDouble (&buf[3]); 2904106424Sroberto datum_coeffs[1] = bGetDouble (&buf[11]); 2905106424Sroberto datum_coeffs[2] = bGetDouble (&buf[19]); 2906106424Sroberto datum_coeffs[3] = bGetDouble (&buf[27]); 2907106424Sroberto datum_coeffs[4] = bGetDouble (&buf[35]); 2908106424Sroberto return FALSE; 2909106424Sroberto} 2910106424Sroberto 2911106424Sroberto 2912290001Sglebius/* datum index and coefficients */ 2913290001Sglebiusshort 2914290001Sglebiusrpt_0x8F15( 2915290001Sglebius TSIPPKT *rpt, 2916290001Sglebius short *datum_idx, 2917290001Sglebius double datum_coeffs[5] 2918290001Sglebius ) 2919106424Sroberto{ 2920106424Sroberto unsigned char *buf; 2921106424Sroberto buf = rpt->buf; 2922106424Sroberto 2923106424Sroberto if (rpt->len != 43) return TRUE; 2924106424Sroberto *datum_idx = bGetShort(&buf[1]); 2925106424Sroberto datum_coeffs[0] = bGetDouble (&buf[3]); 2926106424Sroberto datum_coeffs[1] = bGetDouble (&buf[11]); 2927106424Sroberto datum_coeffs[2] = bGetDouble (&buf[19]); 2928106424Sroberto datum_coeffs[3] = bGetDouble (&buf[27]); 2929106424Sroberto datum_coeffs[4] = bGetDouble (&buf[35]); 2930106424Sroberto return FALSE; 2931106424Sroberto} 2932106424Sroberto 2933106424Sroberto 2934106424Sroberto#define MAX_LONG (2147483648.) /* 2**31 */ 2935106424Sroberto 2936290001Sglebiusshort 2937290001Sglebiusrpt_0x8F20( 2938290001Sglebius TSIPPKT *rpt, 2939290001Sglebius unsigned char *info, 2940290001Sglebius double *lat, 2941290001Sglebius double *lon, 2942290001Sglebius double *alt, 2943290001Sglebius double vel_enu[], 2944290001Sglebius double *time_of_fix, 2945290001Sglebius short *week_num, 2946290001Sglebius unsigned char *nsvs, 2947290001Sglebius unsigned char sv_prn[], 2948290001Sglebius short sv_IODC[], 2949290001Sglebius short *datum_index 2950290001Sglebius ) 2951106424Sroberto{ 2952106424Sroberto short 2953290001Sglebius isv; 2954106424Sroberto unsigned char 2955290001Sglebius *buf, prnx, iode; 2956106424Sroberto unsigned long 2957290001Sglebius ulongtemp; 2958106424Sroberto long 2959290001Sglebius longtemp; 2960106424Sroberto double 2961290001Sglebius vel_scale; 2962106424Sroberto 2963106424Sroberto buf = rpt->buf; 2964106424Sroberto 2965106424Sroberto if (rpt->len != 56) return TRUE; 2966106424Sroberto 2967106424Sroberto vel_scale = (buf[24]&1)? 0.020 : 0.005; 2968106424Sroberto vel_enu[0] = bGetShort (buf+2)*vel_scale; 2969106424Sroberto vel_enu[1] = bGetShort (buf+4)*vel_scale; 2970106424Sroberto vel_enu[2] = bGetShort (buf+6)*vel_scale; 2971106424Sroberto 2972106424Sroberto *time_of_fix = bGetULong (buf+8)*.001; 2973106424Sroberto 2974106424Sroberto longtemp = bGetLong (buf+12); 2975106424Sroberto *lat = longtemp*(GPS_PI/MAX_LONG); 2976106424Sroberto 2977106424Sroberto ulongtemp = bGetULong (buf+16); 2978106424Sroberto *lon = ulongtemp*(GPS_PI/MAX_LONG); 2979106424Sroberto if (*lon > GPS_PI) *lon -= 2.0*GPS_PI; 2980106424Sroberto 2981106424Sroberto *alt = bGetLong (buf+20)*.001; 2982106424Sroberto /* 25 blank; 29 = UTC */ 2983106424Sroberto (*datum_index) = (short)((short)buf[26]-1); 2984106424Sroberto *info = buf[27]; 2985106424Sroberto *nsvs = buf[28]; 2986106424Sroberto *week_num = bGetShort (&buf[30]); 2987106424Sroberto for (isv = 0; isv < 8; isv++) { 2988106424Sroberto prnx = buf[32+2*isv]; 2989106424Sroberto sv_prn[isv] = (unsigned char)(prnx&0x3F); 2990290001Sglebius iode = buf[33+2*isv]; 2991106424Sroberto sv_IODC[isv] = (short)(iode | ((prnx>>6)<<8)); 2992106424Sroberto } 2993106424Sroberto return FALSE; 2994106424Sroberto} 2995106424Sroberto 2996290001Sglebiusshort 2997290001Sglebiusrpt_0x8F41( 2998290001Sglebius TSIPPKT *rpt, 2999290001Sglebius unsigned char *bSearchRange, 3000290001Sglebius unsigned char *bBoardOptions, 3001290001Sglebius unsigned long *iiSerialNumber, 3002290001Sglebius unsigned char *bBuildYear, 3003290001Sglebius unsigned char *bBuildMonth, 3004290001Sglebius unsigned char *bBuildDay, 3005290001Sglebius unsigned char *bBuildHour, 3006290001Sglebius float *fOscOffset, 3007290001Sglebius unsigned short *iTestCodeId 3008290001Sglebius ) 3009106424Sroberto{ 3010290001Sglebius if (rpt->len != 17) return FALSE; 3011106424Sroberto *bSearchRange = rpt->buf[1]; 3012106424Sroberto *bBoardOptions = rpt->buf[2]; 3013106424Sroberto *iiSerialNumber = bGetLong(&rpt->buf[3]); 3014106424Sroberto *bBuildYear = rpt->buf[7]; 3015106424Sroberto *bBuildMonth = rpt->buf[8]; 3016106424Sroberto *bBuildDay = rpt->buf[9]; 3017106424Sroberto *bBuildHour = rpt->buf[10]; 3018106424Sroberto *fOscOffset = bGetSingle(&rpt->buf[11]); 3019106424Sroberto *iTestCodeId = bGetShort(&rpt->buf[15]); 3020106424Sroberto/* Tsipx8E41Data = *Tsipx8E41; */ 3021106424Sroberto return TRUE; 3022106424Sroberto} 3023106424Sroberto 3024290001Sglebiusshort 3025290001Sglebiusrpt_0x8F42( 3026290001Sglebius TSIPPKT *rpt, 3027290001Sglebius unsigned char *bProdOptionsPre, 3028290001Sglebius unsigned char *bProdNumberExt, 3029290001Sglebius unsigned short *iCaseSerialNumberPre, 3030290001Sglebius unsigned long *iiCaseSerialNumber, 3031290001Sglebius unsigned long *iiProdNumber, 3032290001Sglebius unsigned short *iPremiumOptions, 3033290001Sglebius unsigned short *iMachineID, 3034290001Sglebius unsigned short *iKey 3035290001Sglebius ) 3036106424Sroberto{ 3037290001Sglebius if (rpt->len != 19) return FALSE; 3038106424Sroberto *bProdOptionsPre = rpt->buf[1]; 3039106424Sroberto *bProdNumberExt = rpt->buf[2]; 3040106424Sroberto *iCaseSerialNumberPre = bGetShort(&rpt->buf[3]); 3041106424Sroberto *iiCaseSerialNumber = bGetLong(&rpt->buf[5]); 3042106424Sroberto *iiProdNumber = bGetLong(&rpt->buf[9]); 3043106424Sroberto *iPremiumOptions = bGetShort(&rpt->buf[13]); 3044106424Sroberto *iMachineID = bGetShort(&rpt->buf[15]); 3045106424Sroberto *iKey = bGetShort(&rpt->buf[17]); 3046106424Sroberto return TRUE; 3047106424Sroberto} 3048106424Sroberto 3049290001Sglebiusshort 3050290001Sglebiusrpt_0x8F45( 3051290001Sglebius TSIPPKT *rpt, 3052290001Sglebius unsigned char *bSegMask 3053290001Sglebius ) 3054106424Sroberto{ 3055290001Sglebius if (rpt->len != 2) return FALSE; 3056106424Sroberto *bSegMask = rpt->buf[1]; 3057106424Sroberto return TRUE; 3058106424Sroberto} 3059106424Sroberto 3060106424Sroberto/* Stinger PPS definition */ 3061290001Sglebiusshort 3062290001Sglebiusrpt_0x8F4A_16( 3063290001Sglebius TSIPPKT *rpt, 3064290001Sglebius unsigned char *pps_enabled, 3065290001Sglebius unsigned char *pps_timebase, 3066290001Sglebius unsigned char *pos_polarity, 3067290001Sglebius double *pps_offset, 3068290001Sglebius float *bias_unc_threshold 3069290001Sglebius ) 3070106424Sroberto{ 3071106424Sroberto unsigned char 3072290001Sglebius *buf; 3073106424Sroberto 3074290001Sglebius buf = rpt->buf; 3075290001Sglebius if (rpt->len != 16) return TRUE; 3076290001Sglebius *pps_enabled = buf[1]; 3077290001Sglebius *pps_timebase = buf[2]; 3078290001Sglebius *pos_polarity = buf[3]; 3079290001Sglebius *pps_offset = bGetDouble(&buf[4]); 3080290001Sglebius *bias_unc_threshold = bGetSingle(&buf[12]); 3081106424Sroberto return FALSE; 3082106424Sroberto} 3083106424Sroberto 3084290001Sglebiusshort 3085290001Sglebiusrpt_0x8F4B( 3086290001Sglebius TSIPPKT *rpt, 3087290001Sglebius unsigned long *decorr_max 3088290001Sglebius ) 3089106424Sroberto{ 3090106424Sroberto unsigned char 3091290001Sglebius *buf; 3092106424Sroberto 3093290001Sglebius buf = rpt->buf; 3094290001Sglebius if (rpt->len != 5) return TRUE; 3095290001Sglebius *decorr_max = bGetLong(&buf[1]); 3096290001Sglebius return FALSE; 3097106424Sroberto} 3098106424Sroberto 3099290001Sglebiusshort 3100290001Sglebiusrpt_0x8F4D( 3101290001Sglebius TSIPPKT *rpt, 3102290001Sglebius unsigned long *event_mask 3103290001Sglebius ) 3104106424Sroberto{ 3105106424Sroberto unsigned char 3106290001Sglebius *buf; 3107106424Sroberto 3108290001Sglebius buf = rpt->buf; 3109290001Sglebius if (rpt->len != 5) return TRUE; 3110290001Sglebius *event_mask = bGetULong (&buf[1]); 3111290001Sglebius return FALSE; 3112106424Sroberto} 3113106424Sroberto 3114290001Sglebiusshort 3115290001Sglebiusrpt_0x8FA5( 3116290001Sglebius TSIPPKT *rpt, 3117290001Sglebius unsigned char *spktmask 3118290001Sglebius ) 3119106424Sroberto{ 3120106424Sroberto unsigned char 3121290001Sglebius *buf; 3122106424Sroberto 3123290001Sglebius buf = rpt->buf; 3124290001Sglebius if (rpt->len != 5) return TRUE; 3125290001Sglebius spktmask[0] = buf[1]; 3126290001Sglebius spktmask[1] = buf[2]; 3127290001Sglebius spktmask[2] = buf[3]; 3128290001Sglebius spktmask[3] = buf[4]; 3129290001Sglebius return FALSE; 3130106424Sroberto} 3131106424Sroberto 3132290001Sglebiusshort 3133290001Sglebiusrpt_0x8FAD( 3134290001Sglebius TSIPPKT *rpt, 3135290001Sglebius unsigned short *COUNT, 3136290001Sglebius double *FracSec, 3137290001Sglebius unsigned char *Hour, 3138290001Sglebius unsigned char *Minute, 3139290001Sglebius unsigned char *Second, 3140290001Sglebius unsigned char *Day, 3141290001Sglebius unsigned char *Month, 3142290001Sglebius unsigned short *Year, 3143290001Sglebius unsigned char *Status, 3144290001Sglebius unsigned char *Flags 3145290001Sglebius ) 3146106424Sroberto{ 3147106424Sroberto if (rpt->len != 22) return TRUE; 3148106424Sroberto 3149290001Sglebius *COUNT = bGetUShort(&rpt->buf[1]); 3150290001Sglebius *FracSec = bGetDouble(&rpt->buf[3]); 3151290001Sglebius *Hour = rpt->buf[11]; 3152290001Sglebius *Minute = rpt->buf[12]; 3153290001Sglebius *Second = rpt->buf[13]; 3154290001Sglebius *Day = rpt->buf[14]; 3155290001Sglebius *Month = rpt->buf[15]; 3156290001Sglebius *Year = bGetUShort(&rpt->buf[16]); 3157290001Sglebius *Status = rpt->buf[18]; 3158290001Sglebius *Flags = rpt->buf[19]; 3159290001Sglebius return FALSE; 3160106424Sroberto} 3161106424Sroberto 3162106424Sroberto 3163106424Sroberto/* 3164106424Sroberto * ************************************************************************* 3165106424Sroberto * 3166106424Sroberto * Trimble Navigation, Ltd. 3167106424Sroberto * OEM Products Development Group 3168106424Sroberto * P.O. Box 3642 3169106424Sroberto * 645 North Mary Avenue 3170106424Sroberto * Sunnyvale, California 94088-3642 3171106424Sroberto * 3172106424Sroberto * Corporate Headquarter: 3173106424Sroberto * Telephone: (408) 481-8000 3174106424Sroberto * Fax: (408) 481-6005 3175106424Sroberto * 3176106424Sroberto * Technical Support Center: 3177106424Sroberto * Telephone: (800) 767-4822 (U.S. and Canada) 3178106424Sroberto * (408) 481-6940 (outside U.S. and Canada) 3179106424Sroberto * Fax: (408) 481-6020 3180106424Sroberto * BBS: (408) 481-7800 3181106424Sroberto * e-mail: trimble_support@trimble.com 3182106424Sroberto * ftp://ftp.trimble.com/pub/sct/embedded/bin 3183106424Sroberto * 3184106424Sroberto * ************************************************************************* 3185106424Sroberto * 3186106424Sroberto * T_REPORT.C consists of a primary function TranslateTSIPReportToText() 3187106424Sroberto * called by main(). 3188106424Sroberto * 3189106424Sroberto * This function takes a character buffer that has been received as a report 3190106424Sroberto * from a TSIP device and interprets it. The character buffer has been 3191106424Sroberto * assembled using tsip_input_proc() in T_PARSER.C. 3192106424Sroberto * 3193106424Sroberto * A large case statement directs processing to one of many mid-level 3194106424Sroberto * functions. The mid-level functions specific to the current report 3195106424Sroberto * code passes the report buffer to the appropriate report decoder 3196106424Sroberto * rpt_0x?? () in T_PARSER.C, which converts the byte stream in rpt.buf 3197106424Sroberto * to data values approporaite for use. 3198106424Sroberto * 3199106424Sroberto * ************************************************************************* 3200106424Sroberto * 3201106424Sroberto */ 3202106424Sroberto 3203106424Sroberto 3204106424Sroberto#define GOOD_PARSE 0 3205106424Sroberto#define BADID_PARSE 1 3206106424Sroberto#define BADLEN_PARSE 2 3207106424Sroberto#define BADDATA_PARSE 3 3208106424Sroberto 3209106424Sroberto#define B_TSIP 0x02 3210106424Sroberto#define B_NMEA 0x04 3211106424Sroberto 3212106424Sroberto 3213106424Sroberto/* pbuf is the pointer to the current location of the text output */ 3214106424Srobertostatic char 3215290001Sglebius*pbuf; 3216106424Sroberto 3217106424Sroberto/* keep track of whether the message has been successfully parsed */ 3218106424Srobertostatic short 3219290001Sglebiusparsed; 3220106424Sroberto 3221106424Sroberto 3222106424Sroberto/* convert time of week into day-hour-minute-second and print */ 3223290001Sglebiuschar * 3224290001Sglebiusshow_time( 3225290001Sglebius float time_of_week 3226290001Sglebius ) 3227106424Sroberto{ 3228106424Sroberto short days, hours, minutes; 3229106424Sroberto float seconds; 3230106424Sroberto double tow = 0; 3231290001Sglebius static char timestring [80]; 3232106424Sroberto 3233106424Sroberto if (time_of_week == -1.0) 3234290001Sglebius { 3235106424Sroberto sprintf(timestring, " <No time yet> "); 3236106424Sroberto } 3237106424Sroberto else if ((time_of_week >= 604800.0) || (time_of_week < 0.0)) 3238290001Sglebius { 3239106424Sroberto sprintf(timestring, " <Bad time> "); 3240106424Sroberto } 3241290001Sglebius else 3242290001Sglebius { 3243106424Sroberto if (time_of_week < 604799.9) 3244106424Sroberto tow = time_of_week + .00000001; 3245106424Sroberto seconds = (float)fmod(tow, 60.); 3246106424Sroberto minutes = (short) fmod(tow/60., 60.); 3247106424Sroberto hours = (short)fmod(tow / 3600., 24.); 3248106424Sroberto days = (short)(tow / 86400.0); 3249106424Sroberto sprintf(timestring, " %s %02d:%02d:%05.2f ", 3250290001Sglebius dayname[days], hours, minutes, seconds); 3251290001Sglebius } 3252290001Sglebius return timestring; 3253106424Sroberto} 3254106424Sroberto 3255106424Sroberto/**/ 3256106424Sroberto/* 0x3D */ 3257290001Sglebiusstatic void 3258290001Sglebiusrpt_chan_A_config( 3259290001Sglebius TSIPPKT *rpt 3260290001Sglebius ) 3261106424Sroberto{ 3262106424Sroberto unsigned char 3263290001Sglebius tx_baud_index, rx_baud_index, 3264290001Sglebius char_format_index, stop_bits, 3265290001Sglebius tx_mode_index, rx_mode_index, 3266290001Sglebius databits, parity; 3267106424Sroberto int 3268290001Sglebius i, nbaud; 3269106424Sroberto 3270106424Sroberto /* unload rptbuf */ 3271106424Sroberto if (rpt_0x3D (rpt, 3272290001Sglebius &tx_baud_index, &rx_baud_index, &char_format_index, 3273290001Sglebius &stop_bits, &tx_mode_index, &rx_mode_index)) { 3274106424Sroberto parsed = BADLEN_PARSE; 3275106424Sroberto return; 3276106424Sroberto } 3277106424Sroberto 3278106424Sroberto pbuf += sprintf(pbuf, "\nChannel A Configuration"); 3279106424Sroberto 3280290001Sglebius nbaud = sizeof(old_baudnum); 3281106424Sroberto 3282106424Sroberto for (i = 0; i < nbaud; ++i) if (tx_baud_index == old_baudnum[i]) break; 3283106424Sroberto pbuf += sprintf(pbuf, "\n Transmit speed: %s at %s", 3284290001Sglebius old_output_ch[tx_mode_index], st_baud_text_app[i]); 3285106424Sroberto 3286106424Sroberto for (i = 0; i < nbaud; ++i) if (rx_baud_index == old_baudnum[i]) break; 3287106424Sroberto pbuf += sprintf(pbuf, "\n Receive speed: %s at %s", 3288290001Sglebius old_input_ch[rx_mode_index], st_baud_text_app[i]); 3289106424Sroberto 3290106424Sroberto databits = (unsigned char)((char_format_index & 0x03) + 5); 3291106424Sroberto 3292106424Sroberto parity = (unsigned char)(char_format_index >> 2); 3293106424Sroberto if (parity > 4) parity = 2; 3294106424Sroberto 3295106424Sroberto pbuf += sprintf(pbuf, "\n Character format (bits/char, parity, stop bits): %d-%s-%d", 3296290001Sglebius databits, old_parity_text[parity], stop_bits); 3297106424Sroberto} 3298106424Sroberto 3299106424Sroberto/**/ 3300106424Sroberto/* 0x40 */ 3301290001Sglebiusstatic void 3302290001Sglebiusrpt_almanac_data_page( 3303290001Sglebius TSIPPKT *rpt 3304290001Sglebius ) 3305106424Sroberto{ 3306106424Sroberto unsigned char 3307290001Sglebius sv_prn; 3308106424Sroberto short 3309290001Sglebius week_num; 3310106424Sroberto float 3311290001Sglebius t_zc, 3312290001Sglebius eccentricity, 3313290001Sglebius t_oa, 3314290001Sglebius i_0, 3315290001Sglebius OMEGA_dot, 3316290001Sglebius sqrt_A, 3317290001Sglebius OMEGA_0, 3318290001Sglebius omega, 3319290001Sglebius M_0; 3320106424Sroberto 3321106424Sroberto /* unload rptbuf */ 3322106424Sroberto if (rpt_0x40 (rpt, 3323290001Sglebius &sv_prn, &week_num, &t_zc, &eccentricity, &t_oa, 3324290001Sglebius &i_0, &OMEGA_dot, &sqrt_A, &OMEGA_0, &omega, &M_0)) { 3325106424Sroberto parsed = BADLEN_PARSE; 3326106424Sroberto return; 3327106424Sroberto } 3328106424Sroberto 3329106424Sroberto pbuf += sprintf(pbuf, "\nAlmanac for SV %02d", sv_prn); 3330106424Sroberto pbuf += sprintf(pbuf, "\n Captured:%15.0f %s", 3331290001Sglebius t_zc, show_time (t_zc)); 3332106424Sroberto pbuf += sprintf(pbuf, "\n week:%15d", week_num); 3333106424Sroberto pbuf += sprintf(pbuf, "\n Eccentricity:%15g", eccentricity); 3334106424Sroberto pbuf += sprintf(pbuf, "\n T_oa:%15.0f %s", 3335290001Sglebius t_oa, show_time (t_oa)); 3336106424Sroberto pbuf += sprintf(pbuf, "\n i 0:%15g", i_0); 3337106424Sroberto pbuf += sprintf(pbuf, "\n OMEGA dot:%15g", OMEGA_dot); 3338106424Sroberto pbuf += sprintf(pbuf, "\n sqrt A:%15g", sqrt_A); 3339106424Sroberto pbuf += sprintf(pbuf, "\n OMEGA 0:%15g", OMEGA_0); 3340106424Sroberto pbuf += sprintf(pbuf, "\n omega:%15g", omega); 3341106424Sroberto pbuf += sprintf(pbuf, "\n M 0:%15g", M_0); 3342106424Sroberto} 3343106424Sroberto 3344106424Sroberto/* 0x41 */ 3345290001Sglebiusstatic void 3346290001Sglebiusrpt_GPS_time( 3347290001Sglebius TSIPPKT *rpt 3348290001Sglebius ) 3349106424Sroberto{ 3350106424Sroberto float 3351290001Sglebius time_of_week, UTC_offset; 3352106424Sroberto short 3353290001Sglebius week_num; 3354106424Sroberto 3355106424Sroberto /* unload rptbuf */ 3356106424Sroberto if (rpt_0x41 (rpt, &time_of_week, &UTC_offset, &week_num)) { 3357106424Sroberto parsed = BADLEN_PARSE; 3358106424Sroberto return; 3359106424Sroberto } 3360106424Sroberto 3361106424Sroberto pbuf += sprintf(pbuf, "\nGPS time:%s GPS week: %d UTC offset %.1f", 3362290001Sglebius show_time(time_of_week), week_num, UTC_offset); 3363106424Sroberto 3364106424Sroberto} 3365106424Sroberto 3366106424Sroberto/* 0x42 */ 3367290001Sglebiusstatic void 3368290001Sglebiusrpt_single_ECEF_position( 3369290001Sglebius TSIPPKT *rpt 3370290001Sglebius ) 3371106424Sroberto{ 3372106424Sroberto float 3373290001Sglebius ECEF_pos[3], time_of_fix; 3374106424Sroberto 3375106424Sroberto /* unload rptbuf */ 3376106424Sroberto if (rpt_0x42 (rpt, ECEF_pos, &time_of_fix)) { 3377106424Sroberto parsed = BADLEN_PARSE; 3378106424Sroberto return; 3379106424Sroberto } 3380106424Sroberto 3381106424Sroberto pbuf += sprintf(pbuf, "\nSXYZ: %15.0f %15.0f %15.0f %s", 3382290001Sglebius ECEF_pos[0], ECEF_pos[1], ECEF_pos[2], 3383290001Sglebius show_time(time_of_fix)); 3384106424Sroberto} 3385106424Sroberto 3386106424Sroberto/* 0x43 */ 3387290001Sglebiusstatic void 3388290001Sglebiusrpt_single_ECEF_velocity( 3389290001Sglebius TSIPPKT *rpt 3390290001Sglebius ) 3391106424Sroberto{ 3392106424Sroberto 3393106424Sroberto float 3394290001Sglebius ECEF_vel[3], freq_offset, time_of_fix; 3395106424Sroberto 3396106424Sroberto /* unload rptbuf */ 3397106424Sroberto if (rpt_0x43 (rpt, ECEF_vel, &freq_offset, &time_of_fix)) { 3398106424Sroberto parsed = BADLEN_PARSE; 3399106424Sroberto return; 3400106424Sroberto } 3401106424Sroberto 3402106424Sroberto pbuf += sprintf(pbuf, "\nVelECEF: %11.3f %11.3f %11.3f %12.3f%s", 3403290001Sglebius ECEF_vel[0], ECEF_vel[1], ECEF_vel[2], freq_offset, 3404290001Sglebius show_time(time_of_fix)); 3405106424Sroberto} 3406106424Sroberto 3407106424Sroberto/* 0x45 */ 3408290001Sglebiusstatic void 3409290001Sglebiusrpt_SW_version( 3410290001Sglebius TSIPPKT *rpt 3411290001Sglebius ) 3412290001Sglebius{ 3413106424Sroberto unsigned char 3414290001Sglebius major_nav_version, minor_nav_version, 3415290001Sglebius nav_day, nav_month, nav_year, 3416290001Sglebius major_dsp_version, minor_dsp_version, 3417290001Sglebius dsp_day, dsp_month, dsp_year; 3418106424Sroberto 3419106424Sroberto /* unload rptbuf */ 3420106424Sroberto if (rpt_0x45 (rpt, 3421290001Sglebius &major_nav_version, &minor_nav_version, 3422290001Sglebius &nav_day, &nav_month, &nav_year, 3423290001Sglebius &major_dsp_version, &minor_dsp_version, 3424290001Sglebius &dsp_day, &dsp_month, &dsp_year)) { 3425106424Sroberto parsed = BADLEN_PARSE; 3426106424Sroberto return; 3427106424Sroberto } 3428106424Sroberto 3429106424Sroberto pbuf += sprintf(pbuf, 3430290001Sglebius "\nFW Versions: Nav Proc %2d.%02d %2d/%2d/%2d Sig Proc %2d.%02d %2d/%2d/%2d", 3431290001Sglebius major_nav_version, minor_nav_version, nav_day, nav_month, nav_year, 3432290001Sglebius major_dsp_version, minor_dsp_version, dsp_day, dsp_month, dsp_year); 3433106424Sroberto} 3434106424Sroberto 3435106424Sroberto/* 0x46 */ 3436290001Sglebiusstatic void 3437290001Sglebiusrpt_rcvr_health( 3438290001Sglebius TSIPPKT *rpt 3439290001Sglebius ) 3440106424Sroberto{ 3441106424Sroberto unsigned char 3442290001Sglebius status1, status2; 3443290001Sglebius const char 3444290001Sglebius *text; 3445290001Sglebius static const char const 3446290001Sglebius *sc_text[] = { 3447290001Sglebius "Doing position fixes", 3448290001Sglebius "Don't have GPS time yet", 3449290001Sglebius "Waiting for almanac collection", 3450290001Sglebius "DOP too high ", 3451290001Sglebius "No satellites available", 3452290001Sglebius "Only 1 satellite available", 3453290001Sglebius "Only 2 satellites available", 3454290001Sglebius "Only 3 satellites available", 3455290001Sglebius "No satellites usable ", 3456290001Sglebius "Only 1 satellite usable", 3457290001Sglebius "Only 2 satellites usable", 3458290001Sglebius "Only 3 satellites usable", 3459290001Sglebius "Chosen satellite unusable"}; 3460106424Sroberto 3461106424Sroberto 3462106424Sroberto /* unload rptbuf */ 3463106424Sroberto if (rpt_0x46 (rpt, &status1, &status2)) 3464106424Sroberto { 3465106424Sroberto parsed = BADLEN_PARSE; 3466106424Sroberto return; 3467106424Sroberto } 3468106424Sroberto 3469290001Sglebius text = (status1 < COUNTOF(sc_text)) 3470290001Sglebius ? sc_text[status1] 3471290001Sglebius : "(out of range)"; 3472106424Sroberto pbuf += sprintf(pbuf, "\nRcvr status1: %s (%02Xh); ", 3473290001Sglebius text, status1); 3474106424Sroberto 3475106424Sroberto pbuf += sprintf(pbuf, "status2: %s, %s (%02Xh)", 3476290001Sglebius (status2 & 0x01)?"No BBRAM":"BBRAM OK", 3477290001Sglebius (status2 & 0x10)?"No Ant":"Ant OK", 3478290001Sglebius status2); 3479106424Sroberto} 3480106424Sroberto 3481106424Sroberto/* 0x47 */ 3482290001Sglebiusstatic void 3483290001Sglebiusrpt_SNR_all_SVs( 3484290001Sglebius TSIPPKT *rpt 3485290001Sglebius ) 3486106424Sroberto{ 3487106424Sroberto unsigned char 3488290001Sglebius nsvs, sv_prn[12]; 3489106424Sroberto short 3490290001Sglebius isv; 3491106424Sroberto float 3492290001Sglebius snr[12]; 3493106424Sroberto 3494106424Sroberto /* unload rptbuf */ 3495106424Sroberto if (rpt_0x47 (rpt, &nsvs, sv_prn, snr)) 3496290001Sglebius { 3497106424Sroberto parsed = BADLEN_PARSE; 3498106424Sroberto return; 3499106424Sroberto } 3500106424Sroberto 3501106424Sroberto pbuf += sprintf(pbuf, "\nSNR for satellites: %d", nsvs); 3502106424Sroberto for (isv = 0; isv < nsvs; isv++) 3503290001Sglebius { 3504106424Sroberto pbuf += sprintf(pbuf, "\n SV %02d %6.2f", 3505290001Sglebius sv_prn[isv], snr[isv]); 3506106424Sroberto } 3507106424Sroberto} 3508106424Sroberto 3509106424Sroberto/* 0x48 */ 3510290001Sglebiusstatic void 3511290001Sglebiusrpt_GPS_system_message( 3512290001Sglebius TSIPPKT *rpt 3513290001Sglebius ) 3514106424Sroberto{ 3515106424Sroberto unsigned char 3516290001Sglebius message[23]; 3517106424Sroberto 3518106424Sroberto /* unload rptbuf */ 3519106424Sroberto if (rpt_0x48 (rpt, message)) 3520290001Sglebius { 3521106424Sroberto parsed = BADLEN_PARSE; 3522106424Sroberto return; 3523106424Sroberto } 3524106424Sroberto 3525106424Sroberto pbuf += sprintf(pbuf, "\nGPS message: %s", message); 3526106424Sroberto} 3527106424Sroberto 3528106424Sroberto/* 0x49 */ 3529290001Sglebiusstatic void 3530290001Sglebiusrpt_almanac_health_page( 3531290001Sglebius TSIPPKT *rpt 3532290001Sglebius ) 3533106424Sroberto{ 3534106424Sroberto short 3535290001Sglebius iprn; 3536106424Sroberto unsigned char 3537290001Sglebius sv_health [32]; 3538106424Sroberto 3539106424Sroberto /* unload rptbuf */ 3540106424Sroberto if (rpt_0x49 (rpt, sv_health)) 3541290001Sglebius { 3542106424Sroberto parsed = BADLEN_PARSE; 3543106424Sroberto return; 3544106424Sroberto } 3545106424Sroberto 3546106424Sroberto pbuf += sprintf(pbuf, "\nAlmanac health page:"); 3547106424Sroberto for (iprn = 0; iprn < 32; iprn++) 3548290001Sglebius { 3549106424Sroberto if (!(iprn%5)) *pbuf++ = '\n'; 3550106424Sroberto pbuf += sprintf(pbuf, " SV%02d %2X", 3551290001Sglebius (iprn+1) , sv_health[iprn]); 3552106424Sroberto } 3553106424Sroberto} 3554106424Sroberto 3555106424Sroberto/* 0x4A */ 3556290001Sglebiusstatic void 3557290001Sglebiusrpt_single_lla_position( 3558290001Sglebius TSIPPKT *rpt 3559290001Sglebius ) 3560290001Sglebius{ 3561106424Sroberto short 3562290001Sglebius lat_deg, lon_deg; 3563106424Sroberto float 3564290001Sglebius lat, lon, 3565290001Sglebius alt, clock_bias, time_of_fix; 3566106424Sroberto double lat_min, lon_min; 3567106424Sroberto unsigned char 3568290001Sglebius north_south, east_west; 3569106424Sroberto 3570106424Sroberto if (rpt_0x4A (rpt, 3571290001Sglebius &lat, &lon, &alt, &clock_bias, &time_of_fix)) 3572290001Sglebius { 3573106424Sroberto parsed = BADLEN_PARSE; 3574106424Sroberto return; 3575106424Sroberto } 3576106424Sroberto 3577106424Sroberto /* convert from radians to degrees */ 3578106424Sroberto lat *= (float)R2D; 3579106424Sroberto north_south = 'N'; 3580106424Sroberto if (lat < 0.0) 3581290001Sglebius { 3582106424Sroberto north_south = 'S'; 3583106424Sroberto lat = -lat; 3584106424Sroberto } 3585106424Sroberto lat_deg = (short)lat; 3586106424Sroberto lat_min = (lat - lat_deg) * 60.0; 3587106424Sroberto 3588106424Sroberto lon *= (float)R2D; 3589106424Sroberto east_west = 'E'; 3590106424Sroberto if (lon < 0.0) 3591290001Sglebius { 3592106424Sroberto east_west = 'W'; 3593106424Sroberto lon = -lon; 3594106424Sroberto } 3595106424Sroberto lon_deg = (short)lon; 3596106424Sroberto lon_min = (lon - lon_deg) * 60.0; 3597106424Sroberto 3598106424Sroberto pbuf += sprintf(pbuf, "\nSLLA: %4d: %06.3f %c%5d:%06.3f %c%10.2f %12.2f%s", 3599290001Sglebius lat_deg, lat_min, north_south, 3600290001Sglebius lon_deg, lon_min, east_west, 3601290001Sglebius alt, clock_bias, 3602290001Sglebius show_time(time_of_fix)); 3603106424Sroberto} 3604106424Sroberto 3605106424Sroberto/* 0x4A */ 3606290001Sglebiusstatic void 3607290001Sglebiusrpt_ref_alt( 3608290001Sglebius TSIPPKT *rpt 3609290001Sglebius ) 3610290001Sglebius{ 3611106424Sroberto float 3612290001Sglebius alt, dummy; 3613106424Sroberto unsigned char 3614290001Sglebius alt_flag; 3615106424Sroberto 3616290001Sglebius if (rpt_0x4A_2 (rpt, &alt, &dummy, &alt_flag)) 3617290001Sglebius { 3618106424Sroberto parsed = BADLEN_PARSE; 3619106424Sroberto return; 3620106424Sroberto } 3621106424Sroberto 3622106424Sroberto pbuf += sprintf(pbuf, "\nReference Alt: %.1f m; %s", 3623290001Sglebius alt, alt_flag?"ON":"OFF"); 3624106424Sroberto} 3625106424Sroberto 3626106424Sroberto/* 0x4B */ 3627290001Sglebiusstatic void 3628290001Sglebiusrpt_rcvr_id_and_status( 3629290001Sglebius TSIPPKT *rpt 3630290001Sglebius ) 3631106424Sroberto{ 3632106424Sroberto 3633106424Sroberto unsigned char 3634290001Sglebius machine_id, status3, status4; 3635106424Sroberto 3636106424Sroberto /* unload rptbuf */ 3637106424Sroberto if (rpt_0x4B (rpt, &machine_id, &status3, &status4)) 3638290001Sglebius { 3639106424Sroberto parsed = BADLEN_PARSE; 3640106424Sroberto return; 3641106424Sroberto } 3642106424Sroberto 3643106424Sroberto pbuf += sprintf(pbuf, "\nRcvr Machine ID: %d; Status3 = %s, %s (%02Xh)", 3644290001Sglebius machine_id, 3645290001Sglebius (status3 & 0x02)?"No RTC":"RTC OK", 3646290001Sglebius (status3 & 0x08)?"No Alm":"Alm OK", 3647290001Sglebius status3); 3648106424Sroberto} 3649106424Sroberto 3650106424Sroberto/* 0x4C */ 3651290001Sglebiusstatic void 3652290001Sglebiusrpt_operating_parameters( 3653290001Sglebius TSIPPKT *rpt 3654290001Sglebius ) 3655106424Sroberto{ 3656106424Sroberto unsigned char 3657290001Sglebius dyn_code; 3658106424Sroberto float 3659290001Sglebius el_mask, snr_mask, dop_mask, dop_switch; 3660106424Sroberto 3661106424Sroberto /* unload rptbuf */ 3662106424Sroberto if (rpt_0x4C (rpt, &dyn_code, &el_mask, 3663290001Sglebius &snr_mask, &dop_mask, &dop_switch)) 3664290001Sglebius { 3665106424Sroberto parsed = BADLEN_PARSE; 3666106424Sroberto return; 3667106424Sroberto } 3668106424Sroberto 3669106424Sroberto pbuf += sprintf(pbuf, "\nOperating Parameters:"); 3670106424Sroberto pbuf += sprintf(pbuf, "\n Dynamics code = %d %s", 3671290001Sglebius dyn_code, dyn_text[dyn_code]); 3672290001Sglebius pbuf += sprintf(pbuf, "\n Elevation mask = %.2f", el_mask * R2D); 3673106424Sroberto pbuf += sprintf(pbuf, "\n SNR mask = %.2f", snr_mask); 3674106424Sroberto pbuf += sprintf(pbuf, "\n DOP mask = %.2f", dop_mask); 3675106424Sroberto pbuf += sprintf(pbuf, "\n DOP switch = %.2f", dop_switch); 3676106424Sroberto} 3677106424Sroberto 3678106424Sroberto/* 0x4D */ 3679290001Sglebiusstatic void 3680290001Sglebiusrpt_oscillator_offset( 3681290001Sglebius TSIPPKT *rpt 3682290001Sglebius ) 3683106424Sroberto{ 3684106424Sroberto float 3685290001Sglebius osc_offset; 3686106424Sroberto 3687106424Sroberto /* unload rptbuf */ 3688106424Sroberto if (rpt_0x4D (rpt, &osc_offset)) 3689290001Sglebius { 3690106424Sroberto parsed = BADLEN_PARSE; 3691106424Sroberto return; 3692106424Sroberto } 3693106424Sroberto 3694106424Sroberto pbuf += sprintf(pbuf, "\nOscillator offset: %.2f Hz = %.3f PPM", 3695290001Sglebius osc_offset, osc_offset/1575.42); 3696106424Sroberto} 3697106424Sroberto 3698106424Sroberto/* 0x4E */ 3699290001Sglebiusstatic void 3700290001Sglebiusrpt_GPS_time_set_response( 3701290001Sglebius TSIPPKT *rpt 3702290001Sglebius ) 3703106424Sroberto{ 3704106424Sroberto unsigned char 3705290001Sglebius response; 3706106424Sroberto 3707106424Sroberto /* unload rptbuf */ 3708106424Sroberto if (rpt_0x4E (rpt, &response)) 3709290001Sglebius { 3710106424Sroberto parsed = BADLEN_PARSE; 3711106424Sroberto return; 3712106424Sroberto } 3713106424Sroberto 3714106424Sroberto switch (response) 3715290001Sglebius { 3716290001Sglebius case 'Y': 3717106424Sroberto pbuf += sprintf(pbuf, "\nTime set accepted"); 3718106424Sroberto break; 3719106424Sroberto 3720290001Sglebius case 'N': 3721106424Sroberto pbuf += sprintf(pbuf, "\nTime set rejected or not required"); 3722106424Sroberto break; 3723106424Sroberto 3724290001Sglebius default: 3725106424Sroberto parsed = BADDATA_PARSE; 3726106424Sroberto } 3727106424Sroberto} 3728106424Sroberto 3729106424Sroberto/* 0x4F */ 3730290001Sglebiusstatic void 3731290001Sglebiusrpt_UTC_offset( 3732290001Sglebius TSIPPKT *rpt 3733290001Sglebius ) 3734106424Sroberto{ 3735106424Sroberto double 3736290001Sglebius a0; 3737106424Sroberto float 3738290001Sglebius a1, time_of_data; 3739106424Sroberto short 3740290001Sglebius dt_ls, wn_t, wn_lsf, dn, dt_lsf; 3741106424Sroberto 3742106424Sroberto /* unload rptbuf */ 3743106424Sroberto if (rpt_0x4F (rpt, &a0, &a1, &time_of_data, 3744290001Sglebius &dt_ls, &wn_t, &wn_lsf, &dn, &dt_lsf)) { 3745106424Sroberto parsed = BADLEN_PARSE; 3746106424Sroberto return; 3747106424Sroberto } 3748106424Sroberto 3749106424Sroberto pbuf += sprintf(pbuf, "\nUTC Correction Data"); 3750106424Sroberto pbuf += sprintf(pbuf, "\n A_0 = %g ", a0); 3751106424Sroberto pbuf += sprintf(pbuf, "\n A_1 = %g ", a1); 3752106424Sroberto pbuf += sprintf(pbuf, "\n delta_t_LS = %d ", dt_ls); 3753106424Sroberto pbuf += sprintf(pbuf, "\n t_ot = %.0f ", time_of_data); 3754106424Sroberto pbuf += sprintf(pbuf, "\n WN_t = %d ", wn_t ); 3755106424Sroberto pbuf += sprintf(pbuf, "\n WN_LSF = %d ", wn_lsf ); 3756106424Sroberto pbuf += sprintf(pbuf, "\n DN = %d ", dn ); 3757106424Sroberto pbuf += sprintf(pbuf, "\n delta_t_LSF = %d ", dt_lsf ); 3758106424Sroberto} 3759106424Sroberto 3760106424Sroberto/**/ 3761106424Sroberto/* 0x54 */ 3762290001Sglebiusstatic void 3763290001Sglebiusrpt_1SV_bias( 3764290001Sglebius TSIPPKT *rpt 3765290001Sglebius ) 3766106424Sroberto{ 3767106424Sroberto float 3768290001Sglebius clock_bias, freq_offset, time_of_fix; 3769106424Sroberto 3770106424Sroberto /* unload rptbuf */ 3771106424Sroberto if (rpt_0x54 (rpt, &clock_bias, &freq_offset, &time_of_fix)) { 3772106424Sroberto parsed = BADLEN_PARSE; 3773106424Sroberto return; 3774106424Sroberto } 3775106424Sroberto 3776106424Sroberto pbuf += sprintf (pbuf, "\nTime Fix Clock Bias: %6.2f m Freq Bias: %6.2f m/s%s", 3777290001Sglebius clock_bias, freq_offset, show_time (time_of_fix)); 3778106424Sroberto} 3779106424Sroberto 3780106424Sroberto/* 0x55 */ 3781290001Sglebiusstatic void 3782290001Sglebiusrpt_io_opt( 3783290001Sglebius TSIPPKT *rpt 3784290001Sglebius ) 3785106424Sroberto{ 3786106424Sroberto unsigned char 3787290001Sglebius pos_code, vel_code, time_code, aux_code; 3788106424Sroberto 3789106424Sroberto /* unload rptbuf */ 3790106424Sroberto if (rpt_0x55 (rpt, 3791290001Sglebius &pos_code, &vel_code, &time_code, &aux_code)) { 3792106424Sroberto parsed = BADLEN_PARSE; 3793106424Sroberto return; 3794106424Sroberto } 3795106424Sroberto /* rptbuf unloaded */ 3796106424Sroberto 3797106424Sroberto pbuf += sprintf(pbuf, "\nI/O Options: %2X %2X %2X %2X", 3798290001Sglebius pos_code, vel_code, time_code, aux_code); 3799106424Sroberto 3800106424Sroberto if (pos_code & 0x01) { 3801106424Sroberto pbuf += sprintf(pbuf, "\n ECEF XYZ position output"); 3802106424Sroberto } 3803106424Sroberto 3804106424Sroberto if (pos_code & 0x02) { 3805106424Sroberto pbuf += sprintf(pbuf, "\n LLA position output"); 3806106424Sroberto } 3807106424Sroberto 3808106424Sroberto pbuf += sprintf(pbuf, (pos_code & 0x04)? 3809290001Sglebius "\n MSL altitude output (Geoid height) ": 3810290001Sglebius "\n WGS-84 altitude output"); 3811106424Sroberto 3812106424Sroberto pbuf += sprintf(pbuf, (pos_code & 0x08)? 3813290001Sglebius "\n MSL altitude input": 3814290001Sglebius "\n WGS-84 altitude input"); 3815106424Sroberto 3816106424Sroberto pbuf += sprintf(pbuf, (pos_code & 0x10)? 3817290001Sglebius "\n Double precision": 3818290001Sglebius "\n Single precision"); 3819106424Sroberto 3820106424Sroberto if (pos_code & 0x20) { 3821106424Sroberto pbuf += sprintf(pbuf, "\n All Enabled Superpackets"); 3822106424Sroberto } 3823106424Sroberto 3824106424Sroberto if (vel_code & 0x01) { 3825106424Sroberto pbuf += sprintf(pbuf, "\n ECEF XYZ velocity output"); 3826106424Sroberto } 3827106424Sroberto 3828106424Sroberto if (vel_code & 0x02) { 3829106424Sroberto pbuf += sprintf(pbuf, "\n ENU velocity output"); 3830106424Sroberto } 3831106424Sroberto 3832106424Sroberto pbuf += sprintf(pbuf, (time_code & 0x01)? 3833290001Sglebius "\n Time tags in UTC": 3834290001Sglebius "\n Time tags in GPS time"); 3835106424Sroberto 3836106424Sroberto if (time_code & 0x02) { 3837106424Sroberto pbuf += sprintf(pbuf, "\n Fixes delayed to integer seconds"); 3838106424Sroberto } 3839106424Sroberto 3840106424Sroberto if (time_code & 0x04) { 3841106424Sroberto pbuf += sprintf(pbuf, "\n Fixes sent only on request"); 3842106424Sroberto } 3843106424Sroberto 3844106424Sroberto if (time_code & 0x08) { 3845106424Sroberto pbuf += sprintf(pbuf, "\n Synchronized measurements"); 3846106424Sroberto } 3847106424Sroberto 3848106424Sroberto if (time_code & 0x10) { 3849106424Sroberto pbuf += sprintf(pbuf, "\n Minimize measurement propagation"); 3850106424Sroberto } 3851106424Sroberto 3852290001Sglebius pbuf += sprintf(pbuf, (time_code & 0x20) ? 3853290001Sglebius "\n PPS output at all times" : 3854290001Sglebius "\n PPS output during fixes"); 3855106424Sroberto 3856106424Sroberto if (aux_code & 0x01) { 3857106424Sroberto pbuf += sprintf(pbuf, "\n Raw measurement output"); 3858106424Sroberto } 3859106424Sroberto 3860106424Sroberto if (aux_code & 0x02) { 3861106424Sroberto pbuf += sprintf(pbuf, "\n Code-phase smoothed before output"); 3862106424Sroberto } 3863106424Sroberto 3864106424Sroberto if (aux_code & 0x04) { 3865106424Sroberto pbuf += sprintf(pbuf, "\n Additional fix status"); 3866106424Sroberto } 3867106424Sroberto 3868106424Sroberto pbuf += sprintf(pbuf, (aux_code & 0x08)? 3869290001Sglebius "\n Signal Strength Output as dBHz" : 3870290001Sglebius "\n Signal Strength Output as AMU"); 3871106424Sroberto} 3872106424Sroberto 3873106424Sroberto/* 0x56 */ 3874290001Sglebiusstatic void 3875290001Sglebiusrpt_ENU_velocity( 3876290001Sglebius TSIPPKT *rpt 3877290001Sglebius ) 3878106424Sroberto{ 3879106424Sroberto float 3880290001Sglebius vel_ENU[3], freq_offset, time_of_fix; 3881106424Sroberto 3882106424Sroberto /* unload rptbuf */ 3883106424Sroberto if (rpt_0x56 (rpt, vel_ENU, &freq_offset, &time_of_fix)) { 3884106424Sroberto parsed = BADLEN_PARSE; 3885106424Sroberto return; 3886106424Sroberto } 3887106424Sroberto 3888106424Sroberto pbuf += sprintf(pbuf, "\nVel ENU: %11.3f %11.3f %11.3f %12.3f%s", 3889290001Sglebius vel_ENU[0], vel_ENU[1], vel_ENU[2], freq_offset, 3890290001Sglebius show_time (time_of_fix)); 3891106424Sroberto} 3892106424Sroberto 3893106424Sroberto/* 0x57 */ 3894290001Sglebiusstatic void 3895290001Sglebiusrpt_last_fix_info( 3896290001Sglebius TSIPPKT *rpt 3897290001Sglebius ) 3898106424Sroberto{ 3899106424Sroberto unsigned char 3900290001Sglebius source_code, diag_code; 3901106424Sroberto short 3902290001Sglebius week_num; 3903106424Sroberto float 3904290001Sglebius time_of_fix; 3905106424Sroberto 3906106424Sroberto /* unload rptbuf */ 3907106424Sroberto if (rpt_0x57 (rpt, &source_code, &diag_code, &week_num, &time_of_fix)) { 3908106424Sroberto parsed = BADLEN_PARSE; 3909106424Sroberto return; 3910106424Sroberto } 3911106424Sroberto 3912106424Sroberto pbuf += sprintf(pbuf, "\n source code %d; diag code: %2Xh", 3913290001Sglebius source_code, diag_code); 3914106424Sroberto pbuf += sprintf(pbuf, "\n Time of last fix:%s", show_time(time_of_fix)); 3915106424Sroberto pbuf += sprintf(pbuf, "\n Week of last fix: %d", week_num); 3916106424Sroberto} 3917106424Sroberto 3918106424Sroberto/* 0x58 */ 3919290001Sglebiusstatic void 3920290001Sglebiusrpt_GPS_system_data( 3921290001Sglebius TSIPPKT *rpt 3922290001Sglebius ) 3923106424Sroberto{ 3924106424Sroberto unsigned char 3925290001Sglebius iprn, 3926290001Sglebius op_code, data_type, sv_prn, 3927290001Sglebius data_length, data_packet[250]; 3928106424Sroberto ALM_INFO 3929290001Sglebius *almanac; 3930106424Sroberto ALH_PARMS 3931290001Sglebius *almh; 3932106424Sroberto UTC_INFO 3933290001Sglebius *utc; 3934106424Sroberto ION_INFO 3935290001Sglebius *ionosphere; 3936106424Sroberto EPHEM_CLOCK 3937290001Sglebius *cdata; 3938106424Sroberto EPHEM_ORBIT 3939290001Sglebius *edata; 3940106424Sroberto NAV_INFO 3941290001Sglebius *nav_data; 3942106424Sroberto unsigned char 3943290001Sglebius curr_t_oa; 3944106424Sroberto unsigned short 3945290001Sglebius curr_wn_oa; 3946106424Sroberto static char 3947290001Sglebius *datname[] = 3948290001Sglebius {"", "", "Almanac Orbit", 3949290001Sglebius "Health Page & Ref Time", "Ionosphere", "UTC ", 3950290001Sglebius "Ephemeris"}; 3951106424Sroberto 3952106424Sroberto /* unload rptbuf */ 3953106424Sroberto if (rpt_0x58 (rpt, &op_code, &data_type, &sv_prn, 3954290001Sglebius &data_length, data_packet)) 3955290001Sglebius { 3956106424Sroberto parsed = BADLEN_PARSE; 3957106424Sroberto return; 3958106424Sroberto } 3959106424Sroberto 3960106424Sroberto pbuf += sprintf(pbuf, "\nSystem data [%d]: %s SV%02d", 3961290001Sglebius data_type, datname[data_type], sv_prn); 3962106424Sroberto switch (op_code) 3963106424Sroberto { 3964290001Sglebius case 1: 3965106424Sroberto pbuf += sprintf(pbuf, " Acknowledgment"); 3966106424Sroberto break; 3967290001Sglebius case 2: 3968106424Sroberto pbuf += sprintf(pbuf, " length = %d bytes", data_length); 3969106424Sroberto switch (data_type) { 3970290001Sglebius case 2: 3971106424Sroberto /* Almanac */ 3972106424Sroberto if (sv_prn == 0 || sv_prn > 32) { 3973106424Sroberto pbuf += sprintf(pbuf, " Binary PRN invalid"); 3974106424Sroberto return; 3975106424Sroberto } 3976106424Sroberto almanac = (ALM_INFO*)data_packet; 3977106424Sroberto pbuf += sprintf(pbuf, "\n t_oa_raw = % -12d SV_hlth = % -12d ", 3978290001Sglebius almanac->t_oa_raw , almanac->SV_health ); 3979106424Sroberto pbuf += sprintf(pbuf, "\n e = % -12g t_oa = % -12g ", 3980290001Sglebius almanac->e , almanac->t_oa ); 3981106424Sroberto pbuf += sprintf(pbuf, "\n i_0 = % -12g OMEGADOT = % -12g ", 3982290001Sglebius almanac->i_0 , almanac->OMEGADOT ); 3983106424Sroberto pbuf += sprintf(pbuf, "\n sqrt_A = % -12g OMEGA_0 = % -12g ", 3984290001Sglebius almanac->sqrt_A , almanac->OMEGA_0 ); 3985106424Sroberto pbuf += sprintf(pbuf, "\n omega = % -12g M_0 = % -12g ", 3986290001Sglebius almanac->omega , almanac->M_0 ); 3987106424Sroberto pbuf += sprintf(pbuf, "\n a_f0 = % -12g a_f1 = % -12g ", 3988290001Sglebius almanac->a_f0 , almanac->a_f1 ); 3989106424Sroberto pbuf += sprintf(pbuf, "\n Axis = % -12g n = % -12g ", 3990290001Sglebius almanac->Axis , almanac->n ); 3991106424Sroberto pbuf += sprintf(pbuf, "\n OMEGA_n = % -12g ODOT_n = % -12g ", 3992290001Sglebius almanac->OMEGA_n , almanac->ODOT_n ); 3993106424Sroberto pbuf += sprintf(pbuf, "\n t_zc = % -12g weeknum = % -12d ", 3994290001Sglebius almanac->t_zc , almanac->weeknum ); 3995106424Sroberto pbuf += sprintf(pbuf, "\n wn_oa = % -12d", almanac->wn_oa ); 3996106424Sroberto break; 3997106424Sroberto 3998290001Sglebius case 3: 3999106424Sroberto /* Almanac health page */ 4000106424Sroberto almh = (ALH_PARMS*)data_packet; 4001106424Sroberto pbuf += sprintf(pbuf, "\n t_oa = %d, wn_oa&0xFF = %d ", 4002290001Sglebius almh->t_oa, almh->WN_a); 4003106424Sroberto pbuf += sprintf(pbuf, "\nAlmanac health page:"); 4004106424Sroberto for (iprn = 0; iprn < 32; iprn++) { 4005106424Sroberto if (!(iprn%5)) *pbuf++ = '\n'; 4006106424Sroberto pbuf += sprintf(pbuf, " SV%02d %2X", 4007290001Sglebius (iprn+1) , almh->SV_health[iprn]); 4008106424Sroberto } 4009106424Sroberto curr_t_oa = data_packet[34]; 4010106424Sroberto curr_wn_oa = (unsigned short)((data_packet[35]<<8) + data_packet[36]); 4011106424Sroberto pbuf += sprintf(pbuf, "\n current t_oa = %d, wn_oa = %d ", 4012290001Sglebius curr_t_oa, curr_wn_oa); 4013106424Sroberto break; 4014106424Sroberto 4015290001Sglebius case 4: 4016106424Sroberto /* Ionosphere */ 4017106424Sroberto ionosphere = (ION_INFO*)data_packet; 4018106424Sroberto pbuf += sprintf(pbuf, "\n alpha_0 = % -12g alpha_1 = % -12g ", 4019290001Sglebius ionosphere->alpha_0, ionosphere->alpha_1); 4020106424Sroberto pbuf += sprintf(pbuf, "\n alpha_2 = % -12g alpha_3 = % -12g ", 4021290001Sglebius ionosphere->alpha_2, ionosphere->alpha_3); 4022106424Sroberto pbuf += sprintf(pbuf, "\n beta_0 = % -12g beta_1 = % -12g ", 4023290001Sglebius ionosphere->beta_0, ionosphere->beta_1); 4024106424Sroberto pbuf += sprintf(pbuf, "\n beta_2 = % -12g beta_3 = % -12g ", 4025290001Sglebius ionosphere->beta_2, ionosphere->beta_3); 4026106424Sroberto break; 4027106424Sroberto 4028290001Sglebius case 5: 4029106424Sroberto /* UTC */ 4030106424Sroberto utc = (UTC_INFO*)data_packet; 4031106424Sroberto pbuf += sprintf(pbuf, "\n A_0 = %g ", utc->A_0); 4032106424Sroberto pbuf += sprintf(pbuf, "\n A_1 = %g ", utc->A_1); 4033106424Sroberto pbuf += sprintf(pbuf, "\n delta_t_LS = %d ", utc->delta_t_LS); 4034106424Sroberto pbuf += sprintf(pbuf, "\n t_ot = %.0f ", utc->t_ot ); 4035106424Sroberto pbuf += sprintf(pbuf, "\n WN_t = %d ", utc->WN_t ); 4036106424Sroberto pbuf += sprintf(pbuf, "\n WN_LSF = %d ", utc->WN_LSF ); 4037106424Sroberto pbuf += sprintf(pbuf, "\n DN = %d ", utc->DN ); 4038106424Sroberto pbuf += sprintf(pbuf, "\n delta_t_LSF = %d ", utc->delta_t_LSF ); 4039106424Sroberto break; 4040106424Sroberto 4041290001Sglebius case 6: /* Ephemeris */ 4042106424Sroberto if (sv_prn == 0 || sv_prn > 32) { 4043106424Sroberto pbuf += sprintf(pbuf, " Binary PRN invalid"); 4044106424Sroberto return; 4045106424Sroberto } 4046106424Sroberto nav_data = (NAV_INFO*)data_packet; 4047106424Sroberto 4048106424Sroberto pbuf += sprintf(pbuf, "\n SV_PRN = % -12d . t_ephem = % -12g . ", 4049290001Sglebius nav_data->sv_number , nav_data->t_ephem ); 4050106424Sroberto cdata = &(nav_data->ephclk); 4051106424Sroberto pbuf += sprintf(pbuf, 4052290001Sglebius "\n weeknum = % -12d . codeL2 = % -12d . L2Pdata = % -12d", 4053290001Sglebius cdata->weeknum , cdata->codeL2 , cdata->L2Pdata ); 4054106424Sroberto pbuf += sprintf(pbuf, 4055290001Sglebius "\n SVacc_raw = % -12d .SV_health = % -12d . IODC = % -12d", 4056290001Sglebius cdata->SVacc_raw, cdata->SV_health, cdata->IODC ); 4057106424Sroberto pbuf += sprintf(pbuf, 4058290001Sglebius "\n T_GD = % -12g . t_oc = % -12g . a_f2 = % -12g", 4059290001Sglebius cdata->T_GD, cdata->t_oc, cdata->a_f2 ); 4060106424Sroberto pbuf += sprintf(pbuf, 4061290001Sglebius "\n a_f1 = % -12g . a_f0 = % -12g . SVacc = % -12g", 4062290001Sglebius cdata->a_f1, cdata->a_f0, cdata->SVacc ); 4063106424Sroberto edata = &(nav_data->ephorb); 4064106424Sroberto pbuf += sprintf(pbuf, 4065290001Sglebius "\n IODE = % -12d .fit_intvl = % -12d . C_rs = % -12g", 4066290001Sglebius edata->IODE, edata->fit_interval, edata->C_rs ); 4067106424Sroberto pbuf += sprintf(pbuf, 4068290001Sglebius "\n delta_n = % -12g . M_0 = % -12g . C_uc = % -12g", 4069290001Sglebius edata->delta_n, edata->M_0, edata->C_uc ); 4070106424Sroberto pbuf += sprintf(pbuf, 4071290001Sglebius "\n ecc = % -12g . C_us = % -12g . sqrt_A = % -12g", 4072290001Sglebius edata->e, edata->C_us, edata->sqrt_A ); 4073106424Sroberto pbuf += sprintf(pbuf, 4074290001Sglebius "\n t_oe = % -12g . C_ic = % -12g . OMEGA_0 = % -12g", 4075290001Sglebius edata->t_oe, edata->C_ic, edata->OMEGA_0 ); 4076106424Sroberto pbuf += sprintf(pbuf, 4077290001Sglebius "\n C_is = % -12g . i_0 = % -12g . C_rc = % -12g", 4078290001Sglebius edata->C_is, edata->i_0, edata->C_rc ); 4079106424Sroberto pbuf += sprintf(pbuf, 4080290001Sglebius "\n omega = % -12g . OMEGADOT = % -12g . IDOT = % -12g", 4081290001Sglebius edata->omega, edata->OMEGADOT, edata->IDOT ); 4082106424Sroberto pbuf += sprintf(pbuf, 4083290001Sglebius "\n Axis = % -12g . n = % -12g . r1me2 = % -12g", 4084290001Sglebius edata->Axis, edata->n, edata->r1me2 ); 4085106424Sroberto pbuf += sprintf(pbuf, 4086290001Sglebius "\n OMEGA_n = % -12g . ODOT_n = % -12g", 4087290001Sglebius edata->OMEGA_n, edata->ODOT_n ); 4088106424Sroberto break; 4089106424Sroberto } 4090106424Sroberto } 4091106424Sroberto} 4092106424Sroberto 4093106424Sroberto 4094106424Sroberto/* 0x59: */ 4095290001Sglebiusstatic void 4096290001Sglebiusrpt_SVs_enabled( 4097290001Sglebius TSIPPKT *rpt 4098290001Sglebius ) 4099106424Sroberto{ 4100106424Sroberto unsigned char 4101290001Sglebius numsvs, 4102290001Sglebius code_type, 4103290001Sglebius status_code[32]; 4104106424Sroberto short 4105290001Sglebius iprn; 4106106424Sroberto 4107106424Sroberto /* unload rptbuf */ 4108106424Sroberto if (rpt_0x59 (rpt, &code_type, status_code)) 4109290001Sglebius { 4110106424Sroberto parsed = BADLEN_PARSE; 4111106424Sroberto return; 4112106424Sroberto } 4113290001Sglebius switch (code_type) 4114290001Sglebius { 4115290001Sglebius case 3: pbuf += sprintf(pbuf, "\nSVs Disabled:\n"); break; 4116290001Sglebius case 6: pbuf += sprintf(pbuf, "\nSVs with Health Ignored:\n"); break; 4117290001Sglebius default: return; 4118290001Sglebius } 4119290001Sglebius numsvs = 0; 4120290001Sglebius for (iprn = 0; iprn < 32; iprn++) 4121290001Sglebius { 4122290001Sglebius if (status_code[iprn]) 4123290001Sglebius { 4124290001Sglebius pbuf += sprintf(pbuf, " %02d", iprn+1); 4125290001Sglebius numsvs++; 4126290001Sglebius } 4127290001Sglebius } 4128290001Sglebius if (numsvs == 0) pbuf += sprintf(pbuf, "None"); 4129106424Sroberto} 4130106424Sroberto 4131106424Sroberto 4132106424Sroberto/* 0x5A */ 4133290001Sglebiusstatic void 4134290001Sglebiusrpt_raw_msmt( 4135290001Sglebius TSIPPKT *rpt 4136290001Sglebius ) 4137106424Sroberto{ 4138106424Sroberto unsigned char 4139290001Sglebius sv_prn; 4140106424Sroberto float 4141290001Sglebius sample_length, signal_level, code_phase, Doppler; 4142106424Sroberto double 4143290001Sglebius time_of_fix; 4144106424Sroberto 4145106424Sroberto /* unload rptbuf */ 4146106424Sroberto if (rpt_0x5A (rpt, &sv_prn, &sample_length, &signal_level, 4147290001Sglebius &code_phase, &Doppler, &time_of_fix)) 4148290001Sglebius { 4149106424Sroberto parsed = BADLEN_PARSE; 4150106424Sroberto return; 4151106424Sroberto } 4152106424Sroberto 4153106424Sroberto pbuf += sprintf(pbuf, "\n %02d %5.0f %7.1f %10.2f %10.2f %12.3f %s", 4154290001Sglebius sv_prn, sample_length, signal_level, code_phase, Doppler, time_of_fix, 4155290001Sglebius show_time ((float)time_of_fix)); 4156106424Sroberto} 4157106424Sroberto 4158106424Sroberto/* 0x5B */ 4159290001Sglebiusstatic void 4160290001Sglebiusrpt_SV_ephemeris_status( 4161290001Sglebius TSIPPKT *rpt 4162290001Sglebius ) 4163106424Sroberto{ 4164106424Sroberto unsigned char 4165290001Sglebius sv_prn, sv_health, sv_iode, fit_interval_flag; 4166106424Sroberto float 4167290001Sglebius time_of_collection, time_of_eph, sv_accy; 4168106424Sroberto 4169106424Sroberto /* unload rptbuf */ 4170106424Sroberto if (rpt_0x5B (rpt, &sv_prn, &sv_health, &sv_iode, &fit_interval_flag, 4171290001Sglebius &time_of_collection, &time_of_eph, &sv_accy)) 4172290001Sglebius { 4173106424Sroberto parsed = BADLEN_PARSE; 4174106424Sroberto return; 4175106424Sroberto } 4176106424Sroberto 4177106424Sroberto pbuf += sprintf(pbuf, "\n SV%02d %s %2Xh %2Xh ", 4178290001Sglebius sv_prn, show_time (time_of_collection), sv_health, sv_iode); 4179106424Sroberto /* note: cannot use show_time twice in same call */ 4180106424Sroberto pbuf += sprintf(pbuf, "%s %1d %4.1f", 4181290001Sglebius show_time (time_of_eph), fit_interval_flag, sv_accy); 4182106424Sroberto} 4183106424Sroberto 4184106424Sroberto/* 0x5C */ 4185290001Sglebiusstatic void 4186290001Sglebiusrpt_SV_tracking_status( 4187290001Sglebius TSIPPKT *rpt 4188290001Sglebius ) 4189106424Sroberto{ 4190106424Sroberto unsigned char 4191290001Sglebius sv_prn, chan, slot, acq_flag, eph_flag, 4192290001Sglebius old_msmt_flag, integer_msec_flag, bad_data_flag, 4193290001Sglebius data_collect_flag; 4194106424Sroberto float 4195290001Sglebius signal_level, time_of_last_msmt, 4196290001Sglebius elev, azim; 4197106424Sroberto 4198106424Sroberto /* unload rptbuf */ 4199106424Sroberto if (rpt_0x5C (rpt, 4200290001Sglebius &sv_prn, &slot, &chan, &acq_flag, &eph_flag, 4201290001Sglebius &signal_level, &time_of_last_msmt, &elev, &azim, 4202290001Sglebius &old_msmt_flag, &integer_msec_flag, &bad_data_flag, 4203290001Sglebius &data_collect_flag)) 4204290001Sglebius { 4205106424Sroberto parsed = BADLEN_PARSE; 4206106424Sroberto return; 4207106424Sroberto } 4208106424Sroberto 4209106424Sroberto pbuf += sprintf(pbuf, 4210290001Sglebius "\n SV%2d %1d %1d %1d %4.1f %s %5.1f %5.1f", 4211290001Sglebius sv_prn, chan, 4212290001Sglebius acq_flag, eph_flag, signal_level, 4213290001Sglebius show_time(time_of_last_msmt), 4214290001Sglebius elev*R2D, azim*R2D); 4215106424Sroberto} 4216106424Sroberto 4217106424Sroberto/**/ 4218106424Sroberto/* 0x6D */ 4219290001Sglebiusstatic void 4220290001Sglebiusrpt_allSV_selection( 4221290001Sglebius TSIPPKT *rpt 4222290001Sglebius ) 4223106424Sroberto{ 4224106424Sroberto unsigned char 4225290001Sglebius manual_mode, nsvs, sv_prn[8], ndim; 4226106424Sroberto short 4227290001Sglebius islot; 4228106424Sroberto float 4229290001Sglebius pdop, hdop, vdop, tdop; 4230106424Sroberto 4231106424Sroberto /* unload rptbuf */ 4232106424Sroberto if (rpt_0x6D (rpt, 4233290001Sglebius &manual_mode, &nsvs, &ndim, sv_prn, 4234290001Sglebius &pdop, &hdop, &vdop, &tdop)) 4235290001Sglebius { 4236106424Sroberto parsed = BADLEN_PARSE; 4237106424Sroberto return; 4238106424Sroberto } 4239106424Sroberto 4240106424Sroberto switch (ndim) 4241290001Sglebius { 4242290001Sglebius case 0: 4243106424Sroberto pbuf += sprintf(pbuf, "\nMode: Searching, %d-SV:", nsvs); 4244290001Sglebius break; 4245290001Sglebius case 1: 4246106424Sroberto pbuf += sprintf(pbuf, "\nMode: One-SV Timing:"); 4247290001Sglebius break; 4248290001Sglebius case 3: case 4: 4249106424Sroberto pbuf += sprintf(pbuf, "\nMode: %c-%dD, %d-SV:", 4250290001Sglebius manual_mode ? 'M' : 'A', ndim - 1, nsvs); 4251290001Sglebius break; 4252290001Sglebius case 5: 4253106424Sroberto pbuf += sprintf(pbuf, "\nMode: Timing, %d-SV:", nsvs); 4254290001Sglebius break; 4255290001Sglebius default: 4256106424Sroberto pbuf += sprintf(pbuf, "\nMode: Unknown = %d:", ndim); 4257290001Sglebius break; 4258290001Sglebius } 4259106424Sroberto 4260106424Sroberto for (islot = 0; islot < nsvs; islot++) 4261290001Sglebius { 4262106424Sroberto if (sv_prn[islot]) pbuf += sprintf(pbuf, " %02d", sv_prn[islot]); 4263106424Sroberto } 4264290001Sglebius if (ndim == 3 || ndim == 4) 4265290001Sglebius { 4266106424Sroberto pbuf += sprintf(pbuf, "; DOPs: P %.1f H %.1f V %.1f T %.1f", 4267290001Sglebius pdop, hdop, vdop, tdop); 4268290001Sglebius } 4269106424Sroberto} 4270106424Sroberto 4271106424Sroberto/**/ 4272106424Sroberto/* 0x82 */ 4273290001Sglebiusstatic void 4274290001Sglebiusrpt_DGPS_position_mode( 4275290001Sglebius TSIPPKT *rpt 4276290001Sglebius ) 4277106424Sroberto{ 4278106424Sroberto unsigned char 4279290001Sglebius diff_mode; 4280106424Sroberto 4281106424Sroberto /* unload rptbuf */ 4282106424Sroberto if (rpt_0x82 (rpt, &diff_mode)) { 4283106424Sroberto parsed = BADLEN_PARSE; 4284106424Sroberto return; 4285106424Sroberto } 4286106424Sroberto 4287106424Sroberto pbuf += sprintf(pbuf, "\nFix is%s DGPS-corrected (%s mode) (%d)", 4288290001Sglebius (diff_mode&1) ? "" : " not", 4289290001Sglebius (diff_mode&2) ? "auto" : "manual", 4290290001Sglebius diff_mode); 4291106424Sroberto} 4292106424Sroberto 4293106424Sroberto/* 0x83 */ 4294290001Sglebiusstatic void 4295290001Sglebiusrpt_double_ECEF_position( 4296290001Sglebius TSIPPKT *rpt 4297290001Sglebius ) 4298106424Sroberto{ 4299106424Sroberto double 4300290001Sglebius ECEF_pos[3], clock_bias; 4301106424Sroberto float 4302290001Sglebius time_of_fix; 4303106424Sroberto 4304106424Sroberto /* unload rptbuf */ 4305106424Sroberto if (rpt_0x83 (rpt, ECEF_pos, &clock_bias, &time_of_fix)) 4306290001Sglebius { 4307106424Sroberto parsed = BADLEN_PARSE; 4308106424Sroberto return; 4309106424Sroberto } 4310106424Sroberto 4311106424Sroberto pbuf += sprintf(pbuf, "\nDXYZ:%12.2f %13.2f %13.2f %12.2f%s", 4312290001Sglebius ECEF_pos[0], ECEF_pos[1], ECEF_pos[2], clock_bias, 4313290001Sglebius show_time(time_of_fix)); 4314106424Sroberto} 4315106424Sroberto 4316106424Sroberto/* 0x84 */ 4317290001Sglebiusstatic void 4318290001Sglebiusrpt_double_lla_position( 4319290001Sglebius TSIPPKT *rpt 4320290001Sglebius ) 4321106424Sroberto{ 4322106424Sroberto short 4323290001Sglebius lat_deg, lon_deg; 4324106424Sroberto double 4325290001Sglebius lat, lon, lat_min, lon_min, 4326290001Sglebius alt, clock_bias; 4327106424Sroberto float 4328290001Sglebius time_of_fix; 4329106424Sroberto unsigned char 4330290001Sglebius north_south, east_west; 4331106424Sroberto 4332106424Sroberto /* unload rptbuf */ 4333106424Sroberto if (rpt_0x84 (rpt, 4334290001Sglebius &lat, &lon, &alt, &clock_bias, &time_of_fix)) 4335290001Sglebius { 4336106424Sroberto parsed = BADLEN_PARSE; 4337106424Sroberto return; 4338106424Sroberto } 4339106424Sroberto 4340106424Sroberto lat *= R2D; 4341106424Sroberto lon *= R2D; 4342106424Sroberto if (lat < 0.0) { 4343106424Sroberto north_south = 'S'; 4344106424Sroberto lat = -lat; 4345106424Sroberto } else { 4346106424Sroberto north_south = 'N'; 4347106424Sroberto } 4348106424Sroberto lat_deg = (short)lat; 4349106424Sroberto lat_min = (lat - lat_deg) * 60.0; 4350106424Sroberto 4351106424Sroberto if (lon < 0.0) { 4352106424Sroberto east_west = 'W'; 4353106424Sroberto lon = -lon; 4354106424Sroberto } else { 4355106424Sroberto east_west = 'E'; 4356106424Sroberto } 4357106424Sroberto lon_deg = (short)lon; 4358106424Sroberto lon_min = (lon - lon_deg) * 60.0; 4359106424Sroberto pbuf += sprintf(pbuf, "\nDLLA: %2d:%08.5f %c; %3d:%08.5f %c; %10.2f %12.2f%s", 4360290001Sglebius lat_deg, lat_min, north_south, 4361290001Sglebius lon_deg, lon_min, east_west, 4362290001Sglebius alt, clock_bias, 4363290001Sglebius show_time(time_of_fix)); 4364106424Sroberto} 4365106424Sroberto 4366106424Sroberto/* 0xBB */ 4367290001Sglebiusstatic void 4368290001Sglebiusrpt_complete_rcvr_config( 4369290001Sglebius TSIPPKT *rpt 4370290001Sglebius ) 4371106424Sroberto{ 4372106424Sroberto TSIP_RCVR_CFG TsipxBB ; 4373106424Sroberto /* unload rptbuf */ 4374106424Sroberto if (rpt_Paly0xBB (rpt, &TsipxBB)) 4375106424Sroberto { 4376106424Sroberto parsed = BADLEN_PARSE; 4377106424Sroberto return; 4378106424Sroberto } 4379106424Sroberto 4380106424Sroberto pbuf += sprintf(pbuf, "\n operating mode: %s", 4381290001Sglebius NavModeText0xBB[TsipxBB.operating_mode]); 4382106424Sroberto pbuf += sprintf(pbuf, "\n dynamics: %s", 4383290001Sglebius dyn_text[TsipxBB.dyn_code]); 4384106424Sroberto pbuf += sprintf(pbuf, "\n elev angle mask: %g deg", 4385290001Sglebius TsipxBB.elev_mask * R2D); 4386106424Sroberto pbuf += sprintf(pbuf, "\n SNR mask: %g AMU", 4387290001Sglebius TsipxBB.cno_mask); 4388106424Sroberto pbuf += sprintf(pbuf, "\n DOP mask: %g", 4389290001Sglebius TsipxBB.dop_mask); 4390106424Sroberto pbuf += sprintf(pbuf, "\n DOP switch: %g", 4391290001Sglebius TsipxBB.dop_switch); 4392106424Sroberto return ; 4393106424Sroberto} 4394106424Sroberto 4395106424Sroberto/* 0xBC */ 4396290001Sglebiusstatic void 4397290001Sglebiusrpt_rcvr_serial_port_config( 4398290001Sglebius TSIPPKT *rpt 4399290001Sglebius ) 4400106424Sroberto{ 4401106424Sroberto unsigned char 4402290001Sglebius port_num, in_baud, out_baud, data_bits, parity, stop_bits, flow_control, 4403290001Sglebius protocols_in, protocols_out, reserved; 4404106424Sroberto unsigned char known; 4405106424Sroberto 4406106424Sroberto /* unload rptbuf */ 4407106424Sroberto if (rpt_0xBC (rpt, &port_num, &in_baud, &out_baud, &data_bits, &parity, 4408290001Sglebius &stop_bits, &flow_control, &protocols_in, &protocols_out, &reserved)) { 4409106424Sroberto parsed = BADLEN_PARSE; 4410106424Sroberto return; 4411106424Sroberto } 4412106424Sroberto /* rptbuf unloaded */ 4413106424Sroberto 4414106424Sroberto pbuf += sprintf(pbuf, "\n RECEIVER serial port %s config:", 4415290001Sglebius rcvr_port_text[port_num]); 4416106424Sroberto 4417106424Sroberto pbuf += sprintf(pbuf, "\n I/O Baud %s/%s, %d - %s - %d", 4418290001Sglebius st_baud_text_app[in_baud], 4419290001Sglebius st_baud_text_app[out_baud], 4420290001Sglebius data_bits+5, 4421290001Sglebius parity_text[parity], 4422290001Sglebius stop_bits=1); 4423106424Sroberto pbuf += sprintf(pbuf, "\n Input protocols: "); 4424106424Sroberto known = FALSE; 4425106424Sroberto if (protocols_in&B_TSIP) 4426290001Sglebius { 4427106424Sroberto pbuf += sprintf(pbuf, "%s ", protocols_in_text[1]); 4428106424Sroberto known = TRUE; 4429106424Sroberto } 4430106424Sroberto if (known == FALSE) pbuf += sprintf(pbuf, "No known"); 4431106424Sroberto 4432106424Sroberto pbuf += sprintf(pbuf, "\n Output protocols: "); 4433106424Sroberto known = FALSE; 4434106424Sroberto if (protocols_out&B_TSIP) 4435290001Sglebius { 4436106424Sroberto pbuf += sprintf(pbuf, "%s ", protocols_out_text[1]); 4437106424Sroberto known = TRUE; 4438106424Sroberto } 4439106424Sroberto if (protocols_out&B_NMEA) 4440290001Sglebius { 4441106424Sroberto pbuf += sprintf(pbuf, "%s ", protocols_out_text[2]); 4442106424Sroberto known = TRUE; 4443106424Sroberto } 4444106424Sroberto if (known == FALSE) pbuf += sprintf(pbuf, "No known"); 4445106424Sroberto reserved = reserved; 4446106424Sroberto 4447290001Sglebius} 4448106424Sroberto 4449106424Sroberto/* 0x8F */ 4450106424Sroberto/* 8F0B */ 4451290001Sglebiusstatic void 4452290001Sglebiusrpt_8F0B( 4453290001Sglebius TSIPPKT *rpt 4454290001Sglebius ) 4455106424Sroberto{ 4456106424Sroberto const char 4457290001Sglebius *oprtng_dim[7] = { 4458290001Sglebius "horizontal (2-D)", 4459290001Sglebius "full position (3-D)", 4460290001Sglebius "single satellite (0-D)", 4461290001Sglebius "automatic", 4462290001Sglebius "N/A", 4463290001Sglebius "N/A", 4464290001Sglebius "overdetermined clock"}; 4465290001Sglebius char 4466290001Sglebius sv_id[8]; 4467290001Sglebius unsigned char 4468290001Sglebius month, 4469290001Sglebius date, 4470290001Sglebius dim_mode, 4471290001Sglebius north_south, 4472290001Sglebius east_west; 4473290001Sglebius unsigned short 4474290001Sglebius event; 4475106424Sroberto short 4476290001Sglebius utc_offset, 4477290001Sglebius year, 4478290001Sglebius local_index; 4479290001Sglebius short 4480290001Sglebius lat_deg, 4481290001Sglebius lon_deg; 4482290001Sglebius float 4483290001Sglebius bias_unc, 4484290001Sglebius dr_unc; 4485290001Sglebius double 4486290001Sglebius tow, 4487290001Sglebius bias, 4488290001Sglebius drift, 4489290001Sglebius lat, 4490290001Sglebius lon, 4491290001Sglebius alt, 4492290001Sglebius lat_min, 4493290001Sglebius lon_min; 4494290001Sglebius int 4495290001Sglebius numfix, 4496290001Sglebius numnotfix; 4497106424Sroberto 4498106424Sroberto if (rpt_0x8F0B(rpt, 4499290001Sglebius &event, 4500290001Sglebius &tow, 4501290001Sglebius &date, 4502290001Sglebius &month, 4503290001Sglebius &year, 4504290001Sglebius &dim_mode, 4505290001Sglebius &utc_offset, 4506290001Sglebius &bias, 4507290001Sglebius &drift, 4508290001Sglebius &bias_unc, 4509290001Sglebius &dr_unc, 4510290001Sglebius &lat, 4511290001Sglebius &lon, 4512290001Sglebius &alt, 4513290001Sglebius sv_id)) 4514290001Sglebius { 4515106424Sroberto parsed = BADLEN_PARSE; 4516106424Sroberto return; 4517106424Sroberto } 4518106424Sroberto 4519106424Sroberto if (event == 0) 4520290001Sglebius { 4521290001Sglebius pbuf += sprintf(pbuf, "\nNew partial+full meas"); 4522106424Sroberto } 4523290001Sglebius else 4524290001Sglebius { 4525106424Sroberto pbuf += sprintf(pbuf, "\nEvent count: %5d", event); 4526290001Sglebius } 4527106424Sroberto 4528106424Sroberto pbuf += sprintf(pbuf, "\nGPS time : %s %2d/%2d/%2d (DMY)", 4529290001Sglebius show_time(tow), date, month, year); 4530106424Sroberto pbuf += sprintf(pbuf, "\nMode : %s", oprtng_dim[dim_mode]); 4531106424Sroberto pbuf += sprintf(pbuf, "\nUTC offset: %2d", utc_offset); 4532106424Sroberto pbuf += sprintf(pbuf, "\nClock Bias: %6.2f m", bias); 4533106424Sroberto pbuf += sprintf(pbuf, "\nFreq bias : %6.2f m/s", drift); 4534106424Sroberto pbuf += sprintf(pbuf, "\nBias unc : %6.2f m", bias_unc); 4535106424Sroberto pbuf += sprintf(pbuf, "\nFreq unc : %6.2f m/s", dr_unc); 4536106424Sroberto 4537106424Sroberto lat *= R2D; /* convert from radians to degrees */ 4538106424Sroberto lon *= R2D; 4539106424Sroberto if (lat < 0.0) 4540290001Sglebius { 4541106424Sroberto north_south = 'S'; 4542106424Sroberto lat = -lat; 4543106424Sroberto } 4544290001Sglebius else 4545290001Sglebius { 4546106424Sroberto north_south = 'N'; 4547106424Sroberto } 4548106424Sroberto 4549106424Sroberto lat_deg = (short)lat; 4550106424Sroberto lat_min = (lat - lat_deg) * 60.0; 4551106424Sroberto if (lon < 0.0) 4552290001Sglebius { 4553106424Sroberto east_west = 'W'; 4554106424Sroberto lon = -lon; 4555106424Sroberto } 4556290001Sglebius else 4557290001Sglebius { 4558106424Sroberto east_west = 'E'; 4559106424Sroberto } 4560106424Sroberto 4561106424Sroberto lon_deg = (short)lon; 4562106424Sroberto lon_min = (lon - lon_deg) * 60.0; 4563106424Sroberto pbuf += sprintf(pbuf, "\nPosition :"); 4564106424Sroberto pbuf += sprintf(pbuf, " %4d %6.3f %c", lat_deg, lat_min, north_south); 4565106424Sroberto pbuf += sprintf(pbuf, " %5d %6.3f %c", lon_deg, lon_min, east_west); 4566106424Sroberto pbuf += sprintf(pbuf, " %10.2f", alt); 4567106424Sroberto 4568290001Sglebius numfix = numnotfix = 0; 4569106424Sroberto for (local_index=0; local_index<8; local_index++) 4570290001Sglebius { 4571106424Sroberto if (sv_id[local_index] < 0) numnotfix++; 4572106424Sroberto if (sv_id[local_index] > 0) numfix++; 4573290001Sglebius } 4574290001Sglebius if (numfix > 0) 4575290001Sglebius { 4576106424Sroberto pbuf += sprintf(pbuf, "\nSVs used in fix : "); 4577106424Sroberto for (local_index=0; local_index<8; local_index++) 4578290001Sglebius { 4579106424Sroberto if (sv_id[local_index] > 0) 4580290001Sglebius { 4581290001Sglebius pbuf += sprintf(pbuf, "%2d ", sv_id[local_index]); 4582290001Sglebius } 4583290001Sglebius } 4584290001Sglebius } 4585290001Sglebius if (numnotfix > 0) 4586290001Sglebius { 4587106424Sroberto pbuf += sprintf(pbuf, "\nOther SVs tracked: "); 4588106424Sroberto for (local_index=0; local_index<8; local_index++) 4589290001Sglebius { 4590106424Sroberto if (sv_id[local_index] < 0) 4591290001Sglebius { 4592290001Sglebius pbuf += sprintf(pbuf, "%2d ", sv_id[local_index]); 4593290001Sglebius } 4594290001Sglebius } 4595290001Sglebius } 4596106424Sroberto} 4597106424Sroberto 4598106424Sroberto/* 0x8F14 */ 4599106424Sroberto/* Datum parameters */ 4600290001Sglebiusstatic void 4601290001Sglebiusrpt_8F14( 4602290001Sglebius TSIPPKT *rpt 4603290001Sglebius ) 4604106424Sroberto{ 4605106424Sroberto double 4606290001Sglebius datum_coeffs[5]; 4607106424Sroberto short 4608290001Sglebius datum_idx; 4609106424Sroberto 4610106424Sroberto /* unload rptbuf */ 4611106424Sroberto if (rpt_0x8F14 (rpt, &datum_idx, datum_coeffs)) 4612290001Sglebius { 4613106424Sroberto parsed = BADLEN_PARSE; 4614106424Sroberto return; 4615106424Sroberto } 4616106424Sroberto 4617106424Sroberto if (datum_idx == -1) 4618290001Sglebius { 4619290001Sglebius pbuf += sprintf(pbuf, "\nUser-Entered Datum:"); 4620106424Sroberto pbuf += sprintf(pbuf, "\n dx = %6.1f", datum_coeffs[0]); 4621106424Sroberto pbuf += sprintf(pbuf, "\n dy = %6.1f", datum_coeffs[1]); 4622106424Sroberto pbuf += sprintf(pbuf, "\n dz = %6.1f", datum_coeffs[2]); 4623106424Sroberto pbuf += sprintf(pbuf, "\n a-axis = %10.3f", datum_coeffs[3]); 4624106424Sroberto pbuf += sprintf(pbuf, "\n e-squared = %16.14f", datum_coeffs[4]); 4625290001Sglebius } 4626290001Sglebius else if (datum_idx == 0) 4627290001Sglebius { 4628290001Sglebius pbuf += sprintf(pbuf, "\nWGS-84 datum, Index 0 "); 4629290001Sglebius } 4630290001Sglebius else 4631290001Sglebius { 4632290001Sglebius pbuf += sprintf(pbuf, "\nStandard Datum, Index %3d ", datum_idx); 4633290001Sglebius } 4634106424Sroberto} 4635106424Sroberto 4636106424Sroberto/* 0x8F15 */ 4637106424Sroberto/* Datum parameters */ 4638290001Sglebiusstatic void 4639290001Sglebiusrpt_8F15( 4640290001Sglebius TSIPPKT *rpt 4641290001Sglebius ) 4642106424Sroberto{ 4643106424Sroberto double 4644290001Sglebius datum_coeffs[5]; 4645106424Sroberto short 4646290001Sglebius datum_idx; 4647106424Sroberto 4648106424Sroberto /* unload rptbuf */ 4649106424Sroberto if (rpt_0x8F15 (rpt, &datum_idx, datum_coeffs)) { 4650106424Sroberto parsed = BADLEN_PARSE; 4651106424Sroberto return; 4652106424Sroberto } 4653106424Sroberto 4654106424Sroberto if (datum_idx == -1) 4655290001Sglebius { 4656290001Sglebius pbuf += sprintf(pbuf, "\nUser-Entered Datum:"); 4657106424Sroberto pbuf += sprintf(pbuf, "\n dx = %6.1f", datum_coeffs[0]); 4658106424Sroberto pbuf += sprintf(pbuf, "\n dy = %6.1f", datum_coeffs[1]); 4659106424Sroberto pbuf += sprintf(pbuf, "\n dz = %6.1f", datum_coeffs[2]); 4660106424Sroberto pbuf += sprintf(pbuf, "\n a-axis = %10.3f", datum_coeffs[3]); 4661106424Sroberto pbuf += sprintf(pbuf, "\n e-squared = %16.14f", datum_coeffs[4]); 4662290001Sglebius } 4663290001Sglebius else if (datum_idx == 0) 4664290001Sglebius { 4665290001Sglebius pbuf += sprintf(pbuf, "\nWGS-84 datum, Index 0 "); 4666290001Sglebius } 4667290001Sglebius else 4668290001Sglebius { 4669290001Sglebius pbuf += sprintf(pbuf, "\nStandard Datum, Index %3d ", datum_idx); 4670290001Sglebius } 4671106424Sroberto} 4672106424Sroberto 4673106424Sroberto/* 0x8F20 */ 4674106424Sroberto#define INFO_DGPS 0x02 4675106424Sroberto#define INFO_2D 0x04 4676106424Sroberto#define INFO_ALTSET 0x08 4677106424Sroberto#define INFO_FILTERED 0x10 4678290001Sglebiusstatic void 4679290001Sglebiusrpt_8F20( 4680290001Sglebius TSIPPKT *rpt 4681290001Sglebius ) 4682106424Sroberto{ 4683106424Sroberto unsigned char 4684290001Sglebius info, nsvs, sv_prn[32]; 4685106424Sroberto short 4686290001Sglebius week_num, datum_index, sv_IODC[32]; 4687106424Sroberto double 4688290001Sglebius lat, lon, alt, time_of_fix; 4689106424Sroberto double 4690290001Sglebius londeg, latdeg, vel[3]; 4691106424Sroberto short 4692290001Sglebius isv; 4693290001Sglebius char 4694290001Sglebius datum_string[20]; 4695106424Sroberto 4696106424Sroberto /* unload rptbuf */ 4697106424Sroberto if (rpt_0x8F20 (rpt, 4698290001Sglebius &info, &lat, &lon, &alt, vel, 4699290001Sglebius &time_of_fix, 4700290001Sglebius &week_num, &nsvs, sv_prn, sv_IODC, &datum_index)) 4701106424Sroberto { 4702106424Sroberto parsed = BADLEN_PARSE; 4703106424Sroberto return; 4704106424Sroberto } 4705106424Sroberto pbuf += sprintf(pbuf, 4706290001Sglebius "\nFix at: %04d:%3s:%02d:%02d:%06.3f GPS (=UTC+%2ds) FixType: %s%s%s", 4707290001Sglebius week_num, 4708290001Sglebius dayname[(short)(time_of_fix/86400.0)], 4709290001Sglebius (short)fmod(time_of_fix/3600., 24.), 4710290001Sglebius (short)fmod(time_of_fix/60., 60.), 4711290001Sglebius fmod(time_of_fix, 60.), 4712290001Sglebius (char)rpt->buf[29], /* UTC offset */ 4713290001Sglebius (info & INFO_DGPS)?"Diff":"", 4714290001Sglebius (info & INFO_2D)?"2D":"3D", 4715290001Sglebius (info & INFO_FILTERED)?"-Filtrd":""); 4716106424Sroberto 4717290001Sglebius if (datum_index > 0) 4718290001Sglebius { 4719106424Sroberto sprintf(datum_string, "Datum%3d", datum_index); 4720290001Sglebius } 4721290001Sglebius else if (datum_index) 4722290001Sglebius { 4723106424Sroberto sprintf(datum_string, "Unknown "); 4724290001Sglebius } 4725290001Sglebius else 4726290001Sglebius { 4727106424Sroberto sprintf(datum_string, "WGS-84"); 4728290001Sglebius } 4729106424Sroberto 4730106424Sroberto /* convert from radians to degrees */ 4731106424Sroberto latdeg = R2D * fabs(lat); 4732106424Sroberto londeg = R2D * fabs(lon); 4733106424Sroberto pbuf += sprintf(pbuf, 4734290001Sglebius "\n Pos: %4d:%09.6f %c %5d:%09.6f %c %10.2f m HAE (%s)", 4735290001Sglebius (short)latdeg, fmod (latdeg, 1.)*60.0, 4736290001Sglebius (lat<0.0)?'S':'N', 4737290001Sglebius (short)londeg, fmod (londeg, 1.)*60.0, 4738290001Sglebius (lon<0.0)?'W':'E', 4739290001Sglebius alt, 4740290001Sglebius datum_string); 4741106424Sroberto pbuf += sprintf(pbuf, 4742290001Sglebius "\n Vel: %9.3f E %9.3f N %9.3f U (m/sec)", 4743290001Sglebius vel[0], vel[1], vel[2]); 4744106424Sroberto 4745106424Sroberto pbuf += sprintf(pbuf, 4746290001Sglebius "\n SVs: "); 4747106424Sroberto for (isv = 0; isv < nsvs; isv++) { 4748106424Sroberto pbuf += sprintf(pbuf, " %02d", sv_prn[isv]); 4749106424Sroberto } 4750106424Sroberto pbuf += sprintf(pbuf, " (IODEs:"); 4751106424Sroberto for (isv = 0; isv < nsvs; isv++) { 4752106424Sroberto pbuf += sprintf(pbuf, " %02X", sv_IODC[isv]&0xFF); 4753106424Sroberto } 4754106424Sroberto pbuf += sprintf(pbuf, ")"); 4755106424Sroberto} 4756106424Sroberto 4757106424Sroberto/* 0x8F41 */ 4758290001Sglebiusstatic void 4759290001Sglebiusrpt_8F41( 4760290001Sglebius TSIPPKT *rpt 4761290001Sglebius ) 4762106424Sroberto{ 4763106424Sroberto unsigned char 4764290001Sglebius bSearchRange, 4765290001Sglebius bBoardOptions, 4766290001Sglebius bBuildYear, 4767290001Sglebius bBuildMonth, 4768290001Sglebius bBuildDay, 4769290001Sglebius bBuildHour; 4770106424Sroberto float 4771290001Sglebius fOscOffset; 4772106424Sroberto unsigned short 4773290001Sglebius iTestCodeId; 4774106424Sroberto unsigned long 4775290001Sglebius iiSerialNumber; 4776106424Sroberto 4777290001Sglebius if (!rpt_0x8F41(rpt, 4778290001Sglebius &bSearchRange, 4779290001Sglebius &bBoardOptions, 4780290001Sglebius &iiSerialNumber, 4781290001Sglebius &bBuildYear, 4782290001Sglebius &bBuildMonth, 4783290001Sglebius &bBuildDay, 4784290001Sglebius &bBuildHour, 4785290001Sglebius &fOscOffset, 4786290001Sglebius &iTestCodeId)) 4787290001Sglebius { 4788106424Sroberto parsed = BADLEN_PARSE; 4789290001Sglebius return; 4790290001Sglebius } 4791106424Sroberto 4792290001Sglebius pbuf += sprintf(pbuf, "\n search range: %d", 4793290001Sglebius bSearchRange); 4794290001Sglebius pbuf += sprintf(pbuf, "\n board options: %d", 4795290001Sglebius bBoardOptions); 4796290001Sglebius pbuf += sprintf(pbuf, "\n board serial #: %ld", 4797290001Sglebius iiSerialNumber); 4798290001Sglebius pbuf += sprintf(pbuf, "\n build date/hour: %02d/%02d/%02d %02d:00", 4799290001Sglebius bBuildDay, bBuildMonth, bBuildYear, bBuildHour); 4800290001Sglebius pbuf += sprintf(pbuf, "\n osc offset: %.3f PPM (%.0f Hz)", 4801290001Sglebius fOscOffset/1575.42, fOscOffset); 4802290001Sglebius pbuf += sprintf(pbuf, "\n test code: %d", 4803290001Sglebius iTestCodeId); 4804106424Sroberto} 4805106424Sroberto 4806106424Sroberto/* 0x8F42 */ 4807290001Sglebiusstatic void 4808290001Sglebiusrpt_8F42( 4809290001Sglebius TSIPPKT *rpt 4810290001Sglebius ) 4811106424Sroberto{ 4812106424Sroberto unsigned char 4813290001Sglebius bProdOptionsPre, 4814290001Sglebius bProdNumberExt; 4815106424Sroberto unsigned short 4816290001Sglebius iCaseSerialNumberPre, 4817290001Sglebius iPremiumOptions, 4818290001Sglebius iMachineID, 4819290001Sglebius iKey; 4820106424Sroberto unsigned long 4821290001Sglebius iiCaseSerialNumber, 4822290001Sglebius iiProdNumber; 4823106424Sroberto 4824290001Sglebius if (!rpt_0x8F42(rpt, 4825290001Sglebius &bProdOptionsPre, 4826290001Sglebius &bProdNumberExt, 4827290001Sglebius &iCaseSerialNumberPre, 4828290001Sglebius &iiCaseSerialNumber, 4829290001Sglebius &iiProdNumber, 4830290001Sglebius &iPremiumOptions, 4831290001Sglebius &iMachineID, 4832290001Sglebius &iKey)) 4833290001Sglebius { 4834106424Sroberto parsed = BADLEN_PARSE; 4835290001Sglebius return; 4836290001Sglebius } 4837106424Sroberto 4838106424Sroberto pbuf += sprintf(pbuf, "\nProduct ID 8F42"); 4839290001Sglebius pbuf += sprintf(pbuf, "\n extension: %d", bProdNumberExt); 4840290001Sglebius pbuf += sprintf(pbuf, "\n case serial # prefix: %d", iCaseSerialNumberPre); 4841290001Sglebius pbuf += sprintf(pbuf, "\n case serial #: %ld", iiCaseSerialNumber); 4842290001Sglebius pbuf += sprintf(pbuf, "\n prod. #: %ld", iiProdNumber); 4843106424Sroberto pbuf += sprintf(pbuf, "\n premium options: %Xh", iPremiumOptions); 4844290001Sglebius pbuf += sprintf(pbuf, "\n machine ID: %d", iMachineID); 4845290001Sglebius pbuf += sprintf(pbuf, "\n key: %Xh", iKey); 4846106424Sroberto} 4847106424Sroberto 4848106424Sroberto/* 0x8F45 */ 4849290001Sglebiusstatic void 4850290001Sglebiusrpt_8F45( 4851290001Sglebius TSIPPKT *rpt 4852290001Sglebius ) 4853106424Sroberto{ 4854290001Sglebius unsigned char bSegMask; 4855106424Sroberto 4856290001Sglebius if (!rpt_0x8F45(rpt, 4857290001Sglebius &bSegMask)) 4858290001Sglebius { 4859106424Sroberto parsed = BADLEN_PARSE; 4860106424Sroberto return; 4861106424Sroberto } 4862106424Sroberto pbuf += sprintf(pbuf, "\nCleared Segment Mask: %Xh", bSegMask); 4863106424Sroberto} 4864106424Sroberto 4865106424Sroberto/* Stinger PPS def */ 4866290001Sglebiusstatic void 4867290001Sglebiusrpt_8F4A( 4868290001Sglebius TSIPPKT *rpt 4869290001Sglebius ) 4870106424Sroberto{ 4871106424Sroberto unsigned char 4872290001Sglebius pps_enabled, 4873290001Sglebius pps_timebase, 4874290001Sglebius pps_polarity; 4875290001Sglebius float 4876290001Sglebius bias_unc_threshold; 4877290001Sglebius double 4878290001Sglebius pps_offset; 4879106424Sroberto 4880106424Sroberto if (rpt_0x8F4A_16 (rpt, 4881290001Sglebius &pps_enabled, 4882290001Sglebius &pps_timebase, 4883290001Sglebius &pps_polarity, 4884290001Sglebius &pps_offset, 4885290001Sglebius &bias_unc_threshold)) 4886290001Sglebius { 4887290001Sglebius parsed = BADLEN_PARSE; 4888290001Sglebius return; 4889290001Sglebius } 4890106424Sroberto 4891106424Sroberto pbuf += sprintf(pbuf, "\nPPS is %s", pps_enabled?"enabled":"disabled"); 4892290001Sglebius pbuf += sprintf(pbuf, "\n timebase: %s", PPSTimeBaseText[pps_timebase]); 4893290001Sglebius pbuf += sprintf(pbuf, "\n polarity: %s", PPSPolarityText[pps_polarity]); 4894290001Sglebius pbuf += sprintf(pbuf, "\n offset: %.1f ns, ", pps_offset*1.e9); 4895290001Sglebius pbuf += sprintf(pbuf, "\n biasunc: %.1f ns", bias_unc_threshold/GPS_C*1.e9); 4896106424Sroberto} 4897106424Sroberto 4898106424Sroberto/* fast-SA decorrolation time for self-survey */ 4899290001Sglebiusstatic void 4900290001Sglebiusrpt_8F4B( 4901290001Sglebius TSIPPKT *rpt 4902290001Sglebius ) 4903106424Sroberto{ 4904106424Sroberto unsigned long 4905290001Sglebius decorr_max; 4906106424Sroberto 4907290001Sglebius if (rpt_0x8F4B(rpt, &decorr_max)) 4908290001Sglebius { 4909106424Sroberto parsed = BADLEN_PARSE; 4910290001Sglebius return; 4911290001Sglebius } 4912106424Sroberto 4913290001Sglebius pbuf += sprintf(pbuf, 4914290001Sglebius "\nMax # of position fixes for self-survey : %ld", 4915290001Sglebius decorr_max); 4916106424Sroberto} 4917106424Sroberto 4918290001Sglebiusstatic void 4919290001Sglebiusrpt_8F4D( 4920290001Sglebius TSIPPKT *rpt 4921290001Sglebius ) 4922106424Sroberto{ 4923106424Sroberto static char 4924290001Sglebius *linestart; 4925106424Sroberto unsigned long 4926290001Sglebius OutputMask; 4927290001Sglebius static unsigned long 4928290001Sglebius MaskBit[] = { 4929290001Sglebius 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 4930290001Sglebius 0x00000020, 4931290001Sglebius 0x00000100L, 0x00000800L, 0x00001000L, 4932290001Sglebius 0x40000000L, 0x80000000L}; 4933290001Sglebius int 4934290001Sglebius ichoice, 4935290001Sglebius numchoices; 4936106424Sroberto 4937290001Sglebius if (rpt_0x8F4D(rpt, &OutputMask)) 4938290001Sglebius { 4939106424Sroberto parsed = BADLEN_PARSE; 4940290001Sglebius return; 4941290001Sglebius } 4942106424Sroberto 4943290001Sglebius pbuf += sprintf(pbuf, "\nAuto-Report Mask: %02X %02X %02X %02X", 4944290001Sglebius (unsigned char)(OutputMask>>24), 4945290001Sglebius (unsigned char)(OutputMask>>16), 4946290001Sglebius (unsigned char)(OutputMask>>8), 4947290001Sglebius (unsigned char)OutputMask); 4948106424Sroberto 4949290001Sglebius numchoices = sizeof(MaskText)/sizeof(char*); 4950290001Sglebius pbuf += sprintf(pbuf, "\nAuto-Reports scheduled for Output:"); 4951290001Sglebius linestart = pbuf; 4952290001Sglebius for (ichoice = 0; ichoice < numchoices; ichoice++) 4953290001Sglebius { 4954290001Sglebius if (OutputMask&MaskBit[ichoice]) 4955290001Sglebius { 4956290001Sglebius pbuf += sprintf(pbuf, "%s %s", 4957290001Sglebius (pbuf==linestart)?"\n ":",", 4958290001Sglebius MaskText[ichoice]); 4959106424Sroberto if (pbuf-linestart > 60) linestart = pbuf; 4960290001Sglebius } 4961290001Sglebius } 4962106424Sroberto 4963290001Sglebius pbuf += sprintf(pbuf, "\nAuto-Reports NOT scheduled for Output:"); 4964290001Sglebius linestart = pbuf; 4965290001Sglebius for (ichoice = 0; ichoice < numchoices; ichoice++) 4966290001Sglebius { 4967290001Sglebius if (OutputMask&MaskBit[ichoice]) continue; 4968106424Sroberto pbuf += sprintf(pbuf, "%s %s", 4969290001Sglebius (pbuf==linestart)?"\n ":",", 4970290001Sglebius MaskText[ichoice]); 4971106424Sroberto if (pbuf-linestart > 60) linestart = pbuf; 4972290001Sglebius } 4973106424Sroberto} 4974106424Sroberto 4975290001Sglebiusstatic void 4976290001Sglebiusrpt_8FA5( 4977290001Sglebius TSIPPKT *rpt 4978290001Sglebius ) 4979106424Sroberto{ 4980106424Sroberto unsigned char 4981290001Sglebius spktmask[4]; 4982106424Sroberto 4983290001Sglebius if (rpt_0x8FA5(rpt, spktmask)) 4984290001Sglebius { 4985106424Sroberto parsed = BADLEN_PARSE; 4986290001Sglebius return; 4987290001Sglebius } 4988106424Sroberto 4989290001Sglebius pbuf += sprintf(pbuf, "\nSuperpacket auto-output mask: %02X %02X %02X %02X", 4990290001Sglebius spktmask[0], spktmask[1], spktmask[2], spktmask[3]); 4991106424Sroberto 4992290001Sglebius if (spktmask[0]&0x01) pbuf+= sprintf (pbuf, "\n PPS 8F-0B"); 4993290001Sglebius if (spktmask[0]&0x02) pbuf+= sprintf (pbuf, "\n Event 8F-0B"); 4994290001Sglebius if (spktmask[0]&0x10) pbuf+= sprintf (pbuf, "\n PPS 8F-AD"); 4995290001Sglebius if (spktmask[0]&0x20) pbuf+= sprintf (pbuf, "\n Event 8F-AD"); 4996290001Sglebius if (spktmask[2]&0x01) pbuf+= sprintf (pbuf, "\n ppos Fix 8F-20"); 4997106424Sroberto} 4998106424Sroberto 4999290001Sglebiusstatic void 5000290001Sglebiusrpt_8FAD( 5001290001Sglebius TSIPPKT *rpt 5002290001Sglebius ) 5003106424Sroberto{ 5004290001Sglebius unsigned short 5005290001Sglebius Count, 5006290001Sglebius Year; 5007290001Sglebius double 5008290001Sglebius FracSec; 5009290001Sglebius unsigned char 5010290001Sglebius Hour, 5011290001Sglebius Minute, 5012290001Sglebius Second, 5013290001Sglebius Day, 5014290001Sglebius Month, 5015290001Sglebius Status, 5016290001Sglebius Flags; 5017106424Sroberto static char* Status8FADText[] = { 5018290001Sglebius "CODE_DOING_FIXES", 5019290001Sglebius "CODE_GOOD_1_SV", 5020290001Sglebius "CODE_APPX_1SV", 5021290001Sglebius "CODE_NEED_TIME", 5022290001Sglebius "CODE_NEED_INITIALIZATION", 5023290001Sglebius "CODE_PDOP_HIGH", 5024290001Sglebius "CODE_BAD_1SV", 5025290001Sglebius "CODE_0SVS", 5026290001Sglebius "CODE_1SV", 5027290001Sglebius "CODE_2SVS", 5028290001Sglebius "CODE_3SVS", 5029290001Sglebius "CODE_NO_INTEGRITY", 5030290001Sglebius "CODE_DCORR_GEN", 5031290001Sglebius "CODE_OVERDET_CLK", 5032290001Sglebius "Invalid Status"}, 5033290001Sglebius *LeapStatusText[] = { 5034290001Sglebius " UTC Avail", " ", " ", " ", 5035290001Sglebius " Scheduled", " Pending", " Warning", " In Progress"}; 5036290001Sglebius int i; 5037106424Sroberto 5038106424Sroberto if (rpt_0x8FAD (rpt, 5039290001Sglebius &Count, 5040290001Sglebius &FracSec, 5041290001Sglebius &Hour, 5042290001Sglebius &Minute, 5043290001Sglebius &Second, 5044290001Sglebius &Day, 5045290001Sglebius &Month, 5046290001Sglebius &Year, 5047290001Sglebius &Status, 5048290001Sglebius &Flags)) 5049290001Sglebius { 5050106424Sroberto parsed = BADLEN_PARSE; 5051106424Sroberto return; 5052290001Sglebius } 5053106424Sroberto 5054106424Sroberto pbuf += sprintf(pbuf, "\n8FAD Count: %d Status: %s", 5055290001Sglebius Count, Status8FADText[Status]); 5056106424Sroberto 5057290001Sglebius pbuf += sprintf(pbuf, "\n Leap Flags:"); 5058290001Sglebius if (Flags) 5059290001Sglebius { 5060290001Sglebius for (i=0; i<8; i++) 5061290001Sglebius { 5062290001Sglebius if (Flags&(1<<i)) pbuf += sprintf(pbuf, LeapStatusText[i]); 5063290001Sglebius } 5064290001Sglebius } 5065290001Sglebius else 5066290001Sglebius { 5067290001Sglebius pbuf += sprintf(pbuf, " UTC info not available"); 5068290001Sglebius } 5069106424Sroberto 5070106424Sroberto pbuf += sprintf(pbuf, "\n %02d/%02d/%04d (DMY) %02d:%02d:%02d.%09ld UTC", 5071290001Sglebius Day, Month, Year, Hour, Minute, Second, (long)(FracSec*1.e9)); 5072106424Sroberto} 5073106424Sroberto 5074106424Sroberto 5075290001Sglebiusint 5076290001Sglebiusprint_msg_table_header( 5077290001Sglebius int rptcode, 5078290001Sglebius char *HdrStr, 5079290001Sglebius int force 5080290001Sglebius ) 5081106424Sroberto{ 5082106424Sroberto /* force header is to help auto-output function */ 5083106424Sroberto /* last_rptcode is to determine whether to print a header */ 5084132451Sroberto /* for the first occurrence of a series of reports */ 5085106424Sroberto static int 5086290001Sglebius last_rptcode = 0; 5087290001Sglebius int 5088290001Sglebius numchars; 5089106424Sroberto 5090290001Sglebius numchars = 0; 5091106424Sroberto if (force || rptcode!=last_rptcode) 5092290001Sglebius { 5093106424Sroberto /* supply a header in console output */ 5094290001Sglebius switch (rptcode) 5095106424Sroberto { 5096290001Sglebius case 0x5A: 5097106424Sroberto numchars = sprintf(HdrStr, "\nRaw Measurement Data"); 5098106424Sroberto numchars += sprintf(HdrStr+numchars, 5099290001Sglebius "\n SV Sample SNR Code Phase Doppler Seconds Time of Meas"); 5100106424Sroberto break; 5101106424Sroberto 5102290001Sglebius case 0x5B: 5103106424Sroberto numchars = sprintf(HdrStr, "\nEphemeris Status"); 5104106424Sroberto numchars += sprintf(HdrStr+numchars, 5105290001Sglebius "\n SV Time collected Health IODE t oe Fit URA"); 5106106424Sroberto break; 5107106424Sroberto 5108290001Sglebius case 0x5C: 5109106424Sroberto numchars = sprintf(HdrStr, "\nTracking Info"); 5110106424Sroberto numchars += sprintf(HdrStr+numchars, 5111290001Sglebius "\n SV C Acq Eph SNR Time of Meas Elev Azim "); 5112106424Sroberto break; 5113106424Sroberto 5114290001Sglebius } 5115106424Sroberto } 5116106424Sroberto last_rptcode = rptcode; 5117290001Sglebius return (short)numchars; 5118106424Sroberto} 5119106424Sroberto 5120290001Sglebiusstatic void 5121290001Sglebiusunknown_rpt( 5122290001Sglebius TSIPPKT *rpt 5123290001Sglebius ) 5124106424Sroberto{ 5125106424Sroberto int i; 5126106424Sroberto 5127106424Sroberto /* app-specific rpt packets */ 5128106424Sroberto if (parsed == BADLEN_PARSE) 5129290001Sglebius { 5130106424Sroberto pbuf += sprintf(pbuf, "\nTSIP report packet ID %2Xh, length %d: Bad length", 5131290001Sglebius rpt->code, rpt->len); 5132290001Sglebius } 5133106424Sroberto if (parsed == BADID_PARSE) 5134290001Sglebius { 5135106424Sroberto pbuf += sprintf(pbuf, 5136290001Sglebius "\nTSIP report packet ID %2Xh, length %d: translation not supported", 5137290001Sglebius rpt->code, rpt->len); 5138290001Sglebius } 5139106424Sroberto 5140106424Sroberto if (parsed == BADDATA_PARSE) 5141290001Sglebius { 5142106424Sroberto pbuf += sprintf(pbuf, 5143290001Sglebius "\nTSIP report packet ID %2Xh, length %d: data content incorrect", 5144290001Sglebius rpt->code, rpt->len); 5145290001Sglebius } 5146106424Sroberto 5147106424Sroberto for (i = 0; i < rpt->len; i++) { 5148106424Sroberto if ((i % 20) == 0) *pbuf++ = '\n'; 5149106424Sroberto pbuf += sprintf(pbuf, " %02X", rpt->buf[i]); 5150106424Sroberto } 5151106424Sroberto} 5152106424Sroberto/**/ 5153290001Sglebius 5154106424Sroberto/* 5155106424Sroberto** main subroutine, called from ProcessInputBytesWhileWaitingForKBHit() 5156106424Sroberto*/ 5157290001Sglebiusvoid 5158290001SglebiusTranslateTSIPReportToText( 5159290001Sglebius TSIPPKT *rpt, 5160290001Sglebius char *TextOutputBuffer 5161290001Sglebius ) 5162106424Sroberto{ 5163106424Sroberto 5164106424Sroberto /* pbuf is the pointer to the current location of the text output */ 5165106424Sroberto pbuf = TextOutputBuffer; 5166106424Sroberto 5167290001Sglebius /* keep track of whether the message has been successfully parsed */ 5168106424Sroberto parsed = GOOD_PARSE; 5169106424Sroberto 5170106424Sroberto /* print a header if this is the first of a series of messages */ 5171106424Sroberto pbuf += print_msg_table_header (rpt->code, pbuf, FALSE); 5172106424Sroberto 5173290001Sglebius /* process incoming TSIP report according to code */ 5174106424Sroberto switch (rpt->code) 5175290001Sglebius { 5176290001Sglebius case 0x3D: rpt_chan_A_config (rpt); break; 5177290001Sglebius case 0x40: rpt_almanac_data_page (rpt); break; 5178290001Sglebius case 0x41: rpt_GPS_time (rpt); break; 5179290001Sglebius case 0x42: rpt_single_ECEF_position (rpt); break; 5180290001Sglebius case 0x43: rpt_single_ECEF_velocity (rpt); break; 5181290001Sglebius case 0x45: rpt_SW_version (rpt); break; 5182290001Sglebius case 0x46: rpt_rcvr_health (rpt); break; 5183290001Sglebius case 0x47: rpt_SNR_all_SVs (rpt); break; 5184290001Sglebius case 0x48: rpt_GPS_system_message (rpt); break; 5185290001Sglebius case 0x49: rpt_almanac_health_page (rpt); break; 5186290001Sglebius case 0x4A: switch (rpt->len) { 5187290001Sglebius /* 5188290001Sglebius ** special case (=slip-up) in the TSIP protocol; 5189290001Sglebius ** parsing method depends on length 5190290001Sglebius */ 5191290001Sglebius case 20: rpt_single_lla_position (rpt); break; 5192290001Sglebius case 9: rpt_ref_alt (rpt); break; 5193106424Sroberto } break; 5194290001Sglebius case 0x4B: rpt_rcvr_id_and_status (rpt);break; 5195290001Sglebius case 0x4C: rpt_operating_parameters (rpt); break; 5196290001Sglebius case 0x4D: rpt_oscillator_offset (rpt); break; 5197290001Sglebius case 0x4E: rpt_GPS_time_set_response (rpt); break; 5198290001Sglebius case 0x4F: rpt_UTC_offset (rpt); break; 5199290001Sglebius case 0x54: rpt_1SV_bias (rpt); break; 5200290001Sglebius case 0x55: rpt_io_opt (rpt); break; 5201290001Sglebius case 0x56: rpt_ENU_velocity (rpt); break; 5202290001Sglebius case 0x57: rpt_last_fix_info (rpt); break; 5203290001Sglebius case 0x58: rpt_GPS_system_data (rpt); break; 5204290001Sglebius case 0x59: rpt_SVs_enabled (rpt); break; 5205290001Sglebius case 0x5A: rpt_raw_msmt (rpt); break; 5206290001Sglebius case 0x5B: rpt_SV_ephemeris_status (rpt); break; 5207290001Sglebius case 0x5C: rpt_SV_tracking_status (rpt); break; 5208290001Sglebius case 0x6D: rpt_allSV_selection (rpt); break; 5209290001Sglebius case 0x82: rpt_DGPS_position_mode (rpt); break; 5210290001Sglebius case 0x83: rpt_double_ECEF_position (rpt); break; 5211290001Sglebius case 0x84: rpt_double_lla_position (rpt); break; 5212290001Sglebius case 0xBB: rpt_complete_rcvr_config (rpt); break; 5213290001Sglebius case 0xBC: rpt_rcvr_serial_port_config (rpt); break; 5214106424Sroberto 5215290001Sglebius case 0x8F: switch (rpt->buf[0]) 5216290001Sglebius { 5217290001Sglebius /* superpackets; parsed according to subcodes */ 5218290001Sglebius case 0x0B: rpt_8F0B(rpt); break; 5219290001Sglebius case 0x14: rpt_8F14(rpt); break; 5220290001Sglebius case 0x15: rpt_8F15(rpt); break; 5221290001Sglebius case 0x20: rpt_8F20(rpt); break; 5222290001Sglebius case 0x41: rpt_8F41(rpt); break; 5223290001Sglebius case 0x42: rpt_8F42(rpt); break; 5224290001Sglebius case 0x45: rpt_8F45(rpt); break; 5225290001Sglebius case 0x4A: rpt_8F4A(rpt); break; 5226290001Sglebius case 0x4B: rpt_8F4B(rpt); break; 5227290001Sglebius case 0x4D: rpt_8F4D(rpt); break; 5228290001Sglebius case 0xA5: rpt_8FA5(rpt); break; 5229290001Sglebius case 0xAD: rpt_8FAD(rpt); break; 5230290001Sglebius default: parsed = BADID_PARSE; break; 5231106424Sroberto } 5232106424Sroberto break; 5233106424Sroberto 5234290001Sglebius default: parsed = BADID_PARSE; break; 5235106424Sroberto } 5236106424Sroberto 5237106424Sroberto if (parsed != GOOD_PARSE) 5238106424Sroberto { 5239290001Sglebius /* 5240290001Sglebius **The message has TSIP structure (DLEs, etc.) 5241290001Sglebius ** but could not be parsed by above routines 5242290001Sglebius */ 5243106424Sroberto unknown_rpt (rpt); 5244106424Sroberto } 5245106424Sroberto 5246290001Sglebius /* close TextOutputBuffer */ 5247290001Sglebius pbuf = '\0'; 5248106424Sroberto} 5249106424Sroberto 5250106424Sroberto#endif /* TRIMBLE_OUTPUT_FUNC */ 5251106424Sroberto 5252106424Sroberto#else /* defined(REFCLOCK) && defined(CLOCK_RIPENCC) */ 5253106424Srobertoint refclock_ripencc_bs; 5254106424Sroberto#endif /* defined(REFCLOCK) && defined(CLOCK_RIPENCC) */ 5255106424Sroberto 5256