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>