2) PRECISION should be -4/-5 (63ms/31ms) for the following reasons:
a) The ARC documentation claims the internal clock is (only)
- accurate to about 20ms relative to Rugby (plus there must be
- noticable drift and delay in the ms range due to transmission
- delays and changing atmospheric effects). This clock is not
- designed for ms accuracy as NTP has spoilt us all to expect.
+ accurate to about 20ms relative to Rugby (plus there must be
+ noticable drift and delay in the ms range due to transmission
+ delays and changing atmospheric effects). This clock is not
+ designed for ms accuracy as NTP has spoilt us all to expect.
b) The clock oscillator looks like a simple uncompensated quartz
- crystal of the sort used in digital watches (ie 32768Hz) which
- can have large temperature coefficients and drifts; it is not
- clear if this oscillator is properly disciplined to the MSF
- transmission, but as the default is to resync only once per
- *day*, we can imagine that it is not, and is free-running. We
- can minimise drift by resyncing more often (at the cost of
- reduced battery life), but drift/wander may still be
- significant.
+ crystal of the sort used in digital watches (ie 32768Hz) which
+ can have large temperature coefficients and drifts; it is not
+ clear if this oscillator is properly disciplined to the MSF
+ transmission, but as the default is to resync only once per
+ *day*, we can imagine that it is not, and is free-running. We
+ can minimise drift by resyncing more often (at the cost of
+ reduced battery life), but drift/wander may still be
+ significant.
c) Note that the bit time of 3.3ms adds to the potential error in
- the the clock timestamp, since the bit clock of the serial link
- may effectively be free-running with respect to the host clock
- and the MSF clock. Actually, the error is probably 1/16th of
- the above, since the input data is probably sampled at at least
- 16x the bit rate.
+ the the clock timestamp, since the bit clock of the serial link
+ may effectively be free-running with respect to the host clock
+ and the MSF clock. Actually, the error is probably 1/16th of
+ the above, since the input data is probably sampled at at least
+ 16x the bit rate.
By keeping the clock marked as not very precise, it will have a
fairly large dispersion, and thus will tend to be used as a
IN ANY CASE, BE SURE TO SET AN APPROPRIATE FUDGE FACTOR TO REMOVE
ANY RESIDUAL SKEW, eg:
- server 127.127.27.0 # ARCRON MSF radio clock unit 0.
- # Fudge timestamps by about 20ms.
- fudge 127.127.27.0 time1 0.020
+ server 127.127.27.0 # ARCRON MSF radio clock unit 0.
+ # Fudge timestamps by about 20ms.
+ fudge 127.127.27.0 time1 0.020
You will need to observe your system's behaviour, assuming you have
some other NTP source to compare it with, to work out what the
/* 12. year tens */
/* 13. year units */
/* 14. BST/UTC status */
-/* bit 7 parity */
-/* bit 6 always 0 */
-/* bit 5 always 1 */
-/* bit 4 always 1 */
-/* bit 3 always 0 */
-/* bit 2 =1 if UTC is in effect, complementary to the BST bit */
-/* bit 1 =1 if BST is in effect, according to the BST bit */
-/* bit 0 BST/UTC change impending bit=1 in case of change impending */
+/* bit 7 parity */
+/* bit 6 always 0 */
+/* bit 5 always 1 */
+/* bit 4 always 1 */
+/* bit 3 always 0 */
+/* bit 2 =1 if UTC is in effect, complementary to the BST bit */
+/* bit 1 =1 if BST is in effect, according to the BST bit */
+/* bit 0 BST/UTC change impending bit=1 in case of change impending */
/* 15. status */
-/* bit 7 parity */
-/* bit 6 always 0 */
-/* bit 5 always 1 */
-/* bit 4 always 1 */
-/* bit 3 =1 if low battery is detected */
-/* bit 2 =1 if the very last reception attempt failed and a valid */
-/* time information already exists (bit0=1) */
-/* =0 if the last reception attempt was successful */
-/* bit 1 =1 if at least one reception since 2:30 am was successful */
-/* =0 if no reception attempt since 2:30 am was successful */
-/* bit 0 =1 if the RC Computer Clock contains valid time information */
-/* This bit is zero after reset and one after the first */
-/* successful reception attempt */
+/* bit 7 parity */
+/* bit 6 always 0 */
+/* bit 5 always 1 */
+/* bit 4 always 1 */
+/* bit 3 =1 if low battery is detected */
+/* bit 2 =1 if the very last reception attempt failed and a valid */
+/* time information already exists (bit0=1) */
+/* =0 if the last reception attempt was successful */
+/* bit 1 =1 if at least one reception since 2:30 am was successful */
+/* =0 if no reception attempt since 2:30 am was successful */
+/* bit 0 =1 if the RC Computer Clock contains valid time information */
+/* This bit is zero after reset and one after the first */
+/* successful reception attempt */
/* DHD note:
Also note g<cr> command which confirms that a resync is in progress, and
/*
* Interface definitions
*/
-#define DEVICE "/dev/arc%d" /* Device name and unit. */
-#define SPEED B300 /* UART speed (300 baud) */
-#define PRECISION (-4) /* Precision (~63 ms). */
-#define HIGHPRECISION (-5) /* If things are going well... */
-#define REFID "MSFa" /* Reference ID. */
-#define REFID_MSF "MSF" /* Reference ID. */
-#define REFID_DCF77 "DCF" /* Reference ID. */
-#define REFID_WWVB "WWVB" /* Reference ID. */
-#define DESCRIPTION "ARCRON MSF/DCF/WWVB Receiver"
+#define DEVICE "/dev/arc%d" /* Device name and unit. */
+#define SPEED B300 /* UART speed (300 baud) */
+#define PRECISION (-4) /* Precision (~63 ms). */
+#define HIGHPRECISION (-5) /* If things are going well... */
+#define REFID "MSFa" /* Reference ID. */
+#define REFID_MSF "MSF" /* Reference ID. */
+#define REFID_DCF77 "DCF" /* Reference ID. */
+#define REFID_WWVB "WWVB" /* Reference ID. */
+#define DESCRIPTION "ARCRON MSF/DCF/WWVB Receiver"
#ifdef PRE_NTP420
#define MODE ttlmax
#define MODE ttl
#endif
-#define LENARC 16 /* Format `o' timecode length. */
+#define LENARC 16 /* Format `o' timecode length. */
-#define BITSPERCHAR 11 /* Bits per character. */
-#define BITTIME 0x0DA740E /* Time for 1 bit at 300bps. */
-#define CHARTIME10 0x8888888 /* Time for 10-bit char at 300bps. */
-#define CHARTIME11 0x962FC96 /* Time for 11-bit char at 300bps. */
-#define CHARTIME /* Time for char at 300bps. */ \
+#define BITSPERCHAR 11 /* Bits per character. */
+#define BITTIME 0x0DA740E /* Time for 1 bit at 300bps. */
+#define CHARTIME10 0x8888888 /* Time for 10-bit char at 300bps. */
+#define CHARTIME11 0x962FC96 /* Time for 11-bit char at 300bps. */
+#define CHARTIME /* Time for char at 300bps. */ \
( (BITSPERCHAR == 11) ? CHARTIME11 : ( (BITSPERCHAR == 10) ? CHARTIME10 : \
(BITSPERCHAR * BITTIME) ) )
#endif
};
-#define DEFAULT_RESYNC_TIME (57*60) /* Gap between resync attempts (s). */
-#define RETRY_RESYNC_TIME (27*60) /* Gap to emergency resync attempt. */
+#define DEFAULT_RESYNC_TIME (57*60) /* Gap between resync attempts (s). */
+#define RETRY_RESYNC_TIME (27*60) /* Gap to emergency resync attempt. */
#ifdef ARCRON_KEEN
-#define INITIAL_RESYNC_DELAY 500 /* Delay before first resync. */
+#define INITIAL_RESYNC_DELAY 500 /* Delay before first resync. */
#else
-#define INITIAL_RESYNC_DELAY 50 /* Delay before first resync. */
+#define INITIAL_RESYNC_DELAY 50 /* Delay before first resync. */
#endif
static const int moff[12] =
/* Flags for a raw open() of the clock serial device. */
#ifdef O_NOCTTY /* Good, we can avoid tty becoming controlling tty. */
#define OPEN_FLAGS (O_RDWR | O_NOCTTY)
-#else /* Oh well, it may not matter... */
+#else /* Oh well, it may not matter... */
#define OPEN_FLAGS (O_RDWR)
#endif
/* Length of queue of command bytes to be sent. */
-#define CMDQUEUELEN 4 /* Enough for two cmds + each \r. */
+#define CMDQUEUELEN 4 /* Enough for two cmds + each \r. */
/* Queue tick time; interval in seconds between chars taken off queue. */
/* Must be >= 2 to allow o\r response to come back uninterrupted. */
-#define QUEUETICK 2 /* Allow o\r reply to finish. */
+#define QUEUETICK 2 /* Allow o\r reply to finish. */
/*
* ARC unit control structure
*/
struct arcunit {
- l_fp lastrec; /* Time tag for the receive time (system). */
- int status; /* Clock status. */
+ l_fp lastrec; /* Time tag for the receive time (system). */
+ int status; /* Clock status. */
- int quality; /* Quality of reception 0--5 for unit. */
+ int quality; /* Quality of reception 0--5 for unit. */
/* We may also use the values -1 or 6 internally. */
u_long quality_stamp; /* Next time to reset quality average. */
u_long next_resync; /* Next resync time (s) compared to current_time. */
- int resyncing; /* Resync in progress if true. */
+ int resyncing; /* Resync in progress if true. */
/* In the outgoing queue, cmdqueue[0] is next to be sent. */
char cmdqueue[CMDQUEUELEN+1]; /* Queue of outgoing commands + \0. */
static void arc_event_handler (struct peer *);
#endif /* 0 */
-#define QUALITY_UNKNOWN -1 /* Indicates unknown clock quality. */
+#define QUALITY_UNKNOWN -1 /* Indicates unknown clock quality. */
#define MIN_CLOCK_QUALITY 0 /* Min quality clock will return. */
#define MIN_CLOCK_QUALITY_OK 3 /* Min quality for OK reception. */
#define MAX_CLOCK_QUALITY 5 /* Max quality clock will return. */
/*
* Function prototypes
*/
-static int arc_start (int, struct peer *);
-static void arc_shutdown (int, struct peer *);
-static void arc_receive (struct recvbuf *);
-static void arc_poll (int, struct peer *);
+static int arc_start (int, struct peer *);
+static void arc_shutdown (int, struct peer *);
+static void arc_receive (struct recvbuf *);
+static void arc_poll (int, struct peer *);
/*
* Transfer vector
*/
struct refclock refclock_arc = {
- arc_start, /* start up driver */
- arc_shutdown, /* shut down driver */
- arc_poll, /* transmit poll message */
- noentry, /* not used (old arc_control) */
- noentry, /* initialize driver (not used) */
- noentry, /* not used (old arc_buginfo) */
- NOFLAGS /* not used */
+ arc_start, /* start up driver */
+ arc_shutdown, /* shut down driver */
+ arc_poll, /* transmit poll message */
+ noentry, /* not used (old arc_control) */
+ noentry, /* initialize driver (not used) */
+ noentry, /* not used (old arc_buginfo) */
+ NOFLAGS /* not used */
};
/* Queue us up for the next tick. */
if(spaceleft < sl) { /* Should not normally happen... */
#ifdef DEBUG
msyslog(LOG_NOTICE, "ARCRON: send-buffer overrun (%d/%d)",
- sl, spaceleft);
+ sl, spaceleft);
#endif
- return(0); /* FAILED! */
+ return(0); /* FAILED! */
}
/* Copy in the command to be sent. */
(((q) < MIN_CLOCK_QUALITY_OK) ? "TOO POOR, will not use clock" : \
"OK, will use clock"))
- /*
+/*
* arc_receive - receive data from the serial interface
*/
- static void
+static void
arc_receive(
struct recvbuf *rbufp
)
/* Just in case we still have lots of rubbish in the buffer... */
/* ...and to avoid the same timestamp being reused by mistake, */
/* eg on receipt of the \r coming in on its own after the */
- /* timecode. */
+ /* timecode. */
if(pp->lencode >= LENARC) {
#ifdef DEBUG
if(debug && (rbufp->recv_buffer[0] != '\r'))
}
#endif
msyslog(LOG_NOTICE,
- "ARCRON: sync finished, signal quality %d: %s",
- up->quality,
- quality_action(up->quality));
+ "ARCRON: sync finished, signal quality %d: %s",
+ up->quality,
+ quality_action(up->quality));
up->resyncing = 0; /* Resync is over. */
quality_average = 0;
quality_sum = 0;
if(pp->year >= YEAR_PIVOT+2000-2 ) { /* Y2KFixes */
/*This should get attention B^> */
msyslog(LOG_NOTICE,
- "ARCRON: fix me! EITHER YOUR DATE IS BADLY WRONG or else I will break soon!");
+ "ARCRON: fix me! EITHER YOUR DATE IS BADLY WRONG or else I will break soon!");
}
#ifdef DEBUG
if(debug) {
if(peer->MODE > 0) {
if(pp->sloppyclockflag & CLK_FLAG1) {
struct tm local;
- struct tm *gmtp;
- time_t unixtime;
+ struct tm *gmtp;
+ time_t unixtime;
- /*
- * Convert to GMT for sites that distribute localtime.
+ /*
+ * Convert to GMT for sites that distribute localtime.
* This means we have to do Y2K conversion on the
* 2-digit year; otherwise, we get the time wrong.
- */
-
+ */
+
+ memset(&local, 0, sizeof(local));
+
local.tm_year = pp->year-1900;
- local.tm_mon = month-1;
- local.tm_mday = pp->day;
- local.tm_hour = pp->hour;
- local.tm_min = pp->minute;
- local.tm_sec = pp->second;
- switch (peer->MODE) {
+ local.tm_mon = month-1;
+ local.tm_mday = pp->day;
+ local.tm_hour = pp->hour;
+ local.tm_min = pp->minute;
+ local.tm_sec = pp->second;
+ switch (peer->MODE) {
case 1:
local.tm_isdst = (flags & 2);
break;
case 2:
- local.tm_isdst = (flags & 2);
+ local.tm_isdst = (flags & 2);
break;
case 3:
switch (flags & 3) {
case 0: /* It is unclear exactly when the
- Arcron changes from DST->ST and
+ Arcron changes from DST->ST and
ST->DST. Testing has shown this
to be irregular. For the time
being, let the OS decide. */
- local.tm_isdst = 0;
+ local.tm_isdst = 0;
#ifdef DEBUG
if (debug)
printf ("arc: DST = 00 (0)\n");
#endif
break;
case 1: /* dst->st time */
- local.tm_isdst = -1;
+ local.tm_isdst = -1;
#ifdef DEBUG
if (debug)
printf ("arc: DST = 01 (1)\n");
#endif
break;
case 2: /* st->dst time */
- local.tm_isdst = -1;
+ local.tm_isdst = -1;
#ifdef DEBUG
if (debug)
printf ("arc: DST = 10 (2)\n");
break;
default:
msyslog(LOG_NOTICE, "ARCRON: Invalid mode %d",
- peer->MODE);
+ peer->MODE);
return;
break;
}
- unixtime = mktime (&local);
- if ((gmtp = gmtime (&unixtime)) == NULL)
- {
+ unixtime = mktime (&local);
+ if ((gmtp = gmtime (&unixtime)) == NULL)
+ {
pp->lencode = 0;
- refclock_report (peer, CEVNT_FAULT);
- return;
- }
+ refclock_report (peer, CEVNT_FAULT);
+ return;
+ }
pp->year = gmtp->tm_year+1900;
- month = gmtp->tm_mon+1;
- pp->day = ymd2yd(pp->year,month,gmtp->tm_mday);
- /* pp->day = gmtp->tm_yday; */
- pp->hour = gmtp->tm_hour;
- pp->minute = gmtp->tm_min;
- pp->second = gmtp->tm_sec;
+ month = gmtp->tm_mon+1;
+ pp->day = ymd2yd(pp->year,month,gmtp->tm_mday);
+ /* pp->day = gmtp->tm_yday; */
+ pp->hour = gmtp->tm_hour;
+ pp->minute = gmtp->tm_min;
+ pp->second = gmtp->tm_sec;
#ifdef DEBUG
- if (debug)
+ if (debug)
{
printf ("arc: time is %04d/%02d/%02d %02d:%02d:%02d UTC\n",
pp->year,month,gmtp->tm_mday,pp->hour,pp->minute,
#endif
} else
{
- /*
- * For more rational sites distributing UTC
- */
- pp->day = ymd2yd(pp->year,month,pp->day);
+ /*
+ * For more rational sites distributing UTC
+ */
+ pp->day = ymd2yd(pp->year,month,pp->day);
}
}
if(up->saved_flags != pp->sloppyclockflag) {
#ifdef DEBUG
msyslog(LOG_NOTICE, "ARCRON: flags enabled: %s%s%s%s",
- ((pp->sloppyclockflag & CLK_FLAG1) ? "1" : "."),
- ((pp->sloppyclockflag & CLK_FLAG2) ? "2" : "."),
- ((pp->sloppyclockflag & CLK_FLAG3) ? "3" : "."),
- ((pp->sloppyclockflag & CLK_FLAG4) ? "4" : "."));
+ ((pp->sloppyclockflag & CLK_FLAG1) ? "1" : "."),
+ ((pp->sloppyclockflag & CLK_FLAG2) ? "2" : "."),
+ ((pp->sloppyclockflag & CLK_FLAG3) ? "3" : "."),
+ ((pp->sloppyclockflag & CLK_FLAG4) ? "4" : "."));
/* Note effects of flags changing... */
if(debug) {
printf("arc: PRECISION = %d.\n", peer->precision);