refclock: allow drivers to provide cooked PPS samples
Split RCL_AddPulse() in order to provide a new function for refclock drivers which can make PPS samples without having raw system time, e.g. from PHC timestamps.
This commit is contained in:
parent
1bf2384a1f
commit
6b74917954
2 changed files with 33 additions and 17 deletions
48
refclock.c
48
refclock.c
|
@ -404,24 +404,37 @@ RCL_AddSample(RCL_Instance instance, struct timespec *sample_time, double offset
|
||||||
int
|
int
|
||||||
RCL_AddPulse(RCL_Instance instance, struct timespec *pulse_time, double second)
|
RCL_AddPulse(RCL_Instance instance, struct timespec *pulse_time, double second)
|
||||||
{
|
{
|
||||||
double correction, dispersion, offset;
|
double correction, dispersion;
|
||||||
struct timespec cooked_time;
|
struct timespec cooked_time;
|
||||||
|
|
||||||
|
LCL_GetOffsetCorrection(pulse_time, &correction, &dispersion);
|
||||||
|
UTI_AddDoubleToTimespec(pulse_time, correction, &cooked_time);
|
||||||
|
second += correction;
|
||||||
|
|
||||||
|
if (!UTI_IsTimeOffsetSane(pulse_time, 0.0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return RCL_AddCookedPulse(instance, &cooked_time, second, dispersion, correction);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
RCL_AddCookedPulse(RCL_Instance instance, struct timespec *cooked_time,
|
||||||
|
double second, double dispersion, double raw_correction)
|
||||||
|
{
|
||||||
|
double offset;
|
||||||
int rate;
|
int rate;
|
||||||
NTP_Leap leap;
|
NTP_Leap leap;
|
||||||
|
|
||||||
leap = LEAP_Normal;
|
if (!UTI_IsTimeOffsetSane(cooked_time, second) ||
|
||||||
LCL_GetOffsetCorrection(pulse_time, &correction, &dispersion);
|
!valid_sample_time(instance, cooked_time))
|
||||||
UTI_AddDoubleToTimespec(pulse_time, correction, &cooked_time);
|
|
||||||
dispersion += instance->precision;
|
|
||||||
|
|
||||||
if (!UTI_IsTimeOffsetSane(pulse_time, 0.0) ||
|
|
||||||
!valid_sample_time(instance, &cooked_time))
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
leap = LEAP_Normal;
|
||||||
|
dispersion += instance->precision;
|
||||||
rate = instance->pps_rate;
|
rate = instance->pps_rate;
|
||||||
assert(rate > 0);
|
assert(rate > 0);
|
||||||
|
|
||||||
offset = -second - correction + instance->offset;
|
offset = -second + instance->offset;
|
||||||
|
|
||||||
/* Adjust the offset to [-0.5/rate, 0.5/rate) interval */
|
/* Adjust the offset to [-0.5/rate, 0.5/rate) interval */
|
||||||
offset -= (long)(offset * rate) / (double)rate;
|
offset -= (long)(offset * rate) / (double)rate;
|
||||||
|
@ -445,7 +458,7 @@ RCL_AddPulse(RCL_Instance instance, struct timespec *pulse_time, double second)
|
||||||
|
|
||||||
ref_dispersion += filter_get_avg_sample_dispersion(&lock_refclock->filter);
|
ref_dispersion += filter_get_avg_sample_dispersion(&lock_refclock->filter);
|
||||||
|
|
||||||
sample_diff = UTI_DiffTimespecsToDouble(&cooked_time, &ref_sample_time);
|
sample_diff = UTI_DiffTimespecsToDouble(cooked_time, &ref_sample_time);
|
||||||
if (fabs(sample_diff) >= (double)instance->max_lock_age / rate) {
|
if (fabs(sample_diff) >= (double)instance->max_lock_age / rate) {
|
||||||
DEBUG_LOG("refclock pulse ignored samplediff=%.9f",
|
DEBUG_LOG("refclock pulse ignored samplediff=%.9f",
|
||||||
sample_diff);
|
sample_diff);
|
||||||
|
@ -468,8 +481,8 @@ RCL_AddPulse(RCL_Instance instance, struct timespec *pulse_time, double second)
|
||||||
|
|
||||||
leap = lock_refclock->leap_status;
|
leap = lock_refclock->leap_status;
|
||||||
|
|
||||||
DEBUG_LOG("refclock pulse second=%.9f offset=%.9f offdiff=%.9f samplediff=%.9f",
|
DEBUG_LOG("refclock pulse offset=%.9f offdiff=%.9f samplediff=%.9f",
|
||||||
second, offset, ref_offset - offset, sample_diff);
|
offset, ref_offset - offset, sample_diff);
|
||||||
} else {
|
} else {
|
||||||
struct timespec ref_time;
|
struct timespec ref_time;
|
||||||
int is_synchronised, stratum;
|
int is_synchronised, stratum;
|
||||||
|
@ -479,24 +492,25 @@ RCL_AddPulse(RCL_Instance instance, struct timespec *pulse_time, double second)
|
||||||
/* Ignore the pulse if we are not well synchronized and the local
|
/* Ignore the pulse if we are not well synchronized and the local
|
||||||
reference is not active */
|
reference is not active */
|
||||||
|
|
||||||
REF_GetReferenceParams(&cooked_time, &is_synchronised, &leap, &stratum,
|
REF_GetReferenceParams(cooked_time, &is_synchronised, &leap, &stratum,
|
||||||
&ref_id, &ref_time, &root_delay, &root_dispersion);
|
&ref_id, &ref_time, &root_delay, &root_dispersion);
|
||||||
distance = fabs(root_delay) / 2 + root_dispersion;
|
distance = fabs(root_delay) / 2 + root_dispersion;
|
||||||
|
|
||||||
if (leap == LEAP_Unsynchronised || distance >= 0.5 / rate) {
|
if (leap == LEAP_Unsynchronised || distance >= 0.5 / rate) {
|
||||||
DEBUG_LOG("refclock pulse ignored second=%.9f sync=%d dist=%.9f",
|
DEBUG_LOG("refclock pulse ignored offset=%.9f sync=%d dist=%.9f",
|
||||||
second, leap != LEAP_Unsynchronised, distance);
|
offset, leap != LEAP_Unsynchronised, distance);
|
||||||
/* Drop also all stored samples */
|
/* Drop also all stored samples */
|
||||||
filter_reset(&instance->filter);
|
filter_reset(&instance->filter);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
filter_add_sample(&instance->filter, &cooked_time, offset, dispersion);
|
filter_add_sample(&instance->filter, cooked_time, offset, dispersion);
|
||||||
instance->leap_status = leap;
|
instance->leap_status = leap;
|
||||||
instance->pps_active = 1;
|
instance->pps_active = 1;
|
||||||
|
|
||||||
log_sample(instance, &cooked_time, 0, 1, offset + correction - instance->offset, offset, dispersion);
|
log_sample(instance, cooked_time, 0, 1, offset + raw_correction - instance->offset,
|
||||||
|
offset, dispersion);
|
||||||
|
|
||||||
/* for logging purposes */
|
/* for logging purposes */
|
||||||
if (!instance->driver->poll)
|
if (!instance->driver->poll)
|
||||||
|
|
|
@ -71,6 +71,8 @@ extern char *RCL_GetDriverParameter(RCL_Instance instance);
|
||||||
extern char *RCL_GetDriverOption(RCL_Instance instance, char *name);
|
extern char *RCL_GetDriverOption(RCL_Instance instance, char *name);
|
||||||
extern int RCL_AddSample(RCL_Instance instance, struct timespec *sample_time, double offset, int leap);
|
extern int RCL_AddSample(RCL_Instance instance, struct timespec *sample_time, double offset, int leap);
|
||||||
extern int RCL_AddPulse(RCL_Instance instance, struct timespec *pulse_time, double second);
|
extern int RCL_AddPulse(RCL_Instance instance, struct timespec *pulse_time, double second);
|
||||||
|
extern int RCL_AddCookedPulse(RCL_Instance instance, struct timespec *cooked_time,
|
||||||
|
double second, double dispersion, double raw_correction);
|
||||||
extern double RCL_GetPrecision(RCL_Instance instance);
|
extern double RCL_GetPrecision(RCL_Instance instance);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue