Home | History | Annotate | Line # | Download | only in libparse
      1 /*	$NetBSD: clk_hopf6021.c,v 1.8 2024/08/18 20:47:17 christos Exp $	*/
      2 
      3 /*
      4  * /src/NTP/ntp4-dev/libparse/clk_hopf6021.c,v 4.10 2004/11/14 15:29:41 kardel RELEASE_20050508_A
      5  *
      6  * clk_hopf6021.c,v 4.10 2004/11/14 15:29:41 kardel RELEASE_20050508_A
      7  *
      8  * Radiocode Clocks HOPF Funkuhr 6021 mit serieller Schnittstelle
      9  * base code version from 24th Nov 1995 - history at end
     10  *
     11  * Created by F.Schnekenbuehl <frank (at) comsys.dofn.de> from clk_rcc8000.c
     12  * Nortel DASA Network Systems GmbH, Department: ND250
     13  * A Joint venture of Daimler-Benz Aerospace and Nortel
     14  *
     15  * This program is distributed in the hope that it will be useful,
     16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     18  *
     19  */
     20 
     21 #ifdef HAVE_CONFIG_H
     22 # include <config.h>
     23 #endif
     24 
     25 #include "ntp_types.h"
     26 
     27 #if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_HOPF6021)
     28 
     29 #include "ntp_fp.h"
     30 #include "ntp_unixtime.h"
     31 #include "ntp_calendar.h"
     32 
     33 #include "parse.h"
     34 
     35 #ifndef PARSESTREAM
     36 #include "ntp_stdlib.h"
     37 #include <stdio.h>
     38 #else
     39 #include "sys/parsestreams.h"
     40 extern int printf (const char *, ...);
     41 #endif
     42 
     43 #include "ascii.h"
     44 
     45 /*
     46  * hopf Funkuhr 6021
     47  *      used with 9600,8N1,
     48  *      UTC ueber serielle Schnittstelle
     49  *      Sekundenvorlauf ON
     50  *      ETX zum Sekundenvorlauf ON
     51  *      Datenstring 6021
     52  *      Ausgabe Uhrzeit und Datum
     53  *      Senden mit Steuerzeichen
     54  *      Senden sekuendlich
     55  */
     56 
     57 /*
     58  *  Type 6021 Serial Output format
     59  *
     60  *      000000000011111111 / char
     61  *      012345678901234567 \ position
     62  *      sABHHMMSSDDMMYYnre  Actual
     63  *       C4110046231195     Parse
     64  *      s              enr  Check
     65  *
     66  *  s = STX (0x02), e = ETX (0x03)
     67  *  n = NL  (0x0A), r = CR  (0x0D)
     68  *
     69  *  A B - Status and weekday
     70  *
     71  *  A - Status
     72  *
     73  *      8 4 2 1
     74  *      x x x 0  - no announcement
     75  *      x x x 1  - Summertime - wintertime - summertime announcement
     76  *      x x 0 x  - Wintertime
     77  *      x x 1 x  - Summertime
     78  *      0 0 x x  - Time/Date invalid
     79  *      0 1 x x  - Internal clock used
     80  *      1 0 x x  - Radio clock
     81  *      1 1 x x  - Radio clock highprecision
     82  *
     83  *  B - 8 4 2 1
     84  *      0 x x x  - MESZ/MEZ
     85  *      1 x x x  - UTC
     86  *      x 0 0 1  - Monday
     87  *      x 0 1 0  - Tuesday
     88  *      x 0 1 1  - Wednesday
     89  *      x 1 0 0  - Thursday
     90  *      x 1 0 1  - Friday
     91  *      x 1 1 0  - Saturday
     92  *      x 1 1 1  - Sunday
     93  */
     94 
     95 #define HOPF_DSTWARN	0x01	/* DST switch warning */
     96 #define HOPF_DST	0x02	/* DST in effect */
     97 
     98 #define HOPF_MODE	0x0C	/* operation mode mask */
     99 #define  HOPF_INVALID	0x00	/* no time code available */
    100 #define  HOPF_INTERNAL	0x04	/* internal clock */
    101 #define  HOPF_RADIO	0x08	/* radio clock */
    102 #define  HOPF_RADIOHP	0x0C	/* high precision radio clock */
    103 
    104 #define HOPF_UTC	0x08	/* time code in UTC */
    105 #define HOPF_WMASK	0x07	/* mask for weekday code */
    106 
    107 static struct format hopf6021_fmt =
    108 {
    109 	{
    110 		{  9, 2 }, {11, 2}, { 13, 2}, /* Day, Month, Year */
    111 		{  3, 2 }, { 5, 2}, {  7, 2}, /* Hour, Minute, Second */
    112 		{  2, 1 }, { 1, 1}, {  0, 0}, /* Weekday, Flags, Zone */
    113 		/* ... */
    114 	},
    115 	(const unsigned char *)"\002              \n\r\003",
    116 	0
    117 };
    118 
    119 #define OFFS(x) format->field_offsets[(x)].offset
    120 #define STOI(x, y) Stoi(&buffer[OFFS(x)], y, format->field_offsets[(x)].length)
    121 
    122 static parse_cvt_fnc_t cvt_hopf6021;
    123 static parse_inp_fnc_t inp_hopf6021;
    124 static unsigned char   hexval(unsigned char);
    125 
    126 clockformat_t clock_hopf6021 =
    127 {
    128   inp_hopf6021,			/* HOPF 6021 input handling */
    129   cvt_hopf6021,                 /* Radiocode clock conversion */
    130   0,				/* no direct PPS monitoring */
    131   (void *)&hopf6021_fmt,        /* conversion configuration */
    132   "hopf Funkuhr 6021",          /* clock format name */
    133   19,                           /* string buffer */
    134   0                            /* private data length, no private data */
    135 };
    136 
    137 /* parse_cvt_fnc_t cvt_hopf6021 */
    138 static u_long
    139 cvt_hopf6021(
    140 	     unsigned char *buffer,
    141 	     int            size,
    142 	     struct format *format,
    143 	     clocktime_t   *clock_time,
    144 	     void          *local
    145 	     )
    146 {
    147 	unsigned char status,weekday;
    148 
    149 	if (!Strok(buffer, format->fixed_string))
    150 	{
    151 		return CVT_NONE;
    152 	}
    153 
    154 	if (  STOI(O_DAY,   &clock_time->day)    ||
    155 	      STOI(O_MONTH, &clock_time->month)  ||
    156 	      STOI(O_YEAR,  &clock_time->year)   ||
    157 	      STOI(O_HOUR,  &clock_time->hour)   ||
    158 	      STOI(O_MIN,   &clock_time->minute) ||
    159 	      STOI(O_SEC,   &clock_time->second)
    160 	      )
    161 	{
    162 		return CVT_FAIL|CVT_BADFMT;
    163 	}
    164 
    165 	clock_time->usecond = 0;
    166 	clock_time->flags   = 0;
    167 
    168 	status  = hexval(buffer[OFFS(O_FLAGS)]);
    169 	weekday = hexval(buffer[OFFS(O_WDAY)]);
    170 
    171 	if ((status == 0xFF) || (weekday == 0xFF))
    172 	{
    173 		return CVT_FAIL|CVT_BADFMT;
    174 	}
    175 
    176 	if (weekday & HOPF_UTC)
    177 	{
    178 		clock_time->flags     |= PARSEB_UTC;
    179 		clock_time->utcoffset  = 0;
    180 	}
    181 	else if (status & HOPF_DST)
    182 	{
    183 		clock_time->flags     |= PARSEB_DST;
    184 		clock_time->utcoffset  = -2*60*60; /* MET DST */
    185 	}
    186 	else
    187 	{
    188 		clock_time->utcoffset  = -1*60*60; /* MET */
    189 	}
    190 
    191 	if (status & HOPF_DSTWARN)
    192 	{
    193 		clock_time->flags |= PARSEB_ANNOUNCE;
    194 	}
    195 
    196 	switch (status & HOPF_MODE)
    197 	{
    198 	    default:	/* dummy: we cover all 4 cases. */
    199 	    case HOPF_INVALID:  /* Time/Date invalid */
    200 		clock_time->flags |= PARSEB_POWERUP;
    201 		break;
    202 
    203 	    case HOPF_INTERNAL: /* internal clock */
    204 		clock_time->flags |= PARSEB_NOSYNC;
    205 		break;
    206 
    207 	    case HOPF_RADIO:    /* Radio clock */
    208 	    case HOPF_RADIOHP:  /* Radio clock high precision */
    209 		break;
    210 	}
    211 
    212 	return CVT_OK;
    213 }
    214 
    215 /*
    216  * parse_inp_fnc_t inp_hopf6021
    217  *
    218  * grab data from input stream
    219  */
    220 static u_long
    221 inp_hopf6021(
    222 	     parse_t      *parseio,
    223 	     char         ch,
    224 	     timestamp_t  *tstamp
    225 	  )
    226 {
    227 	unsigned int rtc;
    228 
    229 	parseprintf(DD_PARSE, ("inp_hopf6021(0x%p, 0x%x, ...)\n", (void*)parseio, ch));
    230 
    231 	switch (ch)
    232 	{
    233 	case ETX:
    234 		parseprintf(DD_PARSE, ("inp_hopf6021: EOL seen\n"));
    235 		parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */
    236 		if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP)
    237 			return parse_end(parseio);
    238 		else
    239 			return rtc;
    240 
    241 	default:
    242 		return parse_addchar(parseio, ch);
    243 	}
    244 }
    245 
    246 /*
    247  * convert a hex-digit to numeric value
    248  */
    249 static unsigned char
    250 hexval(
    251 	unsigned char ch
    252 	)
    253 {
    254 	unsigned int dv;
    255 
    256 	if ((dv = ch - '0') >= 10u)
    257 	{
    258 		if ((dv -= 'A'-'0') < 6u || (dv -= 'a'-'A') < 6u)
    259 		{
    260 			dv += 10;
    261 		}
    262 		else
    263 		{
    264 			dv = 0xFF;
    265 		}
    266 	}
    267 	return (unsigned char)dv;
    268 }
    269 
    270 #else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_HOPF6021) */
    271 NONEMPTY_TRANSLATION_UNIT
    272 #endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_HOPF6021) */
    273 
    274 /*
    275  * History:
    276  *
    277  * clk_hopf6021.c,v
    278  * Revision 4.10  2004/11/14 15:29:41  kardel
    279  * support PPSAPI, upgrade Copyright to Berkeley style
    280  *
    281  * Revision 4.7  1999/11/28 09:13:49  kardel
    282  * RECON_4_0_98F
    283  *
    284  * Revision 4.6  1998/11/15 20:27:57  kardel
    285  * Release 4.0.73e13 reconcilation
    286  *
    287  * Revision 4.5  1998/06/14 21:09:35  kardel
    288  * Sun acc cleanup
    289  *
    290  * Revision 4.4  1998/06/13 12:02:38  kardel
    291  * fix SYSV clock name clash
    292  *
    293  * Revision 4.3  1998/06/12 15:22:27  kardel
    294  * fix prototypes
    295  *
    296  * Revision 4.2  1998/06/12 09:13:25  kardel
    297  * conditional compile macros fixed
    298  * printf prototype
    299  *
    300  * Revision 4.1  1998/05/24 09:39:52  kardel
    301  * implementation of the new IO handling model
    302  *
    303  * Revision 4.0  1998/04/10 19:45:29  kardel
    304  * Start 4.0 release version numbering
    305  *
    306  * from V3 3.6 log info deleted 1998/04/11 kardel
    307  */
    308