Home | History | Annotate | Line # | Download | only in util
tg2.c revision 1.4.14.1
      1 /*	$NetBSD: tg2.c,v 1.4.14.1 2018/09/30 01:45:29 pgoyette Exp $	*/
      2 
      3 /*
      4  * tg.c generate WWV or IRIG signals for test
      5  */
      6 /*
      7  * This program can generate audio signals that simulate the WWV/H
      8  * broadcast timecode. Alternatively, it can generate the IRIG-B
      9  * timecode commonly used to synchronize laboratory equipment. It is
     10  * intended to test the WWV/H driver (refclock_wwv.c) and the IRIG
     11  * driver (refclock_irig.c) in the NTP driver collection.
     12  *
     13  * Besides testing the drivers themselves, this program can be used to
     14  * synchronize remote machines over audio transmission lines or program
     15  * feeds. The program reads the time on the local machine and sets the
     16  * initial epoch of the signal generator within one millisecond.
     17  * Alernatively, the initial epoch can be set to an arbitrary time. This
     18  * is useful when searching for bugs and testing for correct response to
     19  * a leap second in UTC. Note however, the ultimate accuracy is limited
     20  * by the intrinsic frequency error of the codec sample clock, which can
     21  # reach well over 100 PPM.
     22  *
     23  * The default is to route generated signals to the line output
     24  * jack; the s option on the command line routes these signals to the
     25  * internal speaker as well. The v option controls the speaker volume
     26  * over the range 0-255. The signal generator by default uses WWV
     27  * format; the h option switches to WWVH format and the i option
     28  * switches to IRIG-B format.
     29  *
     30  * Once started the program runs continuously. The default initial epoch
     31  * for the signal generator is read from the computer system clock when
     32  * the program starts. The y option specifies an alternate epoch using a
     33  * string yydddhhmmss, where yy is the year of century, ddd the day of
     34  * year, hh the hour of day and mm the minute of hour. For instance,
     35  * 1946Z on 1 January 2006 is 060011946. The l option lights the leap
     36  * warning bit in the WWV/H timecode, so is handy to check for correct
     37  * behavior at the next leap second epoch. The remaining options are
     38  * specified below under the Parse Options heading. Most of these are
     39  * for testing.
     40  *
     41  * During operation the program displays the WWV/H timecode (9 digits)
     42  * or IRIG timecode (20 digits) as each new string is constructed. The
     43  * display is followed by the BCD binary bits as transmitted. Note that
     44  * the transmissionorder is low-order first as the frame is processed
     45  * left to right. For WWV/H The leap warning L preceeds the first bit.
     46  * For IRIG the on-time marker M preceeds the first (units) bit, so its
     47  * code is delayed one bit and the next digit (tens) needs only three
     48  * bits.
     49  *
     50  * The program has been tested with the Sun Blade 1500 running Solaris
     51  * 10, but not yet with other machines. It uses no special features and
     52  * should be readily portable to other hardware and operating systems.
     53  *
     54  * $Log: tg2.c,v $
     55  * Revision 1.4.14.1  2018/09/30 01:45:29  pgoyette
     56  * Ssync with HEAD
     57  *
     58  * Revision 1.5  2018/09/29 21:52:35  christos
     59  * merge conflicts
     60  *
     61  * Revision 1.1.1.6  2018/09/29 17:28:38  christos
     62  * ---
     63  * (4.2.8p12) 2018/08/14 Released by Harlan Stenn <stenn (at) ntp.org>
     64  *
     65  * * [Sec 3505] CVE-2018-12327 - Arbitrary Code Execution Vulnerability
     66  *   - fixed stack buffer overflow in the openhost() command-line call
     67  *     of NTPQ/NTPDC <perlinger (at) ntp.org>
     68  * * [Sec 3012] noepeer tweaks.  <stenn (at) ntp.org>
     69  * * [Bug 3521] Fix a logic bug in the INVALIDNAK checks.  <stenn (at) ntp.org>
     70  * * [Bug 3509] Add support for running as non-root on FreeBSD, Darwin,
     71  *              other TrustedBSD platforms
     72  *   - applied patch by Ian Lepore <perlinger (at) ntp.org>
     73  * * [Bug 3506] Service Control Manager interacts poorly with NTPD <perlinger (at) ntp.org>
     74  *   - changed interaction with SCM to signal pending startup
     75  * * [Bug 3486] Buffer overflow in ntpq/ntpq.c:tstflags() <perlinger (at) ntp.org>
     76  *   - applied patch by Gerry Garvey
     77  * * [Bug 3485] Undefined sockaddr used in error messages in ntp_config.c <perlinger (at) ntp.org>
     78  *   - applied patch by Gerry Garvey
     79  * * [Bug 3484] ntpq response from ntpd is incorrect when REFID is null <perlinger (at) ntp.org>
     80  *   - rework of ntpq 'nextvar()' key/value parsing
     81  * * [Bug 3482] Fixes for compilation warnings (ntp_io.c & ntpq-subs.c) <perlinger (at) ntp.org>
     82  *   - applied patch by Gerry Garvey (with mods)
     83  * * [Bug 3480] Refclock sample filter not cleared on clock STEP <perlinger (at) ntp.org>
     84  *   - applied patch by Gerry Garvey
     85  * * [Bug 3479] ctl_putrefid() allows unsafe characters through to ntpq <perlinger (at) ntp.org>
     86  *   - applied patch by Gerry Garvey (with mods)
     87  * * [Bug 3476]ctl_putstr() sends empty unquoted string [...] <perlinger (at) ntp.org>
     88  *   - applied patch by Gerry Garvey (with mods); not sure if that's bug or feature, though
     89  * * [Bug 3475] modify prettydate() to suppress output of zero time <perlinger (at) ntp.org>
     90  *   - applied patch by Gerry Garvey
     91  * * [Bug 3474] Missing pmode in mode7 peer info response <perlinger (at) ntp.org>
     92  *   - applied patch by Gerry Garvey
     93  * * [Bug 3471] Check for openssl/[ch]mac.h.  HStenn.
     94  *   - add #define ENABLE_CMAC support in configure.  HStenn.
     95  * * [Bug 3470] ntpd4.2.8p11 fails to compile without OpenSSL <perlinger (at) ntp.org>
     96  * * [Bug 3469] Incomplete string compare [...] in is_refclk_addr <perlinger (at) ntp.org>
     97  *   - patch by Stephen Friedl
     98  * * [Bug 3467] Potential memory fault in ntpq [...] <perlinger (at) ntp.org>
     99  *   - fixed IO redirection and CTRL-C handling in ntq and ntpdc
    100  * * [Bug 3465] Default TTL values cannot be used <perlinger (at) ntp.org>
    101  * * [Bug 3461] refclock_shm.c: clear error status on clock recovery <perlinger (at) ntp.org>
    102  *   - initial patch by Hal Murray; also fixed refclock_report() trouble
    103  * * [Bug 3460] Fix typo in ntpq.texi, reported by Kenyon Ralph.  <stenn (at) ntp.org>
    104  * * [Bug 3456] Use uintptr_t rather than size_t to store an integer in a pointer
    105  *   - According to Brooks Davis, there was only one location <perlinger (at) ntp.org>
    106  * * [Bug 3449] ntpq - display "loop" instead of refid [...] <perlinger (at) ntp.org>
    107  *   - applied patch by Gerry Garvey
    108  * * [Bug 3445] Symmetric peer won't sync on startup <perlinger (at) ntp.org>
    109  *   - applied patch by Gerry Garvey
    110  * * [Bug 3442] Fixes for ntpdate as suggested by Gerry Garvey,
    111  *   with modifications
    112  *   New macro REFID_ISTEXT() which is also used in ntpd/ntp_control.c.
    113  * * [Bug 3434] ntpd clears STA_UNSYNC on start <perlinger (at) ntp.org>
    114  *   - applied patch by Miroslav Lichvar
    115  * * [Bug 3426] ntpdate.html -t default is 2 seconds.  Leonid Evdokimov.
    116  * * [Bug 3121] Drop root privileges for the forked DNS worker <perlinger (at) ntp.org>
    117  *   - integrated patch by  Reinhard Max
    118  * * [Bug 2821] minor build issues <perlinger (at) ntp.org>
    119  *   - applied patches by Christos Zoulas, including real bug fixes
    120  * * html/authopt.html: cleanup, from <stenn (at) ntp.org>
    121  * * ntpd/ntpd.c: DROPROOT cleanup.  <stenn (at) ntp.org>
    122  * * Symmetric key range is 1-65535.  Update docs.  <stenn (at) ntp.org>
    123  * * html/authentic.html: cleanup, from <stenn (at) ntp.org>
    124  *
    125  * Revision 1.28  2007/02/12 23:57:45  dmw
    126  * v0.23 2007-02-12 dmw:
    127  * - Changed statistics to include calculated error
    128  *   of frequency, based on number of added or removed
    129  *   cycles over time.
    130  *
    131  * Revision 1.27  2007/02/09 02:28:59  dmw
    132  * v0.22 2007-02-08 dmw:
    133  * - Changed default for rate correction to "enabled", "-j" switch now disables.
    134  * - Adjusted help message accordingly.
    135  * - Added "2007" to modifications note at end of help message.
    136  *
    137  * Revision 1.26  2007/02/08 03:36:17  dmw
    138  * v0.21 2007-02-07 dmw:
    139  * - adjusted strings for shorten and lengthen to make
    140  *   fit on smaller screen.
    141  *
    142  * Revision 1.25  2007/02/01 06:08:09  dmw
    143  * v0.20 2007-02-01 dmw:
    144  * - Added periodic display of running time along with legend on IRIG-B, allows tracking how
    145  *   close IRIG output is to actual clock time.
    146  *
    147  * Revision 1.24  2007/01/31 19:24:11  dmw
    148  * v0.19 2007-01-31 dmw:
    149  * - Added tracking of how many seconds have been adjusted,
    150  *   how many cycles added (actually in milliseconds), how
    151  *   many cycles removed, print periodically if verbose is
    152  *   active.
    153  * - Corrected lack of lengthen or shorten of minute & hour
    154  *   pulses for WWV format.
    155  *
    156  * Revision 1.23  2007/01/13 07:09:12  dmw
    157  * v0.18 2007-01-13 dmw:
    158  * - added -k option, which allows force of long or short
    159  *   cycles, to test against IRIG-B decoder.
    160  *
    161  * Revision 1.22  2007/01/08 16:27:23  dmw
    162  * v0.17 2007-01-08 dmw:
    163  * - Changed -j option to **enable** rate correction, not disable.
    164  *
    165  * Revision 1.21  2007/01/08 06:22:36  dmw
    166  * v0.17 2007-01-08 dmw:
    167  * - Run stability check versus ongoing system clock (assume NTP correction)
    168  *   and adjust time code rate to try to correct, if gets too far out of sync.
    169  *   Disable this algorithm with -j option.
    170  *
    171  * Revision 1.20  2006/12/19 04:59:04  dmw
    172  * v0.16 2006-12-18 dmw
    173  * - Corrected print of setting of output frequency, always
    174  *   showed 8000 samples/sec, now as specified on command line.
    175  * - Modified to reflect new employer Norscan.
    176  *
    177  * Revision 1.19  2006/12/19 03:45:38  dmw
    178  * v0.15 2006-12-18 dmw:
    179  * - Added count of number of seconds to output then exit,
    180  *   default zero for forever.
    181  *
    182  * Revision 1.18  2006/12/18 05:43:36  dmw
    183  * v0.14 2006-12-17 dmw:
    184  * - Corrected WWV(H) signal to leave "tick" sound off of 29th and 59th second of minute.
    185  * - Adjusted verbose output format for WWV(H).
    186  *
    187  * Revision 1.17  2006/12/18 02:31:33  dmw
    188  * v0.13 2006-12-17 dmw:
    189  * - Put SPARC code back in, hopefully will work, but I don't have
    190  *   a SPARC to try it on...
    191  * - Reworked Verbose mode, different flag to initiate (x not v)
    192  *   and actually implement turn off of verbosity when this flag used.
    193  * - Re-claimed v flag for output level.
    194  * - Note that you must define OSS_MODS to get OSS to compile,
    195  *   otherwise will expect to compile using old SPARC options, as
    196  *   it used to be.
    197  *
    198  * Revision 1.16  2006/10/26 19:08:43  dmw
    199  * v0.12 2006-10-26 dmw:
    200  * - Reversed output binary dump for IRIG, makes it easier to read the numbers.
    201  *
    202  * Revision 1.15  2006/10/24 15:57:09  dmw
    203  * v0.11 2006-10-24 dmw:
    204  * - another tweak.
    205  *
    206  * Revision 1.14  2006/10/24 15:55:53  dmw
    207  * v0.11 2006-10-24 dmw:
    208  * - Curses a fix to the fix to the fix of the usaeg.
    209  *
    210  * Revision 1.13  2006/10/24 15:53:25  dmw
    211  * v0.11 (still) 2006-10-24 dmw:
    212  * - Messed with usage message that's all.
    213  *
    214  * Revision 1.12  2006/10/24 15:50:05  dmw
    215  * v0.11 2006-10-24 dmw:
    216  * - oops, needed to note "hours" in usage of that offset.
    217  *
    218  * Revision 1.11  2006/10/24 15:49:09  dmw
    219  * v0.11 2006-10-24 dmw:
    220  * - Added ability to offset actual time sent, from the UTC time
    221  *   as per the computer.
    222  *
    223  * Revision 1.10  2006/10/24 03:25:55  dmw
    224  * v0.10 2006-10-23 dmw:
    225  * - Corrected polarity of correction of offset when going into or out of DST.
    226  * - Ensure that zero offset is always positive (pet peeve).
    227  *
    228  * Revision 1.9  2006/10/24 00:00:35  dmw
    229  * v0.9 2006-10-23 dmw:
    230  * - Shift time offset when DST in or out.
    231  *
    232  * Revision 1.8  2006/10/23 23:49:28  dmw
    233  * v0.8 2006-10-23 dmw:
    234  * - made offset of zero default positive.
    235  *
    236  * Revision 1.7  2006/10/23 23:44:13  dmw
    237  * v0.7 2006-10-23 dmw:
    238  * - Added unmodulated and inverted unmodulated output.
    239  *
    240  * Revision 1.6  2006/10/23 18:10:37  dmw
    241  * v0.6 2006-10-23 dmw:
    242  * - Cleaned up usage message.
    243  * - Require at least one option, or prints usage message and exits.
    244  *
    245  * Revision 1.5  2006/10/23 16:58:10  dmw
    246  * v0.5 2006-10-23 dmw:
    247  * - Finally added a usage message.
    248  * - Added leap second pending and DST change pending into IEEE 1344.
    249  * - Default code type is now IRIG-B with IEEE 1344.
    250  *
    251  * Revision 1.4  2006/10/23 03:27:25  dmw
    252  * v0.4 2006-10-22 dmw:
    253  * - Added leap second addition and deletion.
    254  * - Added DST changing forward and backward.
    255  * - Changed date specification to more conventional year, month, and day of month
    256  *   (rather than day of year).
    257  *
    258  * Revision 1.3  2006/10/22 21:04:12  dmw
    259  * v0.2 2006-10-22 dmw:
    260  * - Corrected format of legend line.
    261  *
    262  * Revision 1.2  2006/10/22 21:01:07  dmw
    263  * v0.1 2006-10-22 dmw:
    264  * - Added some more verbose output (as is my style)
    265  * - Corrected frame format - there were markers in the
    266  *   middle of frames, now correctly as "zero" bits.
    267  * - Added header line to show fields of output.
    268  * - Added straight binary seconds, were not implemented
    269  *   before.
    270  * - Added IEEE 1344 with parity.
    271  *
    272  *
    273  */
    274 #include <stdio.h>
    275 #include <stdlib.h>
    276 #include <time.h>
    277 
    278 #ifdef  HAVE_CONFIG_H
    279 #include "config.h"
    280 #undef VERSION		/* avoid conflict below */
    281 #endif
    282 
    283 #ifdef  HAVE_SYS_SOUNDCARD_H
    284 #include <sys/soundcard.h>
    285 #else
    286 # ifdef HAVE_SYS_AUDIOIO_H
    287 # include <sys/audioio.h>
    288 # else
    289 # include <sys/audio.h>
    290 # endif
    291 #endif
    292 
    293 #include "ntp_stdlib.h"	/* for strlcat(), strlcpy() */
    294 
    295 #include <math.h>
    296 #include <errno.h>
    297 #include <sys/types.h>
    298 #include <sys/stat.h>
    299 #include <fcntl.h>
    300 #include <string.h>
    301 #include <unistd.h>
    302 #include <ctype.h>
    303 #include <sys/ioctl.h>
    304 #include <sys/time.h>
    305 
    306 #define VERSION		(0)
    307 #define	ISSUE		(23)
    308 #define	ISSUE_DATE	"2007-02-12"
    309 
    310 #define	SECOND	(8000)			/* one second of 125-us samples */
    311 #define BUFLNG	(400)			/* buffer size */
    312 #define	DEVICE	"/dev/audio"	/* default audio device */
    313 #define	WWV		(0)				/* WWV encoder */
    314 #define	IRIG	(1)				/* IRIG-B encoder */
    315 #define	OFF		(0)				/* zero amplitude */
    316 #define	LOW		(1)				/* low amplitude */
    317 #define	HIGH	(2)				/* high amplitude */
    318 #define	DATA0	(200)			/* WWV/H 0 pulse */
    319 #define	DATA1	(500)			/* WWV/H 1 pulse */
    320 #define PI		(800)			/* WWV/H PI pulse */
    321 #define	M2		(2)				/* IRIG 0 pulse */
    322 #define	M5		(5)				/* IRIG 1 pulse */
    323 #define	M8		(8)				/* IRIG PI pulse */
    324 
    325 #define	NUL		(0)
    326 
    327 #define	SECONDS_PER_MINUTE	(60)
    328 #define SECONDS_PER_HOUR	(3600)
    329 
    330 #define	OUTPUT_DATA_STRING_LENGTH	(200)
    331 
    332 /* Attempt at unmodulated - "high" */
    333 int u6000[] = {
    334 	247, 247, 247, 247, 247, 247, 247, 247, 247, 247,	/*  0- 9 */
    335     247, 247, 247, 247, 247, 247, 247, 247, 247, 247,	/* 10-19 */
    336     247, 247, 247, 247, 247, 247, 247, 247, 247, 247,	/* 20-29 */
    337     247, 247, 247, 247, 247, 247, 247, 247, 247, 247,	/* 30-39 */
    338     247, 247, 247, 247, 247, 247, 247, 247, 247, 247,	/* 40-49 */
    339     247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 	/* 50-59 */
    340     247, 247, 247, 247, 247, 247, 247, 247, 247, 247,	/* 60-69 */
    341     247, 247, 247, 247, 247, 247, 247, 247, 247, 247}; 	/* 70-79 */
    342 
    343 /* Attempt at unmodulated - "low" */
    344 int u3000[] = {
    345 	119, 119, 119, 119, 119, 119, 119, 119, 119, 119,	/*  0- 9 */
    346     119, 119, 119, 119, 119, 119, 119, 119, 119, 119,	/* 10-19 */
    347     119, 119, 119, 119, 119, 119, 119, 119, 119, 119,	/* 20-29 */
    348     119, 119, 119, 119, 119, 119, 119, 119, 119, 119,	/* 30-39 */
    349     119, 119, 119, 119, 119, 119, 119, 119, 119, 119,	/* 40-49 */
    350     119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 	/* 50-59 */
    351     119, 119, 119, 119, 119, 119, 119, 119, 119, 119,	/* 60-69 */
    352     119, 119, 119, 119, 119, 119, 119, 119, 119, 119}; 	/* 70-79 */
    353 
    354 /*
    355  * Companded sine table amplitude 3000 units
    356  */
    357 int c3000[] = {1, 48, 63, 70, 78, 82, 85, 89, 92, 94,	/* 0-9 */
    358      96,  98,  99, 100, 101, 101, 102, 103, 103, 103,	/* 10-19 */
    359     103, 103, 103, 103, 102, 101, 101, 100,  99,  98,	/* 20-29 */
    360      96,  94,  92,  89,  85,  82,  78,  70,  63,  48,	/* 30-39 */
    361     129, 176, 191, 198, 206, 210, 213, 217, 220, 222,	/* 40-49 */
    362     224, 226, 227, 228, 229, 229, 230, 231, 231, 231, 	/* 50-59 */
    363     231, 231, 231, 231, 230, 229, 229, 228, 227, 226,	/* 60-69 */
    364     224, 222, 220, 217, 213, 210, 206, 198, 191, 176}; 	/* 70-79 */
    365 /*
    366  * Companded sine table amplitude 6000 units
    367  */
    368 int c6000[] = {1, 63, 78, 86, 93, 98, 101, 104, 107, 110, /* 0-9 */
    369     112, 113, 115, 116, 117, 117, 118, 118, 119, 119,	/* 10-19 */
    370     119, 119, 119, 118, 118, 117, 117, 116, 115, 113,	/* 20-29 */
    371     112, 110, 107, 104, 101,  98,  93,  86,  78,  63,	/* 30-39 */
    372     129, 191, 206, 214, 221, 226, 229, 232, 235, 238,	/* 40-49 */
    373     240, 241, 243, 244, 245, 245, 246, 246, 247, 247, 	/* 50-59 */
    374     247, 247, 247, 246, 246, 245, 245, 244, 243, 241,	/* 60-69 */
    375     240, 238, 235, 232, 229, 226, 221, 214, 206, 191}; 	/* 70-79 */
    376 
    377 /*
    378  * Decoder operations at the end of each second are driven by a state
    379  * machine. The transition matrix consists of a dispatch table indexed
    380  * by second number. Each entry in the table contains a case switch
    381  * number and argument.
    382  */
    383 struct progx {
    384 	int sw;			/* case switch number */
    385 	int arg;		/* argument */
    386 };
    387 
    388 /*
    389  * Case switch numbers
    390  */
    391 #define DATA	(0)		/* send data (0, 1, PI) */
    392 #define COEF	(1)		/* send BCD bit */
    393 #define	DEC		(2)		/* decrement to next digit and send PI */
    394 #define	MIN		(3)		/* minute pulse */
    395 #define	LEAP	(4)		/* leap warning */
    396 #define	DUT1	(5)		/* DUT1 bits */
    397 #define	DST1	(6)		/* DST1 bit */
    398 #define	DST2	(7)		/* DST2 bit */
    399 #define DECZ	(8)		/* decrement to next digit and send zero */
    400 #define DECC	(9)		/* decrement to next digit and send bit */
    401 #define NODEC	(10)	/* no decerement to next digit, send PI */
    402 #define DECX	(11)	/* decrement to next digit, send PI, but no tick */
    403 #define DATAX	(12)	/* send data (0, 1, PI), but no tick */
    404 
    405 /*
    406  * WWV/H format (100-Hz, 9 digits, 1 m frame)
    407  */
    408 struct progx progx[] = {
    409 	{MIN,	800},		/* 0 minute sync pulse */
    410 	{DATA,	DATA0},		/* 1 */
    411 	{DST2,	0},		/* 2 DST2 */
    412 	{LEAP,	0},		/* 3 leap warning */
    413 	{COEF,	1},		/* 4 1 year units */
    414 	{COEF,	2},		/* 5 2 */
    415 	{COEF,	4},		/* 6 4 */
    416 	{COEF,	8},		/* 7 8 */
    417 	{DEC,	DATA0},		/* 8 */
    418 	{DATA,	PI},		/* 9 p1 */
    419 	{COEF,	1},		/* 10 1 minute units */
    420 	{COEF,	2},		/* 11 2 */
    421 	{COEF,	4},		/* 12 4 */
    422 	{COEF,	8},		/* 13 8 */
    423 	{DEC,	DATA0},		/* 14 */
    424 	{COEF,	1},		/* 15 10 minute tens */
    425 	{COEF,	2},		/* 16 20 */
    426 	{COEF,	4},		/* 17 40 */
    427 	{COEF,	8},		/* 18 80 (not used) */
    428 	{DEC,	PI},		/* 19 p2 */
    429 	{COEF,	1},		/* 20 1 hour units */
    430 	{COEF,	2},		/* 21 2 */
    431 	{COEF,	4},		/* 22 4 */
    432 	{COEF,	8},		/* 23 8 */
    433 	{DEC,	DATA0},		/* 24 */
    434 	{COEF,	1},		/* 25 10 hour tens */
    435 	{COEF,	2},		/* 26 20 */
    436 	{COEF,	4},		/* 27 40 (not used) */
    437 	{COEF,	8},		/* 28 80 (not used) */
    438 	{DECX,	PI},		/* 29 p3 */
    439 	{COEF,	1},		/* 30 1 day units */
    440 	{COEF,	2},		/* 31 2 */
    441 	{COEF,	4},		/* 32 4 */
    442 	{COEF,	8},		/* 33 8 */
    443 	{DEC,	DATA0},		/* 34 not used */
    444 	{COEF,	1},		/* 35 10 day tens */
    445 	{COEF,	2},		/* 36 20 */
    446 	{COEF,	4},		/* 37 40 */
    447 	{COEF,	8},		/* 38 80 */
    448 	{DEC,	PI},		/* 39 p4 */
    449 	{COEF,	1},		/* 40 100 day hundreds */
    450 	{COEF,	2},		/* 41 200 */
    451 	{COEF,	4},		/* 42 400 (not used) */
    452 	{COEF,	8},		/* 43 800 (not used) */
    453 	{DEC,	DATA0},		/* 44 */
    454 	{DATA,	DATA0},		/* 45 */
    455 	{DATA,	DATA0},		/* 46 */
    456 	{DATA,	DATA0},		/* 47 */
    457 	{DATA,	DATA0},		/* 48 */
    458 	{DATA,	PI},		/* 49 p5 */
    459 	{DUT1,	8},		/* 50 DUT1 sign */
    460 	{COEF,	1},		/* 51 10 year tens */
    461 	{COEF,	2},		/* 52 20 */
    462 	{COEF,	4},		/* 53 40 */
    463 	{COEF,	8},		/* 54 80 */
    464 	{DST1,	0},		/* 55 DST1 */
    465 	{DUT1,	1},		/* 56 0.1 DUT1 fraction */
    466 	{DUT1,	2},		/* 57 0.2 */
    467 	{DUT1,	4},		/* 58 0.4 */
    468 	{DATAX,	PI},		/* 59 p6 */
    469 	{DATA,	DATA0},		/* 60 leap */
    470 };
    471 
    472 /*
    473  * IRIG format frames (1000 Hz, 1 second for 10 frames of data)
    474  */
    475 
    476 /*
    477  * IRIG format frame 10 - MS straight binary seconds
    478  */
    479 struct progx progu[] = {
    480 	{COEF,	2},		/* 0 0x0 0200 seconds */
    481 	{COEF,	4},		/* 1 0x0 0400 */
    482 	{COEF,	8},		/* 2 0x0 0800 */
    483 	{DECC,	1},		/* 3 0x0 1000 */
    484 	{COEF,	2},		/* 4 0x0 2000 */
    485 	{COEF,	4},		/* 6 0x0 4000 */
    486 	{COEF,	8},		/* 7 0x0 8000 */
    487 	{DECC,	1},		/* 8 0x1 0000 */
    488 	{COEF,  2},     /* 9 0x2 0000 - but only 86,401 / 0x1 5181 seconds in a day, so always zero */
    489 	{NODEC,	M8},	/* 9 PI */
    490 };
    491 
    492 /*
    493  * IRIG format frame 8 - MS control functions
    494  */
    495 struct progx progv[] = {
    496 	{COEF,	2},		/*  0 CF # 19 */
    497 	{COEF,	4},		/*  1 CF # 20 */
    498 	{COEF,	8},		/*  2 CF # 21 */
    499 	{DECC,	1},		/*  3 CF # 22 */
    500 	{COEF,	2},		/*  4 CF # 23 */
    501 	{COEF,	4},		/*  6 CF # 24 */
    502 	{COEF,	8},		/*  7 CF # 25 */
    503 	{DECC,	1},		/*  8 CF # 26 */
    504 	{COEF,  2},		/*  9 CF # 27 */
    505 	{DEC,	M8},	/* 10 PI */
    506 };
    507 
    508 /*
    509  * IRIG format frames 7 & 9 - LS control functions & LS straight binary seconds
    510  */
    511 struct progx progw[] = {
    512 	{COEF,	1},		/*  0  CF # 10, 0x0 0001 seconds */
    513 	{COEF,	2},		/*  1  CF # 11, 0x0 0002 */
    514 	{COEF,	4},		/*  2  CF # 12, 0x0 0004 */
    515 	{COEF,	8},		/*  3  CF # 13, 0x0 0008 */
    516 	{DECC,	1},		/*  4  CF # 14, 0x0 0010 */
    517 	{COEF,	2},		/*  6  CF # 15, 0x0 0020 */
    518 	{COEF,	4},		/*  7  CF # 16, 0x0 0040 */
    519 	{COEF,	8},		/*  8  CF # 17, 0x0 0080 */
    520 	{DECC,  1},		/*  9  CF # 18, 0x0 0100 */
    521 	{NODEC,	M8},	/* 10  PI */
    522 };
    523 
    524 /*
    525  * IRIG format frames 2 to 6 - minutes, hours, days, hundreds days, 2 digit years (also called control functions bits 1-9)
    526  */
    527 struct progx progy[] = {
    528 	{COEF,	1},		/* 0 1 units, CF # 1 */
    529 	{COEF,	2},		/* 1 2 units, CF # 2 */
    530 	{COEF,	4},		/* 2 4 units, CF # 3 */
    531 	{COEF,	8},		/* 3 8 units, CF # 4 */
    532 	{DECZ,	M2},	/* 4 zero bit, CF # 5 / unused, default zero in years */
    533 	{COEF,	1},		/* 5 10 tens, CF # 6 */
    534 	{COEF,	2},		/* 6 20 tens, CF # 7*/
    535 	{COEF,	4},		/* 7 40 tens, CF # 8*/
    536 	{COEF,	8},		/* 8 80 tens, CF # 9*/
    537 	{DEC,	M8},	/* 9 PI */
    538 };
    539 
    540 /*
    541  * IRIG format first frame, frame 1 - seconds
    542  */
    543 struct progx progz[] = {
    544 	{MIN,	M8},	/* 0 PI (on-time marker for the second at zero cross of 1st cycle) */
    545 	{COEF,	1},		/* 1 1 units */
    546 	{COEF,	2},		/* 2 2 */
    547 	{COEF,	4},		/* 3 4 */
    548 	{COEF,	8},		/* 4 8 */
    549 	{DECZ,	M2},	/* 5 zero bit */
    550 	{COEF,	1},		/* 6 10 tens */
    551 	{COEF,	2},		/* 7 20 */
    552 	{COEF,	4},		/* 8 40 */
    553 	{DEC,	M8},	/* 9 PI */
    554 };
    555 
    556 /* LeapState values. */
    557 #define	LEAPSTATE_NORMAL			(0)
    558 #define	LEAPSTATE_DELETING			(1)
    559 #define	LEAPSTATE_INSERTING			(2)
    560 #define	LEAPSTATE_ZERO_AFTER_INSERT	(3)
    561 
    562 
    563 /*
    564  * Forward declarations
    565  */
    566 void	WWV_Second(int, int);		/* send second */
    567 void	WWV_SecondNoTick(int, int);	/* send second with no tick */
    568 void	digit(int);		/* encode digit */
    569 void	peep(int, int, int);	/* send cycles */
    570 void	poop(int, int, int, int); /* Generate unmodulated from similar tables */
    571 void	delay(int);		/* delay samples */
    572 int		ConvertMonthDayToDayOfYear (int, int, int);	/* Calc day of year from year month & day */
    573 void	Help (void);	/* Usage message */
    574 void	ReverseString(char *);
    575 
    576 /*
    577  * Extern declarations, don't know why not in headers
    578  */
    579 //float	round ( float );
    580 
    581 /*
    582  * Global variables
    583  */
    584 char	buffer[BUFLNG];		/* output buffer */
    585 int	bufcnt = 0;		/* buffer counter */
    586 int	fd;			/* audio codec file descriptor */
    587 int	tone = 1000;		/* WWV sync frequency */
    588 int HourTone = 1500;	/* WWV hour on-time frequency */
    589 int	encode = IRIG;		/* encoder select */
    590 int	leap = 0;		/* leap indicator */
    591 int	DstFlag = 0;		/* winter/summer time */
    592 int	dut1 = 0;		/* DUT1 correction (sign, magnitude) */
    593 int	utc = 0;		/* option epoch */
    594 int IrigIncludeYear = FALSE;	/* Whether to send year in first control functions area, between P5 and P6. */
    595 int IrigIncludeIeee = FALSE;	/* Whether to send IEEE 1344 control functions extensions between P6 and P8. */
    596 int	StraightBinarySeconds = 0;
    597 int	ControlFunctions = 0;
    598 int	Debug = FALSE;
    599 int Verbose = TRUE;
    600 char	*CommandName;
    601 
    602 #ifndef  HAVE_SYS_SOUNDCARD_H
    603 int	level = AUDIO_MAX_GAIN / 8; /* output level */
    604 int	port = AUDIO_LINE_OUT;	/* output port */
    605 #endif
    606 
    607 int		TotalSecondsCorrected = 0;
    608 int		TotalCyclesAdded = 0;
    609 int		TotalCyclesRemoved = 0;
    610 
    611 
    612 /*
    613  * Main program
    614  */
    615 int
    616 main(
    617 	int		argc,		/* command line options */
    618 	char	**argv		/* poiniter to list of tokens */
    619 	)
    620 {
    621 #ifndef  HAVE_SYS_SOUNDCARD_H
    622 	audio_info_t info;	/* Sun audio structure */
    623 	int	rval;           /* For IOCTL calls */
    624 #endif
    625 
    626 	struct	timeval	 TimeValue;				/* System clock at startup */
    627 	time_t			 SecondsPartOfTime;		/* Sent to gmtime() for calculation of TimeStructure (can apply offset). */
    628 	time_t			 BaseRealTime;			/* Base realtime so can determine seconds since starting. */
    629 	time_t			 NowRealTime;			/* New realtime to can determine seconds as of now. */
    630 	unsigned		 SecondsRunningRealTime;	/* Difference between NowRealTime and BaseRealTime. */
    631 	unsigned		 SecondsRunningSimulationTime;	/* Time that the simulator has been running. */
    632 	int				 SecondsRunningDifference;	/* Difference between what real time says we have been running */
    633 												/* and what simulator says we have been running - will slowly  */
    634 												/* change because of clock drift. */
    635 	int				 ExpectedRunningDifference = 0;	/* Stable value that we've obtained from check at initial start-up.	*/
    636 	unsigned		 StabilityCount;		/* Used to check stability of difference while starting */
    637 #define	RUN_BEFORE_STABILITY_CHECK	(30)	// Must run this many seconds before even checking stability.
    638 #define	MINIMUM_STABILITY_COUNT		(10)	// Number of consecutive differences that need to be within initial stability band to say we are stable.
    639 #define	INITIAL_STABILITY_BAND		( 2)	// Determining initial stability for consecutive differences within +/- this value.
    640 #define	RUNNING_STABILITY_BAND		( 5)	// When running, stability is defined as difference within +/- this value.
    641 
    642 	struct	tm		*TimeStructure = NULL;	/* Structure returned by gmtime */
    643 	char	device[200];	/* audio device */
    644 	char	code[200];	/* timecode */
    645 	int	temp;
    646 	int	arg = 0;
    647 	int	sw = 0;
    648 	int	ptr = 0;
    649 
    650 	int	Year;
    651 	int	Month;
    652 	int	DayOfMonth;
    653 	int	Hour;
    654 	int	Minute;
    655 	int	Second = 0;
    656 	int	DayOfYear;
    657 
    658 	int	BitNumber;
    659 #ifdef HAVE_SYS_SOUNDCARD_H
    660 	int	AudioFormat;
    661 	int	MonoStereo;     /* 0=mono, 1=stereo */
    662 #define	MONO	(0)
    663 #define	STEREO	(1)
    664 	int	SampleRate;
    665 	int	SampleRateDifference;
    666 #endif
    667 	int	SetSampleRate;
    668 	char FormatCharacter = '3';		/* Default is IRIG-B with IEEE 1344 extensions */
    669 	char AsciiValue;
    670 	int	HexValue;
    671 	int	OldPtr = 0;
    672 	int FrameNumber = 0;
    673 
    674 	/* Time offset for IEEE 1344 indication. */
    675 	float TimeOffset = 0.0;
    676 	int	OffsetSignBit = 0;
    677 	int OffsetOnes = 0;
    678 	int OffsetHalf = 0;
    679 
    680 	int	TimeQuality = 0;	/* Time quality for IEEE 1344 indication. */
    681 	char ParityString[200];	/* Partial output string, to calculate parity on. */
    682 	int	ParitySum = 0;
    683 	int	ParityValue;
    684 	char *StringPointer;
    685 
    686 	/* Flags to indicate requested leap second addition or deletion by command line option. */
    687 	/* Should be mutually exclusive - generally ensured by code which interprets command line option. */
    688 	int	InsertLeapSecond = FALSE;
    689 	int	DeleteLeapSecond = FALSE;
    690 
    691 	/* Date and time of requested leap second addition or deletion. */
    692 	int	LeapYear					= 0;
    693 	int LeapMonth					= 0;
    694 	int	LeapDayOfMonth				= 0;
    695 	int LeapHour					= 0;
    696 	int	LeapMinute					= 0;
    697 	int	LeapDayOfYear				= 0;
    698 
    699 	/* State flag for the insertion and deletion of leap seconds, esp. deletion, */
    700 	/* where the logic gets a bit tricky. */
    701 	int	LeapState = LEAPSTATE_NORMAL;
    702 
    703 	/* Flags for indication of leap second pending and leap secod polarity in IEEE 1344 */
    704 	int	LeapSecondPending = FALSE;
    705 	int	LeapSecondPolarity = FALSE;
    706 
    707 	/* Date and time of requested switch into or out of DST by command line option. */
    708 	int	DstSwitchYear				= 0;
    709 	int DstSwitchMonth				= 0;
    710 	int	DstSwitchDayOfMonth			= 0;
    711 	int DstSwitchHour				= 0;
    712 	int	DstSwitchMinute				= 0;
    713 	int	DstSwitchDayOfYear			= 0;
    714 
    715 	/* Indicate when we have been asked to switch into or out of DST by command line option. */
    716 	int	DstSwitchFlag = FALSE;
    717 
    718 	/* To allow predict for DstPendingFlag in IEEE 1344 */
    719 	int	DstSwitchPendingYear		= 0;	/* Default value isn't valid, but I don't care. */
    720 	int	DstSwitchPendingDayOfYear	= 0;
    721 	int	DstSwitchPendingHour		= 0;
    722 	int	DstSwitchPendingMinute		= 0;
    723 
    724 	/* /Flag for indication of a DST switch pending in IEEE 1344 */
    725 	int	DstPendingFlag = FALSE;
    726 
    727 	/* Attempt at unmodulated */
    728 	int	Unmodulated = FALSE;
    729 	int UnmodulatedInverted = FALSE;
    730 
    731 	/* Offset to actual time value sent. */
    732 	float	UseOffsetHoursFloat;
    733 	int		UseOffsetSecondsInt = 0;
    734 	float	UseOffsetSecondsFloat;
    735 
    736 	/* String to allow us to put out reversed data - so can read the binary numbers. */
    737 	char	OutputDataString[OUTPUT_DATA_STRING_LENGTH];
    738 
    739 	/* Number of seconds to send before exiting.  Default = 0 = forever. */
    740 	int		SecondsToSend = 0;
    741 	int		CountOfSecondsSent = 0;	/* Counter of seconds */
    742 
    743 	/* Flags to indicate whether to add or remove a cycle for time adjustment. */
    744 	int		AddCycle = FALSE;	 	// We are ahead, add cycle to slow down and get back in sync.
    745 	int		RemoveCycle = FALSE;	// We are behind, remove cycle to slow down and get back in sync.
    746 	int		RateCorrection;			// Aggregate flag for passing to subroutines.
    747 	int		EnableRateCorrection = TRUE;
    748 
    749 	float	RatioError;
    750 
    751 
    752 	CommandName = argv[0];
    753 
    754 	if	(argc < 1)
    755 		{
    756 		Help ();
    757 		exit (-1);
    758 		}
    759 
    760 	/*
    761 	 * Parse options
    762 	 */
    763 	strlcpy(device, DEVICE, sizeof(device));
    764 	Year = 0;
    765 	SetSampleRate = SECOND;
    766 
    767 #if	HAVE_SYS_SOUNDCARD_H
    768 	while ((temp = getopt(argc, argv, "a:b:c:df:g:hHi:jk:l:o:q:r:stu:xy:z?")) != -1) {
    769 #else
    770 	while ((temp = getopt(argc, argv, "a:b:c:df:g:hHi:jk:l:o:q:r:stu:v:xy:z?")) != -1) {
    771 #endif
    772 		switch (temp) {
    773 
    774 		case 'a':	/* specify audio device (/dev/audio) */
    775 			strlcpy(device, optarg, sizeof(device));
    776 			break;
    777 
    778 		case 'b':	/* Remove (delete) a leap second at the end of the specified minute. */
    779 			sscanf(optarg, "%2d%2d%2d%2d%2d", &LeapYear, &LeapMonth, &LeapDayOfMonth,
    780 			    &LeapHour, &LeapMinute);
    781 			InsertLeapSecond = FALSE;
    782 			DeleteLeapSecond = TRUE;
    783 			break;
    784 
    785 		case 'c':	/* specify number of seconds to send output for before exiting, 0 = forever */
    786 			sscanf(optarg, "%d", &SecondsToSend);
    787 			break;
    788 
    789 		case 'd':	/* set DST for summer (WWV/H only) / start with DST active (IRIG) */
    790 			DstFlag++;
    791 			break;
    792 
    793 		case 'f':	/* select format: i=IRIG-98 (default) 2=IRIG-2004 3-IRIG+IEEE-1344 w=WWV(H) */
    794 			sscanf(optarg, "%c", &FormatCharacter);
    795 			break;
    796 
    797 		case 'g':	/* Date and time to switch back into / out of DST active. */
    798 			sscanf(optarg, "%2d%2d%2d%2d%2d", &DstSwitchYear, &DstSwitchMonth, &DstSwitchDayOfMonth,
    799 			    &DstSwitchHour, &DstSwitchMinute);
    800 			DstSwitchFlag = TRUE;
    801 			break;
    802 
    803 		case 'h':
    804 		case 'H':
    805 		case '?':
    806 			Help ();
    807 			exit(-1);
    808 			break;
    809 
    810 		case 'i':	/* Insert (add) a leap second at the end of the specified minute. */
    811 			sscanf(optarg, "%2d%2d%2d%2d%2d", &LeapYear, &LeapMonth, &LeapDayOfMonth,
    812 			    &LeapHour, &LeapMinute);
    813 			InsertLeapSecond = TRUE;
    814 			DeleteLeapSecond = FALSE;
    815 			break;
    816 
    817 		case 'j':
    818 			EnableRateCorrection = FALSE;
    819 			break;
    820 
    821 		case 'k':
    822 			sscanf (optarg, "%d", &RateCorrection);
    823 			EnableRateCorrection = FALSE;
    824 			if  (RateCorrection < 0)
    825 				{
    826 				RemoveCycle = TRUE;
    827 				AddCycle = FALSE;
    828 
    829 				if  (Verbose)
    830 					printf ("\n> Forcing rate correction removal of cycle...\n");
    831 				}
    832 			else
    833 				{
    834 				if  (RateCorrection > 0)
    835 					{
    836 					RemoveCycle = FALSE;
    837 					AddCycle = TRUE;
    838 
    839 					if  (Verbose)
    840 						printf ("\n> Forcing rate correction addition of cycle...\n");
    841 					}
    842 				}
    843 			break;
    844 
    845 		case 'l':	/* use time offset from UTC */
    846 			sscanf(optarg, "%f", &UseOffsetHoursFloat);
    847 			UseOffsetSecondsFloat = UseOffsetHoursFloat * (float) SECONDS_PER_HOUR;
    848 			UseOffsetSecondsInt = (int) (UseOffsetSecondsFloat + 0.5);
    849 			break;
    850 
    851 		case 'o':	/* Set IEEE 1344 time offset in hours - positive or negative, to the half hour */
    852 			sscanf(optarg, "%f", &TimeOffset);
    853 			if  (TimeOffset >= -0.2)
    854 				{
    855 				OffsetSignBit = 0;
    856 
    857 				if  (TimeOffset > 0)
    858 					{
    859 					OffsetOnes    = TimeOffset;
    860 
    861 					if  ( (TimeOffset - floor(TimeOffset)) >= 0.4)
    862 						OffsetHalf = 1;
    863 					else
    864 						OffsetHalf = 0;
    865 					}
    866 				else
    867 					{
    868 					OffsetOnes    = 0;
    869 					OffsetHalf    = 0;
    870 					}
    871 				}
    872 			else
    873 				{
    874 				OffsetSignBit = 1;
    875 				OffsetOnes    = -TimeOffset;
    876 
    877 				if  ( (ceil(TimeOffset) - TimeOffset) >= 0.4)
    878 					OffsetHalf = 1;
    879 				else
    880 					OffsetHalf = 0;
    881 				}
    882 
    883 			/*printf ("\nGot TimeOffset = %3.1f, OffsetSignBit = %d, OffsetOnes = %d, OffsetHalf = %d...\n",
    884 					TimeOffset, OffsetSignBit, OffsetOnes, OffsetHalf);
    885 			*/
    886 			break;
    887 
    888 		case 'q':	/* Hex quality code 0 to 0x0F - 0 = maximum, 0x0F = no lock */
    889 			sscanf(optarg, "%x", &TimeQuality);
    890 			TimeQuality &= 0x0F;
    891 			/*printf ("\nGot TimeQuality = 0x%1X...\n", TimeQuality);
    892 			*/
    893 			break;
    894 
    895 		case 'r':	/* sample rate (nominally 8000, integer close to 8000 I hope) */
    896 			sscanf(optarg, "%d", &SetSampleRate);
    897 			break;
    898 
    899 		case 's':	/* set leap warning bit (WWV/H only) */
    900 			leap++;
    901 			break;
    902 
    903 		case 't':	/* select WWVH sync frequency */
    904 			tone = 1200;
    905 			break;
    906 
    907 		case 'u':	/* set DUT1 offset (-7 to +7) */
    908 			sscanf(optarg, "%d", &dut1);
    909 			if (dut1 < 0)
    910 				dut1 = abs(dut1);
    911 			else
    912 				dut1 |= 0x8;
    913 			break;
    914 
    915 #ifndef  HAVE_SYS_SOUNDCARD_H
    916 		case 'v':	/* set output level (0-255) */
    917 			sscanf(optarg, "%d", &level);
    918 			break;
    919 #endif
    920 
    921 		case 'x':	/* Turn off verbose output. */
    922 			Verbose = FALSE;
    923 			break;
    924 
    925 		case 'y':	/* Set initial date and time */
    926 			sscanf(optarg, "%2d%2d%2d%2d%2d%2d", &Year, &Month, &DayOfMonth,
    927 			    &Hour, &Minute, &Second);
    928 			utc++;
    929 			break;
    930 
    931 		case 'z':	/* Turn on Debug output (also turns on Verbose below) */
    932 			Debug = TRUE;
    933 			break;
    934 
    935 		default:
    936 			printf("Invalid option \"%c\", aborting...\n", temp);
    937 			exit (-1);
    938 			break;
    939 		}
    940 	}
    941 
    942 	if  (Debug)
    943 	    Verbose = TRUE;
    944 
    945 	if  (InsertLeapSecond || DeleteLeapSecond)
    946 		{
    947 		LeapDayOfYear = ConvertMonthDayToDayOfYear (LeapYear, LeapMonth, LeapDayOfMonth);
    948 
    949 		if	(Debug)
    950 			{
    951 			printf ("\nHave request for leap second %s at year %4d day %3d at %2.2dh%2.2d....\n",\
    952 					DeleteLeapSecond ? "DELETION" : (InsertLeapSecond ? "ADDITION" : "( error ! )" ),
    953 					LeapYear, LeapDayOfYear, LeapHour, LeapMinute);
    954 			}
    955 		}
    956 
    957 	if	(DstSwitchFlag)
    958 		{
    959 		DstSwitchDayOfYear = ConvertMonthDayToDayOfYear (DstSwitchYear, DstSwitchMonth, DstSwitchDayOfMonth);
    960 
    961 		/* Figure out time of minute previous to DST switch, so can put up warning flag in IEEE 1344 */
    962 		DstSwitchPendingYear		= DstSwitchYear;
    963 		DstSwitchPendingDayOfYear	= DstSwitchDayOfYear;
    964 		DstSwitchPendingHour		= DstSwitchHour;
    965 		DstSwitchPendingMinute		= DstSwitchMinute - 1;
    966 		if 	(DstSwitchPendingMinute < 0)
    967 			{
    968 			DstSwitchPendingMinute = 59;
    969 			DstSwitchPendingHour--;
    970 			if	(DstSwitchPendingHour < 0)
    971 				{
    972 				DstSwitchPendingHour = 23;
    973 				DstSwitchPendingDayOfYear--;
    974 				if	(DstSwitchPendingDayOfYear < 1)
    975 					{
    976 					DstSwitchPendingYear--;
    977 					}
    978 				}
    979 			}
    980 
    981 		if	(Debug)
    982 			{
    983 			printf ("\nHave DST switch request for year %4d day %3d at %2.2dh%2.2d,",
    984 					DstSwitchYear, DstSwitchDayOfYear, DstSwitchHour, DstSwitchMinute);
    985 			printf ("\n    so will have warning at year %4d day %3d at %2.2dh%2.2d.\n",
    986 					DstSwitchPendingYear, DstSwitchPendingDayOfYear, DstSwitchPendingHour, DstSwitchPendingMinute);
    987 			}
    988 		}
    989 
    990 	switch (tolower(FormatCharacter)) {
    991 	case 'i':
    992 		printf ("\nFormat is IRIG-1998 (no year coded)...\n\n");
    993 		encode = IRIG;
    994 		IrigIncludeYear = FALSE;
    995 		IrigIncludeIeee = FALSE;
    996 		break;
    997 
    998 	case '2':
    999 		printf ("\nFormat is IRIG-2004 (BCD year coded)...\n\n");
   1000 		encode = IRIG;
   1001 		IrigIncludeYear = TRUE;
   1002 		IrigIncludeIeee = FALSE;
   1003 		break;
   1004 
   1005 	case '3':
   1006 		printf ("\nFormat is IRIG with IEEE-1344 (BCD year coded, and more control functions)...\n\n");
   1007 		encode = IRIG;
   1008 		IrigIncludeYear = TRUE;
   1009 		IrigIncludeIeee = TRUE;
   1010 		break;
   1011 
   1012 	case '4':
   1013 		printf ("\nFormat is unmodulated IRIG with IEEE-1344 (BCD year coded, and more control functions)...\n\n");
   1014 		encode = IRIG;
   1015 		IrigIncludeYear = TRUE;
   1016 		IrigIncludeIeee = TRUE;
   1017 
   1018 		Unmodulated = TRUE;
   1019 		UnmodulatedInverted = FALSE;
   1020 		break;
   1021 
   1022 	case '5':
   1023 		printf ("\nFormat is inverted unmodulated IRIG with IEEE-1344 (BCD year coded, and more control functions)...\n\n");
   1024 		encode = IRIG;
   1025 		IrigIncludeYear = TRUE;
   1026 		IrigIncludeIeee = TRUE;
   1027 
   1028 		Unmodulated = TRUE;
   1029 		UnmodulatedInverted = TRUE;
   1030 		break;
   1031 
   1032 	case 'w':
   1033 		printf ("\nFormat is WWV(H)...\n\n");
   1034 		encode = WWV;
   1035 		break;
   1036 
   1037 	default:
   1038 		printf ("\n\nUnexpected format value of \'%c\', cannot parse, aborting...\n\n", FormatCharacter);
   1039 		exit (-1);
   1040 		break;
   1041 	}
   1042 
   1043 	/*
   1044 	 * Open audio device and set options
   1045 	 */
   1046 	fd = open(device, O_WRONLY);
   1047 	if (fd <= 0) {
   1048 		printf("Unable to open audio device \"%s\", aborting: %s\n", device, strerror(errno));
   1049 		exit(1);
   1050 	}
   1051 
   1052 #ifdef  HAVE_SYS_SOUNDCARD_H
   1053 	/* First set coding type */
   1054 	AudioFormat = AFMT_MU_LAW;
   1055 	if (ioctl(fd, SNDCTL_DSP_SETFMT, &AudioFormat)==-1)
   1056 	{ /* Fatal error */
   1057 	printf ("\nUnable to set output format, aborting...\n\n");
   1058 	exit(-1);
   1059 	}
   1060 
   1061 	if  (AudioFormat != AFMT_MU_LAW)
   1062 	{
   1063 	printf ("\nUnable to set output format for mu law, aborting...\n\n");
   1064 	exit(-1);
   1065 	}
   1066 
   1067 	/* Next set number of channels */
   1068 	MonoStereo = MONO;	/* Mono */
   1069 	if (ioctl(fd, SNDCTL_DSP_STEREO, &MonoStereo)==-1)
   1070 	{ /* Fatal error */
   1071 	printf ("\nUnable to set mono/stereo, aborting...\n\n");
   1072 	exit(-1);
   1073 	}
   1074 
   1075 	if (MonoStereo != MONO)
   1076 	{
   1077 	printf ("\nUnable to set mono/stereo for mono, aborting...\n\n");
   1078 	exit(-1);
   1079 	}
   1080 
   1081 	/* Now set sample rate */
   1082 	SampleRate = SetSampleRate;
   1083 	if (ioctl(fd, SNDCTL_DSP_SPEED, &SampleRate)==-1)
   1084 	{ /* Fatal error */
   1085 	printf ("\nUnable to set sample rate to %d, returned %d, aborting...\n\n", SetSampleRate, SampleRate);
   1086 	exit(-1);
   1087 	}
   1088 
   1089 	SampleRateDifference = SampleRate - SetSampleRate;
   1090 
   1091 	if  (SampleRateDifference < 0)
   1092 		SampleRateDifference = - SampleRateDifference;
   1093 
   1094 	/* Fixed allowable sample rate error 0.1% */
   1095 	if (SampleRateDifference > (SetSampleRate/1000))
   1096 	{
   1097 	printf ("\nUnable to set sample rate to %d, result was %d, more than 0.1 percent, aborting...\n\n", SetSampleRate, SampleRate);
   1098 	exit(-1);
   1099 	}
   1100 	else
   1101 	{
   1102 	/* printf ("\nAttempt to set sample rate to %d, actual %d...\n\n", SetSampleRate, SampleRate); */
   1103 	}
   1104 #else
   1105 	rval = ioctl(fd, AUDIO_GETINFO, &info);
   1106 	if (rval < 0) {
   1107 		printf("\naudio control %s", strerror(errno));
   1108 		exit(0);
   1109 	}
   1110 	info.play.port = port;
   1111 	info.play.gain = level;
   1112 	info.play.sample_rate = SetSampleRate;
   1113 	info.play.channels = 1;
   1114 	info.play.precision = 8;
   1115 	info.play.encoding = AUDIO_ENCODING_ULAW;
   1116 	printf("\nport %d gain %d rate %d chan %d prec %d encode %d\n",
   1117 	    info.play.port, info.play.gain, info.play.sample_rate,
   1118 	    info.play.channels, info.play.precision,
   1119 	    info.play.encoding);
   1120 	ioctl(fd, AUDIO_SETINFO, &info);
   1121 #endif
   1122 
   1123  	/*
   1124 	 * Unless specified otherwise, read the system clock and
   1125 	 * initialize the time.
   1126 	 */
   1127 	gettimeofday(&TimeValue, NULL);		// Now always read the system time to keep "real time" of operation.
   1128 	NowRealTime = BaseRealTime = SecondsPartOfTime = TimeValue.tv_sec;
   1129 	SecondsRunningSimulationTime = 0;	// Just starting simulation, running zero seconds as of now.
   1130 	StabilityCount = 0;					// No stability yet.
   1131 
   1132 	if	(utc)
   1133 		{
   1134 		DayOfYear = ConvertMonthDayToDayOfYear (Year, Month, DayOfMonth);
   1135 		}
   1136 	else
   1137 		{
   1138 		/* Apply offset to time. */
   1139 		if	(UseOffsetSecondsInt >= 0)
   1140 			SecondsPartOfTime += (time_t)   UseOffsetSecondsInt;
   1141 		else
   1142 			SecondsPartOfTime -= (time_t) (-UseOffsetSecondsInt);
   1143 
   1144 		TimeStructure = gmtime(&SecondsPartOfTime);
   1145 		Minute = TimeStructure->tm_min;
   1146 		Hour = TimeStructure->tm_hour;
   1147 		DayOfYear = TimeStructure->tm_yday + 1;
   1148 		Year = TimeStructure->tm_year % 100;
   1149 		Second = TimeStructure->tm_sec;
   1150 
   1151 		/*
   1152 		 * Delay the first second so the generator is accurately
   1153 		 * aligned with the system clock within one sample (125
   1154 		 * microseconds ).
   1155 		 */
   1156 		delay(SECOND - TimeValue.tv_usec * 8 / 1000);
   1157 		}
   1158 
   1159 	StraightBinarySeconds = Second + (Minute * SECONDS_PER_MINUTE) + (Hour * SECONDS_PER_HOUR);
   1160 
   1161 	memset(code, 0, sizeof(code));
   1162 	switch (encode) {
   1163 
   1164 	/*
   1165 	 * For WWV/H and default time, carefully set the signal
   1166 	 * generator seconds number to agree with the current time.
   1167 	 */
   1168 	case WWV:
   1169 		printf("WWV time signal, starting point:\n");
   1170 		printf(" Year = %02d, Day of year = %03d, Time = %02d:%02d:%02d, Minute tone = %d Hz, Hour tone = %d Hz.\n",
   1171 		    Year, DayOfYear, Hour, Minute, Second, tone, HourTone);
   1172 		snprintf(code, sizeof(code), "%01d%03d%02d%02d%01d",
   1173 		    Year / 10, DayOfYear, Hour, Minute, Year % 10);
   1174 		if  (Verbose)
   1175 			{
   1176 		    printf("\n Year = %2.2d, Day of year = %3d, Time = %2.2d:%2.2d:%2.2d, Code = %s",
   1177 				Year, DayOfYear, Hour, Minute, Second, code);
   1178 
   1179 				if  ((EnableRateCorrection) || (RemoveCycle) || (AddCycle))
   1180 				printf (", CountOfSecondsSent = %d, TotalCyclesAdded = %d, TotalCyclesRemoved = %d\n", CountOfSecondsSent, TotalCyclesAdded, TotalCyclesRemoved);
   1181 			else
   1182 				printf ("\n");
   1183 			}
   1184 
   1185 		ptr = 8;
   1186 		for (BitNumber = 0; BitNumber <= Second; BitNumber++) {
   1187 			if (progx[BitNumber].sw == DEC)
   1188 				ptr--;
   1189 		}
   1190 		break;
   1191 
   1192 	/*
   1193 	 * For IRIG the signal generator runs every second, so requires
   1194 	 * no additional alignment.
   1195 	 */
   1196 	case IRIG:
   1197 		printf ("IRIG-B time signal, starting point:\n");
   1198 		printf (" Year = %02d, Day of year = %03d, Time = %02d:%02d:%02d, Straight binary seconds (SBS) = %05d / 0x%04X.\n",
   1199 		    Year, DayOfYear, Hour, Minute, Second, StraightBinarySeconds, StraightBinarySeconds);
   1200 		printf ("\n");
   1201 		if  (Verbose)
   1202 		    {
   1203     		printf ("Codes: \".\" = marker/position indicator, \"-\" = zero dummy bit, \"0\" = zero bit, \"1\" = one bit.\n");
   1204 			if  ((EnableRateCorrection) || (AddCycle) || (RemoveCycle))
   1205 				{
   1206 				printf ("       \"o\" = short zero, \"*\" = long zero, \"x\" = short one, \"+\" = long one.\n");
   1207 				}
   1208 	    	printf ("Numerical values are time order reversed in output to make it easier to read.\n");
   1209     		/*                 111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999 */
   1210 	    	/*       0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 */
   1211 		    printf ("\n");
   1212     		printf ("Legend of output codes:\n");
   1213 	    	//printf ("\n");
   1214 		    //printf ("|  StraightBinSecs  | IEEE_1344_Control |   Year  |    Day_of_Year    |  Hours  | Minutes |Seconds |\n");
   1215     		//printf ("|  ---------------  | ----------------- |   ----  |    -----------    |  -----  | ------- |------- |\n");
   1216 	    	//printf ("|                   |                   |         |                   |         |         |        |\n");
   1217 	    	}
   1218 		break;
   1219 	}
   1220 
   1221 	/*
   1222 	 * Run the signal generator to generate new timecode strings
   1223 	 * once per minute for WWV/H and once per second for IRIG.
   1224 	 */
   1225 	for (CountOfSecondsSent=0; ((SecondsToSend==0) || (CountOfSecondsSent<SecondsToSend)); CountOfSecondsSent++)
   1226 		{
   1227 		if  ((encode == IRIG) && (((Second % 20) == 0) || (CountOfSecondsSent == 0)))
   1228 			{
   1229 	    	printf ("\n");
   1230 
   1231 			printf (" Year = %02d, Day of year = %03d, Time = %02d:%02d:%02d, Straight binary seconds (SBS) = %05d / 0x%04X.\n",
   1232 			    Year, DayOfYear, Hour, Minute, Second, StraightBinarySeconds, StraightBinarySeconds);
   1233 			if  ((EnableRateCorrection) || (RemoveCycle) || (AddCycle))
   1234 				{
   1235 				printf (" CountOfSecondsSent = %d, TotalCyclesAdded = %d, TotalCyclesRemoved = %d\n", CountOfSecondsSent, TotalCyclesAdded, TotalCyclesRemoved);
   1236 				if  ((CountOfSecondsSent != 0) && ((TotalCyclesAdded != 0) || (TotalCyclesRemoved != 0)))
   1237 					{
   1238 					RatioError = ((float) (TotalCyclesAdded - TotalCyclesRemoved)) / (1000.0 * (float) CountOfSecondsSent);
   1239 					printf (" Adjusted by %2.1f%%, apparent send frequency is %4.2f Hz not %d Hz.\n\n",
   1240 									RatioError*100.0, (1.0+RatioError)*((float) SetSampleRate), SetSampleRate);
   1241 					}
   1242 				}
   1243 			else
   1244 				printf ("\n");
   1245 
   1246 		    /* printf ("|Seconds | Minutes |  Hours  |    Day_of_Year    |   Year  | IEEE_1344_Control |  StraightBinSecs  |\n");
   1247     		printf ("|------- | ------- |  -----  |    -----------    |   ----  | ----------------- |-------------------|\n");
   1248 	    	printf ("|        |         |         |                   |         |                   |                   |\n");*/
   1249 		    printf ("|  StraightBinSecs  | IEEE_1344_Control |   Year  |    Day_of_Year    |  Hours  | Minutes |Seconds |\n");
   1250     		printf ("|  ---------------  | ----------------- |   ----  |    -----------    |  -----  | ------- |------- |\n");
   1251 	    	printf ("|                   |                   |         |                   |         |         |        |\n");
   1252 			}
   1253 
   1254 		if  (RemoveCycle)
   1255 			{
   1256 			RateCorrection = -1;
   1257 			TotalSecondsCorrected ++;
   1258 			}
   1259 		else
   1260 			{
   1261 			if  (AddCycle)
   1262 				{
   1263 				TotalSecondsCorrected ++;
   1264 				RateCorrection = +1;
   1265 				}
   1266 			else
   1267 				RateCorrection = 0;
   1268 			}
   1269 
   1270 		/*
   1271 		 * Crank the state machine to propagate carries to the
   1272 		 * year of century. Note that we delayed up to one
   1273 		 * second for alignment after reading the time, so this
   1274 		 * is the next second.
   1275 		 */
   1276 
   1277 		if  (LeapState == LEAPSTATE_NORMAL)
   1278 			{
   1279 			/* If on the second of a leap (second 59 in the specified minute), then add or delete a second */
   1280 			if  ((Year == LeapYear) && (DayOfYear == LeapDayOfYear) && (Hour == LeapHour) && (Minute == LeapMinute))
   1281 				{
   1282 				/* To delete a second, which means we go from 58->60 instead of 58->59->00. */
   1283 				if  ((DeleteLeapSecond) && (Second == 58))
   1284 					{
   1285 					LeapState = LEAPSTATE_DELETING;
   1286 
   1287 					if	(Debug)
   1288 						printf ("\n<--- Ready to delete a leap second...\n");
   1289 					}
   1290 				else
   1291 					{	/* Delete takes precedence over insert. */
   1292 					/* To add a second, which means we go from 59->60->00 instead of 59->00. */
   1293 					if  ((InsertLeapSecond) && (Second == 59))
   1294 						{
   1295 						LeapState = LEAPSTATE_INSERTING;
   1296 
   1297 						if	(Debug)
   1298 							printf ("\n<--- Ready to insert a leap second...\n");
   1299 						}
   1300 					}
   1301 				}
   1302 			}
   1303 
   1304 		switch (LeapState)
   1305 			{
   1306 			case LEAPSTATE_NORMAL:
   1307 				Second = (Second + 1) % 60;
   1308 				break;
   1309 
   1310 			case LEAPSTATE_DELETING:
   1311 				Second = 0;
   1312 				LeapState = LEAPSTATE_NORMAL;
   1313 
   1314 				if	(Debug)
   1315 					printf ("\n<--- Deleting a leap second...\n");
   1316 				break;
   1317 
   1318 			case LEAPSTATE_INSERTING:
   1319 				Second = 60;
   1320 				LeapState = LEAPSTATE_ZERO_AFTER_INSERT;
   1321 
   1322 				if	(Debug)
   1323 					printf ("\n<--- Inserting a leap second...\n");
   1324 				break;
   1325 
   1326 			case LEAPSTATE_ZERO_AFTER_INSERT:
   1327 				Second = 0;
   1328 				LeapState = LEAPSTATE_NORMAL;
   1329 
   1330 				if	(Debug)
   1331 					printf ("\n<--- Inserted a leap second, now back to zero...\n");
   1332 				break;
   1333 
   1334 			default:
   1335 				printf ("\n\nLeap second state invalid value of %d, aborting...", LeapState);
   1336 				exit (-1);
   1337 				break;
   1338 			}
   1339 
   1340 		/* Check for second rollover, increment minutes and ripple upward if required. */
   1341 		if (Second == 0) {
   1342 			Minute++;
   1343 			if (Minute >= 60) {
   1344 				Minute = 0;
   1345 				Hour++;
   1346 			}
   1347 
   1348 			/* Check for activation of DST switch. */
   1349 			/* If DST is active, this would mean that at the appointed time, we de-activate DST, */
   1350 			/* which translates to going backward an hour (repeating the last hour). */
   1351 			/* If DST is not active, this would mean that at the appointed time, we activate DST, */
   1352 			/* which translates to going forward an hour (skipping the next hour). */
   1353 			if	(DstSwitchFlag)
   1354 				{
   1355 				/* The actual switch happens on the zero'th second of the actual minute specified. */
   1356 				if	((Year == DstSwitchYear) && (DayOfYear == DstSwitchDayOfYear) && (Hour == DstSwitchHour) && (Minute == DstSwitchMinute))
   1357 					{
   1358 					if  (DstFlag == 0)
   1359 						{	/* DST flag is zero, not in DST, going to DST, "spring ahead", so increment hour by two instead of one. */
   1360 						Hour++;
   1361 						DstFlag = 1;
   1362 
   1363 						/* Must adjust offset to keep consistent with UTC. */
   1364 						/* Here we have to increase offset by one hour.  If it goes from negative to positive, then we fix that. */
   1365 						if	(OffsetSignBit == 0)
   1366 							{	/* Offset is positive */
   1367 							if	(OffsetOnes == 0x0F)
   1368 								{
   1369 								OffsetSignBit = 1;
   1370 								OffsetOnes    = (OffsetHalf == 0) ? 8 : 7;
   1371 								}
   1372 							else
   1373 								OffsetOnes++;
   1374 							}
   1375 						else
   1376 							{	/* Offset is negative */
   1377 							if  (OffsetOnes == 0)
   1378 								{
   1379 								OffsetSignBit = 0;
   1380 								OffsetOnes    = (OffsetHalf == 0) ? 1 : 0;
   1381 								}
   1382 							else
   1383 								OffsetOnes--;
   1384 							}
   1385 
   1386 						if	(Debug)
   1387 							printf ("\n<--- DST activated, spring ahead an hour, new offset !...\n");
   1388 						}
   1389 					else
   1390 						{	/* DST flag is non zero, in DST, going out of DST, "fall back", so no increment of hour. */
   1391 						Hour--;
   1392 						DstFlag = 0;
   1393 
   1394 						/* Must adjust offset to keep consistent with UTC. */
   1395 						/* Here we have to reduce offset by one hour.  If it goes negative, then we fix that. */
   1396 						if	(OffsetSignBit == 0)
   1397 							{	/* Offset is positive */
   1398 							if  (OffsetOnes == 0)
   1399 								{
   1400 								OffsetSignBit = 1;
   1401 								OffsetOnes    = (OffsetHalf == 0) ? 1 : 0;
   1402 								}
   1403 							else
   1404 								OffsetOnes--;
   1405 							}
   1406 						else
   1407 							{	/* Offset is negative */
   1408 							if	(OffsetOnes == 0x0F)
   1409 								{
   1410 								OffsetSignBit = 0;
   1411 								OffsetOnes    = (OffsetHalf == 0) ? 8 : 7;
   1412 								}
   1413 							else
   1414 								OffsetOnes++;
   1415 							}
   1416 
   1417 						if	(Debug)
   1418 							printf ("\n<--- DST de-activated, fall back an hour!...\n");
   1419 						}
   1420 
   1421 					DstSwitchFlag = FALSE;	/* One time deal, not intended to run this program past two switches... */
   1422 					}
   1423 				}
   1424 
   1425 			if (Hour >= 24) {
   1426 				/* Modified, just in case dumb case where activating DST advances 23h59:59 -> 01h00:00 */
   1427 				Hour = Hour % 24;
   1428 				DayOfYear++;
   1429 			}
   1430 
   1431 			/*
   1432 			 * At year rollover check for leap second.
   1433 			 */
   1434 			if (DayOfYear >= (Year & 0x3 ? 366 : 367)) {
   1435 				if (leap) {
   1436 					WWV_Second(DATA0, RateCorrection);
   1437 					if  (Verbose)
   1438 					    printf("\nLeap!");
   1439 					leap = 0;
   1440 				}
   1441 				DayOfYear = 1;
   1442 				Year++;
   1443 			}
   1444 			if (encode == WWV) {
   1445 				snprintf(code, sizeof(code),
   1446 				    "%01d%03d%02d%02d%01d", Year / 10,
   1447 				    DayOfYear, Hour, Minute, Year % 10);
   1448 				if  (Verbose)
   1449 				    printf("\n Year = %2.2d, Day of year = %3d, Time = %2.2d:%2.2d:%2.2d, Code = %s",
   1450 						Year, DayOfYear, Hour, Minute, Second, code);
   1451 
   1452 				if  ((EnableRateCorrection) || (RemoveCycle) || (AddCycle))
   1453 					{
   1454 					printf (", CountOfSecondsSent = %d, TotalCyclesAdded = %d, TotalCyclesRemoved = %d\n", CountOfSecondsSent, TotalCyclesAdded, TotalCyclesRemoved);
   1455 					if  ((CountOfSecondsSent != 0) && ((TotalCyclesAdded != 0) || (TotalCyclesRemoved != 0)))
   1456 						{
   1457 						RatioError = ((float) (TotalCyclesAdded - TotalCyclesRemoved)) / (1000.0 * (float) CountOfSecondsSent);
   1458 						printf (" Adjusted by %2.1f%%, apparent send frequency is %4.2f Hz not %d Hz.\n\n",
   1459 										RatioError*100.0, (1.0+RatioError)*((float) SetSampleRate), SetSampleRate);
   1460 						}
   1461 					}
   1462 				else
   1463 					printf ("\n");
   1464 
   1465 				ptr = 8;
   1466 			}
   1467 		}	/* End of "if  (Second == 0)" */
   1468 
   1469 		/* After all that, if we are in the minute just prior to a leap second, warn of leap second pending */
   1470 		/* and of the polarity */
   1471 		if  ((Year == LeapYear) && (DayOfYear == LeapDayOfYear) && (Hour == LeapHour) && (Minute == LeapMinute))
   1472 			{
   1473 			LeapSecondPending = TRUE;
   1474 			LeapSecondPolarity = DeleteLeapSecond;
   1475 			}
   1476 		else
   1477 			{
   1478 			LeapSecondPending = FALSE;
   1479 			LeapSecondPolarity = FALSE;
   1480 			}
   1481 
   1482 		/* Notification through IEEE 1344 happens during the whole minute previous to the minute specified. */
   1483 		/* The time of that minute has been previously calculated. */
   1484 		if	((Year == DstSwitchPendingYear) && (DayOfYear == DstSwitchPendingDayOfYear) &&
   1485 					(Hour == DstSwitchPendingHour) && (Minute == DstSwitchPendingMinute))
   1486 			{
   1487 			DstPendingFlag = TRUE;
   1488 			}
   1489 		else
   1490 			{
   1491 			DstPendingFlag = FALSE;
   1492 			}
   1493 
   1494 
   1495 		StraightBinarySeconds = Second + (Minute * SECONDS_PER_MINUTE) + (Hour * SECONDS_PER_HOUR);
   1496 
   1497 		if (encode == IRIG) {
   1498 			if  (IrigIncludeIeee)
   1499 				{
   1500 				if  ((OffsetOnes == 0) && (OffsetHalf == 0))
   1501 					OffsetSignBit = 0;
   1502 
   1503 				ControlFunctions = (LeapSecondPending == 0 ? 0x00000 : 0x00001) | (LeapSecondPolarity == 0 ? 0x00000 : 0x00002)
   1504 						| (DstPendingFlag == 0 ? 0x00000 : 0x00004) | (DstFlag == 0 ? 0x00000 : 0x00008)
   1505 						| (OffsetSignBit == 0 ? 0x00000 : 0x00010)  | ((OffsetOnes & 0x0F) << 5)           | (OffsetHalf == 0 ? 0x00000 : 0x00200)
   1506 						| ((TimeQuality & 0x0F) << 10);
   1507 				/* if  (Verbose)
   1508 				        printf ("\nDstFlag = %d, OffsetSignBit = %d, OffsetOnes = %d, OffsetHalf = %d, TimeQuality = 0x%1.1X ==> ControlFunctions = 0x%5.5X...",
   1509 						    DstFlag, OffsetSignBit, OffsetOnes, OffsetHalf, TimeQuality, ControlFunctions);
   1510 				*/
   1511 				}
   1512 			else
   1513 				ControlFunctions = 0;
   1514 
   1515 			/*
   1516 						      YearDay HourMin Sec
   1517 			snprintf(code, sizeof(code), "%04x%04d%06d%02d%02d%02d",
   1518 				0, Year, DayOfYear, Hour, Minute, Second);
   1519 			*/
   1520 			if  (IrigIncludeYear) {
   1521 				snprintf(ParityString, sizeof(ParityString),
   1522 				    "%04X%02d%04d%02d%02d%02d",
   1523 				    ControlFunctions & 0x7FFF, Year,
   1524 				    DayOfYear, Hour, Minute, Second);
   1525 			} else {
   1526 				snprintf(ParityString, sizeof(ParityString),
   1527 				    "%04X%02d%04d%02d%02d%02d",
   1528 				    ControlFunctions & 0x7FFF,
   1529 				    0, DayOfYear, Hour, Minute, Second);
   1530 			}
   1531 
   1532 			if  (IrigIncludeIeee)
   1533 				{
   1534 				ParitySum = 0;
   1535 				for (StringPointer=ParityString; *StringPointer!=NUL; StringPointer++)
   1536 					{
   1537 					switch (toupper(*StringPointer))
   1538 						{
   1539 						case '1':
   1540 						case '2':
   1541 						case '4':
   1542 						case '8':
   1543 							ParitySum += 1;
   1544 							break;
   1545 
   1546 						case '3':
   1547 						case '5':
   1548 						case '6':
   1549 						case '9':
   1550 						case 'A':
   1551 						case 'C':
   1552 							ParitySum += 2;
   1553 							break;
   1554 
   1555 						case '7':
   1556 						case 'B':
   1557 						case 'D':
   1558 						case 'E':
   1559 							ParitySum += 3;
   1560 							break;
   1561 
   1562 						case 'F':
   1563 							ParitySum += 4;
   1564 							break;
   1565 						}
   1566 					}
   1567 
   1568 				if  ((ParitySum & 0x01) == 0x01)
   1569 					ParityValue = 0x01;
   1570 				else
   1571 					ParityValue = 0;
   1572 				}
   1573 			else
   1574 				ParityValue = 0;
   1575 
   1576 			ControlFunctions |= ((ParityValue & 0x01) << 14);
   1577 
   1578 			if  (IrigIncludeYear) {
   1579 				snprintf(code, sizeof(code),
   1580 				    /* YearDay HourMin Sec */
   1581 				    "%05X%05X%02d%04d%02d%02d%02d",
   1582 				    StraightBinarySeconds,
   1583 				    ControlFunctions, Year, DayOfYear,
   1584 				    Hour, Minute, Second);
   1585 			} else {
   1586 				snprintf(code, sizeof(code),
   1587 				    /* YearDay HourMin Sec */
   1588 				    "%05X%05X%02d%04d%02d%02d%02d",
   1589 				    StraightBinarySeconds,
   1590 				    ControlFunctions, 0, DayOfYear,
   1591 				    Hour, Minute, Second);
   1592 			}
   1593 
   1594 			if  (Debug)
   1595 				printf("\nCode string: %s, ParityString = %s, ParitySum = 0x%2.2X, ParityValue = %d, DstFlag = %d...\n", code, ParityString, ParitySum, ParityValue, DstFlag);
   1596 
   1597 			ptr = strlen(code)-1;
   1598 			OldPtr = 0;
   1599 		}
   1600 
   1601 		/*
   1602 		 * Generate data for the second
   1603 		 */
   1604 		switch (encode) {
   1605 
   1606 		/*
   1607 		 * The IRIG second consists of 20 BCD digits of width-
   1608 		 * modulateod pulses at 2, 5 and 8 ms and modulated 50
   1609 		 * percent on the 1000-Hz carrier.
   1610 		 */
   1611 		case IRIG:
   1612 			/* Initialize the output string */
   1613 			OutputDataString[0] = '\0';
   1614 
   1615 			for (BitNumber = 0; BitNumber < 100; BitNumber++) {
   1616 				FrameNumber = (BitNumber/10) + 1;
   1617 				switch (FrameNumber)
   1618 					{
   1619 					case 1:
   1620 						/* bits 0 to 9, first frame */
   1621 						sw  = progz[BitNumber % 10].sw;
   1622 						arg = progz[BitNumber % 10].arg;
   1623 						break;
   1624 
   1625 					case 2:
   1626 					case 3:
   1627 					case 4:
   1628 					case 5:
   1629 					case 6:
   1630 						/* bits 10 to 59, second to sixth frame */
   1631 						sw  = progy[BitNumber % 10].sw;
   1632 						arg = progy[BitNumber % 10].arg;
   1633 						break;
   1634 
   1635 					case 7:
   1636 						/* bits 60 to 69, seventh frame */
   1637 						sw  = progw[BitNumber % 10].sw;
   1638 						arg = progw[BitNumber % 10].arg;
   1639 						break;
   1640 
   1641 					case 8:
   1642 						/* bits 70 to 79, eighth frame */
   1643 						sw  = progv[BitNumber % 10].sw;
   1644 						arg = progv[BitNumber % 10].arg;
   1645 						break;
   1646 
   1647 					case 9:
   1648 						/* bits 80 to 89, ninth frame */
   1649 						sw  = progw[BitNumber % 10].sw;
   1650 						arg = progw[BitNumber % 10].arg;
   1651 						break;
   1652 
   1653 					case 10:
   1654 						/* bits 90 to 99, tenth frame */
   1655 						sw  = progu[BitNumber % 10].sw;
   1656 						arg = progu[BitNumber % 10].arg;
   1657 						break;
   1658 
   1659 					default:
   1660 						/* , Unexpected values of FrameNumber */
   1661 						printf ("\n\nUnexpected value of FrameNumber = %d, cannot parse, aborting...\n\n", FrameNumber);
   1662 						exit (-1);
   1663 						break;
   1664 					}
   1665 
   1666 				switch(sw) {
   1667 
   1668 				case DECC:	/* decrement pointer and send bit. */
   1669 					ptr--;
   1670 				case COEF:	/* send BCD bit */
   1671 					AsciiValue = toupper(code[ptr]);
   1672 					HexValue   = isdigit(AsciiValue) ? AsciiValue - '0' : (AsciiValue - 'A')+10;
   1673 					/* if  (Debug) {
   1674 						if  (ptr != OldPtr) {
   1675 						if  (Verbose)
   1676 						    printf("\n(%c->%X)", AsciiValue, HexValue);
   1677 						OldPtr = ptr;
   1678 						}
   1679 					}
   1680 					*/
   1681 					// OK, adjust all unused bits in hundreds of days.
   1682 					if  ((FrameNumber == 5) && ((BitNumber % 10) > 1))
   1683 						{
   1684 						if  (RateCorrection < 0)
   1685 							{	// Need to remove cycles to catch up.
   1686 							if  ((HexValue & arg) != 0)
   1687 								{
   1688 								if  (Unmodulated)
   1689 									{
   1690 									poop(M5, 1000, HIGH, UnmodulatedInverted);
   1691 									poop(M5-1, 1000, LOW,  UnmodulatedInverted);
   1692 
   1693 									TotalCyclesRemoved += 1;
   1694 									}
   1695 								else
   1696 									{
   1697 									peep(M5, 1000, HIGH);
   1698 									peep(M5-1, 1000, LOW);
   1699 
   1700 									TotalCyclesRemoved += 1;
   1701 									}
   1702 								strlcat(OutputDataString, "x", OUTPUT_DATA_STRING_LENGTH);
   1703 								}
   1704 							else
   1705 								{
   1706 								if	(Unmodulated)
   1707 									{
   1708 									poop(M2, 1000, HIGH, UnmodulatedInverted);
   1709 									poop(M8-1, 1000, LOW,  UnmodulatedInverted);
   1710 
   1711 									TotalCyclesRemoved += 1;
   1712 									}
   1713 								else
   1714 									{
   1715 									peep(M2, 1000, HIGH);
   1716 									peep(M8-1, 1000, LOW);
   1717 
   1718 									TotalCyclesRemoved += 1;
   1719 									}
   1720 								strlcat(OutputDataString, "o", OUTPUT_DATA_STRING_LENGTH);
   1721 								}
   1722 							}	// End of true clause for "if  (RateCorrection < 0)"
   1723 						else
   1724 							{	// Else clause for "if  (RateCorrection < 0)"
   1725 							if  (RateCorrection > 0)
   1726 								{	// Need to add cycles to slow back down.
   1727 								if  ((HexValue & arg) != 0)
   1728 									{
   1729 									if  (Unmodulated)
   1730 										{
   1731 										poop(M5, 1000, HIGH, UnmodulatedInverted);
   1732 										poop(M5+1, 1000, LOW,  UnmodulatedInverted);
   1733 
   1734 										TotalCyclesAdded += 1;
   1735 										}
   1736 									else
   1737 										{
   1738 										peep(M5, 1000, HIGH);
   1739 										peep(M5+1, 1000, LOW);
   1740 
   1741 										TotalCyclesAdded += 1;
   1742 										}
   1743 									strlcat(OutputDataString, "+", OUTPUT_DATA_STRING_LENGTH);
   1744 									}
   1745 								else
   1746 									{
   1747 									if	(Unmodulated)
   1748 										{
   1749 										poop(M2, 1000, HIGH, UnmodulatedInverted);
   1750 										poop(M8+1, 1000, LOW,  UnmodulatedInverted);
   1751 
   1752 										TotalCyclesAdded += 1;
   1753 										}
   1754 									else
   1755 										{
   1756 										peep(M2, 1000, HIGH);
   1757 										peep(M8+1, 1000, LOW);
   1758 
   1759 										TotalCyclesAdded += 1;
   1760 										}
   1761 									strlcat(OutputDataString, "*", OUTPUT_DATA_STRING_LENGTH);
   1762 									}
   1763 								}	// End of true clause for "if  (RateCorrection > 0)"
   1764 							else
   1765 								{	// Else clause for "if  (RateCorrection > 0)"
   1766 								// Rate is OK, just do what you feel!
   1767 								if  ((HexValue & arg) != 0)
   1768 									{
   1769 									if  (Unmodulated)
   1770 										{
   1771 										poop(M5, 1000, HIGH, UnmodulatedInverted);
   1772 										poop(M5, 1000, LOW,  UnmodulatedInverted);
   1773 										}
   1774 									else
   1775 										{
   1776 										peep(M5, 1000, HIGH);
   1777 										peep(M5, 1000, LOW);
   1778 										}
   1779 									strlcat(OutputDataString, "1", OUTPUT_DATA_STRING_LENGTH);
   1780 									}
   1781 								else
   1782 									{
   1783 									if	(Unmodulated)
   1784 										{
   1785 										poop(M2, 1000, HIGH, UnmodulatedInverted);
   1786 										poop(M8, 1000, LOW,  UnmodulatedInverted);
   1787 										}
   1788 									else
   1789 										{
   1790 										peep(M2, 1000, HIGH);
   1791 										peep(M8, 1000, LOW);
   1792 										}
   1793 									strlcat(OutputDataString, "0", OUTPUT_DATA_STRING_LENGTH);
   1794 									}
   1795 								}	// End of else clause for "if  (RateCorrection > 0)"
   1796 							}	// End of else claues for "if  (RateCorrection < 0)"
   1797 						}	// End of true clause for "if  ((FrameNumber == 5) && (BitNumber == 8))"
   1798 					else
   1799 						{	// Else clause for "if  ((FrameNumber == 5) && (BitNumber == 8))"
   1800 						if  ((HexValue & arg) != 0)
   1801 							{
   1802 							if  (Unmodulated)
   1803 								{
   1804 								poop(M5, 1000, HIGH, UnmodulatedInverted);
   1805 								poop(M5, 1000, LOW,  UnmodulatedInverted);
   1806 								}
   1807 							else
   1808 								{
   1809 								peep(M5, 1000, HIGH);
   1810 								peep(M5, 1000, LOW);
   1811 								}
   1812 							strlcat(OutputDataString, "1", OUTPUT_DATA_STRING_LENGTH);
   1813 							}
   1814 						else
   1815 							{
   1816 							if	(Unmodulated)
   1817 								{
   1818 								poop(M2, 1000, HIGH, UnmodulatedInverted);
   1819 								poop(M8, 1000, LOW,  UnmodulatedInverted);
   1820 								}
   1821 							else
   1822 								{
   1823 								peep(M2, 1000, HIGH);
   1824 								peep(M8, 1000, LOW);
   1825 								}
   1826 							strlcat(OutputDataString, "0", OUTPUT_DATA_STRING_LENGTH);
   1827 							}
   1828 						} // end of else clause for "if  ((FrameNumber == 5) && (BitNumber == 8))"
   1829 					break;
   1830 
   1831 				case DECZ:	/* decrement pointer and send zero bit */
   1832 					ptr--;
   1833 					if	(Unmodulated)
   1834 						{
   1835 						poop(M2, 1000, HIGH, UnmodulatedInverted);
   1836 						poop(M8, 1000, LOW,  UnmodulatedInverted);
   1837 						}
   1838 					else
   1839 						{
   1840 						peep(M2, 1000, HIGH);
   1841 						peep(M8, 1000, LOW);
   1842 						}
   1843 					strlcat(OutputDataString, "-", OUTPUT_DATA_STRING_LENGTH);
   1844 					break;
   1845 
   1846 				case DEC:	/* send marker/position indicator IM/PI bit */
   1847 					ptr--;
   1848 				case NODEC:	/* send marker/position indicator IM/PI bit but no decrement pointer */
   1849 				case MIN:	/* send "second start" marker/position indicator IM/PI bit */
   1850 					if  (Unmodulated)
   1851 						{
   1852 						poop(arg,      1000, HIGH, UnmodulatedInverted);
   1853 						poop(10 - arg, 1000, LOW,  UnmodulatedInverted);
   1854 						}
   1855 					else
   1856 						{
   1857 						peep(arg,      1000, HIGH);
   1858 						peep(10 - arg, 1000, LOW);
   1859 						}
   1860 					strlcat(OutputDataString, ".", OUTPUT_DATA_STRING_LENGTH);
   1861 					break;
   1862 
   1863 				default:
   1864 					printf ("\n\nUnknown state machine value \"%d\", unable to continue, aborting...\n\n", sw);
   1865 					exit (-1);
   1866 					break;
   1867 				}
   1868 				if (ptr < 0)
   1869 					break;
   1870 			}
   1871 			ReverseString ( OutputDataString );
   1872 			if  (Verbose)
   1873 				{
   1874     			printf("%s", OutputDataString);
   1875 				if  (RateCorrection > 0)
   1876 					printf(" fast\n");
   1877 				else
   1878 					{
   1879 					if  (RateCorrection < 0)
   1880 						printf (" slow\n");
   1881 					else
   1882 						printf ("\n");
   1883 					}
   1884 				}
   1885 			break;
   1886 
   1887 		/*
   1888 		 * The WWV/H second consists of 9 BCD digits of width-
   1889 		 * modulateod pulses 200, 500 and 800 ms at 100-Hz.
   1890 		 */
   1891 		case WWV:
   1892 			sw = progx[Second].sw;
   1893 			arg = progx[Second].arg;
   1894 			switch(sw) {
   1895 
   1896 			case DATA:		/* send data bit */
   1897 				WWV_Second(arg, RateCorrection);
   1898 				if  (Verbose)
   1899 					{
   1900 					if  (arg == DATA0)
   1901 						printf ("0");
   1902 					else
   1903 						{
   1904 						if  (arg == DATA1)
   1905 							printf ("1");
   1906 						else
   1907 							{
   1908 							if  (arg == PI)
   1909 								printf ("P");
   1910 							else
   1911 								printf ("?");
   1912 							}
   1913 						}
   1914 					}
   1915 				break;
   1916 
   1917 			case DATAX:		/* send data bit */
   1918 				WWV_SecondNoTick(arg, RateCorrection);
   1919 				if  (Verbose)
   1920 					{
   1921 					if  (arg == DATA0)
   1922 						printf ("0");
   1923 					else
   1924 						{
   1925 						if  (arg == DATA1)
   1926 							printf ("1");
   1927 						else
   1928 							{
   1929 							if  (arg == PI)
   1930 								printf ("P");
   1931 							else
   1932 								printf ("?");
   1933 							}
   1934 						}
   1935 					}
   1936 				break;
   1937 
   1938 			case COEF:		/* send BCD bit */
   1939 				if (code[ptr] & arg) {
   1940 					WWV_Second(DATA1, RateCorrection);
   1941 					if  (Verbose)
   1942 					    printf("1");
   1943 				} else {
   1944 					WWV_Second(DATA0, RateCorrection);
   1945 					if  (Verbose)
   1946 					    printf("0");
   1947 				}
   1948 				break;
   1949 
   1950 			case LEAP:		/* send leap bit */
   1951 				if (leap) {
   1952 					WWV_Second(DATA1, RateCorrection);
   1953 					if  (Verbose)
   1954 					    printf("L");
   1955 				} else {
   1956 					WWV_Second(DATA0, RateCorrection);
   1957 					if  (Verbose)
   1958 					    printf("0");
   1959 				}
   1960 				break;
   1961 
   1962 			case DEC:		/* send data bit */
   1963 				ptr--;
   1964 				WWV_Second(arg, RateCorrection);
   1965 				if  (Verbose)
   1966 					{
   1967 					if  (arg == DATA0)
   1968 						printf ("0");
   1969 					else
   1970 						{
   1971 						if  (arg == DATA1)
   1972 							printf ("1");
   1973 						else
   1974 							{
   1975 							if  (arg == PI)
   1976 								printf ("P");
   1977 							else
   1978 								printf ("?");
   1979 							}
   1980 						}
   1981 					}
   1982 				break;
   1983 
   1984 			case DECX:		/* send data bit with no tick */
   1985 				ptr--;
   1986 				WWV_SecondNoTick(arg, RateCorrection);
   1987 				if  (Verbose)
   1988 					{
   1989 					if  (arg == DATA0)
   1990 						printf ("0");
   1991 					else
   1992 						{
   1993 						if  (arg == DATA1)
   1994 							printf ("1");
   1995 						else
   1996 							{
   1997 							if  (arg == PI)
   1998 								printf ("P");
   1999 							else
   2000 								printf ("?");
   2001 							}
   2002 						}
   2003 					}
   2004 				break;
   2005 
   2006 			case MIN:		/* send minute sync */
   2007 				if  (Minute == 0)
   2008 					{
   2009 					peep(arg, HourTone, HIGH);
   2010 
   2011 					if  (RateCorrection < 0)
   2012 						{
   2013 						peep( 990 - arg, HourTone, OFF);
   2014 						TotalCyclesRemoved += 10;
   2015 
   2016 						if  (Debug)
   2017 							printf ("\n* Shorter Second: ");
   2018 						}
   2019 					else
   2020 						{
   2021 						if	(RateCorrection > 0)
   2022 							{
   2023 							peep(1010 - arg, HourTone, OFF);
   2024 
   2025 							TotalCyclesAdded += 10;
   2026 
   2027 							if  (Debug)
   2028 								printf ("\n* Longer Second: ");
   2029 							}
   2030 						else
   2031 							{
   2032 							peep(1000 - arg, HourTone, OFF);
   2033 							}
   2034 						}
   2035 
   2036 					if  (Verbose)
   2037 					    printf("H");
   2038 					}
   2039 				else
   2040 					{
   2041 					peep(arg, tone, HIGH);
   2042 
   2043 					if  (RateCorrection < 0)
   2044 						{
   2045 						peep( 990 - arg, tone, OFF);
   2046 						TotalCyclesRemoved += 10;
   2047 
   2048 						if  (Debug)
   2049 							printf ("\n* Shorter Second: ");
   2050 						}
   2051 					else
   2052 						{
   2053 						if	(RateCorrection > 0)
   2054 							{
   2055 							peep(1010 - arg, tone, OFF);
   2056 
   2057 							TotalCyclesAdded += 10;
   2058 
   2059 							if  (Debug)
   2060 								printf ("\n* Longer Second: ");
   2061 							}
   2062 						else
   2063 							{
   2064 							peep(1000 - arg, tone, OFF);
   2065 							}
   2066 						}
   2067 
   2068 					if  (Verbose)
   2069 					    printf("M");
   2070 					}
   2071 				break;
   2072 
   2073 			case DUT1:		/* send DUT1 bits */
   2074 				if (dut1 & arg)
   2075 					{
   2076 					WWV_Second(DATA1, RateCorrection);
   2077 					if  (Verbose)
   2078 					    printf("1");
   2079 					}
   2080 				else
   2081 					{
   2082 					WWV_Second(DATA0, RateCorrection);
   2083 					if  (Verbose)
   2084 					    printf("0");
   2085 					}
   2086 				break;
   2087 
   2088 			case DST1:		/* send DST1 bit */
   2089 				ptr--;
   2090 				if (DstFlag)
   2091 					{
   2092 					WWV_Second(DATA1, RateCorrection);
   2093 					if  (Verbose)
   2094 					    printf("1");
   2095 					}
   2096 				else
   2097 					{
   2098 					WWV_Second(DATA0, RateCorrection);
   2099 					if  (Verbose)
   2100 					    printf("0");
   2101 					}
   2102 				break;
   2103 
   2104 			case DST2:		/* send DST2 bit */
   2105 				if (DstFlag)
   2106 					{
   2107 					WWV_Second(DATA1, RateCorrection);
   2108 					if  (Verbose)
   2109 					    printf("1");
   2110 					}
   2111 				else
   2112 					{
   2113 					WWV_Second(DATA0, RateCorrection);
   2114 					if  (Verbose)
   2115 					    printf("0");
   2116 					}
   2117 				break;
   2118 			}
   2119 		}
   2120 
   2121 	if  (EnableRateCorrection)
   2122 		{
   2123 		SecondsRunningSimulationTime++;
   2124 
   2125 		gettimeofday(&TimeValue, NULL);
   2126 		NowRealTime = TimeValue.tv_sec;
   2127 
   2128 		if  (NowRealTime >= BaseRealTime)		// Just in case system time corrects backwards, do not blow up.
   2129 			{
   2130 			SecondsRunningRealTime = (unsigned) (NowRealTime - BaseRealTime);
   2131 			SecondsRunningDifference = SecondsRunningSimulationTime - SecondsRunningRealTime;
   2132 
   2133 			if  (Debug)
   2134 				{
   2135 				printf ("> NowRealTime = 0x%8.8X, BaseRealtime = 0x%8.8X, SecondsRunningRealTime = 0x%8.8X, SecondsRunningSimulationTime = 0x%8.8X.\n",
   2136 							(unsigned) NowRealTime, (unsigned) BaseRealTime, SecondsRunningRealTime, SecondsRunningSimulationTime);
   2137 				printf ("> SecondsRunningDifference = 0x%8.8X, ExpectedRunningDifference = 0x%8.8X.\n",
   2138 							SecondsRunningDifference, ExpectedRunningDifference);
   2139 				}
   2140 
   2141 			if  (SecondsRunningSimulationTime > RUN_BEFORE_STABILITY_CHECK)
   2142 				{
   2143 				if  (StabilityCount < MINIMUM_STABILITY_COUNT)
   2144 					{
   2145 					if  (StabilityCount == 0)
   2146 						{
   2147 						ExpectedRunningDifference = SecondsRunningDifference;
   2148 						StabilityCount++;
   2149 						if  (Debug)
   2150 							printf ("> Starting stability check.\n");
   2151 						}
   2152 					else
   2153 						{	// Else for "if  (StabilityCount == 0)"
   2154 						if  ((ExpectedRunningDifference+INITIAL_STABILITY_BAND > SecondsRunningDifference)
   2155 								&& (ExpectedRunningDifference-INITIAL_STABILITY_BAND < SecondsRunningDifference))
   2156 							{	// So far, still within stability band, increment count.
   2157 							StabilityCount++;
   2158 							if  (Debug)
   2159 								printf ("> StabilityCount = %d.\n", StabilityCount);
   2160 							}
   2161 						else
   2162 							{	// Outside of stability band, start over.
   2163 							StabilityCount = 0;
   2164 							if  (Debug)
   2165 								printf ("> Out of stability band, start over.\n");
   2166 							}
   2167 						} // End of else for "if  (StabilityCount == 0)"
   2168 					}	// End of true clause for "if  (StabilityCount < MINIMUM_STABILITY_COUNT))"
   2169 				else
   2170 					{	// Else clause for "if  (StabilityCount < MINIMUM_STABILITY_COUNT))" - OK, so we are supposed to be stable.
   2171 					if  (AddCycle)
   2172 						{
   2173 						if  (ExpectedRunningDifference >= SecondsRunningDifference)
   2174 							{
   2175 							if  (Debug)
   2176 								printf ("> Was adding cycles, ExpectedRunningDifference >= SecondsRunningDifference, can stop it now.\n");
   2177 
   2178 							AddCycle = FALSE;
   2179 							RemoveCycle = FALSE;
   2180 							}
   2181 						else
   2182 							{
   2183 							if  (Debug)
   2184 								printf ("> Was adding cycles, not done yet.\n");
   2185 							}
   2186 						}
   2187 					else
   2188 						{
   2189 						if  (RemoveCycle)
   2190 							{
   2191 							if  (ExpectedRunningDifference <= SecondsRunningDifference)
   2192 								{
   2193 								if  (Debug)
   2194 									printf ("> Was removing cycles, ExpectedRunningDifference <= SecondsRunningDifference, can stop it now.\n");
   2195 
   2196 								AddCycle = FALSE;
   2197 								RemoveCycle = FALSE;
   2198 								}
   2199 							else
   2200 								{
   2201 								if  (Debug)
   2202 									printf ("> Was removing cycles, not done yet.\n");
   2203 								}
   2204 							}
   2205 						else
   2206 							{
   2207 							if  ((ExpectedRunningDifference+RUNNING_STABILITY_BAND > SecondsRunningDifference)
   2208 									&& (ExpectedRunningDifference-RUNNING_STABILITY_BAND < SecondsRunningDifference))
   2209 								{	// All is well, within tolerances.
   2210 								if  (Debug)
   2211 									printf ("> All is well, within tolerances.\n");
   2212 								}
   2213 							else
   2214 								{	// Oops, outside tolerances.  Else clause of "if  ((ExpectedRunningDifference...SecondsRunningDifference)"
   2215 								if  (ExpectedRunningDifference > SecondsRunningDifference)
   2216 									{
   2217 									if  (Debug)
   2218 										printf ("> ExpectedRunningDifference > SecondsRunningDifference, running behind real time.\n");
   2219 
   2220 									// Behind real time, have to add a cycle to slow down and get back in sync.
   2221 									AddCycle = FALSE;
   2222 									RemoveCycle = TRUE;
   2223 									}
   2224 								else
   2225 									{	// Else clause of "if  (ExpectedRunningDifference < SecondsRunningDifference)"
   2226 									if  (ExpectedRunningDifference < SecondsRunningDifference)
   2227 										{
   2228 										if  (Debug)
   2229 											printf ("> ExpectedRunningDifference < SecondsRunningDifference, running ahead of real time.\n");
   2230 
   2231 										// Ahead of real time, have to remove a cycle to speed up and get back in sync.
   2232 										AddCycle = TRUE;
   2233 										RemoveCycle = FALSE;
   2234 										}
   2235 									else
   2236 										{
   2237 										if  (Debug)
   2238 											printf ("> Oops, outside tolerances, but doesn't fit the profiles, how can this be?\n");
   2239 										}
   2240 									}	// End of else clause of "if  (ExpectedRunningDifference > SecondsRunningDifference)"
   2241 								}	// End of else clause of "if  ((ExpectedRunningDifference...SecondsRunningDifference)"
   2242 							}	// End of else clause of "if  (RemoveCycle)".
   2243 						}	// End of else clause of "if  (AddCycle)".
   2244 					}	// End of else clause for "if  (StabilityCount < MINIMUM_STABILITY_COUNT))"
   2245 				}	// End of true clause for "if  ((SecondsRunningSimulationTime > RUN_BEFORE_STABILITY_CHECK)"
   2246 			}	// End of true clause for "if  (NowRealTime >= BaseRealTime)"
   2247 		else
   2248 			{
   2249 			if  (Debug)
   2250 				printf ("> Hmm, time going backwards?\n");
   2251 			}
   2252 		}	// End of true clause for "if  (EnableRateCorrection)"
   2253 
   2254 	fflush (stdout);
   2255 	}
   2256 
   2257 
   2258 printf ("\n\n>> Completed %d seconds, exiting...\n\n", SecondsToSend);
   2259 return (0);
   2260 }
   2261 
   2262 
   2263 /*
   2264  * Generate WWV/H 0 or 1 data pulse.
   2265  */
   2266 void WWV_Second(
   2267 	int	code,		/* DATA0, DATA1, PI */
   2268 	int Rate		/* <0 -> do a short second, 0 -> normal second, >0 -> long second */
   2269 	)
   2270 {
   2271 	/*
   2272 	 * The WWV data pulse begins with 5 ms of 1000 Hz follwed by a
   2273 	 * guard time of 25 ms. The data pulse is 170, 570 or 770 ms at
   2274 	 * 100 Hz corresponding to 0, 1 or position indicator (PI),
   2275 	 * respectively. Note the 100-Hz data pulses are transmitted 6
   2276 	 * dB below the 1000-Hz sync pulses. Originally the data pulses
   2277 	 * were transmited 10 dB below the sync pulses, but the station
   2278 	 * engineers increased that to 6 dB because the Heath GC-1000
   2279 	 * WWV/H radio clock worked much better.
   2280 	 */
   2281 	peep(5, tone, HIGH);		/* send seconds tick */
   2282 	peep(25, tone, OFF);
   2283 	peep(code - 30, 100, LOW);	/* send data */
   2284 
   2285 	/* The quiet time is shortened or lengthened to get us back on time */
   2286 	if  (Rate < 0)
   2287 		{
   2288 		peep( 990 - code, 100, OFF);
   2289 
   2290 		TotalCyclesRemoved += 10;
   2291 
   2292 		if  (Debug)
   2293 			printf ("\n* Shorter Second: ");
   2294 		}
   2295 	else
   2296 		{
   2297 		if  (Rate > 0)
   2298 			{
   2299 			peep(1010 - code, 100, OFF);
   2300 
   2301 			TotalCyclesAdded += 10;
   2302 
   2303 			if  (Debug)
   2304 				printf ("\n* Longer Second: ");
   2305 			}
   2306 		else
   2307 			peep(1000 - code, 100, OFF);
   2308 		}
   2309 }
   2310 
   2311 /*
   2312  * Generate WWV/H 0 or 1 data pulse, with no tick, for 29th and 59th seconds
   2313  */
   2314 void WWV_SecondNoTick(
   2315 	int	code,		/* DATA0, DATA1, PI */
   2316 	int Rate		/* <0 -> do a short second, 0 -> normal second, >0 -> long second */
   2317 	)
   2318 {
   2319 	/*
   2320 	 * The WWV data pulse begins with 5 ms of 1000 Hz follwed by a
   2321 	 * guard time of 25 ms. The data pulse is 170, 570 or 770 ms at
   2322 	 * 100 Hz corresponding to 0, 1 or position indicator (PI),
   2323 	 * respectively. Note the 100-Hz data pulses are transmitted 6
   2324 	 * dB below the 1000-Hz sync pulses. Originally the data pulses
   2325 	 * were transmited 10 dB below the sync pulses, but the station
   2326 	 * engineers increased that to 6 dB because the Heath GC-1000
   2327 	 * WWV/H radio clock worked much better.
   2328 	 */
   2329 	peep(30, tone, OFF);		/* send seconds non-tick */
   2330 	peep(code - 30, 100, LOW);	/* send data */
   2331 
   2332 	/* The quiet time is shortened or lengthened to get us back on time */
   2333 	if  (Rate < 0)
   2334 		{
   2335 		peep( 990 - code, 100, OFF);
   2336 
   2337 		TotalCyclesRemoved += 10;
   2338 
   2339 		if  (Debug)
   2340 			printf ("\n* Shorter Second: ");
   2341 		}
   2342 	else
   2343 		{
   2344 		if  (Rate > 0)
   2345 			{
   2346 			peep(1010 - code, 100, OFF);
   2347 
   2348 			TotalCyclesAdded += 10;
   2349 
   2350 			if  (Debug)
   2351 				printf ("\n* Longer Second: ");
   2352 			}
   2353 		else
   2354 			peep(1000 - code, 100, OFF);
   2355 		}
   2356 }
   2357 
   2358 /*
   2359  * Generate cycles of 100 Hz or any multiple of 100 Hz.
   2360  */
   2361 void peep(
   2362 	int	pulse,		/* pulse length (ms) */
   2363 	int	freq,		/* frequency (Hz) */
   2364 	int	amp		/* amplitude */
   2365 	)
   2366 {
   2367 	int	increm;		/* phase increment */
   2368 	int	i, j;
   2369 
   2370 	if (amp == OFF || freq == 0)
   2371 		increm = 10;
   2372 	else
   2373 		increm = freq / 100;
   2374 	j = 0;
   2375 	for (i = 0 ; i < pulse * 8; i++) {
   2376 		switch (amp) {
   2377 
   2378 		case HIGH:
   2379 			buffer[bufcnt++] = ~c6000[j];
   2380 			break;
   2381 
   2382 		case LOW:
   2383 			buffer[bufcnt++] = ~c3000[j];
   2384 			break;
   2385 
   2386 		default:
   2387 			buffer[bufcnt++] = ~0;
   2388 		}
   2389 		if (bufcnt >= BUFLNG) {
   2390 			write(fd, buffer, BUFLNG);
   2391 			bufcnt = 0;
   2392 		}
   2393 		j = (j + increm) % 80;
   2394 	}
   2395 }
   2396 
   2397 
   2398 /*
   2399  * Generate unmodulated from similar tables.
   2400  */
   2401 void poop(
   2402 	int	pulse,		/* pulse length (ms) */
   2403 	int	freq,		/* frequency (Hz) */
   2404 	int	amp,		/* amplitude */
   2405 	int inverted	/* is upside down */
   2406 	)
   2407 {
   2408 	int	increm;		/* phase increment */
   2409 	int	i, j;
   2410 
   2411 	if (amp == OFF || freq == 0)
   2412 		increm = 10;
   2413 	else
   2414 		increm = freq / 100;
   2415 	j = 0;
   2416 	for (i = 0 ; i < pulse * 8; i++) {
   2417 		switch (amp) {
   2418 
   2419 		case HIGH:
   2420 			if  (inverted)
   2421 				buffer[bufcnt++] = ~u3000[j];
   2422 			else
   2423 				buffer[bufcnt++] = ~u6000[j];
   2424 			break;
   2425 
   2426 		case LOW:
   2427 			if  (inverted)
   2428 				buffer[bufcnt++] = ~u6000[j];
   2429 			else
   2430 				buffer[bufcnt++] = ~u3000[j];
   2431 			break;
   2432 
   2433 		default:
   2434 			buffer[bufcnt++] = ~0;
   2435 		}
   2436 		if (bufcnt >= BUFLNG) {
   2437 			write(fd, buffer, BUFLNG);
   2438 			bufcnt = 0;
   2439 		}
   2440 		j = (j + increm) % 80;
   2441 	}
   2442 }
   2443 
   2444 /*
   2445  * Delay for initial phasing
   2446  */
   2447 void delay (
   2448 	int	Delay		/* delay in samples */
   2449 	)
   2450 {
   2451 	int	samples;	/* samples remaining */
   2452 
   2453 	samples = Delay;
   2454 	memset(buffer, 0, BUFLNG);
   2455 	while (samples >= BUFLNG) {
   2456 		write(fd, buffer, BUFLNG);
   2457 		samples -= BUFLNG;
   2458 	}
   2459 		write(fd, buffer, samples);
   2460 }
   2461 
   2462 
   2463 /* Calc day of year from year month & day */
   2464 /* Year - 0 means 2000, 100 means 2100. */
   2465 /* Month - 1 means January, 12 means December. */
   2466 /* DayOfMonth - 1 is first day of month */
   2467 int
   2468 ConvertMonthDayToDayOfYear (int YearValue, int MonthValue, int DayOfMonthValue)
   2469 	{
   2470 	int	ReturnValue;
   2471 	int	LeapYear;
   2472 	int	MonthCounter;
   2473 
   2474 	/* Array of days in a month.  Note that here January is zero. */
   2475 	/* NB: have to add 1 to days in February in a leap year! */
   2476 	int DaysInMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
   2477 
   2478 
   2479 	LeapYear = FALSE;
   2480 	if  ((YearValue % 4) == 0)
   2481 		{
   2482 		if  ((YearValue % 100) == 0)
   2483 			{
   2484 			if  ((YearValue % 400) == 0)
   2485 				{
   2486 				LeapYear = TRUE;
   2487 				}
   2488 			}
   2489 		else
   2490 			{
   2491 			LeapYear = TRUE;
   2492 			}
   2493 		}
   2494 
   2495 	if  (Debug)
   2496 		printf ("\nConvertMonthDayToDayOfYear(): Year %d %s a leap year.\n", YearValue+2000, LeapYear ? "is" : "is not");
   2497 
   2498 	/* Day of month given us starts in this algorithm. */
   2499 	ReturnValue = DayOfMonthValue;
   2500 
   2501 	/* Add in days in month for each month past January. */
   2502 	for (MonthCounter=1; MonthCounter<MonthValue; MonthCounter++)
   2503 		{
   2504 		ReturnValue += DaysInMonth [ MonthCounter - 1 ];
   2505 		}
   2506 
   2507 	/* Add a day for leap years where we are past February. */
   2508 	if  ((LeapYear) && (MonthValue > 2))
   2509 		{
   2510 		ReturnValue++;
   2511 		}
   2512 
   2513 	if  (Debug)
   2514 		printf ("\nConvertMonthDayToDayOfYear(): %4.4d-%2.2d-%2.2d represents day %3d of year.\n",
   2515 				YearValue+2000, MonthValue, DayOfMonthValue, ReturnValue);
   2516 
   2517 	return (ReturnValue);
   2518 	}
   2519 
   2520 
   2521 void
   2522 Help ( void )
   2523 	{
   2524 	printf ("\n\nTime Code Generation - IRIG-B or WWV, v%d.%d, %s dmw", VERSION, ISSUE, ISSUE_DATE);
   2525 	printf ("\n\nUsage: %s [option]*", CommandName);
   2526 	printf ("\n\nOptions: -a device_name                 Output audio device name (default /dev/audio)");
   2527 	printf (  "\n         -b yymmddhhmm                  Remove leap second at end of minute specified");
   2528 	printf (  "\n         -c seconds_to_send             Number of seconds to send (default 0 = forever)");
   2529 	printf (  "\n         -d                             Start with IEEE 1344 DST active");
   2530 	printf (  "\n         -f format_type                 i = Modulated IRIG-B 1998 (no year coded)");
   2531 	printf (  "\n                                        2 = Modulated IRIG-B 2002 (year coded)");
   2532 	printf (  "\n                                        3 = Modulated IRIG-B w/IEEE 1344 (year & control funcs) (default)");
   2533 	printf (  "\n                                        4 = Unmodulated IRIG-B w/IEEE 1344 (year & control funcs)");
   2534 	printf (  "\n                                        5 = Inverted unmodulated IRIG-B w/IEEE 1344 (year & control funcs)");
   2535 	printf (  "\n                                        w = WWV(H)");
   2536 	printf (  "\n         -g yymmddhhmm                  Switch into/out of DST at beginning of minute specified");
   2537 	printf (  "\n         -i yymmddhhmm                  Insert leap second at end of minute specified");
   2538 	printf (  "\n         -j                             Disable time rate correction against system clock (default enabled)");
   2539 	printf (  "\n         -k nn                          Force rate correction for testing (+1 = add cycle, -1 = remove cycle)");
   2540 	printf (  "\n         -l time_offset                 Set offset of time sent to UTC as per computer, +/- float hours");
   2541 	printf (  "\n         -o time_offset                 Set IEEE 1344 time offset, +/-, to 0.5 hour (default 0)");
   2542 	printf (  "\n         -q quality_code_hex            Set IEEE 1344 quality code (default 0)");
   2543 	printf (  "\n         -r sample_rate                 Audio sample rate (default 8000)");
   2544 	printf (  "\n         -s                             Set leap warning bit (WWV[H] only)");
   2545 	printf (  "\n         -t sync_frequency              WWV(H) on-time pulse tone frequency (default 1200)");
   2546 	printf (  "\n         -u DUT1_offset                 Set WWV(H) DUT1 offset -7 to +7 (default 0)");
   2547 #ifndef  HAVE_SYS_SOUNDCARD_H
   2548 	printf (  "\n         -v initial_output_level        Set initial output level (default %d, must be 0 to 255)", AUDIO_MAX_GAIN/8);
   2549 #endif
   2550 	printf (  "\n         -x                             Turn off verbose output (default on)");
   2551 	printf (  "\n         -y yymmddhhmmss                Set initial date and time as specified (default system time)");
   2552 	printf ("\n\nThis software licenced under the GPL, modifications performed 2006 & 2007 by Dean Weiten");
   2553 	printf (  "\nContact: Dean Weiten, Norscan Instruments Ltd., Winnipeg, MB, Canada, ph (204)-233-9138, E-mail dmw (at) norscan.com");
   2554 	printf ("\n\n");
   2555 	}
   2556 
   2557 /* Reverse string order for nicer print. */
   2558 void
   2559 ReverseString(char *str)
   2560 	{
   2561 	int		StringLength;
   2562 	int		IndexCounter;
   2563 	int		CentreOfString;
   2564 	char	TemporaryCharacter;
   2565 
   2566 
   2567 	StringLength	= strlen(str);
   2568 	CentreOfString	= (StringLength/2)+1;
   2569 	for (IndexCounter = StringLength; IndexCounter >= CentreOfString; IndexCounter--)
   2570 		{
   2571 		TemporaryCharacter				= str[IndexCounter-1];
   2572 		str[IndexCounter-1]				= str[StringLength-IndexCounter];
   2573 		str[StringLength-IndexCounter]	= TemporaryCharacter;
   2574 		}
   2575 	}
   2576 
   2577