Lines Matching +full:ideal +full:- +full:factor +full:- +full:value
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
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:
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
168 probably ideal for. For an isolated network without other time
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
177 the PRECISION will revert to the normal value while the clock
180 IN ANY CASE, BE SURE TO SET AN APPROPRIATE FUDGE FACTOR TO REMOVE
189 fudge factor should be. For my Sun SS1 running SunOS 4.1.3_U1 with
199 clashing with any regular event at a regular time-past-the-hour
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
260 accuracy; maybe could be done via fudge factor or unit number.
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
314 /* 7. day of week 1-monday 7-sunday */
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))
413 is on-time. The values are represented as the fractional part of
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.
513 Outside the special hour this value is unconditionally set
516 On finding itself in this timeslot, as long as the value is
517 non-negative, the receive routine sets it to a positive value to
520 In the poll routine, if this value is positive and we are not
522 midnight), start resyncing and set this value negative 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. */
595 struct refclockproc *pp = peer->procptr; in arc_event_handler()
596 register struct arcunit *up = pp->unitptr; in arc_event_handler()
603 c = up->cmdqueue[0]; /* Next char to be sent. */ in arc_event_handler()
606 { up->cmdqueue[i] = up->cmdqueue[i+1]; } in arc_event_handler()
610 if(write(pp->io.fd, &c, 1) != 1) { in arc_event_handler()
611 msyslog(LOG_NOTICE, "ARCRON: write to fd %d failed", pp->io.fd); in arc_event_handler()
614 else if(debug) { printf("arc: sent `%2.2x', fd %d.\n", c, pp->io.fd); } in arc_event_handler()
622 * arc_start - open the devices and initialize data for processing
648 temp_fd = refclock_open(&peer->srcadr, device, SPEED, LDISC_CLK); in arc_start()
660 temp_fd = -1; /* not used after this, at *this* time. */ in arc_start()
663 if (-1 == fcntl(fd, F_SETFL, 0)) /* clear the descriptor flags */ in arc_start()
704 pp = peer->procptr; in arc_start()
705 pp->io.clock_recv = arc_receive; in arc_start()
706 pp->io.srcclock = peer; in arc_start()
707 pp->io.datalen = 0; in arc_start()
708 pp->io.fd = fd; in arc_start()
709 if (!io_addclock(&pp->io)) { in arc_start()
711 pp->io.fd = -1; in arc_start()
715 pp->unitptr = up; in arc_start()
720 peer->precision = PRECISION; in arc_start()
721 peer->stratum = 2; /* Default to stratum 2 not 0. */ in arc_start()
722 pp->clockdesc = DESCRIPTION; in arc_start()
723 if (peer->MODE > 3) { in arc_start()
724 msyslog(LOG_NOTICE, "ARCRON: Invalid mode %d", peer->MODE); in arc_start()
728 if(debug) { printf("arc: mode = %d.\n", peer->MODE); } in arc_start()
730 switch (peer->MODE) { in arc_start()
732 memcpy((char *)&pp->refid, REFID_MSF, 4); in arc_start()
735 memcpy((char *)&pp->refid, REFID_DCF77, 4); in arc_start()
738 memcpy((char *)&pp->refid, REFID_WWVB, 4); in arc_start()
741 memcpy((char *)&pp->refid, REFID, 4); in arc_start()
745 up->next_resync = current_time + INITIAL_RESYNC_DELAY + (67*unit)%1009; in arc_start()
748 up->resyncing = 0; /* Not resyncing yet. */ in arc_start()
749 up->saved_flags = 0; /* Default is all flags off. */ in arc_start()
753 for(i = CMDQUEUELEN; i >= 0; --i) { up->cmdqueue[i] = '\0'; } in arc_start()
758 up->quality = QUALITY_UNKNOWN; /* Trust the clock immediately. */ in arc_start()
760 up->quality = MIN_CLOCK_QUALITY;/* Don't trust the clock yet. */ in arc_start()
763 peer->procptr->action = arc_event_handler; in arc_start()
772 * arc_shutdown - shut down the clock
783 peer->procptr->action = dummy_event_handler; in arc_shutdown()
785 pp = peer->procptr; in arc_shutdown()
786 up = pp->unitptr; in arc_shutdown()
787 if (-1 != pp->io.fd) in arc_shutdown()
788 io_closeclock(&pp->io); in arc_shutdown()
805 { if(up->cmdqueue[CMDQUEUELEN - 1 - spaceleft] != '\0') { break; } } in space_left()
830 msyslog(LOG_NOTICE, "ARCRON: send-buffer overrun (%d/%d)", in send_slow()
837 while(*s && spaceleft > 0) { up->cmdqueue[CMDQUEUELEN - spaceleft--] = *s++; } in send_slow()
847 *val = (p[0] - '0') * 10 + p[1] - '0'; in get2()
855 *val = p[0] - '0'; in get1()
866 * arc_receive - receive data from the serial interface
889 peer = rbufp->recv_peer; in arc_receive()
890 pp = peer->procptr; in arc_receive()
891 up = pp->unitptr; in arc_receive()
898 if((up->resyncing) && (space_left(up) == CMDQUEUELEN)) { in arc_receive()
900 if(debug > 1) { printf("arc: inserting signal-quality poll.\n"); } in arc_receive()
902 send_slow(up, pp->io.fd, "g\r"); in arc_receive()
913 assumption also works if receive the characters one-by-one.) in arc_receive()
915 arc_last_offset = pp->lencode+rbufp->recv_length - 1; in arc_receive()
925 `on-time' character. in arc_receive()
936 c = rbufp->recv_buffer[0]; in arc_receive()
937 if((pp->a_lastcode[0] == 'o') && in arc_receive()
939 (pp->lencode == 1) && in arc_receive()
941 ((pp->lencode != 1) || (c != '\r')) && in arc_receive()
945 timestamp = rbufp->recv_time; in arc_receive()
947 if(debug) { /* Show \r as `R', other non-printing char as `?'. */ in arc_receive()
948 printf("arc: stamp -->%c<-- (%d chars rcvd)\n", in arc_receive()
950 rbufp->recv_length); in arc_receive()
955 Now correct timestamp by offset of last byte received---we in arc_receive()
970 pp->lencode = 0; in arc_receive()
979 "arc: %s%d char(s) rcvd, the last for lastcode[%d]; -%sms offset applied.\n", in arc_receive()
980 ((rbufp->recv_length > 1) ? "*** " : ""), in arc_receive()
981 rbufp->recv_length, in arc_receive()
1001 if(L_ISZERO(&(up->lastrec)) || in arc_receive()
1002 L_ISGEQ(&(up->lastrec), ×tamp)) in arc_receive()
1009 if(!L_ISZERO(&(up->lastrec))) { in arc_receive()
1011 diff = up->lastrec; in arc_receive()
1013 printf("arc: adjusted timestamp by -%sms.\n", in arc_receive()
1019 up->lastrec = timestamp; in arc_receive()
1028 if(pp->lencode >= LENARC) { in arc_receive()
1030 if(debug && (rbufp->recv_buffer[0] != '\r')) in arc_receive()
1031 { printf("arc: rubbish in pp->a_lastcode[].\n"); } in arc_receive()
1033 pp->lencode = 0; in arc_receive()
1038 for(i = 0; i < rbufp->recv_length; i++) { in arc_receive()
1039 if(pp->lencode >= LENARC) { break; } /* Avoid overflow... */ in arc_receive()
1040 c = rbufp->recv_buffer[i]; in arc_receive()
1043 if(c != '\r' && c != 'h') { pp->a_lastcode[pp->lencode++] = c; } in arc_receive()
1052 if((c == 'o') && (pp->lencode == 1)) { in arc_receive()
1053 L_CLR(&(up->lastrec)); in arc_receive()
1059 if (pp->lencode == 0) return; in arc_receive()
1062 if(pp->a_lastcode[0] == 'g') { in arc_receive()
1065 if(pp->lencode < 3) { return; } /* Need more data... */ in arc_receive()
1066 r = (pp->a_lastcode[1] & 0x7f); /* Strip parity. */ in arc_receive()
1067 q = (pp->a_lastcode[2] & 0x7f); /* Strip parity. */ in arc_receive()
1076 if(r == '3') { /* Only use quality value whilst sync in progress. */ in arc_receive()
1077 if (up->quality_stamp < current_time) { in arc_receive()
1083 up->quality_stamp = in arc_receive()
1084 current_time + 60 - cal.second + 5; in arc_receive()
1094 } else if( /* (r == '2') && */ up->resyncing) { in arc_receive()
1095 up->quality = quality_average; in arc_receive()
1100 up->quality, in arc_receive()
1101 quality_action(up->quality)); in arc_receive()
1106 up->quality, in arc_receive()
1107 quality_action(up->quality)); in arc_receive()
1108 up->resyncing = 0; /* Resync is over. */ in arc_receive()
1115 if((up->quality == QUALITY_UNKNOWN) || in arc_receive()
1116 (up->quality < MIN_CLOCK_QUALITY_OK)) in arc_receive()
1117 { up->next_resync = current_time + RETRY_RESYNC_TIME; } in arc_receive()
1120 pp->lencode = 0; in arc_receive()
1125 if(pp->a_lastcode[0] != 'o') { in arc_receive()
1126 pp->lencode = 0; in arc_receive()
1132 if(pp->lencode < LENARC) { return; } in arc_receive()
1141 if(L_ISZERO(&(up->lastrec))) { in arc_receive()
1145 pp->lencode = 0; in arc_receive()
1152 quality value to `6' for his s/w) and terminate the string for in arc_receive()
1155 pp->a_lastcode[pp->lencode] = ((up->quality == QUALITY_UNKNOWN) ? in arc_receive()
1156 '6' : ('0' + up->quality)); in arc_receive()
1157 pp->a_lastcode[pp->lencode + 1] = '\0'; /* Terminate for printf(). */ in arc_receive()
1160 /* We don't use the micro-/milli- second part... */ in arc_receive()
1161 pp->usec = 0; in arc_receive()
1162 pp->msec = 0; in arc_receive()
1164 /* We don't use the nano-second part... */ in arc_receive()
1165 pp->nsec = 0; in arc_receive()
1168 if (pp->a_lastcode[0] != 'o' in arc_receive()
1169 || !get2(pp->a_lastcode + 1, &pp->hour) in arc_receive()
1170 || !get2(pp->a_lastcode + 3, &pp->minute) in arc_receive()
1171 || !get2(pp->a_lastcode + 5, &pp->second) in arc_receive()
1172 || !get1(pp->a_lastcode + 7, &wday) in arc_receive()
1173 || !get2(pp->a_lastcode + 8, &pp->day) in arc_receive()
1174 || !get2(pp->a_lastcode + 10, &month) in arc_receive()
1175 || !get2(pp->a_lastcode + 12, &pp->year)) { in arc_receive()
1180 pp->lencode = 0; in arc_receive()
1184 flags = pp->a_lastcode[14]; in arc_receive()
1185 status = pp->a_lastcode[15]; in arc_receive()
1193 array-bounds problems, etc. in arc_receive()
1195 if((pp->hour < 0) || (pp->hour > 23) || in arc_receive()
1196 (pp->minute < 0) || (pp->minute > 59) || in arc_receive()
1197 (pp->second < 0) || (pp->second > 60) /*Allow for leap seconds.*/ || in arc_receive()
1199 (pp->day < 1) || (pp->day > 31) || in arc_receive()
1201 (pp->year < 0) || (pp->year > 99)) { in arc_receive()
1203 pp->lencode = 0; in arc_receive()
1209 if(peer->MODE == 0) { /* compatiblity to original version */ in arc_receive()
1213 pp->lencode = 0; in arc_receive()
1220 /* Year-2000 alert! */ in arc_receive()
1221 /* Attempt to wrap 2-digit date into sensible window. */ in arc_receive()
1222 if(pp->year < YEAR_PIVOT) { pp->year += 100; } /* Y2KFixes */ in arc_receive()
1223 pp->year += 1900; /* use full four-digit year */ /* Y2KFixes */ in arc_receive()
1227 hero I am... PLEASE FIX LEAP-YEAR AND WRAP CODE IN 209X! in arc_receive()
1229 if(pp->year >= YEAR_PIVOT+2000-2 ) { /* Y2KFixes */ in arc_receive()
1238 pp->hour, pp->minute, pp->second, in arc_receive()
1239 pp->day, month, pp->year, flags, status); in arc_receive()
1244 The status value tested for is not strictly supported by the in arc_receive()
1245 clock spec since the value of bit 2 (0x4) is claimed to be in arc_receive()
1249 pp->leap = LEAP_NOWARNING; in arc_receive()
1252 if(status != up->status) in arc_receive()
1255 if(status != up->status) { in arc_receive()
1257 pp->leap = LEAP_NOTINSYNC; /* MSF clock is free-running. */ in arc_receive()
1258 up->status = status; in arc_receive()
1259 pp->lencode = 0; in arc_receive()
1264 up->status = status; in arc_receive()
1266 if (peer->MODE == 0) { /* compatiblity to original version */ in arc_receive()
1269 pp->day += moff[month - 1]; in arc_receive()
1271 if(isleap_4(pp->year) && month > 2) { pp->day++; }/* Y2KFixes */ in arc_receive()
1275 pp->hour--; in arc_receive()
1276 if (pp->hour < 0) { in arc_receive()
1277 pp->hour = 23; in arc_receive()
1278 pp->day--; in arc_receive()
1281 if(pp->day < 0) { in arc_receive()
1282 pp->lencode = 0; in arc_receive()
1290 if(peer->MODE > 0) { in arc_receive()
1291 if(pp->sloppyclockflag & CLK_FLAG1) { in arc_receive()
1299 * 2-digit year; otherwise, we get the time wrong. in arc_receive()
1304 local.tm_year = pp->year-1900; in arc_receive()
1305 local.tm_mon = month-1; in arc_receive()
1306 local.tm_mday = pp->day; in arc_receive()
1307 local.tm_hour = pp->hour; in arc_receive()
1308 local.tm_min = pp->minute; in arc_receive()
1309 local.tm_sec = pp->second; in arc_receive()
1310 switch (peer->MODE) { in arc_receive()
1320 Arcron changes from DST->ST and in arc_receive()
1321 ST->DST. Testing has shown this in arc_receive()
1330 case 1: /* dst->st time */ in arc_receive()
1331 local.tm_isdst = -1; in arc_receive()
1337 case 2: /* st->dst time */ in arc_receive()
1338 local.tm_isdst = -1; in arc_receive()
1355 peer->MODE); in arc_receive()
1362 pp->lencode = 0; in arc_receive()
1366 pp->year = gmtp->tm_year+1900; in arc_receive()
1367 month = gmtp->tm_mon+1; in arc_receive()
1368 pp->day = ymd2yd(pp->year,month,gmtp->tm_mday); in arc_receive()
1369 /* pp->day = gmtp->tm_yday; */ in arc_receive()
1370 pp->hour = gmtp->tm_hour; in arc_receive()
1371 pp->minute = gmtp->tm_min; in arc_receive()
1372 pp->second = gmtp->tm_sec; in arc_receive()
1377 pp->year,month,gmtp->tm_mday,pp->hour,pp->minute, in arc_receive()
1378 pp->second); in arc_receive()
1386 pp->day = ymd2yd(pp->year,month,pp->day); in arc_receive()
1390 if (peer->MODE == 0) { /* compatiblity to original version */ in arc_receive()
1393 if(up->quality == QUALITY_UNKNOWN) { in arc_receive()
1394 peer->precision = PRECISION; in arc_receive()
1396 peer->precision = ((pp->sloppyclockflag & CLK_FLAG3) ? in arc_receive()
1400 if ((status == 0x3) && (pp->sloppyclockflag & CLK_FLAG2)) { in arc_receive()
1401 peer->precision = ((pp->sloppyclockflag & CLK_FLAG3) ? in arc_receive()
1403 } else if (up->quality == QUALITY_UNKNOWN) { in arc_receive()
1404 peer->precision = PRECISION; in arc_receive()
1406 peer->precision = ((pp->sloppyclockflag & CLK_FLAG3) ? in arc_receive()
1412 if(up->saved_flags != pp->sloppyclockflag) { in arc_receive()
1415 ((pp->sloppyclockflag & CLK_FLAG1) ? "1" : "."), in arc_receive()
1416 ((pp->sloppyclockflag & CLK_FLAG2) ? "2" : "."), in arc_receive()
1417 ((pp->sloppyclockflag & CLK_FLAG3) ? "3" : "."), in arc_receive()
1418 ((pp->sloppyclockflag & CLK_FLAG4) ? "4" : ".")); in arc_receive()
1421 printf("arc: PRECISION = %d.\n", peer->precision); in arc_receive()
1424 up->saved_flags = pp->sloppyclockflag; in arc_receive()
1428 pp->lastrec = up->lastrec; in arc_receive()
1431 /* Find out if a leap-second might just have happened... in arc_receive()
1434 if((pp->hour == 0) && in arc_receive()
1435 (pp->day == 1) && in arc_receive()
1442 /* Definitely not leap-second territory... */ in arc_receive()
1448 pp->lencode = 0; in arc_receive()
1452 record_clock_stats(&peer->srcadr, pp->a_lastcode); in arc_receive()
1467 struct refclockproc *pp = peer->procptr; in request_time()
1468 register struct arcunit *up = pp->unitptr; in request_time()
1472 if (!send_slow(up, pp->io.fd, "o\r")) { in request_time()
1478 pp->lencode = 0; in request_time()
1482 pp->polls++; in request_time()
1486 * arc_poll - called by the transmit procedure
1498 pp = peer->procptr; in arc_poll()
1499 up = pp->unitptr; in arc_poll()
1501 pp->lencode = 0; in arc_poll()
1502 memset(pp->a_lastcode, 0, sizeof(pp->a_lastcode)); in arc_poll()
1507 tcflush(pp->io.fd, TCIFLUSH); in arc_poll()
1511 resync_needed = ( !(pp->sloppyclockflag & CLK_FLAG2) && in arc_poll()
1512 (up->next_resync <= current_time) ); in arc_poll()
1516 Try to catch a potential leap-second insertion or deletion quickly. in arc_poll()
1519 leap-seconds spooking their hosts, this clock does not even in arc_poll()
1521 leap-second insertion or deletion for up to a whole sample in arc_poll()
1525 the day immediately following a leap-second-insertion point in arc_poll()
1533 (!up->resyncing)) { /* No resync in progress yet. */ in arc_poll()
1535 possible_leap = -1; /* Prevent multiple resyncs. */ in arc_poll()
1542 /* First, reset quality value to `unknown' so we can detect */ in arc_poll()
1544 /* being set to some other value. */ in arc_poll()
1545 up->quality = QUALITY_UNKNOWN; in arc_poll()
1548 up->resyncing = 1; in arc_poll()
1555 send_slow(up, pp->io.fd, "h\r"); in arc_poll()
1558 up->next_resync = current_time + DEFAULT_RESYNC_TIME; in arc_poll()
1566 /* synced so quickly we did not catch it---we'll */ in arc_poll()
1567 /* double-check the clock is OK elsewhere. */ in arc_poll()
1570 (up->quality != QUALITY_UNKNOWN) && in arc_poll()
1572 (up->quality == QUALITY_UNKNOWN) || in arc_poll()
1574 (up->quality < MIN_CLOCK_QUALITY_OK)) { in arc_poll()
1577 printf("arc: clock quality %d too poor.\n", up->quality); in arc_poll()
1580 pp->lencode = 0; in arc_poll()