Replace fixed-point format with floating-point in cmdmon protocol

This commit is contained in:
Miroslav Lichvar 2009-12-12 18:23:26 +01:00
parent 84f8463f2a
commit b49470117d
5 changed files with 147 additions and 71 deletions

57
candm.h
View file

@ -102,6 +102,13 @@ typedef struct {
/* This is used in tv_sec_high for 32-bit timestamps */ /* This is used in tv_sec_high for 32-bit timestamps */
#define TV_NOHIGHSEC 0x7fffffff #define TV_NOHIGHSEC 0x7fffffff
/* 32-bit floating-point format consisting of 7-bit signed exponent
and 25-bit signed coefficient without hidden bit.
The result is calculated as: 2^(exp - 25) * coef */
typedef struct {
int32_t f;
} Float;
/* The EOR (end of record) fields are used by the offsetof operator in /* The EOR (end of record) fields are used by the offsetof operator in
pktlength.c, to get the number of bytes that ought to be pktlength.c, to get the number of bytes that ought to be
transmitted for each packet type. */ transmitted for each packet type. */
@ -145,18 +152,18 @@ typedef struct {
typedef struct { typedef struct {
IPAddr address; IPAddr address;
int32_t new_max_delay; Float new_max_delay;
int32_t EOR; int32_t EOR;
} REQ_Modify_Maxdelay; } REQ_Modify_Maxdelay;
typedef struct { typedef struct {
IPAddr address; IPAddr address;
int32_t new_max_delay_ratio; Float new_max_delay_ratio;
int32_t EOR; int32_t EOR;
} REQ_Modify_Maxdelayratio; } REQ_Modify_Maxdelayratio;
typedef struct { typedef struct {
int32_t new_max_update_skew; Float new_max_update_skew;
int32_t EOR; int32_t EOR;
} REQ_Modify_Maxupdateskew; } REQ_Modify_Maxupdateskew;
@ -216,8 +223,8 @@ typedef struct {
int32_t maxpoll; int32_t maxpoll;
int32_t presend_minpoll; int32_t presend_minpoll;
uint32_t authkey; uint32_t authkey;
int32_t max_delay; Float max_delay;
int32_t max_delay_ratio; Float max_delay_ratio;
uint32_t flags; uint32_t flags;
int32_t EOR; int32_t EOR;
} REQ_NTP_Source; } REQ_NTP_Source;
@ -232,7 +239,7 @@ typedef struct {
} REQ_WriteRtc; } REQ_WriteRtc;
typedef struct { typedef struct {
int32_t dfreq; Float dfreq;
int32_t EOR; int32_t EOR;
} REQ_Dfreq; } REQ_Dfreq;
@ -325,7 +332,8 @@ typedef struct {
Version 3 : NTP_Source message lengthened (auto_offline) Version 3 : NTP_Source message lengthened (auto_offline)
Version 4 : IPv6 addressing added, 64-bit time values, sourcestats Version 4 : IPv6 addressing added, 64-bit time values, sourcestats
and tracking reports extended, added flags to NTP source request and tracking reports extended, added flags to NTP source request,
replaced fixed-point format with floating-point
*/ */
@ -398,13 +406,6 @@ typedef struct {
#define PERMIT_LOCAL 1 #define PERMIT_LOCAL 1
#define PERMIT_AUTH 2 #define PERMIT_AUTH 2
/* ================================================== */
/* These conversion utilities are used to convert between the internal
and the 'wire' representation of real quantities */
#define WIRE2REAL(x) ((double) ((int32_t) ntohl(x)) / 65536.0)
#define REAL2WIRE(x) (htonl((int32_t)(0.5 + 65536.0 * (x))))
/* ================================================== */ /* ================================================== */
/* Reply codes */ /* Reply codes */
@ -487,11 +488,11 @@ typedef struct {
Timeval ref_time; Timeval ref_time;
uint32_t current_correction_s; uint32_t current_correction_s;
uint32_t current_correction_us; uint32_t current_correction_us;
int32_t freq_ppm; Float freq_ppm;
int32_t resid_freq_ppm; Float resid_freq_ppm;
int32_t skew_ppm; Float skew_ppm;
int32_t root_delay; Float root_delay;
int32_t root_dispersion; Float root_dispersion;
int32_t EOR; int32_t EOR;
} RPY_Tracking; } RPY_Tracking;
@ -502,8 +503,8 @@ typedef struct {
uint32_t n_runs; uint32_t n_runs;
uint32_t span_seconds; uint32_t span_seconds;
uint32_t sd_us; uint32_t sd_us;
int32_t resid_freq_ppm; Float resid_freq_ppm;
int32_t skew_ppm; Float skew_ppm;
int32_t EOR; int32_t EOR;
} RPY_Sourcestats; } RPY_Sourcestats;
@ -512,15 +513,15 @@ typedef struct {
uint16_t n_samples; uint16_t n_samples;
uint16_t n_runs; uint16_t n_runs;
uint32_t span_seconds; uint32_t span_seconds;
int32_t rtc_seconds_fast; Float rtc_seconds_fast;
int32_t rtc_gain_rate_ppm; Float rtc_gain_rate_ppm;
int32_t EOR; int32_t EOR;
} RPY_Rtc; } RPY_Rtc;
typedef struct { typedef struct {
uint32_t centiseconds; uint32_t centiseconds;
int32_t dfreq_ppm; Float dfreq_ppm;
int32_t new_afreq_ppm; Float new_afreq_ppm;
int32_t EOR; int32_t EOR;
} RPY_ManualTimestamp; } RPY_ManualTimestamp;
@ -562,9 +563,9 @@ typedef struct {
typedef struct { typedef struct {
Timeval when; Timeval when;
int32_t slewed_offset; Float slewed_offset;
int32_t orig_offset; Float orig_offset;
int32_t residual; Float residual;
} RPY_ManualListSample; } RPY_ManualListSample;
typedef struct { typedef struct {

View file

@ -423,7 +423,7 @@ process_cmd_maxdelay(CMD_Request *msg, char *line)
if (read_address_double(line, &address, &max_delay)) { if (read_address_double(line, &address, &max_delay)) {
UTI_IPHostToNetwork(&address, &msg->data.modify_maxdelay.address); UTI_IPHostToNetwork(&address, &msg->data.modify_maxdelay.address);
msg->data.modify_maxdelay.new_max_delay = REAL2WIRE(max_delay); msg->data.modify_maxdelay.new_max_delay = UTI_FloatHostToNetwork(max_delay);
msg->command = htons(REQ_MODIFY_MAXDELAY); msg->command = htons(REQ_MODIFY_MAXDELAY);
ok = 1; ok = 1;
} else { } else {
@ -445,7 +445,7 @@ process_cmd_maxdelayratio(CMD_Request *msg, char *line)
if (read_address_double(line, &address, &max_delay_ratio)) { if (read_address_double(line, &address, &max_delay_ratio)) {
UTI_IPHostToNetwork(&address, &msg->data.modify_maxdelayratio.address); UTI_IPHostToNetwork(&address, &msg->data.modify_maxdelayratio.address);
msg->data.modify_maxdelayratio.new_max_delay_ratio = REAL2WIRE(max_delay_ratio); msg->data.modify_maxdelayratio.new_max_delay_ratio = UTI_FloatHostToNetwork(max_delay_ratio);
msg->command = htons(REQ_MODIFY_MAXDELAYRATIO); msg->command = htons(REQ_MODIFY_MAXDELAYRATIO);
ok = 1; ok = 1;
} else { } else {
@ -465,7 +465,7 @@ process_cmd_maxupdateskew(CMD_Request *msg, char *line)
double new_max_update_skew; double new_max_update_skew;
if (sscanf(line, "%lf", &new_max_update_skew) == 1) { if (sscanf(line, "%lf", &new_max_update_skew) == 1) {
msg->data.modify_maxupdateskew.new_max_update_skew = REAL2WIRE(new_max_update_skew); msg->data.modify_maxupdateskew.new_max_update_skew = UTI_FloatHostToNetwork(new_max_update_skew);
msg->command = htons(REQ_MODIFY_MAXUPDATESKEW); msg->command = htons(REQ_MODIFY_MAXUPDATESKEW);
ok = 1; ok = 1;
} else { } else {
@ -845,9 +845,9 @@ process_cmd_dfreq(CMD_Request *msg, char *line)
double dfreq; double dfreq;
msg->command = htons(REQ_DFREQ); msg->command = htons(REQ_DFREQ);
if (sscanf(line, "%lf", &dfreq) == 1) { if (sscanf(line, "%lf", &dfreq) == 1) {
msg->data.dfreq.dfreq = REAL2WIRE(dfreq); msg->data.dfreq.dfreq = UTI_FloatHostToNetwork(dfreq);
} else { } else {
msg->data.dfreq.dfreq = REAL2WIRE(0.0); msg->data.dfreq.dfreq = UTI_FloatHostToNetwork(0.0);
} }
} }
@ -908,8 +908,8 @@ process_cmd_add_server_or_peer(CMD_Request *msg, char *line)
msg->data.ntp_source.maxpoll = htonl(data.params.maxpoll); msg->data.ntp_source.maxpoll = htonl(data.params.maxpoll);
msg->data.ntp_source.presend_minpoll = htonl(data.params.presend_minpoll); msg->data.ntp_source.presend_minpoll = htonl(data.params.presend_minpoll);
msg->data.ntp_source.authkey = htonl(data.params.authkey); msg->data.ntp_source.authkey = htonl(data.params.authkey);
msg->data.ntp_source.max_delay = REAL2WIRE(data.params.max_delay); msg->data.ntp_source.max_delay = UTI_FloatHostToNetwork(data.params.max_delay);
msg->data.ntp_source.max_delay_ratio = REAL2WIRE(data.params.max_delay_ratio); msg->data.ntp_source.max_delay_ratio = UTI_FloatHostToNetwork(data.params.max_delay_ratio);
msg->data.ntp_source.flags = htonl( msg->data.ntp_source.flags = htonl(
(data.params.online ? REQ_ADDSRC_ONLINE : 0) | (data.params.online ? REQ_ADDSRC_ONLINE : 0) |
(data.params.auto_offline ? REQ_ADDSRC_AUTOOFFLINE : 0)); (data.params.auto_offline ? REQ_ADDSRC_AUTOOFFLINE : 0));
@ -1682,9 +1682,9 @@ process_cmd_sourcestats(char *line)
n_samples = ntohl(reply.data.sourcestats.n_samples); n_samples = ntohl(reply.data.sourcestats.n_samples);
n_runs = ntohl(reply.data.sourcestats.n_runs); n_runs = ntohl(reply.data.sourcestats.n_runs);
span_seconds = ntohl(reply.data.sourcestats.span_seconds); span_seconds = ntohl(reply.data.sourcestats.span_seconds);
resid_freq_ppm = WIRE2REAL(reply.data.sourcestats.resid_freq_ppm);
skew_ppm = WIRE2REAL(reply.data.sourcestats.skew_ppm);
sd_us = ntohl(reply.data.sourcestats.sd_us); sd_us = ntohl(reply.data.sourcestats.sd_us);
resid_freq_ppm = UTI_FloatNetworkToHost(reply.data.sourcestats.resid_freq_ppm);
skew_ppm = UTI_FloatNetworkToHost(reply.data.sourcestats.skew_ppm);
if (ip_addr.family == IPADDR_UNSPEC) if (ip_addr.family == IPADDR_UNSPEC)
snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_RefidToString(ref_id)); snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_RefidToString(ref_id));
@ -1760,11 +1760,11 @@ process_cmd_tracking(char *line)
correction = (double) correction_tv.tv_sec + 1.0e-6 * correction_tv.tv_usec; correction = (double) correction_tv.tv_sec + 1.0e-6 * correction_tv.tv_usec;
printf("System time : %.6f seconds %s of NTP time\n", fabs(correction), printf("System time : %.6f seconds %s of NTP time\n", fabs(correction),
(correction > 0.0) ? "slow" : "fast"); (correction > 0.0) ? "slow" : "fast");
freq_ppm = WIRE2REAL(reply.data.tracking.freq_ppm); freq_ppm = UTI_FloatNetworkToHost(reply.data.tracking.freq_ppm);
resid_freq_ppm = WIRE2REAL(reply.data.tracking.resid_freq_ppm); resid_freq_ppm = UTI_FloatNetworkToHost(reply.data.tracking.resid_freq_ppm);
skew_ppm = WIRE2REAL(reply.data.tracking.skew_ppm); skew_ppm = UTI_FloatNetworkToHost(reply.data.tracking.skew_ppm);
root_delay = WIRE2REAL(reply.data.tracking.root_delay); root_delay = UTI_FloatNetworkToHost(reply.data.tracking.root_delay);
root_dispersion = WIRE2REAL(reply.data.tracking.root_dispersion); root_dispersion = UTI_FloatNetworkToHost(reply.data.tracking.root_dispersion);
printf("Frequency : %.3f ppm %s\n", fabs(freq_ppm), (freq_ppm < 0.0) ? "slow" : "fast"); printf("Frequency : %.3f ppm %s\n", fabs(freq_ppm), (freq_ppm < 0.0) ? "slow" : "fast");
printf("Residual freq : %.3f ppm\n", resid_freq_ppm); printf("Residual freq : %.3f ppm\n", resid_freq_ppm);
printf("Skew : %.3f ppm\n", skew_ppm); printf("Skew : %.3f ppm\n", skew_ppm);
@ -1796,8 +1796,8 @@ process_cmd_rtcreport(char *line)
n_samples = ntohs(reply.data.rtc.n_samples); n_samples = ntohs(reply.data.rtc.n_samples);
n_runs = ntohs(reply.data.rtc.n_runs); n_runs = ntohs(reply.data.rtc.n_runs);
span_seconds = ntohl(reply.data.rtc.span_seconds); span_seconds = ntohl(reply.data.rtc.span_seconds);
coef_seconds_fast = WIRE2REAL(reply.data.rtc.rtc_seconds_fast); coef_seconds_fast = UTI_FloatNetworkToHost(reply.data.rtc.rtc_seconds_fast);
coef_gain_rate_ppm = WIRE2REAL(reply.data.rtc.rtc_gain_rate_ppm); coef_gain_rate_ppm = UTI_FloatNetworkToHost(reply.data.rtc.rtc_gain_rate_ppm);
printf("RTC ref time (UTC) : %s", asctime(&ref_time_tm)); printf("RTC ref time (UTC) : %s", asctime(&ref_time_tm));
printf("Number of samples : %d\n", n_samples); printf("Number of samples : %d\n", n_samples);
printf("Number of runs : %d\n", n_runs); printf("Number of runs : %d\n", n_runs);
@ -2126,9 +2126,9 @@ process_cmd_manual_list(const char *line)
for (i=0; i<n_samples; i++) { for (i=0; i<n_samples; i++) {
sample = &reply.data.manual_list.samples[i]; sample = &reply.data.manual_list.samples[i];
UTI_TimevalNetworkToHost(&sample->when, &when); UTI_TimevalNetworkToHost(&sample->when, &when);
slewed_offset = WIRE2REAL(sample->slewed_offset); slewed_offset = UTI_FloatNetworkToHost(sample->slewed_offset);
orig_offset = WIRE2REAL(sample->orig_offset); orig_offset = UTI_FloatNetworkToHost(sample->orig_offset);
residual = WIRE2REAL(sample->residual); residual = UTI_FloatNetworkToHost(sample->residual);
printf("%2d %s %10.2f %10.2f %10.2f\n", i, time_to_log_form(when.tv_sec), slewed_offset, orig_offset, residual); printf("%2d %s %10.2f %10.2f %10.2f\n", i, time_to_log_form(when.tv_sec), slewed_offset, orig_offset, residual);
} }
return 1; return 1;
@ -2180,8 +2180,8 @@ process_cmd_settime(char *line)
if (request_reply(&request, &reply, RPY_MANUAL_TIMESTAMP, 1)) { if (request_reply(&request, &reply, RPY_MANUAL_TIMESTAMP, 1)) {
offset_cs = ntohl(reply.data.manual_timestamp.centiseconds); offset_cs = ntohl(reply.data.manual_timestamp.centiseconds);
offset = 0.01 * (double) offset_cs; offset = 0.01 * (double) offset_cs;
dfreq_ppm = WIRE2REAL(reply.data.manual_timestamp.dfreq_ppm); dfreq_ppm = UTI_FloatNetworkToHost(reply.data.manual_timestamp.dfreq_ppm);
new_afreq_ppm = WIRE2REAL(reply.data.manual_timestamp.new_afreq_ppm); new_afreq_ppm = UTI_FloatNetworkToHost(reply.data.manual_timestamp.new_afreq_ppm);
printf("Clock was %.2f seconds fast. Frequency change = %.2fppm, new frequency = %.2fppm\n", printf("Clock was %.2f seconds fast. Frequency change = %.2fppm, new frequency = %.2fppm\n",
offset, dfreq_ppm, new_afreq_ppm); offset, dfreq_ppm, new_afreq_ppm);
return 1; return 1;

View file

@ -881,7 +881,7 @@ handle_modify_maxdelay(CMD_Request *rx_message, CMD_Reply *tx_message)
IPAddr address; IPAddr address;
UTI_IPNetworkToHost(&rx_message->data.modify_maxdelay.address, &address); UTI_IPNetworkToHost(&rx_message->data.modify_maxdelay.address, &address);
status = NSR_ModifyMaxdelay(&address, status = NSR_ModifyMaxdelay(&address,
WIRE2REAL(rx_message->data.modify_maxdelay.new_max_delay)); UTI_FloatNetworkToHost(rx_message->data.modify_maxdelay.new_max_delay));
if (status) { if (status) {
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
} else { } else {
@ -898,7 +898,7 @@ handle_modify_maxdelayratio(CMD_Request *rx_message, CMD_Reply *tx_message)
IPAddr address; IPAddr address;
UTI_IPNetworkToHost(&rx_message->data.modify_maxdelayratio.address, &address); UTI_IPNetworkToHost(&rx_message->data.modify_maxdelayratio.address, &address);
status = NSR_ModifyMaxdelayratio(&address, status = NSR_ModifyMaxdelayratio(&address,
WIRE2REAL(rx_message->data.modify_maxdelayratio.new_max_delay_ratio)); UTI_FloatNetworkToHost(rx_message->data.modify_maxdelayratio.new_max_delay_ratio));
if (status) { if (status) {
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
} else { } else {
@ -911,7 +911,7 @@ handle_modify_maxdelayratio(CMD_Request *rx_message, CMD_Reply *tx_message)
static void static void
handle_modify_maxupdateskew(CMD_Request *rx_message, CMD_Reply *tx_message) handle_modify_maxupdateskew(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
REF_ModifyMaxupdateskew(WIRE2REAL(rx_message->data.modify_maxupdateskew.new_max_update_skew)); REF_ModifyMaxupdateskew(UTI_FloatNetworkToHost(rx_message->data.modify_maxupdateskew.new_max_update_skew));
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
} }
@ -928,8 +928,8 @@ handle_settime(CMD_Request *rx_message, CMD_Reply *tx_message)
tx_message->status = htons(STT_SUCCESS); tx_message->status = htons(STT_SUCCESS);
tx_message->reply = htons(RPY_MANUAL_TIMESTAMP); tx_message->reply = htons(RPY_MANUAL_TIMESTAMP);
tx_message->data.manual_timestamp.centiseconds = htonl(offset_cs); tx_message->data.manual_timestamp.centiseconds = htonl(offset_cs);
tx_message->data.manual_timestamp.dfreq_ppm = REAL2WIRE(dfreq_ppm); tx_message->data.manual_timestamp.dfreq_ppm = UTI_FloatHostToNetwork(dfreq_ppm);
tx_message->data.manual_timestamp.new_afreq_ppm = REAL2WIRE(new_afreq_ppm); tx_message->data.manual_timestamp.new_afreq_ppm = UTI_FloatHostToNetwork(new_afreq_ppm);
} else { } else {
tx_message->status = htons(STT_NOTENABLED); tx_message->status = htons(STT_NOTENABLED);
} }
@ -1236,8 +1236,8 @@ handle_add_server(CMD_Request *rx_message, CMD_Reply *tx_message)
params.authkey = ntohl(rx_message->data.ntp_source.authkey); params.authkey = ntohl(rx_message->data.ntp_source.authkey);
params.online = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_ONLINE ? 1 : 0; params.online = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_ONLINE ? 1 : 0;
params.auto_offline = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_AUTOOFFLINE ? 1 : 0; params.auto_offline = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_AUTOOFFLINE ? 1 : 0;
params.max_delay = WIRE2REAL(rx_message->data.ntp_source.max_delay); params.max_delay = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay);
params.max_delay_ratio = WIRE2REAL(rx_message->data.ntp_source.max_delay_ratio); params.max_delay_ratio = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay_ratio);
status = NSR_AddServer(&rem_addr, &params); status = NSR_AddServer(&rem_addr, &params);
switch (status) { switch (status) {
case NSR_Success: case NSR_Success:
@ -1276,8 +1276,8 @@ handle_add_peer(CMD_Request *rx_message, CMD_Reply *tx_message)
params.authkey = ntohl(rx_message->data.ntp_source.authkey); params.authkey = ntohl(rx_message->data.ntp_source.authkey);
params.online = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_ONLINE ? 1 : 0; params.online = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_ONLINE ? 1 : 0;
params.auto_offline = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_AUTOOFFLINE ? 1 : 0; params.auto_offline = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_AUTOOFFLINE ? 1 : 0;
params.max_delay = WIRE2REAL(rx_message->data.ntp_source.max_delay); params.max_delay = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay);
params.max_delay_ratio = WIRE2REAL(rx_message->data.ntp_source.max_delay_ratio); params.max_delay_ratio = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay_ratio);
status = NSR_AddPeer(&rem_addr, &params); status = NSR_AddPeer(&rem_addr, &params);
switch (status) { switch (status) {
case NSR_Success: case NSR_Success:
@ -1350,7 +1350,7 @@ static void
handle_dfreq(CMD_Request *rx_message, CMD_Reply *tx_message) handle_dfreq(CMD_Request *rx_message, CMD_Reply *tx_message)
{ {
double dfreq; double dfreq;
dfreq = WIRE2REAL(rx_message->data.dfreq.dfreq); dfreq = UTI_FloatNetworkToHost(rx_message->data.dfreq.dfreq);
LCL_AccumulateDeltaFrequency(dfreq * 1.0e-6); LCL_AccumulateDeltaFrequency(dfreq * 1.0e-6);
LOG(LOGS_INFO, LOGF_CmdMon, "Accumulated delta freq of %.3fppm", dfreq); LOG(LOGS_INFO, LOGF_CmdMon, "Accumulated delta freq of %.3fppm", dfreq);
} }
@ -1385,11 +1385,11 @@ handle_tracking(CMD_Request *rx_message, CMD_Reply *tx_message)
UTI_TimevalHostToNetwork(&rpt.ref_time, &tx_message->data.tracking.ref_time); UTI_TimevalHostToNetwork(&rpt.ref_time, &tx_message->data.tracking.ref_time);
tx_message->data.tracking.current_correction_s = htonl(rpt.current_correction.tv_sec); tx_message->data.tracking.current_correction_s = htonl(rpt.current_correction.tv_sec);
tx_message->data.tracking.current_correction_us = htonl(rpt.current_correction.tv_usec); tx_message->data.tracking.current_correction_us = htonl(rpt.current_correction.tv_usec);
tx_message->data.tracking.freq_ppm = REAL2WIRE(rpt.freq_ppm); tx_message->data.tracking.freq_ppm = UTI_FloatHostToNetwork(rpt.freq_ppm);
tx_message->data.tracking.resid_freq_ppm = REAL2WIRE(rpt.resid_freq_ppm); tx_message->data.tracking.resid_freq_ppm = UTI_FloatHostToNetwork(rpt.resid_freq_ppm);
tx_message->data.tracking.skew_ppm = REAL2WIRE(rpt.skew_ppm); tx_message->data.tracking.skew_ppm = UTI_FloatHostToNetwork(rpt.skew_ppm);
tx_message->data.tracking.root_delay = REAL2WIRE(rpt.root_delay); tx_message->data.tracking.root_delay = UTI_FloatHostToNetwork(rpt.root_delay);
tx_message->data.tracking.root_dispersion = REAL2WIRE(rpt.root_dispersion); tx_message->data.tracking.root_dispersion = UTI_FloatHostToNetwork(rpt.root_dispersion);
} }
/* ================================================== */ /* ================================================== */
@ -1410,9 +1410,9 @@ handle_sourcestats(CMD_Request *rx_message, CMD_Reply *tx_message)
tx_message->data.sourcestats.n_samples = htonl(report.n_samples); tx_message->data.sourcestats.n_samples = htonl(report.n_samples);
tx_message->data.sourcestats.n_runs = htonl(report.n_runs); tx_message->data.sourcestats.n_runs = htonl(report.n_runs);
tx_message->data.sourcestats.span_seconds = htonl(report.span_seconds); tx_message->data.sourcestats.span_seconds = htonl(report.span_seconds);
tx_message->data.sourcestats.resid_freq_ppm = REAL2WIRE(report.resid_freq_ppm);
tx_message->data.sourcestats.skew_ppm = REAL2WIRE(report.skew_ppm);
tx_message->data.sourcestats.sd_us = htonl((unsigned long) (0.5 + report.sd_us)); tx_message->data.sourcestats.sd_us = htonl((unsigned long) (0.5 + report.sd_us));
tx_message->data.sourcestats.resid_freq_ppm = UTI_FloatHostToNetwork(report.resid_freq_ppm);
tx_message->data.sourcestats.skew_ppm = UTI_FloatHostToNetwork(report.skew_ppm);
} else { } else {
tx_message->status = htons(STT_NOSUCHSOURCE); tx_message->status = htons(STT_NOSUCHSOURCE);
} }
@ -1433,8 +1433,8 @@ handle_rtcreport(CMD_Request *rx_message, CMD_Reply *tx_message)
tx_message->data.rtc.n_samples = htons(report.n_samples); tx_message->data.rtc.n_samples = htons(report.n_samples);
tx_message->data.rtc.n_runs = htons(report.n_runs); tx_message->data.rtc.n_runs = htons(report.n_runs);
tx_message->data.rtc.span_seconds = htonl(report.span_seconds); tx_message->data.rtc.span_seconds = htonl(report.span_seconds);
tx_message->data.rtc.rtc_seconds_fast = REAL2WIRE(report.rtc_seconds_fast); tx_message->data.rtc.rtc_seconds_fast = UTI_FloatHostToNetwork(report.rtc_seconds_fast);
tx_message->data.rtc.rtc_gain_rate_ppm = REAL2WIRE(report.rtc_gain_rate_ppm); tx_message->data.rtc.rtc_gain_rate_ppm = UTI_FloatHostToNetwork(report.rtc_gain_rate_ppm);
} else { } else {
tx_message->status = htons(STT_NORTC); tx_message->status = htons(STT_NORTC);
} }
@ -1648,9 +1648,9 @@ handle_manual_list(CMD_Request *rx_message, CMD_Reply *tx_message)
for (i=0; i<n_samples; i++) { for (i=0; i<n_samples; i++) {
sample = &tx_message->data.manual_list.samples[i]; sample = &tx_message->data.manual_list.samples[i];
UTI_TimevalHostToNetwork(&report[i].when, &sample->when); UTI_TimevalHostToNetwork(&report[i].when, &sample->when);
sample->slewed_offset = REAL2WIRE(report[i].slewed_offset); sample->slewed_offset = UTI_FloatHostToNetwork(report[i].slewed_offset);
sample->orig_offset = REAL2WIRE(report[i].orig_offset); sample->orig_offset = UTI_FloatHostToNetwork(report[i].orig_offset);
sample->residual = REAL2WIRE(report[i].residual); sample->residual = UTI_FloatHostToNetwork(report[i].residual);
} }
} }

72
util.c
View file

@ -522,5 +522,77 @@ UTI_TimevalHostToNetwork(struct timeval *src, Timeval *dest)
dest->tv_sec_low = htonl(src->tv_sec); dest->tv_sec_low = htonl(src->tv_sec);
} }
/* ================================================== */
#define FLOAT_EXP_BITS 7
#define FLOAT_EXP_MIN (-(1 << (FLOAT_EXP_BITS - 1)))
#define FLOAT_EXP_MAX (-FLOAT_EXP_MIN - 1)
#define FLOAT_COEF_BITS ((int)sizeof (int32_t) * 8 - FLOAT_EXP_BITS)
#define FLOAT_COEF_MIN (-(1 << (FLOAT_COEF_BITS - 1)))
#define FLOAT_COEF_MAX (-FLOAT_COEF_MIN - 1)
double
UTI_FloatNetworkToHost(Float f)
{
int32_t exp, coef, x;
x = ntohl(f.f);
exp = (x >> FLOAT_COEF_BITS) - FLOAT_COEF_BITS;
coef = x << FLOAT_EXP_BITS >> FLOAT_EXP_BITS;
return coef * pow(2.0, exp);
}
Float
UTI_FloatHostToNetwork(double x)
{
int32_t exp, coef, neg;
Float f;
if (x < 0.0) {
x = -x;
neg = 1;
} else {
neg = 0;
}
if (x < 1.0e-100) {
exp = coef = 0;
} else if (x > 1.0e100) {
exp = FLOAT_EXP_MAX;
coef = FLOAT_COEF_MAX + neg;
} else {
exp = log(x) / log(2) + 1;
coef = x * pow(2.0, -exp + FLOAT_COEF_BITS) + 0.5;
assert(coef > 0);
/* we may need to shift up to two bits down */
while (coef > FLOAT_COEF_MAX + neg) {
coef >>= 1;
exp++;
}
if (exp > FLOAT_EXP_MAX) {
/* overflow */
exp = FLOAT_EXP_MAX;
coef = FLOAT_COEF_MAX + neg;
} else if (exp < FLOAT_EXP_MIN) {
/* underflow */
if (exp + FLOAT_COEF_BITS >= FLOAT_EXP_MIN) {
coef >>= FLOAT_EXP_MIN - exp;
exp = FLOAT_EXP_MIN;
} else {
exp = coef = 0;
}
}
}
/* negate back */
if (neg)
coef = (uint32_t)-coef << FLOAT_EXP_BITS >> FLOAT_EXP_BITS;
f.f = htonl(exp << FLOAT_COEF_BITS | coef);
return f;
}
/* ================================================== */ /* ================================================== */

3
util.h
View file

@ -99,6 +99,9 @@ extern void UTI_Int64ToTimeval(NTP_int64 *src, struct timeval *dest);
extern void UTI_TimevalNetworkToHost(Timeval *src, struct timeval *dest); extern void UTI_TimevalNetworkToHost(Timeval *src, struct timeval *dest);
extern void UTI_TimevalHostToNetwork(struct timeval *src, Timeval *dest); extern void UTI_TimevalHostToNetwork(struct timeval *src, Timeval *dest);
extern double UTI_FloatNetworkToHost(Float x);
extern Float UTI_FloatHostToNetwork(double x);
#if defined (INLINE_UTILITIES) #if defined (INLINE_UTILITIES)
#define INLINE_STATIC inline static #define INLINE_STATIC inline static
#include "util.c" #include "util.c"