Annotation of embedaddon/ntp/parseutil/testdcf.c, revision 1.1.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>