1 /* $NetBSD: dcfd.c,v 1.3 2006/06/11 19:34:21 kardel Exp $ */
4 * /src/NTP/REPOSITORY/ntp4-dev/parseutil/dcfd.c,v 4.18 2005/10/07 22:08:18 kardel RELEASE_20051008_A
6 * dcfd.c,v 4.18 2005/10/07 22:08:18 kardel RELEASE_20051008_A
8 * DCF77 100/200ms pulse synchronisation daemon program (via 50Baud serial line)
12 * simple NTP loopfilter logic for local clock
13 * interactive display for debugging
16 * Leap second handling (at that level you should switch to NTP Version 4 - really!)
18 * Copyright (c) 1995-2005 by Frank Kardel <kardel <AT> ntp.org>
19 * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, Germany
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions
24 * 1. Redistributions of source code must retain the above copyright
25 * notice, this list of conditions and the following disclaimer.
26 * 2. Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in the
28 * documentation and/or other materials provided with the distribution.
29 * 3. Neither the name of the author nor the names of its contributors
30 * may be used to endorse or promote products derived from this software
31 * without specific prior written permission.
33 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
34 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
37 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 #include <sys/ioctl.h>
55 #include <sys/types.h>
62 * NTP compilation environment
64 #include "ntp_stdlib.h"
65 #include "ntpd.h" /* indirectly include ntp.h to get YEAR_PIVOT Y2KFixes */
68 * select which terminal handling to use (currently only SysV variants)
70 #if defined(HAVE_TERMIOS_H) || defined(STREAM)
72 #define TTY_GETATTR(_FD_, _ARG_) tcgetattr((_FD_), (_ARG_))
73 #define TTY_SETATTR(_FD_, _ARG_) tcsetattr((_FD_), TCSANOW, (_ARG_))
74 #else /* not HAVE_TERMIOS_H || STREAM */
75 # if defined(HAVE_TERMIO_H) || defined(HAVE_SYSV_TTYS)
77 # define TTY_GETATTR(_FD_, _ARG_) ioctl((_FD_), TCGETA, (_ARG_))
78 # define TTY_SETATTR(_FD_, _ARG_) ioctl((_FD_), TCSETAW, (_ARG_))
79 # endif/* HAVE_TERMIO_H || HAVE_SYSV_TTYS */
80 #endif /* not HAVE_TERMIOS_H || STREAM */
84 #include "Bletch: MUST DEFINE ONE OF 'HAVE_TERMIOS_H' or 'HAVE_TERMIO_H'"
88 #define days_per_year(_x_) (((_x_) % 4) ? 365 : (((_x_) % 400) ? 365 : 366))
91 #define timernormalize(_a_) \
92 if ((_a_)->tv_usec >= 1000000) \
94 (_a_)->tv_sec += (_a_)->tv_usec / 1000000; \
95 (_a_)->tv_usec = (_a_)->tv_usec % 1000000; \
97 if ((_a_)->tv_usec < 0) \
99 (_a_)->tv_sec -= 1 + (-(_a_)->tv_usec / 1000000); \
100 (_a_)->tv_usec = 999999 - (-(_a_)->tv_usec - 1); \
106 #define timeradd(_a_, _b_) \
107 (_a_)->tv_sec += (_b_)->tv_sec; \
108 (_a_)->tv_usec += (_b_)->tv_usec; \
109 timernormalize((_a_))
114 #define timersub(_a_, _b_) \
115 (_a_)->tv_sec -= (_b_)->tv_sec; \
116 (_a_)->tv_usec -= (_b_)->tv_usec; \
117 timernormalize((_a_))
122 #define PRINTF if (interactive) printf
123 #define LPRINTF if (interactive && loop_filter_debug) printf
126 #define dprintf(_x_) LPRINTF _x_
135 static char *revision
= "4.18";
138 * display received data (avoids also detaching from tty)
140 static int interactive
= 0;
143 * display loopfilter (clock control) variables
145 static int loop_filter_debug
= 0;
148 * do not set/adjust system time
150 static int no_set
= 0;
153 * time that passes between start of DCF impulse and time stamping (fine
154 * adjustment) in microseconds (receiver/OS dependent)
156 #define DEFAULT_DELAY 230000 /* rough estimate */
159 * The two states we can be in - eithe we receive nothing
160 * usable or we have the correct time
165 static int sync_state
= NO_SYNC
;
166 static time_t last_sync
;
168 static unsigned long ticks
= 0;
170 static char pat
[] = "-\\|/";
172 #define LINES (24-2) /* error lines after which the two headlines are repeated */
174 #define MAX_UNSYNC (10*60) /* allow synchronisation loss for 10 minutes */
175 #define NOTICE_INTERVAL (20*60) /* mention missing synchronisation every 20 minutes */
178 * clock adjustment PLL - see NTP protocol spec (RFC1305) for details
182 #define TIMECONSTANT 2
183 #define ADJINTERVAL 0
184 #define FREQ_WEIGHT 18
185 #define PHASE_WEIGHT 7
186 #define MAX_DRIFT 0x3FFFFFFF
188 #define R_SHIFT(_X_, _Y_) (((_X_) < 0) ? -(-(_X_) >> (_Y_)) : ((_X_) >> (_Y_)))
190 static struct timeval max_adj_offset
= { 0, 128000 };
192 static long clock_adjust
= 0; /* current adjustment value (usec * 2^USECSCALE) */
193 static long accum_drift
= 0; /* accumulated drift value (usec / ADJINTERVAL) */
194 static long adjustments
= 0;
195 static char skip_adjust
= 1; /* discard first adjustment (bad samples) */
200 #define DCFB_ANNOUNCE 0x0001 /* switch time zone warning (DST switch) */
201 #define DCFB_DST 0x0002 /* DST in effect */
202 #define DCFB_LEAP 0x0004 /* LEAP warning (1 hour prior to occurrence) */
203 #define DCFB_ALTERNATE 0x0008 /* alternate antenna used */
205 struct clocktime
/* clock time broken up from time code */
207 long wday
; /* Day of week: 1: Monday - 7: Sunday */
215 long utcoffset
; /* in minutes */
216 long flags
; /* current clock status (DCF77 state flags) */
219 typedef struct clocktime clocktime_t
;
222 * (usually) quick constant multiplications
224 #define TIMES10(_X_) (((_X_) << 3) + ((_X_) << 1)) /* *8 + *2 */
225 #define TIMES24(_X_) (((_X_) << 4) + ((_X_) << 3)) /* *16 + *8 */
226 #define TIMES60(_X_) ((((_X_) << 4) - (_X_)) << 2) /* *(16 - 1) *4 */
228 * generic l_abs() function
230 #define l_abs(_x_) (((_x_) < 0) ? -(_x_) : (_x_))
233 * conversion related return/error codes
235 #define CVT_MASK 0x0000000F /* conversion exit code */
236 #define CVT_NONE 0x00000001 /* format not applicable */
237 #define CVT_FAIL 0x00000002 /* conversion failed - error code returned */
238 #define CVT_OK 0x00000004 /* conversion succeeded */
239 #define CVT_BADFMT 0x00000010 /* general format error - (unparsable) */
240 #define CVT_BADDATE 0x00000020 /* invalid date */
241 #define CVT_BADTIME 0x00000040 /* invalid time */
244 * DCF77 raw time code
246 * From "Zur Zeit", Physikalisch-Technische Bundesanstalt (PTB), Braunschweig
247 * und Berlin, Maerz 1989
249 * Timecode transmission:
251 * time marks are send every second except for the second before the
253 * time marks consist of a reduction of transmitter power to 25%
254 * of the nominal level
255 * the falling edge is the time indication (on time)
256 * time marks of a 100ms duration constitute a logical 0
257 * time marks of a 200ms duration constitute a logical 1
259 * see the spec. (basically a (non-)inverted psuedo random phase shift)
263 * 0 - 10 AM: free, FM: 0
265 * 15 R - alternate antenna
266 * 16 A1 - expect zone change (1 hour before)
267 * 17 - 18 Z1,Z2 - time zone
270 * 1 0 MESZ (MED, MET DST)
272 * 19 A2 - expect leap insertion/deletion (1 hour before)
273 * 20 S - start of time code (1)
274 * 21 - 24 M1 - BCD (lsb first) Minutes
275 * 25 - 27 M10 - BCD (lsb first) 10 Minutes
276 * 28 P1 - Minute Parity (even)
277 * 29 - 32 H1 - BCD (lsb first) Hours
278 * 33 - 34 H10 - BCD (lsb first) 10 Hours
279 * 35 P2 - Hour Parity (even)
280 * 36 - 39 D1 - BCD (lsb first) Days
281 * 40 - 41 D10 - BCD (lsb first) 10 Days
282 * 42 - 44 DW - BCD (lsb first) day of week (1: Monday -> 7: Sunday)
283 * 45 - 49 MO - BCD (lsb first) Month
285 * 51 - 53 Y1 - BCD (lsb first) Years
286 * 54 - 57 Y10 - BCD (lsb first) 10 Years
287 * 58 P3 - Date Parity (even)
288 * 59 - usually missing (minute indication), except for leap insertion
291 /*-----------------------------------------------------------------------
292 * conversion table to map DCF77 bit stream into data fields.
294 * Each field of the DCF77 code is described with two adjacent entries in
295 * this table. The first entry specifies the offset into the DCF77 data stream
296 * while the length is given as the difference between the start index and
297 * the start index of the following field.
299 static struct rawdcfcode
301 char offset
; /* start bit */
304 { 0 }, { 15 }, { 16 }, { 17 }, { 19 }, { 20 }, { 21 }, { 25 }, { 28 }, { 29 },
305 { 33 }, { 35 }, { 36 }, { 40 }, { 42 }, { 45 }, { 49 }, { 50 }, { 54 }, { 58 }, { 59 }
308 /*-----------------------------------------------------------------------
309 * symbolic names for the fields of DCF77 describes in "rawdcfcode".
310 * see comment above for the structure of the DCF77 data
333 /*-----------------------------------------------------------------------
334 * parity field table (same encoding as rawdcfcode)
335 * This table describes the sections of the DCF77 code that are
340 char offset
; /* start bit of parity field */
343 { 21 }, { 29 }, { 36 }, { 59 }
346 /*-----------------------------------------------------------------------
347 * offsets for parity field descriptions
353 /*-----------------------------------------------------------------------
354 * legal values for time zone information
356 #define DCF_Z_MET 0x2
357 #define DCF_Z_MED 0x1
359 /*-----------------------------------------------------------------------
360 * symbolic representation if the DCF77 data stream
362 static struct dcfparam
364 unsigned char onebits
[60];
365 unsigned char zerobits
[60];
368 "###############RADMLS1248124P124812P1248121241248112481248P", /* 'ONE' representation */
369 "--------------------s-------p------p----------------------p" /* 'ZERO' representation */
372 /*-----------------------------------------------------------------------
373 * extract a bitfield from DCF77 datastream
374 * All numeric fields are LSB first.
375 * buf holds a pointer to a DCF77 data buffer in symbolic
377 * idx holds the index to the field description in rawdcfcode
381 register unsigned char *buf
,
385 register unsigned long sum
= 0;
386 register int i
, first
;
388 first
= rawdcfcode
[idx
].offset
;
390 for (i
= rawdcfcode
[idx
+1].offset
- 1; i
>= first
; i
--)
393 sum
|= (buf
[i
] != dcfparam
.zerobits
[i
]);
398 /*-----------------------------------------------------------------------
399 * check even parity integrity for a bitfield
401 * buf holds a pointer to a DCF77 data buffer in symbolic
403 * idx holds the index to the field description in partab
407 register unsigned char *buf
,
412 register unsigned psum
= 1;
414 last
= partab
[idx
+1].offset
;
416 for (i
= partab
[idx
].offset
; i
< last
; i
++)
417 psum
^= (buf
[i
] != dcfparam
.zerobits
[i
]);
422 /*-----------------------------------------------------------------------
423 * convert a DCF77 data buffer into wall clock time + flags
425 * buffer holds a pointer to a DCF77 data buffer in symbolic
427 * size describes the length of DCF77 information in bits (represented
428 * as chars in symbolic notation
429 * clock points to a wall clock time description of the DCF77 data (result)
433 unsigned char *buffer
,
435 clocktime_t
*clock_time
440 PRINTF("%-30s", "*** INCOMPLETE");
445 * check Start and Parity bits
447 if ((ext_bf(buffer
, DCF_S
) == 1) &&
448 pcheck(buffer
, DCF_P_P1
) &&
449 pcheck(buffer
, DCF_P_P2
) &&
450 pcheck(buffer
, DCF_P_P3
))
453 * buffer OK - extract all fields and build wall clock time from them
456 clock_time
->flags
= 0;
457 clock_time
->usecond
= 0;
458 clock_time
->second
= 0;
459 clock_time
->minute
= ext_bf(buffer
, DCF_M10
);
460 clock_time
->minute
= TIMES10(clock_time
->minute
) + ext_bf(buffer
, DCF_M1
);
461 clock_time
->hour
= ext_bf(buffer
, DCF_H10
);
462 clock_time
->hour
= TIMES10(clock_time
->hour
) + ext_bf(buffer
, DCF_H1
);
463 clock_time
->day
= ext_bf(buffer
, DCF_D10
);
464 clock_time
->day
= TIMES10(clock_time
->day
) + ext_bf(buffer
, DCF_D1
);
465 clock_time
->month
= ext_bf(buffer
, DCF_MO0
);
466 clock_time
->month
= TIMES10(clock_time
->month
) + ext_bf(buffer
, DCF_MO
);
467 clock_time
->year
= ext_bf(buffer
, DCF_Y10
);
468 clock_time
->year
= TIMES10(clock_time
->year
) + ext_bf(buffer
, DCF_Y1
);
469 clock_time
->wday
= ext_bf(buffer
, DCF_DW
);
472 * determine offset to UTC by examining the time zone
474 switch (ext_bf(buffer
, DCF_Z
))
477 clock_time
->utcoffset
= -60;
481 clock_time
->flags
|= DCFB_DST
;
482 clock_time
->utcoffset
= -120;
486 PRINTF("%-30s", "*** BAD TIME ZONE");
487 return CVT_FAIL
|CVT_BADFMT
;
491 * extract various warnings from DCF77
493 if (ext_bf(buffer
, DCF_A1
))
494 clock_time
->flags
|= DCFB_ANNOUNCE
;
496 if (ext_bf(buffer
, DCF_A2
))
497 clock_time
->flags
|= DCFB_LEAP
;
499 if (ext_bf(buffer
, DCF_R
))
500 clock_time
->flags
|= DCFB_ALTERNATE
;
507 * bad format - not for us
509 PRINTF("%-30s", "*** BAD FORMAT (invalid/parity)");
510 return CVT_FAIL
|CVT_BADFMT
;
514 /*-----------------------------------------------------------------------
515 * raw dcf input routine - fix up 50 baud
516 * characters for 1/0 decision
520 unsigned char *buffer
,
522 clocktime_t
*clock_time
525 register unsigned char *s
= buffer
;
526 register unsigned char *e
= buffer
+ size
;
527 register unsigned char *b
= dcfparam
.onebits
;
528 register unsigned char *c
= dcfparam
.zerobits
;
529 register unsigned rtc
= CVT_NONE
;
530 register unsigned int i
, lowmax
, highmax
, cutoff
, span
;
532 unsigned char histbuf
[BITS
];
534 * the input buffer contains characters with runs of consecutive
535 * bits set. These set bits are an indication of the DCF77 pulse
536 * length. We assume that we receive the pulse at 50 Baud. Thus
537 * a 100ms pulse would generate a 4 bit train (20ms per bit and
539 * a 200ms pulse would create all zeroes (and probably a frame error)
541 * The basic idea is that on corret reception we must have two
542 * maxima in the pulse length distribution histogram. (one for
543 * the zero representing pulses and one for the one representing
545 * There will always be ones in the datastream, thus we have to see
547 * The best point to cut for a 1/0 decision is the minimum between those
548 * between the maxima. The following code tries to find this cutoff point.
552 * clear histogram buffer
554 for (i
= 0; i
< BITS
; i
++)
563 * convert sequences of set bits into bits counts updating
564 * the histogram alongway
568 register unsigned int ch
= *s
^ 0xFF;
570 * check integrity and update histogramm
572 if (!((ch
+1) & ch
) || !*s
)
590 * invalid character (no consecutive bit sequence)
592 dprintf(("parse: cvt_rawdcf: character check for 0x%x@%d FAILED\n", *s
, s
- buffer
));
593 *s
= (unsigned char)~0;
594 rtc
= CVT_FAIL
|CVT_BADFMT
;
600 * first cutoff estimate (average bit count - must be between both
609 cutoff
= 4; /* doesn't really matter - it'll fail anyway, but gives error output */
612 dprintf(("parse: cvt_rawdcf: average bit count: %d\n", cutoff
));
614 lowmax
= 0; /* weighted sum */
615 highmax
= 0; /* bitcount */
618 * collect weighted sum of lower bits (left of initial guess)
620 dprintf(("parse: cvt_rawdcf: histogram:"));
621 for (i
= 0; i
<= cutoff
; i
++)
623 lowmax
+= histbuf
[i
] * i
;
624 highmax
+= histbuf
[i
];
625 dprintf((" %d", histbuf
[i
]));
632 lowmax
+= highmax
/ 2;
635 * calculate lower bit maximum (weighted sum / bit count)
637 * avoid divide by zero
648 highmax
= 0; /* weighted sum of upper bits counts */
649 cutoff
= 0; /* bitcount */
652 * collect weighted sum of lower bits (right of initial guess)
654 for (; i
< BITS
; i
++)
656 highmax
+=histbuf
[i
] * i
;
658 dprintf((" %d", histbuf
[i
]));
663 * determine upper maximum (weighted sum / bit count)
675 * following now holds:
676 * lowmax <= cutoff(initial guess) <= highmax
677 * best cutoff is the minimum nearest to higher bits
681 * find the minimum between lowmax and highmax (detecting
682 * possibly a minimum span)
684 span
= cutoff
= lowmax
;
685 for (i
= lowmax
; i
<= highmax
; i
++)
687 if (histbuf
[cutoff
] > histbuf
[i
])
690 * got a new minimum move beginning of minimum (cutoff) and
691 * end of minimum (span) there
696 if (histbuf
[cutoff
] == histbuf
[i
])
699 * minimum not better yet - but it spans more than
700 * one bit value - follow it
707 * cutoff point for 1/0 decision is the middle of the minimum section
710 cutoff
= (cutoff
+ span
) / 2;
712 dprintf(("parse: cvt_rawdcf: lower maximum %d, higher maximum %d, cutoff %d\n", lowmax
, highmax
, cutoff
));
715 * convert the bit counts to symbolic 1/0 information for data conversion
718 while ((s
< e
) && *c
&& *b
)
720 if (*s
== (unsigned char)~0)
730 * symbolic 1/0 representation
732 *s
= (*s
>= cutoff
) ? *b
: *c
;
740 * if everything went well so far return the result of the symbolic
741 * conversion routine else just the accumulated errors
745 PRINTF("%-30s", "*** BAD DATA");
748 return (rtc
== CVT_NONE
) ? convert_rawdcf(buffer
, size
, clock_time
) : rtc
;
751 /*-----------------------------------------------------------------------
752 * convert a wall clock time description of DCF77 to a Unix time (seconds
753 * since 1.1. 1970 UTC)
757 clocktime_t
*clock_time
,
761 #define SETRTC(_X_) { if (cvtrtc) *cvtrtc = (_X_); }
762 static int days_of_month
[] =
764 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
770 * map 2 digit years to 19xx (DCF77 is a 20th century item)
772 if ( clock_time
->year
< YEAR_PIVOT
) /* in case of Y2KFixes [ */
773 clock_time
->year
+= 100; /* *year%100, make tm_year */
774 /* *(do we need this?) */
775 if ( clock_time
->year
< YEAR_BREAK
) /* (failsafe if) */
776 clock_time
->year
+= 1900; /* Y2KFixes ] */
779 * must have been a really bad year code - drop it
781 if (clock_time
->year
< (YEAR_PIVOT
+ 1900) ) /* Y2KFixes */
783 SETRTC(CVT_FAIL
|CVT_BADDATE
);
787 * sorry, slow section here - but it's not time critical anyway
791 * calculate days since 1970 (watching leap years)
793 t
= julian0( clock_time
->year
) - julian0( 1970 );
796 if (clock_time
->month
<= 0 || clock_time
->month
> 12)
798 SETRTC(CVT_FAIL
|CVT_BADDATE
);
799 return -1; /* bad month */
801 /* adjust current leap year */
803 if (clock_time
->month
< 3 && days_per_year(clock_time
->year
) == 366)
808 * collect days from months excluding the current one
810 for (i
= 1; i
< clock_time
->month
; i
++)
812 t
+= days_of_month
[i
];
815 if (clock_time
->day
< 1 || ((clock_time
->month
== 2 && days_per_year(clock_time
->year
) == 366) ?
816 clock_time
->day
> 29 : clock_time
->day
> days_of_month
[clock_time
->month
]))
818 SETRTC(CVT_FAIL
|CVT_BADDATE
);
819 return -1; /* bad day */
823 * collect days from date excluding the current one
825 t
+= clock_time
->day
- 1;
828 if (clock_time
->hour
< 0 || clock_time
->hour
>= 24)
830 SETRTC(CVT_FAIL
|CVT_BADTIME
);
831 return -1; /* bad hour */
835 * calculate hours from 1. 1. 1970
837 t
= TIMES24(t
) + clock_time
->hour
;
840 if (clock_time
->minute
< 0 || clock_time
->minute
> 59)
842 SETRTC(CVT_FAIL
|CVT_BADTIME
);
843 return -1; /* bad min */
847 * calculate minutes from 1. 1. 1970
849 t
= TIMES60(t
) + clock_time
->minute
;
853 * calculate UTC in minutes
855 t
+= clock_time
->utcoffset
;
857 if (clock_time
->second
< 0 || clock_time
->second
> 60) /* allow for LEAPs */
859 SETRTC(CVT_FAIL
|CVT_BADTIME
);
860 return -1; /* bad sec */
864 * calculate UTC in seconds - phew !
866 t
= TIMES60(t
) + clock_time
->second
;
871 /*-----------------------------------------------------------------------
872 * cheap half baked 1/0 decision - for interactive operation only
883 /*-----------------------------------------------------------------------
884 * week day representation
886 static const char *wday
[8] =
898 /*-----------------------------------------------------------------------
899 * generate a string representation for a timeval
908 if (val
->tv_sec
== 0)
909 sprintf(buf
, "%c0.%06ld", (val
->tv_usec
< 0) ? '-' : '+', (long int)l_abs(val
->tv_usec
));
911 sprintf(buf
, "%ld.%06ld", (long int)val
->tv_sec
, (long int)l_abs(val
->tv_usec
));
915 /*-----------------------------------------------------------------------
916 * correct the current time by an offset by setting the time rigorously
920 struct timeval
*offset
923 struct timeval the_time
;
928 LPRINTF("set_time: %s ", pr_timeval(offset
));
929 syslog(LOG_NOTICE
, "setting time (offset %s)", pr_timeval(offset
));
931 if (gettimeofday(&the_time
, 0L) == -1)
933 perror("gettimeofday()");
937 timeradd(&the_time
, offset
);
938 if (settimeofday(&the_time
, 0L) == -1)
940 perror("settimeofday()");
945 /*-----------------------------------------------------------------------
946 * slew the time by a given offset
953 struct timeval time_offset
;
958 time_offset
.tv_sec
= offset
/ 1000000;
959 time_offset
.tv_usec
= offset
% 1000000;
961 LPRINTF("adj_time: %ld us ", (long int)offset
);
962 if (adjtime(&time_offset
, 0L) == -1)
966 /*-----------------------------------------------------------------------
967 * read in a possibly previously written drift value
971 const char *drift_file
976 df
= fopen(drift_file
, "r");
979 int idrift
= 0, fdrift
= 0;
981 fscanf(df
, "%4d.%03d", &idrift
, &fdrift
);
983 LPRINTF("read_drift: %d.%03d ppm ", idrift
, fdrift
);
985 accum_drift
= idrift
<< USECSCALE
;
986 fdrift
= (fdrift
<< USECSCALE
) / 1000;
987 accum_drift
+= fdrift
& (1<<USECSCALE
);
988 LPRINTF("read_drift: drift_comp %ld ", (long int)accum_drift
);
992 /*-----------------------------------------------------------------------
993 * write out the current drift value
997 const char *drift_file
,
1004 df
= fopen(drift_file
, "w");
1007 int idrift
= R_SHIFT(accum_drift
, USECSCALE
);
1008 int fdrift
= accum_drift
& ((1<<USECSCALE
)-1);
1010 LPRINTF("update_drift: drift_comp %ld ", (long int)accum_drift
);
1011 fdrift
= (fdrift
* 1000) / (1<<USECSCALE
);
1012 fprintf(df
, "%4d.%03d %c%ld.%06ld %.24s\n", idrift
, fdrift
,
1013 (offset
< 0) ? '-' : '+', (long int)(l_abs(offset
) / 1000000),
1014 (long int)(l_abs(offset
) % 1000000), asctime(localtime(&reftime
)));
1016 LPRINTF("update_drift: %d.%03d ppm ", idrift
, fdrift
);
1020 /*-----------------------------------------------------------------------
1021 * process adjustments derived from the DCF77 observation
1022 * (controls clock PLL)
1026 struct timeval
*offset
,
1027 const char *drift_file
,
1031 struct timeval toffset
;
1032 register long usecoffset
;
1045 toffset
.tv_sec
= l_abs(toffset
.tv_sec
);
1046 toffset
.tv_usec
= l_abs(toffset
.tv_usec
);
1047 if (timercmp(&toffset
, &max_adj_offset
, >))
1050 * hopeless - set the clock - and clear the timing
1058 usecoffset
= offset
->tv_sec
* 1000000 + offset
->tv_usec
;
1060 clock_adjust
= R_SHIFT(usecoffset
, TIMECONSTANT
); /* adjustment to make for next period */
1063 while (adjustments
> (1 << tmp
))
1066 if (tmp
> FREQ_WEIGHT
)
1069 accum_drift
+= R_SHIFT(usecoffset
<< USECSCALE
, TIMECONSTANT
+TIMECONSTANT
+FREQ_WEIGHT
-tmp
);
1071 if (accum_drift
> MAX_DRIFT
) /* clamp into interval */
1072 accum_drift
= MAX_DRIFT
;
1074 if (accum_drift
< -MAX_DRIFT
)
1075 accum_drift
= -MAX_DRIFT
;
1077 update_drift(drift_file
, usecoffset
, reftime
);
1078 LPRINTF("clock_adjust: %s, clock_adjust %ld, drift_comp %ld(%ld) ",
1079 pr_timeval(offset
),(long int) R_SHIFT(clock_adjust
, USECSCALE
),
1080 (long int)R_SHIFT(accum_drift
, USECSCALE
), (long int)accum_drift
);
1083 /*-----------------------------------------------------------------------
1084 * adjust the clock by a small mount to simulate frequency correction
1091 register long adjustment
;
1095 adjustment
= R_SHIFT(clock_adjust
, PHASE_WEIGHT
);
1097 clock_adjust
-= adjustment
;
1099 adjustment
+= R_SHIFT(accum_drift
, USECSCALE
+ADJINTERVAL
);
1101 adj_time(adjustment
);
1104 /*-----------------------------------------------------------------------
1105 * control synchronisation status (warnings) and do periodic adjusts
1106 * (frequency control simulation)
1113 static unsigned long last_notice
= 0;
1115 #if !defined(HAVE_SIGACTION) && !defined(HAVE_SIGVEC)
1116 (void)signal(SIGALRM
, tick
);
1121 ticks
+= 1<<ADJINTERVAL
;
1123 if ((ticks
- last_sync
) > MAX_UNSYNC
)
1126 * not getting time for a while
1128 if (sync_state
== SYNC
)
1131 * completely lost information
1133 sync_state
= NO_SYNC
;
1134 syslog(LOG_INFO
, "DCF77 reception lost (timeout)");
1135 last_notice
= ticks
;
1139 * in NO_SYNC state - look whether its time to speak up again
1141 if ((ticks
- last_notice
) > NOTICE_INTERVAL
)
1143 syslog(LOG_NOTICE
, "still not synchronized to DCF77 - check receiver/signal");
1144 last_notice
= ticks
;
1149 (void) alarm(1<<ADJINTERVAL
);
1153 /*-----------------------------------------------------------------------
1154 * break association from terminal to avoid catching terminal
1155 * or process group related signals (-> daemon operation)
1164 # else /* not HAVE_DAEMON */
1172 #if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
1173 max_fd
= sysconf(_SC_OPEN_MAX
);
1174 #else /* HAVE_SYSCONF && _SC_OPEN_MAX */
1175 max_fd
= getdtablesize();
1176 #endif /* HAVE_SYSCONF && _SC_OPEN_MAX */
1177 for (s
= 0; s
< max_fd
; s
++)
1178 (void) close((int)s
);
1179 (void) open("/", 0);
1187 proc2_$
who_am_i(&puid
);
1188 proc2_$
make_server(&puid
, &st
);
1190 #endif /* SYS_DOMAINOS */
1191 #if defined(HAVE_SETPGID) || defined(HAVE_SETSID)
1193 if (setsid() == (pid_t
)-1)
1194 syslog(LOG_ERR
, "dcfd: setsid(): %m");
1196 if (setpgid(0, 0) == -1)
1197 syslog(LOG_ERR
, "dcfd: setpgid(): %m");
1199 #else /* HAVE_SETPGID || HAVE_SETSID */
1203 fid
= open("/dev/tty", 2);
1206 (void) ioctl(fid
, (u_long
) TIOCNOTTY
, (char *) 0);
1209 # ifdef HAVE_SETPGRP_0
1211 # else /* HAVE_SETPGRP_0 */
1212 (void) setpgrp(0, getpid());
1213 # endif /* HAVE_SETPGRP_0 */
1215 #endif /* HAVE_SETPGID || HAVE_SETSID */
1217 #endif /* not HAVE_DAEMON */
1220 /*-----------------------------------------------------------------------
1221 * list possible arguments and options
1228 fprintf(stderr
, "usage: %s [-n] [-f] [-l] [-t] [-i] [-o] [-d <drift_file>] [-D <input delay>] <device>\n", program
);
1229 fprintf(stderr
, "\t-n do not change time\n");
1230 fprintf(stderr
, "\t-i interactive\n");
1231 fprintf(stderr
, "\t-t trace (print all datagrams)\n");
1232 fprintf(stderr
, "\t-f print all databits (includes PTB private data)\n");
1233 fprintf(stderr
, "\t-l print loop filter debug information\n");
1234 fprintf(stderr
, "\t-o print offet average for current minute\n");
1235 fprintf(stderr
, "\t-Y make internal Y2K checks then exit\n"); /* Y2KFixes */
1236 fprintf(stderr
, "\t-d <drift_file> specify alternate drift file\n");
1237 fprintf(stderr
, "\t-D <input delay>specify delay from input edge to processing in micro seconds\n");
1240 /*-----------------------------------------------------------------------
1241 * check_y2k() - internal check of Y2K logic
1242 * (a lot of this logic lifted from ../ntpd/check_y2k.c)
1247 int year
; /* current working year */
1248 int year0
= 1900; /* sarting year for NTP time */
1249 int yearend
; /* ending year we test for NTP time.
1250 * 32-bit systems: through 2036, the
1251 **year in which NTP time overflows.
1252 * 64-bit systems: a reasonable upper
1253 **limit (well, maybe somewhat beyond
1254 **reasonable, but well before the
1255 **max time, by which time the earth
1258 struct tm LocalTime
;
1260 int Fatals
, Warnings
;
1261 #define Error(year) if ( (year)>=2036 && LocalTime.tm_year < 110 ) \
1262 Warnings++; else Fatals++
1264 Fatals
= Warnings
= 0;
1266 Time
= time( (time_t *)NULL
);
1267 LocalTime
= *localtime( &Time
);
1269 year
= ( sizeof( u_long
) > 4 ) /* save max span using year as temp */
1270 ? ( 400 * 3 ) /* three greater gregorian cycles */
1271 : ((int)(0x7FFFFFFF / 365.242 / 24/60/60)* 2 ); /*32-bit limit*/
1272 /* NOTE: will automacially expand test years on
1273 * 64 bit machines.... this may cause some of the
1274 * existing ntp logic to fail for years beyond
1275 * 2036 (the current 32-bit limit). If all checks
1276 * fail ONLY beyond year 2036 you may ignore such
1277 * errors, at least for a decade or so. */
1278 yearend
= year0
+ year
;
1280 year
= 1900+YEAR_PIVOT
;
1281 printf( " starting year %04d\n", (int) year
);
1282 printf( " ending year %04d\n", (int) yearend
);
1284 for ( ; year
< yearend
; year
++ )
1295 ct
.hour
= ct
.minute
= ct
.second
= ct
.usecond
= 0;
1300 Observed
= dcf_to_unixtime( &ct
, &Flag
);
1301 /* seems to be a clone of parse_to_unixtime() with
1302 * *a minor difference to arg2 type */
1303 if ( ct
.year
!= year
)
1306 "%04d: dcf_to_unixtime(,%d) CORRUPTED ct.year: was %d\n",
1307 (int)year
, (int)Flag
, (int)ct
.year
);
1311 t
= julian0(year
) - julian0(1970); /* Julian day from 1970 */
1312 Expected
= t
* 24 * 60 * 60;
1313 if ( Observed
!= Expected
|| Flag
)
1314 { /* time difference */
1316 "%04d: dcf_to_unixtime(,%d) FAILURE: was=%lu s/b=%lu (%ld)\n",
1318 (unsigned long)Observed
, (unsigned long)Expected
,
1319 ((long)Observed
- (long)Expected
) );
1324 if ( year
>= YEAR_PIVOT
+1900 )
1326 /* check year % 100 code we put into dcf_to_unixtime() */
1327 ct
.year
= year
% 100;
1330 Observed
= dcf_to_unixtime( &ct
, &Flag
);
1332 if ( Observed
!= Expected
|| Flag
)
1333 { /* time difference */
1335 "%04d: dcf_to_unixtime(%d,%d) FAILURE: was=%lu s/b=%lu (%ld)\n",
1336 year
, (int)ct
.year
, (int)Flag
,
1337 (unsigned long)Observed
, (unsigned long)Expected
,
1338 ((long)Observed
- (long)Expected
) );
1343 /* check year - 1900 code we put into dcf_to_unixtime() */
1344 ct
.year
= year
- 1900;
1347 Observed
= dcf_to_unixtime( &ct
, &Flag
);
1349 if ( Observed
!= Expected
|| Flag
) { /* time difference */
1351 "%04d: dcf_to_unixtime(%d,%d) FAILURE: was=%lu s/b=%lu (%ld)\n",
1352 year
, (int)ct
.year
, (int)Flag
,
1353 (unsigned long)Observed
, (unsigned long)Expected
,
1354 ((long)Observed
- (long)Expected
) );
1366 /*--------------------------------------------------
1367 * rawdcf_init - set up modem lines for RAWDCF receivers
1369 #if defined(TIOCMSET) && (defined(TIOCM_DTR) || defined(CIOCM_DTR))
1376 * You can use the RS232 to supply the power for a DCF77 receiver.
1377 * Here a voltage between the DTR and the RTS line is used. Unfortunately
1378 * the name has changed from CIOCM_DTR to TIOCM_DTR recently.
1382 int sl232
= TIOCM_DTR
; /* turn on DTR for power supply */
1384 int sl232
= CIOCM_DTR
; /* turn on DTR for power supply */
1387 if (ioctl(fd
, TIOCMSET
, (caddr_t
)&sl232
) == -1)
1389 syslog(LOG_NOTICE
, "rawdcf_init: WARNING: ioctl(fd, TIOCMSET, [C|T]IOCM_DTR): %m");
1398 syslog(LOG_NOTICE
, "rawdcf_init: WARNING: OS interface incapable of setting DTR to power DCF modules");
1400 #endif /* DTR initialisation type */
1402 /*-----------------------------------------------------------------------
1403 * main loop - argument interpreter / setup / main loop
1415 const char *drift_file
= "/etc/dcfd.drift";
1419 int delay
= DEFAULT_DELAY
; /* average delay from input edge to time stamping */
1430 while ((c
= *++arg
))
1444 loop_filter_debug
= 1;
1470 fprintf(stderr
, "%s: -D requires integer argument\n", argv
[0]);
1483 fprintf(stderr
, "%s: -d requires file name argument\n", argv
[0]);
1490 exit( errs
? 1 : 0 );
1493 fprintf(stderr
, "%s: unknown option -%c\n", argv
[0], c
);
1502 fprintf(stderr
, "%s: device specified twice\n", argv
[0]);
1515 fprintf(stderr
, "%s: device not specified\n", argv
[0]);
1523 * get access to DCF77 tty port
1525 fd
= open(file
, O_RDONLY
);
1534 struct timeval t
, tt
, tlast
;
1535 struct timeval timeout
;
1536 struct timeval phase
;
1537 struct timeval time_offset
;
1538 char pbuf
[61]; /* printable version */
1539 char buf
[61]; /* raw data */
1540 clocktime_t clock_time
; /* wall clock time */
1541 time_t utc_time
= 0;
1542 time_t last_utc_time
= 0;
1545 #if defined(HAVE_TERMIOS_H) || defined(STREAM)
1546 struct termios term
;
1547 #else /* not HAVE_TERMIOS_H || STREAM */
1548 # if defined(HAVE_TERMIO_H) || defined(HAVE_SYSV_TTYS)
1550 # endif/* HAVE_TERMIO_H || HAVE_SYSV_TTYS */
1551 #endif /* not HAVE_TERMIOS_H || STREAM */
1552 unsigned int rtc
= CVT_NONE
;
1557 timeout
.tv_usec
= 500000;
1560 phase
.tv_usec
= delay
;
1563 * setup TTY (50 Baud, Read, 8Bit, No Hangup, 1 character IO)
1565 if (TTY_GETATTR(fd
, &term
) == -1)
1567 perror("tcgetattr");
1571 memset(term
.c_cc
, 0, sizeof(term
.c_cc
));
1572 term
.c_cc
[VMIN
] = 1;
1573 #ifdef NO_PARENB_IGNPAR
1574 term
.c_cflag
= CS8
|CREAD
|CLOCAL
;
1576 term
.c_cflag
= CS8
|CREAD
|CLOCAL
|PARENB
;
1578 term
.c_iflag
= IGNPAR
;
1582 cfsetispeed(&term
, B50
);
1583 cfsetospeed(&term
, B50
);
1585 if (TTY_SETATTR(fd
, &term
) == -1)
1587 perror("tcsetattr");
1592 * lose terminal if in daemon operation
1598 * get syslog() initialized
1601 openlog("dcfd", LOG_PID
, LOG_DAEMON
);
1603 openlog("dcfd", LOG_PID
);
1607 * setup periodic operations (state control / frequency control)
1609 #ifdef HAVE_SIGACTION
1611 struct sigaction act
;
1613 # ifdef HAVE_SA_SIGACTION_IN_STRUCT_SIGACTION
1614 act
.sa_sigaction
= (void (*) P((int, siginfo_t
*, void *)))0;
1615 # endif /* HAVE_SA_SIGACTION_IN_STRUCT_SIGACTION */
1616 act
.sa_handler
= tick
;
1617 sigemptyset(&act
.sa_mask
);
1620 if (sigaction(SIGALRM
, &act
, (struct sigaction
*)0) == -1)
1622 syslog(LOG_ERR
, "sigaction(SIGALRM): %m");
1631 vec
.sv_handler
= tick
;
1635 if (sigvec(SIGALRM
, &vec
, (struct sigvec
*)0) == -1)
1637 syslog(LOG_ERR
, "sigvec(SIGALRM): %m");
1642 (void) signal(SIGALRM
, tick
);
1648 struct itimerval it
;
1650 it
.it_interval
.tv_sec
= 1<<ADJINTERVAL
;
1651 it
.it_interval
.tv_usec
= 0;
1652 it
.it_value
.tv_sec
= 1<<ADJINTERVAL
;
1653 it
.it_value
.tv_usec
= 0;
1655 if (setitimer(ITIMER_REAL
, &it
, (struct itimerval
*)0) == -1)
1657 syslog(LOG_ERR
, "setitimer: %m");
1662 (void) alarm(1<<ADJINTERVAL
);
1665 PRINTF(" DCF77 monitor %s - Copyright (C) 1993-2005 by Frank Kardel\n\n", revision
);
1668 for ( i
= 0; i
< 60; i
++)
1671 read_drift(drift_file
);
1674 * what time is it now (for interval measurement)
1676 gettimeofday(&tlast
, 0L);
1679 * loop until input trouble ...
1686 while ((rrc
= read(fd
, &c
, 1)) == 1)
1688 gettimeofday(&t
, 0L);
1690 timersub(&t
, &tlast
);
1694 PRINTF(" %s", &"PTB private....RADMLSMin....PHour..PMDay..DayMonthYear....P\n"[offset
]);
1695 PRINTF(" %s", &"---------------RADMLS1248124P124812P1248121241248112481248P\n"[offset
]);
1700 * timeout -> possible minute mark -> interpretation
1702 if (timercmp(&t
, &timeout
, >))
1704 PRINTF("%c %.*s ", pat
[i
% (sizeof(pat
)-1)], 59 - offset
, &pbuf
[offset
]);
1706 if ((rtc
= cvt_rawdcf((unsigned char *)buf
, i
, &clock_time
)) != CVT_OK
)
1709 * this data was bad - well - forget synchronisation for now
1712 if (sync_state
== SYNC
)
1714 sync_state
= NO_SYNC
;
1715 syslog(LOG_INFO
, "DCF77 reception lost (bad data)");
1722 PRINTF("\r %.*s ", 59 - offset
, &buf
[offset
]);
1729 * collect first character
1731 if (((c
^0xFF)+1) & (c
^0xFF))
1734 pbuf
[0] = type(c
) ? '#' : '-';
1736 for ( i
= 1; i
< 60; i
++)
1749 * initial guess (usually correct)
1751 if (((c
^0xFF)+1) & (c
^0xFF))
1754 pbuf
[i
] = type(c
) ? '#' : '-';
1756 PRINTF("%c %.*s ", pat
[i
% (sizeof(pat
)-1)], 59 - offset
, &pbuf
[offset
]);
1759 if (i
== 0 && rtc
== CVT_OK
)
1762 * we got a good time code here - try to convert it to
1765 if ((utc_time
= dcf_to_unixtime(&clock_time
, &rtc
)) == -1)
1767 PRINTF("*** BAD CONVERSION\n");
1770 if (utc_time
!= (last_utc_time
+ 60))
1773 * well, two successive sucessful telegrams are not 60 seconds
1776 PRINTF("*** NO MINUTE INC\n");
1777 if (sync_state
== SYNC
)
1779 sync_state
= NO_SYNC
;
1780 syslog(LOG_INFO
, "DCF77 reception lost (data mismatch)");
1783 rtc
= CVT_FAIL
|CVT_BADTIME
|CVT_BADDATE
;
1788 last_utc_time
= utc_time
;
1796 * valid time code - determine offset and
1797 * note regained reception
1800 if (sync_state
== NO_SYNC
)
1802 syslog(LOG_INFO
, "receiving DCF77");
1807 * we had at least one minute SYNC - thus
1808 * last error is valid
1810 time_offset
.tv_sec
= lasterror
/ 1000000;
1811 time_offset
.tv_usec
= lasterror
% 1000000;
1812 adjust_clock(&time_offset
, drift_file
, utc_time
);
1817 time_offset
.tv_sec
= utc_time
+ i
;
1818 time_offset
.tv_usec
= 0;
1820 timeradd(&time_offset
, &phase
);
1822 usecerror
+= (time_offset
.tv_sec
- tt
.tv_sec
) * 1000000 + time_offset
.tv_usec
1826 * output interpreted DCF77 data
1828 PRINTF(offsets
? "%s, %2ld:%02ld:%02d, %ld.%02ld.%02ld, <%s%s%s%s> (%c%ld.%06lds)" :
1829 "%s, %2ld:%02ld:%02d, %ld.%02ld.%02ld, <%s%s%s%s>",
1830 wday
[clock_time
.wday
],
1831 clock_time
.hour
, clock_time
.minute
, i
, clock_time
.day
, clock_time
.month
,
1833 (clock_time
.flags
& DCFB_ALTERNATE
) ? "R" : "_",
1834 (clock_time
.flags
& DCFB_ANNOUNCE
) ? "A" : "_",
1835 (clock_time
.flags
& DCFB_DST
) ? "D" : "_",
1836 (clock_time
.flags
& DCFB_LEAP
) ? "L" : "_",
1837 (lasterror
< 0) ? '-' : '+', l_abs(lasterror
) / 1000000, l_abs(lasterror
) % 1000000
1840 if (trace
&& (i
== 0))
1845 lasterror
= usecerror
/ (i
+1);
1849 lasterror
= 0; /* we cannot calculate phase errors on bad reception */
1864 } while ((rrc
== -1) && (errno
== EINTR
));
1867 * lost IO - sorry guys
1869 syslog(LOG_ERR
, "TERMINATING - cannot read from device %s (%m)", file
);
1883 * Revision 4.18 2005/10/07 22:08:18 kardel
1884 * make dcfd.c compile on NetBSD 3.99.9 again (configure/sigvec compatibility fix)
1886 * Revision 4.17.2.1 2005/10/03 19:15:16 kardel
1887 * work around configure not detecting a missing sigvec compatibility
1888 * interface on NetBSD 3.99.9 and above
1890 * Revision 4.17 2005/08/10 10:09:44 kardel
1891 * output revision information
1893 * Revision 4.16 2005/08/10 06:33:25 kardel
1896 * Revision 4.15 2005/08/10 06:28:45 kardel
1897 * fix setting of baud rate
1899 * Revision 4.14 2005/04/16 17:32:10 kardel
1902 * Revision 4.13 2004/11/14 15:29:41 kardel
1903 * support PPSAPI, upgrade Copyright to Berkeley style