1c0b746e5SOllivier Robert /* 2c0b746e5SOllivier Robert * /src/NTP/ntp-4/libparse/clk_rawdcf.c,v 4.6 1998/06/14 21:09:37 kardel RELEASE_19990228_A 3c0b746e5SOllivier Robert * 4c0b746e5SOllivier Robert * clk_rawdcf.c,v 4.6 1998/06/14 21:09:37 kardel RELEASE_19990228_A 5c0b746e5SOllivier Robert * 6c0b746e5SOllivier Robert * Raw DCF77 pulse clock support 7c0b746e5SOllivier Robert * 8c0b746e5SOllivier Robert * Copyright (C) 1992-1998 by Frank Kardel 9c0b746e5SOllivier Robert * Friedrich-Alexander Universit�t Erlangen-N�rnberg, Germany 10c0b746e5SOllivier Robert * 11c0b746e5SOllivier Robert * This program is distributed in the hope that it will be useful, 12c0b746e5SOllivier Robert * but WITHOUT ANY WARRANTY; without even the implied warranty of 13c0b746e5SOllivier Robert * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 14c0b746e5SOllivier Robert * 15c0b746e5SOllivier Robert */ 16c0b746e5SOllivier Robert 17c0b746e5SOllivier Robert #ifdef HAVE_CONFIG_H 18c0b746e5SOllivier Robert # include <config.h> 19c0b746e5SOllivier Robert #endif 20c0b746e5SOllivier Robert 21c0b746e5SOllivier Robert #if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_RAWDCF) 22c0b746e5SOllivier Robert 23c0b746e5SOllivier Robert #include <sys/types.h> 24c0b746e5SOllivier Robert #include <sys/time.h> 25c0b746e5SOllivier Robert 26c0b746e5SOllivier Robert #include "ntp_fp.h" 27c0b746e5SOllivier Robert #include "ntp_unixtime.h" 28c0b746e5SOllivier Robert #include "ntp_calendar.h" 29c0b746e5SOllivier Robert 30c0b746e5SOllivier Robert #include "parse.h" 31c0b746e5SOllivier Robert #ifdef PARSESTREAM 32c0b746e5SOllivier Robert # include <sys/parsestreams.h> 33c0b746e5SOllivier Robert #endif 34c0b746e5SOllivier Robert 35c0b746e5SOllivier Robert #ifndef PARSEKERNEL 36c0b746e5SOllivier Robert # include "ntp_stdlib.h" 37c0b746e5SOllivier Robert #endif 38c0b746e5SOllivier Robert 39c0b746e5SOllivier Robert /* 40c0b746e5SOllivier Robert * DCF77 raw time code 41c0b746e5SOllivier Robert * 42c0b746e5SOllivier Robert * From "Zur Zeit", Physikalisch-Technische Bundesanstalt (PTB), Braunschweig 43c0b746e5SOllivier Robert * und Berlin, Maerz 1989 44c0b746e5SOllivier Robert * 45c0b746e5SOllivier Robert * Timecode transmission: 46c0b746e5SOllivier Robert * AM: 47c0b746e5SOllivier Robert * time marks are send every second except for the second before the 48c0b746e5SOllivier Robert * next minute mark 49c0b746e5SOllivier Robert * time marks consist of a reduction of transmitter power to 25% 50c0b746e5SOllivier Robert * of the nominal level 51c0b746e5SOllivier Robert * the falling edge is the time indication (on time) 52c0b746e5SOllivier Robert * time marks of a 100ms duration constitute a logical 0 53c0b746e5SOllivier Robert * time marks of a 200ms duration constitute a logical 1 54c0b746e5SOllivier Robert * FM: 55c0b746e5SOllivier Robert * see the spec. (basically a (non-)inverted psuedo random phase shift) 56c0b746e5SOllivier Robert * 57c0b746e5SOllivier Robert * Encoding: 58c0b746e5SOllivier Robert * Second Contents 59c0b746e5SOllivier Robert * 0 - 10 AM: free, FM: 0 60c0b746e5SOllivier Robert * 11 - 14 free 61c0b746e5SOllivier Robert * 15 R - alternate antenna 62c0b746e5SOllivier Robert * 16 A1 - expect zone change (1 hour before) 63c0b746e5SOllivier Robert * 17 - 18 Z1,Z2 - time zone 64c0b746e5SOllivier Robert * 0 0 illegal 65c0b746e5SOllivier Robert * 0 1 MEZ (MET) 66c0b746e5SOllivier Robert * 1 0 MESZ (MED, MET DST) 67c0b746e5SOllivier Robert * 1 1 illegal 68c0b746e5SOllivier Robert * 19 A2 - expect leap insertion/deletion (1 hour before) 69c0b746e5SOllivier Robert * 20 S - start of time code (1) 70c0b746e5SOllivier Robert * 21 - 24 M1 - BCD (lsb first) Minutes 71c0b746e5SOllivier Robert * 25 - 27 M10 - BCD (lsb first) 10 Minutes 72c0b746e5SOllivier Robert * 28 P1 - Minute Parity (even) 73c0b746e5SOllivier Robert * 29 - 32 H1 - BCD (lsb first) Hours 74c0b746e5SOllivier Robert * 33 - 34 H10 - BCD (lsb first) 10 Hours 75c0b746e5SOllivier Robert * 35 P2 - Hour Parity (even) 76c0b746e5SOllivier Robert * 36 - 39 D1 - BCD (lsb first) Days 77c0b746e5SOllivier Robert * 40 - 41 D10 - BCD (lsb first) 10 Days 78c0b746e5SOllivier Robert * 42 - 44 DW - BCD (lsb first) day of week (1: Monday -> 7: Sunday) 79c0b746e5SOllivier Robert * 45 - 49 MO - BCD (lsb first) Month 80c0b746e5SOllivier Robert * 50 MO0 - 10 Months 81c0b746e5SOllivier Robert * 51 - 53 Y1 - BCD (lsb first) Years 82c0b746e5SOllivier Robert * 54 - 57 Y10 - BCD (lsb first) 10 Years 83c0b746e5SOllivier Robert * 58 P3 - Date Parity (even) 84c0b746e5SOllivier Robert * 59 - usually missing (minute indication), except for leap insertion 85c0b746e5SOllivier Robert */ 86c0b746e5SOllivier Robert 87c0b746e5SOllivier Robert static u_long pps_rawdcf P((parse_t *, int, timestamp_t *)); 88c0b746e5SOllivier Robert static u_long cvt_rawdcf P((unsigned char *, int, struct format *, clocktime_t *, void *)); 89c0b746e5SOllivier Robert static u_long inp_rawdcf P((parse_t *, unsigned int, timestamp_t *)); 90c0b746e5SOllivier Robert 91c0b746e5SOllivier Robert clockformat_t clock_rawdcf = 92c0b746e5SOllivier Robert { 93c0b746e5SOllivier Robert inp_rawdcf, /* DCF77 input handling */ 94c0b746e5SOllivier Robert cvt_rawdcf, /* raw dcf input conversion */ 95c0b746e5SOllivier Robert pps_rawdcf, /* examining PPS information */ 96c0b746e5SOllivier Robert 0, /* no private configuration data */ 97c0b746e5SOllivier Robert "RAW DCF77 Timecode", /* direct decoding / time synthesis */ 98c0b746e5SOllivier Robert 99c0b746e5SOllivier Robert 61, /* bit buffer */ 100c0b746e5SOllivier Robert 0 /* no private data (currently in input buffer) */ 101c0b746e5SOllivier Robert }; 102c0b746e5SOllivier Robert 103c0b746e5SOllivier Robert static struct dcfparam 104c0b746e5SOllivier Robert { 105c0b746e5SOllivier Robert unsigned char onebits[60]; 106c0b746e5SOllivier Robert unsigned char zerobits[60]; 107c0b746e5SOllivier Robert } dcfparameter = 108c0b746e5SOllivier Robert { 109c0b746e5SOllivier Robert "###############RADMLS1248124P124812P1248121241248112481248P", /* 'ONE' representation */ 110c0b746e5SOllivier Robert "--------------------s-------p------p----------------------p" /* 'ZERO' representation */ 111c0b746e5SOllivier Robert }; 112c0b746e5SOllivier Robert 113c0b746e5SOllivier Robert static struct rawdcfcode 114c0b746e5SOllivier Robert { 115c0b746e5SOllivier Robert char offset; /* start bit */ 116c0b746e5SOllivier Robert } rawdcfcode[] = 117c0b746e5SOllivier Robert { 118c0b746e5SOllivier Robert { 0 }, { 15 }, { 16 }, { 17 }, { 19 }, { 20 }, { 21 }, { 25 }, { 28 }, { 29 }, 119c0b746e5SOllivier Robert { 33 }, { 35 }, { 36 }, { 40 }, { 42 }, { 45 }, { 49 }, { 50 }, { 54 }, { 58 }, { 59 } 120c0b746e5SOllivier Robert }; 121c0b746e5SOllivier Robert 122c0b746e5SOllivier Robert #define DCF_M 0 123c0b746e5SOllivier Robert #define DCF_R 1 124c0b746e5SOllivier Robert #define DCF_A1 2 125c0b746e5SOllivier Robert #define DCF_Z 3 126c0b746e5SOllivier Robert #define DCF_A2 4 127c0b746e5SOllivier Robert #define DCF_S 5 128c0b746e5SOllivier Robert #define DCF_M1 6 129c0b746e5SOllivier Robert #define DCF_M10 7 130c0b746e5SOllivier Robert #define DCF_P1 8 131c0b746e5SOllivier Robert #define DCF_H1 9 132c0b746e5SOllivier Robert #define DCF_H10 10 133c0b746e5SOllivier Robert #define DCF_P2 11 134c0b746e5SOllivier Robert #define DCF_D1 12 135c0b746e5SOllivier Robert #define DCF_D10 13 136c0b746e5SOllivier Robert #define DCF_DW 14 137c0b746e5SOllivier Robert #define DCF_MO 15 138c0b746e5SOllivier Robert #define DCF_MO0 16 139c0b746e5SOllivier Robert #define DCF_Y1 17 140c0b746e5SOllivier Robert #define DCF_Y10 18 141c0b746e5SOllivier Robert #define DCF_P3 19 142c0b746e5SOllivier Robert 143c0b746e5SOllivier Robert static struct partab 144c0b746e5SOllivier Robert { 145c0b746e5SOllivier Robert char offset; /* start bit of parity field */ 146c0b746e5SOllivier Robert } partab[] = 147c0b746e5SOllivier Robert { 148c0b746e5SOllivier Robert { 21 }, { 29 }, { 36 }, { 59 } 149c0b746e5SOllivier Robert }; 150c0b746e5SOllivier Robert 151c0b746e5SOllivier Robert #define DCF_P_P1 0 152c0b746e5SOllivier Robert #define DCF_P_P2 1 153c0b746e5SOllivier Robert #define DCF_P_P3 2 154c0b746e5SOllivier Robert 155c0b746e5SOllivier Robert #define DCF_Z_MET 0x2 156c0b746e5SOllivier Robert #define DCF_Z_MED 0x1 157c0b746e5SOllivier Robert 158c0b746e5SOllivier Robert static u_long 159c0b746e5SOllivier Robert ext_bf( 160c0b746e5SOllivier Robert register unsigned char *buf, 161c0b746e5SOllivier Robert register int idx, 162c0b746e5SOllivier Robert register unsigned char *zero 163c0b746e5SOllivier Robert ) 164c0b746e5SOllivier Robert { 165c0b746e5SOllivier Robert register u_long sum = 0; 166c0b746e5SOllivier Robert register int i, first; 167c0b746e5SOllivier Robert 168c0b746e5SOllivier Robert first = rawdcfcode[idx].offset; 169c0b746e5SOllivier Robert 170c0b746e5SOllivier Robert for (i = rawdcfcode[idx+1].offset - 1; i >= first; i--) 171c0b746e5SOllivier Robert { 172c0b746e5SOllivier Robert sum <<= 1; 173c0b746e5SOllivier Robert sum |= (buf[i] != zero[i]); 174c0b746e5SOllivier Robert } 175c0b746e5SOllivier Robert return sum; 176c0b746e5SOllivier Robert } 177c0b746e5SOllivier Robert 178c0b746e5SOllivier Robert static unsigned 179c0b746e5SOllivier Robert pcheck( 180c0b746e5SOllivier Robert unsigned char *buf, 181c0b746e5SOllivier Robert int idx, 182c0b746e5SOllivier Robert unsigned char *zero 183c0b746e5SOllivier Robert ) 184c0b746e5SOllivier Robert { 185c0b746e5SOllivier Robert int i,last; 186c0b746e5SOllivier Robert unsigned psum = 1; 187c0b746e5SOllivier Robert 188c0b746e5SOllivier Robert last = partab[idx+1].offset; 189c0b746e5SOllivier Robert 190c0b746e5SOllivier Robert for (i = partab[idx].offset; i < last; i++) 191c0b746e5SOllivier Robert psum ^= (buf[i] != zero[i]); 192c0b746e5SOllivier Robert 193c0b746e5SOllivier Robert return psum; 194c0b746e5SOllivier Robert } 195c0b746e5SOllivier Robert 196c0b746e5SOllivier Robert static u_long 197c0b746e5SOllivier Robert convert_rawdcf( 198c0b746e5SOllivier Robert unsigned char *buffer, 199c0b746e5SOllivier Robert int size, 200c0b746e5SOllivier Robert struct dcfparam *dcfprm, 201c0b746e5SOllivier Robert clocktime_t *clock_time 202c0b746e5SOllivier Robert ) 203c0b746e5SOllivier Robert { 204c0b746e5SOllivier Robert register unsigned char *s = buffer; 205c0b746e5SOllivier Robert register unsigned char *b = dcfprm->onebits; 206c0b746e5SOllivier Robert register unsigned char *c = dcfprm->zerobits; 207c0b746e5SOllivier Robert register int i; 208c0b746e5SOllivier Robert 209c0b746e5SOllivier Robert parseprintf(DD_RAWDCF,("parse: convert_rawdcf: \"%s\"\n", buffer)); 210c0b746e5SOllivier Robert 211c0b746e5SOllivier Robert if (size < 57) 212c0b746e5SOllivier Robert { 213c0b746e5SOllivier Robert #ifndef PARSEKERNEL 214c0b746e5SOllivier Robert msyslog(LOG_ERR, "parse: convert_rawdcf: INCOMPLETE DATA - time code only has %d bits\n", size); 215c0b746e5SOllivier Robert #endif 216c0b746e5SOllivier Robert return CVT_NONE; 217c0b746e5SOllivier Robert } 218c0b746e5SOllivier Robert 219c0b746e5SOllivier Robert for (i = 0; i < 58; i++) 220c0b746e5SOllivier Robert { 221c0b746e5SOllivier Robert if ((*s != *b) && (*s != *c)) 222c0b746e5SOllivier Robert { 223c0b746e5SOllivier Robert /* 224c0b746e5SOllivier Robert * we only have two types of bytes (ones and zeros) 225c0b746e5SOllivier Robert */ 226c0b746e5SOllivier Robert #ifndef PARSEKERNEL 227c0b746e5SOllivier Robert msyslog(LOG_ERR, "parse: convert_rawdcf: BAD DATA - no conversion for \"%s\"\n", buffer); 228c0b746e5SOllivier Robert #endif 229c0b746e5SOllivier Robert return CVT_NONE; 230c0b746e5SOllivier Robert } 231c0b746e5SOllivier Robert b++; 232c0b746e5SOllivier Robert c++; 233c0b746e5SOllivier Robert s++; 234c0b746e5SOllivier Robert } 235c0b746e5SOllivier Robert 236c0b746e5SOllivier Robert /* 237c0b746e5SOllivier Robert * check Start and Parity bits 238c0b746e5SOllivier Robert */ 239c0b746e5SOllivier Robert if ((ext_bf(buffer, DCF_S, dcfprm->zerobits) == 1) && 240c0b746e5SOllivier Robert pcheck(buffer, DCF_P_P1, dcfprm->zerobits) && 241c0b746e5SOllivier Robert pcheck(buffer, DCF_P_P2, dcfprm->zerobits) && 242c0b746e5SOllivier Robert pcheck(buffer, DCF_P_P3, dcfprm->zerobits)) 243c0b746e5SOllivier Robert { 244c0b746e5SOllivier Robert /* 245c0b746e5SOllivier Robert * buffer OK 246c0b746e5SOllivier Robert */ 247c0b746e5SOllivier Robert parseprintf(DD_RAWDCF,("parse: convert_rawdcf: parity check passed\n")); 248c0b746e5SOllivier Robert 249c0b746e5SOllivier Robert clock_time->flags = PARSEB_S_ANTENNA|PARSEB_S_LEAP; 250c0b746e5SOllivier Robert clock_time->utctime= 0; 251c0b746e5SOllivier Robert clock_time->usecond= 0; 252c0b746e5SOllivier Robert clock_time->second = 0; 253c0b746e5SOllivier Robert clock_time->minute = ext_bf(buffer, DCF_M10, dcfprm->zerobits); 254c0b746e5SOllivier Robert clock_time->minute = TIMES10(clock_time->minute) + ext_bf(buffer, DCF_M1, dcfprm->zerobits); 255c0b746e5SOllivier Robert clock_time->hour = ext_bf(buffer, DCF_H10, dcfprm->zerobits); 256c0b746e5SOllivier Robert clock_time->hour = TIMES10(clock_time->hour) + ext_bf(buffer, DCF_H1, dcfprm->zerobits); 257c0b746e5SOllivier Robert clock_time->day = ext_bf(buffer, DCF_D10, dcfprm->zerobits); 258c0b746e5SOllivier Robert clock_time->day = TIMES10(clock_time->day) + ext_bf(buffer, DCF_D1, dcfprm->zerobits); 259c0b746e5SOllivier Robert clock_time->month = ext_bf(buffer, DCF_MO0, dcfprm->zerobits); 260c0b746e5SOllivier Robert clock_time->month = TIMES10(clock_time->month) + ext_bf(buffer, DCF_MO, dcfprm->zerobits); 261c0b746e5SOllivier Robert clock_time->year = ext_bf(buffer, DCF_Y10, dcfprm->zerobits); 262c0b746e5SOllivier Robert clock_time->year = TIMES10(clock_time->year) + ext_bf(buffer, DCF_Y1, dcfprm->zerobits); 263c0b746e5SOllivier Robert 264c0b746e5SOllivier Robert switch (ext_bf(buffer, DCF_Z, dcfprm->zerobits)) 265c0b746e5SOllivier Robert { 266c0b746e5SOllivier Robert case DCF_Z_MET: 267c0b746e5SOllivier Robert clock_time->utcoffset = -1*60*60; 268c0b746e5SOllivier Robert break; 269c0b746e5SOllivier Robert 270c0b746e5SOllivier Robert case DCF_Z_MED: 271c0b746e5SOllivier Robert clock_time->flags |= PARSEB_DST; 272c0b746e5SOllivier Robert clock_time->utcoffset = -2*60*60; 273c0b746e5SOllivier Robert break; 274c0b746e5SOllivier Robert 275c0b746e5SOllivier Robert default: 276c0b746e5SOllivier Robert parseprintf(DD_RAWDCF,("parse: convert_rawdcf: BAD TIME ZONE\n")); 277c0b746e5SOllivier Robert return CVT_FAIL|CVT_BADFMT; 278c0b746e5SOllivier Robert } 279c0b746e5SOllivier Robert 280c0b746e5SOllivier Robert if (ext_bf(buffer, DCF_A1, dcfprm->zerobits)) 281c0b746e5SOllivier Robert clock_time->flags |= PARSEB_ANNOUNCE; 282c0b746e5SOllivier Robert 283c0b746e5SOllivier Robert if (ext_bf(buffer, DCF_A2, dcfprm->zerobits)) 284c0b746e5SOllivier Robert clock_time->flags |= PARSEB_LEAPADD; /* default: DCF77 data format deficiency */ 285c0b746e5SOllivier Robert 286c0b746e5SOllivier Robert if (ext_bf(buffer, DCF_R, dcfprm->zerobits)) 287c0b746e5SOllivier Robert clock_time->flags |= PARSEB_ALTERNATE; 288c0b746e5SOllivier Robert 289c0b746e5SOllivier Robert parseprintf(DD_RAWDCF,("parse: convert_rawdcf: TIME CODE OK: %d:%d, %d.%d.%d, flags 0x%lx\n", 290c0b746e5SOllivier Robert (int)clock_time->hour, (int)clock_time->minute, (int)clock_time->day, (int)clock_time->month,(int) clock_time->year, 291c0b746e5SOllivier Robert (u_long)clock_time->flags)); 292c0b746e5SOllivier Robert return CVT_OK; 293c0b746e5SOllivier Robert } 294c0b746e5SOllivier Robert else 295c0b746e5SOllivier Robert { 296c0b746e5SOllivier Robert /* 297c0b746e5SOllivier Robert * bad format - not for us 298c0b746e5SOllivier Robert */ 299c0b746e5SOllivier Robert #ifndef PARSEKERNEL 300c0b746e5SOllivier Robert msyslog(LOG_ERR, "parse: convert_rawdcf: parity check FAILED for \"%s\"\n", buffer); 301c0b746e5SOllivier Robert #endif 302c0b746e5SOllivier Robert return CVT_FAIL|CVT_BADFMT; 303c0b746e5SOllivier Robert } 304c0b746e5SOllivier Robert } 305c0b746e5SOllivier Robert 306c0b746e5SOllivier Robert /* 307c0b746e5SOllivier Robert * raw dcf input routine - needs to fix up 50 baud 308c0b746e5SOllivier Robert * characters for 1/0 decision 309c0b746e5SOllivier Robert */ 310c0b746e5SOllivier Robert static u_long 311c0b746e5SOllivier Robert cvt_rawdcf( 312c0b746e5SOllivier Robert unsigned char *buffer, 313c0b746e5SOllivier Robert int size, 314c0b746e5SOllivier Robert struct format *param, 315c0b746e5SOllivier Robert clocktime_t *clock_time, 316c0b746e5SOllivier Robert void *local 317c0b746e5SOllivier Robert ) 318c0b746e5SOllivier Robert { 319c0b746e5SOllivier Robert register unsigned char *s = (unsigned char *)buffer; 320c0b746e5SOllivier Robert register unsigned char *e = s + size; 321c0b746e5SOllivier Robert register unsigned char *b = dcfparameter.onebits; 322c0b746e5SOllivier Robert register unsigned char *c = dcfparameter.zerobits; 323c0b746e5SOllivier Robert register unsigned rtc = CVT_NONE; 324c0b746e5SOllivier Robert register unsigned int i, lowmax, highmax, cutoff, span; 325c0b746e5SOllivier Robert #define BITS 9 326c0b746e5SOllivier Robert unsigned char histbuf[BITS]; 327c0b746e5SOllivier Robert /* 328c0b746e5SOllivier Robert * the input buffer contains characters with runs of consecutive 329c0b746e5SOllivier Robert * bits set. These set bits are an indication of the DCF77 pulse 330c0b746e5SOllivier Robert * length. We assume that we receive the pulse at 50 Baud. Thus 331c0b746e5SOllivier Robert * a 100ms pulse would generate a 4 bit train (20ms per bit and 332c0b746e5SOllivier Robert * start bit) 333c0b746e5SOllivier Robert * a 200ms pulse would create all zeroes (and probably a frame error) 334c0b746e5SOllivier Robert */ 335c0b746e5SOllivier Robert 336c0b746e5SOllivier Robert for (i = 0; i < BITS; i++) 337c0b746e5SOllivier Robert { 338c0b746e5SOllivier Robert histbuf[i] = 0; 339c0b746e5SOllivier Robert } 340c0b746e5SOllivier Robert 341c0b746e5SOllivier Robert cutoff = 0; 342c0b746e5SOllivier Robert lowmax = 0; 343c0b746e5SOllivier Robert 344c0b746e5SOllivier Robert while (s < e) 345c0b746e5SOllivier Robert { 346c0b746e5SOllivier Robert register unsigned int ch = *s ^ 0xFF; 347c0b746e5SOllivier Robert /* 348c0b746e5SOllivier Robert * these lines are left as an excercise to the reader 8-) 349c0b746e5SOllivier Robert */ 350c0b746e5SOllivier Robert if (!((ch+1) & ch) || !*s) 351c0b746e5SOllivier Robert { 352c0b746e5SOllivier Robert 353c0b746e5SOllivier Robert for (i = 0; ch; i++) 354c0b746e5SOllivier Robert { 355c0b746e5SOllivier Robert ch >>= 1; 356c0b746e5SOllivier Robert } 357c0b746e5SOllivier Robert 358c0b746e5SOllivier Robert *s = i; 359c0b746e5SOllivier Robert histbuf[i]++; 360c0b746e5SOllivier Robert cutoff += i; 361c0b746e5SOllivier Robert lowmax++; 362c0b746e5SOllivier Robert } 363c0b746e5SOllivier Robert else 364c0b746e5SOllivier Robert { 365c0b746e5SOllivier Robert parseprintf(DD_RAWDCF,("parse: cvt_rawdcf: character check for 0x%x@%d FAILED\n", *s, (int)(s - (unsigned char *)buffer))); 366c0b746e5SOllivier Robert *s = (unsigned char)~0; 367c0b746e5SOllivier Robert rtc = CVT_FAIL|CVT_BADFMT; 368c0b746e5SOllivier Robert } 369c0b746e5SOllivier Robert s++; 370c0b746e5SOllivier Robert } 371c0b746e5SOllivier Robert 372c0b746e5SOllivier Robert if (lowmax) 373c0b746e5SOllivier Robert { 374c0b746e5SOllivier Robert cutoff /= lowmax; 375c0b746e5SOllivier Robert } 376c0b746e5SOllivier Robert else 377c0b746e5SOllivier Robert { 378c0b746e5SOllivier Robert cutoff = 4; /* doesn't really matter - it'll fail anyway, but gives error output */ 379c0b746e5SOllivier Robert } 380c0b746e5SOllivier Robert 381c0b746e5SOllivier Robert parseprintf(DD_RAWDCF,("parse: cvt_rawdcf: average bit count: %d\n", cutoff)); 382c0b746e5SOllivier Robert 383c0b746e5SOllivier Robert lowmax = 0; 384c0b746e5SOllivier Robert highmax = 0; 385c0b746e5SOllivier Robert 386c0b746e5SOllivier Robert parseprintf(DD_RAWDCF,("parse: cvt_rawdcf: histogram:")); 387c0b746e5SOllivier Robert for (i = 0; i <= cutoff; i++) 388c0b746e5SOllivier Robert { 389c0b746e5SOllivier Robert lowmax+=histbuf[i] * i; 390c0b746e5SOllivier Robert highmax += histbuf[i]; 391c0b746e5SOllivier Robert parseprintf(DD_RAWDCF,(" %d", histbuf[i])); 392c0b746e5SOllivier Robert } 393c0b746e5SOllivier Robert parseprintf(DD_RAWDCF, (" <M>")); 394c0b746e5SOllivier Robert 395c0b746e5SOllivier Robert lowmax += highmax / 2; 396c0b746e5SOllivier Robert 397c0b746e5SOllivier Robert if (highmax) 398c0b746e5SOllivier Robert { 399c0b746e5SOllivier Robert lowmax /= highmax; 400c0b746e5SOllivier Robert } 401c0b746e5SOllivier Robert else 402c0b746e5SOllivier Robert { 403c0b746e5SOllivier Robert lowmax = 0; 404c0b746e5SOllivier Robert } 405c0b746e5SOllivier Robert 406c0b746e5SOllivier Robert highmax = 0; 407c0b746e5SOllivier Robert cutoff = 0; 408c0b746e5SOllivier Robert 409c0b746e5SOllivier Robert for (; i < BITS; i++) 410c0b746e5SOllivier Robert { 411c0b746e5SOllivier Robert highmax+=histbuf[i] * i; 412c0b746e5SOllivier Robert cutoff +=histbuf[i]; 413c0b746e5SOllivier Robert parseprintf(DD_RAWDCF,(" %d", histbuf[i])); 414c0b746e5SOllivier Robert } 415c0b746e5SOllivier Robert parseprintf(DD_RAWDCF,("\n")); 416c0b746e5SOllivier Robert 417c0b746e5SOllivier Robert if (cutoff) 418c0b746e5SOllivier Robert { 419c0b746e5SOllivier Robert highmax /= cutoff; 420c0b746e5SOllivier Robert } 421c0b746e5SOllivier Robert else 422c0b746e5SOllivier Robert { 423c0b746e5SOllivier Robert highmax = BITS-1; 424c0b746e5SOllivier Robert } 425c0b746e5SOllivier Robert 426c0b746e5SOllivier Robert span = cutoff = lowmax; 427c0b746e5SOllivier Robert for (i = lowmax; i <= highmax; i++) 428c0b746e5SOllivier Robert { 429c0b746e5SOllivier Robert if (histbuf[cutoff] > histbuf[i]) 430c0b746e5SOllivier Robert { 431c0b746e5SOllivier Robert cutoff = i; 432c0b746e5SOllivier Robert span = i; 433c0b746e5SOllivier Robert } 434c0b746e5SOllivier Robert else 435c0b746e5SOllivier Robert if (histbuf[cutoff] == histbuf[i]) 436c0b746e5SOllivier Robert { 437c0b746e5SOllivier Robert span = i; 438c0b746e5SOllivier Robert } 439c0b746e5SOllivier Robert } 440c0b746e5SOllivier Robert 441c0b746e5SOllivier Robert cutoff = (cutoff + span) / 2; 442c0b746e5SOllivier Robert 443c0b746e5SOllivier Robert parseprintf(DD_RAWDCF,("parse: cvt_rawdcf: lower maximum %d, higher maximum %d, cutoff %d\n", lowmax, highmax, cutoff)); 444c0b746e5SOllivier Robert 445c0b746e5SOllivier Robert s = (unsigned char *)buffer; 446c0b746e5SOllivier Robert while ((s < e) && *c && *b) 447c0b746e5SOllivier Robert { 448c0b746e5SOllivier Robert if (*s == (unsigned char)~0) 449c0b746e5SOllivier Robert { 450c0b746e5SOllivier Robert *s = '?'; 451c0b746e5SOllivier Robert } 452c0b746e5SOllivier Robert else 453c0b746e5SOllivier Robert { 454c0b746e5SOllivier Robert *s = (*s >= cutoff) ? *b : *c; 455c0b746e5SOllivier Robert } 456c0b746e5SOllivier Robert s++; 457c0b746e5SOllivier Robert b++; 458c0b746e5SOllivier Robert c++; 459c0b746e5SOllivier Robert } 460c0b746e5SOllivier Robert 461c0b746e5SOllivier Robert return (rtc == CVT_NONE) ? convert_rawdcf(buffer, size, &dcfparameter, clock_time) : rtc; 462c0b746e5SOllivier Robert } 463c0b746e5SOllivier Robert 464c0b746e5SOllivier Robert /* 465c0b746e5SOllivier Robert * pps_rawdcf 466c0b746e5SOllivier Robert * 467c0b746e5SOllivier Robert * currently a very stupid version - should be extended to decode 468c0b746e5SOllivier Robert * also ones and zeros (which is easy) 469c0b746e5SOllivier Robert */ 470c0b746e5SOllivier Robert /*ARGSUSED*/ 471c0b746e5SOllivier Robert static u_long 472c0b746e5SOllivier Robert pps_rawdcf( 473c0b746e5SOllivier Robert register parse_t *parseio, 474c0b746e5SOllivier Robert register int status, 475c0b746e5SOllivier Robert register timestamp_t *ptime 476c0b746e5SOllivier Robert ) 477c0b746e5SOllivier Robert { 478c0b746e5SOllivier Robert if (!status) /* negative edge for simpler wiring (Rx->DCD) */ 479c0b746e5SOllivier Robert { 480c0b746e5SOllivier Robert parseio->parse_dtime.parse_ptime = *ptime; 481c0b746e5SOllivier Robert parseio->parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS; 482c0b746e5SOllivier Robert } 483c0b746e5SOllivier Robert 484c0b746e5SOllivier Robert return CVT_NONE; 485c0b746e5SOllivier Robert } 486c0b746e5SOllivier Robert 487c0b746e5SOllivier Robert static u_long 488c0b746e5SOllivier Robert snt_rawdcf( 489c0b746e5SOllivier Robert register parse_t *parseio, 490c0b746e5SOllivier Robert register timestamp_t *ptime 491c0b746e5SOllivier Robert ) 492c0b746e5SOllivier Robert { 493c0b746e5SOllivier Robert if ((parseio->parse_dtime.parse_status & CVT_MASK) == CVT_OK) 494c0b746e5SOllivier Robert { 495c0b746e5SOllivier Robert parseio->parse_dtime.parse_stime = *ptime; 496c0b746e5SOllivier Robert 497c0b746e5SOllivier Robert #ifdef PARSEKERNEL 498c0b746e5SOllivier Robert parseio->parse_dtime.parse_time.tv.tv_sec++; 499c0b746e5SOllivier Robert #else 500c0b746e5SOllivier Robert parseio->parse_dtime.parse_time.fp.l_ui++; 501c0b746e5SOllivier Robert #endif 502c0b746e5SOllivier Robert 503c0b746e5SOllivier Robert parseprintf(DD_RAWDCF,("parse: snt_rawdcf: time stamp synthesized offset %d seconds\n", parseio->parse_index - 1)); 504c0b746e5SOllivier Robert 505c0b746e5SOllivier Robert return updatetimeinfo(parseio, parseio->parse_lstate); 506c0b746e5SOllivier Robert } 507c0b746e5SOllivier Robert return CVT_NONE; 508c0b746e5SOllivier Robert } 509c0b746e5SOllivier Robert 510c0b746e5SOllivier Robert /* 511c0b746e5SOllivier Robert * inp_rawdcf 512c0b746e5SOllivier Robert * 513c0b746e5SOllivier Robert * grep DCF77 data from input stream 514c0b746e5SOllivier Robert */ 515c0b746e5SOllivier Robert static u_long 516c0b746e5SOllivier Robert inp_rawdcf( 517c0b746e5SOllivier Robert parse_t *parseio, 518c0b746e5SOllivier Robert unsigned int ch, 519c0b746e5SOllivier Robert timestamp_t *tstamp 520c0b746e5SOllivier Robert ) 521c0b746e5SOllivier Robert { 522c0b746e5SOllivier Robert static struct timeval timeout = { 1, 500000 }; /* 1.5 secongs denote second #60 */ 523c0b746e5SOllivier Robert 524c0b746e5SOllivier Robert parseprintf(DD_PARSE, ("inp_rawdcf(0x%x, 0x%x, ...)\n", (int)parseio, (int)ch)); 525c0b746e5SOllivier Robert 526c0b746e5SOllivier Robert parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */ 527c0b746e5SOllivier Robert 528c0b746e5SOllivier Robert if (parse_timedout(parseio, tstamp, &timeout)) 529c0b746e5SOllivier Robert { 530c0b746e5SOllivier Robert parseprintf(DD_PARSE, ("inp_rawdcf: time out seen\n")); 531c0b746e5SOllivier Robert 532c0b746e5SOllivier Robert (void) parse_end(parseio); 533c0b746e5SOllivier Robert (void) parse_addchar(parseio, ch); 534c0b746e5SOllivier Robert return PARSE_INP_TIME; 535c0b746e5SOllivier Robert } 536c0b746e5SOllivier Robert else 537c0b746e5SOllivier Robert { 538c0b746e5SOllivier Robert unsigned int rtc; 539c0b746e5SOllivier Robert 540c0b746e5SOllivier Robert rtc = parse_addchar(parseio, ch); 541c0b746e5SOllivier Robert if (rtc == PARSE_INP_SKIP) 542c0b746e5SOllivier Robert { 543c0b746e5SOllivier Robert if (snt_rawdcf(parseio, tstamp) == CVT_OK) 544c0b746e5SOllivier Robert return PARSE_INP_SYNTH; 545c0b746e5SOllivier Robert } 546c0b746e5SOllivier Robert return rtc; 547c0b746e5SOllivier Robert } 548c0b746e5SOllivier Robert } 549c0b746e5SOllivier Robert 550c0b746e5SOllivier Robert #else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_RAWDCF) */ 551c0b746e5SOllivier Robert int clk_rawdcf_bs; 552c0b746e5SOllivier Robert #endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_RAWDCF) */ 553c0b746e5SOllivier Robert 554c0b746e5SOllivier Robert /* 555c0b746e5SOllivier Robert * History: 556c0b746e5SOllivier Robert * 557c0b746e5SOllivier Robert * clk_rawdcf.c,v 558c0b746e5SOllivier Robert * Revision 4.6 1998/06/14 21:09:37 kardel 559c0b746e5SOllivier Robert * Sun acc cleanup 560c0b746e5SOllivier Robert * 561c0b746e5SOllivier Robert * Revision 4.5 1998/06/13 12:04:16 kardel 562c0b746e5SOllivier Robert * fix SYSV clock name clash 563c0b746e5SOllivier Robert * 564c0b746e5SOllivier Robert * Revision 4.4 1998/06/12 15:22:28 kardel 565c0b746e5SOllivier Robert * fix prototypes 566c0b746e5SOllivier Robert * 567c0b746e5SOllivier Robert * Revision 4.3 1998/06/06 18:33:36 kardel 568c0b746e5SOllivier Robert * simplified condidional compile expression 569c0b746e5SOllivier Robert * 570c0b746e5SOllivier Robert * Revision 4.2 1998/05/24 11:04:18 kardel 571c0b746e5SOllivier Robert * triggering PPS on negative edge for simpler wiring (Rx->DCD) 572c0b746e5SOllivier Robert * 573c0b746e5SOllivier Robert * Revision 4.1 1998/05/24 09:39:53 kardel 574c0b746e5SOllivier Robert * implementation of the new IO handling model 575c0b746e5SOllivier Robert * 576c0b746e5SOllivier Robert * Revision 4.0 1998/04/10 19:45:30 kardel 577c0b746e5SOllivier Robert * Start 4.0 release version numbering 578c0b746e5SOllivier Robert * 579c0b746e5SOllivier Robert * from V3 3.24 log info deleted 1998/04/11 kardel 580c0b746e5SOllivier Robert * 581c0b746e5SOllivier Robert */ 582