]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
configure.ac:
authorHal Murray <murray@ntp.org>
Sun, 13 Dec 2009 08:23:02 +0000 (03:23 -0500)
committerHal Murray <murray@ntp.org>
Sun, 13 Dec 2009 08:23:02 +0000 (03:23 -0500)
  comment for Bug 254
ChangeLog:
  Adding tg2.c
tg2.c:
  BitKeeper file /m/pogo/users/murray/tg2/util/tg2.c
Makefile.am:
  Adding tg2

bk: 4b24a466CEAm-GwtEHlbkH0PjnXu1w

ChangeLog
configure.ac
util/Makefile.am
util/tg2.c [new file with mode: 0644]

index 6610385f01b1193bd5ca1d34984b512c4040288d..8c6ab17997ad9d0387a9dbf76fafafee0496b552 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,4 @@
+* add util/tg2, a clone of tg that works on Linux, NetBSD, and FreeBSD
 (4.2.7) 2009/12/09 Released by Harlan Stenn <stenn@ntp.org>
 * [Bug 1407] configure.ac: recent GNU Make -v does not include "version".
 
index 476e7bf0fa562ddb9b3c7638e8109068e6babfd6..7615f4de100a1f2addbc292eb7b5232150f11362 100644 (file)
@@ -584,7 +584,7 @@ esac
 AC_CHECK_HEADERS(sys/select.h sys/signal.h sys/sockio.h)
 # HMS: Checked sys/socket.h earlier
 case "$host" in
- *-*-netbsd*) ;;
+ *-*-netbsd*) ;;       # Bug 254
  *) AC_CHECK_HEADERS(machine/soundcard.h sys/soundcard.h)
     ;;
 esac
index f546abea7ff8d35e2397b3e98b522654d663eed9..fd132053341d90aa329e6947848c097447ba7d48 100644 (file)
@@ -5,7 +5,7 @@ AUTOMAKE_OPTIONS=
 bin_PROGRAMS=  @MAKE_NTPTIME@ @MAKE_TICKADJ@ @MAKE_TIMETRIM@ \
                ntp-keygen
 EXTRA_PROGRAMS=        audio-pcm byteorder hist jitter kern longsize \
-       ntptime pps-api precision sht testrs6000 tg tickadj timetrim
+       ntptime pps-api precision sht testrs6000 tg tg2 tickadj timetrim
 
 AM_CPPFLAGS= -I$(top_srcdir)/include -I$(top_srcdir)/lib/isc/include \
        -I$(top_srcdir)/lib/isc/nothreads/include \
@@ -13,6 +13,7 @@ AM_CPPFLAGS= -I$(top_srcdir)/include -I$(top_srcdir)/lib/isc/include \
 
 # LDADD might need RESLIB and ADJLIB
 LDADD=         ../libntp/libntp.a
+tg2_LDADD=     -lm
 ntp_keygen_SOURCES = ntp-keygen.c ntp-keygen-opts.c ntp-keygen-opts.h
 ntp_keygen_LDADD=      @LCRYPTO@ $(LIBOPTS_LDADD) ../libntp/libntp.a
 
diff --git a/util/tg2.c b/util/tg2.c
new file mode 100644 (file)
index 0000000..9735a63
--- /dev/null
@@ -0,0 +1,2499 @@
+/*
+ * tg.c generate WWV or IRIG signals for test
+ */
+/*
+ * This program can generate audio signals that simulate the WWV/H
+ * broadcast timecode. Alternatively, it can generate the IRIG-B
+ * timecode commonly used to synchronize laboratory equipment. It is
+ * intended to test the WWV/H driver (refclock_wwv.c) and the IRIG
+ * driver (refclock_irig.c) in the NTP driver collection.
+ *
+ * Besides testing the drivers themselves, this program can be used to
+ * synchronize remote machines over audio transmission lines or program
+ * feeds. The program reads the time on the local machine and sets the
+ * initial epoch of the signal generator within one millisecond.
+ * Alernatively, the initial epoch can be set to an arbitrary time. This
+ * is useful when searching for bugs and testing for correct response to
+ * a leap second in UTC. Note however, the ultimate accuracy is limited
+ * by the intrinsic frequency error of the codec sample clock, which can
+ # reach well over 100 PPM.
+ *
+ * The default is to route generated signals to the line output
+ * jack; the s option on the command line routes these signals to the
+ * internal speaker as well. The v option controls the speaker volume
+ * over the range 0-255. The signal generator by default uses WWV
+ * format; the h option switches to WWVH format and the i option
+ * switches to IRIG-B format.
+ *
+ * Once started the program runs continuously. The default initial epoch
+ * for the signal generator is read from the computer system clock when
+ * the program starts. The y option specifies an alternate epoch using a
+ * string yydddhhmmss, where yy is the year of century, ddd the day of
+ * year, hh the hour of day and mm the minute of hour. For instance,
+ * 1946Z on 1 January 2006 is 060011946. The l option lights the leap
+ * warning bit in the WWV/H timecode, so is handy to check for correct
+ * behavior at the next leap second epoch. The remaining options are
+ * specified below under the Parse Options heading. Most of these are
+ * for testing.
+ *
+ * During operation the program displays the WWV/H timecode (9 digits)
+ * or IRIG timecode (20 digits) as each new string is constructed. The
+ * display is followed by the BCD binary bits as transmitted. Note that
+ * the transmissionorder is low-order first as the frame is processed
+ * left to right. For WWV/H The leap warning L preceeds the first bit.
+ * For IRIG the on-time marker M preceeds the first (units) bit, so its
+ * code is delayed one bit and the next digit (tens) needs only three
+ * bits.
+ *
+ * The program has been tested with the Sun Blade 1500 running Solaris
+ * 10, but not yet with other machines. It uses no special features and
+ * should be readily portable to other hardware and operating systems.
+ *
+ * $Log: tg.c,v $
+ * Revision 1.28  2007/02/12 23:57:45  dmw
+ * v0.23 2007-02-12 dmw:
+ * - Changed statistics to include calculated error
+ *   of frequency, based on number of added or removed
+ *   cycles over time.
+ *
+ * Revision 1.27  2007/02/09 02:28:59  dmw
+ * v0.22 2007-02-08 dmw:
+ * - Changed default for rate correction to "enabled", "-j" switch now disables.
+ * - Adjusted help message accordingly.
+ * - Added "2007" to modifications note at end of help message.
+ *
+ * Revision 1.26  2007/02/08 03:36:17  dmw
+ * v0.21 2007-02-07 dmw:
+ * - adjusted strings for shorten and lengthen to make
+ *   fit on smaller screen.
+ *
+ * Revision 1.25  2007/02/01 06:08:09  dmw
+ * v0.20 2007-02-01 dmw:
+ * - Added periodic display of running time along with legend on IRIG-B, allows tracking how
+ *   close IRIG output is to actual clock time.
+ *
+ * Revision 1.24  2007/01/31 19:24:11  dmw
+ * v0.19 2007-01-31 dmw:
+ * - Added tracking of how many seconds have been adjusted,
+ *   how many cycles added (actually in milliseconds), how
+ *   many cycles removed, print periodically if verbose is
+ *   active.
+ * - Corrected lack of lengthen or shorten of minute & hour
+ *   pulses for WWV format.
+ *
+ * Revision 1.23  2007/01/13 07:09:12  dmw
+ * v0.18 2007-01-13 dmw:
+ * - added -k option, which allows force of long or short
+ *   cycles, to test against IRIG-B decoder.
+ *
+ * Revision 1.22  2007/01/08 16:27:23  dmw
+ * v0.17 2007-01-08 dmw:
+ * - Changed -j option to **enable** rate correction, not disable.
+ *
+ * Revision 1.21  2007/01/08 06:22:36  dmw
+ * v0.17 2007-01-08 dmw:
+ * - Run stability check versus ongoing system clock (assume NTP correction)
+ *   and adjust time code rate to try to correct, if gets too far out of sync.
+ *   Disable this algorithm with -j option.
+ *
+ * Revision 1.20  2006/12/19 04:59:04  dmw
+ * v0.16 2006-12-18 dmw
+ * - Corrected print of setting of output frequency, always
+ *   showed 8000 samples/sec, now as specified on command line.
+ * - Modified to reflect new employer Norscan.
+ *
+ * Revision 1.19  2006/12/19 03:45:38  dmw
+ * v0.15 2006-12-18 dmw:
+ * - Added count of number of seconds to output then exit,
+ *   default zero for forever.
+ *
+ * Revision 1.18  2006/12/18 05:43:36  dmw
+ * v0.14 2006-12-17 dmw:
+ * - Corrected WWV(H) signal to leave "tick" sound off of 29th and 59th second of minute.
+ * - Adjusted verbose output format for WWV(H).
+ *
+ * Revision 1.17  2006/12/18 02:31:33  dmw
+ * v0.13 2006-12-17 dmw:
+ * - Put SPARC code back in, hopefully will work, but I don't have
+ *   a SPARC to try it on...
+ * - Reworked Verbose mode, different flag to initiate (x not v)
+ *   and actually implement turn off of verbosity when this flag used.
+ * - Re-claimed v flag for output level.
+ * - Note that you must define OSS_MODS to get OSS to compile,
+ *   otherwise will expect to compile using old SPARC options, as
+ *   it used to be.
+ *
+ * Revision 1.16  2006/10/26 19:08:43  dmw
+ * v0.12 2006-10-26 dmw:
+ * - Reversed output binary dump for IRIG, makes it easier to read the numbers.
+ *
+ * Revision 1.15  2006/10/24 15:57:09  dmw
+ * v0.11 2006-10-24 dmw:
+ * - another tweak.
+ *
+ * Revision 1.14  2006/10/24 15:55:53  dmw
+ * v0.11 2006-10-24 dmw:
+ * - Curses a fix to the fix to the fix of the usaeg.
+ *
+ * Revision 1.13  2006/10/24 15:53:25  dmw
+ * v0.11 (still) 2006-10-24 dmw:
+ * - Messed with usage message that's all.
+ *
+ * Revision 1.12  2006/10/24 15:50:05  dmw
+ * v0.11 2006-10-24 dmw:
+ * - oops, needed to note "hours" in usage of that offset.
+ *
+ * Revision 1.11  2006/10/24 15:49:09  dmw
+ * v0.11 2006-10-24 dmw:
+ * - Added ability to offset actual time sent, from the UTC time
+ *   as per the computer.
+ *
+ * Revision 1.10  2006/10/24 03:25:55  dmw
+ * v0.10 2006-10-23 dmw:
+ * - Corrected polarity of correction of offset when going into or out of DST.
+ * - Ensure that zero offset is always positive (pet peeve).
+ *
+ * Revision 1.9  2006/10/24 00:00:35  dmw
+ * v0.9 2006-10-23 dmw:
+ * - Shift time offset when DST in or out.
+ *
+ * Revision 1.8  2006/10/23 23:49:28  dmw
+ * v0.8 2006-10-23 dmw:
+ * - made offset of zero default positive.
+ *
+ * Revision 1.7  2006/10/23 23:44:13  dmw
+ * v0.7 2006-10-23 dmw:
+ * - Added unmodulated and inverted unmodulated output.
+ *
+ * Revision 1.6  2006/10/23 18:10:37  dmw
+ * v0.6 2006-10-23 dmw:
+ * - Cleaned up usage message.
+ * - Require at least one option, or prints usage message and exits.
+ *
+ * Revision 1.5  2006/10/23 16:58:10  dmw
+ * v0.5 2006-10-23 dmw:
+ * - Finally added a usage message.
+ * - Added leap second pending and DST change pending into IEEE 1344.
+ * - Default code type is now IRIG-B with IEEE 1344.
+ *
+ * Revision 1.4  2006/10/23 03:27:25  dmw
+ * v0.4 2006-10-22 dmw:
+ * - Added leap second addition and deletion.
+ * - Added DST changing forward and backward.
+ * - Changed date specification to more conventional year, month, and day of month
+ *   (rather than day of year).
+ *
+ * Revision 1.3  2006/10/22 21:04:12  dmw
+ * v0.2 2006-10-22 dmw:
+ * - Corrected format of legend line.
+ *
+ * Revision 1.2  2006/10/22 21:01:07  dmw
+ * v0.1 2006-10-22 dmw:
+ * - Added some more verbose output (as is my style)
+ * - Corrected frame format - there were markers in the
+ *   middle of frames, now correctly as "zero" bits.
+ * - Added header line to show fields of output.
+ * - Added straight binary seconds, were not implemented
+ *   before.
+ * - Added IEEE 1344 with parity.
+ *
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#ifdef  HAVE_CONFIG_H
+#include "config.h"
+#undef VERSION         /* avoid conflict below */
+#endif
+
+#ifdef  HAVE_SYS_SOUNDCARD_H
+#include <sys/soundcard.h>
+#else
+# ifdef HAVE_SYS_AUDIOIO_H
+# include <sys/audioio.h>
+# else
+# include <sys/audio.h>
+# endif
+#endif
+
+#include <math.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+
+#define VERSION                (0)
+#define        ISSUE           (23)
+#define        ISSUE_DATE      "2007-02-12"
+
+#define        SECOND  (8000)                  /* one second of 125-us samples */
+#define BUFLNG (400)                   /* buffer size */
+#define        DEVICE  "/dev/audio"    /* default audio device */
+#define        WWV             (0)                             /* WWV encoder */
+#define        IRIG    (1)                             /* IRIG-B encoder */
+#define        OFF             (0)                             /* zero amplitude */
+#define        LOW             (1)                             /* low amplitude */
+#define        HIGH    (2)                             /* high amplitude */
+#define        DATA0   (200)                   /* WWV/H 0 pulse */
+#define        DATA1   (500)                   /* WWV/H 1 pulse */
+#define PI             (800)                   /* WWV/H PI pulse */
+#define        M2              (2)                             /* IRIG 0 pulse */
+#define        M5              (5)                             /* IRIG 1 pulse */
+#define        M8              (8)                             /* IRIG PI pulse */
+
+#define        FALSE   (0)
+#define        TRUE    (1)
+
+#define        NUL             (0)
+
+#define        SECONDS_PER_MINUTE      (60)
+#define SECONDS_PER_HOUR       (3600)
+
+#define        OUTPUT_DATA_STRING_LENGTH       (200)
+
+/* Attempt at unmodulated - "high" */
+int u6000[] = {
+       247, 247, 247, 247, 247, 247, 247, 247, 247, 247,       /*  0- 9 */
+    247, 247, 247, 247, 247, 247, 247, 247, 247, 247,  /* 10-19 */
+    247, 247, 247, 247, 247, 247, 247, 247, 247, 247,  /* 20-29 */
+    247, 247, 247, 247, 247, 247, 247, 247, 247, 247,  /* 30-39 */
+    247, 247, 247, 247, 247, 247, 247, 247, 247, 247,  /* 40-49 */
+    247, 247, 247, 247, 247, 247, 247, 247, 247, 247,  /* 50-59 */
+    247, 247, 247, 247, 247, 247, 247, 247, 247, 247,  /* 60-69 */
+    247, 247, 247, 247, 247, 247, 247, 247, 247, 247};         /* 70-79 */
+
+/* Attempt at unmodulated - "low" */
+int u3000[] = {
+       119, 119, 119, 119, 119, 119, 119, 119, 119, 119,       /*  0- 9 */
+    119, 119, 119, 119, 119, 119, 119, 119, 119, 119,  /* 10-19 */
+    119, 119, 119, 119, 119, 119, 119, 119, 119, 119,  /* 20-29 */
+    119, 119, 119, 119, 119, 119, 119, 119, 119, 119,  /* 30-39 */
+    119, 119, 119, 119, 119, 119, 119, 119, 119, 119,  /* 40-49 */
+    119, 119, 119, 119, 119, 119, 119, 119, 119, 119,  /* 50-59 */
+    119, 119, 119, 119, 119, 119, 119, 119, 119, 119,  /* 60-69 */
+    119, 119, 119, 119, 119, 119, 119, 119, 119, 119};         /* 70-79 */
+
+/*
+ * Companded sine table amplitude 3000 units
+ */
+int c3000[] = {1, 48, 63, 70, 78, 82, 85, 89, 92, 94,  /* 0-9 */
+     96,  98,  99, 100, 101, 101, 102, 103, 103, 103,  /* 10-19 */
+    103, 103, 103, 103, 102, 101, 101, 100,  99,  98,  /* 20-29 */
+     96,  94,  92,  89,  85,  82,  78,  70,  63,  48,  /* 30-39 */
+    129, 176, 191, 198, 206, 210, 213, 217, 220, 222,  /* 40-49 */
+    224, 226, 227, 228, 229, 229, 230, 231, 231, 231,  /* 50-59 */
+    231, 231, 231, 231, 230, 229, 229, 228, 227, 226,  /* 60-69 */
+    224, 222, 220, 217, 213, 210, 206, 198, 191, 176};         /* 70-79 */
+/*
+ * Companded sine table amplitude 6000 units
+ */
+int c6000[] = {1, 63, 78, 86, 93, 98, 101, 104, 107, 110, /* 0-9 */
+    112, 113, 115, 116, 117, 117, 118, 118, 119, 119,  /* 10-19 */
+    119, 119, 119, 118, 118, 117, 117, 116, 115, 113,  /* 20-29 */
+    112, 110, 107, 104, 101,  98,  93,  86,  78,  63,  /* 30-39 */
+    129, 191, 206, 214, 221, 226, 229, 232, 235, 238,  /* 40-49 */
+    240, 241, 243, 244, 245, 245, 246, 246, 247, 247,  /* 50-59 */
+    247, 247, 247, 246, 246, 245, 245, 244, 243, 241,  /* 60-69 */
+    240, 238, 235, 232, 229, 226, 221, 214, 206, 191};         /* 70-79 */
+
+/*
+ * 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 DATA   (0)             /* send data (0, 1, PI) */
+#define COEF   (1)             /* send BCD bit */
+#define        DEC             (2)             /* decrement to next digit and send PI */
+#define        MIN             (3)             /* minute pulse */
+#define        LEAP    (4)             /* leap warning */
+#define        DUT1    (5)             /* DUT1 bits */
+#define        DST1    (6)             /* DST1 bit */
+#define        DST2    (7)             /* DST2 bit */
+#define DECZ   (8)             /* decrement to next digit and send zero */
+#define DECC   (9)             /* decrement to next digit and send bit */
+#define NODEC  (10)    /* no decerement to next digit, send PI */
+#define DECX   (11)    /* decrement to next digit, send PI, but no tick */
+#define DATAX  (12)    /* send data (0, 1, PI), but no tick */
+
+/*
+ * WWV/H format (100-Hz, 9 digits, 1 m frame)
+ */
+struct progx progx[] = {
+       {MIN,   800},           /* 0 minute sync pulse */
+       {DATA,  DATA0},         /* 1 */
+       {DST2,  0},             /* 2 DST2 */
+       {LEAP,  0},             /* 3 leap warning */
+       {COEF,  1},             /* 4 1 year units */
+       {COEF,  2},             /* 5 2 */
+       {COEF,  4},             /* 6 4 */
+       {COEF,  8},             /* 7 8 */
+       {DEC,   DATA0},         /* 8 */
+       {DATA,  PI},            /* 9 p1 */
+       {COEF,  1},             /* 10 1 minute units */
+       {COEF,  2},             /* 11 2 */
+       {COEF,  4},             /* 12 4 */
+       {COEF,  8},             /* 13 8 */
+       {DEC,   DATA0},         /* 14 */
+       {COEF,  1},             /* 15 10 minute tens */
+       {COEF,  2},             /* 16 20 */
+       {COEF,  4},             /* 17 40 */
+       {COEF,  8},             /* 18 80 (not used) */
+       {DEC,   PI},            /* 19 p2 */
+       {COEF,  1},             /* 20 1 hour units */
+       {COEF,  2},             /* 21 2 */
+       {COEF,  4},             /* 22 4 */
+       {COEF,  8},             /* 23 8 */
+       {DEC,   DATA0},         /* 24 */
+       {COEF,  1},             /* 25 10 hour tens */
+       {COEF,  2},             /* 26 20 */
+       {COEF,  4},             /* 27 40 (not used) */
+       {COEF,  8},             /* 28 80 (not used) */
+       {DECX,  PI},            /* 29 p3 */
+       {COEF,  1},             /* 30 1 day units */
+       {COEF,  2},             /* 31 2 */
+       {COEF,  4},             /* 32 4 */
+       {COEF,  8},             /* 33 8 */
+       {DEC,   DATA0},         /* 34 not used */
+       {COEF,  1},             /* 35 10 day tens */
+       {COEF,  2},             /* 36 20 */
+       {COEF,  4},             /* 37 40 */
+       {COEF,  8},             /* 38 80 */
+       {DEC,   PI},            /* 39 p4 */
+       {COEF,  1},             /* 40 100 day hundreds */
+       {COEF,  2},             /* 41 200 */
+       {COEF,  4},             /* 42 400 (not used) */
+       {COEF,  8},             /* 43 800 (not used) */
+       {DEC,   DATA0},         /* 44 */
+       {DATA,  DATA0},         /* 45 */
+       {DATA,  DATA0},         /* 46 */
+       {DATA,  DATA0},         /* 47 */
+       {DATA,  DATA0},         /* 48 */
+       {DATA,  PI},            /* 49 p5 */
+       {DUT1,  8},             /* 50 DUT1 sign */
+       {COEF,  1},             /* 51 10 year tens */
+       {COEF,  2},             /* 52 20 */
+       {COEF,  4},             /* 53 40 */
+       {COEF,  8},             /* 54 80 */
+       {DST1,  0},             /* 55 DST1 */
+       {DUT1,  1},             /* 56 0.1 DUT1 fraction */
+       {DUT1,  2},             /* 57 0.2 */
+       {DUT1,  4},             /* 58 0.4 */
+       {DATAX, PI},            /* 59 p6 */
+       {DATA,  DATA0},         /* 60 leap */
+};
+
+/*
+ * IRIG format frames (1000 Hz, 1 second for 10 frames of data)
+ */
+
+/*
+ * IRIG format frame 10 - MS straight binary seconds
+ */
+struct progx progu[] = {
+       {COEF,  2},             /* 0 0x0 0200 seconds */
+       {COEF,  4},             /* 1 0x0 0400 */
+       {COEF,  8},             /* 2 0x0 0800 */
+       {DECC,  1},             /* 3 0x0 1000 */
+       {COEF,  2},             /* 4 0x0 2000 */
+       {COEF,  4},             /* 6 0x0 4000 */
+       {COEF,  8},             /* 7 0x0 8000 */
+       {DECC,  1},             /* 8 0x1 0000 */
+       {COEF,  2},     /* 9 0x2 0000 - but only 86,401 / 0x1 5181 seconds in a day, so always zero */
+       {NODEC, M8},    /* 9 PI */
+};
+
+/*
+ * IRIG format frame 8 - MS control functions
+ */
+struct progx progv[] = {
+       {COEF,  2},             /*  0 CF # 19 */
+       {COEF,  4},             /*  1 CF # 20 */
+       {COEF,  8},             /*  2 CF # 21 */
+       {DECC,  1},             /*  3 CF # 22 */
+       {COEF,  2},             /*  4 CF # 23 */
+       {COEF,  4},             /*  6 CF # 24 */
+       {COEF,  8},             /*  7 CF # 25 */
+       {DECC,  1},             /*  8 CF # 26 */
+       {COEF,  2},             /*  9 CF # 27 */
+       {DEC,   M8},    /* 10 PI */
+};
+
+/*
+ * IRIG format frames 7 & 9 - LS control functions & LS straight binary seconds
+ */
+struct progx progw[] = {
+       {COEF,  1},             /*  0  CF # 10, 0x0 0001 seconds */
+       {COEF,  2},             /*  1  CF # 11, 0x0 0002 */
+       {COEF,  4},             /*  2  CF # 12, 0x0 0004 */
+       {COEF,  8},             /*  3  CF # 13, 0x0 0008 */
+       {DECC,  1},             /*  4  CF # 14, 0x0 0010 */
+       {COEF,  2},             /*  6  CF # 15, 0x0 0020 */
+       {COEF,  4},             /*  7  CF # 16, 0x0 0040 */
+       {COEF,  8},             /*  8  CF # 17, 0x0 0080 */
+       {DECC,  1},             /*  9  CF # 18, 0x0 0100 */
+       {NODEC, M8},    /* 10  PI */
+};
+
+/*
+ * IRIG format frames 2 to 6 - minutes, hours, days, hundreds days, 2 digit years (also called control functions bits 1-9)
+ */
+struct progx progy[] = {
+       {COEF,  1},             /* 0 1 units, CF # 1 */
+       {COEF,  2},             /* 1 2 units, CF # 2 */
+       {COEF,  4},             /* 2 4 units, CF # 3 */
+       {COEF,  8},             /* 3 8 units, CF # 4 */
+       {DECZ,  M2},    /* 4 zero bit, CF # 5 / unused, default zero in years */
+       {COEF,  1},             /* 5 10 tens, CF # 6 */
+       {COEF,  2},             /* 6 20 tens, CF # 7*/
+       {COEF,  4},             /* 7 40 tens, CF # 8*/
+       {COEF,  8},             /* 8 80 tens, CF # 9*/
+       {DEC,   M8},    /* 9 PI */
+};
+
+/*
+ * IRIG format first frame, frame 1 - seconds
+ */
+struct progx progz[] = {
+       {MIN,   M8},    /* 0 PI (on-time marker for the second at zero cross of 1st cycle) */
+       {COEF,  1},             /* 1 1 units */
+       {COEF,  2},             /* 2 2 */
+       {COEF,  4},             /* 3 4 */
+       {COEF,  8},             /* 4 8 */
+       {DECZ,  M2},    /* 5 zero bit */
+       {COEF,  1},             /* 6 10 tens */
+       {COEF,  2},             /* 7 20 */
+       {COEF,  4},             /* 8 40 */
+       {DEC,   M8},    /* 9 PI */
+};
+
+/* LeapState values. */
+#define        LEAPSTATE_NORMAL                        (0)
+#define        LEAPSTATE_DELETING                      (1)
+#define        LEAPSTATE_INSERTING                     (2)
+#define        LEAPSTATE_ZERO_AFTER_INSERT     (3)
+
+
+/*
+ * Forward declarations
+ */
+void   WWV_Second(int, int);           /* send second */
+void   WWV_SecondNoTick(int, int);     /* send second with no tick */
+void   digit(int);             /* encode digit */
+void   peep(int, int, int);    /* send cycles */
+void   poop(int, int, int, int); /* Generate unmodulated from similar tables */
+void   delay(int);             /* delay samples */
+int            ConvertMonthDayToDayOfYear (int, int, int);     /* Calc day of year from year month & day */
+void   Help (void);    /* Usage message */
+void   ReverseString(char *);
+
+/*
+ * Extern declarations, don't know why not in headers
+ */
+//float        round ( float );
+
+/*
+ * Global variables
+ */
+char   buffer[BUFLNG];         /* output buffer */
+int    bufcnt = 0;             /* buffer counter */
+int    fd;                     /* audio codec file descriptor */
+int    tone = 1000;            /* WWV sync frequency */
+int HourTone = 1500;   /* WWV hour on-time frequency */
+int    encode = IRIG;          /* encoder select */
+int    leap = 0;               /* leap indicator */
+int    DstFlag = 0;            /* winter/summer time */
+int    dut1 = 0;               /* DUT1 correction (sign, magnitude) */
+int    utc = 0;                /* option epoch */
+int IrigIncludeYear = FALSE;   /* Whether to send year in first control functions area, between P5 and P6. */
+int IrigIncludeIeee = FALSE;   /* Whether to send IEEE 1344 control functions extensions between P6 and P8. */
+int    StraightBinarySeconds = 0;
+int    ControlFunctions = 0;
+int    Debug = FALSE;
+int Verbose = TRUE;
+char   *CommandName;
+
+#ifndef  HAVE_SYS_SOUNDCARD_H
+int    level = AUDIO_MAX_GAIN / 8; /* output level */
+int    port = AUDIO_LINE_OUT;  /* output port */
+#endif
+
+int            TotalSecondsCorrected = 0;
+int            TotalCyclesAdded = 0;
+int            TotalCyclesRemoved = 0;
+
+
+/*
+ * Main program
+ */
+int
+main(
+       int             argc,           /* command line options */
+       char    **argv          /* poiniter to list of tokens */
+       )
+{
+#ifndef  HAVE_SYS_SOUNDCARD_H
+       audio_info_t info;      /* Sun audio structure */
+       int     rval;           /* For IOCTL calls */
+#endif
+
+       struct  timeval  TimeValue;                             /* System clock at startup */
+       time_t                   SecondsPartOfTime;             /* Sent to gmtime() for calculation of TimeStructure (can apply offset). */
+       time_t                   BaseRealTime;                  /* Base realtime so can determine seconds since starting. */
+       time_t                   NowRealTime;                   /* New realtime to can determine seconds as of now. */
+       unsigned                 SecondsRunningRealTime;        /* Difference between NowRealTime and BaseRealTime. */
+       unsigned                 SecondsRunningSimulationTime;  /* Time that the simulator has been running. */
+       int                              SecondsRunningDifference;      /* Difference between what real time says we have been running */
+                                                                                               /* and what simulator says we have been running - will slowly  */
+                                                                                               /* change because of clock drift. */
+       int                              ExpectedRunningDifference = 0; /* Stable value that we've obtained from check at initial start-up.     */
+       unsigned                 StabilityCount;                /* Used to check stability of difference while starting */
+#define        RUN_BEFORE_STABILITY_CHECK      (30)    // Must run this many seconds before even checking stability.
+#define        MINIMUM_STABILITY_COUNT         (10)    // Number of consecutive differences that need to be within initial stability band to say we are stable.
+#define        INITIAL_STABILITY_BAND          ( 2)    // Determining initial stability for consecutive differences within +/- this value.
+#define        RUNNING_STABILITY_BAND          ( 5)    // When running, stability is defined as difference within +/- this value.
+
+       struct  tm              *TimeStructure = NULL;  /* Structure returned by gmtime */
+       char    device[200];    /* audio device */
+       char    code[200];      /* timecode */
+       int     temp;
+       int     arg = 0;
+       int     sw = 0;
+       int     ptr = 0;
+
+       int     Year;
+       int     Month;
+       int     DayOfMonth;
+       int     Hour;
+       int     Minute;
+       int     Second = 0;
+       int     DayOfYear;
+
+       int     BitNumber;
+       int     AudioFormat;
+       int MonoStereo;     /* 0=mono, 1=stereo */
+#define        MONO    (0)
+#define        STEREO  (1)
+       int     SetSampleRate;
+       int     SampleRate;
+       int     SampleRateDifference;
+       char FormatCharacter = '3';             /* Default is IRIG-B with IEEE 1344 extensions */
+       char AsciiValue;
+       int     HexValue;
+       int     OldPtr = 0;
+       int FrameNumber = 0;
+
+       /* Time offset for IEEE 1344 indication. */
+       float TimeOffset = 0.0;
+       int     OffsetSignBit = 0;
+       int OffsetOnes = 0;
+       int OffsetHalf = 0;
+
+       int     TimeQuality = 0;        /* Time quality for IEEE 1344 indication. */
+       char ParityString[200]; /* Partial output string, to calculate parity on. */
+       int     ParitySum = 0;
+       int     ParityValue;
+       char *StringPointer;
+
+       /* Flags to indicate requested leap second addition or deletion by command line option. */
+       /* Should be mutually exclusive - generally ensured by code which interprets command line option. */
+       int     InsertLeapSecond = FALSE;
+       int     DeleteLeapSecond = FALSE;
+
+       /* Date and time of requested leap second addition or deletion. */
+       int     LeapYear                                        = 0;
+       int LeapMonth                                   = 0;
+       int     LeapDayOfMonth                          = 0;
+       int LeapHour                                    = 0;
+       int     LeapMinute                                      = 0;
+       int     LeapDayOfYear                           = 0;
+
+       /* State flag for the insertion and deletion of leap seconds, esp. deletion, */
+       /* where the logic gets a bit tricky. */
+       int     LeapState = LEAPSTATE_NORMAL;
+
+       /* Flags for indication of leap second pending and leap secod polarity in IEEE 1344 */
+       int     LeapSecondPending = FALSE;
+       int     LeapSecondPolarity = FALSE;
+
+       /* Date and time of requested switch into or out of DST by command line option. */
+       int     DstSwitchYear                           = 0;
+       int DstSwitchMonth                              = 0;
+       int     DstSwitchDayOfMonth                     = 0;
+       int DstSwitchHour                               = 0;
+       int     DstSwitchMinute                         = 0;
+       int     DstSwitchDayOfYear                      = 0;
+
+       /* Indicate when we have been asked to switch into or out of DST by command line option. */
+       int     DstSwitchFlag = FALSE;
+
+       /* To allow predict for DstPendingFlag in IEEE 1344 */
+       int     DstSwitchPendingYear            = 0;    /* Default value isn't valid, but I don't care. */
+       int     DstSwitchPendingDayOfYear       = 0;
+       int     DstSwitchPendingHour            = 0;
+       int     DstSwitchPendingMinute          = 0;
+
+       /* /Flag for indication of a DST switch pending in IEEE 1344 */
+       int     DstPendingFlag = FALSE;
+
+       /* Attempt at unmodulated */
+       int     Unmodulated = FALSE;
+       int UnmodulatedInverted = FALSE;
+
+       /* Offset to actual time value sent. */
+       float   UseOffsetHoursFloat;
+       int             UseOffsetSecondsInt = 0;
+       float   UseOffsetSecondsFloat;
+
+       /* String to allow us to put out reversed data - so can read the binary numbers. */
+       char    OutputDataString[OUTPUT_DATA_STRING_LENGTH];
+       
+       /* Number of seconds to send before exiting.  Default = 0 = forever. */
+       int             SecondsToSend = 0;
+       int             CountOfSecondsSent = 0; /* Counter of seconds */
+       
+       /* Flags to indicate whether to add or remove a cycle for time adjustment. */
+       int             AddCycle = FALSE;               // We are ahead, add cycle to slow down and get back in sync.
+       int             RemoveCycle = FALSE;    // We are behind, remove cycle to slow down and get back in sync.
+       int             RateCorrection;                 // Aggregate flag for passing to subroutines.
+       int             EnableRateCorrection = TRUE;
+       
+       float   RatioError;
+
+
+       CommandName = argv[0];
+
+       if      (argc < 1)
+               {
+               Help ();
+               exit (-1);
+               }
+
+       /*
+        * Parse options
+        */
+       strcpy(device, DEVICE);
+       Year = 0;
+       SetSampleRate = SECOND;
+       
+#if    HAVE_SYS_SOUNDCARD_H
+       while ((temp = getopt(argc, argv, "a:b:c:df:g:hHi:jk:l:o:q:r:stu:xy:z?")) != -1) {
+#else
+       while ((temp = getopt(argc, argv, "a:b:c:df:g:hHi:jk:l:o:q:r:stu:v:xy:z?")) != -1) {
+#endif
+               switch (temp) {
+
+               case 'a':       /* specify audio device (/dev/audio) */
+                       strcpy(device, optarg);
+                       break;
+
+               case 'b':       /* Remove (delete) a leap second at the end of the specified minute. */
+                       sscanf(optarg, "%2d%2d%2d%2d%2d", &LeapYear, &LeapMonth, &LeapDayOfMonth,
+                           &LeapHour, &LeapMinute);
+                       InsertLeapSecond = FALSE;
+                       DeleteLeapSecond = TRUE;
+                       break;
+                       
+               case 'c':       /* specify number of seconds to send output for before exiting, 0 = forever */
+                       sscanf(optarg, "%d", &SecondsToSend);
+                       break;
+
+               case 'd':       /* set DST for summer (WWV/H only) / start with DST active (IRIG) */
+                       DstFlag++;
+                       break;
+
+               case 'f':       /* select format: i=IRIG-98 (default) 2=IRIG-2004 3-IRIG+IEEE-1344 w=WWV(H) */
+                       sscanf(optarg, "%c", &FormatCharacter);
+                       break;
+
+               case 'g':       /* Date and time to switch back into / out of DST active. */
+                       sscanf(optarg, "%2d%2d%2d%2d%2d", &DstSwitchYear, &DstSwitchMonth, &DstSwitchDayOfMonth,
+                           &DstSwitchHour, &DstSwitchMinute);
+                       DstSwitchFlag = TRUE;
+                       break;
+
+               case 'h':
+               case 'H':
+               case '?':
+                       Help ();
+                       exit(-1);
+                       break;
+
+               case 'i':       /* Insert (add) a leap second at the end of the specified minute. */
+                       sscanf(optarg, "%2d%2d%2d%2d%2d", &LeapYear, &LeapMonth, &LeapDayOfMonth,
+                           &LeapHour, &LeapMinute);
+                       InsertLeapSecond = TRUE;
+                       DeleteLeapSecond = FALSE;
+                       break;
+                       
+               case 'j':
+                       EnableRateCorrection = FALSE;
+                       break;
+
+               case 'k':
+                       sscanf (optarg, "%d", &RateCorrection);
+                       EnableRateCorrection = FALSE;
+                       if  (RateCorrection < 0)
+                               {
+                               RemoveCycle = TRUE;
+                               AddCycle = FALSE;
+                               
+                               if  (Verbose)
+                                       printf ("\n> Forcing rate correction removal of cycle...\n");
+                               }
+                       else
+                               {
+                               if  (RateCorrection > 0)
+                                       {
+                                       RemoveCycle = FALSE;
+                                       AddCycle = TRUE;
+                               
+                                       if  (Verbose)
+                                               printf ("\n> Forcing rate correction addition of cycle...\n");
+                                       }
+                               }
+                       break;
+
+               case 'l':       /* use time offset from UTC */
+                       sscanf(optarg, "%f", &UseOffsetHoursFloat);
+                       UseOffsetSecondsFloat = UseOffsetHoursFloat * (float) SECONDS_PER_HOUR;
+                       UseOffsetSecondsInt = (int) (UseOffsetSecondsFloat + 0.5);
+                       break;
+
+               case 'o':       /* Set IEEE 1344 time offset in hours - positive or negative, to the half hour */
+                       sscanf(optarg, "%f", &TimeOffset);
+                       if  (TimeOffset >= -0.2)
+                               {
+                               OffsetSignBit = 0;
+
+                               if  (TimeOffset > 0)
+                                       {
+                                       OffsetOnes    = TimeOffset;
+
+                                       if  ( (TimeOffset - floor(TimeOffset)) >= 0.4)
+                                               OffsetHalf = 1;
+                                       else
+                                               OffsetHalf = 0;
+                                       }
+                               else
+                                       {
+                                       OffsetOnes    = 0;
+                                       OffsetHalf    = 0;
+                                       }
+                               }
+                       else
+                               {
+                               OffsetSignBit = 1;
+                               OffsetOnes    = -TimeOffset;
+
+                               if  ( (ceil(TimeOffset) - TimeOffset) >= 0.4)
+                                       OffsetHalf = 1;
+                               else
+                                       OffsetHalf = 0;
+                               }
+
+                       /*printf ("\nGot TimeOffset = %3.1f, OffsetSignBit = %d, OffsetOnes = %d, OffsetHalf = %d...\n",
+                                       TimeOffset, OffsetSignBit, OffsetOnes, OffsetHalf);
+                       */
+                       break;
+
+               case 'q':       /* Hex quality code 0 to 0x0F - 0 = maximum, 0x0F = no lock */
+                       sscanf(optarg, "%x", &TimeQuality);
+                       TimeQuality &= 0x0F;
+                       /*printf ("\nGot TimeQuality = 0x%1X...\n", TimeQuality);
+                       */
+                       break;
+
+               case 'r':       /* sample rate (nominally 8000, integer close to 8000 I hope) */
+                       sscanf(optarg, "%d", &SetSampleRate);
+                       break;
+
+               case 's':       /* set leap warning bit (WWV/H only) */
+                       leap++;
+                       break;
+
+               case 't':       /* select WWVH sync frequency */
+                       tone = 1200;
+                       break;
+
+               case 'u':       /* set DUT1 offset (-7 to +7) */
+                       sscanf(optarg, "%d", &dut1);
+                       if (dut1 < 0)
+                               dut1 = abs(dut1);
+                       else
+                               dut1 |= 0x8;
+                       break;
+
+#ifndef  HAVE_SYS_SOUNDCARD_H
+               case 'v':       /* set output level (0-255) */
+                       sscanf(optarg, "%d", &level);
+                       break;
+#endif
+
+               case 'x':       /* Turn off verbose output. */
+                       Verbose = FALSE;
+                       break;
+
+               case 'y':       /* Set initial date and time */
+                       sscanf(optarg, "%2d%2d%2d%2d%2d%2d", &Year, &Month, &DayOfMonth,
+                           &Hour, &Minute, &Second);
+                       utc++;
+                       break;
+
+               case 'z':       /* Turn on Debug output (also turns on Verbose below) */
+                       Debug = TRUE;
+                       break;
+
+               default:
+                       printf("Invalid option \"%c\", aborting...\n", temp);
+                       exit (-1);
+                       break;
+               }
+       }
+
+       if  (Debug)
+           Verbose = TRUE;
+
+       if  (InsertLeapSecond || DeleteLeapSecond)
+               {
+               LeapDayOfYear = ConvertMonthDayToDayOfYear (LeapYear, LeapMonth, LeapDayOfMonth);
+
+               if      (Debug)
+                       {
+                       printf ("\nHave request for leap second %s at year %4d day %3d at %2.2dh%2.2d....\n",\
+                                       DeleteLeapSecond ? "DELETION" : (InsertLeapSecond ? "ADDITION" : "( error ! )" ),
+                                       LeapYear, LeapDayOfYear, LeapHour, LeapMinute);
+                       }
+               }
+
+       if      (DstSwitchFlag)
+               {
+               DstSwitchDayOfYear = ConvertMonthDayToDayOfYear (DstSwitchYear, DstSwitchMonth, DstSwitchDayOfMonth);
+
+               /* Figure out time of minute previous to DST switch, so can put up warning flag in IEEE 1344 */
+               DstSwitchPendingYear            = DstSwitchYear;
+               DstSwitchPendingDayOfYear       = DstSwitchDayOfYear;
+               DstSwitchPendingHour            = DstSwitchHour;
+               DstSwitchPendingMinute          = DstSwitchMinute - 1;
+               if      (DstSwitchPendingMinute < 0)
+                       {
+                       DstSwitchPendingMinute = 59;
+                       DstSwitchPendingHour--;
+                       if      (DstSwitchPendingHour < 0)
+                               {
+                               DstSwitchPendingHour = 23;
+                               DstSwitchPendingDayOfYear--;
+                               if      (DstSwitchPendingDayOfYear < 1)
+                                       {
+                                       DstSwitchPendingYear--;
+                                       }
+                               }
+                       }
+
+               if      (Debug)
+                       {
+                       printf ("\nHave DST switch request for year %4d day %3d at %2.2dh%2.2d,",
+                                       DstSwitchYear, DstSwitchDayOfYear, DstSwitchHour, DstSwitchMinute);
+                       printf ("\n    so will have warning at year %4d day %3d at %2.2dh%2.2d.\n",
+                                       DstSwitchPendingYear, DstSwitchPendingDayOfYear, DstSwitchPendingHour, DstSwitchPendingMinute);
+                       }
+               }
+
+       switch (tolower(FormatCharacter)) {
+       case 'i':
+               printf ("\nFormat is IRIG-1998 (no year coded)...\n\n");
+               encode = IRIG;
+               IrigIncludeYear = FALSE;
+               IrigIncludeIeee = FALSE;
+               break;
+
+       case '2':
+               printf ("\nFormat is IRIG-2004 (BCD year coded)...\n\n");
+               encode = IRIG;
+               IrigIncludeYear = TRUE;
+               IrigIncludeIeee = FALSE;
+               break;
+
+       case '3':
+               printf ("\nFormat is IRIG with IEEE-1344 (BCD year coded, and more control functions)...\n\n");
+               encode = IRIG;
+               IrigIncludeYear = TRUE;
+               IrigIncludeIeee = TRUE;
+               break;
+
+       case '4':
+               printf ("\nFormat is unmodulated IRIG with IEEE-1344 (BCD year coded, and more control functions)...\n\n");
+               encode = IRIG;
+               IrigIncludeYear = TRUE;
+               IrigIncludeIeee = TRUE;
+
+               Unmodulated = TRUE;
+               UnmodulatedInverted = FALSE;
+               break;
+
+       case '5':
+               printf ("\nFormat is inverted unmodulated IRIG with IEEE-1344 (BCD year coded, and more control functions)...\n\n");
+               encode = IRIG;
+               IrigIncludeYear = TRUE;
+               IrigIncludeIeee = TRUE;
+
+               Unmodulated = TRUE;
+               UnmodulatedInverted = TRUE;
+               break;
+
+       case 'w':
+               printf ("\nFormat is WWV(H)...\n\n");
+               encode = WWV;
+               break;
+
+       default:
+               printf ("\n\nUnexpected format value of \'%c\', cannot parse, aborting...\n\n", FormatCharacter);
+               exit (-1);
+               break;
+       }
+
+       /*
+        * Open audio device and set options
+        */
+       fd = open(device, O_WRONLY);
+       if (fd <= 0) {
+               printf("Unable to open audio device \"%s\", aborting: %s\n", device, strerror(errno));
+               exit(1);
+       }
+
+#ifdef  HAVE_SYS_SOUNDCARD_H
+       /* First set coding type */
+       AudioFormat = AFMT_MU_LAW;
+       if (ioctl(fd, SNDCTL_DSP_SETFMT, &AudioFormat)==-1)
+       { /* Fatal error */
+       printf ("\nUnable to set output format, aborting...\n\n");
+       exit(-1);
+       }
+
+       if  (AudioFormat != AFMT_MU_LAW)
+       {
+       printf ("\nUnable to set output format for mu law, aborting...\n\n");
+       exit(-1);
+       }
+
+       /* Next set number of channels */
+       MonoStereo = MONO;      /* Mono */
+       if (ioctl(fd, SNDCTL_DSP_STEREO, &MonoStereo)==-1)
+       { /* Fatal error */
+       printf ("\nUnable to set mono/stereo, aborting...\n\n");
+       exit(-1);
+       }
+
+       if (MonoStereo != MONO)
+       {
+       printf ("\nUnable to set mono/stereo for mono, aborting...\n\n");
+       exit(-1);
+       }
+
+       /* Now set sample rate */
+       SampleRate = SetSampleRate;
+       if (ioctl(fd, SNDCTL_DSP_SPEED, &SampleRate)==-1)
+       { /* Fatal error */
+       printf ("\nUnable to set sample rate to %d, returned %d, aborting...\n\n", SetSampleRate, SampleRate);
+       exit(-1);
+       }
+
+       SampleRateDifference = SampleRate - SetSampleRate;
+
+       if  (SampleRateDifference < 0)
+               SampleRateDifference = - SampleRateDifference;
+
+       /* Fixed allowable sample rate error 0.1% */
+       if (SampleRateDifference > (SetSampleRate/1000))
+       {
+       printf ("\nUnable to set sample rate to %d, result was %d, more than 0.1 percent, aborting...\n\n", SetSampleRate, SampleRate);
+       exit(-1);
+       }
+       else
+       {
+       /* printf ("\nAttempt to set sample rate to %d, actual %d...\n\n", SetSampleRate, SampleRate); */
+       }
+#else
+       rval = ioctl(fd, AUDIO_GETINFO, &info);
+       if (rval < 0) {
+               printf("\naudio control %s", strerror(errno));
+               exit(0);
+       }
+       info.play.port = port;
+       info.play.gain = level;
+       info.play.sample_rate = SetSampleRate;
+       info.play.channels = 1;
+       info.play.precision = 8;
+       info.play.encoding = AUDIO_ENCODING_ULAW;
+       printf("\nport %d gain %d rate %d chan %d prec %d encode %d\n",
+           info.play.port, info.play.gain, info.play.sample_rate,
+           info.play.channels, info.play.precision,
+           info.play.encoding);
+       ioctl(fd, AUDIO_SETINFO, &info);
+#endif
+
+       /*
+        * Unless specified otherwise, read the system clock and
+        * initialize the time.
+        */
+       gettimeofday(&TimeValue, NULL);         // Now always read the system time to keep "real time" of operation.
+       NowRealTime = BaseRealTime = SecondsPartOfTime = TimeValue.tv_sec;
+       SecondsRunningSimulationTime = 0;       // Just starting simulation, running zero seconds as of now.
+       StabilityCount = 0;                                     // No stability yet.
+
+       if      (utc)
+               {
+               DayOfYear = ConvertMonthDayToDayOfYear (Year, Month, DayOfMonth);
+               }
+       else
+               {
+               /* Apply offset to time. */
+               if      (UseOffsetSecondsInt >= 0)
+                       SecondsPartOfTime += (time_t)   UseOffsetSecondsInt;
+               else
+                       SecondsPartOfTime -= (time_t) (-UseOffsetSecondsInt);
+
+               TimeStructure = gmtime(&SecondsPartOfTime);
+               Minute = TimeStructure->tm_min;
+               Hour = TimeStructure->tm_hour;
+               DayOfYear = TimeStructure->tm_yday + 1;
+               Year = TimeStructure->tm_year % 100;
+               Second = TimeStructure->tm_sec;
+
+               /*
+                * Delay the first second so the generator is accurately
+                * aligned with the system clock within one sample (125
+                * microseconds ).
+                */
+               delay(SECOND - TimeValue.tv_usec * 8 / 1000);
+               }
+
+       StraightBinarySeconds = Second + (Minute * SECONDS_PER_MINUTE) + (Hour * SECONDS_PER_HOUR);
+
+       memset(code, 0, sizeof(code));
+       switch (encode) {
+
+       /*
+        * For WWV/H and default time, carefully set the signal
+        * generator seconds number to agree with the current time.
+        */
+       case WWV:
+               printf("WWV time signal, starting point:\n");
+               printf(" Year = %02d, Day of year = %03d, Time = %02d:%02d:%02d, Minute tone = %d Hz, Hour tone = %d Hz.\n",
+                   Year, DayOfYear, Hour, Minute, Second, tone, HourTone);
+               sprintf(code, "%01d%03d%02d%02d%01d",
+                   Year / 10, DayOfYear, Hour, Minute, Year % 10);
+               if  (Verbose)
+                       {
+                   printf("\n Year = %2.2d, Day of year = %3d, Time = %2.2d:%2.2d:%2.2d, Code = %s", 
+                               Year, DayOfYear, Hour, Minute, Second, code);
+
+                               if  ((EnableRateCorrection) || (RemoveCycle) || (AddCycle))
+                               printf (", CountOfSecondsSent = %d, TotalCyclesAdded = %d, TotalCyclesRemoved = %d\n", CountOfSecondsSent, TotalCyclesAdded, TotalCyclesRemoved);
+                       else
+                               printf ("\n");
+                       }
+
+               ptr = 8;
+               for (BitNumber = 0; BitNumber <= Second; BitNumber++) {
+                       if (progx[BitNumber].sw == DEC)
+                               ptr--;
+               }
+               break;
+
+       /*
+        * For IRIG the signal generator runs every second, so requires
+        * no additional alignment.
+        */
+       case IRIG:
+               printf ("IRIG-B time signal, starting point:\n");
+               printf (" Year = %02d, Day of year = %03d, Time = %02d:%02d:%02d, Straight binary seconds (SBS) = %05d / 0x%04X.\n",
+                   Year, DayOfYear, Hour, Minute, Second, StraightBinarySeconds, StraightBinarySeconds);
+               printf ("\n");
+               if  (Verbose)
+                   {
+               printf ("Codes: \".\" = marker/position indicator, \"-\" = zero dummy bit, \"0\" = zero bit, \"1\" = one bit.\n");
+                       if  ((EnableRateCorrection) || (AddCycle) || (RemoveCycle))
+                               {
+                               printf ("       \"o\" = short zero, \"*\" = long zero, \"x\" = short one, \"+\" = long one.\n");
+                               }
+               printf ("Numerical values are time order reversed in output to make it easier to read.\n");
+               /*                 111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999 */
+               /*       0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 */
+                   printf ("\n");
+               printf ("Legend of output codes:\n");
+               //printf ("\n");
+                   //printf ("|  StraightBinSecs  | IEEE_1344_Control |   Year  |    Day_of_Year    |  Hours  | Minutes |Seconds |\n");
+               //printf ("|  ---------------  | ----------------- |   ----  |    -----------    |  -----  | ------- |------- |\n");
+               //printf ("|                   |                   |         |                   |         |         |        |\n");
+               }
+               break;
+       }
+
+       /*
+        * Run the signal generator to generate new timecode strings
+        * once per minute for WWV/H and once per second for IRIG.
+        */
+       for (CountOfSecondsSent=0; ((SecondsToSend==0) || (CountOfSecondsSent<SecondsToSend)); CountOfSecondsSent++)
+               {
+               if  ((encode == IRIG) && (((Second % 20) == 0) || (CountOfSecondsSent == 0)))
+                       {
+               printf ("\n");
+
+                       printf (" Year = %02d, Day of year = %03d, Time = %02d:%02d:%02d, Straight binary seconds (SBS) = %05d / 0x%04X.\n",
+                           Year, DayOfYear, Hour, Minute, Second, StraightBinarySeconds, StraightBinarySeconds);
+                       if  ((EnableRateCorrection) || (RemoveCycle) || (AddCycle))
+                               {
+                               printf (" CountOfSecondsSent = %d, TotalCyclesAdded = %d, TotalCyclesRemoved = %d\n", CountOfSecondsSent, TotalCyclesAdded, TotalCyclesRemoved);
+                               if  ((CountOfSecondsSent != 0) && ((TotalCyclesAdded != 0) || (TotalCyclesRemoved != 0)))
+                                       {
+                                       RatioError = ((float) (TotalCyclesAdded - TotalCyclesRemoved)) / (1000.0 * (float) CountOfSecondsSent);
+                                       printf (" Adjusted by %2.1f%%, apparent send frequency is %4.2f Hz not %d Hz.\n\n", 
+                                                                       RatioError*100.0, (1.0+RatioError)*((float) SetSampleRate), SetSampleRate);
+                                       }
+                               }
+                       else
+                               printf ("\n");
+
+                   /* printf ("|Seconds | Minutes |  Hours  |    Day_of_Year    |   Year  | IEEE_1344_Control |  StraightBinSecs  |\n");
+               printf ("|------- | ------- |  -----  |    -----------    |   ----  | ----------------- |-------------------|\n");
+               printf ("|        |         |         |                   |         |                   |                   |\n");*/
+                   printf ("|  StraightBinSecs  | IEEE_1344_Control |   Year  |    Day_of_Year    |  Hours  | Minutes |Seconds |\n");
+               printf ("|  ---------------  | ----------------- |   ----  |    -----------    |  -----  | ------- |------- |\n");
+               printf ("|                   |                   |         |                   |         |         |        |\n");
+                       }
+
+               if  (RemoveCycle)
+                       {
+                       RateCorrection = -1;
+                       TotalSecondsCorrected ++;
+                       }
+               else
+                       {
+                       if  (AddCycle)
+                               {
+                               TotalSecondsCorrected ++;
+                               RateCorrection = +1;
+                               }
+                       else
+                               RateCorrection = 0;
+                       }
+
+               /*
+                * Crank the state machine to propagate carries to the
+                * year of century. Note that we delayed up to one
+                * second for alignment after reading the time, so this
+                * is the next second.
+                */
+
+               if  (LeapState == LEAPSTATE_NORMAL)
+                       {
+                       /* If on the second of a leap (second 59 in the specified minute), then add or delete a second */
+                       if  ((Year == LeapYear) && (DayOfYear == LeapDayOfYear) && (Hour == LeapHour) && (Minute == LeapMinute))
+                               {
+                               /* To delete a second, which means we go from 58->60 instead of 58->59->00. */
+                               if  ((DeleteLeapSecond) && (Second == 58))
+                                       {
+                                       LeapState = LEAPSTATE_DELETING;
+
+                                       if      (Debug)
+                                               printf ("\n<--- Ready to delete a leap second...\n");
+                                       }
+                               else
+                                       {       /* Delete takes precedence over insert. */
+                                       /* To add a second, which means we go from 59->60->00 instead of 59->00. */
+                                       if  ((InsertLeapSecond) && (Second == 59))
+                                               {
+                                               LeapState = LEAPSTATE_INSERTING;
+
+                                               if      (Debug)
+                                                       printf ("\n<--- Ready to insert a leap second...\n");
+                                               }
+                                       }
+                               }
+                       }
+
+               switch (LeapState)
+                       {
+                       case LEAPSTATE_NORMAL:
+                               Second = (Second + 1) % 60;
+                               break;
+
+                       case LEAPSTATE_DELETING:
+                               Second = 0;
+                               LeapState = LEAPSTATE_NORMAL;
+
+                               if      (Debug)
+                                       printf ("\n<--- Deleting a leap second...\n");
+                               break;
+
+                       case LEAPSTATE_INSERTING:
+                               Second = 60;
+                               LeapState = LEAPSTATE_ZERO_AFTER_INSERT;
+
+                               if      (Debug)
+                                       printf ("\n<--- Inserting a leap second...\n");
+                               break;
+
+                       case LEAPSTATE_ZERO_AFTER_INSERT:
+                               Second = 0;
+                               LeapState = LEAPSTATE_NORMAL;
+
+                               if      (Debug)
+                                       printf ("\n<--- Inserted a leap second, now back to zero...\n");
+                               break;
+
+                       default:
+                               printf ("\n\nLeap second state invalid value of %d, aborting...", LeapState);
+                               exit (-1);
+                               break;
+                       }
+
+               /* Check for second rollover, increment minutes and ripple upward if required. */
+               if (Second == 0) {
+                       Minute++;
+                       if (Minute >= 60) {
+                               Minute = 0;
+                               Hour++;
+                       }
+
+                       /* Check for activation of DST switch. */
+                       /* If DST is active, this would mean that at the appointed time, we de-activate DST, */
+                       /* which translates to going backward an hour (repeating the last hour). */
+                       /* If DST is not active, this would mean that at the appointed time, we activate DST, */
+                       /* which translates to going forward an hour (skipping the next hour). */
+                       if      (DstSwitchFlag)
+                               {
+                               /* The actual switch happens on the zero'th second of the actual minute specified. */
+                               if      ((Year == DstSwitchYear) && (DayOfYear == DstSwitchDayOfYear) && (Hour == DstSwitchHour) && (Minute == DstSwitchMinute))
+                                       {
+                                       if  (DstFlag == 0)
+                                               {       /* DST flag is zero, not in DST, going to DST, "spring ahead", so increment hour by two instead of one. */
+                                               Hour++;
+                                               DstFlag = 1;
+
+                                               /* Must adjust offset to keep consistent with UTC. */
+                                               /* Here we have to increase offset by one hour.  If it goes from negative to positive, then we fix that. */
+                                               if      (OffsetSignBit == 0)
+                                                       {       /* Offset is positive */
+                                                       if      (OffsetOnes == 0x0F)
+                                                               {
+                                                               OffsetSignBit = 1;
+                                                               OffsetOnes    = (OffsetHalf == 0) ? 8 : 7;
+                                                               }
+                                                       else
+                                                               OffsetOnes++;
+                                                       }
+                                               else
+                                                       {       /* Offset is negative */
+                                                       if  (OffsetOnes == 0)
+                                                               {
+                                                               OffsetSignBit = 0;
+                                                               OffsetOnes    = (OffsetHalf == 0) ? 1 : 0;
+                                                               }
+                                                       else
+                                                               OffsetOnes--;
+                                                       }
+
+                                               if      (Debug)
+                                                       printf ("\n<--- DST activated, spring ahead an hour, new offset !...\n");
+                                               }
+                                       else
+                                               {       /* DST flag is non zero, in DST, going out of DST, "fall back", so no increment of hour. */
+                                               Hour--;
+                                               DstFlag = 0;
+
+                                               /* Must adjust offset to keep consistent with UTC. */
+                                               /* Here we have to reduce offset by one hour.  If it goes negative, then we fix that. */
+                                               if      (OffsetSignBit == 0)
+                                                       {       /* Offset is positive */
+                                                       if  (OffsetOnes == 0)
+                                                               {
+                                                               OffsetSignBit = 1;
+                                                               OffsetOnes    = (OffsetHalf == 0) ? 1 : 0;
+                                                               }
+                                                       else
+                                                               OffsetOnes--;
+                                                       }
+                                               else
+                                                       {       /* Offset is negative */
+                                                       if      (OffsetOnes == 0x0F)
+                                                               {
+                                                               OffsetSignBit = 0;
+                                                               OffsetOnes    = (OffsetHalf == 0) ? 8 : 7;
+                                                               }
+                                                       else
+                                                               OffsetOnes++;
+                                                       }
+
+                                               if      (Debug)
+                                                       printf ("\n<--- DST de-activated, fall back an hour!...\n");
+                                               }
+
+                                       DstSwitchFlag = FALSE;  /* One time deal, not intended to run this program past two switches... */
+                                       }
+                               }
+
+                       if (Hour >= 24) {
+                               /* Modified, just in case dumb case where activating DST advances 23h59:59 -> 01h00:00 */
+                               Hour = Hour % 24;
+                               DayOfYear++;
+                       }
+
+                       /*
+                        * At year rollover check for leap second.
+                        */
+                       if (DayOfYear >= (Year & 0x3 ? 366 : 367)) {
+                               if (leap) {
+                                       WWV_Second(DATA0, RateCorrection);
+                                       if  (Verbose)
+                                           printf("\nLeap!");
+                                       leap = 0;
+                               }
+                               DayOfYear = 1;
+                               Year++;
+                       }
+                       if (encode == WWV) {
+                               sprintf(code, "%01d%03d%02d%02d%01d",
+                                   Year / 10, DayOfYear, Hour, Minute, Year % 10);
+                               if  (Verbose)
+                                   printf("\n Year = %2.2d, Day of year = %3d, Time = %2.2d:%2.2d:%2.2d, Code = %s", 
+                                               Year, DayOfYear, Hour, Minute, Second, code);
+
+                               if  ((EnableRateCorrection) || (RemoveCycle) || (AddCycle))
+                                       {
+                                       printf (", CountOfSecondsSent = %d, TotalCyclesAdded = %d, TotalCyclesRemoved = %d\n", CountOfSecondsSent, TotalCyclesAdded, TotalCyclesRemoved);
+                                       if  ((CountOfSecondsSent != 0) && ((TotalCyclesAdded != 0) || (TotalCyclesRemoved != 0)))
+                                               {
+                                               RatioError = ((float) (TotalCyclesAdded - TotalCyclesRemoved)) / (1000.0 * (float) CountOfSecondsSent);
+                                               printf (" Adjusted by %2.1f%%, apparent send frequency is %4.2f Hz not %d Hz.\n\n", 
+                                                                               RatioError*100.0, (1.0+RatioError)*((float) SetSampleRate), SetSampleRate);
+                                               }
+                                       }
+                               else
+                                       printf ("\n");
+
+                               ptr = 8;
+                       }
+               }       /* End of "if  (Second == 0)" */
+
+               /* After all that, if we are in the minute just prior to a leap second, warn of leap second pending */
+               /* and of the polarity */
+               if  ((Year == LeapYear) && (DayOfYear == LeapDayOfYear) && (Hour == LeapHour) && (Minute == LeapMinute))
+                       {
+                       LeapSecondPending = TRUE;
+                       LeapSecondPolarity = DeleteLeapSecond;
+                       }
+               else
+                       {
+                       LeapSecondPending = FALSE;
+                       LeapSecondPolarity = FALSE;
+                       }
+
+               /* Notification through IEEE 1344 happens during the whole minute previous to the minute specified. */
+               /* The time of that minute has been previously calculated. */
+               if      ((Year == DstSwitchPendingYear) && (DayOfYear == DstSwitchPendingDayOfYear) &&
+                                       (Hour == DstSwitchPendingHour) && (Minute == DstSwitchPendingMinute))
+                       {
+                       DstPendingFlag = TRUE;
+                       }
+               else
+                       {
+                       DstPendingFlag = FALSE;
+                       }
+
+
+               StraightBinarySeconds = Second + (Minute * SECONDS_PER_MINUTE) + (Hour * SECONDS_PER_HOUR);
+
+               if (encode == IRIG) {
+                       if  (IrigIncludeIeee)
+                               {
+                               if  ((OffsetOnes == 0) && (OffsetHalf == 0))
+                                       OffsetSignBit = 0;
+
+                               ControlFunctions = (LeapSecondPending == 0 ? 0x00000 : 0x00001) | (LeapSecondPolarity == 0 ? 0x00000 : 0x00002)
+                                               | (DstPendingFlag == 0 ? 0x00000 : 0x00004) | (DstFlag == 0 ? 0x00000 : 0x00008)
+                                               | (OffsetSignBit == 0 ? 0x00000 : 0x00010)  | ((OffsetOnes & 0x0F) << 5)           | (OffsetHalf == 0 ? 0x00000 : 0x00200)
+                                               | ((TimeQuality & 0x0F) << 10);
+                               /* if  (Verbose)
+                                       printf ("\nDstFlag = %d, OffsetSignBit = %d, OffsetOnes = %d, OffsetHalf = %d, TimeQuality = 0x%1.1X ==> ControlFunctions = 0x%5.5X...",
+                                                   DstFlag, OffsetSignBit, OffsetOnes, OffsetHalf, TimeQuality, ControlFunctions);
+                               */
+                               }
+                       else
+                               ControlFunctions = 0;
+
+                       /*
+                                          YearDay HourMin Sec
+                       sprintf(code, "%04x%04d%06d%02d%02d%02d",
+                               0, Year, DayOfYear, Hour, Minute, Second);
+                       */
+                       if  (IrigIncludeYear) {
+                               sprintf(ParityString, "%04X%02d%04d%02d%02d%02d",
+                                       ControlFunctions & 0x7FFF, Year, DayOfYear, Hour, Minute, Second);
+                       }
+                       else {
+                               sprintf(ParityString, "%04X%02d%04d%02d%02d%02d",
+                                       ControlFunctions & 0x7FFF,    0, DayOfYear, Hour, Minute, Second);
+                       }
+
+                       if  (IrigIncludeIeee)
+                               {
+                               ParitySum = 0;
+                               for (StringPointer=ParityString; *StringPointer!=NUL; StringPointer++)
+                                       {
+                                       switch (toupper(*StringPointer))
+                                               {
+                                               case '1':
+                                               case '2':
+                                               case '4':
+                                               case '8':
+                                                       ParitySum += 1;
+                                                       break;
+
+                                               case '3':
+                                               case '5':
+                                               case '6':
+                                               case '9':
+                                               case 'A':
+                                               case 'C':
+                                                       ParitySum += 2;
+                                                       break;
+
+                                               case '7':
+                                               case 'B':
+                                               case 'D':
+                                               case 'E':
+                                                       ParitySum += 3;
+                                                       break;
+
+                                               case 'F':
+                                                       ParitySum += 4;
+                                                       break;
+                                               }
+                                       }
+
+                               if  ((ParitySum & 0x01) == 0x01)
+                                       ParityValue = 0x01;
+                               else
+                                       ParityValue = 0;
+                               }
+                       else
+                               ParityValue = 0;
+
+                       ControlFunctions |= ((ParityValue & 0x01) << 14);
+
+                       if  (IrigIncludeYear) {
+                               /*                 YearDay HourMin Sec*/
+                               sprintf(code, "%05X%05X%02d%04d%02d%02d%02d",
+                                       StraightBinarySeconds, ControlFunctions, Year, DayOfYear, Hour, Minute, Second);
+                       }
+                       else {
+                               /*                 YearDay HourMin Sec*/
+                               sprintf(code, "%05X%05X%02d%04d%02d%02d%02d",
+                                       StraightBinarySeconds, ControlFunctions,    0, DayOfYear, Hour, Minute, Second);
+                       }
+
+                       if  (Debug)
+                               printf("\nCode string: %s, ParityString = %s, ParitySum = 0x%2.2X, ParityValue = %d, DstFlag = %d...\n", code, ParityString, ParitySum, ParityValue, DstFlag);
+
+                       ptr = strlen(code)-1;
+                       OldPtr = 0;
+               }
+
+               /*
+                * Generate data for the second
+                */
+               switch(encode) {
+
+               /*
+                * The IRIG second consists of 20 BCD digits of width-
+                * modulateod pulses at 2, 5 and 8 ms and modulated 50
+                * percent on the 1000-Hz carrier.
+                */
+               case IRIG:
+                       strcpy (OutputDataString, "");  /* Initialize the output string */
+
+                       for (BitNumber = 0; BitNumber < 100; BitNumber++) {
+                               FrameNumber = (BitNumber/10) + 1;
+                               switch (FrameNumber)
+                                       {
+                                       case 1:
+                                               /* bits 0 to 9, first frame */
+                                               sw  = progz[BitNumber % 10].sw;
+                                               arg = progz[BitNumber % 10].arg;
+                                               break;
+
+                                       case 2:
+                                       case 3:
+                                       case 4:
+                                       case 5:
+                                       case 6:
+                                               /* bits 10 to 59, second to sixth frame */
+                                               sw  = progy[BitNumber % 10].sw;
+                                               arg = progy[BitNumber % 10].arg;
+                                               break;
+
+                                       case 7:
+                                               /* bits 60 to 69, seventh frame */
+                                               sw  = progw[BitNumber % 10].sw;
+                                               arg = progw[BitNumber % 10].arg;
+                                               break;
+
+                                       case 8:
+                                               /* bits 70 to 79, eighth frame */
+                                               sw  = progv[BitNumber % 10].sw;
+                                               arg = progv[BitNumber % 10].arg;
+                                               break;
+
+                                       case 9:
+                                               /* bits 80 to 89, ninth frame */
+                                               sw  = progw[BitNumber % 10].sw;
+                                               arg = progw[BitNumber % 10].arg;
+                                               break;
+
+                                       case 10:
+                                               /* bits 90 to 99, tenth frame */
+                                               sw  = progu[BitNumber % 10].sw;
+                                               arg = progu[BitNumber % 10].arg;
+                                               break;
+
+                                       default:
+                                               /* , Unexpected values of FrameNumber */
+                                               printf ("\n\nUnexpected value of FrameNumber = %d, cannot parse, aborting...\n\n", FrameNumber);
+                                               exit (-1);
+                                               break;
+                                       }
+
+                               switch(sw) {
+
+                               case DECC:      /* decrement pointer and send bit. */
+                                       ptr--;
+                               case COEF:      /* send BCD bit */
+                                       AsciiValue = toupper(code[ptr]);
+                                       HexValue   = isdigit(AsciiValue) ? AsciiValue - '0' : (AsciiValue - 'A')+10;
+                                       /* if  (Debug) {
+                                               if  (ptr != OldPtr) {
+                                               if  (Verbose)
+                                                   printf("\n(%c->%X)", AsciiValue, HexValue);
+                                               OldPtr = ptr;
+                                               }
+                                       }
+                                       */
+                                       // OK, adjust all unused bits in hundreds of days.
+                                       if  ((FrameNumber == 5) && ((BitNumber % 10) > 1))
+                                               {
+                                               if  (RateCorrection < 0)
+                                                       {       // Need to remove cycles to catch up.
+                                                       if  ((HexValue & arg) != 0) 
+                                                               {
+                                                               if  (Unmodulated)
+                                                                       {
+                                                                       poop(M5, 1000, HIGH, UnmodulatedInverted);
+                                                                       poop(M5-1, 1000, LOW,  UnmodulatedInverted);
+
+                                                                       TotalCyclesRemoved += 1;
+                                                                       }
+                                                               else
+                                                                       {
+                                                                       peep(M5, 1000, HIGH);
+                                                                       peep(M5-1, 1000, LOW);
+
+                                                                       TotalCyclesRemoved += 1;
+                                                                       }
+                                                   /* OutputDataString OUTPUT_DATA_STRING_LENGTH */
+                                                               strncat(OutputDataString, "x", OUTPUT_DATA_STRING_LENGTH);
+                                                               }
+                                                       else 
+                                                               {
+                                                               if      (Unmodulated)
+                                                                       {
+                                                                       poop(M2, 1000, HIGH, UnmodulatedInverted);
+                                                                       poop(M8-1, 1000, LOW,  UnmodulatedInverted);
+
+                                                                       TotalCyclesRemoved += 1;
+                                                                       }
+                                                               else
+                                                                       {
+                                                                       peep(M2, 1000, HIGH);
+                                                                       peep(M8-1, 1000, LOW);
+
+                                                                       TotalCyclesRemoved += 1;
+                                                                       }
+                                                               strncat(OutputDataString, "o", OUTPUT_DATA_STRING_LENGTH);
+                                                               }
+                                                       }       // End of true clause for "if  (RateCorrection < 0)"
+                                               else
+                                                       {       // Else clause for "if  (RateCorrection < 0)"
+                                                       if  (RateCorrection > 0)
+                                                               {       // Need to add cycles to slow back down.
+                                                               if  ((HexValue & arg) != 0) 
+                                                                       {
+                                                                       if  (Unmodulated)
+                                                                               {
+                                                                               poop(M5, 1000, HIGH, UnmodulatedInverted);
+                                                                               poop(M5+1, 1000, LOW,  UnmodulatedInverted);
+
+                                                                               TotalCyclesAdded += 1;
+                                                                               }
+                                                                       else
+                                                                               {
+                                                                               peep(M5, 1000, HIGH);
+                                                                               peep(M5+1, 1000, LOW);
+
+                                                                               TotalCyclesAdded += 1;
+                                                                               }
+                                                           /* OutputDataString OUTPUT_DATA_STRING_LENGTH */
+                                                                       strncat(OutputDataString, "+", OUTPUT_DATA_STRING_LENGTH);
+                                                                       }
+                                                               else 
+                                                                       {
+                                                                       if      (Unmodulated)
+                                                                               {
+                                                                               poop(M2, 1000, HIGH, UnmodulatedInverted);
+                                                                               poop(M8+1, 1000, LOW,  UnmodulatedInverted);
+
+                                                                               TotalCyclesAdded += 1;
+                                                                               }
+                                                                       else
+                                                                               {
+                                                                               peep(M2, 1000, HIGH);
+                                                                               peep(M8+1, 1000, LOW);
+
+                                                                               TotalCyclesAdded += 1;
+                                                                               }
+                                                                       strncat(OutputDataString, "*", OUTPUT_DATA_STRING_LENGTH);
+                                                                       }
+                                                               }       // End of true clause for "if  (RateCorrection > 0)"
+                                                       else
+                                                               {       // Else clause for "if  (RateCorrection > 0)"
+                                                               // Rate is OK, just do what you feel!
+                                                               if  ((HexValue & arg) != 0) 
+                                                                       {
+                                                                       if  (Unmodulated)
+                                                                               {
+                                                                               poop(M5, 1000, HIGH, UnmodulatedInverted);
+                                                                               poop(M5, 1000, LOW,  UnmodulatedInverted);
+                                                                               }
+                                                                       else
+                                                                               {
+                                                                               peep(M5, 1000, HIGH);
+                                                                               peep(M5, 1000, LOW);
+                                                                               }
+                                                           /* OutputDataString OUTPUT_DATA_STRING_LENGTH */
+                                                                       strncat(OutputDataString, "1", OUTPUT_DATA_STRING_LENGTH);
+                                                                       }
+                                                               else 
+                                                                       {
+                                                                       if      (Unmodulated)
+                                                                               {
+                                                                               poop(M2, 1000, HIGH, UnmodulatedInverted);
+                                                                               poop(M8, 1000, LOW,  UnmodulatedInverted);
+                                                                               }
+                                                                       else
+                                                                               {
+                                                                               peep(M2, 1000, HIGH);
+                                                                               peep(M8, 1000, LOW);
+                                                                               }
+                                                                       strncat(OutputDataString, "0", OUTPUT_DATA_STRING_LENGTH);
+                                                                       }
+                                                               }       // End of else clause for "if  (RateCorrection > 0)"
+                                                       }       // End of else claues for "if  (RateCorrection < 0)"
+                                               }       // End of true clause for "if  ((FrameNumber == 5) && (BitNumber == 8))"
+                                       else
+                                               {       // Else clause for "if  ((FrameNumber == 5) && (BitNumber == 8))"
+                                               if  ((HexValue & arg) != 0) 
+                                                       {
+                                                       if  (Unmodulated)
+                                                               {
+                                                               poop(M5, 1000, HIGH, UnmodulatedInverted);
+                                                               poop(M5, 1000, LOW,  UnmodulatedInverted);
+                                                               }
+                                                       else
+                                                               {
+                                                               peep(M5, 1000, HIGH);
+                                                               peep(M5, 1000, LOW);
+                                                               }
+                                           /* OutputDataString OUTPUT_DATA_STRING_LENGTH */
+                                                       strncat(OutputDataString, "1", OUTPUT_DATA_STRING_LENGTH);
+                                                       }
+                                               else 
+                                                       {
+                                                       if      (Unmodulated)
+                                                               {
+                                                               poop(M2, 1000, HIGH, UnmodulatedInverted);
+                                                               poop(M8, 1000, LOW,  UnmodulatedInverted);
+                                                               }
+                                                       else
+                                                               {
+                                                               peep(M2, 1000, HIGH);
+                                                               peep(M8, 1000, LOW);
+                                                               }
+                                                       strncat(OutputDataString, "0", OUTPUT_DATA_STRING_LENGTH);
+                                                       }
+                                               } // end of else clause for "if  ((FrameNumber == 5) && (BitNumber == 8))"
+                                       break;
+
+                               case DECZ:      /* decrement pointer and send zero bit */
+                                       ptr--;
+                                       if      (Unmodulated)
+                                               {
+                                               poop(M2, 1000, HIGH, UnmodulatedInverted);
+                                               poop(M8, 1000, LOW,  UnmodulatedInverted);
+                                               }
+                                       else
+                                               {
+                                               peep(M2, 1000, HIGH);
+                                               peep(M8, 1000, LOW);
+                                               }
+                                       strncat(OutputDataString, "-", OUTPUT_DATA_STRING_LENGTH);
+                                       break;
+
+                               case DEC:       /* send marker/position indicator IM/PI bit */
+                                       ptr--;
+                               case NODEC:     /* send marker/position indicator IM/PI bit but no decrement pointer */
+                               case MIN:       /* send "second start" marker/position indicator IM/PI bit */
+                                       if  (Unmodulated)
+                                               {
+                                               poop(arg,      1000, HIGH, UnmodulatedInverted);
+                                               poop(10 - arg, 1000, LOW,  UnmodulatedInverted);
+                                               }
+                                       else
+                                               {
+                                               peep(arg,      1000, HIGH);
+                                               peep(10 - arg, 1000, LOW);
+                                               }
+                                       strncat(OutputDataString, ".", OUTPUT_DATA_STRING_LENGTH);
+                                       break;
+
+                               default:
+                                       printf ("\n\nUnknown state machine value \"%d\", unable to continue, aborting...\n\n", sw);
+                                       exit (-1);
+                                       break;
+                               }
+                               if (ptr < 0)
+                                       break;
+                       }
+                       ReverseString ( OutputDataString );
+                       if  (Verbose)
+                               {
+                       printf("%s", OutputDataString);
+                               if  (RateCorrection > 0)
+                                       printf(" fast\n");
+                               else
+                                       {
+                                       if  (RateCorrection < 0)
+                                               printf (" slow\n");
+                                       else
+                                               printf ("\n");
+                                       }
+                               }
+                       break;
+
+               /*
+                * The WWV/H second consists of 9 BCD digits of width-
+                * modulateod pulses 200, 500 and 800 ms at 100-Hz.
+                */
+               case WWV:
+                       sw = progx[Second].sw;
+                       arg = progx[Second].arg;
+                       switch(sw) {
+
+                       case DATA:              /* send data bit */
+                               WWV_Second(arg, RateCorrection);
+                               if  (Verbose)
+                                       {
+                                       if  (arg == DATA0)
+                                               printf ("0");
+                                       else
+                                               {
+                                               if  (arg == DATA1)
+                                                       printf ("1");
+                                               else
+                                                       {
+                                                       if  (arg == PI)
+                                                               printf ("P");
+                                                       else
+                                                               printf ("?");
+                                                       }
+                                               }
+                                       }
+                               break;
+
+                       case DATAX:             /* send data bit */
+                               WWV_SecondNoTick(arg, RateCorrection);
+                               if  (Verbose)
+                                       {
+                                       if  (arg == DATA0)
+                                               printf ("0");
+                                       else
+                                               {
+                                               if  (arg == DATA1)
+                                                       printf ("1");
+                                               else
+                                                       {
+                                                       if  (arg == PI)
+                                                               printf ("P");
+                                                       else
+                                                               printf ("?");
+                                                       }
+                                               }
+                                       }
+                               break;
+
+                       case COEF:              /* send BCD bit */
+                               if (code[ptr] & arg) {
+                                       WWV_Second(DATA1, RateCorrection);
+                                       if  (Verbose)
+                                           printf("1");
+                               } else {
+                                       WWV_Second(DATA0, RateCorrection);
+                                       if  (Verbose)
+                                           printf("0");
+                               }
+                               break;
+
+                       case LEAP:              /* send leap bit */
+                               if (leap) {
+                                       WWV_Second(DATA1, RateCorrection);
+                                       if  (Verbose)
+                                           printf("L");
+                               } else {
+                                       WWV_Second(DATA0, RateCorrection);
+                                       if  (Verbose)
+                                           printf("0");
+                               }
+                               break;
+
+                       case DEC:               /* send data bit */
+                               ptr--;
+                               WWV_Second(arg, RateCorrection);
+                               if  (Verbose)
+                                       {
+                                       if  (arg == DATA0)
+                                               printf ("0");
+                                       else
+                                               {
+                                               if  (arg == DATA1)
+                                                       printf ("1");
+                                               else
+                                                       {
+                                                       if  (arg == PI)
+                                                               printf ("P");
+                                                       else
+                                                               printf ("?");
+                                                       }
+                                               }
+                                       }
+                               break;
+
+                       case DECX:              /* send data bit with no tick */
+                               ptr--;
+                               WWV_SecondNoTick(arg, RateCorrection);
+                               if  (Verbose)
+                                       {
+                                       if  (arg == DATA0)
+                                               printf ("0");
+                                       else
+                                               {
+                                               if  (arg == DATA1)
+                                                       printf ("1");
+                                               else
+                                                       {
+                                                       if  (arg == PI)
+                                                               printf ("P");
+                                                       else
+                                                               printf ("?");
+                                                       }
+                                               }
+                                       }
+                               break;
+
+                       case MIN:               /* send minute sync */
+                               if  (Minute == 0)
+                                       {
+                                       peep(arg, HourTone, HIGH);
+
+                                       if  (RateCorrection < 0)
+                                               {
+                                               peep( 990 - arg, HourTone, OFF);
+                                               TotalCyclesRemoved += 10;
+
+                                               if  (Debug)
+                                                       printf ("\n* Shorter Second: ");
+                                               }
+                                       else
+                                               {
+                                               if      (RateCorrection > 0)
+                                                       {
+                                                       peep(1010 - arg, HourTone, OFF);
+
+                                                       TotalCyclesAdded += 10;
+
+                                                       if  (Debug)
+                                                               printf ("\n* Longer Second: ");
+                                                       }
+                                               else
+                                                       {
+                                                       peep(1000 - arg, HourTone, OFF);
+                                                       }
+                                               }
+
+                                       if  (Verbose)
+                                           printf("H");
+                                       }
+                               else
+                                       {
+                                       peep(arg, tone, HIGH);
+
+                                       if  (RateCorrection < 0)
+                                               {
+                                               peep( 990 - arg, tone, OFF);
+                                               TotalCyclesRemoved += 10;
+
+                                               if  (Debug)
+                                                       printf ("\n* Shorter Second: ");
+                                               }
+                                       else
+                                               {
+                                               if      (RateCorrection > 0)
+                                                       {
+                                                       peep(1010 - arg, tone, OFF);
+
+                                                       TotalCyclesAdded += 10;
+
+                                                       if  (Debug)
+                                                               printf ("\n* Longer Second: ");
+                                                       }
+                                               else
+                                                       {
+                                                       peep(1000 - arg, tone, OFF);
+                                                       }
+                                               }
+
+                                       if  (Verbose)
+                                           printf("M");
+                                       }
+                               break;
+
+                       case DUT1:              /* send DUT1 bits */
+                               if (dut1 & arg)
+                                       {
+                                       WWV_Second(DATA1, RateCorrection);
+                                       if  (Verbose)
+                                           printf("1");
+                                       }
+                               else
+                                       {
+                                       WWV_Second(DATA0, RateCorrection);
+                                       if  (Verbose)
+                                           printf("0");
+                                       }
+                               break;
+
+                       case DST1:              /* send DST1 bit */
+                               ptr--;
+                               if (DstFlag)
+                                       {
+                                       WWV_Second(DATA1, RateCorrection);
+                                       if  (Verbose)
+                                           printf("1");
+                                       }
+                               else
+                                       {
+                                       WWV_Second(DATA0, RateCorrection);
+                                       if  (Verbose)
+                                           printf("0");
+                                       }
+                               break;
+
+                       case DST2:              /* send DST2 bit */
+                               if (DstFlag)
+                                       {
+                                       WWV_Second(DATA1, RateCorrection);
+                                       if  (Verbose)
+                                           printf("1");
+                                       }
+                               else
+                                       {
+                                       WWV_Second(DATA0, RateCorrection);
+                                       if  (Verbose)
+                                           printf("0");
+                                       }
+                               break;
+                       }
+               }
+
+       if  (EnableRateCorrection)
+               {
+               SecondsRunningSimulationTime++;
+
+               gettimeofday(&TimeValue, NULL);
+               NowRealTime = TimeValue.tv_sec;
+
+               if  (NowRealTime >= BaseRealTime)               // Just in case system time corrects backwards, do not blow up.
+                       {
+                       SecondsRunningRealTime = (unsigned) (NowRealTime - BaseRealTime);
+                       SecondsRunningDifference = SecondsRunningSimulationTime - SecondsRunningRealTime;
+
+                       if  (Debug)
+                               {
+                               printf ("> NowRealTime = 0x%8.8X, BaseRealtime = 0x%8.8X, SecondsRunningRealTime = 0x%8.8X, SecondsRunningSimulationTime = 0x%8.8X.\n",
+                                                       (unsigned) NowRealTime, (unsigned) BaseRealTime, SecondsRunningRealTime, SecondsRunningSimulationTime);
+                               printf ("> SecondsRunningDifference = 0x%8.8X, ExpectedRunningDifference = 0x%8.8X.\n",
+                                                       SecondsRunningDifference, ExpectedRunningDifference);
+                               }
+
+                       if  (SecondsRunningSimulationTime > RUN_BEFORE_STABILITY_CHECK)
+                               {
+                               if  (StabilityCount < MINIMUM_STABILITY_COUNT)
+                                       {
+                                       if  (StabilityCount == 0)
+                                               {
+                                               ExpectedRunningDifference = SecondsRunningDifference;
+                                               StabilityCount++;
+                                               if  (Debug)
+                                                       printf ("> Starting stability check.\n");
+                                               }
+                                       else
+                                               {       // Else for "if  (StabilityCount == 0)"
+                                               if  ((ExpectedRunningDifference+INITIAL_STABILITY_BAND > SecondsRunningDifference)
+                                                               && (ExpectedRunningDifference-INITIAL_STABILITY_BAND < SecondsRunningDifference))
+                                                       {       // So far, still within stability band, increment count.
+                                                       StabilityCount++;
+                                                       if  (Debug)
+                                                               printf ("> StabilityCount = %d.\n", StabilityCount);
+                                                       }
+                                               else
+                                                       {       // Outside of stability band, start over.
+                                                       StabilityCount = 0;
+                                                       if  (Debug)
+                                                               printf ("> Out of stability band, start over.\n");
+                                                       }
+                                               } // End of else for "if  (StabilityCount == 0)"
+                                       }       // End of true clause for "if  (StabilityCount < MINIMUM_STABILITY_COUNT))"
+                               else
+                                       {       // Else clause for "if  (StabilityCount < MINIMUM_STABILITY_COUNT))" - OK, so we are supposed to be stable.
+                                       if  (AddCycle)
+                                               {
+                                               if  (ExpectedRunningDifference >= SecondsRunningDifference)
+                                                       {
+                                                       if  (Debug)
+                                                               printf ("> Was adding cycles, ExpectedRunningDifference >= SecondsRunningDifference, can stop it now.\n");
+
+                                                       AddCycle = FALSE;
+                                                       RemoveCycle = FALSE;
+                                                       }
+                                               else
+                                                       {
+                                                       if  (Debug)
+                                                               printf ("> Was adding cycles, not done yet.\n");
+                                                       }
+                                               }
+                                       else
+                                               {
+                                               if  (RemoveCycle)
+                                                       {
+                                                       if  (ExpectedRunningDifference <= SecondsRunningDifference)
+                                                               {
+                                                               if  (Debug)
+                                                                       printf ("> Was removing cycles, ExpectedRunningDifference <= SecondsRunningDifference, can stop it now.\n");
+
+                                                               AddCycle = FALSE;
+                                                               RemoveCycle = FALSE;
+                                                               }
+                                                       else
+                                                               {
+                                                               if  (Debug)
+                                                                       printf ("> Was removing cycles, not done yet.\n");
+                                                               }
+                                                       }
+                                               else
+                                                       {
+                                                       if  ((ExpectedRunningDifference+RUNNING_STABILITY_BAND > SecondsRunningDifference)
+                                                                       && (ExpectedRunningDifference-RUNNING_STABILITY_BAND < SecondsRunningDifference))
+                                                               {       // All is well, within tolerances.
+                                                               if  (Debug)
+                                                                       printf ("> All is well, within tolerances.\n");
+                                                               }
+                                                       else
+                                                               {       // Oops, outside tolerances.  Else clause of "if  ((ExpectedRunningDifference...SecondsRunningDifference)"
+                                                               if  (ExpectedRunningDifference > SecondsRunningDifference)
+                                                                       {
+                                                                       if  (Debug)
+                                                                               printf ("> ExpectedRunningDifference > SecondsRunningDifference, running behind real time.\n");
+
+                                                                       // Behind real time, have to add a cycle to slow down and get back in sync.
+                                                                       AddCycle = FALSE;
+                                                                       RemoveCycle = TRUE;
+                                                                       }
+                                                               else
+                                                                       {       // Else clause of "if  (ExpectedRunningDifference < SecondsRunningDifference)"
+                                                                       if  (ExpectedRunningDifference < SecondsRunningDifference)
+                                                                               {
+                                                                               if  (Debug)
+                                                                                       printf ("> ExpectedRunningDifference < SecondsRunningDifference, running ahead of real time.\n");
+
+                                                                               // Ahead of real time, have to remove a cycle to speed up and get back in sync.
+                                                                               AddCycle = TRUE;
+                                                                               RemoveCycle = FALSE;
+                                                                               }
+                                                                       else
+                                                                               {
+                                                                               if  (Debug)
+                                                                                       printf ("> Oops, outside tolerances, but doesn't fit the profiles, how can this be?\n");
+                                                                               }
+                                                                       }       // End of else clause of "if  (ExpectedRunningDifference > SecondsRunningDifference)"
+                                                               }       // End of else clause of "if  ((ExpectedRunningDifference...SecondsRunningDifference)"
+                                                       }       // End of else clause of "if  (RemoveCycle)".
+                                               }       // End of else clause of "if  (AddCycle)".
+                                       }       // End of else clause for "if  (StabilityCount < MINIMUM_STABILITY_COUNT))"
+                               }       // End of true clause for "if  ((SecondsRunningSimulationTime > RUN_BEFORE_STABILITY_CHECK)"
+                       }       // End of true clause for "if  (NowRealTime >= BaseRealTime)"
+               else
+                       {
+                       if  (Debug)
+                               printf ("> Hmm, time going backwards?\n");
+                       }
+               }       // End of true clause for "if  (EnableRateCorrection)"
+               
+       fflush (stdout);
+       }
+       
+       
+printf ("\n\n>> Completed %d seconds, exiting...\n\n", SecondsToSend);
+return (0);
+}
+
+
+/*
+ * Generate WWV/H 0 or 1 data pulse.
+ */
+void WWV_Second(
+       int     code,           /* DATA0, DATA1, PI */
+       int Rate                /* <0 -> do a short second, 0 -> normal second, >0 -> long second */
+       )
+{
+       /*
+        * The WWV data pulse begins with 5 ms of 1000 Hz follwed by a
+        * guard time of 25 ms. The data pulse is 170, 570 or 770 ms at
+        * 100 Hz corresponding to 0, 1 or position indicator (PI),
+        * respectively. Note the 100-Hz data pulses are transmitted 6
+        * dB below the 1000-Hz sync pulses. Originally the data pulses
+        * were transmited 10 dB below the sync pulses, but the station
+        * engineers increased that to 6 dB because the Heath GC-1000
+        * WWV/H radio clock worked much better.
+        */
+       peep(5, tone, HIGH);            /* send seconds tick */
+       peep(25, tone, OFF);
+       peep(code - 30, 100, LOW);      /* send data */
+       
+       /* The quiet time is shortened or lengthened to get us back on time */
+       if  (Rate < 0)
+               {
+               peep( 990 - code, 100, OFF);
+               
+               TotalCyclesRemoved += 10;
+
+               if  (Debug)
+                       printf ("\n* Shorter Second: ");
+               }
+       else
+               {
+               if  (Rate > 0)
+                       {
+                       peep(1010 - code, 100, OFF);
+
+                       TotalCyclesAdded += 10;
+
+                       if  (Debug)
+                               printf ("\n* Longer Second: ");
+                       }
+               else
+                       peep(1000 - code, 100, OFF);
+               }
+}
+
+/*
+ * Generate WWV/H 0 or 1 data pulse, with no tick, for 29th and 59th seconds
+ */
+void WWV_SecondNoTick(
+       int     code,           /* DATA0, DATA1, PI */
+       int Rate                /* <0 -> do a short second, 0 -> normal second, >0 -> long second */
+       )
+{
+       /*
+        * The WWV data pulse begins with 5 ms of 1000 Hz follwed by a
+        * guard time of 25 ms. The data pulse is 170, 570 or 770 ms at
+        * 100 Hz corresponding to 0, 1 or position indicator (PI),
+        * respectively. Note the 100-Hz data pulses are transmitted 6
+        * dB below the 1000-Hz sync pulses. Originally the data pulses
+        * were transmited 10 dB below the sync pulses, but the station
+        * engineers increased that to 6 dB because the Heath GC-1000
+        * WWV/H radio clock worked much better.
+        */
+       peep(30, tone, OFF);            /* send seconds non-tick */
+       peep(code - 30, 100, LOW);      /* send data */
+
+       /* The quiet time is shortened or lengthened to get us back on time */
+       if  (Rate < 0)
+               {
+               peep( 990 - code, 100, OFF);
+
+               TotalCyclesRemoved += 10;
+
+               if  (Debug)
+                       printf ("\n* Shorter Second: ");
+               }
+       else
+               {
+               if  (Rate > 0)
+                       {
+                       peep(1010 - code, 100, OFF);
+
+                       TotalCyclesAdded += 10;
+
+                       if  (Debug)
+                               printf ("\n* Longer Second: ");
+                       }
+               else
+                       peep(1000 - code, 100, OFF);
+               }
+}
+
+/*
+ * Generate cycles of 100 Hz or any multiple of 100 Hz.
+ */
+void peep(
+       int     pulse,          /* pulse length (ms) */
+       int     freq,           /* frequency (Hz) */
+       int     amp             /* amplitude */
+       )
+{
+       int     increm;         /* phase increment */
+       int     i, j;
+
+       if (amp == OFF || freq == 0)
+               increm = 10;
+       else
+               increm = freq / 100;
+       j = 0;
+       for (i = 0 ; i < pulse * 8; i++) {
+               switch (amp) {
+
+               case HIGH:
+                       buffer[bufcnt++] = ~c6000[j];
+                       break;
+
+               case LOW:
+                       buffer[bufcnt++] = ~c3000[j];
+                       break;
+
+               default:
+                       buffer[bufcnt++] = ~0;
+               }
+               if (bufcnt >= BUFLNG) {
+                       write(fd, buffer, BUFLNG);
+                       bufcnt = 0;
+               }
+               j = (j + increm) % 80;
+       }
+}
+
+
+/*
+ * Generate unmodulated from similar tables.
+ */
+void poop(
+       int     pulse,          /* pulse length (ms) */
+       int     freq,           /* frequency (Hz) */
+       int     amp,            /* amplitude */
+       int inverted    /* is upside down */
+       )
+{
+       int     increm;         /* phase increment */
+       int     i, j;
+
+       if (amp == OFF || freq == 0)
+               increm = 10;
+       else
+               increm = freq / 100;
+       j = 0;
+       for (i = 0 ; i < pulse * 8; i++) {
+               switch (amp) {
+
+               case HIGH:
+                       if  (inverted)
+                               buffer[bufcnt++] = ~u3000[j];
+                       else
+                               buffer[bufcnt++] = ~u6000[j];
+                       break;
+
+               case LOW:
+                       if  (inverted)
+                               buffer[bufcnt++] = ~u6000[j];
+                       else
+                               buffer[bufcnt++] = ~u3000[j];
+                       break;
+
+               default:
+                       buffer[bufcnt++] = ~0;
+               }
+               if (bufcnt >= BUFLNG) {
+                       write(fd, buffer, BUFLNG);
+                       bufcnt = 0;
+               }
+               j = (j + increm) % 80;
+       }
+}
+
+/*
+ * Delay for initial phasing
+ */
+void delay (
+       int     Delay           /* delay in samples */
+       )
+{
+       int     samples;        /* samples remaining */
+
+       samples = Delay;
+       memset(buffer, 0, BUFLNG);
+       while (samples >= BUFLNG) {
+               write(fd, buffer, BUFLNG);
+               samples -= BUFLNG;
+       }
+               write(fd, buffer, samples);
+}
+
+
+/* Calc day of year from year month & day */
+/* Year - 0 means 2000, 100 means 2100. */
+/* Month - 1 means January, 12 means December. */
+/* DayOfMonth - 1 is first day of month */
+int
+ConvertMonthDayToDayOfYear (int YearValue, int MonthValue, int DayOfMonthValue)
+       {
+       int     ReturnValue;
+       int     LeapYear;
+       int     MonthCounter;
+
+       /* Array of days in a month.  Note that here January is zero. */
+       /* NB: have to add 1 to days in February in a leap year! */
+       int DaysInMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+
+       LeapYear = FALSE;
+       if  ((YearValue % 4) == 0)
+               {
+               if  ((YearValue % 100) == 0)
+                       {
+                       if  ((YearValue % 400) == 0)
+                               {
+                               LeapYear = TRUE;
+                               }
+                       }
+               else
+                       {
+                       LeapYear = TRUE;
+                       }
+               }
+
+       if  (Debug)
+               printf ("\nConvertMonthDayToDayOfYear(): Year %d %s a leap year.\n", YearValue+2000, LeapYear ? "is" : "is not");
+
+       /* Day of month given us starts in this algorithm. */
+       ReturnValue = DayOfMonthValue;
+
+       /* Add in days in month for each month past January. */
+       for (MonthCounter=1; MonthCounter<MonthValue; MonthCounter++)
+               {
+               ReturnValue += DaysInMonth [ MonthCounter - 1 ];
+               }
+
+       /* Add a day for leap years where we are past February. */
+       if  ((LeapYear) && (MonthValue > 2))
+               {
+               ReturnValue++;
+               }
+
+       if  (Debug)
+               printf ("\nConvertMonthDayToDayOfYear(): %4.4d-%2.2d-%2.2d represents day %3d of year.\n",
+                               YearValue+2000, MonthValue, DayOfMonthValue, ReturnValue);
+
+       return (ReturnValue);
+       }
+
+
+void
+Help ( void )
+       {
+       printf ("\n\nTime Code Generation - IRIG-B or WWV, v%d.%d, %s dmw", VERSION, ISSUE, ISSUE_DATE);
+       printf ("\n\nRCS Info:");
+       printf (  "\n  $Header: /home/dmw/src/IRIG_generation/ntp-4.2.2p3/util/RCS/tg.c,v 1.28 2007/02/12 23:57:45 dmw Exp $");
+       printf ("\n\nUsage: %s [option]*", CommandName);
+       printf ("\n\nOptions: -a device_name                 Output audio device name (default /dev/audio)");
+       printf (  "\n         -b yymmddhhmm                  Remove leap second at end of minute specified");
+       printf (  "\n         -c seconds_to_send             Number of seconds to send (default 0 = forever)");
+       printf (  "\n         -d                             Start with IEEE 1344 DST active");
+       printf (  "\n         -f format_type                 i = Modulated IRIG-B 1998 (no year coded)");
+       printf (  "\n                                        2 = Modulated IRIG-B 2002 (year coded)");
+       printf (  "\n                                        3 = Modulated IRIG-B w/IEEE 1344 (year & control funcs) (default)");
+       printf (  "\n                                        4 = Unmodulated IRIG-B w/IEEE 1344 (year & control funcs)");
+       printf (  "\n                                        5 = Inverted unmodulated IRIG-B w/IEEE 1344 (year & control funcs)");
+       printf (  "\n                                        w = WWV(H)");
+       printf (  "\n         -g yymmddhhmm                  Switch into/out of DST at beginning of minute specified");
+       printf (  "\n         -i yymmddhhmm                  Insert leap second at end of minute specified");
+       printf (  "\n         -j                             Disable time rate correction against system clock (default enabled)");
+       printf (  "\n         -k nn                          Force rate correction for testing (+1 = add cycle, -1 = remove cycle)");
+       printf (  "\n         -l time_offset                 Set offset of time sent to UTC as per computer, +/- float hours");
+       printf (  "\n         -o time_offset                 Set IEEE 1344 time offset, +/-, to 0.5 hour (default 0)");
+       printf (  "\n         -q quality_code_hex            Set IEEE 1344 quality code (default 0)");
+       printf (  "\n         -r sample_rate                 Audio sample rate (default 8000)");
+       printf (  "\n         -s                             Set leap warning bit (WWV[H] only)");
+       printf (  "\n         -t sync_frequency              WWV(H) on-time pulse tone frequency (default 1200)");
+       printf (  "\n         -u DUT1_offset                 Set WWV(H) DUT1 offset -7 to +7 (default 0)");
+#ifndef  HAVE_SYS_SOUNDCARD_H
+       printf (  "\n         -v initial_output_level        Set initial output level (default %d, must be 0 to 255)", AUDIO_MAX_GAIN/8);
+#endif
+       printf (  "\n         -x                             Turn off verbose output (default on)");
+       printf (  "\n         -y yymmddhhmmss                Set initial date and time as specified (default system time)");
+       printf ("\n\nThis software licenced under the GPL, modifications performed 2006 & 2007 by Dean Weiten");
+       printf (  "\nContact: Dean Weiten, Norscan Instruments Ltd., Winnipeg, MB, Canada, ph (204)-233-9138, E-mail dmw@norscan.com");
+       printf ("\n\n");
+       }
+
+/* Reverse string order for nicer print. */
+void
+ReverseString(char *str)
+       {
+       int             StringLength;
+       int             IndexCounter;
+       int             CentreOfString;
+       char    TemporaryCharacter;
+
+
+       StringLength    = strlen(str);
+       CentreOfString  = (StringLength/2)+1;
+       for (IndexCounter = StringLength; IndexCounter >= CentreOfString; IndexCounter--)
+               {
+               TemporaryCharacter                              = str[IndexCounter-1];
+               str[IndexCounter-1]                             = str[StringLength-IndexCounter];
+               str[StringLength-IndexCounter]  = TemporaryCharacter;
+               }
+       }
+