PageRenderTime 137ms CodeModel.GetById 35ms app.highlight 85ms RepoModel.GetById 1ms app.codeStats 1ms

/contrib/ntp/ntpd/refclock_ripencc.c

https://bitbucket.org/freebsd/freebsd-head/
C | 4866 lines | 3751 code | 591 blank | 524 comment | 411 complexity | 262eb696cb696d14c100f9b876355fbe MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2 * $Id: refclock_ripencc.c,v 1.13 2002/06/18 14:20:55 marks Exp marks $
   3 *
   4 * Copyright (c) 2002  RIPE NCC
   5 *
   6 * All Rights Reserved
   7 *
   8 * Permission to use, copy, modify, and distribute this software and its
   9 * documentation for any purpose and without fee is hereby granted,
  10 * provided that the above copyright notice appear in all copies and that
  11 * both that copyright notice and this permission notice appear in
  12 * supporting documentation, and that the name of the author not be
  13 * used in advertising or publicity pertaining to distribution of the
  14 * software without specific, written prior permission.
  15 *
  16 * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  17 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  18 * AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  19 * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  20 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  21 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22 *
  23 *
  24 *
  25 * This driver was developed for use with the RIPE NCC TTM project.
  26 *
  27 *
  28 * The initial driver was developed by Daniel Karrenberg <dfk@ripe.net> 
  29 * using the code made available by Trimble. This was for xntpd-3.x.x
  30 *
  31 * Rewrite of the driver for ntpd-4.x.x by Mark Santcroos <marks@ripe.net>
  32 *
  33 */
  34
  35#ifdef HAVE_CONFIG_H
  36#include <config.h>
  37#endif /* HAVE_CONFIG_H */
  38
  39#if defined(REFCLOCK) && defined(CLOCK_RIPENCC)
  40
  41#include "ntp_stdlib.h"
  42#include "ntpd.h"
  43#include "ntp_refclock.h"
  44#include "ntp_unixtime.h"
  45#include "ntp_io.h"
  46
  47#ifdef HAVE_PPSAPI
  48# include "ppsapi_timepps.h"
  49#endif
  50
  51/*
  52 * Definitions
  53 */
  54
  55/* we are on little endian */
  56#define BYTESWAP
  57
  58/* 
  59 * DEBUG statements: uncomment if necessary
  60 */
  61/* #define DEBUG_NCC */ /* general debug statements */
  62/* #define DEBUG_PPS */ /* debug pps */
  63/* #define DEBUG_RAW */ /* print raw packets */
  64
  65#define TRIMBLE_OUTPUT_FUNC
  66#define TSIP_VERNUM "7.12a"
  67
  68#ifndef FALSE
  69#define FALSE 	(0)
  70#define TRUE 	(!FALSE)
  71#endif /* FALSE */
  72
  73#define GPS_PI 	(3.1415926535898)
  74#define GPS_C 		(299792458.)
  75#define	D2R		(GPS_PI/180.0)
  76#define	R2D		(180.0/GPS_PI)
  77#define WEEK 	(604800.)
  78#define MAXCHAN  (8)
  79
  80/* control characters for TSIP packets */
  81#define DLE 	(0x10)
  82#define ETX 	(0x03)
  83
  84#define MAX_RPTBUF (256)
  85
  86/* values of TSIPPKT.status */
  87#define TSIP_PARSED_EMPTY 	0
  88#define TSIP_PARSED_FULL 	1
  89#define TSIP_PARSED_DLE_1 	2
  90#define TSIP_PARSED_DATA 	3
  91#define TSIP_PARSED_DLE_2 	4
  92
  93#define UTCF_UTC_AVAIL  (unsigned char) (1)             /* UTC available */
  94#define UTCF_LEAP_SCHD  (unsigned char) (1<<4)  /* Leap scheduled */
  95#define UTCF_LEAP_PNDG  (unsigned char) (1<<5)  /* Leap pending, will occur at end of day */
  96
  97#define DEVICE  "/dev/gps%d"	/* name of radio device */
  98#define PRECISION       (-9)    /* precision assumed (about 2 ms) */
  99#define PPS_PRECISION   (-20)	/* precision assumed (about 1 us) */
 100#define REFID           "GPS\0" /* reference id */
 101#define REFID_LEN	4
 102#define DESCRIPTION     "RIPE NCC GPS (Palisade)"	/* Description */
 103#define SPEED232        B9600   /* 9600 baud */
 104
 105#define NSAMPLES        3       /* stages of median filter */
 106
 107/* Structures */
 108
 109/* TSIP packets have the following structure, whether report or command. */
 110typedef struct {
 111	short 
 112		counter, 	/* counter */
 113		len;		/* size of buf; < MAX_RPTBUF unsigned chars */
 114	unsigned char
 115		status,		/* TSIP packet format/parse status */
 116		code,		/* TSIP code */
 117		buf[MAX_RPTBUF];/* report or command string */
 118} TSIPPKT;
 119
 120/* TSIP binary data structures */
 121typedef struct {
 122	unsigned char
 123		t_oa_raw, SV_health;
 124	float
 125		e, t_oa, i_0, OMEGADOT, sqrt_A,
 126		OMEGA_0, omega, M_0, a_f0, a_f1,
 127		Axis, n, OMEGA_n, ODOT_n, t_zc;
 128	short
 129		weeknum, wn_oa;
 130} ALM_INFO;
 131
 132typedef struct {     /*  Almanac health page (25) parameters  */
 133	unsigned char
 134		WN_a, SV_health[32], t_oa;
 135} ALH_PARMS;
 136
 137typedef struct {     /*  Universal Coordinated Time (UTC) parms */
 138	double
 139		A_0;
 140	float
 141		A_1;
 142	short
 143		delta_t_LS;
 144	float
 145		t_ot;
 146	short
 147		WN_t, WN_LSF, DN, delta_t_LSF;
 148} UTC_INFO;
 149
 150typedef struct {      /*  Ionospheric info (float)  */
 151	float
 152		alpha_0, alpha_1, alpha_2, alpha_3,
 153		beta_0, beta_1, beta_2, beta_3;
 154} ION_INFO;
 155
 156typedef struct {      /*  Subframe 1 info (float)  */
 157	short
 158		weeknum;
 159	unsigned char
 160		codeL2, L2Pdata, SVacc_raw, SV_health;
 161	short
 162		IODC;
 163	float
 164		T_GD, t_oc, a_f2, a_f1, a_f0, SVacc;
 165} EPHEM_CLOCK;
 166
 167typedef	struct {     /*  Ephemeris info (float)  */
 168	unsigned char
 169		IODE, fit_interval;
 170	float
 171		C_rs, delta_n;
 172	double
 173		M_0;
 174	float
 175		C_uc;
 176	double
 177		e;
 178	float
 179		C_us;
 180	double
 181		sqrt_A;
 182	float
 183		t_oe, C_ic;
 184	double
 185		OMEGA_0;
 186	float
 187		C_is;
 188	double
 189		i_0;
 190	float
 191		C_rc;
 192	double
 193		omega;
 194	float
 195		OMEGADOT, IDOT;
 196	double
 197		Axis, n, r1me2, OMEGA_n, ODOT_n;
 198} EPHEM_ORBIT;
 199
 200typedef struct {     /* Navigation data structure */
 201	short
 202		sv_number;     /* SV number (0 = no entry) */
 203	float
 204		t_ephem;       /* time of ephemeris collection */
 205	EPHEM_CLOCK
 206		ephclk;        /* subframe 1 data */
 207	EPHEM_ORBIT
 208		ephorb;        /* ephemeris data */
 209} NAV_INFO;
 210
 211typedef struct {
 212	unsigned char
 213		bSubcode,
 214		operating_mode,
 215		dgps_mode,
 216		dyn_code,
 217		trackmode;
 218	float
 219		elev_mask,
 220		cno_mask,
 221		dop_mask,
 222		dop_switch;
 223	unsigned char
 224		dgps_age_limit;
 225} TSIP_RCVR_CFG;
 226
 227
 228#ifdef TRIMBLE_OUTPUT_FUNC
 229static char
 230	*dayname[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"},
 231	old_baudnum[] = {0, 1, 4, 5, 6, 8, 9, 11, 28, 12},
 232        *st_baud_text_app [] = {"", "", "  300", "  600", " 1200", " 2400", 
 233		" 4800", " 9600", "19200", "38400"},
 234	*old_parity_text[] = {"EVEN", "ODD", "", "", "NONE"},
 235	*parity_text [] = {"NONE", "ODD", "EVEN"},
 236	*old_input_ch[] = { "TSIP", "RTCM (6 of 8 bits)"},
 237	*old_output_ch[] = { "TSIP", "No output", "", "", "", "NMEA 0183"},
 238	*protocols_in_text[] = { "", "TSIP", "", ""},
 239	*protocols_out_text[] =	{ "", "TSIP", "NMEA"},
 240	*rcvr_port_text [] = { "Port A      ", "Port B      ", "Current Port"},
 241	*dyn_text [] = {"Unchanged", "Land", "Sea", "Air", "Static"},
 242	*NavModeText0xBB[] = {"automatic", "time only (0-D)", "", "2-D",
 243		"3-D", "", "", "OverDetermined Time"},
 244	*PPSTimeBaseText[] = {"GPS", "UTC", "USER"},
 245	*PPSPolarityText[] = {"Positive", "Negative"},
 246  	*MaskText[] = { "Almanac  ", "Ephemeris", "UTC      ", "Iono     ",
 247		"GPS Msg  ", "Alm Hlth ", "Time Fix ", "SV Select",
 248		"Ext Event", "Pos Fix  ", "Raw Meas "};
 249
 250#endif /* TRIMBLE_OUTPUT_FUNC */
 251
 252/*
 253 * Unit control structure
 254 */
 255struct ripencc_unit {                   
 256        int unit;                       /* unit number */
 257        int     pollcnt;                /* poll message counter */
 258        int     polled;                 /* Hand in a sample? */
 259        char leapdelta;                 /* delta of next leap event */
 260        unsigned char utcflags;         /* delta of next leap event */
 261        l_fp    tstamp;                 /* timestamp of last poll */
 262        
 263        struct timespec ts;             /* last timestamp */
 264        pps_params_t pps_params;        /* pps parameters */
 265        pps_info_t pps_info;            /* last pps data */
 266        pps_handle_t handle;            /* pps handlebars */
 267
 268};
 269
 270
 271/*******************        PROTOYPES            *****************/
 272
 273/*  prototypes for report parsing primitives */
 274short rpt_0x3D (TSIPPKT *rpt, unsigned char *tx_baud_index,
 275	unsigned char *rx_baud_index, unsigned char *char_format_index,
 276	unsigned char *stop_bits, unsigned char *tx_mode_index,
 277	unsigned char *rx_mode_index);
 278short rpt_0x40 (TSIPPKT *rpt, unsigned char *sv_prn, short *week_num,
 279	float *t_zc, float *eccentricity, float *t_oa, float *i_0,
 280	float *OMEGA_dot, float *sqrt_A, float *OMEGA_0, float *omega,
 281	float *M_0);
 282short rpt_0x41 (TSIPPKT *rpt, float *time_of_week, float *UTC_offset,
 283	short *week_num);
 284short rpt_0x42 (TSIPPKT *rpt, float ECEF_pos[3], float *time_of_fix);
 285short rpt_0x43 (TSIPPKT *rpt, float ECEF_vel[3], float *freq_offset,
 286	float *time_of_fix);
 287short rpt_0x45 (TSIPPKT *rpt, unsigned char *major_nav_version,
 288	unsigned char *minor_nav_version, unsigned char *nav_day,
 289	unsigned char *nav_month, unsigned char *nav_year,
 290	unsigned char *major_dsp_version, unsigned char *minor_dsp_version,
 291	unsigned char *dsp_day, unsigned char *dsp_month,
 292	unsigned char *dsp_year);
 293short rpt_0x46 (TSIPPKT *rpt, unsigned char *status1, unsigned char *status2);
 294short rpt_0x47 (TSIPPKT *rpt, unsigned char *nsvs, unsigned char *sv_prn,
 295	float *snr);
 296short rpt_0x48 (TSIPPKT *rpt, unsigned char *message);
 297short rpt_0x49 (TSIPPKT *rpt, unsigned char *sv_health);
 298short rpt_0x4A (TSIPPKT *rpt, float *lat, float *lon, float *alt,
 299	float *clock_bias, float *time_of_fix);
 300short rpt_0x4A_2 (TSIPPKT *rpt, float *alt, float *dummy,
 301	unsigned char *alt_flag);
 302short rpt_0x4B (TSIPPKT *rpt, unsigned char *machine_id,
 303	unsigned char *status3, unsigned char *status4);
 304short rpt_0x4C (TSIPPKT *rpt, unsigned char *dyn_code, float *el_mask,
 305	float *snr_mask, float *dop_mask, float *dop_switch);
 306short rpt_0x4D (TSIPPKT *rpt, float *osc_offset);
 307short rpt_0x4E (TSIPPKT *rpt, unsigned char *response);
 308short rpt_0x4F (TSIPPKT *rpt, double *a0, float *a1, float *time_of_data,
 309	short *dt_ls, short *wn_t, short *wn_lsf, short *dn, short *dt_lsf);
 310short rpt_0x54 (TSIPPKT *rpt, float *clock_bias, float *freq_offset,
 311	float *time_of_fix);
 312short rpt_0x55 (TSIPPKT *rpt, unsigned char *pos_code, unsigned char *vel_code,
 313	unsigned char *time_code, unsigned char *aux_code);
 314short rpt_0x56 (TSIPPKT *rpt, float vel_ENU[3], float *freq_offset,
 315	float *time_of_fix);
 316short rpt_0x57 (TSIPPKT *rpt, unsigned char *source_code,
 317	unsigned char *diag_code, short *week_num, float *time_of_fix);
 318short rpt_0x58 (TSIPPKT *rpt, unsigned char *op_code, unsigned char *data_type,
 319	unsigned char *sv_prn, unsigned char *data_length,
 320	unsigned char *data_packet);
 321short rpt_0x59 (TSIPPKT *rpt, unsigned char *code_type,
 322	unsigned char status_code[32]);
 323short rpt_0x5A (TSIPPKT *rpt, unsigned char *sv_prn, float *sample_length,
 324	float *signal_level, float *code_phase, float *Doppler,
 325	double *time_of_fix);
 326short rpt_0x5B (TSIPPKT *rpt, unsigned char *sv_prn, unsigned char *sv_health,
 327	unsigned char *sv_iode, unsigned char *fit_interval_flag,
 328	float *time_of_collection, float *time_of_eph, float *sv_accy);
 329short rpt_0x5C (TSIPPKT *rpt, unsigned char *sv_prn, unsigned char *slot,
 330	unsigned char *chan, unsigned char *acq_flag, unsigned char *eph_flag,
 331	float *signal_level, float *time_of_last_msmt, float *elev,
 332	float *azim, unsigned char *old_msmt_flag,
 333	unsigned char *integer_msec_flag, unsigned char *bad_data_flag,
 334	unsigned char *data_collect_flag);
 335short rpt_0x6D (TSIPPKT *rpt, unsigned char *manual_mode, unsigned char *nsvs,
 336	unsigned char *ndim, unsigned char sv_prn[], float *pdop,
 337	float *hdop, float *vdop, float *tdop);
 338short rpt_0x82 (TSIPPKT *rpt, unsigned char *diff_mode);
 339short rpt_0x83 (TSIPPKT *rpt, double ECEF_pos[3], double *clock_bias,
 340	float *time_of_fix);
 341short rpt_0x84 (TSIPPKT *rpt, double *lat, double *lon, double *alt,
 342	double *clock_bias, float *time_of_fix);
 343short rpt_Paly0xBB(TSIPPKT *rpt, TSIP_RCVR_CFG *TsipxBB);
 344short rpt_0xBC   (TSIPPKT *rpt, unsigned char *port_num,
 345	unsigned char *in_baud, unsigned char *out_baud,
 346	unsigned char *data_bits, unsigned char *parity,
 347	unsigned char *stop_bits, unsigned char *flow_control,
 348	unsigned char *protocols_in, unsigned char *protocols_out,
 349	unsigned char *reserved);
 350
 351/* prototypes for superpacket parsers */
 352
 353short rpt_0x8F0B (TSIPPKT *rpt, unsigned short *event, double *tow,
 354   unsigned char *date, unsigned char *month, short *year,
 355   unsigned char *dim_mode, short *utc_offset, double *bias, double *drift,
 356   float *bias_unc, float *dr_unc, double *lat, double *lon, double *alt,
 357   char sv_id[8]);
 358short rpt_0x8F14 (TSIPPKT *rpt, short *datum_idx, double datum_coeffs[5]);
 359short rpt_0x8F15 (TSIPPKT *rpt, short *datum_idx, double datum_coeffs[5]);
 360short rpt_0x8F20 (TSIPPKT *rpt, unsigned char *info, double *lat,
 361	double *lon, double *alt, double vel_enu[], double *time_of_fix,
 362	short *week_num, unsigned char *nsvs, unsigned char sv_prn[], 
 363	short sv_IODC[], short *datum_index);
 364short rpt_0x8F41 (TSIPPKT *rpt, unsigned char *bSearchRange,
 365	unsigned char *bBoardOptions, unsigned long *iiSerialNumber,
 366	unsigned char *bBuildYear, unsigned char *bBuildMonth,
 367	unsigned char *bBuildDay, unsigned char *bBuildHour,
 368	float *fOscOffset, unsigned short *iTestCodeId);
 369short rpt_0x8F42 (TSIPPKT *rpt, unsigned char *bProdOptionsPre,
 370	unsigned char *bProdNumberExt, unsigned short *iCaseSerialNumberPre,
 371	unsigned long *iiCaseSerialNumber, unsigned long *iiProdNumber,
 372	unsigned short *iPremiumOptions, unsigned short *iMachineID,
 373	unsigned short *iKey);
 374short rpt_0x8F45 (TSIPPKT *rpt, unsigned char *bSegMask);
 375short rpt_0x8F4A_16 (TSIPPKT *rpt, unsigned char *pps_enabled,
 376	unsigned char *pps_timebase, unsigned char *pos_polarity,
 377	double *pps_offset, float *bias_unc_threshold);
 378short rpt_0x8F4B (TSIPPKT *rpt, unsigned long *decorr_max);
 379short rpt_0x8F4D (TSIPPKT *rpt, unsigned long *event_mask);
 380short rpt_0x8FA5 (TSIPPKT *rpt, unsigned char *spktmask);
 381short rpt_0x8FAD (TSIPPKT *rpt, unsigned short *COUNT, double *FracSec,
 382    unsigned char *Hour, unsigned char *Minute, unsigned char *Second,
 383    unsigned char *Day, unsigned char *Month, unsigned short *Year,
 384    unsigned char *Status, unsigned char *Flags);
 385
 386/**/
 387/* prototypes for command-encode primitives with suffix convention:  */
 388/* c = clear, s = set, q = query, e = enable, d = disable            */
 389void cmd_0x1F  (TSIPPKT *cmd);
 390void cmd_0x26  (TSIPPKT *cmd);
 391void cmd_0x2F  (TSIPPKT *cmd);
 392void cmd_0x35s (TSIPPKT *cmd, unsigned char pos_code, unsigned char vel_code,
 393	unsigned char time_code, unsigned char opts_code);
 394void cmd_0x3C  (TSIPPKT *cmd, unsigned char sv_prn);
 395void cmd_0x3Ds (TSIPPKT *cmd, unsigned char baud_out, unsigned char baud_inp,
 396	unsigned char char_code, unsigned char stopbitcode,
 397	unsigned char output_mode, unsigned char input_mode);
 398void cmd_0xBBq (TSIPPKT *cmd, unsigned char subcode) ;
 399
 400/* prototypes 8E commands */
 401void cmd_0x8E0Bq (TSIPPKT *cmd);
 402void cmd_0x8E41q (TSIPPKT *cmd);
 403void cmd_0x8E42q (TSIPPKT *cmd);
 404void cmd_0x8E4Aq (TSIPPKT *cmd);
 405void cmd_0x8E4As (TSIPPKT *cmd, unsigned char PPSOnOff, unsigned char TimeBase,
 406	unsigned char Polarity, double PPSOffset, float Uncertainty);
 407void cmd_0x8E4Bq (TSIPPKT *cmd);
 408void cmd_0x8E4Ds (TSIPPKT *cmd, unsigned long AutoOutputMask);
 409void cmd_0x8EADq (TSIPPKT *cmd);
 410
 411/* header/source border XXXXXXXXXXXXXXXXXXXXXXXXXX */
 412
 413/* Trimble parse functions */
 414static 	int	parse0x8FAD	P((TSIPPKT *, struct peer *));
 415static 	int	parse0x8F0B	P((TSIPPKT *, struct peer *));
 416#ifdef TRIMBLE_OUTPUT_FUNC
 417static 	int	parseany	P((TSIPPKT *, struct peer *));
 418static 	void	TranslateTSIPReportToText	P((TSIPPKT *, char *));
 419#endif /* TRIMBLE_OUTPUT_FUNC */
 420static 	int	parse0x5C	P((TSIPPKT *, struct peer *));
 421static 	int	parse0x4F	P((TSIPPKT *, struct peer *));
 422static	void	tsip_input_proc	P((TSIPPKT *, int));
 423
 424/* Trimble helper functions */
 425static	void	bPutFloat 	P((float *, unsigned char *));
 426static	void	bPutDouble 	P((double *, unsigned char *));
 427static	void	bPutULong 	P((unsigned long *, unsigned char *));
 428static	int	print_msg_table_header	P((int rptcode, char *HdrStr, int force));
 429static	char *	show_time	P((float time_of_week));
 430
 431/* RIPE NCC functions */
 432static	void	ripencc_control	P((int, struct refclockstat *, struct
 433				refclockstat *, struct peer *));
 434static	int	ripencc_ppsapi	P((struct peer *, int, int));
 435static	int	ripencc_get_pps_ts	P((struct ripencc_unit *, l_fp *));
 436static	int	ripencc_start	P((int, struct peer *));
 437static 	void	ripencc_shutdown	P((int, struct peer *));
 438static 	void	ripencc_poll	P((int, struct peer *));
 439static 	void	ripencc_send	P((struct peer *, TSIPPKT spt));
 440static 	void	ripencc_receive	P((struct recvbuf *));
 441
 442/* fill in reflock structure for our clock */
 443struct refclock refclock_ripencc = {
 444	ripencc_start,		/* start up driver */
 445	ripencc_shutdown,	/* shut down driver */
 446	ripencc_poll,		/* transmit poll message */
 447	ripencc_control,	/* control function */
 448	noentry,		/* initialize driver */
 449	noentry,		/* debug info */
 450	NOFLAGS			/* clock flags */
 451};
 452
 453/*
 454 *  Tables to compute the ddd of year form icky dd/mm timecode. Viva la
 455 *  leap.
 456 */
 457static int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 458static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 459
 460
 461/*
 462 * ripencc_start - open the GPS devices and initialize data for processing
 463 */
 464static int
 465ripencc_start(int unit, struct peer *peer)
 466{
 467	register struct ripencc_unit *up;
 468	struct refclockproc *pp;
 469	char device[40];
 470	int fd;
 471	struct termios tio;
 472	TSIPPKT spt;
 473
 474	/*
 475	 * Open serial port
 476	 */
 477	(void)snprintf(device, sizeof(device), DEVICE, unit);
 478	if (!(fd = refclock_open(device, SPEED232, LDISC_RAW)))
 479		return (0);
 480
 481	/* from refclock_palisade.c */
 482	if (tcgetattr(fd, &tio) < 0) {
 483		msyslog(LOG_ERR, "Palisade(%d) tcgetattr(fd, &tio): %m",unit);
 484		return (0);
 485	}
 486
 487	/*
 488	 * set flags
 489	 */
 490	tio.c_cflag |= (PARENB|PARODD);
 491	tio.c_iflag &= ~ICRNL;
 492	if (tcsetattr(fd, TCSANOW, &tio) == -1) {
 493		msyslog(LOG_ERR, "Palisade(%d) tcsetattr(fd, &tio): %m",unit);
 494		return (0);
 495	}
 496
 497	/*
 498	 * Allocate and initialize unit structure
 499	 */
 500	if (!(up = (struct ripencc_unit *) 
 501				emalloc(sizeof(struct ripencc_unit)))) {
 502		(void) close(fd);
 503		return (0);
 504	}
 505	memset((char *)up, 0, sizeof(struct ripencc_unit));
 506	pp = peer->procptr;
 507	pp->io.clock_recv = ripencc_receive;
 508	pp->io.srcclock = (caddr_t)peer;
 509	pp->io.datalen = 0;
 510	pp->io.fd = fd;
 511	if (!io_addclock(&pp->io)) {
 512		(void) close(fd);
 513		free(up);
 514		return (0);
 515	}
 516	pp->unitptr = (caddr_t)up;
 517
 518	/*
 519	 * Initialize miscellaneous variables
 520	 */
 521	peer->precision = PRECISION;
 522	pp->clockdesc = DESCRIPTION;
 523	memcpy((char *)&pp->refid, REFID, REFID_LEN);
 524	up->pollcnt = 2;
 525	up->unit = unit;
 526	up->leapdelta = 0;
 527	up->utcflags = 0;
 528
 529	/*
 530	 * Initialize the Clock
 531	 */
 532
 533	/* query software versions */
 534	cmd_0x1F(&spt);			
 535	ripencc_send(peer, spt);          
 536
 537	/* query receiver health */
 538	cmd_0x26(&spt);			
 539	ripencc_send(peer, spt);
 540
 541	/* query serial numbers */	
 542	cmd_0x8E42q(&spt);		
 543	ripencc_send(peer, spt);  
 544	
 545	/* query manuf params */
 546	cmd_0x8E41q(&spt);		
 547	ripencc_send(peer, spt); 
 548
 549	/* i/o opts */ /* trimble manual page A30 */
 550	cmd_0x35s(&spt, 
 551		0x1C, 	/* position */
 552		0x00, 	/* velocity */
 553		0x05, 	/* timing */
 554		0x0a); 	/* auxilary */
 555	ripencc_send(peer, spt);
 556	
 557	/* turn off port A */
 558	cmd_0x3Ds (&spt,
 559		0x0B, /* baud_out */
 560		0x0B, /* baud_inp */
 561		0x07, /* char_code */
 562		0x07, /* stopbitcode */
 563		0x01, /* output_mode */
 564		0x00); /* input_mode */
 565	ripencc_send(peer, spt);
 566
 567	/* set i/o options */
 568	cmd_0x8E4As (&spt,
 569		0x01, 		/* PPS on */
 570		0x01, 		/* Timebase UTC */
 571		0x00, 		/* polarity positive */
 572		0., 		/* 100 ft. cable XXX make flag */
 573		1e-6 * GPS_C); 	/* turn of biasuncert. > (1us) */
 574	ripencc_send(peer,spt);
 575
 576	/* all outomatic packet output off */
 577	cmd_0x8E4Ds(&spt,
 578		0x00000000); /* AutoOutputMask */
 579	ripencc_send(peer, spt);
 580
 581	cmd_0xBBq (&spt,
 582		0x00); /* query primary configuration */
 583	ripencc_send(peer,spt);
 584
 585
 586	/* query PPS parameters */
 587	cmd_0x8E4Aq (&spt); /* query PPS params */
 588	ripencc_send(peer,spt);
 589
 590	/* query survey limit */
 591	cmd_0x8E4Bq (&spt); /* query survey limit */
 592	ripencc_send(peer,spt);
 593
 594#ifdef DEBUG_NCC
 595	if (debug)
 596		printf("ripencc_start: success\n");
 597#endif /* DEBUG_NCC */
 598
 599	/*
 600	 * Start the PPSAPI interface if it is there. Default to use
 601	 * the assert edge and do not enable the kernel hardpps.
 602	 */
 603	if (time_pps_create(fd, &up->handle) < 0) {
 604		up->handle = 0;
 605		msyslog(LOG_ERR, "refclock_ripencc: time_pps_create failed: %m");
 606		return (1);
 607	}
 608
 609	return(ripencc_ppsapi(peer, 0, 0));
 610}
 611
 612/*
 613 * ripencc_control - fudge control
 614 */
 615static void
 616ripencc_control(
 617	int unit,		/* unit (not used) */
 618	struct refclockstat *in, /* input parameters (not used) */
 619	struct refclockstat *out, /* output parameters (not used) */
 620	struct peer *peer	/* peer structure pointer */
 621	)
 622{
 623	struct refclockproc *pp;
 624
 625#ifdef DEBUG_NCC
 626	msyslog(LOG_INFO,"%s()",__FUNCTION__);
 627#endif /* DEBUG_NCC */
 628
 629	pp = peer->procptr;
 630	ripencc_ppsapi(peer, pp->sloppyclockflag & CLK_FLAG2,
 631	    pp->sloppyclockflag & CLK_FLAG3);
 632}
 633
 634
 635/*
 636 * Initialize PPSAPI
 637 */
 638int
 639ripencc_ppsapi(
 640	struct peer *peer,	/* peer structure pointer */
 641	int enb_clear,		/* clear enable */
 642	int enb_hardpps		/* hardpps enable */
 643	)
 644{
 645	struct refclockproc *pp;
 646	struct ripencc_unit *up;
 647	int capability;
 648
 649	pp = peer->procptr;
 650	up = (struct ripencc_unit *)pp->unitptr;
 651	if (time_pps_getcap(up->handle, &capability) < 0) {
 652		msyslog(LOG_ERR,
 653		    "refclock_ripencc: time_pps_getcap failed: %m");
 654		return (0);
 655	}
 656	memset(&up->pps_params, 0, sizeof(pps_params_t));
 657	if (enb_clear)
 658		up->pps_params.mode = capability & PPS_CAPTURECLEAR;
 659	else
 660		up->pps_params.mode = capability & PPS_CAPTUREASSERT;
 661	if (!up->pps_params.mode) {
 662		msyslog(LOG_ERR,
 663		    "refclock_ripencc: invalid capture edge %d",
 664		    !enb_clear);
 665		return (0);
 666	}
 667	up->pps_params.mode |= PPS_TSFMT_TSPEC;
 668	if (time_pps_setparams(up->handle, &up->pps_params) < 0) {
 669		msyslog(LOG_ERR,
 670		    "refclock_ripencc: time_pps_setparams failed: %m");
 671		return (0);
 672	}
 673	if (enb_hardpps) {
 674		if (time_pps_kcbind(up->handle, PPS_KC_HARDPPS,
 675				    up->pps_params.mode & ~PPS_TSFMT_TSPEC,
 676				    PPS_TSFMT_TSPEC) < 0) {
 677			msyslog(LOG_ERR,
 678			    "refclock_ripencc: time_pps_kcbind failed: %m");
 679			return (0);
 680		}
 681		pps_enable = 1;
 682	}
 683	peer->precision = PPS_PRECISION;
 684
 685#if DEBUG_NCC
 686	if (debug) {
 687		time_pps_getparams(up->handle, &up->pps_params);
 688		printf(
 689		    "refclock_ripencc: capability 0x%x version %d mode 0x%x kern %d\n",
 690		    capability, up->pps_params.api_version,
 691		    up->pps_params.mode, enb_hardpps);
 692	}
 693#endif /* DEBUG_NCC */
 694
 695	return (1);
 696}
 697
 698/*
 699 * This function is called every 64 seconds from ripencc_receive
 700 * It will fetch the pps time 
 701 *
 702 * Return 0 on failure and 1 on success.
 703 */
 704static int
 705ripencc_get_pps_ts(
 706	struct ripencc_unit *up,
 707	l_fp *tsptr
 708	)
 709{
 710	pps_info_t pps_info;
 711	struct timespec timeout, ts;
 712	double dtemp;
 713	l_fp tstmp;
 714
 715#ifdef DEBUG_PPS
 716	msyslog(LOG_INFO,"ripencc_get_pps_ts\n");
 717#endif /* DEBUG_PPS */
 718
 719
 720	/*
 721	 * Convert the timespec nanoseconds field to ntp l_fp units.
 722	 */ 
 723	if (up->handle == 0)
 724		return (0);
 725	timeout.tv_sec = 0;
 726	timeout.tv_nsec = 0;
 727	memcpy(&pps_info, &up->pps_info, sizeof(pps_info_t));
 728	if (time_pps_fetch(up->handle, PPS_TSFMT_TSPEC, &up->pps_info,
 729	    &timeout) < 0)
 730		return (0);
 731	if (up->pps_params.mode & PPS_CAPTUREASSERT) {
 732		if (pps_info.assert_sequence ==
 733		    up->pps_info.assert_sequence)
 734			return (0);
 735		ts = up->pps_info.assert_timestamp;
 736	} else if (up->pps_params.mode & PPS_CAPTURECLEAR) {
 737		if (pps_info.clear_sequence ==
 738		    up->pps_info.clear_sequence)
 739			return (0);
 740		ts = up->pps_info.clear_timestamp;
 741	} else {
 742		return (0);
 743	}
 744	if ((up->ts.tv_sec == ts.tv_sec) && (up->ts.tv_nsec == ts.tv_nsec))
 745		return (0);
 746	up->ts = ts;
 747
 748	tstmp.l_ui = ts.tv_sec + JAN_1970;
 749	dtemp = ts.tv_nsec * FRAC / 1e9;
 750	tstmp.l_uf = (u_int32)dtemp;
 751
 752#ifdef DEBUG_PPS
 753	msyslog(LOG_INFO,"ts.tv_sec: %d\n",(int)ts.tv_sec);
 754	msyslog(LOG_INFO,"ts.tv_nsec: %ld\n",ts.tv_nsec);
 755#endif /* DEBUG_PPS */
 756
 757	*tsptr = tstmp;
 758	return (1);
 759}
 760
 761/*
 762 * ripencc_shutdown - shut down a GPS clock
 763 */
 764static void
 765ripencc_shutdown(int unit, struct peer *peer)
 766{
 767	register struct ripencc_unit *up;
 768	struct refclockproc *pp;
 769
 770	pp = peer->procptr;
 771	up = (struct ripencc_unit *)pp->unitptr;
 772
 773	if (up->handle != 0)
 774		time_pps_destroy(up->handle);
 775
 776	io_closeclock(&pp->io);
 777
 778	free(up);
 779}
 780
 781/*
 782 * ripencc_poll - called by the transmit procedure
 783 */
 784static void
 785ripencc_poll(int unit, struct peer *peer)
 786{
 787	register struct ripencc_unit *up;
 788	struct refclockproc *pp;
 789	TSIPPKT spt;
 790
 791#ifdef DEBUG_NCC
 792	if (debug)
 793		fprintf(stderr, "ripencc_poll(%d)\n", unit);
 794#endif /* DEBUG_NCC */
 795	pp = peer->procptr;
 796	up = (struct ripencc_unit *)pp->unitptr;
 797	if (up->pollcnt == 0)
 798		refclock_report(peer, CEVNT_TIMEOUT);
 799	else
 800		up->pollcnt--;
 801
 802	pp->polls++;
 803	up->polled = 1;
 804
 805	/* poll for UTC superpacket */
 806	cmd_0x8EADq (&spt);
 807	ripencc_send(peer,spt);
 808}
 809
 810/*
 811 * ripencc_send - send message to clock
 812 * use the structures being created by the trimble functions!
 813 * makes the code more readable/clean
 814 */
 815static void
 816ripencc_send(struct peer *peer, TSIPPKT spt)
 817{
 818	unsigned char *ip, *op;
 819	unsigned char obuf[512];
 820
 821#ifdef DEBUG_RAW
 822	{
 823		register struct ripencc_unit *up;
 824		register struct refclockproc *pp;	
 825
 826		pp = peer->procptr;
 827		up = (struct ripencc_unit *)pp->unitptr;
 828		if (debug)
 829			printf("ripencc_send(%d, %02X)\n", up->unit, cmd);
 830	}
 831#endif /* DEBUG_RAW */
 832
 833	ip = spt.buf;
 834	op = obuf;
 835
 836	*op++ = 0x10;
 837	*op++ = spt.code;
 838
 839	while (spt.len--) {
 840		if (op-obuf > sizeof(obuf)-5) {
 841			msyslog(LOG_ERR, "ripencc_send obuf overflow!");
 842			refclock_report(peer, CEVNT_FAULT);
 843			return;
 844		}
 845			
 846		if (*ip == 0x10)  /* byte stuffing */
 847			*op++ = 0x10;
 848		*op++ = *ip++;
 849	}
 850	
 851	*op++ = 0x10;
 852	*op++ = 0x03;
 853
 854#ifdef DEBUG_RAW
 855	if (debug) { /* print raw packet */
 856		unsigned char *cp;
 857		int i;
 858
 859		printf("ripencc_send: len %d\n", op-obuf);
 860		for (i=1, cp=obuf; cp<op; i++, cp++) {
 861			printf(" %02X", *cp);
 862			if (i%10 == 0) 
 863				printf("\n");
 864		}
 865		printf("\n");
 866	}
 867#endif /* DEBUG_RAW */
 868
 869	if (write(peer->procptr->io.fd, obuf, op-obuf) == -1) {
 870			refclock_report(peer, CEVNT_FAULT);
 871	}
 872}
 873
 874/*
 875 * ripencc_receive()
 876 *
 877 * called when a packet is received on the serial port
 878 * takes care of further processing
 879 *
 880 */
 881static void
 882ripencc_receive(struct recvbuf *rbufp)
 883{
 884	register struct ripencc_unit *up;
 885	register struct refclockproc *pp;	
 886	struct peer *peer;
 887	static TSIPPKT rpt; /* structure for current incoming TSIP report  */ 
 888	TSIPPKT spt; /* send packet */
 889	int ns_since_pps;			
 890	int i;
 891	char *cp;
 892	/* Use these variables to hold data until we decide its worth keeping */
 893	char    rd_lastcode[BMAX];
 894	l_fp    rd_tmp;
 895	u_short rd_lencode;
 896
 897	/* msyslog(LOG_INFO, "%s",__FUNCTION__); */
 898
 899	/*
 900	 * Initialize pointers and read the timecode and timestamp
 901	 */
 902	peer = (struct peer *)rbufp->recv_srcclock;
 903	pp = peer->procptr;
 904	up = (struct ripencc_unit *)pp->unitptr;
 905	rd_lencode = refclock_gtlin(rbufp, rd_lastcode, BMAX, &rd_tmp);
 906
 907#ifdef DEBUG_RAW
 908	if (debug)
 909		fprintf(stderr, "ripencc_receive(%d)\n", up->unit);
 910#endif /* DEBUG_RAW */
 911
 912#ifdef DEBUG_RAW
 913	if (debug) { /* print raw packet */
 914		int i;
 915		unsigned char *cp;
 916
 917		printf("ripencc_receive: len %d\n", rbufp->recv_length);
 918		for (i=1, cp=(char*)&rbufp->recv_space; i <= rbufp->recv_length; i++, cp++) {
 919			printf(" %02X", *cp);
 920			if (i%10 == 0) 
 921				printf("\n");
 922		}
 923		printf("\n");
 924	}
 925#endif /* DEBUG_RAW */
 926
 927	cp = (char*) &rbufp->recv_space;
 928	i=rbufp->recv_length;
 929
 930	while (i--) { /* loop over received chars */
 931
 932		tsip_input_proc(&rpt, (unsigned char) *cp++);
 933
 934		if (rpt.status != TSIP_PARSED_FULL)
 935			continue;
 936
 937		switch (rpt.code) {
 938
 939		case 0x8F:	/* superpacket */
 940
 941			switch (rpt.buf[0]) {
 942
 943			case 0xAD:	/* UTC Time */
 944				/*
 945				 * When polling on port B the timecode 
 946				 * is the time of the previous PPS.
 947				 * If we completed receiving the packet 
 948				 * less than 150ms after the turn of the second, 
 949				 * it may have the code of the previous second.
 950				 * We do not trust that and simply poll again
 951				 * without even parsing it.
 952				 *
 953				 * More elegant would be to re-schedule the poll,
 954				 * but I do not know (yet) how to do that cleanly.
 955				 *
 956				 */
 957				/* BLA ns_since_pps = ncc_tstmp(rbufp, &trtmp); */
 958/*   if (up->polled && ns_since_pps > -1 && ns_since_pps < 150) { */
 959
 960				ns_since_pps=200;
 961				if (up->polled && ns_since_pps < 150) {
 962					msyslog(LOG_INFO, "%s(): up->polled",__FUNCTION__);
 963					ripencc_poll(up->unit, peer);
 964					break;
 965				}
 966
 967			        /*
 968 				 * Parse primary utc time packet
 969				 * and fill refclock structure 
 970				 * from results. 
 971				 */
 972				if (parse0x8FAD(&rpt, peer) < 0) {
 973						msyslog(LOG_INFO, "%s(): parse0x8FAD < 0",__FUNCTION__);
 974						refclock_report(peer, CEVNT_BADREPLY);
 975						break;
 976				}
 977				/*
 978				 * If the PPSAPI is working, rather use its 
 979				 * timestamps.
 980				 * assume that the PPS occurs on the second 
 981				 * so blow any msec
 982				 */
 983				if (ripencc_get_pps_ts(up, &rd_tmp) == 1) {
 984					pp->lastrec = up->tstamp = rd_tmp;
 985					pp->nsec = 0;
 986				}
 987				else
 988					msyslog(LOG_INFO, "%s(): ripencc_get_pps_ts returns failure\n",__FUNCTION__);
 989
 990
 991				if (!up->polled) { 
 992					msyslog(LOG_INFO, "%s(): unrequested packet\n",__FUNCTION__);
 993					/* unrequested packet */
 994					break;
 995				}
 996
 997				/* we have been polled ! */
 998				up->polled = 0;
 999				up->pollcnt = 2;
1000
1001				/* poll for next packet */
1002				cmd_0x8E0Bq(&spt);
1003				ripencc_send(peer,spt);
1004				
1005				if (ns_since_pps < 0) { /* no PPS */
1006					msyslog(LOG_INFO, "%s(): ns_since_pps < 0",__FUNCTION__);
1007					refclock_report(peer, CEVNT_BADTIME);
1008					break;
1009				}
1010
1011				/*
1012				 * Process the new sample in the median filter and determine the
1013				 * reference clock offset and dispersion. 
1014 				 */
1015				if (!refclock_process(pp)) {
1016					msyslog(LOG_INFO, "%s(): !refclock_process",__FUNCTION__);
1017					refclock_report(peer, CEVNT_BADTIME);
1018					break;
1019				}
1020
1021				refclock_receive(peer);
1022				break;
1023			
1024			case 0x0B: /* comprehensive time packet */
1025				parse0x8F0B(&rpt, peer);
1026				break;
1027
1028			default: /* other superpackets */
1029#ifdef DEBUG_NCC
1030				msyslog(LOG_INFO, "%s(): calling parseany",__FUNCTION__);
1031#endif /* DEBUG_NCC */
1032#ifdef TRIMBLE_OUTPUT_FUNC
1033				parseany(&rpt, peer);
1034#endif /* TRIMBLE_OUTPUT_FUNC */
1035				break;
1036			}
1037			break;
1038
1039		case 0x4F:	/* UTC parameters, for leap info */
1040			parse0x4F(&rpt, peer);
1041			break;
1042
1043		case 0x5C:	/* sat tracking data */
1044			parse0x5C(&rpt, peer);
1045			break;
1046
1047		default: /* other packets */
1048#ifdef TRIMBLE_OUTPUT_FUNC
1049			parseany(&rpt, peer);
1050#endif /* TRIMBLE_OUTPUT_FUNC */
1051			break;
1052		}
1053   		rpt.status = TSIP_PARSED_EMPTY;
1054	}
1055}
1056
1057/* 
1058 * All trimble functions that are directly referenced from driver code
1059 * (so not from parseany)
1060 */
1061
1062void cmd_0x1F (TSIPPKT *cmd)
1063/* request software versions */
1064{
1065	cmd->len = 0;
1066	cmd->code = 0x1F;
1067}
1068
1069void cmd_0x26 (TSIPPKT *cmd)
1070/* request receiver health */
1071{
1072	cmd->len = 0;
1073	cmd->code = 0x26;
1074}
1075
1076
1077
1078
1079void cmd_0x2F (TSIPPKT *cmd)
1080/* request UTC params */
1081{
1082	cmd->len = 0;
1083	cmd->code = 0x2F;
1084}
1085
1086void cmd_0x35s  (TSIPPKT *cmd, unsigned char pos_code, unsigned char vel_code,
1087	unsigned char time_code, unsigned char opts_code)
1088/* set serial I/O options */
1089{
1090	cmd->buf[0] = pos_code;
1091	cmd->buf[1] = vel_code;
1092	cmd->buf[2] = time_code;
1093	cmd->buf[3] = opts_code;
1094	cmd->len = 4;
1095	cmd->code = 0x35;
1096}
1097void cmd_0x3C  (TSIPPKT *cmd, unsigned char sv_prn)
1098/* request tracking status */
1099{
1100	cmd->buf[0] = sv_prn;
1101	cmd->len = 1;
1102	cmd->code = 0x3C;
1103}
1104
1105
1106void cmd_0x3Ds (TSIPPKT *cmd,
1107	unsigned char baud_out, unsigned char baud_inp,
1108   unsigned char char_code, unsigned char stopbitcode,
1109   unsigned char output_mode, unsigned char input_mode)
1110/* set Channel A configuration for dual-port operation */
1111{
1112	cmd->buf[0] = baud_out;		/* XMT baud rate */
1113	cmd->buf[1] = baud_inp;		/* RCV baud rate */
1114	cmd->buf[2] = char_code;	   /* parity and #bits per byte */
1115	cmd->buf[3] = stopbitcode;	/* number of stop bits code */
1116	cmd->buf[4] = output_mode;	/* Ch. A transmission mode */
1117	cmd->buf[5] = input_mode;	/* Ch. A reception mode */
1118	cmd->len = 6;
1119	cmd->code = 0x3D;
1120}
1121
1122
1123/* query primary configuration */
1124void cmd_0xBBq (TSIPPKT *cmd,
1125	unsigned char subcode)
1126{
1127
1128	cmd->len = 1;
1129	cmd->code = 0xBB;
1130	cmd->buf[0] = subcode;
1131}
1132
1133
1134/**** Superpackets ****/
1135void cmd_0x8E0Bq (TSIPPKT *cmd)
1136/* 8E-0B to query 8F-0B controls */
1137{
1138
1139	cmd->len = 1;
1140	cmd->code = 0x8E;
1141	cmd->buf[0] = 0x0B;
1142}
1143
1144
1145void cmd_0x8E41q (TSIPPKT *cmd)
1146/* 8F-41 to query board serial number */
1147{
1148
1149	cmd->len = 1;
1150	cmd->code = 0x8E;
1151	cmd->buf[0] = 0x41;
1152}
1153
1154
1155void cmd_0x8E42q (TSIPPKT *cmd)
1156/* 8F-42 to query product serial number */
1157{
1158
1159	cmd->len = 1;
1160	cmd->code = 0x8E;
1161	cmd->buf[0] = 0x42;
1162}
1163void cmd_0x8E4Aq (TSIPPKT *cmd)
1164/* 8F-4A to query PPS parameters */
1165{
1166	cmd->len = 1;
1167	cmd->code = 0x8E;
1168	cmd->buf[0] = 0x4A;
1169}
1170
1171
1172/* set i/o options */
1173void cmd_0x8E4As (TSIPPKT *cmd,
1174	unsigned char PPSOnOff,
1175	unsigned char TimeBase,
1176	unsigned char Polarity,
1177   double PPSOffset,
1178   float Uncertainty)
1179{
1180	cmd->len = 16;
1181	cmd->code = 0x8E;
1182	cmd->buf[0] = 0x4A;
1183	cmd->buf[1] = PPSOnOff;
1184	cmd->buf[2] = TimeBase;
1185	cmd->buf[3] = Polarity;
1186	bPutDouble (&PPSOffset, &cmd->buf[4]);
1187	bPutFloat (&Uncertainty, &cmd->buf[12]);
1188}
1189void cmd_0x8E4Bq (TSIPPKT *cmd)
1190/* 8F-4B query survey limit */
1191{
1192	cmd->len = 1;
1193	cmd->code = 0x8E;
1194	cmd->buf[0] = 0x4B;
1195}
1196
1197
1198/* poll for UTC superpacket */
1199void cmd_0x8EADq (TSIPPKT *cmd)
1200/* 8E-AD to query 8F-AD controls */
1201{
1202	cmd->len = 1;
1203	cmd->code = 0x8E;
1204	cmd->buf[0] = 0xAD;
1205}
1206
1207/* all outomatic packet output off */
1208void cmd_0x8E4Ds (TSIPPKT *cmd,
1209	unsigned long AutoOutputMask)
1210{
1211	cmd->len = 5;
1212	cmd->code = 0x8E;
1213	cmd->buf[0] = 0x4D;
1214	bPutULong (&AutoOutputMask, &cmd->buf[1]);
1215}
1216
1217
1218
1219
1220/* for DOS machines, reverse order of bytes as they come through the
1221 * serial port. */
1222#ifdef BYTESWAP
1223static short bGetShort (unsigned char *bp)
1224{
1225	short outval;
1226   unsigned char *optr;
1227
1228   optr = (unsigned char*)&outval + 1;
1229   *optr-- = *bp++;
1230   *optr = *bp;
1231	return outval;
1232}
1233
1234#ifdef TRIMBLE_OUTPUT_FUNC
1235static unsigned short bGetUShort (unsigned char *bp)
1236{
1237	unsigned short outval;
1238   unsigned char *optr;
1239
1240   optr = (unsigned char*)&outval + 1;
1241   *optr-- = *bp++;
1242   *optr = *bp;
1243	return outval;
1244}
1245
1246static long bGetLong (unsigned char *bp)
1247{
1248	long outval;
1249   unsigned char *optr;
1250
1251   optr = (unsigned char*)&outval + 3;
1252   *optr-- = *bp++;
1253   *optr-- = *bp++;
1254   *optr-- = *bp++;
1255   *optr = *bp;
1256	return outval;
1257}
1258
1259static unsigned long bGetULong (unsigned char *bp)
1260{
1261	unsigned long outval;
1262   unsigned char *optr;
1263
1264   optr = (unsigned char*)&outval + 3;
1265   *optr-- = *bp++;
1266   *optr-- = *bp++;
1267   *optr-- = *bp++;
1268   *optr = *bp;
1269	return outval;
1270}
1271#endif /* TRIMBLE_OUTPUT_FUNC */
1272
1273static float bGetSingle (unsigned char *bp)
1274{
1275	float outval;
1276   unsigned char *optr;
1277
1278   optr = (unsigned char*)&outval + 3;
1279   *optr-- = *bp++;
1280   *optr-- = *bp++;
1281   *optr-- = *bp++;
1282   *optr = *bp;
1283	return outval;
1284}
1285
1286static double bGetDouble (unsigned char *bp)
1287{
1288	double outval;
1289   unsigned char *optr;
1290
1291   optr = (unsigned char*)&outval + 7;
1292   *optr-- = *bp++;
1293   *optr-- = *bp++;
1294   *optr-- = *bp++;
1295   *optr-- = *bp++;
1296   *optr-- = *bp++;
1297   *optr-- = *bp++;
1298   *optr-- = *bp++;
1299   *optr = *bp;
1300	return outval;
1301}
1302
1303#else /* not BYTESWAP */
1304
1305#define bGetShort(bp) 	(*(short*)(bp))
1306#define bGetLong(bp) 	(*(long*)(bp))
1307#define bGetULong(bp) 	(*(unsigned long*)(bp))
1308#define bGetSingle(bp) 	(*(float*)(bp))
1309#define bGetDouble(bp)	(*(double*)(bp))
1310
1311#endif /* BYTESWAP */
1312/*
1313 * Byte-reversal is necessary for little-endian (Intel-based) machines.
1314 * TSIP streams are Big-endian (Motorola-based).
1315 */
1316#ifdef BYTESWAP
1317
1318void
1319bPutFloat (float *in, unsigned char *out)
1320{
1321	unsigned char *inptr;
1322
1323   inptr = (unsigned char*)in + 3;
1324   *out++ = *inptr--;
1325   *out++ = *inptr--;
1326   *out++ = *inptr--;
1327   *out = *inptr;
1328}
1329
1330static void
1331bPutULong (unsigned long *in, unsigned char *out)
1332{
1333	unsigned char *inptr;
1334
1335   inptr = (unsigned char*)in + 3;
1336   *out++ = *inptr--;
1337   *out++ = *inptr--;
1338   *out++ = *inptr--;
1339   *out = *inptr;
1340}
1341
1342static void
1343bPutDouble (double *in, unsigned char *out)
1344{
1345	unsigned char *inptr;
1346
1347   inptr = (unsigned char*)in + 7;
1348   *out++ = *inptr--;
1349   *out++ = *inptr--;
1350   *out++ = *inptr--;
1351   *out++ = *inptr--;
1352   *out++ = *inptr--;
1353   *out++ = *inptr--;
1354   *out++ = *inptr--;
1355   *out = *inptr;
1356}
1357
1358#else	/* not BYTESWAP */
1359
1360void bPutShort (short a, unsigned char *cmdbuf) {*(short*) cmdbuf = a;}
1361void bPutULong (long a, unsigned char *cmdbuf) 	{*(long*) cmdbuf = a;}
1362void bPutFloat (float a, unsigned char *cmdbuf) {*(float*) cmdbuf = a;}
1363void bPutDouble (double a, unsigned char *cmdbuf){*(double*) cmdbuf = a;}
1364
1365#endif /* BYTESWAP */
1366
1367/*
1368 * Parse primary utc time packet
1369 * and fill refclock structure 
1370 * from results. 
1371 *
1372 * 0 = success
1373 * -1 = errors
1374 */
1375
1376static int
1377parse0x8FAD(rpt, peer)
1378	TSIPPKT *rpt;
1379	struct peer *peer;	
1380{
1381	register struct refclockproc *pp;	
1382	register struct ripencc_unit *up;
1383
1384	unsigned day, month, year;	/* data derived from received timecode */
1385	unsigned hour, minute, second;
1386	unsigned char trackstat, utcflags;
1387
1388   	static char logbuf[1024];	/* logging string buffer */
1389	int i;
1390	unsigned char *buf;
1391		
1392	buf = rpt->buf;
1393	pp = peer->procptr;
1394
1395	if (rpt->len != 22) 
1396		return (-1);
1397	
1398	if (bGetShort(&buf[1]) != 0) {
1399#ifdef DEBUG_NCC
1400		if (debug) 
1401			printf("parse0x8FAD: event count != 0\n");
1402#endif /* DEBUG_NCC */
1403		return(-1);
1404	}
1405
1406
1407	if (bGetDouble(&buf[3]) != 0.0) {
1408#ifdef DEBUG_NCC
1409		if (debug) 
1410			printf("parse0x8FAD: fracsecs != 0\n");
1411#endif /* DEBUG_NCC */
1412		return(-1);
1413	}
1414
1415	hour = (unsigned int) buf[11];
1416	minute = (unsigned int) buf[12];
1417	second = (unsigned int) buf[13];
1418	day =		(unsigned int) buf[14];
1419	month =		(unsigned int) buf[15];
1420	year =		bGetShort(&buf[16]);
1421	trackstat = buf[18];
1422	utcflags = buf[19];
1423
1424
1425	sprintf(logbuf, "U1 %d.%d.%d %02d:%02d:%02d %d %02x",
1426		day, month, year, hour, minute, second, trackstat, utcflags);
1427
1428#ifdef DEBUG_NCC
1429	if (debug) 
1430   		puts(logbuf);
1431#endif /* DEBUG_NCC */
1432
1433	record_clock_stats(&peer->srcadr, logbuf);
1434
1435	if (!utcflags & UTCF_UTC_AVAIL)
1436		return(-1);
1437
1438	/* poll for UTC parameters once and then if UTC flag changed */
1439	up = (struct ripencc_unit *) pp->unitptr;
1440	if (utcflags != up->utcflags) {
1441		TSIPPKT spt; /* local structure for send packet */
1442		cmd_0x2F (&spt); /* request UTC params */
1443		ripencc_send(peer,spt);
1444		up->utcflags = utcflags;
1445	}
1446	
1447	/*
1448	 * If we hit the leap second, we choose to skip this sample
1449	 * rather than rely on other code to be perfectly correct.
1450	 * No offense, just defense ;-).
1451	 */
1452	if (second == 60)
1453		return(-1);
1454
1455	/* now check and convert the time we received */
1456
1457	pp->year = year;
1458	if (month < 1 || month > 12 || day < 1 || day > 31) 
1459		return(-1);
1460
1461	if (pp->year % 4) {
1462		if (day > day1tab[month - 1]) 
1463			return(-1);
1464		for (i = 0; i < month - 1; i++)
1465			day += day1tab[i];
1466	} else {
1467		if (day > day2tab[month - 1]) 
1468			return(-1);
1469		for (i = 0; i < month - 1; i++)
1470			day += day2tab[i];
1471	}
1472	pp->day = day;
1473	pp->hour = hour;
1474	pp->minute = minute;
1475	pp-> second = second;
1476	pp->nsec = 0;
1477
1478	if ((utcflags&UTCF_LEAP_PNDG) && up->leapdelta != 0) 
1479		pp-> leap = (up->leapdelta > 0 ? LEAP_ADDSECOND : LEAP_DELSECOND); 
1480	else
1481		pp-> leap = LEAP_NOWARNING;  
1482
1483	return (0);
1484}
1485
1486/*
1487 * Parse comprehensive time packet 
1488 *
1489 * 0 = success
1490 * -1 = errors
1491 */
1492
1493int parse0x8F0B(rpt, peer)
1494	TSIPPKT *rpt;
1495	struct peer *peer;	
1496{
1497	register struct refclockproc *pp;	
1498
1499	unsigned day, month, year;	/* data derived from received timecode */
1500	unsigned hour, minute, second;
1501	unsigned utcoff;
1502	unsigned char mode;
1503	double  bias, rate;
1504	float biasunc, rateunc;
1505	double lat, lon, alt;
1506	short lat_deg, lon_deg;
1507	float lat_min, lon_min;
1508	unsigned char north_south, east_west;
1509	char sv[9];
1510
1511   	static char logbuf[1024];	/* logging string buffer */
1512	unsigned char b;
1513	int i;
1514	unsigned char *buf;
1515	double tow;
1516		
1517	buf = rpt->buf;
1518	pp = peer->procptr;
1519
1520	if (rpt->len != 74) 
1521		return (-1);
1522	
1523	if (bGetShort(&buf[1]) != 0)
1524		return(-1);;
1525
1526	tow =  bGetDouble(&buf[3]);
1527
1528	if (tow == -1.0) {
1529		return(-1);
1530	}
1531	else if ((tow >= 604800.0) || (tow < 0.0)) {
1532		return(-1);
1533	}
1534	else
1535	{
1536		if (tow < 604799.9) tow = tow + .00000001;
1537		second = (unsigned int) fmod(tow, 60.);
1538		minute =  (unsigned int) fmod(tow/60., 60.);
1539		hour = (unsigned int )fmod(tow / 3600., 24.);
1540	} 
1541
1542
1543	day =		(unsigned int) buf[11];
1544	month =		(unsigned int) buf[12];
1545	year =		bGetShort(&buf[13]);
1546	mode =		buf[15];
1547	utcoff =	bGetShort(&buf[16]);
1548	bias = 		bGetDouble(&buf[18]) / GPS_C * 1e9;	/* ns */
1549	rate = 		bGetDouble(&buf[26]) / GPS_C * 1e9;	/* ppb */ 
1550	biasunc = 	bGetSingle(&buf[34]) / GPS_C * 1e9;	/* ns */
1551	rateunc = 	bGetSingle(&buf[38]) / GPS_C * 1e9;	/* ppb */
1552	lat = 		bGetDouble(&buf[42]) * R2D;
1553	lon = 		bGetDouble(&buf[50]) * R2D;
1554	alt = 		bGetDouble(&buf[58]);
1555
1556	if (lat < 0.0) {
1557		north_south = 'S';
1558		lat = -lat;
1559	}
1560	else {
1561		north_south = 'N';
1562	}
1563	lat_deg = (short)lat;
1564	lat_min = (lat - lat_deg) * 60.0;
1565
1566	if (lon < 0.0) {
1567		east_west = 'W';
1568		lon = -lon;
1569	}
1570	else {
1571		east_west = 'E';
1572	}
1573
1574	lon_deg = (short)lon;
1575	lon_min = (lon - lon_deg) * 60.0;
1576
1577	for (i=0; i<8; i++) {
1578		sv[i] = buf[i + 66];
1579		if (sv[i]) {
1580			TSIPPKT spt; /* local structure for sendpacket */
1581			b = (unsigned char) (sv[i]<0 ? -sv[i] : sv[i]);
1582			/* request tracking status */
1583			cmd_0x3C  (&spt, b);
1584			ripencc_send(peer,spt);
1585		}
1586	}
1587
1588
1589	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",
1590		day, month, year, hour, minute, second, mode, bias, biasunc, rate, rateunc, utcoff,
1591		lat_deg, lat_min, north_south, lon_deg, lon_min, east_west, alt,
1592		sv[0], sv[1], sv[2], sv[3], sv[4], sv[5], sv[6], sv[7]);
1593
1594#ifdef DEBUG_NCC
1595	if (debug) 
1596   		puts(logbuf);
1597#endif /* DEBUG_NCC */
1598
1599	record_clock_stats(&peer->srcadr, logbuf);
1600
1601	return (0);
1602}
1603
1604#ifdef TRIMBLE_OUTPUT_FUNC
1605/* 
1606 * Parse any packet using Trimble machinery
1607 */
1608int parseany(rpt, peer)	
1609	TSIPPKT *rpt;
1610	struct peer *peer;	
1611{
1612   	static char logbuf[1024];	/* logging string buffer */
1613
1614   	TranslateTSIPReportToText (rpt, logbuf);	/* anything else */
1615#ifdef DEBUG_NCC
1616	if (debug) 
1617   		puts(&logbuf[1]);
1618#endif /* DEBUG_NCC */
1619	record_clock_stats(&peer->srcadr, &logbuf[1]);
1620	return(0);
1621}
1622#endif /* TRIMBLE_OUTPUT_FUNC */
1623
1624
1625/*
1626 * Parse UTC Parameter Packet
1627 * 
1628 * See the IDE for documentation!
1629 *
1630 * 0 = success
1631 * -1 = errors
1632 */
1633
1634int parse0x4F(rpt, peer)
1635	TSIPPKT *rpt;
1636	struct peer *peer;	
1637{
1638	register struct ripencc_unit *up;
1639
1640	double a0;
1641	float a1, tot;
1642	int dt_ls, wn_t, wn_lsf, dn, dt_lsf;
1643
1644   	static char logbuf[1024];	/* logging string buffer */
1645	unsigned char *buf;
1646		
1647	buf = rpt->buf;
1648	
1649	if (rpt->len != 26) 
1650		return (-1);
1651	a0 = bGetDouble (buf);
1652	a1 = bGetSingle (&buf[8]);
1653	dt_ls = bGetShort (&buf[12]);
1654	tot = bGetSingle (&buf[14]);
1655	wn_t = bGetShort (&buf[18]);
1656	wn_lsf = bGetShort (&buf[20]);
1657	dn = bGetShort (&buf[22]);
1658	dt_lsf = bGetShort (&buf[24]);
1659
1660	sprintf(logbuf, "L1 %d %d %d %g %g %g %d %d %d",
1661		dt_lsf - dt_ls, dt_ls, dt_lsf, a0, a1, tot, wn_t, wn_lsf, dn); 
1662
1663#ifdef DEBUG_NCC
1664	if (debug) 
1665   		puts(logbuf);
1666#endif /* DEBUG_NCC */
1667
1668	record_clock_stats(&peer->srcadr, logbuf);
1669
1670	up = (struct ripencc_unit *) peer->procptr->unitptr;
1671	up->leapdelta = dt_lsf - dt_ls;
1672
1673	return (0);
1674}
1675
1676/*
1677 * Parse Tracking Status packet
1678 *
1679 * 0 = success
1680 * -1 = errors
1681 */
1682
1683int parse0x5C(rpt, peer)
1684	TSIPPKT *rpt;
1685	struct peer *peer;	
1686{
1687	unsigned char prn, channel, aqflag, ephstat;
1688	float snr, azinuth, elevation;
1689
1690   	static char logbuf[1024];	/* logging string buffer */
1691	unsigned char *buf;
1692		
1693	buf = rpt->buf;
1694	
1695	if (rpt->len != 24) 
1696		return(-1);
1697
1698	prn = buf[0];
1699	channel = (unsigned char)(buf[1] >> 3);
1700	if (channel == 0x10) 
1701		channel = 2;
1702	else 
1703		channel++;
1704	aqflag = buf[2];
1705	ephstat = buf[3];
1706	snr = bGetSingle(&buf[4]);
1707	elevation = bGetSingle(&buf[12]) * R2D;
1708	azinuth = bGetSingle(&buf[16]) * R2D;
1709
1710	sprintf(logbuf, "S1 %02d %d %d %02x %4.1f %5.1f %4.1f",
1711		prn, channel, aqflag, ephstat, snr, azinuth, elevation);
1712
1713#ifdef DEBUG_NCC
1714	if (debug) 
1715   		puts(logbuf);
1716#endif /* DEBUG_NCC */
1717
1718	record_clock_stats(&peer->srcadr, logbuf);
1719
1720	return (0);
1721}
1722
1723/******* Code below is from Trimble Tsipchat *************/
1724
1725/*
1726 * *************************************************************************
1727 *
1728 * Trimble Navigation, Ltd.
1729 * OEM Products Development Group
1730 * P.O. Box 3642
1731 * 645 North Mary Avenue
1732 * Sunnyvale, California 94088-3642
1733 *
1734 * Corporate Headquarter:
1735 *    Telephone:  (408) 481-8000
1736 *    Fax:        (408) 481-6005
1737 *
1738 * Technical Support Center:
1739 *    Telephone:  (800) 767-4822	(U.S. and Canada)
1740 *                (408) 481-6940    (outside U.S. and Canada)
1741 *    Fax:        (408) 481-6020
1742 *    BBS:        (408) 481-7800
1743 *    e-mail:     trimble_support@trimble.com
1744 *		ftp://ftp.trimble.com/pub/sct/embedded/bin
1745 *
1746 * *************************************************************************
1747 *
1748 * -------  BYTE-SWAPPING  -------
1749 * TSIP is big-endian (Motorola) protocol.  To use on little-endian (Intel)
1750 * systems, the bytes of all multi-byte types (shorts, floats, doubles, etc.)
1751 * must be reversed.  This is controlled by the MACRO BYTESWAP; if defined, it
1752 * assumes little-endian protocol.
1753 * --------------------------------
1754 *
1755 * T_PARSER.C and T_PARSER.H contains primitive functions that interpret
1756 * reports received from the receiver.  A second source file pair,
1757 * T_FORMAT.C and T_FORMAT.H, contin the matching TSIP command formatters.
1758 *
1759 * The module is in very portable, basic C language.  It can be used as is, or
1760 * with minimal changes if a TSIP communications application is needed separate
1761 * from TSIPCHAT. The construction of most argument lists avoid the use of
1762 * structures, but the developer is encouraged to reconstruct them using such
1763 * definitions to meet project requirements.  Declarations of T_PARSER.C
1764 * functions are included in T_PARSER.H to provide prototyping definitions.
1765 *
1766 * There are two types of functions: a serial input processing routine,
1767 *                            tsip_input_proc()
1768 * which assembles incoming bytes into a TSIPPKT structure, and the
1769 * report parsers, rpt_0x??().
1770 *
1771 * 1) The function tsip_input_proc() accumulates bytes from the receiver,
1772 * strips control bytes (DLE), and checks if the report end sequence (DLE ETX)
1773 * has been received.  rpt.status is defined as TSIP_PARSED_FULL (== 1)
1774 * if a complete packet is available.
1775 *
1776 * 2) The functions rpt_0x??() are report string interpreters patterned after
1777 * the document called "Trimble Standard Interface Protocol".  It should be
1778 * noted that if the report buffer is sent into the receiver with the wrong
1779 * length (byte count), the rpt_0x??() returns the Boolean equivalence for
1780 * TRUE.
1781 *
1782 * *************************************************************************
1783 *
1784 */
1785
1786
1787/**/
1788static void tsip_input_proc (
1789	TSIPPKT *rpt,
1790	int inbyte)
1791/* reads bytes until serial buffer is empty or a complete report
1792 * has been received; end of report is signified by DLE ETX.
1793 */
1794{
1795	unsigned char newbyte;
1796
1797	if (inbyte < 0 || inbyte > 0xFF) return;
1798
1799	newbyte = (unsigned char)(inbyte);
1800	switch (rpt->status)
1801	{
1802	case TSIP_PARSED_DLE_1:
1803		switch (newbyte)
1804		{
1805		case 0:
1806		case ETX:
1807      	/* illegal TSIP IDs */
1808         rpt->len = 0;
1809			rpt->status = TSIP_PARSED_EMPTY;
1810			break;
1811		case DLE:
1812      	/* try normal message start again */
1813			rpt->len = 0;
1814			rpt->status = TSIP_PARSED_DLE_1;
1815			break;
1816		default:
1817      	/* legal TSIP ID; start message */
1818			rpt->code = newbyte;
1819         rpt->len = 0;
1820			rpt->status = TSIP_PARSED_DATA;
1821			break;
1822		}
1823		break;
1824	case TSIP_PARSED_DATA:
1825		switch (newbyte) {
1826		case DLE:
1827      	/* expect DLE or ETX next */
1828			rpt->status = TSIP_PARSED_DLE_2;
1829			break;
1830		default:
1831      	/* normal data byte  */
1832			rpt->buf[rpt->len] = newbyte;
1833			rpt->len++;
1834         /* no change in rpt->status */
1835			break;
1836		}
1837		break;
1838	case TSIP_PARSED_DLE_2:
1839		switch (newbyte) {
1840		case DLE:
1841      	/* normal data byte */
1842			rpt->buf[rpt->len] = newbyte;
1843			rpt->len++;
1844			rpt->status = TSIP_PARSED_DATA;
1845			break;
1846		case ETX:
1847			/* end of message; return TRUE here. */
1848			rpt->status = TSIP_PARSED_FULL;
1849			break;
1850		default:
1851			/* error: treat as TSIP_PARSED_DLE_1; start new report packet */
1852			rpt->code = newbyte;
1853         rpt->len = 0;
1854			rpt->status = TSIP_PARSED_DATA;
1855		}
1856		break;
1857	case TSIP_PARSED_FULL:
1858	case TSIP_PARSED_EMPTY:
1859	default:
1860		switch (newbyte) {
1861		case DLE:
1862      	/* normal message start */
1863			rpt->len = 0;
1864			rpt->status = TSIP_PARSED_DLE_1;
1865			break;
1866		default:
1867			/* error: ignore newbyte */
1868			rpt->len = 0;
1869			rpt->status = TSIP_PARSED_EMPTY;
1870		}
1871		break;
1872	}
1873	if (rpt->len > MAX_RPTBUF) {
1874		/* error: start new report packet */
1875		rpt->status = TSIP_PARSED_EMPTY;
1876		rpt->len = 0;
1877	}
1878}
1879
1880#ifdef TRIMBLE_OUTPUT_FUNC
1881
1882/**/
1883short rpt_0x3D (TSIPPKT *rpt,
1884	unsigned char *tx_baud_index,
1885	unsigned char *rx_baud_index,
1886	unsigned char *char_format_index,
1887	unsigned char *stop_bits,
1888	unsigned char *tx_mode_index,
1889	unsigned char *rx_mode_index)
1890/* Channel A configuration for dual port operation */
1891{
1892	unsigned char *buf;
1893	buf = rpt->buf;
1894
1895	if (rpt->len != 6) return TRUE;
1896	*tx_baud_index = buf[0];
1897	*rx_baud_index = buf[1];
1898	*char_format_index = buf[2];
1899	*stop_bits = (unsigned char)((buf[3] == 0x07) ? 1 : 2);
1900	*tx_mode_index = buf[4];
1901	*rx_mode_index = buf[5];
1902	return FALSE;
1903}
1904
1905/**/
1906short rpt_0x40 (TSIPPKT *rpt,
1907	unsigned char *sv_prn,
1908	short *week_num,
1909	float *t_zc,
1910	float *eccentricity,
1911	float *t_oa,
1912	float *i_0,
1913	float *OMEGA_dot,
1914	float *sqrt_A,
1915	float *OMEGA_0,
1916	float *omega,
1917	float *M_0)
1918/* almanac data for specified satellite */
1919{
1920	unsigned char *buf;
1921	buf = rpt->buf;
1922
1923	if (rpt->len != 39) return TRUE;
1924	*sv_prn = buf[0];
1925	*t_zc = bGetSingle (&buf[1]);
1926	*week_num = bGetShort (&buf[5]);
1927	*eccentricity = bGetSingle (&buf[7]);
1928	*t_oa = bGetSingle (&buf[11]);
1929	*i_0 = bGetSingle (&buf[15]);
1930	*OMEGA_dot = bGetSingle (&buf[19]);
1931	*sqrt_A = bGetSingle (&buf[23]);
1932	*OMEGA_0 = bGetSingle (&buf[27]);
1933	*omega = bGetSingle (&buf[31]);
1934	*M_0 = bGetSingle (&buf[35]);
1935	return FALSE;
1936}
1937
1938short rpt_0x41 (TSIPPKT *rpt,
1939	float *time_of_week,
1940	float *UTC_offset,
1941	short *week_num)
1942/* GPS time */
1943{
1944	unsigned char *buf;
1945	buf = rpt->buf;
1946	
1947	if (rpt->len != 10) return TRUE;
1948	*time_of_week = bGetSingle (buf);
1949	*week_num = bGetShort (&buf[4]);
1950	*UTC_offset = bGetSingle (&buf[6]);
1951	return FALSE;
1952}
1953
1954short rpt_0x42 (TSIPPKT *rpt,
1955	float pos_ECEF[3],
1956	float *time_of_fix)
1957/* position in ECEF, single precision */
1958{
1959	unsigned char *buf;
1960	buf = rpt->buf;
1961	
1962	if (rpt->len != 16) return TRUE;
1963	pos_ECEF[0] = bGetSingle (buf);
1964	pos_ECEF[1]= bGetSingle (&buf[4]);
1965	pos_ECEF[2]= bGetSingle (&buf[8]);
1966	*time_of_fix = bGetSingle (&buf[12]);
1967	return FALSE;
1968}
1969
1970short rpt_0x43 (TSIPPKT *rpt,
1971	float ECEF_vel[3],
1972	float *freq_offset,
1973	float *time_of_fix)
1974/* velocity in ECEF, single precision */
1975{
1976	unsigned char *buf;
1977	buf = rpt->bu

Large files files are truncated, but you can click here to view the full file