2 * refclock_jjy - clock driver for JJY receivers
5 /**********************************************************************/
7 /* Copyright (C) 2001-2004, Takao Abe. All rights reserved. */
9 /* Permission to use, copy, modify, and distribute this software */
10 /* and its documentation for any purpose is hereby granted */
11 /* without fee, provided that the following conditions are met: */
13 /* One retains the entire copyright notice properly, and both the */
14 /* copyright notice and this license. in the documentation and/or */
15 /* other materials provided with the distribution. */
17 /* This software and the name of the author must not be used to */
18 /* endorse or promote products derived from this software without */
19 /* prior written permission. */
21 /* THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESSED OR IMPLIED */
22 /* WARRANTIES OF ANY KIND, INCLUDING, BUT NOT LIMITED TO, THE */
23 /* IMPLIED WARRANTIES OF MERCHANTABLILITY AND FITNESS FOR A */
24 /* PARTICULAR PURPOSE. */
25 /* IN NO EVENT SHALL THE AUTHOR TAKAO ABE BE LIABLE FOR ANY DIRECT, */
26 /* INDIRECT, GENERAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
27 /* ( INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE */
28 /* GOODS OR SERVICES; LOSS OF USE, DATA OR PROFITS; OR BUSINESS */
29 /* INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, */
30 /* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ( INCLUDING */
31 /* NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF */
32 /* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
34 /* This driver is developed in my private time, and is opened as */
35 /* voluntary contributions for the NTP. */
36 /* The manufacturer of the JJY receiver has not participated in */
37 /* a development of this driver. */
38 /* The manufacturer does not warrant anything about this driver, */
39 /* and is not liable for anything about this driver. */
41 /**********************************************************************/
43 /* Author Takao Abe */
44 /* Email abetakao@bea.hi-ho.ne.jp */
45 /* Homepage http://www.bea.hi-ho.ne.jp/abetakao/ */
47 /**********************************************************************/
52 /* [New] Support the Tristate Ltd. JJY receiver */
55 /* [Change] Log to clockstats even if bad reply */
56 /* [Fix] PRECISION = (-3) (about 100 ms) */
57 /* [Add] Support the C-DEX Co.Ltd. JJY receiver */
60 /* [Fix] C-DEX JST2000 ( fukusima@goto.info.waseda.ac.jp ) */
63 /* [Fix] Portability for FreeBSD ( patched by the user ) */
66 /* [Change] Command send timing for the Tristate Ltd. JJY receiver */
67 /* JJY-01 ( Firmware version 2.01 ) */
68 /* Thanks to Andy Taki for testing under FreeBSD */
71 /* [Add] Support the Echo Keisokuki LT-2000 receiver */
74 /* [Fix] C-DEX JST2000 */
75 /* Thanks to Hideo Kuramatsu for the patch */
78 /* [Add] Support the CITIZEN T.I.C JJY-200 receiver */
80 /**********************************************************************/
86 #if defined(REFCLOCK) && defined(CLOCK_JJY)
97 #include "ntp_refclock.h"
98 #include "ntp_calendar.h"
99 #include "ntp_stdlib.h"
101 /**********************************************************************/
103 /* The Tristate Ltd. JJY receiver JJY01 */
105 /* Command Response Remarks */
106 /* ------------ ---------------------- --------------------- */
107 /* date<CR><LF> YYYY/MM/DD XXX<CR><LF> */
108 /* time<CR><LF> HH:MM:SS<CR><LF> */
109 /* stim<CR><LF> HH:MM:SS<CR><LF> Reply at just second */
111 /* During synchronization after a receiver is turned on, */
112 /* It replies the past time from 2000/01/01 00:00:00. */
113 /* The function "refclock_process" checks the time and tells */
114 /* as an insanity time. */
116 /**********************************************************************/
118 /* The C-DEX Co. Ltd. JJY receiver JST2000 */
120 /* Command Response Remarks */
121 /* ------------ ---------------------- --------------------- */
122 /* <ENQ>1J<ETX> <STX>JYYMMDD HHMMSSS<ETX> */
124 /**********************************************************************/
126 /* The Echo Keisokuki Co. Ltd. JJY receiver LT2000 */
128 /* Command Response Remarks */
129 /* ------------ ---------------------- --------------------- */
130 /* # Mode 1 (Request&Send) */
131 /* T YYMMDDWHHMMSS<BCC1><BCC2><CR> */
132 /* C Mode 2 (Continuous) */
133 /* YYMMDDWHHMMSS<ST1><ST2><ST3><ST4><CR> */
134 /* <SUB> Second signal */
136 /**********************************************************************/
138 /* The CITIZEN T.I.C CO., LTD. JJY receiver JJY200 */
140 /* Command Response Remarks */
141 /* ------------ ---------------------- --------------------- */
142 /* 'XX YY/MM/DD W HH:MM:SS<CR> */
144 /* W: 0(Monday)-6(Sunday) */
146 /**********************************************************************/
149 * Interface definitions
151 #define DEVICE "/dev/jjy%d" /* device name and unit */
152 #define SPEED232 B9600 /* uart speed (9600 baud) */
153 #define SPEED232_TRISTATE_JJY01 B9600 /* UART speed (9600 baud) */
154 #define SPEED232_CDEX_JST2000 B9600 /* UART speed (9600 baud) */
155 #define SPEED232_ECHOKEISOKUKI_LT2000 B9600 /* UART speed (9600 baud) */
156 #define SPEED232_CITIZENTIC_JJY200 B4800 /* UART speed (4800 baud) */
157 #define REFID "JJY" /* reference ID */
158 #define DESCRIPTION "JJY Receiver"
159 #define PRECISION (-3) /* precision assumed (about 100 ms) */
162 * JJY unit control structure
165 char unittype ; /* UNITTYPE_XXXXXXXXXX */
166 short operationmode ; /* Echo Keisokuki LT-2000 : 1 or 2 */
168 short linediscipline ; /* LDISC_CLK or LDISC_RAW */
169 char bPollFlag ; /* Set by jjy_pool and Reset by jjy_receive */
172 int year, month, day, hour, minute, second, msecond ;
174 #define MAX_LINECOUNT 8
175 #define MAX_RAWBUF 64
177 int charexpect [ MAX_LINECOUNT ] ;
179 char rawbuf [ MAX_RAWBUF ] ;
182 #define UNITTYPE_TRISTATE_JJY01 1
183 #define UNITTYPE_CDEX_JST2000 2
184 #define UNITTYPE_ECHOKEISOKUKI_LT2000 3
185 #define UNITTYPE_CITIZENTIC_JJY200 4
188 * Function prototypes
190 static int jjy_start P((int, struct peer *));
191 static void jjy_shutdown P((int, struct peer *));
192 static void jjy_poll P((int, struct peer *));
193 static void jjy_poll_tristate_jjy01 P((int, struct peer *));
194 static void jjy_poll_cdex_jst2000 P((int, struct peer *));
195 static void jjy_poll_echokeisokuki_lt2000 P((int, struct peer *));
196 static void jjy_poll_citizentic_jjy200 P((int, struct peer *));
197 static void jjy_receive P((struct recvbuf *));
198 static int jjy_receive_tristate_jjy01 P((struct recvbuf *));
199 static int jjy_receive_cdex_jst2000 P((struct recvbuf *));
200 static int jjy_receive_echokeisokuki_lt2000 P((struct recvbuf *));
201 static int jjy_receive_citizentic_jjy200 P((struct recvbuf *));
206 struct refclock refclock_jjy = {
207 jjy_start, /* start up driver */
208 jjy_shutdown, /* shutdown driver */
209 jjy_poll, /* transmit poll message */
210 noentry, /* not used */
211 noentry, /* not used */
212 noentry, /* not used */
213 NOFLAGS /* not used */
217 * Start up driver return code
219 #define RC_START_SUCCESS 1
220 #define RC_START_ERROR 0
223 * Local constants definition
226 #define MAX_LOGTEXT 64
229 /**************************************************************************************************/
230 /* jjy_start - open the devices and initialize data for processing */
231 /**************************************************************************************************/
233 jjy_start ( int unit, struct peer *peer )
237 struct refclockproc *pp ;
245 printf ( "jjy_start (refclock_jjy.c) : %s mode=%d ", ntoa(&peer->srcadr), peer->ttl ) ;
246 printf ( DEVICE, unit ) ;
253 if ( ! ( pDeviceName = (char*) emalloc ( strlen(DEVICE) + 10 ) ) ) {
254 return RC_START_ERROR ;
256 sprintf ( pDeviceName, DEVICE, unit ) ;
259 * peer->ttl is a mode number specified by "127.127.40.X mode N" in the ntp.conf
261 switch ( peer->ttl ) {
264 iDiscipline = LDISC_CLK ;
265 iSpeed232 = SPEED232_TRISTATE_JJY01 ;
268 iDiscipline = LDISC_RAW ;
269 iSpeed232 = SPEED232_CDEX_JST2000 ;
272 iDiscipline = LDISC_CLK ;
273 iSpeed232 = SPEED232_ECHOKEISOKUKI_LT2000 ;
276 iDiscipline = LDISC_CLK ;
277 iSpeed232 = SPEED232_CITIZENTIC_JJY200 ;
280 msyslog ( LOG_ERR, "JJY receiver [ %s mode %d ] : Unsupported mode",
281 ntoa(&peer->srcadr), peer->ttl ) ;
282 free ( (void*) pDeviceName ) ;
283 return RC_START_ERROR ;
286 if ( ! ( fd = refclock_open ( pDeviceName, iSpeed232, iDiscipline ) ) ) {
287 free ( (void*) pDeviceName ) ;
288 return RC_START_ERROR ;
290 free ( (void*) pDeviceName ) ;
293 * Allocate and initialize unit structure
295 if ( ! ( up = (struct jjyunit *) emalloc (sizeof(struct jjyunit)) ) ) {
297 return RC_START_ERROR ;
300 memset ( (char*)up, 0, sizeof(struct jjyunit) ) ;
301 up->linediscipline = iDiscipline ;
304 * peer->ttl is a mode number specified by "127.127.40.X mode N" in the ntp.conf
306 switch ( peer->ttl ) {
309 * The mode 0 is a default clock type at this time.
310 * But this will be change to auto-detect mode in the future.
313 up->unittype = UNITTYPE_TRISTATE_JJY01 ;
316 up->charexpect[0] = 14 ; /* YYYY/MM/DD WWW<CR><LF> */
317 up->charexpect[1] = 8 ; /* HH:MM:SS<CR><LF> */
320 up->unittype = UNITTYPE_CDEX_JST2000 ;
322 up->charexpect[0] = 15 ; /* <STX>JYYMMDD HHMMSSS<ETX> */
325 up->unittype = UNITTYPE_ECHOKEISOKUKI_LT2000 ;
326 up->operationmode = 2 ; /* Mode 2 : Continuous mode */
328 switch ( up->operationmode ) {
330 up->charexpect[0] = 15 ; /* YYMMDDWHHMMSS<BCC1><BCC2><CR> */
333 up->charexpect[0] = 17 ; /* YYMMDDWHHMMSS<ST1><ST2><ST3><ST4><CR> */
338 up->unittype = UNITTYPE_CITIZENTIC_JJY200 ;
340 up->charexpect[0] = 23 ; /* 'XX YY/MM/DD W HH:MM:SS<CR> */
343 msyslog ( LOG_ERR, "JJY receiver [ %s mode %d ] : Unsupported mode",
344 ntoa(&peer->srcadr), peer->ttl ) ;
346 free ( (void*) up ) ;
347 return RC_START_ERROR ;
351 pp->unitptr = (caddr_t) up ;
352 pp->io.clock_recv = jjy_receive ;
353 pp->io.srcclock = (caddr_t) peer ;
356 if ( ! io_addclock(&pp->io) ) {
358 free ( (void*) up ) ;
359 return RC_START_ERROR ;
363 * Initialize miscellaneous variables
365 peer->precision = PRECISION ;
367 pp->clockdesc = DESCRIPTION ;
368 memcpy ( (char*)&pp->refid, REFID, strlen(REFID) ) ;
370 return RC_START_SUCCESS ;
375 /**************************************************************************************************/
376 /* jjy_shutdown - shutdown the clock */
377 /**************************************************************************************************/
379 jjy_shutdown ( int unit, struct peer *peer )
383 struct refclockproc *pp;
386 up = (struct jjyunit *) pp->unitptr ;
387 io_closeclock ( &pp->io ) ;
388 free ( (void*) up ) ;
393 /**************************************************************************************************/
394 /* jjy_receive - receive data from the serial interface */
395 /**************************************************************************************************/
397 jjy_receive ( struct recvbuf *rbufp )
401 struct refclockproc *pp ;
404 l_fp tRecvTimestamp; /* arrival timestamp */
406 char sLogText [ MAX_LOGTEXT ] ;
410 * Initialize pointers and read the timecode and timestamp
412 peer = (struct peer *) rbufp->recv_srcclock ;
414 up = (struct jjyunit *) pp->unitptr ;
417 * Get next input line
419 pp->lencode = refclock_gtlin ( rbufp, pp->a_lastcode, BMAX, &tRecvTimestamp ) ;
421 if ( up->linediscipline == LDISC_RAW ) {
423 * The reply with <STX> and <ETX> may give a blank line
425 if ( pp->lencode == 0 && up->charcount == 0 ) return ;
427 * Copy received charaters to temporary buffer
429 for ( i = 0 ; i < pp->lencode && up->charcount < MAX_RAWBUF - 2 ; i ++ , up->charcount ++ ) {
430 up->rawbuf[up->charcount] = pp->a_lastcode[i] ;
432 while ( up->charcount > 0 && up->rawbuf[0] < ' ' ) {
433 for ( i = 0 ; i < up->charcount - 1 ; i ++ ) up->rawbuf[i] = up->rawbuf[i+1] ;
437 for ( i = 0 ; i < up->charcount ; i ++ ) {
438 if ( up->rawbuf[i] < ' ' ) {
443 if ( pp->lencode > 0 && up->linecount < up->lineexpect ) {
444 if ( bCntrlChar == 0 && up->charcount < up->charexpect[up->linecount] ) return ;
446 up->rawbuf[up->charcount] = 0 ;
449 * The reply with <CR><LF> gives a blank line
451 if ( pp->lencode == 0 ) return ;
454 * We get down to business
457 pp->lastrec = tRecvTimestamp ;
461 if ( up->lineerror != 0 ) return ;
463 switch ( up->unittype ) {
465 case UNITTYPE_TRISTATE_JJY01 :
466 rc = jjy_receive_tristate_jjy01 ( rbufp ) ;
469 case UNITTYPE_CDEX_JST2000 :
470 rc = jjy_receive_cdex_jst2000 ( rbufp ) ;
473 case UNITTYPE_ECHOKEISOKUKI_LT2000 :
474 rc = jjy_receive_echokeisokuki_lt2000 ( rbufp ) ;
477 case UNITTYPE_CITIZENTIC_JJY200 :
478 rc = jjy_receive_citizentic_jjy200 ( rbufp ) ;
487 if ( up->linediscipline == LDISC_RAW ) {
488 if ( up->linecount <= up->lineexpect && up->charcount > up->charexpect[up->linecount-1] ) {
489 for ( i = 0 ; i < up->charcount - up->charexpect[up->linecount-1] ; i ++ ) {
490 up->rawbuf[i] = up->rawbuf[i+up->charexpect[up->linecount-1]] ;
492 up->charcount -= up->charexpect[up->linecount-1] ;
498 if ( rc == 0 ) return ;
502 if ( up->lineerror != 0 ) {
503 refclock_report ( peer, CEVNT_BADREPLY ) ;
504 strcpy ( sLogText, "BAD REPLY [" ) ;
505 if ( up->linediscipline == LDISC_RAW ) {
506 strncat ( sLogText, up->rawbuf, MAX_LOGTEXT - strlen ( sLogText ) - 1 ) ;
508 strncat ( sLogText, pp->a_lastcode, MAX_LOGTEXT - strlen ( sLogText ) - 1 ) ;
510 sLogText[MAX_LOGTEXT-1] = 0 ;
511 if ( strlen ( sLogText ) < MAX_LOGTEXT - 2 ) strcat ( sLogText, "]" ) ;
512 record_clock_stats ( &peer->srcadr, sLogText ) ;
516 pp->year = up->year ;
517 pp->day = ymd2yd ( up->year, up->month, up->day ) ;
518 pp->hour = up->hour ;
519 pp->minute = up->minute ;
520 pp->second = up->second ;
521 pp->nsec = up->msecond * 1000000;
527 if ( pp->hour < 0 ) {
532 pp->day = ymd2yd ( pp->year, 12, 31 ) ;
537 printf ( "jjy_receive (refclock_jjy.c) : %04d/%02d/%02d %02d:%02d:%02d.%1d JST ",
538 up->year, up->month, up->day, up->hour, up->minute, up->second, up->msecond/100 ) ;
539 printf ( "( %04d/%03d %02d:%02d:%02d.%1d UTC )\n",
540 pp->year, pp->day, pp->hour, pp->minute, pp->second, (int)(pp->nsec/100000000) ) ;
545 * Process the new sample in the median filter and determine the
546 * timecode timestamp.
549 sprintf ( sLogText, "%04d/%02d/%02d %02d:%02d:%02d.%1d JST",
550 up->year, up->month, up->day, up->hour, up->minute, up->second, up->msecond/100 ) ;
551 record_clock_stats ( &peer->srcadr, sLogText ) ;
553 if ( ! refclock_process ( pp ) ) {
554 refclock_report(peer, CEVNT_BADTIME);
558 pp->lastref = pp->lastrec;
559 refclock_receive(peer);
563 /**************************************************************************************************/
566 jjy_receive_tristate_jjy01 ( struct recvbuf *rbufp )
569 static char *sFunctionName = "jjy_receive_tristate_jjy01" ;
572 struct refclockproc *pp ;
580 * Initialize pointers and read the timecode and timestamp
582 peer = (struct peer *) rbufp->recv_srcclock ;
584 up = (struct jjyunit *) pp->unitptr ;
586 if ( up->linediscipline == LDISC_RAW ) {
588 iLen = up->charcount ;
590 pBuf = pp->a_lastcode ;
594 switch ( up->linecount ) {
596 case 1 : /* YYYY/MM/DD WWW */
601 printf ( "%s (refclock_jjy.c) : Reply length error ( up->linecount=%d iLen=%d )\n", sFunctionName, up->linecount, iLen ) ;
607 rc = sscanf ( pBuf, "%4d/%2d/%2d", &up->year, &up->month, &up->day ) ;
608 if ( rc != 3 || up->year < 2000 || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31 ) {
611 printf ( "%s (refclock_jjy.c) : Date error ( up->linecount=%d )\n", sFunctionName, up->linecount ) ;
618 /*** Start of modification on 2004/10/31 */
620 * Following codes are moved from the function jjy_poll_tristate_jjy01 in this source.
621 * The Tristate JJY-01 ( Firmware version 1.01 ) accepts "time" and "stim" commands without any delay.
622 * But the JJY-01 ( Firmware version 2.01 ) does not accept these commands continuously,
623 * so this driver issues the second command "stim" after the reply of the first command "date".
627 * Send "stim<CR><LF>" or "time<CR><LF>" command
631 if ( up->version >= 100 ) {
634 printf ( "%s (refclock_jjy.c) : send 'stim<CR><LF>'\n", sFunctionName ) ;
637 if ( write ( pp->io.fd, "stim\r\n",6 ) != 6 ) {
638 refclock_report ( peer, CEVNT_FAULT ) ;
643 printf ( "%s (refclock_jjy.c) : send 'time<CR><LF>'\n", sFunctionName ) ;
646 if ( write ( pp->io.fd, "time\r\n",6 ) != 6 ) {
647 refclock_report ( peer, CEVNT_FAULT ) ;
650 /*** End of modification ***/
654 case 2 : /* HH:MM:SS */
659 printf ( "%s (refclock_jjy.c) : Reply length error ( up->linecount=%d iLen=%d )\n", sFunctionName, up->linecount, iLen ) ;
665 rc = sscanf ( pBuf, "%2d:%2d:%2d", &up->hour, &up->minute, &up->second ) ;
666 if ( rc != 3 || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
669 printf ( "%s (refclock_jjy.c) : Time error ( up->linecount=%d )\n", sFunctionName, up->linecount ) ;
676 if ( up->hour == 0 && up->minute == 0 && up->second <= 2 ) {
678 * The command "date" and "time" ( or "stim" ) were sent to the JJY receiver continuously.
679 * But the JJY receiver replies a date and time separately.
680 * Just after midnight transitions, we ignore this time.
686 default : /* Unexpected reply */
697 /**************************************************************************************************/
700 jjy_receive_cdex_jst2000 ( struct recvbuf *rbufp )
703 static char *sFunctionName = "jjy_receive_cdex_jst2000" ;
706 struct refclockproc *pp ;
714 * Initialize pointers and read the timecode and timestamp
716 peer = (struct peer *) rbufp->recv_srcclock ;
718 up = (struct jjyunit *) pp->unitptr ;
720 if ( up->linediscipline == LDISC_RAW ) {
722 iLen = up->charcount ;
724 pBuf = pp->a_lastcode ;
728 switch ( up->linecount ) {
730 case 1 : /* JYYMMDD HHMMSSS */
735 printf ( "%s (refclock_jjy.c) : Reply length error ( iLen=%d )\n", sFunctionName, iLen ) ;
741 rc = sscanf ( pBuf, "J%2d%2d%2d%*1d%2d%2d%2d%1d",
742 &up->year, &up->month, &up->day, &up->hour, &up->minute, &up->second, &up->msecond ) ;
743 if ( rc != 7 || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31
744 || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
747 printf ( "%s (refclock_jjy.c) : Time error (rc=%d) [ %02d %02d %02d * %02d %02d %02d.%1d ]\n", sFunctionName,
748 rc, up->year, up->month, up->day, up->hour, up->minute, up->second, up->msecond ) ;
758 default : /* Unexpected reply */
769 /**************************************************************************************************/
772 jjy_receive_echokeisokuki_lt2000 ( struct recvbuf *rbufp )
775 static char *sFunctionName = "jjy_receive_echokeisokuki_lt2000" ;
778 struct refclockproc *pp ;
784 int i, ibcc, ibcc1, ibcc2 ;
787 * Initialize pointers and read the timecode and timestamp
789 peer = (struct peer *) rbufp->recv_srcclock ;
791 up = (struct jjyunit *) pp->unitptr ;
793 if ( up->linediscipline == LDISC_RAW ) {
795 iLen = up->charcount ;
797 pBuf = pp->a_lastcode ;
801 switch ( up->linecount ) {
803 case 1 : /* YYMMDDWHHMMSS<BCC1><BCC2> or YYMMDDWHHMMSS<ST1><ST2><ST3><ST4> */
805 if ( ( up->operationmode == 1 && iLen != 15 ) || ( up->operationmode == 2 && iLen != 17 ) ) {
808 printf ( "%s (refclock_jjy.c) : Reply length error ( iLen=%d )\n", sFunctionName, iLen ) ;
811 if ( up->operationmode == 1 ) {
814 printf ( "%s (refclock_jjy.c) : send '#'\n", sFunctionName ) ;
817 if ( write ( pp->io.fd, "#",1 ) != 1 ) {
818 refclock_report ( peer, CEVNT_FAULT ) ;
825 if ( up->operationmode == 1 ) {
827 for ( i = ibcc = 0 ; i < 13 ; i ++ ) ibcc ^= pBuf[i] ;
828 ibcc1 = 0x30 | ( ( ibcc >> 4 ) & 0xF ) ;
829 ibcc2 = 0x30 | ( ( ibcc ) & 0xF ) ;
830 if ( pBuf[13] != ibcc1 || pBuf[14] != ibcc2 ) {
833 printf ( "%s (refclock_jjy.c) : BCC error ( Recv=%02X,%02X / Calc=%02X,%02X)\n", sFunctionName, pBuf[13]&0xFF, pBuf[14]&0xFF, ibcc1, ibcc2 ) ;
842 rc = sscanf ( pBuf, "%2d%2d%2d%*1d%2d%2d%2d",
843 &up->year, &up->month, &up->day, &up->hour, &up->minute, &up->second ) ;
844 if ( rc != 6 || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31
845 || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
848 printf ( "%s (refclock_jjy.c) : Time error (rc=%d) [ %02d %02d %02d * %02d %02d %02d ]\n", sFunctionName,
849 rc, up->year, up->month, up->day, up->hour, up->minute, up->second ) ;
858 if ( up->operationmode == 2 ) {
860 /* A time stamp comes on every 0.5 seccond in the mode 2 of the LT-2000. */
863 if ( pp->second < 0 ) {
866 if ( pp->minute < 0 ) {
869 if ( pp->hour < 0 ) {
874 pp->day = ymd2yd ( pp->year, 12, 31 ) ;
880 /* Switch from mode 2 to mode 1 in order to restraint of useless time stamp. */
883 printf ( "%s (refclock_jjy.c) : send '#'\n", sFunctionName ) ;
886 if ( write ( pp->io.fd, "#",1 ) != 1 ) {
887 refclock_report ( peer, CEVNT_FAULT ) ;
894 default : /* Unexpected reply */
898 printf ( "%s (refclock_jjy.c) : send '#'\n", sFunctionName ) ;
901 if ( write ( pp->io.fd, "#",1 ) != 1 ) {
902 refclock_report ( peer, CEVNT_FAULT ) ;
914 /**************************************************************************************************/
917 jjy_receive_citizentic_jjy200 ( struct recvbuf *rbufp )
920 static char *sFunctionName = "jjy_receive_citizentic_jjy200" ;
923 struct refclockproc *pp ;
929 char cApostrophe, sStatus[3] ;
933 * Initialize pointers and read the timecode and timestamp
935 peer = (struct peer *) rbufp->recv_srcclock ;
937 up = (struct jjyunit *) pp->unitptr ;
939 if ( up->linediscipline == LDISC_RAW ) {
941 iLen = up->charcount ;
943 pBuf = pp->a_lastcode ;
948 * JJY-200 sends a timestamp every second.
949 * So, a timestamp is ignored unless it is right after polled.
951 if ( ! up->bPollFlag ) return 0 ;
953 switch ( up->linecount ) {
955 case 1 : /* 'XX YY/MM/DD W HH:MM:SS<CR> */
960 printf ( "%s (refclock_jjy.c) : Reply length error ( iLen=%d )\n", sFunctionName, iLen ) ;
967 rc = sscanf ( pBuf, "%c%2s %2d/%2d/%2d %1d %2d:%2d:%2d",
968 &cApostrophe, sStatus,
969 &up->year, &up->month, &up->day, &iWeekday, &up->hour, &up->minute, &up->second ) ;
971 if ( rc != 9 || cApostrophe != '\'' || strcmp( sStatus, "OK" ) != 0
972 || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31
974 || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
977 printf ( "%s (refclock_jjy.c) : Time error (rc=%d) [ %c %2s %02d %02d %02d %d %02d %02d %02d ]\n", sFunctionName,
978 rc, cApostrophe, sStatus, up->year, up->month, up->day, iWeekday, up->hour, up->minute, up->second ) ;
990 default : /* Unexpected reply */
1001 /**************************************************************************************************/
1002 /* jjy_poll - called by the transmit procedure */
1003 /**************************************************************************************************/
1005 jjy_poll ( int unit, struct peer *peer )
1009 struct refclockproc *pp;
1012 up = (struct jjyunit *) pp->unitptr ;
1014 if ( pp->polls > 0 && up->linecount == 0 ) {
1016 * No reply for last command
1018 refclock_report ( peer, CEVNT_TIMEOUT ) ;
1023 printf ( "jjy_poll (refclock_jjy.c) : %ld\n", pp->polls ) ;
1034 switch ( up->unittype ) {
1036 case UNITTYPE_TRISTATE_JJY01 :
1037 jjy_poll_tristate_jjy01 ( unit, peer ) ;
1040 case UNITTYPE_CDEX_JST2000 :
1041 jjy_poll_cdex_jst2000 ( unit, peer ) ;
1044 case UNITTYPE_ECHOKEISOKUKI_LT2000 :
1045 jjy_poll_echokeisokuki_lt2000 ( unit, peer ) ;
1048 case UNITTYPE_CITIZENTIC_JJY200 :
1049 jjy_poll_citizentic_jjy200 ( unit, peer ) ;
1059 /**************************************************************************************************/
1062 jjy_poll_tristate_jjy01 ( int unit, struct peer *peer )
1065 struct refclockproc *pp;
1070 * Send "date<CR><LF>" command
1075 printf ( "jjy_poll_tristate_jjy01 (refclock_jjy.c) : send 'date<CR><LF>'\n" ) ;
1079 if ( write ( pp->io.fd, "date\r\n",6 ) != 6 ) {
1080 refclock_report ( peer, CEVNT_FAULT ) ;
1085 /**************************************************************************************************/
1088 jjy_poll_cdex_jst2000 ( int unit, struct peer *peer )
1091 struct refclockproc *pp;
1096 * Send "<ENQ>1J<ETX>" command
1101 printf ( "jjy_poll_cdex_jst2000 (refclock_jjy.c) : send '<ENQ>1J<ETX>'\n" ) ;
1105 if ( write ( pp->io.fd, "\0051J\003", 4 ) != 4 ) {
1106 refclock_report ( peer, CEVNT_FAULT ) ;
1111 /**************************************************************************************************/
1114 jjy_poll_echokeisokuki_lt2000 ( int unit, struct peer *peer )
1118 struct refclockproc *pp;
1123 up = (struct jjyunit *) pp->unitptr ;
1126 * Send "T" or "C" command
1129 switch ( up->operationmode ) {
1130 case 1 : sCmd[0] = 'T' ; break ;
1131 case 2 : sCmd[0] = 'C' ; break ;
1137 printf ( "jjy_poll_echokeisokuki_lt2000 (refclock_jjy.c) : send '%s'\n", sCmd ) ;
1141 if ( write ( pp->io.fd, sCmd, 1 ) != 1 ) {
1142 refclock_report ( peer, CEVNT_FAULT ) ;
1147 /**************************************************************************************************/
1150 jjy_poll_citizentic_jjy200 ( int unit, struct peer *peer )
1153 /* Do nothing ( up->bPollFlag is set by the jjy_poll ) */
1158 int refclock_jjy_bs ;
1159 #endif /* REFCLOCK */