"Fossies" - the Fresh Open Source Software Archive

Member "ntp-4.2.8p15/ntpd/refclock_palisade.c" (23 Jun 2020, 35997 Bytes) of package /linux/misc/ntp-4.2.8p15.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "refclock_palisade.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.2.8p14_vs_4.2.8p15.

    1 /*
    2  * This software was developed by the Software and Component Technologies
    3  * group of Trimble Navigation, Ltd.
    4  *
    5  * Copyright (c) 1997, 1998, 1999, 2000  Trimble Navigation Ltd.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *    This product includes software developed by Trimble Navigation, Ltd.
   19  * 4. The name of Trimble Navigation Ltd. may not be used to endorse or
   20  *    promote products derived from this software without specific prior
   21  *    written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY TRIMBLE NAVIGATION LTD. ``AS IS'' AND
   24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26  * ARE DISCLAIMED.  IN NO EVENT SHALL TRIMBLE NAVIGATION LTD. BE LIABLE
   27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33  * SUCH DAMAGE.
   34  */
   35 
   36 /*
   37  * refclock_palisade - clock driver for the Trimble Palisade GPS
   38  * timing receiver
   39  *
   40  * For detailed information on this program, please refer to the html 
   41  * Refclock 29 page accompanying the NTP distribution.
   42  *
   43  * for questions / bugs / comments, contact:
   44  * sven_dietrich@trimble.com
   45  *
   46  * Sven-Thorsten Dietrich
   47  * 645 North Mary Avenue
   48  * Post Office Box 3642
   49  * Sunnyvale, CA 94088-3642
   50  *
   51  * Version 2.45; July 14, 1999
   52  *
   53  *
   54  *
   55  * 31/03/06: Added support for Thunderbolt GPS Disciplined Clock.
   56  *       Contact: Fernando Pablo Hauscarriaga
   57  *       E-mail: fernandoph@iar.unlp.edu.ar
   58  *       Home page: www.iar.unlp.edu.ar/~fernandoph
   59  *        Instituto Argentino de Radioastronomia
   60  *              www.iar.unlp.edu.ar
   61  *
   62  * 14/01/07: Conditinal compilation for Thunderbolt support no longer needed
   63  *       now we use mode 2 for decode thunderbolt packets.
   64  *       Fernando P. Hauscarriaga
   65  *
   66  * 30/08/09: Added support for Trimble Acutime Gold Receiver.
   67  *       Fernando P. Hauscarriaga (fernandoph@iar.unlp.edu.ar)
   68  *
   69  * 21/04/18: Added support for Resolution devices.
   70  *
   71  * 03/09/19: Added support for ACE III & Copernicus II.
   72  */
   73 
   74 #ifdef HAVE_CONFIG_H
   75 # include "config.h"
   76 #endif
   77 
   78 #if defined(REFCLOCK) && defined(CLOCK_PALISADE)
   79 
   80 #ifdef SYS_WINNT
   81 extern int async_write(int, const void *, unsigned int);
   82 #undef write
   83 #define write(fd, data, octets) async_write(fd, data, octets)
   84 #endif
   85 
   86 #include "refclock_palisade.h"
   87 
   88 #ifdef DEBUG
   89 const char * Tracking_Status[15][15] = { 
   90     { "Doing Fixes\0" }, { "Good 1SV\0" }, { "Approx. 1SV\0" },
   91     {"Need Time\0" }, { "Need INIT\0" }, { "PDOP too High\0" },
   92     { "Bad 1SV\0" }, { "0SV Usable\0" }, { "1SV Usable\0" },
   93     { "2SV Usable\0" }, { "3SV Usable\0" }, { "No Integrity\0" },
   94     { "Diff Corr\0" }, { "Overdet Clock\0" }, { "Invalid\0" } };
   95 #endif
   96 
   97 /*
   98  * Transfer vector
   99  */
  100 struct refclock refclock_palisade = {
  101     palisade_start,     /* start up driver */
  102     palisade_shutdown,  /* shut down driver */
  103     palisade_poll,      /* transmit poll message */
  104     noentry,        /* not used  */
  105     noentry,        /* initialize driver (not used) */
  106     noentry,        /* not used */
  107     NOFLAGS         /* not used */
  108 };
  109 
  110 static int decode_date(struct refclockproc *pp, const char *cp);
  111 
  112 /* Extract the clock type from the mode setting */
  113 #define CLK_TYPE(x) ((int)(((x)->ttl) & 0x7F))
  114 
  115 /* Supported clock types */
  116 #define CLK_TRIMBLE 0   /* Trimble Palisade */
  117 #define CLK_PRAECIS 1   /* Endrun Technologies Praecis */
  118 #define CLK_THUNDERBOLT 2   /* Trimble Thunderbolt GPS Receiver */
  119 #define CLK_ACUTIME     3   /* Trimble Acutime Gold */
  120 #define CLK_ACUTIMEB    4   /* Trimble Actutime Gold Port B */
  121 #define CLK_RESOLUTION  5   /* Trimble Resolution Receivers */
  122 #define CLK_ACE     6   /* Trimble ACE III */
  123 #define CLK_COPERNICUS  7   /* Trimble Copernicus II */
  124 
  125 int praecis_msg;
  126 static void praecis_parse(struct recvbuf *rbufp, struct peer *peer);
  127 
  128 /* These routines are for sending packets to the Thunderbolt receiver
  129  * They are taken from Markus Prosch
  130  */
  131 
  132 /*
  133  * sendcmd - Build data packet for sending
  134  */
  135 static void 
  136 sendcmd (
  137     struct packettx *buffer,
  138     int c
  139     )
  140 {
  141     *buffer->data = DLE;
  142     *(buffer->data + 1) = (unsigned char)c;
  143     buffer->size = 2;
  144 }
  145 
  146 /*
  147  * sendsupercmd - Build super data packet for sending
  148  */
  149 static void 
  150 sendsupercmd (
  151     struct packettx *buffer,
  152     int c1,
  153     int c2
  154     )
  155 {
  156     *buffer->data = DLE;
  157     *(buffer->data + 1) = (unsigned char)c1;
  158     *(buffer->data + 2) = (unsigned char)c2;
  159     buffer->size = 3;
  160 }
  161 
  162 /*
  163  * sendbyte -
  164  */
  165 static void 
  166 sendbyte (
  167     struct packettx *buffer,
  168     int b
  169     )
  170 {
  171     if (b == DLE)
  172         *(buffer->data+buffer->size++) = DLE;
  173     *(buffer->data+buffer->size++) = (unsigned char)b;
  174 }
  175 
  176 /*
  177  * sendint -
  178  */
  179 static void 
  180 sendint (
  181     struct packettx *buffer,
  182     int a
  183     )
  184 {
  185     sendbyte(buffer, (unsigned char)((a>>8) & 0xff));
  186     sendbyte(buffer, (unsigned char)(a & 0xff));
  187 }
  188 
  189 /*
  190  * sendetx - Send packet or super packet to the device
  191  */
  192 static int 
  193 sendetx (
  194     struct packettx *buffer,
  195     int fd
  196     )
  197 {
  198     int result;
  199     
  200     *(buffer->data+buffer->size++) = DLE;
  201     *(buffer->data+buffer->size++) = ETX;
  202     result = write(fd, buffer->data, (unsigned long)buffer->size);
  203     
  204     if (result != -1)
  205         return (result);
  206     else
  207         return (-1);
  208 }
  209 
  210 /*
  211  * init_thunderbolt - Prepares Thunderbolt receiver to be used with
  212  *            NTP (also taken from Markus Prosch).
  213  */
  214 static void
  215 init_thunderbolt (
  216     int fd
  217     )
  218 {
  219     struct packettx tx;
  220     
  221     tx.size = 0;
  222     tx.data = (u_char *) emalloc(100);
  223 
  224     /* set UTC time */
  225     sendsupercmd (&tx, 0x8E, 0xA2);
  226     sendbyte     (&tx, 0x3);
  227     sendetx      (&tx, fd);
  228     
  229     /* activate packets 0x8F-AB and 0x8F-AC */
  230     sendsupercmd (&tx, 0x8E, 0xA5);
  231     sendint      (&tx, 0x5);
  232     sendetx      (&tx, fd);
  233 
  234     free(tx.data);
  235 }
  236 
  237 /*
  238  * init_acutime - Prepares Acutime Receiver to be used with NTP
  239  */
  240 static void
  241 init_acutime (
  242     int fd
  243     )
  244 {
  245     /* Disable all outputs, Enable Event-Polling on PortA so
  246        we can ask for time packets */
  247     struct packettx tx;
  248 
  249     tx.size = 0;
  250     tx.data = (u_char *) emalloc(100);
  251 
  252     sendsupercmd(&tx, 0x8E, 0xA5);
  253     sendbyte(&tx, 0x02);
  254     sendbyte(&tx, 0x00);
  255     sendbyte(&tx, 0x00);
  256     sendbyte(&tx, 0x00);
  257     sendetx(&tx, fd);
  258 
  259     free(tx.data);
  260 }
  261 
  262 /*
  263  * init_resolution - Prepares Resolution receiver to be used with NTP
  264  */
  265 static void
  266 init_resolution (
  267     int fd
  268     )
  269 {
  270     struct packettx tx;
  271     
  272     tx.size = 0;
  273     tx.data = (u_char *) emalloc(100);
  274 
  275     /* set UTC time */
  276     sendsupercmd (&tx, 0x8E, 0xA2);
  277     sendbyte     (&tx, 0x3);
  278     sendetx      (&tx, fd);
  279 
  280     /* squelch PPS output unless locked to at least one satellite */
  281     sendsupercmd (&tx, 0x8E, 0x4E);
  282     sendbyte     (&tx, 0x3);
  283     sendetx      (&tx, fd);
  284     
  285     /* activate packets 0x8F-AB and 0x8F-AC */
  286     sendsupercmd (&tx, 0x8E, 0xA5);
  287     sendint      (&tx, 0x5);
  288     sendetx      (&tx, fd);
  289 
  290     free(tx.data);
  291 }
  292 
  293 /*
  294  * palisade_start - open the devices and initialize data for processing
  295  */
  296 static int
  297 palisade_start (
  298     int unit,
  299     struct peer *peer
  300     )
  301 {
  302     struct palisade_unit *up;
  303     struct refclockproc *pp;
  304     int fd;
  305     char gpsdev[20];
  306     struct termios tio;
  307     u_int speed;
  308 
  309     snprintf(gpsdev, sizeof(gpsdev), DEVICE, unit);
  310 
  311     /*
  312      * Open serial port. 
  313      */
  314     speed = (CLK_TYPE(peer) == CLK_COPERNICUS) ? SPEED232COP : SPEED232;
  315     fd = refclock_open(gpsdev, speed, LDISC_RAW);
  316     if (fd <= 0) {
  317 #ifdef DEBUG
  318         printf("Palisade(%d) start: open %s failed\n", unit, gpsdev);
  319 #endif
  320         return 0;
  321     }
  322 
  323     msyslog(LOG_NOTICE, "Palisade(%d) fd: %d dev: %s", unit, fd,
  324         gpsdev);
  325 
  326     if (tcgetattr(fd, &tio) < 0) {
  327         msyslog(LOG_ERR, 
  328             "Palisade(%d) tcgetattr(fd, &tio): %m",unit);
  329 #ifdef DEBUG
  330         printf("Palisade(%d) tcgetattr(fd, &tio)\n",unit);
  331 #endif
  332         close(fd);
  333         return (0);
  334     }
  335 
  336     tio.c_cflag |= (PARENB|PARODD);
  337     tio.c_iflag &= ~ICRNL;
  338 
  339     /*
  340      * Allocate and initialize unit structure
  341      */
  342     up = emalloc_zero(sizeof(*up));
  343 
  344     up->type = CLK_TYPE(peer);
  345     switch (up->type) {
  346         case CLK_TRIMBLE:
  347         /* Normal mode, do nothing */
  348         break;
  349         case CLK_PRAECIS:
  350         msyslog(LOG_NOTICE, "Palisade(%d) Praecis mode enabled"
  351             ,unit);
  352         break;
  353         case CLK_THUNDERBOLT:
  354         msyslog(LOG_NOTICE, "Palisade(%d) Thunderbolt mode enabled"
  355             ,unit);
  356         tio.c_cflag = (CS8|CLOCAL|CREAD);
  357         break;
  358         case CLK_ACUTIME:
  359         msyslog(LOG_NOTICE, "Palisade(%d) Acutime Gold mode enabled"
  360             ,unit);
  361         break;
  362         case CLK_RESOLUTION:
  363         msyslog(LOG_NOTICE, "Palisade(%d) Resolution mode enabled"
  364             ,unit);
  365         tio.c_cflag = (CS8|CLOCAL|CREAD|PARENB|PARODD);
  366         break;
  367         case CLK_ACE:
  368         msyslog(LOG_NOTICE, "Palisade(%d) ACE III mode enabled"
  369             ,unit);
  370         tio.c_cflag = (CS8|CLOCAL|CREAD|PARENB|PARODD);
  371         break;
  372         case CLK_COPERNICUS:
  373         msyslog(LOG_NOTICE, "Palisade(%d) Copernicus II mode enabled"
  374             ,unit);
  375         /* Must use ORing/ANDing to set/clear c_cflag bits otherwise
  376            CBAUD gets set back to 0. This ought to be an issue for
  377            the other modes above but it seems that the baud rate
  378            defaults to 9600 if CBAUD gets set to 0.                 */
  379         tio.c_cflag &= ~(PARENB|PARODD);
  380         break;
  381         default:
  382         msyslog(LOG_NOTICE, "Palisade(%d) mode unknown",unit);
  383         break;
  384     }
  385     if (tcsetattr(fd, TCSANOW, &tio) == -1) {
  386         msyslog(LOG_ERR, "Palisade(%d) tcsetattr(fd, &tio): %m",unit);
  387 #ifdef DEBUG
  388         printf("Palisade(%d) tcsetattr(fd, &tio)\n",unit);
  389 #endif
  390         close(fd);
  391         free(up);
  392         return 0;
  393     }
  394 
  395     pp = peer->procptr;
  396     pp->io.clock_recv = palisade_io;
  397     pp->io.srcclock = peer;
  398     pp->io.datalen = 0;
  399     pp->io.fd = fd;
  400     if (!io_addclock(&pp->io)) {
  401 #ifdef DEBUG
  402         printf("Palisade(%d) io_addclock\n",unit);
  403 #endif
  404         close(fd);
  405         pp->io.fd = -1;
  406         free(up);
  407         return (0);
  408     }
  409 
  410     /*
  411      * Initialize miscellaneous variables
  412      */
  413     pp->unitptr = up;
  414     pp->clockdesc = DESCRIPTION;
  415 
  416     peer->precision = PRECISION;
  417     peer->sstclktype = CTL_SST_TS_UHF;
  418     peer->minpoll = TRMB_MINPOLL;
  419     peer->maxpoll = TRMB_MAXPOLL;
  420     memcpy((char *)&pp->refid, REFID, 4);
  421     
  422     up->leap_status = 0;
  423     up->unit = (short) unit;
  424     up->rpt_status = TSIP_PARSED_EMPTY;
  425     up->rpt_cnt = 0;
  426 
  427     if (up->type == CLK_THUNDERBOLT)
  428         init_thunderbolt(fd);
  429     if (up->type == CLK_ACUTIME)
  430         init_acutime(fd);
  431     if (up->type == CLK_RESOLUTION)
  432         init_resolution(fd);
  433 
  434     return 1;
  435 }
  436 
  437 
  438 /*
  439  * palisade_shutdown - shut down the clock
  440  */
  441 static void
  442 palisade_shutdown (
  443     int unit,
  444     struct peer *peer
  445     )
  446 {
  447     struct palisade_unit *up;
  448     struct refclockproc *pp;
  449     pp = peer->procptr;
  450     up = pp->unitptr;
  451     if (-1 != pp->io.fd)
  452         io_closeclock(&pp->io);
  453     if (NULL != up)
  454         free(up);
  455 }
  456 
  457 
  458 /* 
  459  * unpack helpers
  460  */
  461 
  462 static inline uint8_t
  463 get_u8(
  464     const char *cp)
  465 {
  466     return ((const u_char*)cp)[0];
  467 }
  468 
  469 static inline uint16_t
  470 get_u16(
  471     const char *cp)
  472 {
  473     return ((uint16_t)get_u8(cp) << 8) | get_u8(cp + 1);
  474 }
  475 
  476 /*
  477  * unpack & fix date (the receiver provides a valid time for 1024 weeks
  478  * after 1997-12-14 and therefore folds back in 2017, 2037,...)
  479  *
  480  * Returns -1 on error, day-of-month + (month * 32) othertwise.
  481  */
  482 int
  483 decode_date(
  484     struct refclockproc *pp,
  485     const char          *cp)
  486 {
  487     static int32_t  s_baseday = 0;
  488     
  489     struct calendar jd;
  490     int32_t         rd;
  491 
  492     if (0 == s_baseday) {
  493         if (!ntpcal_get_build_date(&jd)) {
  494             jd.year     = 2015;
  495             jd.month    = 1;
  496             jd.monthday = 1;
  497         }
  498         s_baseday = ntpcal_date_to_rd(&jd);
  499     }
  500 
  501     /* get date fields and convert to RDN */
  502     jd.monthday = get_u8 (  cp  );
  503     jd.month    = get_u8 (cp + 1);
  504     jd.year     = get_u16(cp + 2);
  505     rd = ntpcal_date_to_rd(&jd);
  506 
  507     /* for the paranoid: do reverse calculation and cross-check */
  508     ntpcal_rd_to_date(&jd, rd);
  509     if ((jd.monthday != get_u8 (  cp  )) ||
  510         (jd.month    != get_u8 (cp + 1)) ||
  511         (jd.year     != get_u16(cp + 2))  )
  512         return - 1;
  513     
  514     /* calculate cycle shift to base day and calculate re-folded
  515      * date
  516      *
  517      * One could do a proper modulo calculation here, but a counting
  518      * loop is probably faster for the next few rollovers...
  519      */
  520     while (rd < s_baseday)
  521         rd += 7*1024;
  522     ntpcal_rd_to_date(&jd, rd);
  523 
  524     /* fill refclock structure & indicate success */
  525     pp->day  = jd.yearday;
  526     pp->year = jd.year; 
  527     return ((int)jd.month << 5) | jd.monthday;
  528 }
  529     
  530 
  531 /* 
  532  * TSIP_decode - decode the TSIP data packets 
  533  */
  534 int
  535 TSIP_decode (
  536     struct peer *peer
  537     )
  538 {
  539     int st;
  540     long   secint;
  541     double secs;
  542     double secfrac;
  543     unsigned short event = 0;
  544     int mmday;
  545     long tow;
  546     uint16_t wn;
  547     int GPS_UTC_Offset;
  548     
  549     struct palisade_unit *up;
  550     struct refclockproc *pp;
  551 
  552     pp = peer->procptr;
  553     up = pp->unitptr;
  554 
  555     /*
  556      * Check the time packet, decode its contents. 
  557      * If the timecode has invalid length or is not in
  558      * proper format, declare bad format and exit.
  559      */
  560 
  561     if ((up->type != CLK_THUNDERBOLT) &&
  562         (up->type != CLK_ACUTIME    ) &&
  563         (up->type != CLK_RESOLUTION ) &&
  564         (up->type != CLK_ACE        ) &&
  565         (up->type != CLK_COPERNICUS )   )
  566     {
  567         if ((up->rpt_buf[0] == (char) 0x41) ||
  568             (up->rpt_buf[0] == (char) 0x46) ||
  569             (up->rpt_buf[0] == (char) 0x54) ||
  570             (up->rpt_buf[0] == (char) 0x4B) ||
  571             (up->rpt_buf[0] == (char) 0x6D)) {
  572 
  573             /* standard time packet - GPS time and GPS week number */
  574 #ifdef DEBUG
  575             printf("Palisade Port B packets detected. Connect to Port A\n");
  576 #endif
  577 
  578             return 0;   
  579         }
  580     }
  581 
  582     /*
  583      * We cast both to u_char as 0x8f uses the sign bit on a char
  584      */
  585     if ((u_char) up->rpt_buf[0] == (u_char) 0x8f) {
  586         /* 
  587          * Superpackets
  588          */
  589         event = (unsigned short) (getint((u_char *) &mb(1)) & 0xffff);
  590         if (!((pp->sloppyclockflag & CLK_FLAG2) || event)) 
  591             /* Ignore Packet */
  592             return 0;      
  593     
  594         switch (mb(0) & 0xff) {
  595 
  596             case PACKET_8F0B: 
  597 
  598             if (up->polled <= 0)
  599                 return 0;
  600 
  601             if (up->rpt_cnt != LENCODE_8F0B)  /* check length */
  602                 break;
  603         
  604 #ifdef DEBUG
  605             if (debug > 1) {
  606                 int ts;
  607                 double lat, lon, alt;
  608                 lat = getdbl((u_char *) &mb(42)) * R2D;
  609                 lon = getdbl((u_char *) &mb(50)) * R2D;
  610                 alt = getdbl((u_char *) &mb(58));
  611 
  612                 printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n",
  613                        up->unit, lat,lon,alt);
  614                 printf("TSIP_decode: unit %d: Sats:",
  615                        up->unit);
  616                 for (st = 66, ts = 0; st <= 73; st++)
  617                     if (mb(st)) {
  618                         if (mb(st) > 0) ts++;
  619                         printf(" %02d", mb(st));
  620                     }
  621                 printf(" : Tracking %d\n", ts); 
  622             }
  623 #endif
  624 
  625             GPS_UTC_Offset = getint((u_char *) &mb(16));  
  626             if (GPS_UTC_Offset == 0) { /* Check UTC offset */ 
  627 #ifdef DEBUG
  628                 printf("TSIP_decode: UTC Offset Unknown\n");
  629 #endif
  630                 break;
  631             }
  632 
  633             secs = getdbl((u_char *) &mb(3));
  634             secint = (long) secs;
  635             secfrac = secs - secint; /* 0.0 <= secfrac < 1.0 */
  636 
  637             pp->nsec = (long) (secfrac * 1000000000); 
  638 
  639             secint %= 86400;    /* Only care about today */
  640             pp->hour = secint / 3600;
  641             secint %= 3600;
  642             pp->minute = secint / 60;
  643             secint %= 60;
  644             pp->second = secint % 60;
  645 
  646             mmday = decode_date(pp, &mb(11));
  647             if (mmday < 0)
  648                 break;
  649 
  650 #ifdef DEBUG
  651             if (debug > 1)
  652                 printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%09ld %02d/%02d/%04d UTC %02d\n",
  653                        up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, 
  654                        pp->second, pp->nsec, (mmday >> 5), (mmday & 31), pp->year, GPS_UTC_Offset);
  655 #endif
  656             /* Only use this packet when no
  657              * 8F-AD's are being received
  658              */
  659 
  660             if (up->leap_status) {
  661                 up->leap_status = 0;
  662                 return 0;
  663             }
  664 
  665             return 2;
  666             break;
  667 
  668             case PACKET_NTP:
  669             /* Palisade-NTP Packet */
  670 
  671             if (up->rpt_cnt != LENCODE_NTP) /* check length */
  672                 break;
  673     
  674             up->leap_status = mb(19);
  675 
  676             if (up->polled  <= 0) 
  677                 return 0;
  678                 
  679             /* Check Tracking Status */
  680             st = mb(18);
  681             if (st < 0 || st > 14)
  682                 st = 14;
  683             if ((st >= 2 && st <= 7) || st == 11 || st == 12) {
  684 #ifdef DEBUG
  685                 printf("TSIP_decode: Not Tracking Sats : %s\n",
  686                        *Tracking_Status[st]);
  687 #endif
  688                 refclock_report(peer, CEVNT_BADTIME);
  689                 up->polled = -1;
  690                 return 0;
  691                 break;
  692             }
  693 
  694             mmday = decode_date(pp, &mb(14));
  695             if (mmday < 0)
  696                 break;
  697             up->month  = (mmday >> 5);  /* Save for LEAP check */
  698 
  699             if ( (up->leap_status & PALISADE_LEAP_PENDING) &&
  700             /* Avoid early announce: https://bugs.ntp.org/2773 */
  701                 (6 == up->month || 12 == up->month) ) {
  702                 if (up->leap_status & PALISADE_UTC_TIME)  
  703                     pp->leap = LEAP_ADDSECOND;
  704                 else
  705                     pp->leap = LEAP_DELSECOND;
  706             }
  707             else if (up->leap_status)
  708                 pp->leap = LEAP_NOWARNING;
  709         
  710             else {  /* UTC flag is not set:
  711                  * Receiver may have been reset, and lost
  712                  * its UTC almanac data */
  713                 pp->leap = LEAP_NOTINSYNC;
  714 #ifdef DEBUG
  715                 printf("TSIP_decode: UTC Almanac unavailable: %d\n",
  716                        mb(19)); 
  717 #endif
  718                 refclock_report(peer, CEVNT_BADTIME);
  719                 up->polled = -1;
  720                 return 0;
  721             }
  722 
  723             pp->nsec = (long) (getdbl((u_char *) &mb(3))
  724                        * 1000000000);
  725 
  726             pp->hour = mb(11);
  727             pp->minute = mb(12);
  728             pp->second = mb(13);
  729 
  730 #ifdef DEBUG
  731             if (debug > 1)
  732                 printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%09ld %02d/%02d/%04d UTC %02x %s\n",
  733                        up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, 
  734                        pp->second, pp->nsec, (mmday >> 5), (mmday & 31), pp->year,
  735                        mb(19), *Tracking_Status[st]);
  736 #endif
  737             return 1;
  738             break;
  739 
  740             case PACKET_8FAC:   
  741             if (up->polled <= 0)
  742                 return 0; 
  743 
  744             if (up->rpt_cnt != LENCODE_8FAC)/* check length */
  745                 break;
  746 
  747 #ifdef DEBUG
  748             if (debug > 1) {
  749                 double lat, lon, alt;
  750                 lat = getdbl((u_char *) &mb(36)) * R2D;
  751                 lon = getdbl((u_char *) &mb(44)) * R2D;
  752                 alt = getdbl((u_char *) &mb(52));
  753 
  754                 printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n",
  755                        up->unit, lat,lon,alt);
  756                 printf("TSIP_decode: unit %d\n", up->unit);
  757             }
  758 #endif
  759             if ( (getint((u_char *) &mb(10)) & 0x80) &&
  760             /* Avoid early announce: https://bugs.ntp.org/2773 */
  761                 (6 == up->month || 12 == up->month) )
  762                 pp->leap = LEAP_ADDSECOND;  /* we ASSUME addsecond */
  763             else 
  764                 pp->leap = LEAP_NOWARNING;
  765 
  766 #ifdef DEBUG
  767             if (debug > 1) 
  768                 printf("TSIP_decode: unit %d: 0x%02x leap %d\n",
  769                        up->unit, mb(0) & 0xff, pp->leap);
  770             if (debug > 1) {
  771                 printf("Receiver MODE: 0x%02X\n", (u_char)mb(1));
  772                 if (mb(1) == 0x00)
  773                     printf("                AUTOMATIC\n");
  774                 if (mb(1) == 0x01)
  775                     printf("                SINGLE SATELLITE\n");   
  776                 if (mb(1) == 0x03)
  777                     printf("                HORIZONTAL(2D)\n");
  778                 if (mb(1) == 0x04)
  779                     printf("                FULL POSITION(3D)\n");
  780                 if (mb(1) == 0x05)
  781                     printf("                DGPR REFERENCE\n");
  782                 if (mb(1) == 0x06)
  783                     printf("                CLOCK HOLD(2D)\n");
  784                 if (mb(1) == 0x07)
  785                     printf("                OVERDETERMINED CLOCK\n");
  786 
  787                 printf("\n** Disciplining MODE 0x%02X:\n", (u_char)mb(2));
  788                 if (mb(2) == 0x00)
  789                     printf("                NORMAL\n");
  790                 if (mb(2) == 0x01)
  791                     printf("                POWER-UP\n");
  792                 if (mb(2) == 0x02)
  793                     printf("                AUTO HOLDOVER\n");
  794                 if (mb(2) == 0x03)
  795                     printf("                MANUAL HOLDOVER\n");
  796                 if (mb(2) == 0x04)
  797                     printf("                RECOVERY\n");
  798                 if (mb(2) == 0x06)
  799                     printf("                DISCIPLINING DISABLED\n");
  800             }
  801 #endif   
  802             return 0;
  803             break;
  804 
  805             case PACKET_8FAB:
  806             /* Thunderbolt Primary Timing Packet */
  807 
  808             if (up->rpt_cnt != LENCODE_8FAB) /* check length */
  809                 break;
  810 
  811             if (up->polled  <= 0)
  812                 return 0;
  813 
  814             GPS_UTC_Offset = getint((u_char *) &mb(7));
  815 
  816             if (GPS_UTC_Offset == 0){ /* Check UTC Offset */
  817 #ifdef DEBUG
  818                 printf("TSIP_decode: UTC Offset Unknown\n");
  819 #endif
  820                 break;
  821             }
  822 
  823 
  824             if ((mb(9) & 0x1d) == 0x0) {
  825                 /* if we know the GPS time and the UTC offset,
  826                    we expect UTC timing information !!! */
  827 
  828                 pp->leap = LEAP_NOTINSYNC;
  829                 refclock_report(peer, CEVNT_BADTIME);
  830                 up->polled = -1;
  831                 return 0;
  832             }
  833 
  834             pp->nsec = 0;
  835 #ifdef DEBUG        
  836             printf("\nTiming Flags are:\n");
  837             printf("Timing flag value is: 0x%X\n", mb(9));
  838             if ((mb(9) & 0x01) != 0)
  839                 printf ("   Getting UTC time\n");
  840             else
  841                 printf ("   Getting GPS time\n");
  842             if ((mb(9) & 0x02) != 0)
  843                 printf ("   PPS is from UTC\n");
  844             else
  845                 printf ("   PPS is from GPS\n");
  846             if ((mb(9) & 0x04) != 0)
  847                 printf ("   Time is not Set\n");
  848             else
  849                 printf ("   Time is Set\n");
  850             if ((mb(9) & 0x08) != 0)
  851                 printf("    I dont have UTC info\n");
  852             else
  853                 printf ("   I have UTC info\n");
  854             if ((mb(9) & 0x10) != 0)
  855                 printf ("   Time is from USER\n\n");
  856             else
  857                 printf ("   Time is from GPS\n\n"); 
  858 #endif      
  859 
  860             mmday = decode_date(pp, &mb(13));
  861             if (mmday < 0)
  862                 break;
  863             tow = getlong((u_char *) &mb(1));
  864 #ifdef DEBUG        
  865             if (debug > 1) {
  866                 printf("pp->day: %d\n", pp->day); 
  867                 printf("TOW: %ld\n", tow);
  868                 printf("DAY: %d\n", (mmday & 31));
  869             }
  870 #endif
  871             pp->hour = mb(12);
  872             pp->minute = mb(11);
  873             pp->second = mb(10);
  874 
  875 
  876 #ifdef DEBUG
  877             if (debug > 1)
  878                 printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%09ld %02d/%02d/%04d ",
  879                        up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, pp->second,
  880                        pp->nsec, (mmday >> 5), (mmday & 31), pp->year);
  881 #endif
  882             return 1;
  883             break;
  884 
  885             default:
  886             /* Ignore Packet */
  887             return 0;
  888         } /* switch */
  889     } /* if 8F packets */
  890 
  891     else if (up->rpt_buf[0] == (u_char)0x42) {
  892         printf("0x42\n");
  893         return 0;
  894     }
  895     else if (up->rpt_buf[0] == (u_char)0x43) {
  896         printf("0x43\n");
  897         return 0;
  898     }
  899     else if ((up->rpt_buf[0] == PACKET_41) & (up->type == CLK_THUNDERBOLT)){
  900         printf("Undocumented 0x41 packet on Thunderbolt\n");
  901         return 0;
  902     }
  903     else if ((up->rpt_buf[0] == PACKET_41A) & (up->type == CLK_ACUTIME)) {
  904 #ifdef DEBUG
  905         printf("GPS TOW: %ld\n", (long)getlong((u_char *) &mb(0)));
  906         printf("GPS WN: %d\n", getint((u_char *) &mb(4)));
  907         printf("GPS UTC-GPS Offset: %ld\n", (long)getlong((u_char *) &mb(6)));
  908 #endif
  909         return 0;
  910     }
  911 
  912     /* GPS time packet for ACE III or Copernicus II receiver */
  913     else if ((up->rpt_buf[0] == PACKET_41) &&
  914              ((up->type == CLK_ACE) || (up->type == CLK_COPERNICUS))) {
  915 #ifdef DEBUG
  916         if ((debug > 1) && (up->type == CLK_ACE))
  917             printf("TSIP_decode: Packet 0x41 seen in ACE III mode\n");
  918         if ((debug > 1) && (up->type == CLK_COPERNICUS))
  919             printf("TSIP_decode: Packet 0x41 seen in Copernicus II mode\n");
  920 #endif
  921         if (up->rpt_cnt != LENCODE_41) { /* check length */
  922             refclock_report(peer, CEVNT_BADREPLY);
  923             up->polled = -1;
  924 #ifdef DEBUG
  925             printf("TSIP_decode: unit %d: bad packet %02x len %d\n", 
  926                 up->unit, up->rpt_buf[0] & 0xff, up->rpt_cnt);
  927 #endif
  928             return 0;
  929         }
  930         if (up->polled  <= 0)
  931             return 0;
  932         tow = (long)getsingle((u_char *) &mb(0));
  933         wn = (uint16_t)getint((u_char *) &mb(4));
  934         GPS_UTC_Offset = (int)getsingle((u_char *) &mb(6));
  935         if (GPS_UTC_Offset == 0){ /* Check UTC Offset */
  936 #ifdef DEBUG
  937             printf("TSIP_decode: UTC Offset Unknown\n");
  938 #endif
  939             refclock_report(peer, CEVNT_BADREPLY);
  940             up->polled = -1;
  941             return 0;
  942         }
  943         /* Get date & time from WN & ToW minus offset */
  944         {
  945             TCivilDate cd;
  946             TGpsDatum wd;
  947             l_fp ugo; /* UTC-GPS offset, negative number */
  948             ugo.Ul_i.Xl_i = (int32_t)-GPS_UTC_Offset;
  949             ugo.l_uf = 0;
  950             wd = gpscal_from_gpsweek((wn % 1024), (int32_t)tow, ugo);
  951             gpscal_to_calendar(&cd, &wd);
  952             pp->year = cd.year;
  953             pp->day = cd.yearday;
  954             pp->hour = cd.hour;
  955             pp->minute = cd.minute;
  956             pp->second = cd.second;
  957             pp->nsec = 0;
  958             pp->leap = LEAP_NOWARNING;
  959 #ifdef DEBUG
  960             if (debug > 1)  {
  961                 printf("GPS TOW: %ld\n", tow);
  962                 printf("GPS WN: %d\n", wn);
  963                 printf("GPS UTC-GPS Offset: %d\n", GPS_UTC_Offset);
  964                 printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%09ld %02d/%02d/%04d ",
  965                        up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, pp->second,
  966                        pp->nsec, cd.month, cd.monthday, pp->year);
  967             }
  968 #endif
  969         }
  970         return 1;
  971     }
  972 
  973     /* Health Status for Acutime Receiver */
  974     else if ((up->rpt_buf[0] == PACKET_46) & (up->type == CLK_ACUTIME)) {
  975 #ifdef DEBUG
  976         if (debug > 1)
  977         /* Status Codes */
  978             switch (mb(0)) {
  979                 case 0x00:
  980                 printf ("Doing Position Fixes\n");
  981                 break;
  982                 case 0x01:
  983                 printf ("Do not have GPS time yet\n");
  984                 break;
  985                 case 0x03:
  986                 printf ("PDOP is too high\n");
  987                 break;
  988                 case 0x08:
  989                 printf ("No usable satellites\n");
  990                 break;
  991                 case 0x09:
  992                 printf ("Only 1 usable satellite\n");
  993                 break;
  994                 case 0x0A:
  995                 printf ("Only 2 usable satellites\n");
  996                 break;
  997                 case 0x0B:
  998                 printf ("Only 3 usable satellites\n");
  999                 break;
 1000                 case 0x0C:
 1001                 printf("The Chosen satellite is unusable\n");
 1002                 break;
 1003             }
 1004 #endif
 1005         /* Error Codes */
 1006         if (mb(1) != 0) {
 1007             
 1008             refclock_report(peer, CEVNT_BADTIME);
 1009             up->polled = -1;
 1010 #ifdef DEBUG
 1011             if (debug > 1) {
 1012                 if (mb(1) & 0x01)
 1013                     printf ("Signal Processor Error, reset unit.\n");
 1014                 if (mb(1) & 0x02)
 1015                     printf ("Alignment error, channel or chip 1, reset unit.\n");
 1016                 if (mb(1) & 0x03)
 1017                     printf ("Alignment error, channel or chip 2, reset unit.\n");
 1018                 if (mb(1) & 0x04)
 1019                     printf ("Antenna feed line fault (open or short)\n");
 1020                 if (mb(1) & 0x05)
 1021                     printf ("Excessive reference frequency error, refer to packet 0x2D and packet 0x4D documentation for further information\n");
 1022             }
 1023 #endif
 1024         
 1025         return 0;
 1026         }
 1027     }
 1028 
 1029     /* Health Status for Copernicus II Receiver */
 1030     else if ((up->rpt_buf[0] == PACKET_46) && (up->type == CLK_COPERNICUS)) {
 1031 #ifdef DEBUG
 1032         if (debug > 1)
 1033         /* Status Codes */
 1034             switch (mb(0)) {
 1035                 case 0x00:
 1036                 printf ("Doing Position Fixes\n");
 1037                 break;
 1038                 case 0x01:
 1039                 printf ("Do not have GPS time yet\n");
 1040                 break;
 1041                 case 0x03:
 1042                 printf ("PDOP is too high\n");
 1043                 break;
 1044                 case 0x04:
 1045                 printf("The Chosen satellite is unusable\n");
 1046                 break;
 1047                 case 0x08:
 1048                 printf ("No usable satellites\n");
 1049                 break;
 1050                 case 0x09:
 1051                 printf ("Only 1 usable satellite\n");
 1052                 break;
 1053                 case 0x0A:
 1054                 printf ("Only 2 usable satellites\n");
 1055                 break;
 1056                 case 0x0B:
 1057                 printf ("Only 3 usable satellites\n");
 1058                 break;
 1059             }
 1060 #endif
 1061         /* Error Codes */
 1062         if ((mb(1) & 0x3E) != 0) {  /* Don't regard bits 0 and 6 as errors */
 1063             refclock_report(peer, CEVNT_BADTIME);
 1064             up->polled = -1;
 1065 #ifdef DEBUG
 1066             if (debug > 1) {
 1067                 if ((mb(1) & 0x18) == 0x08)
 1068                     printf ("Antenna feed line fault (open)\n");
 1069                 if ((mb(1) & 0x18) == 0x18)
 1070                     printf ("Antenna feed line fault (short)\n");
 1071             }
 1072 #endif
 1073         }
 1074         return 0;
 1075     }
 1076 
 1077     /* Other packets output by ACE III & Copernicus II Receivers, dropped silently */
 1078     else if (((up->rpt_buf[0] == (char) 0x4A) ||
 1079           (up->rpt_buf[0] == (char) 0x4B) ||
 1080           (up->rpt_buf[0] == (char) 0x56) ||
 1081           (up->rpt_buf[0] == (char) 0x5F) ||
 1082           (up->rpt_buf[0] == (char) 0x6D) ||
 1083           (up->rpt_buf[0] == (char) 0x82) ||
 1084           (up->rpt_buf[0] == (char) 0x84)) &&
 1085          ((up->type == CLK_ACE) || (up->type == CLK_COPERNICUS))) {
 1086 #ifdef DEBUG
 1087         if ((debug > 1) && (up->type == CLK_ACE))
 1088             printf("TSIP_decode: Packet 0x%2x seen in ACE III mode\n", (up->rpt_buf[0] & 0XFF));
 1089         if ((debug > 1) && (up->type == CLK_COPERNICUS))
 1090             printf("TSIP_decode: Packet 0x%2x seen in Copernicus II mode\n", (up->rpt_buf[0] & 0XFF));
 1091 #endif
 1092         return 0;
 1093     }
 1094 
 1095     else if (up->rpt_buf[0] == 0x54)
 1096         return 0;
 1097 
 1098     else if (up->rpt_buf[0] == PACKET_6D) {
 1099 #ifdef DEBUG
 1100         int sats;
 1101 
 1102         if ((mb(0) & 0x01) && (mb(0) & 0x02))
 1103             printf("2d Fix Dimension\n");
 1104         if (mb(0) & 0x04)
 1105             printf("3d Fix Dimension\n");
 1106 
 1107         if (mb(0) & 0x08)
 1108             printf("Fix Mode is MANUAL\n");
 1109         else
 1110             printf("Fix Mode is AUTO\n");
 1111     
 1112         sats = mb(0) & 0xF0;
 1113         sats = sats >> 4;
 1114         printf("Tracking %d Satellites\n", sats);
 1115 #endif
 1116         return 0;
 1117     } /* else if not super packet */
 1118     refclock_report(peer, CEVNT_BADREPLY);
 1119     up->polled = -1;
 1120 #ifdef DEBUG
 1121     printf("TSIP_decode: unit %d: bad packet %02x-%02x event %d len %d\n", 
 1122            up->unit, up->rpt_buf[0] & 0xff, mb(0) & 0xff, 
 1123            event, up->rpt_cnt);
 1124 #endif
 1125     return 0;
 1126 }
 1127 
 1128 /*
 1129  * palisade__receive - receive data from the serial interface
 1130  */
 1131 
 1132 static void
 1133 palisade_receive (
 1134     struct peer * peer
 1135     )
 1136 {
 1137     struct palisade_unit *up;
 1138     struct refclockproc *pp;
 1139 
 1140     /*
 1141      * Initialize pointers and read the timecode and timestamp.
 1142      */
 1143     pp = peer->procptr;
 1144     up = pp->unitptr;
 1145         
 1146     if (! TSIP_decode(peer)) return;
 1147     
 1148     if (up->polled <= 0) 
 1149         return;   /* no poll pending, already received or timeout */
 1150 
 1151     up->polled = 0;  /* Poll reply received */
 1152     pp->lencode = 0; /* clear time code */
 1153 #ifdef DEBUG
 1154     if (debug) 
 1155         printf(
 1156             "palisade_receive: unit %d: %4d %03d %02d:%02d:%02d.%09ld\n",
 1157             up->unit, pp->year, pp->day, pp->hour, pp->minute, 
 1158             pp->second, pp->nsec);
 1159 #endif
 1160 
 1161     /*
 1162      * Process the sample
 1163      * Generate timecode: YYYY DoY HH:MM:SS.microsec 
 1164      * report and process 
 1165      */
 1166 
 1167     snprintf(pp->a_lastcode, sizeof(pp->a_lastcode),
 1168          "%4d %03d %02d:%02d:%02d.%09ld",
 1169          pp->year, pp->day,
 1170          pp->hour,pp->minute, pp->second, pp->nsec); 
 1171     pp->lencode = 24;
 1172 
 1173     if (!refclock_process(pp)) {
 1174         refclock_report(peer, CEVNT_BADTIME);
 1175 
 1176 #ifdef DEBUG
 1177         printf("palisade_receive: unit %d: refclock_process failed!\n",
 1178                up->unit);
 1179 #endif
 1180         return;
 1181     }
 1182 
 1183     record_clock_stats(&peer->srcadr, pp->a_lastcode); 
 1184 
 1185 #ifdef DEBUG
 1186     if (debug)
 1187         printf("palisade_receive: unit %d: %s\n",
 1188                up->unit, prettydate(&pp->lastrec));
 1189 #endif
 1190     pp->lastref = pp->lastrec;
 1191     refclock_receive(peer);
 1192 }
 1193 
 1194 
 1195 /*
 1196  * palisade_poll - called by the transmit procedure
 1197  *
 1198  */
 1199 static void
 1200 palisade_poll (
 1201     int unit,
 1202     struct peer *peer
 1203     )
 1204 {
 1205     struct palisade_unit *up;
 1206     struct refclockproc *pp;
 1207     
 1208     pp = peer->procptr;
 1209     up = pp->unitptr;
 1210 
 1211     pp->polls++;
 1212     if (up->polled > 0) /* last reply never arrived or error */ 
 1213         refclock_report(peer, CEVNT_TIMEOUT);
 1214 
 1215     up->polled = 2; /* synchronous packet + 1 event */
 1216     
 1217 #ifdef DEBUG
 1218     if (debug)
 1219         printf("palisade_poll: unit %d: polling %s\n", unit,
 1220                (pp->sloppyclockflag & CLK_FLAG2) ? 
 1221                "synchronous packet" : "event");
 1222 #endif 
 1223 
 1224     if (pp->sloppyclockflag & CLK_FLAG2) 
 1225         return;  /* using synchronous packet input */
 1226 
 1227     if(up->type == CLK_PRAECIS) {
 1228         if(write(peer->procptr->io.fd,"SPSTAT\r\n",8) < 0)
 1229             msyslog(LOG_ERR, "Palisade(%d) write: %m:",unit);
 1230         else {
 1231             praecis_msg = 1;
 1232             return;
 1233         }
 1234     }
 1235 
 1236     if (HW_poll(pp) < 0) 
 1237         refclock_report(peer, CEVNT_FAULT); 
 1238 }
 1239 
 1240 static void
 1241 praecis_parse (
 1242     struct recvbuf *rbufp,
 1243     struct peer *peer
 1244     )
 1245 {
 1246     static char buf[100];
 1247     static int p = 0;
 1248     struct refclockproc *pp;
 1249 
 1250     pp = peer->procptr;
 1251 
 1252     memcpy(buf+p,rbufp->recv_space.X_recv_buffer, rbufp->recv_length);
 1253     p += rbufp->recv_length;
 1254 
 1255     if(buf[p-2] == '\r' && buf[p-1] == '\n') {
 1256         buf[p-2] = '\0';
 1257         record_clock_stats(&peer->srcadr, buf);
 1258 
 1259         p = 0;
 1260         praecis_msg = 0;
 1261 
 1262         if (HW_poll(pp) < 0)
 1263             refclock_report(peer, CEVNT_FAULT);
 1264 
 1265     }
 1266 }
 1267 
 1268 static void
 1269 palisade_io (
 1270     struct recvbuf *rbufp
 1271     )
 1272 {
 1273     /*
 1274      * Initialize pointers and read the timecode and timestamp.
 1275      */
 1276     struct palisade_unit *up;
 1277     struct refclockproc *pp;
 1278     struct peer *peer;
 1279 
 1280     char * c, * d;
 1281 
 1282     peer = rbufp->recv_peer;
 1283     pp = peer->procptr;
 1284     up = pp->unitptr;
 1285 
 1286     if(up->type == CLK_PRAECIS) {
 1287         if(praecis_msg) {
 1288             praecis_parse(rbufp,peer);
 1289             return;
 1290         }
 1291     }
 1292 
 1293     c = (char *) &rbufp->recv_space;
 1294     d = c + rbufp->recv_length;
 1295         
 1296     while (c != d) {
 1297 
 1298         /* Build time packet */
 1299         switch (up->rpt_status) {
 1300 
 1301             case TSIP_PARSED_DLE_1:
 1302             switch (*c)
 1303             {
 1304                 case 0:
 1305                 case DLE:
 1306                 case ETX:
 1307                 up->rpt_status = TSIP_PARSED_EMPTY;
 1308                 break;
 1309 
 1310                 default:
 1311                 up->rpt_status = TSIP_PARSED_DATA;
 1312                 /* save packet ID */
 1313                 up->rpt_buf[0] = *c;
 1314                 break;
 1315             }
 1316             break;
 1317 
 1318             case TSIP_PARSED_DATA:
 1319             if (*c == DLE)
 1320                 up->rpt_status = TSIP_PARSED_DLE_2;
 1321             else 
 1322                 mb(up->rpt_cnt++) = *c;
 1323             break;
 1324 
 1325             case TSIP_PARSED_DLE_2:
 1326             if (*c == DLE) {
 1327                 up->rpt_status = TSIP_PARSED_DATA;
 1328                 mb(up->rpt_cnt++) = 
 1329                     *c;
 1330             }
 1331             else if (*c == ETX) 
 1332                 up->rpt_status = TSIP_PARSED_FULL;
 1333             else    {
 1334                 /* error: start new report packet */
 1335                 up->rpt_status = TSIP_PARSED_DLE_1;
 1336                 up->rpt_buf[0] = *c;
 1337             }
 1338             break;
 1339 
 1340             case TSIP_PARSED_FULL:
 1341             case TSIP_PARSED_EMPTY:
 1342             default:
 1343             if ( *c != DLE)
 1344                 up->rpt_status = TSIP_PARSED_EMPTY;
 1345             else 
 1346                 up->rpt_status = TSIP_PARSED_DLE_1;
 1347             break;
 1348         }
 1349         
 1350         c++;
 1351 
 1352         if (up->rpt_status == TSIP_PARSED_DLE_1) {
 1353             up->rpt_cnt = 0;
 1354             if (pp->sloppyclockflag & CLK_FLAG2) 
 1355                 /* stamp it */
 1356                 get_systime(&pp->lastrec);
 1357         }
 1358         else if (up->rpt_status == TSIP_PARSED_EMPTY)
 1359             up->rpt_cnt = 0;
 1360 
 1361         else if (up->rpt_cnt > BMAX) 
 1362             up->rpt_status =TSIP_PARSED_EMPTY;
 1363 
 1364         if (up->rpt_status == TSIP_PARSED_FULL) 
 1365             palisade_receive(peer);
 1366 
 1367     } /* while chars in buffer */
 1368 }
 1369 
 1370 
 1371 /*
 1372  * Trigger the Palisade's event input, which is driven off the RTS
 1373  *
 1374  * Take a system time stamp to match the GPS time stamp.
 1375  *
 1376  */
 1377 long
 1378 HW_poll (
 1379     struct refclockproc * pp    /* pointer to unit structure */
 1380     )
 1381 {   
 1382     int x;  /* state before & after RTS set */
 1383     struct palisade_unit *up;
 1384     struct packettx tx;
 1385 
 1386     up = pp->unitptr;
 1387 
 1388     if (up->type == CLK_ACE) {
 1389         /* Poll by sending a 0x21 command */
 1390         tx.size = 0;
 1391         tx.data = (u_char *) emalloc(100);
 1392         sendcmd (&tx, 0x21);
 1393         sendetx (&tx, pp->io.fd);
 1394         free(tx.data);
 1395     } else {
 1396 
 1397     /* read the current status, so we put things back right */
 1398     if (ioctl(pp->io.fd, TIOCMGET, &x) < 0) {
 1399         DPRINTF(1, ("Palisade HW_poll: unit %d: GET %m\n",
 1400             up->unit));
 1401         msyslog(LOG_ERR, "Palisade(%d) HW_poll: ioctl(fd,GET): %m", 
 1402             up->unit);
 1403         return -1;
 1404     }
 1405   
 1406     x |= TIOCM_RTS;        /* turn on RTS  */
 1407 
 1408     /* Edge trigger */
 1409     if (up->type == CLK_ACUTIME)
 1410         write (pp->io.fd, "", 1);
 1411         
 1412     if (ioctl(pp->io.fd, TIOCMSET, &x) < 0) { 
 1413 #ifdef DEBUG
 1414         if (debug)
 1415             printf("Palisade HW_poll: unit %d: SET \n", up->unit);
 1416 #endif
 1417         msyslog(LOG_ERR,
 1418             "Palisade(%d) HW_poll: ioctl(fd, SET, RTS_on): %m", 
 1419             up->unit);
 1420         return -1;
 1421     }
 1422 
 1423     x &= ~TIOCM_RTS;        /* turn off RTS  */
 1424     
 1425     } /* (up->type != CLK_ACE) */
 1426 
 1427     /* poll timestamp */
 1428     get_systime(&pp->lastrec);
 1429 
 1430     if (up->type != CLK_ACE) {
 1431     if (ioctl(pp->io.fd, TIOCMSET, &x) == -1) {
 1432 #ifdef DEBUG
 1433         if (debug)
 1434             printf("Palisade HW_poll: unit %d: UNSET \n", up->unit);
 1435 #endif
 1436         msyslog(LOG_ERR,
 1437             "Palisade(%d) HW_poll: ioctl(fd, UNSET, RTS_off): %m", 
 1438             up->unit);
 1439         return -1;
 1440     }
 1441     }
 1442 
 1443     return 0;
 1444 }
 1445 
 1446 /*
 1447  * copy/swap a big-endian palisade double into a host double
 1448  */
 1449 static double
 1450 getdbl (
 1451     u_char *bp
 1452     )
 1453 {
 1454 #ifdef WORDS_BIGENDIAN
 1455     double out;
 1456 
 1457     memcpy(&out, bp, sizeof(out));
 1458     return out;
 1459 #else
 1460     union {
 1461         u_char ch[8];
 1462         u_int32 u32[2];
 1463     } ui;
 1464         
 1465     union {
 1466         double out;
 1467         u_int32 u32[2];
 1468     } uo;
 1469 
 1470     memcpy(ui.ch, bp, sizeof(ui.ch));
 1471     /* least-significant 32 bits of double from swapped bp[4] to bp[7] */
 1472     uo.u32[0] = ntohl(ui.u32[1]);
 1473     /* most-significant 32 bits from swapped bp[0] to bp[3] */
 1474     uo.u32[1] = ntohl(ui.u32[0]);
 1475 
 1476     return uo.out;
 1477 #endif
 1478 }
 1479 
 1480 /*
 1481  * copy/swap a big-endian palisade short into a host short
 1482  */
 1483 static short
 1484 getint (
 1485     u_char *bp
 1486     )
 1487 {
 1488     u_short us;
 1489 
 1490     memcpy(&us, bp, sizeof(us));
 1491     return (short)ntohs(us);
 1492 }
 1493 
 1494 /*
 1495  * copy/swap a big-endian palisade 32-bit int into a host 32-bit int
 1496  */
 1497 static int32
 1498 getlong(
 1499     u_char *bp
 1500     )
 1501 {
 1502     u_int32 u32;
 1503 
 1504     memcpy(&u32, bp, sizeof(u32));
 1505     return (int32)(u_int32)ntohl(u32);
 1506 }
 1507 
 1508 /*
 1509  * copy/swap a big-endian 32-bit single-precision floating point into a host 32-bit int
 1510  */
 1511 static int32
 1512 getsingle(
 1513     u_char *bp
 1514     )
 1515 {
 1516     u_int32 mantissa;
 1517     int8_t exponent;
 1518     uint8_t sign, exp_field;
 1519     int32 res;
 1520 
 1521     memcpy(&mantissa, bp, sizeof(mantissa));
 1522     mantissa = ((u_int32)ntohl(mantissa) & 0x7FFFFF) | 0x800000;
 1523     exp_field = ((uint8_t)bp[0] << 1) + ((uint8_t)bp[1] >> 7);
 1524     exponent = (int8_t)exp_field - 127;
 1525     sign = ((uint8_t)bp[0] >> 7);
 1526     if (exponent > 23)
 1527         res = (int32)(mantissa << (exponent - 23));
 1528     else
 1529         res = (int32)(mantissa >> (23 - exponent));
 1530     return sign ? -res : res;
 1531 }
 1532 
 1533 #else   /* REFCLOCK && CLOCK_PALISADE*/
 1534 int refclock_palisade_c_notempty;
 1535 #endif