Lines Matching +full:buffered +full:- +full:positive
2 * refclock_wwv - clock driver for NIST WWV/H time/frequency station
43 * kHz and mu-law companding. This is the same standard as used by the
53 * Report 97-8-1, University of Delaware, August 1997, 25 pp., available
61 * a nonzero ICOM ID select code. The C-IV trace is turned on if the
68 * port, where 0 is the mike port (default) and 1 is the line-in port.
74 * CEVNT_PROP propagation failure - no stations heard
82 #define PRECISION (-10) /* precision assumed (about 1 ms) */
99 #define AUDIO_PHI 5e-6 /* dispersion growth factor */
201 * Tone frequency definitions. The increments are for 4.5-deg sine
233 * The on-time synchronization point is the positive-going zero crossing
234 * of the first cycle of the 5-ms second pulse. The IIR baseband filter
236 * ms at 1000 Hz. The fudge value -0.45 ms due to the codec and other
242 * The resulting offsets with a 2.4-GHz P4 running FreeBSD 6.1 are
243 * generally within .02 ms short-term with .02 ms jitter. The long-term
247 #define PDELAY ((.91 + 4.7 - 0.45) / 1000) /* system delay (s) */
250 * Table of sine values at 4.5-degree increments. This is used by the
254 0.000000e+00, 7.845910e-02, 1.564345e-01, 2.334454e-01, /* 0-3 */
255 3.090170e-01, 3.826834e-01, 4.539905e-01, 5.224986e-01, /* 4-7 */
256 5.877853e-01, 6.494480e-01, 7.071068e-01, 7.604060e-01, /* 8-11 */
257 8.090170e-01, 8.526402e-01, 8.910065e-01, 9.238795e-01, /* 12-15 */
258 9.510565e-01, 9.723699e-01, 9.876883e-01, 9.969173e-01, /* 16-19 */
259 1.000000e+00, 9.969173e-01, 9.876883e-01, 9.723699e-01, /* 20-23 */
260 9.510565e-01, 9.238795e-01, 8.910065e-01, 8.526402e-01, /* 24-27 */
261 8.090170e-01, 7.604060e-01, 7.071068e-01, 6.494480e-01, /* 28-31 */
262 5.877853e-01, 5.224986e-01, 4.539905e-01, 3.826834e-01, /* 32-35 */
263 3.090170e-01, 2.334454e-01, 1.564345e-01, 7.845910e-02, /* 36-39 */
264 -0.000000e+00, -7.845910e-02, -1.564345e-01, -2.334454e-01, /* 40-43 */
265 -3.090170e-01, -3.826834e-01, -4.539905e-01, -5.224986e-01, /* 44-47 */
266 -5.877853e-01, -6.494480e-01, -7.071068e-01, -7.604060e-01, /* 48-51 */
267 -8.090170e-01, -8.526402e-01, -8.910065e-01, -9.238795e-01, /* 52-55 */
268 -9.510565e-01, -9.723699e-01, -9.876883e-01, -9.969173e-01, /* 56-59 */
269 -1.000000e+00, -9.969173e-01, -9.876883e-01, -9.723699e-01, /* 60-63 */
270 -9.510565e-01, -9.238795e-01, -8.910065e-01, -8.526402e-01, /* 64-67 */
271 -8.090170e-01, -7.604060e-01, -7.071068e-01, -6.494480e-01, /* 68-71 */
272 -5.877853e-01, -5.224986e-01, -4.539905e-01, -3.826834e-01, /* 72-75 */
273 -3.090170e-01, -2.334454e-01, -1.564345e-01, -7.845910e-02, /* 76-79 */
294 #define DECIM9 4 /* BCD digit 0-9 */
295 #define DECIM6 5 /* BCD digit 0-6 */
296 #define DECIM3 6 /* BCD digit 0-3 */
297 #define DECIM2 7 /* BCD digit 0-2 */
365 {MSCBIT, DUTS}, /* 50 dut+- */
379 * BCD coefficients for maximum-likelihood digit decode
381 #define P15 1. /* max positive number */
382 #define N15 -1. /* max negative number */
385 * Digits 0-9
388 #define N9 (N15 / 4) /* space (-1) */
405 * Digits 0-6 (minute tens)
408 #define N6 (N15 / 3) /* space (-1) */
422 * Digits 0-3 (day hundreds)
425 #define N3 (N15 / 2) /* space (-1) */
436 * Digits 0-2 (hour tens)
439 #define N2 (N15 / 2) /* space (-1) */
461 * order. The maximum-likelihood timecode is formed from the digits
462 * corresponding to the maximum-likelihood values reading in the
471 double like[10]; /* likelihood integrator 0-9 */
537 int repoch; /* buffered sync epoch */
627 * wwv_start - open the devices and initialize data for processing
663 pp = peer->procptr;
664 pp->io.clock_recv = wwv_receive;
665 pp->io.srcclock = peer;
666 pp->io.datalen = 0;
667 pp->io.fd = fd;
668 if (!io_addclock(&pp->io)) {
673 pp->unitptr = up;
678 peer->precision = PRECISION;
679 pp->clockdesc = DESCRIPTION;
682 * The companded samples are encoded sign-magnitude. The table
685 up->comp[0] = up->comp[OFFSET] = 0.;
686 up->comp[1] = 1.; up->comp[OFFSET + 1] = -1.;
687 up->comp[2] = 3.; up->comp[OFFSET + 2] = -3.;
690 up->comp[i] = up->comp[i - 1] + step;
691 up->comp[OFFSET + i] = -up->comp[i];
695 DTOLFP(1. / WWV_SEC, &up->tick);
701 up->decvec[MN].radix = 10; /* minutes */
702 up->decvec[MN + 1].radix = 6;
703 up->decvec[HR].radix = 10; /* hours */
704 up->decvec[HR + 1].radix = 3;
705 up->decvec[DA].radix = 10; /* days */
706 up->decvec[DA + 1].radix = 10;
707 up->decvec[DA + 2].radix = 4;
708 up->decvec[YR].radix = 10; /* years */
709 up->decvec[YR + 1].radix = 10;
724 if (peer->ttl != 0) {
725 if (peer->ttl & 0x80)
726 up->fd_icom = icom_init("/dev/icom", B1200,
729 up->fd_icom = icom_init("/dev/icom", B9600,
732 if (up->fd_icom > 0) {
735 close(up->fd_icom);
736 up->fd_icom = 0;
752 * wwv_shutdown - shut down the clock
763 pp = peer->procptr;
764 up = pp->unitptr;
768 io_closeclock(&pp->io);
770 if (up->fd_icom > 0)
771 close(up->fd_icom);
778 * wwv_receive - receive data from the audio device
802 peer = rbufp->recv_peer;
803 pp = peer->procptr;
804 up = pp->unitptr;
807 * Main loop - read until there ain't no more. Note codec
808 * samples are bit-inverted.
810 DTOLFP((double)rbufp->recv_length / WWV_SEC, <emp);
811 L_SUB(&rbufp->recv_time, <emp);
812 up->timestamp = rbufp->recv_time;
813 dpt = rbufp->recv_buffer;
814 for (bufcnt = 0; bufcnt < rbufp->recv_length; bufcnt++) {
815 sample = up->comp[~*dpt++ & 0xff];
824 up->clipcnt++;
825 } else if (sample < -MAXAMP) {
826 sample = -MAXAMP;
827 up->clipcnt++;
838 up->phase += (up->freq + clock_codec) / WWV_SEC;
839 if (up->phase >= .5) {
840 up->phase -= 1.;
841 } else if (up->phase < -.5) {
842 up->phase += 1.;
848 L_ADD(&up->timestamp, &up->tick);
854 if (pp->sloppyclockflag & CLK_FLAG2)
855 up->port = 2;
857 up->port = 1;
858 if (pp->sloppyclockflag & CLK_FLAG3)
859 up->mongain = MONGAIN;
861 up->mongain = 0;
866 * wwv_poll - called by the transmit procedure
882 pp = peer->procptr;
883 up = pp->unitptr;
884 if (up->errflg)
885 refclock_report(peer, up->errflg);
886 up->errflg = 0;
887 pp->polls++;
892 * wwv_rf - process signals and demodulate to baseband
895 * output signal is the 100-Hz filtered baseband data signal in
899 * There are two 1-s ramps used by this program. Both count the 8000
902 * counts the samples starting at the 5-ms second sync pulse found
905 * There are two 1-m ramps used by this program. The mphase ramp counts
908 * the minute starting at the 800-ms minute sync pulse found during the
931 static double lpf[5]; /* 150-Hz lpf delay line */
933 static double bpf[9]; /* 1000/1200-Hz bpf delay line */
935 static double mf[41]; /* 1000/1200-Hz mf delay line */
976 pp = peer->procptr;
977 up = pp->unitptr;
998 * Baseband data demodulation. The 100-Hz subcarrier is
999 * extracted using a 150-Hz IIR lowpass filter. This attenuates
1000 * the 1000/1200-Hz sync signals, as well as the 440-Hz and
1001 * 600-Hz tones and most of the noise and voice modulation
1008 * Matlab IIR 4th-order IIR elliptic, 150 Hz lowpass, 0.2 dB
1009 * passband ripple, -50 dB stopband ripple, phase delay 0.97 ms.
1011 data = (lpf[4] = lpf[3]) * 8.360961e-01;
1012 data += (lpf[3] = lpf[2]) * -3.481740e+00;
1014 data += (lpf[1] = lpf[0]) * -3.807229e+00;
1015 lpf[0] = isig * DGAIN - data;
1016 data = lpf[0] * 3.281435e-03
1017 + lpf[1] * -1.149947e-02
1018 + lpf[2] * 1.654858e-02
1019 + lpf[3] * -1.149947e-02
1020 + lpf[4] * 3.281435e-03;
1023 * The 100-Hz data signal is demodulated using a pair of
1026 * multiplying the filtered signal by 100-Hz sine and cosine
1027 * signals, respectively. The signals are processed by 170-ms
1032 i = up->datapt;
1033 up->datapt = (up->datapt + IN100) % 80;
1035 up->irig -= ibuf[iptr];
1037 up->irig += dtemp;
1041 up->qrig -= qbuf[iptr];
1043 up->qrig += dtemp;
1048 * extracted using a 600-Hz IIR bandpass filter. This removes
1049 * the 100-Hz data subcarrier, as well as the 440-Hz and 600-Hz
1052 * Matlab 4th-order IIR elliptic, 800-1400 Hz bandpass, 0.2 dB
1053 * passband ripple, -50 dB stopband ripple, phase delay 0.91 ms.
1055 syncx = (bpf[8] = bpf[7]) * 4.897278e-01;
1056 syncx += (bpf[7] = bpf[6]) * -2.765914e+00;
1058 syncx += (bpf[5] = bpf[4]) * -1.517732e+01;
1060 syncx += (bpf[3] = bpf[2]) * -1.814365e+01;
1062 syncx += (bpf[1] = bpf[0]) * -4.735040e+00;
1063 bpf[0] = isig - syncx;
1064 syncx = bpf[0] * 8.203628e-03
1065 + bpf[1] * -2.375732e-02
1066 + bpf[2] * 3.353214e-02
1067 + bpf[3] * -4.080258e-02
1068 + bpf[4] * 4.605479e-02
1069 + bpf[5] * -4.080258e-02
1070 + bpf[6] * 3.353214e-02
1071 + bpf[7] * -2.375732e-02
1072 + bpf[8] * 8.203628e-03;
1080 * by 1000-Hz (WWV) and 1200-Hz (WWVH) sine and cosine signals,
1081 * respectively. The WWV and WWVH signals are processed by 800-
1085 * processed by 5-ms synchronous matched filters and combined to
1094 up->mphase = (up->mphase + 1) % WWV_MIN;
1095 epoch = up->mphase % WWV_SEC;
1104 ciamp -= cibuf[jptr];
1107 csiamp -= csibuf[kptr];
1113 cqamp -= cqbuf[jptr];
1116 csqamp -= csqbuf[kptr];
1120 sp = &up->mitig[up->achan].wwv;
1121 sp->amp = sqrt(ciamp * ciamp + cqamp * cqamp) / SYNCYC;
1122 if (!(up->status & MSYNC))
1123 wwv_qrz(peer, sp, (int)(pp->fudgetime1 * WWV_SEC));
1132 hiamp -= hibuf[jptr];
1135 hsiamp -= hsibuf[kptr];
1141 hqamp -= hqbuf[jptr];
1144 hsqamp -= hsqbuf[kptr];
1148 rp = &up->mitig[up->achan].wwvh;
1149 rp->amp = sqrt(hiamp * hiamp + hqamp * hqamp) / SYNCYC;
1150 if (!(up->status & MSYNC))
1151 wwv_qrz(peer, rp, (int)(pp->fudgetime2 * WWV_SEC));
1159 if (up->mphase == 0) {
1160 up->watch++;
1161 if (!(up->status & MSYNC)) {
1170 up->watch = 0;
1178 if (up->status & LEPSEC) {
1179 up->mphase -= WWV_SEC;
1180 if (up->mphase < 0)
1181 up->mphase += WWV_MIN;
1192 * already synchronized to the second, the buffered sync epoch
1201 if (up->status & MSYNC) {
1203 } else if (up->sptr != NULL) {
1204 sp = up->sptr;
1205 if (sp->metric >= TTHR && epoch == sp->mepoch % WWV_SEC)
1207 up->rsec = (60 - sp->mepoch / WWV_SEC) % 60;
1208 up->rphase = 0;
1209 up->status |= MSYNC;
1210 up->watch = 0;
1211 if (!(up->status & SSYNC))
1212 up->repoch = up->yepoch = epoch;
1214 up->repoch = up->yepoch;
1220 * The second sync pulse is extracted using 5-ms (40 sample) FIR
1226 if (up->status & SELV)
1229 else if (up->status & SELH)
1236 * Enhance the seconds sync pulse using a 1-s (8000-sample) comb
1246 dtemp = (epobuf[epoch] += (mfsync - epobuf[epoch]) /
1247 up->avgint);
1253 j = epoch - 6 * MS;
1259 up->epomax = epomax;
1260 up->eposnr = wwv_snr(epomax, nxtmax);
1261 epopos -= TCKCYC * MS;
1265 if (!(up->status & SSYNC))
1266 up->alarm |= SYNERR;
1268 if (!(up->status & MSYNC))
1275 * wwv_qrz - identify and acquire WWV/WWVH minute sync pulse
1281 * involves searching through the entire 480,000-sample minute. The
1287 * amounts to a range-gate discriminator. A valid pulse must have peak
1306 pp = peer->procptr;
1307 up = pp->unitptr;
1314 epoch = up->mphase - pdelay - SYNSIZ;
1317 if (sp->amp > sp->maxeng) {
1318 sp->maxeng = sp->amp;
1319 sp->pos = epoch;
1321 sp->noieng += sp->amp;
1330 if (up->mphase == 0) {
1331 sp->synmax = sp->maxeng;
1332 sp->synsnr = wwv_snr(sp->synmax, (sp->noieng -
1333 sp->synmax) / WWV_MIN);
1334 if (sp->count == 0)
1335 sp->lastpos = sp->pos;
1336 epoch = (sp->pos - sp->lastpos) % WWV_MIN;
1337 sp->reach <<= 1;
1338 if (sp->reach & (1 << AMAX))
1339 sp->count--;
1340 if (sp->synmax > ATHR && sp->synsnr > ASNR) {
1342 sp->reach |= 1;
1343 sp->count++;
1344 sp->mepoch = sp->lastpos = sp->pos;
1345 } else if (sp->count == 1) {
1346 sp->lastpos = sp->pos;
1349 if (up->watch > ACQSN)
1350 sp->metric = 0;
1352 sp->metric = wwv_metric(sp);
1353 if (pp->sloppyclockflag & CLK_FLAG4) {
1356 up->status, up->gain, sp->refid,
1357 sp->reach & 0xffff, sp->metric, sp->synmax,
1358 sp->synsnr, sp->pos % WWV_SEC, epoch);
1359 record_clock_stats(&peer->srcadr, tbuf);
1365 sp->maxeng = sp->noieng = 0;
1371 * wwv_endpoc - identify and acquire second sync pulse
1375 * disciplines the sample clock using a frequency-lock loop (FLL).
1380 * great deal of heavy-handed heuristic data filtering and grooming.
1407 pp = peer->procptr;
1408 up = pp->unitptr;
1421 if (up->epomax < STHR || up->eposnr < SSNR) {
1422 up->status &= ~(SSYNC | FGATE);
1426 if (!(up->status & (SELV | SELH)))
1430 * A three-stage median filter is used to help denoise the
1465 tmp2 = (tepoch - xepoch) % WWV_SEC;
1468 if (syncnt > SCMP && up->status & MSYNC && (up->status &
1469 FGATE || scount - zcount <= up->avgint)) {
1470 up->status |= SSYNC;
1471 up->yepoch = tepoch;
1479 if ((pp->sloppyclockflag & CLK_FLAG4) && !(up->status &
1483 up->status, up->gain, tepoch, up->epomax,
1484 up->eposnr, tmp2, avgcnt, syncnt,
1486 record_clock_stats(&peer->srcadr, tbuf);
1493 if (avgcnt < up->avgint) {
1499 * The sample clock frequency is disciplined using a first-order
1506 * epoch difference (125-us units) and time difference (seconds)
1538 * to zero; if it decrements to -3, the interval is halved and
1541 dtemp = (mepoch - zepoch) % WWV_SEC;
1542 if (up->status & FGATE) {
1544 up->freq += (dtemp / 2.) / ((mcount - zcount) *
1546 if (up->freq > MAXFREQ)
1547 up->freq = MAXFREQ;
1548 else if (up->freq < -MAXFREQ)
1549 up->freq = -MAXFREQ;
1554 if (up->avgint < MAXAVG) {
1555 up->avgint <<= 1;
1561 if (avginc > -3) {
1562 avginc--;
1564 if (up->avgint > MINAVG) {
1565 up->avgint >>= 1;
1571 if (pp->sloppyclockflag & CLK_FLAG4) {
1574 up->status, up->epomax, up->eposnr, mepoch,
1575 up->avgint, maxrun, mcount - zcount, dtemp,
1576 up->freq * 1e6 / WWV_SEC);
1577 record_clock_stats(&peer->srcadr, tbuf);
1587 up->status |= FGATE;
1595 * wwv_epoch - epoch scanner
1597 * This routine extracts data signals from the 100-Hz subcarrier. It
1609 * disciplined using the hardlimited quadrature-phase signal sampled at
1610 * the same time as the in-phase signal. The phase tracking loop uses
1611 * phase adjustments of plus-minus one sample (125 us).
1623 pp = peer->procptr;
1624 up = pp->unitptr;
1633 cp = &up->mitig[up->achan];
1634 if (cp->wwv.amp > cp->wwv.syneng)
1635 cp->wwv.syneng = cp->wwv.amp;
1636 if (cp->wwvh.amp > cp->wwvh.syneng)
1637 cp->wwvh.syneng = cp->wwvh.amp;
1638 if (up->rphase == 800 * MS)
1639 up->repoch = up->yepoch;
1643 * This gives a guard time of +-15 ms from the beginning of the
1650 if (up->rphase == 15 * MS)
1651 sigmin = sigzer = sigone = up->irig;
1656 * compute the SNR. Use the Q sample to adjust the 100-Hz
1659 if (up->rphase == 200 * MS) {
1660 sigzer = up->irig;
1661 engmax = sqrt(up->irig * up->irig + up->qrig *
1662 up->qrig);
1663 up->datpha = up->qrig / up->avgint;
1664 if (up->datpha >= 0) {
1665 up->datapt++;
1666 if (up->datapt >= 80)
1667 up->datapt -= 80;
1669 up->datapt--;
1670 if (up->datapt < 0)
1671 up->datapt += 80;
1680 else if (up->rphase == 500 * MS)
1681 sigone = up->irig;
1685 * adjust the codec gain. Note the epoch is buffered from the
1697 up->rphase++;
1698 if (up->mphase % WWV_SEC == up->repoch) {
1699 up->status &= ~(DGATE | BGATE);
1700 engmin = sqrt(up->irig * up->irig + up->qrig *
1701 up->qrig);
1702 up->datsig = engmax;
1703 up->datsnr = wwv_snr(engmax, engmin);
1710 if (engmax < DTHR || up->datsnr < DSNR) {
1711 up->status |= DGATE;
1714 sigzer -= sigone;
1715 sigone -= sigmin;
1716 wwv_rsec(peer, sigone - sigzer);
1718 if (up->status & (DGATE | BGATE))
1719 up->errcnt++;
1720 if (up->errcnt > MAXERR)
1721 up->alarm |= LOWERR;
1723 cp = &up->mitig[up->achan];
1724 cp->wwv.syneng = 0;
1725 cp->wwvh.syneng = 0;
1726 up->rphase = 0;
1732 * wwv_rsec - process receiver second
1735 * implement the per-second state machine. The machine assembles BCD
1738 * Normally, the minute has 60 seconds numbered 0-59. If the leap
1761 pp = peer->procptr;
1762 up = pp->unitptr;
1770 * values), a hit on one (positive values) or a miss (zero
1777 nsec = up->rsec;
1778 up->rsec++;
1779 bitvec[nsec] += (bit - bitvec[nsec]) / TCONST;
1792 case IDLE: /* 9, 45-49 */
1811 cp = &up->mitig[up->achan];
1812 cp->wwv.synmax = cp->wwv.syneng;
1813 cp->wwvh.synmax = cp->wwvh.syneng;
1827 cp = &up->mitig[up->achan];
1832 sp = &cp->wwv;
1833 sp->synsnr = wwv_snr(sp->synmax, sp->amp);
1834 sp->reach <<= 1;
1835 if (sp->reach & (1 << AMAX))
1836 sp->count--;
1837 if (sp->synmax >= QTHR && sp->synsnr >= QSNR &&
1838 !(up->status & (DGATE | BGATE))) {
1839 sp->reach |= 1;
1840 sp->count++;
1842 sp->metric = wwv_metric(sp);
1847 rp = &cp->wwvh;
1848 rp->synsnr = wwv_snr(rp->synmax, rp->amp);
1849 rp->reach <<= 1;
1850 if (rp->reach & (1 << AMAX))
1851 rp->count--;
1852 if (rp->synmax >= QTHR && rp->synsnr >= QSNR &&
1853 !(up->status & (DGATE | BGATE))) {
1854 rp->reach |= 1;
1855 rp->count++;
1857 rp->metric = wwv_metric(rp);
1858 if (pp->sloppyclockflag & CLK_FLAG4) {
1861 up->status, up->gain, up->yepoch,
1862 up->epomax, up->eposnr, up->datsig,
1863 up->datsnr,
1864 sp->refid, sp->reach & 0xffff,
1865 sp->metric, sp->synmax, sp->synsnr,
1866 rp->refid, rp->reach & 0xffff,
1867 rp->metric, rp->synmax, rp->synsnr);
1868 record_clock_stats(&peer->srcadr, tbuf);
1874 up->errcnt = up->digcnt = up->alarm = 0;
1884 if (up->status & INSYNC) {
1885 if (up->watch > PANIC) {
1889 } else if (up->status & DSYNC) {
1890 if (up->watch > SYNCH) {
1894 } else if (up->watch > DATA) {
1906 case COEF1: /* 4-7 */
1910 case COEF: /* 10-13, 15-17, 20-23, 25-26,
1911 30-33, 35-38, 40-41, 51-54 */
1912 if (up->status & DSYNC)
1918 case COEF2: /* 18, 27-28, 42-43 */
1929 wwv_corr4(peer, &up->decvec[arg], bcddld, bcd2);
1933 wwv_corr4(peer, &up->decvec[arg], bcddld, bcd3);
1937 wwv_corr4(peer, &up->decvec[arg], bcddld, bcd6);
1941 wwv_corr4(peer, &up->decvec[arg], bcddld, bcd9);
1945 * Miscellaneous bits. If above the positive threshold, declare
1951 wwv_corr4(peer, &up->decvec[YR + 1], bcddld, bcd9);
1954 case MSCBIT: /* 2-3, 50, 56-57 */
1956 if (!(up->misc & arg))
1957 up->alarm |= CMPERR;
1958 up->misc |= arg;
1959 } else if (bitvec[nsec] < -BTHR) {
1960 if (up->misc & arg)
1961 up->alarm |= CMPERR;
1962 up->misc &= ~arg;
1964 up->status |= BGATE;
1975 if (!(up->misc & arg))
1976 up->alarm |= CMPERR;
1977 up->misc |= arg;
1978 } else if (bitvec[nsec] < -BTHR) {
1979 if (up->misc & arg)
1980 up->alarm |= CMPERR;
1981 up->misc &= ~arg;
1983 up->status |= BGATE;
1985 up->status &= ~(SELV | SELH);
1987 if (up->fd_icom > 0) {
1988 up->schan = (up->schan + 1) % NCHAN;
1989 wwv_qsy(peer, up->schan);
1991 up->mitig[up->achan].gain = up->gain;
1994 up->mitig[up->achan].gain = up->gain;
2010 if (up->status & LEPSEC)
2016 up->status &= ~LEPSEC;
2018 up->rsec = 0;
2022 if ((pp->sloppyclockflag & CLK_FLAG4) && !(up->status &
2026 nsec, up->status, up->gain, up->yepoch, up->epomax,
2027 up->eposnr, up->datsig, up->datsnr, bit);
2028 record_clock_stats(&peer->srcadr, tbuf);
2034 pp->disp += AUDIO_PHI;
2057 pp = peer->procptr;
2058 up = pp->unitptr;
2059 if (!(up->status & SSYNC))
2060 up->alarm |= SYNERR;
2061 if (up->digcnt < 9)
2062 up->alarm |= NINERR;
2063 if (!(up->alarm))
2064 up->status |= INSYNC;
2065 if (up->status & INSYNC && up->status & SSYNC) {
2066 if (up->misc & SECWAR)
2067 pp->leap = LEAP_ADDSECOND;
2069 pp->leap = LEAP_NOWARNING;
2070 pp->second = up->rsec;
2071 pp->minute = up->decvec[MN].digit + up->decvec[MN +
2073 pp->hour = up->decvec[HR].digit + up->decvec[HR +
2075 pp->day = up->decvec[DA].digit + up->decvec[DA +
2076 1].digit * 10 + up->decvec[DA + 2].digit * 100;
2077 pp->year = up->decvec[YR].digit + up->decvec[YR +
2079 pp->year += 2000;
2081 if (!clocktime(pp->day, pp->hour, pp->minute,
2082 pp->second, GMT, up->timestamp.l_ui,
2083 &pp->yearstart, &offset.l_ui)) {
2084 up->errflg = CEVNT_BADTIME;
2086 up->watch = 0;
2087 pp->disp = 0;
2088 pp->lastref = up->timestamp;
2090 up->timestamp, PDELAY + up->pdelay);
2094 pp->lencode = timecode(up, pp->a_lastcode,
2095 sizeof(pp->a_lastcode));
2096 record_clock_stats(&peer->srcadr, pp->a_lastcode);
2099 printf("wwv: timecode %d %s\n", pp->lencode,
2100 pp->a_lastcode);
2106 * wwv_corr4 - determine maximum-likelihood digit
2111 * maximum-likelihood digit, while the ratio of this value to the next
2131 pp = peer->procptr;
2132 up = pp->unitptr;
2142 topmax = nxtmax = -MAXAMP;
2147 acc = (vp->like[i] += (acc - vp->like[i]) / TCONST);
2156 vp->digprb = topmax;
2157 vp->digsnr = wwv_snr(topmax, nxtmax);
2160 * The current maximum-likelihood digit is compared to the last
2161 * maximum-likelihood digit. If different, the compare counter
2162 * and maximum-likelihood digit are reset. When the compare
2173 if (vp->digprb < BTHR || vp->digsnr < BSNR) {
2174 up->status |= BGATE;
2176 if (vp->digit != mldigit) {
2177 up->alarm |= CMPERR;
2178 if (vp->count > 0)
2179 vp->count--;
2180 if (vp->count == 0)
2181 vp->digit = mldigit;
2183 if (vp->count < BCMP)
2184 vp->count++;
2185 if (vp->count == BCMP) {
2186 up->status |= DSYNC;
2187 up->digcnt++;
2191 if ((pp->sloppyclockflag & CLK_FLAG4) && !(up->status &
2195 up->rsec - 1, up->status, up->gain, up->yepoch,
2196 up->epomax, vp->radix, vp->digit, mldigit,
2197 vp->count, vp->digprb, vp->digsnr);
2198 record_clock_stats(&peer->srcadr, tbuf);
2208 * wwv_tsec - transmitter minute processing
2224 pp = peer->procptr;
2225 up = pp->unitptr;
2231 temp = carry(&up->decvec[MN]); /* minute units */
2232 if (!(up->status & DSYNC))
2239 temp = carry(&up->decvec[MN + 1]);
2241 temp = carry(&up->decvec[HR]);
2243 temp = carry(&up->decvec[HR + 1]);
2252 minute = up->decvec[MN].digit + up->decvec[MN + 1].digit *
2253 10 + up->decvec[HR].digit * 60 + up->decvec[HR +
2255 day = up->decvec[DA].digit + up->decvec[DA + 1].digit * 10 +
2256 up->decvec[DA + 2].digit * 100;
2261 isleap = up->decvec[YR].digit & 0x3;
2262 if (up->misc & SECWAR && up->status & INSYNC) {
2265 up->status |= LEPSEC;
2276 while (carry(&up->decvec[HR]) != 0); /* advance to minute 0 */
2277 while (carry(&up->decvec[HR + 1]) != 0);
2279 temp = carry(&up->decvec[DA]); /* carry days */
2281 temp = carry(&up->decvec[DA + 1]);
2283 temp = carry(&up->decvec[DA + 2]);
2294 while (carry(&up->decvec[DA]) != 1); /* advance to day 1 */
2295 while (carry(&up->decvec[DA + 1]) != 0);
2296 while (carry(&up->decvec[DA + 2]) != 0);
2297 temp = carry(&up->decvec[YR]); /* carry years */
2299 carry(&up->decvec[YR + 1]);
2304 * carry - process digit
2309 * match the maximum-likelihood digit corresponding to that position.
2319 dp->digit++;
2320 if (dp->digit == dp->radix)
2321 dp->digit = 0;
2322 temp = dp->like[dp->radix - 1];
2323 for (j = dp->radix - 1; j > 0; j--)
2324 dp->like[j] = dp->like[j - 1];
2325 dp->like[0] = temp;
2326 return (dp->digit);
2331 * wwv_snr - compute SNR or likelihood function
2366 * wwv_newchan - change to new data channel
2405 pp = peer->procptr;
2406 up = pp->unitptr;
2416 rp = &up->mitig[i].wwvh;
2417 dtemp = rp->metric;
2423 rp = &up->mitig[i].wwv;
2424 dtemp = rp->metric;
2440 up->status &= ~(SELV | SELH);
2442 up->dchan = (up->dchan + 1) % NCHAN;
2443 if (up->status & METRIC) {
2444 up->status &= ~METRIC;
2449 up->dchan = j;
2450 up->sptr = sp;
2451 memcpy(&pp->refid, sp->refid, 4);
2452 peer->refid = pp->refid;
2453 up->status |= METRIC;
2454 if (sp->select & SELV) {
2455 up->status |= SELV;
2456 up->pdelay = pp->fudgetime1;
2457 } else if (sp->select & SELH) {
2458 up->status |= SELH;
2459 up->pdelay = pp->fudgetime2;
2461 up->pdelay = 0;
2466 if (up->fd_icom > 0)
2467 wwv_qsy(peer, up->dchan);
2474 * wwv_newgame - reset and start over
2497 pp = peer->procptr;
2498 up = pp->unitptr;
2504 if (up->status)
2505 up->errflg = CEVNT_TIMEOUT;
2506 peer->leap = LEAP_NOTINSYNC;
2507 up->watch = up->status = up->alarm = 0;
2508 up->avgint = MINAVG;
2509 up->freq = 0;
2510 up->gain = MAXGAIN / 2;
2518 memset(up->mitig, 0, sizeof(up->mitig));
2520 cp = &up->mitig[i];
2521 cp->gain = up->gain;
2522 cp->wwv.select = SELV;
2523 snprintf(cp->wwv.refid, sizeof(cp->wwv.refid), "WV%.0f",
2525 cp->wwvh.select = SELH;
2526 snprintf(cp->wwvh.refid, sizeof(cp->wwvh.refid), "WH%.0f",
2529 up->dchan = (DCHAN + NCHAN - 1) % NCHAN;
2531 up->schan = up->dchan;
2535 * wwv_metric - compute station metric
2539 * the minute sync pulse amplitude. The combined value is scaled 0-100.
2548 dtemp = sp->count * MAXAMP;
2549 if (sp->synmax < MAXAMP)
2550 dtemp += sp->synmax;
2552 dtemp += MAXAMP - 1;
2560 * wwv_qsy - Tune ICOM receiver
2576 pp = peer->procptr;
2577 up = pp->unitptr;
2578 if (up->fd_icom > 0) {
2579 up->mitig[up->achan].gain = up->gain;
2580 rval = icom_freq(up->fd_icom, peer->ttl & 0x7f,
2582 up->achan = chan;
2583 up->gain = up->mitig[up->achan].gain;
2591 * timecode - assemble timecode string and length
2593 * Prettytime format - similar to Spectracom
2598 * q error bits (hex 0-F)
2608 * agc audio gain (0-255)
2610 * sig signal quality (0-100)
2629 * Common fixed-format fields
2631 synchar = (up->status & INSYNC) ? ' ' : '?';
2632 year = up->decvec[YR].digit + up->decvec[YR + 1].digit * 10 +
2634 day = up->decvec[DA].digit + up->decvec[DA + 1].digit * 10 +
2635 up->decvec[DA + 2].digit * 100;
2636 hour = up->decvec[HR].digit + up->decvec[HR + 1].digit * 10;
2637 minute = up->decvec[MN].digit + up->decvec[MN + 1].digit * 10;
2639 leapchar = (up->misc & SECWAR) ? 'L' : ' ';
2640 dst = dstcod[(up->misc >> 4) & 0x3];
2641 dut = up->misc & 0x7;
2642 if (!(up->misc & DUTS))
2643 dut = -dut;
2644 snprintf(tc, tcsiz, "%c%1X", synchar, up->alarm);
2651 * Specific variable-format fields
2653 sp = up->sptr;
2655 up->watch, up->mitig[up->dchan].gain, sp->refid,
2656 sp->metric, up->errcnt, up->freq / WWV_SEC * 1e6,
2657 up->avgint);
2665 * wwv_gain - adjust codec gain
2683 pp = peer->procptr;
2684 up = pp->unitptr;
2691 if (up->clipcnt == 0) {
2692 up->gain += 4;
2693 if (up->gain > MAXGAIN)
2694 up->gain = MAXGAIN;
2695 } else if (up->clipcnt > MAXCLP) {
2696 up->gain -= 4;
2697 if (up->gain < 0)
2698 up->gain = 0;
2700 audio_gain(up->gain, up->mongain, up->port);
2701 up->clipcnt = 0;