1 /* 2 * /src/NTP/ntp-4/libparse/clk_schmid.c,v 4.5 1999/11/28 09:13:51 kardel RELEASE_19991128_A 3 * 4 * clk_schmid.c,v 4.5 1999/11/28 09:13:51 kardel RELEASE_19991128_A 5 * 6 * Schmid clock support 7 * 8 * Copyright (C) 1992-1998 by Frank Kardel 9 * Friedrich-Alexander Universit�t Erlangen-N�rnberg, Germany 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 14 * 15 */ 16 17 #if HAVE_CONFIG_H 18 # include <config.h> 19 #endif 20 21 #if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_SCHMID) 22 23 #include "ntp_fp.h" 24 #include "ntp_unixtime.h" 25 #include "ntp_calendar.h" 26 27 #include "parse.h" 28 29 #ifndef PARSESTREAM 30 #include "ntp_stdlib.h" 31 #include <stdio.h> 32 #else 33 #include "sys/parsestreams.h" 34 extern void printf P((const char *, ...)); 35 #endif 36 37 /* 38 * Description courtesy of Adam W. Feigin et. al (Swisstime iis.ethz.ch) 39 * 40 * The command to Schmid's DCF77 clock is a single byte; each bit 41 * allows the user to select some part of the time string, as follows (the 42 * output for the lsb is sent first). 43 * 44 * Bit 0: time in MEZ, 4 bytes *binary, not BCD*; hh.mm.ss.tenths 45 * Bit 1: date 3 bytes *binary, not BCD: dd.mm.yy 46 * Bit 2: week day, 1 byte (unused here) 47 * Bit 3: time zone, 1 byte, 0=MET, 1=MEST. (unused here) 48 * Bit 4: clock status, 1 byte, 0=time invalid, 49 * 1=time from crystal backup, 50 * 3=time from DCF77 51 * Bit 5: transmitter status, 1 byte, 52 * bit 0: backup antenna 53 * bit 1: time zone change within 1h 54 * bit 3,2: TZ 01=MEST, 10=MET 55 * bit 4: leap second will be 56 * added within one hour 57 * bits 5-7: Zero 58 * Bit 6: time in backup mode, units of 5 minutes (unused here) 59 * 60 */ 61 #define WS_TIME 0x01 62 #define WS_SIGNAL 0x02 63 64 #define WS_ALTERNATE 0x01 65 #define WS_ANNOUNCE 0x02 66 #define WS_TZ 0x0c 67 #define WS_MET 0x08 68 #define WS_MEST 0x04 69 #define WS_LEAP 0x10 70 71 static u_long cvt_schmid P((unsigned char *, int, struct format *, clocktime_t *, void *)); 72 static unsigned long inp_schmid P((parse_t *, unsigned int, timestamp_t *)); 73 74 clockformat_t clock_schmid = 75 { 76 inp_schmid, /* no input handling */ 77 cvt_schmid, /* Schmid conversion */ 78 0, /* not direct PPS monitoring */ 79 0, /* conversion configuration */ 80 "Schmid", /* Schmid receiver */ 81 12, /* binary data buffer */ 82 0, /* no private data (complete messages) */ 83 }; 84 85 86 static u_long 87 cvt_schmid( 88 unsigned char *buffer, 89 int size, 90 struct format *format, 91 clocktime_t *clock_time, 92 void *local 93 ) 94 { 95 if ((size != 11) || (buffer[10] != (unsigned char)'\375')) 96 { 97 return CVT_NONE; 98 } 99 else 100 { 101 if (buffer[0] > 23 || buffer[1] > 59 || buffer[2] > 59 || buffer[3] > 9) /* Time */ 102 { 103 return CVT_FAIL|CVT_BADTIME; 104 } 105 else 106 if (buffer[4] < 1 || buffer[4] > 31 || buffer[5] < 1 || buffer[5] > 12 107 || buffer[6] > 99) 108 { 109 return CVT_FAIL|CVT_BADDATE; 110 } 111 else 112 { 113 clock_time->hour = buffer[0]; 114 clock_time->minute = buffer[1]; 115 clock_time->second = buffer[2]; 116 clock_time->usecond = buffer[3] * 100000; 117 clock_time->day = buffer[4]; 118 clock_time->month = buffer[5]; 119 clock_time->year = buffer[6]; 120 121 clock_time->flags = 0; 122 123 switch (buffer[8] & WS_TZ) 124 { 125 case WS_MET: 126 clock_time->utcoffset = -1*60*60; 127 break; 128 129 case WS_MEST: 130 clock_time->utcoffset = -2*60*60; 131 clock_time->flags |= PARSEB_DST; 132 break; 133 134 default: 135 return CVT_FAIL|CVT_BADFMT; 136 } 137 138 if (!(buffer[7] & WS_TIME)) 139 { 140 clock_time->flags |= PARSEB_POWERUP; 141 } 142 143 if (!(buffer[7] & WS_SIGNAL)) 144 { 145 clock_time->flags |= PARSEB_NOSYNC; 146 } 147 148 if (buffer[7] & WS_SIGNAL) 149 { 150 if (buffer[8] & WS_ALTERNATE) 151 { 152 clock_time->flags |= PARSEB_ALTERNATE; 153 } 154 155 if (buffer[8] & WS_ANNOUNCE) 156 { 157 clock_time->flags |= PARSEB_ANNOUNCE; 158 } 159 160 if (buffer[8] & WS_LEAP) 161 { 162 clock_time->flags |= PARSEB_LEAPADD; /* default: DCF77 data format deficiency */ 163 } 164 } 165 166 clock_time->flags |= PARSEB_S_LEAP|PARSEB_S_ANTENNA; 167 168 return CVT_OK; 169 } 170 } 171 } 172 173 /* 174 * inp_schmid 175 * 176 * grep data from input stream 177 */ 178 static u_long 179 inp_schmid( 180 parse_t *parseio, 181 unsigned int ch, 182 timestamp_t *tstamp 183 ) 184 { 185 unsigned int rtc; 186 187 parseprintf(DD_PARSE, ("inp_schmid(0x%lx, 0x%x, ...)\n", (long)parseio, ch)); 188 189 switch (ch) 190 { 191 case 0xFD: /* */ 192 parseprintf(DD_PARSE, ("mbg_input: ETX seen\n")); 193 if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP) 194 return parse_end(parseio); 195 else 196 return rtc; 197 198 default: 199 return parse_addchar(parseio, ch); 200 } 201 } 202 203 #else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SCHMID) */ 204 int clk_schmid_bs; 205 #endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SCHMID) */ 206 207 /* 208 * History: 209 * 210 * clk_schmid.c,v 211 * Revision 4.5 1999/11/28 09:13:51 kardel 212 * RECON_4_0_98F 213 * 214 * Revision 4.4 1998/06/13 12:06:03 kardel 215 * fix SYSV clock name clash 216 * 217 * Revision 4.3 1998/06/12 15:22:29 kardel 218 * fix prototypes 219 * 220 * Revision 4.2 1998/06/12 09:13:26 kardel 221 * conditional compile macros fixed 222 * printf prototype 223 * 224 * Revision 4.1 1998/05/24 09:39:53 kardel 225 * implementation of the new IO handling model 226 * 227 * Revision 4.0 1998/04/10 19:45:31 kardel 228 * Start 4.0 release version numbering 229 * 230 * from V3 3.22 log info deleted 1998/04/11 kardel 231 */ 232