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