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