~ubuntu-branches/debian/squeeze/ntp/squeeze-201010051545

« back to all changes in this revision

Viewing changes to util/tg.c

  • Committer: Bazaar Package Importer
  • Author(s): Kurt Roeckx
  • Date: 2009-01-05 21:10:03 UTC
  • mfrom: (1.2.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20090105211003-mh6zc3um4k1uhsj7
Tags: 1:4.2.4p4+dfsg-8
It did not properly check the return value of EVP_VerifyFinal
which results in an malformed DSA signature being treated as
a good signature rather than as an error.  (CVE-2009-0021)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * tg.c generate WWV or IRIG signals for test
 
3
 */
 
4
/*
 
5
 * This program can generate audio signals that simulate the WWV/H
 
6
 * broadcast timecode. Alternatively, it can generate the IRIG-B
 
7
 * timecode commonly used to synchronize laboratory equipment. It is
 
8
 * intended to test the WWV/H driver (refclock_wwv.c) and the IRIG
 
9
 * driver (refclock_irig.c) in the NTP driver collection.
 
10
 *
 
11
 * Besides testing the drivers themselves, this program can be used to
 
12
 * synchronize remote machines over audio transmission lines or program
 
13
 * feeds. The program reads the time on the local machine and sets the
 
14
 * initial epoch of the signal generator within one millisecond.
 
15
 * Alernatively, the initial epoch can be set to an arbitrary time. This
 
16
 * is useful when searching for bugs and testing for correct response to
 
17
 * a leap second in UTC. Note however, the ultimate accuracy is limited
 
18
 * by the intrinsic frequency error of the codec sample clock, which can
 
19
 # reach well over 100 PPM.
 
20
 *
 
21
 * The default is to route generated signals to the line output
 
22
 * jack; the s option on the command line routes these signals to the
 
23
 * internal speaker as well. The v option controls the speaker volume
 
24
 * over the range 0-255. The signal generator by default uses WWV
 
25
 * format; the h option switches to WWVH format and the i option
 
26
 * switches to IRIG-B format.
 
27
 *
 
28
 * Once started the program runs continuously. The default initial epoch
 
29
 * for the signal generator is read from the computer system clock when
 
30
 * the program starts. The y option specifies an alternate epoch using a
 
31
 * string yydddhhmmss, where yy is the year of century, ddd the day of
 
32
 * year, hh the hour of day and mm the minute of hour. For instance,
 
33
 * 1946Z on 1 January 2006 is 060011946. The l option lights the leap
 
34
 * warning bit in the WWV/H timecode, so is handy to check for correct
 
35
 * behavior at the next leap second epoch. The remaining options are
 
36
 * specified below under the Parse Options heading. Most of these are
 
37
 * for testing.
 
38
 *
 
39
 * During operation the program displays the WWV/H timecode (9 digits)
 
40
 * or IRIG timecode (20 digits) as each new string is constructed. The
 
41
 * display is followed by the BCD binary bits as transmitted. Note that
 
42
 * the transmissionorder is low-order first as the frame is processed
 
43
 * left to right. For WWV/H The leap warning L preceeds the first bit.
 
44
 * For IRIG the on-time marker M preceeds the first (units) bit, so its
 
45
 * code is delayed one bit and the next digit (tens) needs only three
 
46
 * bits.
 
47
 *
 
48
 * The program has been tested with the Sun Blade 1500 running Solaris
 
49
 * 10, but not yet with other machines. It uses no special features and
 
50
 * should be readily portable to other hardware and operating systems.
 
51
 */
 
52
#include <stdio.h>
 
53
#include <stdlib.h>
 
54
#include <time.h>
 
55
#include <sys/audio.h>
 
56
#include <math.h>
 
57
#include <errno.h>
 
58
#include <sys/types.h>
 
59
#include <sys/stat.h>
 
60
#include <fcntl.h>
 
61
#include <string.h>
 
62
#include <unistd.h>
 
63
 
 
64
#define SECOND  8000            /* one second of 125-us samples */
 
65
#define BUFLNG  400             /* buffer size */
 
66
#define DEVICE  "/dev/audio"    /* default audio device */
 
67
#define WWV     0               /* WWV encoder */
 
68
#define IRIG    1               /* IRIG-B encoder */
 
69
#define OFF     0               /* zero amplitude */
 
70
#define LOW     1               /* low amplitude */
 
71
#define HIGH    2               /* high amplitude */
 
72
#define DATA0   200             /* WWV/H 0 pulse */
 
73
#define DATA1   500             /* WWV/H 1 pulse */
 
74
#define PI      800             /* WWV/H PI pulse */
 
75
#define M2      2               /* IRIG 0 pulse */
 
76
#define M5      5               /* IRIG 1 pulse */
 
77
#define M8      8               /* IRIG PI pulse */
 
78
 
 
79
/*
 
80
 * Companded sine table amplitude 3000 units
 
81
 */
 
82
int c3000[] = {1, 48, 63, 70, 78, 82, 85, 89, 92, 94,   /* 0-9 */
 
83
     96,  98,  99, 100, 101, 101, 102, 103, 103, 103,   /* 10-19 */
 
84
    103, 103, 103, 103, 102, 101, 101, 100,  99,  98,   /* 20-29 */
 
85
     96,  94,  92,  89,  85,  82,  78,  70,  63,  48,   /* 30-39 */
 
86
    129, 176, 191, 198, 206, 210, 213, 217, 220, 222,   /* 40-49 */
 
87
    224, 226, 227, 228, 229, 229, 230, 231, 231, 231,   /* 50-59 */
 
88
    231, 231, 231, 231, 230, 229, 229, 228, 227, 226,   /* 60-69 */
 
89
    224, 222, 220, 217, 213, 210, 206, 198, 191, 176};  /* 70-79 */
 
90
/*
 
91
 * Companded sine table amplitude 6000 units
 
92
 */
 
93
int c6000[] = {1, 63, 78, 86, 93, 98, 101, 104, 107, 110, /* 0-9 */
 
94
    112, 113, 115, 116, 117, 117, 118, 118, 119, 119,   /* 10-19 */
 
95
    119, 119, 119, 118, 118, 117, 117, 116, 115, 113,   /* 20-29 */
 
96
    112, 110, 107, 104, 101,  98,  93,  86,  78,  63,   /* 30-39 */
 
97
    129, 191, 206, 214, 221, 226, 229, 232, 235, 238,   /* 40-49 */
 
98
    240, 241, 243, 244, 245, 245, 246, 246, 247, 247,   /* 50-59 */
 
99
    247, 247, 247, 246, 246, 245, 245, 244, 243, 241,   /* 60-69 */
 
100
    240, 238, 235, 232, 229, 226, 221, 214, 206, 191};  /* 70-79 */
 
101
 
 
102
/*
 
103
 * Decoder operations at the end of each second are driven by a state
 
104
 * machine. The transition matrix consists of a dispatch table indexed
 
105
 * by second number. Each entry in the table contains a case switch
 
106
 * number and argument.
 
107
 */
 
108
struct progx {
 
109
        int sw;                 /* case switch number */
 
110
        int arg;                /* argument */
 
111
};
 
112
 
 
113
/*
 
114
 * Case switch numbers
 
115
 */
 
116
#define DATA    0               /* send data (0, 1, PI) */
 
117
#define COEF    1               /* send BCD bit */
 
118
#define DEC     2               /* decrement to next digit */
 
119
#define MIN     3               /* minute pulse */
 
120
#define LEAP    4               /* leap warning */
 
121
#define DUT1    5               /* DUT1 bits */
 
122
#define DST1    6               /* DST1 bit */
 
123
#define DST2    7               /* DST2 bit */
 
124
 
 
125
/*
 
126
 * WWV/H format (100-Hz, 9 digits, 1 m frame)
 
127
 */
 
128
struct progx progx[] = {
 
129
        {MIN,   800},           /* 0 minute sync pulse */
 
130
        {DATA,  DATA0},         /* 1 */
 
131
        {DST2,  0},             /* 2 DST2 */
 
132
        {LEAP,  0},             /* 3 leap warning */
 
133
        {COEF,  1},             /* 4 1 year units */
 
134
        {COEF,  2},             /* 5 2 */
 
135
        {COEF,  4},             /* 6 4 */
 
136
        {COEF,  8},             /* 7 8 */
 
137
        {DEC,   DATA0},         /* 8 */
 
138
        {DATA,  PI},            /* 9 p1 */
 
139
        {COEF,  1},             /* 10 1 minute units */
 
140
        {COEF,  2},             /* 11 2 */
 
141
        {COEF,  4},             /* 12 4 */
 
142
        {COEF,  8},             /* 13 8 */
 
143
        {DEC,   DATA0},         /* 14 */
 
144
        {COEF,  1},             /* 15 10 minute tens */
 
145
        {COEF,  2},             /* 16 20 */
 
146
        {COEF,  4},             /* 17 40 */
 
147
        {COEF,  8},             /* 18 80 (not used) */
 
148
        {DEC,   PI},            /* 19 p2 */
 
149
        {COEF,  1},             /* 20 1 hour units */
 
150
        {COEF,  2},             /* 21 2 */
 
151
        {COEF,  4},             /* 22 4 */
 
152
        {COEF,  8},             /* 23 8 */
 
153
        {DEC,   DATA0},         /* 24 */
 
154
        {COEF,  1},             /* 25 10 hour tens */
 
155
        {COEF,  2},             /* 26 20 */
 
156
        {COEF,  4},             /* 27 40 (not used) */
 
157
        {COEF,  8},             /* 28 80 (not used) */
 
158
        {DEC,   PI},            /* 29 p3 */
 
159
        {COEF,  1},             /* 30 1 day units */
 
160
        {COEF,  2},             /* 31 2 */
 
161
        {COEF,  4},             /* 32 4 */
 
162
        {COEF,  8},             /* 33 8 */
 
163
        {DEC,   DATA0},         /* 34 not used */
 
164
        {COEF,  1},             /* 35 10 day tens */
 
165
        {COEF,  2},             /* 36 20 */
 
166
        {COEF,  4},             /* 37 40 */
 
167
        {COEF,  8},             /* 38 80 */
 
168
        {DEC,   PI},            /* 39 p4 */
 
169
        {COEF,  1},             /* 40 100 day hundreds */
 
170
        {COEF,  2},             /* 41 200 */
 
171
        {COEF,  4},             /* 42 400 (not used) */
 
172
        {COEF,  8},             /* 43 800 (not used) */
 
173
        {DEC,   DATA0},         /* 44 */
 
174
        {DATA,  DATA0},         /* 45 */
 
175
        {DATA,  DATA0},         /* 46 */
 
176
        {DATA,  DATA0},         /* 47 */
 
177
        {DATA,  DATA0},         /* 48 */
 
178
        {DATA,  PI},            /* 49 p5 */
 
179
        {DUT1,  8},             /* 50 DUT1 sign */
 
180
        {COEF,  1},             /* 51 10 year tens */
 
181
        {COEF,  2},             /* 52 20 */
 
182
        {COEF,  4},             /* 53 40 */
 
183
        {COEF,  8},             /* 54 80 */
 
184
        {DST1,  0},             /* 55 DST1 */
 
185
        {DUT1,  1},             /* 56 0.1 DUT1 fraction */
 
186
        {DUT1,  2},             /* 57 0.2 */
 
187
        {DUT1,  4},             /* 58 0.4 */
 
188
        {DATA,  PI},            /* 59 p6 */
 
189
        {DATA,  DATA0},         /* 60 leap */
 
190
};
 
191
 
 
192
/*
 
193
 * IRIG format except first frame (1000 Hz, 20 digits, 1 s frame)
 
194
 */
 
195
struct progx progy[] = {
 
196
        {COEF,  1},             /* 0 1 units */
 
197
        {COEF,  2},             /* 1 2 */
 
198
        {COEF,  4},             /* 2 4 */
 
199
        {COEF,  8},             /* 3 8 */
 
200
        {DEC,   M2},            /* 4 im */
 
201
        {COEF,  1},             /* 5 10 tens */
 
202
        {COEF,  2},             /* 6 20 */
 
203
        {COEF,  4},             /* 7 40 */
 
204
        {COEF,  8},             /* 8 80 */
 
205
        {DEC,   M8},            /* 9 pi */
 
206
};
 
207
 
 
208
/*
 
209
 * IRIG format first frame (1000 Hz, 20 digits, 1 s frame)
 
210
 */
 
211
struct progx progz[] = {
 
212
        {MIN,   M8},            /* 0 pi (second) */
 
213
        {COEF,  1},             /* 1 1 units */
 
214
        {COEF,  2},             /* 2 2 */
 
215
        {COEF,  4},             /* 3 4 */
 
216
        {COEF,  8},             /* 4 8 */
 
217
        {DEC,   M2},            /* 5 im */
 
218
        {COEF,  1},             /* 6 10 tens */
 
219
        {COEF,  2},             /* 7 20 */
 
220
        {COEF,  4},             /* 8 40 */
 
221
        {DEC,   M8},            /* 9 pi */
 
222
};
 
223
 
 
224
/*
 
225
 * Forward declarations
 
226
 */
 
227
void    sec(int);               /* send second */
 
228
void    digit(int);             /* encode digit */
 
229
void    peep(int, int, int);    /* send cycles */
 
230
void    delay(int);             /* delay samples */
 
231
 
 
232
/*
 
233
 * Global variables
 
234
 */
 
235
char    buffer[BUFLNG];         /* output buffer */
 
236
int     bufcnt = 0;             /* buffer counter */
 
237
int     second = 0;             /* seconds counter */
 
238
int     fd;                     /* audio codec file descriptor */
 
239
int     tone = 1000;            /* WWV sync frequency */
 
240
int     level = AUDIO_MAX_GAIN / 8; /* output level */
 
241
int     port = AUDIO_LINE_OUT;  /* output port */
 
242
int     encode = WWV;           /* encoder select */
 
243
int     leap = 0;               /* leap indicator */
 
244
int     dst = 0;                /* winter/summer time */
 
245
int     dut1 = 0;               /* DUT1 correction (sign, magnitude) */
 
246
int     utc = 0;                /* option epoch */
 
247
 
 
248
/*
 
249
 * Main program
 
250
 */
 
251
int
 
252
main(
 
253
        int     argc,           /* command line options */
 
254
        char    **argv          /* poiniter to list of tokens */
 
255
        )
 
256
{
 
257
        struct timeval tv;      /* system clock at startup */
 
258
        audio_info_t info;      /* Sun audio structure */
 
259
        struct tm *tm = NULL;   /* structure returned by gmtime */
 
260
        char    device[50];     /* audio device */
 
261
        char    code[100];      /* timecode */
 
262
        int     rval, temp, arg, sw, ptr;
 
263
        int     minute, hour, day, year;
 
264
        int     i;
 
265
 
 
266
        /*
 
267
         * Parse options
 
268
         */
 
269
        strcpy(device, DEVICE);
 
270
        year = 0;
 
271
        while ((temp = getopt(argc, argv, "a:dhilsu:v:y:")) != -1) {
 
272
                switch (temp) {
 
273
 
 
274
                case 'a':       /* specify audio device (/dev/audio) */
 
275
                        strcpy(device, optarg);
 
276
                        break;
 
277
 
 
278
                case 'd':       /* set DST for summer (WWV/H only) */
 
279
                        dst++;
 
280
                        break;
 
281
 
 
282
                case 'h':       /* select WWVH sync frequency */
 
283
                        tone = 1200;
 
284
                        break;
 
285
 
 
286
                case 'i':       /* select irig format */
 
287
                        encode = IRIG;
 
288
                        break;
 
289
 
 
290
                case 'l':       /* set leap warning bit (WWV/H only) */
 
291
                        leap++;
 
292
                        break;
 
293
 
 
294
                case 's':       /* enable speaker */
 
295
                        port |= AUDIO_SPEAKER;
 
296
                        break;
 
297
 
 
298
                case 'u':       /* set DUT1 offset (-7 to +7) */
 
299
                        sscanf(optarg, "%d", &dut1);
 
300
                        if (dut1 < 0)
 
301
                                dut1 = abs(dut1);
 
302
                        else
 
303
                                dut1 |= 0x8;
 
304
                        break;
 
305
 
 
306
                case 'v':       /* set output level (0-255) */
 
307
                        sscanf(optarg, "%d", &level);
 
308
                        break;
 
309
 
 
310
                case 'y':       /* set initial date and time */
 
311
                        sscanf(optarg, "%2d%3d%2d%2d", &year, &day,
 
312
                            &hour, &minute);
 
313
                        utc++;
 
314
                        break;
 
315
 
 
316
                defult:
 
317
                        printf("invalid option %c\n", temp);
 
318
                        break;
 
319
                }
 
320
        }
 
321
 
 
322
        /*
 
323
         * Open audio device and set options
 
324
         */
 
325
        fd = open("/dev/audio", O_WRONLY);
 
326
        if (fd <= 0) {
 
327
                printf("audio open %s\n", strerror(errno));
 
328
                exit(1);
 
329
        }
 
330
        rval = ioctl(fd, AUDIO_GETINFO, &info);
 
331
        if (rval < 0) {
 
332
                printf("audio control %s\n", strerror(errno));
 
333
                exit(0);
 
334
        }
 
335
        info.play.port = port;
 
336
        info.play.gain = level;
 
337
        info.play.sample_rate = SECOND;
 
338
        info.play.channels = 1;
 
339
        info.play.precision = 8;
 
340
        info.play.encoding = AUDIO_ENCODING_ULAW;
 
341
        printf("port %d gain %d rate %d chan %d prec %d encode %d\n",
 
342
            info.play.port, info.play.gain, info.play.sample_rate,
 
343
            info.play.channels, info.play.precision,
 
344
            info.play.encoding);
 
345
        ioctl(fd, AUDIO_SETINFO, &info);
 
346
 
 
347
        /*
 
348
         * Unless specified otherwise, read the system clock and
 
349
         * initialize the time.
 
350
         */
 
351
        if (!utc) {
 
352
                gettimeofday(&tv, NULL);
 
353
                tm = gmtime(&tv.tv_sec);
 
354
                minute = tm->tm_min;
 
355
                hour = tm->tm_hour;
 
356
                day = tm->tm_yday + 1;
 
357
                year = tm->tm_year % 100;
 
358
                second = tm->tm_sec;
 
359
 
 
360
                /*
 
361
                 * Delay the first second so the generator is accurately
 
362
                 * aligned with the system clock within one sample (125
 
363
                 * microseconds ).
 
364
                 */
 
365
                delay(SECOND - tv.tv_usec * 8 / 1000);
 
366
        }
 
367
        memset(code, 0, sizeof(code));
 
368
        switch (encode) {
 
369
 
 
370
        /*
 
371
         * For WWV/H and default time, carefully set the signal
 
372
         * generator seconds number to agree with the current time.
 
373
         */ 
 
374
        case WWV:
 
375
                printf("year %d day %d time %02d:%02d:%02d tone %d\n",
 
376
                    year, day, hour, minute, second, tone);
 
377
                sprintf(code, "%01d%03d%02d%02d%01d", year / 10, day,
 
378
                    hour, minute, year % 10);
 
379
                printf("%s\n", code);
 
380
                ptr = 8;
 
381
                for (i = 0; i <= second; i++) {
 
382
                        if (progx[i].sw == DEC)
 
383
                                ptr--;
 
384
                }
 
385
                break;
 
386
 
 
387
        /*
 
388
         * For IRIG the signal generator runs every second, so requires
 
389
         * no additional alignment.
 
390
         */
 
391
        case IRIG:
 
392
                printf("sbs %x year %d day %d time %02d:%02d:%02d\n",
 
393
                    0, year, day, hour, minute, second);
 
394
                break;
 
395
        }
 
396
 
 
397
        /*
 
398
         * Run the signal generator to generate new timecode strings
 
399
         * once per minute for WWV/H and once per second for IRIG.
 
400
         */
 
401
        while(1) {
 
402
 
 
403
                /*
 
404
                 * Crank the state machine to propagate carries to the
 
405
                 * year of century. Note that we delayed up to one
 
406
                 * second for alignment after reading the time, so this
 
407
                 * is the next second.
 
408
                 */
 
409
                second = (second + 1) % 60;
 
410
                if (second == 0) {
 
411
                        minute++;
 
412
                        if (minute >= 60) {
 
413
                                minute = 0;
 
414
                                hour++;
 
415
                        }
 
416
                        if (hour >= 24) {
 
417
                                hour = 0;
 
418
                                day++;
 
419
                        }
 
420
 
 
421
                        /*
 
422
                         * At year rollover check for leap second.
 
423
                         */
 
424
                        if (day >= (year & 0x3 ? 366 : 367)) {
 
425
                                if (leap) {
 
426
                                        sec(DATA0);
 
427
                                        printf("\nleap!");
 
428
                                        leap = 0;
 
429
                                }
 
430
                                day = 1;
 
431
                                year++;
 
432
                        }
 
433
                        if (encode == WWV) {
 
434
                                sprintf(code, "%01d%03d%02d%02d%01d",
 
435
                                    year / 10, day, hour, minute, year %
 
436
                                    10);
 
437
                                printf("\n%s\n", code);
 
438
                                ptr = 8;
 
439
                        }
 
440
                }
 
441
                if (encode == IRIG) {
 
442
                        sprintf(code, "%04x%04d%06d%02d%02d%02d", 0,
 
443
                            year, day, hour, minute, second);
 
444
                        printf("%s\n", code);
 
445
                        ptr = 19;
 
446
                }
 
447
 
 
448
                /*
 
449
                 * Generate data for the second
 
450
                 */
 
451
                switch(encode) {
 
452
 
 
453
                /*
 
454
                 * The IRIG second consists of 20 BCD digits of width-
 
455
                 * modulateod pulses at 2, 5 and 8 ms and modulated 50
 
456
                 * percent on the 1000-Hz carrier.
 
457
                 */
 
458
                case IRIG:
 
459
                        for (i = 0; i < 100; i++) {
 
460
                                if (i < 10) {
 
461
                                        sw = progz[i].sw;
 
462
                                        arg = progz[i].arg;
 
463
                                } else {
 
464
                                        sw = progy[i % 10].sw;
 
465
                                        arg = progy[i % 10].arg;
 
466
                                }
 
467
                                switch(sw) {
 
468
 
 
469
                                case COEF:      /* send BCD bit */
 
470
                                        if (code[ptr] & arg) {
 
471
                                                peep(M5, 1000, HIGH);
 
472
                                                peep(M5, 1000, LOW);
 
473
                                                printf("1");
 
474
                                        } else {
 
475
                                                peep(M2, 1000, HIGH);
 
476
                                                peep(M8, 1000, LOW);
 
477
                                                printf("0");
 
478
                                        }
 
479
                                        break;
 
480
 
 
481
                                case DEC:       /* send IM/PI bit */
 
482
                                        ptr--;
 
483
                                        printf(" ");
 
484
                                        peep(arg, 1000, HIGH);
 
485
                                        peep(10 - arg, 1000, LOW);
 
486
                                        break;
 
487
 
 
488
                                case MIN:       /* send data bit */
 
489
                                        peep(arg, 1000, HIGH);
 
490
                                        peep(10 - arg, 1000, LOW);
 
491
                                        printf("M ");
 
492
                                        break;
 
493
                                }
 
494
                                if (ptr < 0)
 
495
                                        break;
 
496
                        }
 
497
                        printf("\n");
 
498
                        break;
 
499
 
 
500
                /*
 
501
                 * The WWV/H second consists of 9 BCD digits of width-
 
502
                 * modulateod pulses 200, 500 and 800 ms at 100-Hz.
 
503
                 */
 
504
                case WWV:
 
505
                        sw = progx[second].sw;
 
506
                        arg = progx[second].arg;
 
507
                        switch(sw) {
 
508
 
 
509
                        case DATA:              /* send data bit */
 
510
                                sec(arg);
 
511
                                break;
 
512
 
 
513
                        case COEF:              /* send BCD bit */
 
514
                                if (code[ptr] & arg) {
 
515
                                        sec(DATA1);
 
516
                                        printf("1");
 
517
                                } else {
 
518
                                        sec(DATA0);
 
519
                                        printf("0");
 
520
                                }
 
521
                                break;
 
522
 
 
523
                        case LEAP:              /* send leap bit */
 
524
                                if (leap) {
 
525
                                        sec(DATA1);
 
526
                                        printf("L ");
 
527
                                } else {
 
528
                                        sec(DATA0);
 
529
                                        printf("  ");
 
530
                                }
 
531
                                break;
 
532
 
 
533
                        case DEC:               /* send data bit */
 
534
                                ptr--;
 
535
                                sec(arg);
 
536
                                printf(" ");
 
537
                                break;
 
538
 
 
539
                        case MIN:               /* send minute sync */
 
540
                                peep(arg, tone, HIGH);
 
541
                                peep(1000 - arg, tone, OFF);
 
542
                                break;
 
543
 
 
544
                        case DUT1:              /* send DUT1 bits */
 
545
                                if (dut1 & arg)
 
546
                                        sec(DATA1);
 
547
                                else
 
548
                                        sec(DATA0);
 
549
                                break;
 
550
                                
 
551
                        case DST1:              /* send DST1 bit */
 
552
                                ptr--;
 
553
                                if (dst)
 
554
                                        sec(DATA1);
 
555
                                else
 
556
                                        sec(DATA0);
 
557
                                printf(" ");
 
558
                                break;
 
559
 
 
560
                        case DST2:              /* send DST2 bit */
 
561
                                if (dst)
 
562
                                        sec(DATA1);
 
563
                                else
 
564
                                        sec(DATA0);
 
565
                                break;
 
566
                        }
 
567
                }
 
568
        }
 
569
}
 
570
 
 
571
 
 
572
/*
 
573
 * Generate WWV/H 0 or 1 data pulse.
 
574
 */
 
575
void sec(
 
576
        int     code            /* DATA0, DATA1, PI */
 
577
        )
 
578
{
 
579
        /*
 
580
         * The WWV data pulse begins with 5 ms of 1000 Hz follwed by a
 
581
         * guard time of 25 ms. The data pulse is 170, 570 or 770 ms at
 
582
         * 100 Hz corresponding to 0, 1 or position indicator (PI),
 
583
         * respectively. Note the 100-Hz data pulses are transmitted 6
 
584
         * dB below the 1000-Hz sync pulses. Originally the data pulses
 
585
         * were transmited 10 dB below the sync pulses, but the station
 
586
         * engineers increased that to 6 dB because the Heath GC-1000
 
587
         * WWV/H radio clock worked much better.
 
588
         */
 
589
        peep(5, tone, HIGH);            /* send seconds tick */
 
590
        peep(25, tone, OFF);
 
591
        peep(code - 30, 100, LOW);      /* send data */
 
592
        peep(1000 - code, 100, OFF);
 
593
}
 
594
 
 
595
 
 
596
/*
 
597
 * Generate cycles of 100 Hz or any multiple of 100 Hz.
 
598
 */
 
599
void peep(
 
600
        int     pulse,          /* pulse length (ms) */
 
601
        int     freq,           /* frequency (Hz) */
 
602
        int     amp             /* amplitude */
 
603
        )
 
604
{
 
605
        int     increm;         /* phase increment */
 
606
        int     i, j;
 
607
 
 
608
        if (amp == OFF || freq == 0)
 
609
                increm = 10;
 
610
        else
 
611
                increm = freq / 100;
 
612
        j = 0;
 
613
        for (i = 0 ; i < pulse * 8; i++) {
 
614
                switch (amp) {
 
615
 
 
616
                case HIGH:
 
617
                        buffer[bufcnt++] = ~c6000[j];
 
618
                        break;
 
619
 
 
620
                case LOW:
 
621
                        buffer[bufcnt++] = ~c3000[j];
 
622
                        break;
 
623
 
 
624
                default:
 
625
                        buffer[bufcnt++] = ~0;
 
626
                }
 
627
                if (bufcnt >= BUFLNG) {
 
628
                        write(fd, buffer, BUFLNG);
 
629
                        bufcnt = 0;
 
630
                }
 
631
                j = (j + increm) % 80;
 
632
        }
 
633
}
 
634
 
 
635
 
 
636
/*
 
637
 * Delay for initial phasing
 
638
 */
 
639
void delay (
 
640
        int     delay           /* delay in samples */
 
641
        )
 
642
{
 
643
        int     samples;        /* samples remaining */
 
644
 
 
645
        samples = delay;
 
646
        memset(buffer, 0, BUFLNG);
 
647
        while (samples >= BUFLNG) {
 
648
                write(fd, buffer, BUFLNG);
 
649
                samples -= BUFLNG;
 
650
        }
 
651
                write(fd, buffer, samples);
 
652
}