From: Juergen Perlinger Date: Fri, 13 Sep 2019 06:18:14 +0000 (+0200) Subject: [Bug 3617] Add support for ACE III and Copernicus II receivers X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8193764becee25b8e612254aa9f90b4f3c416b72;p=thirdparty%2Fntp.git [Bug 3617] Add support for ACE III and Copernicus II receivers bk: 5d7b34a61pGLgi-kTf-9UCpuuc-_Mg --- diff --git a/ChangeLog b/ChangeLog index 20b3c6325..308a79e65 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,8 @@ * [Sec 3610] process_control() should bail earlier on short packets. stenn@ - Reported by Philippe Antoine +* [Bug 3617] Add support for ACE III and Copernicus II receivers + - integrated patch by Richard Steedman * [Bug 3613] Propagate noselect to mobilized pool servers - Reported by Martin Burnicki * [Bug 3611] NMEA time interpreted incorrectly diff --git a/html/drivers/driver29.html b/html/drivers/driver29.html index 4939d8012..0a5659c7f 100644 --- a/html/drivers/driver29.html +++ b/html/drivers/driver29.html @@ -11,7 +11,7 @@

Trimble Palisade and Thunderbolt Receivers

Last update: - 21-Oct-2010 23:44 + 13-Sep-2019 08:07 UTC


@@ -69,13 +69,28 @@ 9600 baud, 8-bits, 1-stop, no parity + + +
+ Serial I/O (Copernicus II):
+ + 38400 baud, 8-bits, 1-stop, no parity +

Description

The refclock_palisade driver supports Trimble Navigation's Palisade Smart Antenna GPS receiver.
Additional software and information about the Palisade GPS is available from: http://www.trimble.com/oem/ntp.
Latest NTP driver source, executables and documentation is maintained at: ftp://ftp.trimble.com/pub/ntp -

This documentation describes version 7.12 of the GPS Firmware and version 2.46 (July 15, 1999) and later, of the driver source.
 

+

This documentation describes version 7.12 of the GPS Firmware and version 2.46 (July 15, 1999) and later, of the driver source.

This documentation describes version 1 of the Thunderbolt Receiver Firmware, no tests have been made on further firmwares, please read "Notes on the Thunderbolt Receiver's Firmware" at the end of this documentation for more information.

+

This driver also supports the following receivers:

+
+

Endrun Technologies Praecis NTP server with GPS

+

Trimble Acutime Gold smart antenna

+

Trimble Resolution family

+

Trimble ACE III

+

Trimble Copernicus II

+

Operating System Compatibility

The Palisade driver has been tested on the following software and hardware platforms:
 
@@ -118,7 +133,7 @@

- Attention: Thunderbolt Receiver has not being tested on the previous software and hardware plataforms. + Attention: Other receiver types have not being tested on the previous software and hardware plataforms.

GPS Receiver

The Palisade GPS receiver is an 8-channel smart antenna, housing the GPS receiver, antenna and interface in a single unit, and is designed for rooftop deployment in static timing applications.

Palisade generates a PPS synchronized to UTC within +/- 100 ns.  The Palisade's external event input with 40 nanosecond resolution is utilized by the Palisade NTP driver for asynchronous precision time transfer.

@@ -232,7 +247,41 @@ # and set flag2 to turn off event polling.
fudge 127.127.29.0 flag2 1
#------------------------------------------------------------------------------
 

- Currently the Thunderbolt mode doesn't support event polling, the reasons are explained on the "Notes on the Thunderbolt Receiver's Firmware" section at the end of this documentation. + +

Resolution NTP Configuration file

+ #------------------------------------------------------------------------------ +

Configuration without event polling:
+ #------------------------------------------------------------------------------
+ # The Primary reference
+ server 127.127.29.0 mode 5 # Trimble Resolution GPS (Stratum 1).
+ # Set packet delay
+ fudge 127.127.29.0 time1 0.410
+ # and set flag2 to turn off event polling.
+ fudge 127.127.29.0 flag2 1
+ #------------------------------------------------------------------------------
 

+ +

ACE III NTP Configuration file

+ #------------------------------------------------------------------------------ +

Configuration with event polling:
+ #------------------------------------------------------------------------------
+ # The Primary reference
+ server 127.127.29.0 mode 6 # Trimble ACE III GPS (Stratum 1).
+ # Set packet delay
+ fudge 127.127.29.0 time1 0.720
+ #------------------------------------------------------------------------------
 

+ +

Copernicus II NTP Configuration file

+ #------------------------------------------------------------------------------ +

Configuration without event polling:
+ #------------------------------------------------------------------------------
+ # The Primary reference
+ server 127.127.29.0 mode 7 # Trimble Copernicus II GPS (Stratum 1).
+ # Set packet delay
+ fudge 127.127.29.0 time1 0.240
+ # and set flag2 to turn off event polling.
+ fudge 127.127.29.0 flag2 1
+ #------------------------------------------------------------------------------
 

+ Currently the Thunderbolt mode doesn't support event polling, the reasons are explained on the "Notes on the Thunderbolt Receiver's Firmware" section at the end of this documentation. The Resolution and Copernicus II modes require event polling to be disabled whereas the ACE III requires polling to be enabled.

Time Transfer and Polling

Time transfer to the NTP host is performed via the Palisade's comprehensive time packet output. The time packets are output once per second, and whenever an event timestamp is requested.

The driver requests an event time stamp at the end of each polling interval, by pulsing the RTS (request to send) line on the serial port. The Palisade GPS responds with a time stamped event packet.

@@ -269,7 +318,16 @@

Mode Parameter

mode number -
The mode parameter to the server command specifies the specific hardware this driver is for. The default is 0 for a normal Trimble Palisade. The other options are 1 for an Endrun Praecis in Trimble emulation mode, and 2 for the Trimble Thunderbolt GPS Disciplined Clock Receiver. +
+ The mode parameter to the server command specifies the specific hardware this driver is for. The default is 0 for a normal Trimble Palisade. The other options are: +
+

1 for an Endrun Praecis in Trimble emulation mode

+

2 for the Trimble Thunderbolt GPS Disciplined Clock Receiver

+

3 for the Acutime Gold smart antenna

+

5 for Trimble Resolution devices

+

6 for the Trimble ACE III board

+

7 for the Trimble Copernicus II device

+

DEFINEs

The following constants are defined in the driver source code. These defines may be modified to improve performance or adapt to new operating systems.
  @@ -290,16 +348,16 @@ Accuracy of time transfer 1 microsecond - - CURRENT_UTC - Valid GPS - UTC offset - 13 - SPEED232 Host RS-232 baud rate B9600 + + SPEED232COP + Host RS-232 baud rate (Copernicus II mode) + B38400 + TRMB_MINPOLL  Minimum polling interval diff --git a/ntpd/refclock_palisade.c b/ntpd/refclock_palisade.c index 492c149ad..e698d72cc 100644 --- a/ntpd/refclock_palisade.c +++ b/ntpd/refclock_palisade.c @@ -52,8 +52,6 @@ * * * - * 21/04/18: Added support for Resolution devices. - * * 31/03/06: Added support for Thunderbolt GPS Disciplined Clock. * Contact: Fernando Pablo Hauscarriaga * E-mail: fernandoph@iar.unlp.edu.ar @@ -67,6 +65,10 @@ * * 30/08/09: Added support for Trimble Acutime Gold Receiver. * Fernando P. Hauscarriaga (fernandoph@iar.unlp.edu.ar) + * + * 21/04/18: Added support for Resolution devices. + * + * 03/09/19: Added support for ACE III & Copernicus II. */ #ifdef HAVE_CONFIG_H @@ -117,6 +119,8 @@ static int decode_date(struct refclockproc *pp, const char *cp); #define CLK_ACUTIME 3 /* Trimble Acutime Gold */ #define CLK_ACUTIMEB 4 /* Trimble Actutime Gold Port B */ #define CLK_RESOLUTION 5 /* Trimble Resolution Receivers */ +#define CLK_ACE 6 /* Trimble ACE III */ +#define CLK_COPERNICUS 7 /* Trimble Copernicus II */ int praecis_msg; static void praecis_parse(struct recvbuf *rbufp, struct peer *peer); @@ -125,7 +129,6 @@ static void praecis_parse(struct recvbuf *rbufp, struct peer *peer); * They are taken from Markus Prosch */ -#ifdef PALISADE_SENDCMD_RESURRECTED /* * sendcmd - Build data packet for sending */ @@ -139,7 +142,6 @@ sendcmd ( *(buffer->data + 1) = (unsigned char)c; buffer->size = 2; } -#endif /* PALISADE_SENDCMD_RESURRECTED */ /* * sendsupercmd - Build super data packet for sending @@ -308,7 +310,9 @@ palisade_start ( /* * Open serial port. */ - fd = refclock_open(gpsdev, SPEED232, LDISC_RAW); + u_int speed; + speed = (CLK_TYPE(peer) == CLK_COPERNICUS) ? SPEED232COP : SPEED232; + fd = refclock_open(gpsdev, speed, LDISC_RAW); if (fd <= 0) { #ifdef DEBUG printf("Palisade(%d) start: open %s failed\n", unit, gpsdev); @@ -360,6 +364,20 @@ palisade_start ( ,unit); tio.c_cflag = (CS8|CLOCAL|CREAD|PARENB|PARODD); break; + case CLK_ACE: + msyslog(LOG_NOTICE, "Palisade(%d) ACE III mode enabled" + ,unit); + tio.c_cflag = (CS8|CLOCAL|CREAD|PARENB|PARODD); + break; + case CLK_COPERNICUS: + msyslog(LOG_NOTICE, "Palisade(%d) Copernicus II mode enabled" + ,unit); + /* Must use ORing/ANDing to set/clear c_cflag bits otherwise + CBAUD gets set back to 0. This ought to be an issue for + the other modes above but it seems that the baud rate + defaults to 9600 if CBAUD gets set to 0. */ + tio.c_cflag &= ~(PARENB|PARODD); + break; default: msyslog(LOG_NOTICE, "Palisade(%d) mode unknown",unit); break; @@ -524,6 +542,9 @@ TSIP_decode ( double secfrac; unsigned short event = 0; int mmday; + long tow; + uint16_t wn; + int GPS_UTC_Offset; struct palisade_unit *up; struct refclockproc *pp; @@ -539,7 +560,9 @@ TSIP_decode ( if ((up->type != CLK_THUNDERBOLT) && (up->type != CLK_ACUTIME ) && - (up->type != CLK_RESOLUTION) ) + (up->type != CLK_RESOLUTION ) && + (up->type != CLK_ACE ) && + (up->type != CLK_COPERNICUS ) ) { if ((up->rpt_buf[0] == (char) 0x41) || (up->rpt_buf[0] == (char) 0x46) || @@ -557,7 +580,7 @@ TSIP_decode ( } /* - * We cast both to u_char to as 0x8f uses the sign bit on a char + * We cast both to u_char as 0x8f uses the sign bit on a char */ if ((u_char) up->rpt_buf[0] == (u_char) 0x8f) { /* @@ -569,8 +592,6 @@ TSIP_decode ( return 0; switch (mb(0) & 0xff) { - int GPS_UTC_Offset; - long tow; case PACKET_8F0B: @@ -883,11 +904,70 @@ TSIP_decode ( #ifdef DEBUG printf("GPS TOW: %ld\n", (long)getlong((u_char *) &mb(0))); printf("GPS WN: %d\n", getint((u_char *) &mb(4))); - printf("GPS UTC-GPS Offser: %ld\n", (long)getlong((u_char *) &mb(6))); + printf("GPS UTC-GPS Offset: %ld\n", (long)getlong((u_char *) &mb(6))); #endif return 0; } + /* GPS time packet for ACE III or Copernicus II receiver */ + else if ((up->rpt_buf[0] == PACKET_41) && + ((up->type == CLK_ACE) || (up->type == CLK_COPERNICUS))) { +#ifdef DEBUG + if ((debug > 1) && (up->type == CLK_ACE)) + printf("TSIP_decode: Packet 0x41 seen in ACE III mode\n"); + if ((debug > 1) && (up->type == CLK_COPERNICUS)) + printf("TSIP_decode: Packet 0x41 seen in Copernicus II mode\n"); +#endif + if (up->rpt_cnt != LENCODE_41) { /* check length */ + refclock_report(peer, CEVNT_BADREPLY); + up->polled = -1; +#ifdef DEBUG + printf("TSIP_decode: unit %d: bad packet %02x len %d\n", + up->unit, up->rpt_buf[0] & 0xff, up->rpt_cnt); +#endif + return 0; + } + if (up->polled <= 0) + return 0; + tow = (long)getsingle((u_char *) &mb(0)); + wn = (uint16_t)getint((u_char *) &mb(4)); + GPS_UTC_Offset = (int)getsingle((u_char *) &mb(6)); + if (GPS_UTC_Offset == 0){ /* Check UTC Offset */ +#ifdef DEBUG + printf("TSIP_decode: UTC Offset Unknown\n"); +#endif + refclock_report(peer, CEVNT_BADREPLY); + up->polled = -1; + return 0; + } + /* Get date & time from WN & ToW minus offset */ + TCivilDate cd; + TGpsDatum wd; + l_fp ugo; /* UTC-GPS offset, negative number */ + ugo.Ul_i.Xl_i = (int32_t)-GPS_UTC_Offset; + ugo.l_uf = 0; + wd = gpscal_from_gpsweek((wn % 1024), (int32_t)tow, ugo); + gpscal_to_calendar(&cd, &wd); + pp->year = cd.year; + pp->day = cd.yearday; + pp->hour = cd.hour; + pp->minute = cd.minute; + pp->second = cd.second; + pp->nsec = 0; + pp->leap = LEAP_NOWARNING; +#ifdef DEBUG + if (debug > 1) { + printf("GPS TOW: %ld\n", tow); + printf("GPS WN: %d\n", wn); + printf("GPS UTC-GPS Offset: %d\n", GPS_UTC_Offset); + printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%09ld %02d/%02d/%04d ", + up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, pp->second, + pp->nsec, cd.month, cd.monthday, pp->year); + } +#endif + return 1; + } + /* Health Status for Acutime Receiver */ else if ((up->rpt_buf[0] == PACKET_46) & (up->type == CLK_ACUTIME)) { #ifdef DEBUG @@ -898,7 +978,7 @@ TSIP_decode ( printf ("Doing Position Fixes\n"); break; case 0x01: - printf ("Do no have GPS time yet\n"); + printf ("Do not have GPS time yet\n"); break; case 0x03: printf ("PDOP is too high\n"); @@ -943,6 +1023,73 @@ TSIP_decode ( return 0; } } + + /* Health Status for Copernicus II Receiver */ + else if ((up->rpt_buf[0] == PACKET_46) && (up->type == CLK_COPERNICUS)) { +#ifdef DEBUG + if (debug > 1) + /* Status Codes */ + switch (mb(0)) { + case 0x00: + printf ("Doing Position Fixes\n"); + break; + case 0x01: + printf ("Do not have GPS time yet\n"); + break; + case 0x03: + printf ("PDOP is too high\n"); + break; + case 0x04: + printf("The Chosen satellite is unusable\n"); + break; + case 0x08: + printf ("No usable satellites\n"); + break; + case 0x09: + printf ("Only 1 usable satellite\n"); + break; + case 0x0A: + printf ("Only 2 usable satellites\n"); + break; + case 0x0B: + printf ("Only 3 usable satellites\n"); + break; + } +#endif + /* Error Codes */ + if ((mb(1) & 0x3E) != 0) { /* Don't regard bits 0 and 6 as errors */ + refclock_report(peer, CEVNT_BADTIME); + up->polled = -1; +#ifdef DEBUG + if (debug > 1) { + if ((mb(1) & 0x18) == 0x08) + printf ("Antenna feed line fault (open)\n"); + if ((mb(1) & 0x18) == 0x18) + printf ("Antenna feed line fault (short)\n"); + } +#endif + } + return 0; + } + + /* Other packets output by ACE III & Copernicus II Receivers, dropped silently */ + else if (((up->rpt_buf[0] == (char) 0x4A) || + (up->rpt_buf[0] == (char) 0x4B) || + (up->rpt_buf[0] == (char) 0x56) || + (up->rpt_buf[0] == (char) 0x5F) || + (up->rpt_buf[0] == (char) 0x6D) || + (up->rpt_buf[0] == (char) 0x82) || + (up->rpt_buf[0] == (char) 0x84)) && + ((up->type == CLK_ACE) || (up->type == CLK_COPERNICUS))) { +#ifdef DEBUG + if ((debug > 1) && (up->type == CLK_ACE)) + printf("TSIP_decode: Packet 0x%2x seen in ACE III mode\n", (up->rpt_buf[0] & 0XFF)); + if ((debug > 1) && (up->type == CLK_COPERNICUS)) + printf("TSIP_decode: Packet 0x%2x seen in Copernicus II mode\n", (up->rpt_buf[0] & 0XFF)); +#endif + return 0; + } + else if (up->rpt_buf[0] == 0x54) return 0; @@ -1232,9 +1379,19 @@ HW_poll ( { int x; /* state before & after RTS set */ struct palisade_unit *up; + struct packettx tx; up = pp->unitptr; + if (up->type == CLK_ACE) { + /* Poll by sending a 0x21 command */ + tx.size = 0; + tx.data = (u_char *) emalloc(100); + sendcmd (&tx, 0x21); + sendetx (&tx, pp->io.fd); + free(tx.data); + } else { + /* read the current status, so we put things back right */ if (ioctl(pp->io.fd, TIOCMGET, &x) < 0) { DPRINTF(1, ("Palisade HW_poll: unit %d: GET %m\n", @@ -1263,9 +1420,12 @@ HW_poll ( x &= ~TIOCM_RTS; /* turn off RTS */ + } /* (up->type != CLK_ACE) */ + /* poll timestamp */ get_systime(&pp->lastrec); + if (up->type != CLK_ACE) { if (ioctl(pp->io.fd, TIOCMSET, &x) == -1) { #ifdef DEBUG if (debug) @@ -1276,6 +1436,7 @@ HW_poll ( up->unit); return -1; } + } return 0; } @@ -1342,6 +1503,31 @@ getlong( return (int32)(u_int32)ntohl(u32); } +/* + * copy/swap a big-endian 32-bit single-precision floating point into a host 32-bit int + */ +static int32 +getsingle( + u_char *bp + ) +{ + u_int32 mantissa; + int8_t exponent; + uint8_t sign, exp_field; + int32 res; + + memcpy(&mantissa, bp, sizeof(mantissa)); + mantissa = ((u_int32)ntohl(mantissa) & 0x7FFFFF) | 0x800000; + exp_field = ((uint8_t)bp[0] << 1) + ((uint8_t)bp[1] >> 7); + exponent = (int8_t)exp_field - 127; + sign = ((uint8_t)bp[0] >> 7); + if (exponent > 23) + res = (int32)(mantissa << (exponent - 23)); + else + res = (int32)(mantissa >> (23 - exponent)); + return sign ? -res : res; +} + #else /* REFCLOCK && CLOCK_PALISADE*/ int refclock_palisade_c_notempty; #endif diff --git a/ntpd/refclock_palisade.h b/ntpd/refclock_palisade.h index 3782a5eb9..22dd36813 100644 --- a/ntpd/refclock_palisade.h +++ b/ntpd/refclock_palisade.h @@ -82,6 +82,7 @@ #include "ntp_control.h" #include "ntp_refclock.h" #include "ntp_unixtime.h" +#include "ntp_calgps.h" #include "ntp_stdlib.h" /* @@ -98,6 +99,7 @@ */ #define DEVICE "/dev/palisade%d" /* device name and unit */ #define SPEED232 B9600 /* uart speed (9600 baud) */ +#define SPEED232COP B38400 /* uart speed for Copernicus II (38400 baud) */ /* * TSIP Report Definitions @@ -108,6 +110,8 @@ #define LENCODE_8FAC 68 /* Length of Thunderbolt 8F-AC Position Packet*/ #define LENCODE_8FAB 17 /* Length of Thunderbolt Primary Timing Packet*/ +#define LENCODE_41 10 /* Length of Copernicus II GPS Time Packet*/ + /* Allowed Sub-Packet ID's */ #define PACKET_8F0B 0x0B #define PACKET_NTP 0xAD @@ -187,11 +191,10 @@ long HW_poll (struct refclockproc *); static double getdbl (u_char *); static short getint (u_char *); static int32 getlong (u_char *); +static int32 getsingle (u_char *); -#ifdef PALISADE_SENDCMD_RESURRECTED static void sendcmd (struct packettx *buffer, int c); -#endif static void sendsupercmd (struct packettx *buffer, int c1, int c2); static void sendbyte (struct packettx *buffer, int b); static void sendint (struct packettx *buffer, int a);