From: Harlan Stenn Date: Fri, 29 Dec 2006 03:56:08 +0000 (-0500) Subject: codec (audio) and ICOM changes from Dave Mills X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2b0cfa35fc9a36fee53613b90659724b890d86f3;p=thirdparty%2Fntp.git codec (audio) and ICOM changes from Dave Mills bk: 459491d8m5VC2u6MYPGHzHIz9B8CQA --- diff --git a/NEWS b/NEWS index 368453d412..db1744b23f 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,5 @@ +* codec (audio) and ICOM changes from Dave Mills. + (4.2.4) Released by Harlan Stenn * monopt.html fixes from Dave Mills. * [Bug 452] Do not report kernel PLL/FLL flips. diff --git a/include/ntp.h b/include/ntp.h index db08ebb7c7..56e7804a63 100644 --- a/include/ntp.h +++ b/include/ntp.h @@ -764,6 +764,7 @@ struct pkt { #define LOOP_HUFFPUFF 9 /* set huff-n'-puff filter length */ #define LOOP_FREQ 10 /* set initial frequency */ #define LOOP_KERN_CLEAR 11 /* reset kernel pll parameters */ +#define LOOP_CODEC 12 /* set audio codec frequency */ /* * Configuration items for the stats printer diff --git a/include/ntp_config.h b/include/ntp_config.h index 66d4f9f902..ae657a9919 100644 --- a/include/ntp_config.h +++ b/include/ntp_config.h @@ -141,6 +141,7 @@ #define CONF_CLOCK_ALLAN 5 #define CONF_CLOCK_HUFFPUFF 6 #define CONF_CLOCK_FREQ 7 +#define CONF_CLOCK_CODEC 8 /* * "tos" modifier keywords diff --git a/include/ntpd.h b/include/ntpd.h index 3495cc85d4..73148f5d8d 100644 --- a/include/ntpd.h +++ b/include/ntpd.h @@ -317,6 +317,7 @@ extern double clock_max; /* max offset before step (s) */ extern double clock_panic; /* max offset before panic (s) */ extern double clock_phi; /* dispersion rate (s/s) */ extern double clock_minstep; /* step timeout (s) */ +extern double clock_codec; /* codec frequency */ extern u_long pps_control; /* last pps sample time */ #ifdef KERNEL_PLL extern int pll_status; /* status bits for kernel pll */ diff --git a/libntp/audio.c b/libntp/audio.c index 8d2f7c2ca9..00770c266a 100644 --- a/libntp/audio.c +++ b/libntp/audio.c @@ -377,9 +377,10 @@ audio_gain( if (debug > 1) printf("audio_gain: gain %d/%d\n", gain, l); # endif +#if 0 /* not a good idea to do this; connector wiring dependency */ /* figure out what channel(s) to use. just nuke right for now. */ r = 0 ; /* setting to zero nicely mutes the channel */ - +#endif l |= r << 8; if ( cf_agc ) rval = ioctl(ctl_fd, agc, &l); diff --git a/libntp/icom.c b/libntp/icom.c index 280667eb45..b14a64710f 100644 --- a/libntp/icom.c +++ b/libntp/icom.c @@ -15,33 +15,40 @@ #include "l_stdlib.h" /* - * Scraps + * Packet routines + * + * These routines send a packet and receive the response. If an error + * (collision) occurs on transmit, the packet is resent. If an error + * occurs on receive (timeout), all input to the terminating FI is + * discarded and the packet is resent. If the maximum number of retries + * is not exceeded, the program returns the number of octets in the user + * buffer; otherwise, it returns zero. + * + * ICOM frame format + * + * Frames begin with a two-octet preamble PR-PR followyd by the + * transceiver address RE, controller address TX, control code CN, zero + * or more data octets DA (depending on command), and terminator FI. + * Since the bus is bidirectional, every octet output is echoed on + * input. Every valid frame sent is answered with a frame in the same + * format, but with the RE and TX fields interchanged. The CN field is + * set to NAK if an error has occurred. Otherwise, the data are returned + * in this and following DA octets. If no data are returned, the CN + * octet is set to ACK. + * + * +------+------+------+------+------+--//--+------+ + * | PR | PR | RE | TX | CN | DA | FI | + * +------+------+------+------+------+--//--+------+ */ -#define BMAX 50 /* max command length */ -#define DICOM /dev/icom/ /* ICOM port link */ - /* - * FSA definitions + * Scraps */ -#define S_IDLE 0 /* idle */ -#define S_HDR 1 /* header */ -#define S_TX 2 /* address */ -#define S_DATA 3 /* data */ -#define S_ERROR 4 /* error */ +#define DICOM /dev/icom/ /* ICOM port link */ /* * Local function prototypes */ static void doublefreq P((double, u_char *, int)); -static int sndpkt P((int, int, u_char *, u_char *)); -static int sndoctet P((int, int)); -static int rcvoctet P((int)); - -/* - * Local variables - */ -static int flags; /* trace flags */ -static int state; /* fsa state */ /* @@ -54,17 +61,16 @@ icom_freq( /* returns 0 (ok), EIO (error) */ double freq /* frequency (MHz) */ ) { - u_char cmd[BMAX], rsp[BMAX]; + u_char cmd[] = {PAD, PR, PR, 0, TX, V_SFREQ, 0, 0, 0, 0, FI, + FI}; int temp; - cmd[0] = V_SFREQ; + cmd[3] = ident; if (ident == IC735) temp = 4; else temp = 5; - doublefreq(freq * 1e6, &cmd[1], temp); - temp = sndpkt(fd, ident, cmd, rsp); - if (temp < 1 || rsp[0] != ACK) - return (EIO); + doublefreq(freq * 1e6, &cmd[6], temp); + temp = write(fd, cmd, temp + 7); return (0); } @@ -96,33 +102,6 @@ doublefreq( /* returns void */ x[i] = FI; } - -/* - * Packet routines - * - * These routines send a packet and receive the response. If an error - * (collision) occurs on transmit, the packet is resent. If an error - * occurs on receive (timeout), all input to the terminating FI is - * discarded and the packet is resent. If the maximum number of retries - * is not exceeded, the program returns the number of octets in the user - * buffer; otherwise, it returns zero. - * - * ICOM frame format - * - * Frames begin with a two-octet preamble PR-PR followyd by the - * transceiver address RE, controller address TX, control code CN, zero - * or more data octets DA (depending on command), and terminator FI. - * Since the bus is bidirectional, every octet output is echoed on - * input. Every valid frame sent is answered with a frame in the same - * format, but with the RE and TX fields interchanged. The CN field is - * set to NAK if an error has occurred. Otherwise, the data are returned - * in this and following DA octets. If no data are returned, the CN - * octet is set to ACK. - * - * +------+------+------+------+------+--//--+------+ - * | PR | PR | RE | TX | CN | DA | FI | - * +------+------+------+------+------+--//--+------+ - */ /* * icom_open() - open and initialize serial interface * @@ -138,7 +117,7 @@ icom_init( int trace /* trace flags */ ) { TTY ttyb; - int fd; + int fd, flags; flags = trace; fd = open(device, O_RDWR, 0777); @@ -148,7 +127,7 @@ icom_init( tcgetattr(fd, &ttyb); ttyb.c_iflag = 0; /* input modes */ ttyb.c_oflag = 0; /* output modes */ - ttyb.c_cflag = IBAUD|CS8|CREAD|CLOCAL; /* control modes */ + ttyb.c_cflag = IBAUD|CS8|CLOCAL; /* control modes (no read) */ ttyb.c_lflag = 0; /* local modes */ ttyb.c_cc[VMIN] = 0; /* min chars */ ttyb.c_cc[VTIME] = 5; /* receive timeout */ @@ -158,168 +137,4 @@ icom_init( return (fd); } - -/* - * sndpkt(r, x, y) - send packet and receive response - * - * This routine sends a command frame, which consists of all except the - * preamble octets PR-PR. It then listens for the response frame and - * returns the payload to the caller. The routine checks for correct - * response header format; that is, the length of the response vector - * returned to the caller must be at least 2 and the RE and TX octets - * must be interchanged; otherwise, the operation is retried up to - * the number of times specified in a global variable. - * - * The trace function, which is enabled by the P_TRACE bit of the global - * flags variable, prints all characters received or echoed on the bus - * preceded by a T (transmit) or R (receive). The P_ERMSG bit of the - * flags variable enables printing of bus error messages. - * - * Note that the first octet sent is a PAD in order to allow time for - * the radio to flush its receive buffer after sending the previous - * response. Even with this precaution, some of the older radios - * occasionally fail to receive a command and it has to be sent again. - */ -static int -sndpkt( /* returns octet count */ - int fd, /* file descriptor */ - int r, /* radio address */ - u_char *cmd, /* command vector */ - u_char *rsp /* response vector */ - ) -{ - int i, j, temp; - - (void)tcflush(fd, TCIOFLUSH); - for (i = 0; i < RETRY; i++) { - state = S_IDLE; - - /* - * Transmit packet. - */ - if (flags & P_TRACE) - printf("icom T:"); - sndoctet(fd, PAD); /* send header */ - sndoctet(fd, PR); - sndoctet(fd, PR); - sndoctet(fd, r); - sndoctet(fd, TX); - for (j = 0; j < BMAX; j++) { /* send body */ - if (sndoctet(fd, cmd[j]) == FI) - break; - } - while (rcvoctet(fd) != FI); /* purge echos */ - if (cmd[0] == V_FREQT || cmd[0] == V_MODET) - return (0); /* shortcut for broadcast */ - - /* - * Receive packet. First, delete all characters - * preceeding a PR, then discard all PRs. Check that the - * RE and TX fields are correctly interchanged, then - * copy the remaining data and FI to the user buffer. - */ - if (flags & P_TRACE) - printf("\nicom R:"); - j = 0; - while ((temp = rcvoctet(fd)) != FI) { - switch (state) { - - case S_IDLE: - if (temp != PR) - continue; - state = S_HDR; - break; - - case S_HDR: - if (temp == PR) { - continue; - } else if (temp != TX) { - if (flags & P_ERMSG) - printf( - "icom: TX error\n"); - state = S_ERROR; - } - state = S_TX; - break; - - case S_TX: - if (temp != r) { - if (flags & P_ERMSG) - printf( - "icom: RE error\n"); - state = S_ERROR; - } - state = S_DATA; - break; - - case S_DATA: - if (j >= BMAX ) { - if (flags & P_ERMSG) - printf( - "icom: buffer overrun\n"); - state = S_ERROR; - j = 0; - } - rsp[j++] = (u_char)temp; - break; - - case S_ERROR: - break; - } - } - if (flags & P_TRACE) - printf("\n"); - if (j > 0) { - rsp[j++] = FI; - return (j); - } - } - if (flags & P_ERMSG) - printf("icom: retries exceeded\n"); - return (0); -} - - -/* - * Interface routines - * - * These routines read and write octets on the bus. In case of receive - * timeout a FI code is returned. In case of output collision (echo - * does not match octet sent), the remainder of the collision frame - * (including the trailing FI) is discarded. - */ -/* - * sndoctet(fd, x) - send octet - */ -static int -sndoctet( /* returns octet */ - int fd, /* file descriptor */ - int x /* octet */ - ) -{ - u_char y; - - y = (u_char)x; - write(fd, &y, 1); - return (x); -} - - -/* - * rcvoctet(fd) - receive octet - */ -static int -rcvoctet( /* returns octet */ - int fd /* file descriptor */ - ) -{ - u_char y; - - if (read(fd, &y, 1) < 1) - y = FI; /* come here if timeout */ - if (flags & P_TRACE && y != PAD) - printf(" %02x", y); - return (y); -} - /* end program */ diff --git a/ntpd/ntp_config.c b/ntpd/ntp_config.c index d4ba6b42af..d9bbc34b34 100644 --- a/ntpd/ntp_config.c +++ b/ntpd/ntp_config.c @@ -238,6 +238,7 @@ static struct keyword tinker_keywords[] = { { "allan", CONF_CLOCK_ALLAN }, { "huffpuff", CONF_CLOCK_HUFFPUFF }, { "freq", CONF_CLOCK_FREQ }, + { "codec", CONF_CLOCK_CODEC }, { "", CONFIG_UNKNOWN } }; @@ -1086,6 +1087,9 @@ getconfig( case CONF_CLOCK_FREQ: loop_config(LOOP_FREQ, ftemp); + + case CONF_CLOCK_CODEC: + loop_config(LOOP_CODEC, ftemp); break; } } diff --git a/ntpd/ntp_loopfilter.c b/ntpd/ntp_loopfilter.c index a103d3aeca..c604bd92b1 100644 --- a/ntpd/ntp_loopfilter.c +++ b/ntpd/ntp_loopfilter.c @@ -129,6 +129,7 @@ static double clock_offset; /* offset (s) */ double clock_jitter; /* offset jitter (s) */ double drift_comp; /* frequency (s/s) */ double clock_stability; /* frequency stability (wander) (s/s) */ +double clock_codec; /* audio codec frequency (sambles/s) */ u_long sys_clocktime; /* last system clock update */ u_long pps_control; /* last pps update */ u_long sys_tai; /* UTC offset from TAI (s) */ @@ -617,16 +618,6 @@ local_clock( } } - /* - * Switch to FLL mode if the poll interval is - * greater than MAXDPOLL, so that the kernel - * loop behaves as the daemon loop; viz., - * selects the FLL when necessary, etc. For - * legacy only. - */ - if (sys_poll > NTP_MAXDPOLL) - ntv.status |= STA_FLL; - /* * If the PPS signal is up and enabled, light * the frequency bit. If the PPS driver is @@ -1049,6 +1040,10 @@ loop_config( drift_comp = freq / 1e6; rstclock(S_FSET, 0, 0); break; + + case LOOP_CODEC: /* audio codec frequency */ + clock_codec = freq; + break; } } diff --git a/ntpd/refclock_irig.c b/ntpd/refclock_irig.c index 6be09d9bac..9660df6e5a 100644 --- a/ntpd/refclock_irig.c +++ b/ntpd/refclock_irig.c @@ -462,7 +462,7 @@ irig_receive( * per second, which results in a frequency change of * 125 PPM. */ - up->phase += up->freq / SECOND; + up->phase += (up->freq + clock_codec) / SECOND; up->phase += pp->fudgetime2 / 1e6; if (up->phase >= .5) { up->phase -= 1.; diff --git a/ntpd/refclock_wwv.c b/ntpd/refclock_wwv.c index b7e0d9a6b1..db227009d8 100644 --- a/ntpd/refclock_wwv.c +++ b/ntpd/refclock_wwv.c @@ -92,6 +92,7 @@ #define TCKSIZ (TCKCYC * MS) /* tick filter size */ #define NCHAN 5 /* number of radio channels */ #define AUDIO_PHI 5e-6 /* dispersion growth factor */ +#define TBUF 128 /* max monitor line length */ /* * Tunable parameters. The DGAIN parameter can be changed to fit the @@ -102,12 +103,10 @@ * radio is not tunable, the DCHAN parameter can be changed to fit the * expected best propagation frequency: higher if further from the * transmitter, lower if nearer. The compromise value works for the US - * right coast. The FREQ_OFFSET parameter can be used as a frequency - * vernier to correct codec requency if greater than MAXFREQ. + * right coast. */ #define DCHAN 3 /* default radio channel (15 Mhz) */ #define DGAIN 5. /* subcarrier gain */ -#define FREQ_OFFSET 0. /* codec frequency correction (PPM) */ /* * General purpose status bits (status) @@ -837,8 +836,7 @@ wwv_receive( * per second, which results in a frequency change of * 125 PPM. */ - up->phase += up->freq / SECOND; - up->phase += FREQ_OFFSET / 1e6; + up->phase += (up->freq + clock_codec) / SECOND; if (up->phase >= .5) { up->phase -= 1.; } else if (up->phase < -.5) { @@ -1174,10 +1172,6 @@ wwv_rf( */ if (!wwv_newchan(peer)) up->watch = 0; -#ifdef ICOM - if (up->fd_icom > 0) - wwv_qsy(peer, up->dchan); -#endif /* ICOM */ } else { /* @@ -1212,7 +1206,8 @@ wwv_rf( wwv_epoch(peer); } else if (up->sptr != NULL) { sp = up->sptr; - if (sp->metric >= TTHR && epoch == sp->mepoch % SECOND) { + if (sp->metric >= TTHR && epoch == sp->mepoch % SECOND) + { up->rsec = (60 - sp->mepoch / SECOND) % 60; up->rphase = 0; up->status |= MSYNC; @@ -1313,7 +1308,7 @@ wwv_qrz( { struct refclockproc *pp; struct wwvunit *up; - char tbuf[80]; /* monitor buffer */ + char tbuf[TBUF]; /* monitor buffer */ long epoch; pp = peer->procptr; @@ -1365,7 +1360,7 @@ wwv_qrz( sp->metric = wwv_metric(sp); if (pp->sloppyclockflag & CLK_FLAG4) { sprintf(tbuf, - "wwv8 %04x %3d %s %04x %.0f %.0f/%.1f %4ld %4ld", + "wwv8 %04x %3d %s %04x %.0f %.0f/%.1f %ld %ld", up->status, up->gain, sp->refid, sp->reach & 0xffff, sp->metric, sp->synmax, sp->synsnr, sp->pos % SECOND, epoch); @@ -1413,7 +1408,7 @@ wwv_endpoc( static int avgcnt; /* averaging interval counter */ static int avginc; /* averaging ratchet */ static int iniflg; /* initialization flag */ - char tbuf[80]; /* monitor buffer */ + char tbuf[TBUF]; /* monitor buffer */ double dtemp; int tmp2; @@ -1768,7 +1763,7 @@ wwv_rsec( struct wwvunit *up; struct chan *cp; struct sync *sp, *rp; - char tbuf[80]; /* monitor buffer */ + char tbuf[TBUF]; /* monitor buffer */ int sw, arg, nsec; pp = peer->procptr; @@ -1887,35 +1882,28 @@ wwv_rsec( up->errcnt = up->digcnt = up->alarm = 0; /* - * We now begin the minute scan. If not yet synchronized - * to a station, restart if the units digit has not been - * found within the DATA timeout (15 m) or if not - * synchronized within the SYNCH timeout (40 m). After - * synchronizing to a station, restart if no stations - * are found within the PANIC timeout (2 days). + * If synchronized to a station, restart if no stations + * have been heard within the PANIC timeout (2 days). If + * not and the minute digit has been found, restart if + * not synchronized withing the SYNCH timeout (40 m). If + * not, restart if the unit digit has not been found + * within the DATA timeout (15 m). */ if (up->status & INSYNC) { if (up->watch > PANIC) { wwv_newgame(peer); return; } - } else { - if (!(up->status & DSYNC)) { - if (up->watch > DATA) { - wwv_newgame(peer); - return; - } - } + } else if (up->status & DSYNC) { if (up->watch > SYNCH) { wwv_newgame(peer); return; } + } else if (up->watch > DATA) { + wwv_newgame(peer); + return; } wwv_newchan(peer); -#ifdef ICOM - if (up->fd_icom > 0) - wwv_qsy(peer, up->dchan); -#endif /* ICOM */ break; /* @@ -1987,7 +1975,7 @@ wwv_rsec( /* * Save the data channel gain, then QSY to the probe channel and - * dim the seconds comb filters. The newchan() routine will + * dim the seconds comb filters. The www_newchan() routine will * light them back up. */ case MSC21: /* 58 */ @@ -2143,7 +2131,7 @@ wwv_corr4( struct wwvunit *up; double topmax, nxtmax; /* metrics */ double acc; /* accumulator */ - char tbuf[80]; /* monitor buffer */ + char tbuf[TBUF]; /* monitor buffer */ int mldigit; /* max likelihood digit */ int i, j; @@ -2420,16 +2408,14 @@ wwv_newchan( struct wwvunit *up; struct sync *sp, *rp; double rank, dtemp; - int i, j; + int i, j, rval; pp = peer->procptr; up = (struct wwvunit *)pp->unitptr; /* * Search all five station pairs looking for the channel with - * maximum metric. If no station is found above thresholds, tune - * to WWV on 15 MHz, set the reference ID to NONE and wait for - * hotter ions. + * maximum metric. */ sp = NULL; j = 0; @@ -2453,21 +2439,29 @@ wwv_newchan( /* * If the strongest signal is less than the MTHR threshold (13), - * we are beneath the waves, so squelch the second sync. If the - * strongest signal is greater than the threshold, tune to that - * frequency and transmitter QTH. + * we are beneath the waves, so squelch the second sync and + * advance to the next station. This makes sure all stations are + * scanned when the ions grow dim. If the strongest signal is + * greater than the threshold, tune to that frequency and + * transmitter QTH. */ if (rank < MTHR) { up->dchan = (up->dchan + 1) % NCHAN; up->status &= ~(SELV | SELH); - return (FALSE); + rval = FALSE; + } else { + up->dchan = j; + up->status |= SELV | SELH; + up->sptr = sp; + memcpy(&pp->refid, sp->refid, 4); + peer->refid = pp->refid; + rval = TRUE; } - up->dchan = j; - up->status |= SELV | SELH; - up->sptr = sp; - memcpy(&pp->refid, sp->refid, 4); - peer->refid = pp->refid; - return (TRUE); +#ifdef ICOM + if (up->fd_icom > 0) + wwv_qsy(peer, up->dchan); +#endif /* ICOM */ + return (rval); } @@ -2514,7 +2508,8 @@ wwv_newgame( /* * Initialize the station processes for audio gain, select bit, * station/frequency identifier and reference identifier. Start - * probing at the next channel after the data channel. + * probing at the strongest channel or the default channel if + * nothing heard. */ memset(up->mitig, 0, sizeof(up->mitig)); for (i = 0; i < NCHAN; i++) { @@ -2525,13 +2520,9 @@ wwv_newgame( cp->wwvh.select = SELH; sprintf(cp->wwvh.refid, "WH%.0f", floor(qsy[i])); } - up->dchan = (DCHAN + NCHAN - 1) % NCHAN;; + up->dchan = (DCHAN + NCHAN - 1) % NCHAN; wwv_newchan(peer); - up->achan = up->schan = up->dchan; -#ifdef ICOM - if (up->fd_icom > 0) - wwv_qsy(peer, up->dchan); -#endif /* ICOM */ + up->schan = up->dchan; } /*