#define POS_HOLD_AVERAGE 10000
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#if defined(REFCLOCK) && defined(CLOCK_ONCORE)
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#ifdef HAVE_PPSAPI
# ifdef HAVE_TIMEPPS_H
# include <timepps.h>
# else
# ifdef HAVE_SYS_TIMEPPS_H
# include <sys/timepps.h>
# endif
# endif
#endif
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_unixtime.h"
#include "ntp_refclock.h"
#include "ntp_stdlib.h"
#ifdef HAVE_SYS_TERMIOS_H
#include <sys/termios.h>
#endif
#ifdef HAVE_SYS_PPSCLOCK_H
# include <sys/ppsclock.h>
#endif
#ifndef HAVE_STRUCT_PPSCLOCKEV
struct ppsclockev {
# ifdef HAVE_TIMESPEC
struct timespec tv;
# else
struct timeval tv;
# endif
u_int serial;
};
#endif
enum receive_state {
ONCORE_NO_IDEA,
ONCORE_RESET_SENT,
ONCORE_TEST_SENT,
ONCORE_ID_SENT,
ONCORE_ALMANAC,
ONCORE_RUN
};
enum site_survey_state {
ONCORE_SS_UNKNOWN,
ONCORE_SS_HW,
ONCORE_SS_SW,
ONCORE_SS_DONE
};
struct instance {
int unit;
int ttyfd;
int ppsfd;
#ifdef HAVE_PPSAPI
pps_handle_t pps_h;
pps_params_t pps_p;
#endif
enum receive_state state;
enum site_survey_state site_survey;
struct refclockproc *pp;
struct peer *peer;
int Bj_day;
int assert;
long delay;
long offset;
double ss_lat;
double ss_long;
double ss_ht;
int ss_count;
u_char ss_ht_type;
int posn_set;
int printed;
int pollcnt;
int polled;
u_int ev_serial;
int Rcvptr;
u_char Rcvbuf[500];
u_char Ea[77];
u_char En[70];
u_char Cj[300];
u_char As;
u_char Ay;
u_char Az;
u_char init_type;
s_char saw_tooth;
};
#define rcvbuf instance->Rcvbuf
#define rcvptr instance->Rcvptr
static void oncore_consume P((struct instance *));
static void oncore_poll P((int, struct peer *));
static void oncore_read_config P((struct instance *));
static void oncore_receive P((struct recvbuf *));
static void oncore_sendmsg P((int fd, u_char *, u_int));
static void oncore_shutdown P((int, struct peer *));
static int oncore_start P((int, struct peer *));
static void oncore_stats P((struct instance *));
static void oncore_msg_any P((struct instance *, u_char *, u_int, int));
static void oncore_msg_As P((struct instance *, u_char *, u_int));
static void oncore_msg_At P((struct instance *, u_char *, u_int));
static void oncore_msg_Ay P((struct instance *, u_char *, u_int));
static void oncore_msg_Az P((struct instance *, u_char *, u_int));
static void oncore_msg_Bj P((struct instance *, u_char *, u_int));
static void oncore_msg_Cf P((struct instance *, u_char *, u_int));
static void oncore_msg_Cj P((struct instance *, u_char *, u_int));
static void oncore_msg_Ea P((struct instance *, u_char *, u_int));
static void oncore_msg_En P((struct instance *, u_char *, u_int));
static void oncore_msg_Fa P((struct instance *, u_char *, u_int));
struct refclock refclock_oncore = {
oncore_start,
oncore_shutdown,
oncore_poll,
noentry,
noentry,
noentry,
NOFLAGS
};
static struct {
const char flag[3];
const int len;
void (*handler) P((struct instance *, u_char *, u_int));
const char *fmt;
} oncore_messages[] = {
{ "Ea", 76, oncore_msg_Ea, "mdyyhmsffffaaaaoooohhhhmmmmvvhhddtntimsdimsdimsdimsdimsdimsdimsdimsdsC" },
{ "En", 69, oncore_msg_En, "otaapxxxxxxxxxxpysreensffffsffffsffffsffffsffffsffffsffffsffffC" },
{ "Ab", 10, 0, "" },
{ "Ac", 11, 0, "" },
{ "Ad", 11, 0, "" },
{ "Ae", 11, 0, "" },
{ "Af", 15, 0, "" },
{ "As", 20, oncore_msg_As, "" },
{ "At", 8, oncore_msg_At, "" },
{ "Aw", 8, 0, "" },
{ "Ay", 11, oncore_msg_Ay, "" },
{ "Az", 11, oncore_msg_Az, "" },
{ "AB", 8, 0, "" },
{ "Bb", 92, 0, "" },
{ "Bj", 8, oncore_msg_Bj, "" },
{ "Cb", 33, 0, "" },
{ "Cf", 7, oncore_msg_Cf, "" },
{ "Cg", 8, 0, "" },
{ "Ch", 9, 0, "" },
{ "Cj", 294, oncore_msg_Cj, "" },
{ "Ek", 71, 0, "" },
{ "Fa", 9, oncore_msg_Fa, "" },
{ "Sz", 8, 0, "" },
{ {0}, 7, 0, ""}
};
u_char oncore_cmd_Ad[] = { 'A', 'd', 0,0,0,0 };
u_char oncore_cmd_Ae[] = { 'A', 'e', 0,0,0,0 };
u_char oncore_cmd_Af[] = { 'A', 'f', 0,0,0,0, 0 };
static u_char oncore_cmd_At[] = { 'A', 't', 2 };
u_char oncore_cmd_As[] = { 'A', 's', 0,0,0,0, 0,0,0,0, 0,0,0,0, 0 };
u_char oncore_cmd_Asx[]= { 'A', 's', 0x7f, 0xff, 0xff, 0xff,
0x7f, 0xff, 0xff, 0xff,
0x7f, 0xff, 0xff, 0xff, 0xff };
u_char oncore_cmd_Aw[] = { 'A', 'w', 1 };
u_char oncore_cmd_Ay[] = { 'A', 'y', 0, 0, 0, 0 };
u_char oncore_cmd_Ayx[] = { 'A', 'y', 0xff, 0xff, 0xff, 0xff };
u_char oncore_cmd_Az[] = { 'A', 'z', 0, 0, 0, 0 };
u_char oncore_cmd_Azx[] = { 'A', 'z', 0xff, 0xff, 0xff, 0xff };
u_char oncore_cmd_AB[] = { 'A', 'B', 4 };
u_char oncore_cmd_Bb[] = { 'B', 'b', 0 };
u_char oncore_cmd_Bj[] = { 'B', 'j', 0 };
static u_char oncore_cmd_Cf[] = { 'C', 'f' };
u_char oncore_cmd_Cg[] = { 'C', 'g', 1 };
static u_char oncore_cmd_Cj[] = { 'C', 'j' };
static u_char oncore_cmd_Ea[] = { 'E', 'a', 1 };
u_char oncore_cmd_Ek[] = { 'E', 'k', 0 };
static u_char oncore_cmd_En[] = { 'E', 'n', 1, 1, 0,10, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
static u_char oncore_cmd_Fa[] = { 'F', 'a' };
#define DEVICE1 "/dev/oncore.serial.%d"
#define DEVICE2 "/dev/oncore.pps.%d"
#define INIT_FILE "/etc/ntp.oncore"
#define SPEED B9600
#define w32_buf(buf,w) { unsigned int i_tmp; \
i_tmp = (w<0) ? (~(-w)+1) : (w); \
(buf)[0] = (i_tmp >> 24) & 0xff; \
(buf)[1] = (i_tmp >> 16) & 0xff; \
(buf)[2] = (i_tmp >> 8) & 0xff; \
(buf)[3] = (i_tmp ) & 0xff; \
}
#define w32(buf) (((buf)[0]&0xff) << 24 | \
((buf)[1]&0xff) << 16 | \
((buf)[2]&0xff) << 8 | \
((buf)[3]&0xff) )
#define buf_w32(buf) (((buf)[0]&0200) ? (-(~w32(buf)+1)) : w32(buf))
static int
oncore_start(
int unit,
struct peer *peer
)
{
register struct instance *instance;
struct refclockproc *pp;
int fd1, fd2, mode;
char device1[30], device2[30];
const char *cp;
struct stat stat1, stat2;
(void)sprintf(device1, DEVICE1, unit);
(void)sprintf(device2, DEVICE2, unit);
if (stat(device1, &stat1)) {
perror("ONCORE: stat fd1");
exit(1);
}
if (stat(device2, &stat2)) {
perror("ONCORE: stat fd2");
exit(1);
}
if ((stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino)) {
if (!(fd1 = refclock_open(device1, SPEED, LDISC_RAW
#ifdef HAVE_PPSAPI
#else
| LDISC_PPS
#endif
))) {
perror("ONCORE: fd1");
exit(1);
}
fd2 = fd1;
} else {
if (!(fd1=refclock_open(device1, SPEED, LDISC_RAW))) {
perror("ONCORE: fd1");
exit(1);
}
if ((fd2=open(device2, O_RDWR)) < 0) {
perror("ONCORE: fd2");
exit(1);
}
}
if (!(instance = (struct instance *)emalloc(sizeof *instance))) {
perror("malloc");
close(fd1);
return (0);
}
memset((char *) instance, 0, sizeof *instance);
pp = peer->procptr;
pp->nstages = 16;
pp->nskeep = pp->nstages * 3 / 5;
pp->unitptr = (caddr_t)instance;
instance->unit = unit;
instance->ttyfd = fd1;
instance->ppsfd = fd2;
instance->Bj_day = -1;
instance->assert = 1;
oncore_read_config(instance);
#ifdef HAVE_PPSAPI
if (time_pps_create(fd2, &instance->pps_h) < 0) {
perror("time_pps_create");
exit(1);
}
if (instance->assert) {
instance->pps_p.mode = PPS_CAPTUREASSERT | PPS_OFFSETASSERT | PPS_HARDPPSONASSERT;
instance->pps_p.assert_offset.tv_sec = 0;
instance->pps_p.assert_offset.tv_nsec = 0;
} else {
instance->pps_p.mode = PPS_CAPTURECLEAR | PPS_OFFSETCLEAR | PPS_HARDPPSONCLEAR;
instance->pps_p.clear_offset.tv_sec = 0;
instance->pps_p.clear_offset.tv_nsec = 0;
}
if (time_pps_setparams(instance->pps_h, &instance->pps_p) < 0) {
perror("time_pps_setparams");
exit(1);
}
#endif
instance->pp = pp;
instance->peer = peer;
instance->state = ONCORE_NO_IDEA;
cp = "state = ONCORE_NO_IDEA";
record_clock_stats(&(instance->peer->srcadr), cp);
peer->precision = -26;
peer->minpoll = 4;
peer->maxpoll = 4;
pp->clockdesc = "Motorola UT/VP Oncore GPS Receiver";
memcpy((char *)&pp->refid, "GPS\0", 4);
pp->io.clock_recv = oncore_receive;
pp->io.srcclock = (caddr_t)peer;
pp->io.datalen = 0;
pp->io.fd = fd1;
if (!io_addclock(&pp->io)) {
perror("io_addclock");
(void) close(fd1);
free(instance);
return (0);
}
pp->unitptr = (caddr_t)instance;
mode = instance->init_type;
if (mode == 3 || mode == 4) {
oncore_sendmsg(instance->ttyfd, oncore_cmd_Cf, sizeof oncore_cmd_Cf);
instance->state = ONCORE_RESET_SENT;
cp = "state = ONCORE_RESET_SENT";
record_clock_stats(&(instance->peer->srcadr), cp);
} else {
oncore_sendmsg(instance->ttyfd, oncore_cmd_Fa, sizeof oncore_cmd_Fa);
instance->state = ONCORE_TEST_SENT;
cp = "state = ONCORE_TEST_SENT";
record_clock_stats(&(instance->peer->srcadr), cp);
}
instance->pollcnt = 2;
return (1);
}
static void
oncore_read_config(
struct instance *instance
)
{
FILE *fd;
char *cp, line[100], units[2], device[20];
int i, j, sign, lat_flg, long_flg, ht_flg, mode;
double f1, f2, f3;
sprintf(device, "%s%d", INIT_FILE, instance->unit);
if ((fd=fopen(device, "r")) == NULL)
if ((fd=fopen(INIT_FILE, "r")) == NULL) {
instance->init_type = 4;
return;
}
mode = 0;
lat_flg = long_flg = ht_flg = 0;
while (fgets(line, 100, fd)) {
if ((cp=strchr(line, '#')))
*cp = '\0';
i = strlen(line);
for (j=0; j<i; j++)
if (islower(line[j]))
line[j] = toupper(line[j]);
for (j=0; j<i; j++)
if (line[j] == '=')
line[j] = ' ';
for (j=0; j<i; j++)
if (line[j] != ' ')
break;
if (!strncmp(&line[j], "LAT", 3)) {
j += 3;
f1 = f2 = f3 = 0;
sscanf(&line[j], "%lf %lf %lf", &f1, &f2, &f3);
sign = 1;
if (f1 < 0) {
f1 = -f1;
sign = -1;
}
instance->ss_lat = sign*1000*(fabs(f3) + 60*(fabs(f2) + 60*f1));
lat_flg++;
} else if (!strncmp(&line[j], "LON", 3)) {
j += 3;
f1 = f2 = f3 = 0;
sscanf(&line[j], "%lf %lf %lf", &f1, &f2, &f3);
sign = 1;
if (f1 < 0) {
f1 = -f1;
sign = -1;
}
instance->ss_long = sign*1000*(fabs(f3) + 60*(fabs(f2) + 60*f1));
long_flg++;
} else if (!strncmp(&line[j], "HT", 2)) {
instance->ss_ht_type = 0;
if (!strncmp(&line[j], "HTGPS", 5)) {
instance->ss_ht_type = 0;
j +=3;
}
if (!strncmp(&line[j], "HTMSL", 5)) {
instance->ss_ht_type = 1;
j +=3;
}
j += 2;
f1 = 0;
units[0] = '\0';
sscanf(&line[j], "%lf %1s", &f1, units);
if (units[0] == 'F')
f1 = 0.3048 * f1;
instance->ss_ht = 100 * f1;
ht_flg++;
} else if (!strncmp(&line[j], "DELAY", 5)) {
j += 5;
f1 = 0;
units[0] = '\0';
sscanf(&line[j], "%lf %1s", &f1, units);
if (units[0] == 'N')
;
else if (units[0] == 'U')
f1 = 1000 * f1;
else if (units[0] == 'M')
f1 = 1000000 * f1;
else
f1 = 1000000000 * f1;
if (f1 < 0 || f1 > 1.e9)
f1 = 0;
instance->delay = f1;
} else if (!strncmp(&line[j], "OFFSET", 6)) {
j += 6;
f1 = 0;
units[0] = '\0';
sscanf(&line[j], "%lf %1s", &f1, units);
if (units[0] == 'N')
;
else if (units[0] == 'U')
f1 = 1000 * f1;
else if (units[0] == 'M')
f1 = 1000000 * f1;
else
f1 = 1000000000 * f1;
if (f1 < 0 || f1 > 1.e9)
f1 = 0;
instance->offset = f1;
} else if (!strncmp(&line[j], "MODE", 4)) {
j += 4;
sscanf(&line[j], "%d", &mode);
if (mode < 0 || mode > 4)
mode = 4;
instance->init_type = mode;
} else if (!strncmp(&line[j], "ASSERT", 6)) {
instance->assert = 1;
} else if (!strncmp(&line[j], "CLEAR", 5)) {
instance->assert = 0;
}
}
fclose(fd);
instance->posn_set = 1;
if ((lat_flg || long_flg || ht_flg) && !(lat_flg * long_flg * ht_flg)) {
printf("ONCORE: incomplete data on %s\n", INIT_FILE);
instance->posn_set = 0;
if (mode == 1 || mode == 3)
instance->init_type++;
}
}
static void
oncore_shutdown(
int unit,
struct peer *peer
)
{
register struct instance *instance;
struct refclockproc *pp;
pp = peer->procptr;
instance = (struct instance *) pp->unitptr;
free(instance);
}
static void
oncore_poll(
int unit,
struct peer *peer
)
{
struct instance *instance;
instance = (struct instance *) peer->procptr->unitptr;
if (!instance->pollcnt)
refclock_report(peer, CEVNT_TIMEOUT);
else
instance->pollcnt--;
peer->procptr->polls++;
instance->polled = 1;
}
static void
oncore_receive(
struct recvbuf *rbufp
)
{
u_int i;
u_char *p;
struct peer *peer;
struct instance *instance;
peer = (struct peer *)rbufp->recv_srcclock;
instance = (struct instance *) peer->procptr->unitptr;
p = (u_char *) &rbufp->recv_space;
#if 0
if (debug > 4) {
int i;
printf("ONCORE: >>>");
for(i=0; i<rbufp->recv_length; i++)
printf("%02x ", p[i]);
printf("\n");
printf("ONCORE: >>>");
for(i=0; i<rbufp->recv_length; i++)
printf("%03o ", p[i]);
printf("\n");
}
#endif
i = rbufp->recv_length;
if (rcvbuf+rcvptr+i > &rcvbuf[sizeof rcvbuf])
i = sizeof(rcvbuf) - rcvptr;
memcpy(rcvbuf+rcvptr, p, i);
rcvptr += i;
oncore_consume(instance);
}
static void
oncore_consume(
struct instance *instance
)
{
int i, l, j, m;
while (rcvptr >= 7) {
if (rcvbuf[0] != '@' || rcvbuf[1] != '@') {
for (i=1; i < rcvptr-1; i++)
if (rcvbuf[i] == '@' && rcvbuf[i+1] == '@')
break;
if (debug > 4)
printf("ONCORE: >>> skipping %d chars\n", i);
if (i != rcvptr)
memcpy(rcvbuf, rcvbuf+i, (unsigned)(rcvptr-i));
rcvptr -= i;
}
l = sizeof(oncore_messages)/sizeof(oncore_messages[0]) -1;
for(m=0; m<l; m++)
if (!strncmp(oncore_messages[m].flag, (char *)(rcvbuf+2), 2))
break;
l = oncore_messages[m].len;
#if 0
if (debug > 3)
printf("ONCORE: GOT: %c%c %d of %d entry %d\n", rcvbuf[2], rcvbuf[3], rcvptr, l, m);
#endif
if (rcvptr < l)
return;
j = 0;
for (i = 2; i < l-3; i++)
j ^= rcvbuf[i];
if (j == rcvbuf[l-3]) {
oncore_msg_any(instance, rcvbuf, (unsigned) (l-3), m);
if (oncore_messages[m].handler)
oncore_messages[m].handler(instance, rcvbuf, (unsigned) (l-3));
} else if (debug) {
printf("ONCORE: Checksum mismatch! calc %o is %o\n", j, rcvbuf[l-3]);
printf("ONCORE: @@%c%c ", rcvbuf[2], rcvbuf[3]);
for (i=4; i<l; i++)
printf("%03o ", rcvbuf[i]);
printf("\n");
}
if (l != rcvptr)
memcpy(rcvbuf, rcvbuf+l, (unsigned) (rcvptr-l));
rcvptr -= l;
}
}
static void
oncore_sendmsg(
int fd,
u_char *ptr,
u_int len
)
{
u_char cs = 0;
printf("ONCORE: Send @@%c%c %d\n", ptr[0], ptr[1], len);
write(fd, "@@", 2);
write(fd, ptr, len);
while (len--)
cs ^= *ptr++;
write(fd, &cs, 1);
write(fd, "\r\n", 2);
}
static void
oncore_msg_any(
struct instance *instance,
u_char *buf,
u_int len,
int idx
)
{
int i;
const char *fmt = oncore_messages[idx].fmt;
const char *p;
struct timeval tv;
if (debug > 3) {
GETTIMEOFDAY(&tv, 0);
printf("ONCORE: %ld.%06ld\n", (long) tv.tv_sec, (long) tv.tv_usec);
if (!*fmt) {
printf(">>@@%c%c ", buf[2], buf[3]);
for(i=2; i < len && i < 2400 ; i++)
printf("%02x", buf[i]);
printf("\n");
return;
} else {
printf("##");
for (p = fmt; *p; p++) {
putchar(*p);
putchar('_');
}
printf("\n%c%c", buf[2], buf[3]);
i = 4;
for (p = fmt; *p; p++) {
printf("%02x", buf[i++]);
}
printf("\n");
}
}
}
static void
oncore_msg_Cf(
struct instance *instance,
u_char *buf,
u_int len
)
{
const char *cp;
if (instance->state == ONCORE_RESET_SENT) {
oncore_sendmsg(instance->ttyfd, oncore_cmd_Fa, sizeof oncore_cmd_Fa);
instance->state = ONCORE_TEST_SENT;
cp = "state = ONCORE_TEST_SENT";
record_clock_stats(&(instance->peer->srcadr), cp);
}
}
static void
oncore_msg_Fa(
struct instance *instance,
u_char *buf,
u_int len
)
{
const char *cp;
if (instance->state == ONCORE_TEST_SENT) {
if (debug > 2)
printf("ONCORE: >>@@Fa %x %x\n", buf[4], buf[5]);
if (buf[4] || buf[5]) {
printf("ONCORE: SELF TEST FAILED\n");
exit(1);
}
sleep(2);
oncore_sendmsg(instance->ttyfd, oncore_cmd_Cj, sizeof oncore_cmd_Cj);
instance->state = ONCORE_ID_SENT;
cp = "state = ONCORE_ID_SENT";
record_clock_stats(&(instance->peer->srcadr), cp);
}
}
static void
oncore_msg_Cj(
struct instance *instance,
u_char *buf,
u_int len
)
{
const char *cp;
int mode;
if (instance->state != ONCORE_ID_SENT)
return;
memcpy(instance->Cj, buf, len);
oncore_sendmsg(instance->ttyfd, oncore_cmd_Cg, sizeof oncore_cmd_Cg);
oncore_sendmsg(instance->ttyfd, oncore_cmd_Bb, sizeof oncore_cmd_Bb);
oncore_sendmsg(instance->ttyfd, oncore_cmd_Ek, sizeof oncore_cmd_Ek);
oncore_sendmsg(instance->ttyfd, oncore_cmd_Aw, sizeof oncore_cmd_Aw);
oncore_sendmsg(instance->ttyfd, oncore_cmd_AB, sizeof oncore_cmd_AB);
mode = instance->init_type;
if (debug)
printf("ONCORE: INIT mode = %d\n", mode);
switch (mode) {
case 0:
instance->site_survey = ONCORE_SS_DONE;
break;
case 1:
case 3:
w32_buf(&oncore_cmd_As[2], (int) instance->ss_lat);
w32_buf(&oncore_cmd_As[6], (int) instance->ss_long);
w32_buf(&oncore_cmd_As[10], (int) instance->ss_ht);
oncore_cmd_As[14] = instance->ss_ht_type;
oncore_sendmsg(instance->ttyfd, oncore_cmd_As, sizeof oncore_cmd_As);
instance->site_survey = ONCORE_SS_DONE;
oncore_cmd_At[2] = 1;
oncore_sendmsg(instance->ttyfd, oncore_cmd_At, sizeof oncore_cmd_At);
record_clock_stats(&(instance->peer->srcadr), "Now in 0D mode");
break;
case 2:
case 4:
if (instance->posn_set) {
w32_buf(&oncore_cmd_Ad[2], (int) instance->ss_lat);
w32_buf(&oncore_cmd_Ae[2], (int) instance->ss_long);
w32_buf(&oncore_cmd_Af[2], (int) instance->ss_ht);
oncore_cmd_Af[6] = instance->ss_ht_type;
oncore_sendmsg(instance->ttyfd, oncore_cmd_Ad, sizeof oncore_cmd_Ad);
oncore_sendmsg(instance->ttyfd, oncore_cmd_Ae, sizeof oncore_cmd_Ae);
oncore_sendmsg(instance->ttyfd, oncore_cmd_Af, sizeof oncore_cmd_Af);
}
instance->site_survey = ONCORE_SS_UNKNOWN;
oncore_cmd_At[2] = 2;
oncore_sendmsg(instance->ttyfd, oncore_cmd_At, sizeof oncore_cmd_At);
break;
}
if (mode != 0) {
w32_buf(&oncore_cmd_Az[2], instance->delay);
oncore_sendmsg(instance->ttyfd, oncore_cmd_Az, sizeof oncore_cmd_Az);
w32_buf(&oncore_cmd_Ay[2], instance->offset);
oncore_sendmsg(instance->ttyfd, oncore_cmd_Ay, sizeof oncore_cmd_Ay);
}
oncore_sendmsg(instance->ttyfd, oncore_cmd_Ea, sizeof oncore_cmd_Ea);
instance->state = ONCORE_ALMANAC;
cp = "state = ONCORE_ALMANAC";
record_clock_stats(&(instance->peer->srcadr), cp);
}
static void
oncore_msg_Ea(
struct instance *instance,
u_char *buf,
u_int len
)
{
const char *cp;
if (instance->state != ONCORE_ALMANAC && instance->state != ONCORE_RUN)
return;
memcpy(instance->Ea, buf, len);
if (instance->state == ONCORE_ALMANAC) {
if ((instance->Ea[72] & 1)) {
if (debug)
printf("ONCORE: waiting for almanac\n");
return;
} else {
oncore_sendmsg(instance->ttyfd, oncore_cmd_En, sizeof oncore_cmd_En);
instance->state = ONCORE_RUN;
cp = "state = ONCORE_RUN";
record_clock_stats(&(instance->peer->srcadr), cp);
}
}
if ((instance->site_survey == ONCORE_SS_HW) && !(instance->Ea[37] & 0x20)) {
instance->site_survey = ONCORE_SS_DONE;
record_clock_stats(&(instance->peer->srcadr), "Now in 0D mode");
}
if (!instance->printed && instance->site_survey == ONCORE_SS_DONE) {
instance->printed = 1;
oncore_sendmsg(instance->ttyfd, oncore_cmd_Asx, sizeof oncore_cmd_Asx);
oncore_sendmsg(instance->ttyfd, oncore_cmd_Ayx, sizeof oncore_cmd_Ayx);
oncore_sendmsg(instance->ttyfd, oncore_cmd_Azx, sizeof oncore_cmd_Azx);
}
if ((buf[4] == 6) || (buf[4] == 12)) {
if (instance->Bj_day != buf[5]) {
instance->Bj_day = buf[5];
oncore_sendmsg(instance->ttyfd, oncore_cmd_Bj, sizeof oncore_cmd_Bj);
}
}
instance->pp->year = buf[6]*256+buf[7];
instance->pp->day = ymd2yd(buf[6]*256+buf[7], buf[4], buf[5]);
instance->pp->hour = buf[8];
instance->pp->minute = buf[9];
instance->pp->second = buf[10];
if (instance->site_survey != ONCORE_SS_SW)
return;
if (instance->Ea[37] & 1)
return;
if (instance->Ea[72] & 0x52)
return;
if (!(instance->Ea[72] & 0x20))
return;
instance->ss_lat += buf_w32(&instance->Ea[15]);
instance->ss_long += buf_w32(&instance->Ea[19]);
instance->ss_ht += buf_w32(&instance->Ea[23]);
instance->ss_count++;
if (debug)
printf("ONCORE: AVG %d %d %d %d\n",
instance->ss_count,
(unsigned) (instance->ss_lat / instance->ss_count),
(unsigned) (instance->ss_long / instance->ss_count),
(unsigned) (instance->ss_ht / instance->ss_count)
);
if (instance->ss_count != POS_HOLD_AVERAGE)
return;
instance->ss_lat /= POS_HOLD_AVERAGE;
instance->ss_long /= POS_HOLD_AVERAGE;
instance->ss_ht /= POS_HOLD_AVERAGE;
w32_buf(&oncore_cmd_As[2], (int) instance->ss_lat);
w32_buf(&oncore_cmd_As[6], (int) instance->ss_long);
w32_buf(&oncore_cmd_As[10], (int) instance->ss_ht);
oncore_cmd_As[14] = 0;
oncore_sendmsg(instance->ttyfd, oncore_cmd_As, sizeof oncore_cmd_As);
oncore_cmd_At[2] = 1;
oncore_sendmsg(instance->ttyfd, oncore_cmd_At, sizeof oncore_cmd_At);
record_clock_stats(&(instance->peer->srcadr), "Now in 0D mode");
instance->site_survey = ONCORE_SS_DONE;
}
static void
oncore_msg_En(
struct instance *instance,
u_char *buf,
u_int len
)
{
int j;
l_fp ts, ts_tmp;
double dmy;
#ifdef HAVE_TIMESPEC
struct timespec *tsp = 0;
#else
struct timeval *tsp = 0;
#endif
#ifdef HAVE_PPSAPI
pps_info_t pps_i;
#else
#ifdef HAVE_CIOGETEV
struct ppsclockev ev;
u_long r = CIOGETEV;
#endif
#ifdef HAVE_TIOCGPPSEV
struct ppsclockev ev;
u_long r = TIOCGPPSEV;
#endif
#endif
if (instance->state != ONCORE_RUN)
return;
memcpy(instance->En, buf, len);
if (instance->Ea[72] & 1)
return;
if (instance->En[21])
return;
#ifdef HAVE_PPSAPI
j = instance->ev_serial;
if (time_pps_fetch(instance->pps_h, &pps_i) < 0) {
printf("ONCORE: time_pps_fetch failed\n");
return;
}
if (instance->assert) {
tsp = &pps_i.assert_timestamp;
if (debug > 2)
printf("ONCORE: serial/j (%d, %d) %ld.%09ld\n",
pps_i.assert_sequence, j, tsp->tv_sec, tsp->tv_nsec);
if (pps_i.assert_sequence == j) {
printf("ONCORE: oncore_msg_En, error serial pps\n");
return;
}
instance->ev_serial = pps_i.assert_sequence;
} else {
tsp = &pps_i.clear_timestamp;
if (debug > 2)
printf("ONCORE: serial/j (%d, %d) %ld.%09ld\n",
pps_i.clear_sequence, j, tsp->tv_sec, tsp->tv_nsec);
if (pps_i.clear_sequence == j) {
printf("ONCORE: oncore_msg_En, error serial pps\n");
return;
}
instance->ev_serial = pps_i.clear_sequence;
}
dmy = tsp->tv_nsec;
dmy /= 1e9;
ts.l_uf = dmy * 4294967296.0;
ts.l_ui = tsp->tv_sec;
#if 0
alternate code for previous 4 lines is
dmy = 1.0e-9*tsp->tv_nsec;
DTOLFP(dmy, &ts);
dmy = tsp->tv_sec;
DTOLFP(dmy, &ts_tmp);
L_ADD(&ts, &ts_tmp);
or more simply
dmy = 1.0e-9*tsp->tv_nsec;
DTOLFP(dmy, &ts);
ts.l_ui = tsp->tv_sec;
#endif
#else
j = instance->ev_serial;
if (ioctl(instance->ppsfd, r, (caddr_t) &ev) < 0) {
perror("ONCORE: IOCTL:");
return;
}
tsp = &ev.tv;
if (debug > 2)
printf("ONCORE: serial/j (%d, %d) %ld.%06ld\n",
ev.serial, j, tsp->tv_sec, tsp->tv_usec);
if (ev.serial == j) {
printf("ONCORE: oncore_msg_En, error serial pps\n");
return;
}
instance->ev_serial = ev.serial;
TVTOTS(tsp, &ts);
#endif
j = instance->saw_tooth + instance->offset;
instance->saw_tooth = (s_char) buf[25];
#ifdef HAVE_PPSAPI
if (instance->assert) {
instance->pps_p.assert_offset.tv_nsec =
-(instance->saw_tooth + instance->offset);
} else {
instance->pps_p.clear_offset.tv_nsec =
-(instance->saw_tooth + instance->offset);
}
if (time_pps_setparams(instance->pps_h, &instance->pps_p))
perror("time_pps_setparams");
#else
dmy = -1.0e-9*j;
DTOLFP(dmy, &ts_tmp);
L_ADD(&ts, &ts_tmp);
#endif
ts.l_ui += JAN_1970;
instance->pp->lastrec = ts;
instance->pp->msec = 0;
ts_tmp = ts;
ts_tmp.l_ui = 0;
LFPTOD(&ts_tmp, dmy);
j = 1.0e9*dmy;
sprintf(instance->pp->a_lastcode,
"%u.%09u %d %d %2d %2d %2d %2ld rstat %02x dop %d nsat %2d,%d raim %d sigma %d neg-sawtooth %3d sat %d%d%d%d%d%d%d%d",
ts.l_ui, j,
instance->pp->year, instance->pp->day,
instance->pp->hour, instance->pp->minute, instance->pp->second,
(long) tsp->tv_sec % 60,
instance->Ea[72], instance->Ea[37], instance->Ea[38], instance->Ea[39], instance->En[21],
instance->En[23]*256+instance->En[24], (s_char) buf[25],
instance->Ea[41], instance->Ea[45], instance->Ea[49], instance->Ea[53],
instance->Ea[57], instance->Ea[61], instance->Ea[65], instance->Ea[69]
);
if (debug > 2) {
int i;
i = strlen(instance->pp->a_lastcode);
printf("ONCORE: len = %d %s\n", i, instance->pp->a_lastcode);
}
if (!refclock_process(instance->pp)) {
refclock_report(instance->peer, CEVNT_BADTIME);
return;
}
record_clock_stats(&(instance->peer->srcadr), instance->pp->a_lastcode);
instance->pollcnt = 2;
if (instance->polled) {
instance->polled = 0;
refclock_receive(instance->peer);
}
}
static void
oncore_msg_At(
struct instance *instance,
u_char *buf,
u_int len
)
{
if (instance->site_survey != ONCORE_SS_UNKNOWN)
return;
if (buf[4] == 2)
instance->site_survey = ONCORE_SS_HW;
else {
instance->site_survey = ONCORE_SS_SW;
oncore_cmd_At[2] = 0;
instance->ss_lat = instance->ss_long = instance->ss_ht = 0;
oncore_sendmsg(instance->ttyfd, oncore_cmd_At, sizeof oncore_cmd_At);
}
}
static void
oncore_msg_Bj(
struct instance *instance,
u_char *buf,
u_int len
)
{
const char *cp;
switch(buf[4]) {
case 1:
instance->peer->leap = LEAP_ADDSECOND;
cp = "Set peer.leap to LEAP_ADDSECOND";
break;
case 2:
instance->peer->leap = LEAP_DELSECOND;
cp = "Set peer.leap to LEAP_DELSECOND";
break;
case 0:
default:
instance->peer->leap = LEAP_NOWARNING;
cp = "Set peer.leap to LEAP_NOWARNING";
break;
}
record_clock_stats(&(instance->peer->srcadr), cp);
}
static void
oncore_msg_As(
struct instance *instance,
u_char *buf,
u_int len
)
{
int lat, lon, ht;
if (!instance->printed || instance->As)
return;
instance->As = 1;
lat = buf_w32(&buf[4]);
instance->ss_lat = lat;
lon = buf_w32(&buf[8]);
instance->ss_long = lon;
ht = buf_w32(&buf[12]);
instance->ss_ht = ht;
instance->ss_ht_type = buf[16];
if (instance->Ay && instance->Az)
oncore_stats(instance);
}
static void
oncore_msg_Ay(
struct instance *instance,
u_char *buf,
u_int len
)
{
if (!instance->printed || instance->Ay)
return;
instance->Ay = 1;
instance->offset = buf_w32(&buf[4]);
if (instance->As && instance->Az)
oncore_stats(instance);
}
static void
oncore_msg_Az(
struct instance *instance,
u_char *buf,
u_int len
)
{
if (!instance->printed || instance->Az)
return;
instance->Az = 1;
instance->delay = buf_w32(&buf[4]);
if (instance->As && instance->Ay)
oncore_stats(instance);
}
static void
oncore_stats(
struct instance *instance
)
{
char Msg[120], ew, ns, *cp, *cp1;
const char *Ht;
double xd, xm, xs, yd, ym, ys, hm, hft;
int idx, idy, is, imx, imy;
long lat, lon;
instance->Cj[294] = '\0';
for (cp=(char *)instance->Cj; cp< (char *) &instance->Cj[294]; ) {
cp1 = strchr(cp, '\r');
if (!cp1)
cp1 = (char *)&instance->Cj[294];
*cp1 = '\0';
record_clock_stats(&(instance->peer->srcadr), cp);
*cp1 = '\r';
cp = cp1+2;
}
record_clock_stats(&(instance->peer->srcadr), "Posn:");
ew = 'E';
lon = instance->ss_long;
if (lon < 0) {
ew = 'W';
lon = -lon;
}
ns = 'N';
lat = instance->ss_lat;
if (lat < 0) {
ns = 'S';
lat = -lat;
}
hm = instance->ss_ht/100.;
hft= hm/0.3048;
Ht = instance->ss_ht_type ? "MSL" : "GPS";
xd = lat/3600000.;
yd = lon/3600000.;
sprintf(Msg, "Lat = %c %11.7fdeg, Long = %c %11.7fdeg, Alt = %5.2fm (%5.2fft) %s", ns, xd, ew, yd, hm, hft, Ht);
record_clock_stats(&(instance->peer->srcadr), Msg);
idx = xd;
idy = yd;
imx = lat%3600000;
imy = lon%3600000;
xm = imx/60000.;
ym = imy/60000.;
sprintf(Msg, "Lat = %c %3ddeg %7.4fm, Long = %c %3ddeg %8.5fm, Alt = %5.2fm (%5.2fft) %s", ns, idx, xm, ew, idy, ym, hm, hft, Ht);
record_clock_stats(&(instance->peer->srcadr), Msg);
imx = xm;
imy = ym;
is = lat%60000;
xs = is/1000.;
is = lon%60000;
ys = is/1000.;
sprintf(Msg, "Lat = %c %3ddeg %2dm %5.2fs, Long = %c %3ddeg %2dm %5.2fs, Alt = %5.2fm (%5.2fft) %s", ns, idx, imx, xs, ew, idy, imy, ys, hm, hft, Ht);
record_clock_stats(&(instance->peer->srcadr), Msg);
sprintf(Msg, "Cable delay is set to %ld ns", instance->delay);
record_clock_stats(&(instance->peer->srcadr), Msg);
sprintf(Msg, "PPS Offset is set to %ld ns", instance->offset);
record_clock_stats(&(instance->peer->srcadr), Msg);
#ifdef HAVE_PPSAPI
if (instance->assert)
cp = "Timing on Assert.";
else
cp = "Timing on Clear.";
record_clock_stats(&(instance->peer->srcadr), cp);
#endif
}
#else
int refclock_oncore_bs;
#endif