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 --- |