clk_hopf6021.c revision 54359
154359Sroberto/*
254359Sroberto * /src/NTP/ntp-4/libparse/clk_hopf6021.c,v 4.6 1998/11/15 20:27:57 kardel RELEASE_19990228_A
354359Sroberto *
454359Sroberto * clk_hopf6021.c,v 4.6 1998/11/15 20:27:57 kardel RELEASE_19990228_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 <sys/types.h>
2654359Sroberto#include <sys/time.h>
2754359Sroberto
2854359Sroberto#include "ntp_fp.h"
2954359Sroberto#include "ntp_unixtime.h"
3054359Sroberto#include "ntp_calendar.h"
3154359Sroberto#include "ascii.h"
3254359Sroberto
3354359Sroberto#include "parse.h"
3454359Sroberto
3554359Sroberto#ifndef PARSESTREAM
3654359Sroberto#include "ntp_stdlib.h"
3754359Sroberto#include <stdio.h>
3854359Sroberto#else
3954359Sroberto#include "sys/parsestreams.h"
4054359Srobertoextern void printf P((const char *, ...));
4154359Sroberto#endif
4254359Sroberto
4354359Sroberto/*
4454359Sroberto * hopf Funkuhr 6021
4554359Sroberto *      used with 9600,8N1,
4654359Sroberto *      UTC ueber serielle Schnittstelle
4754359Sroberto *      Sekundenvorlauf ON
4854359Sroberto *      ETX zum Sekundenvorlauf ON
4954359Sroberto *      Datenstring 6021
5054359Sroberto *      Ausgabe Uhrzeit und Datum
5154359Sroberto *      Senden mit Steuerzeichen
5254359Sroberto *      Senden sekuendlich
5354359Sroberto */
5454359Sroberto
5554359Sroberto/*
5654359Sroberto *  Type 6021 Serial Output format
5754359Sroberto *
5854359Sroberto *      000000000011111111 / char
5954359Sroberto *      012345678901234567 \ position
6054359Sroberto *      sABHHMMSSDDMMYYnre  Actual
6154359Sroberto *       C4110046231195     Parse
6254359Sroberto *      s              enr  Check
6354359Sroberto *
6454359Sroberto *  s = STX (0x02), e = ETX (0x03)
6554359Sroberto *  n = NL  (0x0A), r = CR  (0x0D)
6654359Sroberto *
6754359Sroberto *  A B - Status and weekday
6854359Sroberto *
6954359Sroberto *  A - Status
7054359Sroberto *
7154359Sroberto *      8 4 2 1
7254359Sroberto *      x x x 0  - no announcement
7354359Sroberto *      x x x 1  - Summertime - wintertime - summertime announcement
7454359Sroberto *      x x 0 x  - Wintertime
7554359Sroberto *      x x 1 x  - Summertime
7654359Sroberto *      0 0 x x  - Time/Date invalid
7754359Sroberto *      0 1 x x  - Internal clock used
7854359Sroberto *      1 0 x x  - Radio clock
7954359Sroberto *      1 1 x x  - Radio clock highprecision
8054359Sroberto *
8154359Sroberto *  B - 8 4 2 1
8254359Sroberto *      0 x x x  - MESZ/MEZ
8354359Sroberto *      1 x x x  - UTC
8454359Sroberto *      x 0 0 1  - Monday
8554359Sroberto *      x 0 1 0  - Tuesday
8654359Sroberto *      x 0 1 1  - Wednesday
8754359Sroberto *      x 1 0 0  - Thursday
8854359Sroberto *      x 1 0 1  - Friday
8954359Sroberto *      x 1 1 0  - Saturday
9054359Sroberto *      x 1 1 1  - Sunday
9154359Sroberto */
9254359Sroberto
9354359Sroberto#define HOPF_DSTWARN	0x01	/* DST switch warning */
9454359Sroberto#define HOPF_DST	0x02	/* DST in effect */
9554359Sroberto
9654359Sroberto#define HOPF_MODE	0x0C	/* operation mode mask */
9754359Sroberto#define  HOPF_INVALID	0x00	/* no time code available */
9854359Sroberto#define  HOPF_INTERNAL	0x04	/* internal clock */
9954359Sroberto#define  HOPF_RADIO	0x08	/* radio clock */
10054359Sroberto#define  HOPF_RADIOHP	0x0C	/* high precision radio clock */
10154359Sroberto
10254359Sroberto#define HOPF_UTC	0x08	/* time code in UTC */
10354359Sroberto#define HOPF_WMASK	0x07	/* mask for weekday code */
10454359Sroberto
10554359Srobertostatic struct format hopf6021_fmt =
10654359Sroberto{
10754359Sroberto	{
10854359Sroberto		{  9, 2 }, {11, 2}, { 13, 2}, /* Day, Month, Year */
10954359Sroberto		{  3, 2 }, { 5, 2}, {  7, 2}, /* Hour, Minute, Second */
11054359Sroberto		{  2, 1 }, { 1, 1}, {  0, 0}, /* Weekday, Flags, Zone */
11154359Sroberto		/* ... */
11254359Sroberto	},
11354359Sroberto	(const unsigned char *)"\002              \n\r\003",
11454359Sroberto	0
11554359Sroberto};
11654359Sroberto
11754359Sroberto#define OFFS(x) format->field_offsets[(x)].offset
11854359Sroberto#define STOI(x, y) Stoi(&buffer[OFFS(x)], y, format->field_offsets[(x)].length)
11954359Sroberto#define hexval(x) (('0' <= (x) && (x) <= '9') ? (x) - '0' : \
12054359Sroberto		   ('a' <= (x) && (x) <= 'f') ? (x) - 'a' + 10 : \
12154359Sroberto		   ('A' <= (x) && (x) <= 'F') ? (x) - 'A' + 10 : \
12254359Sroberto		   -1)
12354359Sroberto
12454359Srobertostatic unsigned long cvt_hopf6021 P((unsigned char *, int, struct format *, clocktime_t *, void *));
12554359Srobertostatic unsigned long inp_hopf6021 P((parse_t *, unsigned int, timestamp_t *));
12654359Sroberto
12754359Srobertoclockformat_t clock_hopf6021 =
12854359Sroberto{
12954359Sroberto  inp_hopf6021,			/* HOPF 6021 input handling */
13054359Sroberto  cvt_hopf6021,                 /* Radiocode clock conversion */
13154359Sroberto  0,				/* no direct PPS monitoring */
13254359Sroberto  (void *)&hopf6021_fmt,        /* conversion configuration */
13354359Sroberto  "hopf Funkuhr 6021",          /* clock format name */
13454359Sroberto  19,                           /* string buffer */
13554359Sroberto  0                            /* private data length, no private data */
13654359Sroberto};
13754359Sroberto
13854359Srobertostatic unsigned long
13954359Srobertocvt_hopf6021(
14054359Sroberto	     unsigned char *buffer,
14154359Sroberto	     int            size,
14254359Sroberto	     struct format *format,
14354359Sroberto	     clocktime_t   *clock_time,
14454359Sroberto	     void          *local
14554359Sroberto	     )
14654359Sroberto{
14754359Sroberto	unsigned char status,weekday;
14854359Sroberto
14954359Sroberto	if (!Strok(buffer, format->fixed_string))
15054359Sroberto	{
15154359Sroberto		return CVT_NONE;
15254359Sroberto	}
15354359Sroberto
15454359Sroberto	if (  STOI(O_DAY,   &clock_time->day)    ||
15554359Sroberto	      STOI(O_MONTH, &clock_time->month)  ||
15654359Sroberto	      STOI(O_YEAR,  &clock_time->year)   ||
15754359Sroberto	      STOI(O_HOUR,  &clock_time->hour)   ||
15854359Sroberto	      STOI(O_MIN,   &clock_time->minute) ||
15954359Sroberto	      STOI(O_SEC,   &clock_time->second)
16054359Sroberto	      )
16154359Sroberto	{
16254359Sroberto		return CVT_FAIL|CVT_BADFMT;
16354359Sroberto	}
16454359Sroberto
16554359Sroberto	clock_time->usecond   = 0;
16654359Sroberto	clock_time->utcoffset = 0;
16754359Sroberto
16854359Sroberto	status = hexval(buffer[OFFS(O_FLAGS)]);
16954359Sroberto	weekday= hexval(buffer[OFFS(O_WDAY)]);
17054359Sroberto
17154359Sroberto	if ((status == 0xFF) || (weekday == 0xFF))
17254359Sroberto	{
17354359Sroberto		return CVT_FAIL|CVT_BADFMT;
17454359Sroberto	}
17554359Sroberto
17654359Sroberto	clock_time->flags  = 0;
17754359Sroberto
17854359Sroberto	if (weekday & HOPF_UTC)
17954359Sroberto	{
18054359Sroberto		clock_time->flags |= PARSEB_UTC;
18154359Sroberto	}
18254359Sroberto	else
18354359Sroberto	{
18454359Sroberto		if (status & HOPF_DST)
18554359Sroberto		{
18654359Sroberto			clock_time->flags     |= PARSEB_DST;
18754359Sroberto			clock_time->utcoffset  = -2*60*60; /* MET DST */
18854359Sroberto		}
18954359Sroberto		else
19054359Sroberto		{
19154359Sroberto			clock_time->utcoffset  = -1*60*60; /* MET */
19254359Sroberto		}
19354359Sroberto	}
19454359Sroberto
19554359Sroberto	clock_time->flags |= (status & HOPF_DSTWARN)  ? PARSEB_ANNOUNCE : 0;
19654359Sroberto
19754359Sroberto	switch (status & HOPF_MODE)
19854359Sroberto	{
19954359Sroberto	    case HOPF_INVALID:  /* Time/Date invalid */
20054359Sroberto		clock_time->flags |= PARSEB_POWERUP;
20154359Sroberto		break;
20254359Sroberto
20354359Sroberto	    case HOPF_INTERNAL: /* internal clock */
20454359Sroberto		clock_time->flags |= PARSEB_NOSYNC;
20554359Sroberto		break;
20654359Sroberto
20754359Sroberto	    case HOPF_RADIO:    /* Radio clock */
20854359Sroberto	    case HOPF_RADIOHP:  /* Radio clock high precision */
20954359Sroberto		break;
21054359Sroberto
21154359Sroberto	    default:
21254359Sroberto		return CVT_FAIL|CVT_BADFMT;
21354359Sroberto	}
21454359Sroberto
21554359Sroberto	return CVT_OK;
21654359Sroberto}
21754359Sroberto
21854359Sroberto/*
21954359Sroberto * inp_hopf6021
22054359Sroberto *
22154359Sroberto * grep data from input stream
22254359Sroberto */
22354359Srobertostatic u_long
22454359Srobertoinp_hopf6021(
22554359Sroberto	     parse_t      *parseio,
22654359Sroberto	     unsigned int  ch,
22754359Sroberto	     timestamp_t  *tstamp
22854359Sroberto	  )
22954359Sroberto{
23054359Sroberto	unsigned int rtc;
23154359Sroberto
23254359Sroberto	parseprintf(DD_PARSE, ("inp_hopf6021(0x%x, 0x%x, ...)\n", (int)parseio, (int)ch));
23354359Sroberto
23454359Sroberto	switch (ch)
23554359Sroberto	{
23654359Sroberto	case ETX:
23754359Sroberto		parseprintf(DD_PARSE, ("inp_hopf6021: EOL seen\n"));
23854359Sroberto		parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */
23954359Sroberto		if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP)
24054359Sroberto			return parse_end(parseio);
24154359Sroberto		else
24254359Sroberto			return rtc;
24354359Sroberto
24454359Sroberto	default:
24554359Sroberto		return parse_addchar(parseio, ch);
24654359Sroberto	}
24754359Sroberto}
24854359Sroberto
24954359Sroberto#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_HOPF6021) */
25054359Srobertoint clk_hopf6021_bs;
25154359Sroberto#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_HOPF6021) */
25254359Sroberto
25354359Sroberto/*
25454359Sroberto * History:
25554359Sroberto *
25654359Sroberto * clk_hopf6021.c,v
25754359Sroberto * Revision 4.6  1998/11/15 20:27:57  kardel
25854359Sroberto * Release 4.0.73e13 reconcilation
25954359Sroberto *
26054359Sroberto * Revision 4.5  1998/06/14 21:09:35  kardel
26154359Sroberto * Sun acc cleanup
26254359Sroberto *
26354359Sroberto * Revision 4.4  1998/06/13 12:02:38  kardel
26454359Sroberto * fix SYSV clock name clash
26554359Sroberto *
26654359Sroberto * Revision 4.3  1998/06/12 15:22:27  kardel
26754359Sroberto * fix prototypes
26854359Sroberto *
26954359Sroberto * Revision 4.2  1998/06/12 09:13:25  kardel
27054359Sroberto * conditional compile macros fixed
27154359Sroberto * printf prototype
27254359Sroberto *
27354359Sroberto * Revision 4.1  1998/05/24 09:39:52  kardel
27454359Sroberto * implementation of the new IO handling model
27554359Sroberto *
27654359Sroberto * Revision 4.0  1998/04/10 19:45:29  kardel
27754359Sroberto * Start 4.0 release version numbering
27854359Sroberto *
27954359Sroberto * from V3 3.6 log info deleted 1998/04/11 kardel
28054359Sroberto */
281