refclock: improve precision with large offset

If a SHM or PHC refclock has a very large offset compensated by the
offset option, or ignored with the pps or local option, there is a
persistent loss of precision in the calculation of the sample offset
using the double format.

Rework the code to delay the calculation of the accumulated offset to
include the specificed compensation and remaining correction of the
system clock, where the calculation can be split to improve the
precision. In the pps mode ignore integer seconds competely.

The precision of the SOCK refclock is now limited to 1 nanosecond due to
the extra double->timespec->double conversion.
This commit is contained in:
Miroslav Lichvar
2022-02-23 10:23:18 +01:00
parent 62757cda49
commit 663dde1ad7
5 changed files with 34 additions and 21 deletions

View File

@@ -60,8 +60,8 @@ struct sock_sample {
static void read_sample(int sockfd, int event, void *anything)
{
struct timespec sys_ts, ref_ts;
struct sock_sample sample;
struct timespec ts;
RCL_Instance instance;
int s;
@@ -86,13 +86,18 @@ static void read_sample(int sockfd, int event, void *anything)
return;
}
UTI_TimevalToTimespec(&sample.tv, &ts);
UTI_NormaliseTimespec(&ts);
UTI_TimevalToTimespec(&sample.tv, &sys_ts);
UTI_NormaliseTimespec(&sys_ts);
if (!UTI_IsTimeOffsetSane(&sys_ts, sample.offset))
return;
UTI_AddDoubleToTimespec(&sys_ts, sample.offset, &ref_ts);
if (sample.pulse) {
RCL_AddPulse(instance, &ts, sample.offset);
RCL_AddPulse(instance, &sys_ts, sample.offset);
} else {
RCL_AddSample(instance, &ts, sample.offset, sample.leap);
RCL_AddSample(instance, &sys_ts, &ref_ts, sample.leap);
}
}