1*eabc0478Schristos /* $NetBSD: clk_wharton.c,v 1.7 2024/08/18 20:47:17 christos Exp $ */ 2abb0f93cSkardel 3abb0f93cSkardel /* 4abb0f93cSkardel * /src/NTP/ntp4-dev/libparse/clk_wharton.c,v 4.2 2004/11/14 15:29:41 kardel RELEASE_20050508_A 5abb0f93cSkardel * 6abb0f93cSkardel * clk_wharton.c,v 4.2 2004/11/14 15:29:41 kardel RELEASE_20050508_A 7abb0f93cSkardel * 8abb0f93cSkardel * From Philippe De Muyter <phdm@macqel.be>, 1999 9abb0f93cSkardel */ 10abb0f93cSkardel #ifdef HAVE_CONFIG_H 11abb0f93cSkardel #include <config.h> 12abb0f93cSkardel #endif 13abb0f93cSkardel 14*eabc0478Schristos #include "ntp_types.h" 15*eabc0478Schristos 16abb0f93cSkardel #if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_WHARTON_400A) 17abb0f93cSkardel /* 18abb0f93cSkardel * Support for WHARTON 400A Series clock + 404.2 serial interface. 19abb0f93cSkardel */ 20abb0f93cSkardel 21abb0f93cSkardel #include "ntp_fp.h" 22abb0f93cSkardel #include "parse.h" 23abb0f93cSkardel 24abb0f93cSkardel #ifndef PARSESTREAM 25abb0f93cSkardel #include "ntp_stdlib.h" 26abb0f93cSkardel #include <stdio.h> 27abb0f93cSkardel #else 28abb0f93cSkardel #include "sys/parsestreams.h" 29abb0f93cSkardel extern void printf (const char *, ...); 30abb0f93cSkardel #endif 31abb0f93cSkardel 32*eabc0478Schristos #include "ascii.h" 33*eabc0478Schristos 34abb0f93cSkardel /* 35abb0f93cSkardel * In private e-mail alastair@wharton.co.uk said : 36abb0f93cSkardel * "If you are going to use the 400A and 404.2 system [for ntp] I recommend 37abb0f93cSkardel * that you set the 400A to output the message every second. The start of 38abb0f93cSkardel * transmission of the first byte of the message is synchronised to the 39abb0f93cSkardel * second edge." 40abb0f93cSkardel * The WHARTON 400A Series is able to send date/time serial messages 41abb0f93cSkardel * in 7 output formats. We use format 1 here because it is the shortest. 42abb0f93cSkardel * For use with this driver, the WHARTON 400A Series clock must be set-up 43abb0f93cSkardel * as follows : 44abb0f93cSkardel * Programmable Selected 45abb0f93cSkardel * Option No Option 46abb0f93cSkardel * BST or CET display 3 9 or 11 47abb0f93cSkardel * No external controller 7 0 48abb0f93cSkardel * Serial Output Format 1 9 1 49abb0f93cSkardel * Baud rate 9600 bps 10 96 50abb0f93cSkardel * Bit length 8 bits 11 8 51abb0f93cSkardel * Parity even 12 E 52abb0f93cSkardel * 53abb0f93cSkardel * WHARTON 400A Series output format 1 is as follows : 54abb0f93cSkardel * 55abb0f93cSkardel * Timestamp STXssmmhhDDMMYYSETX 56abb0f93cSkardel * Pos 0 12345678901234 57abb0f93cSkardel * 0 00000000011111 58abb0f93cSkardel * 59abb0f93cSkardel * STX start transmission (ASCII 0x02) 60abb0f93cSkardel * ETX end transmission (ASCII 0x03) 61abb0f93cSkardel * ss Second expressed in reversed decimal (units then tens) 62abb0f93cSkardel * mm Minute expressed in reversed decimal 63abb0f93cSkardel * hh Hour expressed in reversed decimal 64abb0f93cSkardel * DD Day of month expressed in reversed decimal 65abb0f93cSkardel * MM Month expressed in reversed decimal (January is 1) 66abb0f93cSkardel * YY Year (without century) expressed in reversed decimal 67abb0f93cSkardel * S Status byte : 0x30 + 68abb0f93cSkardel * bit 0 0 = MSF source 1 = DCF source 69abb0f93cSkardel * bit 1 0 = Winter time 1 = Summer time 70abb0f93cSkardel * bit 2 0 = not synchronised 1 = synchronised 71abb0f93cSkardel * bit 3 0 = no early warning 1 = early warning 72abb0f93cSkardel * 73abb0f93cSkardel */ 74abb0f93cSkardel 757476e6e4Schristos static parse_cvt_fnc_t cvt_wharton_400a; 767476e6e4Schristos static parse_inp_fnc_t inp_wharton_400a; 777476e6e4Schristos 78abb0f93cSkardel /* 797476e6e4Schristos * parse_cvt_fnc_t cvt_wharton_400a 80abb0f93cSkardel * 81abb0f93cSkardel * convert simple type format 82abb0f93cSkardel */ 83abb0f93cSkardel static u_long 84abb0f93cSkardel cvt_wharton_400a( 85abb0f93cSkardel unsigned char *buffer, 86abb0f93cSkardel int size, 87abb0f93cSkardel struct format *format, 88abb0f93cSkardel clocktime_t *clock_time, 89abb0f93cSkardel void *local 90abb0f93cSkardel ) 91abb0f93cSkardel { 92abb0f93cSkardel int i; 93abb0f93cSkardel 94abb0f93cSkardel /* The given `size' includes a terminating null-character. */ 958585484eSchristos if (size != 15 || buffer[0] != STX || buffer[14] != ETX 96abb0f93cSkardel || buffer[13] < '0' || buffer[13] > ('0' + 0xf)) 97abb0f93cSkardel return CVT_NONE; 98abb0f93cSkardel for (i = 1; i < 13; i += 1) 99abb0f93cSkardel if (buffer[i] < '0' || buffer[i] > '9') 100abb0f93cSkardel return CVT_NONE; 101abb0f93cSkardel clock_time->second = (buffer[2] - '0') * 10 + buffer[1] - '0'; 102abb0f93cSkardel clock_time->minute = (buffer[4] - '0') * 10 + buffer[3] - '0'; 103abb0f93cSkardel clock_time->hour = (buffer[6] - '0') * 10 + buffer[5] - '0'; 104abb0f93cSkardel clock_time->day = (buffer[8] - '0') * 10 + buffer[7] - '0'; 105abb0f93cSkardel clock_time->month = (buffer[10] - '0') * 10 + buffer[9] - '0'; 106abb0f93cSkardel clock_time->year = (buffer[12] - '0') * 10 + buffer[11] - '0'; 107abb0f93cSkardel clock_time->usecond = 0; 108abb0f93cSkardel if (buffer[13] & 0x1) /* We have CET time */ 109abb0f93cSkardel clock_time->utcoffset = -1*60*60; 110abb0f93cSkardel else /* We have BST time */ 111abb0f93cSkardel clock_time->utcoffset = 0; 112abb0f93cSkardel if (buffer[13] & 0x2) { 113abb0f93cSkardel clock_time->flags |= PARSEB_DST; 114abb0f93cSkardel clock_time->utcoffset += -1*60*60; 115abb0f93cSkardel } 116abb0f93cSkardel if (!(buffer[13] & 0x4)) 117abb0f93cSkardel clock_time->flags |= PARSEB_NOSYNC; 118abb0f93cSkardel if (buffer[13] & 0x8) 119abb0f93cSkardel clock_time->flags |= PARSEB_ANNOUNCE; 120abb0f93cSkardel 121abb0f93cSkardel return CVT_OK; 122abb0f93cSkardel } 123abb0f93cSkardel 124abb0f93cSkardel /* 1257476e6e4Schristos * parse_inp_fnc_t inp_wharton_400a 126abb0f93cSkardel * 1277476e6e4Schristos * grab data from input stream 128abb0f93cSkardel */ 129abb0f93cSkardel static u_long 130abb0f93cSkardel inp_wharton_400a( 131abb0f93cSkardel parse_t *parseio, 1327476e6e4Schristos char ch, 133abb0f93cSkardel timestamp_t *tstamp 134abb0f93cSkardel ) 135abb0f93cSkardel { 136abb0f93cSkardel unsigned int rtc; 137abb0f93cSkardel 1388b8da087Schristos parseprintf(DD_PARSE, ("inp_wharton_400a(0x%p, 0x%x, ...)\n", (void*)parseio, ch)); 139abb0f93cSkardel 140abb0f93cSkardel switch (ch) 141abb0f93cSkardel { 142abb0f93cSkardel case STX: 143abb0f93cSkardel parseprintf(DD_PARSE, ("inp_wharton_400a: STX seen\n")); 144abb0f93cSkardel 145abb0f93cSkardel parseio->parse_index = 1; 146abb0f93cSkardel parseio->parse_data[0] = ch; 147abb0f93cSkardel parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */ 148abb0f93cSkardel return PARSE_INP_SKIP; 149abb0f93cSkardel 150abb0f93cSkardel case ETX: 151abb0f93cSkardel parseprintf(DD_PARSE, ("inp_wharton_400a: ETX seen\n")); 152abb0f93cSkardel if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP) 153abb0f93cSkardel return parse_end(parseio); 154abb0f93cSkardel else 155abb0f93cSkardel return rtc; 156abb0f93cSkardel 157abb0f93cSkardel default: 158abb0f93cSkardel return parse_addchar(parseio, ch); 159abb0f93cSkardel } 160abb0f93cSkardel } 161abb0f93cSkardel 162abb0f93cSkardel clockformat_t clock_wharton_400a = 163abb0f93cSkardel { 164abb0f93cSkardel inp_wharton_400a, /* input handling function */ 165abb0f93cSkardel cvt_wharton_400a, /* conversion function */ 166abb0f93cSkardel 0, /* no PPS monitoring */ 167abb0f93cSkardel 0, /* conversion configuration */ 168abb0f93cSkardel "WHARTON 400A Series clock Output Format 1", /* String format name */ 169abb0f93cSkardel 15, /* string buffer */ 1707476e6e4Schristos 0 /* no private data (complete packets) */ 171abb0f93cSkardel }; 172abb0f93cSkardel 173abb0f93cSkardel #else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_WHARTON_400A) */ 174*eabc0478Schristos NONEMPTY_TRANSLATION_UNIT 175abb0f93cSkardel #endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_WHARTON_400A) */ 176abb0f93cSkardel 177abb0f93cSkardel /* 178abb0f93cSkardel * clk_wharton.c,v 179abb0f93cSkardel * Revision 4.1 1999/02/28 15:27:24 kardel 180abb0f93cSkardel * wharton clock integration 181abb0f93cSkardel * 182abb0f93cSkardel */ 183