154359Sroberto/* 2182007Sroberto * /src/NTP/ntp4-dev/libparse/clk_rcc8000.c,v 4.9 2004/11/14 15:29:41 kardel RELEASE_20050508_A 3290001Sglebius * 4182007Sroberto * clk_rcc8000.c,v 4.9 2004/11/14 15:29:41 kardel RELEASE_20050508_A 554359Sroberto * 654359Sroberto * Radiocode Clocks Ltd RCC 8000 Intelligent Off-Air Master Clock support 754359Sroberto * 854359Sroberto * Created by R.E.Broughton from clk_trimtaip.c 954359Sroberto * 1054359Sroberto * This program is distributed in the hope that it will be useful, 1154359Sroberto * but WITHOUT ANY WARRANTY; without even the implied warranty of 1254359Sroberto * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 1354359Sroberto * 1454359Sroberto */ 1554359Sroberto 1654359Sroberto#if HAVE_CONFIG_H 1754359Sroberto# include <config.h> 1854359Sroberto#endif 1954359Sroberto 2054359Sroberto#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_RCC8000) 2154359Sroberto 2254359Sroberto#include "ntp_fp.h" 2354359Sroberto#include "ntp_unixtime.h" 2454359Sroberto#include "ntp_calendar.h" 2554359Sroberto 2654359Sroberto#include "parse.h" 2754359Sroberto 2854359Sroberto#ifndef PARSESTREAM 2954359Sroberto#include "ntp_stdlib.h" 3054359Sroberto#include <stdio.h> 3154359Sroberto#else 3254359Sroberto#include "sys/parsestreams.h" 33290001Sglebiusextern int printf (const char *, ...); 3454359Sroberto#endif 3554359Sroberto 3654359Sroberto/* Type II Serial Output format 3754359Sroberto * 3854359Sroberto * 0000000000111111111122222222223 / char 3954359Sroberto * 0123456789012345678901234567890 \ posn 4054359Sroberto * HH:MM:SS.XYZ DD/MM/YY DDD W Prn Actual 4154359Sroberto * 33 44 55 666 00 11 22 7 Parse 4254359Sroberto * : : . / / rn Check 4354359Sroberto * "15:50:36.534 30/09/94 273 5 A\x0d\x0a" 4454359Sroberto * 4554359Sroberto * DDD - Day of year number 4654359Sroberto * W - Day of week number (Sunday is 0) 4754359Sroberto * P is the Status. See comment below for details. 4854359Sroberto */ 4954359Sroberto 5054359Sroberto#define O_USEC O_WDAY 5154359Srobertostatic struct format rcc8000_fmt = 52290001Sglebius{ { { 13, 2 }, {16, 2}, { 19, 2}, /* Day, Month, Year */ 53290001Sglebius { 0, 2 }, { 3, 2}, { 6, 2}, /* Hour, Minute, Second */ 5454359Sroberto { 9, 3 }, {28, 1}, { 0, 0}, /* uSec, Status (Valid,Reject,BST,Leapyear) */ }, 55290001Sglebius (const unsigned char *)" : : . / / \r\n", 5654359Sroberto /*"15:50:36.534 30/09/94 273 5 A\x0d\x0a" */ 57290001Sglebius 0 5854359Sroberto}; 5954359Sroberto 60290001Sglebiusstatic parse_cvt_fnc_t cvt_rcc8000; 61290001Sglebiusstatic parse_inp_fnc_t inp_rcc8000; 6254359Sroberto 6354359Srobertoclockformat_t clock_rcc8000 = 6454359Sroberto{ 6554359Sroberto inp_rcc8000, /* no input handling */ 6654359Sroberto cvt_rcc8000, /* Radiocode clock conversion */ 6754359Sroberto 0, /* no direct PPS monitoring */ 6854359Sroberto (void *)&rcc8000_fmt, /* conversion configuration */ 6954359Sroberto "Radiocode RCC8000", 7054359Sroberto 31, /* string buffer */ 7154359Sroberto 0 /* no private data */ 7254359Sroberto}; 7354359Sroberto 74290001Sglebius/* parse_cvt_fnc_t cvt_rcc8000 */ 75290001Sglebiusstatic u_long 7654359Srobertocvt_rcc8000( 7754359Sroberto unsigned char *buffer, 7854359Sroberto int size, 7954359Sroberto struct format *format, 8054359Sroberto clocktime_t *clock_time, 8154359Sroberto void *local 8254359Sroberto ) 8354359Sroberto{ 8454359Sroberto if (!Strok(buffer, format->fixed_string)) return CVT_NONE; 8554359Sroberto#define OFFS(x) format->field_offsets[(x)].offset 8654359Sroberto#define STOI(x, y) Stoi(&buffer[OFFS(x)], y, format->field_offsets[(x)].length) 8754359Sroberto if ( STOI(O_DAY, &clock_time->day) || 8854359Sroberto STOI(O_MONTH, &clock_time->month) || 8954359Sroberto STOI(O_YEAR, &clock_time->year) || 9054359Sroberto STOI(O_HOUR, &clock_time->hour) || 9154359Sroberto STOI(O_MIN, &clock_time->minute) || 9254359Sroberto STOI(O_SEC, &clock_time->second) || 9354359Sroberto STOI(O_USEC, &clock_time->usecond) 9454359Sroberto ) return CVT_FAIL|CVT_BADFMT; 9554359Sroberto clock_time->usecond *= 1000; 9654359Sroberto 9754359Sroberto clock_time->utcoffset = 0; 9854359Sroberto 9954359Sroberto#define RCCP buffer[28] 10054359Sroberto /* 10154359Sroberto * buffer[28] is the ASCII representation of a hex character ( 0 through F ) 10254359Sroberto * The four bits correspond to: 10354359Sroberto * 8 - Valid Time 10454359Sroberto * 4 - Reject Code 10554359Sroberto * 2 - British Summer Time (receiver set to emit GMT all year.) 10654359Sroberto * 1 - Leap year 10754359Sroberto */ 10854359Sroberto#define RCC8000_VALID 0x8 10954359Sroberto#define RCC8000_REJECT 0x4 11054359Sroberto#define RCC8000_BST 0x2 11154359Sroberto#define RCC8000_LEAPY 0x1 11254359Sroberto 11354359Sroberto clock_time->flags = 0; 11454359Sroberto 11554359Sroberto if ( (RCCP >= '0' && RCCP <= '9') || (RCCP >= 'A' && RCCP <= 'F') ) 11654359Sroberto { 11754359Sroberto register int flag; 11854359Sroberto 11954359Sroberto flag = (RCCP >= '0' && RCCP <= '9' ) ? RCCP - '0' : RCCP - 'A' + 10; 12054359Sroberto 12154359Sroberto if (!(flag & RCC8000_VALID)) 12254359Sroberto clock_time->flags |= PARSEB_POWERUP; 12354359Sroberto 12454359Sroberto clock_time->flags |= PARSEB_UTC; /* British special - guess why 8-) */ 125290001Sglebius 12654359Sroberto /* other flags not used */ 12754359Sroberto } 12854359Sroberto return CVT_OK; 12954359Sroberto} 13054359Sroberto/* 131290001Sglebius * parse_inp_fnc_t inp_rcc8000 13254359Sroberto * 133290001Sglebius * grab data from input stream 13454359Sroberto */ 13554359Srobertostatic u_long 13654359Srobertoinp_rcc8000( 13754359Sroberto parse_t *parseio, 138290001Sglebius char ch, 13954359Sroberto timestamp_t *tstamp 14054359Sroberto ) 14154359Sroberto{ 14254359Sroberto unsigned int rtc; 143290001Sglebius 144293896Sglebius parseprintf(DD_PARSE, ("inp_rcc8000(0x%p, 0x%x, ...)\n", (void*)parseio, ch)); 145290001Sglebius 14654359Sroberto switch (ch) 14754359Sroberto { 14854359Sroberto case '\n': 14954359Sroberto parseprintf(DD_PARSE, ("inp_rcc8000: EOL seen\n")); 15054359Sroberto if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP) 15154359Sroberto return parse_end(parseio); 15254359Sroberto else 15354359Sroberto return rtc; 15454359Sroberto 155290001Sglebius 15654359Sroberto default: 15754359Sroberto if (parseio->parse_index == 0) /* take sample at start of message */ 15854359Sroberto { 15954359Sroberto parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */ 16054359Sroberto } 16154359Sroberto return parse_addchar(parseio, ch); 16254359Sroberto } 16354359Sroberto} 16454359Sroberto 16554359Sroberto#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_RCC8000) */ 16654359Srobertoint clk_rcc8000_bs; 16754359Sroberto#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_RCC8000) */ 16854359Sroberto 16954359Sroberto/* 17054359Sroberto * History: 17154359Sroberto * 17254359Sroberto * clk_rcc8000.c,v 173182007Sroberto * Revision 4.9 2004/11/14 15:29:41 kardel 174182007Sroberto * support PPSAPI, upgrade Copyright to Berkeley style 175182007Sroberto * 17656746Sroberto * Revision 4.6 1999/11/28 09:13:51 kardel 17756746Sroberto * RECON_4_0_98F 17856746Sroberto * 17954359Sroberto * Revision 4.5 1998/06/14 21:09:38 kardel 18054359Sroberto * Sun acc cleanup 18154359Sroberto * 18254359Sroberto * Revision 4.4 1998/06/13 12:05:02 kardel 18354359Sroberto * fix SYSV clock name clash 18454359Sroberto * 18554359Sroberto * Revision 4.3 1998/06/12 15:22:29 kardel 18654359Sroberto * fix prototypes 18754359Sroberto * 18854359Sroberto * Revision 4.2 1998/06/12 09:13:25 kardel 18954359Sroberto * conditional compile macros fixed 19054359Sroberto * printf prototype 19154359Sroberto * 19254359Sroberto * Revision 4.1 1998/05/24 09:39:53 kardel 19354359Sroberto * implementation of the new IO handling model 19454359Sroberto * 19554359Sroberto * Revision 4.0 1998/04/10 19:45:30 kardel 19654359Sroberto * Start 4.0 release version numbering 19754359Sroberto * 19854359Sroberto * from V3 3.5 log info deleted 1998/04/11 kardel 19954359Sroberto */ 200