summaryrefslogtreecommitdiffstats
path: root/contrib/ntp/ntpd
diff options
context:
space:
mode:
authorroberto <roberto@FreeBSD.org>2000-01-28 14:55:50 +0000
committerroberto <roberto@FreeBSD.org>2000-01-28 14:55:50 +0000
commitb5b40f9e420899251189775800d9f74092925299 (patch)
tree98efdf1b74d6ecb7828bb502a0350116eeb2fd3c /contrib/ntp/ntpd
parentef64b99e8412f2273dd2e8b3291c2f78ffc4667f (diff)
downloadFreeBSD-src-b5b40f9e420899251189775800d9f74092925299.zip
FreeBSD-src-b5b40f9e420899251189775800d9f74092925299.tar.gz
Virgin import of ntpd 4.0.99b
Diffstat (limited to 'contrib/ntp/ntpd')
-rw-r--r--contrib/ntp/ntpd/Makefile.am29
-rw-r--r--contrib/ntp/ntpd/Makefile.in629
-rw-r--r--contrib/ntp/ntpd/map_vme.c2
-rw-r--r--contrib/ntp/ntpd/ntp_control.c3
-rw-r--r--contrib/ntp/ntpd/ntp_intres.c2
-rw-r--r--contrib/ntp/ntpd/ntp_io.c46
-rw-r--r--contrib/ntp/ntpd/ntp_loopfilter.c31
-rw-r--r--contrib/ntp/ntpd/ntp_proto.c500
-rw-r--r--contrib/ntp/ntpd/ntp_refclock.c27
-rw-r--r--contrib/ntp/ntpd/ntpd.c71
-rw-r--r--contrib/ntp/ntpd/refclock_atom.c8
-rw-r--r--contrib/ntp/ntpd/refclock_chu.c720
-rw-r--r--contrib/ntp/ntpd/refclock_conf.c29
-rw-r--r--contrib/ntp/ntpd/refclock_fg.c350
-rw-r--r--contrib/ntp/ntpd/refclock_gpsvme.c51
-rw-r--r--contrib/ntp/ntpd/refclock_irig.c164
-rw-r--r--contrib/ntp/ntpd/refclock_jupiter.c11
-rw-r--r--contrib/ntp/ntpd/refclock_msfees.c36
-rw-r--r--contrib/ntp/ntpd/refclock_mx4200.c76
-rw-r--r--contrib/ntp/ntpd/refclock_nmea.c7
-rw-r--r--contrib/ntp/ntpd/refclock_oncore.c561
-rw-r--r--contrib/ntp/ntpd/refclock_palisade.c1
-rw-r--r--contrib/ntp/ntpd/refclock_parse.c284
-rw-r--r--contrib/ntp/ntpd/refclock_pcf.c215
-rw-r--r--contrib/ntp/ntpd/refclock_shm.c8
-rw-r--r--contrib/ntp/ntpd/refclock_wwv.c2754
-rw-r--r--contrib/ntp/ntpd/refclock_wwvb.c2
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, &ltemp);
+ DTOLFP(up->bufcnt * 1. / SECOND, &ltemp);
L_SUB(&up->timestamp, &ltemp);
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, &ltemp);
+ DTOLFP((double)up->bufcnt / SECOND, &ltemp);
L_SUB(&up->timestamp, &ltemp);
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,
&ltemp);
pp->lastrec = up->timestamp;
L_SUB(&pp->lastrec, &ltemp);
@@ -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, &ltemp);
+ L_SUB(&up->timestamp, &ltemp);
+ 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>
OpenPOWER on IntegriCloud