diff options
author | roberto <roberto@FreeBSD.org> | 2000-01-28 14:55:50 +0000 |
---|---|---|
committer | roberto <roberto@FreeBSD.org> | 2000-01-28 14:55:50 +0000 |
commit | b5b40f9e420899251189775800d9f74092925299 (patch) | |
tree | 98efdf1b74d6ecb7828bb502a0350116eeb2fd3c /contrib/ntp/ntpd | |
parent | ef64b99e8412f2273dd2e8b3291c2f78ffc4667f (diff) | |
download | FreeBSD-src-b5b40f9e420899251189775800d9f74092925299.zip FreeBSD-src-b5b40f9e420899251189775800d9f74092925299.tar.gz |
Virgin import of ntpd 4.0.99b
Diffstat (limited to 'contrib/ntp/ntpd')
27 files changed, 4950 insertions, 1667 deletions
diff --git a/contrib/ntp/ntpd/Makefile.am b/contrib/ntp/ntpd/Makefile.am index 9926684..2fd16c4 100644 --- a/contrib/ntp/ntpd/Makefile.am +++ b/contrib/ntp/ntpd/Makefile.am @@ -15,22 +15,19 @@ EXTRA_PROGRAMS = check_y2k check-local: @MAKE_CHECK_Y2K@ [ -z "@MAKE_CHECK_Y2K@" ] || ./@MAKE_CHECK_Y2K@ -ntpd_SOURCES = map_vme.c ntp_config.c ntp_control.c ntp_io.c \ - ntp_loopfilter.c ntp_monitor.c ntp_peer.c ntp_proto.c \ - ntp_refclock.c ntp_request.c ntp_restrict.c ntp_timer.c \ - ntp_util.c ntp_intres.c ntp_filegen.c ntpd.c \ - refclock_conf.c refclock_chu.c refclock_local.c \ - refclock_pst.c refclock_wwvb.c refclock_mx4200.c \ - refclock_parse.c refclock_as2201.c refclock_bancomm.c \ - refclock_tpro.c refclock_leitch.c refclock_irig.c \ - refclock_msfees.c refclock_trak.c refclock_datum.c \ - refclock_acts.c refclock_heath.c refclock_nmea.c \ - refclock_atom.c refclock_ptbacts.c refclock_jupiter.c \ - refclock_usno.c refclock_true.c refclock_hpgps.c \ - refclock_shm.c refclock_gpsvme.c refclock_arbiter.c \ - refclock_arc.c refclock_palisade.c refclock_palisade.h \ - refclock_oncore.c refclock_chronolog.c refclock_dumbclock.c \ - refclock_ulink.c jupiter.h +ntpd_SOURCES = jupiter.h map_vme.c ntp_config.c ntp_control.c ntp_filegen.c \ + ntp_intres.c ntp_io.c ntp_loopfilter.c ntp_monitor.c ntp_peer.c \ + ntp_proto.c ntp_refclock.c ntp_request.c ntp_restrict.c ntp_timer.c \ + ntp_util.c ntpd.c refclock_acts.c refclock_arbiter.c refclock_arc.c \ + refclock_as2201.c refclock_atom.c refclock_bancomm.c \ + refclock_chronolog.c refclock_chu.c refclock_conf.c refclock_datum.c \ + refclock_dumbclock.c refclock_fg.c refclock_gpsvme.c refclock_heath.c \ + refclock_hpgps.c refclock_irig.c refclock_jupiter.c refclock_leitch.c \ + refclock_local.c refclock_msfees.c refclock_mx4200.c refclock_nmea.c \ + refclock_oncore.c refclock_palisade.c refclock_palisade.h \ + refclock_parse.c refclock_pcf.c refclock_pst.c refclock_ptbacts.c \ + refclock_shm.c refclock_tpro.c refclock_trak.c refclock_true.c \ + refclock_ulink.c refclock_usno.c refclock_wwv.c refclock_wwvb.c $(PROGRAMS): $(LDADD) diff --git a/contrib/ntp/ntpd/Makefile.in b/contrib/ntp/ntpd/Makefile.in index ac5e591..d12a343 100644 --- a/contrib/ntp/ntpd/Makefile.in +++ b/contrib/ntp/ntpd/Makefile.in @@ -63,15 +63,18 @@ host_alias = @host_alias@ host_triplet = @host@ target_alias = @target_alias@ target_triplet = @target@ +AMDEP = @AMDEP@ AMTAR = @AMTAR@ -AMTARFLAGS = @AMTARFLAGS@ AWK = @AWK@ CC = @CC@ CFLAGS = @CFLAGS@ CHUTEST = @CHUTEST@ CLKTEST = @CLKTEST@ CPP = @CPP@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ DCFD = @DCFD@ +DEPDIR = @DEPDIR@ LDFLAGS = @LDFLAGS@ LIBPARSE = @LIBPARSE@ LIBRSAREF = @LIBRSAREF@ @@ -93,6 +96,7 @@ RSAREF = @RSAREF@ TESTDCF = @TESTDCF@ U = @U@ VERSION = @VERSION@ +install_sh = @install_sh@ #AUTOMAKE_OPTIONS = ../util/ansi2knr no-dependencies @@ -110,22 +114,19 @@ ETAGS_ARGS = Makefile.am check_PROGRAMS = @MAKE_CHECK_Y2K@ EXTRA_PROGRAMS = check_y2k -ntpd_SOURCES = map_vme.c ntp_config.c ntp_control.c ntp_io.c \ - ntp_loopfilter.c ntp_monitor.c ntp_peer.c ntp_proto.c \ - ntp_refclock.c ntp_request.c ntp_restrict.c ntp_timer.c \ - ntp_util.c ntp_intres.c ntp_filegen.c ntpd.c \ - refclock_conf.c refclock_chu.c refclock_local.c \ - refclock_pst.c refclock_wwvb.c refclock_mx4200.c \ - refclock_parse.c refclock_as2201.c refclock_bancomm.c \ - refclock_tpro.c refclock_leitch.c refclock_irig.c \ - refclock_msfees.c refclock_trak.c refclock_datum.c \ - refclock_acts.c refclock_heath.c refclock_nmea.c \ - refclock_atom.c refclock_ptbacts.c refclock_jupiter.c \ - refclock_usno.c refclock_true.c refclock_hpgps.c \ - refclock_shm.c refclock_gpsvme.c refclock_arbiter.c \ - refclock_arc.c refclock_palisade.c refclock_palisade.h \ - refclock_oncore.c refclock_chronolog.c refclock_dumbclock.c \ - refclock_ulink.c jupiter.h +ntpd_SOURCES = jupiter.h map_vme.c ntp_config.c ntp_control.c ntp_filegen.c \ + ntp_intres.c ntp_io.c ntp_loopfilter.c ntp_monitor.c ntp_peer.c \ + ntp_proto.c ntp_refclock.c ntp_request.c ntp_restrict.c ntp_timer.c \ + ntp_util.c ntpd.c refclock_acts.c refclock_arbiter.c refclock_arc.c \ + refclock_as2201.c refclock_atom.c refclock_bancomm.c \ + refclock_chronolog.c refclock_chu.c refclock_conf.c refclock_datum.c \ + refclock_dumbclock.c refclock_fg.c refclock_gpsvme.c refclock_heath.c \ + refclock_hpgps.c refclock_irig.c refclock_jupiter.c refclock_leitch.c \ + refclock_local.c refclock_msfees.c refclock_mx4200.c refclock_nmea.c \ + refclock_oncore.c refclock_palisade.c refclock_palisade.h \ + refclock_parse.c refclock_pcf.c refclock_pst.c refclock_ptbacts.c \ + refclock_shm.c refclock_tpro.c refclock_trak.c refclock_true.c \ + refclock_ulink.c refclock_usno.c refclock_wwv.c refclock_wwvb.c subdir = ntpd mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs @@ -143,21 +144,22 @@ check_y2k_OBJECTS = check_y2k$U.o check_y2k_LDADD = $(LDADD) check_y2k_DEPENDENCIES = version.o ../libntp/libntp.a check_y2k_LDFLAGS = -am_ntpd_OBJECTS = map_vme$U.o ntp_config$U.o ntp_control$U.o ntp_io$U.o \ -ntp_loopfilter$U.o ntp_monitor$U.o ntp_peer$U.o ntp_proto$U.o \ -ntp_refclock$U.o ntp_request$U.o ntp_restrict$U.o ntp_timer$U.o \ -ntp_util$U.o ntp_intres$U.o ntp_filegen$U.o ntpd$U.o refclock_conf$U.o \ -refclock_chu$U.o refclock_local$U.o refclock_pst$U.o refclock_wwvb$U.o \ -refclock_mx4200$U.o refclock_parse$U.o refclock_as2201$U.o \ -refclock_bancomm$U.o refclock_tpro$U.o refclock_leitch$U.o \ -refclock_irig$U.o refclock_msfees$U.o refclock_trak$U.o \ -refclock_datum$U.o refclock_acts$U.o refclock_heath$U.o \ -refclock_nmea$U.o refclock_atom$U.o refclock_ptbacts$U.o \ -refclock_jupiter$U.o refclock_usno$U.o refclock_true$U.o \ -refclock_hpgps$U.o refclock_shm$U.o refclock_gpsvme$U.o \ -refclock_arbiter$U.o refclock_arc$U.o refclock_palisade$U.o \ -refclock_oncore$U.o refclock_chronolog$U.o refclock_dumbclock$U.o \ -refclock_ulink$U.o +am_ntpd_OBJECTS = map_vme$U.o ntp_config$U.o ntp_control$U.o \ +ntp_filegen$U.o ntp_intres$U.o ntp_io$U.o ntp_loopfilter$U.o \ +ntp_monitor$U.o ntp_peer$U.o ntp_proto$U.o ntp_refclock$U.o \ +ntp_request$U.o ntp_restrict$U.o ntp_timer$U.o ntp_util$U.o ntpd$U.o \ +refclock_acts$U.o refclock_arbiter$U.o refclock_arc$U.o \ +refclock_as2201$U.o refclock_atom$U.o refclock_bancomm$U.o \ +refclock_chronolog$U.o refclock_chu$U.o refclock_conf$U.o \ +refclock_datum$U.o refclock_dumbclock$U.o refclock_fg$U.o \ +refclock_gpsvme$U.o refclock_heath$U.o refclock_hpgps$U.o \ +refclock_irig$U.o refclock_jupiter$U.o refclock_leitch$U.o \ +refclock_local$U.o refclock_msfees$U.o refclock_mx4200$U.o \ +refclock_nmea$U.o refclock_oncore$U.o refclock_palisade$U.o \ +refclock_parse$U.o refclock_pcf$U.o refclock_pst$U.o \ +refclock_ptbacts$U.o refclock_shm$U.o refclock_tpro$U.o \ +refclock_trak$U.o refclock_true$U.o refclock_ulink$U.o \ +refclock_usno$U.o refclock_wwv$U.o refclock_wwvb$U.o ntpd_OBJECTS = $(am_ntpd_OBJECTS) ntpd_DEPENDENCIES = version.o ../libntp/libntp.a ntpd_LDFLAGS = @@ -171,16 +173,43 @@ DIST_COMMON = Makefile.am Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) GZIP_ENV = --best +depcomp = $(SHELL) $(top_srcdir)/depcomp +DEP_FILES = @AMDEP@ $(DEPDIR)/check_y2k$U.Po $(DEPDIR)/map_vme$U.Po \ +$(DEPDIR)/ntp_config$U.Po $(DEPDIR)/ntp_control$U.Po \ +$(DEPDIR)/ntp_filegen$U.Po $(DEPDIR)/ntp_intres$U.Po \ +$(DEPDIR)/ntp_io$U.Po $(DEPDIR)/ntp_loopfilter$U.Po \ +$(DEPDIR)/ntp_monitor$U.Po $(DEPDIR)/ntp_peer$U.Po \ +$(DEPDIR)/ntp_proto$U.Po $(DEPDIR)/ntp_refclock$U.Po \ +$(DEPDIR)/ntp_request$U.Po $(DEPDIR)/ntp_restrict$U.Po \ +$(DEPDIR)/ntp_timer$U.Po $(DEPDIR)/ntp_util$U.Po $(DEPDIR)/ntpd$U.Po \ +$(DEPDIR)/refclock_acts$U.Po $(DEPDIR)/refclock_arbiter$U.Po \ +$(DEPDIR)/refclock_arc$U.Po $(DEPDIR)/refclock_as2201$U.Po \ +$(DEPDIR)/refclock_atom$U.Po $(DEPDIR)/refclock_bancomm$U.Po \ +$(DEPDIR)/refclock_chronolog$U.Po $(DEPDIR)/refclock_chu$U.Po \ +$(DEPDIR)/refclock_conf$U.Po $(DEPDIR)/refclock_datum$U.Po \ +$(DEPDIR)/refclock_dumbclock$U.Po $(DEPDIR)/refclock_fg$U.Po \ +$(DEPDIR)/refclock_gpsvme$U.Po $(DEPDIR)/refclock_heath$U.Po \ +$(DEPDIR)/refclock_hpgps$U.Po $(DEPDIR)/refclock_irig$U.Po \ +$(DEPDIR)/refclock_jupiter$U.Po $(DEPDIR)/refclock_leitch$U.Po \ +$(DEPDIR)/refclock_local$U.Po $(DEPDIR)/refclock_msfees$U.Po \ +$(DEPDIR)/refclock_mx4200$U.Po $(DEPDIR)/refclock_nmea$U.Po \ +$(DEPDIR)/refclock_oncore$U.Po $(DEPDIR)/refclock_palisade$U.Po \ +$(DEPDIR)/refclock_parse$U.Po $(DEPDIR)/refclock_pcf$U.Po \ +$(DEPDIR)/refclock_pst$U.Po $(DEPDIR)/refclock_ptbacts$U.Po \ +$(DEPDIR)/refclock_shm$U.Po $(DEPDIR)/refclock_tpro$U.Po \ +$(DEPDIR)/refclock_trak$U.Po $(DEPDIR)/refclock_true$U.Po \ +$(DEPDIR)/refclock_ulink$U.Po $(DEPDIR)/refclock_usno$U.Po \ +$(DEPDIR)/refclock_wwv$U.Po $(DEPDIR)/refclock_wwvb$U.Po SOURCES = check_y2k.c $(ntpd_SOURCES) OBJECTS = check_y2k$U.o $(am_ntpd_OBJECTS) all: all-redirect .SUFFIXES: -.SUFFIXES: .c .o +.SUFFIXES: .c .h .o $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) - cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps ntpd/Makefile + cd $(top_srcdir) && $(AUTOMAKE) --gnu ntpd/Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) cd $(top_builddir) \ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status @@ -222,9 +251,6 @@ distclean-checkPROGRAMS: maintainer-clean-checkPROGRAMS: -.c.o: - $(COMPILE) -c $< - mostlyclean-compile: -rm -f *.o core *.core @@ -249,60 +275,10 @@ clean-kr: distclean-kr: maintainer-clean-kr: -check_y2k$U.o: check_y2k: $(check_y2k_OBJECTS) $(check_y2k_DEPENDENCIES) @rm -f check_y2k $(LINK) $(check_y2k_LDFLAGS) $(check_y2k_OBJECTS) $(check_y2k_LDADD) $(LIBS) -map_vme$U.o: -ntp_config$U.o: -ntp_control$U.o: -ntp_io$U.o: -ntp_loopfilter$U.o: -ntp_monitor$U.o: -ntp_peer$U.o: -ntp_proto$U.o: -ntp_refclock$U.o: -ntp_request$U.o: -ntp_restrict$U.o: -ntp_timer$U.o: -ntp_util$U.o: -ntp_intres$U.o: -ntp_filegen$U.o: -ntpd$U.o: -refclock_conf$U.o: -refclock_chu$U.o: -refclock_local$U.o: -refclock_pst$U.o: -refclock_wwvb$U.o: -refclock_mx4200$U.o: -refclock_parse$U.o: -refclock_as2201$U.o: -refclock_bancomm$U.o: -refclock_tpro$U.o: -refclock_leitch$U.o: -refclock_irig$U.o: -refclock_msfees$U.o: -refclock_trak$U.o: -refclock_datum$U.o: -refclock_acts$U.o: -refclock_heath$U.o: -refclock_nmea$U.o: -refclock_atom$U.o: -refclock_ptbacts$U.o: -refclock_jupiter$U.o: -refclock_usno$U.o: -refclock_true$U.o: -refclock_hpgps$U.o: -refclock_shm$U.o: -refclock_gpsvme$U.o: -refclock_arbiter$U.o: -refclock_arc$U.o: -refclock_palisade$U.o: -refclock_oncore$U.o: -refclock_chronolog$U.o: -refclock_dumbclock$U.o: -refclock_ulink$U.o: ntpd: $(ntpd_OBJECTS) $(ntpd_DEPENDENCIES) @rm -f ntpd @@ -363,6 +339,8 @@ refclock_datum_.c: refclock_datum.c $(ANSI2KNR) $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_datum.c; then echo $(srcdir)/refclock_datum.c; else echo refclock_datum.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > refclock_datum_.c refclock_dumbclock_.c: refclock_dumbclock.c $(ANSI2KNR) $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_dumbclock.c; then echo $(srcdir)/refclock_dumbclock.c; else echo refclock_dumbclock.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > refclock_dumbclock_.c +refclock_fg_.c: refclock_fg.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_fg.c; then echo $(srcdir)/refclock_fg.c; else echo refclock_fg.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > refclock_fg_.c refclock_gpsvme_.c: refclock_gpsvme.c $(ANSI2KNR) $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_gpsvme.c; then echo $(srcdir)/refclock_gpsvme.c; else echo refclock_gpsvme.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > refclock_gpsvme_.c refclock_heath_.c: refclock_heath.c $(ANSI2KNR) @@ -389,6 +367,8 @@ refclock_palisade_.c: refclock_palisade.c $(ANSI2KNR) $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_palisade.c; then echo $(srcdir)/refclock_palisade.c; else echo refclock_palisade.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > refclock_palisade_.c refclock_parse_.c: refclock_parse.c $(ANSI2KNR) $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_parse.c; then echo $(srcdir)/refclock_parse.c; else echo refclock_parse.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > refclock_parse_.c +refclock_pcf_.c: refclock_pcf.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_pcf.c; then echo $(srcdir)/refclock_pcf.c; else echo refclock_pcf.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > refclock_pcf_.c refclock_pst_.c: refclock_pst.c $(ANSI2KNR) $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_pst.c; then echo $(srcdir)/refclock_pst.c; else echo refclock_pst.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > refclock_pst_.c refclock_ptbacts_.c: refclock_ptbacts.c $(ANSI2KNR) @@ -405,6 +385,8 @@ refclock_ulink_.c: refclock_ulink.c $(ANSI2KNR) $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_ulink.c; then echo $(srcdir)/refclock_ulink.c; else echo refclock_ulink.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > refclock_ulink_.c refclock_usno_.c: refclock_usno.c $(ANSI2KNR) $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_usno.c; then echo $(srcdir)/refclock_usno.c; else echo refclock_usno.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > refclock_usno_.c +refclock_wwv_.c: refclock_wwv.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_wwv.c; then echo $(srcdir)/refclock_wwv.c; else echo refclock_wwv.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > refclock_wwv_.c refclock_wwvb_.c: refclock_wwvb.c $(ANSI2KNR) $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_wwvb.c; then echo $(srcdir)/refclock_wwvb.c; else echo refclock_wwvb.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > refclock_wwvb_.c check_y2k_.o map_vme_.o ntp_config_.o ntp_control_.o ntp_filegen_.o \ @@ -413,34 +395,38 @@ ntp_proto_.o ntp_refclock_.o ntp_request_.o ntp_restrict_.o \ ntp_timer_.o ntp_util_.o ntpd_.o refclock_acts_.o refclock_arbiter_.o \ refclock_arc_.o refclock_as2201_.o refclock_atom_.o refclock_bancomm_.o \ refclock_chronolog_.o refclock_chu_.o refclock_conf_.o \ -refclock_datum_.o refclock_dumbclock_.o refclock_gpsvme_.o \ -refclock_heath_.o refclock_hpgps_.o refclock_irig_.o \ +refclock_datum_.o refclock_dumbclock_.o refclock_fg_.o \ +refclock_gpsvme_.o refclock_heath_.o refclock_hpgps_.o refclock_irig_.o \ refclock_jupiter_.o refclock_leitch_.o refclock_local_.o \ refclock_msfees_.o refclock_mx4200_.o refclock_nmea_.o \ refclock_oncore_.o refclock_palisade_.o refclock_parse_.o \ -refclock_pst_.o refclock_ptbacts_.o refclock_shm_.o refclock_tpro_.o \ -refclock_trak_.o refclock_true_.o refclock_ulink_.o refclock_usno_.o \ -refclock_wwvb_.o : $(ANSI2KNR) +refclock_pcf_.o refclock_pst_.o refclock_ptbacts_.o refclock_shm_.o \ +refclock_tpro_.o refclock_trak_.o refclock_true_.o refclock_ulink_.o \ +refclock_usno_.o refclock_wwv_.o refclock_wwvb_.o : $(ANSI2KNR) tags: TAGS -ID: $(HEADERS) $(SOURCES) $(LISP) - list='$(SOURCES) $(HEADERS)'; \ - unique=`for i in $$list; do echo $$i; done | \ - ${AWK:-awk} ' { files[$$0] = 1; } \ +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ - here=`pwd` && cd $(srcdir) \ - && mkid -f$$here/ID $$unique $(LISP) + mkid -f$$here/ID $$unique $(LISP) -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ - list='$(SOURCES) $(HEADERS)'; \ - unique=`for i in $$list; do echo $$i; done | \ - ${AWK:-awk} ' { files[$$0] = 1; } \ + list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ - || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + || etags $(ETAGS_ARGS) $$tags $$unique $(LISP) mostlyclean-tags: @@ -457,356 +443,84 @@ distdir: $(DISTFILES) @for file in $(DISTFILES); do \ d=$(srcdir); \ if test -d $$d/$$file; then \ - cp -pr $$d/$$file $(distdir)/$$file; \ + cp -pR $$d/$$file $(distdir); \ else \ test -f $(distdir)/$$file \ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ || cp -p $$d/$$file $(distdir)/$$file || :; \ fi; \ done -check_y2k.o: check_y2k.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_malloc.h \ - ../include/ntp_refclock.h ../include/recvbuff.h \ - ../include/ntp_calendar.h ../include/parse.h \ - ../include/parse_conf.h -map_vme.o: map_vme.c ../config.h -ntp_config.o: ntp_config.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_unixtime.h ../include/ntp_filegen.h \ - ../include/ntp_stdlib.h ../include/ntp_string.h \ - ../include/l_stdlib.h -ntp_control.o: ntp_control.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_control.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h -ntp_filegen.o: ntp_filegen.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_string.h ../include/ntp_calendar.h \ - ../include/ntp_filegen.h ../include/ntp_stdlib.h \ - ../include/l_stdlib.h -ntp_intres.o: ntp_intres.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_request.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h -ntp_io.o: ntp_io.c ../config.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h ../include/iosignal.h \ - ../include/ntp_if.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h -ntp_loopfilter.o: ntp_loopfilter.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_unixtime.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h \ - ../include/ntp_syscall.h -ntp_monitor.o: ntp_monitor.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h ../include/ntp_if.h \ - ../include/ntp_stdlib.h ../include/ntp_string.h \ - ../include/l_stdlib.h -ntp_peer.o: ntp_peer.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h -ntp_proto.o: ntp_proto.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h \ - ../include/ntp_unixtime.h ../include/ntp_control.h -ntp_refclock.o: ntp_refclock.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_unixtime.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h -ntp_request.o: ntp_request.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_request.h ../include/ntp_control.h \ - ../include/ntp_if.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h \ - ../include/ntp_syscall.h -ntp_restrict.o: ntp_restrict.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_if.h \ - ../include/ntp_stdlib.h ../include/ntp_string.h \ - ../include/l_stdlib.h -ntp_timer.o: ntp_timer.c ../config.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h -ntp_util.o: ntp_util.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_unixtime.h ../include/ntp_filegen.h \ - ../include/ntp_if.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h -ntpd.o: ntpd.c ../config.h ../include/ntpd.h ../include/ntp_syslog.h \ - ../include/ntp_fp.h ../include/ntp_types.h \ - ../include/ntp_machine.h ../include/ntp_proto.h \ - ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_stdlib.h ../include/ntp_string.h \ - ../include/l_stdlib.h -refclock_acts.o: refclock_acts.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_unixtime.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h \ - ../include/ntp_control.h -refclock_arbiter.o: refclock_arbiter.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_stdlib.h ../include/ntp_string.h \ - ../include/l_stdlib.h -refclock_arc.o: refclock_arc.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_stdlib.h ../include/ntp_string.h \ - ../include/l_stdlib.h -refclock_as2201.o: refclock_as2201.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_unixtime.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h -refclock_atom.o: refclock_atom.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_unixtime.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h -refclock_bancomm.o: refclock_bancomm.c ../config.h -refclock_chronolog.o: refclock_chronolog.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_calendar.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h -refclock_chu.o: refclock_chu.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_calendar.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h -refclock_conf.o: refclock_conf.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h -refclock_datum.o: refclock_datum.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_unixtime.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h -refclock_dumbclock.o: refclock_dumbclock.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_calendar.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h -refclock_gpsvme.o: refclock_gpsvme.c ../config.h -refclock_heath.o: refclock_heath.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_stdlib.h ../include/ntp_string.h \ - ../include/l_stdlib.h -refclock_hpgps.o: refclock_hpgps.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_stdlib.h ../include/ntp_string.h \ - ../include/l_stdlib.h -refclock_irig.o: refclock_irig.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_calendar.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h -refclock_jupiter.o: refclock_jupiter.c ../config.h -refclock_leitch.o: refclock_leitch.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_unixtime.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h -refclock_local.o: refclock_local.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h \ - ../include/ntp_syscall.h -refclock_msfees.o: refclock_msfees.c ../config.h -refclock_mx4200.o: refclock_mx4200.c ../config.h -refclock_nmea.o: refclock_nmea.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_stdlib.h ../include/ntp_string.h \ - ../include/l_stdlib.h -refclock_oncore.o: refclock_oncore.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_unixtime.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h -refclock_palisade.o: refclock_palisade.c ../config.h refclock_palisade.h \ - ../include/ntpd.h ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_control.h ../include/ntp_unixtime.h \ - ../include/ntp_stdlib.h ../include/ntp_string.h \ - ../include/l_stdlib.h -refclock_parse.o: refclock_parse.c ../config.h -refclock_pst.o: refclock_pst.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_stdlib.h ../include/ntp_string.h \ - ../include/l_stdlib.h -refclock_ptbacts.o: refclock_ptbacts.c ../config.h refclock_acts.c \ - ../include/ntpd.h ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_unixtime.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h \ - ../include/ntp_control.h -refclock_shm.o: refclock_shm.c ../config.h -refclock_tpro.o: refclock_tpro.c ../config.h -refclock_trak.o: refclock_trak.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_stdlib.h ../include/ntp_string.h \ - ../include/l_stdlib.h ../include/ntp_unixtime.h -refclock_true.o: refclock_true.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_unixtime.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h -refclock_ulink.o: refclock_ulink.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_calendar.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h -refclock_usno.o: refclock_usno.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_unixtime.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h \ - ../include/ntp_control.h -refclock_wwvb.o: refclock_wwvb.c ../config.h ../include/ntpd.h \ - ../include/ntp_syslog.h ../include/ntp_fp.h \ - ../include/ntp_types.h ../include/ntp_machine.h \ - ../include/ntp_proto.h ../include/ntp.h ../include/ntp_select.h \ - ../include/ntp_malloc.h ../include/ntp_refclock.h \ - ../include/recvbuff.h ../include/ntp_io.h \ - ../include/ntp_calendar.h ../include/ntp_stdlib.h \ - ../include/ntp_string.h ../include/l_stdlib.h + +@AMDEP@include $(DEPDIR)/check_y2k$U.Po +@AMDEP@include $(DEPDIR)/map_vme$U.Po +@AMDEP@include $(DEPDIR)/ntp_config$U.Po +@AMDEP@include $(DEPDIR)/ntp_control$U.Po +@AMDEP@include $(DEPDIR)/ntp_filegen$U.Po +@AMDEP@include $(DEPDIR)/ntp_intres$U.Po +@AMDEP@include $(DEPDIR)/ntp_io$U.Po +@AMDEP@include $(DEPDIR)/ntp_loopfilter$U.Po +@AMDEP@include $(DEPDIR)/ntp_monitor$U.Po +@AMDEP@include $(DEPDIR)/ntp_peer$U.Po +@AMDEP@include $(DEPDIR)/ntp_proto$U.Po +@AMDEP@include $(DEPDIR)/ntp_refclock$U.Po +@AMDEP@include $(DEPDIR)/ntp_request$U.Po +@AMDEP@include $(DEPDIR)/ntp_restrict$U.Po +@AMDEP@include $(DEPDIR)/ntp_timer$U.Po +@AMDEP@include $(DEPDIR)/ntp_util$U.Po +@AMDEP@include $(DEPDIR)/ntpd$U.Po +@AMDEP@include $(DEPDIR)/refclock_acts$U.Po +@AMDEP@include $(DEPDIR)/refclock_arbiter$U.Po +@AMDEP@include $(DEPDIR)/refclock_arc$U.Po +@AMDEP@include $(DEPDIR)/refclock_as2201$U.Po +@AMDEP@include $(DEPDIR)/refclock_atom$U.Po +@AMDEP@include $(DEPDIR)/refclock_bancomm$U.Po +@AMDEP@include $(DEPDIR)/refclock_chronolog$U.Po +@AMDEP@include $(DEPDIR)/refclock_chu$U.Po +@AMDEP@include $(DEPDIR)/refclock_conf$U.Po +@AMDEP@include $(DEPDIR)/refclock_datum$U.Po +@AMDEP@include $(DEPDIR)/refclock_dumbclock$U.Po +@AMDEP@include $(DEPDIR)/refclock_fg$U.Po +@AMDEP@include $(DEPDIR)/refclock_gpsvme$U.Po +@AMDEP@include $(DEPDIR)/refclock_heath$U.Po +@AMDEP@include $(DEPDIR)/refclock_hpgps$U.Po +@AMDEP@include $(DEPDIR)/refclock_irig$U.Po +@AMDEP@include $(DEPDIR)/refclock_jupiter$U.Po +@AMDEP@include $(DEPDIR)/refclock_leitch$U.Po +@AMDEP@include $(DEPDIR)/refclock_local$U.Po +@AMDEP@include $(DEPDIR)/refclock_msfees$U.Po +@AMDEP@include $(DEPDIR)/refclock_mx4200$U.Po +@AMDEP@include $(DEPDIR)/refclock_nmea$U.Po +@AMDEP@include $(DEPDIR)/refclock_oncore$U.Po +@AMDEP@include $(DEPDIR)/refclock_palisade$U.Po +@AMDEP@include $(DEPDIR)/refclock_parse$U.Po +@AMDEP@include $(DEPDIR)/refclock_pcf$U.Po +@AMDEP@include $(DEPDIR)/refclock_pst$U.Po +@AMDEP@include $(DEPDIR)/refclock_ptbacts$U.Po +@AMDEP@include $(DEPDIR)/refclock_shm$U.Po +@AMDEP@include $(DEPDIR)/refclock_tpro$U.Po +@AMDEP@include $(DEPDIR)/refclock_trak$U.Po +@AMDEP@include $(DEPDIR)/refclock_true$U.Po +@AMDEP@include $(DEPDIR)/refclock_ulink$U.Po +@AMDEP@include $(DEPDIR)/refclock_usno$U.Po +@AMDEP@include $(DEPDIR)/refclock_wwv$U.Po +@AMDEP@include $(DEPDIR)/refclock_wwvb$U.Po + +mostlyclean-depend: + +clean-depend: + +distclean-depend: + -rm -rf $(DEPDIR) + +maintainer-clean-depend: + +@AMDEP@CCDEPMODE = @CCDEPMODE@ + +.c.o: +@AMDEP@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(COMPILE) -c -o $@ $< info-am: info: info-am @@ -847,27 +561,29 @@ distclean-generic: -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: + -rm -f Makefile.in mostlyclean-am: mostlyclean-binPROGRAMS mostlyclean-checkPROGRAMS \ mostlyclean-compile mostlyclean-kr mostlyclean-tags \ - mostlyclean-generic + mostlyclean-depend mostlyclean-generic mostlyclean: mostlyclean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-compile clean-kr \ - clean-tags clean-generic mostlyclean-am + clean-tags clean-depend clean-generic mostlyclean-am clean: clean-am distclean-am: distclean-binPROGRAMS distclean-checkPROGRAMS \ distclean-compile distclean-kr distclean-tags \ - distclean-generic clean-am + distclean-depend distclean-generic clean-am distclean: distclean-am maintainer-clean-am: maintainer-clean-binPROGRAMS \ maintainer-clean-checkPROGRAMS maintainer-clean-compile \ maintainer-clean-kr maintainer-clean-tags \ - maintainer-clean-generic distclean-am + maintainer-clean-depend maintainer-clean-generic \ + distclean-am @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." @@ -879,10 +595,11 @@ mostlyclean-checkPROGRAMS distclean-checkPROGRAMS clean-checkPROGRAMS \ maintainer-clean-checkPROGRAMS mostlyclean-compile distclean-compile \ clean-compile maintainer-clean-compile mostlyclean-kr distclean-kr \ clean-kr maintainer-clean-kr tags mostlyclean-tags distclean-tags \ -clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi \ -check-local check check-am installcheck-am installcheck install-exec-am \ -install-exec install-data-am install-data install-am install \ -uninstall-am uninstall all-redirect all-am all install-strip \ +clean-tags maintainer-clean-tags distdir mostlyclean-depend \ +distclean-depend clean-depend maintainer-clean-depend info-am info \ +dvi-am dvi check-local check check-am installcheck-am installcheck \ +install-exec-am install-exec install-data-am install-data install-am \ +install uninstall-am uninstall all-redirect all-am all install-strip \ installdirs mostlyclean-generic distclean-generic clean-generic \ maintainer-clean-generic clean mostlyclean distclean maintainer-clean diff --git a/contrib/ntp/ntpd/map_vme.c b/contrib/ntp/ntpd/map_vme.c index 3c161cc..e4569ce 100644 --- a/contrib/ntp/ntpd/map_vme.c +++ b/contrib/ntp/ntpd/map_vme.c @@ -74,7 +74,7 @@ map_vme ( } if(tx.error) printf("io_testr failed internal error %d\n",tx.error); - if(tx.access_result <= 0) { + if(tx.access_result < 0) { printf("io_testr failed\n"); exit(2); } diff --git a/contrib/ntp/ntpd/ntp_control.c b/contrib/ntp/ntpd/ntp_control.c index e63765f..e2fb039 100644 --- a/contrib/ntp/ntpd/ntp_control.c +++ b/contrib/ntp/ntpd/ntp_control.c @@ -341,6 +341,9 @@ static u_char clocktypes[] = { CTL_SST_TS_LF, /* REFCLK_CHRONOLOG (32) */ CTL_SST_TS_LF, /* REFCLK_DUMBCLOCK (32) */ CTL_SST_TS_LF, /* REFCLK_ULINK (33) */ + CTL_SST_TS_LF, /* REFCLK_PCF (35) */ + CTL_SST_TS_LF, /* REFCLK_WWW (36) */ + CTL_SST_TS_LF, /* REFCLK_FG (37) */ }; diff --git a/contrib/ntp/ntpd/ntp_intres.c b/contrib/ntp/ntpd/ntp_intres.c index 1829914..e9a387e 100644 --- a/contrib/ntp/ntpd/ntp_intres.c +++ b/contrib/ntp/ntpd/ntp_intres.c @@ -152,7 +152,7 @@ ntp_intres(void) #endif /* NTP_POSIX_SOURCE */ #ifdef DEBUG - if (debug) { + if (debug > 1) { msyslog(LOG_INFO, "NTP_INTRES running"); } #endif diff --git a/contrib/ntp/ntpd/ntp_io.c b/contrib/ntp/ntpd/ntp_io.c index e920249..6ab7d26 100644 --- a/contrib/ntp/ntpd/ntp_io.c +++ b/contrib/ntp/ntpd/ntp_io.c @@ -19,6 +19,12 @@ #ifdef HAVE_NETINET_IN_H # include <netinet/in.h> #endif +#ifdef HAVE_NETINET_IN_SYSTM_H +# include <netinet/in_systm.h> +#else /* Some old linux systems at least have in_system.h instead. */ +# include <netinet/in_system.h> +#endif /* HAVE_NETINET_IN_SYSTM_H */ +#include <netinet/ip.h> #ifdef HAVE_SYS_IOCTL_H # include <sys/ioctl.h> #endif @@ -880,7 +886,7 @@ open_socket( int turn_off_reuse ) { - int fd; + int fd, tos; int on = 1, off = 0; /* create a datagram (UDP) socket */ @@ -905,6 +911,15 @@ open_socket( msyslog(LOG_ERR, "setsockopt SO_REUSEADDR on fails: %m"); } +#if defined(IPTOS_LOWDELAY) && defined(IPPROTO_IP) && defined(IP_TOS) + /* set IP_TOS to minimize packet delay */ + tos = IPTOS_LOWDELAY; + if (setsockopt(fd, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(tos)) < 0) + { + msyslog(LOG_ERR, "setsockopt IPTOS_LOWDELAY on fails: %m"); + } +#endif /* IPTOS_LOWDELAY && IPPROTO_IP && IP_TOS */ + /* * bind the local address. */ @@ -1326,11 +1341,7 @@ input_handler( { char buf[RX_BUFF_SIZE]; -#ifndef SYS_WINNT (void) read(fd, buf, sizeof buf); -#else - (void) ReadFile((HANDLE)fd, buf, (DWORD)sizeof buf, NULL, NULL); -#endif /* SYS_WINNT */ packets_dropped++; goto select_again; } @@ -1340,14 +1351,8 @@ input_handler( i = (rp->datalen == 0 || rp->datalen > sizeof(rb->recv_space)) ? sizeof(rb->recv_space) : rp->datalen; -#ifndef SYS_WINNT rb->recv_length = - read(fd, (char *)&rb->recv_space, (unsigned)i) -#else /* SYS_WINNT */ - ReadFile((HANDLE)fd, (char *)&rb->recv_space, (DWORD)i, - (LPDWORD)&(rb->recv_length), NULL) -#endif /* SYS_WINNT */ - ; + read(fd, (char *)&rb->recv_space, (unsigned)i); if (rb->recv_length == -1) { @@ -1546,35 +1551,20 @@ input_handler( } else if (n == -1) { -#ifndef SYS_WINNT int err = errno; -#else - DWORD err = WSAGetLastError(); -#endif /* SYS_WINNT */ /* * extended FAU debugging output */ msyslog(LOG_ERR, "select(%d, %s, 0L, 0L, &0.000000) error: %m", maxactivefd+1, fdbits(maxactivefd, &activefds)); - if ( -#ifndef SYS_WINNT - (err == EBADF) -#else - (err == WSAEBADF) -#endif /* SYS_WINNT */ - ) - { + if (err == EBADF) { int j, b; fds = activefds; for (j = 0; j <= maxactivefd; j++) if ( -#ifndef SYS_WINNT (FD_ISSET(j, &fds) && (read(j, &b, 0) == -1)) -#else - (FD_ISSET(j, &fds) && (!ReadFile((HANDLE)j, &b, 0, NULL, NULL))) -#endif /* SYS_WINNT */ ) msyslog(LOG_ERR, "Bad file descriptor %d", j); } diff --git a/contrib/ntp/ntpd/ntp_loopfilter.c b/contrib/ntp/ntpd/ntp_loopfilter.c index 6e0e134..15b625d 100644 --- a/contrib/ntp/ntpd/ntp_loopfilter.c +++ b/contrib/ntp/ntpd/ntp_loopfilter.c @@ -194,7 +194,7 @@ local_clock( #ifndef SYS_WINNT if (fabs(fp_offset) >= clock_panic && !correct_any) { msyslog(LOG_ERR, - "time error %.0f over %d seconds; set clock manually)", + "time error %.0f over %d seconds; set clock manually", fp_offset, (int)clock_panic); return (-1); } @@ -286,7 +286,7 @@ local_clock( * reset or shaken, but never stirred. */ default: - if (allow_set_backward) { + if (allow_set_backward | correct_any) { step_systime(fp_offset); NLOG(NLOG_SYNCEVENT|NLOG_SYSEVENT) msyslog(LOG_NOTICE, "time reset %.6f s", @@ -299,7 +299,6 @@ local_clock( fp_offset); rstclock(S_FREQ); last_offset = clock_offset = fp_offset; - return (0); } break; } @@ -355,7 +354,8 @@ local_clock( ULOGTOD(sys_poll + 1)) { #ifdef DEBUG if (debug) - printf("local_clock: popcorn %.6f %.6f\n", + printf( + "local_clock: popcorn %.6f %.6f\n", fp_offset, last_offset); #endif last_offset = fp_offset; @@ -364,14 +364,17 @@ local_clock( /* * Compute the FLL and PLL frequency adjustments - * conditioned on two weighting factors, one - * which limits the time constant determined - * from the Allan intercept, the other which - * limits the gain factor as a function of - * update interval. The net effect is to favor - * the PLL adjustments at the smaller update - * intervals and the FLL adjustments at the - * larger ones. + * conditioned on intricate weighting factors. + * For the FLL, the averaging interval is + * clamped not to decrease below the Allan + * intercept and the gain is decreased from + * unity for mu above CLOCK_MINSEC (1024 s) to + * zero below CLOCK_MINSEC (256 s). For the PLL, + * the averaging interval is clamped not to + * exceed the sustem poll interval. These + * measures insure stability of the clock + * discipline even when the rules of fair + * engagement are broken. */ dtemp = max(mu, allan_xpt); etemp = min(max(0, mu - CLOCK_MINSEC) / @@ -379,7 +382,8 @@ local_clock( flladj = fp_offset * etemp / (dtemp * CLOCK_AVG); dtemp = ULOGTOD(SHIFT_PLL + 2 + sys_poll); - plladj = fp_offset * mu / (dtemp * dtemp); + etemp = min(mu, ULOGTOD(sys_poll)); + plladj = fp_offset * etemp / (dtemp * dtemp); clock_offset = fp_offset; break; } @@ -664,6 +668,7 @@ rstclock( int trans /* new state */ ) { + correct_any = FALSE; state = trans; switch (state) { diff --git a/contrib/ntp/ntpd/ntp_proto.c b/contrib/ntp/ntpd/ntp_proto.c index 6d54291..a24c0e3 100644 --- a/contrib/ntp/ntpd/ntp_proto.c +++ b/contrib/ntp/ntpd/ntp_proto.c @@ -70,6 +70,7 @@ static double clock_combine P((struct peer **, int)); static void peer_xmit P((struct peer *)); static void fast_xmit P((struct recvbuf *, int, u_long)); static void clock_update P((void)); +int default_get_precision P((void)); #ifdef MD5 static void make_keylist P((struct peer *)); #endif /* MD5 */ @@ -100,8 +101,8 @@ transmit( peer->valid++; if (oreach & 0x80) peer->valid--; - if (!(peer->flags & FLAG_CONFIG) && - peer->valid > NTP_SHIFT / 2 && (peer->reach & 0x80) && + if (!(peer->flags & FLAG_CONFIG) && peer->valid > + NTP_SHIFT / 2 && (peer->reach & 0x80) && peer->status < CTL_PST_SEL_SYNCCAND) peer->reach = 0; peer->reach <<= 1; @@ -259,8 +260,8 @@ receive( if (PKT_MODE(pkt->li_vn_mode) == MODE_PRIVATE) { if (restrict_mask & RES_NOQUERY) return; - process_private(rbufp, ((restrict_mask & RES_NOMODIFY) == - 0)); + process_private(rbufp, ((restrict_mask & + RES_NOMODIFY) == 0)); return; } if (PKT_MODE(pkt->li_vn_mode) == MODE_CONTROL) { @@ -289,17 +290,18 @@ receive( /* * If we are not a broadcast client, ignore broadcast packets. */ - if ((PKT_MODE(pkt->li_vn_mode) == MODE_BROADCAST && !sys_bclient)) + if ((PKT_MODE(pkt->li_vn_mode) == MODE_BROADCAST && + !sys_bclient)) return; /* * This is really awful ugly. We figure out whether an extension * field is present and then measure the MAC size. If the number * of words following the packet header is less than or equal to - * 5, no extension field is present and these words constitute the - * MAC. If the number of words is greater than 5, an extension - * field is present and the first word contains the length of - * the extension field and the MAC follows that. + * 5, no extension field is present and these words constitute + * the MAC. If the number of words is greater than 5, an + * extension field is present and the first word contains the + * length of the extension field and the MAC follows that. */ has_mac = 0; /* pkeyid = 0; */ @@ -321,7 +323,8 @@ receive( * MAC itself. */ /* pkeyid = (u_long)ntohl(pkt->keyid2) & 0xffffffff; */ - skeyid = tkeyid = (u_long)ntohl(pkt->keyid3) & 0xffffffff; + skeyid = tkeyid = (u_long)ntohl(pkt->keyid3) & + 0xffffffff; } /* @@ -364,11 +367,12 @@ receive( /* * For multicast mode, generate the session key - * and install in the key cache. For client mode, - * generate the session key for the unicast - * address. For server mode, the session key should - * already be in the key cache, since it was - * generated when the last request was sent. + * and install in the key cache. For client + * mode, generate the session key for the + * unicast address. For server mode, the session + * key should already be in the key cache, since + * it was generated when the last request was + * sent. */ if (hismode == MODE_BROADCAST) { tkeyid = session_key( @@ -389,7 +393,8 @@ receive( * Compute the cryptosum. Note a clogging attack may * succceed in bloating the key cache. */ - if (authdecrypt(skeyid, (u_int32 *)pkt, authlen, has_mac)) + if (authdecrypt(skeyid, (u_int32 *)pkt, authlen, + has_mac)) is_authentic = 1; else sys_badauth++; @@ -409,137 +414,148 @@ receive( peer = findpeer(&rbufp->recv_srcadr, rbufp->dstadr, rbufp->fd, hismode, &retcode); /* - * The new association matching rules are driven by a table specified - * in ntp.h. We have replaced the *default* behaviour of replying - * to bogus packets in server mode in this version. - * A packet must now match an association in order to be processed. - * In the event that no association exists, then an association is - * mobilized if need be. Two different associations can be mobilized - * a) passive associations - * b) client associations due to broadcasts or manycasts. + * The new association matching rules are driven by a table + * specified in ntp.h. We have replaced the *default* behaviour + * of replying to bogus packets in server mode in this version. + * A packet must now match an association in order to be + * processed. In the event that no association exists, then an + * association is mobilized if need be. Two different + * associations can be mobilized a) passive associations b) + * client associations due to broadcasts or manycasts. */ is_error = 0; switch (retcode) { case AM_FXMIT: - /* - * If the client is configured purely as a broadcast client and - * not as an manycast server, it has no business being a server. - * Simply go home. Otherwise, send a MODE_SERVER response and go - * home. Note that we don't do a authentication check here, - * since we can't set the system clock; but, we do set the - * key ID to zero to tell the caller about this. - */ - if (!sys_bclient || sys_manycastserver) { - if (is_authentic) - fast_xmit(rbufp, MODE_SERVER, skeyid); - else - fast_xmit(rbufp, MODE_SERVER, 0); - } - - /* - * We can't get here if an association is mobilized, so just - * toss the key, if appropriate. - */ - if (!is_mystic && skeyid > NTP_MAXKEY) - authtrust(skeyid, 0); - return; + + /* + * If the client is configured purely as a broadcast + * client and not as an manycast server, it has no + * business being a server. Simply go home. Otherwise, + * send a MODE_SERVER response and go home. Note that we + * don't do a authentication check here, since we can't + * set the system clock; but, we do set the key ID to + * zero to tell the caller about this. + */ + if (!sys_bclient || sys_manycastserver) { + if (is_authentic) + fast_xmit(rbufp, MODE_SERVER, skeyid); + else + fast_xmit(rbufp, MODE_SERVER, 0); + } + + /* + * We can't get here if an association is mobilized, so + * just toss the key, if appropriate. + */ + if (!is_mystic && skeyid > NTP_MAXKEY) + authtrust(skeyid, 0); + return; case AM_MANYCAST: - /* - * This could be in response to a multicast packet sent by - * the "manycast" mode association. Find peer based on the - * originate timestamp in the packet. Note that we don't - * mobilize a new association, unless the packet is properly - * authenticated. The response must be properly authenticated - * and it's darn funny of the manycaster isn't around now. - */ - if ((sys_authenticate && !is_authentic)) { - is_error = 1; - break; - } - peer2 = (struct peer *)findmanycastpeer(&pkt->org); - if (peer2 == 0) { - is_error = 1; - break; - } - - /* - * Create a new association and copy the peer variables to it. - * If something goes wrong, carefully pry the new association - * away and return its marbles to the candy store. - */ - peer = newpeer(&rbufp->recv_srcadr, - rbufp->dstadr, MODE_CLIENT, PKT_VERSION(pkt->li_vn_mode), - NTP_MINDPOLL, NTP_MAXDPOLL, 0, skeyid); - if (peer == 0) { - is_error = 1; - break; - } - peer_config_manycast(peer2, peer); - break; + + /* + * This could be in response to a multicast packet sent + * by the "manycast" mode association. Find peer based + * on the originate timestamp in the packet. Note that + * we don't mobilize a new association, unless the + * packet is properly authenticated. The response must + * be properly authenticated and it's darn funny of the + * manycaster isn't around now. + */ + if ((sys_authenticate && !is_authentic)) { + is_error = 1; + break; + } + peer2 = (struct peer *)findmanycastpeer(&pkt->org); + if (peer2 == 0) { + is_error = 1; + break; + } + + /* + * Create a new association and copy the peer variables + * to it. If something goes wrong, carefully pry the new + * association away and return its marbles to the candy + * store. + */ + peer = newpeer(&rbufp->recv_srcadr, rbufp->dstadr, + MODE_CLIENT, PKT_VERSION(pkt->li_vn_mode), + NTP_MINDPOLL, NTP_MAXDPOLL, 0, skeyid); + if (peer == 0) { + is_error = 1; + break; + } + peer_config_manycast(peer2, peer); + break; case AM_ERR: - /* - * Something bad happened. Dirty floor will be mopped by the - * code at the end of this adventure. - */ - is_error = 1; - break; + + /* + * Something bad happened. Dirty floor will be mopped by + * the code at the end of this adventure. + */ + is_error = 1; + break; case AM_NEWPASS: - /* - * Okay, we're going to keep him around. Allocate him some - * memory. But, don't do that unless the packet is properly - * authenticated. - */ - if ((sys_authenticate && !is_authentic)) { - is_error = 1; - break; - } - peer = newpeer(&rbufp->recv_srcadr, - rbufp->dstadr, MODE_PASSIVE, PKT_VERSION(pkt->li_vn_mode), - NTP_MINDPOLL, NTP_MAXDPOLL, 0, skeyid); - break; + + /* + * Okay, we're going to keep him around. Allocate him + * some memory. But, don't do that unless the packet is + * properly authenticated. + */ + if ((sys_authenticate && !is_authentic)) { + is_error = 1; + break; + } + peer = newpeer(&rbufp->recv_srcadr, rbufp->dstadr, + MODE_PASSIVE, PKT_VERSION(pkt->li_vn_mode), + NTP_MINDPOLL, NTP_MAXDPOLL, 0, skeyid); + break; case AM_NEWBCL: - /* - * Broadcast client being set up now. Do this only if the - * packet is properly authenticated. - */ - if ((restrict_mask & RES_NOPEER) || !sys_bclient || - (sys_authenticate && !is_authentic)) { - is_error = 1; - break; - } - peer = newpeer(&rbufp->recv_srcadr, - rbufp->dstadr, MODE_MCLIENT, PKT_VERSION(pkt->li_vn_mode), - NTP_MINDPOLL, NTP_MAXDPOLL, 0, skeyid); - if (peer == 0) - break; - peer->flags |= FLAG_MCAST1 | FLAG_MCAST2 | FLAG_BURST; - peer->hmode = MODE_CLIENT; - break; + + /* + * Broadcast client being set up now. Do this only if + * the packet is properly authenticated. + */ + if ((restrict_mask & RES_NOPEER) || !sys_bclient || + (sys_authenticate && !is_authentic)) { + is_error = 1; + break; + } + peer = newpeer(&rbufp->recv_srcadr, rbufp->dstadr, + MODE_MCLIENT, PKT_VERSION(pkt->li_vn_mode), + NTP_MINDPOLL, NTP_MAXDPOLL, 0, skeyid); + if (peer == 0) + break; + peer->flags |= FLAG_MCAST1 | FLAG_MCAST2 | FLAG_BURST; + peer->hmode = MODE_CLIENT; + break; case AM_POSSBCL: case AM_PROCPKT: - /* - * It seems like it is okay to process the packet now - */ - break; + + /* + * It seems like it is okay to process the packet now + */ + break; default: - /* - * shouldn't be getting here, but simply return anyway! - */ - is_error = 1; + + /* + * shouldn't be getting here, but simply return anyway! + */ + is_error = 1; } if (is_error) { /* - * Error stub. If we get here, something broke. We scuttle - * the autokey if necessary and sink the ship. This can - * occur only upon mobilization, so we can throw the - * structure away without fear of breaking anything. + * Error stub. If we get here, something broke. We + * scuttle the autokey if necessary and sink the ship. + * This can occur only upon mobilization, so we can + * throw the structure away without fear of breaking + * anything. */ if (!is_mystic && skeyid > NTP_MAXKEY) authtrust(skeyid, 0); @@ -548,8 +564,8 @@ receive( unpeer(peer); #ifdef DEBUG if (debug) - printf("match error code %d assoc %d\n", retcode, - peer_associations); + printf("match error code %d assoc %d\n", + retcode, peer_associations); #endif return; } @@ -572,22 +588,23 @@ receive( /* * Determine if this guy is basically trustable. If not, flush - * the bugger. If this is the first packet that is authenticated, - * flush the clock filter. This is to foil clogging attacks that - * might starve the poor dear. + * the bugger. If this is the first packet that is + * authenticated, flush the clock filter. This is to foil + * clogging attacks that might starve the poor dear. */ peer->flash = 0; if (is_authentic) peer->flags |= FLAG_AUTHENTIC; else peer->flags &= ~FLAG_AUTHENTIC; - if (peer->hmode == MODE_BROADCAST && (restrict_mask & RES_DONTTRUST)) + if (peer->hmode == MODE_BROADCAST && (restrict_mask & + RES_DONTTRUST)) peer->flash |= TEST10; /* access denied */ if (peer->flags & FLAG_AUTHENABLE) { if (!(peer->flags & FLAG_AUTHENTIC)) - peer->flash |= TEST5; /* authentication failed */ + peer->flash |= TEST5; /* auth failed */ else if (skeyid == 0) - peer->flash |= TEST9; /* peer not authenticated */ + peer->flash |= TEST9; /* peer not auth */ else if (!(oflags & FLAG_AUTHENABLE)) { peer_clear(peer); report_event(EVNT_PEERAUTH, peer); @@ -596,10 +613,10 @@ receive( if ((peer->flash & ~(u_int)TEST9) != 0) { /* - * The packet is bogus, so we throw it away before becoming - * a denial-of-service hazard. We don't throw the current - * association away if it is configured or if it has prior - * reachable friends. + * The packet is bogus, so we throw it away before + * becoming a denial-of-service hazard. We don't throw + * the current association away if it is configured or + * if it has prior reachable friends. */ if (!is_mystic && skeyid > NTP_MAXKEY) authtrust(skeyid, 0); @@ -617,8 +634,8 @@ receive( #ifdef MD5 /* * The autokey dance. The cha-cha requires that the hash of the - * current session key matches the previous key identifier. Heaps - * of trouble if the steps falter. + * current session key matches the previous key identifier. + * Heaps of trouble if the steps falter. */ if (skeyid > NTP_MAXKEY) { int i; @@ -633,7 +650,8 @@ receive( } else if (peer->flags & FLAG_MCAST2) { if (peer->pkeyid > NTP_MAXKEY) authtrust(peer->pkeyid, 0); - for (i = 0; i < 4 && tkeyid != peer->pkeyid; i++) { + for (i = 0; i < 4 && tkeyid != peer->pkeyid; + i++) { tkeyid = session_key( ntohl((&rbufp->recv_srcadr)->sin_addr.s_addr), ntohl(rbufp->dstadr->bcast.sin_addr.s_addr), @@ -642,7 +660,8 @@ receive( } else { if (peer->pkeyid > NTP_MAXKEY) authtrust(peer->pkeyid, 0); - for (i = 0; i < 4 && tkeyid != peer->pkeyid; i++) { + for (i = 0; i < 4 && tkeyid != peer->pkeyid; + i++) { tkeyid = session_key( ntohl((&rbufp->recv_srcadr)->sin_addr.s_addr), ntohl(rbufp->dstadr->sin.sin_addr.s_addr), @@ -658,9 +677,10 @@ receive( #endif /* MD5 */ /* - * Gawdz, it's come to this. Process the dang packet. If something - * breaks and the association doesn't deserve to live, toss it. - * Be careful in active mode and return a packet anyway. + * Gawdz, it's come to this. Process the dang packet. If + * something breaks and the association doesn't deserve to live, + * toss it. Be careful in active mode and return a packet + * anyway. */ process_packet(peer, pkt, &(rbufp->recv_time)); if (!(peer->flags & FLAG_CONFIG) && peer->reach == 0) { @@ -810,15 +830,15 @@ process_packet( p_disp = CLOCK_PHI * (peer->rec.l_ui - p_org.l_ui); /* - * If running in a broadcast association, the clock offset is (t1 - * - t0) corrected by the one-way delay, but we can't measure - * that directly; therefore, we start up in client/server mode, - * calculate the clock offset, using the engineered refinement - * algorithms, while also receiving broadcasts. When a broadcast - * is received in client/server mode, we calculate a correction - * factor to use after switching back to broadcast mode. We know - * NTP_SKEWFACTOR == 16, which accounts for the simplified ei - * calculation. + * If running in a broadcast association, the clock offset is + * (t1 - t0) corrected by the one-way delay, but we can't + * measure that directly; therefore, we start up in + * client/server mode, calculate the clock offset, using the + * engineered refinement algorithms, while also receiving + * broadcasts. When a broadcast is received in client/server + * mode, we calculate a correction factor to use after switching + * back to broadcast mode. We know NTP_SKEWFACTOR == 16, which + * accounts for the simplified ei calculation. * * If FLAG_MCAST2 is set, we are a broadcast/multicast client. * If FLAG_MCAST1 is set, we haven't calculated the propagation @@ -868,7 +888,8 @@ process_packet( clock_filter(peer, p_offset, p_del, fabs(p_disp)); clock_select(); record_peer_stats(&peer->srcadr, ctlpeerstatus(peer), - peer->offset, peer->delay, peer->disp, SQRT(peer->variance)); + peer->offset, peer->delay, peer->disp, + SQRT(peer->variance)); return(1); } @@ -941,7 +962,8 @@ clock_update(void) else sys_refid = sys_peer->srcadr.sin_addr.s_addr; sys_reftime = sys_peer->rec; - sys_rootdelay = sys_peer->rootdelay + fabs(sys_peer->delay); + sys_rootdelay = sys_peer->rootdelay + + fabs(sys_peer->delay); sys_leap = leap_consensus; } if (oleap != sys_leap) @@ -992,14 +1014,15 @@ poll_update( else peer->nextdate += RANDPOLL(BURST_INTERVAL1); } else { - update = max(min(peer->ppoll, peer->hpoll), peer->minpoll); + update = max(min(peer->ppoll, peer->hpoll), + peer->minpoll); peer->nextdate = peer->outdate + RANDPOLL(update); } #ifdef DEBUG if (debug > 1) printf("poll_update: at %lu %s poll %d burst %d last %lu next %lu\n", - current_time, ntoa(&peer->srcadr), hpoll, peer->burst, - peer->outdate, peer->nextdate); + current_time, ntoa(&peer->srcadr), hpoll, + peer->burst, peer->outdate, peer->nextdate); #endif } @@ -1079,7 +1102,8 @@ clock_filter( */ peer->filter_offset[peer->filter_nextpt] = sample_offset; peer->filter_delay[peer->filter_nextpt] = sample_delay; - x = LOGTOD(peer->precision) + LOGTOD(sys_precision) + sample_disp; + x = LOGTOD(peer->precision) + LOGTOD(sys_precision) + + sample_disp; peer->filter_disp[peer->filter_nextpt] = min(x, MAXDISPERSE); peer->filter_epoch[peer->filter_nextpt] = current_time; distance[0] = min(x + fabs(sample_delay) / 2, MAXDISTANCE); @@ -1115,7 +1139,8 @@ clock_filter( x = NTP_FWEIGHT * (x + peer->filter_disp[ord[i]]); if (i < n) { z += 1. / distance[i]; - off += peer->filter_offset[ord[i]] / distance[i]; + off += peer->filter_offset[ord[i]] / + distance[i]; y += DIFF(peer->filter_offset[ord[i]], peer->filter_offset[ord[0]]); } @@ -1239,7 +1264,7 @@ clock_select(void) peer->flags &= ~FLAG_SYSPEER; peer->status = CTL_PST_SEL_REJECT; if (peer->flags & FLAG_NOSELECT) - continue; /* noselect (survey only) */ + continue; /* noselect (survey) */ if (peer->reach == 0) continue; /* unreachable */ if (peer->stratum > 1 && peer->refid == @@ -1248,7 +1273,7 @@ clock_select(void) if (root_distance(peer) >= MAXDISTANCE + 2 * CLOCK_PHI * ULOGTOD(sys_poll)) { peer->seldisptoolarge++; - continue; /* too noisy or broken */ + continue; /* noisy or broken */ } /* @@ -1321,7 +1346,7 @@ clock_select(void) if (debug > 1) for (i = 0; i < nl3; i++) printf("select: endpoint %2d %.6f\n", - endpoint[index[i]].type, endpoint[index[i]].val); + endpoint[index[i]].type, endpoint[index[i]].val); #endif i = 0; j = nl3 - 1; @@ -1367,9 +1392,10 @@ clock_select(void) } else { if (sys_peer != 0) { report_event(EVNT_PEERSTCHG, - (struct peer *)0); + (struct peer *)0); NLOG(NLOG_SYNCSTATUS) - msyslog(LOG_INFO, "synchronisation lost"); + msyslog(LOG_INFO, + "synchronisation lost"); } sys_peer = 0; return; @@ -1416,7 +1442,7 @@ clock_select(void) if (debug > 1) for (i = 0; i < nlist; i++) printf("select: %s distance %.6f\n", - ntoa(&peer_list[i]->srcadr), synch[i]); + ntoa(&peer_list[i]->srcadr), synch[i]); #endif /* @@ -1506,7 +1532,8 @@ clock_select(void) typesystem = peer_list[i]; if (peer_list[i]->flags & FLAG_PREFER) { typeprefer = peer_list[i]; - if (fabs(typeprefer->offset) < clock_max) + if (fabs(typeprefer->offset) < + clock_max) pps_update = 1; } } else { @@ -1519,24 +1546,26 @@ clock_select(void) * Mitigation rules of the game. There are several types of * peers that make a difference here: (1) prefer local peers * (type REFCLK_LOCALCLOCK with FLAG_PREFER) or prefer modem - * peers (type REFCLK_NIST_ATOM etc with FLAG_PREFER), (2) pps peers - * (type REFCLK_ATOM_PPS), (3) remaining prefer peers (flag - * FLAG_PREFER), (4) the existing system peer, if any, (5) the - * head of the survivor list. Note that only one peer can be + * peers (type REFCLK_NIST_ATOM etc with FLAG_PREFER), (2) pps + * peers (type REFCLK_ATOM_PPS), (3) remaining prefer peers + * (flag FLAG_PREFER), (4) the existing system peer, if any, (5) + * the head of the survivor list. Note that only one peer can be * declared prefer. The order of preference is in the order * stated. Note that all of these must be at the lowest stratum, * i.e., the stratum of the head of the survivor list. */ osys_peer = sys_peer; - if (typeprefer && (typeprefer->refclktype == REFCLK_LOCALCLOCK || - typeprefer->sstclktype == CTL_SST_TS_TELEPHONE || !typepps)) { + if (typeprefer && (typeprefer->refclktype == REFCLK_LOCALCLOCK + || typeprefer->sstclktype == CTL_SST_TS_TELEPHONE || + !typepps)) { sys_peer = typeprefer; sys_peer->status = CTL_PST_SEL_SYSPEER; sys_offset = sys_peer->offset; sys_epsil = sys_peer->variance; #ifdef DEBUG if (debug > 1) - printf("select: prefer offset %.6f\n", sys_offset); + printf("select: prefer offset %.6f\n", + sys_offset); #endif } else if (typepps && pps_update) { sys_peer = typepps; @@ -1650,15 +1679,18 @@ peer_xmit( if (peer->flags & FLAG_SKEY) { /* - * In SKEY mode, allocate and initialize a key list if - * not already done. Then, use the list in inverse - * order, discarding keys once used. Keep the latest - * key around until the next one, so clients can use - * client/server packets to compute propagation delay. - * Note we have to wait until the receive side of the - * socket is bound and the server address confirmed. + * In autokey mode, allocate and initialize a + * key list if not already done. Then, use the + * list in inverse order, discarding keys once + * used. Keep the latest key around until the + * next one, so clients can use client/server + * packets to compute propagation delay. Note we + * have to wait until the receive side of the + * socket is bound and the server address + * confirmed. */ - if (ntohl(peer->dstadr->sin.sin_addr.s_addr) == 0 && + if (ntohl(peer->dstadr->sin.sin_addr.s_addr) == + 0 && ntohl(peer->dstadr->bcast.sin_addr.s_addr) == 0) peer->keyid = 0; else { @@ -1686,13 +1718,13 @@ peer_xmit( get_systime(&peer->xmt); L_ADD(&peer->xmt, &sys_authdelay); HTONL_FP(&peer->xmt, &xpkt.xmt); - sendlen += authencrypt(xkeyid, (u_int32 *)&xpkt, sendlen); + sendlen += authencrypt(xkeyid, (u_int32 *)&xpkt, + sendlen); get_systime(&xmt_tx); sendpkt(&peer->srcadr, find_rtt ? any_interface : - peer->dstadr, - ((peer->cast_flags & MDF_MCAST) && !find_rtt) ? - ((peer->cast_flags & MDF_ACAST) ? -7 : peer->ttl) : -7, - &xpkt, sendlen); + peer->dstadr, ((peer->cast_flags & MDF_MCAST) && + !find_rtt) ? ((peer->cast_flags & MDF_ACAST) ? -7 : + peer->ttl) : -7, &xpkt, sendlen); /* * Calculate the encryption delay. Keep the minimum over @@ -1710,9 +1742,9 @@ peer_xmit( #ifdef DEBUG if (debug) printf( - "transmit: at %ld to %s mode %d keyid %08lx index %d\n", - current_time, ntoa(&peer->srcadr), - peer->hmode, xkeyid, peer->keynumber); + "transmit: at %ld to %s mode %d keyid %08lx index %d\n", + current_time, ntoa(&peer->srcadr), + peer->hmode, xkeyid, peer->keynumber); #endif } else { /* @@ -1721,10 +1753,9 @@ peer_xmit( get_systime(&(peer->xmt)); HTONL_FP(&peer->xmt, &xpkt.xmt); sendpkt(&(peer->srcadr), find_rtt ? any_interface : - peer->dstadr, - ((peer->cast_flags & MDF_MCAST) && !find_rtt) ? - ((peer->cast_flags & MDF_ACAST) ? -7 : peer->ttl) : -8, - &xpkt, sendlen); + peer->dstadr, ((peer->cast_flags & MDF_MCAST) && + !find_rtt) ? ((peer->cast_flags & MDF_ACAST) ? -7 : + peer->ttl) : -8, &xpkt, sendlen); peer->sent++; #ifdef DEBUG if (debug) @@ -1783,10 +1814,11 @@ fast_xmit( get_systime(&xmt_ts); L_ADD(&xmt_ts, &sys_authdelay); HTONL_FP(&xmt_ts, &xpkt.xmt); - sendlen += authencrypt(xkeyid, (u_int32 *)&xpkt, sendlen); + sendlen += authencrypt(xkeyid, (u_int32 *)&xpkt, + sendlen); get_systime(&xmt_tx); sendpkt(&rbufp->recv_srcadr, rbufp->dstadr, -9, &xpkt, - sendlen); + sendlen); /* * Calculate the encryption delay. Keep the minimum over @@ -1803,9 +1835,9 @@ fast_xmit( #ifdef DEBUG if (debug) printf( - "transmit: at %ld to %s mode %d keyid %08lx\n", - current_time, ntoa(&rbufp->recv_srcadr), - xmode, xkeyid); + "transmit: at %ld to %s mode %d keyid %08lx\n", + current_time, ntoa(&rbufp->recv_srcadr), + xmode, xkeyid); #endif } else { @@ -1868,15 +1900,14 @@ make_keylist( peer->keylist[i] = keyid; peer->keynumber = i; keyid = session_key( - ntohl(peer->dstadr->sin.sin_addr.s_addr), - (peer->hmode == MODE_BROADCAST || (peer->flags & - FLAG_MCAST2)) ? - ntohl(peer->dstadr->bcast.sin_addr.s_addr): - ntohl(peer->srcadr.sin_addr.s_addr), - keyid, ltemp); + ntohl(peer->dstadr->sin.sin_addr.s_addr), + (peer->hmode == MODE_BROADCAST || (peer->flags & + FLAG_MCAST2)) ? + ntohl(peer->dstadr->bcast.sin_addr.s_addr): + ntohl(peer->srcadr.sin_addr.s_addr), keyid, ltemp); ltemp -= 1 << peer->hpoll; if (auth_havekey(keyid) || keyid <= NTP_MAXKEY || - ltemp <= (1 << (peer->hpoll + 1))) + ltemp <= (1 << (peer->hpoll + 1))) break; } } @@ -1925,23 +1956,21 @@ default_get_precision(void) #endif #if defined(__FreeBSD__) && __FreeBSD__ >= 3 u_long freq; - int j; + size_t j; /* Try to see if we can find the frequency of of the counter * which drives our timekeeping */ j = sizeof freq; - i = sysctlbyname("kern.timecounter.frequency", - &freq, &j , 0, 0); + i = sysctlbyname("kern.timecounter.frequency", &freq, &j , 0, + 0); if (i) - i = sysctlbyname("machdep.tsc_freq", - &freq, &j , 0, 0); + i = sysctlbyname("machdep.tsc_freq", &freq, &j , 0, 0); if (i) - i = sysctlbyname("machdep.i586_freq", - &freq, &j , 0, 0); + i = sysctlbyname("machdep.i586_freq", &freq, &j , 0, 0); if (i) - i = sysctlbyname("machdep.i8254_freq", - &freq, &j , 0, 0); + i = sysctlbyname("machdep.i8254_freq", &freq, &j , 0, + 0); if (!i) { for (i = 1; freq ; i--) freq >>= 1; @@ -1977,7 +2006,7 @@ default_get_precision(void) val = diff; } } - NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */ + NLOG(NLOG_SYSINFO) msyslog(LOG_INFO, "precision = %ld usec", val); if (usec >= HUSECS) val = MINSTEP; /* val <= MINSTEP; fast machine */ @@ -2042,9 +2071,9 @@ init_proto(void) * Some system clocks should only be adjusted in 10ms increments. */ #if defined RELIANTUNIX_CLOCK - systime_10ms_ticks = 1; /* Reliant UNIX */ + systime_10ms_ticks = 1; /* Reliant UNIX */ #elif defined SCO5_CLOCK - if (sys_precision >= (s_char)-10) /* pre- SCO OpenServer 5.0.6 */ + if (sys_precision >= (s_char)-10) /* pre-SCO OpenServer 5.0.6 */ systime_10ms_ticks = 1; #endif if (systime_10ms_ticks) @@ -2066,21 +2095,24 @@ proto_config( * Figure out what he wants to change, then do it */ switch (item) { - case PROTO_KERNEL: + case PROTO_KERNEL: + /* * Turn on/off kernel discipline */ kern_enable = (int)value; break; - case PROTO_NTP: + case PROTO_NTP: + /* * Turn on/off clock discipline */ ntp_enable = (int)value; break; - case PROTO_MONITOR: + case PROTO_MONITOR: + /* * Turn on/off monitoring */ @@ -2090,14 +2122,16 @@ proto_config( mon_stop(MON_ON); break; - case PROTO_FILEGEN: + case PROTO_FILEGEN: + /* * Turn on/off statistics */ stats_control = (int)value; break; - case PROTO_BROADCLIENT: + case PROTO_BROADCLIENT: + /* * Turn on/off facility to listen to broadcasts */ @@ -2108,39 +2142,45 @@ proto_config( io_unsetbclient(); break; - case PROTO_MULTICAST_ADD: + case PROTO_MULTICAST_ADD: + /* * Add muliticast group address */ io_multicast_add(value); break; - case PROTO_MULTICAST_DEL: + case PROTO_MULTICAST_DEL: + /* * Delete multicast group address */ io_multicast_del(value); break; - case PROTO_BROADDELAY: + case PROTO_BROADDELAY: + /* * Set default broadcast delay */ sys_bdelay = dvalue; break; - case PROTO_AUTHENTICATE: + case PROTO_AUTHENTICATE: + /* * Specify the use of authenticated data */ sys_authenticate = (int)value; break; - default: + default: + /* * Log this error */ - msyslog(LOG_ERR, "proto_config: illegal item %d, value %ld", + msyslog(LOG_ERR, + "proto_config: illegal item %d, value %ld", item, value); break; } diff --git a/contrib/ntp/ntpd/ntp_refclock.c b/contrib/ntp/ntpd/ntp_refclock.c index c7b9166..c47031c 100644 --- a/contrib/ntp/ntpd/ntp_refclock.c +++ b/contrib/ntp/ntpd/ntp_refclock.c @@ -20,11 +20,12 @@ #ifdef REFCLOCK #ifdef TTYCLK -# ifdef SCO5_CLOCK -# include <sys/sio.h> -# else +# ifdef HAVE_SYS_CLKDEFS_H # include <sys/clkdefs.h> # endif +# ifdef HAVE_SYS_SIO_H +# include <sys/sio.h> +# endif #endif /* TTYCLK */ #ifdef HAVE_PPSCLOCK_H @@ -32,7 +33,13 @@ #endif /* HAVE_PPSCLOCK_H */ #ifdef HAVE_PPSAPI -#include <sys/timepps.h> +# ifdef HAVE_TIMEPPS_H +# include <timepps.h> +# else +# ifdef HAVE_SYS_TIMEPPS_H +# include <sys/timepps.h> +# endif +# endif #endif /* HAVE_PPSAPI */ /* @@ -755,10 +762,11 @@ int refclock_open( char *dev, /* device name pointer */ int speed, /* serial port speed (code) */ - int flags /* line discipline flags */ + int lflags /* line discipline flags */ ) { int fd, i; + int flags; #ifdef HAVE_TERMIOS struct termios ttyb, *ttyp; #endif /* HAVE_TERMIOS */ @@ -775,6 +783,9 @@ refclock_open( /* * Open serial port and set default options */ + flags = lflags; + if (strcmp(dev, pps_device) == 0) + flags |= LDISC_PPS; #ifdef O_NONBLOCK fd = open(dev, O_RDWR | O_NONBLOCK, 0777); #else @@ -936,12 +947,6 @@ refclock_open( "refclock_open: fd %d ioctl failed: %m", fd); return (0); } - - /* - * If this is the PPS device, so say and initialize the thing. - */ - if (strcmp(dev, pps_device) == 0) - (void)refclock_ioctl(fd, LDISC_PPS); return (fd); } #endif /* HAVE_TERMIOS || HAVE_SYSV_TTYS || HAVE_BSD_TTYS */ diff --git a/contrib/ntp/ntpd/ntpd.c b/contrib/ntp/ntpd/ntpd.c index 923b1f7..3dbef60 100644 --- a/contrib/ntp/ntpd/ntpd.c +++ b/contrib/ntp/ntpd/ntpd.c @@ -108,13 +108,13 @@ #define SIGDIE4 SIGTERM #endif /* SYS_WINNT */ -#if defined SYS_WINNT || defined SYS_CYGWIN32 +#if defined SYS_WINNT /* handles for various threads, process, and objects */ HANDLE ResolverThreadHandle = NULL; /* variables used to inform the Service Control Manager of our current state */ SERVICE_STATUS ssStatus; SERVICE_STATUS_HANDLE sshStatusHandle; -HANDLE WaitHandles[3] = { NULL, NULL, NULL }; +HANDLE WaitHandles[2] = { NULL, NULL }; char szMsgPath[255]; static BOOL WINAPI OnConsoleEvent(DWORD dwCtrlType); #endif /* SYS_WINNT */ @@ -122,11 +122,7 @@ static BOOL WINAPI OnConsoleEvent(DWORD dwCtrlType); /* * Scheduling priority we run at */ -#if !defined SYS_WINNT # define NTPD_PRIO (-12) -#else -# define NTPD_PRIO REALTIME_PRIORITY_CLASS -#endif /* * Debugging flag @@ -230,13 +226,35 @@ set_process_priority(void) int done = 0; #ifdef SYS_WINNT + DWORD SingleCPUMask = 0; + DWORD ProcessAffinityMask, SystemAffinityMask; + if (!GetProcessAffinityMask(GetCurrentProcess(), &ProcessAffinityMask, &SystemAffinityMask)) + msyslog(LOG_ERR, "GetProcessAffinityMask: %m"); + else { + SingleCPUMask = 1; +# ifdef DEBUG + msyslog(LOG_INFO, "System AffinityMask = %x", SystemAffinityMask ); +# endif + } + while (SingleCPUMask && !(SingleCPUMask & SystemAffinityMask)) { + SingleCPUMask = SingleCPUMask << 1; + } + + if (!SingleCPUMask) + msyslog(LOG_ERR, "Can't set Processor Affinity Mask"); + else if (!SetProcessAffinityMask(GetCurrentProcess(), SingleCPUMask)) + msyslog(LOG_ERR, "SetProcessAffinityMask: %m"); +# ifdef DEBUG + else msyslog(LOG_INFO,"ProcessorAffinity Mask: %x", SingleCPUMask ); +# endif + if (!SetPriorityClass(GetCurrentProcess(), (DWORD) REALTIME_PRIORITY_CLASS)) msyslog(LOG_ERR, "SetPriorityClass: %m"); else ++done; -#else /* not SYS_WINNT */ -# if defined(HAVE_SCHED_SETSCHEDULER) +#endif +# if defined(HAVE_SCHED_SETSCHEDULER) if (!done) { extern int config_priority_override, config_priority; int pmax, pmin; @@ -300,11 +318,11 @@ set_process_priority(void) } # endif /* HAVE_BSD_NICE */ # endif /* NTPD_PRIO && NTPD_PRIO != 0 */ -#endif /* not SYS_WINNT */ if (!done) msyslog(LOG_ERR, "set_process_priority: No way found to improve our priority"); } + /* * Main program. Initialize us, disconnect us from the tty if necessary, * and loop waiting for I/O and/or timer expiries. @@ -549,7 +567,6 @@ service_main( # define LOG_NTP LOG_DAEMON # endif openlog(cp, LOG_PID | LOG_NDELAY, LOG_NTP); -#ifndef SYS_CYGWIN32 # ifdef DEBUG if (debug) setlogmask(LOG_UPTO(LOG_DEBUG)); @@ -557,8 +574,6 @@ service_main( # endif /* DEBUG */ setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */ # endif /* LOG_DAEMON */ -#endif - #endif /* !SYS_WINNT && !VMS */ NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */ @@ -669,7 +684,7 @@ service_main( /* * Set up signals we should never pay attention to. */ -#if defined SIGPIPE && !defined SYS_CYGWIN32 +#if defined SIGPIPE (void) signal_no_reset(SIGPIPE, SIG_IGN); #endif /* SIGPIPE */ @@ -759,33 +774,20 @@ service_main( * yet to learn about anything else that is. */ # if defined(HAVE_IO_COMPLETION_PORT) - { WaitHandles[0] = CreateEvent(NULL, FALSE, FALSE, NULL); /* exit reques */ - WaitHandles[1] = get_recv_buff_event(); - WaitHandles[2] = get_timer_handle(); + WaitHandles[1] = get_timer_handle(); for (;;) { - DWORD Index = MsgWaitForMultipleObjectsEx(sizeof(WaitHandles)/sizeof(WaitHandles[0]), WaitHandles, INFINITE, QS_ALLEVENTS, MWMO_ALERTABLE); + DWORD Index = WaitForMultipleObjectsEx(sizeof(WaitHandles)/sizeof(WaitHandles[0]), WaitHandles, FALSE, 1000, MWMO_ALERTABLE); switch (Index) { case WAIT_OBJECT_0 + 0 : /* exit request */ exit(0); break; - case WAIT_OBJECT_0 + 1 : {/* recv buffer */ - if (NULL != (rbuf = get_full_recv_buffer())) { - if (rbuf->receiver != NULL) { - rbuf->receiver(rbuf); - } - freerecvbuf(rbuf); - } - } - break; - - case WAIT_OBJECT_0 + 2 : /* 1 second timer */ + case WAIT_OBJECT_0 + 1 : /* timer */ timer(); break; - - case WAIT_OBJECT_0 + 3 : { /* Windows message */ + case WAIT_OBJECT_0 + 2 : { /* Windows message */ MSG msg; while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) { @@ -800,10 +802,9 @@ service_main( case WAIT_TIMEOUT : break; - } + } /* switch */ + rbuflist = getrecvbufs(); /* get received buffers */ - } - } # else /* normal I/O */ was_alarmed = 0; @@ -858,7 +859,7 @@ service_main( else if (nfound == -1 && errno != EINTR) msyslog(LOG_ERR, "select() error: %m"); else if (debug) { -# if !defined SYS_VXWORKS && !defined SYS_CYGWIN32 && !defined SCO5_CLOCK /* to unclutter log */ +# if !defined SYS_VXWORKS && !defined SCO5_CLOCK /* to unclutter log */ msyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound); # endif } @@ -887,6 +888,7 @@ service_main( was_alarmed = 0; } +# endif /* HAVE_IO_COMPLETION_PORT */ /* * Call the data procedure to handle each received * packet. @@ -908,7 +910,6 @@ service_main( * Go around again */ } -# endif /* HAVE_IO_COMPLETION_PORT */ exit(1); /* unreachable */ return 1; /* DEC OSF cc braindamage */ } diff --git a/contrib/ntp/ntpd/refclock_atom.c b/contrib/ntp/ntpd/refclock_atom.c index 63e17c1..764f6e0 100644 --- a/contrib/ntp/ntpd/refclock_atom.c +++ b/contrib/ntp/ntpd/refclock_atom.c @@ -26,7 +26,13 @@ # include <sys/ppsclock.h> #endif #ifdef HAVE_PPSAPI -#include <sys/timepps.h> +# ifdef HAVE_TIMEPPS_H +# include <timepps.h> +# else +# ifdef HAVE_SYS_TIMEPPS_H +# include <sys/timepps.h> +# endif +# endif #endif /* HAVE_PPSAPI */ /* diff --git a/contrib/ntp/ntpd/refclock_chu.c b/contrib/ntp/ntpd/refclock_chu.c index 0b2ae78..4235b8e 100644 --- a/contrib/ntp/ntpd/refclock_chu.c +++ b/contrib/ntp/ntpd/refclock_chu.c @@ -1,38 +1,35 @@ /* - * refclock_chu - clock driver for Canadian radio CHU receivers + * refclock_chu - clock driver for Canadian CHU time/frequency station */ - #ifdef HAVE_CONFIG_H #include <config.h> #endif #if defined(REFCLOCK) && defined(CLOCK_CHU) -/* #define AUDIO_CHUa */ - #include <stdio.h> #include <ctype.h> #include <sys/time.h> #include <time.h> #include <math.h> -#ifdef AUDIO_CHU -#ifdef HAVE_SYS_AUDIOIO_H -#include <sys/audioio.h> -#endif /* HAVE_SYS_AUDIOIO_H */ -#ifdef HAVE_SUN_AUDIOIO_H -#include <sun/audioio.h> -#endif /* HAVE_SUN_AUDIOIO_H */ -#endif /* AUDIO_CHU */ - #include "ntpd.h" #include "ntp_io.h" #include "ntp_refclock.h" #include "ntp_calendar.h" #include "ntp_stdlib.h" +#ifdef AUDIO_CHU +#include "audio.h" +#endif /* AUDIO_CHU */ + +#define ICOM 1 /* undefine to suppress ICOM code */ + +#ifdef ICOM +#include "icom.h" +#endif /* ICOM */ /* - * Clock driver for Canadian radio CHU receivers + * Audio CHU demodulator/decoder * * This driver synchronizes the computer time using data encoded in * radio transmissions from Canadian time/frequency station CHU in @@ -40,8 +37,14 @@ * 7335 kHz and 14670 kHz in upper sideband, compatible AM mode. An * ordinary shortwave receiver can be tuned manually to one of these * frequencies or, in the case of ICOM receivers, the receiver can be - * tuned automatically using the minimuf and icom programs as - * propagation conditions change throughout the day and night. + * tuned automatically using this program as propagation conditions + * change throughout the day and night. + * + * The driver receives, demodulates and decodes the radio signals when + * connected to the audio codec of a Sun workstation running SunOS or + * Solaris, and with a little help, other workstations with similar + * codecs or sound cards. In this implementation, only one audio driver + * and codec can be supported on a single machine. * * The driver can be compiled to use a Bell 103 compatible modem or * modem chip to receive the radio signal and demodulate the data. @@ -168,28 +171,34 @@ * input port, where 0 is the mike port (default) and 1 is the line-in * port. It does not seem useful to select the compact disc player port. * Fudge flag3 enables audio monitoring of the input signal. For this - * purpose, the speaker volume must be set before the driver is started. + * purpose, the speaker volume must be set before the driver is started. + * + * The ICOM code is normally compiled in the driver. It isn't used, + * unless the mode keyword on the server configuration command specifies + * a nonzero ICOM ID select code. The C-IV trace is turned on if the + * debug level is greater than one. */ - /* * Interface definitions */ #define SPEED232 B300 /* uart speed (300 baud) */ #define PRECISION (-10) /* precision assumed (about 1 ms) */ #define REFID "CHU" /* reference ID */ +#ifdef ICOM +#define DWELL 5 /* minutes before qsy */ +#define NCHAN 3 /* number of channels */ +#endif /* ICOM */ #ifdef AUDIO_CHU #define DESCRIPTION "CHU Modem Receiver" /* WRU */ /* * Audio demodulator definitions */ -#define AUDIO_BUFSIZ 160 /* codec buffer size (Solaris only) */ -#define SAMPLE 8000 /* nominal sample rate (Hz) */ +#define SECOND 8000 /* nominal sample rate (Hz) */ #define BAUD 300 /* modulation rate (bps) */ #define OFFSET 128 /* companded sample offset */ #define SIZE 256 /* decompanding table size */ #define MAXSIG 6000. /* maximum signal level */ -#define DRPOUT 100. /* dropout signal level */ #define LIMIT 1000. /* soft limiter threshold */ #define AGAIN 6. /* baseband gain */ #define LAG 10 /* discriminator lag */ @@ -208,8 +217,8 @@ #define MINCHAR 9 /* min characters per burst */ #define MINDIST 28 /* min burst distance (of 40) */ #define MINSYNC 8 /* min sync distance (of 16) */ -#define MINDEC .5 /* decoder majority rule (of 1.) */ #define MINSTAMP 20 /* min timestamps (of 60) */ +#define PANIC (4 * 1440) /* panic restart */ /* * Hex extension codes (>= 16) @@ -219,24 +228,37 @@ #define HEX_HARD 18 /* hard error */ /* - * Error flags (up->errflg) + * Status bits (status) */ -#define CHU_ERR_RUNT 0x001 /* runt burst */ -#define CHU_ERR_NOISE 0x002 /* noise burst */ -#define CHU_ERR_BFRAME 0x004 /* invalid format B frame sync */ -#define CHU_ERR_BFORMAT 0x008 /* invalid format B data */ -#define CHU_ERR_AFRAME 0x010 /* invalid format A frame sync */ -#define CHU_ERR_DECODE 0x020 /* invalid data decode */ -#define CHU_ERR_STAMP 0x040 /* too few timestamps */ -#define CHU_ERR_AFORMAT 0x080 /* invalid format A data */ -#ifdef AUDIO_CHU -#define CHU_ERR_ERROR 0x100 /* codec error (overrun) */ -#endif /* AUDIO_CHU */ +#define RUNT 0x0001 /* runt burst */ +#define NOISE 0x0002 /* noise burst */ +#define BFRAME 0x0004 /* invalid format B frame sync */ +#define BFORMAT 0x0008 /* invalid format B data */ +#define AFRAME 0x0010 /* invalid format A frame sync */ +#define AFORMAT 0x0020 /* invalid format A data */ +#define DECODE 0x0040 /* invalid data decode */ +#define STAMP 0x0080 /* too few timestamps */ +#define INYEAR 0x0100 /* valid B frame */ +#define INSYNC 0x0200 /* clock synchronized */ + +/* + * Alarm status bits (alarm) + * + * These alarms are set at the end of a minute in which at least one + * burst was received. SYNERR is raised if the AFRAME or BFRAME status + * bits are set during the minute, FMTERR is raised if the AFORMAT or + * BFORMAT status bits are set, DECERR is raised if the DECODE status + * bit is set and TSPERR is raised if the STAMP status bit is set. + */ +#define SYNERR 0x01 /* frame sync error */ +#define FMTERR 0x02 /* data format error */ +#define DECERR 0x04 /* data decoding error */ +#define TSPERR 0x08 /* insufficient data */ #ifdef AUDIO_CHU struct surv { double shift[12]; /* mark register */ - double max, min; /* max/min envelope signals */ + double es_max, es_min; /* max/min envelope signals */ double dist; /* sample distance */ int uart; /* decoded character */ }; @@ -253,8 +275,14 @@ struct chuunit { l_fp laststamp; /* last buffer timestamp */ l_fp charstamp; /* character time as a l_fp */ int errflg; /* error flags */ + int status; /* status bits */ int bufptr; /* buffer index pointer */ - int pollcnt; /* poll message counter */ + char ident[10]; /* transmitter frequency */ +#ifdef ICOM + int chan; /* frequency identifier */ + int dwell; /* dwell minutes at current frequency */ + int fd_icom; /* ICOM file descriptor */ +#endif /* ICOM */ /* * Character burst variables @@ -264,9 +292,18 @@ struct chuunit { int ndx; /* buffer start index */ int prevsec; /* previous burst second */ int burdist; /* burst distance */ + int mindist; /* minimum distance */ int syndist; /* sync distance */ int burstcnt; /* format A bursts this minute */ + /* + * Format particulars + */ + int leap; /* leap/dut code */ + int dut; /* UTC1 correction */ + int tai; /* TAI - UTC correction */ + int dst; /* Canadian DST code */ + #ifdef AUDIO_CHU /* * Audio codec variables @@ -313,28 +350,23 @@ static void chu_poll P((int, struct peer *)); static void chu_decode P((struct peer *, int)); static void chu_burst P((struct peer *)); static void chu_clear P((struct peer *)); -static void chu_update P((struct peer *, int)); -static void chu_year P((struct peer *, int)); +static void chu_a P((struct peer *, int)); +static void chu_b P((struct peer *, int)); static int chu_dist P((int, int)); +static int chu_major P((struct peer *)); #ifdef AUDIO_CHU static void chu_uart P((struct surv *, double)); static void chu_rf P((struct peer *, double)); static void chu_gain P((struct peer *)); -static int chu_audio P((void)); -static void chu_debug P((void)); #endif /* AUDIO_CHU */ /* * Global variables */ static char hexchar[] = "0123456789abcdef_-="; -#ifdef AUDIO_CHU -#ifdef HAVE_SYS_AUDIOIO_H -struct audio_device device; /* audio device ident */ -#endif /* HAVE_SYS_AUDIOIO_H */ -static struct audio_info info; /* audio device info */ -static int chu_ctl_fd; /* audio control file descriptor */ -#endif /* AUDIO_CHU */ +#ifdef ICOM +static double qsy[NCHAN] = {3.33, 7.335, 14.67}; /* frequencies (MHz) */ +#endif /* ICOM */ /* * Transfer vector @@ -361,11 +393,11 @@ chu_start( { struct chuunit *up; struct refclockproc *pp; - - /* - * Local variables - */ int fd; /* file descriptor */ +#ifdef ICOM + char tbuf[80]; /* trace buffer */ + int temp; +#endif /* ICOM */ #ifdef AUDIO_CHU int i; /* index */ double step; /* codec adjustment */ @@ -373,16 +405,18 @@ chu_start( /* * Open audio device */ - fd = open("/dev/audio", O_RDWR | O_NONBLOCK, 0777); - if (fd == -1) { - perror("chu: audio"); + fd = audio_init(); + if (fd < 0) return (0); - } +#ifdef DEBUG + if (debug) + audio_show(); +#endif #else char device[20]; /* device name */ /* - * Open serial port. Use RAW line discipline (required). + * Open serial port in raw mode. */ (void)sprintf(device, DEVICE, unit); if (!(fd = refclock_open(device, SPEED232, LDISC_RAW))) { @@ -418,14 +452,8 @@ chu_start( pp->clockdesc = DESCRIPTION; memcpy((char *)&pp->refid, REFID, 4); DTOLFP(CHAR, &up->charstamp); - up->pollcnt = 2; #ifdef AUDIO_CHU - up->gain = (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN) / 2; - if (chu_audio() < 0) { - io_closeclock(&pp->io); - free(up); - return (0); - } + up->gain = 127; /* * The companded samples are encoded sign-magnitude. The table @@ -441,8 +469,43 @@ chu_start( if (i % 16 == 0) step *= 2.; } - DTOLFP(1. / SAMPLE, &up->tick); + DTOLFP(1. / SECOND, &up->tick); #endif /* AUDIO_CHU */ + strcpy(up->ident, "X"); +#ifdef ICOM + temp = 0; +#ifdef DEBUG + if (debug > 1) + temp = P_TRACE; +#endif + if (peer->ttl > 0) { + if (peer->ttl & 0x80) + up->fd_icom = icom_init("/dev/icom", B1200, + temp); + else + up->fd_icom = icom_init("/dev/icom", B9600, + temp); + } + if (up->fd_icom > 0) { + if (icom_freq(up->fd_icom, peer->ttl & 0x7f, + qsy[up->chan]) < 0) { + NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT) + msyslog(LOG_ERR, + "ICOM bus error; autotune disabled"); + up->errflg = CEVNT_FAULT; + close(up->fd_icom); + up->fd_icom = 0; + } else { + sprintf(up->ident, "%.1f", qsy[up->chan]); + sprintf(tbuf, "chu: QSY to %s MHz", up->ident); + record_clock_stats(&peer->srcadr, tbuf); +#ifdef DEBUG + if (debug) + printf("%s\n", tbuf); +#endif + } + } +#endif /* ICOM */ return (1); } @@ -462,6 +525,8 @@ chu_shutdown( pp = peer->procptr; up = (struct chuunit *)pp->unitptr; io_closeclock(&pp->io); + if (up->fd_icom > 0) + close(up->fd_icom); free(up); } @@ -479,15 +544,12 @@ chu_receive( struct refclockproc *pp; struct peer *peer; - /* - * Local variables - */ double sample; /* codec sample */ u_char *dpt; /* buffer pointer */ l_fp ltemp; /* l_fp temp */ - double dtemp; /* double temp */ int isneg; /* parity flag */ - int i, j; /* index temps */ + double dtemp; + int i, j; peer = (struct peer *)rbufp->recv_srcclock; pp = peer->procptr; @@ -499,7 +561,7 @@ chu_receive( */ up->timestamp = rbufp->recv_time; up->bufcnt = rbufp->recv_length; - DTOLFP(up->bufcnt * 1. / SAMPLE, <emp); + DTOLFP(up->bufcnt * 1. / SECOND, <emp); L_SUB(&up->timestamp, <emp); dpt = (u_char *)&rbufp->recv_space; for (up->bufptr = 0; up->bufptr < up->bufcnt; up->bufptr++) { @@ -517,14 +579,13 @@ chu_receive( sample = -MAXSIG; up->clipcnt++; } - up->seccnt = (up->seccnt + 1) % SAMPLE; + up->seccnt = (up->seccnt + 1) % SECOND; if (up->seccnt == 0) { if (pp->sloppyclockflag & CLK_FLAG2) - up->port = AUDIO_LINE_IN; + up->port = 2; else - up->port = AUDIO_MICROPHONE; + up->port = 1; chu_gain(peer); - up->clipcnt = 0; } chu_rf(peer, sample); @@ -584,7 +645,7 @@ chu_receive( * code. Hopefully, the compiler will efficiently implement the move- * and-muiltiply-and-add operations. */ -void +static void chu_rf( struct peer *peer, /* peer structure pointer */ double sample /* analog sample */ @@ -603,10 +664,11 @@ chu_rf( double lpf; /* lowpass signal */ double span; /* UART signal span */ double dist; /* UART signal distance */ - int i, j; /* index temps */ + int i, j; pp = peer->procptr; up = (struct chuunit *)pp->unitptr; + /* * Bandpass filter. 4th-order elliptic, 500-Hz bandpass centered * at 2125 Hz. Passband ripple 0.3 dB, stopband ripple 50 dB. @@ -684,10 +746,7 @@ chu_rf( lpf += (up->lpf[2] = up->lpf[1]) * 2.003159e-01; lpf += (up->lpf[1] = up->lpf[0]) * 1.084671e-01; lpf += up->lpf[0] = disc * 2.538771e-02; -/* -printf("%8.3f %8.3f\n", disc, lpf); -return; -*/ + /* * Maximum likelihood decoder. The UART updates each of the * eight survivors and determines the span, slice level and @@ -697,11 +756,11 @@ return; * survivor with maximum distance determines the final decoded * character. */ - up->baud += 1. / SAMPLE; + up->baud += 1. / SECOND; if (up->baud > 1. / (BAUD * 8.)) { up->baud -= 1. / (BAUD * 8.); sp = &up->surv[up->decptr]; - span = sp->max - sp->min; + span = sp->es_max - sp->es_min; up->maxsignal += (span - up->maxsignal) / 80.; if (up->dbrk > 0) { up->dbrk--; @@ -734,34 +793,31 @@ return; * program selects over the last eight survivors the one with maximum * distance to determine the decoded character. */ -void +static void chu_uart( struct surv *sp, /* survivor structure pointer */ double sample /* baseband signal */ ) { - /* - * Local variables - */ - double max, min; /* max/min envelope */ + double es_max, es_min; /* max/min envelope */ double slice; /* slice level */ double dist; /* distance */ - double dtemp; /* double temp */ - int i; /* index temp */ + double dtemp; + int i; /* * Save the sample and shift right. At the same time, measure * the maximum and minimum over all eleven samples. */ - max = -1e6; - min = 1e6; + es_max = -1e6; + es_min = 1e6; sp->shift[0] = sample; for (i = 11; i > 0; i--) { sp->shift[i] = sp->shift[i - 1]; - if (sp->shift[i] > max) - max = sp->shift[i]; - if (sp->shift[i] < min) - min = sp->shift[i]; + if (sp->shift[i] > es_max) + es_max = sp->shift[i]; + if (sp->shift[i] < es_min) + es_min = sp->shift[i]; } /* @@ -770,7 +826,7 @@ chu_uart( * the distance on the assumption the first and last bits must * be mark, the second space and the rest either mark or space. */ - slice = (max + min) / 2.; + slice = (es_max + es_min) / 2.; dist = 0; sp->uart = 0; for (i = 1; i < 12; i++) { @@ -779,19 +835,19 @@ chu_uart( if (dtemp > slice) sp->uart |= 0x1; if (i == 1 || i == 11) { - dist += dtemp - min; + dist += dtemp - es_min; } else if (i == 10) { - dist += max - dtemp; + dist += es_max - dtemp; } else { if (dtemp > slice) - dist += dtemp - min; + dist += dtemp - es_min; else - dist += max - dtemp; + dist += es_max - dtemp; } } - sp->max = max; - sp->min = min; - sp->dist = dist / (11 * (max - min)); + sp->es_max = es_max; + sp->es_min = es_min; + sp->dist = dist / (11 * (es_max - es_min)); } @@ -836,11 +892,8 @@ chu_decode( struct refclockproc *pp; struct chuunit *up; - /* - * Local variables - */ l_fp tstmp; /* timestamp temp */ - double dtemp; /* double temp */ + double dtemp; pp = peer->procptr; up = (struct chuunit *)pp->unitptr; @@ -888,10 +941,7 @@ chu_burst( struct chuunit *up; struct refclockproc *pp; - /* - * Local variables - */ - int i; /* index temp */ + int i; pp = peer->procptr; up = (struct chuunit *)pp->unitptr; @@ -903,7 +953,7 @@ chu_burst( * match the inverse for format B. */ if (up->ndx < MINCHAR) { - up->errflg |= CHU_ERR_RUNT; + up->status |= RUNT; return; } up->burdist = 0; @@ -913,15 +963,16 @@ chu_burst( /* * If the burst distance is at least MINDIST, this must be a * format A burst; if the value is not greater than -MINDIST, it - * must be a format B burst; otherwise, it is a noise burst and - * of no use to anybody. + * must be a format B burst. If the B burst is perfect, we + * believe it; otherwise, it is a noise burst and of no use to + * anybody. */ if (up->burdist >= MINDIST) { - chu_update(peer, up->ndx); + chu_a(peer, up->ndx); } else if (up->burdist <= -MINDIST) { - chu_year(peer, up->ndx); + chu_b(peer, up->ndx); } else { - up->errflg |= CHU_ERR_NOISE; + up->status |= NOISE; return; } @@ -931,18 +982,16 @@ chu_burst( * process the minute. Don't do this if this is called from the * timer interrupt routine. */ - if (peer->outdate == current_time) - up->pollcnt = 2; - else + if (peer->outdate != current_time) peer->nextdate = current_time + 10; } /* - * chu_year - decode format B burst + * chu_b - decode format B burst */ static void -chu_year( +chu_b( struct peer *peer, int nchar ) @@ -950,16 +999,10 @@ chu_year( struct refclockproc *pp; struct chuunit *up; - /* - * Local variables - */ u_char code[11]; /* decoded timecode */ + char tbuf[80]; /* trace buffer */ l_fp offset; /* timestamp offset */ - int leap; /* leap/dut code */ - int dut; /* UTC1 correction */ - int tai; /* TAI - UTC correction */ - int dst; /* Canadian DST code */ - int i; /* index temp */ + int i; pp = peer->procptr; up = (struct chuunit *)pp->unitptr; @@ -970,37 +1013,39 @@ chu_year( * is considered valid only if all characters are valid; that * is, only if the distance is 40. */ - sprintf(pp->a_lastcode, "%2d %2d ", nchar, -up->burdist); + sprintf(tbuf, "chuB %04x %2d %2d ", up->status, nchar, + -up->burdist); for (i = 0; i < nchar; i++) - sprintf(&pp->a_lastcode[strlen(pp->a_lastcode)], "%02x", + sprintf(&tbuf[strlen(tbuf)], "%02x", up->cbuf[i]); - pp->lencode = strlen(pp->a_lastcode); if (pp->sloppyclockflag & CLK_FLAG4) - record_clock_stats(&peer->srcadr, pp->a_lastcode); + record_clock_stats(&peer->srcadr, tbuf); #ifdef DEBUG - if (debug > 2) - printf("chu: %s\n", pp->a_lastcode); + if (debug) + printf("%s\n", tbuf); #endif - if (-up->burdist < 40) { - up->errflg |= CHU_ERR_BFRAME; + if (up->burdist > -40) { + up->status |= BFRAME; return; } + up->status |= INYEAR; /* * Convert the burst data to internal format. If this succeeds, - * save the timestamps for later. The leap, dut, tai and dst are - * presently unused. + * save the timestamps for later. */ for (i = 0; i < 5; i++) { code[2 * i] = hexchar[up->cbuf[i] & 0xf]; code[2 * i + 1] = hexchar[(up->cbuf[i] >> 4) & 0xf]; } - if (sscanf((char *)code, "%1x%1d%4d%2d%2x", &leap, &dut, - &pp->year, &tai, &dst) != 5) { - up->errflg |= CHU_ERR_BFORMAT; + if (sscanf((char *)code, "%1x%1d%4d%2d%2x", &up->leap, &up->dut, + &pp->year, &up->tai, &up->dst) != 5) { + up->status |= BFORMAT; return; } + if (up->leap & 0x8) + up->dut = -up->dut; offset.l_ui = 31; offset.l_f = 0; for (i = 0; i < nchar && i < 10; i++) { @@ -1014,10 +1059,10 @@ chu_year( /* - * chu_update - decode format A burst + * chu_a - decode format A burst */ static void -chu_update( +chu_a( struct peer *peer, int nchar ) @@ -1025,13 +1070,11 @@ chu_update( struct refclockproc *pp; struct chuunit *up; - /* - * Local variables - */ + char tbuf[80]; /* trace buffer */ l_fp offset; /* timestamp offset */ int val; /* distance */ - int temp; /* common temp */ - int i, j, k; /* index temps */ + int temp; + int i, j, k; pp = peer->procptr; up = (struct chuunit *)pp->unitptr; @@ -1061,31 +1104,29 @@ chu_update( k = i; } } - temp = (up->cbuf[k + 4] >> 4) & 0xf; if (temp > 9 || k + 9 >= nchar || temp != ((up->cbuf[k + 9] >> 4) & 0xf)) temp = 0; #ifdef AUDIO_CHU - sprintf(pp->a_lastcode, "%3d %4.0f %2d %2d %2d %2d %1d ", - up->gain, up->maxsignal, nchar, up->burdist, k, up->syndist, - temp); + sprintf(tbuf, "chuA %04x %4.0f %2d %2d %2d %2d %1d ", + up->status, up->maxsignal, nchar, up->burdist, k, + up->syndist, temp); #else - sprintf(pp->a_lastcode, "%2d %2d %2d %2d %1d ", nchar, - up->burdist, k, up->syndist, temp); + sprintf(tbuf, "chuA %04x %2d %2d %2d %2d %1d ", up->status, + nchar, up->burdist, k, up->syndist, temp); #endif /* AUDIO_CHU */ for (i = 0; i < nchar; i++) - sprintf(&pp->a_lastcode[strlen(pp->a_lastcode)], "%02x", + sprintf(&tbuf[strlen(tbuf)], "%02x", up->cbuf[i]); - pp->lencode = strlen(pp->a_lastcode); if (pp->sloppyclockflag & CLK_FLAG4) - record_clock_stats(&peer->srcadr, pp->a_lastcode); + record_clock_stats(&peer->srcadr, tbuf); #ifdef DEBUG - if (debug > 2) - printf("chu: %s\n", pp->a_lastcode); + if (debug) + printf("%s\n", tbuf); #endif if (up->syndist < MINSYNC) { - up->errflg |= CHU_ERR_AFRAME; + up->status |= AFRAME; return; } @@ -1127,8 +1168,10 @@ chu_update( i += 2; continue; } - up->decode[i++][up->cbuf[j] & 0xf]++; - up->decode[i++][(up->cbuf[j] >> 4) & 0xf]++; + up->decode[i][up->cbuf[j] & 0xf]++; + i++; + up->decode[i][(up->cbuf[j] >> 4) & 0xf]++; + i++; } up->burstcnt++; } @@ -1140,53 +1183,155 @@ chu_update( static void chu_poll( int unit, - struct peer *peer + struct peer *peer /* peer structure pointer */ ) { struct refclockproc *pp; struct chuunit *up; - - /* - * Local variables - */ - u_char code[11]; /* decoded timecode */ - l_fp toffset, offset; /* l_fp temps */ - int mindist; /* minimum distance */ - int val1, val2; /* maximum distance */ - int synchar; /* should be a 6 in traffic */ - double dtemp; /* double temp */ - int temp; /* common temp */ - int i, j, k; /* index temps */ - + char synchar, qual, leapchar; + int minset; + int temp; +#ifdef ICOM + char tbuf[80]; /* trace buffer */ +#endif /* ICOM */ pp = peer->procptr; up = (struct chuunit *)pp->unitptr; + if (pp->coderecv == pp->codeproc) + up->errflg = CEVNT_TIMEOUT; + else + pp->polls++; + minset = ((current_time - peer->update) + 30) / 60; + if (up->status & INSYNC) { + if (minset > PANIC) + up->status = 0; + else + peer->reach |= 1; + } /* * Process the last burst, if still in the burst buffer. * Don't mess with anything if nothing has been heard. */ chu_burst(peer); - if (up->pollcnt == 0) - refclock_report(peer, CEVNT_TIMEOUT); - else - up->pollcnt--; - if (up->burstcnt == 0) { - chu_clear(peer); +#ifdef ICOM + if (up->burstcnt > 2) { + up->dwell = 0; + } else if (up->dwell < DWELL) { + up->dwell++; + } else if (up->fd_icom > 0) { + up->dwell = 0; + up->chan = (up->chan + 1) % NCHAN; + icom_freq(up->fd_icom, peer->ttl & 0x7f, qsy[up->chan]); + sprintf(up->ident, "%.3f", qsy[up->chan]); + sprintf(tbuf, "chu: QSY to %s MHz", up->ident); + record_clock_stats(&peer->srcadr, tbuf); +#ifdef DEBUG + if (debug) + printf("%s\n", tbuf); +#endif + } +#endif /* ICOM */ + if (up->burstcnt == 0) return; + temp = chu_major(peer); + if (up->status & INYEAR) + up->status |= INSYNC; + qual = 0; + if (up->status & (BFRAME | AFRAME)) + qual |= SYNERR; + if (up->status & (BFORMAT | AFORMAT)) + qual |= FMTERR; + if (up->status & DECODE) + qual |= DECERR; + if (up->status & STAMP) + qual |= TSPERR; + synchar = leapchar = ' '; + if (!(up->status & INSYNC)) { + pp->leap = LEAP_NOTINSYNC; + synchar = '?'; + } else if (up->leap & 0x2) { + pp->leap = LEAP_ADDSECOND; + leapchar = 'L'; + } else { + pp->leap = LEAP_NOWARNING; } +#ifdef AUDIO_CHU + sprintf(pp->a_lastcode, + "%c%1X %4d %3d %02d:%02d:%02d.000 %c%x %+d %d %d %s %d %d %d %d", + synchar, qual, pp->year, pp->day, pp->hour, pp->minute, + pp->second, leapchar, up->dst, up->dut, minset, up->gain, + up->ident, up->tai, up->burstcnt, up->mindist, up->ntstamp); +#else + sprintf(pp->a_lastcode, + "%c%1X %4d %3d %02d:%02d:%02d.000 %c%x %+d %d %s %d %d %d %d", + synchar, qual, pp->year, pp->day, pp->hour, pp->minute, + pp->second, leapchar, up->dst, up->dut, minset, + up->ident, up->tai, up->burstcnt, up->mindist, up->ntstamp); +#endif /* AUDIO_CHU */ + pp->lencode = strlen(pp->a_lastcode); /* - * Majority decoder. Select the character with the most - * occurrences for each burst position. The distance for the - * character is this number of occurrences. If no occurrences - * are found, assume a miss '_'; if only a single occurrence is - * found, assume a soft error '-'; if two different characters + * If timestamps have been stuffed, the timecode is ipso fatso + * correct and can be selected to discipline the clock. + */ + if (temp > 0) { + record_clock_stats(&peer->srcadr, pp->a_lastcode); + refclock_receive(peer); + } else if (pp->sloppyclockflag & CLK_FLAG4) { + record_clock_stats(&peer->srcadr, pp->a_lastcode); + } +#ifdef DEBUG + if (debug) + printf("chu: timecode %d %s\n", pp->lencode, + pp->a_lastcode); +#endif + chu_clear(peer); + if (up->errflg) + refclock_report(peer, up->errflg); + up->errflg = 0; +} + + +/* + * chu_major - majority decoder + */ +static int +chu_major( + struct peer *peer /* peer structure pointer */ + ) +{ + struct refclockproc *pp; + struct chuunit *up; + + u_char code[11]; /* decoded timecode */ + l_fp toffset, offset; /* l_fp temps */ + int val1, val2; /* maximum distance */ + int synchar; /* stray cat */ + double dtemp; + int temp; + int i, j, k; + + pp = peer->procptr; + up = (struct chuunit *)pp->unitptr; + + /* + * Majority decoder. Each burst encodes two replications at each + * digit position in the timecode. Each row of the decoding + * matrix encodes the number of occurences of each digit found + * at the corresponding position. The maximum over all + * occurences at each position is the distance for this position + * and the corresponding digit is the maximumn likelihood + * candidate. If the distance is zero, assume a miss '_'; if the + * distance is not more than half the total number of + * occurences, assume a soft error '-'; if two different digits * with the same distance are found, assume a hard error '='. - * The decoding distance is defined as the minimum of the - * character distances. + * These will later cause a format error when the timecode is + * interpreted. The decoding distance is defined as the minimum + * distance over the first nine digits. The tenth digit varies + * over the seconds, so we don't count it. */ - mindist = 16; - for (i = 0; i < 10; i++) { + up->mindist = 16; + for (i = 0; i < 9; i++) { val1 = val2 = 0; k = 0; for (j = 0; j < 16; j++) { @@ -1197,21 +1342,30 @@ chu_poll( k = j; } } - if (val1 > 0 && val1 == val2) + if (val1 == 0) + code[i] = HEX_MISS; + else if (val1 == val2) code[i] = HEX_HARD; - else if (val1 < 2) + else if (val1 <= up->burstcnt) code[i] = HEX_SOFT; else code[i] = k; - if (val1 < mindist) - mindist = val1; + if (val1 < up->mindist) + up->mindist = val1; code[i] = hexchar[code[i]]; } code[i] = 0; - if (mindist < up->burstcnt * 2 * MINDEC) - up->errflg |= CHU_ERR_DECODE; + + /* + * A valid timecode requires at least three bursts and a + * decoding distance greater than half the total number of + * occurences. A valid timecode also requires at least 20 valid + * timestamps. + */ + if (up->burstcnt < 3 || up->mindist <= up->burstcnt) + up->status |= DECODE; if (up->ntstamp < MINSTAMP) - up->errflg |= CHU_ERR_STAMP; + up->status |= STAMP; /* * Compute the timecode timestamp from the days, hours and @@ -1220,34 +1374,21 @@ chu_poll( * seconds. Note that this code relies on the filesystem time * for the years and does not use the years of the timecode. */ - if (sscanf((char *)code, "%1x%3d%2d%2d", &synchar, &pp->day, &pp->hour, - &pp->minute) != 4) - up->errflg |= CHU_ERR_AFORMAT; - sprintf(pp->a_lastcode, - "%02x %4d %3d %02d:%02d:%02d %2d %2d %2d", - up->errflg, pp->year, pp->day, pp->hour, pp->minute, - pp->second, up->burstcnt, mindist, up->ntstamp); - pp->lencode = strlen(pp->a_lastcode); - record_clock_stats(&peer->srcadr, pp->a_lastcode); -#ifdef DEBUG - if (debug > 2) - printf("chu: %s\n", pp->a_lastcode); -#endif - if (up->errflg & (CHU_ERR_DECODE | CHU_ERR_STAMP | - CHU_ERR_AFORMAT)) { - refclock_report(peer, CEVNT_BADREPLY); - chu_clear(peer); - return; + if (sscanf((char *)code, "%1x%3d%2d%2d", &synchar, &pp->day, + &pp->hour, &pp->minute) != 4) { + up->status |= AFORMAT; + return (0); + } + if (up->status & (DECODE | STAMP)) { + up->errflg = CEVNT_BADREPLY; + return (0); } L_CLR(&offset); if (!clocktime(pp->day, pp->hour, pp->minute, 0, GMT, up->tstamp[0].l_ui, &pp->yearstart, &offset.l_ui)) { - refclock_report(peer, CEVNT_BADTIME); - chu_clear(peer); - return; + up->errflg = CEVNT_BADTIME; + return (0); } - pp->polls++; - pp->leap = LEAP_NOWARNING; pp->lastref = offset; pp->variance = 0; for (i = 0; i < up->ntstamp; i++) { @@ -1256,9 +1397,7 @@ chu_poll( LFPTOD(&toffset, dtemp); SAMPLE(dtemp + FUDGE + pp->fudgetime1); } - if (i > 0) - refclock_receive(peer); - chu_clear(peer); + return (i); } @@ -1267,25 +1406,22 @@ chu_poll( */ static void chu_clear( - struct peer *peer + struct peer *peer /* peer structure pointer */ ) { struct refclockproc *pp; struct chuunit *up; - - /* - * Local variables - */ - int i, j; /* index temps */ + int i, j; pp = peer->procptr; up = (struct chuunit *)pp->unitptr; /* - * Clear stuff for following minute. + * Clear stuff for the minute. */ - up->ndx = up->ntstamp = up->prevsec = 0; - up->errflg = 0; + up->ndx = up->prevsec = 0; + up->burstcnt = up->mindist = up->ntstamp = 0; + up->status &= INSYNC | INYEAR; up->burstcnt = 0; for (i = 0; i < 20; i++) { for (j = 0; j < 16; j++) @@ -1303,12 +1439,9 @@ chu_dist( int y /* another octet of bits */ ) { - /* - * Local variables - */ int val; /* bit count */ - int temp; /* misc temporary */ - int i; /* index temporary */ + int temp; + int i; /* * The distance is determined as the weight of the exclusive OR @@ -1353,112 +1486,23 @@ chu_gain( /* * Apparently, the codec uses only the high order bits of the * gain control field. Thus, it may take awhile for changes to - * wiggle the hardware bits. Set the new bits in the structure - * and call AUDIO_SETINFO. Upon return, the old bits are in the - * structure. + * wiggle the hardware bits. */ if (up->clipcnt == 0) { up->gain += 4; - if (up->gain > AUDIO_MAX_GAIN) - up->gain = AUDIO_MAX_GAIN; - } else if (up->clipcnt > SAMPLE / 100) { + if (up->gain > 255) + up->gain = 255; + } else if (up->clipcnt > SECOND / 100) { up->gain -= 4; - if (up->gain < AUDIO_MIN_GAIN) - up->gain = AUDIO_MIN_GAIN; - } - AUDIO_INITINFO(&info); - info.record.port = up->port; - info.record.gain = up->gain; - info.record.error = 0; - ioctl(chu_ctl_fd, (int)AUDIO_SETINFO, &info); - if (info.record.error) - up->errflg |= CHU_ERR_ERROR; -} - - -/* - * chu_audio - initialize audio device - * - * This code works with SunOS 4.1.3 and Solaris 2.6; however, it is - * believed generic and applicable to other systems with a minor twid - * or two. All it does is open the device, set the buffer size (Solaris - * only), preset the gain and set the input port. It assumes that the - * codec sample rate (8000 Hz), precision (8 bits), number of channels - * (1) and encoding (ITU-T G.711 mu-law companded) have been set by - * default. - */ -static int -chu_audio( - ) -{ - /* - * Open audio control device - */ - if ((chu_ctl_fd = open("/dev/audioctl", O_RDWR)) < 0) { - perror("audioctl"); - return(-1); - } -#ifdef HAVE_SYS_AUDIOIO_H - /* - * Set audio device parameters. - */ - AUDIO_INITINFO(&info); - info.record.buffer_size = AUDIO_BUFSIZ; - if (ioctl(chu_ctl_fd, (int)AUDIO_SETINFO, &info) < 0) { - perror("AUDIO_SETINFO"); - close(chu_ctl_fd); - return(-1); + if (up->gain < 0) + up->gain = 0; } -#endif /* HAVE_SYS_AUDIOIO_H */ -#ifdef DEBUG - chu_debug(); -#endif /* DEBUG */ - return(0); + audio_gain(up->gain, up->port); + up->clipcnt = 0; } - - -#ifdef DEBUG -/* - * chu_debug - display audio parameters - * - * This code doesn't really do anything, except satisfy curiousity and - * verify the ioctl's work. - */ -static void -chu_debug( - ) -{ - if (debug == 0) - return; -#ifdef HAVE_SYS_AUDIOIO_H - ioctl(chu_ctl_fd, (int)AUDIO_GETDEV, &device); - printf("chu: name %s, version %s, config %s\n", - device.name, device.version, device.config); -#endif /* HAVE_SYS_AUDIOIO_H */ - ioctl(chu_ctl_fd, (int)AUDIO_GETINFO, &info); - printf( - "chu: samples %d, channels %d, precision %d, encoding %d\n", - info.record.sample_rate, info.record.channels, - info.record.precision, info.record.encoding); -#ifdef HAVE_SYS_AUDIOIO_H - printf("chu: gain %d, port %d, buffer %d\n", - info.record.gain, info.record.port, - info.record.buffer_size); -#else /* HAVE_SYS_AUDIOIO_H */ - printf("chu: gain %d, port %d\n", - info.record.gain, info.record.port); -#endif /* HAVE_SYS_AUDIOIO_H */ - printf( - "chu: samples %d, eof %d, pause %d, error %d, waiting %d, balance %d\n", - info.record.samples, info.record.eof, - info.record.pause, info.record.error, - info.record.waiting, info.record.balance); - printf("chu: monitor %d, muted %d\n", - info.monitor_gain, info.output_muted); -} -#endif /* DEBUG */ #endif /* AUDIO_CHU */ + #else int refclock_chu_bs; #endif /* REFCLOCK */ diff --git a/contrib/ntp/ntpd/refclock_conf.c b/contrib/ntp/ntpd/refclock_conf.c index d203dd7..71140c8 100644 --- a/contrib/ntp/ntpd/refclock_conf.c +++ b/contrib/ntp/ntpd/refclock_conf.c @@ -42,7 +42,13 @@ extern struct refclock refclock_chu; #define refclock_chu refclock_none #endif -#ifdef CLOCK_WWVB +#ifdef CLOCK_WWV +extern struct refclock refclock_wwv; +#else +#define refclock_wwv refclock_none +#endif + +#ifdef CLOCK_SPECTRACOM extern struct refclock refclock_wwvb; #else #define refclock_wwvb refclock_none @@ -168,7 +174,7 @@ extern struct refclock refclock_arc; #define refclock_arc refclock_none #endif -#ifdef SHM +#ifdef CLOCK_SHM extern struct refclock refclock_shm; #else #define refclock_shm refclock_none @@ -210,6 +216,18 @@ extern struct refclock refclock_ulink; #define refclock_ulink refclock_none #endif +#ifdef CLOCK_PCF +extern struct refclock refclock_pcf; +#else +#define refclock_pcf refclock_none +#endif + +#ifdef CLOCK_FG +extern struct refclock refclock_fg; +#else +#define refclock_fg refclock_none +#endif + /* * Order is clock_start(), clock_shutdown(), clock_poll(), @@ -222,10 +240,10 @@ struct refclock *refclock_conf[] = { &refclock_local, /* 1 REFCLK_LOCAL */ &refclock_trak, /* 2 REFCLK_GPS_TRAK */ &refclock_pst, /* 3 REFCLK_WWV_PST */ - &refclock_wwvb, /* 4 REFCLK_WWVB_SPECTRACOM */ + &refclock_wwvb, /* 4 REFCLK_SPECTRACOM */ &refclock_true, /* 5 REFCLK_TRUETIME */ &refclock_irig, /* 6 REFCLK_IRIG_AUDIO */ - &refclock_chu, /* 7 REFCLK_CHU */ + &refclock_chu, /* 7 REFCLK_CHU_AUDIO */ &refclock_parse, /* 8 REFCLK_PARSE */ &refclock_mx4200, /* 9 REFCLK_GPS_MX4200 */ &refclock_as2201, /* 10 REFCLK_GPS_AS2201 */ @@ -253,6 +271,9 @@ struct refclock *refclock_conf[] = { &refclock_chronolog, /* 32 REFCLK_CHRONOLOG */ &refclock_dumbclock, /* 33 REFCLK_DUMBCLOCK */ &refclock_ulink, /* 34 REFCLOCK_ULINK */ + &refclock_pcf, /* 35 REFCLOCK_PCF */ + &refclock_wwv, /* 36 REFCLOCK_WWV_AUDIO */ + &refclock_fg /* 37 REFCLOCK_FG */ }; u_char num_refclock_conf = sizeof(refclock_conf)/sizeof(struct refclock *); diff --git a/contrib/ntp/ntpd/refclock_fg.c b/contrib/ntp/ntpd/refclock_fg.c new file mode 100644 index 0000000..f1320b0 --- /dev/null +++ b/contrib/ntp/ntpd/refclock_fg.c @@ -0,0 +1,350 @@ +/* + * refclock_fg - clock driver for the Forum Graphic GPS datating station + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#if defined(REFCLOCK) && defined(CLOCK_FG) + +#include <time.h> + +#include "ntpd.h" +#include "ntp_io.h" +#include "ntp_refclock.h" +#include "ntp_calendar.h" +#include "ntp_stdlib.h" + +/* + * This driver supports the Forum Graphic GPS dating station. + * More information about FG GPS is available on http://www.forumgraphic.com + * Contact das@amt.ru for any question about this driver. + */ + +/* + * Interface definitions + */ +#define DEVICE "/dev/fgclock%d" +#define PRECISION (-10) /* precision assumed (about 1 ms) */ +#define REFID "GPS" +#define DESCRIPTION "Forum Graphic GPS dating station" +#define LENFG 26 /* timecode length */ +#define SPEED232 B9600 /* uart speed (9600 baud) */ + +/* + * Function prototypes + */ +static int fg_init P((int)); +static int fg_start P((int, struct peer *)); +static void fg_shutdown P((int, struct peer *)); +static void fg_poll P((int, struct peer *)); +static void fg_receive P((struct recvbuf *)); + +/* + * Forum Graphic unit control structure + */ + +struct fgunit { + int pollnum; /* Use peer.poll instead? */ + int status; /* Hug to check status information on GPS */ + int y2kwarn; /* Y2K bug */ +}; + +/* + * Queries definition + */ +static char fginit[] = { 0x10, 0x48, 0x10, 0x0D, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0 }; +static char fgdate[] = { 0x10, 0x44, 0x10, 0x0D, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0 }; + +/* + * Transfer vector + */ +struct refclock refclock_fg = { + fg_start, /* start up driver */ + fg_shutdown, /* shut down driver */ + fg_poll, /* transmit poll message */ + noentry, /* not used */ + noentry, /* initialize driver (not used) */ + noentry, /* not used */ + NOFLAGS /* not used */ +}; + +/* + * fg_init - Initialization of FG GPS. + */ + +static int +fg_init( + int fd + ) +{ + if (write(fd, fginit, LENFG) != LENFG) + return 0; + + return (1); + +} + +/* + * fg_start - open the device and initialize data for processing + */ +static int +fg_start( + int unit, + struct peer *peer + ) +{ + struct refclockproc *pp; + struct fgunit *up; + int fd; + char device[20]; + + + /* + * Open device file for reading. + */ + (void)sprintf(device, DEVICE, unit); + +#ifdef DEBUG + if (debug) + printf ("starting FG with device %s\n",device); +#endif + if (!(fd = refclock_open(device, SPEED232, LDISC_CLK))) + return (0); + + /* + * Allocate and initialize unit structure + */ + + if (!(up = (struct fgunit *) + emalloc(sizeof(struct fgunit)))) { + (void) close(fd); + return (0); + } + memset((char *)up, 0, sizeof(struct fgunit)); + pp = peer->procptr; + pp->unitptr = (caddr_t)up; + pp->io.clock_recv = fg_receive; + pp->io.srcclock = (caddr_t)peer; + pp->io.datalen = 0; + pp->io.fd = fd; + if (!io_addclock(&pp->io)) { + (void) close(fd); + return (0); + } + + + /* + * Initialize miscellaneous variables + */ + peer->precision = PRECISION; + pp->clockdesc = DESCRIPTION; + memcpy((char *)&pp->refid, REFID, 3); + up->pollnum = 0; + + /* + * Setup dating station to use GPS receiver. + * GPS receiver should work before this operation. + */ + if(!fg_init(pp->io.fd)) + refclock_report(peer, CEVNT_FAULT); + + return (1); +} + + +/* + * fg_shutdown - shut down the clock + */ +static void +fg_shutdown( + int unit, + struct peer *peer + ) +{ + struct refclockproc *pp; + struct fgunit *up; + + pp = peer->procptr; + up = (struct fgunit *)pp->unitptr; + io_closeclock(&pp->io); + free(up); +} + + +/* + * fg_poll - called by the transmit procedure + */ +static void +fg_poll( + int unit, + struct peer *peer + ) +{ + struct refclockproc *pp; + + pp = peer->procptr; + + /* + * Time to poll the clock. The FG clock responds to a + * "<DLE>D<DLE><CR>" by returning a timecode in the format specified + * above. If nothing is heard from the clock for two polls, + * declare a timeout and keep going. + */ + + if (write(pp->io.fd, fgdate, LENFG) != LENFG) + refclock_report(peer, CEVNT_FAULT); + else + pp->polls++; + + if (peer->burst > 0) + return; + /* + if (pp->coderecv == pp->codeproc) { + refclock_report(peer, CEVNT_TIMEOUT); + return; + } + */ + peer->burst = NSTAGE; + + record_clock_stats(&peer->srcadr, pp->a_lastcode); + + + return; + +} + +/* + * fg_receive - receive data from the serial interface + */ +static void +fg_receive( + struct recvbuf *rbufp + ) +{ + struct refclockproc *pp; + struct fgunit *up; + struct peer *peer; + char *bpt; + + /* + * Initialize pointers and read the timecode and timestamp + * We can't use gtlin function because we need bynary data in buf */ + + peer = (struct peer *)rbufp->recv_srcclock; + pp = peer->procptr; + up = (struct fgunit *)pp->unitptr; + + /* + * Below hug to implement receiving of status information + */ + if(!up->pollnum) + { + up->pollnum++; + return; + } + + + if (rbufp->recv_length < (LENFG-2)) + { + refclock_report(peer, CEVNT_BADREPLY); + return; /* The reply is invalid discard it. */ + } + + /* Below I trying to find a correct reply in buffer. + * Sometime GPS reply located in the beginnig of buffer, + * sometime you can find it with some offset. + */ + + bpt = (char *)rbufp->recv_space.X_recv_buffer; + while(*bpt != '') + bpt++; + +#define BP2(x) ( bpt[x] & 15 ) +#define BP1(x) (( bpt[x] & 240 ) >> 4) + + pp->year = BP1(2)*10 + BP2(2); + + if(pp->year == 94) + { + refclock_report(peer, CEVNT_BADREPLY); + if(!fg_init(pp->io.fd)) + refclock_report(peer, CEVNT_FAULT); + return; + /* GPS is just powered up. The date is invalid - + discarding it. Initilize GPS one more time */ + /* Sorry - this driver will broken in 2094 ;) */ + } + + if (pp->year < 99) + pp->year += 100; + + pp->year += 1900; + pp->day = 100 * BP2(3) + 10 * BP1(4) + BP2(4); + +/* + After Jan, 10 2000 Forum Graphic GPS receiver had a very strange + benahour. It doubles day number for an hours in replys after 10:10:10 UTC + and doubles min every hour at HH:10:ss for a minute. + Hope it is a problem of my unit only and not a Y2K problem of FG GPS. + Below small code to avoid such situation. +*/ + if(up->y2kwarn > 10) + pp->hour = BP1(6)*10 + BP2(6); + else + pp->hour = BP1(5)*10 + BP2(5); + + if((up->y2kwarn > 10) && (pp->hour == 10)) + { + pp->minute = BP1(7)*10 + BP2(7); + pp->second = BP1(8)*10 + BP2(8); + pp->msec = BP1(9)*10 + BP2(9); + pp->usec = BP1(10); + } else { + pp->hour = BP1(5)*10 + BP2(5); + pp->minute = BP1(6)*10 + BP2(6); + pp->second = BP1(7)*10 + BP2(7); + pp->msec = BP1(8)*10 + BP2(8); + pp->usec = BP1(9); + } + + if((pp->hour == 10) && (pp->minute == 10)) + { + up->y2kwarn++; + } + + sprintf(pp->a_lastcode, "%d %d %d %d %d", pp->year, pp->day, pp->hour, pp->minute, pp->second); + pp->lencode = strlen(pp->a_lastcode); + /*get_systime(&pp->lastrec);*/ + +#ifdef DEBUG + if (debug) + printf ("fg: time is %04d/%03d %02d:%02d:%02d UTC\n", + pp->year, pp->day, pp->hour, pp->minute, pp->second); +#endif + + if (peer->stratum <= 1) + peer->refid = pp->refid; + pp->disp = (10e-6); + pp->lastrec = rbufp->recv_time; /* Is it better then get_systime()? */ + /* pp->leap = LEAP_NOWARNING; */ + + /* + * Process the new sample in the median filter and determine the + * timecode timestamp. + */ + + if (!refclock_process(pp)) + refclock_report(peer, CEVNT_BADTIME); + + refclock_receive(peer); + return; +} + + +#else +int refclock_fg_bs; +#endif /* REFCLOCK */ diff --git a/contrib/ntp/ntpd/refclock_gpsvme.c b/contrib/ntp/ntpd/refclock_gpsvme.c index a7c6d23..b37466b 100644 --- a/contrib/ntp/ntpd/refclock_gpsvme.c +++ b/contrib/ntp/ntpd/refclock_gpsvme.c @@ -40,9 +40,10 @@ extern int init_vme(); /* This is just a call to map_vme() */ /* It doesn't have to be extern */ -unsigned short *greg[NREGS]; /* GPS registers defined in gps.h */ -void *gps_base; /* Base address of GPS VME card returned by */ /* the map_vme() call */ +extern unsigned short *greg[NREGS]; /* made extern to avoid being in both map_vme.c and this file */ +extern void *gps_base; /* mjb lmco 12/20/99 */ + extern caddr_t map_vme (); extern void unmap_vme(); /* Unmaps the VME space */ @@ -57,6 +58,8 @@ struct vmedate { /* structure needed by ntp */ }; struct vmedate *get_gpsvme_time(); +struct vmedate * time_vme; /* added to emulate LM refclock_gpsvme + (Made global per RES suggestion to fix mem leak DW lmco) mjb lmco 12/15/99 */ /* END OF STUFF FROM RES */ @@ -134,13 +137,13 @@ static u_char sloppyclockflag[MAXUNITS]; * Function prototypes */ static void vme_init (void); -static int vme_start (u_int, struct peer *); -static void vme_shutdown (int); +static int vme_start (int, struct peer *); +static void vme_shutdown (int, struct peer *); static void vme_report_event (struct vmeunit *, int); static void vme_receive (struct recvbuf *); static void vme_poll (int unit, struct peer *); -static void vme_control (u_int, struct refclockstat *, struct refclockstat *); -static void vme_buginfo (int, struct refclockbug *); +static void vme_control (int, struct refclockstat *, struct refclockstat *, struct peer *); +static void vme_buginfo (int, struct refclockbug *, struct peer *); /* * Transfer vector @@ -233,6 +236,8 @@ vme_start( } else { vme = (struct vmeunit *) emalloc(sizeof(struct vmeunit)); + time_vme = (struct vmedate *)malloc(sizeof(struct vmedate)); /* Added to emulate LM's refclock_gpsvme + (added to fix mem lead DW lmco) mjb lmco 12/22/99 */ } } bzero((char *)vme, sizeof(struct vmeunit)); @@ -347,9 +352,6 @@ vme_poll( struct tm *tadr; - vme = (struct vmeunit *)emalloc(sizeof(struct vmeunit *)); - tptr = (struct vmedate *)emalloc(sizeof(struct vmedate *)); - if (unit >= MAXUNITS) { msyslog(LOG_ERR, "vme_poll: unit %d invalid", unit); @@ -435,13 +437,14 @@ vme_poll( } /* - * vme_control - set fudge factors, return statistics + * vme_control - set fudge factors, return statistics2 */ static void vme_control( u_int unit, struct refclockstat *in, - struct refclockstat *out + struct refclockstat *out, + struct peer * peer ) { register struct vmeunit *vme; @@ -453,7 +456,8 @@ vme_control( if (in != 0) { if (in->haveflags & CLK_HAVETIME1) - fudgefactor[unit] = in->fudgetime1; + DTOLFP(in->fudgetime1, &fudgefactor[unit]); /* added mjb lmco 12/20/99 */ + if (in->haveflags & CLK_HAVEVAL1) { stratumtouse[unit] = (u_char)(in->fudgeval1 & 0xf); if (unitinuse[unit]) { @@ -482,16 +486,19 @@ vme_control( out->haveflags = CLK_HAVETIME1|CLK_HAVEVAL1|CLK_HAVEVAL2|CLK_HAVEFLAG1; out->clockdesc = VMEDESCRIPTION; - out->fudgetime1 = fudgefactor[unit]; - out->fudgetime2.l_ui = 0; - out->fudgetime2.l_uf = 0; - out->fudgeval1 = (LONG)stratumtouse[unit]; + LFPTOD(&fudgefactor[unit], out->fudgetime1); /* added mjb lmco 12/20/99 */ + + out ->fudgetime2 = 0; /* should do what above was supposed to do mjb lmco 12/20/99 */ + + out->fudgeval1 = (long)stratumtouse[unit]; /*changed from above LONG was not + defined mjb lmco 12/15/99 */ + out->fudgeval2 = 0; out->flags = sloppyclockflag[unit]; if (unitinuse[unit]) { vme = vmeunits[unit]; out->lencode = vme->lencode; - out->lastcode = vme->lastcode; + out->p_lastcode = vme->lastcode; out->timereset = current_time - vme->timestarted; out->polls = vme->polls; out->noresponse = vme->noreply; @@ -501,7 +508,7 @@ vme_control( out->currentstatus = vme->status; } else { out->lencode = 0; - out->lastcode = ""; + out->p_lastcode = ""; out->polls = out->noresponse = 0; out->badformat = out->baddata = 0; out->timereset = 0; @@ -516,7 +523,8 @@ vme_control( static void vme_buginfo( int unit, - register struct refclockbug *bug + register struct refclockbug *bug, + struct peer * peer ) { register struct vmeunit *vme; @@ -559,7 +567,7 @@ vme_buginfo( struct vmedate * get_gpsvme_time(void) { - struct vmedate *time_vme; + extern struct vmedate *time_vme; unsigned short set, hr, min, sec, ums, hms, status; int ret; char ti[3]; @@ -570,7 +578,6 @@ get_gpsvme_time(void) char *gpsmicro; gpsmicro = (char *) malloc(7); - time_vme = (struct vmedate *)malloc(sizeof(struct vmedate )); *greg = (unsigned short *)malloc(sizeof(short) * NREGS); @@ -602,7 +609,7 @@ get_gpsvme_time(void) /* unmap_vme(); */ if (!status) { - return ((void *)NULL); + return (NULL); /* fixed mjb lmco 12/20/99 */ } else return (time_vme); diff --git a/contrib/ntp/ntpd/refclock_irig.c b/contrib/ntp/ntpd/refclock_irig.c index eccbda8..ab4b525 100644 --- a/contrib/ntp/ntpd/refclock_irig.c +++ b/contrib/ntp/ntpd/refclock_irig.c @@ -11,12 +11,6 @@ #include <ctype.h> #include <sys/time.h> #include <math.h> -#ifdef HAVE_SYS_AUDIOIO_H -#include <sys/audioio.h> -#endif /* HAVE_SYS_AUDIOIO_H */ -#ifdef HAVE_SUN_AUDIOIO_H -#include <sun/audioio.h> -#endif /* HAVE_SUN_AUDIOIO_H */ #ifdef HAVE_SYS_IOCTL_H #include <sys/ioctl.h> #endif /* HAVE_SYS_IOCTL_H */ @@ -26,6 +20,7 @@ #include "ntp_refclock.h" #include "ntp_calendar.h" #include "ntp_stdlib.h" +#include "audio.h" /* * Audio IRIG-B/E demodulator/decoder @@ -149,8 +144,7 @@ #define REFID "IRIG" /* reference ID */ #define DESCRIPTION "Generic IRIG Audio Driver" /* WRU */ -#define AUDIO_BUFSIZ 160 /* codec buffer size (Solaris only) */ -#define SAMPLES 8000 /* nominal sample rate (Hz) */ +#define SECOND 8000 /* nominal sample rate (Hz) */ #define BAUD 80 /* samples per baud interval */ #define OFFSET 128 /* companded sample offset */ #define SIZE 256 /* decompanding table size */ @@ -162,7 +156,7 @@ #define MAXSIG 6000. /* maximum signal level */ #define DRPOUT 100. /* dropout signal level */ #define MODMIN 0.5 /* minimum modulation index */ -#define MAXFREQ (250e-6 * SAMPLES) /* freq tolerance (.025%) */ +#define MAXFREQ (250e-6 * SECOND) /* freq tolerance (.025%) */ #define PI 3.1415926535 /* the real thing */ /* @@ -269,8 +263,6 @@ static void irig_base P((struct peer *, double)); static void irig_rf P((struct peer *, double)); static void irig_decode P((struct peer *, int)); static void irig_gain P((struct peer *)); -static int irig_audio P((void)); -static void irig_debug P((void)); /* * Transfer vector @@ -288,11 +280,6 @@ struct refclock refclock_irig = { /* * Global variables */ -#ifdef HAVE_SYS_AUDIOIO_H -struct audio_device device; /* audio device ident */ -#endif /* HAVE_SYS_AUDIOIO_H */ -static struct audio_info info; /* audio device info */ -static int irig_ctl_fd; /* audio control file descriptor */ static char hexchar[] = { /* really quick decoding table */ '0', '8', '4', 'c', /* 0000 0001 0010 0011 */ '2', 'a', '6', 'e', /* 0100 0101 0110 0111 */ @@ -323,11 +310,13 @@ irig_start( /* * Open audio device */ - fd = open("/dev/audio", O_RDWR | O_NONBLOCK, 0777); - if (fd == -1) { - perror("audio"); + fd = audio_init(); + if (fd < 0) return (0); - } +#ifdef DEBUG + if (debug) + audio_show(); +#endif /* * Allocate and initialize unit structure @@ -359,11 +348,7 @@ irig_start( up->tc = MINTC; up->decim = 1; up->fdelay = IRIG_B; - up->gain = (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN) / 2; - if (irig_audio() < 0) { - io_closeclock(&pp->io); - return(0); - } + up->gain = 127; up->pollcnt = 2; /* @@ -380,7 +365,7 @@ irig_start( if (i % 16 == 0) step *= 2.; } - DTOLFP(1. / SAMPLES, &up->tick); + DTOLFP(1. / SECOND, &up->tick); return (1); } @@ -436,7 +421,7 @@ irig_receive( */ up->timestamp = rbufp->recv_time; up->bufcnt = rbufp->recv_length; - DTOLFP((double)up->bufcnt / SAMPLES, <emp); + DTOLFP((double)up->bufcnt / SECOND, <emp); L_SUB(&up->timestamp, <emp); dpt = rbufp->recv_buffer; for (up->bufptr = 0; up->bufptr < up->bufcnt; up->bufptr++) { @@ -462,7 +447,7 @@ irig_receive( * unit produces a change of 360 degrees; a frequency * change of one unit produces a change of 1 Hz. */ - up->phase += up->freq / SAMPLES; + up->phase += up->freq / SECOND; if (up->phase >= .5) { up->phase -= 1.; } else if (up->phase < -.5) { @@ -478,7 +463,7 @@ irig_receive( * Once each second, determine the IRIG format, codec * port and gain. */ - up->seccnt = (up->seccnt + 1) % SAMPLES; + up->seccnt = (up->seccnt + 1) % SECOND; if (up->seccnt == 0) { if (up->irig_b > up->irig_e) { up->decim = 1; @@ -488,11 +473,10 @@ irig_receive( up->fdelay = IRIG_E; } if (pp->sloppyclockflag & CLK_FLAG2) - up->port = AUDIO_LINE_IN; + up->port = 2; else - up->port = AUDIO_MICROPHONE; + up->port = 1; irig_gain(peer); - up->clipcnt = 0; up->irig_b = up->irig_e = 0; } } @@ -755,7 +739,7 @@ irig_base( * this plus the delay since the last carrier positive * zero crossing. */ - DTOLFP(up->decim * (dtemp / SAMPLES + 1.) + up->fdelay, + DTOLFP(up->decim * (dtemp / SECOND + 1.) + up->fdelay, <emp); pp->lastrec = up->timestamp; L_SUB(&pp->lastrec, <emp); @@ -890,9 +874,9 @@ irig_decode( "%02x %c %2d %3d %02d:%02d:%02d %4.0f %3d %6.3f %2d %2d %6.3f %6.1f %s", up->errflg, syncchar, pp->year, pp->day, pp->hour, pp->minute, pp->second, - up->maxsignal, info.record.gain, up->modndx, + up->maxsignal, up->gain, up->modndx, up->envxing, up->tc, up->yxing, up->freq * - 1e6 / SAMPLES, ulfptoa(&up->montime, 6)); + 1e6 / SECOND, ulfptoa(&up->montime, 6)); pp->lencode = strlen(pp->a_lastcode); if (up->timecnt == 0 || pp->sloppyclockflag & CLK_FLAG4) @@ -964,116 +948,22 @@ irig_gain( /* * Apparently, the codec uses only the high order bits of the * gain control field. Thus, it may take awhile for changes to - * wiggle the hardware bits. Set the new bits in the structure - * and call AUDIO_SETINFO. Upon return, the old bits are in the - * structure. + * wiggle the hardware bits. */ if (up->clipcnt == 0) { up->gain += 4; - if (up->gain > AUDIO_MAX_GAIN) - up->gain = AUDIO_MAX_GAIN; - } else if (up->clipcnt > SAMPLES / 100) { + if (up->gain > 255) + up->gain = 255; + } else if (up->clipcnt > SECOND / 100) { up->gain -= 4; - if (up->gain < AUDIO_MIN_GAIN) - up->gain = AUDIO_MIN_GAIN; - } - AUDIO_INITINFO(&info); - info.record.port = up->port; - info.record.gain = up->gain; - info.record.error = 0; - ioctl(irig_ctl_fd, (int)AUDIO_SETINFO, &info); - if (info.record.error) - up->errflg |= IRIG_ERR_ERROR; -} - - -/* - * irig_audio - initialize audio device - * - * This code works with SunOS 4.1.3 and Solaris 2.6; however, it is - * believed generic and applicable to other systems with a minor twid - * or two. All it does is open the device, set the buffer size (Solaris - * only), preset the gain and set the input port. It assumes that the - * codec sample rate (8000 Hz), precision (8 bits), number of channels - * (1) and encoding (ITU-T G.711 mu-law companded) have been set by - * default. - */ -static int -irig_audio( - ) -{ - /* - * Open audio control device - */ - if ((irig_ctl_fd = open("/dev/audioctl", O_RDWR)) < 0) { - perror("audioctl"); - return(-1); + if (up->gain < 0) + up->gain = 0; } -#ifdef HAVE_SYS_AUDIOIO_H - /* - * Set audio device parameters. - */ - AUDIO_INITINFO(&info); - info.record.buffer_size = AUDIO_BUFSIZ; - if (ioctl(irig_ctl_fd, (int)AUDIO_SETINFO, &info) < 0) { - perror("AUDIO_SETINFO"); - close(irig_ctl_fd); - return(-1); - } -#endif /* HAVE_SYS_AUDIOIO_H */ -#ifdef DEBUG - irig_debug(); -#endif /* DEBUG */ - return(0); + audio_gain(up->gain, up->port); + up->clipcnt = 0; } -#ifdef DEBUG -/* - * irig_debug - display audio parameters - * - * This code doesn't really do anything, except satisfy curiousity and - * verify the ioctl's work. - */ -static void -irig_debug( - ) -{ - if (debug == 0) - return; -#ifdef HAVE_SYS_AUDIOIO_H - ioctl(irig_ctl_fd, (int)AUDIO_GETDEV, &device); - printf("irig: name %s, version %s, config %s\n", - device.name, device.version, device.config); -#endif /* HAVE_SYS_AUDIOIO_H */ - ioctl(irig_ctl_fd, (int)AUDIO_GETINFO, &info); - printf( - "irig: samples %d, channels %d, precision %d, encoding %d\n", - info.record.sample_rate, info.record.channels, - info.record.precision, info.record.encoding); -#ifdef HAVE_SYS_AUDIOIO_H - printf("irig: gain %d, port %d, buffer %d\n", - info.record.gain, info.record.port, - info.record.buffer_size); -#else /* HAVE_SYS_AUDIOIO_H */ - printf("irig: gain %d, port %d\n", - info.record.gain, info.record.port); -#endif /* HAVE_SYS_AUDIOIO_H */ - printf( - "irig: samples %d, eof %d, pause %d, error %d, waiting %d, balance %d\n", - info.record.samples, info.record.eof, - info.record.pause, info.record.error, - info.record.waiting, info.record.balance); -#ifdef __NetBSD__ - printf("irig: monitor %d, blocksize %d, hiwat %d, lowat %d, mode %d\n", - info.monitor_gain, info.blocksize, info.hiwat, info.lowat, info.mode); -#else /* __NetBSD__ */ - printf("irig: monitor %d, muted %d\n", - info.monitor_gain, info.output_muted); -#endif /* __NetBSD__ */ -} -#endif /* DEBUG */ - #else int refclock_irig_bs; #endif /* REFCLOCK */ diff --git a/contrib/ntp/ntpd/refclock_jupiter.c b/contrib/ntp/ntpd/refclock_jupiter.c index f22714b..b337e0c 100644 --- a/contrib/ntp/ntpd/refclock_jupiter.c +++ b/contrib/ntp/ntpd/refclock_jupiter.c @@ -762,10 +762,11 @@ jupiter_process(register struct peer *peer) } /* Compare two l_fp's, used with qsort() */ -int #ifdef QSORT_USES_VOID_P +int jupiter_cmpl_fp(register const void *p1, register const void *p2) #else +int jupiter_cmpl_fp(register const l_fp *fp1, register const l_fp *fp2) #endif { @@ -960,7 +961,7 @@ jupiter_pps(register struct peer *peer) /* * jupiter_debug - print debug messages */ -#if __STDC__ +#if defined(__STDC__) static void jupiter_debug(struct peer *peer, char *fmt, ...) #else @@ -968,17 +969,17 @@ static void jupiter_debug(peer, fmt, va_alist) struct peer *peer; char *fmt; -#endif +#endif /* __STDC__ */ { va_list ap; if (debug) { -#if __STDC__ +#if defined(__STDC__) va_start(ap, fmt); #else va_start(ap); -#endif +#endif /* __STDC__ */ /* * Print debug message to stdout * In the future, we may want to get get more creative... diff --git a/contrib/ntp/ntpd/refclock_msfees.c b/contrib/ntp/ntpd/refclock_msfees.c index 01fe27f..db6c6b1 100644 --- a/contrib/ntp/ntpd/refclock_msfees.c +++ b/contrib/ntp/ntpd/refclock_msfees.c @@ -322,10 +322,6 @@ static int deltas[60]; static l_fp acceptable_slop; /* = { 0, 1 << (FRACTION_PREC -2) }; */ static l_fp onesec; /* = { 1, 0 }; */ -#ifdef DEBUG -static int debug; -#endif - #ifndef DUMP_BUF_SIZE /* Size of buffer to be used by dump_buf */ #define DUMP_BUF_SIZE 10112 #endif @@ -354,8 +350,13 @@ static void msfees_init P((void)); static void dump_buf P((l_fp *coffs, int from, int to, char *text)); static void ees_report_event P((struct eesunit *ees, int code)); static void ees_receive P((struct recvbuf *rbufp)); -static int offcompare P((l_fp *a, l_fp *b)); static void ees_process P((struct eesunit *ees)); +#ifdef QSORT_USES_VOID_P +static int offcompare P((const void *va, const void *vb)); +#else +static int offcompare P((const l_fp *a, const l_fp *b)); +#endif /* QSORT_USES_VOID_P */ + /* * Transfer vector @@ -1221,14 +1222,27 @@ ees_receive( /* offcompare - auxiliary comparison routine for offset sort */ +#ifdef QSORT_USES_VOID_P +static int +offcompare( + const void *va, + const void *vb + ) +{ + const l_fp *a = (const l_fp *)va; + const l_fp *b = (const l_fp *)vb; + return(L_ISGEQ(a, b) ? (L_ISEQU(a, b) ? 0 : 1) : -1); +} +#else static int offcompare( - l_fp *a, - l_fp *b + const l_fp *a, + const l_fp *b ) { return(L_ISGEQ(a, b) ? (L_ISEQU(a, b) ? 0 : 1) : -1); } +#endif /* QSORT_USES_VOID_P */ /* ees_process - process a pile of samples from the clock */ @@ -1349,12 +1363,12 @@ ees_process( new = offset.l_uf + ((diff * (samd -1)) / samd); /* Sign change -> need to fix up int part */ - if ((new & (1 << 31)) != - (((long) offset.l_uf) & ( 1 << 31))) + if ((new & 0x80000000) != + (((long) offset.l_uf) & 0x80000000)) { NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */ msyslog(LOG_INFO, "I: %lx != %lx (%lx %lx), so add %d", - new & (1 << 31), - ((long) offset.l_uf) & ( 1 << 31), + new & 0x80000000, + ((long) offset.l_uf) & 0x80000000, new, (long) offset.l_uf, (new < 0) ? -1 : 1); offset.l_ui += (new < 0) ? -1 : 1; diff --git a/contrib/ntp/ntpd/refclock_mx4200.c b/contrib/ntp/ntpd/refclock_mx4200.c index 28f563f..f08bb23 100644 --- a/contrib/ntp/ntpd/refclock_mx4200.c +++ b/contrib/ntp/ntpd/refclock_mx4200.c @@ -127,9 +127,6 @@ struct ppsclockev { */ #define INTERVAL 1 /* Interval between position measurements (s) */ #define AVGING_TIME 24 /* Number of hours to average */ -#define USUAL_EDOP 1.06066 /* used for normalizing EDOP */ -#define USUAL_NDOP 1.06066 /* used for normalizing NDOP */ -#define USUAL_VDOP 2.00 /* used for normalizing VDOP */ #define NOT_INITIALIZED -9999. /* initial pivot longitude */ /* @@ -165,13 +162,13 @@ static char pmvxg[] = "PMVXG"; #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) #ifndef __attribute__ #define __attribute__(args) -#endif -#endif +#endif /* __attribute__ */ +#endif /* __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) */ #else #ifndef __attribute__ #define __attribute__(args) -#endif -#endif +#endif /* __attribute__ */ +#endif /* __GNUC__ */ /* XXX end */ /* @@ -230,18 +227,6 @@ mx4200_start( int fd; char gpsdev[20]; -#ifdef HAVE_TIOCGPPSEV -#ifdef HAVE_TERMIOS - struct termios ttyb; -#endif /* HAVE_TERMIOS */ -#ifdef HAVE_SYSV_TTYS - struct termio ttyb; -#endif /* HAVE_SYSV_TTYS */ -#ifdef HAVE_BSD_TTYS - struct sgttyb ttyb; -#endif /* HAVE_BSD_TTYS */ -#endif /* HAVE_TIOCGPPSEV */ - /* * Open serial port */ @@ -249,24 +234,6 @@ mx4200_start( if (!(fd = refclock_open(gpsdev, SPEED232, LDISC_PPS))) { return (0); } -#ifdef HAVE_TIOCGPPSEV - if (fdpps > 0) { - /* - * Truly nasty hack in order to get this to work on Solaris 7. - * Really, refclock_open() should set the port properly, but - * it doesn't work (as of ntp-4.0.98a) - almost 99% dropped - * PPS signals with "Interrupted system call". Even this - * still gives a 5% error rate. - */ - ttyb.c_iflag = IGNCR; - ttyb.c_oflag = 0; - ttyb.c_cflag = CS8 | CREAD | CLOCAL; - ttyb.c_lflag = ICANON; - if (tcsetattr(fdpps, TCSAFLUSH, &ttyb) < 0) { - return (0); - } - } -#endif /* HAVE_TIOCGPPSEV */ /* * Allocate unit structure @@ -360,9 +327,9 @@ mx4200_config( up->filt_lat = 0.0; up->filt_lon = 0.0; up->filt_alt = 0.0; - up->edop = USUAL_EDOP; - up->ndop = USUAL_NDOP; - up->vdop = USUAL_VDOP; + up->edop = 1; + up->ndop = 1; + up->vdop = 1; up->last_leap = 0; /* LEAP_NOWARNING */ up->clamp_time = current_time + (AVGING_TIME * 60 * 60); up->log_time = current_time + SLEEPTIME; @@ -612,7 +579,7 @@ mx4200_ref( minute = (lon - (double)(int)lon) * 60.0; sprintf(lons,"%03d%02.4f", (int)lon, minute); - mx4200_send(peer, "%s,%03d,,,,,%s,%c,%s,%c,%.2f,", pmvxg, + mx4200_send(peer, "%s,%03d,,,,,%s,%c,%s,%c,%.2f,%d", pmvxg, PMVXG_S_INITMODEA, /* day of month */ /* month of year */ @@ -622,8 +589,8 @@ mx4200_ref( nsc, /* north/south */ lons, /* longitude DDDMM.MMMM */ ewc, /* east/west */ - alt); /* Altitude */ - /* Altitude Reference */ + alt, /* Altitude */ + 1); /* Altitude Reference (0=WGS84 ellipsoid, 1=MSL geoid) */ msyslog(LOG_DEBUG, "mx4200: reconfig to fixed location: %s %c, %s %c, %.2f m", @@ -1359,19 +1326,19 @@ mx4200_parse_p( /* * Calculate running weighted averages */ - weight = USUAL_EDOP / up->edop; + weight = 1. / up->edop; weight *= weight; up->avg_lon = (up->filt_lon * up->avg_lon) + (weight * lon); up->filt_lon += weight; up->avg_lon = up->avg_lon / up->filt_lon; - weight = USUAL_NDOP / up->ndop; + weight = 1. / up->ndop; weight *= weight; up->avg_lat = (up->filt_lat * up->avg_lat) + (weight * lat); up->filt_lat += weight; up->avg_lat = up->avg_lat / up->filt_lat; - weight = USUAL_VDOP / up->vdop; + weight = 1. / up->vdop; weight *= weight; up->avg_alt = (up->filt_alt * up->avg_alt) + (weight * alt); up->filt_alt += weight; @@ -1673,15 +1640,15 @@ mx4200_pps( /* * mx4200_debug - print debug messages */ -#if __STDC__ +#if defined(__STDC__) static void mx4200_debug(struct peer *peer, char *fmt, ...) #else - static void +static void mx4200_debug(peer, fmt, va_alist) struct peer *peer; char *fmt; -#endif +#endif /* __STDC__ */ { va_list ap; struct refclockproc *pp; @@ -1689,11 +1656,11 @@ mx4200_debug(peer, fmt, va_alist) if (debug) { -#if __STDC__ +#if defined(__STDC__) va_start(ap, fmt); #else va_start(ap); -#endif +#endif /* __STDC__ */ pp = peer->procptr; up = (struct mx4200unit *)pp->unitptr; @@ -1712,11 +1679,12 @@ mx4200_debug(peer, fmt, va_alist) /* * Send a character string to the receiver. Checksum is appended here. */ +#if defined(__STDC__) static void -#if __STDC__ mx4200_send(struct peer *peer, char *fmt, ...) #else - mx4200_send(peer, fmt, va_alist) +static void +mx4200_send(peer, fmt, va_alist) struct peer *peer; char *fmt; va_dcl @@ -1731,7 +1699,7 @@ mx4200_send(struct peer *peer, char *fmt, ...) char buf[1024]; u_char ck; -#if __STDC__ +#if defined(__STDC__) va_start(ap, fmt); #else va_start(ap); diff --git a/contrib/ntp/ntpd/refclock_nmea.c b/contrib/ntp/ntpd/refclock_nmea.c index 211d01e..d90f71c 100644 --- a/contrib/ntp/ntpd/refclock_nmea.c +++ b/contrib/ntp/ntpd/refclock_nmea.c @@ -32,7 +32,11 @@ /* * Definitions */ -#define DEVICE "/dev/gps%d" /* name of radio device */ +#ifdef SYS_WINNT +# define DEVICE "COM%d:" /* COM 1 - 3 supported */ +#else +# define DEVICE "/dev/gps%d" /* name of radio device */ +#endif #define SPEED232 B4800 /* uart speed (4800 bps) */ #define PRECISION (-9) /* precision assumed (about 2 ms) */ #define DCD_PRECISION (-20) /* precision assumed (about 1 us) */ @@ -98,6 +102,7 @@ nmea_start( * Open serial port. Use CLK line discipline, if available. */ (void)sprintf(device, DEVICE, unit); + if (!(fd = refclock_open(device, SPEED232, LDISC_CLK))) return (0); diff --git a/contrib/ntp/ntpd/refclock_oncore.c b/contrib/ntp/ntpd/refclock_oncore.c index 9ff3d23..e0ba177 100644 --- a/contrib/ntp/ntpd/refclock_oncore.c +++ b/contrib/ntp/ntpd/refclock_oncore.c @@ -55,6 +55,13 @@ #define POS_HOLD_AVERAGE 10000 /* nb, 10000s ~= 2h45m */ +/* + * ONCORE_SHMEM_STATUS will create a mmap(2)'ed file named according to a + * "STATUS" line in the oncore config file, which contains the most recent + * copy of all types of messages we recognize. This file can be mmap(2)'ed + * by monitoring and statistics programs. + */ + #ifdef HAVE_CONFIG_H #include <config.h> #endif @@ -66,6 +73,14 @@ #include <sys/types.h> #include <sys/time.h> #include <sys/stat.h> +#ifdef ONCORE_SHMEM_STATUS +# ifdef HAVE_SYS_MMAN_H +# include <sys/mman.h> +# ifndef MAP_FAILED +# define MAP_FAILED ((u_char *) -1) +# endif /* not MAP_FAILED */ +# endif /* HAVE_SYS_MMAN_H */ +#endif /* ONCORE_SHMEM_STATUS */ #ifdef HAVE_PPSAPI # ifdef HAVE_TIMEPPS_H @@ -77,6 +92,10 @@ # endif #endif +#ifdef HAVE_SYS_SIO_H +# include <sys/sio.h> +#endif + #include "ntpd.h" #include "ntp_io.h" #include "ntp_unixtime.h" @@ -122,6 +141,8 @@ struct instance { int unit; /* 127.127.30.unit */ int ttyfd; /* TTY file descriptor */ int ppsfd; /* PPS file descriptor */ + int statusfd; /* Status shm descriptor */ + u_char *shmem; #ifdef HAVE_PPSAPI pps_handle_t pps_h; pps_params_t pps_p; @@ -134,7 +155,6 @@ struct instance { struct peer *peer; int Bj_day; - int assert; long delay; /* ns */ long offset; /* ns */ @@ -144,11 +164,11 @@ struct instance { double ss_ht; int ss_count; u_char ss_ht_type; - int posn_set; + u_char posn_set; - int printed; + u_char printed; + u_char polled; int pollcnt; - int polled; u_int ev_serial; int Rcvptr; u_char Rcvbuf[500]; @@ -160,6 +180,8 @@ struct instance { u_char Az; u_char init_type; s_char saw_tooth; + u_char timeout; /* flag to retry Cj after Fa reset */ + s_char assert; }; #define rcvbuf instance->Rcvbuf @@ -172,7 +194,6 @@ static void oncore_receive P((struct recvbuf *)); static void oncore_sendmsg P((int fd, u_char *, u_int)); static void oncore_shutdown P((int, struct peer *)); static int oncore_start P((int, struct peer *)); -static void oncore_stats P((struct instance *)); static void oncore_msg_any P((struct instance *, u_char *, u_int, int)); static void oncore_msg_As P((struct instance *, u_char *, u_int)); @@ -180,6 +201,7 @@ static void oncore_msg_At P((struct instance *, u_char *, u_int)); static void oncore_msg_Ay P((struct instance *, u_char *, u_int)); static void oncore_msg_Az P((struct instance *, u_char *, u_int)); static void oncore_msg_Bj P((struct instance *, u_char *, u_int)); +static void oncore_msg_Cb P((struct instance *, u_char *, u_int)); static void oncore_msg_Cf P((struct instance *, u_char *, u_int)); static void oncore_msg_Cj P((struct instance *, u_char *, u_int)); static void oncore_msg_Ea P((struct instance *, u_char *, u_int)); @@ -201,11 +223,12 @@ struct refclock refclock_oncore = { * for the the UT or VP Oncore. */ -static struct { +static struct msg_desc { const char flag[3]; const int len; void (*handler) P((struct instance *, u_char *, u_int)); const char *fmt; + int shmem; } oncore_messages[] = { /* Ea and En first since they're most common */ { "Ea", 76, oncore_msg_Ea, "mdyyhmsffffaaaaoooohhhhmmmmvvhhddtntimsdimsdimsdimsdimsdimsdimsdimsdsC" }, @@ -223,7 +246,7 @@ static struct { { "AB", 8, 0, "" }, { "Bb", 92, 0, "" }, { "Bj", 8, oncore_msg_Bj, "" }, - { "Cb", 33, 0, "" }, + { "Cb", 33, oncore_msg_Cb, "" }, { "Cf", 7, oncore_msg_Cf, "" }, { "Cg", 8, 0, "" }, { "Ch", 9, 0, "" }, @@ -234,6 +257,7 @@ static struct { { {0}, 7, 0, ""} }; +static unsigned int oncore_shmem_Cb; /* * Position Set. @@ -262,6 +286,11 @@ u_char oncore_cmd_Asx[]= { 'A', 's', 0x7f, 0xff, 0xff, 0xff, u_char oncore_cmd_Aw[] = { 'A', 'w', 1 }; /* + * Output Almanac when it changes + */ +u_char oncore_cmd_Be[] = { 'B', 'e', 1 }; + +/* * Read back PPS Offset for Output */ u_char oncore_cmd_Ay[] = { 'A', 'y', 0, 0, 0, 0 }; @@ -281,7 +310,7 @@ u_char oncore_cmd_AB[] = { 'A', 'B', 4 }; /* * Visible Satellite Status Msg. */ -u_char oncore_cmd_Bb[] = { 'B', 'b', 0 }; /* just turn off */ +u_char oncore_cmd_Bb[] = { 'B', 'b', 1 }; /* * Leap Second Pending Message @@ -357,6 +386,10 @@ static u_char oncore_cmd_Fa[] = { 'F', 'a' }; /* from buffer, char *buf, result to an int */ #define buf_w32(buf) (((buf)[0]&0200) ? (-(~w32(buf)+1)) : w32(buf)) +extern int pps_assert; +extern int pps_hardpps; + + /* * oncore_start - initialize data for processing */ @@ -400,8 +433,7 @@ oncore_start( if ((stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino)) { /* same device here */ if (!(fd1 = refclock_open(device1, SPEED, LDISC_RAW -#ifdef HAVE_PPSAPI -#else +#if !defined(HAVE_PPSAPI) && !defined(TIOCDCDTIMESTAMP) | LDISC_PPS #endif ))) { @@ -435,7 +467,7 @@ oncore_start( instance->ppsfd = fd2; instance->Bj_day = -1; - instance->assert = 1; + instance->assert = pps_assert; /* go read any input data in /etc/ntp.oncoreX */ @@ -444,10 +476,26 @@ oncore_start( #ifdef HAVE_PPSAPI if (time_pps_create(fd2, &instance->pps_h) < 0) { perror("time_pps_create"); - exit(1); + return(0); } - if (instance->assert) { + if (time_pps_getcap(instance->pps_h, &mode) < 0) { + msyslog(LOG_ERR, + "refclock_ioctl: time_pps_getcap failed: %m"); + return (0); + } + + if (time_pps_getparams(instance->pps_h, &instance->pps_p) < 0) { + msyslog(LOG_ERR, + "refclock_ioctl: time_pps_getparams failed: %m"); + return (0); + } + + /* nb. only turn things on, if someone else has turned something + * on before we get here, leave it alone! + */ + + if (instance->assert) { /* nb, default or ON */ instance->pps_p.mode = PPS_CAPTUREASSERT | PPS_OFFSETASSERT; instance->pps_p.assert_offset.tv_sec = 0; instance->pps_p.assert_offset.tv_nsec = 0; @@ -457,16 +505,41 @@ oncore_start( instance->pps_p.clear_offset.tv_nsec = 0; } instance->pps_p.mode |= PPS_TSFMT_TSPEC; + instance->pps_p.mode &= mode; /* only do it if it is legal */ + if (time_pps_setparams(instance->pps_h, &instance->pps_p) < 0) { perror("time_pps_setparams"); exit(1); } - if (time_pps_kcbind(instance->pps_h, PPS_KC_HARDPPS, - instance->pps_p.mode & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR), - PPS_TSFMT_TSPEC) < 0) { - perror("time_pps_kcbind"); + + if (pps_device) { + if (stat(pps_device, &stat1)) { + perror("ONCORE: stat pps_device"); + return(0); + } + + /* must have hardpps ON, and fd2 must be the same device as on the pps line */ + + if (pps_hardpps && ((stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino))) { + int i; + + if (instance->assert) + i = PPS_CAPTUREASSERT; + else + i = PPS_CAPTURECLEAR; + + if (i&mode) { + if (time_pps_kcbind(instance->pps_h, PPS_KC_HARDPPS, i, + PPS_TSFMT_TSPEC) < 0) { + msyslog(LOG_ERR, + "refclock_ioctl: time_pps_kcbind failed: %m"); + return (0); + } + } + } } #endif + instance->pp = pp; instance->peer = peer; instance->o_state = ONCORE_NO_IDEA; @@ -500,6 +573,7 @@ oncore_start( * We send info from config to Oncore later. */ + instance->timeout = 1; mode = instance->init_type; if (mode == 3 || mode == 4) { oncore_sendmsg(instance->ttyfd, oncore_cmd_Cf, sizeof oncore_cmd_Cf); @@ -514,10 +588,85 @@ oncore_start( } instance->pollcnt = 2; - return (1); } + + +static void +oncore_init_shmem(struct instance *instance, char *filename) +{ +#ifdef ONCORE_SHMEM_STATUS + int i, l, n; + char *buf; + struct msg_desc *mp; + static unsigned int oncore_shmem_length; + + if (oncore_messages[0].shmem == 0) { + n = 1; + for (mp = oncore_messages; mp->flag[0]; mp++) { + mp->shmem = n; + /* Allocate space for multiplexed almanac */ + if (!strcmp(mp->flag, "Cb")) { + oncore_shmem_Cb = n; + n += (mp->len + 2) * 34; + } + n += mp->len + 2; + } + oncore_shmem_length = n + 2; + fprintf(stderr, "ONCORE: SHMEM length: %d bytes\n", oncore_shmem_length); + } + instance->statusfd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0644); + if (instance->statusfd < 0) { + perror(filename); + exit(4); + } + buf = malloc(oncore_shmem_length); + if (buf == NULL) { + perror("malloc"); + exit(4); + } + memset(buf, 0, sizeof(buf)); + i = write(instance->statusfd, buf, oncore_shmem_length); + if (i != oncore_shmem_length) { + perror(filename); + exit(4); + } + free(buf); + instance->shmem = (u_char *) mmap(0, oncore_shmem_length, + PROT_READ | PROT_WRITE, +#ifdef MAP_HASSEMAPHORE + MAP_HASSEMAPHORE | +#endif + MAP_SHARED, + instance->statusfd, (off_t)0); + if (instance->shmem == MAP_FAILED) { + instance->shmem = 0; + close (instance->statusfd); + exit(4); + } + for (mp = oncore_messages; mp->flag[0]; mp++) { + l = mp->shmem; + instance->shmem[l + 0] = mp->len >> 8; + instance->shmem[l + 1] = mp->len & 0xff; + instance->shmem[l + 2] = '@'; + instance->shmem[l + 3] = '@'; + instance->shmem[l + 4] = mp->flag[0]; + instance->shmem[l + 5] = mp->flag[1]; + if (!strcmp(mp->flag, "Cb")) { + for (i = 1; i < 35; i++) { + instance->shmem[l + i * 35 + 0] = mp->len >> 8; + instance->shmem[l + i * 35 + 1] = mp->len & 0xff; + instance->shmem[l + i * 35 + 2] = '@'; + instance->shmem[l + i * 35 + 3] = '@'; + instance->shmem[l + i * 35 + 4] = mp->flag[0]; + instance->shmem[l + i * 35 + 5] = mp->flag[1]; + } + } + } +#endif /* ONCORE_SHMEM_STATUS */ +} + /* * Read Input file if it exists. */ @@ -603,11 +752,10 @@ oncore_read_config( */ FILE *fd; - char *cp, line[100], units[2], device[20]; - int i, j, sign, lat_flg, long_flg, ht_flg, mode; + char *cp, *cc, *ca, line[100], units[2], device[20]; + int i, sign, lat_flg, long_flg, ht_flg, mode; double f1, f2, f3; - sprintf(device, "%s%d", INIT_FILE, instance->unit); if ((fd=fopen(device, "r")) == NULL) if ((fd=fopen(INIT_FILE, "r")) == NULL) { @@ -618,22 +766,54 @@ oncore_read_config( mode = 0; lat_flg = long_flg = ht_flg = 0; while (fgets(line, 100, fd)) { - if ((cp=strchr(line, '#'))) + + /* Remove comments */ + if ((cp = strchr(line, '#'))) *cp = '\0'; - i = strlen(line); - for (j=0; j<i; j++) /* just in case lower case */ - if (islower((int)line[j])) - line[j] = toupper(line[j]); - for (j=0; j<i; j++) /* let them use `=' between terms */ - if (line[j] == '=') - line[j] = ' '; - for (j=0; j<i; j++) - if (line[j] != ' ') + + /* Remove trailing space */ + for (i = strlen(line); + i > 0 && isascii((int)line[i - 1]) && isspace((int)line[i - 1]); + ) + line[--i] = '\0'; + + /* Remove leading space */ + for (cc = line; *cc && isascii((int)*cc) && isspace((int)*cc); cc++) + continue; + + /* Stop if nothing left */ + if (!*cc) + continue; + + /* Lowercase the command and find the arg */ + for (ca = cc; *ca; ca++) { + if (isascii((int)*ca) && islower((int)*ca)) { + *ca = toupper(*ca); + } else if (isascii((int)*ca) && isspace((int)*ca)) { break; - if (!strncmp(&line[j], "LAT", 3)) { - j += 3; + } else if (*ca == '=') { + *ca = ' '; + break; + } + } + + /* Remove space leading the arg */ + for (; *ca && isascii((int)*ca) && isspace((int)*ca); ca++) + continue; + + if (!strncmp(cc, "STATUS", 6)) { + oncore_init_shmem(instance, ca); + continue; + } + + /* Uppercase argument as well */ + for (cp = ca; *cp; cp++) + if (isascii((int)*cp) && islower((int)*cp)) + *cp = toupper(*cp); + + if (!strncmp(cc, "LAT", 3)) { f1 = f2 = f3 = 0; - sscanf(&line[j], "%lf %lf %lf", &f1, &f2, &f3); + sscanf(ca, "%lf %lf %lf", &f1, &f2, &f3); sign = 1; if (f1 < 0) { f1 = -f1; @@ -641,10 +821,9 @@ oncore_read_config( } instance->ss_lat = sign*1000*(fabs(f3) + 60*(fabs(f2) + 60*f1)); /*miliseconds*/ lat_flg++; - } else if (!strncmp(&line[j], "LON", 3)) { - j += 3; + } else if (!strncmp(cc, "LON", 3)) { f1 = f2 = f3 = 0; - sscanf(&line[j], "%lf %lf %lf", &f1, &f2, &f3); + sscanf(ca, "%lf %lf %lf", &f1, &f2, &f3); sign = 1; if (f1 < 0) { f1 = -f1; @@ -652,29 +831,24 @@ oncore_read_config( } instance->ss_long = sign*1000*(fabs(f3) + 60*(fabs(f2) + 60*f1)); /*miliseconds*/ long_flg++; - } else if (!strncmp(&line[j], "HT", 2)) { - instance->ss_ht_type = 0; - if (!strncmp(&line[j], "HTGPS", 5)) { + } else if (!strncmp(cc, "HT", 2)) { + if (!strncmp(cc, "HTGPS", 5)) instance->ss_ht_type = 0; - j +=3; - } - if (!strncmp(&line[j], "HTMSL", 5)) { + else if (!strncmp(cc, "HTMSL", 5)) instance->ss_ht_type = 1; - j +=3; - } - j += 2; + else + instance->ss_ht_type = 0; f1 = 0; units[0] = '\0'; - sscanf(&line[j], "%lf %1s", &f1, units); + sscanf(ca, "%lf %1s", &f1, units); if (units[0] == 'F') f1 = 0.3048 * f1; instance->ss_ht = 100 * f1; /* cm */ ht_flg++; - } else if (!strncmp(&line[j], "DELAY", 5)) { - j += 5; + } else if (!strncmp(cc, "DELAY", 5)) { f1 = 0; units[0] = '\0'; - sscanf(&line[j], "%lf %1s", &f1, units); + sscanf(ca, "%lf %1s", &f1, units); if (units[0] == 'N') ; else if (units[0] == 'U') @@ -686,11 +860,10 @@ oncore_read_config( if (f1 < 0 || f1 > 1.e9) f1 = 0; instance->delay = f1; /* delay in ns */ - } else if (!strncmp(&line[j], "OFFSET", 6)) { - j += 6; + } else if (!strncmp(cc, "OFFSET", 6)) { f1 = 0; units[0] = '\0'; - sscanf(&line[j], "%lf %1s", &f1, units); + sscanf(ca, "%lf %1s", &f1, units); if (units[0] == 'N') ; else if (units[0] == 'U') @@ -702,15 +875,14 @@ oncore_read_config( if (f1 < 0 || f1 > 1.e9) f1 = 0; instance->offset = f1; /* offset in ns */ - } else if (!strncmp(&line[j], "MODE", 4)) { - j += 4; - sscanf(&line[j], "%d", &mode); + } else if (!strncmp(cc, "MODE", 4)) { + sscanf(ca, "%d", &mode); if (mode < 0 || mode > 4) mode = 4; instance->init_type = mode; - } else if (!strncmp(&line[j], "ASSERT", 6)) { + } else if (!strncmp(cc, "ASSERT", 6)) { instance->assert = 1; - } else if (!strncmp(&line[j], "CLEAR", 5)) { + } else if (!strncmp(cc, "CLEAR", 5)) { instance->assert = 0; } } @@ -763,6 +935,16 @@ oncore_poll( struct instance *instance; instance = (struct instance *) peer->procptr->unitptr; + if (instance->timeout) { + char *cp; + + oncore_sendmsg(instance->ttyfd, oncore_cmd_Cj, sizeof oncore_cmd_Cj); + instance->o_state = ONCORE_ID_SENT; + cp = "state = ONCORE_ID_SENT"; + record_clock_stats(&(instance->peer->srcadr), cp); + return; + } + if (!instance->pollcnt) refclock_report(peer, CEVNT_TIMEOUT); else @@ -822,7 +1004,8 @@ oncore_consume( struct instance *instance ) { - int i, l, j, m; + int i, j, m; + unsigned l; while (rcvptr >= 7) { if (rcvbuf[0] != '@' || rcvbuf[1] != '@') { @@ -858,6 +1041,9 @@ oncore_consume( for (i = 2; i < l-3; i++) j ^= rcvbuf[i]; if (j == rcvbuf[l-3]) { + if (instance->shmem != NULL) + memcpy(instance->shmem + oncore_messages[m].shmem + 2, + rcvbuf, l); oncore_msg_any(instance, rcvbuf, (unsigned) (l-3), m); if (oncore_messages[m].handler) oncore_messages[m].handler(instance, rcvbuf, (unsigned) (l-3)); @@ -942,6 +1128,33 @@ oncore_msg_any( /* + * Demultiplex the almanac into shmem + */ +static void +oncore_msg_Cb( + struct instance *instance, + u_char *buf, + u_int len + ) +{ + int i; + + if (instance->shmem == NULL) + return; + + if (buf[4] == 5) + i = buf[5]; + else if (buf[4] == 4 && buf[5] <= 5) + i = buf[5] + 24; + else if (buf[4] == 4 && buf[5] <= 10) + i = buf[5] + 23; + else + i = 34; + i *= 35; + memcpy(instance->shmem + oncore_shmem_Cb + i + 2, buf, len + 3); +} + +/* * Set to Factory Defaults (Reasonable for UT w/ no Battery Backup * not so for VP (eeprom) or UT with battery */ @@ -964,6 +1177,15 @@ oncore_msg_Cf( +/* there are good reasons NOT to do a @@Fa command with the ONCORE. + * Doing it, it was found that under some circumstances the following + * command would fail if issued immediately after the return from the + * @@Fa, but a 2sec delay seemed to fix things. Since simply calling + * sleep(2) is wastefull, and may cause trouble for some OS's, repeating + * itimer, we set a flag, and test it at the next POLL. If it hasnt + * been cleared, we reissue the @@Ca that is issued below. + */ + static void oncore_msg_Fa( struct instance *instance, @@ -981,12 +1203,6 @@ oncore_msg_Fa( exit(1); } - /* sometimes the @@Cj request does not produce any output - PERHAPS the ONCORE is still busy from the selftest??? - try a 2 second sleep here to see if it makes any difference - */ - - sleep(2); oncore_sendmsg(instance->ttyfd, oncore_cmd_Cj, sizeof oncore_cmd_Cj); instance->o_state = ONCORE_ID_SENT; cp = "state = ONCORE_ID_SENT"; @@ -1006,19 +1222,41 @@ oncore_msg_Cj( u_int len ) { - const char *cp; + char *cp, *cp1; int mode; + instance->timeout = 0; if (instance->o_state != ONCORE_ID_SENT) return; memcpy(instance->Cj, buf, len); + /* Write Receiver ID to clockstats file */ + + instance->Cj[294] = '\0'; + for (cp=(char *)instance->Cj; cp< (char *) &instance->Cj[294]; ) { + cp1 = strchr(cp, '\r'); + if (!cp1) + cp1 = (char *)&instance->Cj[294]; + *cp1 = '\0'; + record_clock_stats(&(instance->peer->srcadr), cp); + *cp1 = '\r'; + cp = cp1+2; + } +#ifdef HAVE_PPSAPI + if (instance->assert) + cp = "Timing on Assert."; + else + cp = "Timing on Clear."; + record_clock_stats(&(instance->peer->srcadr), cp); +#endif + oncore_sendmsg(instance->ttyfd, oncore_cmd_Cg, sizeof oncore_cmd_Cg); /* Set Posn Fix mode (not Idle (VP)) */ oncore_sendmsg(instance->ttyfd, oncore_cmd_Bb, sizeof oncore_cmd_Bb); /* turn off */ oncore_sendmsg(instance->ttyfd, oncore_cmd_Ek, sizeof oncore_cmd_Ek); /* turn off */ oncore_sendmsg(instance->ttyfd, oncore_cmd_Aw, sizeof oncore_cmd_Aw); /* UTC time */ oncore_sendmsg(instance->ttyfd, oncore_cmd_AB, sizeof oncore_cmd_AB); /* Appl type static */ + oncore_sendmsg(instance->ttyfd, oncore_cmd_Be, sizeof oncore_cmd_Be); /* Tell us the Almanac */ mode = instance->init_type; if (debug) @@ -1094,6 +1332,7 @@ oncore_msg_Ea( ) { const char *cp; + char Msg[160]; if (instance->o_state != ONCORE_ALMANAC && instance->o_state != ONCORE_RUN) return; @@ -1128,6 +1367,7 @@ oncore_msg_Ea( /* Read back Position Hold Params */ oncore_sendmsg(instance->ttyfd, oncore_cmd_Asx, sizeof oncore_cmd_Asx); /* Read back PPS Offset for Output */ + /* Nb. This will fail silently for early UT (no plus) model */ oncore_sendmsg(instance->ttyfd, oncore_cmd_Ayx, sizeof oncore_cmd_Ayx); /* Read back Cable Delay for Output */ oncore_sendmsg(instance->ttyfd, oncore_cmd_Azx, sizeof oncore_cmd_Azx); @@ -1184,14 +1424,6 @@ oncore_msg_Ea( instance->ss_ht += buf_w32(&instance->Ea[23]); /* GPS ellipse */ instance->ss_count++; - if (debug) - printf("ONCORE: AVG %d %d %d %d\n", - instance->ss_count, - (unsigned) (instance->ss_lat / instance->ss_count), - (unsigned) (instance->ss_long / instance->ss_count), - (unsigned) (instance->ss_ht / instance->ss_count) - ); - if (instance->ss_count != POS_HOLD_AVERAGE) return; @@ -1199,6 +1431,10 @@ oncore_msg_Ea( instance->ss_long /= POS_HOLD_AVERAGE; instance->ss_ht /= POS_HOLD_AVERAGE; + sprintf(Msg, "Surveyed posn: lat %.3f long %.3f ht %.3f", + instance->ss_lat, instance->ss_long, instance->ss_ht); + record_clock_stats(&(instance->peer->srcadr), Msg); + w32_buf(&oncore_cmd_As[2], (int) instance->ss_lat); w32_buf(&oncore_cmd_As[6], (int) instance->ss_long); w32_buf(&oncore_cmd_As[10], (int) instance->ss_ht); @@ -1240,6 +1476,9 @@ oncore_msg_En( struct ppsclockev ev; int r = TIOCGPPSEV; #endif +#if TIOCDCDTIMESTAMP + struct timeval tv; +#endif #endif /* ! HAVE_PPS_API */ if (instance->o_state != ONCORE_RUN) @@ -1311,7 +1550,8 @@ oncore_msg_En( DTOLFP(dmy, &ts); ts.l_ui = tsp->tv_sec; #endif /* 0 */ -#else /* ! HAVE_PPSAPI */ +#else +# if defined(HAVE_TIOCGPPSEV) || defined(HAVE_CIOGETEV) j = instance->ev_serial; if (ioctl(instance->ppsfd, r, (caddr_t) &ev) < 0) { perror("ONCORE: IOCTL:"); @@ -1333,6 +1573,18 @@ oncore_msg_En( /* convert timeval -> ntp l_fp */ TVTOTS(tsp, &ts); +# else +# if defined(TIOCDCDTIMESTAMP) + if(ioctl(instance->ppsfd, TIOCDCDTIMESTAMP, &tv) < 0) { + perror("ONCORE: ioctl(TIOCDCDTIMESTAMP)"); + return; + } + tsp = &tv; + TVTOTS(tsp, &ts); +# else +#error "Cannot compile -- no PPS mechanism configured!" +# endif +# endif #endif /* now have timestamp in ts */ /* add in saw_tooth and offset */ @@ -1427,19 +1679,25 @@ oncore_msg_At( u_int len ) { - if (instance->site_survey != ONCORE_SS_UNKNOWN) return; - if (buf[4] == 2) + if (buf[4] == 2) { + record_clock_stats(&(instance->peer->srcadr), + "Initiating hardware 3D site survey"); instance->site_survey = ONCORE_SS_HW; - else { - instance->site_survey = ONCORE_SS_SW; - + } else { + char Msg[160]; /* * Probably a VP or an older UT which can't do site-survey. * We will have to do it ourselves */ + + sprintf(Msg, "Initiating software 3D site survey (%d samples)", + POS_HOLD_AVERAGE); + record_clock_stats(&(instance->peer->srcadr), Msg); + instance->site_survey = ONCORE_SS_SW; + oncore_cmd_At[2] = 0; instance->ss_lat = instance->ss_long = instance->ss_ht = 0; oncore_sendmsg(instance->ttyfd, oncore_cmd_At, sizeof oncore_cmd_At); @@ -1497,7 +1755,11 @@ oncore_msg_As( u_int len ) { - int lat, lon, ht; + char Msg[120], ew, ns; + const char *Ht; + double xd, xm, xs, yd, ym, ys, hm, hft; + int idx, idy, is, imx, imy; + long lat, lon, ht; if (!instance->printed || instance->As) return; @@ -1515,86 +1777,7 @@ oncore_msg_As( instance->ss_ht_type = buf[16]; - if (instance->Ay && instance->Az) - oncore_stats(instance); -} - - - -/* - * get PPS Offset - */ -static void -oncore_msg_Ay( - struct instance *instance, - u_char *buf, - u_int len - ) -{ - if (!instance->printed || instance->Ay) - return; - - instance->Ay = 1; - - instance->offset = buf_w32(&buf[4]); - - if (instance->As && instance->Az) - oncore_stats(instance); -} - - - -/* - * get Cable Delay - */ -static void -oncore_msg_Az( - struct instance *instance, - u_char *buf, - u_int len - ) -{ - if (!instance->printed || instance->Az) - return; - - instance->Az = 1; - - instance->delay = buf_w32(&buf[4]); - - if (instance->As && instance->Ay) - oncore_stats(instance); -} - - - -/* - * print init data in ONCORE to clockstats file - */ -static void -oncore_stats( - struct instance *instance - ) -{ - char Msg[120], ew, ns, *cp, *cp1; - const char *Ht; - double xd, xm, xs, yd, ym, ys, hm, hft; - int idx, idy, is, imx, imy; - long lat, lon; - - /* First, Receiver ID */ - - instance->Cj[294] = '\0'; - for (cp=(char *)instance->Cj; cp< (char *) &instance->Cj[294]; ) { - cp1 = strchr(cp, '\r'); - if (!cp1) - cp1 = (char *)&instance->Cj[294]; - *cp1 = '\0'; - record_clock_stats(&(instance->peer->srcadr), cp); - *cp1 = '\r'; - cp = cp1+2; - } - - /* Next Position */ + /* Print out Position */ record_clock_stats(&(instance->peer->srcadr), "Posn:"); ew = 'E'; @@ -1637,24 +1820,58 @@ oncore_stats( ys = is/1000.; sprintf(Msg, "Lat = %c %3ddeg %2dm %5.2fs, Long = %c %3ddeg %2dm %5.2fs, Alt = %5.2fm (%5.2fft) %s", ns, idx, imx, xs, ew, idy, imy, ys, hm, hft, Ht); record_clock_stats(&(instance->peer->srcadr), Msg); +} - /* finally, cable delay and PPS offset */ - sprintf(Msg, "Cable delay is set to %ld ns", instance->delay); - record_clock_stats(&(instance->peer->srcadr), Msg); + +/* + * get PPS Offset + * Nb. @@Ay is not supported for early UT (no plus) model + */ +static void +oncore_msg_Ay( + struct instance *instance, + u_char *buf, + u_int len + ) +{ + char Msg[120]; + + if (!instance->printed || instance->Ay) + return; + + instance->Ay = 1; + + instance->offset = buf_w32(&buf[4]); sprintf(Msg, "PPS Offset is set to %ld ns", instance->offset); record_clock_stats(&(instance->peer->srcadr), Msg); - -#ifdef HAVE_PPSAPI - if (instance->assert) - cp = "Timing on Assert."; - else - cp = "Timing on Clear."; - record_clock_stats(&(instance->peer->srcadr), cp); -#endif } + + +/* + * get Cable Delay + */ +static void +oncore_msg_Az( + struct instance *instance, + u_char *buf, + u_int len + ) +{ + char Msg[120]; + + if (!instance->printed || instance->Az) + return; + + instance->Az = 1; + + instance->delay = buf_w32(&buf[4]); + + sprintf(Msg, "Cable delay is set to %ld ns", instance->delay); + record_clock_stats(&(instance->peer->srcadr), Msg); +} #else int refclock_oncore_bs; #endif /* REFCLOCK */ diff --git a/contrib/ntp/ntpd/refclock_palisade.c b/contrib/ntp/ntpd/refclock_palisade.c index b9a0e2a..bedf6e8 100644 --- a/contrib/ntp/ntpd/refclock_palisade.c +++ b/contrib/ntp/ntpd/refclock_palisade.c @@ -86,6 +86,7 @@ struct refclock refclock_palisade = { NOFLAGS /* not used */ }; +int day_of_year P((char *dt)); /* * palisade_start - open the devices and initialize data for processing diff --git a/contrib/ntp/ntpd/refclock_parse.c b/contrib/ntp/ntpd/refclock_parse.c index 6771a13..95b93aa 100644 --- a/contrib/ntp/ntpd/refclock_parse.c +++ b/contrib/ntp/ntpd/refclock_parse.c @@ -1,7 +1,7 @@ /* - * /src/NTP/ntp-4/ntpd/refclock_parse.c,v 4.29 1999/02/28 19:58:23 kardel RELEASE_19990228_A + * /src/NTP/ntp-4/ntpd/refclock_parse.c,v 4.36 1999/11/28 17:18:20 kardel RELEASE_19991128_A * - * refclock_parse.c,v 4.29 1999/02/28 19:58:23 kardel RELEASE_19990228_A + * refclock_parse.c,v 4.36 1999/11/28 17:18:20 kardel RELEASE_19991128_A * * generic reference clock driver for receivers * @@ -134,7 +134,7 @@ #include "ascii.h" #include "ieee754io.h" -static char rcsid[]="refclock_parse.c,v 4.29 1999/02/28 19:58:23 kardel RELEASE_19990228_A"; +static char rcsid[]="refclock_parse.c,v 4.36 1999/11/28 17:18:20 kardel RELEASE_19991128_A"; /**=========================================================================== ** external interface to ntp mechanism @@ -341,7 +341,7 @@ struct parseunit u_char flags; /* flags (leap_control) */ u_long lastchange; /* time (ntp) when last state change accured */ u_long statetime[CEVNT_MAX+1]; /* accumulated time of clock states */ - u_char pollneeddata; /* 1 for receive sample expected in PPS mode */ + u_long pollneeddata; /* current_time(!=0) for receive sample expected in PPS mode */ u_short lastformat; /* last format used */ u_long lastsync; /* time (ntp) when clock was last seen fully synchronized */ u_long lastmissed; /* time (ntp) when poll didn't get data (powerup heuristic) */ @@ -609,16 +609,17 @@ static poll_info_t wsdcf_pollinfo = { WS_POLLRATE, WS_POLLCMD, WS_CMDSIZE }; * RAWDCF receivers that need to be powered from DTR * (like Expert mouse clock) */ -static int rawdcfdtr_init P((struct parseunit *)); -#define RAWDCFDTR_DESCRIPTION "RAW DCF77 CODE (DTR OPTION)" -#define RAWDCFDTR_INIT rawdcfdtr_init +static int rawdcf_init_1 P((struct parseunit *)); +#define RAWDCFDTRSET_DESCRIPTION "RAW DCF77 CODE (DTR SET/RTS CLR)" +#define RAWDCFDTRSET_INIT rawdcf_init_1 /* - * RAWDCF receivers that need to be powered from RTS + * RAWDCF receivers that need to be powered from + * DTR CLR and RTS SET */ -static int rawdcfrts_init P((struct parseunit *)); -#define RAWDCFRTS_DESCRIPTION "RAW DCF77 CODE (RTS OPTION)" -#define RAWDCFRTS_INIT rawdcfrts_init +static int rawdcf_init_2 P((struct parseunit *)); +#define RAWDCFDTRCLRRTSSET_DESCRIPTION "RAW DCF77 CODE (DTR CLR/RTS SET)" +#define RAWDCFDTRCLRRTSSET_INIT rawdcf_init_2 /* * Trimble GPS receivers (TAIP and TSIP protocols) @@ -766,6 +767,8 @@ static poll_info_t rcc8000_pollinfo = { RCC_POLLRATE, RCC_POLLCMD, RCC_CMDSIZE } #define COMPUTIME_SAMPLES 5 #define COMPUTIME_KEEP 3 +static poll_info_t we400a_pollinfo = { 60, "T", 1 }; + /* * Varitext Radio Clock Receiver */ @@ -1144,7 +1147,7 @@ static struct parse_clockinfo { /* mode 14 */ RAWDCF_FLAGS, NO_POLL, - RAWDCFDTR_INIT, + RAWDCFDTRSET_INIT, NO_EVENT, NO_END, NO_MESSAGE, @@ -1152,7 +1155,7 @@ static struct parse_clockinfo RAWDCF_ROOTDELAY, RAWDCF_BASEDELAY, DCF_A_ID, - RAWDCFDTR_DESCRIPTION, + RAWDCFDTRSET_DESCRIPTION, RAWDCF_FORMAT, DCF_TYPE, RAWDCF_MAXUNSYNC, @@ -1165,31 +1168,54 @@ static struct parse_clockinfo RAWDCF_KEEP }, { /* mode 15 */ - 0, /* operation flags (io modes) */ - NO_POLL, /* active poll routine */ - NO_INIT, /* active poll init routine */ - NO_EVENT, /* special event handling (e.g. reset clock) */ - NO_END, /* active poll end routine */ - NO_MESSAGE, /* process a lower layer message */ - NO_DATA, /* local data area for "poll" mechanism */ - 0, /* rootdelay */ - 11.0 /* bits */ / 9600, /* current offset by which the RS232 - time code is delayed from the actual time */ - DCF_ID, /* ID code */ - "WHARTON 400A Series clock", /* device name */ - "WHARTON 400A Series clock Output Format 1", /* fixed format */ - /* Must match a format-name in a libparse/clk_xxx.c file */ - DCF_TYPE, /* clock type (ntp control) */ - (1*60*60)/*?*/, /* time to trust oscillator after loosing synch */ - B9600, /* terminal input & output baudrate */ - (CS8|CREAD|PARENB|CLOCAL|HUPCL), /* terminal control flags */ - 0, /* terminal input flags */ - 0, /* terminal output flags */ - 0, /* terminal local flags */ - 5/*?*/, /* samples for median filter */ - 3/*?*/, /* samples for median filter to keep */ + 0, /* operation flags (io modes) */ + poll_dpoll, /* active poll routine */ + poll_init, /* active poll init routine */ + NO_EVENT, /* special event handling (e.g. reset clock) */ + NO_END, /* active poll end routine */ + NO_MESSAGE, /* process a lower layer message */ + ((void *)(&we400a_pollinfo)), /* local data area for "poll" mechanism */ + 0, /* rootdelay */ + 1.0 / 960, /* current offset by which the RS232 + time code is delayed from the actual time */ + DCF_ID, /* ID code */ + "WHARTON 400A Series clock", /* device name */ + "WHARTON 400A Series clock Output Format 5", /* fixed format */ + /* Must match a format-name in a libparse/clk_xxx.c file */ + DCF_TYPE, /* clock type (ntp control) */ + (1*60*60), /* time to trust oscillator after loosing synch */ + B9600, /* terminal input & output baudrate */ + (CS8|CREAD|PARENB|CLOCAL|HUPCL),/* terminal control flags */ + 0, /* terminal input flags */ + 0, /* terminal output flags */ + 0, /* terminal local flags */ + 5, /* samples for median filter */ + 3, /* samples for median filter to keep */ }, - { /* mode 16 */ + { /* mode 16 - RAWDCF RTS set, DTR clr */ + RAWDCF_FLAGS, + NO_POLL, + RAWDCFDTRCLRRTSSET_INIT, + NO_EVENT, + NO_END, + NO_MESSAGE, + NO_DATA, + RAWDCF_ROOTDELAY, + RAWDCF_BASEDELAY, + DCF_A_ID, + RAWDCFDTRCLRRTSSET_DESCRIPTION, + RAWDCF_FORMAT, + DCF_TYPE, + RAWDCF_MAXUNSYNC, + RAWDCF_SPEED, + RAWDCF_CFLAG, + RAWDCF_IFLAG, + RAWDCF_OFLAG, + RAWDCF_LFLAG, + RAWDCF_SAMPLES, + RAWDCF_KEEP + }, + { /* mode 17 */ VARITEXT_FLAGS, NO_POLL, NO_INIT, @@ -1211,30 +1237,7 @@ static struct parse_clockinfo VARITEXT_LFLAG, VARITEXT_SAMPLES, VARITEXT_KEEP - }, - { /* mode 17 */ - RAWDCF_FLAGS, - NO_POLL, - RAWDCFRTS_INIT, - NO_EVENT, - NO_END, - NO_MESSAGE, - NO_DATA, - RAWDCF_ROOTDELAY, - RAWDCF_BASEDELAY, - DCF_A_ID, - RAWDCFRTS_DESCRIPTION, - RAWDCF_FORMAT, - DCF_TYPE, - RAWDCF_MAXUNSYNC, - RAWDCF_SPEED, - RAWDCF_CFLAG, - RAWDCF_IFLAG, - RAWDCF_OFLAG, - RAWDCF_LFLAG, - RAWDCF_SAMPLES, - RAWDCF_KEEP - }, + } }; static int ncltypes = sizeof(parse_clockinfo) / sizeof(struct parse_clockinfo); @@ -1554,9 +1557,9 @@ ppsclock_init( ioctl(parse->generic->io.fd, I_PUSH, (caddr_t)m2) == -1) { if (errno != EINVAL) - { - msyslog(LOG_ERR, "PARSE receiver #%d: ppsclock_init: ioctl(fd, I_PUSH, \"ppsclock\"): %m", - CLK_UNIT(parse->peer)); + { + msyslog(LOG_ERR, "PARSE receiver #%d: ppsclock_init: ioctl(fd, I_PUSH, \"ppsclock\"): %m", + CLK_UNIT(parse->peer)); } return 0; } @@ -1586,8 +1589,8 @@ stream_init( if (ioctl(parse->generic->io.fd, I_PUSH, (caddr_t)m1) == -1) { if (errno != EINVAL) /* accept non-existence */ - { - msyslog(LOG_ERR, "PARSE receiver #%d: stream_init: ioctl(fd, I_PUSH, \"parse\"): %m", CLK_UNIT(parse->peer)); + { + msyslog(LOG_ERR, "PARSE receiver #%d: stream_init: ioctl(fd, I_PUSH, \"parse\"): %m", CLK_UNIT(parse->peer)); } return 0; } @@ -2032,10 +2035,10 @@ local_input( } else { - memmove((caddr_t)rbufp->recv_buffer, - (caddr_t)&parse->parseio.parse_dtime, - sizeof(parsetime_t)); - parse_iodone(&parse->parseio); + memmove((caddr_t)rbufp->recv_buffer, + (caddr_t)&parse->parseio.parse_dtime, + sizeof(parsetime_t)); + parse_iodone(&parse->parseio); rbufp->recv_length = sizeof(parsetime_t); return 1; /* got something & in place return */ } @@ -2132,18 +2135,18 @@ parsestate( const char *name; } flagstrings[] = { - { PARSEB_ANNOUNCE, "DST SWITCH WARNING" }, - { PARSEB_POWERUP, "NOT SYNCHRONIZED" }, - { PARSEB_NOSYNC, "TIME CODE NOT CONFIRMED" }, - { PARSEB_DST, "DST" }, - { PARSEB_UTC, "UTC DISPLAY" }, - { PARSEB_LEAPADD, "LEAP ADD WARNING" }, - { PARSEB_LEAPDEL, "LEAP DELETE WARNING" }, + { PARSEB_ANNOUNCE, "DST SWITCH WARNING" }, + { PARSEB_POWERUP, "NOT SYNCHRONIZED" }, + { PARSEB_NOSYNC, "TIME CODE NOT CONFIRMED" }, + { PARSEB_DST, "DST" }, + { PARSEB_UTC, "UTC DISPLAY" }, + { PARSEB_LEAPADD, "LEAP ADD WARNING" }, + { PARSEB_LEAPDEL, "LEAP DELETE WARNING" }, { PARSEB_LEAPSECOND, "LEAP SECOND" }, - { PARSEB_ALTERNATE,"ALTERNATE ANTENNA" }, - { PARSEB_TIMECODE, "TIME CODE" }, - { PARSEB_PPS, "PPS" }, - { PARSEB_POSITION, "POSITION" }, + { PARSEB_ALTERNATE, "ALTERNATE ANTENNA" }, + { PARSEB_TIMECODE, "TIME CODE" }, + { PARSEB_PPS, "PPS" }, + { PARSEB_POSITION, "POSITION" }, { 0 } }; @@ -2538,9 +2541,6 @@ parse_start( peer->sstclktype = parse->parse_type->cl_type; peer->precision = sys_precision; - peer->burst = NTP_SHIFT; - peer->flags |= FLAG_BURST; - peer->stratum = STRATUM_REFCLOCK; if (peer->stratum <= 1) memmove((char *)&parse->generic->refid, parse->parse_type->cl_id, 4); @@ -2737,7 +2737,7 @@ parse_start( } #endif #endif - + /* * try to do any special initializations */ @@ -2816,9 +2816,11 @@ parse_poll( */ parse->generic->polls++; - if (parse->pollneeddata) + if (parse->pollneeddata && + ((current_time - parse->pollneeddata) > (1<<(max(min(parse->peer->hpoll, parse->peer->ppoll), parse->peer->minpoll))))) { /* + * start worrying when exceeding a poll inteval * bad news - didn't get a response last time */ parse->generic->noreply++; @@ -2832,7 +2834,7 @@ parse_poll( /* * we just mark that we want the next sample for the clock filter */ - parse->pollneeddata = 1; + parse->pollneeddata = current_time; if (parse->parse_type->cl_poll) { @@ -3380,7 +3382,7 @@ parse_process( if (reftime.l_uf & (unsigned)0x80000000) reftime.l_ui++; reftime.l_uf = 0; - + /* * implied on second offset @@ -3535,7 +3537,7 @@ parse_process( refclock_receive(parse->peer); } - + /**=========================================================================== ** special code for special clocks **/ @@ -4149,7 +4151,7 @@ poll_init( return 0; } - + /**=========================================================================== ** Trimble support **/ @@ -4260,7 +4262,7 @@ trimbletaip_event( * of the PPS pulse for accurate timing. Where it is determined that * the offset is way off, when first starting up ntpd for example, * the timing of the data stream is used until the offset becomes low enough - * (|offset| < clock_max), at which point the pps offset is used. + * (|offset| < CLOCK_MAX), at which point the pps offset is used. * * It can use either option for receiving PPS information - the 'ppsclock' * stream pushed onto the serial data interface to timestamp the Carrier @@ -4349,6 +4351,12 @@ struct txbuf u_char *txt; /* pointer to actual data buffer */ }; +void sendcmd P((struct txbuf *buf, int c)); +void sendbyte P((struct txbuf *buf, int b)); +void sendetx P((struct txbuf *buf, struct parseunit *parse)); +void sendint P((struct txbuf *buf, int a)); +void sendflt P((struct txbuf *buf, double a)); + void sendcmd( struct txbuf *buf, @@ -4441,7 +4449,7 @@ static int trimbletsip_setup( struct parseunit *parse, const char *reason - ) + ) { u_char buffer[256]; struct txbuf buf; @@ -4449,34 +4457,34 @@ trimbletsip_setup( buf.txt = buffer; sendcmd(&buf, CMD_CVERSION); /* request software versions */ - sendetx(&buf, parse); - + sendetx(&buf, parse); + sendcmd(&buf, CMD_COPERPARAM); /* set operating parameters */ - sendbyte(&buf, 4); /* static */ - sendflt(&buf, 5.0*D2R); /* elevation angle mask = 10 deg XXX */ - sendflt(&buf, 4.0); /* s/n ratio mask = 6 XXX */ - sendflt(&buf, 12.0); /* PDOP mask = 12 */ - sendflt(&buf, 8.0); /* PDOP switch level = 8 */ - sendetx(&buf, parse); - + sendbyte(&buf, 4); /* static */ + sendflt(&buf, 5.0*D2R); /* elevation angle mask = 10 deg XXX */ + sendflt(&buf, 4.0); /* s/n ratio mask = 6 XXX */ + sendflt(&buf, 12.0); /* PDOP mask = 12 */ + sendflt(&buf, 8.0); /* PDOP switch level = 8 */ + sendetx(&buf, parse); + sendcmd(&buf, CMD_CMODESEL); /* fix mode select */ - sendbyte(&buf, 0); /* automatic */ - sendetx(&buf, parse); - + sendbyte(&buf, 0); /* automatic */ + sendetx(&buf, parse); + sendcmd(&buf, CMD_CMESSAGE); /* request system message */ - sendetx(&buf, parse); - + sendetx(&buf, parse); + sendcmd(&buf, CMD_CSUPER); /* superpacket fix */ - sendbyte(&buf, 0x2); /* binary mode */ - sendetx(&buf, parse); - + sendbyte(&buf, 0x2); /* binary mode */ + sendetx(&buf, parse); + sendcmd(&buf, CMD_CIOOPTIONS); /* set I/O options */ sendbyte(&buf, TRIM_POS_OPT); /* position output */ sendbyte(&buf, 0x00); /* no velocity output */ sendbyte(&buf, TRIM_TIME_OPT); /* UTC, compute on seconds */ sendbyte(&buf, 0x00); /* no raw measurements */ - sendetx(&buf, parse); - + sendetx(&buf, parse); + sendcmd(&buf, CMD_CUTCPARAM); /* request UTC correction data */ sendetx(&buf, parse); @@ -4605,7 +4613,7 @@ trimbletsip_init( #ifdef VEOL2 tio.c_cc[VEOL2] = DLE; #endif -} + } if (TTY_SETATTR(parse->generic->io.fd, &tio) == -1) { @@ -5133,11 +5141,12 @@ trimbletsip_message( **/ /*-------------------------------------------------- - * rawdcfdtr_init - set up modem lines for RAWDCF receivers + * rawdcf_init_1 - set up modem lines for RAWDCF receivers + * SET DTR line */ #if defined(TIOCMSET) && (defined(TIOCM_DTR) || defined(CIOCM_DTR)) static int -rawdcfdtr_init( +rawdcf_init_1( struct parseunit *parse ) { @@ -5155,7 +5164,7 @@ rawdcfdtr_init( if (ioctl(parse->generic->io.fd, TIOCMSET, (caddr_t)&sl232) == -1) { - msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init: WARNING: ioctl(fd, TIOCMSET, [C|T]IOCM_DTR): %m", CLK_UNIT(parse->peer)); + msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_1: WARNING: ioctl(fd, TIOCMSET, [C|T]IOCM_DTR): %m", CLK_UNIT(parse->peer)); } return 0; } @@ -5165,47 +5174,49 @@ rawdcfdtr_init( struct parseunit *parse ) { - msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init: WARNING: OS interface incapable of setting DTR to power DCF modules", CLK_UNIT(parse->peer)); + msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_1: WARNING: OS interface incapable of setting DTR to power DCF modules", CLK_UNIT(parse->peer)); return 0; } #endif /* DTR initialisation type */ /*-------------------------------------------------- - * rawdcfrts_init - set up modem lines for RAWDCF receivers + * rawdcf_init_2 - set up modem lines for RAWDCF receivers + * CLR DTR line, SET RTS line */ -#if defined(TIOCMSET) && (defined(TIOCM_RTS) || defined(CIOCM_RTS)) +#if defined(TIOCMSET) && (defined(TIOCM_RTS) || defined(CIOCM_RTS)) static int -rawdcfrts_init( +rawdcf_init_2( struct parseunit *parse ) { /* * You can use the RS232 to supply the power for a DCF77 receiver. - * Here a voltage between the RTS and the DTR line is used. + * Here a voltage between the DTR and the RTS line is used. Unfortunately + * the name has changed from CIOCM_DTR to TIOCM_DTR recently. */ #ifdef TIOCM_RTS - int sl232 = TIOCM_RTS; /* turn on RTS for power supply */ + int sl232 = TIOCM_RTS; /* turn on RTS, clear DTR for power supply */ #else - int sl232 = CIOCM_RTS; /* turn on RTS for power supply */ + int sl232 = CIOCM_RTS; /* turn on DTR for power supply */ #endif if (ioctl(parse->generic->io.fd, TIOCMSET, (caddr_t)&sl232) == -1) { - msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init: WARNING: ioctl(fd, TIOCMSET, [C|T]IOCM_RTS): %m", CLK_UNIT(parse->peer)); + msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_2: WARNING: ioctl(fd, TIOCMSET, [C|T]IOCM_RTS): %m", CLK_UNIT(parse->peer)); } return 0; } #else static int -rawdcfrts_init( +rawdcf_init_2( struct parseunit *parse ) { - msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init: WARNING: OS interface incapable of setting RTS to power DCF modules", CLK_UNIT(parse->peer)); + msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_2: WARNING: OS interface incapable of setting RTS to power DCF modules", CLK_UNIT(parse->peer)); return 0; } -#endif /* RTS initialisation type */ +#endif /* DTR initialisation type */ #else /* defined(REFCLOCK) && defined(PARSE) */ int refclock_parse_bs; @@ -5215,6 +5226,27 @@ int refclock_parse_bs; * History: * * refclock_parse.c,v + * Revision 4.36 1999/11/28 17:18:20 kardel + * disabled burst mode + * + * Revision 4.35 1999/11/28 09:14:14 kardel + * RECON_4_0_98F + * + * Revision 4.34 1999/05/14 06:08:05 kardel + * store current_time in a suitable container (u_long) + * + * Revision 4.33 1999/05/13 21:48:38 kardel + * double the no response timeout interval + * + * Revision 4.32 1999/05/13 20:09:13 kardel + * complain only about missing polls after a full poll interval + * + * Revision 4.31 1999/05/13 19:59:32 kardel + * add clock type 16 for RTS set DTR clr in RAWDCF + * + * Revision 4.30 1999/02/28 20:36:43 kardel + * fixed printf fmt + * * Revision 4.29 1999/02/28 19:58:23 kardel * updated copyright information * diff --git a/contrib/ntp/ntpd/refclock_pcf.c b/contrib/ntp/ntpd/refclock_pcf.c new file mode 100644 index 0000000..c882404 --- /dev/null +++ b/contrib/ntp/ntpd/refclock_pcf.c @@ -0,0 +1,215 @@ +/* + * refclock_pcf - clock driver for the Conrad parallel port radio clock + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PCF) + +#include <time.h> + +#include "ntpd.h" +#include "ntp_io.h" +#include "ntp_refclock.h" +#include "ntp_calendar.h" +#include "ntp_stdlib.h" + +/* + * This driver supports the parallel port radio clocks sold by Conrad + * Electronic under order numbers 967602 and 642002. + * + * It requires that the local timezone be CET/CEST and that the pcfclock + * device driver be installed. A device driver for Linux 2.2 is available + * at http://home.pages.de/~voegele/pcf.html. + */ + +/* + * Interface definitions + */ +#define DEVICE "/dev/pcfclock%d" +#define PRECISION (-1) /* precision assumed (about 0.5 s) */ +#define REFID "PCF" +#define DESCRIPTION "Conrad parallel port radio clock" + +#define LENPCF 18 /* timecode length */ + +/* + * Function prototypes + */ +static int pcf_start P((int, struct peer *)); +static void pcf_shutdown P((int, struct peer *)); +static void pcf_poll P((int, struct peer *)); + +/* + * Transfer vector + */ +struct refclock refclock_pcf = { + pcf_start, /* start up driver */ + pcf_shutdown, /* shut down driver */ + pcf_poll, /* transmit poll message */ + noentry, /* not used */ + noentry, /* initialize driver (not used) */ + noentry, /* not used */ + NOFLAGS /* not used */ +}; + + +/* + * pcf_start - open the device and initialize data for processing + */ +static int +pcf_start( + int unit, + struct peer *peer + ) +{ + struct refclockproc *pp; + int fd; + char device[20]; + + /* + * Open device file for reading. + */ + (void)sprintf(device, DEVICE, unit); +#ifdef DEBUG + if (debug) + printf ("starting PCF with device %s\n",device); +#endif + if ((fd = open(device, O_RDONLY)) == -1) { + return (0); + } + + pp = peer->procptr; + pp->io.clock_recv = noentry; + pp->io.srcclock = (caddr_t)peer; + pp->io.datalen = 0; + pp->io.fd = fd; + + /* + * Initialize miscellaneous variables + */ + peer->precision = PRECISION; + pp->clockdesc = DESCRIPTION; + memcpy((char *)&pp->refid, REFID, 4); + + return (1); +} + + +/* + * pcf_shutdown - shut down the clock + */ +static void +pcf_shutdown( + int unit, + struct peer *peer + ) +{ + struct refclockproc *pp; + + pp = peer->procptr; + (void)close(pp->io.fd); +} + + +/* + * pcf_poll - called by the transmit procedure + */ +static void +pcf_poll( + int unit, + struct peer *peer + ) +{ + struct refclockproc *pp; + char buf[LENPCF]; + struct tm tm, *tp; + time_t t; + + pp = peer->procptr; + + buf[0] = 0; + if (read(pp->io.fd, buf, sizeof(buf)) < sizeof(buf) || buf[0] != 9) { + refclock_report(peer, CEVNT_FAULT); + return; + } + + tm.tm_mday = buf[11] * 10 + buf[10]; + tm.tm_mon = buf[13] * 10 + buf[12] - 1; + tm.tm_year = buf[15] * 10 + buf[14]; + tm.tm_hour = buf[7] * 10 + buf[6]; + tm.tm_min = buf[5] * 10 + buf[4]; + tm.tm_sec = buf[3] * 10 + buf[2]; + tm.tm_isdst = -1; + + /* + * Y2K convert the 2-digit year + */ + if (tm.tm_year < 99) + tm.tm_year += 100; + + t = mktime(&tm); + if (t == (time_t) -1) { + refclock_report(peer, CEVNT_BADTIME); + return; + } + +#if defined(__GLIBC__) && defined(_BSD_SOURCE) + if ((tm.tm_isdst > 0 && tm.tm_gmtoff != 7200) + || (tm.tm_isdst == 0 && tm.tm_gmtoff != 3600) + || tm.tm_isdst < 0) { +#ifdef DEBUG + if (debug) + printf ("local time zone not set to CET/CEST\n"); +#endif + refclock_report(peer, CEVNT_BADTIME); + return; + } +#endif + + pp->lencode = strftime(pp->a_lastcode, BMAX, "%Y %m %d %H %M %S", &tm); + +#if defined(_REENTRANT) || defined(_THREAD_SAFE) + tp = gmtime_r(&t, &tm); +#else + tp = gmtime(&t); +#endif + if (!tp) { + refclock_report(peer, CEVNT_FAULT); + return; + } + + get_systime(&pp->lastrec); + pp->polls++; + pp->year = tp->tm_year + 1900; + pp->day = tp->tm_yday + 1; + pp->hour = tp->tm_hour; + pp->minute = tp->tm_min; + pp->second = tp->tm_sec; + pp->usec = buf[16] * 31250; + if (buf[17] & 1) + pp->usec += 500000; + +#ifdef DEBUG + if (debug) + printf ("pcf%d: time is %04d/%02d/%02d %02d:%02d:%02d UTC\n", + unit, pp->year, tp->tm_mon + 1, tp->tm_mday, pp->hour, + pp->minute, pp->second); +#endif + + if (!refclock_process(pp)) { + refclock_report(peer, CEVNT_BADTIME); + return; + } + record_clock_stats(&peer->srcadr, pp->a_lastcode); + if (buf[1] & 1) + pp->leap = LEAP_NOTINSYNC; + else + pp->leap = LEAP_NOWARNING; + refclock_receive(peer); +} +#else +int refclock_pcf_bs; +#endif /* REFCLOCK */ diff --git a/contrib/ntp/ntpd/refclock_shm.c b/contrib/ntp/ntpd/refclock_shm.c index fe05b02..a8094c8 100644 --- a/contrib/ntp/ntpd/refclock_shm.c +++ b/contrib/ntp/ntpd/refclock_shm.c @@ -264,7 +264,7 @@ shm_poll( int ok=1; switch (up->mode) { case 0: { - tvr.tv_sec=up->receiveTimeStampSec-172800; + tvr.tv_sec=up->receiveTimeStampSec; tvr.tv_usec=up->receiveTimeStampUSec; tvt.tv_sec=up->clockTimeStampSec; tvt.tv_usec=up->clockTimeStampUSec; @@ -272,7 +272,7 @@ shm_poll( break; case 1: { int cnt=up->count; - tvr.tv_sec=up->receiveTimeStampSec-172800; + tvr.tv_sec=up->receiveTimeStampSec; tvr.tv_usec=up->receiveTimeStampUSec; tvt.tv_sec=up->clockTimeStampSec; tvt.tv_usec=up->clockTimeStampUSec; @@ -282,17 +282,17 @@ shm_poll( default: msyslog (LOG_ERR, "SHM: bad mode found in shared memory: %d",up->mode); } - /*msyslog(LOG_NOTICE,"poll2a tvr.s %d tvr.u %d tvt.s %d tvt.u %d",tvr.tv_sec,tvr.tv_usec,tvt.tv_sec,tvt.tv_usec);*/ up->valid=0; if (ok) { TVTOTS(&tvr,&pp->lastrec); /* pp->lasttime = current_time; */ pp->polls++; t=gmtime (&tvt.tv_sec); - pp->day=t->tm_yday;/*+2; */ + pp->day=t->tm_yday+1; pp->hour=t->tm_hour; pp->minute=t->tm_min; pp->second=t->tm_sec; + pp->msec=0; pp->usec=tvt.tv_usec; peer->precision=up->precision; pp->leap=up->leap; diff --git a/contrib/ntp/ntpd/refclock_wwv.c b/contrib/ntp/ntpd/refclock_wwv.c new file mode 100644 index 0000000..52e76e6 --- /dev/null +++ b/contrib/ntp/ntpd/refclock_wwv.c @@ -0,0 +1,2754 @@ +/* + * refclock_wwv - clock driver for NIST WWV/H time/frequency station + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#if defined(REFCLOCK) && defined(CLOCK_WWV) + +#include <stdio.h> +#include <ctype.h> +#include <sys/time.h> +#include <math.h> +#ifdef HAVE_SYS_IOCTL_H +#include <sys/ioctl.h> +#endif /* HAVE_SYS_IOCTL_H */ + +#include "ntpd.h" +#include "ntp_io.h" +#include "ntp_refclock.h" +#include "ntp_calendar.h" +#include "ntp_stdlib.h" +#include "audio.h" + +#define ICOM 1 /* undefine to suppress ICOM code */ + +#ifdef ICOM +#include "icom.h" +#endif /* ICOM */ + +/* + * Audio WWV/H demodulator/decoder + * + * This driver synchronizes the computer time using data encoded in + * radio transmissions from NIST time/frequency stations WWV in Boulder, + * CO, and WWVH in Kauai, HI. Transmikssions are made continuously on + * 2.5, 5, 10, 15 and 20 MHz in AM mode. An ordinary shortwave receiver + * can be tuned manually to one of these frequencies or, in the case of + * ICOM receivers, the receiver can be tuned automatically using this + * program as propagation conditions change throughout the day and + * night. + * + * The driver receives, demodulates and decodes the radio signals when + * connected to the audio codec of a Sun workstation running SunOS or + * Solaris, and with a little help, other workstations with similar + * codecs or sound cards. In this implementation, only one audio driver + * and codec can be supported on a single machine. + * + * The demodulation and decoding algorithms used in this driver are + * based on those developed for the TAPR DSP93 development board and the + * TI 320C25 digital signal processor described in: Mills, D.L. A + * precision radio clock for WWV transmissions. Electrical Engineering + * Report 97-8-1, University of Delaware, August 1997, 25 pp. Available + * from www.eecis.udel.edu/~mills/reports.htm. The algorithms described + * in this report have been modified somewhat to improve performance + * under weak signal conditions and to provide an automatic station + * identification feature. + * + * The ICOM code is normally compiled in the driver. It isn't used, + * unless the mode keyword on the server configuration command specifies + * a nonzero ICOM ID select code. The C-IV trace is turned on if the + * debug level is greater than one. + */ +/* + * Interface definitions + */ +#define PRECISION (-10) /* precision assumed (about 1 ms) */ +#define REFID "NONE" /* reference ID */ +#define DESCRIPTION "WWV/H Audio Demodulator/Decoder" /* WRU */ +#define SECOND 8000 /* second epoch (sample rate) (Hz) */ +#define MINUTE (SECOND * 60) /* minute epoch */ +#define OFFSET 128 /* companded sample offset */ +#define SIZE 256 /* decompanding table size */ +#define MAXSIG 6000. /* maximum signal level reference */ +#define MAXSNR 30. /* max SNR reference */ +#define DGAIN 20. /* data channel gain reference */ +#define SGAIN 10. /* sync channel gain reference */ +#define MAXFREQ (125e-6 * SECOND) /* freq tolerance (.0125%) */ +#define PI 3.1415926535 /* the real thing */ +#define DATSIZ (170 * MS) /* data matched filter size */ +#define SYNSIZ (800 * MS) /* minute sync matched filter size */ +#define UTCYEAR 72 /* the first UTC year */ +#define MAXERR 30 /* max data bit errors in minute */ +#define NCHAN 5 /* number of channels */ + +/* + * Macroni + */ +#define MOD(x, y) ((x) < 0 ? -(-(x) % (y)) : (x) % (y)) + +/* + * General purpose status bits (status) + * + * Notes: SELV and/or SELH are set when the minute sync pulse from + * either or both WWV and/or WWVH stations has been heard. MSYNC is set + * when the minute sync pulse has been acquired and never reset. SSYNC + * is set when the second sync pulse has been acquired and cleared by + * watchdog or signal loss. DSYNC is set when the minutes unit digit has + * reached the threshold and INSYNC is set when if all nine digits have + * reached the threshold and never cleared. + * + * DGATE is set if a data bit is invalid, BGATE is set if a BCD digit + * bit is invalid. SFLAG is set when during seconds 59, 0 and 1 while + * probing for alternate frequencies. LEPSEC is set when the SECWAR of + * the timecode is set on the last second of 30 June or 31 December. At + * the end of this minute both the receiver and transmitter insert + * second 60 in the minute and the minute sync slips a second. + */ +#define MSYNC 0x0001 /* minute epoch sync */ +#define SSYNC 0x0002 /* second epoch sync */ +#define DSYNC 0x0004 /* minute units sync */ +#define INSYNC 0x0008 /* clock synchronized */ +#define DGATE 0x0010 /* data bit error */ +#define BGATE 0x0020 /* BCD digit bit error */ +#define SFLAG 0x1000 /* probe flag */ +#define LEPSEC 0x2000 /* leap second in progress */ + +/* + * Station scoreboard bits (select) + * + * These are used to establish the signal quality for each of the five + * frequencies and two stations. + */ +#define JITRNG 0x0001 /* jitter above threshold */ +#define SYNCNG 0x0002 /* sync below threshold or SNR */ +#define DATANG 0x0004 /* data below threshold or SNR */ +#define SELV 0x0100 /* WWV station select */ +#define SELH 0x0200 /* WWVH station select */ + +/* + * Alarm status bits (alarm) + * + * These bits indicate various alarm conditions, which are decoded to + * form the quality character included in the timecode. There are four + * four-bit nibble fields in the word, each corresponding to a specific + * alarm condition. At the end of each second, the word is shifted left + * one position and the least significant bit of each nibble cleared. + * This bit can be set during the next minute if the associated alarm + * condition is raised. This provides a way to remember alarm conditions + * up to four minutes. + * + * If not tracking both minute sync and second sync, the SYNERR alarm is + * raised. The data error counter is incremented for each invalid data + * bit. If too many data bit errors are encountered in one minute, the + * MODERR alarm is raised. The DECERR alarm is raised if a maximum + * likelihood digit fails to compare with the current clock digit. If + * the probability of any miscellaneous bit or any digit falls below the + * threshold, the SYMERR alarm is raised. + */ +#define DECERR 0 /* BCD digit compare error */ +#define SYMERR 4 /* low bit or digit probability */ +#define MODERR 8 /* too many data bit errors */ +#define SYNERR 12 /* not synchronized to station */ + +/* + * Watchdog timeouts (watch) + * + * If these timeouts expire, the status bits are mashed to zero and the + * driver starts from scratch. Suitably more refined procedures may be + * developed in future. All these are in minutes. + */ +#define ACQSN 5 /* acquisition timeout */ +#define HSPEC 15 /* second sync timeout */ +#define DIGIT 30 /* minute unit digit timeout */ +#define PANIC (4 * 1440) /* panic timeout */ + +/* + * Thresholds. These establish the minimum signal level, minimum SNR and + * maximum jitter thresholds which establish the error and false alarm + * rates of the receiver. The values defined here may be on the + * adventurous side in the interest of the highest sensitivity. + */ +#define ATHR 2000 /* acquisition amplitude threshold */ +#define ASNR 6.0 /* acquisition SNR threshold (dB) */ +#define AWND 50 /* acquisition window threshold (ms) */ +#define AMIN 3 /* acquisition min compare count */ +#define AMAX 6 /* max compare count */ +#define QTHR 2000 /* QSY amplitude threshold */ +#define QSNR 20.0 /* QSY SNR threshold (dB) */ +#define STHR 500 /* second sync amplitude threshold */ +#define SCMP 10 /* second sync compare threshold */ +#define DTHR 1000 /* bit amplitude threshold */ +#define DSNR 10.0 /* bit SNR threshold (dB) */ +#define BTHR 1000 /* digit probability threshold */ +#define BSNR 3.0 /* digit likelihood threshold (dB) */ +#define BCMP 5 /* digit compare threshold (dB) */ + +/* + * Tone frequency definitions. + */ +#define MS 8 /* samples per millisecond */ +#define IN100 1 /* 100 Hz 4.5-deg sin table */ +#define IN1000 10 /* 1000 Hz 4.5-deg sin table */ +#define IN1200 12 /* 1200 Hz 4.5-deg sin table */ + +/* + * Acquisition and tracking time constants. Usually powers of 2. + */ +#define MINAVG 8 /* min time constant (s) */ +#define MAXAVG 7 /* max time constant (log2 s) */ +#define TCONST 16 /* minute time constant (s) */ +#define SYNCTC (1024 / (1 << MAXAVG)) /* FLL constant (s) */ + +/* + * Miscellaneous status bits (misc) + * + * These bits correspond to designated bits in the WWV/H timecode. The + * bit probabilities are exponentially averaged over several minutes and + * processed by a integrator and threshold. + */ +#define DUT1 0x01 /* 56 DUT .1 */ +#define DUT2 0x02 /* 57 DUT .2 */ +#define DUT4 0x04 /* 58 DUT .4 */ +#define DUTS 0x08 /* 50 DUT sign */ +#define DST1 0x10 /* 55 DST1 DST in progress */ +#define DST2 0x20 /* 2 DST2 DST change warning */ +#define SECWAR 0x40 /* 3 leap second warning */ + +/* + * The total system delay with the DSP93 program is at 22.5 ms, + * including the propagation delay from Ft. Collins, CO, to Newark, DE + * (8.9 ms), the communications receiver delay and the delay of the + * DSP93 program itself. The DSP93 program delay is due mainly to the + * 400-Hz FIR bandpass filter (5 ms) and second sync matched filter (5 + * ms), leaving about 3.6 ms for the receiver delay and strays. + * + * The total system delay with this program is estimated at 27.1 ms by + * comparison with another PPS-synchronized NTP server over a 10-Mb/s + * Ethernet. The propagation and receiver delays are the same as with + * the DSP93 program. The program delay is due only to the 600-Hz + * IIR bandpass filter (1.1 ms), since other delays have been removed. + * Assuming 4.7 ms for the receiver, program and strays, this leaves + * 13.5 ms for the audio codec and operating system latencies for a + * total of 18.2 ms. as the systematic delay. The additional propagation + * delay specific to each receiver location can be programmed in the + * fudge time1 and time2 values for WWV and WWVH, respectively. + */ +#define PDELAY (.0036 + .0011 + .0135) /* net system delay (s) */ + +/* + * Table of sine values at 4.5-degree increments. This is used by the + * synchronous matched filter demodulators. The integral of sine-squared + * over one complete cycle is PI, so the table is normallized by 1 / PI. + */ +double sintab[] = { + 0.000000e+00, 2.497431e-02, 4.979464e-02, 7.430797e-02, /* 0-3 */ + 9.836316e-02, 1.218119e-01, 1.445097e-01, 1.663165e-01, /* 4-7 */ + 1.870979e-01, 2.067257e-01, 2.250791e-01, 2.420447e-01, /* 8-11 */ + 2.575181e-01, 2.714038e-01, 2.836162e-01, 2.940800e-01, /* 12-15 */ + 3.027307e-01, 3.095150e-01, 3.143910e-01, 3.173286e-01, /* 16-19 */ + 3.183099e-01, 3.173286e-01, 3.143910e-01, 3.095150e-01, /* 20-23 */ + 3.027307e-01, 2.940800e-01, 2.836162e-01, 2.714038e-01, /* 24-27 */ + 2.575181e-01, 2.420447e-01, 2.250791e-01, 2.067257e-01, /* 28-31 */ + 1.870979e-01, 1.663165e-01, 1.445097e-01, 1.218119e-01, /* 32-35 */ + 9.836316e-02, 7.430797e-02, 4.979464e-02, 2.497431e-02, /* 36-39 */ +-0.000000e+00, -2.497431e-02, -4.979464e-02, -7.430797e-02, /* 40-43 */ +-9.836316e-02, -1.218119e-01, -1.445097e-01, -1.663165e-01, /* 44-47 */ +-1.870979e-01, -2.067257e-01, -2.250791e-01, -2.420447e-01, /* 48-51 */ +-2.575181e-01, -2.714038e-01, -2.836162e-01, -2.940800e-01, /* 52-55 */ +-3.027307e-01, -3.095150e-01, -3.143910e-01, -3.173286e-01, /* 56-59 */ +-3.183099e-01, -3.173286e-01, -3.143910e-01, -3.095150e-01, /* 60-63 */ +-3.027307e-01, -2.940800e-01, -2.836162e-01, -2.714038e-01, /* 64-67 */ +-2.575181e-01, -2.420447e-01, -2.250791e-01, -2.067257e-01, /* 68-71 */ +-1.870979e-01, -1.663165e-01, -1.445097e-01, -1.218119e-01, /* 72-75 */ +-9.836316e-02, -7.430797e-02, -4.979464e-02, -2.497431e-02, /* 76-79 */ + 0.000000e+00}; /* 80 */ + +/* + * Decoder operations at the end of each second are driven by a state + * machine. The transition matrix consists of a dispatch table indexed + * by second number. Each entry in the table contains a case switch + * number and argument. + */ +struct progx { + int sw; /* case switch number */ + int arg; /* argument */ +}; + +/* + * Case switch numbers + */ +#define IDLE 0 /* no operation */ +#define COEF 1 /* BCD bit conditioned on DSYNC */ +#define COEF1 2 /* BCD bit */ +#define COEF2 3 /* BCD bit ignored */ +#define DECIM9 4 /* BCD digit 0-9 */ +#define DECIM6 5 /* BCD digit 0-6 */ +#define DECIM3 6 /* BCD digit 0-3 */ +#define DECIM2 7 /* BCD digit 0-2 */ +#define MSCBIT 8 /* miscellaneous bit */ +#define MSC20 9 /* miscellaneous bit */ +#define MSC21 10 /* QSY probe channel */ +#define MIN1 11 /* minute */ +#define MIN2 12 /* leap second */ +#define SYNC2 13 /* QSY data channel */ +#define SYNC3 14 /* QSY data channel */ + +/* + * Offsets in decoding matrix + */ +#define MN 0 /* minute digits (2) */ +#define HR 2 /* hour digits (2) */ +#define DA 4 /* day digits (3) */ +#define YR 7 /* year digits (2) */ + +struct progx progx[] = { + {SYNC2, 0}, /* 0 latch sync max */ + {SYNC3, 0}, /* 1 QSY data channel */ + {MSCBIT, DST2}, /* 2 dst2 */ + {MSCBIT, SECWAR}, /* 3 lw */ + {COEF, 0}, /* 4 1 year units */ + {COEF, 1}, /* 5 2 */ + {COEF, 2}, /* 6 4 */ + {COEF, 3}, /* 7 8 */ + {DECIM9, YR}, /* 8 */ + {IDLE, 0}, /* 9 p1 */ + {COEF1, 0}, /* 10 1 minute units */ + {COEF1, 1}, /* 11 2 */ + {COEF1, 2}, /* 12 4 */ + {COEF1, 3}, /* 13 8 */ + {DECIM9, MN}, /* 14 */ + {COEF, 0}, /* 15 10 minute tens */ + {COEF, 1}, /* 16 20 */ + {COEF, 2}, /* 17 40 */ + {COEF2, 3}, /* 18 80 (not used) */ + {DECIM6, MN + 1}, /* 19 p2 */ + {COEF, 0}, /* 20 1 hour units */ + {COEF, 1}, /* 21 2 */ + {COEF, 2}, /* 22 4 */ + {COEF, 3}, /* 23 8 */ + {DECIM9, HR}, /* 24 */ + {COEF, 0}, /* 25 10 hour tens */ + {COEF, 1}, /* 26 20 */ + {COEF2, 2}, /* 27 40 (not used) */ + {COEF2, 3}, /* 28 80 (not used) */ + {DECIM2, HR + 1}, /* 29 p3 */ + {COEF, 0}, /* 30 1 day units */ + {COEF, 1}, /* 31 2 */ + {COEF, 2}, /* 32 4 */ + {COEF, 3}, /* 33 8 */ + {DECIM9, DA}, /* 34 */ + {COEF, 0}, /* 35 10 day tens */ + {COEF, 1}, /* 36 20 */ + {COEF, 2}, /* 37 40 */ + {COEF, 3}, /* 38 80 */ + {DECIM9, DA + 1}, /* 39 p4 */ + {COEF, 0}, /* 40 100 day hundreds */ + {COEF, 1}, /* 41 200 */ + {COEF2, 2}, /* 42 400 (not used) */ + {COEF2, 3}, /* 43 800 (not used) */ + {DECIM3, DA + 2}, /* 44 */ + {IDLE, 0}, /* 45 */ + {IDLE, 0}, /* 46 */ + {IDLE, 0}, /* 47 */ + {IDLE, 0}, /* 48 */ + {IDLE, 0}, /* 49 p5 */ + {MSCBIT, DUTS}, /* 50 dut+- */ + {COEF, 0}, /* 51 10 year tens */ + {COEF, 1}, /* 52 20 */ + {COEF, 2}, /* 53 40 */ + {COEF, 3}, /* 54 80 */ + {MSC20, DST1}, /* 55 dst1 */ + {MSCBIT, DUT1}, /* 56 0.1 dut */ + {MSCBIT, DUT2}, /* 57 0.2 */ + {MSC21, DUT4}, /* 58 0.4 QSY probe channel */ + {MIN1, 0}, /* 59 p6 latch sync min */ + {MIN2, 0} /* 60 leap second */ +}; + +/* + * BCD coefficients for maximum likelihood digit decode + */ +#define P15 1. /* max positive number */ +#define N15 -1. /* max negative number */ + +/* + * Digits 0-9 + */ +#define P9 (P15 / 4) /* mark (+1) */ +#define N9 (N15 / 4) /* space (-1) */ + +double bcd9[][4] = { + {N9, N9, N9, N9}, /* 0 */ + {P9, N9, N9, N9}, /* 1 */ + {N9, P9, N9, N9}, /* 2 */ + {P9, P9, N9, N9}, /* 3 */ + {N9, N9, P9, N9}, /* 4 */ + {P9, N9, P9, N9}, /* 5 */ + {N9, P9, P9, N9}, /* 6 */ + {P9, P9, P9, N9}, /* 7 */ + {N9, N9, N9, P9}, /* 8 */ + {P9, N9, N9, P9}, /* 9 */ + {0, 0, 0, 0} /* backstop */ +}; + +/* + * Digits 0-6 (minute tens) + */ +#define P6 (P15 / 3) /* mark (+1) */ +#define N6 (N15 / 3) /* space (-1) */ + +double bcd6[][4] = { + {N6, N6, N6, 0}, /* 0 */ + {P6, N6, N6, 0}, /* 1 */ + {N6, P6, N6, 0}, /* 2 */ + {P6, P6, N6, 0}, /* 3 */ + {N6, N6, P6, 0}, /* 4 */ + {P6, N6, P6, 0}, /* 5 */ + {N6, P6, P6, 0}, /* 6 */ + {0, 0, 0, 0} /* backstop */ +}; + +/* + * Digits 0-3 (day hundreds) + */ +#define P3 (P15 / 2) /* mark (+1) */ +#define N3 (N15 / 2) /* space (-1) */ + +double bcd3[][4] = { + {N3, N3, 0, 0}, /* 0 */ + {P3, N3, 0, 0}, /* 1 */ + {N3, P3, 0, 0}, /* 2 */ + {P3, P3, 0, 0}, /* 3 */ + {0, 0, 0, 0} /* backstop */ +}; + +/* + * Digits 0-2 (hour tens) + */ +#define P2 (P15 / 2) /* mark (+1) */ +#define N2 (N15 / 2) /* space (-1) */ + +double bcd2[][4] = { + {N2, N2, 0, 0}, /* 0 */ + {P2, N2, 0, 0}, /* 1 */ + {N2, P2, 0, 0}, /* 2 */ + {0, 0, 0, 0} /* backstop */ +}; + +/* + * DST decode (DST2 DST1) for prettyprint + */ +char dstcod[] = { + 'S', /* 00 standard time */ + 'I', /* 01 daylight warning */ + 'O', /* 10 standard warning */ + 'D' /* 11 daylight time */ +}; + +/* + * The decoding matrix consists of nine row vectors, one for each digit + * of the timecode. The digits are stored from least to most significant + * order. The maximum likelihood timecode is formed from the digits + * corresponding to the maximum likelihood values reading in the + * opposite order: yy ddd hh:mm. + */ +struct decvec { + int radix; /* radix (3, 4, 6, 10) */ + int digit; /* current clock digit */ + int mldigit; /* maximum likelihood digit */ + int phase; /* maximum likelihood digit phase */ + int count; /* match count */ + double digprb; /* max digit probability */ + double digsnr; /* likelihood function (dB) */ + double like[10]; /* likelihood integrator 0-9 */ +}; + +/* + * The station structure is used to acquire the minute pulse from WWV + * and/or WWVH. These stations are distinguished by the frequency used + * for the second and minute sync pulses, 1000 Hz for WWV and 1200 Hz + * for WWVH. Other than frequency, the format is the same. + */ +struct sync { + double amp; /* sync amplitude (I, Q square) */ + double synamp; /* sync envelope at 800 ms */ + double synmax; /* sync envelope at 0 s */ + double synmin; /* avg sync envelope at 59 s, 1 s */ + double synsnr; /* sync signal SNR */ + double noise; /* max amplitude off pulse */ + double sigmax; /* max amplitude on pulse */ + double lastmax; /* last max amplitude on pulse */ + long pos; /* position at maximum amplitude */ + long lastpos; /* last position at maximum amplitude */ + long jitter; /* shake, wiggle and waggle */ + long mepoch; /* minute synch epoch */ + int count; /* compare counter */ + char refid[5]; /* reference identifier */ + char ident[4]; /* station identifier */ + int select; /* select bits */ +}; + +/* + * The channel structure is used to mitigate between channels. At this + * point we have already decided which station to use. + */ +struct chan { + int gain; /* audio gain */ + int errcnt; /* data bit error counter */ + double noiamp; /* I-channel average noise amplitude */ + struct sync wwv; /* wwv station */ + struct sync wwvh; /* wwvh station */ +}; + +/* + * WWV unit control structure + */ +struct wwvunit { + l_fp timestamp; /* audio sample timestamp */ + l_fp tick; /* audio sample increment */ + double comp[SIZE]; /* decompanding table */ + double phase, freq; /* logical clock phase and frequency */ + double monitor; /* audio monitor point */ + int fd_icom; /* ICOM file descriptor */ + int errflg; /* error flags */ + int bufcnt; /* samples in buffer */ + int bufptr; /* buffer index pointer */ + int port; /* codec port */ + int gain; /* codec gain */ + int clipcnt; /* sample clipped count */ + int seccnt; /* second countdown */ + int minset; /* minutes since last clock set */ + int watch; /* watchcat */ + int swatch; /* second sync watchcat */ + + /* + * Variables used to establish basic system timing + */ + int avgint; /* log2 master time constant (s) */ + int epoch; /* second epoch ramp */ + int repoch; /* receiver sync epoch */ + int yepoch; /* transmitter sync epoch */ + double epomax; /* second sync amplitude */ + double irig; /* data I channel amplitude */ + double qrig; /* data Q channel amplitude */ + int datapt; /* 100 Hz ramp */ + double datpha; /* 100 Hz VFO control */ + int rphase; /* receiver sample counter */ + int rsec; /* receiver seconds counter */ + long mphase; /* minute sample counter */ + long nepoch; /* minute epoch index */ + + /* + * Variables used to mitigate which channel to use + */ + struct chan mitig[NCHAN]; /* channel data */ + struct sync *sptr; /* station pointer */ + int dchan; /* data channel */ + int schan; /* probe channel */ + int achan; /* active channel */ + + /* + * Variables used by the clock state machine + */ + struct decvec decvec[9]; /* decoding matrix */ + int cdelay; /* WWV propagation delay (samples) */ + int hdelay; /* WVVH propagation delay (samples) */ + int pdelay; /* propagation delay (samples) */ + int tphase; /* transmitter sample counter */ + int tsec; /* transmitter seconds counter */ + int digcnt; /* count of digits synchronized */ + + /* + * Variables used to estimate signal levels and bit/digit + * probabilities + */ + double sigamp; /* I-channel peak signal amplitude */ + double noiamp; /* I-channel average noise amplitude */ + double datsnr; /* data SNR (dB) */ + + /* + * Variables used to establish status and alarm conditions + */ + int status; /* status bits */ + int alarm; /* alarm flashers */ + int misc; /* miscellaneous timecode bits */ + int errcnt; /* data bit error counter */ +}; + +/* + * Function prototypes + */ +static int wwv_start P((int, struct peer *)); +static void wwv_shutdown P((int, struct peer *)); +static void wwv_receive P((struct recvbuf *)); +static void wwv_poll P((int, struct peer *)); + +/* + * More function prototypes + */ +static void wwv_epoch P((struct peer *)); +static void wwv_rf P((struct peer *, double)); +static void wwv_endpoc P((struct peer *, double, int)); +static void wwv_rsec P((struct peer *, double)); +static void wwv_qrz P((struct peer *, struct sync *, + double)); +static void wwv_corr4 P((struct peer *, struct decvec *, + double [], double [][4])); +static void wwv_gain P((struct peer *)); +static void wwv_tsec P((struct wwvunit *)); +static double wwv_data P((struct wwvunit *, double)); +static int timecode P((struct wwvunit *, char *)); +static double wwv_snr P((double, double)); +static int carry P((struct decvec *)); +static void wwv_newchan P((struct peer *)); +static int wwv_qsy P((struct peer *, int)); +static double qsy[NCHAN] = {2.5, 5, 10, 15, 20}; /* frequencies (MHz) */ + +/* + * Transfer vector + */ +struct refclock refclock_wwv = { + wwv_start, /* start up driver */ + wwv_shutdown, /* shut down driver */ + wwv_poll, /* transmit poll message */ + noentry, /* not used (old wwv_control) */ + noentry, /* initialize driver (not used) */ + noentry, /* not used (old wwv_buginfo) */ + NOFLAGS /* not used */ +}; + + +/* + * wwv_start - open the devices and initialize data for processing + */ +static int +wwv_start( + int unit, /* instance number (not used) */ + struct peer *peer /* peer structure pointer */ + ) +{ + struct refclockproc *pp; + struct wwvunit *up; + struct chan *cp; +#ifdef ICOM + int temp; +#endif /* ICOM */ + + /* + * Local variables + */ + int fd; /* file descriptor */ + int i; /* index */ + double step; /* codec adjustment */ + + /* + * Open audio device + */ + fd = audio_init(); + if (fd < 0) + return (0); +#ifdef DEBUG + if (debug) + audio_show(); +#endif + + /* + * Allocate and initialize unit structure + */ + if (!(up = (struct wwvunit *) + emalloc(sizeof(struct wwvunit)))) { + (void) close(fd); + return (0); + } + memset((char *)up, 0, sizeof(struct wwvunit)); + pp = peer->procptr; + pp->unitptr = (caddr_t)up; + pp->io.clock_recv = wwv_receive; + pp->io.srcclock = (caddr_t)peer; + pp->io.datalen = 0; + pp->io.fd = fd; + if (!io_addclock(&pp->io)) { + (void)close(fd); + free(up); + return (0); + } + + /* + * Initialize miscellaneous variables + */ + peer->precision = PRECISION; + pp->clockdesc = DESCRIPTION; + memcpy((char *)&pp->refid, REFID, 4); + DTOLFP(1. / SECOND, &up->tick); + + /* + * The companded samples are encoded sign-magnitude. The table + * contains all the 256 values in the interest of speed. + */ + up->comp[0] = up->comp[OFFSET] = 0.; + up->comp[1] = 1; up->comp[OFFSET + 1] = -1.; + up->comp[2] = 3; up->comp[OFFSET + 2] = -3.; + step = 2.; + for (i = 3; i < OFFSET; i++) { + up->comp[i] = up->comp[i - 1] + step; + up->comp[OFFSET + i] = -up->comp[i]; + if (i % 16 == 0) + step *= 2.; + } + + /* + * Initialize the decoding matrix with the radix for each digit + * position. + */ + up->decvec[MN].radix = 10; /* minutes */ + up->decvec[MN + 1].radix = 6; + up->decvec[HR].radix = 10; /* hours */ + up->decvec[HR + 1].radix = 3; + up->decvec[DA].radix = 10; /* days */ + up->decvec[DA + 1].radix = 10; + up->decvec[DA + 2].radix = 4; + up->decvec[YR].radix = 10; /* years */ + up->decvec[YR + 1].radix = 10; + + /* + * Initialize the station processes for audio gain, select bit, + * station/frequency identifier and reference identifier. + */ + up->gain = 127; + for (i = 0; i < NCHAN; i++) { + cp = &up->mitig[i]; + cp->gain = up->gain; + cp->wwv.select = SELV; + strcpy(cp->wwv.refid, "WWV "); + sprintf(cp->wwv.ident,"C%.0f", floor(qsy[i])); + cp->wwvh.select = SELH; + strcpy(cp->wwvh.refid, "WWVH"); + sprintf(cp->wwvh.ident, "H%.0f", floor(qsy[i])); + } + + /* + * Initialize autotune if available. Start out at 15 MHz. Note + * that the ICOM select code must be less than 128, so the high + * order bit can be used to select the line speed. + */ +#ifdef ICOM + temp = 0; +#ifdef DEBUG + if (debug > 1) + temp = P_TRACE; +#endif + if (peer->ttl != 0) { + if (peer->ttl & 0x80) + up->fd_icom = icom_init("/dev/icom", B1200, + temp); + else + up->fd_icom = icom_init("/dev/icom", B9600, + temp); + } + if (up->fd_icom > 0) { + up->schan = 3; + if ((temp = wwv_qsy(peer, up->schan)) < 0) { + NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT) + msyslog(LOG_ERR, + "ICOM bus error; autotune disabled"); + up->errflg = CEVNT_FAULT; + close(up->fd_icom); + up->fd_icom = 0; + } + } +#endif /* ICOM */ + return (1); +} + + +/* + * wwv_shutdown - shut down the clock + */ +static void +wwv_shutdown( + int unit, /* instance number (not used) */ + struct peer *peer /* peer structure pointer */ + ) +{ + struct refclockproc *pp; + struct wwvunit *up; + + pp = peer->procptr; + up = (struct wwvunit *)pp->unitptr; + io_closeclock(&pp->io); + if (up->fd_icom > 0) + close(up->fd_icom); + free(up); +} + + +/* + * wwv_receive - receive data from the audio device + * + * This routine reads input samples and adjusts the logical clock to + * track the A/D sample clock by dropping or duplicating codec samples. + * It also controls the A/D signal level with an AGC loop to mimimize + * quantization noise and avoid overload. + */ +static void +wwv_receive( + struct recvbuf *rbufp /* receive buffer structure pointer */ + ) +{ + struct peer *peer; + struct refclockproc *pp; + struct wwvunit *up; + + /* + * Local variables + */ + double sample; /* codec sample */ + u_char *dpt; /* buffer pointer */ + l_fp ltemp; + int isneg; + double dtemp; + int i, j; + + peer = (struct peer *)rbufp->recv_srcclock; + pp = peer->procptr; + up = (struct wwvunit *)pp->unitptr; + + /* + * Main loop - read until there ain't no more. Note codec + * samples are bit-inverted. + */ + up->timestamp = rbufp->recv_time; + up->bufcnt = rbufp->recv_length; + DTOLFP((double)up->bufcnt / SECOND, <emp); + L_SUB(&up->timestamp, <emp); + dpt = rbufp->recv_buffer; + for (up->bufptr = 0; up->bufptr < up->bufcnt; up->bufptr++) { + sample = up->comp[~*dpt & 0xff]; + + /* + * Clip noise spikes greater than MAXSIG. If no clips, + * increase the gain a tad; if the clips are too high, + * decrease a tad. + */ + if (sample > MAXSIG) { + sample = MAXSIG; + up->clipcnt++; + } else if (sample < -MAXSIG) { + sample = -MAXSIG; + up->clipcnt++; + } + + /* + * Variable frequency oscillator. A phase change of one + * unit produces a change of 360 degrees; a frequency + * change of one unit produces a change of 1 Hz. + */ + up->phase += up->freq / SECOND; + if (up->phase >= .5) { + up->phase -= 1.; + } else if (up->phase < - .5) { + up->phase += 1.; + wwv_rf(peer, sample); + wwv_rf(peer, sample); + } else { + wwv_rf(peer, sample); + } + L_ADD(&up->timestamp, &up->tick); + + /* + * Once each second adjust the codec port and gain. + * While at it, initialize the propagation delay for + * both WWV and WWVH. Don't forget to correct for the + * receiver phase delay, mostly due to the 600-Hz + * IIR bandpass filter used for the sync signals. + */ + up->cdelay = (int)(SECOND * (pp->fudgetime1 + PDELAY)); + up->hdelay = (int)(SECOND * (pp->fudgetime2 + PDELAY)); + up->seccnt = (up->seccnt + 1) % SECOND; + if (up->seccnt == 0) { + if (pp->sloppyclockflag & CLK_FLAG2) + up->port = 2; + else + up->port = 1; + } + + /* + * During development, it is handy to have an audio + * monitor that can be switched to various signals. This + * code converts the linear signal left in up->monitor + * to codec format. + */ + isneg = 0; + dtemp = up->monitor; + if (sample < 0) { + isneg = 1; + dtemp -= dtemp; + } + i = 0; + j = OFFSET >> 1; + while (j != 0) { + if (dtemp > up->comp[i]) + i += j; + else if (dtemp < up->comp[i]) + i -= j; + else + break; + j >>= 1; + } + if (isneg) + *dpt = ~(i + OFFSET); + else + *dpt = ~i; + dpt++; + } + + /* + * Squawk to the monitor speaker if enabled. + */ + if (pp->sloppyclockflag & CLK_FLAG3) + if (write(pp->io.fd, (u_char *)&rbufp->recv_space, + (u_int)up->bufcnt) < 0) + perror("wwv:"); +} + + +/* + * wwv_poll - called by the transmit procedure + * + * This routine keeps track of status. If nothing is heard for two + * successive poll intervals, a timeout event is declared and any + * orphaned timecode updates are sent to foster care. Once the clock is + * set, it always appears reachable, unless reset by watchdog timeout. + */ +static void +wwv_poll( + int unit, /* instance number (not used) */ + struct peer *peer /* peer structure pointer */ + ) +{ + struct refclockproc *pp; + struct wwvunit *up; + + pp = peer->procptr; + up = (struct wwvunit *)pp->unitptr; + if (pp->coderecv == pp->codeproc) + up->errflg = CEVNT_TIMEOUT; + else + pp->polls++; + if (up->status & INSYNC) + peer->reach |= 1; + if (up->errflg) + refclock_report(peer, up->errflg); + up->errflg = 0; +} + + +/* + * wwv_rf - process signals and demodulate to baseband + * + * This routine grooms and filters decompanded raw audio samples. The + * output signals include the 100-Hz baseband data signal in quadrature + * form, plus the epoch index of the second sync signal and the second + * index of the minute sync signal. + * + * There are three 1-s ramps used by this program, all spanning the + * range 0-7999 logical samples for exactly one second, as determined by + * the logical clock. The first drives the second epoch and runs + * continuously. The second determines the receiver phase and the third + * the transmitter phase within the second. The receiver second begins + * upon arrival of the 5-ms second sync pulse which begins the second; + * while the transmitter second begins before it by the specified + * propagation delay. + * + * There are three 1-m ramps spanning the range 0-59 seconds. The first + * drives the minute epoch in samples and runs continuously. The second + * determines the receiver second and the third the transmitter second. + * The receiver second begins upon arrival of the 800-ms sync pulse sent + * during the first second of the minute; while the transmitter second + * begins before it by the specified propagation delay. + * + * The output signals include the epoch maximum and phase and second + * maximum and index. The epoch phase provides the master reference for + * all signal and timing functions, while the second index identifies + * the first second of the minute. The epoch and second maxima are used + * to calculate SNR for gating functions. + * + * Demodulation operations are based on three synthesized quadrature + * sinusoids: 100 Hz for the data subcarrier, 1000 Hz for the WWV sync + * signals and 1200 Hz for the WWVH sync signal. These drive synchronous + * matched filters for the data subcarrier (170 ms at 100 Hz), WWV + * minute sync signal (800 ms at 1000 Hz) and WWVH minute sync signal + * (800 ms at 1200 Hz). Two additional matched filters are switched in + * as required for the WWV seconds sync signal (5 ms at 1000 Hz) and + * WWVH seconds sync signal (5 ms at 1200 Hz). + */ +static void +wwv_rf( + struct peer *peer, /* peerstructure pointer */ + double isig /* input signal */ + ) +{ + struct refclockproc *pp; + struct wwvunit *up; + + static double lpf[5]; /* 150-Hz lpf delay line */ + double data; /* lpf output */ + static double bpf[9]; /* 1000/1200-Hz bpf delay line */ + double syncx; /* bpf output */ + static double mf[41]; /* 1000/1200-Hz mf delay line */ + double mfsync; /* mf output */ + + static int iptr; /* data channel pointer */ + static double ibuf[DATSIZ]; /* data I channel delay line */ + static double qbuf[DATSIZ]; /* data Q channel delay line */ + + static int jptr; /* sync channel pointer */ + static double cibuf[SYNSIZ]; /* wwv I channel delay line */ + static double cqbuf[SYNSIZ]; /* wwv Q channel delay line */ + static double ciamp; /* wwv I channel amplitude */ + static double cqamp; /* wwv Q channel amplitude */ + static int csinptr; /* wwv channel phase */ + static double hibuf[SYNSIZ]; /* wwvh I channel delay line */ + static double hqbuf[SYNSIZ]; /* wwvh Q channel delay line */ + static double hiamp; /* wwvh I channel amplitude */ + static double hqamp; /* wwvh Q channel amplitude */ + static int hsinptr; /* wwvh channels phase */ + + static double epobuf[SECOND]; /* epoch sync comb filter */ + static double epomax; /* epoch sync amplitude buffer */ + static int epopos; /* epoch sync position buffer */ + + static int iniflg; /* initialization flag */ + struct sync *sp; + double dtemp; + long ltemp; + int i; + + pp = peer->procptr; + up = (struct wwvunit *)pp->unitptr; + if (!iniflg) { + iniflg = 1; + memset((char *)lpf, 0, sizeof(lpf)); + memset((char *)bpf, 0, sizeof(bpf)); + memset((char *)mf, 0, sizeof(mf)); + memset((char *)ibuf, 0, sizeof(ibuf)); + memset((char *)qbuf, 0, sizeof(qbuf)); + memset((char *)cibuf, 0, sizeof(cibuf)); + memset((char *)cqbuf, 0, sizeof(cqbuf)); + memset((char *)hibuf, 0, sizeof(hibuf)); + memset((char *)hqbuf, 0, sizeof(hqbuf)); + memset((char *)epobuf, 0, sizeof(epobuf)); + } + up->monitor = isig; /* change for debug */ + + /* + * Baseband data demodulation. The 100-Hz subcarrier is + * extracted using a 150-Hz IIR lowpass filter. This attenuates + * the 1000/1200-Hz sync signals, as well as the 440-Hz and + * 600-Hz tones and most of the noise and voice modulation + * components. + * + * Matlab IIR 4th-order IIR elliptic, 150 Hz lowpass, 0.2 dB + * passband ripple, -50 dB stopband ripple. + */ + data = (lpf[4] = lpf[3]) * 8.360961e-01; + data += (lpf[3] = lpf[2]) * -3.481740e+00; + data += (lpf[2] = lpf[1]) * 5.452988e+00; + data += (lpf[1] = lpf[0]) * -3.807229e+00; + lpf[0] = isig - data; + data = lpf[0] * 3.281435e-03 + + lpf[1] * -1.149947e-02 + + lpf[2] * 1.654858e-02 + + lpf[3] * -1.149947e-02 + + lpf[4] * 3.281435e-03; + + /* + * The I and Q quadrature data signals are produced by + * multiplying the filtered signal by 100-Hz sine and cosine + * signals, respectively. The data signals are demodulated by + * 170-ms synchronous matched filters to produce the amplitude + * and phase signals used by the decoder. Note the correction + * due to the propagation delay is necessary for seamless + * handover between WWV and WWVH. + */ + i = up->datapt - up->pdelay % 80; + if (i < 0) + i += 80; + up->datapt = (up->datapt + IN100) % 80; + dtemp = sintab[i] * data / DATSIZ * DGAIN; + up->irig -= ibuf[iptr]; + ibuf[iptr] = dtemp; + up->irig += dtemp; + i = (i + 20) % 80; + dtemp = sintab[i] * data / DATSIZ * DGAIN; + up->qrig -= qbuf[iptr]; + qbuf[iptr] = dtemp; + up->qrig += dtemp; + iptr = (iptr + 1) % DATSIZ; + + /* + * Baseband sync demodulation. The 1000/1200 sync signals are + * extracted using a 600-Hz IIR bandpass filter. This removes + * the 100-Hz data subcarrier, as well as the 440-Hz and 600-Hz + * tones and most of the noise and voice modulation components. + * + * Matlab 4th-order IIR elliptic, 800-1400 Hz bandpass, 0.2 dB + * passband ripple, -50 dB stopband ripple. + */ + syncx = (bpf[8] = bpf[7]) * 4.897278e-01; + syncx += (bpf[7] = bpf[6]) * -2.765914e+00; + syncx += (bpf[6] = bpf[5]) * 8.110921e+00; + syncx += (bpf[5] = bpf[4]) * -1.517732e+01; + syncx += (bpf[4] = bpf[3]) * 1.975197e+01; + syncx += (bpf[3] = bpf[2]) * -1.814365e+01; + syncx += (bpf[2] = bpf[1]) * 1.159783e+01; + syncx += (bpf[1] = bpf[0]) * -4.735040e+00; + bpf[0] = isig - syncx; + syncx = bpf[0] * 8.203628e-03 + + bpf[1] * -2.375732e-02 + + bpf[2] * 3.353214e-02 + + bpf[3] * -4.080258e-02 + + bpf[4] * 4.605479e-02 + + bpf[5] * -4.080258e-02 + + bpf[6] * 3.353214e-02 + + bpf[7] * -2.375732e-02 + + bpf[8] * 8.203628e-03; + + /* + * The I and Q quadrature minute sync signals are produced by + * multiplying the filtered signal by 1000-Hz (WWV) and 1200-Hz + * (WWVH) sine and cosine signals, respectively. The resulting + * signals are demodulated by 800-ms synchronous matched filters + * to synchronize the second and minute and to detect which one + * (or both) the WWV or WWVH signal is present. + */ + up->mphase = (up->mphase + 1) % MINUTE; + + i = csinptr; + csinptr = (csinptr + IN1000) % 80; + dtemp = sintab[i] * syncx / SYNSIZ * SGAIN; + ciamp = ciamp - cibuf[jptr] + dtemp; + cibuf[jptr] = dtemp; + i = (i + 20) % 80; + dtemp = sintab[i] * syncx / SYNSIZ * SGAIN; + cqamp = cqamp - cqbuf[jptr] + dtemp; + cqbuf[jptr] = dtemp; + dtemp = ciamp * ciamp + cqamp * cqamp; + wwv_qrz(peer, &up->mitig[up->schan].wwv, dtemp); + + i = hsinptr; + hsinptr = (hsinptr + IN1200) % 80; + dtemp = sintab[i] * syncx / SYNSIZ * SGAIN; + hiamp = hiamp - hibuf[jptr] + dtemp; + hibuf[jptr] = dtemp; + i = (i + 20) % 80; + dtemp = sintab[i] * syncx / SYNSIZ * SGAIN; + hqamp = hqamp - hqbuf[jptr] + dtemp; + hqbuf[jptr] = dtemp; + dtemp = hiamp * hiamp + hqamp * hqamp; + wwv_qrz(peer, &up->mitig[up->schan].wwvh, dtemp); + + jptr = (jptr + 1) % SYNSIZ; + + if (up->mphase == 0) { + + /* + * This section is called once per minute at the minute + * epoch independently of the transmitter or receiver + * minute. If the leap bit is set, set the minute epoch + * back one second so the station processes don't miss a + * beat. Then, increment the watchdog counter and test + * for two sets of conditions depending on whether + * minute sync has been acquired or not. + */ + up->watch++; + if (up->rsec == 60) { + up->mphase -= SECOND; + if (up->mphase < 0) + up->mphase += MINUTE; + } else if (!(up->status & MSYNC)) { + + /* + * If minute sync has not been acquired, the + * program listens for minute sync pulses from + * both WWV and WWVH. The station with the + * greater compare count is selected, with ties + * broken by WWV, but only if the count is at + * least three. Once a station has been + * acquired, it is initialized and begins + * tracking the signal. + */ + if (up->mitig[up->achan].wwv.count >= + up->mitig[up->achan].wwvh.count) + sp = &up->mitig[up->achan].wwv; + else + sp = &up->mitig[up->achan].wwvh; + if (sp->count >= AMIN) { + up->watch = up->swatch = 0; + up->status |= MSYNC; + ltemp = sp->mepoch - SYNSIZ; + if (ltemp < 0) + ltemp += MINUTE; + up->rsec = (MINUTE - ltemp) / SECOND; + if (!(up->status & SSYNC)) { + up->repoch = ltemp % SECOND; + up->yepoch = up->repoch - + up->pdelay; + if (up->yepoch < 0) + up->yepoch += SECOND; + } + wwv_newchan(peer); + } else if (sp->count == 0 || up->watch >= ACQSN) + { + up->watch = sp->count = 0; + up->schan = (up->schan + 1) % NCHAN; + wwv_qsy(peer, up->schan); + } + } else { + + /* + * If minute sync has been acquired, the program + * watches for timeout. The timeout is reset + * when the clock is set or verified. If a + * timeout occurs and the minute units digit has + * not synchronized, reset the program and start + * over. + */ + if (up->watch > DIGIT && !(up->status & DSYNC)) + up->watch = up->status = 0; + + /* + * If the second sync times out, dim the sync + * lamp and raise an alarm. + */ + up->swatch++; + if (up->swatch > HSPEC) + up->status &= ~SSYNC; + if (!(up->status & SSYNC)) + up->alarm |= 1 << SYNERR; + } + } + + /* + * The second sync pulse is extracted using 5-ms FIR matched + * filters at 1000 Hz for WWV or 1200 Hz for WWVH. This pulse is + * used for the most precise synchronization, since if provides + * a resolution of one sample (125 us). + */ + if (up->status & SELV) { + up->pdelay = up->cdelay; + + /* + * WWV FIR matched filter, five cycles of 1000-Hz + * sinewave. + */ + mf[40] = mf[39]; + mfsync = (mf[39] = mf[38]) * 4.224514e-02; + mfsync += (mf[38] = mf[37]) * 5.974365e-02; + mfsync += (mf[37] = mf[36]) * 4.224514e-02; + mf[36] = mf[35]; + mfsync += (mf[35] = mf[34]) * -4.224514e-02; + mfsync += (mf[34] = mf[33]) * -5.974365e-02; + mfsync += (mf[33] = mf[32]) * -4.224514e-02; + mf[32] = mf[31]; + mfsync += (mf[31] = mf[30]) * 4.224514e-02; + mfsync += (mf[30] = mf[29]) * 5.974365e-02; + mfsync += (mf[29] = mf[28]) * 4.224514e-02; + mf[28] = mf[27]; + mfsync += (mf[27] = mf[26]) * -4.224514e-02; + mfsync += (mf[26] = mf[25]) * -5.974365e-02; + mfsync += (mf[25] = mf[24]) * -4.224514e-02; + mf[24] = mf[23]; + mfsync += (mf[23] = mf[22]) * 4.224514e-02; + mfsync += (mf[22] = mf[21]) * 5.974365e-02; + mfsync += (mf[21] = mf[20]) * 4.224514e-02; + mf[20] = mf[19]; + mfsync += (mf[19] = mf[18]) * -4.224514e-02; + mfsync += (mf[18] = mf[17]) * -5.974365e-02; + mfsync += (mf[17] = mf[16]) * -4.224514e-02; + mf[16] = mf[15]; + mfsync += (mf[15] = mf[14]) * 4.224514e-02; + mfsync += (mf[14] = mf[13]) * 5.974365e-02; + mfsync += (mf[13] = mf[12]) * 4.224514e-02; + mf[12] = mf[11]; + mfsync += (mf[11] = mf[10]) * -4.224514e-02; + mfsync += (mf[10] = mf[9]) * -5.974365e-02; + mfsync += (mf[9] = mf[8]) * -4.224514e-02; + mf[8] = mf[7]; + mfsync += (mf[7] = mf[6]) * 4.224514e-02; + mfsync += (mf[6] = mf[5]) * 5.974365e-02; + mfsync += (mf[5] = mf[4]) * 4.224514e-02; + mf[4] = mf[3]; + mfsync += (mf[3] = mf[2]) * -4.224514e-02; + mfsync += (mf[2] = mf[1]) * -5.974365e-02; + mfsync += (mf[1] = mf[0]) * -4.224514e-02; + mf[0] = syncx; + } else if (up->status & SELH) { + up->pdelay = up->hdelay; + + /* + * WWVH FIR matched filter, six cycles of 1200-Hz + * sinewave. + */ + mf[40] = mf[39]; + mfsync = (mf[39] = mf[38]) * 4.833363e-02; + mfsync += (mf[38] = mf[37]) * 5.681959e-02; + mfsync += (mf[37] = mf[36]) * 1.846180e-02; + mfsync += (mf[36] = mf[35]) * -3.511644e-02; + mfsync += (mf[35] = mf[34]) * -5.974365e-02; + mfsync += (mf[34] = mf[33]) * -3.511644e-02; + mfsync += (mf[33] = mf[32]) * 1.846180e-02; + mfsync += (mf[32] = mf[31]) * 5.681959e-02; + mfsync += (mf[31] = mf[30]) * 4.833363e-02; + mf[30] = mf[29]; + mfsync += (mf[29] = mf[28]) * -4.833363e-02; + mfsync += (mf[28] = mf[27]) * -5.681959e-02; + mfsync += (mf[27] = mf[26]) * -1.846180e-02; + mfsync += (mf[26] = mf[25]) * 3.511644e-02; + mfsync += (mf[25] = mf[24]) * 5.974365e-02; + mfsync += (mf[24] = mf[23]) * 3.511644e-02; + mfsync += (mf[23] = mf[22]) * -1.846180e-02; + mfsync += (mf[22] = mf[21]) * -5.681959e-02; + mfsync += (mf[21] = mf[20]) * -4.833363e-02; + mf[20] = mf[19]; + mfsync += (mf[19] = mf[18]) * 4.833363e-02; + mfsync += (mf[18] = mf[17]) * 5.681959e-02; + mfsync += (mf[17] = mf[16]) * 1.846180e-02; + mfsync += (mf[16] = mf[15]) * -3.511644e-02; + mfsync += (mf[15] = mf[14]) * -5.974365e-02; + mfsync += (mf[14] = mf[13]) * -3.511644e-02; + mfsync += (mf[13] = mf[12]) * 1.846180e-02; + mfsync += (mf[12] = mf[11]) * 5.681959e-02; + mfsync += (mf[11] = mf[10]) * 4.833363e-02; + mf[10] = mf[9]; + mfsync += (mf[9] = mf[8]) * -4.833363e-02; + mfsync += (mf[8] = mf[7]) * -5.681959e-02; + mfsync += (mf[7] = mf[6]) * -1.846180e-02; + mfsync += (mf[6] = mf[5]) * 3.511644e-02; + mfsync += (mf[5] = mf[4]) * 5.974365e-02; + mfsync += (mf[4] = mf[3]) * 3.511644e-02; + mfsync += (mf[3] = mf[2]) * -1.846180e-02; + mfsync += (mf[2] = mf[1]) * -5.681959e-02; + mfsync += (mf[1] = mf[0]) * -4.833363e-02; + mf[0] = syncx; + } else { + mfsync = 0; + } + + /* + * Extract the seconds sync pulse using a 1-s comb filter at + * baseband. Correct for the FIR matched filter delay, which is + * 5 ms for both the WWV and WWVH filters. Blank the signal when + * probing. + */ + up->epoch = (up->epoch + 1) % SECOND; + if (up->epoch == 0) { + wwv_endpoc(peer, epomax, epopos); + up->epomax = epomax; + epomax = 0; + if (!(up->status & MSYNC)) + wwv_gain(peer); + } + dtemp = (epobuf[up->epoch] += (mfsync - epobuf[up->epoch]) / + (MINAVG << up->avgint)); + if (dtemp > epomax) { + epomax = dtemp; + epopos = up->epoch - up->pdelay - 5 * MS; + if (epopos < 0) + epopos += SECOND; + } + if (up->status & MSYNC) + wwv_epoch(peer); +} + + +/* + * wwv_qrz - identify and acquire WWV/WWVH minute sync pulse + * + * This routine implements a virtual station process used to acquire + * minute sync and to mitigate among the ten frequency and station + * combinations. During minute sync acquisition, the process probes each + * frequency in turn for the minute pulse from either station, which + * involves searching through the entire epoch minute of samples. After + * minute sync acquisition, the process searches only during the probe + * window, which occupies seconds 59, 0 and 1, to construct a metric + * used to determine which frequency and station provides the best + * signal. + * + * The pulse discriminator requires that (a) the peak on-pulse sample + * amplitude must be above 2000, (b) the SNR relative to the peak + * off-pulse sample amplitude must be reduced 6 dB or more below the + * peak and (c) the maximum difference between the current and previous + * epoch indices must be less than 50 ms. A compare counter keeps track + * of the number of successive intervals which satisfy these criteria. + * + * Students of radar receiver technology will discover this algorithm + * amounts to a range gate discriminator. In practice, the performance + * of this gadget is amazing. Once setting teeth in a station, it hangs + * on until the minute beep can barely be heard and long after the + * second tick and comb filter have given up. + */ +static void +wwv_qrz( + struct peer *peer, /* peerstructure pointer */ + struct sync *sp, /* sync channel structure */ + double syncx /* bandpass filtered sync signal */ + ) +{ + struct refclockproc *pp; + struct wwvunit *up; + char tbuf[80]; /* monitor buffer */ + double snr; /* on-pulse/off-pulse ratio (dB) */ + long epoch; + int isgood; + + pp = peer->procptr; + up = (struct wwvunit *)pp->unitptr; + + /* + * Find the sample with peak energy, which defines the minute + * epoch. If minute sync has been acquired, search only the + * probe window; otherwise, search the entire minute. If a + * maximum has been found with good amplitude, search only the + * second before and after that position for the next maximum + * and the rest of the window for the noise. + */ + if (!(up->status & MSYNC) || up->status & SFLAG) { + sp->amp = syncx; + if (up->status & MSYNC) + epoch = up->nepoch; + else if (sp->count > 1) + epoch = sp->mepoch; + else + epoch = sp->lastpos; + if (syncx > sp->sigmax) { + sp->sigmax = syncx; + sp->pos = up->mphase; + } + if (abs(MOD(up->mphase - epoch, MINUTE)) > SYNSIZ && + syncx > sp->noise) { + sp->noise = syncx; + } + } + if (up->mphase == 0) { + + /* + * At the end of the minute, determine the epoch of the + * sync pulse, as well as the SNR and difference between + * the current and previous epoch (jitter). + */ + sp->jitter = MOD(sp->pos - sp->lastpos, MINUTE); + sp->select &= ~JITRNG; + if (abs(sp->jitter) > AWND * MS) + sp->select |= JITRNG; + sp->sigmax = sqrt(sp->sigmax); + sp->noise = sqrt(sp->noise); + if (up->status & MSYNC) { + + /* + * If in minute sync, just count the runs up and + * down. + */ + if (sp->select & (DATANG | SYNCNG | JITRNG)) { + if (sp->count > 0) + sp->count--; + } else { + if (sp->count < AMAX) + sp->count++; + } + } else { + + /* + * If not yet in minute sync, we have to do a + * little dance to find a valid minute sync + * pulse, emphasis valid. + */ + snr = wwv_snr(sp->sigmax, sp->noise); + isgood = sp->sigmax > ATHR && snr > ASNR && + !(sp->select & JITRNG); + switch (sp->count) { + + /* + * In state 0 the station was not heard during + * the previous probe. Look for the biggest blip + * greater than the amplitude threshold in the + * minute and assume that the minute sync pulse. + * If found, bump to state 1. + */ + case 0: + if (sp->sigmax >= ATHR) + sp->count++; + break; + + /* + * In state 1 a candidate blip has been found + * and the next minute has been searched for + * another blip. If none are found greater than + * the threshold, or if the biggest blip outside + * the candidate pulse is less than 6 dB below + * the biggest blip, drop back to state 0 and + * hunt some more. Otherwise, a legitimate + * minute pulse may have been found, so bump to + * state 2. + */ + case 1: + if (sp->sigmax < ATHR) { + sp->count--; + break; + } else if (!isgood) { + break; + } + /* fall through */ + + /* + * In states 2 and above, continue to groom + * samples as before and drop back to the + * previous state if the groom fails. If it + * succeeds, bump to the next state until + * reaching the clamp, if ever. + */ + default: + if (!isgood) { + sp->count--; + break; + } + sp->mepoch = sp->pos; + if (sp->count < AMAX) + sp->count++; + break; + } + sprintf(tbuf, + "wwv8 %d %3d %-3s %d %5.0f %5.1f %7ld %7ld %7ld", + up->port, up->gain, sp->ident, sp->count, + sp->sigmax, snr, sp->pos, sp->jitter, + MOD(sp->pos - up->nepoch - SYNSIZ, MINUTE)); + if (pp->sloppyclockflag & CLK_FLAG4) + record_clock_stats(&peer->srcadr, tbuf); +#ifdef DEBUG + if (debug) + printf("%s\n", tbuf); +#endif + } + sp->lastmax = sp->sigmax; + sp->lastpos = sp->pos; + sp->sigmax = sp->noise = 0; + } +} + + +/* + * wwv_endpoc - process receiver epoch + * + * This routine is called at the end of the receiver epoch. It + * determines the epoch position within the second and disciplines the + * sample clock using a frequency-lock loop (FLL). + * + * Seconds sync is determined in the RF input routine as the maximum + * over all 8000 samples in the second comb filter. To assure accurate + * and reliable time and frequency discipline, this routine performs a + * great deal of heavy-handed data filtering and grooming. + */ +static void +wwv_endpoc( + struct peer *peer, /* peer structure pointer */ + double epomax, /* epoch max */ + int epopos /* epoch max position */ + ) +{ + struct refclockproc *pp; + struct wwvunit *up; + + static int epoch_mf[3]; /* epoch median filter */ + static int tepoch; /* median filter epoch */ + static int tspan; /* median filter span */ + static int xepoch; /* last second epoch */ + static int zepoch; /* last averaging interval epoch */ + static int syncnt; /* second epoch run length counter */ + static int jitcnt; /* jitter holdoff counter */ + static int avgcnt; /* averaging interval counter */ + static int avginc; /* averaging ratchet */ + + static int iniflg; /* initialization flag */ + char tbuf[80]; /* monitor buffer */ + double dtemp; + int tmp2, tmp3; + + pp = peer->procptr; + up = (struct wwvunit *)pp->unitptr; + if (!iniflg) { + iniflg = 1; + memset((char *)epoch_mf, 0, sizeof(epoch_mf)); + } + + /* + * A three-stage median filter is used to help denoise the + * seconds sync pulse. The median sample becomes the candidate + * epoch; the difference between the other two samples becomes + * the span, which is used currently only for debugging. + */ + epoch_mf[2] = epoch_mf[1]; + epoch_mf[1] = epoch_mf[0]; + epoch_mf[0] = epopos; + if (epoch_mf[0] > epoch_mf[1]) { + if (epoch_mf[1] > epoch_mf[2]) { + tepoch = epoch_mf[1]; /* 0 1 2 */ + tspan = epoch_mf[0] - epoch_mf[2]; + } else if (epoch_mf[2] > epoch_mf[0]) { + tepoch = epoch_mf[0]; /* 2 0 1 */ + tspan = epoch_mf[2] - epoch_mf[1]; + } else { + tepoch = epoch_mf[2]; /* 0 2 1 */ + tspan = epoch_mf[0] - epoch_mf[1]; + } + } else { + if (epoch_mf[1] < epoch_mf[2]) { + tepoch = epoch_mf[1]; /* 2 1 0 */ + tspan = epoch_mf[2] - epoch_mf[0]; + } else if (epoch_mf[2] < epoch_mf[0]) { + tepoch = epoch_mf[0]; /* 1 0 2 */ + tspan = epoch_mf[1] - epoch_mf[2]; + } else { + tepoch = epoch_mf[2]; /* 1 2 0 */ + tspan = epoch_mf[1] - epoch_mf[0]; + } + } + + /* + * If the epoch candidate is within 1 ms of the last one, the + * new candidate replaces the last one and the jitter counter is + * reset; otherwise, the candidate is ignored and the jitter + * counter is incremented. If the jitter counter exceeds the + * frequency averaging interval, the new candidate replaces the + * old one anyway. The compare counter is incremented if the new + * candidate is identical to the last one; otherwise, it is + * forced to zero. If the compare counter increments to 10, the + * epoch is reset and the receiver second epoch is set. + * + * Careful attention to detail here. If the signal amplitude + * falls below the threshold or if no stations are heard, we + * certainly cannot be in sync. + */ + tmp2 = MOD(tepoch - xepoch, SECOND); + if (up->epomax < STHR || !(up->status & (SELV | SELH))) { + up->status &= ~SSYNC; + jitcnt = syncnt = avgcnt = 0; + } else if (abs(tmp2) <= MS || jitcnt >= (MINAVG << up->avgint)) + { + jitcnt = 0; + if (tmp2 != 0) { + xepoch = tepoch; + syncnt = 0; + } else { + if (syncnt < SCMP) { + syncnt++; + } else { + up->status |= SSYNC; + up->swatch = 0; + up->repoch = tepoch; + up->yepoch = up->repoch; + if (up->yepoch < 0) + up->yepoch += SECOND; + } + } + avgcnt++; + } else { + jitcnt++; + syncnt = avgcnt = 0; + } + if (!(up->status & SSYNC) && 0) { + sprintf(tbuf, + "wwv1 %2d %04x %5.0f %2d %5.0f %5d %5d %5d %2d %4d", + up->rsec, up->status, up->epomax, avgcnt, epomax, + tepoch, tspan, tmp2, syncnt, jitcnt); + if (pp->sloppyclockflag & CLK_FLAG4) + record_clock_stats(&peer->srcadr, tbuf); +#ifdef DEBUG + if (debug) + printf("%s\n", tbuf); +#endif /* DEBUG */ + } + + /* + * The sample clock frequency is disciplined using a first-order + * feedback loop with time constant consistent with the Allan + * intercept of typical computer clocks. The loop update is + * calculated each averaging interval from the epoch change in + * 125-us units and interval length in seconds. The interval is + * doubled after four intervals where epoch change is not more + * than one sample. + * + * The averaging interval affects other receiver functions, + * including the the 1000/1200-Hz comb filter and sample clock + * loop. It also affects the 100-Hz subcarrier loop and the bit + * and digit comparison counter thresholds. + */ + tmp3 = MOD(tepoch - zepoch, SECOND); + if (avgcnt >= (MINAVG << up->avgint)) { + if (abs(tmp3) < MS) { + dtemp = (double)tmp3 / avgcnt; + up->freq += dtemp / SYNCTC; + if (up->freq > MAXFREQ) + up->freq = MAXFREQ; + else if (up->freq < -MAXFREQ) + up->freq = -MAXFREQ; + if (abs(tmp3) <= 1 && up->avgint < MAXAVG) { + if (avginc < 4) { + avginc++; + } else { + avginc = 0; + up->avgint++; + } + } + if (up->avgint < MAXAVG) { + sprintf(tbuf, + "wwv2 %2d %04x %5.0f %5d %5d %2d %2d %6.1f %6.1f", + up->rsec, up->status, up->epomax, + MINAVG << up->avgint, avgcnt, + avginc, tmp3, dtemp / SECOND * 1e6, + up->freq / SECOND * 1e6); + if (pp->sloppyclockflag & CLK_FLAG4) + record_clock_stats( + &peer->srcadr, tbuf); +#ifdef DEBUG + if (debug) + printf("%s\n", tbuf); +#endif /* DEBUG */ + } + } + zepoch = tepoch; + avgcnt = 0; + } +} + + +/* + * wwv_epoch - main loop + * + * This routine establishes receiver and transmitter epoch + * synchronization and determines the data subcarrier pulse length. + * Receiver synchronization is determined by the minute sync pulse + * detected in the wwv_rf() routine and the second sync pulse detected + * in the wwv_epoch() routine. This establishes when to sample the data + * subcarrier in-phase signal for the maximum level and noise level and + * when to determine the pulse length. The transmitter second leads the + * receiver second by the propagation delay, receiver delay and filter + * delay of this program. It establishes the clock time and implements + * the sometimes idiosyncratic conventional clock time and civil + * calendar. + * + * Most communications radios use a highpass filter in the audio stages, + * which can do nasty things to the subcarrier phase relative to the + * sync pulses. Therefore, the data subcarrier reference phase is + * disciplined using the hardlimited quadrature-phase signal sampled at + * the same time as the in-phase signal. The phase tracking loop uses + * phase adjustments of plus-minus one sample (125 us). + */ +static void +wwv_epoch( + struct peer *peer /* peer structure pointer */ + ) +{ + static double dpulse; /* data pulse length */ + struct refclockproc *pp; + struct wwvunit *up; + struct chan *cp; + struct sync *sp; + l_fp offset; /* NTP format offset */ + double dtemp; + + pp = peer->procptr; + up = (struct wwvunit *)pp->unitptr; + + /* + * Sample the minute sync pulse amplitude at epoch 800 for both + * the WWV and WWVH stations. This will be used later for + * channel mitigation. + */ + cp = &up->mitig[up->achan]; + if (up->rphase == 800 * MS) { + sp = &cp->wwv; + sp->synamp = sqrt(sp->amp); + sp = &cp->wwvh; + sp->synamp = sqrt(sp->amp); + } + + if (up->rsec == 0) { + up->sigamp = up->datsnr = 0; + } else { + + /* + * Estimate the noise level by integrating the I-channel + * energy at epoch 30 ms. + */ + if (up->rphase == 30 * MS) { + if (!(up->status & SFLAG)) + up->noiamp += (up->irig - up->noiamp) / + (MINAVG << up->avgint); + else + cp->noiamp += (sqrt(up->irig * + up->irig + up->qrig * up->qrig) - + cp->noiamp) / 8; + + /* + * Strobe the peak I-channel data signal at epoch 200 + * ms. Compute the SNR and adjust the 100-Hz reference + * oscillator phase using the Q-channel data signal at + * that epoch. Save the envelope amplitude for the probe + * channel. + */ + } else if (up->rphase == 200 * MS) { + if (!(up->status & SFLAG)) { + up->sigamp = up->irig; + if (up->sigamp < 0) + up->sigamp = 0; + up->datsnr = wwv_snr(up->sigamp, + up->noiamp); + up->datpha = up->qrig / (MINAVG << + up->avgint); + if (up->datpha >= 0) { + up->datapt++; + if (up->datapt >= 80) + up->datapt -= 80; + } else { + up->datapt--; + if (up->datapt < 0) + up->datapt += 80; + } + } else { + up->sigamp = sqrt(up->irig * up->irig + + up->qrig * up->qrig); + up->datsnr = wwv_snr(up->sigamp, + cp->noiamp); + } + + /* + * The slice level is set half way between the peak + * signal and noise levels. Strobe the negative zero + * crossing after epoch 200 ms and record the epoch at + * that time. This defines the length of the data pulse, + * which will later be converted into scaled bit + * probabilities. + */ + } else if (up->rphase > 200 * MS) { + dtemp = (up->sigamp + up->noiamp) / 2; + if (up->irig < dtemp && dpulse == 0) + dpulse = up->rphase; + } + } + + /* + * At the end of the transmitter second, crank the clock state + * machine. Note we have to be careful to set the transmitter + * epoch at the same time as the receiver epoch to be sure the + * right propagation delay is used. We don't bother the heavy + * machinery unless the clock is set. + */ + up->tphase++; + if (up->epoch == up->yepoch) { + wwv_tsec(up); + up->tphase = 0; + + /* + * Determine the current offset from the time of century + * and the sample timestamp, but only if the SYNERR + * alarm has not been raised in the present or previous + * minute. + */ + if (!(up->status & SFLAG) && up->status & INSYNC && + (up->alarm & (3 << SYNERR)) == 0) { + pp->second = up->tsec; + pp->minute = up->decvec[MN].digit + + up->decvec[MN + 1].digit * 10; + pp->hour = up->decvec[HR].digit + + up->decvec[HR + 1].digit * 10; + pp->day = up->decvec[DA].digit + up->decvec[DA + + 1].digit * 10 + up->decvec[DA + 2].digit * + 100; + pp->year = up->decvec[YR].digit + + up->decvec[YR + 1].digit * 10; + if (pp->year < UTCYEAR) + pp->year += 2000; + else + pp->year += 1900; + + /* + * We have to simulate refclock_process() here, + * since the fudgetime gets added much earlier + * than this. + */ + pp->lastrec = up->timestamp; + L_CLR(&offset); + if (!clocktime(pp->day, pp->hour, pp->minute, + pp->second, GMT, pp->lastrec.l_ui, + &pp->yearstart, &offset.l_ui)) + up->errflg = CEVNT_BADTIME; + else + refclock_process_offset(pp, offset, + pp->lastrec, 0.); + } + } + + /* + * At the end of the receiver second, process the data bit and + * update the decoding matrix probabilities. + */ + up->rphase++; + if (up->epoch == up->repoch) { + wwv_rsec(peer, dpulse); + wwv_gain(peer); + up->rphase = dpulse = 0; + } +} + + +/* + * wwv_rsec - process receiver second + * + * This routine is called at the end of each receiver second to + * implement the per-second state machine. The machine assembles BCD + * digit bits, decodes miscellaneous bits and dances the leap seconds. + * + * Normally, the minute has 60 seconds numbered 0-59. If the leap + * warning bit is set, the last minute (1439) of 30 June (day 181 or 182 + * for leap years) or 31 December (day 365 or 366 for leap years) is + * augmented by one second numbered 60. This is accomplished by + * extending the minute interval by one second and teaching the state + * machine to ignore it. BTW, stations WWV/WWVH cowardly kill the + * transmitter carrier for a few seconds around the leap to avoid icky + * details of transmission format during the leap. + */ +static void +wwv_rsec( + struct peer *peer, /* peer structure pointer */ + double dpulse + ) +{ + static int iniflg; /* initialization flag */ + static double bcddld[4]; /* BCD data bits */ + static double bitvec[61]; /* bit integrator for misc bits */ + struct refclockproc *pp; + struct wwvunit *up; + struct chan *cp; + struct sync *sp, *rp; + double bit; /* bit likelihood */ + char tbuf[80]; /* monitor buffer */ + int sw, arg, nsec; + + pp = peer->procptr; + up = (struct wwvunit *)pp->unitptr; + if (!iniflg) { + iniflg = 1; + memset((char *)bitvec, 0, sizeof(bitvec)); + } + + /* + * The bit represents the probability of a hit on zero (negative + * values), a hit on one (positive values) or a miss (zero + * value). The likelihood vector is the exponential average of + * these probabilities. Only the bits of this vector + * corresponding to the miscellaneous bits of the timecode are + * used, but it's easier to do them all. After that, crank the + * seconds state machine. + */ + nsec = up->rsec + 1; + bit = wwv_data(up, dpulse); + bitvec[up->rsec] += (bit - bitvec[up->rsec]) / TCONST; + sw = progx[up->rsec].sw; + arg = progx[up->rsec].arg; + switch (sw) { + + /* + * Ignore this second. + */ + case IDLE: /* 9, 45-49 */ + break; + + /* + * Probe channel stuff + * + * The WWV/H format contains data pulses in second 59 (position + * identifier) and second 1 (not used), and the minute sync + * pulse in second 0. At the end of second 58, we QSYed to the + * probe channel, which rotates over all WWV/H frequencies. At + * the end of second 59, we latched the sync noise and tested + * for data bit error. At the end of second 0, we now latch the + * sync peak. + */ + case SYNC2: /* 0 */ + cp = &up->mitig[up->achan]; + sp = &cp->wwv; + sp->synmax = sp->synamp; + sp = &cp->wwvh; + sp->synmax = sp->synamp; + break; + + /* + * At the end of second 1, latch and average the sync noise and + * test for data bit error. Set SYNCNG if the sync pulse + * amplitude and SNR are not above thresholds. Set DATANG if + * data error occured on both second 59 and second 1. Finally, + * QSY back to the data channel. + */ + case SYNC3: /* 1 */ + cp = &up->mitig[up->achan]; + if (up->sigamp < DTHR || up->datsnr < DSNR) + cp->errcnt++; + + sp = &cp->wwv; + sp->synmin = (sp->synmin + sp->synamp) / 2; + sp->synsnr = wwv_snr(sp->synmax, sp->synmin); + sp->select &= ~(DATANG | SYNCNG); + if (sp->synmax < QTHR || sp->synsnr < QSNR) + sp->select |= SYNCNG; + if (cp->errcnt > 1) + sp->select |= DATANG; + + rp = &cp->wwvh; + rp->synmin = (rp->synmin + rp->synamp) / 2; + rp->synsnr = wwv_snr(rp->synmax, rp->synmin); + rp->select &= ~(DATANG | SYNCNG); + if (rp->synmax < QTHR || rp->synsnr < QSNR) + rp->select |= SYNCNG; + if (cp->errcnt > 1) + rp->select |= DATANG; + + cp->errcnt = 0; + sprintf(tbuf, + "wwv5 %d %3d %-3s %04x %d %.0f/%.1f/%ld %s %04x %d %.0f/%.1f/%ld", + up->port, up->gain, sp->ident, sp->select, + sp->count, sp->synmax, sp->synsnr, sp->jitter, + rp->ident, rp->select, rp->count, rp->synmax, + rp->synsnr, rp->jitter); + if (pp->sloppyclockflag & CLK_FLAG4) + record_clock_stats(&peer->srcadr, tbuf); +#ifdef DEBUG + if (debug) + printf("%s\n", tbuf); +#endif /* DEBUG */ + up->status &= ~SFLAG; + wwv_newchan(peer); + break; + + /* + * Save the bit probability in the BCD data vector at the index + * given by the argument. Note that all bits of the vector have + * to be above the data gate threshold for the digit to be + * considered valid. Bits not used in the digit are forced to + * zero and not checked for errors. + */ + case COEF1: /* 10-13 */ + if (up->status & DGATE) + up->status |= BGATE; + bcddld[arg] = bit; + break; + + case COEF2: /* 18, 27-28, 42-43 */ + bcddld[arg] = 0; + break; + + case COEF: /* 4-7, 15-17, 20-23, 25-26, + 30-33, 35-38, 40-41, 51-54 */ + if (up->status & DGATE || !(up->status & DSYNC)) + up->status |= BGATE; + bcddld[arg] = bit; + break; + + /* + * Correlate coefficient vector with each valid digit vector and + * save in decoding matrix. We step through the decoding matrix + * digits correlating each with the coefficients and saving the + * greatest and the next lower for later SNR calculation. + */ + case DECIM2: /* 29 */ + wwv_corr4(peer, &up->decvec[arg], bcddld, bcd2); + break; + + case DECIM3: /* 44 */ + wwv_corr4(peer, &up->decvec[arg], bcddld, bcd3); + break; + + case DECIM6: /* 19 */ + wwv_corr4(peer, &up->decvec[arg], bcddld, bcd6); + break; + + case DECIM9: /* 8, 14, 24, 34, 39 */ + wwv_corr4(peer, &up->decvec[arg], bcddld, bcd9); + break; + + /* + * Miscellaneous bits. If above the positive threshold, declare + * 1; if below the negative threshold, declare 0; otherwise + * raise the SYMERR alarm. At the end of second 58, QSY to the + * probe channel. + */ + case MSC20: /* 55 */ + wwv_corr4(peer, &up->decvec[YR + 1], bcddld, bcd9); + /* fall through */ + + case MSCBIT: /* 2, 3, 50, 56-57 */ + if (bitvec[up->rsec] > BTHR) + up->misc |= arg; + else if (bitvec[up->rsec] < -BTHR) + up->misc &= ~arg; + else + up->alarm |= 1 << SYMERR; + break; + + case MSC21: /* 58 */ + if (bitvec[up->rsec] > BTHR) + up->misc |= arg; + else if (bitvec[up->rsec] < -BTHR) + up->misc &= ~arg; + else + up->alarm |= 1 << SYMERR; + up->schan = (up->schan + 1) % NCHAN; + wwv_qsy(peer, up->schan); + up->status |= SFLAG; + break; + + /* + * The endgames + * + * Second 59 contains the first data pulse of the probe + * sequence. Check it for validity and establish the noise floor + * for the minute sync SNR. + */ + case MIN1: /* 59 */ + cp = &up->mitig[up->achan]; + if (up->sigamp < DTHR || up->datsnr < DSNR) + cp->errcnt++; + sp = &cp->wwv; + sp->synmin = sp->synamp; + sp = &cp->wwvh; + sp->synmin = sp->synamp; + + /* + * If SECWARN is set on the last minute of 30 June or 31 + * December, LEPSEC bit is set. At the end of the minute + * in which LEPSEC is set the transmitter and receiver + * insert an extra second (60) in the timescale and the + * minute sync skips a second. We only get to test this + * wrinkle at intervals of about 18 months, the actual + * mileage may vary. + */ + if (up->tsec == 60) { + up->status &= ~LEPSEC; + break; + } + /* fall through */ + + /* + * If all nine clock digits are valid and the SYNERR alarm is + * not raised in the current or previous second, the clock is + * set or validated. If at least one digit is set, which by + * design must be the minute units digit, the clock state + * machine begins to count the minutes. + */ + case MIN2: /* 59/60 */ + up->minset = ((current_time - peer->update) + 30) / 60; + if (up->digcnt > 0) + up->status |= DSYNC; + if (up->digcnt >= 9 && (up->alarm & (3 << SYNERR)) == 0) + { + up->status |= INSYNC; + up->watch = 0; + } + pp->lencode = timecode(up, pp->a_lastcode); + if (up->misc & SECWAR) + pp->leap = LEAP_ADDSECOND; + else + pp->leap = LEAP_NOWARNING; + refclock_receive(peer); + record_clock_stats(&peer->srcadr, pp->a_lastcode); +#ifdef DEBUG + if (debug) + printf("wwv: timecode %d %s\n", pp->lencode, + pp->a_lastcode); +#endif /* DEBUG */ + + /* + * The ultimate watchdog is the interval since the + * reference clock interface code last received an + * update from this driver. If the interval is greater + * than a couple of days, manual intervention is + * probably required, so the program resets and tries to + * resynchronized from scratch. + */ + if (up->minset > PANIC) + up->status = 0; + up->alarm = (up->alarm & ~0x8888) << 1; + up->nepoch = (up->mphase + SYNSIZ) % MINUTE; + up->errcnt = up->digcnt = nsec = 0; + break; + } + if (!(up->status & DSYNC)) { + sprintf(tbuf, + "wwv3 %2d %04x %5.0f %5.0f %5.0f %5.1f %5.0f %5.0f", + up->rsec, up->status, up->epomax, up->sigamp, + up->datpha, up->datsnr, bit, bitvec[up->rsec]); + if (pp->sloppyclockflag & CLK_FLAG4) + record_clock_stats(&peer->srcadr, tbuf); +#ifdef DEBUG + if (debug) + printf("%s\n", tbuf); +#endif /* DEBUG */ + } + up->rsec = up->tsec = nsec; + return; +} + + +/* + * wwv_data - calculate bit probability + * + * This routine is called at the end of the receiver second to calculate + * the probabilities that the previous second contained a zero (P0), one + * (P1) or position indicator (P2) pulse. If not in sync or if the data + * bit is bad, a bit error is declared and the probabilities are forced + * to zero. Otherwise, the data gate is enabled and the probabilities + * are calculated. Note that the data matched filter contributes half + * the pulse width, or 85 ms.. + */ +static double +wwv_data( + struct wwvunit *up, /* driver unit pointer */ + double pulse /* pulse length (sample units) */ + ) +{ + double p0, p1, p2; /* probabilities */ + double dpulse; /* pulse length in ms */ + + p0 = p1 = p2 = 0; + dpulse = pulse - DATSIZ / 2; + + /* + * If the data amplitude or SNR are below threshold or if the + * pulse length is less than 170 ms, declare an erasure. + */ + if (up->sigamp < DTHR || up->datsnr < DSNR || dpulse < DATSIZ) { + up->status |= DGATE; + up->errcnt++; + if (up->errcnt > MAXERR) + up->alarm |= 1 << MODERR; + return (0); + } + + /* + * The probability of P0 is one below 200 ms falling to zero at + * 500 ms. The probability of P1 is zero below 200 ms rising to + * one at 500 ms and falling to zero at 800 ms. The probability + * of P2 is zero below 500 ms, rising to one above 800 ms. + */ + up->status &= ~DGATE; + if (dpulse < (200 * MS)) { + p0 = 1; + } else if (dpulse < 500 * MS) { + dpulse -= 200 * MS; + p1 = dpulse / (300 * MS); + p0 = 1 - p1; + } else if (dpulse < 800 * MS) { + dpulse -= 500 * MS; + p2 = dpulse / (300 * MS); + p1 = 1 - p2; + } else { + p2 = 1; + } + + /* + * The ouput is a metric that ranges from -1 (P0), to +1 (P1) + * scaled for convenience. An output of zero represents an + * erasure, either because of a data error or pulse length + * greater than 500 ms. At the moment, we don't use P2. + */ + return ((p1 - p0) * MAXSIG); +} + + +/* + * wwv_corr4 - determine maximum likelihood digit + * + * This routine correlates the received digit vector with the BCD + * coefficient vectors corresponding to all valid digits at the given + * position in the decoding matrix. The maximum value corresponds to the + * maximum likelihood digit, while the ratio of this value to the next + * lower value determines the likelihood function. Note that, if the + * digit is invalid, the likelihood vector is averaged toward a miss. + */ +static void +wwv_corr4( + struct peer *peer, /* peer unit pointer */ + struct decvec *vp, /* decoding table pointer */ + double data[], /* received data vector */ + double tab[][4] /* correlation vector array */ + ) +{ + struct refclockproc *pp; + struct wwvunit *up; + + double topmax, nxtmax; /* metrics */ + double acc; /* accumulator */ + char tbuf[80]; /* monitor buffer */ + int mldigit; /* max likelihood digit */ + int diff; /* decoding difference */ + int i, j; + + pp = peer->procptr; + up = (struct wwvunit *)pp->unitptr; + + /* + * Correlate digit vector with each BCD coefficient vector. If + * any BCD digit bit is bad, consider all bits a miss. + */ + mldigit = 0; + topmax = nxtmax = -MAXSIG; + for (i = 0; tab[i][0] != 0; i++) { + acc = 0; + for (j = 0; j < 4; j++) { + if (!(up->status & BGATE)) + acc += data[j] * tab[i][j]; + } + acc = (vp->like[i] += (acc - vp->like[i]) / TCONST); + if (acc > topmax) { + nxtmax = topmax; + topmax = acc; + mldigit = i; + } else if (acc > nxtmax) { + nxtmax = acc; + } + } + vp->mldigit = mldigit; + vp->digprb = topmax; + vp->digsnr = wwv_snr(topmax, nxtmax); + + /* + * The maximum likelihood digit is compared with the current + * clock digit. The difference represents the decoding phase + * error. If the digit probability and likelihood are good and + * the difference stays the same for a number of comparisons, + * the clock digit is reset to the maximum likelihood digit. + */ + diff = mldigit - vp->digit; + if (diff < 0) + diff += vp->radix; + if (diff != vp->phase) { + vp->phase = diff; + vp->count = 0; + } + if (vp->digprb < BTHR || vp->digsnr < BSNR) { + vp->count = 0; + up->alarm |= 1 << SYMERR; + } else if (vp->count < BCMP) { + if (!(up->status & INSYNC)) { + vp->phase = 0; + vp->digit = mldigit; + } + vp->count++; + } else { + vp->phase = 0; + vp->digit = mldigit; + up->digcnt++; + } + if (vp->digit != mldigit) + up->alarm |= 1 << DECERR; + if (!(up->status & INSYNC)) { + sprintf(tbuf, + "wwv4 %2d %04x %5.0f %2d %d %d %d %d %5.0f %5.1f", + up->rsec, up->status, up->epomax, vp->radix, + vp->digit, vp->mldigit, vp->phase, vp->count, + vp->digprb, vp->digsnr); + if (pp->sloppyclockflag & CLK_FLAG4) + record_clock_stats(&peer->srcadr, tbuf); +#ifdef DEBUG + if (debug) + printf("%s\n", tbuf); +#endif /* DEBUG */ + } + up->status &= ~BGATE; +} + + +/* + * wwv_tsec - transmitter second processing + * + * This routine is called at the end of the transmitter second. It + * implements a state machine that advances the logical clock subject to + * the funny rules that govern the conventional clock and calendar. Note + * that carries from the least significant (minutes) digit are inhibited + * until that digit is synchronized. + */ +static void +wwv_tsec( + struct wwvunit *up /* driver structure pointer */ + ) +{ + int minute, day, isleap; + int temp; + + up->tsec++; + if (up->tsec < 60 || up->status & LEPSEC) + return; + up->tsec = 0; + + /* + * Advance minute unit of the day. If the minute unit is not + * synchronized, go no further. + */ + temp = carry(&up->decvec[MN]); /* minute units */ + if (!(up->status & DSYNC)) + return; + + /* + * Propagate carries through the day. + */ + if (temp == 0) /* carry minutes */ + temp = carry(&up->decvec[MN + 1]); + if (temp == 0) /* carry hours */ + temp = carry(&up->decvec[HR]); + if (temp == 0) + temp = carry(&up->decvec[HR + 1]); + + /* + * Decode the current minute and day. Set the leap second enable + * bit on the last minute of 30 June and 31 December. + */ + minute = up->decvec[MN].digit + up->decvec[MN + 1].digit * + 10 + up->decvec[HR].digit * 60 + up->decvec[HR + + 1].digit * 600; + day = up->decvec[DA].digit + up->decvec[DA + 1].digit * 10 + + up->decvec[DA + 2].digit * 100; + isleap = (up->decvec[YR].digit & 0x3) == 0; + if (minute == 1439 && (day == (isleap ? 182 : 183) || day == + (isleap ? 365 : 366)) && up->misc & SECWAR) + up->status |= LEPSEC; + + /* + * Roll the day if this the first minute and propagate carries + * through the year. + */ + if (minute != 1440) + return; + minute = 0; + while (carry(&up->decvec[HR]) != 0); /* advance to minute 0 */ + while (carry(&up->decvec[HR + 1]) != 0); + day++; + temp = carry(&up->decvec[DA]); /* carry days */ + if (temp == 0) + temp = carry(&up->decvec[DA + 1]); + if (temp == 0) + temp = carry(&up->decvec[DA + 2]); + + /* + * Roll the year if this the first day and propagate carries + * through the century. + */ + if (day != (isleap ? 365 : 366)) + return; + day = 1; + while (carry(&up->decvec[DA]) != 1); /* advance to day 1 */ + while (carry(&up->decvec[DA + 1]) != 0); + while (carry(&up->decvec[DA + 2]) != 0); + temp = carry(&up->decvec[YR]); /* carry years */ + if (temp) + carry(&up->decvec[YR + 1]); +} + + +/* + * carry - process digit + * + * This routine rotates a likelihood vector one position and increments + * the clock digit modulo the radix. It returns the new clock digit - + * zero if a carry occured. Once synchronized, the clock digit will + * match the maximum likelihood digit corresponding to that position. + */ +static int +carry( + struct decvec *dp /* decoding table pointer */ + ) +{ + int temp; + int j; + + dp->digit++; /* advance clock digit */ + if (dp->digit == dp->radix) { /* modulo radix */ + dp->digit = 0; + } + temp = dp->like[dp->radix - 1]; /* rotate likelihood vector */ + for (j = dp->radix - 1; j > 0; j--) + dp->like[j] = dp->like[j - 1]; + dp->like[0] = temp; + return (dp->digit); +} + + +/* + * wwv_snr - compute SNR or likelihood function + */ +static double +wwv_snr( + double signal, /* signal */ + double noise /* noise */ + ) +{ + double rval; + + /* + * This is a little tricky. Due to the way things are measured, + * either or both the signal or noise amplitude can be negative + * or zero. The intent is that, if the signal is negative or + * zero, the SNR must always be zero. This can happen with the + * subcarrier SNR before the phase has been aligned. On the + * other hand, in the likelihood function the "noise" is the + * next maximum down from the peak and this could be negative. + * However, in this case the SNR is truly stupendous, so we + * simply cap at MAXSNR dB. + */ + if (signal <= 0) { + rval = 0; + } else if (noise <= 0) { + rval = MAXSNR; + } else { + rval = 20 * log10(signal / noise); + if (rval > MAXSNR) + rval = MAXSNR; + } + return (rval); +} + +/* + * wwv_newchan - change to new data channel + * + * Assuming the radio can be tuned by this program, it actually appears + * as a 10-channel receiver, one channel for each of WWV and WWVH on + * each of five frequencies. While the radio is tuned to the working + * data channel (frequency and station) for most of the minute, during + * seconds 59, 0 and 1 the radio is tuned to a probe channel, in order + * to pick up minute sync and data pulses. The search for WWV and WWVH + * stations operates simultaneously, with WWV on 1000 Hz and WWVH on + * 1200 Hz. The probe channel rotates for each minute over the five + * frequencies. At the end of each rotation, this routine mitigates over + * all channels and chooses the best frequency and station. + */ +static void +wwv_newchan( + struct peer *peer /* peer structure pointer */ + ) +{ + struct refclockproc *pp; + struct wwvunit *up; + struct chan *cp; + struct sync *sp, *rp; + int rank; + int i, j; + + pp = peer->procptr; + up = (struct wwvunit *)pp->unitptr; + + /* + * Reset the matched filter selector and station pointer to + * avoid fooling around should we lose this game. + */ + up->sptr = 0; + up->status &= ~(SELV | SELH); + + /* + * Search all five station pairs looking for the station with + * the maximum compare counter. Ties go to the highest frequency + * and then to WWV. + */ + j = 0; + sp = (struct sync *)0; + rank = 0; + for (i = 0; i < NCHAN; i++) { + cp = &up->mitig[i]; + rp = &cp->wwvh; + if (rp->count >= rank) { + sp = rp; + rank = rp->count; + j = i; + } + rp = &cp->wwv; + if (rp->count >= rank) { + sp = rp; + rank = rp->count; + j = i; + } + } + + /* + * If we find a station, continue to track it. If not, X marks + * the spot and we wait for better ions. + */ + if (rank > 0) { + up->dchan = j; + up->sptr = sp; + up->status |= sp->select & (SELV | SELH); + memcpy((char *)&pp->refid, sp->refid, 4); + memcpy((char *)&peer->refid, sp->refid, 4); + wwv_qsy(peer, up->dchan); + } +} + + +/* + * wwv_qsy - Tune ICOM receiver + * + * This routine saves the AGC for the current channel, switches to a new + * channel and restores the AGC for that channel. If a tunable receiver + * is not available, just fake it. + */ +static int +wwv_qsy( + struct peer *peer, /* peer structure pointer */ + int chan /* channel */ + ) +{ + struct refclockproc *pp; + struct wwvunit *up; + int rval = 0; + + pp = peer->procptr; + up = (struct wwvunit *)pp->unitptr; + up->mitig[up->achan].gain = up->gain; +#ifdef ICOM + if (up->fd_icom > 0) + rval = icom_freq(up->fd_icom, peer->ttl & 0x7f, + qsy[chan]); +#endif /* ICOM */ + up->achan = chan; + up->gain = up->mitig[up->achan].gain; + return (rval); +} + + +/* + * timecode - assemble timecode string and length + * + * Prettytime format - similar to Spectracom + * + * sq yy ddd hh:mm:ss.fff ld dut lset agc stn comp errs freq avgt + * + * s sync indicator ('?' or ' ') + * q quality character (hex 0-F) + * yyyy year of century + * ddd day of year + * hh hour of day + * mm minute of hour + * ss minute of hour + * fff millisecond of second + * l leap second warning ' ' or 'L' + * d DST state 'S', 'D', 'I', or 'O' + * dut DUT sign and magnitude in deciseconds + * lset minutes since last clock update + * agc audio gain (0-255) + * iden station identifier (station and frequency) + * comp minute sync compare counter + * errs bit errors in last minute * freq frequency offset (PPM) * avgt averaging time (s) */ +static int +timecode( + struct wwvunit *up, /* driver structure pointer */ + char *ptr /* target string */ + ) +{ + struct sync *sp; + int year, day, hour, minute, second, frac, dut; + char synchar, qual, leapchar, dst; + char cptr[50]; + + + /* + * Common fixed-format fields + */ + synchar = (up->status & INSYNC) ? ' ' : '?'; + qual = 0; + if (up->alarm & (3 << DECERR)) + qual |= 0x1; + if (up->alarm & (3 << SYMERR)) + qual |= 0x2; + if (up->alarm & (3 << MODERR)) + qual |= 0x4; + if (up->alarm & (3 << SYNERR)) + qual |= 0x8; + year = up->decvec[7].digit + up->decvec[7].digit * 10; + if (year < UTCYEAR) + year += 2000; + else + year += 1900; + day = up->decvec[4].digit + up->decvec[5].digit * 10 + + up->decvec[6].digit * 100; + hour = up->decvec[2].digit + up->decvec[3].digit * 10; + minute = up->decvec[0].digit + up->decvec[1].digit * 10; + second = up->tsec; + frac = (up->tphase * 1000) / SECOND; + leapchar = (up->misc & SECWAR) ? 'L' : ' '; + dst = dstcod[(up->misc >> 4) & 0x3]; + dut = up->misc & 0x7; + if (!(up->misc & DUTS)) + dut = -dut; + sprintf(ptr, "%c%1X", synchar, qual); + sprintf(cptr, " %4d %03d %02d:%02d:%02d.%.03d %c%c %+d", + year, day, hour, minute, second, frac, leapchar, dst, dut); + strcat(ptr, cptr); + + /* + * Specific variable-format fields + */ + sp = up->sptr; + if (sp != 0) + sprintf(cptr, " %d %d %s %d %d %.1f %d", up->minset, + up->mitig[up->dchan].gain, sp->ident, sp->count, + up->errcnt, up->freq / SECOND * 1e6, MINAVG << + up->avgint); + else + sprintf(cptr, " %d %d X 0 %d %.1f %d", up->minset, + up->mitig[up->dchan].gain, up->errcnt, up->freq / + SECOND * 1e6, MINAVG << up->avgint); + strcat(ptr, cptr); + return (strlen(ptr)); +} + + +/* + * wwv_gain - adjust codec gain + * + * This routine is called once each second. If the signal envelope + * amplitude is too low, the codec gain is bumped up by four units; if + * too high, it is bumped down. The decoder is relatively insensitive to + * amplitude, so this crudity works just fine. The input port is set and + * the error flag is cleared, mostly to be ornery. + */ +static void +wwv_gain( + struct peer *peer /* peer structure pointer */ + ) +{ + struct refclockproc *pp; + struct wwvunit *up; + + pp = peer->procptr; + up = (struct wwvunit *)pp->unitptr; + + /* + * Apparently, the codec uses only the high order bits of the + * gain control field. Thus, it may take awhile for changes to + * wiggle the hardware bits. + */ + if (up->clipcnt == 0) { + up->gain += 4; + if (up->gain > 255) + up->gain = 255; + } else if (up->clipcnt > SECOND / 100) { + up->gain -= 4; + if (up->gain < 0) + up->gain = 0; + } + audio_gain(up->gain, up->port); + up->clipcnt = 0; +} + + +#else +int refclock_wwv_bs; +#endif /* REFCLOCK */ diff --git a/contrib/ntp/ntpd/refclock_wwvb.c b/contrib/ntp/ntpd/refclock_wwvb.c index 9d3b3d6..63d6e0b 100644 --- a/contrib/ntp/ntpd/refclock_wwvb.c +++ b/contrib/ntp/ntpd/refclock_wwvb.c @@ -6,7 +6,7 @@ #include <config.h> #endif -#if defined(REFCLOCK) && defined(CLOCK_WWVB) +#if defined(REFCLOCK) && defined(CLOCK_SPECTRACOM) #include <stdio.h> #include <ctype.h> |