/contrib/ntp/libparse/clk_wharton.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 181 lines · 91 code · 16 blank · 74 comment · 20 complexity · 296f0a75c5971118fd2b10089b2c67a9 MD5 · raw file

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