Annotation of embedaddon/ntp/ntpd/refclock_hpgps.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * refclock_hpgps - clock driver for HP 58503A GPS receiver
        !             3:  */
        !             4: 
        !             5: #ifdef HAVE_CONFIG_H
        !             6: # include <config.h>
        !             7: #endif
        !             8: 
        !             9: #if defined(REFCLOCK) && defined(CLOCK_HPGPS)
        !            10: 
        !            11: #include "ntpd.h"
        !            12: #include "ntp_io.h"
        !            13: #include "ntp_refclock.h"
        !            14: #include "ntp_stdlib.h"
        !            15: 
        !            16: #include <stdio.h>
        !            17: #include <ctype.h>
        !            18: 
        !            19: /* Version 0.1 April  1, 1995  
        !            20:  *         0.2 April 25, 1995
        !            21:  *             tolerant of missing timecode response prompt and sends
        !            22:  *             clear status if prompt indicates error;
        !            23:  *             can use either local time or UTC from receiver;
        !            24:  *             can get receiver status screen via flag4
        !            25:  *
        !            26:  * WARNING!: This driver is UNDER CONSTRUCTION
        !            27:  * Everything in here should be treated with suspicion.
        !            28:  * If it looks wrong, it probably is.
        !            29:  *
        !            30:  * Comments and/or questions to: Dave Vitanye
        !            31:  *                               Hewlett Packard Company
        !            32:  *                               dave@scd.hp.com
        !            33:  *                               (408) 553-2856
        !            34:  *
        !            35:  * Thanks to the author of the PST driver, which was the starting point for
        !            36:  * this one.
        !            37:  *
        !            38:  * This driver supports the HP 58503A Time and Frequency Reference Receiver.
        !            39:  * This receiver uses HP SmartClock (TM) to implement an Enhanced GPS receiver.
        !            40:  * The receiver accuracy when locked to GPS in normal operation is better
        !            41:  * than 1 usec. The accuracy when operating in holdover is typically better
        !            42:  * than 10 usec. per day.
        !            43:  *
        !            44:  * The same driver also handles the HP Z3801A which is available surplus
        !            45:  * from the cell phone industry.  It's popular with hams.
        !            46:  * It needs a different line setup: 19200 baud, 7 data bits, odd parity
        !            47:  * That is selected by adding "mode 1" to the server line in ntp.conf
        !            48:  * HP Z3801A code from Jeff Mock added by Hal Murray, Sep 2005
        !            49:  *
        !            50:  *
        !            51:  * The receiver should be operated with factory default settings.
        !            52:  * Initial driver operation: expects the receiver to be already locked
        !            53:  * to GPS, configured and able to output timecode format 2 messages.
        !            54:  *
        !            55:  * The driver uses the poll sequence :PTIME:TCODE? to get a response from
        !            56:  * the receiver. The receiver responds with a timecode string of ASCII
        !            57:  * printing characters, followed by a <cr><lf>, followed by a prompt string
        !            58:  * issued by the receiver, in the following format:
        !            59:  * T#yyyymmddhhmmssMFLRVcc<cr><lf>scpi > 
        !            60:  *
        !            61:  * The driver processes the response at the <cr> and <lf>, so what the
        !            62:  * driver sees is the prompt from the previous poll, followed by this
        !            63:  * timecode. The prompt from the current poll is (usually) left unread until
        !            64:  * the next poll. So (except on the very first poll) the driver sees this:
        !            65:  *
        !            66:  * scpi > T#yyyymmddhhmmssMFLRVcc<cr><lf>
        !            67:  *
        !            68:  * The T is the on-time character, at 980 msec. before the next 1PPS edge.
        !            69:  * The # is the timecode format type. We look for format 2.
        !            70:  * Without any of the CLK or PPS stuff, then, the receiver buffer timestamp
        !            71:  * at the <cr> is 24 characters later, which is about 25 msec. at 9600 bps,
        !            72:  * so the first approximation for fudge time1 is nominally -0.955 seconds.
        !            73:  * This number probably needs adjusting for each machine / OS type, so far:
        !            74:  *  -0.955000 on an HP 9000 Model 712/80 HP-UX 9.05
        !            75:  *  -0.953175 on an HP 9000 Model 370    HP-UX 9.10 
        !            76:  *
        !            77:  * This receiver also provides a 1PPS signal, but I haven't figured out
        !            78:  * how to deal with any of the CLK or PPS stuff yet. Stay tuned.
        !            79:  *
        !            80:  */
        !            81: 
        !            82: /*
        !            83:  * Fudge Factors
        !            84:  *
        !            85:  * Fudge time1 is used to accomodate the timecode serial interface adjustment.
        !            86:  * Fudge flag4 can be set to request a receiver status screen summary, which
        !            87:  * is recorded in the clockstats file.
        !            88:  */
        !            89: 
        !            90: /*
        !            91:  * Interface definitions
        !            92:  */
        !            93: #define        DEVICE          "/dev/hpgps%d" /* device name and unit */
        !            94: #define        SPEED232        B9600   /* uart speed (9600 baud) */
        !            95: #define        SPEED232Z       B19200  /* uart speed (19200 baud) */
        !            96: #define        PRECISION       (-10)   /* precision assumed (about 1 ms) */
        !            97: #define        REFID           "GPS\0" /*  reference ID */
        !            98: #define        DESCRIPTION     "HP 58503A GPS Time and Frequency Reference Receiver" 
        !            99: 
        !           100: #define SMAX            23*80+1 /* for :SYSTEM:PRINT? status screen response */
        !           101: 
        !           102: #define MTZONE          2       /* number of fields in timezone reply */
        !           103: #define MTCODET2        12      /* number of fields in timecode format T2 */
        !           104: #define NTCODET2        21      /* number of chars to checksum in format T2 */
        !           105: 
        !           106: /*
        !           107:  * Tables to compute the day of year from yyyymmdd timecode.
        !           108:  * Viva la leap.
        !           109:  */
        !           110: static int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        !           111: static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        !           112: 
        !           113: /*
        !           114:  * Unit control structure
        !           115:  */
        !           116: struct hpgpsunit {
        !           117:        int     pollcnt;        /* poll message counter */
        !           118:        int     tzhour;         /* timezone offset, hours */
        !           119:        int     tzminute;       /* timezone offset, minutes */
        !           120:        int     linecnt;        /* set for expected multiple line responses */
        !           121:        char    *lastptr;       /* pointer to receiver response data */
        !           122:        char    statscrn[SMAX]; /* receiver status screen buffer */
        !           123: };
        !           124: 
        !           125: /*
        !           126:  * Function prototypes
        !           127:  */
        !           128: static int     hpgps_start     (int, struct peer *);
        !           129: static void    hpgps_shutdown  (int, struct peer *);
        !           130: static void    hpgps_receive   (struct recvbuf *);
        !           131: static void    hpgps_poll      (int, struct peer *);
        !           132: 
        !           133: /*
        !           134:  * Transfer vector
        !           135:  */
        !           136: struct refclock refclock_hpgps = {
        !           137:        hpgps_start,            /* start up driver */
        !           138:        hpgps_shutdown,         /* shut down driver */
        !           139:        hpgps_poll,             /* transmit poll message */
        !           140:        noentry,                /* not used (old hpgps_control) */
        !           141:        noentry,                /* initialize driver */
        !           142:        noentry,                /* not used (old hpgps_buginfo) */
        !           143:        NOFLAGS                 /* not used */
        !           144: };
        !           145: 
        !           146: 
        !           147: /*
        !           148:  * hpgps_start - open the devices and initialize data for processing
        !           149:  */
        !           150: static int
        !           151: hpgps_start(
        !           152:        int unit,
        !           153:        struct peer *peer
        !           154:        )
        !           155: {
        !           156:        register struct hpgpsunit *up;
        !           157:        struct refclockproc *pp;
        !           158:        int fd;
        !           159:        char device[20];
        !           160: 
        !           161:        /*
        !           162:         * Open serial port. Use CLK line discipline, if available.
        !           163:         * Default is HP 58503A, mode arg selects HP Z3801A
        !           164:         */
        !           165:        snprintf(device, sizeof(device), DEVICE, unit);
        !           166:        /* mode parameter to server config line shares ttl slot */
        !           167:        if ((peer->ttl == 1)) {
        !           168:                if (!(fd = refclock_open(device, SPEED232Z,
        !           169:                                LDISC_CLK | LDISC_7O1)))
        !           170:                        return (0);
        !           171:        } else {
        !           172:                if (!(fd = refclock_open(device, SPEED232, LDISC_CLK)))
        !           173:                        return (0);
        !           174:        }
        !           175:        /*
        !           176:         * Allocate and initialize unit structure
        !           177:         */
        !           178:        up = emalloc(sizeof(*up));
        !           179:        memset(up, 0, sizeof(*up));
        !           180:        pp = peer->procptr;
        !           181:        pp->io.clock_recv = hpgps_receive;
        !           182:        pp->io.srcclock = (caddr_t)peer;
        !           183:        pp->io.datalen = 0;
        !           184:        pp->io.fd = fd;
        !           185:        if (!io_addclock(&pp->io)) {
        !           186:                close(fd);
        !           187:                pp->io.fd = -1;
        !           188:                free(up);
        !           189:                return (0);
        !           190:        }
        !           191:        pp->unitptr = (caddr_t)up;
        !           192: 
        !           193:        /*
        !           194:         * Initialize miscellaneous variables
        !           195:         */
        !           196:        peer->precision = PRECISION;
        !           197:        pp->clockdesc = DESCRIPTION;
        !           198:        memcpy((char *)&pp->refid, REFID, 4);
        !           199:        up->tzhour = 0;
        !           200:        up->tzminute = 0;
        !           201: 
        !           202:        *up->statscrn = '\0';
        !           203:        up->lastptr = up->statscrn;
        !           204:        up->pollcnt = 2;
        !           205: 
        !           206:        /*
        !           207:         * Get the identifier string, which is logged but otherwise ignored,
        !           208:         * and get the local timezone information
        !           209:         */
        !           210:        up->linecnt = 1;
        !           211:        if (write(pp->io.fd, "*IDN?\r:PTIME:TZONE?\r", 20) != 20)
        !           212:            refclock_report(peer, CEVNT_FAULT);
        !           213: 
        !           214:        return (1);
        !           215: }
        !           216: 
        !           217: 
        !           218: /*
        !           219:  * hpgps_shutdown - shut down the clock
        !           220:  */
        !           221: static void
        !           222: hpgps_shutdown(
        !           223:        int unit,
        !           224:        struct peer *peer
        !           225:        )
        !           226: {
        !           227:        register struct hpgpsunit *up;
        !           228:        struct refclockproc *pp;
        !           229: 
        !           230:        pp = peer->procptr;
        !           231:        up = (struct hpgpsunit *)pp->unitptr;
        !           232:        if (-1 != pp->io.fd)
        !           233:                io_closeclock(&pp->io);
        !           234:        if (NULL != up)
        !           235:                free(up);
        !           236: }
        !           237: 
        !           238: 
        !           239: /*
        !           240:  * hpgps_receive - receive data from the serial interface
        !           241:  */
        !           242: static void
        !           243: hpgps_receive(
        !           244:        struct recvbuf *rbufp
        !           245:        )
        !           246: {
        !           247:        register struct hpgpsunit *up;
        !           248:        struct refclockproc *pp;
        !           249:        struct peer *peer;
        !           250:        l_fp trtmp;
        !           251:        char tcodechar1;        /* identifies timecode format */
        !           252:        char tcodechar2;        /* identifies timecode format */
        !           253:        char timequal;          /* time figure of merit: 0-9 */
        !           254:        char freqqual;          /* frequency figure of merit: 0-3 */
        !           255:        char leapchar;          /* leapsecond: + or 0 or - */
        !           256:        char servchar;          /* request for service: 0 = no, 1 = yes */
        !           257:        char syncchar;          /* time info is invalid: 0 = no, 1 = yes */
        !           258:        short expectedsm;       /* expected timecode byte checksum */
        !           259:        short tcodechksm;       /* computed timecode byte checksum */
        !           260:        int i,m,n;
        !           261:        int month, day, lastday;
        !           262:        char *tcp;              /* timecode pointer (skips over the prompt) */
        !           263:        char prompt[BMAX];      /* prompt in response from receiver */
        !           264: 
        !           265:        /*
        !           266:         * Initialize pointers and read the receiver response
        !           267:         */
        !           268:        peer = (struct peer *)rbufp->recv_srcclock;
        !           269:        pp = peer->procptr;
        !           270:        up = (struct hpgpsunit *)pp->unitptr;
        !           271:        *pp->a_lastcode = '\0';
        !           272:        pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &trtmp);
        !           273: 
        !           274: #ifdef DEBUG
        !           275:        if (debug)
        !           276:            printf("hpgps: lencode: %d timecode:%s\n",
        !           277:                   pp->lencode, pp->a_lastcode);
        !           278: #endif
        !           279: 
        !           280:        /*
        !           281:         * If there's no characters in the reply, we can quit now
        !           282:         */
        !           283:        if (pp->lencode == 0)
        !           284:            return;
        !           285: 
        !           286:        /*
        !           287:         * If linecnt is greater than zero, we are getting information only,
        !           288:         * such as the receiver identification string or the receiver status
        !           289:         * screen, so put the receiver response at the end of the status
        !           290:         * screen buffer. When we have the last line, write the buffer to
        !           291:         * the clockstats file and return without further processing.
        !           292:         *
        !           293:         * If linecnt is zero, we are expecting either the timezone
        !           294:         * or a timecode. At this point, also write the response
        !           295:         * to the clockstats file, and go on to process the prompt (if any),
        !           296:         * timezone, or timecode and timestamp.
        !           297:         */
        !           298: 
        !           299: 
        !           300:        if (up->linecnt-- > 0) {
        !           301:                if ((int)(pp->lencode + 2) <= (SMAX - (up->lastptr - up->statscrn))) {
        !           302:                        *up->lastptr++ = '\n';
        !           303:                        (void)strcpy(up->lastptr, pp->a_lastcode);
        !           304:                        up->lastptr += pp->lencode;
        !           305:                }
        !           306:                if (up->linecnt == 0) 
        !           307:                    record_clock_stats(&peer->srcadr, up->statscrn);
        !           308:                
        !           309:                return;
        !           310:        }
        !           311: 
        !           312:        record_clock_stats(&peer->srcadr, pp->a_lastcode);
        !           313:        pp->lastrec = trtmp;
        !           314:             
        !           315:        up->lastptr = up->statscrn;
        !           316:        *up->lastptr = '\0';
        !           317:        up->pollcnt = 2;
        !           318: 
        !           319:        /*
        !           320:         * We get down to business: get a prompt if one is there, issue
        !           321:         * a clear status command if it contains an error indication.
        !           322:         * Next, check for either the timezone reply or the timecode reply
        !           323:         * and decode it.  If we don't recognize the reply, or don't get the
        !           324:         * proper number of decoded fields, or get an out of range timezone,
        !           325:         * or if the timecode checksum is bad, then we declare bad format
        !           326:         * and exit.
        !           327:         *
        !           328:         * Timezone format (including nominal prompt):
        !           329:         * scpi > -H,-M<cr><lf>
        !           330:         *
        !           331:         * Timecode format (including nominal prompt):
        !           332:         * scpi > T2yyyymmddhhmmssMFLRVcc<cr><lf>
        !           333:         *
        !           334:         */
        !           335: 
        !           336:        (void)strcpy(prompt,pp->a_lastcode);
        !           337:        tcp = strrchr(pp->a_lastcode,'>');
        !           338:        if (tcp == NULL)
        !           339:            tcp = pp->a_lastcode; 
        !           340:        else
        !           341:            tcp++;
        !           342:        prompt[tcp - pp->a_lastcode] = '\0';
        !           343:        while ((*tcp == ' ') || (*tcp == '\t')) tcp++;
        !           344: 
        !           345:        /*
        !           346:         * deal with an error indication in the prompt here
        !           347:         */
        !           348:        if (strrchr(prompt,'E') > strrchr(prompt,'s')){
        !           349: #ifdef DEBUG
        !           350:                if (debug)
        !           351:                    printf("hpgps: error indicated in prompt: %s\n", prompt);
        !           352: #endif
        !           353:                if (write(pp->io.fd, "*CLS\r\r", 6) != 6)
        !           354:                    refclock_report(peer, CEVNT_FAULT);
        !           355:        }
        !           356: 
        !           357:        /*
        !           358:         * make sure we got a timezone or timecode format and 
        !           359:         * then process accordingly
        !           360:         */
        !           361:        m = sscanf(tcp,"%c%c", &tcodechar1, &tcodechar2);
        !           362: 
        !           363:        if (m != 2){
        !           364: #ifdef DEBUG
        !           365:                if (debug)
        !           366:                    printf("hpgps: no format indicator\n");
        !           367: #endif
        !           368:                refclock_report(peer, CEVNT_BADREPLY);
        !           369:                return;
        !           370:        }
        !           371: 
        !           372:        switch (tcodechar1) {
        !           373: 
        !           374:            case '+':
        !           375:            case '-':
        !           376:                m = sscanf(tcp,"%d,%d", &up->tzhour, &up->tzminute);
        !           377:                if (m != MTZONE) {
        !           378: #ifdef DEBUG
        !           379:                        if (debug)
        !           380:                            printf("hpgps: only %d fields recognized in timezone\n", m);
        !           381: #endif
        !           382:                        refclock_report(peer, CEVNT_BADREPLY);
        !           383:                        return;
        !           384:                }
        !           385:                if ((up->tzhour < -12) || (up->tzhour > 13) || 
        !           386:                    (up->tzminute < -59) || (up->tzminute > 59)){
        !           387: #ifdef DEBUG
        !           388:                        if (debug)
        !           389:                            printf("hpgps: timezone %d, %d out of range\n",
        !           390:                                   up->tzhour, up->tzminute);
        !           391: #endif
        !           392:                        refclock_report(peer, CEVNT_BADREPLY);
        !           393:                        return;
        !           394:                }
        !           395:                return;
        !           396: 
        !           397:            case 'T':
        !           398:                break;
        !           399: 
        !           400:            default:
        !           401: #ifdef DEBUG
        !           402:                if (debug)
        !           403:                    printf("hpgps: unrecognized reply format %c%c\n",
        !           404:                           tcodechar1, tcodechar2);
        !           405: #endif
        !           406:                refclock_report(peer, CEVNT_BADREPLY);
        !           407:                return;
        !           408:        } /* end of tcodechar1 switch */
        !           409: 
        !           410: 
        !           411:        switch (tcodechar2) {
        !           412: 
        !           413:            case '2':
        !           414:                m = sscanf(tcp,"%*c%*c%4d%2d%2d%2d%2d%2d%c%c%c%c%c%2hx",
        !           415:                           &pp->year, &month, &day, &pp->hour, &pp->minute, &pp->second,
        !           416:                           &timequal, &freqqual, &leapchar, &servchar, &syncchar,
        !           417:                           &expectedsm);
        !           418:                n = NTCODET2;
        !           419: 
        !           420:                if (m != MTCODET2){
        !           421: #ifdef DEBUG
        !           422:                        if (debug)
        !           423:                            printf("hpgps: only %d fields recognized in timecode\n", m);
        !           424: #endif
        !           425:                        refclock_report(peer, CEVNT_BADREPLY);
        !           426:                        return;
        !           427:                }
        !           428:                break;
        !           429: 
        !           430:            default:
        !           431: #ifdef DEBUG
        !           432:                if (debug)
        !           433:                    printf("hpgps: unrecognized timecode format %c%c\n",
        !           434:                           tcodechar1, tcodechar2);
        !           435: #endif
        !           436:                refclock_report(peer, CEVNT_BADREPLY);
        !           437:                return;
        !           438:        } /* end of tcodechar2 format switch */
        !           439:            
        !           440:        /* 
        !           441:         * Compute and verify the checksum.
        !           442:         * Characters are summed starting at tcodechar1, ending at just
        !           443:         * before the expected checksum.  Bail out if incorrect.
        !           444:         */
        !           445:        tcodechksm = 0;
        !           446:        while (n-- > 0) tcodechksm += *tcp++;
        !           447:        tcodechksm &= 0x00ff;
        !           448: 
        !           449:        if (tcodechksm != expectedsm) {
        !           450: #ifdef DEBUG
        !           451:                if (debug)
        !           452:                    printf("hpgps: checksum %2hX doesn't match %2hX expected\n",
        !           453:                           tcodechksm, expectedsm);
        !           454: #endif
        !           455:                refclock_report(peer, CEVNT_BADREPLY);
        !           456:                return;
        !           457:        }
        !           458: 
        !           459:        /* 
        !           460:         * Compute the day of year from the yyyymmdd format.
        !           461:         */
        !           462:        if (month < 1 || month > 12 || day < 1) {
        !           463:                refclock_report(peer, CEVNT_BADTIME);
        !           464:                return;
        !           465:        }
        !           466: 
        !           467:        if ( ! isleap_4(pp->year) ) {                           /* Y2KFixes */
        !           468:                /* not a leap year */
        !           469:                if (day > day1tab[month - 1]) {
        !           470:                        refclock_report(peer, CEVNT_BADTIME);
        !           471:                        return;
        !           472:                }
        !           473:                for (i = 0; i < month - 1; i++) day += day1tab[i];
        !           474:                lastday = 365;
        !           475:        } else {
        !           476:                /* a leap year */
        !           477:                if (day > day2tab[month - 1]) {
        !           478:                        refclock_report(peer, CEVNT_BADTIME);
        !           479:                        return;
        !           480:                }
        !           481:                for (i = 0; i < month - 1; i++) day += day2tab[i];
        !           482:                lastday = 366;
        !           483:        }
        !           484: 
        !           485:        /*
        !           486:         * Deal with the timezone offset here. The receiver timecode is in
        !           487:         * local time = UTC + :PTIME:TZONE, so SUBTRACT the timezone values.
        !           488:         * For example, Pacific Standard Time is -8 hours , 0 minutes.
        !           489:         * Deal with the underflows and overflows.
        !           490:         */
        !           491:        pp->minute -= up->tzminute;
        !           492:        pp->hour -= up->tzhour;
        !           493: 
        !           494:        if (pp->minute < 0) {
        !           495:                pp->minute += 60;
        !           496:                pp->hour--;
        !           497:        }
        !           498:        if (pp->minute > 59) {
        !           499:                pp->minute -= 60;
        !           500:                pp->hour++;
        !           501:        }
        !           502:        if (pp->hour < 0)  {
        !           503:                pp->hour += 24;
        !           504:                day--;
        !           505:                if (day < 1) {
        !           506:                        pp->year--;
        !           507:                        if ( isleap_4(pp->year) )               /* Y2KFixes */
        !           508:                            day = 366;
        !           509:                        else
        !           510:                            day = 365;
        !           511:                }
        !           512:        }
        !           513: 
        !           514:        if (pp->hour > 23) {
        !           515:                pp->hour -= 24;
        !           516:                day++;
        !           517:                if (day > lastday) {
        !           518:                        pp->year++;
        !           519:                        day = 1;
        !           520:                }
        !           521:        }
        !           522: 
        !           523:        pp->day = day;
        !           524: 
        !           525:        /*
        !           526:         * Decode the MFLRV indicators.
        !           527:         * NEED TO FIGURE OUT how to deal with the request for service,
        !           528:         * time quality, and frequency quality indicators some day. 
        !           529:         */
        !           530:        if (syncchar != '0') {
        !           531:                pp->leap = LEAP_NOTINSYNC;
        !           532:        }
        !           533:        else {
        !           534:                pp->leap = LEAP_NOWARNING;
        !           535:                switch (leapchar) {
        !           536: 
        !           537:                    case '0':
        !           538:                        break;
        !           539:                      
        !           540:                    /* See http://bugs.ntp.org/1090
        !           541:                     * Ignore leap announcements unless June or December.
        !           542:                     * Better would be to use :GPSTime? to find the month,
        !           543:                     * but that seems too likely to introduce other bugs.
        !           544:                     */
        !           545:                    case '+':
        !           546:                        if ((month==6) || (month==12))
        !           547:                            pp->leap = LEAP_ADDSECOND;
        !           548:                        break;
        !           549:                      
        !           550:                    case '-':
        !           551:                        if ((month==6) || (month==12))
        !           552:                            pp->leap = LEAP_DELSECOND;
        !           553:                        break;
        !           554:                      
        !           555:                    default:
        !           556: #ifdef DEBUG
        !           557:                        if (debug)
        !           558:                            printf("hpgps: unrecognized leap indicator: %c\n",
        !           559:                                   leapchar);
        !           560: #endif
        !           561:                        refclock_report(peer, CEVNT_BADTIME);
        !           562:                        return;
        !           563:                } /* end of leapchar switch */
        !           564:        }
        !           565: 
        !           566:        /*
        !           567:         * Process the new sample in the median filter and determine the
        !           568:         * reference clock offset and dispersion. We use lastrec as both
        !           569:         * the reference time and receive time in order to avoid being
        !           570:         * cute, like setting the reference time later than the receive
        !           571:         * time, which may cause a paranoid protocol module to chuck out
        !           572:         * the data.
        !           573:         */
        !           574:        if (!refclock_process(pp)) {
        !           575:                refclock_report(peer, CEVNT_BADTIME);
        !           576:                return;
        !           577:        }
        !           578:        pp->lastref = pp->lastrec;
        !           579:        refclock_receive(peer);
        !           580: 
        !           581:        /*
        !           582:         * If CLK_FLAG4 is set, ask for the status screen response.
        !           583:         */
        !           584:        if (pp->sloppyclockflag & CLK_FLAG4){
        !           585:                up->linecnt = 22; 
        !           586:                if (write(pp->io.fd, ":SYSTEM:PRINT?\r", 15) != 15)
        !           587:                    refclock_report(peer, CEVNT_FAULT);
        !           588:        }
        !           589: }
        !           590: 
        !           591: 
        !           592: /*
        !           593:  * hpgps_poll - called by the transmit procedure
        !           594:  */
        !           595: static void
        !           596: hpgps_poll(
        !           597:        int unit,
        !           598:        struct peer *peer
        !           599:        )
        !           600: {
        !           601:        register struct hpgpsunit *up;
        !           602:        struct refclockproc *pp;
        !           603: 
        !           604:        /*
        !           605:         * Time to poll the clock. The HP 58503A responds to a
        !           606:         * ":PTIME:TCODE?" by returning a timecode in the format specified
        !           607:         * above. If nothing is heard from the clock for two polls,
        !           608:         * declare a timeout and keep going.
        !           609:         */
        !           610:        pp = peer->procptr;
        !           611:        up = (struct hpgpsunit *)pp->unitptr;
        !           612:        if (up->pollcnt == 0)
        !           613:            refclock_report(peer, CEVNT_TIMEOUT);
        !           614:        else
        !           615:            up->pollcnt--;
        !           616:        if (write(pp->io.fd, ":PTIME:TCODE?\r", 14) != 14) {
        !           617:                refclock_report(peer, CEVNT_FAULT);
        !           618:        }
        !           619:        else
        !           620:            pp->polls++;
        !           621: }
        !           622: 
        !           623: #else
        !           624: int refclock_hpgps_bs;
        !           625: #endif /* REFCLOCK */

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