Deleted Added
full compact
refclock_mx4200.c (56746) refclock_mx4200.c (82498)
1/*
2 * This software was developed by the Computer Systems Engineering group
3 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66.
4 *
5 * Copyright (c) 1992 The Regents of the University of California.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 33 unchanged lines hidden (view full) ---

42 * This code runs on SunOS 4.1.3 with ppsclock-1.6a1 and Solaris 7.
43 */
44
45
46#ifdef HAVE_CONFIG_H
47# include <config.h>
48#endif
49
1/*
2 * This software was developed by the Computer Systems Engineering group
3 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66.
4 *
5 * Copyright (c) 1992 The Regents of the University of California.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 33 unchanged lines hidden (view full) ---

42 * This code runs on SunOS 4.1.3 with ppsclock-1.6a1 and Solaris 7.
43 */
44
45
46#ifdef HAVE_CONFIG_H
47# include <config.h>
48#endif
49
50#if defined(REFCLOCK) && defined(CLOCK_MX4200) && defined(PPS)
50#if defined(REFCLOCK) && defined(CLOCK_MX4200) && defined(HAVE_PPSAPI)
51
51
52#include <stdio.h>
53#include <ctype.h>
54#include <sys/types.h>
55
56#include "ntpd.h"
57#include "ntp_io.h"
58#include "ntp_refclock.h"
59#include "ntp_unixtime.h"
60#include "ntp_stdlib.h"
61
52#include "ntpd.h"
53#include "ntp_io.h"
54#include "ntp_refclock.h"
55#include "ntp_unixtime.h"
56#include "ntp_stdlib.h"
57
58#include <stdio.h>
59#include <ctype.h>
60
62#include "mx4200.h"
63
61#include "mx4200.h"
62
64#ifdef HAVE_SYS_TIME_H
65# include <sys/time.h>
66#endif
67#ifdef HAVE_SYS_TERMIOS_H
68# include <sys/termios.h>
69#endif
70#ifdef HAVE_SYS_PPSCLOCK_H
71# include <sys/ppsclock.h>
72#endif
73
74#ifndef HAVE_STRUCT_PPSCLOCKEV
75struct ppsclockev {
63#ifdef HAVE_SYS_TERMIOS_H
64# include <sys/termios.h>
65#endif
66#ifdef HAVE_SYS_PPSCLOCK_H
67# include <sys/ppsclock.h>
68#endif
69
70#ifndef HAVE_STRUCT_PPSCLOCKEV
71struct ppsclockev {
76# ifdef HAVE_TIMESPEC
72# ifdef HAVE_STRUCT_TIMESPEC
77 struct timespec tv;
78# else
79 struct timeval tv;
80# endif
81 u_int serial;
82};
83#endif /* ! HAVE_STRUCT_PPSCLOCKEV */
84
73 struct timespec tv;
74# else
75 struct timeval tv;
76# endif
77 u_int serial;
78};
79#endif /* ! HAVE_STRUCT_PPSCLOCKEV */
80
81#ifdef HAVE_TIMEPPS_H
82# include <timepps.h>
83#else
84# ifdef HAVE_SYS_TIMEPPS_H
85# include <sys/timepps.h>
86# endif
87#endif
88
85/*
86 * This driver supports the Magnavox Model MX 4200 GPS Receiver
87 * adapted to precision timing applications. It requires the
88 * ppsclock line discipline or streams module described in the
89 * Line Disciplines and Streams Drivers page. It also requires a
90 * gadget box and 1-PPS level converter, such as described in the
91 * Pulse-per-second (PPS) Signal Interfacing page.
92 *
93 * It's likely that other compatible Magnavox receivers such as the
94 * MX 4200D, MX 9212, MX 9012R, MX 9112 will be supported by this code.
95 */
96
97/*
98 * Check this every time you edit the code!
99 */
89/*
90 * This driver supports the Magnavox Model MX 4200 GPS Receiver
91 * adapted to precision timing applications. It requires the
92 * ppsclock line discipline or streams module described in the
93 * Line Disciplines and Streams Drivers page. It also requires a
94 * gadget box and 1-PPS level converter, such as described in the
95 * Pulse-per-second (PPS) Signal Interfacing page.
96 *
97 * It's likely that other compatible Magnavox receivers such as the
98 * MX 4200D, MX 9212, MX 9012R, MX 9112 will be supported by this code.
99 */
100
101/*
102 * Check this every time you edit the code!
103 */
100#define YEAR_RIGHT_NOW 1998
104#define YEAR_LAST_MODIFIED 2000
101
102/*
103 * GPS Definitions
104 */
105#define DEVICE "/dev/gps%d" /* device name and unit */
106#define SPEED232 B4800 /* baud */
107
108/*
109 * Radio interface parameters
110 */
111#define PRECISION (-18) /* precision assumed (about 4 us) */
112#define REFID "GPS\0" /* reference id */
113#define DESCRIPTION "Magnavox MX4200 GPS Receiver" /* who we are */
114#define DEFFUDGETIME 0 /* default fudge time (ms) */
115
116#define SLEEPTIME 32 /* seconds to wait for reconfig to complete */
117
118/*
119 * Position Averaging.
105
106/*
107 * GPS Definitions
108 */
109#define DEVICE "/dev/gps%d" /* device name and unit */
110#define SPEED232 B4800 /* baud */
111
112/*
113 * Radio interface parameters
114 */
115#define PRECISION (-18) /* precision assumed (about 4 us) */
116#define REFID "GPS\0" /* reference id */
117#define DESCRIPTION "Magnavox MX4200 GPS Receiver" /* who we are */
118#define DEFFUDGETIME 0 /* default fudge time (ms) */
119
120#define SLEEPTIME 32 /* seconds to wait for reconfig to complete */
121
122/*
123 * Position Averaging.
120 * Reference: Dr. Thomas A. Clark's Totally Accurate Clock (TAC) files at
121 * ftp://aleph.gsfc.nasa.gov/GPS/totally.accurate.clock/
122 * For a 6-channel Motorola Oncore, he indicates that good nominal
123 * HDOP and VDOP are 1.50 and 2.00 respectively. Given the relationship
124 * HDOP^2 = NDOP^2 + EDOP^2 and assuming EDOP and NDOP are equal, we
125 * have a nominal NDOP = EDOP = sqrt((HDOP*HDOP)/2). An 8-channel
126 * Oncore does well with HDOP=1.20 and VDOP=1.70.
127 */
128#define INTERVAL 1 /* Interval between position measurements (s) */
129#define AVGING_TIME 24 /* Number of hours to average */
130#define NOT_INITIALIZED -9999. /* initial pivot longitude */
131
132/*
133 * MX4200 unit control structure.
134 */
135struct mx4200unit {
136 u_int pollcnt; /* poll message counter */
137 u_int polled; /* Hand in a time sample? */
138 u_int lastserial; /* last pps serial number */
139 struct ppsclockev ppsev; /* PPS control structure */
140 double avg_lat; /* average latitude */
141 double avg_lon; /* average longitude */
142 double avg_alt; /* average height */
143 double central_meridian; /* central meridian */
124 */
125#define INTERVAL 1 /* Interval between position measurements (s) */
126#define AVGING_TIME 24 /* Number of hours to average */
127#define NOT_INITIALIZED -9999. /* initial pivot longitude */
128
129/*
130 * MX4200 unit control structure.
131 */
132struct mx4200unit {
133 u_int pollcnt; /* poll message counter */
134 u_int polled; /* Hand in a time sample? */
135 u_int lastserial; /* last pps serial number */
136 struct ppsclockev ppsev; /* PPS control structure */
137 double avg_lat; /* average latitude */
138 double avg_lon; /* average longitude */
139 double avg_alt; /* average height */
140 double central_meridian; /* central meridian */
144 double filt_lat; /* latitude filter length */
145 double filt_lon; /* longitude filter length */
146 double filt_alt; /* height filter length */
147 double edop; /* EDOP (east DOP) */
148 double ndop; /* NDOP (north DOP) */
149 double vdop; /* VDOP (vertical DOP) */
141 double N_fixes; /* Number of position measurements */
150 int last_leap; /* leap second warning */
151 u_int moving; /* mobile platform? */
152 u_long sloppyclockflag; /* fudge flags */
153 u_int known; /* position known yet? */
154 u_long clamp_time; /* when to stop postion averaging */
155 u_long log_time; /* when to print receiver status */
142 int last_leap; /* leap second warning */
143 u_int moving; /* mobile platform? */
144 u_long sloppyclockflag; /* fudge flags */
145 u_int known; /* position known yet? */
146 u_long clamp_time; /* when to stop postion averaging */
147 u_long log_time; /* when to print receiver status */
148 pps_handle_t pps_h;
149 pps_params_t pps_p;
150 pps_info_t pps_i;
156};
157
158static char pmvxg[] = "PMVXG";
159
160/* XXX should be somewhere else */
161#ifdef __GNUC__
162#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
163#ifndef __attribute__

--- 12 unchanged lines hidden (view full) ---

176 */
177static int mx4200_start P((int, struct peer *));
178static void mx4200_shutdown P((int, struct peer *));
179static void mx4200_receive P((struct recvbuf *));
180static void mx4200_poll P((int, struct peer *));
181
182static char * mx4200_parse_t P((struct peer *));
183static char * mx4200_parse_p P((struct peer *));
151};
152
153static char pmvxg[] = "PMVXG";
154
155/* XXX should be somewhere else */
156#ifdef __GNUC__
157#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
158#ifndef __attribute__

--- 12 unchanged lines hidden (view full) ---

171 */
172static int mx4200_start P((int, struct peer *));
173static void mx4200_shutdown P((int, struct peer *));
174static void mx4200_receive P((struct recvbuf *));
175static void mx4200_poll P((int, struct peer *));
176
177static char * mx4200_parse_t P((struct peer *));
178static char * mx4200_parse_p P((struct peer *));
184static char * mx4200_parse_d P((struct peer *));
185static char * mx4200_parse_s P((struct peer *));
186#ifdef QSORT_USES_VOID_P
187int mx4200_cmpl_fp P((const void *, const void *));
188#else
189int mx4200_cmpl_fp P((const l_fp *, const l_fp *));
190#endif /* not QSORT_USES_VOID_P */
179static char * mx4200_parse_s P((struct peer *));
180#ifdef QSORT_USES_VOID_P
181int mx4200_cmpl_fp P((const void *, const void *));
182#else
183int mx4200_cmpl_fp P((const l_fp *, const l_fp *));
184#endif /* not QSORT_USES_VOID_P */
191static void mx4200_config P((struct peer *));
185static int mx4200_config P((struct peer *));
192static void mx4200_ref P((struct peer *));
193static void mx4200_send P((struct peer *, char *, ...))
194 __attribute__ ((format (printf, 2, 3)));
195static u_char mx4200_cksum P((char *, int));
196static int mx4200_jday P((int, int, int));
197static void mx4200_debug P((struct peer *, char *, ...))
198 __attribute__ ((format (printf, 2, 3)));
199static int mx4200_pps P((struct peer *));

--- 34 unchanged lines hidden (view full) ---

234 if (!(fd = refclock_open(gpsdev, SPEED232, LDISC_PPS))) {
235 return (0);
236 }
237
238 /*
239 * Allocate unit structure
240 */
241 if (!(up = (struct mx4200unit *) emalloc(sizeof(struct mx4200unit)))) {
186static void mx4200_ref P((struct peer *));
187static void mx4200_send P((struct peer *, char *, ...))
188 __attribute__ ((format (printf, 2, 3)));
189static u_char mx4200_cksum P((char *, int));
190static int mx4200_jday P((int, int, int));
191static void mx4200_debug P((struct peer *, char *, ...))
192 __attribute__ ((format (printf, 2, 3)));
193static int mx4200_pps P((struct peer *));

--- 34 unchanged lines hidden (view full) ---

228 if (!(fd = refclock_open(gpsdev, SPEED232, LDISC_PPS))) {
229 return (0);
230 }
231
232 /*
233 * Allocate unit structure
234 */
235 if (!(up = (struct mx4200unit *) emalloc(sizeof(struct mx4200unit)))) {
236 perror("emalloc");
242 (void) close(fd);
243 return (0);
244 }
245 memset((char *)up, 0, sizeof(struct mx4200unit));
246 pp = peer->procptr;
247 pp->io.clock_recv = mx4200_receive;
248 pp->io.srcclock = (caddr_t)peer;
249 pp->io.datalen = 0;

--- 8 unchanged lines hidden (view full) ---

258 /*
259 * Initialize miscellaneous variables
260 */
261 peer->precision = PRECISION;
262 pp->clockdesc = DESCRIPTION;
263 memcpy((char *)&pp->refid, REFID, 4);
264
265 /* Ensure the receiver is properly configured */
237 (void) close(fd);
238 return (0);
239 }
240 memset((char *)up, 0, sizeof(struct mx4200unit));
241 pp = peer->procptr;
242 pp->io.clock_recv = mx4200_receive;
243 pp->io.srcclock = (caddr_t)peer;
244 pp->io.datalen = 0;

--- 8 unchanged lines hidden (view full) ---

253 /*
254 * Initialize miscellaneous variables
255 */
256 peer->precision = PRECISION;
257 pp->clockdesc = DESCRIPTION;
258 memcpy((char *)&pp->refid, REFID, 4);
259
260 /* Ensure the receiver is properly configured */
266 mx4200_config(peer);
267 return (1);
261 return mx4200_config(peer);
268}
269
270
271/*
272 * mx4200_shutdown - shut down the clock
273 */
274static void
275mx4200_shutdown(

--- 9 unchanged lines hidden (view full) ---

285 io_closeclock(&pp->io);
286 free(up);
287}
288
289
290/*
291 * mx4200_config - Configure the receiver
292 */
262}
263
264
265/*
266 * mx4200_shutdown - shut down the clock
267 */
268static void
269mx4200_shutdown(

--- 9 unchanged lines hidden (view full) ---

279 io_closeclock(&pp->io);
280 free(up);
281}
282
283
284/*
285 * mx4200_config - Configure the receiver
286 */
293static void
287static int
294mx4200_config(
295 struct peer *peer
296 )
297{
298 char tr_mode;
299 int add_mode;
300 register struct mx4200unit *up;
301 struct refclockproc *pp;
288mx4200_config(
289 struct peer *peer
290 )
291{
292 char tr_mode;
293 int add_mode;
294 register struct mx4200unit *up;
295 struct refclockproc *pp;
296 int mode;
302
303 pp = peer->procptr;
304 up = (struct mx4200unit *)pp->unitptr;
305
306 /*
307 * Initialize the unit variables
308 *
309 * STRANGE BEHAVIOUR WARNING: The fudge flags are not available

--- 9 unchanged lines hidden (view full) ---

319 }
320 up->pollcnt = 2;
321 up->polled = 0;
322 up->known = 0;
323 up->avg_lat = 0.0;
324 up->avg_lon = 0.0;
325 up->avg_alt = 0.0;
326 up->central_meridian = NOT_INITIALIZED;
297
298 pp = peer->procptr;
299 up = (struct mx4200unit *)pp->unitptr;
300
301 /*
302 * Initialize the unit variables
303 *
304 * STRANGE BEHAVIOUR WARNING: The fudge flags are not available

--- 9 unchanged lines hidden (view full) ---

314 }
315 up->pollcnt = 2;
316 up->polled = 0;
317 up->known = 0;
318 up->avg_lat = 0.0;
319 up->avg_lon = 0.0;
320 up->avg_alt = 0.0;
321 up->central_meridian = NOT_INITIALIZED;
327 up->filt_lat = 0.0;
328 up->filt_lon = 0.0;
329 up->filt_alt = 0.0;
330 up->edop = 1;
331 up->ndop = 1;
332 up->vdop = 1;
322 up->N_fixes = 0.0;
333 up->last_leap = 0; /* LEAP_NOWARNING */
334 up->clamp_time = current_time + (AVGING_TIME * 60 * 60);
335 up->log_time = current_time + SLEEPTIME;
336
323 up->last_leap = 0; /* LEAP_NOWARNING */
324 up->clamp_time = current_time + (AVGING_TIME * 60 * 60);
325 up->log_time = current_time + SLEEPTIME;
326
327 if (time_pps_create(pp->io.fd, &up->pps_h) < 0) {
328 perror("time_pps_create");
329 msyslog(LOG_ERR,
330 "mx4200_config: time_pps_create failed: %m");
331 return (0);
332 }
333 if (time_pps_getcap(up->pps_h, &mode) < 0) {
334 msyslog(LOG_ERR,
335 "mx4200_config: time_pps_getcap failed: %m");
336 return (0);
337 }
338
339 if (time_pps_getparams(up->pps_h, &up->pps_p) < 0) {
340 msyslog(LOG_ERR,
341 "mx4200_config: time_pps_getparams failed: %m");
342 return (0);
343 }
344
345 /* nb. only turn things on, if someone else has turned something
346 * on before we get here, leave it alone!
347 */
348
349 up->pps_p.mode = PPS_CAPTUREASSERT | PPS_TSFMT_TSPEC;
350 up->pps_p.mode &= mode; /* only set what is legal */
351
352 if (time_pps_setparams(up->pps_h, &up->pps_p) < 0) {
353 perror("time_pps_setparams");
354 msyslog(LOG_ERR,
355 "mx4200_config: time_pps_setparams failed: %m");
356 exit(1);
357 }
358
359 if (time_pps_kcbind(up->pps_h, PPS_KC_HARDPPS, PPS_CAPTUREASSERT,
360 PPS_TSFMT_TSPEC) < 0) {
361 perror("time_pps_kcbind");
362 msyslog(LOG_ERR,
363 "mx4200_config: time_pps_kcbind failed: %m");
364 exit(1);
365 }
366
367
337 /*
338 * "007" Control Port Configuration
339 * Zero the output list (do it twice to flush possible junk)
340 */
341 mx4200_send(peer, "%s,%03d,,%d,,,,,,", pmvxg,
342 PMVXG_S_PORTCONF,
343 /* control port output block Label */
344 1); /* clear current output control list (1=yes) */

--- 69 unchanged lines hidden (view full) ---

414 mx4200_send(peer, "%s,%03d,%c,%c,%c,%d,%d,%d,", pmvxg,
415 PMVXG_S_TRECOVCONF,
416 tr_mode, /* time recovery mode (see above ) */
417 'U', /* synchronize to UTC */
418 'A', /* always output a time pulse */
419 500, /* max time error in ns */
420 0, /* user bias in ns */
421 1); /* output "830" sentences to control port */
368 /*
369 * "007" Control Port Configuration
370 * Zero the output list (do it twice to flush possible junk)
371 */
372 mx4200_send(peer, "%s,%03d,,%d,,,,,,", pmvxg,
373 PMVXG_S_PORTCONF,
374 /* control port output block Label */
375 1); /* clear current output control list (1=yes) */

--- 69 unchanged lines hidden (view full) ---

445 mx4200_send(peer, "%s,%03d,%c,%c,%c,%d,%d,%d,", pmvxg,
446 PMVXG_S_TRECOVCONF,
447 tr_mode, /* time recovery mode (see above ) */
448 'U', /* synchronize to UTC */
449 'A', /* always output a time pulse */
450 500, /* max time error in ns */
451 0, /* user bias in ns */
452 1); /* output "830" sentences to control port */
422 /* Multi-satellite mode */
453 /* Multi-satellite mode */
423
424 /*
425 * Output position information (to calculate fixed installation
426 * location) only if we are not moving
427 */
428 if (up->moving) {
429 add_mode = 2; /* delete from list */
430 } else {
431 add_mode = 1; /* add to list */
432 }
433
454
455 /*
456 * Output position information (to calculate fixed installation
457 * location) only if we are not moving
458 */
459 if (up->moving) {
460 add_mode = 2; /* delete from list */
461 } else {
462 add_mode = 1; /* add to list */
463 }
464
434 /*
435 * "007" Control Port Configuration
436 * Output "022" DOPs
437 */
438 mx4200_send(peer, "%s,%03d,%03d,%d,%d,,%d,,,", pmvxg,
439 PMVXG_S_PORTCONF,
440 PMVXG_D_DOPS, /* control port output block Label */
441 0, /* clear current output control list (0=no) */
442 add_mode, /* add/delete sentences from list (1=add, 2=del) */
443 /* must be null */
444 INTERVAL); /* sentence output rate (sec) */
445 /* precision for position output */
446 /* nmea version for cga & gll output */
447 /* pass-through control */
448
465
449
450 /*
451 * "007" Control Port Configuration
452 * Output "021" position, height, velocity reports
453 */
454 mx4200_send(peer, "%s,%03d,%03d,%d,%d,,%d,,,", pmvxg,
455 PMVXG_S_PORTCONF,
456 PMVXG_D_PHV, /* control port output block Label */
457 0, /* clear current output control list (0=no) */
458 add_mode, /* add/delete sentences from list (1=add, 2=del) */
466 /*
467 * "007" Control Port Configuration
468 * Output "021" position, height, velocity reports
469 */
470 mx4200_send(peer, "%s,%03d,%03d,%d,%d,,%d,,,", pmvxg,
471 PMVXG_S_PORTCONF,
472 PMVXG_D_PHV, /* control port output block Label */
473 0, /* clear current output control list (0=no) */
474 add_mode, /* add/delete sentences from list (1=add, 2=del) */
459 /* must be null */
475 /* must be null */
460 INTERVAL); /* sentence output rate (sec) */
476 INTERVAL); /* sentence output rate (sec) */
461 /* precision for position output */
462 /* nmea version for cga & gll output */
463 /* pass-through control */
477 /* precision for position output */
478 /* nmea version for cga & gll output */
479 /* pass-through control */
480
481 return (1);
464}
465
466/*
467 * mx4200_ref - Reconfigure unit as a reference station at a known position.
468 */
469static void
470mx4200_ref(
471 struct peer *peer

--- 13 unchanged lines hidden (view full) ---

485
486 /*
487 * Set up to output status information in the near future
488 */
489 up->log_time = current_time + SLEEPTIME;
490
491 /*
492 * "007" Control Port Configuration
482}
483
484/*
485 * mx4200_ref - Reconfigure unit as a reference station at a known position.
486 */
487static void
488mx4200_ref(
489 struct peer *peer

--- 13 unchanged lines hidden (view full) ---

503
504 /*
505 * Set up to output status information in the near future
506 */
507 up->log_time = current_time + SLEEPTIME;
508
509 /*
510 * "007" Control Port Configuration
493 * Stop outputting "022" DOPs
494 */
495 mx4200_send(peer, "%s,%03d,%03d,%d,%d,,,,,", pmvxg,
496 PMVXG_S_PORTCONF,
497 PMVXG_D_DOPS, /* control port output block Label */
498 0, /* clear current output control list (0=no) */
499 2); /* add/delete sentences from list (2=delete) */
500 /* must be null */
501 /* sentence output rate (sec) */
502 /* precision for position output */
503 /* nmea version for cga & gll output */
504 /* pass-through control */
505
506 /*
507 * "007" Control Port Configuration
508 * Stop outputting "021" position, height, velocity reports
509 */
510 mx4200_send(peer, "%s,%03d,%03d,%d,%d,,,,,", pmvxg,
511 PMVXG_S_PORTCONF,
512 PMVXG_D_PHV, /* control port output block Label */
513 0, /* clear current output control list (0=no) */
514 2); /* add/delete sentences from list (2=delete) */
515 /* must be null */

--- 69 unchanged lines hidden (view full) ---

585 /* month of year */
586 /* year */
587 /* gmt */
588 lats, /* latitude DDMM.MMMM */
589 nsc, /* north/south */
590 lons, /* longitude DDDMM.MMMM */
591 ewc, /* east/west */
592 alt, /* Altitude */
511 * Stop outputting "021" position, height, velocity reports
512 */
513 mx4200_send(peer, "%s,%03d,%03d,%d,%d,,,,,", pmvxg,
514 PMVXG_S_PORTCONF,
515 PMVXG_D_PHV, /* control port output block Label */
516 0, /* clear current output control list (0=no) */
517 2); /* add/delete sentences from list (2=delete) */
518 /* must be null */

--- 69 unchanged lines hidden (view full) ---

588 /* month of year */
589 /* year */
590 /* gmt */
591 lats, /* latitude DDMM.MMMM */
592 nsc, /* north/south */
593 lons, /* longitude DDDMM.MMMM */
594 ewc, /* east/west */
595 alt, /* Altitude */
593 1); /* Altitude Reference (0=WGS84 ellipsoid, 1=MSL geoid) */
596 1); /* Altitude Reference (0=WGS84 ellipsoid, 1=MSL geoid)*/
594
595 msyslog(LOG_DEBUG,
596 "mx4200: reconfig to fixed location: %s %c, %s %c, %.2f m",
597 lats, nsc, lons, ewc, alt );
598
599}
600
601/*

--- 159 unchanged lines hidden (view full) ---

761 mx4200_debug(peer, "mx4200_receive: no sentence\n");
762 refclock_report(peer, CEVNT_BADREPLY);
763 return;
764 }
765 cp++;
766 sentence_type = strtol(cp, &cp, 10);
767
768 /*
597
598 msyslog(LOG_DEBUG,
599 "mx4200: reconfig to fixed location: %s %c, %s %c, %.2f m",
600 lats, nsc, lons, ewc, alt );
601
602}
603
604/*

--- 159 unchanged lines hidden (view full) ---

764 mx4200_debug(peer, "mx4200_receive: no sentence\n");
765 refclock_report(peer, CEVNT_BADREPLY);
766 return;
767 }
768 cp++;
769 sentence_type = strtol(cp, &cp, 10);
770
771 /*
769 * "000" Status message
772 * Process the sentence according to its type.
770 */
773 */
774 switch (sentence_type) {
771
775
772 if (sentence_type == PMVXG_D_STATUS) {
776 /*
777 * "000" Status message
778 */
779 case PMVXG_D_STATUS:
773 /*
774 * XXX
775 * Since we configure the receiver to not give us status
776 * messages and since the receiver outputs status messages by
777 * default after being reset to factory defaults when sent the
778 * "$PMVXG,018,C\r\n" message, any status message we get
779 * indicates the reciever needs to be initialized; thus, it is
780 * not necessary to decode the status message.
781 */
782 if ((cp = mx4200_parse_s(peer)) != NULL) {
783 mx4200_debug(peer,
784 "mx4200_receive: status: %s\n", cp);
785 }
786 mx4200_debug(peer, "mx4200_receive: reset receiver\n");
787 mx4200_config(peer);
780 /*
781 * XXX
782 * Since we configure the receiver to not give us status
783 * messages and since the receiver outputs status messages by
784 * default after being reset to factory defaults when sent the
785 * "$PMVXG,018,C\r\n" message, any status message we get
786 * indicates the reciever needs to be initialized; thus, it is
787 * not necessary to decode the status message.
788 */
789 if ((cp = mx4200_parse_s(peer)) != NULL) {
790 mx4200_debug(peer,
791 "mx4200_receive: status: %s\n", cp);
792 }
793 mx4200_debug(peer, "mx4200_receive: reset receiver\n");
794 mx4200_config(peer);
788 return;
789 }
795 break;
790
791 /*
792 * "021" Position, Height, Velocity message,
793 * if we are still averaging our position
794 */
796
797 /*
798 * "021" Position, Height, Velocity message,
799 * if we are still averaging our position
800 */
795 if (sentence_type == PMVXG_D_PHV && !up->known) {
796 /*
797 * Parse the message, calculating our averaged position.
798 */
799 if ((cp = mx4200_parse_p(peer)) != NULL) {
800 mx4200_debug(peer, "mx4200_receive: pos: %s\n", cp);
801 return;
801 case PMVXG_D_PHV:
802 if (!up->known) {
803 /*
804 * Parse the message, calculating our averaged position.
805 */
806 if ((cp = mx4200_parse_p(peer)) != NULL) {
807 mx4200_debug(peer, "mx4200_receive: pos: %s\n", cp);
808 return;
809 }
810 mx4200_debug(peer,
811 "mx4200_receive: position avg %f %.9f %.9f %.4f\n",
812 up->N_fixes, up->avg_lat, up->avg_lon, up->avg_alt);
813 /*
814 * Reinitialize as a reference station
815 * if position is well known.
816 */
817 if (current_time > up->clamp_time) {
818 up->known++;
819 mx4200_debug(peer, "mx4200_receive: reconfiguring!\n");
820 mx4200_ref(peer);
821 }
802 }
822 }
803 mx4200_debug(peer,
804 "mx4200_receive: position avg %.9f %.9f %.4f\n",
805 up->avg_lat, up->avg_lon, up->avg_alt);
806 mx4200_debug(peer,
807 "mx4200_receive: position len %.4f %.4f %.4f\n",
808 up->filt_lat, up->filt_lon, up->filt_alt);
809 mx4200_debug(peer,
810 "mx4200_receive: position dop %.1f %.1f %.1f\n",
811 up->ndop, up->edop, up->vdop);
812 /*
813 * Reinitialize as a reference station
814 * if position is well known.
815 */
816 if (current_time > up->clamp_time) {
817 up->known++;
818 mx4200_debug(peer, "mx4200_receive: reconfiguring!\n");
819 mx4200_ref(peer);
820 }
821 return;
822 }
823 break;
823
824 /*
824
825 /*
825 * "022" DOPs, if we are still averaging our position
826 */
827 if (sentence_type == PMVXG_D_DOPS && !up->known) {
828 if ((cp = mx4200_parse_d(peer)) != NULL) {
829 mx4200_debug(peer, "mx4200_receive: dop: %s\n", cp);
830 return;
831 }
832 return;
833 }
834
835 /*
836 * Print to the syslog:
837 * "004" Mode Data
838 * "030" Software Configuration
839 * "523" Time Recovery Parameters Currently in Use
840 */
826 * Print to the syslog:
827 * "004" Mode Data
828 * "030" Software Configuration
829 * "523" Time Recovery Parameters Currently in Use
830 */
841 if (sentence_type == PMVXG_D_MODEDATA ||
842 sentence_type == PMVXG_D_SOFTCONF ||
843 sentence_type == PMVXG_D_TRECOVUSEAGE ) {
831 case PMVXG_D_MODEDATA:
832 case PMVXG_D_SOFTCONF:
833 case PMVXG_D_TRECOVUSEAGE:
834
844 if ((cp = mx4200_parse_s(peer)) != NULL) {
845 mx4200_debug(peer,
846 "mx4200_receive: multi-record: %s\n", cp);
835 if ((cp = mx4200_parse_s(peer)) != NULL) {
836 mx4200_debug(peer,
837 "mx4200_receive: multi-record: %s\n", cp);
847 return;
848 }
838 }
849 return;
850 }
839 break;
851
852 /*
853 * "830" Time Recovery Results message
854 */
840
841 /*
842 * "830" Time Recovery Results message
843 */
855 if (sentence_type == PMVXG_D_TRECOVOUT) {
844 case PMVXG_D_TRECOVOUT:
856
857 /*
858 * Capture the last PPS signal.
859 * Precision timestamp is returned in pp->lastrec
860 */
861 if (mx4200_pps(peer) != NULL) {
862 mx4200_debug(peer, "mx4200_receive: pps failure\n");
863 refclock_report(peer, CEVNT_FAULT);

--- 42 unchanged lines hidden (view full) ---

906
907 refclock_receive(peer);
908
909 /*
910 * We have succeeded in answering the poll.
911 * Turn off the flag and return
912 */
913 up->polled = 0;
845
846 /*
847 * Capture the last PPS signal.
848 * Precision timestamp is returned in pp->lastrec
849 */
850 if (mx4200_pps(peer) != NULL) {
851 mx4200_debug(peer, "mx4200_receive: pps failure\n");
852 refclock_report(peer, CEVNT_FAULT);

--- 42 unchanged lines hidden (view full) ---

895
896 refclock_receive(peer);
897
898 /*
899 * We have succeeded in answering the poll.
900 * Turn off the flag and return
901 */
902 up->polled = 0;
914 return;
915 }
903 break;
916
917 /*
918 * Ignore all other sentence types
919 */
904
905 /*
906 * Ignore all other sentence types
907 */
908 default:
909 break;
910
911 } /* switch (sentence_type) */
912
920 return;
921}
922
923
924/*
925 * Parse a mx4200 time recovery message. Returns a string if error.
926 *
927 * A typical message looks like this. Checksum has already been stripped.

--- 36 unchanged lines hidden (view full) ---

964mx4200_parse_t(
965 struct peer *peer
966 )
967{
968 struct refclockproc *pp;
969 struct mx4200unit *up;
970 char time_mark_valid, time_sync, op_mode;
971 int sentence_type, valid;
913 return;
914}
915
916
917/*
918 * Parse a mx4200 time recovery message. Returns a string if error.
919 *
920 * A typical message looks like this. Checksum has already been stripped.

--- 36 unchanged lines hidden (view full) ---

957mx4200_parse_t(
958 struct peer *peer
959 )
960{
961 struct refclockproc *pp;
962 struct mx4200unit *up;
963 char time_mark_valid, time_sync, op_mode;
964 int sentence_type, valid;
972 int year, day_of_year, month, day_of_month, hour, minute, second, leapsec;
965 int year, day_of_year, month, day_of_month;
966 int hour, minute, second, leapsec;
973 int oscillator_offset, time_mark_error, time_bias;
974
975 pp = peer->procptr;
976 up = (struct mx4200unit *)pp->unitptr;
977
978 leapsec = 0; /* Not all receivers output leap second warnings (!) */
967 int oscillator_offset, time_mark_error, time_bias;
968
969 pp = peer->procptr;
970 up = (struct mx4200unit *)pp->unitptr;
971
972 leapsec = 0; /* Not all receivers output leap second warnings (!) */
979 sscanf(pp->a_lastcode, "$PMVXG,%d,%c,%d,%d,%d,%d:%d:%d,%c,%c,%d,%d,%d,%d",
973 sscanf(pp->a_lastcode,
974 "$PMVXG,%d,%c,%d,%d,%d,%d:%d:%d,%c,%c,%d,%d,%d,%d",
980 &sentence_type, &time_mark_valid, &year, &month, &day_of_month,
975 &sentence_type, &time_mark_valid, &year, &month, &day_of_month,
981 &hour, &minute, &second, &time_sync, &op_mode, &oscillator_offset,
982 &time_mark_error, &time_bias, &leapsec);
976 &hour, &minute, &second, &time_sync, &op_mode,
977 &oscillator_offset, &time_mark_error, &time_bias, &leapsec);
983
984 if (sentence_type != PMVXG_D_TRECOVOUT)
985 return ("wrong rec-type");
986
987 switch (time_mark_valid) {
988 case 'T':
989 valid = 1;
990 break;

--- 33 unchanged lines hidden (view full) ---

1024 hour, minute, second);
1025 }
1026
1027 /*
1028 * Check for insane date
1029 * (Certainly can't be any year before this code was last altered!)
1030 */
1031 if (day_of_month > 31 || month > 12 ||
978
979 if (sentence_type != PMVXG_D_TRECOVOUT)
980 return ("wrong rec-type");
981
982 switch (time_mark_valid) {
983 case 'T':
984 valid = 1;
985 break;

--- 33 unchanged lines hidden (view full) ---

1019 hour, minute, second);
1020 }
1021
1022 /*
1023 * Check for insane date
1024 * (Certainly can't be any year before this code was last altered!)
1025 */
1026 if (day_of_month > 31 || month > 12 ||
1032 day_of_month < 1 || month < 1 || year < YEAR_RIGHT_NOW) {
1027 day_of_month < 1 || month < 1 || year < YEAR_LAST_MODIFIED) {
1033 mx4200_debug(peer,
1034 "mx4200_parse_t: bad date (%4d-%02d-%02d)\n",
1035 year, month, day_of_month);
1036 refclock_report(peer, CEVNT_BADDATE);
1037 return ("bad date");
1038 }
1039
1040 /*

--- 204 unchanged lines hidden (view full) ---

1245static char *
1246mx4200_parse_p(
1247 struct peer *peer
1248 )
1249{
1250 struct refclockproc *pp;
1251 struct mx4200unit *up;
1252 int sentence_type, mode;
1028 mx4200_debug(peer,
1029 "mx4200_parse_t: bad date (%4d-%02d-%02d)\n",
1030 year, month, day_of_month);
1031 refclock_report(peer, CEVNT_BADDATE);
1032 return ("bad date");
1033 }
1034
1035 /*

--- 204 unchanged lines hidden (view full) ---

1240static char *
1241mx4200_parse_p(
1242 struct peer *peer
1243 )
1244{
1245 struct refclockproc *pp;
1246 struct mx4200unit *up;
1247 int sentence_type, mode;
1253 double mtime, lat, lon, alt, geoid, vele, veln, weight;
1248 double mtime, lat, lon, alt, geoid, vele, veln;
1254 char north_south, east_west;
1255
1256 pp = peer->procptr;
1257 up = (struct mx4200unit *)pp->unitptr;
1258
1259 /* Should never happen! */
1260 if (up->moving) return ("mobile platform - no pos!");
1261
1249 char north_south, east_west;
1250
1251 pp = peer->procptr;
1252 up = (struct mx4200unit *)pp->unitptr;
1253
1254 /* Should never happen! */
1255 if (up->moving) return ("mobile platform - no pos!");
1256
1262 sscanf ( pp->a_lastcode, "$PMVXG,%d,%lf,%lf,%c,%lf,%c,%lf,%lf,%lf,%lf,%d",
1263 &sentence_type, &mtime, &lat, &north_south, &lon, &east_west, &alt,
1264 &geoid, &vele, &veln, &mode);
1257 sscanf ( pp->a_lastcode,
1258 "$PMVXG,%d,%lf,%lf,%c,%lf,%c,%lf,%lf,%lf,%lf,%d",
1259 &sentence_type, &mtime, &lat, &north_south, &lon, &east_west,
1260 &alt, &geoid, &vele, &veln, &mode);
1265
1266 /* Sentence type */
1267 if (sentence_type != PMVXG_D_PHV)
1268 return ("wrong rec-type");
1269
1270 /*
1271 * return if not navigating
1272 */

--- 46 unchanged lines hidden (view full) ---

1319 "mx4200_receive: central meridian = %.9f \n",
1320 up->central_meridian);
1321 }
1322 lon -= up->central_meridian;
1323 if (lon < -180.0) lon += 360.0;
1324 if (lon > 180.0) lon -= 360.0;
1325
1326 /*
1261
1262 /* Sentence type */
1263 if (sentence_type != PMVXG_D_PHV)
1264 return ("wrong rec-type");
1265
1266 /*
1267 * return if not navigating
1268 */

--- 46 unchanged lines hidden (view full) ---

1315 "mx4200_receive: central meridian = %.9f \n",
1316 up->central_meridian);
1317 }
1318 lon -= up->central_meridian;
1319 if (lon < -180.0) lon += 360.0;
1320 if (lon > 180.0) lon -= 360.0;
1321
1322 /*
1327 * Calculate running weighted averages
1323 * Calculate running averages
1328 */
1324 */
1329 weight = 1. / up->edop;
1330 weight *= weight;
1331 up->avg_lon = (up->filt_lon * up->avg_lon) + (weight * lon);
1332 up->filt_lon += weight;
1333 up->avg_lon = up->avg_lon / up->filt_lon;
1334
1325
1335 weight = 1. / up->ndop;
1336 weight *= weight;
1337 up->avg_lat = (up->filt_lat * up->avg_lat) + (weight * lat);
1338 up->filt_lat += weight;
1339 up->avg_lat = up->avg_lat / up->filt_lat;
1326 up->avg_lon = (up->N_fixes * up->avg_lon) + lon;
1327 up->avg_lat = (up->N_fixes * up->avg_lat) + lat;
1328 up->avg_alt = (up->N_fixes * up->avg_alt) + alt;
1340
1329
1341 weight = 1. / up->vdop;
1342 weight *= weight;
1343 up->avg_alt = (up->filt_alt * up->avg_alt) + (weight * alt);
1344 up->filt_alt += weight;
1345 up->avg_alt = up->avg_alt / up->filt_alt;
1330 up->N_fixes += 1.0;
1346
1331
1332 up->avg_lon /= up->N_fixes;
1333 up->avg_lat /= up->N_fixes;
1334 up->avg_alt /= up->N_fixes;
1335
1347 mx4200_debug(peer,
1336 mx4200_debug(peer,
1348 "mx4200_receive: position rdg %.9f %.9f %.4f (CM=%.9f)\n",
1349 lat, lon, alt, up->central_meridian);
1337 "mx4200_receive: position rdg %.0f: %.9f %.9f %.4f (CM=%.9f)\n",
1338 up->N_fixes, lat, lon, alt, up->central_meridian);
1350
1351 return (NULL);
1352}
1353
1354/*
1339
1340 return (NULL);
1341}
1342
1343/*
1355 * Parse a mx4200 DOP sentence.
1356 *
1357 * A typical message looks like this. Checksum has already been stripped.
1358 *
1359 * $PMVXG,022,SSSSSS.SSEE.E,NN.N,VV.V,XX,XX,XX,XX,XX,XX
1360 *
1361 * Field Field Contents
1362 * ----- --------------
1363 * Block Label: $PMVXG
1364 * Sentence Type: 022=DOPs. The DOP values in this sentence
1365 * correspond to the satellites listed. The PRNs in
1366 * the message are listed in receiver channel number order
1367 * 1 UTC measurement time (seconds into week)
1368 * 2 EDOP (east DOP)
1369 * 3 NDOP (north DOP)
1370 * 4 VDOP (vertical DOP)
1371 * 5 PRN on channel 1
1372 * 6 PRN on channel 2
1373 * 7 PRN on channel 3
1374 * 8 PRN on channel 4
1375 * 9 PRN on channel 5
1376 * 10 PRN on channel 6
1377 * 11 PRN on channel 7 (12-channel receivers only)
1378 * 12 PRN on channel 8 (12-channel receivers only)
1379 * 13 PRN on channel 9 (12-channel receivers only)
1380 * 14 PRN on channel 10 (12-channel receivers only)
1381 * 15 PRN on channel 11 (12-channel receivers only)
1382 * 16 PRN on channel 12 (12-channel receivers only)
1383 */
1384static char *
1385mx4200_parse_d(
1386 struct peer *peer
1387 )
1388{
1389 struct refclockproc *pp;
1390 struct mx4200unit *up;
1391 int sentence_type;
1392 double mtime, edop, ndop, vdop;
1393
1394 pp = peer->procptr;
1395 up = (struct mx4200unit *)pp->unitptr;
1396
1397 /* Should never happen! */
1398 if (up->moving) return ("mobile platform - no dop!");
1399
1400 sscanf ( pp->a_lastcode, "$PMVXG,%d,%lf,%lf,%lf,%lf",
1401 &sentence_type, &mtime, &edop, &ndop, &vdop);
1402
1403 /* Sentence type */
1404 if (sentence_type != PMVXG_D_DOPS)
1405 return ("wrong rec-type");
1406
1407 /* Update values */
1408 if (edop <= 0.0 || ndop <= 0.0 || vdop <= 0.0)
1409 return ("nonpositive dop");
1410 up->edop = edop;
1411 up->ndop = ndop;
1412 up->vdop = vdop;
1413
1414 return (NULL);
1415}
1416
1417/*
1418 * Parse a mx4200 Status sentence
1419 * Parse a mx4200 Mode Data sentence
1420 * Parse a mx4200 Software Configuration sentence
1421 * Parse a mx4200 Time Recovery Parameters Currently in Use sentence
1422 * (used only for logging raw strings)
1423 *
1424 * A typical message looks like this. Checksum has already been stripped.
1425 *

--- 120 unchanged lines hidden (view full) ---

1546
1547 sscanf ( pp->a_lastcode, "$PMVXG,%d", &sentence_type);
1548
1549 /* Sentence type */
1550 switch (sentence_type) {
1551
1552 case PMVXG_D_STATUS:
1553 msyslog(LOG_DEBUG,
1344 * Parse a mx4200 Status sentence
1345 * Parse a mx4200 Mode Data sentence
1346 * Parse a mx4200 Software Configuration sentence
1347 * Parse a mx4200 Time Recovery Parameters Currently in Use sentence
1348 * (used only for logging raw strings)
1349 *
1350 * A typical message looks like this. Checksum has already been stripped.
1351 *

--- 120 unchanged lines hidden (view full) ---

1472
1473 sscanf ( pp->a_lastcode, "$PMVXG,%d", &sentence_type);
1474
1475 /* Sentence type */
1476 switch (sentence_type) {
1477
1478 case PMVXG_D_STATUS:
1479 msyslog(LOG_DEBUG,
1554 "mx4200: status: %s", pp->a_lastcode);
1480 "mx4200: status: %s", pp->a_lastcode);
1555 break;
1556 case PMVXG_D_MODEDATA:
1557 msyslog(LOG_DEBUG,
1481 break;
1482 case PMVXG_D_MODEDATA:
1483 msyslog(LOG_DEBUG,
1558 "mx4200: mode data: %s", pp->a_lastcode);
1484 "mx4200: mode data: %s", pp->a_lastcode);
1559 break;
1560 case PMVXG_D_SOFTCONF:
1561 msyslog(LOG_DEBUG,
1485 break;
1486 case PMVXG_D_SOFTCONF:
1487 msyslog(LOG_DEBUG,
1562 "mx4200: firmware configuration: %s", pp->a_lastcode);
1488 "mx4200: firmware configuration: %s", pp->a_lastcode);
1563 break;
1564 case PMVXG_D_TRECOVUSEAGE:
1565 msyslog(LOG_DEBUG,
1489 break;
1490 case PMVXG_D_TRECOVUSEAGE:
1491 msyslog(LOG_DEBUG,
1566 "mx4200: time recovery parms: %s", pp->a_lastcode);
1492 "mx4200: time recovery parms: %s", pp->a_lastcode);
1567 break;
1568 default:
1569 return ("wrong rec-type");
1570 }
1571
1572 return (NULL);
1573}
1574
1575/*
1493 break;
1494 default:
1495 return ("wrong rec-type");
1496 }
1497
1498 return (NULL);
1499}
1500
1501/*
1576 * Process a PPS signal, returning a timestamp.
1502 * Process a PPS signal, placing a timestamp in pp->lastrec.
1577 */
1578static int
1579mx4200_pps(
1580 struct peer *peer
1581 )
1582{
1583 int temp_serial;
1584 struct refclockproc *pp;
1585 struct mx4200unit *up;
1586
1503 */
1504static int
1505mx4200_pps(
1506 struct peer *peer
1507 )
1508{
1509 int temp_serial;
1510 struct refclockproc *pp;
1511 struct mx4200unit *up;
1512
1587 int request;
1588#ifdef HAVE_CIOGETEV
1589 request = CIOGETEV;
1590#endif
1591#ifdef HAVE_TIOCGPPSEV
1592 request = TIOCGPPSEV;
1593#endif
1513 struct timespec timeout;
1594
1595 pp = peer->procptr;
1596 up = (struct mx4200unit *)pp->unitptr;
1597
1598 /*
1599 * Grab the timestamp of the PPS signal.
1600 */
1514
1515 pp = peer->procptr;
1516 up = (struct mx4200unit *)pp->unitptr;
1517
1518 /*
1519 * Grab the timestamp of the PPS signal.
1520 */
1601 temp_serial = up->ppsev.serial;
1602 if (ioctl(fdpps, request, (caddr_t)&up->ppsev) < 0) {
1603 /* XXX Actually, if this fails, we're pretty much screwed */
1521 temp_serial = up->pps_i.assert_sequence;
1522 timeout.tv_sec = 0;
1523 timeout.tv_nsec = 0;
1524 if (time_pps_fetch(up->pps_h, PPS_TSFMT_TSPEC, &(up->pps_i),
1525 &timeout) < 0) {
1604 mx4200_debug(peer,
1526 mx4200_debug(peer,
1605 "mx4200_pps: CIOGETEV/TIOCGPPSEV: serial=%d, fdpps=%d, %s\n",
1606 up->ppsev.serial, fdpps, strerror(errno));
1527 "mx4200_pps: time_pps_fetch: serial=%d, %s\n",
1528 up->pps_i.assert_sequence, strerror(errno));
1607 refclock_report(peer, CEVNT_FAULT);
1608 return(1);
1609 }
1529 refclock_report(peer, CEVNT_FAULT);
1530 return(1);
1531 }
1610 if (temp_serial == up->ppsev.serial) {
1532 if (temp_serial == up->pps_i.assert_sequence) {
1611 mx4200_debug(peer,
1533 mx4200_debug(peer,
1612 "mx4200_pps: ppsev serial not incrementing: %d\n",
1613 up->ppsev.serial);
1534 "mx4200_pps: assert_sequence serial not incrementing: %d\n",
1535 up->pps_i.assert_sequence);
1614 refclock_report(peer, CEVNT_FAULT);
1615 return(1);
1616 }
1536 refclock_report(peer, CEVNT_FAULT);
1537 return(1);
1538 }
1617
1618 /*
1619 * Check pps serial number against last one
1620 */
1539 /*
1540 * Check pps serial number against last one
1541 */
1621 if (up->lastserial + 1 != up->ppsev.serial && up->lastserial != 0) {
1622 if (up->ppsev.serial == up->lastserial)
1542 if (up->lastserial + 1 != up->pps_i.assert_sequence &&
1543 up->lastserial != 0) {
1544 if (up->pps_i.assert_sequence == up->lastserial) {
1623 mx4200_debug(peer, "mx4200_pps: no new pps event\n");
1545 mx4200_debug(peer, "mx4200_pps: no new pps event\n");
1624 else
1546 } else {
1625 mx4200_debug(peer, "mx4200_pps: missed %d pps events\n",
1547 mx4200_debug(peer, "mx4200_pps: missed %d pps events\n",
1626 up->ppsev.serial - up->lastserial - 1);
1548 up->pps_i.assert_sequence - up->lastserial - 1);
1549 }
1627 refclock_report(peer, CEVNT_FAULT);
1628 }
1550 refclock_report(peer, CEVNT_FAULT);
1551 }
1629 up->lastserial = up->ppsev.serial;
1552 up->lastserial = up->pps_i.assert_sequence;
1630
1631 /*
1632 * Return the timestamp in pp->lastrec
1633 */
1553
1554 /*
1555 * Return the timestamp in pp->lastrec
1556 */
1634 up->ppsev.tv.tv_sec += (u_int32) JAN_1970;
1635 TVTOTS(&up->ppsev.tv,&pp->lastrec);
1636
1557
1558 pp->lastrec.l_ui = up->pps_i.assert_timestamp.tv_sec +
1559 (u_int32) JAN_1970;
1560 pp->lastrec.l_uf = ((double)(up->pps_i.assert_timestamp.tv_nsec) *
1561 4.2949672960) + 0.5;
1562
1637 return(0);
1638}
1639
1640/*
1641 * mx4200_debug - print debug messages
1642 */
1643#if defined(__STDC__)
1644static void

--- 98 unchanged lines hidden ---
1563 return(0);
1564}
1565
1566/*
1567 * mx4200_debug - print debug messages
1568 */
1569#if defined(__STDC__)
1570static void

--- 98 unchanged lines hidden ---