[PATCH] Add support for temperature compensation |
[ Thread Index |
Date Index
| More chrony.tuxfamily.org/chrony-dev Archives
]
- Subject: [PATCH] Add support for temperature compensation
- From: Miroslav Lichvar <mlichvar@xxxxxxxxxx>
- Date: Mon, 12 Apr 2010 17:07:57 +0200
File used to read temperatures, update interval and compensation
coefficients are specified with new tempcomp directive. The frequency
corrections are applied in local module and are invisible in upper
layers.
---
Makefile.in | 2 +-
conf.c | 61 +++++++++++++++++++++++++++++++++++
conf.h | 3 ++
local.c | 35 ++++++++++++++++++--
local.h | 6 +++
logging.c | 2 +-
main.c | 3 ++
tempcomp.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tempcomp.h | 29 +++++++++++++++++
9 files changed, 236 insertions(+), 6 deletions(-)
create mode 100644 tempcomp.c
create mode 100644 tempcomp.h
diff --git a/Makefile.in b/Makefile.in
index 23a83fe..fd12f79 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -46,7 +46,7 @@ OBJS = util.o sched.o regress.o local.o \
nameserv.o acquire.o manual.o addrfilt.o \
cmdparse.o mkdirpp.o rtc.o pktlength.o clientlog.o \
broadcast.o refclock.o refclock_shm.o refclock_sock.o \
- refclock_pps.o
+ refclock_pps.o tempcomp.o
EXTRA_OBJS=@EXTRA_OBJECTS@
diff --git a/conf.c b/conf.c
index 0fdf773..0fa115f 100644
--- a/conf.c
+++ b/conf.c
@@ -105,6 +105,7 @@ static void parse_linux_hz(const char *);
static void parse_linux_freq_scale(const char *);
static void parse_sched_priority(const char *);
static void parse_lockall(const char *);
+static void parse_tempcomp(const char *);
/* ================================================== */
/* Configuration variables */
@@ -125,6 +126,7 @@ static int do_log_statistics = 0;
static int do_log_tracking = 0;
static int do_log_rtc = 0;
static int do_log_refclocks = 0;
+static int do_log_tempcomp = 0;
static int do_dump_on_exit = 0;
static char *logdir = ".";
static char *dumpdir = ".";
@@ -183,6 +185,11 @@ static IPAddr bind_cmd_address4, bind_cmd_address6;
* chronyds being started. */
static char *pidfile = "/var/run/chronyd.pid";
+/* Temperature sensor, update interval and compensation coefficients */
+static char *tempcomp_file = NULL;
+static double tempcomp_interval;
+static double tempcomp_T0, tempcomp_k0, tempcomp_k1, tempcomp_k2;
+
/* Boolean for whether the Linux HZ value has been overridden, and the
* new value. */
static int set_linux_hz = 0;
@@ -239,6 +246,7 @@ static const Command commands[] = {
{"rtcdevice", 9, parse_rtcdevice},
{"pidfile", 7, parse_pidfile},
{"broadcast", 9, parse_broadcast},
+ {"tempcomp", 8, parse_tempcomp},
{"linux_hz", 8, parse_linux_hz},
{"linux_freq_scale", 16, parse_linux_freq_scale},
{"sched_priority", 14, parse_sched_priority},
@@ -679,6 +687,9 @@ parse_log(const char *line)
} else if (!strncmp(line, "refclocks", 9)) {
do_log_refclocks = 1;
line += 9;
+ } else if (!strncmp(line, "tempcomp", 8)) {
+ do_log_tempcomp = 1;
+ line += 8;
} else {
break;
}
@@ -1115,6 +1126,34 @@ parse_broadcast(const char *line)
/* ================================================== */
static void
+parse_tempcomp(const char *line)
+{
+ const char *tmp;
+
+ while (isspace(line[0]))
+ line++;
+ tmp = line;
+ while (line[0] != '\0' && !isspace(line[0]))
+ line++;
+
+ if (line == tmp) {
+ LOG(LOGS_WARN, LOGF_Configure, "Could not read tempcomp filename at line %d", line_number);
+ return;
+ }
+
+ if (sscanf(line, "%lf %lf %lf %lf %lf", &tempcomp_interval, &tempcomp_T0, &tempcomp_k0, &tempcomp_k1, &tempcomp_k2) != 5) {
+ LOG(LOGS_WARN, LOGF_Configure, "Could not read tempcomp interval or coefficients at line %d", line_number);
+ return;
+ }
+
+ tempcomp_file = MallocArray(char, 1 + line - tmp);
+ strncpy(tempcomp_file, tmp, line - tmp);
+ tempcomp_file[line - tmp] = '\0';
+}
+
+/* ================================================== */
+
+static void
parse_linux_hz(const char *line)
{
if (1 == sscanf(line, "%d", &linux_hz)) {
@@ -1273,6 +1312,7 @@ CNF_GetLogRtc(void)
}
/* ================================================== */
+
int
CNF_GetLogRefclocks(void)
{
@@ -1281,6 +1321,14 @@ CNF_GetLogRefclocks(void)
/* ================================================== */
+int
+CNF_GetLogTempComp(void)
+{
+ return do_log_tempcomp;
+}
+
+/* ================================================== */
+
char *
CNF_GetKeysFile(void)
{
@@ -1514,3 +1562,16 @@ CNF_GetLockMemory(void)
{
return lock_memory;
}
+
+/* ================================================== */
+
+void
+CNF_GetTempComp(char **file, double *interval, double *T0, double *k0, double *k1, double *k2)
+{
+ *file = tempcomp_file;
+ *interval = tempcomp_interval;
+ *T0 = tempcomp_T0;
+ *k0 = tempcomp_k0;
+ *k1 = tempcomp_k1;
+ *k2 = tempcomp_k2;
+}
diff --git a/conf.h b/conf.h
index 1ec99f2..31f4cf0 100644
--- a/conf.h
+++ b/conf.h
@@ -53,6 +53,7 @@ extern int CNF_GetLogStatistics(void);
extern int CNF_GetLogTracking(void);
extern int CNF_GetLogRtc(void);
extern int CNF_GetLogRefclocks(void);
+extern int CNF_GetLogTempComp(void);
extern char *CNF_GetKeysFile(void);
extern char *CNF_GetRtcFile(void);
extern unsigned long CNF_GetCommandKey(void);
@@ -81,4 +82,6 @@ extern void CNF_SetupAccessRestrictions(void);
extern int CNF_GetSchedPriority(void);
extern int CNF_GetLockMemory(void);
+extern void CNF_GetTempComp(char **file, double *interval, double *T0, double *k0, double *k1, double *k2);
+
#endif /* GOT_CONF_H */
diff --git a/local.c b/local.c
index 1be6117..c1fb158 100644
--- a/local.c
+++ b/local.c
@@ -45,6 +45,9 @@
/* Variable to store the current frequency, in ppm */
static double current_freq_ppm;
+/* Temperature compensation, in ppm */
+static double temp_comp_ppm;
+
/* ================================================== */
/* Store the system dependent drivers */
@@ -152,6 +155,7 @@ LCL_Initialise(void)
/* This ought to be set from the system driver layer */
current_freq_ppm = 0.0;
+ temp_comp_ppm = 0.0;
calculate_sys_precision();
}
@@ -360,7 +364,7 @@ LCL_GetOffsetCorrection(struct timeval *raw, double *correction, double *err)
double
LCL_ReadAbsoluteFrequency(void)
{
- return (*drv_read_freq)();
+ return (*drv_read_freq)() + temp_comp_ppm;
}
/* ================================================== */
@@ -376,7 +380,7 @@ LCL_SetAbsoluteFrequency(double afreq_ppm)
/* Call the system-specific driver for setting the frequency */
- (*drv_set_freq)(afreq_ppm);
+ (*drv_set_freq)(afreq_ppm - temp_comp_ppm);
dfreq = 1.0e-6 * (afreq_ppm - current_freq_ppm) / (1.0 - 1.0e-6 * current_freq_ppm);
@@ -408,7 +412,7 @@ LCL_AccumulateDeltaFrequency(double dfreq)
(1.0e6 * dfreq);
/* Call the system-specific driver for setting the frequency */
- (*drv_set_freq)(current_freq_ppm);
+ (*drv_set_freq)(current_freq_ppm - temp_comp_ppm);
LCL_ReadRawTime(&raw);
LCL_CookTime(&raw, &cooked, NULL);
@@ -494,7 +498,7 @@ LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset)
#endif
/* Call the system-specific driver for setting the frequency */
- (*drv_set_freq)(current_freq_ppm);
+ (*drv_set_freq)(current_freq_ppm - temp_comp_ppm);
(*drv_accrue_offset)(doffset);
/* Dispatch to all handlers */
@@ -582,3 +586,26 @@ LCL_SetLeap(int leap)
}
/* ================================================== */
+
+void
+LCL_SetTempComp(double freq)
+{
+ if (temp_comp_ppm == freq)
+ return;
+
+ temp_comp_ppm = freq;
+ /* Call the system-specific driver for setting the frequency */
+ (*drv_set_freq)(current_freq_ppm - temp_comp_ppm);
+
+ return;
+}
+
+/* ================================================== */
+
+double
+LCL_GetTempComp(void)
+{
+ return temp_comp_ppm;
+}
+
+/* ================================================== */
diff --git a/local.h b/local.h
index bef1a3e..55f60e7 100644
--- a/local.h
+++ b/local.h
@@ -188,4 +188,10 @@ extern int LCL_MakeStep(double threshold);
and zero cancels scheduled leap second. */
extern void LCL_SetLeap(int leap);
+/* Routine to set a frequency correction (in ppm) that should be substracted
+ from clock frequency to compensate for temperature changes. */
+extern void LCL_SetTempComp(double freq);
+
+extern double LCL_GetTempComp(void);
+
#endif /* GOT_LOCAL_H */
diff --git a/logging.c b/logging.c
index 8271c00..a2f471e 100644
--- a/logging.c
+++ b/logging.c
@@ -58,7 +58,7 @@ struct LogFile {
static int n_filelogs = 0;
/* Increase this when adding a new logfile */
-#define MAX_FILELOGS 5
+#define MAX_FILELOGS 6
static struct LogFile logfiles[MAX_FILELOGS];
diff --git a/main.c b/main.c
index 31f4a5c..7da6250 100644
--- a/main.c
+++ b/main.c
@@ -53,6 +53,7 @@
#include "clientlog.h"
#include "broadcast.h"
#include "nameserv.h"
+#include "tempcomp.h"
/* ================================================== */
@@ -86,6 +87,7 @@ MAI_CleanupAndExit(void)
SRC_DumpSources();
}
+ TMC_Finalise();
MNL_Finalise();
ACQ_Finalise();
KEY_Finalise();
@@ -326,6 +328,7 @@ int main
KEY_Initialise();
ACQ_Initialise();
MNL_Initialise();
+ TMC_Initialise();
LOG_CreateLogFileDir();
diff --git a/tempcomp.c b/tempcomp.c
new file mode 100644
index 0000000..d7f02ad
--- /dev/null
+++ b/tempcomp.c
@@ -0,0 +1,101 @@
+/*
+ chronyd/chronyc - Programs for keeping computer clocks accurate.
+
+ **********************************************************************
+ * Copyright (C) Miroslav Lichvar 2010
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ **********************************************************************
+
+ =======================================================================
+
+ Routines implementing temperature compensation.
+
+ */
+
+#include "conf.h"
+#include "local.h"
+#include "memory.h"
+#include "util.h"
+#include "logging.h"
+#include "sched.h"
+#include "tempcomp.h"
+
+static SCH_TimeoutID timeout_id;
+
+static LOG_FileID logfileid;
+
+static char *filename;
+static double update_interval;
+static double T0, k0, k1, k2;
+
+static void
+read_timeout(void *arg)
+{
+ FILE *f;
+ double temp, comp;
+
+ f = fopen(filename, "r");
+
+ if (f && fscanf(f, "%lf", &temp) == 1) {
+ comp = k0 + (temp - T0) * k1 + (temp - T0) * (temp - T0) * k2;
+
+ /* Don't allow corrections above 10 ppm */
+ if (fabs(comp) < 10.0) {
+ LCL_SetTempComp(comp);
+
+ if (logfileid != -1) {
+ struct timeval now;
+
+ LCL_ReadCookedTime(&now, NULL);
+ LOG_FileWrite(logfileid, "%s %11.4e %11.4e",
+ UTI_TimeToLogForm(now.tv_sec), temp, comp);
+ }
+ }
+ }
+
+ if (f)
+ fclose(f);
+
+ timeout_id = SCH_AddTimeoutByDelay(update_interval, read_timeout, NULL);
+}
+
+void
+TMC_Initialise(void)
+{
+ CNF_GetTempComp(&filename, &update_interval, &T0, &k0, &k1, &k2);
+
+ if (filename == NULL)
+ return;
+
+ if (update_interval <= 0.0)
+ update_interval = 1.0;
+
+ logfileid = CNF_GetLogTempComp() ? LOG_FileOpen("tempcomp",
+ " Date (UTC) Time Temp. Comp.")
+ : -1;
+
+ read_timeout(NULL);
+}
+
+void
+TMC_Finalise(void)
+{
+ if (filename == NULL)
+ return;
+
+ SCH_RemoveTimeout(timeout_id);
+ Free(filename);
+}
diff --git a/tempcomp.h b/tempcomp.h
new file mode 100644
index 0000000..de65469
--- /dev/null
+++ b/tempcomp.h
@@ -0,0 +1,29 @@
+/*
+ chronyd/chronyc - Programs for keeping computer clocks accurate.
+
+ **********************************************************************
+ * Copyright (C) Miroslav Lichvar 2010
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ **********************************************************************
+
+ =======================================================================
+
+ Header file for temperature compensation.
+
+ */
+
+extern void TMC_Initialise(void);
+extern void TMC_Finalise(void);
--
1.6.6.1
--ZGiS0Q5IWpPtfppv--
---
To unsubscribe email chrony-dev-request@xxxxxxxxxxxxxxxxxxxx with "unsubscribe" in the subject.
For help email chrony-dev-request@xxxxxxxxxxxxxxxxxxxx with "help" in the subject.
Trouble? Email listmaster@xxxxxxxxxxxxxxxxxxxx.