154359Sroberto/* 2182007Sroberto * /src/NTP/ntp4-dev/libparse/clk_wharton.c,v 4.2 2004/11/14 15:29:41 kardel RELEASE_20050508_A 354359Sroberto * 4182007Sroberto * clk_wharton.c,v 4.2 2004/11/14 15:29:41 kardel RELEASE_20050508_A 554359Sroberto * 654359Sroberto * From Philippe De Muyter <phdm@macqel.be>, 1999 754359Sroberto */ 854359Sroberto#ifdef HAVE_CONFIG_H 954359Sroberto#include <config.h> 1054359Sroberto#endif 1154359Sroberto 1254359Sroberto#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_WHARTON_400A) 1354359Sroberto/* 1454359Sroberto * Support for WHARTON 400A Series clock + 404.2 serial interface. 1554359Sroberto * 1682498Sroberto * Copyright (C) 1999, 2000 by Philippe De Muyter <phdm@macqel.be> 1754359Sroberto * 1854359Sroberto * This program is distributed in the hope that it will be useful, but WITHOUT 1954359Sroberto * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 2054359Sroberto * FITNESS FOR A PARTICULAR PURPOSE. 2154359Sroberto * 2254359Sroberto */ 2354359Sroberto 2454359Sroberto#include "ntp_fp.h" 2554359Sroberto#include "ascii.h" 2654359Sroberto#include "parse.h" 2754359Sroberto 2854359Sroberto#ifndef PARSESTREAM 2954359Sroberto#include "ntp_stdlib.h" 3054359Sroberto#include <stdio.h> 3154359Sroberto#else 3254359Sroberto#include "sys/parsestreams.h" 33280849Scyextern void printf (const char *, ...); 3454359Sroberto#endif 3554359Sroberto 3654359Sroberto/* 3754359Sroberto * In private e-mail alastair@wharton.co.uk said : 3854359Sroberto * "If you are going to use the 400A and 404.2 system [for ntp] I recommend 3954359Sroberto * that you set the 400A to output the message every second. The start of 4054359Sroberto * transmission of the first byte of the message is synchronised to the 4154359Sroberto * second edge." 4254359Sroberto * The WHARTON 400A Series is able to send date/time serial messages 4354359Sroberto * in 7 output formats. We use format 1 here because it is the shortest. 4454359Sroberto * For use with this driver, the WHARTON 400A Series clock must be set-up 4554359Sroberto * as follows : 4654359Sroberto * Programmable Selected 4754359Sroberto * Option No Option 4854359Sroberto * BST or CET display 3 9 or 11 4954359Sroberto * No external controller 7 0 5054359Sroberto * Serial Output Format 1 9 1 5154359Sroberto * Baud rate 9600 bps 10 96 5254359Sroberto * Bit length 8 bits 11 8 5354359Sroberto * Parity even 12 E 5454359Sroberto * 5554359Sroberto * WHARTON 400A Series output format 1 is as follows : 5654359Sroberto * 5754359Sroberto * Timestamp STXssmmhhDDMMYYSETX 5854359Sroberto * Pos 0 12345678901234 5954359Sroberto * 0 00000000011111 6054359Sroberto * 6154359Sroberto * STX start transmission (ASCII 0x02) 6254359Sroberto * ETX end transmission (ASCII 0x03) 6354359Sroberto * ss Second expressed in reversed decimal (units then tens) 6454359Sroberto * mm Minute expressed in reversed decimal 6554359Sroberto * hh Hour expressed in reversed decimal 6654359Sroberto * DD Day of month expressed in reversed decimal 6754359Sroberto * MM Month expressed in reversed decimal (January is 1) 6854359Sroberto * YY Year (without century) expressed in reversed decimal 6954359Sroberto * S Status byte : 0x30 + 7054359Sroberto * bit 0 0 = MSF source 1 = DCF source 7154359Sroberto * bit 1 0 = Winter time 1 = Summer time 7254359Sroberto * bit 2 0 = not synchronised 1 = synchronised 7354359Sroberto * bit 3 0 = no early warning 1 = early warning 7454359Sroberto * 7554359Sroberto */ 7654359Sroberto 77282408Scystatic parse_cvt_fnc_t cvt_wharton_400a; 78282408Scystatic parse_inp_fnc_t inp_wharton_400a; 79282408Scy 8054359Sroberto/* 81282408Scy * parse_cvt_fnc_t cvt_wharton_400a 8254359Sroberto * 8354359Sroberto * convert simple type format 8454359Sroberto */ 8554359Srobertostatic u_long 8654359Srobertocvt_wharton_400a( 8754359Sroberto unsigned char *buffer, 8854359Sroberto int size, 8954359Sroberto struct format *format, 9054359Sroberto clocktime_t *clock_time, 9154359Sroberto void *local 9254359Sroberto ) 9354359Sroberto{ 9454359Sroberto int i; 9554359Sroberto 9654359Sroberto /* The given `size' includes a terminating null-character. */ 97280849Scy if (size != 15 || buffer[0] != STX || buffer[14] != ETX 9882498Sroberto || buffer[13] < '0' || buffer[13] > ('0' + 0xf)) 9954359Sroberto return CVT_NONE; 10082498Sroberto for (i = 1; i < 13; i += 1) 10154359Sroberto if (buffer[i] < '0' || buffer[i] > '9') 10254359Sroberto return CVT_NONE; 10354359Sroberto clock_time->second = (buffer[2] - '0') * 10 + buffer[1] - '0'; 10454359Sroberto clock_time->minute = (buffer[4] - '0') * 10 + buffer[3] - '0'; 10554359Sroberto clock_time->hour = (buffer[6] - '0') * 10 + buffer[5] - '0'; 10654359Sroberto clock_time->day = (buffer[8] - '0') * 10 + buffer[7] - '0'; 10754359Sroberto clock_time->month = (buffer[10] - '0') * 10 + buffer[9] - '0'; 10854359Sroberto clock_time->year = (buffer[12] - '0') * 10 + buffer[11] - '0'; 10954359Sroberto clock_time->usecond = 0; 11054359Sroberto if (buffer[13] & 0x1) /* We have CET time */ 11154359Sroberto clock_time->utcoffset = -1*60*60; 11254359Sroberto else /* We have BST time */ 11354359Sroberto clock_time->utcoffset = 0; 11454359Sroberto if (buffer[13] & 0x2) { 11554359Sroberto clock_time->flags |= PARSEB_DST; 11654359Sroberto clock_time->utcoffset += -1*60*60; 11754359Sroberto } 11854359Sroberto if (!(buffer[13] & 0x4)) 11954359Sroberto clock_time->flags |= PARSEB_NOSYNC; 12054359Sroberto if (buffer[13] & 0x8) 12154359Sroberto clock_time->flags |= PARSEB_ANNOUNCE; 12254359Sroberto 12354359Sroberto return CVT_OK; 12454359Sroberto} 12554359Sroberto 12654359Sroberto/* 127282408Scy * parse_inp_fnc_t inp_wharton_400a 12854359Sroberto * 129282408Scy * grab data from input stream 13054359Sroberto */ 13154359Srobertostatic u_long 13254359Srobertoinp_wharton_400a( 13354359Sroberto parse_t *parseio, 134282408Scy char ch, 13554359Sroberto timestamp_t *tstamp 13654359Sroberto ) 13754359Sroberto{ 13854359Sroberto unsigned int rtc; 13954359Sroberto 140293423Sdelphij parseprintf(DD_PARSE, ("inp_wharton_400a(0x%p, 0x%x, ...)\n", (void*)parseio, ch)); 14154359Sroberto 14254359Sroberto switch (ch) 14354359Sroberto { 14454359Sroberto case STX: 14554359Sroberto parseprintf(DD_PARSE, ("inp_wharton_400a: STX seen\n")); 14654359Sroberto 14754359Sroberto parseio->parse_index = 1; 14854359Sroberto parseio->parse_data[0] = ch; 14954359Sroberto parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */ 15054359Sroberto return PARSE_INP_SKIP; 15154359Sroberto 15254359Sroberto case ETX: 15354359Sroberto parseprintf(DD_PARSE, ("inp_wharton_400a: ETX seen\n")); 15454359Sroberto if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP) 15554359Sroberto return parse_end(parseio); 15654359Sroberto else 15754359Sroberto return rtc; 15854359Sroberto 15954359Sroberto default: 16054359Sroberto return parse_addchar(parseio, ch); 16154359Sroberto } 16254359Sroberto} 16354359Sroberto 16454359Srobertoclockformat_t clock_wharton_400a = 16554359Sroberto{ 16654359Sroberto inp_wharton_400a, /* input handling function */ 16754359Sroberto cvt_wharton_400a, /* conversion function */ 16854359Sroberto 0, /* no PPS monitoring */ 16954359Sroberto 0, /* conversion configuration */ 17054359Sroberto "WHARTON 400A Series clock Output Format 1", /* String format name */ 17154359Sroberto 15, /* string buffer */ 172282408Scy 0 /* no private data (complete packets) */ 17354359Sroberto}; 17454359Sroberto 17554359Sroberto#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_WHARTON_400A) */ 17654359Srobertoint clk_wharton_400a_bs; 17754359Sroberto#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_WHARTON_400A) */ 17854359Sroberto 17954359Sroberto/* 18054359Sroberto * clk_wharton.c,v 18154359Sroberto * Revision 4.1 1999/02/28 15:27:24 kardel 18254359Sroberto * wharton clock integration 18354359Sroberto * 18454359Sroberto */ 185