111
111
* indicator, year of century, day of year and time of day. The status
112
112
* indicator and year are not produced by some IRIG devices. Following
113
113
* these fields are the signal amplitude (0-8100), codec gain (0-255),
114
* field phase (0-79), time constant (2-20), modulation index (0-1),
115
* carrier phase error (0+-0.5) and carrier frequency error (PPM). The
116
* last field is the on-time timestamp in NTP format.
114
* modulation index (0-1), time constant (2-20), carrier phase error
115
* (us) and carrier frequency error (PPM). The last field is the on-time
116
* timestamp in NTP format.
118
118
* The fraction part of the on-time timestamp is a good indicator of how
119
* well the driver is doing. With an UltrSPARC 30, this thing can keep
120
* the clock within a few tens of microseconds relative to the IRIG-B
121
* signal. Accuracy with IRIG-E is about ten times worse.
119
* well the driver is doing. With an UltrSPARC 30 and Solaris 2.7, this
120
* thing can keep the clock within a few tens of microseconds relative
121
* to the IRIG-B signal. Accuracy with IRIG-E is about ten times worse.
122
* Unfortunately, Sun broke the 2.7 audio driver in 2.8, which has a
123
* 10-ms sawtooth modulation. The driver attempts to remove the
124
* modulation by some clever estimation techniques which mostly work.
125
* Your experience may vary.
123
127
* Unlike other drivers, which can have multiple instantiations, this
124
128
* one supports only one. It does not seem likely that more than one
130
* Fudge flag2 selects the audio input port, where 0 is the mike port
134
* Fudge flag4 causes the dubugging output described above to be
135
* recorded in the clockstats file. When the audio driver is compiled,
136
* fudge flag2 selects the audio input port, where 0 is the mike port
131
137
* (default) and 1 is the line-in port. It does not seem useful to
132
138
* select the compact disc player port. Fudge flag3 enables audio
133
* monitoring of the input signal. For this purpose, the speaker volume
134
* must be set before the driver is started. Fudge flag4 causes the
135
* debugging output described above to be recorded in the clockstats
136
* file. Any of these flags can be changed during operation with the
139
* monitoring of the input signal. For this purpose, the monitor gain is
140
* set to a default value. Fudgetime2 is used as a frequency vernier for
141
* broken codec sample frequency.
141
144
* Interface definitions
155
158
#define MINTC 2 /* min PLL time constant */
156
159
#define MAXTC 20 /* max PLL time constant max */
157
160
#define MAXSIG 6000. /* maximum signal level */
161
#define MAXCLP 100 /* max clips above reference per s */
158
162
#define DRPOUT 100. /* dropout signal level */
159
163
#define MODMIN 0.5 /* minimum modulation index */
160
164
#define MAXFREQ (250e-6 * SECOND) /* freq tolerance (.025%) */
161
165
#define PI 3.1415926535 /* the real thing */
167
#define WIGGLE 11 /* wiggle filter length */
168
#endif /* IRIG_SUCKS */
164
* Experimentally determined fudge factors
171
* Experimentally determined filter delays
166
#define IRIG_B .0019 /* IRIG-B phase delay */
167
#define IRIG_E .0019 /* IRIG-E phase delay */
173
#define IRIG_B .0019 /* IRIG-B filter delay */
174
#define IRIG_E .0019 /* IRIG-E filter delay */
170
177
* Data bit definitions
191
199
u_char timecode[21]; /* timecode string */
192
200
l_fp timestamp; /* audio sample timestamp */
193
201
l_fp tick; /* audio sample increment */
194
double comp[SIZE]; /* decompanding table */
195
202
double integ[BAUD]; /* baud integrator */
196
203
double phase, freq; /* logical clock phase and frequency */
197
204
double zxing; /* phase detector integrator */
198
double yxing; /* phase detector display */
205
double yxing; /* cycle phase */
206
double exing; /* envelope phase */
199
207
double modndx; /* modulation index */
200
208
double irig_b; /* IRIG-B signal amplitude */
201
209
double irig_e; /* IRIG-E signal amplitude */
202
210
int errflg; /* error flags */
203
int bufcnt; /* samples in buffer */
204
int bufptr; /* buffer index pointer */
205
int pollcnt; /* poll counter */
212
* Audio codec variables
214
double comp[SIZE]; /* decompanding table */
206
215
int port; /* codec port */
207
216
int gain; /* codec gain */
217
int mongain; /* codec monitor gain */
208
218
int clipcnt; /* sample clipped count */
209
219
int seccnt; /* second interval counter */
210
int decim; /* sample decimation factor */
282
296
* Global variables
284
298
static char hexchar[] = { /* really quick decoding table */
285
'0', '8', '4', 'c', /* 0000 0001 0010 0011 */
286
'2', 'a', '6', 'e', /* 0100 0101 0110 0111 */
287
'1', '9', '5', 'd', /* 1000 1001 1010 1011 */
288
'3', 'b', '7', 'f' /* 1100 1101 1110 1111 */
299
'0', '8', '4', 'c', /* 0000 0001 0010 0011 */
300
'2', 'a', '6', 'e', /* 0100 0101 0110 0111 */
301
'1', '9', '5', 'd', /* 1000 1001 1010 1011 */
302
'3', 'b', '7', 'f' /* 1100 1101 1110 1111 */
420
434
* Main loop - read until there ain't no more. Note codec
421
435
* samples are bit-inverted.
437
DTOLFP((double)rbufp->recv_length / SECOND, <emp);
438
L_SUB(&rbufp->recv_time, <emp);
423
439
up->timestamp = rbufp->recv_time;
424
up->bufcnt = rbufp->recv_length;
425
DTOLFP((double)up->bufcnt / SECOND, <emp);
426
L_SUB(&up->timestamp, <emp);
427
440
dpt = rbufp->recv_buffer;
428
for (up->bufptr = 0; up->bufptr < up->bufcnt; up->bufptr++) {
441
for (bufcnt = 0; bufcnt < rbufp->recv_length; bufcnt++) {
429
442
sample = up->comp[~*dpt++ & 0xff];
432
445
* Clip noise spikes greater than MAXSIG. If no clips,
433
446
* increase the gain a tad; if the clips are too high,
434
* decrease a tad. Choose either IRIG-B or IRIG-E
435
* according to the energy at the respective filter
438
449
if (sample > MAXSIG) {
447
* Variable frequency oscillator. A phase change of one
448
* unit produces a change of 360 degrees; a frequency
449
* change of one unit produces a change of 1 Hz.
458
* Variable frequency oscillator. The codec oscillator
459
* runs at the nominal rate of 8000 samples per second,
460
* or 125 us per sample. A frequency change of one unit
461
* results in either duplicating or deleting one sample
462
* per second, which results in a frequency change of
451
465
up->phase += up->freq / SECOND;
466
up->phase += pp->fudgetime2 / 1e6;
452
467
if (up->phase >= .5) {
454
469
} else if (up->phase < -.5) {
629
643
up->maxsignal = up->intmax;
630
644
up->noise = up->intmin;
631
645
if (up->maxsignal < DRPOUT)
632
up->errflg |= IRIG_ERR_AMP;
634
up->modndx = (up->intmax - up->intmin) / up->intmax;
646
up->errflg |= IRIG_ERR_AMP;
647
if (up->maxsignal > 0)
648
up->modndx = (up->intmax - up->intmin) /
637
652
if (up->modndx < MODMIN)
638
up->errflg |= IRIG_ERR_MOD;
653
up->errflg |= IRIG_ERR_MOD;
639
654
up->intmin = 1e6; up->intmax = 0;
640
655
if (up->errflg & (IRIG_ERR_AMP | IRIG_ERR_FREQ |
641
IRIG_ERR_MOD | IRIG_ERR_SYNCH)) {
656
IRIG_ERR_MOD | IRIG_ERR_SYNCH)) {
825
841
up->fieldcnt = 0;
827
up->montime = pp->lastrec;
828
843
if (up->errflg == 0) {
830
refclock_process(pp);
832
if (up->timecnt >= MAXSTAGE) {
833
refclock_receive(peer);
848
* You really don't wanna know what comes down
849
* here. Leave it to say Solaris 2.8 broke the
850
* nice clean audio stream, apparently affected
851
* by a 5-ms sawtooth jitter. Sundown on
852
* Solaris. This leaves a little twilight.
854
* The scheme involves differentiation, forward
855
* learning and integration. The sawtooth has a
856
* period of 11 seconds. The timestamp
857
* differences are integrated and subtracted
861
L_SUB(<emp, &pp->lastref);
866
pp->lastref = pp->lastrec;
867
if (!L_ISNEG(<emp))
870
L_ADD(&up->wigwag, <emp);
871
L_SUB(&pp->lastrec, &up->wigwag);
872
up->wiggle[up->wp] = ltemp;
875
* Bottom fisher. To understand this, you have
876
* to know about velocity microphones and AM
877
* transmitters. No further explanation is
878
* offered, as this is truly a black art.
880
up->wigbot[up->wp] = pp->lastrec;
881
for (i = 0; i < WIGGLE; i++) {
883
up->wigbot[i].l_ui++;
884
L_SUB(&pp->lastrec, &up->wigbot[i]);
885
if (L_ISNEG(&pp->lastrec))
889
pp->lastrec = up->wigbot[i];
893
up->wuggle = pp->lastrec;
894
refclock_process(pp);
895
#else /* IRIG_SUCKS */
896
pp->lastref = pp->lastrec;
897
up->wuggle = pp->lastrec;
898
refclock_process(pp);
899
#endif /* IRIG_SUCKS */
848
912
if (up->xptr < 2)
849
913
up->xptr = 2 * FIELD;
850
914
up->timecode[--up->xptr] = hexchar[(up->bits >> 5) &
852
916
up->timecode[--up->xptr] = hexchar[up->bits & 0xf];
853
917
up->fieldcnt = (up->fieldcnt + 1) % FIELD;
854
918
if (up->fieldcnt == 0) {
857
* End of field. Decode the timecode, adjust the
858
* gain and set the input port. Set the port
859
* here on the assumption somebody might even
921
* End of field. Decode the timecode and wind
922
* the clock. Not all IRIG generators have the
923
* year; if so, it is nonzero after year 2000.
924
* Not all have the hardware status bit; if so,
925
* it is lit when the source is okay and dim
926
* when bad. We watch this only if the year is
927
* nonzero. Not all are configured for signature
928
* control. If so, all BCD digits are set to
929
* zero if the source is bad. In this case the
930
* refclock_process() will reject the timecode
862
933
up->xptr = 2 * FIELD;
863
934
if (sscanf((char *)up->timecode,
864
"%6s%2d%c%2s%3d%2d%2d%2d",
865
sbs, &pp->year, &syncchar, spare, &pp->day,
866
&pp->hour, &pp->minute, &pp->second) != 8)
867
pp->leap = LEAP_NOTINSYNC;
935
"%6s%2d%c%2s%3d%2d%2d%2d", sbs, &pp->year,
936
&syncchar, spare, &pp->day, &pp->hour,
937
&pp->minute, &pp->second) != 8)
938
pp->leap = LEAP_NOTINSYNC;
869
pp->leap = LEAP_NOWARNING;
940
pp->leap = LEAP_NOWARNING;
870
941
up->second = (up->second + up->decim) % 60;
945
up->errflg |= IRIG_ERR_CHECK;
871
947
if (pp->second != up->second)
872
up->errflg |= IRIG_ERR_CHECK;
948
up->errflg |= IRIG_ERR_CHECK;
873
949
up->second = pp->second;
874
950
sprintf(pp->a_lastcode,
875
"%02x %c %2d %3d %02d:%02d:%02d %4.0f %3d %6.3f %2d %2d %6.3f %6.1f %s",
876
up->errflg, syncchar, pp->year, pp->day,
877
pp->hour, pp->minute, pp->second,
878
up->maxsignal, up->gain, up->modndx,
879
up->envxing, up->tc, up->yxing, up->freq *
880
1e6 / SECOND, ulfptoa(&up->montime, 6));
951
"%02x %c %2d %3d %02d:%02d:%02d %4.0f %3d %6.3f %2d %6.1f %6.1f %s",
952
up->errflg, syncchar, pp->year, pp->day,
953
pp->hour, pp->minute, pp->second,
954
up->maxsignal, up->gain, up->modndx,
955
up->tc, up->exing * 1e6 / SECOND, up->freq *
956
1e6 / SECOND, ulfptoa(&up->wuggle, 6));
881
957
pp->lencode = strlen(pp->a_lastcode);
882
if (up->timecnt == 0 || pp->sloppyclockflag &
884
record_clock_stats(&peer->srcadr,
958
if (pp->sloppyclockflag & CLK_FLAG4) {
959
record_clock_stats(&peer->srcadr,
888
printf("irig: %s\n", pp->a_lastcode);
889
965
#endif /* DEBUG */
892
969
up->lastbit = bit;