📄 clk_meinberg.c
字号:
/* * /src/NTP/ntp4-dev/libparse/clk_meinberg.c,v 4.12 2005/04/16 17:32:10 kardel RELEASE_20050508_A * * clk_meinberg.c,v 4.12 2005/04/16 17:32:10 kardel RELEASE_20050508_A * * Meinberg clock support * * Copyright (c) 1995-2005 by Frank Kardel <kardel <AT> ntp.org> * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universit鋞 Erlangen-N黵nberg, Germany * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */#ifdef HAVE_CONFIG_H# include <config.h>#endif#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_MEINBERG)#include "ntp_fp.h"#include "ntp_unixtime.h"#include "ntp_calendar.h"#include "ntp_machine.h"#include "parse.h"#ifndef PARSESTREAM#include <stdio.h>#else#include "sys/parsestreams.h"#endif#include "ntp_stdlib.h"#include "ntp_stdlib.h"#include "mbg_gps166.h"#include "binio.h"#include "ascii.h"/* * The Meinberg receiver every second sends a datagram of the following form * (Standard Format) * * <STX>D:<dd>.<mm>.<yy>;T:<w>;U:<hh>:<mm>:<ss>;<S><F><D><A><ETX> * pos: 0 00 00 0 00 0 11 111 1 111 12 2 22 2 22 2 2 2 3 3 3 * 1 23 45 6 78 9 01 234 5 678 90 1 23 4 56 7 8 9 0 1 2 * <STX> = '\002' ASCII start of text * <ETX> = '\003' ASCII end of text * <dd>,<mm>,<yy> = day, month, year(2 digits!!) * <w> = day of week (sunday= 0) * <hh>,<mm>,<ss> = hour, minute, second * <S> = '#' if never synced since powerup for DCF C51 * = '#' if not PZF sychronisation available for PZF 535/509 * = ' ' if ok * <F> = '*' if time comes from internal quartz * = ' ' if completely synched * <D> = 'S' if daylight saving time is active * = 'U' if time is represented in UTC * = ' ' if no special condition exists * <A> = '!' during the hour preceeding an daylight saving time * start/end change * = 'A' leap second insert warning * = ' ' if no special condition exists * * Extended data format (PZFUERL for PZF type clocks) * * <STX><dd>.<mm>.<yy>; <w>; <hh>:<mm>:<ss>; <U><S><F><D><A><L><R><ETX> * pos: 0 00 0 00 0 00 11 1 11 11 1 11 2 22 22 2 2 2 2 2 3 3 3 * 1 23 4 56 7 89 01 2 34 56 7 89 0 12 34 5 6 7 8 9 0 1 2 * <STX> = '\002' ASCII start of text * <ETX> = '\003' ASCII end of text * <dd>,<mm>,<yy> = day, month, year(2 digits!!) * <w> = day of week (sunday= 0) * <hh>,<mm>,<ss> = hour, minute, second * <U> = 'U' UTC time display * <S> = '#' if never synced since powerup else ' ' for DCF C51 * '#' if not PZF sychronisation available else ' ' for PZF 535/509 * <F> = '*' if time comes from internal quartz else ' ' * <D> = 'S' if daylight saving time is active else ' ' * <A> = '!' during the hour preceeding an daylight saving time * start/end change * <L> = 'A' LEAP second announcement * <R> = 'R' alternate antenna * * Meinberg GPS166 receiver * * You must get the Uni-Erlangen firmware for the GPS receiver support * to work to full satisfaction ! * * <STX><dd>.<mm>.<yy>; <w>; <hh>:<mm>:<ss>; <+/-><00:00>; <U><S><F><D><A><L><R><L>; <position...><ETX> * * 000000000111111111122222222223333333333444444444455555555556666666 * 123456789012345678901234567890123456789012345678901234567890123456 * \x0209.07.93; 5; 08:48:26; +00:00; #*S!A L; 49.5736N 11.0280E 373m\x03 * * * <STX> = '\002' ASCII start of text * <ETX> = '\003' ASCII end of text * <dd>,<mm>,<yy> = day, month, year(2 digits!!) * <w> = day of week (sunday= 0) * <hh>,<mm>,<ss> = hour, minute, second * <+/->,<00:00> = offset to UTC * <S> = '#' if never synced since powerup else ' ' * <F> = '*' if position is not confirmed else ' ' * <D> = 'S' if daylight saving time is active else ' ' * <A> = '!' during the hour preceeding an daylight saving time * start/end change * <L> = 'A' LEAP second announcement * <R> = 'R' alternate antenna (reminiscent of PZF535) usually ' ' * <L> = 'L' on 23:59:60 * * Binary messages have a lead in for a fixed header of SOH *//*--------------------------------------------------------------*//* Name: csum() *//* *//* Purpose: Compute a checksum about a number of bytes *//* *//* Input: uchar *p address of the first byte *//* short n the number of bytes *//* *//* Output: -- *//* *//* Ret val: the checksum *//*+-------------------------------------------------------------*/unsigned longmbg_csum( unsigned char *p, unsigned int n ){ unsigned long sum = 0; short i; for ( i = 0; i < n; i++ ) sum += *p++; return( sum );} /* csum */voidget_mbg_header( unsigned char **bufpp, GPS_MSG_HDR *headerp ){ headerp->gps_cmd = get_lsb_short(bufpp); headerp->gps_len = get_lsb_short(bufpp); headerp->gps_data_csum = get_lsb_short(bufpp); headerp->gps_hdr_csum = get_lsb_short(bufpp);}static struct format meinberg_fmt[] ={ { { { 3, 2}, { 6, 2}, { 9, 2}, { 18, 2}, { 21, 2}, { 24, 2}, { 14, 1}, { 27, 4}, { 29, 1}, }, (const unsigned char *)"\2D: . . ;T: ;U: . . ; \3", 0 }, { /* special extended FAU Erlangen extended format */ { { 1, 2}, { 4, 2}, { 7, 2}, { 14, 2}, { 17, 2}, { 20, 2}, { 11, 1}, { 25, 4}, { 27, 1}, }, (const unsigned char *)"\2 . . ; ; : : ; \3", MBG_EXTENDED }, { /* special extended FAU Erlangen GPS format */ { { 1, 2}, { 4, 2}, { 7, 2}, { 14, 2}, { 17, 2}, { 20, 2}, { 11, 1}, { 32, 7}, { 35, 1}, { 25, 2}, { 28, 2}, { 24, 1} }, (const unsigned char *)"\2 . . ; ; : : ; : ; ; . . ", 0 }};static u_long cvt_meinberg P((unsigned char *, int, struct format *, clocktime_t *, void *));static u_long cvt_mgps P((unsigned char *, int, struct format *, clocktime_t *, void *));static u_long mbg_input P((parse_t *, unsigned int, timestamp_t *));static u_long gps_input P((parse_t *, unsigned int, timestamp_t *));struct msg_buf{ unsigned short len; /* len to fill */ unsigned short phase; /* current input phase */};#define MBG_NONE 0 /* no data input */#define MBG_HEADER 1 /* receiving header */#define MBG_DATA 2 /* receiving data */#define MBG_STRING 3 /* receiving standard data message */ clockformat_t clock_meinberg[] ={ { mbg_input, /* normal input handling */ cvt_meinberg, /* Meinberg conversion */ pps_one, /* easy PPS monitoring */ 0, /* conversion configuration */ "Meinberg Standard", /* Meinberg simple format - beware */ 32, /* string buffer */ 0 /* no private data (complete pakets) */ }, { mbg_input, /* normal input handling */ cvt_meinberg, /* Meinberg conversion */ pps_one, /* easy PPS monitoring */ 0, /* conversion configuration */ "Meinberg Extended", /* Meinberg enhanced format */ 32, /* string buffer */ 0 /* no private data (complete pakets) */ }, { gps_input, /* no input handling */ cvt_mgps, /* Meinberg GPS166 conversion */ pps_one, /* easy PPS monitoring */ (void *)&meinberg_fmt[2], /* conversion configuration */ "Meinberg GPS Extended", /* Meinberg FAU GPS format */ 512, /* string buffer */ sizeof(struct msg_buf) /* no private data (complete pakets) */ }};/* * cvt_meinberg * * convert simple type format */static u_longcvt_meinberg( unsigned char *buffer, int size, struct format *unused, clocktime_t *clock_time, void *local ){ struct format *format; /* * select automagically correct data format */ if (Strok(buffer, meinberg_fmt[0].fixed_string)) { format = &meinberg_fmt[0]; } else { if (Strok(buffer, meinberg_fmt[1].fixed_string)) { format = &meinberg_fmt[1]; } else { return CVT_FAIL|CVT_BADFMT; } } /* * collect data */ if (Stoi(&buffer[format->field_offsets[O_DAY].offset], &clock_time->day, format->field_offsets[O_DAY].length) || Stoi(&buffer[format->field_offsets[O_MONTH].offset], &clock_time->month, format->field_offsets[O_MONTH].length) || Stoi(&buffer[format->field_offsets[O_YEAR].offset], &clock_time->year, format->field_offsets[O_YEAR].length) || Stoi(&buffer[format->field_offsets[O_HOUR].offset], &clock_time->hour, format->field_offsets[O_HOUR].length) || Stoi(&buffer[format->field_offsets[O_MIN].offset], &clock_time->minute, format->field_offsets[O_MIN].length) || Stoi(&buffer[format->field_offsets[O_SEC].offset], &clock_time->second, format->field_offsets[O_SEC].length)) { return CVT_FAIL|CVT_BADFMT; } else { unsigned char *f = &buffer[format->field_offsets[O_FLAGS].offset]; clock_time->usecond = 0; clock_time->flags = PARSEB_S_LEAP; if (clock_time->second == 60) clock_time->flags |= PARSEB_LEAPSECOND; /* * in the extended timecode format we have also the * indication that the timecode is in UTC * for compatibilty reasons we start at the USUAL * offset (POWERUP flag) and know that the UTC indication * is the character before the powerup flag */ if ((format->flags & MBG_EXTENDED) && (f[-1] == 'U')) { /* * timecode is in UTC */ clock_time->utcoffset = 0; /* UTC */ clock_time->flags |= PARSEB_UTC; } else { /* * only calculate UTC offset if MET/MED is in time code * or we have the old time code format, where we do not * know whether it is UTC time or MET/MED * pray that nobody switches to UTC in the *old* standard time code * ROMS !!!! The new ROMS have 'U' at the ZONE field - good. */ switch (buffer[format->field_offsets[O_ZONE].offset]) { case ' ': clock_time->utcoffset = -1*60*60; /* MET */ break; case 'S': clock_time->utcoffset = -2*60*60; /* MED */ break; case 'U': /* * timecode is in UTC */ clock_time->utcoffset = 0; /* UTC */ clock_time->flags |= PARSEB_UTC; break; default: return CVT_FAIL|CVT_BADFMT; } } /* * gather status flags */ if (buffer[format->field_offsets[O_ZONE].offset] == 'S') clock_time->flags |= PARSEB_DST; if (f[0] == '#') clock_time->flags |= PARSEB_POWERUP; if (f[1] == '*') clock_time->flags |= PARSEB_NOSYNC; if (f[3] == '!') clock_time->flags |= PARSEB_ANNOUNCE; /* * oncoming leap second * 'a' code not confirmed - earth is not * expected to speed up
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -