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