summaryrefslogtreecommitdiff
path: root/contrib/ntp/ntpd/refclock_palisade.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/ntp/ntpd/refclock_palisade.c')
-rw-r--r--contrib/ntp/ntpd/refclock_palisade.c248
1 files changed, 239 insertions, 9 deletions
diff --git a/contrib/ntp/ntpd/refclock_palisade.c b/contrib/ntp/ntpd/refclock_palisade.c
index d69ce9400e686..e698d72cc5219 100644
--- a/contrib/ntp/ntpd/refclock_palisade.c
+++ b/contrib/ntp/ntpd/refclock_palisade.c
@@ -65,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
@@ -114,6 +118,9 @@ static int decode_date(struct refclockproc *pp, const char *cp);
#define CLK_THUNDERBOLT 2 /* Trimble Thunderbolt GPS Receiver */
#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);
@@ -122,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
*/
@@ -136,7 +142,6 @@ sendcmd (
*(buffer->data + 1) = (unsigned char)c;
buffer->size = 2;
}
-#endif /* PALISADE_SENDCMD_RESURRECTED */
/*
* sendsupercmd - Build super data packet for sending
@@ -255,6 +260,37 @@ init_acutime (
}
/*
+ * init_resolution - Prepares Resolution receiver to be used with NTP
+ */
+static void
+init_resolution (
+ int fd
+ )
+{
+ struct packettx tx;
+
+ tx.size = 0;
+ tx.data = (u_char *) emalloc(100);
+
+ /* set UTC time */
+ sendsupercmd (&tx, 0x8E, 0xA2);
+ sendbyte (&tx, 0x3);
+ sendetx (&tx, fd);
+
+ /* squelch PPS output unless locked to at least one satellite */
+ sendsupercmd (&tx, 0x8E, 0x4E);
+ sendbyte (&tx, 0x3);
+ sendetx (&tx, fd);
+
+ /* activate packets 0x8F-AB and 0x8F-AC */
+ sendsupercmd (&tx, 0x8E, 0xA5);
+ sendint (&tx, 0x5);
+ sendetx (&tx, fd);
+
+ free(tx.data);
+}
+
+/*
* palisade_start - open the devices and initialize data for processing
*/
static int
@@ -274,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);
@@ -321,6 +359,25 @@ palisade_start (
msyslog(LOG_NOTICE, "Palisade(%d) Acutime Gold mode enabled"
,unit);
break;
+ case CLK_RESOLUTION:
+ msyslog(LOG_NOTICE, "Palisade(%d) Resolution mode enabled"
+ ,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;
@@ -371,6 +428,8 @@ palisade_start (
init_thunderbolt(fd);
if (up->type == CLK_ACUTIME)
init_acutime(fd);
+ if (up->type == CLK_RESOLUTION)
+ init_resolution(fd);
return 1;
}
@@ -483,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;
@@ -496,7 +558,12 @@ TSIP_decode (
* proper format, declare bad format and exit.
*/
- if ((up->type != CLK_THUNDERBOLT) & (up->type != CLK_ACUTIME)){
+ if ((up->type != CLK_THUNDERBOLT) &&
+ (up->type != CLK_ACUTIME ) &&
+ (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) ||
(up->rpt_buf[0] == (char) 0x54) ||
@@ -513,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) {
/*
@@ -525,8 +592,6 @@ TSIP_decode (
return 0;
switch (mb(0) & 0xff) {
- int GPS_UTC_Offset;
- long tow;
case PACKET_8F0B:
@@ -839,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
@@ -854,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");
@@ -899,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;
@@ -1188,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",
@@ -1219,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)
@@ -1232,6 +1436,7 @@ HW_poll (
up->unit);
return -1;
}
+ }
return 0;
}
@@ -1298,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