[Git][NTPsec/ntpsec][master] 16 commits: Updates to support Resolution, ACE III and Copernicus II devices

Gary E. Miller (@garyedmundsmiller) gitlab at mg.gitlab.com
Thu Mar 3 19:24:24 UTC 2022



Gary E. Miller pushed to branch master at NTPsec / ntpsec


Commits:
5796f027 by Richard Steedman at 2022-03-03T10:06:25+00:00
Updates to support Resolution, ACE III and Copernicus II devices

- - - - -
6c831c6a by wavelet27 at 2022-03-03T10:06:25+00:00
Updates to support Resolution, ACE III and Copernicus II devices

- - - - -
e5874b10 by wavelet27 at 2022-03-03T10:06:25+00:00
Updated description of time1 driver option

- - - - -
4d44b945 by Richard Steedman at 2022-03-03T10:06:25+00:00
Changed version to 4.00

- - - - -
06f9c6e8 by wavelet27 at 2022-03-03T10:06:25+00:00
Fixed table formatting

- - - - -
5b739887 by Richard Steedman at 2022-03-03T10:06:25+00:00
Fixes based on merge request feedback

- - - - -
7a717ebf by wavelet27 at 2022-03-03T10:06:25+00:00
Replaced multiple config examples with a table of settings

- - - - -
344a3ac0 by Richard Steedman at 2022-03-03T10:06:25+00:00
Further fixes in response to code review feedback

- - - - -
867c12da by Richard Steedman at 2022-03-03T10:06:25+00:00
Fixed portability issue

- - - - -
2198bd3a by Richard Steedman at 2022-03-03T10:06:25+00:00
More changes based on review feedback

- - - - -
71e3c34c by wavelet27 at 2022-03-03T10:06:25+00:00
Changed 'Resolution 360' to 'resolution SMT', clarified GPS to UTC conversion

- - - - -
640e02fd by Richard Steedman at 2022-03-03T10:06:25+00:00
Changed rpt_buf to unsigned char

- - - - -
671b07ab by wavelet27 at 2022-03-03T10:06:25+00:00
Added note about variety of Resolution receivers

- - - - -
314cd599 by Richard Steedman at 2022-03-03T10:06:25+00:00
Fixed day to yday change in a debug message

- - - - -
6b97103d by Richard Steedman at 2022-03-03T10:06:25+00:00
Fixed typos

- - - - -
5e8ab222 by Richard Steedman at 2022-03-03T10:06:25+00:00
More fixes from code review

- - - - -


6 changed files:

- docs/driver_trimble.adoc
- include/gpstolfp.h
- libparse/gpstolfp.c
- ntpd/refclock_oncore.c
- ntpd/refclock_trimble.c
- tests/libparse/gpstolfp.c


Changes:

=====================================
docs/driver_trimble.adoc
=====================================
@@ -1,4 +1,4 @@
-= Trimble Palisade/Thunderbolt/Acutime & Praecis Receivers
+= Trimble Palisade/Thunderbolt/Acutime/Resolution SMT/ACE III/Copernicus & Praecis Receivers
 include::include-html.ad[]
 
 [width="100%",cols="<50%,<50%",frame="none",grid="none"]
@@ -10,16 +10,23 @@ include::include-html.ad[]
 ["verse",subs="normal"]
 Name: trimble
 Reference ID: GPS
-Serial Port: /dev/trimble__u__; 9600 bps 8N1/8O1
+Serial Port: /dev/trimble__u__; 9600/38400 bps 8N1/8O1
 
 == Description
 
-The *refclock trimble* driver version 3.00 supports
+The *refclock trimble* driver version 4.00 supports
 ftp://ftp.trimble.com/pub/sct/embedded/bin/Manuals/Old%20Manuals/PALISADE.PDF[Trimble
-Navigation's Palisade Smart Antenna GPS receiver], Thunderbolt, Acutime 2000
-and Acutime Gold. The EndRun Technologies Praecis Cf, Ct, Ce, and II modules
+Navigation's Palisade Smart Antenna GPS receiver], Thunderbolt, Acutime 2000,
+Acutime Gold, Resolution SMT, ACE III and Copernicus II.
+The EndRun Technologies Praecis Cf, Ct, Ce, and II modules
 (in Palisade emulation mode) are also supported.
 
+There are a number of different Trimble receivers with "Resolution" as part of their name.
+The particular receiver supported by this driver is the "Resolution SMT", part number 66974-45.
+This receiver returns hardware code 3009 decimal when queried by a TSIP Hardware Component
+Information command packet.  It may also support the "Resolution T" receiver (hardware code 3002
+decimal) but has not been tested on that device.
+
 == Tested Receivers
 The driver has been tested with the following receivers :
 
@@ -31,10 +38,13 @@ The driver has been tested with the following receivers :
 | Thunderbolt  48051-61    | 3.00
 | Acutime 2000 39091-00    | 2.02
 | Acutime Gold 55238-00    | 1.12
+| Resolution SMT 66974-45  | 1.14
+| ACE III 39818-00-C       | 8.08
+| Copernicus II 63530-00   | 1.07.01
 |============================================
 
-The driver has been tested with the receivers listed above on the
-following host computers:
+The driver has been tested with the Palisade, Praecis, Thunderbolt and Acutime
+receivers on the following host computers:
 
 [width="50%",cols="<40%,<40%,<20%",options="header"]
 |===========================================
@@ -49,6 +59,9 @@ following host computers:
 3. Power Mac G5(7,2), DP 1.8GHz, StarTech PCI1S550, kernel 4.9.34
 4. Sun SPARC Enterprise T5220, onboard serial port, gcc 4.8.2
 
+The driver has been tested with the Resolution SMT, ACE and Copernicus
+receivers on a Rapsberry Pi 3 running Raspberry Pi OS (Legacy).
+
 
 [[sym]]
 == Operating System Serial Port Configuration
@@ -60,16 +73,19 @@ address when using the legacy syntax.
 The user must provide a symbolic link to an available serial port device. This
 is typically performed by a command such as:
 
-[width="50%",cols="<20%,<80%",options="header"]
-|=========================================
-|OS      | Command
-|FreeBSD | ln -s /dev/ttyu0 /dev/trimble0
-|Linux   | ln -s /dev/ttyS0 /dev/trimble0
-|Solaris | ln -s /dev/term/a /dev/trimble0
-|=========================================
-
-All receivers except the Thunderbolt have a factory default serial port
-configuration of 8O1 (odd parity). The Thunderbolt defaults to 8N1 (no parity).
+[width="50%",cols="<35%,<65%",options="header"]
+|=================================================
+|OS              | Command
+|FreeBSD         | ln -s /dev/ttyu0 /dev/trimble0
+|Linux           | ln -s /dev/ttyS0 /dev/trimble0
+|Solaris         | ln -s /dev/term/a /dev/trimble0
+|Raspberry Pi OS | ln -s /dev/ttyAMA0 /dev/trimble0
+|=================================================
+
+The receivers supported by this driver have a factory default serial port
+configuration of 8O1 (odd parity) except the Thunderbolt and Copernicus II which
+default to 8N1 (no parity).  They have a factory default serial port
+speed of 9600 baud except the Copernicus II which defaults to 38400 baud.
 The driver automatically sets the baud rate and parity of the host to
 match the receiver's factory default values.
 
@@ -78,16 +94,33 @@ match the receiver's factory default values.
 
 NTP configuration file "{ntpconf}"
 
-Acutime 2000 or Acutime Gold:
 ---------------------------------
-refclock trimble unit 0 subtype 3
+refclock trimble unit X subtype Y
 ---------------------------------
 
-Thunderbolt:
+or
+
 ---------------------------------------------
-refclock trimble unit 0 subtype 2 time1 0.020
+refclock trimble unit X subtype Y time1 Z.ZZZ
 ---------------------------------------------
 
+Substituting an appropriate unit number for X. For subtype Y refer to this table:
+
+[width="50%",cols="<50%,<50%",options="header"]
+|=================================
+| subtype | Model
+| 0 |  Palisade
+| 1 |  Praecis
+| 2 |  Thunderbolt
+| 3 |  Acutime 2000 & Acutime Gold
+| 5 |  Resolution SMT
+| 6 |  ACE III
+| 7 |  Copernicus II
+|=================================
+
+Use the 'time Z.ZZZ' option if the delay introduced by decoding of serial messages from the receiver causes the reference clock to appear to be offset compared with other time sources.
+(If the reference clock appears to have an offset of -50ms for example, set time1 to +0.05.)
+
 
 == Initial Setup and Testing for Palisade / Acutime Receivers
 1.  Read the xref:Pal[Palisade / Acutime] notes.
@@ -186,6 +219,74 @@ refclock trimble unit 0 subtype 2 time1 0.020
     set ON. See the Praecis manual for the command to change this setting.
 
 
+== Initial Setup and Testing for Resolution SMT Receivers
+1.  Read the xref:Res[Resolution SMT] notes.
+2.  Power up and allow the receiver to obtain UTC offset data. This can take
+    13 to 30 minutes.
+3.  Configure the serial I/O port and its xref:sym[symbolic link] on the host.
+4.  Add the refclock to your +ntpd+ xref:cfg[configuration file].
+5.  Run +ntpd+ with debug level 2 without detaching from the terminal
+    (-d -d -n). Note: debug level 1 may also be used; only errors will be
+	printed to stdout.
+6.  Check the ntpd xref:log[event log] or stdout for a line similar to
+'TRIMBLE(0) open at /dev/trimble0' to verify that your serial port opened.
+7.  The driver will print +TSIP_decode+ lines to stdout as it processes
+    message packets from the receiver. Note: ntpd must be built with debugging
+	enabled to see +TSIP_decode+ +trimble_poll+ and +trimble_receive+ messages
+..  Check your serial connection if 'trimble_poll: unit __u__: no packets found'
+    appears.
+... The driver may print the message
+    'trimble_poll: unit __u__: packets found but none were usable' to stdout if
+    it failed to reconfigure the receiver to transmit auto-report superpackets.
+8. The driver will print a +trimble_poll+ line with a timecode to stdout when
+    time is successfully transferred.
+..  If TSIP_decode lines are seen but trimble_receive never appears:
+... TSIP_decode lines with 'misconfigured' will appear if the driver failed
+    to reconfigure the receiver at startup.
+
+
+== Initial Setup and Testing for ACE III Receivers
+1.  Read the xref:ACE[ACE III] notes.
+2.  Place the GPS antenna outdoors, with a clear view of the sky for best
+    results -- ACE III is not very good at tracking weak signals.
+3.  Power up and allow the receiver to obtain UTC offset data. This can take
+    13 to 30 minutes.
+4.  Configure the serial I/O port and its xref:sym[symbolic link] on the host.
+5.  Add the refclock to your +ntpd+ xref:cfg[configuration file].
+6.  Run +ntpd+ with debug level 2 without detaching from the terminal
+    (-d -d -n). Note: debug level 1 may also be used; only errors will be
+	printed to stdout.
+7.  Check the ntpd xref:log[event log] or stdout for a line similar to
+'TRIMBLE(0) open at /dev/trimble0' to verify that your serial port opened.
+8.  The driver will print +TSIP_decode+ lines to stdout as it processes
+    message packets from the receiver. Note: ntpd must be built with debugging
+	enabled to see +TSIP_decode+ +trimble_poll+ and +trimble_receive+ messages
+..  Check your serial connection if 'trimble_poll: unit __u__: no packets found'
+    appears.
+9. The driver will print a +trimble_poll+ line with a timecode to stdout when
+    time is successfully transferred.
+
+
+== Initial Setup and Testing for Copernicus II Receivers
+1.  Read the xref:Cop[Copernicus II] notes.
+2.  Power up and allow the receiver to obtain UTC offset data. This can take
+    13 to 30 minutes.
+3.  Configure the serial I/O port and its xref:sym[symbolic link] on the host.
+4.  Add the refclock to your +ntpd+ xref:cfg[configuration file].
+5.  Run +ntpd+ with debug level 2 without detaching from the terminal
+    (-d -d -n). Note: debug level 1 may also be used; only errors will be
+	printed to stdout.
+6.  Check the ntpd xref:log[event log] or stdout for a line similar to
+'TRIMBLE(0) open at /dev/trimble0' to verify that your serial port opened.
+7.  The driver will print +TSIP_decode+ lines to stdout as it processes
+    message packets from the receiver. Note: ntpd must be built with debugging
+	enabled to see +TSIP_decode+ +trimble_poll+ and +trimble_receive+ messages
+..  Check your serial connection if 'trimble_poll: unit __u__: no packets found'
+    appears.
+8. The driver will print a +trimble_poll+ line with a timecode to stdout when
+    time is successfully transferred.
+
+
 [[log]]
 == Event Logging
 
@@ -204,8 +305,7 @@ NTP error messages. Log entries generated by the driver will be of the form:
 
 [[t1]]+time1+ 'time'::
   Specifies the time offset calibration factor, in seconds and fraction,
-  with default 0.0. 'time1' should be set to about 20 ms when using a
-  Thunderbolt.
+  with default 0.0.
 
 [[t2]]+time2+ 'time'::
   Specifies the holdover duration for Thunderbolt, in seconds, with
@@ -225,12 +325,13 @@ NTP error messages. Log entries generated by the driver will be of the form:
 +flag2 {0 | 1}+::
   Not used by this driver. NOTE: Versions of the driver before 3.00 used flag2
   to disable hardware event capture. Event capture is now required for all
-  receivers except the Thunderbolt.
+  receivers except the Thunderbolt, Resolution SMT and Copernicus II.
 
 [[f3]]+flag3 {0 | 1}+::
   Specifies the method used for triggering the receiver's hardware event input.
   The default of 0 uses the serial port RTS line. Set to 1 to use the serial
-  port's TXD line instead of RTS. Value is ignored when using a Thunderbolt.
+  port's TXD line instead of RTS. Value is ignored when using a Thunderbolt, 
+  Resolution SMT, ACE III or Copernicus II.
 
 +flag4 {0 | 1}+::
   Not used by this driver.
@@ -244,6 +345,9 @@ NTP error messages. Log entries generated by the driver will be of the form:
 | 1 | Praecis
 | 2 | Thunderbolt
 | 3 | Acutime 2000 & Acutime Gold
+| 5 | Resolution SMT
+| 6 | ACE III
+| 7 | Copernicus II
 |================================
 note: There is currently no difference between subtype 0 and subtype 3 other
 than the driver startup message.
@@ -382,7 +486,8 @@ mentioned in the receiver manual.
 
 The driver will attempt to set the time report packet and PPS output alignment
 to UTC time since the Thunderbolt defaults to GPS alignment. Time transfer will
-not be allowed unless the receiver reports that it is aligned to UTC time.
+not be allowed unless the receiver reports that it has received the leap second
+offset between GPS and UTC time and is outputting UTC time.
 
 The Thunderbolt does not have an event input. Initially it was thought that
 the firmware could be upgraded to enable event input so that it would operate
@@ -417,7 +522,96 @@ Time transfer during holdover may be enabled by setting xref:t2[time2] to the
 maximum allowable holdover duration in seconds.
 
 
+[[Res]]
+== Resolution SMT Notes
+
+The driver will attempt to set the time report packet and PPS output alignment
+to UTC time since the Resolution SMT defaults to GPS alignment. Time transfer will
+not be allowed unless the receiver reports that it has received the leap second
+offset between GPS and UTC time and is outputting UTC time.  The
+driver will also set the receiver not to output a PPS unless at least one
+satellite is being received.
+
+The Resolution SMT does not have an event input.  The driver therefore uses the
+timecode packets transmitted by the receiver after the beginning of each
+second.  It takes approximately 0.42s to receive the primary and secondary
+timecode packets.  For this reason the xref:t1[+time1+] should be
+set to about 420 ms. The link:driver_pps.html[+pps+] driver should be used along
+with this driver for best results.
+
+The Resolution SMT will have a "GPS Week Number Rollover" problem after
+the following dates:
+[width="50%",cols="<50%,<50%",options="header"]
+|=============================
+| F/W version  | Rollover Date
+| pre-v1.14    | 19-Jun-2027
+| v1.14        | 10-May-2031
+| v2.02        | 21-Aug-2032
+|=============================
+The same workaround mentioned in the
+xref:Pal[Palisade / Acutime Notes] section is implemented for the Resolution SMT.
+
+The receiver must know the current UTC offset from GPS time to be usable with
+ntpd. The receiver automatically decodes the UTC offset data from the +Almanac+
+transmitted by GPS satellites. With good antenna placement, Almanac reception
+can be expected to take 13 minutes or more after receiver power-up. The driver
+will wait for the receiver to report that its UTC offset is valid before
+enabling time transfer.
+
+
+[[ACE]]
+== ACE III Notes
+
+The ACE III does not have an event input.  Rather, the receiver is polled
+by the driver transmitting a 0x21 command to the receiver every second.  The
+link:driver_pps.html[+pps+] driver should be used along
+with this driver for best results.
+
+The timecode packet output by the ACE III contains only the GPS week number,
+time within the week and UTC offset.  A "GPS Week Number Rollover" workaround
+is therefore needed to convert the reported time to UTC.  The same
+workaround mentioned in the xref:Pal[Palisade / Acutime Notes] section is
+implemented for the ACE III.
+
+The receiver must know the current UTC offset from GPS time (caused by insertion or
+deletion of leap seconds in UTC) to be usable with
+ntpd. The receiver automatically decodes the UTC offset data from the +Almanac+
+transmitted by GPS satellites. With good antenna placement, Almanac reception
+can be expected to take 13 minutes or more after receiver power-up. The driver
+will wait for the receiver to report that its UTC offset is valid before
+enabling time transfer.
+
+
+[[Cop]]
+== Copernicus II Notes
+
+The Copernicus II does not have an event input.  The driver therefore uses the
+timecode packet transmitted by the Copernicus II after the beginning of each
+second.  It takes approximately 0.14s to receive the timecode packet.
+For this reason the xref:t1[+time1+] should be set to about 140 ms.
+The link:driver_pps.html[+pps+] driver should be used along
+with this driver for best results.
+
+The timecode packet output by the ACE III contains only the GPS week number,
+time within the week and UTC offset.  A "GPS Week Number Rollover" workaround
+is therefore needed to convert the reported time to UTC.  The same
+workaround mentioned in the xref:Pal[Palisade / Acutime Notes] section is
+implemented for the Copernicus II.
+
+The receiver must know the current UTC offset from GPS time (caused by insertion or
+deletion of leap seconds in UTC) to be usable with
+ntpd. The receiver automatically decodes the UTC offset data from the +Almanac+
+transmitted by GPS satellites. With good antenna placement, Almanac reception
+can be expected to take 13 minutes or more after receiver power-up. The driver
+will wait for the receiver to report that its UTC offset is valid before
+enabling time transfer.
+
+
 == Change Log
+Since version 3.00 (2017-23-09) +
+4.00 +
+* add support for Resolution SMT, ACE III and Copernicus II receivers +
+
 Since version 2.45 (2008-30-09) +
 3.00 +
 * add GPS week number rollover workaround +


=====================================
include/gpstolfp.h
=====================================
@@ -7,5 +7,5 @@
 
 extern void gpstolfp (int weeks, int days, unsigned long seconds, l_fp *);
 extern void gpsweekadj (unsigned int * week, unsigned int build_week);
-extern void gpstocal (unsigned int week, unsigned int TOW, int UTC_offset, struct calendar *);
-extern void caltogps (const struct calendar *, int UTC_offset, unsigned int * week, unsigned int * TOW);
+extern void gpstocal (unsigned int week, unsigned long int TOW, int UTC_offset, struct calendar *);
+extern void caltogps (const struct calendar *, int UTC_offset, unsigned int * week, unsigned long int * TOW);


=====================================
libparse/gpstolfp.c
=====================================
@@ -48,7 +48,7 @@ gpsweekadj(
 void
 gpstocal(
 	unsigned int week,
-	unsigned int TOW,
+	unsigned long int TOW,
 	int UTC_offset,
 	struct calendar * out
 	)
@@ -57,7 +57,7 @@ gpstocal(
 
 	t = (time64_t)((int64_t)GPSORIGIN - UTC_offset);
 	t += (time64_t)week * SECSPERWEEK;
-	t += TOW;
+	t += (time64_t)TOW;
 
 	ntpcal_ntp64_to_date(out, t);
 }
@@ -68,7 +68,7 @@ caltogps(
 	const struct calendar * in,
 	int UTC_offset,
 	unsigned int * week,
-	unsigned int * TOW
+	unsigned long int * TOW
 	)
 {
 	time64_t t;
@@ -76,9 +76,9 @@ caltogps(
 	t = ntpcal_dayjoin(ntpcal_date_to_rd(in) - DAY_NTP_STARTS,
 	                             ntpcal_date_to_daysec(in));
 	t -= (uint64_t)((int64_t)GPSORIGIN - UTC_offset);
-	*week = t / SECSPERWEEK;
+	*week = (unsigned int)(t / SECSPERWEEK);
 	if (NULL != TOW) {
-		*TOW = t % SECSPERWEEK;
+		*TOW = (unsigned long int)(t % SECSPERWEEK);
 	}
 }
 


=====================================
ntpd/refclock_oncore.c
=====================================
@@ -2530,7 +2530,8 @@ oncore_msg_Bl(
 	size_t	len
 	)
 {
-	int	subframe, valid, page, i, j, tow;
+	int	subframe, valid, page, i, j;
+	long int tow;
 	int	day_now, day_lsf;
 	const char	*cp;
 	enum {


=====================================
ntpd/refclock_trimble.c
=====================================
@@ -1,12 +1,12 @@
 /*
  * refclock_trimble - clock driver for the Trimble Palisade, Thunderbolt,
- * Acutime 2000, Acutime Gold and EndRun Technologies Praecis Ct/Cf/Ce/II
- * timing receivers
+ * Acutime 2000, Acutime Gold, Resolution SMT, ACE III, Copernicus II and
+ * EndRun Technologies Praecis Ct/Cf/Ce/II timing receivers
  *
  * For detailed information on this program, please refer to the
  * driver_trimble.html document accompanying the NTPsec distribution.
  *
- * Version 3.00; September 17, 2017
+ * Version 4.00; Febuary 15, 2022
  * refer to driver_trimble.html for change log
  *
  * This software was developed by the Software and Component Technologies
@@ -41,7 +41,7 @@
 /*
  * GPS Definitions
  */
-#define	DESCRIPTION	"Trimble Palisade/Thunderbolt/Acutime GPSes" /* Long name */
+#define	DESCRIPTION	"Trimble Palisade/Thunderbolt/Acutime/Resolution SMT/ACE/Copernicus GPSes" /* Long name */
 #define NAME		"TRIMBLE"	/* shortname */
 #define	PRECISION	(-20)		/* precision assumed (about 1 us) */
 #define	REFID		"GPS\0"		/* reference ID */
@@ -58,6 +58,7 @@
 #define	DEVICE		"/dev/palisade%d" 	/* device name and unit */
 #endif
 #define	SPEED232	B9600		  	/* uart speed (9600 baud) */
+#define	SPEED232COP	B38400		  	/* uart speed for Copernicus II (38400 baud) */
 
 /* parse consts */
 #define RMAX 172 /* TSIP packet 0x58 can be 172 bytes */
@@ -85,7 +86,7 @@
 #endif
 
 /*
- * Structure for build data packets for send (thunderbolt uses it only)
+ * Structure for build data packets for send (used by thunderbolt, ACE III and resolution SMT)
  * taken from Markus Prosch
  */
 struct packettx
@@ -98,45 +99,50 @@ struct packettx
  * Trimble unit control structure.
  */
 struct trimble_unit {
-	short		unit;		/* NTP refclock unit number */
-	bool		got_pkt;	/* decoded a packet this poll */
-	bool		got_time;	/* got a time packet this poll */
-	int		samples;	/* samples in filter this poll */
-	unsigned char	UTC_flags;	/* UTC & leap second flag */
-	unsigned char	trk_status;	/* reported tracking status */
-	char		rpt_status;	/* TSIP Parser State */
-	size_t 		rpt_cnt;	/* TSIP packet length so far */
-	char 		rpt_buf[RMAX]; 	/* packet assembly buffer */
-	int		type;		/* Clock mode type */
-	bool		use_event;	/* receiver has event input */
-	int		MCR;		/* modem control register value at startup */
-	bool		parity_chk;	/* enable parity checking */
-	l_fp		p_recv_time;	/* timestamp of last received packet */
-	unsigned int	week;		/* GPS week number */
-	unsigned int	TOW;		/* GPS time of week */
-	int		UTC_offset;	/* GPS-UTC offset */
-	struct calendar	date;		/* calendar to avoid leap early announce */
-	unsigned int	build_week;	/* GPS week number of ntpd build date */
+	short			unit;		/* NTP refclock unit number */
+	bool			got_pkt;	/* decoded a packet this poll */
+	bool			got_time;	/* got a time packet this poll */
+	int			samples;	/* samples in filter this poll */
+	unsigned char		UTC_flags;	/* UTC & leap second flag */
+	unsigned char		trk_status;	/* reported tracking status */
+	char			rpt_status;	/* TSIP Parser State */
+	size_t 			rpt_cnt;	/* TSIP packet length so far */
+	unsigned char 		rpt_buf[RMAX];	/* packet assembly buffer */
+	int			type;		/* Clock mode type */
+	bool			use_event;	/* receiver has event input */
+	bool			event_reply;	/* response to event input has been received */
+	int			MCR;		/* modem control register value at startup */
+	bool			parity_chk;	/* enable parity checking */
+	l_fp			p_recv_time;	/* timestamp of last received packet */
+	unsigned int		week;		/* GPS week number */
+	unsigned long int	TOW;		/* GPS time of week */
+	int			UTC_offset;	/* GPS-UTC offset */
+	struct  calendar	date;		/* calendar to avoid leap early announce */
+	unsigned int		build_week;	/* GPS week number of ntpd build date */
 };
 
 /*
  * Function prototypes
  */
-static	bool	trimble_start		(int, struct peer *);
-static	void	trimble_poll		(int, struct peer *);
-static	void	trimble_timer		(int, struct peer *);
-static	void 	trimble_io		(struct recvbuf *);
-static	void	trimble_receive		(struct peer *, int);
-static	bool	TSIP_decode		(struct peer *);
-static	void	HW_poll			(struct refclockproc *);
-static	double	getdbl 			(uint8_t *);
-static	short	getint 			(uint8_t *);
-static	int32_t	getlong			(uint8_t *);
-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);
-static  int	sendetx			(struct packettx *buffer, int fd);
-static  void	init_thunderbolt	(int fd);
+static	bool		trimble_start		(int, struct peer *);
+static	void		trimble_poll		(int, struct peer *);
+static	void		trimble_timer		(int, struct peer *);
+static	void 		trimble_io		(struct recvbuf *);
+static	void		trimble_receive		(struct peer *, int);
+static	bool		TSIP_decode		(struct peer *);
+static	void		HW_poll			(struct refclockproc *);
+static	float		getsgl			(uint8_t *);
+static	double		getdbl 			(uint8_t *);
+static	int16_t		gets16	 		(uint8_t *);
+static	uint16_t	getu16	 		(uint8_t *);
+static	uint32_t	getu32			(uint8_t *);
+static  void		sendcmd			(struct packettx *buffer, int c);
+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);
+static  int		sendetx			(struct packettx *buffer, int fd);
+static  void		init_thunderbolt	(int fd);
+static  void		init_resolution_smt	(int fd);
 
 #define PAL_TSTATS 14
 #ifdef DEBUG
@@ -181,15 +187,32 @@ struct refclock refclock_trimble = {
 #define CLK_TYPE(x) ((int)(((x)->cfg.mode) & 0x7F))
 
 /* Supported clock types */
-#define CLK_PALISADE	0	/* Trimble Palisade */
-#define CLK_PRAECIS	1	/* Endrun Technologies Praecis */
-#define CLK_THUNDERBOLT	2	/* Trimble Thunderbolt GPS Receiver */
-#define CLK_ACUTIME     3	/* Trimble Acutime Gold */
+#define CLK_PALISADE		0	/* Trimble Palisade */
+#define CLK_PRAECIS		1	/* Endrun Technologies Praecis */
+#define CLK_THUNDERBOLT		2	/* Trimble Thunderbolt GPS Receiver */
+#define CLK_ACUTIME   		3	/* Trimble Acutime Gold */
+#define CLK_RESOLUTIONSMT	5	/* Trimble Resolution SMT Receivers */
+#define CLK_ACE			6	/* Trimble ACE III */
+#define CLK_COPERNICUS		7	/* Trimble Copernicus II */
 
 /* packet 8f-ad UTC flags */
 #define UTC_AVAILABLE	0x01
 #define LEAP_SCHEDULED	0x10
 
+/*
+ * sendcmd - Build data packet for sending
+ */
+static void
+sendcmd (
+	struct packettx *buffer,
+	int c
+	)
+{
+	*buffer->data = DLE;
+	*(buffer->data + 1) = (unsigned char)c;
+	buffer->size = 2;
+}
+
 /*
  * sendsupercmd - Build super data packet for sending
  */
@@ -265,14 +288,10 @@ init_thunderbolt (
 	)
 {
 	struct packettx tx;
+	uint8_t tx_data[10];
 
 	tx.size = 0;
-	tx.data = (uint8_t *) malloc(100);
-
-	if (NULL == tx.data) {
-	        msyslog(LOG_ERR, "REFCLOCK: init_thunderbolt malloc failed");
-		exit(3);
-	}
+	tx.data = tx_data;
 
 	/* set UTC time */
 	sendsupercmd (&tx, 0x8E, 0xA2);
@@ -283,8 +302,37 @@ init_thunderbolt (
 	sendsupercmd (&tx, 0x8E, 0xA5);
 	sendint      (&tx, 0x5);
 	sendetx      (&tx, fd);
+}
 
-	free(tx.data);
+/*
+ * init_resolution_smt - Prepares Resolution SMT receiver to be used with
+ *		         NTP (also taken from Markus Prosch).
+ */
+static void
+init_resolution_smt (
+	int fd
+	)
+{
+	struct packettx tx;
+	uint8_t tx_data[10];
+
+	tx.size = 0;
+	tx.data = tx_data;
+
+	/* 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);
 }
 
 /*
@@ -300,6 +348,7 @@ trimble_start (
 	struct refclockproc *pp;
 	int fd;
 	struct termios tio;
+	speed_t desired_speed;
 	struct calendar build_date;
 	unsigned int cflag, iflag;
 	char device[20], *path;
@@ -324,7 +373,8 @@ trimble_start (
 	    path = device;
         }
 	fd = refclock_open(path,
-				  peer->cfg.baud ? peer->cfg.baud : SPEED232,
+				  peer->cfg.baud ? peer->cfg.baud :
+				  (CLK_TYPE(peer) == CLK_COPERNICUS) ? SPEED232COP : SPEED232,
 				  LDISC_RAW);
 	if (0 > fd) {
 	        msyslog(LOG_ERR, "REFCLOCK: %s Trimble device open(%s) failed",
@@ -377,6 +427,21 @@ trimble_start (
 		msyslog(LOG_NOTICE, "REFCLOCK: %s Acutime Gold mode enabled",
 			refclock_name(peer));
 		break;
+	    case CLK_RESOLUTIONSMT:
+		msyslog(LOG_NOTICE, "REFCLOCK: %s Resolution SMT mode enabled",
+			refclock_name(peer));
+		up->use_event = false;
+		break;
+	    case CLK_ACE:
+		msyslog(LOG_NOTICE, "REFCLOCK: %s ACE III mode enabled",
+			refclock_name(peer));
+		break;
+	    case CLK_COPERNICUS:
+		msyslog(LOG_NOTICE, "REFCLOCK: %s Copernicus II mode enabled",
+			refclock_name(peer));
+		up->use_event = false;
+		up->parity_chk = false;
+		break;
 	    default:
 	        msyslog(LOG_NOTICE, "REFCLOCK: %s mode unknown",
 			refclock_name(peer));
@@ -402,7 +467,25 @@ trimble_start (
 		free(up);
 		return false;
 	}
-	if (up->use_event) {
+	/*
+	 * On some OS's, the calls to tcsetattr and tcgetattr above reset the baud
+	 * rate to 0 as a side effect. Surprisingly, this doesn't appear to affect
+	 * the operation of devices running at 9600 baud but it certainly does
+	 * affect the 38400 baud Copernicus II.
+	 * As a workaround, apply the baud rate once more here.
+	 */
+	desired_speed = peer->cfg.baud ? peer->cfg.baud :
+	                (CLK_TYPE(peer) == CLK_COPERNICUS) ? SPEED232COP : SPEED232;
+	if (cfsetispeed(&tio, desired_speed) == -1 || cfsetospeed(&tio, desired_speed) == -1 ||
+	    tcsetattr(fd, TCSANOW, &tio) == -1) {
+		msyslog(LOG_ERR, "REFCLOCK: %s: failed to set device baud rate",
+		        refclock_name(peer));
+		close(fd);
+		free(up);
+		return false;
+	}
+
+	if (up->use_event && (up->type != CLK_ACE)) {
 		/*
 		 * The width of the RTS pulse must be either less than 5us or
 		 * greater than 600ms or the Acutime 2000 may try to switch its
@@ -476,6 +559,10 @@ trimble_start (
 		init_thunderbolt(fd);
 	}
 
+	if (up->type == CLK_RESOLUTIONSMT) {
+		init_resolution_smt(fd);
+	}
+
 	return true;
 }
 
@@ -492,6 +579,8 @@ TSIP_decode (
 	double secs, secfrac;
 	unsigned short event, m_alarms;
 	uint32_t holdover_t;
+	float TOWfloat;
+	uint32_t lastrec_frac;
 
 	struct trimble_unit *up;
 	struct refclockproc *pp;
@@ -502,8 +591,8 @@ TSIP_decode (
 
 	if (id == 0x8f) {
 		/* Superpackets */
-		event = (unsigned short) (getint((uint8_t *) &mb(1)) & 0xffff);
-		if ((up->type != CLK_THUNDERBOLT) && !event)
+		event = getu16(&mb(1));
+		if ((up->type != CLK_THUNDERBOLT) && (up->type != CLK_RESOLUTIONSMT) && !event)
 			/* ignore auto-report */
 			return false;
 
@@ -524,9 +613,9 @@ TSIP_decode (
 			if (debug > 1) { /* SPECIAL DEBUG */
 				int st, ts;
 				double lat, lon, alt;
-				lat = getdbl((uint8_t *) &mb(42)) * R2D;
-				lon = getdbl((uint8_t *) &mb(50)) * R2D;
-				alt = getdbl((uint8_t *) &mb(58));
+				lat = getdbl(&mb(42)) * R2D;
+				lon = getdbl(&mb(50)) * R2D;
+				alt = getdbl(&mb(58));
 
 				printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n",
 				       up->unit, lat,lon,alt);
@@ -546,7 +635,7 @@ TSIP_decode (
 				       tracking_status[up->trk_status]));
 				return false;
 			}
-			up->UTC_offset = getint((uint8_t *) &mb(16));
+			up->UTC_offset = gets16(&mb(16));
 			if (!(up->UTC_flags & UTC_AVAILABLE) ||
 			    (up->UTC_offset == 0)) {
 				pp->leap = LEAP_NOTINSYNC;
@@ -555,7 +644,7 @@ TSIP_decode (
 				return false;
 			}
 
-			secs = getdbl((uint8_t *) &mb(3));
+			secs = getdbl(&mb(3));
 			secint = (long) secs;
 			secfrac = secs - secint; /* 0.0 <= secfrac < 1.0 */
 
@@ -567,9 +656,9 @@ TSIP_decode (
 			up->date.minute = (int)(secint / 60);
 			secint %= 60;
 			up->date.second = secint % 60;
-			up->date.monthday = (uint8_t)mb(11);
-			up->date.month = (uint8_t)mb(12);
-			up->date.year = (uint16_t)getint((uint8_t *) &mb(13));
+			up->date.monthday = mb(11);
+			up->date.month = mb(12);
+			up->date.year = getu16(&mb(13));
 			up->date.yearday = 0;
 			caltogps(&up->date, up->UTC_offset, &up->week, &up->TOW);
 			gpsweekadj(&up->week, up->build_week);
@@ -607,11 +696,11 @@ TSIP_decode (
 			}
 
 			/* flags checked in 8f-0b for Palisade and Acutime */
-			up->trk_status = (unsigned char)mb(18);
+			up->trk_status = mb(18);
 			if (up->trk_status > PAL_TSTATS) {
 				up->trk_status = PAL_TSTATS;
 }
-			up->UTC_flags = (unsigned char)mb(19);
+			up->UTC_flags = mb(19);
 
 			/* get timecode from 8f-0b except with Praecis */
 			if (up->type != CLK_PRAECIS)
@@ -630,13 +719,13 @@ TSIP_decode (
 				return false;
 			}
 
-			pp->nsec = (long) (getdbl((uint8_t *) &mb(3)) * NS_PER_S);
-			up->date.year = (uint16_t)getint((uint8_t *) &mb(16));
-			up->date.hour = (uint8_t)mb(11);
-			up->date.minute = (uint8_t)mb(12);
-			up->date.second = (uint8_t)mb(13);
-			up->date.month = (uint8_t)mb(15);
-			up->date.monthday = (uint8_t)mb(14);
+			pp->nsec = (long) (getdbl(&mb(3)) * NS_PER_S);
+			up->date.year = getu16(&mb(16));
+			up->date.hour = mb(11);
+			up->date.minute = mb(12);
+			up->date.second = mb(13);
+			up->date.month = mb(15);
+			up->date.monthday = mb(14);
 			caltogps(&up->date, 0, &up->week, &up->TOW);
 			gpsweekadj(&up->week, up->build_week);
 			gpstocal(up->week, up->TOW, 0, &up->date);
@@ -659,7 +748,7 @@ TSIP_decode (
 		    case 0xAC:
 			/*
 			 * supplemental timing packet: sent after 8f-ab from
-			 * Thunderbolt
+			 * Thunderbolt and Resolution SMT
 			 */
 			if (up->rpt_cnt != 68) {
 				DPRINT(1, ("TSIP_decode: unit %d: 8f-ac packet length is not 68 (%d)\n",
@@ -671,18 +760,18 @@ TSIP_decode (
 #ifdef DEBUG
 			if (debug > 1) { /* SPECIAL DEBUG */
 				double lat, lon, alt;
-				lat = getdbl((uint8_t *) &mb(36)) * R2D;
-				lon = getdbl((uint8_t *) &mb(44)) * R2D;
-				alt = getdbl((uint8_t *) &mb(52));
+				lat = getdbl(&mb(36)) * R2D;
+				lon = getdbl(&mb(44)) * R2D;
+				alt = getdbl(&mb(52));
 				printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n",
 				       up->unit, lat,lon,alt);
 			}
 #endif
-			decod_stat = (unsigned char)mb(12);
+			decod_stat = mb(12);
 			if (decod_stat > TB_DECOD_STATS) {
 				decod_stat = TB_DECOD_STATS;
 }
-			disc_mode = (unsigned char)mb(2);
+			disc_mode = mb(2);
 			if (disc_mode > TB_DISC_MODES) {
 				disc_mode = TB_DISC_MODES;
 }
@@ -691,14 +780,14 @@ TSIP_decode (
 			       tracking_status[tb_decod_conv[decod_stat]],
 			       tb_disc_mode[disc_mode]));
 
-			m_alarms = (unsigned short)getint((uint8_t *) &mb(10));
+			m_alarms = getu16(&mb(10));
 			if (m_alarms & 0x200) {
 				DPRINT(1, ("TSIP_decode: unit %d: 'position questionable' flag is set,\n    you must update the unit's stored position.\n",
 				       up->unit));
 				return false;
 			}
 
-			holdover_t = (uint32_t)getlong((uint8_t *) &mb(4));
+			holdover_t = getu32(&mb(4));
 			if (!tracking_status_usable[tb_decod_conv[decod_stat]])	{
 				if (pp->fudgetime2 < 0.5) {
 					/* holdover not enabled */
@@ -734,7 +823,7 @@ TSIP_decode (
 			else
 				pp->leap = LEAP_NOWARNING;
 
-			DPRINT(2, ("TSIP_decode: unit %d: 8f-ac TOW: %u week: %u adj.t: %02d:%02d:%02d.0 %02d/%02d/%04d\n",
+			DPRINT(2, ("TSIP_decode: unit %d: 8f-ac TOW: %lu week: %u adj.t: %02d:%02d:%02d.0 %02d/%02d/%04d\n",
 			       up->unit, up->TOW, up->week,
 			       up->date.hour, up->date.minute, up->date.second,
 			       up->date.month, up->date.monthday, up->date.year));
@@ -744,7 +833,7 @@ TSIP_decode (
 		    case 0xAB:
 			/*
 			 * primary timing packet: first packet sent after PPS
-			 * from Thunderbolt
+			 * from Thunderbolt and Resolution SMT
 			 */
 			if (up->rpt_cnt != 17) {
 				DPRINT(1, ("TSIP_decode: unit %d: 8f-ab packet length is not 17 (%d)\n",
@@ -752,7 +841,7 @@ TSIP_decode (
 				refclock_report(peer, CEVNT_BADREPLY);
 				return 0;
 			}
-			timing_flags = (unsigned char)mb(9);
+			timing_flags = mb(9);
 #ifdef DEBUG
 			if (debug > 1) { /* SPECIAL DEBUG */
 				printf("TSIP_decode: unit %d: timing flags:0x%02X=\n",
@@ -784,7 +873,7 @@ TSIP_decode (
 			}
 #endif
 			up->UTC_flags = 0;
-			up->UTC_offset = getint((uint8_t *) &mb(7));
+			up->UTC_offset = gets16(&mb(7));
 			if (timing_flags & 0x04 || timing_flags & 0x08 ||
 			    up->UTC_offset == 0) {
 				DPRINT(1, ("TSIP_decode: unit %d: time not set or UTC offset unavailable\n",
@@ -804,8 +893,8 @@ TSIP_decode (
 				refclock_report(peer, CEVNT_BADTIME);
 				return false;
 			}
-			up->TOW = (uint32_t)getlong((uint8_t *) &mb(1));
-			up->week = (uint32_t)getint((uint8_t *) &mb(5));
+			up->TOW = getu32(&mb(1));
+			up->week = getu16(&mb(5));
 
 			pp->lastrec = up->p_recv_time;
 			pp->nsec = 0;
@@ -817,6 +906,64 @@ TSIP_decode (
 			break;
 		} /* switch */
 	}
+
+	else if (id == 0x41) {
+		/*
+		 * GPS time packet from ACE III or Copernicus II receiver.
+		 * The ACE III issues these in response to a HW poll.
+		 * The Copernicus II receiver issues these by default once a second.
+		 */
+		if ((up->type != CLK_ACE) && (up->type != CLK_COPERNICUS))
+			return false;
+
+		if (up->rpt_cnt != 10) {
+			DPRINT(1, ("TSIP_decode: unit %d: 41 packet length is not 10 (%d)\n",
+			       up->unit, (int)up->rpt_cnt));
+			refclock_report(peer, CEVNT_BADREPLY);
+			return false;
+		}
+
+		/*
+                 * A negative value of TOW indicates the receiver has not established the time.
+		 * This can occur even if UTC_offset is correct.
+		 */
+		TOWfloat = getsgl(&mb(0));
+		up->got_time = (TOWfloat >= 0);
+		if (!up->got_time)
+			return false;
+		up->TOW  = (unsigned long int)TOWfloat;
+		up->week = getu16(&mb(4));
+		up->UTC_offset = (int)getsgl(&mb(6));
+		if (up->UTC_offset == 0) {
+			DPRINT(1, ("TSIP_decode: unit %d: UTC data not available\n",
+			       up->unit));
+			return false;
+		}
+
+		gpsweekadj(&up->week, up->build_week);
+		gpstocal(up->week, up->TOW, up->UTC_offset, &up->date);
+
+		/*
+                 * The HW_poll occurs at 1Hz but with random phase w.r.t the system clock.
+                 * If we are using polling, cancel out the random phase offset by setting
+		 * pp->nsec to the fractional part of lastrec.
+		 */
+		if (up->use_event) {
+			lastrec_frac = lfpfrac(pp->lastrec);
+			secfrac = (double)lastrec_frac / FRAC;
+			pp->nsec = (long) (secfrac * NS_PER_S);
+		} else {
+			pp->lastrec = up->p_recv_time;
+			pp->nsec = 0;
+		}
+
+		DPRINT(2, ("TSIP_decode: unit %d: 41 TOW: %lu week: %u UTC %d adj.t: %02d:%02d:%02d.0 %02d/%02d/%04d\n",
+		       up->unit, up->TOW, up->week, up->UTC_offset,
+		       up->date.hour, up->date.minute, up->date.second,
+		       up->date.month, up->date.monthday, up->date.year));
+		return true;
+	}
+
 	return false;
 }
 
@@ -851,28 +998,37 @@ trimble_receive (
 		if (SPSTAT_LEN == up->rpt_cnt &&
 		    up->rpt_buf[up->rpt_cnt - 1] == '\r') {
 			up->rpt_buf[up->rpt_cnt - 1] = '\0';
-			record_clock_stats(peer, up->rpt_buf);
+			record_clock_stats(peer, (char *) up->rpt_buf);
 		}
 		return;
 	}
 
 	/* add sample to filter */
-	pp->lastref = pp->lastrec;
-	pp->year = up->date.year;
-	pp->yday = up->date.yearday;
-	pp->hour = up->date.hour;
-	pp->minute = up->date.minute;
-	pp->second = up->date.second;
-	DPRINT(2, ("trimble_receive: unit %d: %4d %03d %02d:%02d:%02d.%09ld\n",
-		   up->unit, pp->year, pp->yday, pp->hour, pp->minute,
-		   pp->second, pp->nsec));
-	if (!refclock_process(pp)) {
-		refclock_report(peer, CEVNT_BADTIME);
-		DPRINT(1, ("trimble_receive: unit %d: refclock_process failed!\n",
-		       up->unit));
-		return;
+	/*
+         * The ACE III receiver periodically outputs 0x41 packets by itself,
+         * i.e. in addition to those output in response to a poll command.
+	 * When this happens, two 0x41 packets with the same contents will be
+	 * received back to back.  Only process the first of these.
+	 */
+	if (!((up->type == CLK_ACE) && up->event_reply)) {
+		pp->lastref = pp->lastrec;
+		pp->year = up->date.year;
+		pp->yday = up->date.yearday;
+		pp->hour = up->date.hour;
+		pp->minute = up->date.minute;
+		pp->second = up->date.second;
+		DPRINT(2, ("trimble_receive: unit %d: %4d %03d %02d:%02d:%02d.%09ld\n",
+			   up->unit, pp->year, pp->yday, pp->hour, pp->minute,
+			   pp->second, pp->nsec));
+		if (!refclock_process(pp)) {
+			refclock_report(peer, CEVNT_BADTIME);
+			DPRINT(1, ("trimble_receive: unit %d: refclock_process failed!\n",
+			       up->unit));
+			return;
+		}
+		up->samples++;
+		up->event_reply = true;
 	}
-	up->samples++;
 }
 
 /*
@@ -1092,31 +1248,73 @@ HW_poll (
 
 	up = pp->unitptr;
 
-	/* Edge trigger */
-	if (pp->sloppyclockflag & CLK_FLAG3) {
-		IGNORE(write (pp->io.fd, "", 1));
+	struct packettx tx;
+	uint8_t tx_data[10];
+	if (up->type == CLK_ACE) {
+		/* Poll ACE III by sending a 0x21 command */
+		tx.size = 0;
+		tx.data = tx_data;
+		sendcmd (&tx, 0x21);
+		sendetx (&tx, pp->io.fd);
 	} else {
-		up->MCR &= ~TIOCM_RTS; /* set RTS low from high idle state */
-		IGNORE(ioctl(pp->io.fd, TIOCMSET, &up->MCR));
+		/* Edge trigger */
+		if (pp->sloppyclockflag & CLK_FLAG3) {
+			IGNORE(write (pp->io.fd, "", 1));
+		} else {
+			up->MCR &= ~TIOCM_RTS; /* set RTS low from high idle state */
+			IGNORE(ioctl(pp->io.fd, TIOCMSET, &up->MCR));
 
-		/*
-		 * The Acutime 2000 will occasionally transmit with parity
-		 * errors if the low state is held for less than 1ms, and the
-		 * Praecis will produce unstable timestamps if the low state is
-		 * held for less than 12ms.
-		 */
-		nanosleep(&ts, NULL);
+			/*
+			 * The Acutime 2000 will occasionally transmit with parity
+			 * errors if the low state is held for less than 1ms, and the
+			 * Praecis will produce unstable timestamps if the low state is
+			 * held for less than 12ms.
+			 */
+			nanosleep(&ts, NULL);
 
-		up->MCR |= TIOCM_RTS;  /* make edge / restore idle */
-		IGNORE(ioctl(pp->io.fd, TIOCMSET, &up->MCR));
+			up->MCR |= TIOCM_RTS;  /* make edge / restore idle */
+			IGNORE(ioctl(pp->io.fd, TIOCMSET, &up->MCR));
+		}
 	}
+	up->event_reply = 0;
 
 	/* get timestamp after triggering since RAND_bytes is slow */
 	get_systime(&pp->lastrec);
 }
 
 /*
- * getdbl - copy/swap a big-endian palisade double into a host double
+ * getsgl - copy/swap a big-endian Trimble single into a host float
+ */
+static float
+getsgl (
+	uint8_t *bp
+	)
+{
+#ifdef WORDS_BIGENDIAN
+	float out;
+
+	memcpy(&out, bp, sizeof(out));
+	return out;
+#else
+	union {
+		uint8_t ch[4];
+		uint32_t u32;
+	} ui;
+
+	union {
+		float out;
+		uint32_t u32;
+	} uo;
+
+	memcpy(ui.ch, bp, sizeof(ui.ch));
+	uo.u32 = ntohl(ui.u32);
+
+	return uo.out;
+#endif
+}
+
+/*
+ * getdbl - copy/swap a big-endian Trimble double into a host double
  */
 static double
 getdbl (
@@ -1150,29 +1348,43 @@ getdbl (
 }
 
 /*
- * getint - copy/swap a big-endian palisade short into a host short
+ * gets16 - copy/swap a big-endian Trimble SINT16 into a host int16_t
+ */
+static int16_t
+gets16 (
+	uint8_t *bp
+	)
+{
+	int16_t us;
+
+	memcpy(&us, bp, sizeof(us));
+	return ntohs(us);
+}
+
+/*
+ * getu16 - copy/swap a big-endian Trimble UINT16 into a host uint16_t
  */
-static short
-getint (
+static uint16_t
+getu16 (
 	uint8_t *bp
 	)
 {
-	unsigned short us;
+	uint16_t us;
 
 	memcpy(&us, bp, sizeof(us));
-	return (short)ntohs(us);
+	return ntohs(us);
 }
 
 /*
- * getlong -copy/swap a big-endian palisade 32-bit int into a host 32-bit int
+ * getu32 -copy/swap a big-endian Trimble UINT32 into a host uint32_t
  */
-static int32_t
-getlong(
+static uint32_t
+getu32(
 	uint8_t *bp
 	)
 {
 	uint32_t u32;
 
 	memcpy(&u32, bp, sizeof(u32));
-	return (int32_t)(uint32_t)ntohl(u32);
+	return ntohl(u32);
 }


=====================================
tests/libparse/gpstolfp.c
=====================================
@@ -15,7 +15,8 @@ TEST_TEAR_DOWN(gpstolfp){}
 TEST(gpstolfp, check) {
 	uint64_t build_t, gps_t;
 	struct calendar in, out;
-	unsigned int build_week, week, TOW;
+	unsigned int build_week, week;
+	unsigned long int TOW;
 
 	unsigned int bw[] = {MIN_BUILD_GPSWEEK, 2048, MAX_BUILD_GPSWEEK};
 	uint16_t by[] = {2016, 2019, 2096};



View it on GitLab: https://gitlab.com/NTPsec/ntpsec/-/compare/d1897775df7b103c135787b88ef31cbc59719be3...5e8ab22272bf6fb580b5cfd6d00df225d4959e5d

-- 
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/-/compare/d1897775df7b103c135787b88ef31cbc59719be3...5e8ab22272bf6fb580b5cfd6d00df225d4959e5d
You're receiving this email because of your account on gitlab.com.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.ntpsec.org/pipermail/vc/attachments/20220303/2fec445d/attachment-0001.htm>


More information about the vc mailing list