clk_hopf6021.c revision 282408
154359Sroberto/*
2182007Sroberto * /src/NTP/ntp4-dev/libparse/clk_hopf6021.c,v 4.10 2004/11/14 15:29:41 kardel RELEASE_20050508_A
354359Sroberto *
4182007Sroberto * clk_hopf6021.c,v 4.10 2004/11/14 15:29:41 kardel RELEASE_20050508_A
554359Sroberto *
654359Sroberto * Radiocode Clocks HOPF Funkuhr 6021 mit serieller Schnittstelle
754359Sroberto * base code version from 24th Nov 1995 - history at end
854359Sroberto *
954359Sroberto * Created by F.Schnekenbuehl <frank@comsys.dofn.de> from clk_rcc8000.c
1054359Sroberto * Nortel DASA Network Systems GmbH, Department: ND250
1154359Sroberto * A Joint venture of Daimler-Benz Aerospace and Nortel
1254359Sroberto *
1354359Sroberto * This program is distributed in the hope that it will be useful,
1454359Sroberto * but WITHOUT ANY WARRANTY; without even the implied warranty of
1554359Sroberto * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1654359Sroberto *
1754359Sroberto */
1854359Sroberto
1954359Sroberto#ifdef HAVE_CONFIG_H
2054359Sroberto# include <config.h>
2154359Sroberto#endif
2254359Sroberto
2354359Sroberto#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_HOPF6021)
2454359Sroberto
2554359Sroberto#include "ntp_fp.h"
2654359Sroberto#include "ntp_unixtime.h"
2754359Sroberto#include "ntp_calendar.h"
2854359Sroberto#include "ascii.h"
2954359Sroberto
3054359Sroberto#include "parse.h"
3154359Sroberto
3254359Sroberto#ifndef PARSESTREAM
3354359Sroberto#include "ntp_stdlib.h"
3454359Sroberto#include <stdio.h>
3554359Sroberto#else
3654359Sroberto#include "sys/parsestreams.h"
37280849Scyextern int printf (const char *, ...);
3854359Sroberto#endif
3954359Sroberto
40282408Scy/*
41282408Scy * hopf Funkuhr 6021
4254359Sroberto *      used with 9600,8N1,
43282408Scy *      UTC ueber serielle Schnittstelle
4454359Sroberto *      Sekundenvorlauf ON
4554359Sroberto *      ETX zum Sekundenvorlauf ON
4654359Sroberto *      Datenstring 6021
4754359Sroberto *      Ausgabe Uhrzeit und Datum
4854359Sroberto *      Senden mit Steuerzeichen
4954359Sroberto *      Senden sekuendlich
5054359Sroberto */
5154359Sroberto
5254359Sroberto/*
5354359Sroberto *  Type 6021 Serial Output format
5454359Sroberto *
5554359Sroberto *      000000000011111111 / char
5654359Sroberto *      012345678901234567 \ position
5754359Sroberto *      sABHHMMSSDDMMYYnre  Actual
5854359Sroberto *       C4110046231195     Parse
5954359Sroberto *      s              enr  Check
6054359Sroberto *
6154359Sroberto *  s = STX (0x02), e = ETX (0x03)
6254359Sroberto *  n = NL  (0x0A), r = CR  (0x0D)
6354359Sroberto *
6454359Sroberto *  A B - Status and weekday
6554359Sroberto *
6654359Sroberto *  A - Status
6754359Sroberto *
6854359Sroberto *      8 4 2 1
6954359Sroberto *      x x x 0  - no announcement
7054359Sroberto *      x x x 1  - Summertime - wintertime - summertime announcement
7154359Sroberto *      x x 0 x  - Wintertime
7254359Sroberto *      x x 1 x  - Summertime
7354359Sroberto *      0 0 x x  - Time/Date invalid
74282408Scy *      0 1 x x  - Internal clock used
7554359Sroberto *      1 0 x x  - Radio clock
7654359Sroberto *      1 1 x x  - Radio clock highprecision
7754359Sroberto *
7854359Sroberto *  B - 8 4 2 1
7954359Sroberto *      0 x x x  - MESZ/MEZ
8054359Sroberto *      1 x x x  - UTC
8154359Sroberto *      x 0 0 1  - Monday
8254359Sroberto *      x 0 1 0  - Tuesday
8354359Sroberto *      x 0 1 1  - Wednesday
8454359Sroberto *      x 1 0 0  - Thursday
8554359Sroberto *      x 1 0 1  - Friday
8654359Sroberto *      x 1 1 0  - Saturday
8754359Sroberto *      x 1 1 1  - Sunday
8854359Sroberto */
8954359Sroberto
9054359Sroberto#define HOPF_DSTWARN	0x01	/* DST switch warning */
9154359Sroberto#define HOPF_DST	0x02	/* DST in effect */
9254359Sroberto
93282408Scy#define HOPF_MODE	0x0C	/* operation mode mask */
9454359Sroberto#define  HOPF_INVALID	0x00	/* no time code available */
9554359Sroberto#define  HOPF_INTERNAL	0x04	/* internal clock */
96282408Scy#define  HOPF_RADIO	0x08	/* radio clock */
9754359Sroberto#define  HOPF_RADIOHP	0x0C	/* high precision radio clock */
9854359Sroberto
9954359Sroberto#define HOPF_UTC	0x08	/* time code in UTC */
10054359Sroberto#define HOPF_WMASK	0x07	/* mask for weekday code */
10154359Sroberto
10254359Srobertostatic struct format hopf6021_fmt =
10354359Sroberto{
10454359Sroberto	{
105282408Scy		{  9, 2 }, {11, 2}, { 13, 2}, /* Day, Month, Year */
106282408Scy		{  3, 2 }, { 5, 2}, {  7, 2}, /* Hour, Minute, Second */
10754359Sroberto		{  2, 1 }, { 1, 1}, {  0, 0}, /* Weekday, Flags, Zone */
10854359Sroberto		/* ... */
10954359Sroberto	},
11054359Sroberto	(const unsigned char *)"\002              \n\r\003",
111282408Scy	0
11254359Sroberto};
11354359Sroberto
11454359Sroberto#define OFFS(x) format->field_offsets[(x)].offset
11554359Sroberto#define STOI(x, y) Stoi(&buffer[OFFS(x)], y, format->field_offsets[(x)].length)
11654359Sroberto#define hexval(x) (('0' <= (x) && (x) <= '9') ? (x) - '0' : \
11754359Sroberto		   ('a' <= (x) && (x) <= 'f') ? (x) - 'a' + 10 : \
11854359Sroberto		   ('A' <= (x) && (x) <= 'F') ? (x) - 'A' + 10 : \
11954359Sroberto		   -1)
12054359Sroberto
121282408Scystatic parse_cvt_fnc_t cvt_hopf6021;
122282408Scystatic parse_inp_fnc_t inp_hopf6021;
12354359Sroberto
12454359Srobertoclockformat_t clock_hopf6021 =
12554359Sroberto{
12654359Sroberto  inp_hopf6021,			/* HOPF 6021 input handling */
12754359Sroberto  cvt_hopf6021,                 /* Radiocode clock conversion */
12854359Sroberto  0,				/* no direct PPS monitoring */
12954359Sroberto  (void *)&hopf6021_fmt,        /* conversion configuration */
13054359Sroberto  "hopf Funkuhr 6021",          /* clock format name */
13154359Sroberto  19,                           /* string buffer */
13254359Sroberto  0                            /* private data length, no private data */
13354359Sroberto};
13454359Sroberto
135282408Scy/* parse_cvt_fnc_t cvt_hopf6021 */
136282408Scystatic u_long
13754359Srobertocvt_hopf6021(
13854359Sroberto	     unsigned char *buffer,
13954359Sroberto	     int            size,
14054359Sroberto	     struct format *format,
14154359Sroberto	     clocktime_t   *clock_time,
14254359Sroberto	     void          *local
14354359Sroberto	     )
14454359Sroberto{
14554359Sroberto	unsigned char status,weekday;
14654359Sroberto
14754359Sroberto	if (!Strok(buffer, format->fixed_string))
14854359Sroberto	{
14954359Sroberto		return CVT_NONE;
15054359Sroberto	}
15154359Sroberto
15254359Sroberto	if (  STOI(O_DAY,   &clock_time->day)    ||
15354359Sroberto	      STOI(O_MONTH, &clock_time->month)  ||
15454359Sroberto	      STOI(O_YEAR,  &clock_time->year)   ||
15554359Sroberto	      STOI(O_HOUR,  &clock_time->hour)   ||
15654359Sroberto	      STOI(O_MIN,   &clock_time->minute) ||
15754359Sroberto	      STOI(O_SEC,   &clock_time->second)
15854359Sroberto	      )
15954359Sroberto	{
16054359Sroberto		return CVT_FAIL|CVT_BADFMT;
16154359Sroberto	}
16254359Sroberto
16354359Sroberto	clock_time->usecond   = 0;
16454359Sroberto	clock_time->utcoffset = 0;
16554359Sroberto
166282408Scy	status = (u_char) hexval(buffer[OFFS(O_FLAGS)]);
167282408Scy	weekday= (u_char) hexval(buffer[OFFS(O_WDAY)]);
16854359Sroberto
16954359Sroberto	if ((status == 0xFF) || (weekday == 0xFF))
17054359Sroberto	{
17154359Sroberto		return CVT_FAIL|CVT_BADFMT;
17254359Sroberto	}
17354359Sroberto
17454359Sroberto	clock_time->flags  = 0;
17554359Sroberto
17654359Sroberto	if (weekday & HOPF_UTC)
17754359Sroberto	{
17854359Sroberto		clock_time->flags |= PARSEB_UTC;
17954359Sroberto	}
18054359Sroberto	else
18154359Sroberto	{
18254359Sroberto		if (status & HOPF_DST)
18354359Sroberto		{
18454359Sroberto			clock_time->flags     |= PARSEB_DST;
18554359Sroberto			clock_time->utcoffset  = -2*60*60; /* MET DST */
18654359Sroberto		}
18754359Sroberto		else
18854359Sroberto		{
18954359Sroberto			clock_time->utcoffset  = -1*60*60; /* MET */
19054359Sroberto		}
19154359Sroberto	}
19254359Sroberto
19354359Sroberto	clock_time->flags |= (status & HOPF_DSTWARN)  ? PARSEB_ANNOUNCE : 0;
19454359Sroberto
19554359Sroberto	switch (status & HOPF_MODE)
19654359Sroberto	{
19754359Sroberto	    case HOPF_INVALID:  /* Time/Date invalid */
19854359Sroberto		clock_time->flags |= PARSEB_POWERUP;
19954359Sroberto		break;
20054359Sroberto
20154359Sroberto	    case HOPF_INTERNAL: /* internal clock */
20254359Sroberto		clock_time->flags |= PARSEB_NOSYNC;
20354359Sroberto		break;
20454359Sroberto
20554359Sroberto	    case HOPF_RADIO:    /* Radio clock */
20654359Sroberto	    case HOPF_RADIOHP:  /* Radio clock high precision */
20754359Sroberto		break;
20854359Sroberto
20954359Sroberto	    default:
21054359Sroberto		return CVT_FAIL|CVT_BADFMT;
21154359Sroberto	}
21254359Sroberto
21354359Sroberto	return CVT_OK;
21454359Sroberto}
21554359Sroberto
21654359Sroberto/*
217282408Scy * parse_inp_fnc_t inp_hopf6021
21854359Sroberto *
219282408Scy * grab data from input stream
22054359Sroberto */
22154359Srobertostatic u_long
22254359Srobertoinp_hopf6021(
22354359Sroberto	     parse_t      *parseio,
224282408Scy	     char         ch,
22554359Sroberto	     timestamp_t  *tstamp
22654359Sroberto	  )
22754359Sroberto{
22854359Sroberto	unsigned int rtc;
229282408Scy
23082498Sroberto	parseprintf(DD_PARSE, ("inp_hopf6021(0x%lx, 0x%x, ...)\n", (long)parseio, ch));
231282408Scy
23254359Sroberto	switch (ch)
23354359Sroberto	{
23454359Sroberto	case ETX:
23554359Sroberto		parseprintf(DD_PARSE, ("inp_hopf6021: EOL seen\n"));
23654359Sroberto		parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */
23754359Sroberto		if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP)
23854359Sroberto			return parse_end(parseio);
23954359Sroberto		else
24054359Sroberto			return rtc;
24154359Sroberto
24254359Sroberto	default:
24354359Sroberto		return parse_addchar(parseio, ch);
24454359Sroberto	}
24554359Sroberto}
24654359Sroberto
24754359Sroberto#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_HOPF6021) */
24854359Srobertoint clk_hopf6021_bs;
24954359Sroberto#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_HOPF6021) */
25054359Sroberto
25154359Sroberto/*
25254359Sroberto * History:
25354359Sroberto *
25454359Sroberto * clk_hopf6021.c,v
255182007Sroberto * Revision 4.10  2004/11/14 15:29:41  kardel
256182007Sroberto * support PPSAPI, upgrade Copyright to Berkeley style
257182007Sroberto *
25856746Sroberto * Revision 4.7  1999/11/28 09:13:49  kardel
25956746Sroberto * RECON_4_0_98F
26056746Sroberto *
26154359Sroberto * Revision 4.6  1998/11/15 20:27:57  kardel
26254359Sroberto * Release 4.0.73e13 reconcilation
26354359Sroberto *
26454359Sroberto * Revision 4.5  1998/06/14 21:09:35  kardel
26554359Sroberto * Sun acc cleanup
26654359Sroberto *
26754359Sroberto * Revision 4.4  1998/06/13 12:02:38  kardel
26854359Sroberto * fix SYSV clock name clash
26954359Sroberto *
27054359Sroberto * Revision 4.3  1998/06/12 15:22:27  kardel
27154359Sroberto * fix prototypes
27254359Sroberto *
27354359Sroberto * Revision 4.2  1998/06/12 09:13:25  kardel
27454359Sroberto * conditional compile macros fixed
27554359Sroberto * printf prototype
27654359Sroberto *
27754359Sroberto * Revision 4.1  1998/05/24 09:39:52  kardel
27854359Sroberto * implementation of the new IO handling model
27954359Sroberto *
28054359Sroberto * Revision 4.0  1998/04/10 19:45:29  kardel
28154359Sroberto * Start 4.0 release version numbering
28254359Sroberto *
28354359Sroberto * from V3 3.6 log info deleted 1998/04/11 kardel
28454359Sroberto */
285