1*eabc0478Schristos /* $NetBSD: clk_trimtsip.c,v 1.8 2024/08/18 20:47:17 christos Exp $ */ 2abb0f93cSkardel 3abb0f93cSkardel /* 4abb0f93cSkardel * /src/NTP/REPOSITORY/ntp4-dev/libparse/clk_trimtsip.c,v 4.19 2009/11/01 10:47:49 kardel RELEASE_20091101_A 5abb0f93cSkardel * 6abb0f93cSkardel * clk_trimtsip.c,v 4.19 2009/11/01 10:47:49 kardel RELEASE_20091101_A 7abb0f93cSkardel * 8abb0f93cSkardel * Trimble TSIP support 9abb0f93cSkardel * Thanks to Sven Dietrich for providing test hardware 10abb0f93cSkardel * 11abb0f93cSkardel * Copyright (c) 1995-2009 by Frank Kardel <kardel <AT> ntp.org> 127476e6e4Schristos * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universitaet Erlangen-Nuernberg, Germany 13abb0f93cSkardel * 14abb0f93cSkardel * Redistribution and use in source and binary forms, with or without 15abb0f93cSkardel * modification, are permitted provided that the following conditions 16abb0f93cSkardel * are met: 17abb0f93cSkardel * 1. Redistributions of source code must retain the above copyright 18abb0f93cSkardel * notice, this list of conditions and the following disclaimer. 19abb0f93cSkardel * 2. Redistributions in binary form must reproduce the above copyright 20abb0f93cSkardel * notice, this list of conditions and the following disclaimer in the 21abb0f93cSkardel * documentation and/or other materials provided with the distribution. 22abb0f93cSkardel * 3. Neither the name of the author nor the names of its contributors 23abb0f93cSkardel * may be used to endorse or promote products derived from this software 24abb0f93cSkardel * without specific prior written permission. 25abb0f93cSkardel * 26abb0f93cSkardel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 27abb0f93cSkardel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28abb0f93cSkardel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29abb0f93cSkardel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 30abb0f93cSkardel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31abb0f93cSkardel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32abb0f93cSkardel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33abb0f93cSkardel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34abb0f93cSkardel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35abb0f93cSkardel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36abb0f93cSkardel * SUCH DAMAGE. 37abb0f93cSkardel * 38abb0f93cSkardel */ 39abb0f93cSkardel 40abb0f93cSkardel #ifdef HAVE_CONFIG_H 41abb0f93cSkardel # include <config.h> 42abb0f93cSkardel #endif 43abb0f93cSkardel 44abb0f93cSkardel #if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_TRIMTSIP) 45abb0f93cSkardel 46abb0f93cSkardel #include "ntp_syslog.h" 47abb0f93cSkardel #include "ntp_types.h" 48abb0f93cSkardel #include "ntp_fp.h" 498585484eSchristos #include "timevalops.h" 50abb0f93cSkardel #include "ntp_calendar.h" 51abb0f93cSkardel #include "ntp_machine.h" 52abb0f93cSkardel #include "ntp_stdlib.h" 53abb0f93cSkardel 54abb0f93cSkardel #include "parse.h" 55abb0f93cSkardel 56abb0f93cSkardel #ifndef PARSESTREAM 57abb0f93cSkardel # include <stdio.h> 58abb0f93cSkardel #else 59abb0f93cSkardel # include "sys/parsestreams.h" 60abb0f93cSkardel #endif 61abb0f93cSkardel 62abb0f93cSkardel #include "ascii.h" 63abb0f93cSkardel #include "binio.h" 64abb0f93cSkardel #include "ieee754io.h" 65abb0f93cSkardel #include "trimble.h" 66abb0f93cSkardel 67abb0f93cSkardel /* 68abb0f93cSkardel * Trimble low level TSIP parser / time converter 69abb0f93cSkardel * 70abb0f93cSkardel * The receiver uses a serial message protocol called Trimble Standard 71abb0f93cSkardel * Interface Protocol (it can support others but this driver only supports 72abb0f93cSkardel * TSIP). Messages in this protocol have the following form: 73abb0f93cSkardel * 74abb0f93cSkardel * <DLE><id> ... <data> ... <DLE><ETX> 75abb0f93cSkardel * 76abb0f93cSkardel * Any bytes within the <data> portion of value 10 hex (<DLE>) are doubled 77abb0f93cSkardel * on transmission and compressed back to one on reception. Otherwise 78abb0f93cSkardel * the values of data bytes can be anything. The serial interface is RS-422 79abb0f93cSkardel * asynchronous using 9600 baud, 8 data bits with odd party (**note** 9 bits 80abb0f93cSkardel * in total!), and 1 stop bit. The protocol supports byte, integer, single, 81abb0f93cSkardel * and double datatypes. Integers are two bytes, sent most significant first. 82abb0f93cSkardel * Singles are IEEE754 single precision floating point numbers (4 byte) sent 83abb0f93cSkardel * sign & exponent first. Doubles are IEEE754 double precision floating point 84abb0f93cSkardel * numbers (8 byte) sent sign & exponent first. 85abb0f93cSkardel * The receiver supports a large set of messages, only a very small subset of 86abb0f93cSkardel * which is used here. 87abb0f93cSkardel * 88abb0f93cSkardel * From this module the following are recognised: 89abb0f93cSkardel * 90abb0f93cSkardel * ID Description 91abb0f93cSkardel * 92abb0f93cSkardel * 41 GPS Time 93abb0f93cSkardel * 46 Receiver health 94abb0f93cSkardel * 4F UTC correction data (used to get leap second warnings) 95abb0f93cSkardel * 96abb0f93cSkardel * All others are accepted but ignored for time conversion - they are passed up to higher layers. 97abb0f93cSkardel * 98abb0f93cSkardel */ 99abb0f93cSkardel 100abb0f93cSkardel static offsets_t trim_offsets = { 0, 1, 2, 3, 4, 5, 6, 7 }; 101abb0f93cSkardel 102abb0f93cSkardel struct trimble 103abb0f93cSkardel { 104abb0f93cSkardel u_char t_in_pkt; /* first DLE received */ 105abb0f93cSkardel u_char t_dle; /* subsequent DLE received */ 106abb0f93cSkardel u_short t_week; /* GPS week */ 107abb0f93cSkardel u_short t_weekleap; /* GPS week of next/last week */ 108abb0f93cSkardel u_short t_dayleap; /* day in week */ 109abb0f93cSkardel u_short t_gpsutc; /* GPS - UTC offset */ 110abb0f93cSkardel u_short t_gpsutcleap; /* offset at next/last leap */ 111abb0f93cSkardel u_char t_operable; /* receiver feels OK */ 112abb0f93cSkardel u_char t_mode; /* actual operating mode */ 113abb0f93cSkardel u_char t_leap; /* possible leap warning */ 114abb0f93cSkardel u_char t_utcknown; /* utc offset known */ 115abb0f93cSkardel }; 116abb0f93cSkardel 117abb0f93cSkardel #define STATUS_BAD 0 /* BAD or UNINITIALIZED receiver status */ 118abb0f93cSkardel #define STATUS_UNSAFE 1 /* not enough receivers for full precision */ 119abb0f93cSkardel #define STATUS_SYNC 2 /* enough information for good operation */ 120abb0f93cSkardel 1217476e6e4Schristos static unsigned long inp_tsip (parse_t *, char, timestamp_t *); 122abb0f93cSkardel static unsigned long cvt_trimtsip (unsigned char *, int, struct format *, clocktime_t *, void *); 123abb0f93cSkardel 124abb0f93cSkardel struct clockformat clock_trimtsip = 125abb0f93cSkardel { 126abb0f93cSkardel inp_tsip, /* Trimble TSIP input handler */ 127abb0f93cSkardel cvt_trimtsip, /* Trimble TSIP conversion */ 128abb0f93cSkardel pps_one, /* easy PPS monitoring */ 129abb0f93cSkardel 0, /* no configuration data */ 130abb0f93cSkardel "Trimble TSIP", 131abb0f93cSkardel 400, /* input buffer */ 132abb0f93cSkardel sizeof(struct trimble) /* private data */ 133abb0f93cSkardel }; 134abb0f93cSkardel 135abb0f93cSkardel #define ADDSECOND 0x01 136abb0f93cSkardel #define DELSECOND 0x02 137abb0f93cSkardel 138abb0f93cSkardel static unsigned long 139abb0f93cSkardel inp_tsip( 140abb0f93cSkardel parse_t *parseio, 1417476e6e4Schristos char ch, 142abb0f93cSkardel timestamp_t *tstamp 143abb0f93cSkardel ) 144abb0f93cSkardel { 145abb0f93cSkardel struct trimble *t = (struct trimble *)parseio->parse_pdata; 146abb0f93cSkardel 147abb0f93cSkardel if (!t) 148abb0f93cSkardel return PARSE_INP_SKIP; /* local data not allocated - sigh! */ 149abb0f93cSkardel 150abb0f93cSkardel if (!t->t_in_pkt && ch != DLE) { 151abb0f93cSkardel /* wait for start of packet */ 152abb0f93cSkardel return PARSE_INP_SKIP; 153abb0f93cSkardel } 154abb0f93cSkardel 155abb0f93cSkardel if ((parseio->parse_index >= (parseio->parse_dsize - 2)) || 156abb0f93cSkardel (parseio->parse_dtime.parse_msglen >= (sizeof(parseio->parse_dtime.parse_msg) - 2))) 157abb0f93cSkardel { /* OVERFLOW - DROP! */ 158abb0f93cSkardel t->t_in_pkt = t->t_dle = 0; 159abb0f93cSkardel parseio->parse_index = 0; 160abb0f93cSkardel parseio->parse_dtime.parse_msglen = 0; 161abb0f93cSkardel return PARSE_INP_SKIP; 162abb0f93cSkardel } 163abb0f93cSkardel 164abb0f93cSkardel switch (ch) { 165abb0f93cSkardel case DLE: 166abb0f93cSkardel if (!t->t_in_pkt) { 167abb0f93cSkardel t->t_dle = 0; 168abb0f93cSkardel t->t_in_pkt = 1; 169abb0f93cSkardel parseio->parse_index = 0; 170abb0f93cSkardel parseio->parse_data[parseio->parse_index++] = ch; 171abb0f93cSkardel parseio->parse_dtime.parse_msglen = 0; 172abb0f93cSkardel parseio->parse_dtime.parse_msg[parseio->parse_dtime.parse_msglen++] = ch; 173abb0f93cSkardel parseio->parse_dtime.parse_stime = *tstamp; /* pick up time stamp at packet start */ 174abb0f93cSkardel } else if (t->t_dle) { 175abb0f93cSkardel /* Double DLE -> insert a DLE */ 176abb0f93cSkardel t->t_dle = 0; 177abb0f93cSkardel parseio->parse_data[parseio->parse_index++] = DLE; 178abb0f93cSkardel parseio->parse_dtime.parse_msg[parseio->parse_dtime.parse_msglen++] = DLE; 179abb0f93cSkardel } else 180abb0f93cSkardel t->t_dle = 1; 181abb0f93cSkardel break; 182abb0f93cSkardel 183abb0f93cSkardel case ETX: 184abb0f93cSkardel if (t->t_dle) { 185abb0f93cSkardel /* DLE,ETX -> end of packet */ 186abb0f93cSkardel parseio->parse_data[parseio->parse_index++] = DLE; 187abb0f93cSkardel parseio->parse_data[parseio->parse_index] = ch; 1887476e6e4Schristos parseio->parse_ldsize = (u_short) (parseio->parse_index + 1); 189abb0f93cSkardel memcpy(parseio->parse_ldata, parseio->parse_data, parseio->parse_ldsize); 190abb0f93cSkardel parseio->parse_dtime.parse_msg[parseio->parse_dtime.parse_msglen++] = DLE; 191abb0f93cSkardel parseio->parse_dtime.parse_msg[parseio->parse_dtime.parse_msglen++] = ch; 192abb0f93cSkardel t->t_in_pkt = t->t_dle = 0; 193abb0f93cSkardel return PARSE_INP_TIME|PARSE_INP_DATA; 194abb0f93cSkardel } 195abb0f93cSkardel /*FALLTHROUGH*/ 196abb0f93cSkardel 197abb0f93cSkardel default: /* collect data */ 198abb0f93cSkardel t->t_dle = 0; 199abb0f93cSkardel parseio->parse_data[parseio->parse_index++] = ch; 200abb0f93cSkardel parseio->parse_dtime.parse_msg[parseio->parse_dtime.parse_msglen++] = ch; 201abb0f93cSkardel } 202abb0f93cSkardel 203abb0f93cSkardel return PARSE_INP_SKIP; 204abb0f93cSkardel } 205abb0f93cSkardel 2067476e6e4Schristos static short 207abb0f93cSkardel getshort( 208abb0f93cSkardel unsigned char *p 209abb0f93cSkardel ) 210abb0f93cSkardel { 2117476e6e4Schristos return (short) get_msb_short(&p); 212abb0f93cSkardel } 213abb0f93cSkardel 214abb0f93cSkardel /* 215abb0f93cSkardel * cvt_trimtsip 216abb0f93cSkardel * 217abb0f93cSkardel * convert TSIP type format 218abb0f93cSkardel */ 219abb0f93cSkardel static unsigned long 220abb0f93cSkardel cvt_trimtsip( 221abb0f93cSkardel unsigned char *buffer, 222abb0f93cSkardel int size, 223abb0f93cSkardel struct format *format, 224abb0f93cSkardel clocktime_t *clock_time, 225abb0f93cSkardel void *local 226abb0f93cSkardel ) 227abb0f93cSkardel { 228abb0f93cSkardel register struct trimble *t = (struct trimble *)local; /* get local data space */ 229abb0f93cSkardel #define mb(_X_) (buffer[2+(_X_)]) /* shortcut for buffer access */ 230abb0f93cSkardel register u_char cmd; 231abb0f93cSkardel 232abb0f93cSkardel clock_time->flags = 0; 233abb0f93cSkardel 234abb0f93cSkardel if (!t) { 235abb0f93cSkardel return CVT_NONE; /* local data not allocated - sigh! */ 236abb0f93cSkardel } 237abb0f93cSkardel 238abb0f93cSkardel if ((size < 4) || 239abb0f93cSkardel (buffer[0] != DLE) || 240abb0f93cSkardel (buffer[size-1] != ETX) || 241abb0f93cSkardel (buffer[size-2] != DLE)) 242abb0f93cSkardel { 243abb0f93cSkardel printf("TRIMBLE BAD packet, size %d:\n", size); 244abb0f93cSkardel return CVT_NONE; 245abb0f93cSkardel } 246abb0f93cSkardel else 247abb0f93cSkardel { 248abb0f93cSkardel unsigned char *bp; 249abb0f93cSkardel cmd = buffer[1]; 250abb0f93cSkardel 251abb0f93cSkardel switch(cmd) 252abb0f93cSkardel { 253abb0f93cSkardel case CMD_RCURTIME: 254abb0f93cSkardel { /* GPS time */ 255abb0f93cSkardel l_fp secs; 256ccc794f0Schristos u_int week = getshort((unsigned char *)&mb(4)); 257abb0f93cSkardel l_fp utcoffset; 258abb0f93cSkardel l_fp gpstime; 259abb0f93cSkardel 260abb0f93cSkardel bp = &mb(0); 261abb0f93cSkardel if (fetch_ieee754(&bp, IEEE_SINGLE, &secs, trim_offsets) != IEEE_OK) 262abb0f93cSkardel return CVT_FAIL|CVT_BADFMT; 263abb0f93cSkardel 264abb0f93cSkardel if ((secs.l_i <= 0) || 265abb0f93cSkardel (t->t_utcknown == 0)) 266abb0f93cSkardel { 267abb0f93cSkardel clock_time->flags = PARSEB_POWERUP; 268abb0f93cSkardel return CVT_OK; 269abb0f93cSkardel } 270cdfa2a7eSchristos week = basedate_expand_gpsweek(week); 271abb0f93cSkardel 272abb0f93cSkardel /* time OK */ 273abb0f93cSkardel 274abb0f93cSkardel /* fetch UTC offset */ 275abb0f93cSkardel bp = &mb(6); 276abb0f93cSkardel if (fetch_ieee754(&bp, IEEE_SINGLE, &utcoffset, trim_offsets) != IEEE_OK) 277abb0f93cSkardel return CVT_FAIL|CVT_BADFMT; 278abb0f93cSkardel 279abb0f93cSkardel L_SUB(&secs, &utcoffset); /* adjust GPS time to UTC time */ 280abb0f93cSkardel 281abb0f93cSkardel gpstolfp((unsigned short)week, (unsigned short)0, 282abb0f93cSkardel secs.l_ui, &gpstime); 283abb0f93cSkardel 284abb0f93cSkardel gpstime.l_uf = secs.l_uf; 285abb0f93cSkardel 286abb0f93cSkardel clock_time->utctime = gpstime.l_ui - JAN_1970; 287abb0f93cSkardel 288abb0f93cSkardel TSFTOTVU(gpstime.l_uf, clock_time->usecond); 289abb0f93cSkardel 290abb0f93cSkardel if (t->t_leap == ADDSECOND) 291abb0f93cSkardel clock_time->flags |= PARSEB_LEAPADD; 292abb0f93cSkardel 293abb0f93cSkardel if (t->t_leap == DELSECOND) 294abb0f93cSkardel clock_time->flags |= PARSEB_LEAPDEL; 295abb0f93cSkardel 296abb0f93cSkardel switch (t->t_operable) 297abb0f93cSkardel { 298abb0f93cSkardel case STATUS_SYNC: 299abb0f93cSkardel clock_time->flags &= ~(PARSEB_POWERUP|PARSEB_NOSYNC); 300abb0f93cSkardel break; 301abb0f93cSkardel 302abb0f93cSkardel case STATUS_UNSAFE: 303abb0f93cSkardel clock_time->flags |= PARSEB_NOSYNC; 304abb0f93cSkardel break; 305abb0f93cSkardel 306abb0f93cSkardel case STATUS_BAD: 307abb0f93cSkardel clock_time->flags |= PARSEB_NOSYNC|PARSEB_POWERUP; 308abb0f93cSkardel break; 309abb0f93cSkardel } 310abb0f93cSkardel 311abb0f93cSkardel if (t->t_mode == 0) 312abb0f93cSkardel clock_time->flags |= PARSEB_POSITION; 313abb0f93cSkardel 314abb0f93cSkardel clock_time->flags |= PARSEB_S_LEAP|PARSEB_S_POSITION; 315abb0f93cSkardel 316abb0f93cSkardel return CVT_OK; 317abb0f93cSkardel 318abb0f93cSkardel } /* case 0x41 */ 319abb0f93cSkardel 320abb0f93cSkardel case CMD_RRECVHEALTH: 321abb0f93cSkardel { 322abb0f93cSkardel /* TRIMBLE health */ 323abb0f93cSkardel u_char status = mb(0); 324abb0f93cSkardel 325abb0f93cSkardel switch (status) 326abb0f93cSkardel { 327abb0f93cSkardel case 0x00: /* position fixes */ 328abb0f93cSkardel t->t_operable = STATUS_SYNC; 329abb0f93cSkardel break; 330abb0f93cSkardel 331abb0f93cSkardel case 0x09: /* 1 satellite */ 332abb0f93cSkardel case 0x0A: /* 2 satellites */ 333abb0f93cSkardel case 0x0B: /* 3 satellites */ 334abb0f93cSkardel t->t_operable = STATUS_UNSAFE; 335abb0f93cSkardel break; 336abb0f93cSkardel 337abb0f93cSkardel default: 338abb0f93cSkardel t->t_operable = STATUS_BAD; 339abb0f93cSkardel break; 340abb0f93cSkardel } 341abb0f93cSkardel t->t_mode = status; 342abb0f93cSkardel } 343abb0f93cSkardel break; 344abb0f93cSkardel 345abb0f93cSkardel case CMD_RUTCPARAM: 346abb0f93cSkardel { 347abb0f93cSkardel l_fp t0t; 348abb0f93cSkardel unsigned char *lbp; 349abb0f93cSkardel 350abb0f93cSkardel /* UTC correction data - derive a leap warning */ 3517476e6e4Schristos int tls = t->t_gpsutc = (u_short) getshort((unsigned char *)&mb(12)); /* current leap correction (GPS-UTC) */ 3527476e6e4Schristos int tlsf = t->t_gpsutcleap = (u_short) getshort((unsigned char *)&mb(24)); /* new leap correction */ 353abb0f93cSkardel 354cdfa2a7eSchristos t->t_weekleap = basedate_expand_gpsweek( 355cdfa2a7eSchristos (u_short) getshort((unsigned char *)&mb(20))); /* week no of leap correction */ 356abb0f93cSkardel 3577476e6e4Schristos t->t_dayleap = (u_short) getshort((unsigned char *)&mb(22)); /* day in week of leap correction */ 358cdfa2a7eSchristos t->t_week = basedate_expand_gpsweek( 359cdfa2a7eSchristos (u_short) getshort((unsigned char *)&mb(18))); /* current week no */ 360abb0f93cSkardel 361abb0f93cSkardel lbp = (unsigned char *)&mb(14); /* last update time */ 362abb0f93cSkardel if (fetch_ieee754(&lbp, IEEE_SINGLE, &t0t, trim_offsets) != IEEE_OK) 363abb0f93cSkardel return CVT_FAIL|CVT_BADFMT; 364abb0f93cSkardel 365abb0f93cSkardel t->t_utcknown = t0t.l_ui != 0; 366abb0f93cSkardel 367abb0f93cSkardel if ((t->t_utcknown) && /* got UTC information */ 368abb0f93cSkardel (tlsf != tls) && /* something will change */ 369abb0f93cSkardel ((t->t_weekleap - t->t_week) < 5)) /* and close in the future */ 370abb0f93cSkardel { 371abb0f93cSkardel /* generate a leap warning */ 372abb0f93cSkardel if (tlsf > tls) 373abb0f93cSkardel t->t_leap = ADDSECOND; 374abb0f93cSkardel else 375abb0f93cSkardel t->t_leap = DELSECOND; 376abb0f93cSkardel } 377abb0f93cSkardel else 378abb0f93cSkardel { 379abb0f93cSkardel t->t_leap = 0; 380abb0f93cSkardel } 381abb0f93cSkardel } 382abb0f93cSkardel break; 383abb0f93cSkardel 384abb0f93cSkardel default: 385abb0f93cSkardel /* it's validly formed, but we don't care about it! */ 386abb0f93cSkardel break; 387abb0f93cSkardel } 388abb0f93cSkardel } 389abb0f93cSkardel return CVT_SKIP; 390abb0f93cSkardel } 391abb0f93cSkardel 392abb0f93cSkardel #else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_TRIMTSIP && !PARSESTREAM) */ 393*eabc0478Schristos NONEMPTY_TRANSLATION_UNIT 394abb0f93cSkardel #endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_TRIMTSIP && !PARSESTREAM) */ 395abb0f93cSkardel 396abb0f93cSkardel /* 397abb0f93cSkardel * History: 398abb0f93cSkardel * 399abb0f93cSkardel * clk_trimtsip.c,v 400abb0f93cSkardel * Revision 4.19 2009/11/01 10:47:49 kardel 401abb0f93cSkardel * de-P() 402abb0f93cSkardel * 403abb0f93cSkardel * Revision 4.18 2009/11/01 08:46:46 kardel 404abb0f93cSkardel * clarify case FALLTHROUGH 405abb0f93cSkardel * 406abb0f93cSkardel * Revision 4.17 2005/04/16 17:32:10 kardel 407abb0f93cSkardel * update copyright 408abb0f93cSkardel * 409abb0f93cSkardel * Revision 4.16 2004/11/14 15:29:41 kardel 410abb0f93cSkardel * support PPSAPI, upgrade Copyright to Berkeley style 411abb0f93cSkardel * 412abb0f93cSkardel * Revision 4.13 1999/11/28 09:13:51 kardel 413abb0f93cSkardel * RECON_4_0_98F 414abb0f93cSkardel * 415abb0f93cSkardel * Revision 4.12 1999/02/28 13:00:08 kardel 416abb0f93cSkardel * *** empty log message *** 417abb0f93cSkardel * 418abb0f93cSkardel * Revision 4.11 1999/02/28 11:47:54 kardel 419abb0f93cSkardel * (struct trimble): new member t_utcknown 420abb0f93cSkardel * (cvt_trimtsip): fixed status monitoring, bad receiver states are 421abb0f93cSkardel * now recognized 422abb0f93cSkardel * 423abb0f93cSkardel * Revision 4.10 1999/02/27 15:57:15 kardel 424abb0f93cSkardel * use mmemcpy instead of bcopy 425abb0f93cSkardel * 426abb0f93cSkardel * Revision 4.9 1999/02/21 12:17:42 kardel 427abb0f93cSkardel * 4.91f reconcilation 428abb0f93cSkardel * 429abb0f93cSkardel * Revision 4.8 1998/11/15 20:27:58 kardel 430abb0f93cSkardel * Release 4.0.73e13 reconcilation 431abb0f93cSkardel * 432abb0f93cSkardel * Revision 4.7 1998/08/16 18:49:20 kardel 433abb0f93cSkardel * (cvt_trimtsip): initial kernel capable version (no more floats) 434abb0f93cSkardel * (clock_trimtsip =): new format name 435abb0f93cSkardel * 436abb0f93cSkardel * Revision 4.6 1998/08/09 22:26:05 kardel 437abb0f93cSkardel * Trimble TSIP support 438abb0f93cSkardel * 439abb0f93cSkardel * Revision 4.5 1998/08/02 10:37:05 kardel 440abb0f93cSkardel * working TSIP parser 441abb0f93cSkardel * 442abb0f93cSkardel * Revision 4.4 1998/06/28 16:50:40 kardel 443abb0f93cSkardel * (getflt): fixed ENDIAN issue 444abb0f93cSkardel * (getdbl): fixed ENDIAN issue 445abb0f93cSkardel * (getint): use get_msb_short() 446abb0f93cSkardel * (cvt_trimtsip): use gpstolfp() for conversion 447abb0f93cSkardel * 448abb0f93cSkardel * Revision 4.3 1998/06/13 12:07:31 kardel 449abb0f93cSkardel * fix SYSV clock name clash 450abb0f93cSkardel * 451abb0f93cSkardel * Revision 4.2 1998/06/12 15:22:30 kardel 452abb0f93cSkardel * fix prototypes 453abb0f93cSkardel * 454abb0f93cSkardel * Revision 4.1 1998/05/24 09:39:54 kardel 455abb0f93cSkardel * implementation of the new IO handling model 456abb0f93cSkardel * 457abb0f93cSkardel * Revision 4.0 1998/04/10 19:45:32 kardel 458abb0f93cSkardel * Start 4.0 release version numbering 459abb0f93cSkardel * 460abb0f93cSkardel * from V3 1.8 loginfo deleted 1998/04/11 kardel 461abb0f93cSkardel */ 462