Lines Matching +full:first +full:- +full:conversion +full:- +full:delay
2 * refclock_arc - clock driver for ARCRON MSF/DCF/WWVB receivers
35 Modifications by Damon Hart-Davis, <d@hd.org>, 1997.
37 Modifications by Christopher Price, <cprice@cs-home.com>, 2003.
44 Orginally developed and used with ntp3-5.85 by Derek Mulcahy.
46 Built against ntp3-5.90 on Solaris 2.5 using gcc 2.7.2.
52 -------------------------------------------------------------------------------
62 -------------------------------------------------------------------------------
69 2001-02-17 comp.protocols.time.ntp
76 4) Added simplified conversion from localtime to UTC with dst/bst translation
89 -------------------------------------------------------------------------------
95 It works (after a fashion) on both Solaris-1 and Solaris-2.
97 I am currently using ntp3-5.85. I have been running the code for
114 -------------------------------------------------------------------------------
121 off-line once two time polls failed to gain responses.
123 2) Avoiding (at least on Solaris-2) terminal becoming the controlling
124 terminal of the process when we do a low-level open().
127 defined) to try to resync quickly after a potential leap-second
130 4) Code significantly slimmer at run-time than V1.0.
140 2) PRECISION should be -4/-5 (63ms/31ms) for the following reasons:
144 noticable drift and delay in the ms range due to transmission
153 *day*, we can imagine that it is not, and is free-running. We
160 may effectively be free-running with respect to the host clock
172 By default, PRECISION is set to -4, but experience, especially at a
174 this to be altered to -5. (Note that skews of +/- 10ms are to be
175 expected from the clock from time-to-time.) This improvement of
199 clashing with any regular event at a regular time-past-the-hour
208 This avoids ntpd syncing to another peer first and then
216 median-filter size from the typical (previous) value of 3. I
223 inter-character time but without introducting jitter and delay in
230 MSF---thus we should never end up syncing to completely the wrong
234 refclock median-filter routines to get round small bug in 3-5.90
236 bit due NTP Version 4 upgrade - dlm.
238 9) We would appear to have a year-2000 problem with this clock since
239 it returns only the two least-significant digits of the year. But
240 ntpd ignores the year and uses the local-system year instead, so
242 sensible thing with the dates, wrapping them into a 100-year
254 TO-DO LIST
266 * Add very slow auto-adjustment up to a value of +/- time2 to correct
267 for long-term errors in the clock value (time2 defaults to 0 so the
304 /* the start bit edge of the first reply character marks the beginning of */
314 /* 7. day of week 1-monday 7-sunday */
342 /* This bit is zero after reset and one after the first */
347 if so what signal quality (0--5) is available.
382 #define PRECISION (-4) /* Precision (~63 ms). */
383 #define HIGHPRECISION (-5) /* If things are going well... */
400 #define CHARTIME10 0x8888888 /* Time for 10-bit char at 300bps. */
401 #define CHARTIME11 0x962FC96 /* Time for 11-bit char at 300bps. */
406 /* Allow for UART to accept char half-way through final stop bit. */
407 #define INITIALOFFSET ((u_int32)(-BITTIME/2))
411 x (with the first byte being byte 1) is received by the UART,
412 assuming that the initial edge of the start bit of the first byte
413 is on-time. The values are represented as the fractional part of
465 #define INITIAL_RESYNC_DELAY 500 /* Delay before first resync. */
467 #define INITIAL_RESYNC_DELAY 50 /* Delay before first resync. */
493 int quality; /* Quality of reception 0--5 for unit. */
494 /* We may also use the values -1 or 6 internally. */
507 /* The flag `possible_leap' is set non-zero when any MSF unit
508 thinks a leap-second may have happened.
510 Set whenever we receive a valid time sample in the first hour of
511 the first day of the first/seventh months.
517 non-negative, the receive routine sets it to a positive value to
523 indicate that a leap-triggered resync has been started. Having
536 #define QUALITY_UNKNOWN -1 /* Indicates unknown clock quality. */
565 peer->procptr->nextaction = current_time + QUEUETICK; \
568 /* Placeholder event handler---does nothing safely---soaks up loose tick. */
582 Take first character off queue and send to clock if not a null.
595 struct refclockproc *pp = peer->procptr;
596 register struct arcunit *up = pp->unitptr;
603 c = up->cmdqueue[0]; /* Next char to be sent. */
606 { up->cmdqueue[i] = up->cmdqueue[i+1]; }
610 if(write(pp->io.fd, &c, 1) != 1) {
611 msyslog(LOG_NOTICE, "ARCRON: write to fd %d failed", pp->io.fd);
614 else if(debug) { printf("arc: sent `%2.2x', fd %d.\n", c, pp->io.fd); }
622 * arc_start - open the devices and initialize data for processing
648 temp_fd = refclock_open(&peer->srcadr, device, SPEED, LDISC_CLK);
660 temp_fd = -1; /* not used after this, at *this* time. */
663 if (-1 == fcntl(fd, F_SETFL, 0)) /* clear the descriptor flags */
704 pp = peer->procptr;
705 pp->io.clock_recv = arc_receive;
706 pp->io.srcclock = peer;
707 pp->io.datalen = 0;
708 pp->io.fd = fd;
709 if (!io_addclock(&pp->io)) {
711 pp->io.fd = -1;
715 pp->unitptr = up;
720 peer->precision = PRECISION;
721 peer->stratum = 2; /* Default to stratum 2 not 0. */
722 pp->clockdesc = DESCRIPTION;
723 if (peer->MODE > 3) {
724 msyslog(LOG_NOTICE, "ARCRON: Invalid mode %d", peer->MODE);
728 if(debug) { printf("arc: mode = %d.\n", peer->MODE); }
730 switch (peer->MODE) {
732 memcpy((char *)&pp->refid, REFID_MSF, 4);
735 memcpy((char *)&pp->refid, REFID_DCF77, 4);
738 memcpy((char *)&pp->refid, REFID_WWVB, 4);
741 memcpy((char *)&pp->refid, REFID, 4);
745 up->next_resync = current_time + INITIAL_RESYNC_DELAY + (67*unit)%1009;
748 up->resyncing = 0; /* Not resyncing yet. */
749 up->saved_flags = 0; /* Default is all flags off. */
753 for(i = CMDQUEUELEN; i >= 0; --i) { up->cmdqueue[i] = '\0'; }
758 up->quality = QUALITY_UNKNOWN; /* Trust the clock immediately. */
760 up->quality = MIN_CLOCK_QUALITY;/* Don't trust the clock yet. */
763 peer->procptr->action = arc_event_handler;
772 * arc_shutdown - shut down the clock
783 peer->procptr->action = dummy_event_handler;
785 pp = peer->procptr;
786 up = pp->unitptr;
787 if (-1 != pp->io.fd)
788 io_closeclock(&pp->io);
805 { if(up->cmdqueue[CMDQUEUELEN - 1 - spaceleft] != '\0') { break; } }
830 msyslog(LOG_NOTICE, "ARCRON: send-buffer overrun (%d/%d)",
837 while(*s && spaceleft > 0) { up->cmdqueue[CMDQUEUELEN - spaceleft--] = *s++; }
847 *val = (p[0] - '0') * 10 + p[1] - '0';
855 *val = p[0] - '0';
866 * arc_receive - receive data from the serial interface
889 peer = rbufp->recv_peer;
890 pp = peer->procptr;
891 up = pp->unitptr;
898 if((up->resyncing) && (space_left(up) == CMDQUEUELEN)) {
900 if(debug > 1) { printf("arc: inserting signal-quality poll.\n"); }
902 send_slow(up, pp->io.fd, "g\r");
913 assumption also works if receive the characters one-by-one.)
915 arc_last_offset = pp->lencode+rbufp->recv_length - 1;
924 only sample the first character of the timecode as our
925 `on-time' character.
927 * The first character in the buffer is not the echoed `\r'
929 must not be first in the receive buffer with lencode==1.
936 c = rbufp->recv_buffer[0];
937 if((pp->a_lastcode[0] == 'o') &&
939 (pp->lencode == 1) &&
941 ((pp->lencode != 1) || (c != '\r')) &&
945 timestamp = rbufp->recv_time;
947 if(debug) { /* Show \r as `R', other non-printing char as `?'. */
948 printf("arc: stamp -->%c<-- (%d chars rcvd)\n",
950 rbufp->recv_length);
955 Now correct timestamp by offset of last byte received---we
956 subtract from the receive time the delay implied by the
970 pp->lencode = 0;
979 "arc: %s%d char(s) rcvd, the last for lastcode[%d]; -%sms offset applied.\n",
980 ((rbufp->recv_length > 1) ? "*** " : ""),
981 rbufp->recv_length,
998 delay in being delivered to us and is more accurate.
1001 if(L_ISZERO(&(up->lastrec)) ||
1002 L_ISGEQ(&(up->lastrec), ×tamp))
1009 if(!L_ISZERO(&(up->lastrec))) {
1011 diff = up->lastrec;
1013 printf("arc: adjusted timestamp by -%sms.\n",
1019 up->lastrec = timestamp;
1028 if(pp->lencode >= LENARC) {
1030 if(debug && (rbufp->recv_buffer[0] != '\r'))
1031 { printf("arc: rubbish in pp->a_lastcode[].\n"); }
1033 pp->lencode = 0;
1038 for(i = 0; i < rbufp->recv_length; i++) {
1039 if(pp->lencode >= LENARC) { break; } /* Avoid overflow... */
1040 c = rbufp->recv_buffer[i];
1043 if(c != '\r' && c != 'h') { pp->a_lastcode[pp->lencode++] = c; }
1052 if((c == 'o') && (pp->lencode == 1)) {
1053 L_CLR(&(up->lastrec));
1059 if (pp->lencode == 0) return;
1062 if(pp->a_lastcode[0] == 'g') {
1065 if(pp->lencode < 3) { return; } /* Need more data... */
1066 r = (pp->a_lastcode[1] & 0x7f); /* Strip parity. */
1067 q = (pp->a_lastcode[2] & 0x7f); /* Strip parity. */
1077 if (up->quality_stamp < current_time) {
1083 up->quality_stamp =
1084 current_time + 60 - cal.second + 5;
1094 } else if( /* (r == '2') && */ up->resyncing) {
1095 up->quality = quality_average;
1100 up->quality,
1101 quality_action(up->quality));
1106 up->quality,
1107 quality_action(up->quality));
1108 up->resyncing = 0; /* Resync is over. */
1115 if((up->quality == QUALITY_UNKNOWN) ||
1116 (up->quality < MIN_CLOCK_QUALITY_OK))
1117 { up->next_resync = current_time + RETRY_RESYNC_TIME; }
1120 pp->lencode = 0;
1125 if(pp->a_lastcode[0] != 'o') {
1126 pp->lencode = 0;
1132 if(pp->lencode < LENARC) { return; }
1141 if(L_ISZERO(&(up->lastrec))) {
1145 pp->lencode = 0;
1155 pp->a_lastcode[pp->lencode] = ((up->quality == QUALITY_UNKNOWN) ?
1156 '6' : ('0' + up->quality));
1157 pp->a_lastcode[pp->lencode + 1] = '\0'; /* Terminate for printf(). */
1160 /* We don't use the micro-/milli- second part... */
1161 pp->usec = 0;
1162 pp->msec = 0;
1164 /* We don't use the nano-second part... */
1165 pp->nsec = 0;
1168 if (pp->a_lastcode[0] != 'o'
1169 || !get2(pp->a_lastcode + 1, &pp->hour)
1170 || !get2(pp->a_lastcode + 3, &pp->minute)
1171 || !get2(pp->a_lastcode + 5, &pp->second)
1172 || !get1(pp->a_lastcode + 7, &wday)
1173 || !get2(pp->a_lastcode + 8, &pp->day)
1174 || !get2(pp->a_lastcode + 10, &month)
1175 || !get2(pp->a_lastcode + 12, &pp->year)) {
1180 pp->lencode = 0;
1184 flags = pp->a_lastcode[14];
1185 status = pp->a_lastcode[15];
1193 array-bounds problems, etc.
1195 if((pp->hour < 0) || (pp->hour > 23) ||
1196 (pp->minute < 0) || (pp->minute > 59) ||
1197 (pp->second < 0) || (pp->second > 60) /*Allow for leap seconds.*/ ||
1199 (pp->day < 1) || (pp->day > 31) ||
1201 (pp->year < 0) || (pp->year > 99)) {
1203 pp->lencode = 0;
1209 if(peer->MODE == 0) { /* compatiblity to original version */
1213 pp->lencode = 0;
1220 /* Year-2000 alert! */
1221 /* Attempt to wrap 2-digit date into sensible window. */
1222 if(pp->year < YEAR_PIVOT) { pp->year += 100; } /* Y2KFixes */
1223 pp->year += 1900; /* use full four-digit year */ /* Y2KFixes */
1227 hero I am... PLEASE FIX LEAP-YEAR AND WRAP CODE IN 209X!
1229 if(pp->year >= YEAR_PIVOT+2000-2 ) { /* Y2KFixes */
1238 pp->hour, pp->minute, pp->second,
1239 pp->day, month, pp->year, flags, status);
1249 pp->leap = LEAP_NOWARNING;
1252 if(status != up->status)
1255 if(status != up->status) {
1257 pp->leap = LEAP_NOTINSYNC; /* MSF clock is free-running. */
1258 up->status = status;
1259 pp->lencode = 0;
1264 up->status = status;
1266 if (peer->MODE == 0) { /* compatiblity to original version */
1269 pp->day += moff[month - 1];
1271 if(isleap_4(pp->year) && month > 2) { pp->day++; }/* Y2KFixes */
1275 pp->hour--;
1276 if (pp->hour < 0) {
1277 pp->hour = 23;
1278 pp->day--;
1281 if(pp->day < 0) {
1282 pp->lencode = 0;
1290 if(peer->MODE > 0) {
1291 if(pp->sloppyclockflag & CLK_FLAG1) {
1298 * This means we have to do Y2K conversion on the
1299 * 2-digit year; otherwise, we get the time wrong.
1304 local.tm_year = pp->year-1900;
1305 local.tm_mon = month-1;
1306 local.tm_mday = pp->day;
1307 local.tm_hour = pp->hour;
1308 local.tm_min = pp->minute;
1309 local.tm_sec = pp->second;
1310 switch (peer->MODE) {
1320 Arcron changes from DST->ST and
1321 ST->DST. Testing has shown this
1330 case 1: /* dst->st time */
1331 local.tm_isdst = -1;
1337 case 2: /* st->dst time */
1338 local.tm_isdst = -1;
1355 peer->MODE);
1362 pp->lencode = 0;
1366 pp->year = gmtp->tm_year+1900;
1367 month = gmtp->tm_mon+1;
1368 pp->day = ymd2yd(pp->year,month,gmtp->tm_mday);
1369 /* pp->day = gmtp->tm_yday; */
1370 pp->hour = gmtp->tm_hour;
1371 pp->minute = gmtp->tm_min;
1372 pp->second = gmtp->tm_sec;
1377 pp->year,month,gmtp->tm_mday,pp->hour,pp->minute,
1378 pp->second);
1386 pp->day = ymd2yd(pp->year,month,pp->day);
1390 if (peer->MODE == 0) { /* compatiblity to original version */
1393 if(up->quality == QUALITY_UNKNOWN) {
1394 peer->precision = PRECISION;
1396 peer->precision = ((pp->sloppyclockflag & CLK_FLAG3) ?
1400 if ((status == 0x3) && (pp->sloppyclockflag & CLK_FLAG2)) {
1401 peer->precision = ((pp->sloppyclockflag & CLK_FLAG3) ?
1403 } else if (up->quality == QUALITY_UNKNOWN) {
1404 peer->precision = PRECISION;
1406 peer->precision = ((pp->sloppyclockflag & CLK_FLAG3) ?
1412 if(up->saved_flags != pp->sloppyclockflag) {
1415 ((pp->sloppyclockflag & CLK_FLAG1) ? "1" : "."),
1416 ((pp->sloppyclockflag & CLK_FLAG2) ? "2" : "."),
1417 ((pp->sloppyclockflag & CLK_FLAG3) ? "3" : "."),
1418 ((pp->sloppyclockflag & CLK_FLAG4) ? "4" : "."));
1421 printf("arc: PRECISION = %d.\n", peer->precision);
1424 up->saved_flags = pp->sloppyclockflag;
1428 pp->lastrec = up->lastrec;
1431 /* Find out if a leap-second might just have happened...
1432 (ie is this the first hour of the first day of Jan or Jul?)
1434 if((pp->hour == 0) &&
1435 (pp->day == 1) &&
1442 /* Definitely not leap-second territory... */
1448 pp->lencode = 0;
1452 record_clock_stats(&peer->srcadr, pp->a_lastcode);
1467 struct refclockproc *pp = peer->procptr;
1468 register struct arcunit *up = pp->unitptr;
1472 if (!send_slow(up, pp->io.fd, "o\r")) {
1478 pp->lencode = 0;
1482 pp->polls++;
1486 * arc_poll - called by the transmit procedure
1498 pp = peer->procptr;
1499 up = pp->unitptr;
1501 pp->lencode = 0;
1502 memset(pp->a_lastcode, 0, sizeof(pp->a_lastcode));
1507 tcflush(pp->io.fd, TCIFLUSH);
1511 resync_needed = ( !(pp->sloppyclockflag & CLK_FLAG2) &&
1512 (up->next_resync <= current_time) );
1516 Try to catch a potential leap-second insertion or deletion quickly.
1519 leap-seconds spooking their hosts, this clock does not even
1521 leap-second insertion or deletion for up to a whole sample
1524 To try to minimise this effect, if in the first few minutes of
1525 the day immediately following a leap-second-insertion point
1526 (ie in the first hour of the first day of the first and sixth
1533 (!up->resyncing)) { /* No resync in progress yet. */
1535 possible_leap = -1; /* Prevent multiple resyncs. */
1542 /* First, reset quality value to `unknown' so we can detect */
1545 up->quality = QUALITY_UNKNOWN;
1548 up->resyncing = 1;
1555 send_slow(up, pp->io.fd, "h\r");
1558 up->next_resync = current_time + DEFAULT_RESYNC_TIME;
1566 /* synced so quickly we did not catch it---we'll */
1567 /* double-check the clock is OK elsewhere. */
1570 (up->quality != QUALITY_UNKNOWN) &&
1572 (up->quality == QUALITY_UNKNOWN) ||
1574 (up->quality < MIN_CLOCK_QUALITY_OK)) {
1577 printf("arc: clock quality %d too poor.\n", up->quality);
1580 pp->lencode = 0;