Annotation of embedaddon/ntp/parseutil/testdcf.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * /src/NTP/ntp4-dev/parseutil/testdcf.c,v 4.10 2005/08/06 14:18:43 kardel RELEASE_20050806_A
        !             3:  *
        !             4:  * testdcf.c,v 4.10 2005/08/06 14:18:43 kardel RELEASE_20050806_A
        !             5:  *  
        !             6:  * simple DCF77 100/200ms pulse test program (via 50Baud serial line)
        !             7:  *
        !             8:  * Copyright (c) 1995-2005 by Frank Kardel <kardel <AT> ntp.org>
        !             9:  * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, Germany
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer.
        !            16:  * 2. Redistributions in binary form must reproduce the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer in the
        !            18:  *    documentation and/or other materials provided with the distribution.
        !            19:  * 3. Neither the name of the author nor the names of its contributors
        !            20:  *    may be used to endorse or promote products derived from this software
        !            21:  *    without specific prior written permission.
        !            22:  *
        !            23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
        !            24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
        !            27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            33:  * SUCH DAMAGE.
        !            34:  *
        !            35:  */
        !            36: 
        !            37: #include "ntp_stdlib.h"
        !            38: 
        !            39: #include <sys/ioctl.h>
        !            40: #include <unistd.h>
        !            41: #include <stdio.h>
        !            42: #include <fcntl.h>
        !            43: #include <termios.h>
        !            44: 
        !            45: /*
        !            46:  * state flags
        !            47:  */
        !            48: #define DCFB_ANNOUNCE           0x0001 /* switch time zone warning (DST switch) */
        !            49: #define DCFB_DST                0x0002 /* DST in effect */
        !            50: #define DCFB_LEAP              0x0004 /* LEAP warning (1 hour prior to occurrence) */
        !            51: #define DCFB_ALTERNATE         0x0008 /* alternate antenna used */
        !            52: 
        !            53: struct clocktime               /* clock time broken up from time code */
        !            54: {
        !            55:        long wday;
        !            56:        long day;
        !            57:        long month;
        !            58:        long year;
        !            59:        long hour;
        !            60:        long minute;
        !            61:        long second;
        !            62:        long usecond;
        !            63:        long utcoffset; /* in minutes */
        !            64:        long flags;             /* current clock status */
        !            65: };
        !            66: 
        !            67: typedef struct clocktime clocktime_t;
        !            68: 
        !            69: static char type(unsigned int);
        !            70: 
        !            71: #define TIMES10(_X_) (((_X_) << 3) + ((_X_) << 1))
        !            72: 
        !            73: /*
        !            74:  * parser related return/error codes
        !            75:  */
        !            76: #define CVT_MASK       0x0000000F /* conversion exit code */
        !            77: #define   CVT_NONE     0x00000001 /* format not applicable */
        !            78: #define   CVT_FAIL     0x00000002 /* conversion failed - error code returned */
        !            79: #define   CVT_OK       0x00000004 /* conversion succeeded */
        !            80: #define CVT_BADFMT     0x00000010 /* general format error - (unparsable) */
        !            81: 
        !            82: /*
        !            83:  * DCF77 raw time code
        !            84:  *
        !            85:  * From "Zur Zeit", Physikalisch-Technische Bundesanstalt (PTB), Braunschweig
        !            86:  * und Berlin, Maerz 1989
        !            87:  *
        !            88:  * Timecode transmission:
        !            89:  * AM:
        !            90:  *     time marks are send every second except for the second before the
        !            91:  *     next minute mark
        !            92:  *     time marks consist of a reduction of transmitter power to 25%
        !            93:  *     of the nominal level
        !            94:  *     the falling edge is the time indication (on time)
        !            95:  *     time marks of a 100ms duration constitute a logical 0
        !            96:  *     time marks of a 200ms duration constitute a logical 1
        !            97:  * FM:
        !            98:  *     see the spec. (basically a (non-)inverted psuedo random phase shift)
        !            99:  *
        !           100:  * Encoding:
        !           101:  * Second      Contents
        !           102:  * 0  - 10     AM: free, FM: 0
        !           103:  * 11 - 14     free
        !           104:  * 15          R     - alternate antenna
        !           105:  * 16          A1    - expect zone change (1 hour before)
        !           106:  * 17 - 18     Z1,Z2 - time zone
        !           107:  *              0  0 illegal
        !           108:  *              0  1 MEZ  (MET)
        !           109:  *              1  0 MESZ (MED, MET DST)
        !           110:  *              1  1 illegal
        !           111:  * 19          A2    - expect leap insertion/deletion (1 hour before)
        !           112:  * 20          S     - start of time code (1)
        !           113:  * 21 - 24     M1    - BCD (lsb first) Minutes
        !           114:  * 25 - 27     M10   - BCD (lsb first) 10 Minutes
        !           115:  * 28          P1    - Minute Parity (even)
        !           116:  * 29 - 32     H1    - BCD (lsb first) Hours
        !           117:  * 33 - 34      H10   - BCD (lsb first) 10 Hours
        !           118:  * 35          P2    - Hour Parity (even)
        !           119:  * 36 - 39     D1    - BCD (lsb first) Days
        !           120:  * 40 - 41     D10   - BCD (lsb first) 10 Days
        !           121:  * 42 - 44     DW    - BCD (lsb first) day of week (1: Monday -> 7: Sunday)
        !           122:  * 45 - 49     MO    - BCD (lsb first) Month
        !           123:  * 50           MO0   - 10 Months
        !           124:  * 51 - 53     Y1    - BCD (lsb first) Years
        !           125:  * 54 - 57     Y10   - BCD (lsb first) 10 Years
        !           126:  * 58          P3    - Date Parity (even)
        !           127:  * 59                - usually missing (minute indication), except for leap insertion
        !           128:  */
        !           129: 
        !           130: static char revision[] = "4.10";
        !           131: 
        !           132: static struct rawdcfcode 
        !           133: {
        !           134:        char offset;                    /* start bit */
        !           135: } rawdcfcode[] =
        !           136: {
        !           137:        {  0 }, { 15 }, { 16 }, { 17 }, { 19 }, { 20 }, { 21 }, { 25 }, { 28 }, { 29 },
        !           138:        { 33 }, { 35 }, { 36 }, { 40 }, { 42 }, { 45 }, { 49 }, { 50 }, { 54 }, { 58 }, { 59 }
        !           139: };
        !           140: 
        !           141: #define DCF_M  0
        !           142: #define DCF_R  1
        !           143: #define DCF_A1 2
        !           144: #define DCF_Z  3
        !           145: #define DCF_A2 4
        !           146: #define DCF_S  5
        !           147: #define DCF_M1 6
        !           148: #define DCF_M10        7
        !           149: #define DCF_P1 8
        !           150: #define DCF_H1 9
        !           151: #define DCF_H10        10
        !           152: #define DCF_P2 11
        !           153: #define DCF_D1 12
        !           154: #define DCF_D10        13
        !           155: #define DCF_DW 14
        !           156: #define DCF_MO 15
        !           157: #define DCF_MO0        16
        !           158: #define DCF_Y1 17
        !           159: #define DCF_Y10        18
        !           160: #define DCF_P3 19
        !           161: 
        !           162: static struct partab
        !           163: {
        !           164:        char offset;                    /* start bit of parity field */
        !           165: } partab[] =
        !           166: {
        !           167:        { 21 }, { 29 }, { 36 }, { 59 }
        !           168: };
        !           169: 
        !           170: #define DCF_P_P1       0
        !           171: #define DCF_P_P2       1
        !           172: #define DCF_P_P3       2
        !           173: 
        !           174: #define DCF_Z_MET 0x2
        !           175: #define DCF_Z_MED 0x1
        !           176: 
        !           177: static unsigned long
        !           178: ext_bf(
        !           179:        register unsigned char *buf,
        !           180:        register int   idx
        !           181:        )
        !           182: {
        !           183:        register unsigned long sum = 0;
        !           184:        register int i, first;
        !           185: 
        !           186:        first = rawdcfcode[idx].offset;
        !           187:   
        !           188:        for (i = rawdcfcode[idx+1].offset - 1; i >= first; i--)
        !           189:        {
        !           190:                sum <<= 1;
        !           191:                sum |= (buf[i] != '-');
        !           192:        }
        !           193:        return sum;
        !           194: }
        !           195: 
        !           196: static unsigned
        !           197: pcheck(
        !           198:        register unsigned char *buf,
        !           199:        register int   idx
        !           200:        )
        !           201: {
        !           202:        register int i,last;
        !           203:        register unsigned psum = 1;
        !           204: 
        !           205:        last = partab[idx+1].offset;
        !           206: 
        !           207:        for (i = partab[idx].offset; i < last; i++)
        !           208:            psum ^= (buf[i] != '-');
        !           209: 
        !           210:        return psum;
        !           211: }
        !           212: 
        !           213: static unsigned long
        !           214: convert_rawdcf(
        !           215:        register unsigned char   *buffer,
        !           216:        register int              size,
        !           217:        register clocktime_t     *clock_time
        !           218:        )
        !           219: {
        !           220:        if (size < 57)
        !           221:        {
        !           222:                printf("%-30s", "*** INCOMPLETE");
        !           223:                return CVT_NONE;
        !           224:        }
        !           225:   
        !           226:        /*
        !           227:         * check Start and Parity bits
        !           228:         */
        !           229:        if ((ext_bf(buffer, DCF_S) == 1) &&
        !           230:            pcheck(buffer, DCF_P_P1) &&
        !           231:            pcheck(buffer, DCF_P_P2) &&
        !           232:            pcheck(buffer, DCF_P_P3))
        !           233:        {
        !           234:                /*
        !           235:                 * buffer OK
        !           236:                 */
        !           237: 
        !           238:                clock_time->flags  = 0;
        !           239:                clock_time->usecond= 0;
        !           240:                clock_time->second = 0;
        !           241:                clock_time->minute = ext_bf(buffer, DCF_M10);
        !           242:                clock_time->minute = TIMES10(clock_time->minute) + ext_bf(buffer, DCF_M1);
        !           243:                clock_time->hour   = ext_bf(buffer, DCF_H10);
        !           244:                clock_time->hour   = TIMES10(clock_time->hour) + ext_bf(buffer, DCF_H1);
        !           245:                clock_time->day    = ext_bf(buffer, DCF_D10);
        !           246:                clock_time->day    = TIMES10(clock_time->day) + ext_bf(buffer, DCF_D1);
        !           247:                clock_time->month  = ext_bf(buffer, DCF_MO0);
        !           248:                clock_time->month  = TIMES10(clock_time->month) + ext_bf(buffer, DCF_MO);
        !           249:                clock_time->year   = ext_bf(buffer, DCF_Y10);
        !           250:                clock_time->year   = TIMES10(clock_time->year) + ext_bf(buffer, DCF_Y1);
        !           251:                clock_time->wday   = ext_bf(buffer, DCF_DW);
        !           252: 
        !           253:                switch (ext_bf(buffer, DCF_Z))
        !           254:                {
        !           255:                    case DCF_Z_MET:
        !           256:                        clock_time->utcoffset = -60;
        !           257:                        break;
        !           258: 
        !           259:                    case DCF_Z_MED:
        !           260:                        clock_time->flags     |= DCFB_DST;
        !           261:                        clock_time->utcoffset  = -120;
        !           262:                        break;
        !           263: 
        !           264:                    default:
        !           265:                        printf("%-30s", "*** BAD TIME ZONE");
        !           266:                        return CVT_FAIL|CVT_BADFMT;
        !           267:                }
        !           268: 
        !           269:                if (ext_bf(buffer, DCF_A1))
        !           270:                    clock_time->flags |= DCFB_ANNOUNCE;
        !           271: 
        !           272:                if (ext_bf(buffer, DCF_A2))
        !           273:                    clock_time->flags |= DCFB_LEAP;
        !           274: 
        !           275:                if (ext_bf(buffer, DCF_R))
        !           276:                    clock_time->flags |= DCFB_ALTERNATE;
        !           277: 
        !           278:                return CVT_OK;
        !           279:        }
        !           280:        else
        !           281:        {
        !           282:                /*
        !           283:                 * bad format - not for us
        !           284:                 */
        !           285:                printf("%-30s", "*** BAD FORMAT (invalid/parity)");
        !           286:                return CVT_FAIL|CVT_BADFMT;
        !           287:        }
        !           288: }
        !           289: 
        !           290: static char
        !           291: type(
        !           292:        unsigned int c
        !           293:        )
        !           294: {
        !           295:        c ^= 0xFF;
        !           296:        return (c >= 0xF);
        !           297: }
        !           298: 
        !           299: static const char *wday[8] =
        !           300: {
        !           301:        "??",
        !           302:        "Mo",
        !           303:        "Tu",
        !           304:        "We",
        !           305:        "Th",
        !           306:        "Fr",
        !           307:        "Sa",
        !           308:        "Su"
        !           309: };
        !           310: 
        !           311: static char pat[] = "-\\|/";
        !           312: 
        !           313: #define LINES (24-2)   /* error lines after which the two headlines are repeated */
        !           314: 
        !           315: int
        !           316: main(
        !           317:        int argc,
        !           318:        char *argv[]
        !           319:        )
        !           320: {
        !           321:        if ((argc != 2) && (argc != 3))
        !           322:        {
        !           323:                fprintf(stderr, "usage: %s [-f|-t|-ft|-tf] <device>\n", argv[0]);
        !           324:                exit(1);
        !           325:        }
        !           326:        else
        !           327:        {
        !           328:                unsigned char c;
        !           329:                char *file;
        !           330:                int fd;
        !           331:                int offset = 15;
        !           332:                int trace = 0;
        !           333:                int errs = LINES+1;
        !           334: 
        !           335:                /*
        !           336:                 * SIMPLE(!) argument "parser"
        !           337:                 */
        !           338:                if (argc == 3)
        !           339:                {
        !           340:                        if (strcmp(argv[1], "-f") == 0)
        !           341:                            offset = 0;
        !           342:                        if (strcmp(argv[1], "-t") == 0)
        !           343:                            trace = 1;
        !           344:                        if ((strcmp(argv[1], "-ft") == 0) ||
        !           345:                            (strcmp(argv[1], "-tf") == 0))
        !           346:                        {
        !           347:                                offset = 0;
        !           348:                                trace = 1;
        !           349:                        }
        !           350:                        file = argv[2];
        !           351:                }
        !           352:                else
        !           353:                {
        !           354:                        file = argv[1];
        !           355:                }
        !           356: 
        !           357:                fd = open(file, O_RDONLY);
        !           358:                if (fd == -1)
        !           359:                {
        !           360:                        perror(file);
        !           361:                        exit(1);
        !           362:                }
        !           363:                else
        !           364:                {
        !           365:                        int i;
        !           366: #ifdef TIOCM_RTS
        !           367:                        int on = TIOCM_RTS;
        !           368: #endif
        !           369:                        struct timeval t, tt, tlast;
        !           370:                        char buf[61];
        !           371:                        clocktime_t clock_time;
        !           372:                        struct termios term;
        !           373:                        int rtc = CVT_NONE;
        !           374: 
        !           375:                        if (tcgetattr(fd,  &term) == -1)
        !           376:                        {
        !           377:                                perror("tcgetattr");
        !           378:                                exit(1);
        !           379:                        }
        !           380: 
        !           381:                        memset(term.c_cc, 0, sizeof(term.c_cc));
        !           382:                        term.c_cc[VMIN] = 1;
        !           383: #ifdef NO_PARENB_IGNPAR /* Was: defined(SYS_IRIX4) || defined (SYS_IRIX5) */
        !           384:                        /* somehow doesn't grok PARENB & IGNPAR (mj) */
        !           385:                        term.c_cflag = CS8|CREAD|CLOCAL;
        !           386: #else
        !           387:                        term.c_cflag = CS8|CREAD|CLOCAL|PARENB;
        !           388: #endif
        !           389:                        term.c_iflag = IGNPAR;
        !           390:                        term.c_oflag = 0;
        !           391:                        term.c_lflag = 0;
        !           392: 
        !           393:                        cfsetispeed(&term, B50);
        !           394:                        cfsetospeed(&term, B50);
        !           395: 
        !           396:                        if (tcsetattr(fd, TCSANOW, &term) == -1)
        !           397:                        {
        !           398:                                perror("tcsetattr");
        !           399:                                exit(1);
        !           400:                        }
        !           401: 
        !           402: #ifdef I_POP
        !           403:                        while (ioctl(fd, I_POP, 0) == 0)
        !           404:                            ;
        !           405: #endif
        !           406: #if defined(TIOCMBIC) && defined(TIOCM_RTS)
        !           407:                        if (ioctl(fd, TIOCMBIC, (caddr_t)&on) == -1)
        !           408:                        {
        !           409:                                perror("TIOCM_RTS");
        !           410:                        }
        !           411: #endif
        !           412: 
        !           413:                        printf("  DCF77 monitor %s - Copyright (C) 1993-2005, Frank Kardel\n\n", revision);
        !           414: 
        !           415:                        clock_time.hour = 0;
        !           416:                        clock_time.minute = 0;
        !           417:                        clock_time.day = 0;
        !           418:                        clock_time.wday = 0;
        !           419:                        clock_time.month = 0;
        !           420:                        clock_time.year = 0;
        !           421:                        clock_time.flags = 0;
        !           422:                        buf[60] = '\0';
        !           423:                        for ( i = 0; i < 60; i++)
        !           424:                            buf[i] = '.';
        !           425: 
        !           426:                        gettimeofday(&tlast, 0L);
        !           427:                        i = 0;
        !           428:                        while (read(fd, &c, 1) == 1)
        !           429:                        {
        !           430:                                gettimeofday(&t, 0L);
        !           431:                                tt = t;
        !           432:                                t.tv_sec -= tlast.tv_sec;
        !           433:                                t.tv_usec -= tlast.tv_usec;
        !           434:                                if (t.tv_usec < 0)
        !           435:                                {
        !           436:                                        t.tv_usec += 1000000;
        !           437:                                        t.tv_sec  -= 1;
        !           438:                                }
        !           439: 
        !           440:                                if (errs > LINES)
        !           441:                                {
        !           442:                                        printf("  %s", &"PTB private....RADMLSMin....PHour..PMDay..DayMonthYear....P\n"[offset]);
        !           443:                                        printf("  %s", &"---------------RADMLS1248124P124812P1248121241248112481248P\n"[offset]);
        !           444:                                        errs = 0;
        !           445:                                }
        !           446: 
        !           447:                                if (t.tv_sec > 1 ||
        !           448:                                    (t.tv_sec == 1 &&
        !           449:                                     t.tv_usec > 500000))
        !           450:                                {
        !           451:                                        printf("%c %.*s ", pat[i % (sizeof(pat)-1)], 59 - offset, &buf[offset]);
        !           452: 
        !           453:                                        if ((rtc = convert_rawdcf((unsigned char *)buf, i, &clock_time)) != CVT_OK)
        !           454:                                        {
        !           455:                                                printf("\n");
        !           456:                                                clock_time.hour = 0;
        !           457:                                                clock_time.minute = 0;
        !           458:                                                clock_time.day = 0;
        !           459:                                                clock_time.wday = 0;
        !           460:                                                clock_time.month = 0;
        !           461:                                                clock_time.year = 0;
        !           462:                                                clock_time.flags = 0;
        !           463:                                                errs++;
        !           464:                                        }
        !           465: 
        !           466:                                        if (((c^0xFF)+1) & (c^0xFF))
        !           467:                                            buf[0] = '?';
        !           468:                                        else
        !           469:                                            buf[0] = type(c) ? '#' : '-';
        !           470: 
        !           471:                                        for ( i = 1; i < 60; i++)
        !           472:                                            buf[i] = '.';
        !           473: 
        !           474:                                        i = 0;
        !           475:                                }
        !           476:                                else
        !           477:                                {
        !           478:                                        if (((c^0xFF)+1) & (c^0xFF))
        !           479:                                            buf[i] = '?';
        !           480:                                        else
        !           481:                                            buf[i] = type(c) ? '#' : '-';
        !           482: 
        !           483:                                        printf("%c %.*s ", pat[i % (sizeof(pat)-1)], 59 - offset, &buf[offset]);
        !           484:                                }
        !           485: 
        !           486:                                if (rtc == CVT_OK)
        !           487:                                {
        !           488:                                        printf("%s, %2d:%02d:%02d, %d.%02d.%02d, <%s%s%s%s>",
        !           489:                                               wday[clock_time.wday],
        !           490:                                               (int)clock_time.hour, (int)clock_time.minute, (int)i, (int)clock_time.day, (int)clock_time.month,
        !           491:                                               (int)clock_time.year,
        !           492:                                               (clock_time.flags & DCFB_ALTERNATE) ? "R" : "_",
        !           493:                                               (clock_time.flags & DCFB_ANNOUNCE) ? "A" : "_",
        !           494:                                               (clock_time.flags & DCFB_DST) ? "D" : "_",
        !           495:                                               (clock_time.flags & DCFB_LEAP) ? "L" : "_"
        !           496:                                               );
        !           497:                                        if (trace && (i == 0))
        !           498:                                        {
        !           499:                                                printf("\n");
        !           500:                                                errs++;
        !           501:                                        }
        !           502:                                }
        !           503: 
        !           504:                                printf("\r");
        !           505: 
        !           506:                                if (i < 60)
        !           507:                                {
        !           508:                                        i++;
        !           509:                                }
        !           510: 
        !           511:                                tlast = tt;
        !           512: 
        !           513:                                fflush(stdout);
        !           514:                        }
        !           515:                        close(fd);
        !           516:                }
        !           517:        }
        !           518:        return 0;
        !           519: }
        !           520: 
        !           521: /*
        !           522:  * History:
        !           523:  *
        !           524:  * testdcf.c,v
        !           525:  * Revision 4.10  2005/08/06 14:18:43  kardel
        !           526:  * cleanup warnings
        !           527:  *
        !           528:  * Revision 4.9  2005/08/06 14:14:38  kardel
        !           529:  * document revision on startup
        !           530:  *
        !           531:  * Revision 4.8  2005/08/06 14:10:08  kardel
        !           532:  * fix setting of baud rate
        !           533:  *
        !           534:  * Revision 4.7  2005/04/16 17:32:10  kardel
        !           535:  * update copyright
        !           536:  *
        !           537:  * Revision 4.6  2004/11/14 15:29:42  kardel
        !           538:  * support PPSAPI, upgrade Copyright to Berkeley style
        !           539:  *
        !           540:  */

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