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