Lines Matching +full:tune +full:- +full:squelch +full:- +full:level

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
62 * debug level is greater than one.
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) */
88 #define MAXAMP 6000. /* max signal level reference */
99 #define AUDIO_PHI 5e-6 /* dispersion growth factor */
176 * Thresholds. These establish the minimum signal level, minimum SNR and
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
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 */
627 * wwv_start - open the devices and initialize data for processing
663 pp = peer->procptr; in wwv_start()
664 pp->io.clock_recv = wwv_receive; in wwv_start()
665 pp->io.srcclock = peer; in wwv_start()
666 pp->io.datalen = 0; in wwv_start()
667 pp->io.fd = fd; in wwv_start()
668 if (!io_addclock(&pp->io)) { in wwv_start()
673 pp->unitptr = up; in wwv_start()
678 peer->precision = PRECISION; in wwv_start()
679 pp->clockdesc = DESCRIPTION; in wwv_start()
682 * The companded samples are encoded sign-magnitude. The table in wwv_start()
685 up->comp[0] = up->comp[OFFSET] = 0.; in wwv_start()
686 up->comp[1] = 1.; up->comp[OFFSET + 1] = -1.; in wwv_start()
687 up->comp[2] = 3.; up->comp[OFFSET + 2] = -3.; in wwv_start()
690 up->comp[i] = up->comp[i - 1] + step; in wwv_start()
691 up->comp[OFFSET + i] = -up->comp[i]; in wwv_start()
695 DTOLFP(1. / WWV_SEC, &up->tick); in wwv_start()
701 up->decvec[MN].radix = 10; /* minutes */ in wwv_start()
702 up->decvec[MN + 1].radix = 6; in wwv_start()
703 up->decvec[HR].radix = 10; /* hours */ in wwv_start()
704 up->decvec[HR + 1].radix = 3; in wwv_start()
705 up->decvec[DA].radix = 10; /* days */ in wwv_start()
706 up->decvec[DA + 1].radix = 10; in wwv_start()
707 up->decvec[DA + 2].radix = 4; in wwv_start()
708 up->decvec[YR].radix = 10; /* years */ in wwv_start()
709 up->decvec[YR + 1].radix = 10; in wwv_start()
724 if (peer->ttl != 0) { in wwv_start()
725 if (peer->ttl & 0x80) in wwv_start()
726 up->fd_icom = icom_init("/dev/icom", B1200, in wwv_start()
729 up->fd_icom = icom_init("/dev/icom", B9600, in wwv_start()
732 if (up->fd_icom > 0) { in wwv_start()
735 close(up->fd_icom); in wwv_start()
736 up->fd_icom = 0; in wwv_start()
752 * wwv_shutdown - shut down the clock
763 pp = peer->procptr; in wwv_shutdown()
764 up = pp->unitptr; in wwv_shutdown()
768 io_closeclock(&pp->io); in wwv_shutdown()
770 if (up->fd_icom > 0) in wwv_shutdown()
771 close(up->fd_icom); in wwv_shutdown()
778 * wwv_receive - receive data from the audio device
782 * It also controls the A/D signal level with an AGC loop to mimimize
802 peer = rbufp->recv_peer; in wwv_receive()
803 pp = peer->procptr; in wwv_receive()
804 up = pp->unitptr; in wwv_receive()
807 * Main loop - read until there ain't no more. Note codec in wwv_receive()
808 * samples are bit-inverted. in wwv_receive()
810 DTOLFP((double)rbufp->recv_length / WWV_SEC, &ltemp); in wwv_receive()
811 L_SUB(&rbufp->recv_time, &ltemp); in wwv_receive()
812 up->timestamp = rbufp->recv_time; in wwv_receive()
813 dpt = rbufp->recv_buffer; in wwv_receive()
814 for (bufcnt = 0; bufcnt < rbufp->recv_length; bufcnt++) { in wwv_receive()
815 sample = up->comp[~*dpt++ & 0xff]; in wwv_receive()
824 up->clipcnt++; in wwv_receive()
825 } else if (sample < -MAXAMP) { in wwv_receive()
826 sample = -MAXAMP; in wwv_receive()
827 up->clipcnt++; in wwv_receive()
838 up->phase += (up->freq + clock_codec) / WWV_SEC; in wwv_receive()
839 if (up->phase >= .5) { in wwv_receive()
840 up->phase -= 1.; in wwv_receive()
841 } else if (up->phase < -.5) { in wwv_receive()
842 up->phase += 1.; in wwv_receive()
848 L_ADD(&up->timestamp, &up->tick); in wwv_receive()
854 if (pp->sloppyclockflag & CLK_FLAG2) in wwv_receive()
855 up->port = 2; in wwv_receive()
857 up->port = 1; in wwv_receive()
858 if (pp->sloppyclockflag & CLK_FLAG3) in wwv_receive()
859 up->mongain = MONGAIN; in wwv_receive()
861 up->mongain = 0; in wwv_receive()
866 * wwv_poll - called by the transmit procedure
882 pp = peer->procptr; in wwv_poll()
883 up = pp->unitptr; in wwv_poll()
884 if (up->errflg) in wwv_poll()
885 refclock_report(peer, up->errflg); in wwv_poll()
886 up->errflg = 0; in wwv_poll()
887 pp->polls++; in wwv_poll()
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 */ in wwv_rf()
933 static double bpf[9]; /* 1000/1200-Hz bpf delay line */ in wwv_rf()
935 static double mf[41]; /* 1000/1200-Hz mf delay line */ in wwv_rf()
976 pp = peer->procptr; in wwv_rf()
977 up = pp->unitptr; in wwv_rf()
998 * Baseband data demodulation. The 100-Hz subcarrier is in wwv_rf()
999 * extracted using a 150-Hz IIR lowpass filter. This attenuates in wwv_rf()
1000 * the 1000/1200-Hz sync signals, as well as the 440-Hz and in wwv_rf()
1001 * 600-Hz tones and most of the noise and voice modulation in wwv_rf()
1008 * Matlab IIR 4th-order IIR elliptic, 150 Hz lowpass, 0.2 dB in wwv_rf()
1009 * passband ripple, -50 dB stopband ripple, phase delay 0.97 ms. in wwv_rf()
1011 data = (lpf[4] = lpf[3]) * 8.360961e-01; in wwv_rf()
1012 data += (lpf[3] = lpf[2]) * -3.481740e+00; in wwv_rf()
1014 data += (lpf[1] = lpf[0]) * -3.807229e+00; in wwv_rf()
1015 lpf[0] = isig * DGAIN - data; in wwv_rf()
1016 data = lpf[0] * 3.281435e-03 in wwv_rf()
1017 + lpf[1] * -1.149947e-02 in wwv_rf()
1018 + lpf[2] * 1.654858e-02 in wwv_rf()
1019 + lpf[3] * -1.149947e-02 in wwv_rf()
1020 + lpf[4] * 3.281435e-03; in wwv_rf()
1023 * The 100-Hz data signal is demodulated using a pair of in wwv_rf()
1026 * multiplying the filtered signal by 100-Hz sine and cosine in wwv_rf()
1027 * signals, respectively. The signals are processed by 170-ms in wwv_rf()
1032 i = up->datapt; in wwv_rf()
1033 up->datapt = (up->datapt + IN100) % 80; in wwv_rf()
1035 up->irig -= ibuf[iptr]; in wwv_rf()
1037 up->irig += dtemp; in wwv_rf()
1041 up->qrig -= qbuf[iptr]; in wwv_rf()
1043 up->qrig += dtemp; in wwv_rf()
1048 * extracted using a 600-Hz IIR bandpass filter. This removes in wwv_rf()
1049 * the 100-Hz data subcarrier, as well as the 440-Hz and 600-Hz in wwv_rf()
1052 * Matlab 4th-order IIR elliptic, 800-1400 Hz bandpass, 0.2 dB in wwv_rf()
1053 * passband ripple, -50 dB stopband ripple, phase delay 0.91 ms. in wwv_rf()
1055 syncx = (bpf[8] = bpf[7]) * 4.897278e-01; in wwv_rf()
1056 syncx += (bpf[7] = bpf[6]) * -2.765914e+00; in wwv_rf()
1058 syncx += (bpf[5] = bpf[4]) * -1.517732e+01; in wwv_rf()
1060 syncx += (bpf[3] = bpf[2]) * -1.814365e+01; in wwv_rf()
1062 syncx += (bpf[1] = bpf[0]) * -4.735040e+00; in wwv_rf()
1063 bpf[0] = isig - syncx; in wwv_rf()
1064 syncx = bpf[0] * 8.203628e-03 in wwv_rf()
1065 + bpf[1] * -2.375732e-02 in wwv_rf()
1066 + bpf[2] * 3.353214e-02 in wwv_rf()
1067 + bpf[3] * -4.080258e-02 in wwv_rf()
1068 + bpf[4] * 4.605479e-02 in wwv_rf()
1069 + bpf[5] * -4.080258e-02 in wwv_rf()
1070 + bpf[6] * 3.353214e-02 in wwv_rf()
1071 + bpf[7] * -2.375732e-02 in wwv_rf()
1072 + bpf[8] * 8.203628e-03; in wwv_rf()
1080 * by 1000-Hz (WWV) and 1200-Hz (WWVH) sine and cosine signals, in wwv_rf()
1081 * respectively. The WWV and WWVH signals are processed by 800- in wwv_rf()
1085 * processed by 5-ms synchronous matched filters and combined to in wwv_rf()
1094 up->mphase = (up->mphase + 1) % WWV_MIN; in wwv_rf()
1095 epoch = up->mphase % WWV_SEC; in wwv_rf()
1104 ciamp -= cibuf[jptr]; in wwv_rf()
1107 csiamp -= csibuf[kptr]; in wwv_rf()
1113 cqamp -= cqbuf[jptr]; in wwv_rf()
1116 csqamp -= csqbuf[kptr]; in wwv_rf()
1120 sp = &up->mitig[up->achan].wwv; in wwv_rf()
1121 sp->amp = sqrt(ciamp * ciamp + cqamp * cqamp) / SYNCYC; in wwv_rf()
1122 if (!(up->status & MSYNC)) in wwv_rf()
1123 wwv_qrz(peer, sp, (int)(pp->fudgetime1 * WWV_SEC)); in wwv_rf()
1132 hiamp -= hibuf[jptr]; in wwv_rf()
1135 hsiamp -= hsibuf[kptr]; in wwv_rf()
1141 hqamp -= hqbuf[jptr]; in wwv_rf()
1144 hsqamp -= hsqbuf[kptr]; in wwv_rf()
1148 rp = &up->mitig[up->achan].wwvh; in wwv_rf()
1149 rp->amp = sqrt(hiamp * hiamp + hqamp * hqamp) / SYNCYC; in wwv_rf()
1150 if (!(up->status & MSYNC)) in wwv_rf()
1151 wwv_qrz(peer, rp, (int)(pp->fudgetime2 * WWV_SEC)); in wwv_rf()
1159 if (up->mphase == 0) { in wwv_rf()
1160 up->watch++; in wwv_rf()
1161 if (!(up->status & MSYNC)) { in wwv_rf()
1170 up->watch = 0; in wwv_rf()
1178 if (up->status & LEPSEC) { in wwv_rf()
1179 up->mphase -= WWV_SEC; in wwv_rf()
1180 if (up->mphase < 0) in wwv_rf()
1181 up->mphase += WWV_MIN; in wwv_rf()
1201 if (up->status & MSYNC) { in wwv_rf()
1203 } else if (up->sptr != NULL) { in wwv_rf()
1204 sp = up->sptr; in wwv_rf()
1205 if (sp->metric >= TTHR && epoch == sp->mepoch % WWV_SEC) in wwv_rf()
1207 up->rsec = (60 - sp->mepoch / WWV_SEC) % 60; in wwv_rf()
1208 up->rphase = 0; in wwv_rf()
1209 up->status |= MSYNC; in wwv_rf()
1210 up->watch = 0; in wwv_rf()
1211 if (!(up->status & SSYNC)) in wwv_rf()
1212 up->repoch = up->yepoch = epoch; in wwv_rf()
1214 up->repoch = up->yepoch; in wwv_rf()
1220 * The second sync pulse is extracted using 5-ms (40 sample) FIR in wwv_rf()
1226 if (up->status & SELV) in wwv_rf()
1229 else if (up->status & SELH) in wwv_rf()
1236 * Enhance the seconds sync pulse using a 1-s (8000-sample) comb in wwv_rf()
1246 dtemp = (epobuf[epoch] += (mfsync - epobuf[epoch]) / in wwv_rf()
1247 up->avgint); in wwv_rf()
1253 j = epoch - 6 * MS; in wwv_rf()
1259 up->epomax = epomax; in wwv_rf()
1260 up->eposnr = wwv_snr(epomax, nxtmax); in wwv_rf()
1261 epopos -= TCKCYC * MS; in wwv_rf()
1265 if (!(up->status & SSYNC)) in wwv_rf()
1266 up->alarm |= SYNERR; in wwv_rf()
1268 if (!(up->status & MSYNC)) in wwv_rf()
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; in wwv_qrz()
1307 up = pp->unitptr; in wwv_qrz()
1314 epoch = up->mphase - pdelay - SYNSIZ; in wwv_qrz()
1317 if (sp->amp > sp->maxeng) { in wwv_qrz()
1318 sp->maxeng = sp->amp; in wwv_qrz()
1319 sp->pos = epoch; in wwv_qrz()
1321 sp->noieng += sp->amp; in wwv_qrz()
1330 if (up->mphase == 0) { in wwv_qrz()
1331 sp->synmax = sp->maxeng; in wwv_qrz()
1332 sp->synsnr = wwv_snr(sp->synmax, (sp->noieng - in wwv_qrz()
1333 sp->synmax) / WWV_MIN); in wwv_qrz()
1334 if (sp->count == 0) in wwv_qrz()
1335 sp->lastpos = sp->pos; in wwv_qrz()
1336 epoch = (sp->pos - sp->lastpos) % WWV_MIN; in wwv_qrz()
1337 sp->reach <<= 1; in wwv_qrz()
1338 if (sp->reach & (1 << AMAX)) in wwv_qrz()
1339 sp->count--; in wwv_qrz()
1340 if (sp->synmax > ATHR && sp->synsnr > ASNR) { in wwv_qrz()
1342 sp->reach |= 1; in wwv_qrz()
1343 sp->count++; in wwv_qrz()
1344 sp->mepoch = sp->lastpos = sp->pos; in wwv_qrz()
1345 } else if (sp->count == 1) { in wwv_qrz()
1346 sp->lastpos = sp->pos; in wwv_qrz()
1349 if (up->watch > ACQSN) in wwv_qrz()
1350 sp->metric = 0; in wwv_qrz()
1352 sp->metric = wwv_metric(sp); in wwv_qrz()
1353 if (pp->sloppyclockflag & CLK_FLAG4) { in wwv_qrz()
1356 up->status, up->gain, sp->refid, in wwv_qrz()
1357 sp->reach & 0xffff, sp->metric, sp->synmax, in wwv_qrz()
1358 sp->synsnr, sp->pos % WWV_SEC, epoch); in wwv_qrz()
1359 record_clock_stats(&peer->srcadr, tbuf); in wwv_qrz()
1365 sp->maxeng = sp->noieng = 0; in wwv_qrz()
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; in wwv_endpoc()
1408 up = pp->unitptr; in wwv_endpoc()
1421 if (up->epomax < STHR || up->eposnr < SSNR) { in wwv_endpoc()
1422 up->status &= ~(SSYNC | FGATE); in wwv_endpoc()
1426 if (!(up->status & (SELV | SELH))) in wwv_endpoc()
1430 * A three-stage median filter is used to help denoise the in wwv_endpoc()
1465 tmp2 = (tepoch - xepoch) % WWV_SEC; in wwv_endpoc()
1468 if (syncnt > SCMP && up->status & MSYNC && (up->status & in wwv_endpoc()
1469 FGATE || scount - zcount <= up->avgint)) { in wwv_endpoc()
1470 up->status |= SSYNC; in wwv_endpoc()
1471 up->yepoch = tepoch; in wwv_endpoc()
1479 if ((pp->sloppyclockflag & CLK_FLAG4) && !(up->status & in wwv_endpoc()
1483 up->status, up->gain, tepoch, up->epomax, in wwv_endpoc()
1484 up->eposnr, tmp2, avgcnt, syncnt, in wwv_endpoc()
1486 record_clock_stats(&peer->srcadr, tbuf); in wwv_endpoc()
1493 if (avgcnt < up->avgint) { in wwv_endpoc()
1499 * The sample clock frequency is disciplined using a first-order in wwv_endpoc()
1506 * epoch difference (125-us units) and time difference (seconds) in wwv_endpoc()
1538 * to zero; if it decrements to -3, the interval is halved and in wwv_endpoc()
1541 dtemp = (mepoch - zepoch) % WWV_SEC; in wwv_endpoc()
1542 if (up->status & FGATE) { in wwv_endpoc()
1544 up->freq += (dtemp / 2.) / ((mcount - zcount) * in wwv_endpoc()
1546 if (up->freq > MAXFREQ) in wwv_endpoc()
1547 up->freq = MAXFREQ; in wwv_endpoc()
1548 else if (up->freq < -MAXFREQ) in wwv_endpoc()
1549 up->freq = -MAXFREQ; in wwv_endpoc()
1554 if (up->avgint < MAXAVG) { in wwv_endpoc()
1555 up->avgint <<= 1; in wwv_endpoc()
1561 if (avginc > -3) { in wwv_endpoc()
1562 avginc--; in wwv_endpoc()
1564 if (up->avgint > MINAVG) { in wwv_endpoc()
1565 up->avgint >>= 1; in wwv_endpoc()
1571 if (pp->sloppyclockflag & CLK_FLAG4) { in wwv_endpoc()
1574 up->status, up->epomax, up->eposnr, mepoch, in wwv_endpoc()
1575 up->avgint, maxrun, mcount - zcount, dtemp, in wwv_endpoc()
1576 up->freq * 1e6 / WWV_SEC); in wwv_endpoc()
1577 record_clock_stats(&peer->srcadr, tbuf); in wwv_endpoc()
1587 up->status |= FGATE; in wwv_endpoc()
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; in wwv_epoch()
1624 up = pp->unitptr; in wwv_epoch()
1633 cp = &up->mitig[up->achan]; in wwv_epoch()
1634 if (cp->wwv.amp > cp->wwv.syneng) in wwv_epoch()
1635 cp->wwv.syneng = cp->wwv.amp; in wwv_epoch()
1636 if (cp->wwvh.amp > cp->wwvh.syneng) in wwv_epoch()
1637 cp->wwvh.syneng = cp->wwvh.amp; in wwv_epoch()
1638 if (up->rphase == 800 * MS) in wwv_epoch()
1639 up->repoch = up->yepoch; in wwv_epoch()
1643 * This gives a guard time of +-15 ms from the beginning of the in wwv_epoch()
1650 if (up->rphase == 15 * MS) in wwv_epoch()
1651 sigmin = sigzer = sigone = up->irig; in wwv_epoch()
1656 * compute the SNR. Use the Q sample to adjust the 100-Hz in wwv_epoch()
1659 if (up->rphase == 200 * MS) { in wwv_epoch()
1660 sigzer = up->irig; in wwv_epoch()
1661 engmax = sqrt(up->irig * up->irig + up->qrig * in wwv_epoch()
1662 up->qrig); in wwv_epoch()
1663 up->datpha = up->qrig / up->avgint; in wwv_epoch()
1664 if (up->datpha >= 0) { in wwv_epoch()
1665 up->datapt++; in wwv_epoch()
1666 if (up->datapt >= 80) in wwv_epoch()
1667 up->datapt -= 80; in wwv_epoch()
1669 up->datapt--; in wwv_epoch()
1670 if (up->datapt < 0) in wwv_epoch()
1671 up->datapt += 80; in wwv_epoch()
1680 else if (up->rphase == 500 * MS) in wwv_epoch()
1681 sigone = up->irig; in wwv_epoch()
1697 up->rphase++; in wwv_epoch()
1698 if (up->mphase % WWV_SEC == up->repoch) { in wwv_epoch()
1699 up->status &= ~(DGATE | BGATE); in wwv_epoch()
1700 engmin = sqrt(up->irig * up->irig + up->qrig * in wwv_epoch()
1701 up->qrig); in wwv_epoch()
1702 up->datsig = engmax; in wwv_epoch()
1703 up->datsnr = wwv_snr(engmax, engmin); in wwv_epoch()
1710 if (engmax < DTHR || up->datsnr < DSNR) { in wwv_epoch()
1711 up->status |= DGATE; in wwv_epoch()
1714 sigzer -= sigone; in wwv_epoch()
1715 sigone -= sigmin; in wwv_epoch()
1716 wwv_rsec(peer, sigone - sigzer); in wwv_epoch()
1718 if (up->status & (DGATE | BGATE)) in wwv_epoch()
1719 up->errcnt++; in wwv_epoch()
1720 if (up->errcnt > MAXERR) in wwv_epoch()
1721 up->alarm |= LOWERR; in wwv_epoch()
1723 cp = &up->mitig[up->achan]; in wwv_epoch()
1724 cp->wwv.syneng = 0; in wwv_epoch()
1725 cp->wwvh.syneng = 0; in wwv_epoch()
1726 up->rphase = 0; in wwv_epoch()
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; in wwv_rsec()
1762 up = pp->unitptr; in wwv_rsec()
1777 nsec = up->rsec; in wwv_rsec()
1778 up->rsec++; in wwv_rsec()
1779 bitvec[nsec] += (bit - bitvec[nsec]) / TCONST; in wwv_rsec()
1792 case IDLE: /* 9, 45-49 */ in wwv_rsec()
1811 cp = &up->mitig[up->achan]; in wwv_rsec()
1812 cp->wwv.synmax = cp->wwv.syneng; in wwv_rsec()
1813 cp->wwvh.synmax = cp->wwvh.syneng; in wwv_rsec()
1827 cp = &up->mitig[up->achan]; in wwv_rsec()
1832 sp = &cp->wwv; in wwv_rsec()
1833 sp->synsnr = wwv_snr(sp->synmax, sp->amp); in wwv_rsec()
1834 sp->reach <<= 1; in wwv_rsec()
1835 if (sp->reach & (1 << AMAX)) in wwv_rsec()
1836 sp->count--; in wwv_rsec()
1837 if (sp->synmax >= QTHR && sp->synsnr >= QSNR && in wwv_rsec()
1838 !(up->status & (DGATE | BGATE))) { in wwv_rsec()
1839 sp->reach |= 1; in wwv_rsec()
1840 sp->count++; in wwv_rsec()
1842 sp->metric = wwv_metric(sp); in wwv_rsec()
1847 rp = &cp->wwvh; in wwv_rsec()
1848 rp->synsnr = wwv_snr(rp->synmax, rp->amp); in wwv_rsec()
1849 rp->reach <<= 1; in wwv_rsec()
1850 if (rp->reach & (1 << AMAX)) in wwv_rsec()
1851 rp->count--; in wwv_rsec()
1852 if (rp->synmax >= QTHR && rp->synsnr >= QSNR && in wwv_rsec()
1853 !(up->status & (DGATE | BGATE))) { in wwv_rsec()
1854 rp->reach |= 1; in wwv_rsec()
1855 rp->count++; in wwv_rsec()
1857 rp->metric = wwv_metric(rp); in wwv_rsec()
1858 if (pp->sloppyclockflag & CLK_FLAG4) { in wwv_rsec()
1861 up->status, up->gain, up->yepoch, in wwv_rsec()
1862 up->epomax, up->eposnr, up->datsig, in wwv_rsec()
1863 up->datsnr, in wwv_rsec()
1864 sp->refid, sp->reach & 0xffff, in wwv_rsec()
1865 sp->metric, sp->synmax, sp->synsnr, in wwv_rsec()
1866 rp->refid, rp->reach & 0xffff, in wwv_rsec()
1867 rp->metric, rp->synmax, rp->synsnr); in wwv_rsec()
1868 record_clock_stats(&peer->srcadr, tbuf); in wwv_rsec()
1874 up->errcnt = up->digcnt = up->alarm = 0; in wwv_rsec()
1884 if (up->status & INSYNC) { in wwv_rsec()
1885 if (up->watch > PANIC) { in wwv_rsec()
1889 } else if (up->status & DSYNC) { in wwv_rsec()
1890 if (up->watch > SYNCH) { in wwv_rsec()
1894 } else if (up->watch > DATA) { in wwv_rsec()
1906 case COEF1: /* 4-7 */ in wwv_rsec()
1910 case COEF: /* 10-13, 15-17, 20-23, 25-26, in wwv_rsec()
1911 30-33, 35-38, 40-41, 51-54 */ in wwv_rsec()
1912 if (up->status & DSYNC) in wwv_rsec()
1918 case COEF2: /* 18, 27-28, 42-43 */ in wwv_rsec()
1929 wwv_corr4(peer, &up->decvec[arg], bcddld, bcd2); in wwv_rsec()
1933 wwv_corr4(peer, &up->decvec[arg], bcddld, bcd3); in wwv_rsec()
1937 wwv_corr4(peer, &up->decvec[arg], bcddld, bcd6); in wwv_rsec()
1941 wwv_corr4(peer, &up->decvec[arg], bcddld, bcd9); in wwv_rsec()
1951 wwv_corr4(peer, &up->decvec[YR + 1], bcddld, bcd9); in wwv_rsec()
1954 case MSCBIT: /* 2-3, 50, 56-57 */ in wwv_rsec()
1956 if (!(up->misc & arg)) in wwv_rsec()
1957 up->alarm |= CMPERR; in wwv_rsec()
1958 up->misc |= arg; in wwv_rsec()
1959 } else if (bitvec[nsec] < -BTHR) { in wwv_rsec()
1960 if (up->misc & arg) in wwv_rsec()
1961 up->alarm |= CMPERR; in wwv_rsec()
1962 up->misc &= ~arg; in wwv_rsec()
1964 up->status |= BGATE; in wwv_rsec()
1975 if (!(up->misc & arg)) in wwv_rsec()
1976 up->alarm |= CMPERR; in wwv_rsec()
1977 up->misc |= arg; in wwv_rsec()
1978 } else if (bitvec[nsec] < -BTHR) { in wwv_rsec()
1979 if (up->misc & arg) in wwv_rsec()
1980 up->alarm |= CMPERR; in wwv_rsec()
1981 up->misc &= ~arg; in wwv_rsec()
1983 up->status |= BGATE; in wwv_rsec()
1985 up->status &= ~(SELV | SELH); in wwv_rsec()
1987 if (up->fd_icom > 0) { in wwv_rsec()
1988 up->schan = (up->schan + 1) % NCHAN; in wwv_rsec()
1989 wwv_qsy(peer, up->schan); in wwv_rsec()
1991 up->mitig[up->achan].gain = up->gain; in wwv_rsec()
1994 up->mitig[up->achan].gain = up->gain; in wwv_rsec()
2010 if (up->status & LEPSEC) in wwv_rsec()
2016 up->status &= ~LEPSEC; in wwv_rsec()
2018 up->rsec = 0; in wwv_rsec()
2022 if ((pp->sloppyclockflag & CLK_FLAG4) && !(up->status & in wwv_rsec()
2026 nsec, up->status, up->gain, up->yepoch, up->epomax, in wwv_rsec()
2027 up->eposnr, up->datsig, up->datsnr, bit); in wwv_rsec()
2028 record_clock_stats(&peer->srcadr, tbuf); in wwv_rsec()
2034 pp->disp += AUDIO_PHI; in wwv_rsec()
2057 pp = peer->procptr; in wwv_clock()
2058 up = pp->unitptr; in wwv_clock()
2059 if (!(up->status & SSYNC)) in wwv_clock()
2060 up->alarm |= SYNERR; in wwv_clock()
2061 if (up->digcnt < 9) in wwv_clock()
2062 up->alarm |= NINERR; in wwv_clock()
2063 if (!(up->alarm)) in wwv_clock()
2064 up->status |= INSYNC; in wwv_clock()
2065 if (up->status & INSYNC && up->status & SSYNC) { in wwv_clock()
2066 if (up->misc & SECWAR) in wwv_clock()
2067 pp->leap = LEAP_ADDSECOND; in wwv_clock()
2069 pp->leap = LEAP_NOWARNING; in wwv_clock()
2070 pp->second = up->rsec; in wwv_clock()
2071 pp->minute = up->decvec[MN].digit + up->decvec[MN + in wwv_clock()
2073 pp->hour = up->decvec[HR].digit + up->decvec[HR + in wwv_clock()
2075 pp->day = up->decvec[DA].digit + up->decvec[DA + in wwv_clock()
2076 1].digit * 10 + up->decvec[DA + 2].digit * 100; in wwv_clock()
2077 pp->year = up->decvec[YR].digit + up->decvec[YR + in wwv_clock()
2079 pp->year += 2000; in wwv_clock()
2081 if (!clocktime(pp->day, pp->hour, pp->minute, in wwv_clock()
2082 pp->second, GMT, up->timestamp.l_ui, in wwv_clock()
2083 &pp->yearstart, &offset.l_ui)) { in wwv_clock()
2084 up->errflg = CEVNT_BADTIME; in wwv_clock()
2086 up->watch = 0; in wwv_clock()
2087 pp->disp = 0; in wwv_clock()
2088 pp->lastref = up->timestamp; in wwv_clock()
2090 up->timestamp, PDELAY + up->pdelay); in wwv_clock()
2094 pp->lencode = timecode(up, pp->a_lastcode, in wwv_clock()
2095 sizeof(pp->a_lastcode)); in wwv_clock()
2096 record_clock_stats(&peer->srcadr, pp->a_lastcode); in wwv_clock()
2099 printf("wwv: timecode %d %s\n", pp->lencode, in wwv_clock()
2100 pp->a_lastcode); in wwv_clock()
2106 * wwv_corr4 - determine maximum-likelihood digit
2111 * maximum-likelihood digit, while the ratio of this value to the next
2131 pp = peer->procptr; in wwv_corr4()
2132 up = pp->unitptr; in wwv_corr4()
2142 topmax = nxtmax = -MAXAMP; in wwv_corr4()
2147 acc = (vp->like[i] += (acc - vp->like[i]) / TCONST); in wwv_corr4()
2156 vp->digprb = topmax; in wwv_corr4()
2157 vp->digsnr = wwv_snr(topmax, nxtmax); in wwv_corr4()
2160 * The current maximum-likelihood digit is compared to the last in wwv_corr4()
2161 * maximum-likelihood digit. If different, the compare counter in wwv_corr4()
2162 * and maximum-likelihood digit are reset. When the compare in wwv_corr4()
2173 if (vp->digprb < BTHR || vp->digsnr < BSNR) { in wwv_corr4()
2174 up->status |= BGATE; in wwv_corr4()
2176 if (vp->digit != mldigit) { in wwv_corr4()
2177 up->alarm |= CMPERR; in wwv_corr4()
2178 if (vp->count > 0) in wwv_corr4()
2179 vp->count--; in wwv_corr4()
2180 if (vp->count == 0) in wwv_corr4()
2181 vp->digit = mldigit; in wwv_corr4()
2183 if (vp->count < BCMP) in wwv_corr4()
2184 vp->count++; in wwv_corr4()
2185 if (vp->count == BCMP) { in wwv_corr4()
2186 up->status |= DSYNC; in wwv_corr4()
2187 up->digcnt++; in wwv_corr4()
2191 if ((pp->sloppyclockflag & CLK_FLAG4) && !(up->status & in wwv_corr4()
2195 up->rsec - 1, up->status, up->gain, up->yepoch, in wwv_corr4()
2196 up->epomax, vp->radix, vp->digit, mldigit, in wwv_corr4()
2197 vp->count, vp->digprb, vp->digsnr); in wwv_corr4()
2198 record_clock_stats(&peer->srcadr, tbuf); in wwv_corr4()
2208 * wwv_tsec - transmitter minute processing
2224 pp = peer->procptr; in wwv_tsec()
2225 up = pp->unitptr; in wwv_tsec()
2231 temp = carry(&up->decvec[MN]); /* minute units */ in wwv_tsec()
2232 if (!(up->status & DSYNC)) in wwv_tsec()
2239 temp = carry(&up->decvec[MN + 1]); in wwv_tsec()
2241 temp = carry(&up->decvec[HR]); in wwv_tsec()
2243 temp = carry(&up->decvec[HR + 1]); in wwv_tsec()
2252 minute = up->decvec[MN].digit + up->decvec[MN + 1].digit * in wwv_tsec()
2253 10 + up->decvec[HR].digit * 60 + up->decvec[HR + in wwv_tsec()
2255 day = up->decvec[DA].digit + up->decvec[DA + 1].digit * 10 + in wwv_tsec()
2256 up->decvec[DA + 2].digit * 100; in wwv_tsec()
2261 isleap = up->decvec[YR].digit & 0x3; in wwv_tsec()
2262 if (up->misc & SECWAR && up->status & INSYNC) { in wwv_tsec()
2265 up->status |= LEPSEC; in wwv_tsec()
2276 while (carry(&up->decvec[HR]) != 0); /* advance to minute 0 */ in wwv_tsec()
2277 while (carry(&up->decvec[HR + 1]) != 0); in wwv_tsec()
2279 temp = carry(&up->decvec[DA]); /* carry days */ in wwv_tsec()
2281 temp = carry(&up->decvec[DA + 1]); in wwv_tsec()
2283 temp = carry(&up->decvec[DA + 2]); in wwv_tsec()
2294 while (carry(&up->decvec[DA]) != 1); /* advance to day 1 */ in wwv_tsec()
2295 while (carry(&up->decvec[DA + 1]) != 0); in wwv_tsec()
2296 while (carry(&up->decvec[DA + 2]) != 0); in wwv_tsec()
2297 temp = carry(&up->decvec[YR]); /* carry years */ in wwv_tsec()
2299 carry(&up->decvec[YR + 1]); in wwv_tsec()
2304 * carry - process digit
2309 * match the maximum-likelihood digit corresponding to that position.
2319 dp->digit++; in carry()
2320 if (dp->digit == dp->radix) in carry()
2321 dp->digit = 0; in carry()
2322 temp = dp->like[dp->radix - 1]; in carry()
2323 for (j = dp->radix - 1; j > 0; j--) in carry()
2324 dp->like[j] = dp->like[j - 1]; in carry()
2325 dp->like[0] = temp; in carry()
2326 return (dp->digit); in carry()
2331 * wwv_snr - compute SNR or likelihood function
2366 * wwv_newchan - change to new data channel
2388 * The routine performs an important squelch function to keep dirty data
2405 pp = peer->procptr; in wwv_newchan()
2406 up = pp->unitptr; in wwv_newchan()
2416 rp = &up->mitig[i].wwvh; in wwv_newchan()
2417 dtemp = rp->metric; in wwv_newchan()
2423 rp = &up->mitig[i].wwv; in wwv_newchan()
2424 dtemp = rp->metric; in wwv_newchan()
2434 * we are beneath the waves, so squelch the second sync and in wwv_newchan()
2437 * greater than the threshold, tune to that frequency and in wwv_newchan()
2440 up->status &= ~(SELV | SELH); in wwv_newchan()
2442 up->dchan = (up->dchan + 1) % NCHAN; in wwv_newchan()
2443 if (up->status & METRIC) { in wwv_newchan()
2444 up->status &= ~METRIC; in wwv_newchan()
2449 up->dchan = j; in wwv_newchan()
2450 up->sptr = sp; in wwv_newchan()
2451 memcpy(&pp->refid, sp->refid, 4); in wwv_newchan()
2452 peer->refid = pp->refid; in wwv_newchan()
2453 up->status |= METRIC; in wwv_newchan()
2454 if (sp->select & SELV) { in wwv_newchan()
2455 up->status |= SELV; in wwv_newchan()
2456 up->pdelay = pp->fudgetime1; in wwv_newchan()
2457 } else if (sp->select & SELH) { in wwv_newchan()
2458 up->status |= SELH; in wwv_newchan()
2459 up->pdelay = pp->fudgetime2; in wwv_newchan()
2461 up->pdelay = 0; in wwv_newchan()
2466 if (up->fd_icom > 0) in wwv_newchan()
2467 wwv_qsy(peer, up->dchan); in wwv_newchan()
2474 * wwv_newgame - reset and start over
2497 pp = peer->procptr; in wwv_newgame()
2498 up = pp->unitptr; in wwv_newgame()
2504 if (up->status) in wwv_newgame()
2505 up->errflg = CEVNT_TIMEOUT; in wwv_newgame()
2506 peer->leap = LEAP_NOTINSYNC; in wwv_newgame()
2507 up->watch = up->status = up->alarm = 0; in wwv_newgame()
2508 up->avgint = MINAVG; in wwv_newgame()
2509 up->freq = 0; in wwv_newgame()
2510 up->gain = MAXGAIN / 2; in wwv_newgame()
2518 memset(up->mitig, 0, sizeof(up->mitig)); in wwv_newgame()
2520 cp = &up->mitig[i]; in wwv_newgame()
2521 cp->gain = up->gain; in wwv_newgame()
2522 cp->wwv.select = SELV; in wwv_newgame()
2523 snprintf(cp->wwv.refid, sizeof(cp->wwv.refid), "WV%.0f", in wwv_newgame()
2525 cp->wwvh.select = SELH; in wwv_newgame()
2526 snprintf(cp->wwvh.refid, sizeof(cp->wwvh.refid), "WH%.0f", in wwv_newgame()
2529 up->dchan = (DCHAN + NCHAN - 1) % NCHAN; in wwv_newgame()
2531 up->schan = up->dchan; in wwv_newgame()
2535 * wwv_metric - compute station metric
2539 * the minute sync pulse amplitude. The combined value is scaled 0-100.
2548 dtemp = sp->count * MAXAMP; in wwv_metric()
2549 if (sp->synmax < MAXAMP) in wwv_metric()
2550 dtemp += sp->synmax; in wwv_metric()
2552 dtemp += MAXAMP - 1; in wwv_metric()
2560 * wwv_qsy - Tune ICOM receiver
2576 pp = peer->procptr; in wwv_qsy()
2577 up = pp->unitptr; in wwv_qsy()
2578 if (up->fd_icom > 0) { in wwv_qsy()
2579 up->mitig[up->achan].gain = up->gain; in wwv_qsy()
2580 rval = icom_freq(up->fd_icom, peer->ttl & 0x7f, in wwv_qsy()
2582 up->achan = chan; in wwv_qsy()
2583 up->gain = up->mitig[up->achan].gain; in wwv_qsy()
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 in timecode()
2631 synchar = (up->status & INSYNC) ? ' ' : '?'; in timecode()
2632 year = up->decvec[YR].digit + up->decvec[YR + 1].digit * 10 + in timecode()
2634 day = up->decvec[DA].digit + up->decvec[DA + 1].digit * 10 + in timecode()
2635 up->decvec[DA + 2].digit * 100; in timecode()
2636 hour = up->decvec[HR].digit + up->decvec[HR + 1].digit * 10; in timecode()
2637 minute = up->decvec[MN].digit + up->decvec[MN + 1].digit * 10; in timecode()
2639 leapchar = (up->misc & SECWAR) ? 'L' : ' '; in timecode()
2640 dst = dstcod[(up->misc >> 4) & 0x3]; in timecode()
2641 dut = up->misc & 0x7; in timecode()
2642 if (!(up->misc & DUTS)) in timecode()
2643 dut = -dut; in timecode()
2644 snprintf(tc, tcsiz, "%c%1X", synchar, up->alarm); in timecode()
2651 * Specific variable-format fields in timecode()
2653 sp = up->sptr; in timecode()
2655 up->watch, up->mitig[up->dchan].gain, sp->refid, in timecode()
2656 sp->metric, up->errcnt, up->freq / WWV_SEC * 1e6, in timecode()
2657 up->avgint); in timecode()
2665 * wwv_gain - adjust codec gain
2683 pp = peer->procptr; in wwv_gain()
2684 up = pp->unitptr; in wwv_gain()
2691 if (up->clipcnt == 0) { in wwv_gain()
2692 up->gain += 4; in wwv_gain()
2693 if (up->gain > MAXGAIN) in wwv_gain()
2694 up->gain = MAXGAIN; in wwv_gain()
2695 } else if (up->clipcnt > MAXCLP) { in wwv_gain()
2696 up->gain -= 4; in wwv_gain()
2697 if (up->gain < 0) in wwv_gain()
2698 up->gain = 0; in wwv_gain()
2700 audio_gain(up->gain, up->mongain, up->port); in wwv_gain()
2701 up->clipcnt = 0; in wwv_gain()