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