Annotation of embedaddon/ntp/ntpd/refclock_chu.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * refclock_chu - clock driver for Canadian CHU time/frequency station
                      3:  */
                      4: #ifdef HAVE_CONFIG_H
                      5: #include <config.h>
                      6: #endif
                      7: 
                      8: #if defined(REFCLOCK) && defined(CLOCK_CHU)
                      9: 
                     10: #include "ntpd.h"
                     11: #include "ntp_io.h"
                     12: #include "ntp_refclock.h"
                     13: #include "ntp_calendar.h"
                     14: #include "ntp_stdlib.h"
                     15: 
                     16: #include <stdio.h>
                     17: #include <ctype.h>
                     18: #include <math.h>
                     19: 
                     20: #ifdef HAVE_AUDIO
                     21: #include "audio.h"
                     22: #endif /* HAVE_AUDIO */
                     23: 
                     24: #define ICOM   1               /* undefine to suppress ICOM code */
                     25: 
                     26: #ifdef ICOM
                     27: #include "icom.h"
                     28: #endif /* ICOM */
                     29: /*
                     30:  * Audio CHU demodulator/decoder
                     31:  *
                     32:  * This driver synchronizes the computer time using data encoded in
                     33:  * radio transmissions from Canadian time/frequency station CHU in
                     34:  * Ottawa, Ontario. Transmissions are made continuously on 3330 kHz,
                     35:  * 7850 kHz and 14670 kHz in upper sideband, compatible AM mode. An
                     36:  * ordinary shortwave receiver can be tuned manually to one of these
                     37:  * frequencies or, in the case of ICOM receivers, the receiver can be
                     38:  * tuned automatically as propagation conditions change throughout the
                     39:  * day and season.
                     40:  *
                     41:  * The driver requires an audio codec or sound card with sampling rate 8
                     42:  * kHz and mu-law companding. This is the same standard as used by the
                     43:  * telephone industry and is supported by most hardware and operating
                     44:  * systems, including Solaris, SunOS, FreeBSD, NetBSD and Linux. In this
                     45:  * implementation, only one audio driver and codec can be supported on a
                     46:  * single machine.
                     47:  *
                     48:  * The driver can be compiled to use a Bell 103 compatible modem or
                     49:  * modem chip to receive the radio signal and demodulate the data.
                     50:  * Alternatively, the driver can be compiled to use the audio codec of
                     51:  * the workstation or another with compatible audio drivers. In the
                     52:  * latter case, the driver implements the modem using DSP routines, so
                     53:  * the radio can be connected directly to either the microphone on line
                     54:  * input port. In either case, the driver decodes the data using a
                     55:  * maximum-likelihood technique which exploits the considerable degree
                     56:  * of redundancy available to maximize accuracy and minimize errors.
                     57:  *
                     58:  * The CHU time broadcast includes an audio signal compatible with the
                     59:  * Bell 103 modem standard (mark = 2225 Hz, space = 2025 Hz). The signal
                     60:  * consists of nine, ten-character bursts transmitted at 300 bps between
                     61:  * seconds 31 and 39 of each minute. Each character consists of eight
                     62:  * data bits plus one start bit and two stop bits to encode two hex
                     63:  * digits. The burst data consist of five characters (ten hex digits)
                     64:  * followed by a repeat of these characters. In format A, the characters
                     65:  * are repeated in the same polarity; in format B, the characters are
                     66:  * repeated in the opposite polarity.
                     67:  *
                     68:  * Format A bursts are sent at seconds 32 through 39 of the minute in
                     69:  * hex digits (nibble swapped)
                     70:  *
                     71:  *     6dddhhmmss6dddhhmmss
                     72:  *
                     73:  * The first ten digits encode a frame marker (6) followed by the day
                     74:  * (ddd), hour (hh in UTC), minute (mm) and the second (ss). Since
                     75:  * format A bursts are sent during the third decade of seconds the tens
                     76:  * digit of ss is always 3. The driver uses this to determine correct
                     77:  * burst synchronization. These digits are then repeated with the same
                     78:  * polarity.
                     79:  *
                     80:  * Format B bursts are sent at second 31 of the minute in hex digits
                     81:  *
                     82:  *     xdyyyyttaaxdyyyyttaa
                     83:  *
                     84:  * The first ten digits encode a code (x described below) followed by
                     85:  * the DUT1 (d in deciseconds), Gregorian year (yyyy), difference TAI -
                     86:  * UTC (tt) and daylight time indicator (aa) peculiar to Canada. These
                     87:  * digits are then repeated with inverted polarity.
                     88:  *
                     89:  * The x is coded
                     90:  *
                     91:  * 1 Sign of DUT (0 = +)
                     92:  * 2 Leap second warning. One second will be added.
                     93:  * 4 Leap second warning. One second will be subtracted.
                     94:  * 8 Even parity bit for this nibble.
                     95:  *
                     96:  * By design, the last stop bit of the last character in the burst
                     97:  * coincides with 0.5 second. Since characters have 11 bits and are
                     98:  * transmitted at 300 bps, the last stop bit of the first character
                     99:  * coincides with 0.5 - 9 * 11/300 = 0.170 second. Depending on the
                    100:  * UART, character interrupts can vary somewhere between the end of bit
                    101:  * 9 and end of bit 11. These eccentricities can be corrected along with
                    102:  * the radio propagation delay using fudge time 1.
                    103:  *
                    104:  * Debugging aids
                    105:  *
                    106:  * The timecode format used for debugging and data recording includes
                    107:  * data helpful in diagnosing problems with the radio signal and serial
                    108:  * connections. With debugging enabled (-d on the ntpd command line),
                    109:  * the driver produces one line for each burst in two formats
                    110:  * corresponding to format A and B.Each line begins with the format code
                    111:  * chuA or chuB followed by the status code and signal level (0-9999).
                    112:  * The remainder of the line is as follows.
                    113:  *
                    114:  * Following is format A:
                    115:  *
                    116:  *     n b f s m code
                    117:  *
                    118:  * where n is the number of characters in the burst (0-10), b the burst
                    119:  * distance (0-40), f the field alignment (-1, 0, 1), s the
                    120:  * synchronization distance (0-16), m the burst number (2-9) and code
                    121:  * the burst characters as received. Note that the hex digits in each
                    122:  * character are reversed, so the burst
                    123:  *
                    124:  *     10 38 0 16 9 06851292930685129293
                    125:  *
                    126:  * is interpreted as containing 10 characters with burst distance 38,
                    127:  * field alignment 0, synchronization distance 16 and burst number 9.
                    128:  * The nibble-swapped timecode shows day 58, hour 21, minute 29 and
                    129:  * second 39.
                    130:  *
                    131:  * Following is format B:
                    132:  * 
                    133:  *     n b s code
                    134:  *
                    135:  * where n is the number of characters in the burst (0-10), b the burst
                    136:  * distance (0-40), s the synchronization distance (0-40) and code the
                    137:  * burst characters as received. Note that the hex digits in each
                    138:  * character are reversed and the last ten digits inverted, so the burst
                    139:  *
                    140:  *     10 40 1091891300ef6e76ec
                    141:  *
                    142:  * is interpreted as containing 10 characters with burst distance 40.
                    143:  * The nibble-swapped timecode shows DUT1 +0.1 second, year 1998 and TAI
                    144:  * - UTC 31 seconds.
                    145:  *
                    146:  * Each line is preceeded by the code chuA or chuB, as appropriate. If
                    147:  * the audio driver is compiled, the current gain (0-255) and relative
                    148:  * signal level (0-9999) follow the code. The receiver volume control
                    149:  * should be set so that the gain is somewhere near the middle of the
                    150:  * range 0-255, which results in a signal level near 1000.
                    151:  *
                    152:  * In addition to the above, the reference timecode is updated and
                    153:  * written to the clockstats file and debug score after the last burst
                    154:  * received in the minute. The format is
                    155:  *
                    156:  *     sq yyyy ddd hh:mm:ss l s dd t agc ident m b      
                    157:  *
                    158:  * s   '?' before first synchronized and ' ' after that
                    159:  * q   status code (see below)
                    160:  * yyyy        year
                    161:  * ddd day of year
                    162:  * hh:mm:ss time of day
                    163:  * l   leap second indicator (space, L or D)
                    164:  * dst Canadian daylight code (opaque)
                    165:  * t   number of minutes since last synchronized
                    166:  * agc audio gain (0 - 255)
                    167:  * ident identifier (CHU0 3330 kHz, CHU1 7850 kHz, CHU2 14670 kHz)
                    168:  * m   signal metric (0 - 100)
                    169:  * b   number of timecodes for the previous minute (0 - 59)
                    170:  *
                    171:  * Fudge factors
                    172:  *
                    173:  * For accuracies better than the low millisceconds, fudge time1 can be
                    174:  * set to the radio propagation delay from CHU to the receiver. This can
                    175:  * be done conviently using the minimuf program.
                    176:  *
                    177:  * Fudge flag4 causes the dubugging output described above to be
                    178:  * recorded in the clockstats file. When the audio driver is compiled,
                    179:  * fudge flag2 selects the audio input port, where 0 is the mike port
                    180:  * (default) and 1 is the line-in port. It does not seem useful to
                    181:  * select the compact disc player port. Fudge flag3 enables audio
                    182:  * monitoring of the input signal. For this purpose, the monitor gain is
                    183:  * set to a default value.
                    184:  *
                    185:  * The audio codec code is normally compiled in the driver if the
                    186:  * architecture supports it (HAVE_AUDIO defined), but is used only if
                    187:  * the link /dev/chu_audio is defined and valid. The serial port code is
                    188:  * always compiled in the driver, but is used only if the autdio codec
                    189:  * is not available and the link /dev/chu%d is defined and valid.
                    190:  *
                    191:  * The ICOM code is normally compiled in the driver if selected (ICOM
                    192:  * defined), but is used only if the link /dev/icom%d is defined and
                    193:  * valid and the mode keyword on the server configuration command
                    194:  * specifies a nonzero mode (ICOM ID select code). The C-IV speed is
                    195:  * 9600 bps if the high order 0x80 bit of the mode is zero and 1200 bps
                    196:  * if one. The C-IV trace is turned on if the debug level is greater
                    197:  * than one.
                    198:  *
                    199:  * Alarm codes
                    200:  *
                    201:  * CEVNT_BADTIME       invalid date or time
                    202:  * CEVNT_PROP          propagation failure - no stations heard
                    203:  */
                    204: /*
                    205:  * Interface definitions
                    206:  */
                    207: #define        SPEED232        B300    /* uart speed (300 baud) */
                    208: #define        PRECISION       (-10)   /* precision assumed (about 1 ms) */
                    209: #define        REFID           "CHU"   /* reference ID */
                    210: #define        DEVICE          "/dev/chu%d" /* device name and unit */
                    211: #define        SPEED232        B300    /* UART speed (300 baud) */
                    212: #ifdef ICOM
                    213: #define TUNE           .001    /* offset for narrow filter (MHz) */
                    214: #define DWELL          5       /* minutes in a dwell */
                    215: #define NCHAN          3       /* number of channels */
                    216: #define ISTAGE         3       /* number of integrator stages */
                    217: #endif /* ICOM */
                    218: 
                    219: #ifdef HAVE_AUDIO
                    220: /*
                    221:  * Audio demodulator definitions
                    222:  */
                    223: #define SECOND         8000    /* nominal sample rate (Hz) */
                    224: #define BAUD           300     /* modulation rate (bps) */
                    225: #define OFFSET         128     /* companded sample offset */
                    226: #define SIZE           256     /* decompanding table size */
                    227: #define        MAXAMP          6000.   /* maximum signal level */
                    228: #define        MAXCLP          100     /* max clips above reference per s */
                    229: #define        SPAN            800.    /* min envelope span */
                    230: #define LIMIT          1000.   /* soft limiter threshold */
                    231: #define AGAIN          6.      /* baseband gain */
                    232: #define LAG            10      /* discriminator lag */
                    233: #define        DEVICE_AUDIO    "/dev/audio" /* device name */
                    234: #define        DESCRIPTION     "CHU Audio/Modem Receiver" /* WRU */
                    235: #define        AUDIO_BUFSIZ    240     /* audio buffer size (30 ms) */
                    236: #else
                    237: #define        DESCRIPTION     "CHU Modem Receiver" /* WRU */
                    238: #endif /* HAVE_AUDIO */
                    239: 
                    240: /*
                    241:  * Decoder definitions
                    242:  */
                    243: #define CHAR           (11. / 300.) /* character time (s) */
                    244: #define BURST          11      /* max characters per burst */
                    245: #define MINCHAR                9       /* min characters per burst */
                    246: #define MINDIST                28      /* min burst distance (of 40)  */
                    247: #define MINSYNC                8       /* min sync distance (of 16) */
                    248: #define MINSTAMP       20      /* min timestamps (of 60) */
                    249: #define MINMETRIC      50      /* min channel metric (of 160) */
                    250: 
                    251: /*
                    252:  * The on-time synchronization point for the driver is the last stop bit
                    253:  * of the first character 170 ms. The modem delay is 0.8 ms, while the
                    254:  * receiver delay is approxmately 4.7 ms at 2125 Hz. The fudge value 1.3
                    255:  * ms due to the codec and other causes was determined by calibrating to
                    256:  * a PPS signal from a GPS receiver. The additional propagation delay
                    257:  * specific to each receiver location can be programmed in the fudge
                    258:  * time1. 
                    259:  *
                    260:  * The resulting offsets with a 2.4-GHz P4 running FreeBSD 6.1 are
                    261:  * generally within 0.5 ms short term with 0.3 ms jitter. The long-term
                    262:  * offsets vary up to 0.3 ms due to ionospheric layer height variations.
                    263:  * The processor load due to the driver is 0.4 percent.
                    264:  */
                    265: #define        PDELAY  ((170 + .8 + 4.7 + 1.3) / 1000) /* system delay (s) */
                    266: 
                    267: /*
                    268:  * Status bits (status)
                    269:  */
                    270: #define RUNT           0x0001  /* runt burst */
                    271: #define NOISE          0x0002  /* noise burst */
                    272: #define BFRAME         0x0004  /* invalid format B frame sync */
                    273: #define BFORMAT                0x0008  /* invalid format B data */
                    274: #define AFRAME         0x0010  /* invalid format A frame sync */
                    275: #define AFORMAT                0x0020  /* invalid format A data */
                    276: #define DECODE         0x0040  /* invalid data decode */
                    277: #define STAMP          0x0080  /* too few timestamps */
                    278: #define AVALID         0x0100  /* valid A frame */
                    279: #define BVALID         0x0200  /* valid B frame */
                    280: #define INSYNC         0x0400  /* clock synchronized */
                    281: #define        METRIC          0x0800  /* one or more stations heard */
                    282: 
                    283: /*
                    284:  * Alarm status bits (alarm)
                    285:  *
                    286:  * These alarms are set at the end of a minute in which at least one
                    287:  * burst was received. SYNERR is raised if the AFRAME or BFRAME status
                    288:  * bits are set during the minute, FMTERR is raised if the AFORMAT or
                    289:  * BFORMAT status bits are set, DECERR is raised if the DECODE status
                    290:  * bit is set and TSPERR is raised if the STAMP status bit is set.
                    291:  */
                    292: #define SYNERR         0x01    /* frame sync error */
                    293: #define FMTERR         0x02    /* data format error */
                    294: #define DECERR         0x04    /* data decoding error */
                    295: #define TSPERR         0x08    /* insufficient data */
                    296: 
                    297: #ifdef HAVE_AUDIO
                    298: /*
                    299:  * Maximum-likelihood UART structure. There are eight of these
                    300:  * corresponding to the number of phases.
                    301:  */ 
                    302: struct surv {
                    303:        l_fp    cstamp;         /* last bit timestamp */
                    304:        double  shift[12];      /* sample shift register */
                    305:        double  span;           /* shift register envelope span */
                    306:        double  dist;           /* sample distance */
                    307:        int     uart;           /* decoded character */
                    308: };
                    309: #endif /* HAVE_AUDIO */
                    310: 
                    311: #ifdef ICOM
                    312: /*
                    313:  * CHU station structure. There are three of these corresponding to the
                    314:  * three frequencies.
                    315:  */
                    316: struct xmtr {
                    317:        double  integ[ISTAGE];  /* circular integrator */
                    318:        double  metric;         /* integrator sum */
                    319:        int     iptr;           /* integrator pointer */
                    320:        int     probe;          /* dwells since last probe */
                    321: };
                    322: #endif /* ICOM */
                    323: 
                    324: /*
                    325:  * CHU unit control structure
                    326:  */
                    327: struct chuunit {
                    328:        u_char  decode[20][16]; /* maximum-likelihood decoding matrix */
                    329:        l_fp    cstamp[BURST];  /* character timestamps */
                    330:        l_fp    tstamp[MAXSTAGE]; /* timestamp samples */
                    331:        l_fp    timestamp;      /* current buffer timestamp */
                    332:        l_fp    laststamp;      /* last buffer timestamp */
                    333:        l_fp    charstamp;      /* character time as a l_fp */
                    334:        int     second;         /* counts the seconds of the minute */
                    335:        int     errflg;         /* error flags */
                    336:        int     status;         /* status bits */
                    337:        char    ident[5];       /* station ID and channel */
                    338: #ifdef ICOM
                    339:        int     fd_icom;        /* ICOM file descriptor */
                    340:        int     chan;           /* radio channel */
                    341:        int     dwell;          /* dwell cycle */
                    342:        struct xmtr xmtr[NCHAN]; /* station metric */
                    343: #endif /* ICOM */
                    344: 
                    345:        /*
                    346:         * Character burst variables
                    347:         */
                    348:        int     cbuf[BURST];    /* character buffer */
                    349:        int     ntstamp;        /* number of timestamp samples */
                    350:        int     ndx;            /* buffer start index */
                    351:        int     prevsec;        /* previous burst second */
                    352:        int     burdist;        /* burst distance */
                    353:        int     syndist;        /* sync distance */
                    354:        int     burstcnt;       /* format A bursts this minute */
                    355:        double  maxsignal;      /* signal level (modem only) */
                    356:        int     gain;           /* codec gain (modem only) */
                    357: 
                    358:        /*
                    359:         * Format particulars
                    360:         */
                    361:        int     leap;           /* leap/dut code */
                    362:        int     dut;            /* UTC1 correction */
                    363:        int     tai;            /* TAI - UTC correction */
                    364:        int     dst;            /* Canadian DST code */
                    365: 
                    366: #ifdef HAVE_AUDIO
                    367:        /*
                    368:         * Audio codec variables
                    369:         */
                    370:        int     fd_audio;       /* audio port file descriptor */
                    371:        double  comp[SIZE];     /* decompanding table */
                    372:        int     port;           /* codec port */
                    373:        int     mongain;        /* codec monitor gain */
                    374:        int     clipcnt;        /* sample clip count */
                    375:        int     seccnt;         /* second interval counter */
                    376: 
                    377:        /*
                    378:         * Modem variables
                    379:         */
                    380:        l_fp    tick;           /* audio sample increment */
                    381:        double  bpf[9];         /* IIR bandpass filter */
                    382:        double  disc[LAG];      /* discriminator shift register */
                    383:        double  lpf[27];        /* FIR lowpass filter */
                    384:        double  monitor;        /* audio monitor */
                    385:        int     discptr;        /* discriminator pointer */
                    386: 
                    387:        /*
                    388:         * Maximum-likelihood UART variables
                    389:         */
                    390:        double  baud;           /* baud interval */
                    391:        struct surv surv[8];    /* UART survivor structures */
                    392:        int     decptr;         /* decode pointer */
                    393:        int     decpha;         /* decode phase */
                    394:        int     dbrk;           /* holdoff counter */
                    395: #endif /* HAVE_AUDIO */
                    396: };
                    397: 
                    398: /*
                    399:  * Function prototypes
                    400:  */
                    401: static int     chu_start       (int, struct peer *);
                    402: static void    chu_shutdown    (int, struct peer *);
                    403: static void    chu_receive     (struct recvbuf *);
                    404: static void    chu_second      (int, struct peer *);
                    405: static void    chu_poll        (int, struct peer *);
                    406: 
                    407: /*
                    408:  * More function prototypes
                    409:  */
                    410: static void    chu_decode      (struct peer *, int, l_fp);
                    411: static void    chu_burst       (struct peer *);
                    412: static void    chu_clear       (struct peer *);
                    413: static void    chu_a           (struct peer *, int);
                    414: static void    chu_b           (struct peer *, int);
                    415: static int     chu_dist        (int, int);
                    416: static double  chu_major       (struct peer *);
                    417: #ifdef HAVE_AUDIO
                    418: static void    chu_uart        (struct surv *, double);
                    419: static void    chu_rf          (struct peer *, double);
                    420: static void    chu_gain        (struct peer *);
                    421: static void    chu_audio_receive (struct recvbuf *rbufp);
                    422: #endif /* HAVE_AUDIO */
                    423: #ifdef ICOM
                    424: static int     chu_newchan     (struct peer *, double);
                    425: #endif /* ICOM */
                    426: static void    chu_serial_receive (struct recvbuf *rbufp);
                    427: 
                    428: /*
                    429:  * Global variables
                    430:  */
                    431: static char hexchar[] = "0123456789abcdef_*=";
                    432: 
                    433: #ifdef ICOM
                    434: /*
                    435:  * Note the tuned frequencies are 1 kHz higher than the carrier. CHU
                    436:  * transmits on USB with carrier so we can use AM and the narrow SSB
                    437:  * filter.
                    438:  */
                    439: static double qsy[NCHAN] = {3.330, 7.850, 14.670}; /* freq (MHz) */
                    440: #endif /* ICOM */
                    441: 
                    442: /*
                    443:  * Transfer vector
                    444:  */
                    445: struct refclock refclock_chu = {
                    446:        chu_start,              /* start up driver */
                    447:        chu_shutdown,           /* shut down driver */
                    448:        chu_poll,               /* transmit poll message */
                    449:        noentry,                /* not used (old chu_control) */
                    450:        noentry,                /* initialize driver (not used) */
                    451:        noentry,                /* not used (old chu_buginfo) */
                    452:        chu_second              /* housekeeping timer */
                    453: };
                    454: 
                    455: 
                    456: /*
                    457:  * chu_start - open the devices and initialize data for processing
                    458:  */
                    459: static int
                    460: chu_start(
                    461:        int     unit,           /* instance number (not used) */
                    462:        struct peer *peer       /* peer structure pointer */
                    463:        )
                    464: {
                    465:        struct chuunit *up;
                    466:        struct refclockproc *pp;
                    467:        char device[20];        /* device name */
                    468:        int     fd;             /* file descriptor */
                    469: #ifdef ICOM
                    470:        int     temp;
                    471: #endif /* ICOM */
                    472: #ifdef HAVE_AUDIO
                    473:        int     fd_audio;       /* audio port file descriptor */
                    474:        int     i;              /* index */
                    475:        double  step;           /* codec adjustment */
                    476: 
                    477:        /*
                    478:         * Open audio device. Don't complain if not there.
                    479:         */
                    480:        fd_audio = audio_init(DEVICE_AUDIO, AUDIO_BUFSIZ, unit);
                    481: #ifdef DEBUG
                    482:        if (fd_audio > 0 && debug)
                    483:                audio_show();
                    484: #endif
                    485: 
                    486:        /*
                    487:         * If audio is unavailable, Open serial port in raw mode.
                    488:         */
                    489:        if (fd_audio > 0) {
                    490:                fd = fd_audio;
                    491:        } else {
                    492:                snprintf(device, sizeof(device), DEVICE, unit);
                    493:                fd = refclock_open(device, SPEED232, LDISC_RAW);
                    494:        }
                    495: #else /* HAVE_AUDIO */
                    496: 
                    497:        /*
                    498:         * Open serial port in raw mode.
                    499:         */
                    500:        snprintf(device, sizeof(device), DEVICE, unit);
                    501:        fd = refclock_open(device, SPEED232, LDISC_RAW);
                    502: #endif /* HAVE_AUDIO */
                    503:        if (fd <= 0)
                    504:                return (0);
                    505: 
                    506:        /*
                    507:         * Allocate and initialize unit structure
                    508:         */
                    509:        up = emalloc(sizeof(*up));
                    510:        memset(up, 0, sizeof(*up));
                    511:        pp = peer->procptr;
                    512:        pp->unitptr = (caddr_t)up;
                    513:        pp->io.clock_recv = chu_receive;
                    514:        pp->io.srcclock = (caddr_t)peer;
                    515:        pp->io.datalen = 0;
                    516:        pp->io.fd = fd;
                    517:        if (!io_addclock(&pp->io)) {
                    518:                close(fd);
                    519:                pp->io.fd = -1;
                    520:                free(up);
                    521:                pp->unitptr = NULL;
                    522:                return (0);
                    523:        }
                    524: 
                    525:        /*
                    526:         * Initialize miscellaneous variables
                    527:         */
                    528:        peer->precision = PRECISION;
                    529:        pp->clockdesc = DESCRIPTION;
                    530:        strcpy(up->ident, "CHU");
                    531:        memcpy(&pp->refid, up->ident, 4); 
                    532:        DTOLFP(CHAR, &up->charstamp);
                    533: #ifdef HAVE_AUDIO
                    534: 
                    535:        /*
                    536:         * The companded samples are encoded sign-magnitude. The table
                    537:         * contains all the 256 values in the interest of speed. We do
                    538:         * this even if the audio codec is not available. C'est la lazy.
                    539:         */
                    540:        up->fd_audio = fd_audio;
                    541:        up->gain = 127;
                    542:        up->comp[0] = up->comp[OFFSET] = 0.;
                    543:        up->comp[1] = 1; up->comp[OFFSET + 1] = -1.;
                    544:        up->comp[2] = 3; up->comp[OFFSET + 2] = -3.;
                    545:        step = 2.;
                    546:        for (i = 3; i < OFFSET; i++) {
                    547:                up->comp[i] = up->comp[i - 1] + step;
                    548:                up->comp[OFFSET + i] = -up->comp[i];
                    549:                 if (i % 16 == 0)
                    550:                        step *= 2.;
                    551:        }
                    552:        DTOLFP(1. / SECOND, &up->tick);
                    553: #endif /* HAVE_AUDIO */
                    554: #ifdef ICOM
                    555:        temp = 0;
                    556: #ifdef DEBUG
                    557:        if (debug > 1)
                    558:                temp = P_TRACE;
                    559: #endif
                    560:        if (peer->ttl > 0) {
                    561:                if (peer->ttl & 0x80)
                    562:                        up->fd_icom = icom_init("/dev/icom", B1200,
                    563:                            temp);
                    564:                else
                    565:                        up->fd_icom = icom_init("/dev/icom", B9600,
                    566:                            temp);
                    567:        }
                    568:        if (up->fd_icom > 0) {
                    569:                if (chu_newchan(peer, 0) != 0) {
                    570:                        msyslog(LOG_NOTICE, "icom: radio not found");
                    571:                        close(up->fd_icom);
                    572:                        up->fd_icom = 0;
                    573:                } else {
                    574:                        msyslog(LOG_NOTICE, "icom: autotune enabled");
                    575:                }
                    576:        }
                    577: #endif /* ICOM */
                    578:        return (1);
                    579: }
                    580: 
                    581: 
                    582: /*
                    583:  * chu_shutdown - shut down the clock
                    584:  */
                    585: static void
                    586: chu_shutdown(
                    587:        int     unit,           /* instance number (not used) */
                    588:        struct peer *peer       /* peer structure pointer */
                    589:        )
                    590: {
                    591:        struct chuunit *up;
                    592:        struct refclockproc *pp;
                    593: 
                    594:        pp = peer->procptr;
                    595:        up = (struct chuunit *)pp->unitptr;
                    596:        if (up == NULL)
                    597:                return;
                    598: 
                    599:        io_closeclock(&pp->io);
                    600: #ifdef ICOM
                    601:        if (up->fd_icom > 0)
                    602:                close(up->fd_icom);
                    603: #endif /* ICOM */
                    604:        free(up);
                    605: }
                    606: 
                    607: 
                    608: /*
                    609:  * chu_receive - receive data from the audio or serial device
                    610:  */
                    611: static void
                    612: chu_receive(
                    613:        struct recvbuf *rbufp   /* receive buffer structure pointer */
                    614:        )
                    615: {
                    616: #ifdef HAVE_AUDIO
                    617:        struct chuunit *up;
                    618:        struct refclockproc *pp;
                    619:        struct peer *peer;
                    620: 
                    621:        peer = (struct peer *)rbufp->recv_srcclock;
                    622:        pp = peer->procptr;
                    623:        up = (struct chuunit *)pp->unitptr;
                    624: 
                    625:        /*
                    626:         * If the audio codec is warmed up, the buffer contains codec
                    627:         * samples which need to be demodulated and decoded into CHU
                    628:         * characters using the software UART. Otherwise, the buffer
                    629:         * contains CHU characters from the serial port, so the software
                    630:         * UART is bypassed. In this case the CPU will probably run a
                    631:         * few degrees cooler.
                    632:         */
                    633:        if (up->fd_audio > 0)
                    634:                chu_audio_receive(rbufp);
                    635:        else
                    636:                chu_serial_receive(rbufp);
                    637: #else
                    638:        chu_serial_receive(rbufp);
                    639: #endif /* HAVE_AUDIO */
                    640: }
                    641: 
                    642: 
                    643: #ifdef HAVE_AUDIO
                    644: /*
                    645:  * chu_audio_receive - receive data from the audio device
                    646:  */
                    647: static void
                    648: chu_audio_receive(
                    649:        struct recvbuf *rbufp   /* receive buffer structure pointer */
                    650:        )
                    651: {
                    652:        struct chuunit *up;
                    653:        struct refclockproc *pp;
                    654:        struct peer *peer;
                    655: 
                    656:        double  sample;         /* codec sample */
                    657:        u_char  *dpt;           /* buffer pointer */
                    658:        int     bufcnt;         /* buffer counter */
                    659:        l_fp    ltemp;          /* l_fp temp */
                    660: 
                    661:        peer = (struct peer *)rbufp->recv_srcclock;
                    662:        pp = peer->procptr;
                    663:        up = (struct chuunit *)pp->unitptr;
                    664: 
                    665:        /*
                    666:         * Main loop - read until there ain't no more. Note codec
                    667:         * samples are bit-inverted.
                    668:         */
                    669:        DTOLFP((double)rbufp->recv_length / SECOND, &ltemp);
                    670:        L_SUB(&rbufp->recv_time, &ltemp);
                    671:        up->timestamp = rbufp->recv_time;
                    672:        dpt = rbufp->recv_buffer;
                    673:        for (bufcnt = 0; bufcnt < rbufp->recv_length; bufcnt++) {
                    674:                sample = up->comp[~*dpt++ & 0xff];
                    675: 
                    676:                /*
                    677:                 * Clip noise spikes greater than MAXAMP. If no clips,
                    678:                 * increase the gain a tad; if the clips are too high, 
                    679:                 * decrease a tad.
                    680:                 */
                    681:                if (sample > MAXAMP) {
                    682:                        sample = MAXAMP;
                    683:                        up->clipcnt++;
                    684:                } else if (sample < -MAXAMP) {
                    685:                        sample = -MAXAMP;
                    686:                        up->clipcnt++;
                    687:                }
                    688:                chu_rf(peer, sample);
                    689:                L_ADD(&up->timestamp, &up->tick);
                    690: 
                    691:                /*
                    692:                 * Once each second ride gain.
                    693:                 */
                    694:                up->seccnt = (up->seccnt + 1) % SECOND;
                    695:                if (up->seccnt == 0) {
                    696:                        chu_gain(peer);
                    697:                }
                    698:        }
                    699: 
                    700:        /*
                    701:         * Set the input port and monitor gain for the next buffer.
                    702:         */
                    703:        if (pp->sloppyclockflag & CLK_FLAG2)
                    704:                up->port = 2;
                    705:        else
                    706:                up->port = 1;
                    707:        if (pp->sloppyclockflag & CLK_FLAG3)
                    708:                up->mongain = MONGAIN;
                    709:        else
                    710:                up->mongain = 0;
                    711: }
                    712: 
                    713: 
                    714: /*
                    715:  * chu_rf - filter and demodulate the FSK signal
                    716:  *
                    717:  * This routine implements a 300-baud Bell 103 modem with mark 2225 Hz
                    718:  * and space 2025 Hz. It uses a bandpass filter followed by a soft
                    719:  * limiter, FM discriminator and lowpass filter. A maximum-likelihood
                    720:  * decoder samples the baseband signal at eight times the baud rate and
                    721:  * detects the start bit of each character.
                    722:  *
                    723:  * The filters are built for speed, which explains the rather clumsy
                    724:  * code. Hopefully, the compiler will efficiently implement the move-
                    725:  * and-muiltiply-and-add operations.
                    726:  */
                    727: static void
                    728: chu_rf(
                    729:        struct peer *peer,      /* peer structure pointer */
                    730:        double  sample          /* analog sample */
                    731:        )
                    732: {
                    733:        struct refclockproc *pp;
                    734:        struct chuunit *up;
                    735:        struct surv *sp;
                    736: 
                    737:        /*
                    738:         * Local variables
                    739:         */
                    740:        double  signal;         /* bandpass signal */
                    741:        double  limit;          /* limiter signal */
                    742:        double  disc;           /* discriminator signal */
                    743:        double  lpf;            /* lowpass signal */
                    744:        double  dist;           /* UART signal distance */
                    745:        int     i, j;
                    746: 
                    747:        pp = peer->procptr;
                    748:        up = (struct chuunit *)pp->unitptr;
                    749: 
                    750:        /*
                    751:         * Bandpass filter. 4th-order elliptic, 500-Hz bandpass centered
                    752:         * at 2125 Hz. Passband ripple 0.3 dB, stopband ripple 50 dB,
                    753:         * phase delay 0.24 ms.
                    754:         */
                    755:        signal = (up->bpf[8] = up->bpf[7]) * 5.844676e-01;
                    756:        signal += (up->bpf[7] = up->bpf[6]) * 4.884860e-01;
                    757:        signal += (up->bpf[6] = up->bpf[5]) * 2.704384e+00;
                    758:        signal += (up->bpf[5] = up->bpf[4]) * 1.645032e+00;
                    759:        signal += (up->bpf[4] = up->bpf[3]) * 4.644557e+00;
                    760:        signal += (up->bpf[3] = up->bpf[2]) * 1.879165e+00;
                    761:        signal += (up->bpf[2] = up->bpf[1]) * 3.522634e+00;
                    762:        signal += (up->bpf[1] = up->bpf[0]) * 7.315738e-01;
                    763:        up->bpf[0] = sample - signal;
                    764:        signal = up->bpf[0] * 6.176213e-03
                    765:            + up->bpf[1] * 3.156599e-03
                    766:            + up->bpf[2] * 7.567487e-03
                    767:            + up->bpf[3] * 4.344580e-03
                    768:            + up->bpf[4] * 1.190128e-02
                    769:            + up->bpf[5] * 4.344580e-03
                    770:            + up->bpf[6] * 7.567487e-03
                    771:            + up->bpf[7] * 3.156599e-03
                    772:            + up->bpf[8] * 6.176213e-03;
                    773: 
                    774:        up->monitor = signal / 4.;      /* note monitor after filter */
                    775: 
                    776:        /*
                    777:         * Soft limiter/discriminator. The 11-sample discriminator lag
                    778:         * interval corresponds to three cycles of 2125 Hz, which
                    779:         * requires the sample frequency to be 2125 * 11 / 3 = 7791.7
                    780:         * Hz. The discriminator output varies +-0.5 interval for input
                    781:         * frequency 2025-2225 Hz. However, we don't get to sample at
                    782:         * this frequency, so the discriminator output is biased. Life
                    783:         * at 8000 Hz sucks.
                    784:         */
                    785:        limit = signal;
                    786:        if (limit > LIMIT)
                    787:                limit = LIMIT;
                    788:        else if (limit < -LIMIT)
                    789:                limit = -LIMIT;
                    790:        disc = up->disc[up->discptr] * -limit;
                    791:        up->disc[up->discptr] = limit;
                    792:        up->discptr = (up->discptr + 1 ) % LAG;
                    793:        if (disc >= 0)
                    794:                disc = SQRT(disc);
                    795:        else
                    796:                disc = -SQRT(-disc);
                    797: 
                    798:        /*
                    799:         * Lowpass filter. Raised cosine FIR, Ts = 1 / 300, beta = 0.1.
                    800:         */
                    801:        lpf = (up->lpf[26] = up->lpf[25]) * 2.538771e-02;
                    802:        lpf += (up->lpf[25] = up->lpf[24]) * 1.084671e-01;
                    803:        lpf += (up->lpf[24] = up->lpf[23]) * 2.003159e-01;
                    804:        lpf += (up->lpf[23] = up->lpf[22]) * 2.985303e-01;
                    805:        lpf += (up->lpf[22] = up->lpf[21]) * 4.003697e-01;
                    806:        lpf += (up->lpf[21] = up->lpf[20]) * 5.028552e-01;
                    807:        lpf += (up->lpf[20] = up->lpf[19]) * 6.028795e-01;
                    808:        lpf += (up->lpf[19] = up->lpf[18]) * 6.973249e-01;
                    809:        lpf += (up->lpf[18] = up->lpf[17]) * 7.831828e-01;
                    810:        lpf += (up->lpf[17] = up->lpf[16]) * 8.576717e-01;
                    811:        lpf += (up->lpf[16] = up->lpf[15]) * 9.183463e-01;
                    812:        lpf += (up->lpf[15] = up->lpf[14]) * 9.631951e-01;
                    813:        lpf += (up->lpf[14] = up->lpf[13]) * 9.907208e-01;
                    814:        lpf += (up->lpf[13] = up->lpf[12]) * 1.000000e+00;
                    815:        lpf += (up->lpf[12] = up->lpf[11]) * 9.907208e-01;
                    816:        lpf += (up->lpf[11] = up->lpf[10]) * 9.631951e-01;
                    817:        lpf += (up->lpf[10] = up->lpf[9]) * 9.183463e-01;
                    818:        lpf += (up->lpf[9] = up->lpf[8]) * 8.576717e-01;
                    819:        lpf += (up->lpf[8] = up->lpf[7]) * 7.831828e-01;
                    820:        lpf += (up->lpf[7] = up->lpf[6]) * 6.973249e-01;
                    821:        lpf += (up->lpf[6] = up->lpf[5]) * 6.028795e-01;
                    822:        lpf += (up->lpf[5] = up->lpf[4]) * 5.028552e-01;
                    823:        lpf += (up->lpf[4] = up->lpf[3]) * 4.003697e-01;
                    824:        lpf += (up->lpf[3] = up->lpf[2]) * 2.985303e-01;
                    825:        lpf += (up->lpf[2] = up->lpf[1]) * 2.003159e-01;
                    826:        lpf += (up->lpf[1] = up->lpf[0]) * 1.084671e-01;
                    827:        lpf += up->lpf[0] = disc * 2.538771e-02;
                    828: 
                    829:        /*
                    830:         * Maximum-likelihood decoder. The UART updates each of the
                    831:         * eight survivors and determines the span, slice level and
                    832:         * tentative decoded character. Valid 11-bit characters are
                    833:         * framed so that bit 10 and bit 11 (stop bits) are mark and bit
                    834:         * 1 (start bit) is space. When a valid character is found, the
                    835:         * survivor with maximum distance determines the final decoded
                    836:         * character.
                    837:         */
                    838:        up->baud += 1. / SECOND;
                    839:        if (up->baud > 1. / (BAUD * 8.)) {
                    840:                up->baud -= 1. / (BAUD * 8.);
                    841:                up->decptr = (up->decptr + 1) % 8;
                    842:                sp = &up->surv[up->decptr];
                    843:                sp->cstamp = up->timestamp;
                    844:                chu_uart(sp, -lpf * AGAIN);
                    845:                if (up->dbrk > 0) {
                    846:                        up->dbrk--;
                    847:                        if (up->dbrk > 0)
                    848:                                return;
                    849: 
                    850:                        up->decpha = up->decptr;
                    851:                }
                    852:                if (up->decptr != up->decpha)
                    853:                        return;
                    854: 
                    855:                dist = 0;
                    856:                j = -1;
                    857:                for (i = 0; i < 8; i++) {
                    858: 
                    859:                        /*
                    860:                         * The timestamp is taken at the last bit, so
                    861:                         * for correct decoding we reqire sufficient
                    862:                         * span and correct start bit and two stop bits.
                    863:                         */
                    864:                        if ((up->surv[i].uart & 0x601) != 0x600 ||
                    865:                            up->surv[i].span < SPAN)
                    866:                                continue;
                    867: 
                    868:                        if (up->surv[i].dist > dist) {
                    869:                                dist = up->surv[i].dist;
                    870:                                j = i;
                    871:                        }
                    872:                }
                    873:                if (j < 0)
                    874:                        return;
                    875: 
                    876:                /*
                    877:                 * Process the character, then blank the decoder until
                    878:                 * the end of the next character.This sets the decoding
                    879:                 * phase of the entire burst from the phase of the first
                    880:                 * character.
                    881:                 */
                    882:                up->maxsignal = up->surv[j].span;
                    883:                chu_decode(peer, (up->surv[j].uart >> 1) & 0xff,
                    884:                    up->surv[j].cstamp);
                    885:                up->dbrk = 88;
                    886:        }
                    887: }
                    888: 
                    889: 
                    890: /*
                    891:  * chu_uart - maximum-likelihood UART
                    892:  *
                    893:  * This routine updates a shift register holding the last 11 envelope
                    894:  * samples. It then computes the slice level and span over these samples
                    895:  * and determines the tentative data bits and distance. The calling
                    896:  * program selects over the last eight survivors the one with maximum
                    897:  * distance to determine the decoded character.
                    898:  */
                    899: static void
                    900: chu_uart(
                    901:        struct surv *sp,        /* survivor structure pointer */
                    902:        double  sample          /* baseband signal */
                    903:        )
                    904: {
                    905:        double  es_max, es_min; /* max/min envelope */
                    906:        double  slice;          /* slice level */
                    907:        double  dist;           /* distance */
                    908:        double  dtemp;
                    909:        int     i;
                    910: 
                    911:        /*
                    912:         * Save the sample and shift right. At the same time, measure
                    913:         * the maximum and minimum over all eleven samples.
                    914:         */
                    915:        es_max = -1e6;
                    916:        es_min = 1e6;
                    917:        sp->shift[0] = sample;
                    918:        for (i = 11; i > 0; i--) {
                    919:                sp->shift[i] = sp->shift[i - 1];
                    920:                if (sp->shift[i] > es_max)
                    921:                        es_max = sp->shift[i];
                    922:                if (sp->shift[i] < es_min)
                    923:                        es_min = sp->shift[i];
                    924:        }
                    925: 
                    926:        /*
                    927:         * Determine the span as the maximum less the minimum and the
                    928:         * slice level as the minimum plus a fraction of the span. Note
                    929:         * the slight bias toward mark to correct for the modem tendency
                    930:         * to make more mark than space errors. Compute the distance on
                    931:         * the assumption the last two bits must be mark, the first
                    932:         * space and the rest either mark or space. 
                    933:         */ 
                    934:        sp->span = es_max - es_min;
                    935:        slice = es_min + .45 * sp->span;
                    936:        dist = 0;
                    937:        sp->uart = 0;
                    938:        for (i = 1; i < 12; i++) {
                    939:                sp->uart <<= 1;
                    940:                dtemp = sp->shift[i];
                    941:                if (dtemp > slice)
                    942:                        sp->uart |= 0x1;
                    943:                if (i == 1 || i == 2) {
                    944:                        dist += dtemp - es_min;
                    945:                } else if (i == 11) {
                    946:                        dist += es_max - dtemp;
                    947:                } else {
                    948:                        if (dtemp > slice)
                    949:                                dist += dtemp - es_min;
                    950:                        else
                    951:                                dist += es_max - dtemp;
                    952:                }
                    953:        }
                    954:        sp->dist = dist / (11 * sp->span);
                    955: }
                    956: #endif /* HAVE_AUDIO */
                    957: 
                    958: 
                    959: /*
                    960:  * chu_serial_receive - receive data from the serial device
                    961:  */
                    962: static void
                    963: chu_serial_receive(
                    964:        struct recvbuf *rbufp   /* receive buffer structure pointer */
                    965:        )
                    966: {
                    967:        struct chuunit *up;
                    968:        struct refclockproc *pp;
                    969:        struct peer *peer;
                    970: 
                    971:        u_char  *dpt;           /* receive buffer pointer */
                    972: 
                    973:        peer = (struct peer *)rbufp->recv_srcclock;
                    974:        pp = peer->procptr;
                    975:        up = (struct chuunit *)pp->unitptr;
                    976: 
                    977:        dpt = (u_char *)&rbufp->recv_space;
                    978:        chu_decode(peer, *dpt, rbufp->recv_time);
                    979: }
                    980: 
                    981: 
                    982: /*
                    983:  * chu_decode - decode the character data
                    984:  */
                    985: static void
                    986: chu_decode(
                    987:        struct peer *peer,      /* peer structure pointer */
                    988:        int     hexhex,         /* data character */
                    989:        l_fp    cstamp          /* data character timestamp */
                    990:        )
                    991: {
                    992:        struct refclockproc *pp;
                    993:        struct chuunit *up;
                    994: 
                    995:        l_fp    tstmp;          /* timestamp temp */
                    996:        double  dtemp;
                    997: 
                    998:        pp = peer->procptr;
                    999:        up = (struct chuunit *)pp->unitptr;
                   1000: 
                   1001:        /*
                   1002:         * If the interval since the last character is greater than the
                   1003:         * longest burst, process the last burst and start a new one. If
                   1004:         * the interval is less than this but greater than two
                   1005:         * characters, consider this a noise burst and reject it.
                   1006:         */
                   1007:        tstmp = up->timestamp;
                   1008:        if (L_ISZERO(&up->laststamp))
                   1009:                up->laststamp = up->timestamp;
                   1010:        L_SUB(&tstmp, &up->laststamp);
                   1011:        up->laststamp = up->timestamp;
                   1012:        LFPTOD(&tstmp, dtemp);
                   1013:        if (dtemp > BURST * CHAR) {
                   1014:                chu_burst(peer);
                   1015:                up->ndx = 0;
                   1016:        } else if (dtemp > 2.5 * CHAR) {
                   1017:                up->ndx = 0;
                   1018:        }
                   1019: 
                   1020:        /*
                   1021:         * Append the character to the current burst and append the
                   1022:         * character timestamp to the timestamp list.
                   1023:         */
                   1024:        if (up->ndx < BURST) {
                   1025:                up->cbuf[up->ndx] = hexhex & 0xff;
                   1026:                up->cstamp[up->ndx] = cstamp;
                   1027:                up->ndx++;
                   1028: 
                   1029:        }
                   1030: }
                   1031: 
                   1032: 
                   1033: /*
                   1034:  * chu_burst - search for valid burst format
                   1035:  */
                   1036: static void
                   1037: chu_burst(
                   1038:        struct peer *peer
                   1039:        )
                   1040: {
                   1041:        struct chuunit *up;
                   1042:        struct refclockproc *pp;
                   1043: 
                   1044:        int     i;
                   1045: 
                   1046:        pp = peer->procptr;
                   1047:        up = (struct chuunit *)pp->unitptr;
                   1048: 
                   1049:        /*
                   1050:         * Correlate a block of five characters with the next block of
                   1051:         * five characters. The burst distance is defined as the number
                   1052:         * of bits that match in the two blocks for format A and that
                   1053:         * match the inverse for format B.
                   1054:         */
                   1055:        if (up->ndx < MINCHAR) {
                   1056:                up->status |= RUNT;
                   1057:                return;
                   1058:        }
                   1059:        up->burdist = 0;
                   1060:        for (i = 0; i < 5 && i < up->ndx - 5; i++)
                   1061:                up->burdist += chu_dist(up->cbuf[i], up->cbuf[i + 5]);
                   1062: 
                   1063:        /*
                   1064:         * If the burst distance is at least MINDIST, this must be a
                   1065:         * format A burst; if the value is not greater than -MINDIST, it
                   1066:         * must be a format B burst. If the B burst is perfect, we
                   1067:         * believe it; otherwise, it is a noise burst and of no use to
                   1068:         * anybody.
                   1069:         */
                   1070:        if (up->burdist >= MINDIST) {
                   1071:                chu_a(peer, up->ndx);
                   1072:        } else if (up->burdist <= -MINDIST) {
                   1073:                chu_b(peer, up->ndx);
                   1074:        } else {
                   1075:                up->status |= NOISE;
                   1076:                return;
                   1077:        }
                   1078: 
                   1079:        /*
                   1080:         * If this is a valid burst, wait a guard time of ten seconds to
                   1081:         * allow for more bursts, then arm the poll update routine to
                   1082:         * process the minute. Don't do this if this is called from the
                   1083:         * timer interrupt routine.
                   1084:         */
                   1085:        if (peer->outdate != current_time)
                   1086:                peer->nextdate = current_time + 10;
                   1087: }
                   1088: 
                   1089: 
                   1090: /*
                   1091:  * chu_b - decode format B burst
                   1092:  */
                   1093: static void
                   1094: chu_b(
                   1095:        struct peer *peer,
                   1096:        int     nchar
                   1097:        )
                   1098: {
                   1099:        struct  refclockproc *pp;
                   1100:        struct  chuunit *up;
                   1101: 
                   1102:        u_char  code[11];       /* decoded timecode */
                   1103:        char    tbuf[80];       /* trace buffer */
                   1104:        char *  p;
                   1105:        size_t  chars;
                   1106:        size_t  cb;
                   1107:        int     i;
                   1108: 
                   1109:        pp = peer->procptr;
                   1110:        up = (struct chuunit *)pp->unitptr;
                   1111: 
                   1112:        /*
                   1113:         * In a format B burst, a character is considered valid only if
                   1114:         * the first occurence matches the last occurence. The burst is
                   1115:         * considered valid only if all characters are valid; that is,
                   1116:         * only if the distance is 40. Note that once a valid frame has
                   1117:         * been found errors are ignored.
                   1118:         */
                   1119:        snprintf(tbuf, sizeof(tbuf), "chuB %04x %4.0f %2d %2d ",
                   1120:                 up->status, up->maxsignal, nchar, -up->burdist);
                   1121:        cb = sizeof(tbuf);
                   1122:        p = tbuf;
                   1123:        for (i = 0; i < nchar; i++) {
                   1124:                chars = strlen(p);
                   1125:                if (cb < chars + 1) {
                   1126:                        msyslog(LOG_ERR, "chu_b() fatal out buffer");
                   1127:                        exit(1);
                   1128:                }
                   1129:                cb -= chars;
                   1130:                p += chars;
                   1131:                snprintf(p, cb, "%02x", up->cbuf[i]);
                   1132:        }
                   1133:        if (pp->sloppyclockflag & CLK_FLAG4)
                   1134:                record_clock_stats(&peer->srcadr, tbuf);
                   1135: #ifdef DEBUG
                   1136:        if (debug)
                   1137:                printf("%s\n", tbuf);
                   1138: #endif
                   1139:        if (up->burdist > -40) {
                   1140:                up->status |= BFRAME;
                   1141:                return;
                   1142:        }
                   1143: 
                   1144:        /*
                   1145:         * Convert the burst data to internal format. Don't bother with
                   1146:         * the timestamps.
                   1147:         */
                   1148:        for (i = 0; i < 5; i++) {
                   1149:                code[2 * i] = hexchar[up->cbuf[i] & 0xf];
                   1150:                code[2 * i + 1] = hexchar[(up->cbuf[i] >>
                   1151:                    4) & 0xf];
                   1152:        }
                   1153:        if (sscanf((char *)code, "%1x%1d%4d%2d%2x", &up->leap, &up->dut,
                   1154:            &pp->year, &up->tai, &up->dst) != 5) {
                   1155:                up->status |= BFORMAT;
                   1156:                return;
                   1157:        }
                   1158:        up->status |= BVALID;
                   1159:        if (up->leap & 0x8)
                   1160:                up->dut = -up->dut;
                   1161: }
                   1162: 
                   1163: 
                   1164: /*
                   1165:  * chu_a - decode format A burst
                   1166:  */
                   1167: static void
                   1168: chu_a(
                   1169:        struct peer *peer,
                   1170:        int nchar
                   1171:        )
                   1172: {
                   1173:        struct refclockproc *pp;
                   1174:        struct chuunit *up;
                   1175: 
                   1176:        char    tbuf[80];       /* trace buffer */
                   1177:        char *  p;
                   1178:        size_t  chars;
                   1179:        size_t  cb;
                   1180:        l_fp    offset;         /* timestamp offset */
                   1181:        int     val;            /* distance */
                   1182:        int     temp;
                   1183:        int     i, j, k;
                   1184: 
                   1185:        pp = peer->procptr;
                   1186:        up = (struct chuunit *)pp->unitptr;
                   1187: 
                   1188:        /*
                   1189:         * Determine correct burst phase. There are three cases
                   1190:         * corresponding to in-phase, one character early or one
                   1191:         * character late. These cases are distinguished by the position
                   1192:         * of the framing digits 0x6 at positions 0 and 5 and 0x3 at
                   1193:         * positions 4 and 9. The correct phase is when the distance
                   1194:         * relative to the framing digits is maximum. The burst is valid
                   1195:         * only if the maximum distance is at least MINSYNC.
                   1196:         */
                   1197:        up->syndist = k = 0;
                   1198:        val = -16;
                   1199:        for (i = -1; i < 2; i++) {
                   1200:                temp = up->cbuf[i + 4] & 0xf;
                   1201:                if (i >= 0)
                   1202:                        temp |= (up->cbuf[i] & 0xf) << 4;
                   1203:                val = chu_dist(temp, 0x63);
                   1204:                temp = (up->cbuf[i + 5] & 0xf) << 4;
                   1205:                if (i + 9 < nchar)
                   1206:                        temp |= up->cbuf[i + 9] & 0xf;
                   1207:                val += chu_dist(temp, 0x63);
                   1208:                if (val > up->syndist) {
                   1209:                        up->syndist = val;
                   1210:                        k = i;
                   1211:                }
                   1212:        }
                   1213: 
                   1214:        /*
                   1215:         * Extract the second number; it must be in the range 2 through
                   1216:         * 9 and the two repititions must be the same.
                   1217:         */
                   1218:        temp = (up->cbuf[k + 4] >> 4) & 0xf;
                   1219:        if (temp < 2 || temp > 9 || k + 9 >= nchar || temp !=
                   1220:            ((up->cbuf[k + 9] >> 4) & 0xf))
                   1221:                temp = 0;
                   1222:        snprintf(tbuf, sizeof(tbuf),
                   1223:                 "chuA %04x %4.0f %2d %2d %2d %2d %1d ", up->status,
                   1224:                 up->maxsignal, nchar, up->burdist, k, up->syndist,
                   1225:                 temp);
                   1226:        cb = sizeof(tbuf);
                   1227:        p = tbuf;
                   1228:        for (i = 0; i < nchar; i++) {
                   1229:                chars = strlen(p);
                   1230:                if (cb < chars + 1) {
                   1231:                        msyslog(LOG_ERR, "chu_a() fatal out buffer");
                   1232:                        exit(1);
                   1233:                }
                   1234:                cb -= chars;
                   1235:                p += chars;
                   1236:                snprintf(p, cb, "%02x", up->cbuf[i]);
                   1237:        }
                   1238:        if (pp->sloppyclockflag & CLK_FLAG4)
                   1239:                record_clock_stats(&peer->srcadr, tbuf);
                   1240: #ifdef DEBUG
                   1241:        if (debug)
                   1242:                printf("%s\n", tbuf);
                   1243: #endif
                   1244:        if (up->syndist < MINSYNC) {
                   1245:                up->status |= AFRAME;
                   1246:                return;
                   1247:        }
                   1248: 
                   1249:        /*
                   1250:         * A valid burst requires the first seconds number to match the
                   1251:         * last seconds number. If so, the burst timestamps are
                   1252:         * corrected to the current minute and saved for later
                   1253:         * processing. In addition, the seconds decode is advanced from
                   1254:         * the previous burst to the current one.
                   1255:         */
                   1256:        if (temp == 0) {
                   1257:                up->status |= AFORMAT;
                   1258:        } else {
                   1259:                up->status |= AVALID;
                   1260:                up->second = pp->second = 30 + temp;
                   1261:                offset.l_ui = 30 + temp;
                   1262:                offset.l_f = 0;
                   1263:                i = 0;
                   1264:                if (k < 0)
                   1265:                        offset = up->charstamp;
                   1266:                else if (k > 0)
                   1267:                        i = 1;
                   1268:                for (; i < nchar && i < k + 10; i++) {
                   1269:                        up->tstamp[up->ntstamp] = up->cstamp[i];
                   1270:                        L_SUB(&up->tstamp[up->ntstamp], &offset);
                   1271:                        L_ADD(&offset, &up->charstamp);
                   1272:                        if (up->ntstamp < MAXSTAGE - 1)
                   1273:                                up->ntstamp++;
                   1274:                }
                   1275:                while (temp > up->prevsec) {
                   1276:                        for (j = 15; j > 0; j--) {
                   1277:                                up->decode[9][j] = up->decode[9][j - 1];
                   1278:                                up->decode[19][j] =
                   1279:                                    up->decode[19][j - 1];
                   1280:                        }
                   1281:                        up->decode[9][j] = up->decode[19][j] = 0;
                   1282:                        up->prevsec++;
                   1283:                }
                   1284:        }
                   1285: 
                   1286:        /*
                   1287:         * Stash the data in the decoding matrix.
                   1288:         */
                   1289:        i = -(2 * k);
                   1290:        for (j = 0; j < nchar; j++) {
                   1291:                if (i < 0 || i > 18) {
                   1292:                        i += 2;
                   1293:                        continue;
                   1294:                }
                   1295:                up->decode[i][up->cbuf[j] & 0xf]++;
                   1296:                i++;
                   1297:                up->decode[i][(up->cbuf[j] >> 4) & 0xf]++;
                   1298:                i++;
                   1299:        }
                   1300:        up->burstcnt++;
                   1301: }
                   1302: 
                   1303: 
                   1304: /*
                   1305:  * chu_poll - called by the transmit procedure
                   1306:  */
                   1307: static void
                   1308: chu_poll(
                   1309:        int unit,
                   1310:        struct peer *peer       /* peer structure pointer */
                   1311:        )
                   1312: {
                   1313:        struct refclockproc *pp;
                   1314: 
                   1315:        pp = peer->procptr;
                   1316:        pp->polls++;
                   1317: }
                   1318: 
                   1319: 
                   1320: /*
                   1321:  * chu_second - process minute data
                   1322:  */
                   1323: static void
                   1324: chu_second(
                   1325:        int unit,
                   1326:        struct peer *peer       /* peer structure pointer */
                   1327:        )
                   1328: {
                   1329:        struct refclockproc *pp;
                   1330:        struct chuunit *up;
                   1331:        l_fp    offset;
                   1332:        char    synchar, qual, leapchar;
                   1333:        int     minset, i;
                   1334:        double  dtemp;
                   1335: 
                   1336:        pp = peer->procptr;
                   1337:        up = (struct chuunit *)pp->unitptr;
                   1338: 
                   1339:        /*
                   1340:         * This routine is called once per minute to process the
                   1341:         * accumulated burst data. We do a bit of fancy footwork so that
                   1342:         * this doesn't run while burst data are being accumulated.
                   1343:         */
                   1344:        up->second = (up->second + 1) % 60;
                   1345:        if (up->second != 0)
                   1346:                return;
                   1347: 
                   1348:        /*
                   1349:         * Process the last burst, if still in the burst buffer.
                   1350:         * If the minute contains a valid B frame with sufficient A
                   1351:         * frame metric, it is considered valid. However, the timecode
                   1352:         * is sent to clockstats even if invalid.
                   1353:         */
                   1354:        chu_burst(peer);
                   1355:        minset = ((current_time - peer->update) + 30) / 60;
                   1356:        dtemp = chu_major(peer);
                   1357:        qual = 0;
                   1358:        if (up->status & (BFRAME | AFRAME))
                   1359:                qual |= SYNERR;
                   1360:        if (up->status & (BFORMAT | AFORMAT))
                   1361:                qual |= FMTERR;
                   1362:        if (up->status & DECODE)
                   1363:                qual |= DECERR;
                   1364:        if (up->status & STAMP)
                   1365:                qual |= TSPERR;
                   1366:        if (up->status & BVALID && dtemp >= MINMETRIC)
                   1367:                up->status |= INSYNC;
                   1368:        synchar = leapchar = ' ';
                   1369:        if (!(up->status & INSYNC)) {
                   1370:                pp->leap = LEAP_NOTINSYNC;
                   1371:                synchar = '?';
                   1372:        } else if (up->leap & 0x2) {
                   1373:                pp->leap = LEAP_ADDSECOND;
                   1374:                leapchar = 'L';
                   1375:        } else if (up->leap & 0x4) {
                   1376:                pp->leap = LEAP_DELSECOND;
                   1377:                leapchar = 'l';
                   1378:        } else {
                   1379:                pp->leap = LEAP_NOWARNING;
                   1380:        }
                   1381:        snprintf(pp->a_lastcode, sizeof(pp->a_lastcode),
                   1382:            "%c%1X %04d %03d %02d:%02d:%02d %c%x %+d %d %d %s %.0f %d",
                   1383:            synchar, qual, pp->year, pp->day, pp->hour, pp->minute,
                   1384:            pp->second, leapchar, up->dst, up->dut, minset, up->gain,
                   1385:            up->ident, dtemp, up->ntstamp);
                   1386:        pp->lencode = strlen(pp->a_lastcode);
                   1387: 
                   1388:        /*
                   1389:         * If in sync and the signal metric is above threshold, the
                   1390:         * timecode is ipso fatso valid and can be selected to
                   1391:         * discipline the clock.
                   1392:         */
                   1393:        if (up->status & INSYNC && !(up->status & (DECODE | STAMP)) &&
                   1394:            dtemp > MINMETRIC) {
                   1395:                if (!clocktime(pp->day, pp->hour, pp->minute, 0, GMT,
                   1396:                    up->tstamp[0].l_ui, &pp->yearstart, &offset.l_ui)) {
                   1397:                        up->errflg = CEVNT_BADTIME;
                   1398:                } else {
                   1399:                        offset.l_uf = 0;
                   1400:                        for (i = 0; i < up->ntstamp; i++)
                   1401:                                refclock_process_offset(pp, offset,
                   1402:                                up->tstamp[i], PDELAY +
                   1403:                                    pp->fudgetime1);
                   1404:                        pp->lastref = up->timestamp;
                   1405:                        refclock_receive(peer);
                   1406:                }
                   1407:        }
                   1408:        if (dtemp > 0)
                   1409:                record_clock_stats(&peer->srcadr, pp->a_lastcode);
                   1410: #ifdef DEBUG
                   1411:        if (debug)
                   1412:                printf("chu: timecode %d %s\n", pp->lencode,
                   1413:                    pp->a_lastcode);
                   1414: #endif
                   1415: #ifdef ICOM
                   1416:        chu_newchan(peer, dtemp);
                   1417: #endif /* ICOM */
                   1418:        chu_clear(peer);
                   1419:        if (up->errflg)
                   1420:                refclock_report(peer, up->errflg);
                   1421:        up->errflg = 0;
                   1422: }
                   1423: 
                   1424: 
                   1425: /*
                   1426:  * chu_major - majority decoder
                   1427:  */
                   1428: static double
                   1429: chu_major(
                   1430:        struct peer *peer       /* peer structure pointer */
                   1431:        )
                   1432: {
                   1433:        struct refclockproc *pp;
                   1434:        struct chuunit *up;
                   1435: 
                   1436:        u_char  code[11];       /* decoded timecode */
                   1437:        int     metric;         /* distance metric */
                   1438:        int     val1;           /* maximum distance */
                   1439:        int     synchar;        /* stray cat */
                   1440:        int     temp;
                   1441:        int     i, j, k;
                   1442: 
                   1443:        pp = peer->procptr;
                   1444:        up = (struct chuunit *)pp->unitptr;
                   1445: 
                   1446:        /*
                   1447:         * Majority decoder. Each burst encodes two replications at each
                   1448:         * digit position in the timecode. Each row of the decoding
                   1449:         * matrix encodes the number of occurences of each digit found
                   1450:         * at the corresponding position. The maximum over all
                   1451:         * occurrences at each position is the distance for this
                   1452:         * position and the corresponding digit is the maximum-
                   1453:         * likelihood candidate. If the distance is not more than half
                   1454:         * the total number of occurences, a majority has not been found
                   1455:         * and the data are discarded. The decoding distance is defined
                   1456:         * as the sum of the distances over the first nine digits. The
                   1457:         * tenth digit varies over the seconds, so we don't count it.
                   1458:         */
                   1459:        metric = 0;
                   1460:        for (i = 0; i < 9; i++) {
                   1461:                val1 = 0;
                   1462:                k = 0;
                   1463:                for (j = 0; j < 16; j++) {
                   1464:                        temp = up->decode[i][j] + up->decode[i + 10][j];
                   1465:                        if (temp > val1) {
                   1466:                                val1 = temp;
                   1467:                                k = j;
                   1468:                        }
                   1469:                }
                   1470:                if (val1 <= up->burstcnt)
                   1471:                        up->status |= DECODE;
                   1472:                metric += val1;
                   1473:                code[i] = hexchar[k];
                   1474:        }
                   1475: 
                   1476:        /*
                   1477:         * Compute the timecode timestamp from the days, hours and
                   1478:         * minutes of the timecode. Use clocktime() for the aggregate
                   1479:         * minutes and the minute offset computed from the burst
                   1480:         * seconds. Note that this code relies on the filesystem time
                   1481:         * for the years and does not use the years of the timecode.
                   1482:         */
                   1483:        if (sscanf((char *)code, "%1x%3d%2d%2d", &synchar, &pp->day,
                   1484:            &pp->hour, &pp->minute) != 4)
                   1485:                up->status |= DECODE;
                   1486:        if (up->ntstamp < MINSTAMP)
                   1487:                up->status |= STAMP;
                   1488:        return (metric);
                   1489: }
                   1490: 
                   1491: 
                   1492: /*
                   1493:  * chu_clear - clear decoding matrix
                   1494:  */
                   1495: static void
                   1496: chu_clear(
                   1497:        struct peer *peer       /* peer structure pointer */
                   1498:        )
                   1499: {
                   1500:        struct refclockproc *pp;
                   1501:        struct chuunit *up;
                   1502:        int     i, j;
                   1503: 
                   1504:        pp = peer->procptr;
                   1505:        up = (struct chuunit *)pp->unitptr;
                   1506: 
                   1507:        /*
                   1508:         * Clear stuff for the minute.
                   1509:         */
                   1510:        up->ndx = up->prevsec = 0;
                   1511:        up->burstcnt = up->ntstamp = 0;
                   1512:        up->status &= INSYNC | METRIC;
                   1513:        for (i = 0; i < 20; i++) {
                   1514:                for (j = 0; j < 16; j++)
                   1515:                        up->decode[i][j] = 0;
                   1516:        }
                   1517: }
                   1518: 
                   1519: #ifdef ICOM
                   1520: /*
                   1521:  * chu_newchan - called once per minute to find the best channel;
                   1522:  * returns zero on success, nonzero if ICOM error.
                   1523:  */
                   1524: static int
                   1525: chu_newchan(
                   1526:        struct peer *peer,
                   1527:        double  met
                   1528:        )
                   1529: {
                   1530:        struct chuunit *up;
                   1531:        struct refclockproc *pp;
                   1532:        struct xmtr *sp;
                   1533:        int     rval;
                   1534:        double  metric;
                   1535:        int     i;
                   1536: 
                   1537:        pp = peer->procptr;
                   1538:        up = (struct chuunit *)pp->unitptr;
                   1539: 
                   1540:        /*
                   1541:         * The radio can be tuned to three channels: 0 (3330 kHz), 1
                   1542:         * (7850 kHz) and 2 (14670 kHz). There are five one-minute
                   1543:         * dwells in each cycle. During the first dwell the radio is
                   1544:         * tuned to one of the three channels to measure the channel
                   1545:         * metric. The channel is selected as the one least recently
                   1546:         * measured. During the remaining four dwells the radio is tuned
                   1547:         * to the channel with the highest channel metric. 
                   1548:         */
                   1549:        if (up->fd_icom <= 0)
                   1550:                return (0);
                   1551: 
                   1552:        /*
                   1553:         * Update the current channel metric and age of all channels.
                   1554:         * Scan all channels for the highest metric.
                   1555:         */
                   1556:        sp = &up->xmtr[up->chan];
                   1557:        sp->metric -= sp->integ[sp->iptr];
                   1558:        sp->integ[sp->iptr] = met;
                   1559:        sp->metric += sp->integ[sp->iptr];
                   1560:        sp->probe = 0;
                   1561:        sp->iptr = (sp->iptr + 1) % ISTAGE;
                   1562:        metric = 0;
                   1563:        for (i = 0; i < NCHAN; i++) {
                   1564:                up->xmtr[i].probe++;
                   1565:                if (up->xmtr[i].metric > metric) {
                   1566:                        up->status |= METRIC;
                   1567:                        metric = up->xmtr[i].metric;
                   1568:                        up->chan = i;
                   1569:                }
                   1570:        }
                   1571: 
                   1572:        /*
                   1573:         * Start the next dwell. If the first dwell or no stations have
                   1574:         * been heard, continue round-robin scan.
                   1575:         */
                   1576:        up->dwell = (up->dwell + 1) % DWELL;
                   1577:        if (up->dwell == 0 || metric == 0) {
                   1578:                rval = 0;
                   1579:                for (i = 0; i < NCHAN; i++) {
                   1580:                        if (up->xmtr[i].probe > rval) {
                   1581:                                rval = up->xmtr[i].probe;
                   1582:                                up->chan = i;
                   1583:                        }
                   1584:                }
                   1585:        }
                   1586: 
                   1587:        /* Retune the radio at each dwell in case somebody nudges the
                   1588:         * tuning knob.
                   1589:         */
                   1590:        rval = icom_freq(up->fd_icom, peer->ttl & 0x7f, qsy[up->chan] +
                   1591:            TUNE);
                   1592:        snprintf(up->ident, sizeof(up->ident), "CHU%d", up->chan);
                   1593:        memcpy(&pp->refid, up->ident, 4); 
                   1594:        memcpy(&peer->refid, up->ident, 4);
                   1595:        if (metric == 0 && up->status & METRIC) {
                   1596:                up->status &= ~METRIC;
                   1597:                refclock_report(peer, CEVNT_PROP);
                   1598:        } 
                   1599:        return (rval);
                   1600: }
                   1601: #endif /* ICOM */
                   1602: 
                   1603: 
                   1604: /*
                   1605:  * chu_dist - determine the distance of two octet arguments
                   1606:  */
                   1607: static int
                   1608: chu_dist(
                   1609:        int     x,              /* an octet of bits */
                   1610:        int     y               /* another octet of bits */
                   1611:        )
                   1612: {
                   1613:        int     val;            /* bit count */ 
                   1614:        int     temp;
                   1615:        int     i;
                   1616: 
                   1617:        /*
                   1618:         * The distance is determined as the weight of the exclusive OR
                   1619:         * of the two arguments. The weight is determined by the number
                   1620:         * of one bits in the result. Each one bit increases the weight,
                   1621:         * while each zero bit decreases it.
                   1622:         */
                   1623:        temp = x ^ y;
                   1624:        val = 0;
                   1625:        for (i = 0; i < 8; i++) {
                   1626:                if ((temp & 0x1) == 0)
                   1627:                        val++;
                   1628:                else
                   1629:                        val--;
                   1630:                temp >>= 1;
                   1631:        }
                   1632:        return (val);
                   1633: }
                   1634: 
                   1635: 
                   1636: #ifdef HAVE_AUDIO
                   1637: /*
                   1638:  * chu_gain - adjust codec gain
                   1639:  *
                   1640:  * This routine is called at the end of each second. During the second
                   1641:  * the number of signal clips above the MAXAMP threshold (6000). If
                   1642:  * there are no clips, the gain is bumped up; if there are more than
                   1643:  * MAXCLP clips (100), it is bumped down. The decoder is relatively
                   1644:  * insensitive to amplitude, so this crudity works just peachy. The
                   1645:  * routine also jiggles the input port and selectively mutes the
                   1646:  */
                   1647: static void
                   1648: chu_gain(
                   1649:        struct peer *peer       /* peer structure pointer */
                   1650:        )
                   1651: {
                   1652:        struct refclockproc *pp;
                   1653:        struct chuunit *up;
                   1654: 
                   1655:        pp = peer->procptr;
                   1656:        up = (struct chuunit *)pp->unitptr;
                   1657: 
                   1658:        /*
                   1659:         * Apparently, the codec uses only the high order bits of the
                   1660:         * gain control field. Thus, it may take awhile for changes to
                   1661:         * wiggle the hardware bits.
                   1662:         */
                   1663:        if (up->clipcnt == 0) {
                   1664:                up->gain += 4;
                   1665:                if (up->gain > MAXGAIN)
                   1666:                        up->gain = MAXGAIN;
                   1667:        } else if (up->clipcnt > MAXCLP) {
                   1668:                up->gain -= 4;
                   1669:                if (up->gain < 0)
                   1670:                        up->gain = 0;
                   1671:        }
                   1672:        audio_gain(up->gain, up->mongain, up->port);
                   1673:        up->clipcnt = 0;
                   1674: }
                   1675: #endif /* HAVE_AUDIO */
                   1676: 
                   1677: 
                   1678: #else
                   1679: int refclock_chu_bs;
                   1680: #endif /* REFCLOCK */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>