1*eabc0478Schristos /* $NetBSD: clk_schmid.c,v 1.7 2024/08/18 20:47:17 christos Exp $ */ 2abb0f93cSkardel 3abb0f93cSkardel /* 4abb0f93cSkardel * /src/NTP/ntp4-dev/libparse/clk_schmid.c,v 4.9 2005/04/16 17:32:10 kardel RELEASE_20050508_A 5abb0f93cSkardel * 6abb0f93cSkardel * clk_schmid.c,v 4.9 2005/04/16 17:32:10 kardel RELEASE_20050508_A 7abb0f93cSkardel * 8abb0f93cSkardel * Schmid clock support 9abb0f93cSkardel * based on information and testing from Adam W. Feigin et. al (Swisstime iis.ethz.ch) 10abb0f93cSkardel * 115d681e99Schristos * Copyright (c) 1995-2015 by Frank Kardel <kardel <AT> ntp.org> 127476e6e4Schristos * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universitaet Erlangen-Nuernberg, Germany 13abb0f93cSkardel * 14abb0f93cSkardel * Redistribution and use in source and binary forms, with or without 15abb0f93cSkardel * modification, are permitted provided that the following conditions 16abb0f93cSkardel * are met: 17abb0f93cSkardel * 1. Redistributions of source code must retain the above copyright 18abb0f93cSkardel * notice, this list of conditions and the following disclaimer. 19abb0f93cSkardel * 2. Redistributions in binary form must reproduce the above copyright 20abb0f93cSkardel * notice, this list of conditions and the following disclaimer in the 21abb0f93cSkardel * documentation and/or other materials provided with the distribution. 22abb0f93cSkardel * 3. Neither the name of the author nor the names of its contributors 23abb0f93cSkardel * may be used to endorse or promote products derived from this software 24abb0f93cSkardel * without specific prior written permission. 25abb0f93cSkardel * 26abb0f93cSkardel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 27abb0f93cSkardel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28abb0f93cSkardel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29abb0f93cSkardel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 30abb0f93cSkardel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31abb0f93cSkardel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32abb0f93cSkardel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33abb0f93cSkardel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34abb0f93cSkardel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35abb0f93cSkardel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36abb0f93cSkardel * SUCH DAMAGE. 37abb0f93cSkardel * 38abb0f93cSkardel */ 39abb0f93cSkardel 40abb0f93cSkardel #if HAVE_CONFIG_H 41abb0f93cSkardel # include <config.h> 42abb0f93cSkardel #endif 43abb0f93cSkardel 44abb0f93cSkardel #if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_SCHMID) 45abb0f93cSkardel 46abb0f93cSkardel #include "ntp_fp.h" 47abb0f93cSkardel #include "ntp_unixtime.h" 48abb0f93cSkardel #include "ntp_calendar.h" 49abb0f93cSkardel 50abb0f93cSkardel #include "parse.h" 51abb0f93cSkardel 52abb0f93cSkardel #ifndef PARSESTREAM 53abb0f93cSkardel #include "ntp_stdlib.h" 54abb0f93cSkardel #include <stdio.h> 55abb0f93cSkardel #else 56abb0f93cSkardel #include "sys/parsestreams.h" 57abb0f93cSkardel extern int printf (const char *, ...); 58abb0f93cSkardel #endif 59abb0f93cSkardel 60abb0f93cSkardel /* 61abb0f93cSkardel * Description courtesy of Adam W. Feigin et. al (Swisstime iis.ethz.ch) 62abb0f93cSkardel * 63abb0f93cSkardel * The command to Schmid's DCF77 clock is a single byte; each bit 64abb0f93cSkardel * allows the user to select some part of the time string, as follows (the 65abb0f93cSkardel * output for the lsb is sent first). 66abb0f93cSkardel * 67abb0f93cSkardel * Bit 0: time in MEZ, 4 bytes *binary, not BCD*; hh.mm.ss.tenths 68abb0f93cSkardel * Bit 1: date 3 bytes *binary, not BCD: dd.mm.yy 69abb0f93cSkardel * Bit 2: week day, 1 byte (unused here) 70abb0f93cSkardel * Bit 3: time zone, 1 byte, 0=MET, 1=MEST. (unused here) 71abb0f93cSkardel * Bit 4: clock status, 1 byte, 0=time invalid, 72abb0f93cSkardel * 1=time from crystal backup, 73abb0f93cSkardel * 3=time from DCF77 74abb0f93cSkardel * Bit 5: transmitter status, 1 byte, 75abb0f93cSkardel * bit 0: backup antenna 76abb0f93cSkardel * bit 1: time zone change within 1h 77abb0f93cSkardel * bit 3,2: TZ 01=MEST, 10=MET 78abb0f93cSkardel * bit 4: leap second will be 79abb0f93cSkardel * added within one hour 80abb0f93cSkardel * bits 5-7: Zero 81abb0f93cSkardel * Bit 6: time in backup mode, units of 5 minutes (unused here) 82abb0f93cSkardel * 83abb0f93cSkardel */ 84abb0f93cSkardel #define WS_TIME 0x01 85abb0f93cSkardel #define WS_SIGNAL 0x02 86abb0f93cSkardel 877476e6e4Schristos #define WS_CALLBIT 0x01 /* "call bit" used to signalize irregularities in the control facilities */ 88abb0f93cSkardel #define WS_ANNOUNCE 0x02 89abb0f93cSkardel #define WS_TZ 0x0c 90abb0f93cSkardel #define WS_MET 0x08 91abb0f93cSkardel #define WS_MEST 0x04 92abb0f93cSkardel #define WS_LEAP 0x10 93abb0f93cSkardel 947476e6e4Schristos static parse_cvt_fnc_t cvt_schmid; 957476e6e4Schristos static parse_inp_fnc_t inp_schmid; 96abb0f93cSkardel 97abb0f93cSkardel clockformat_t clock_schmid = 98abb0f93cSkardel { 99abb0f93cSkardel inp_schmid, /* no input handling */ 100abb0f93cSkardel cvt_schmid, /* Schmid conversion */ 101abb0f93cSkardel 0, /* not direct PPS monitoring */ 102abb0f93cSkardel 0, /* conversion configuration */ 103abb0f93cSkardel "Schmid", /* Schmid receiver */ 104abb0f93cSkardel 12, /* binary data buffer */ 105abb0f93cSkardel 0, /* no private data (complete messages) */ 106abb0f93cSkardel }; 107abb0f93cSkardel 1087476e6e4Schristos /* parse_cvt_fnc_t */ 109abb0f93cSkardel static u_long 110abb0f93cSkardel cvt_schmid( 111abb0f93cSkardel unsigned char *buffer, 112abb0f93cSkardel int size, 113abb0f93cSkardel struct format *format, 114abb0f93cSkardel clocktime_t *clock_time, 115abb0f93cSkardel void *local 116abb0f93cSkardel ) 117abb0f93cSkardel { 118abb0f93cSkardel if ((size != 11) || (buffer[10] != (unsigned char)'\375')) 119abb0f93cSkardel { 120abb0f93cSkardel return CVT_NONE; 121abb0f93cSkardel } 122abb0f93cSkardel else 123abb0f93cSkardel { 124abb0f93cSkardel if (buffer[0] > 23 || buffer[1] > 59 || buffer[2] > 59 || buffer[3] > 9) /* Time */ 125abb0f93cSkardel { 126abb0f93cSkardel return CVT_FAIL|CVT_BADTIME; 127abb0f93cSkardel } 128abb0f93cSkardel else 129abb0f93cSkardel if (buffer[4] < 1 || buffer[4] > 31 || buffer[5] < 1 || buffer[5] > 12 130abb0f93cSkardel || buffer[6] > 99) 131abb0f93cSkardel { 132abb0f93cSkardel return CVT_FAIL|CVT_BADDATE; 133abb0f93cSkardel } 134abb0f93cSkardel else 135abb0f93cSkardel { 136abb0f93cSkardel clock_time->hour = buffer[0]; 137abb0f93cSkardel clock_time->minute = buffer[1]; 138abb0f93cSkardel clock_time->second = buffer[2]; 139abb0f93cSkardel clock_time->usecond = buffer[3] * 100000; 140abb0f93cSkardel clock_time->day = buffer[4]; 141abb0f93cSkardel clock_time->month = buffer[5]; 142abb0f93cSkardel clock_time->year = buffer[6]; 143abb0f93cSkardel 144abb0f93cSkardel clock_time->flags = 0; 145abb0f93cSkardel 146abb0f93cSkardel switch (buffer[8] & WS_TZ) 147abb0f93cSkardel { 148abb0f93cSkardel case WS_MET: 149abb0f93cSkardel clock_time->utcoffset = -1*60*60; 150abb0f93cSkardel break; 151abb0f93cSkardel 152abb0f93cSkardel case WS_MEST: 153abb0f93cSkardel clock_time->utcoffset = -2*60*60; 154abb0f93cSkardel clock_time->flags |= PARSEB_DST; 155abb0f93cSkardel break; 156abb0f93cSkardel 157abb0f93cSkardel default: 158abb0f93cSkardel return CVT_FAIL|CVT_BADFMT; 159abb0f93cSkardel } 160abb0f93cSkardel 161abb0f93cSkardel if (!(buffer[7] & WS_TIME)) 162abb0f93cSkardel { 163abb0f93cSkardel clock_time->flags |= PARSEB_POWERUP; 164abb0f93cSkardel } 165abb0f93cSkardel 166abb0f93cSkardel if (!(buffer[7] & WS_SIGNAL)) 167abb0f93cSkardel { 168abb0f93cSkardel clock_time->flags |= PARSEB_NOSYNC; 169abb0f93cSkardel } 170abb0f93cSkardel 171abb0f93cSkardel if (buffer[7] & WS_SIGNAL) 172abb0f93cSkardel { 1737476e6e4Schristos if (buffer[8] & WS_CALLBIT) 174abb0f93cSkardel { 1757476e6e4Schristos clock_time->flags |= PARSEB_CALLBIT; 176abb0f93cSkardel } 177abb0f93cSkardel 178abb0f93cSkardel if (buffer[8] & WS_ANNOUNCE) 179abb0f93cSkardel { 180abb0f93cSkardel clock_time->flags |= PARSEB_ANNOUNCE; 181abb0f93cSkardel } 182abb0f93cSkardel 183abb0f93cSkardel if (buffer[8] & WS_LEAP) 184abb0f93cSkardel { 185abb0f93cSkardel clock_time->flags |= PARSEB_LEAPADD; /* default: DCF77 data format deficiency */ 186abb0f93cSkardel } 187abb0f93cSkardel } 188abb0f93cSkardel 1895d681e99Schristos clock_time->flags |= PARSEB_S_LEAP|PARSEB_S_CALLBIT; 190abb0f93cSkardel 191abb0f93cSkardel return CVT_OK; 192abb0f93cSkardel } 193abb0f93cSkardel } 194abb0f93cSkardel } 195abb0f93cSkardel 196abb0f93cSkardel /* 1977476e6e4Schristos * parse_inp_fnc_t inp_schmid 198abb0f93cSkardel * 1997476e6e4Schristos * grab data from input stream 200abb0f93cSkardel */ 201abb0f93cSkardel static u_long 202abb0f93cSkardel inp_schmid( 203abb0f93cSkardel parse_t *parseio, 2047476e6e4Schristos char ch, 205abb0f93cSkardel timestamp_t *tstamp 206abb0f93cSkardel ) 207abb0f93cSkardel { 208abb0f93cSkardel unsigned int rtc; 209abb0f93cSkardel 2108b8da087Schristos parseprintf(DD_PARSE, ("inp_schmid(0x%p, 0x%x, ...)\n", (void*)parseio, ch)); 211abb0f93cSkardel 2127476e6e4Schristos switch ((uint8_t)ch) 213abb0f93cSkardel { 214abb0f93cSkardel case 0xFD: /* */ 2157476e6e4Schristos parseprintf(DD_PARSE, ("inp_schmid: 0xFD seen\n")); 216abb0f93cSkardel if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP) 217abb0f93cSkardel return parse_end(parseio); 218abb0f93cSkardel else 219abb0f93cSkardel return rtc; 220abb0f93cSkardel 221abb0f93cSkardel default: 222abb0f93cSkardel return parse_addchar(parseio, ch); 223abb0f93cSkardel } 224abb0f93cSkardel } 225abb0f93cSkardel 226abb0f93cSkardel #else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SCHMID) */ 227*eabc0478Schristos NONEMPTY_TRANSLATION_UNIT 228abb0f93cSkardel #endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SCHMID) */ 229abb0f93cSkardel 230abb0f93cSkardel /* 231abb0f93cSkardel * History: 232abb0f93cSkardel * 233abb0f93cSkardel * clk_schmid.c,v 234abb0f93cSkardel * Revision 4.9 2005/04/16 17:32:10 kardel 235abb0f93cSkardel * update copyright 236abb0f93cSkardel * 237abb0f93cSkardel * Revision 4.8 2004/11/14 15:29:41 kardel 238abb0f93cSkardel * support PPSAPI, upgrade Copyright to Berkeley style 239abb0f93cSkardel * 240abb0f93cSkardel * Revision 4.5 1999/11/28 09:13:51 kardel 241abb0f93cSkardel * RECON_4_0_98F 242abb0f93cSkardel * 243abb0f93cSkardel * Revision 4.4 1998/06/13 12:06:03 kardel 244abb0f93cSkardel * fix SYSV clock name clash 245abb0f93cSkardel * 246abb0f93cSkardel * Revision 4.3 1998/06/12 15:22:29 kardel 247abb0f93cSkardel * fix prototypes 248abb0f93cSkardel * 249abb0f93cSkardel * Revision 4.2 1998/06/12 09:13:26 kardel 250abb0f93cSkardel * conditional compile macros fixed 251abb0f93cSkardel * printf prototype 252abb0f93cSkardel * 253abb0f93cSkardel * Revision 4.1 1998/05/24 09:39:53 kardel 254abb0f93cSkardel * implementation of the new IO handling model 255abb0f93cSkardel * 256abb0f93cSkardel * Revision 4.0 1998/04/10 19:45:31 kardel 257abb0f93cSkardel * Start 4.0 release version numbering 258abb0f93cSkardel * 259abb0f93cSkardel * from V3 3.22 log info deleted 1998/04/11 kardel 260abb0f93cSkardel */ 261