#define POS_HOLD_AVERAGE 10000
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#if defined(REFCLOCK) && defined(CLOCK_ONCORE)
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_unixtime.h"
#include "ntp_refclock.h"
#include "ntp_stdlib.h"
#include <stdio.h>
#include <ctype.h>
#include <sys/stat.h>
#ifdef ONCORE_SHMEM_STATUS
# ifdef HAVE_SYS_MMAN_H
# include <sys/mman.h>
# ifndef MAP_FAILED
# define MAP_FAILED ((u_char *) -1)
# endif
# endif
#endif
#ifdef HAVE_PPSAPI
# include "ppsapi_timepps.h"
#endif
#ifdef HAVE_SYS_SIO_H
# include <sys/sio.h>
#endif
struct Bl {
int dt_ls;
int dt_lsf;
int WN;
int DN;
int WN_lsf;
int DN_lsf;
int wn_flg;
int lsf_flg;
int Bl_day;
} Bl;
enum receive_state {
ONCORE_NO_IDEA,
ONCORE_CHECK_ID,
ONCORE_CHECK_CHAN,
ONCORE_HAVE_CHAN,
ONCORE_RESET_SENT,
ONCORE_TEST_SENT,
ONCORE_INIT,
ONCORE_ALMANAC,
ONCORE_RUN
};
enum site_survey_state {
ONCORE_SS_UNKNOWN,
ONCORE_SS_TESTING,
ONCORE_SS_HW,
ONCORE_SS_SW,
ONCORE_SS_DONE
};
enum antenna_state {
ONCORE_ANTENNA_UNKNOWN = -1,
ONCORE_ANTENNA_OK = 0,
ONCORE_ANTENNA_OC = 1,
ONCORE_ANTENNA_UC = 2,
ONCORE_ANTENNA_NV = 3
};
enum oncore_model {
ONCORE_BASIC,
ONCORE_PVT6,
ONCORE_VP,
ONCORE_UT,
ONCORE_UTPLUS,
ONCORE_GT,
ONCORE_GTPLUS,
ONCORE_SL,
ONCORE_M12,
ONCORE_UNKNOWN
};
struct RSM {
u_char posn0D;
u_char posn2D;
u_char posn3D;
u_char bad_almanac;
u_char bad_fix;
};
enum posn_mode {
MODE_UNKNOWN,
MODE_0D,
MODE_2D,
MODE_3D
};
struct instance {
int unit;
struct refclockproc *pp;
struct peer *peer;
int ttyfd;
int ppsfd;
int shmemfd;
pps_handle_t pps_h;
pps_params_t pps_p;
enum receive_state o_state;
enum posn_mode mode;
enum site_survey_state site_survey;
enum antenna_state ant_state;
int Bj_day;
u_long delay;
long offset;
u_char *shmem;
char *shmem_fname;
u_int shmem_Cb;
u_int shmem_Ba;
u_int shmem_Ea;
u_int shmem_Ha;
u_char shmem_reset;
u_char shmem_Posn;
u_char shmem_bad_Ea;
u_char almanac_from_shmem;
double ss_lat;
double ss_long;
double ss_ht;
double dH;
int ss_count;
u_char posn_set;
enum oncore_model model;
u_int version;
u_int revision;
u_char chan;
s_char traim;
u_char traim_delay;
u_char count;
u_char count1;
u_char count2;
u_char count3;
u_char count4;
u_char count5;
u_char count5_set;
u_char counta;
u_char pollcnt;
u_char timeout;
u_char max_len;
u_char max_count;
struct RSM rsm;
struct Bl Bl;
u_char printed;
u_char polled;
u_long ev_serial;
int Rcvptr;
u_char Rcvbuf[500];
u_char BEHa[160];
u_char BEHn[80];
u_char Cj[300];
u_char Ag;
u_char saw_At;
u_char saw_Ay;
u_char saw_Az;
s_char saw_Bj;
s_char saw_Gj;
u_char have_dH;
u_char init_type;
s_char saw_tooth;
s_char chan_in;
u_char chan_id;
u_char chan_ck;
s_char traim_in;
s_char traim_id;
u_char traim_ck;
u_char once;
s_char assert;
u_char hardpps;
};
#define rcvbuf instance->Rcvbuf
#define rcvptr instance->Rcvptr
static int oncore_start (int, struct peer *);
static void oncore_poll (int, struct peer *);
static void oncore_shutdown (int, struct peer *);
static void oncore_consume (struct instance *);
static void oncore_read_config (struct instance *);
static void oncore_receive (struct recvbuf *);
static int oncore_ppsapi (struct instance *);
static void oncore_get_timestamp (struct instance *, long, long);
static void oncore_init_shmem (struct instance *);
static void oncore_antenna_report (struct instance *, enum antenna_state);
static void oncore_chan_test (struct instance *);
static void oncore_check_almanac (struct instance *);
static void oncore_check_antenna (struct instance *);
static void oncore_check_leap_sec (struct instance *);
static int oncore_checksum_ok (u_char *, int);
static void oncore_compute_dH (struct instance *);
static void oncore_load_almanac (struct instance *);
static void oncore_log (struct instance *, int, const char *);
static void oncore_print_Cb (struct instance *, u_char *);
static void oncore_print_posn (struct instance *);
static void oncore_sendmsg (struct instance *, u_char *, size_t);
static void oncore_set_posn (struct instance *);
static void oncore_set_traim (struct instance *);
static void oncore_shmem_get_3D (struct instance *);
static void oncore_ss (struct instance *);
static int oncore_wait_almanac (struct instance *);
static void oncore_msg_any (struct instance *, u_char *, size_t, int);
static void oncore_msg_Adef (struct instance *, u_char *, size_t);
static void oncore_msg_Ag (struct instance *, u_char *, size_t);
static void oncore_msg_As (struct instance *, u_char *, size_t);
static void oncore_msg_At (struct instance *, u_char *, size_t);
static void oncore_msg_Ay (struct instance *, u_char *, size_t);
static void oncore_msg_Az (struct instance *, u_char *, size_t);
static void oncore_msg_BaEaHa (struct instance *, u_char *, size_t);
static void oncore_msg_Bd (struct instance *, u_char *, size_t);
static void oncore_msg_Bj (struct instance *, u_char *, size_t);
static void oncore_msg_Bl (struct instance *, u_char *, size_t);
static void oncore_msg_BnEnHn (struct instance *, u_char *, size_t);
static void oncore_msg_CaFaIa (struct instance *, u_char *, size_t);
static void oncore_msg_Cb (struct instance *, u_char *, size_t);
static void oncore_msg_Cf (struct instance *, u_char *, size_t);
static void oncore_msg_Cj (struct instance *, u_char *, size_t);
static void oncore_msg_Cj_id (struct instance *, u_char *, size_t);
static void oncore_msg_Cj_init (struct instance *, u_char *, size_t);
static void oncore_msg_Ga (struct instance *, u_char *, size_t);
static void oncore_msg_Gb (struct instance *, u_char *, size_t);
static void oncore_msg_Gj (struct instance *, u_char *, size_t);
static void oncore_msg_Sz (struct instance *, u_char *, size_t);
struct refclock refclock_oncore = {
oncore_start,
oncore_shutdown,
oncore_poll,
noentry,
noentry,
noentry,
NOFLAGS
};
static struct msg_desc {
const char flag[3];
const int len;
void (*handler) (struct instance *, u_char *, size_t);
const char *fmt;
int shmem;
} oncore_messages[] = {
{ "Ea", 76, oncore_msg_BaEaHa, "mdyyhmsffffaaaaoooohhhhmmmmvvhhddtntimsdimsdimsdimsdimsdimsdimsdimsdsC" },
{ "Ba", 68, oncore_msg_BaEaHa, "mdyyhmsffffaaaaoooohhhhmmmmvvhhddtntimsdimsdimsdimsdimsdimsdsC" },
{ "Ha", 154, oncore_msg_BaEaHa, "mdyyhmsffffaaaaoooohhhhmmmmaaaaoooohhhhmmmmVVvvhhddntimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddssrrccooooTTushmvvvvvvC" },
{ "Bn", 59, oncore_msg_BnEnHn, "otaapxxxxxxxxxxpysreensffffsffffsffffsffffsffffsffffC" },
{ "En", 69, oncore_msg_BnEnHn, "otaapxxxxxxxxxxpysreensffffsffffsffffsffffsffffsffffsffffsffffC" },
{ "Hn", 78, oncore_msg_BnEnHn, "" },
{ "Ab", 10, 0, "" },
{ "Ac", 11, 0, "" },
{ "Ad", 11, oncore_msg_Adef, "" },
{ "Ae", 11, oncore_msg_Adef, "" },
{ "Af", 15, oncore_msg_Adef, "" },
{ "Ag", 8, oncore_msg_Ag, "" },
{ "As", 20, oncore_msg_As, "" },
{ "At", 8, oncore_msg_At, "" },
{ "Au", 12, 0, "" },
{ "Av", 8, 0, "" },
{ "Aw", 8, 0, "" },
{ "Ay", 11, oncore_msg_Ay, "" },
{ "Az", 11, oncore_msg_Az, "" },
{ "AB", 8, 0, "" },
{ "Bb", 92, 0, "" },
{ "Bd", 23, oncore_msg_Bd, "" },
{ "Bj", 8, oncore_msg_Bj, "" },
{ "Bl", 41, oncore_msg_Bl, "" },
{ "Ca", 9, oncore_msg_CaFaIa, "" },
{ "Cb", 33, oncore_msg_Cb, "" },
{ "Cf", 7, oncore_msg_Cf, "" },
{ "Cg", 8, 0, "" },
{ "Ch", 9, 0, "" },
{ "Cj", 294, oncore_msg_Cj, "" },
{ "Ek", 71, 0, "" },
{ "Fa", 9, oncore_msg_CaFaIa, "" },
{ "Ga", 20, oncore_msg_Ga, "" },
{ "Gb", 17, oncore_msg_Gb, "" },
{ "Gc", 8, 0, "" },
{ "Gd", 8, 0, "" },
{ "Ge", 8, 0, "" },
{ "Gj", 21, oncore_msg_Gj, "" },
{ "Ia", 10, oncore_msg_CaFaIa, "" },
{ "Sz", 8, oncore_msg_Sz, "" },
{ {0}, 7, 0, "" }
};
static u_char oncore_cmd_Aa[] = { 'A', 'a', 0, 0, 0 };
static u_char oncore_cmd_Ab[] = { 'A', 'b', 0, 0, 0 };
static u_char oncore_cmd_AB[] = { 'A', 'B', 4 };
static u_char oncore_cmd_Ac[] = { 'A', 'c', 0, 0, 0, 0 };
static u_char oncore_cmd_Ad[] = { 'A', 'd', 0,0,0,0 };
static u_char oncore_cmd_Ae[] = { 'A', 'e', 0,0,0,0 };
static u_char oncore_cmd_Af[] = { 'A', 'f', 0,0,0,0, 0 };
static u_char oncore_cmd_Ag[] = { 'A', 'g', 0 };
static u_char oncore_cmd_Agx[] = { 'A', 'g', 0xff };
static u_char oncore_cmd_As[] = { 'A', 's', 0,0,0,0, 0,0,0,0, 0,0,0,0, 0 };
static u_char oncore_cmd_Asx[] = { 'A', 's', 0x7f,0xff,0xff,0xff,
0x7f,0xff,0xff,0xff,
0x7f,0xff,0xff,0xff, 0xff };
static u_char oncore_cmd_At0[] = { 'A', 't', 0 };
static u_char oncore_cmd_At1[] = { 'A', 't', 1 };
static u_char oncore_cmd_At2[] = { 'A', 't', 2 };
static u_char oncore_cmd_Atx[] = { 'A', 't', 0xff };
static u_char oncore_cmd_Au[] = { 'A', 'u', 0,0,0,0, 0 };
static u_char oncore_cmd_Av0[] = { 'A', 'v', 0 };
static u_char oncore_cmd_Av1[] = { 'A', 'v', 1 };
static u_char oncore_cmd_Aw[] = { 'A', 'w', 1 };
static u_char oncore_cmd_Ay[] = { 'A', 'y', 0, 0, 0, 0 };
static u_char oncore_cmd_Ayx[] = { 'A', 'y', 0xff, 0xff, 0xff, 0xff };
static u_char oncore_cmd_Az[] = { 'A', 'z', 0, 0, 0, 0 };
static u_char oncore_cmd_Azx[] = { 'A', 'z', 0xff, 0xff, 0xff, 0xff };
static u_char oncore_cmd_Ba0[] = { 'B', 'a', 0 };
static u_char oncore_cmd_Ba[] = { 'B', 'a', 1 };
static u_char oncore_cmd_Bb[] = { 'B', 'b', 1 };
static u_char oncore_cmd_Bd[] = { 'B', 'd', 1 };
static u_char oncore_cmd_Be[] = { 'B', 'e', 1 };
static u_char oncore_cmd_Bj[] = { 'B', 'j', 0 };
static u_char oncore_cmd_Bl[] = { 'B', 'l', 1 };
static u_char oncore_cmd_Bn0[] = { 'B', 'n', 0, 1, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 };
static u_char oncore_cmd_Bn[] = { 'B', 'n', 1, 1, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 };
static u_char oncore_cmd_Bnx[] = { 'B', 'n', 0, 0, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 };
static u_char oncore_cmd_Ca[] = { 'C', 'a' };
static u_char oncore_cmd_Cf[] = { 'C', 'f' };
static u_char oncore_cmd_Cg[] = { 'C', 'g', 1 };
static u_char oncore_cmd_Cj[] = { 'C', 'j' };
static u_char oncore_cmd_Ea0[] = { 'E', 'a', 0 };
static u_char oncore_cmd_Ea[] = { 'E', 'a', 1 };
static u_char oncore_cmd_Ek[] = { 'E', 'k', 0 };
static u_char oncore_cmd_En0[] = { 'E', 'n', 0, 1, 0,10, 2, 0,0,0, 0,0,0,0,0,0,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_Enx[] = { 'E', 'n', 0, 0, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 };
static u_char oncore_cmd_Fa[] = { 'F', 'a' };
static u_char oncore_cmd_Ga[] = { 'G', 'a', 0,0,0,0, 0,0,0,0, 0,0,0,0, 0 };
static u_char oncore_cmd_Gax[] = { 'G', 'a', 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff };
static u_char oncore_cmd_Gb[] = { 'G', 'b', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
static u_char oncore_cmd_Gc[] = { 'G', 'c', 1 };
static u_char oncore_cmd_Gd0[] = { 'G', 'd', 0 };
static u_char oncore_cmd_Gd1[] = { 'G', 'd', 1 };
static u_char oncore_cmd_Gd2[] = { 'G', 'd', 2 };
static u_char oncore_cmd_Gd3[] = { 'G', 'd', 3 };
static u_char oncore_cmd_Ge0[] = { 'G', 'e', 0 };
static u_char oncore_cmd_Ge[] = { 'G', 'e', 1 };
static u_char oncore_cmd_Gj[] = { 'G', 'j' };
static u_char oncore_cmd_Ha0[] = { 'H', 'a', 0 };
static u_char oncore_cmd_Ha[] = { 'H', 'a', 1 };
static u_char oncore_cmd_Hn0[] = { 'H', 'n', 0 };
static u_char oncore_cmd_Hn[] = { 'H', 'n', 1 };
static u_char oncore_cmd_Ia[] = { 'I', 'a' };
static char *Month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jly",
"Aug", "Sep", "Oct", "Nov", "Dec" };
#define DEVICE1 "/dev/oncore.serial.%d"
#define DEVICE2 "/dev/oncore.pps.%d"
#define SPEED B9600
#define w32_buf(buf,w) { u_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
)
{
#define STRING_LEN 32
register struct instance *instance;
struct refclockproc *pp;
int fd1, fd2;
char device1[STRING_LEN], device2[STRING_LEN], Msg[160];
struct stat stat1, stat2;
instance = emalloc(sizeof(*instance));
memset(instance, 0, sizeof(*instance));
pp = peer->procptr;
pp->unitptr = (caddr_t) instance;
instance->pp = pp;
instance->unit = unit;
instance->peer = peer;
instance->assert = 1;
instance->once = 1;
instance->Bj_day = -1;
instance->traim = -1;
instance->traim_in = -1;
instance->chan_in = -1;
instance->model = ONCORE_UNKNOWN;
instance->mode = MODE_UNKNOWN;
instance->site_survey = ONCORE_SS_UNKNOWN;
instance->Ag = 0xff;
instance->ant_state = ONCORE_ANTENNA_UNKNOWN;
peer->precision = -26;
peer->minpoll = 4;
peer->maxpoll = 4;
pp->clockdesc = "Motorola Oncore GPS Receiver";
memcpy((char *)&pp->refid, "GPS\0", (size_t) 4);
oncore_log(instance, LOG_NOTICE, "ONCORE DRIVER -- CONFIGURING");
instance->o_state = ONCORE_NO_IDEA;
(void)snprintf(device1, sizeof(device1), DEVICE1, unit);
(void)snprintf(device2, sizeof(device2), DEVICE2, unit);
#ifndef SYS_WINNT
if (stat(device1, &stat1)) {
snprintf(Msg, sizeof(Msg), "Can't stat fd1 (%s)",
device1);
oncore_log(instance, LOG_ERR, Msg);
return(0);
}
if (stat(device2, &stat2)) {
stat2.st_dev = stat2.st_ino = -2;
snprintf(Msg, sizeof(Msg),
"Can't stat fd2 (%s) errno = %d",
device2, errno);
oncore_log(instance, LOG_ERR, Msg);
}
#endif
if (!(fd1 = refclock_open(device1, SPEED, LDISC_RAW))) {
snprintf(Msg, sizeof(Msg), "Can't open fd1 (%s)",
device1);
oncore_log(instance, LOG_ERR, Msg);
return(0);
}
#ifndef SYS_WINNT
if ((stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino))
fd2 = fd1;
else
#endif
{
if ((fd2=tty_open(device2, O_RDWR, 0777)) < 0) {
snprintf(Msg, sizeof(Msg),
"Can't open fd2 (%s)", device2);
oncore_log(instance, LOG_ERR, Msg);
return(0);
}
}
if (time_pps_create(fd2, &instance->pps_h) < 0) {
oncore_log(instance, LOG_ERR, "exit, PPSAPI not found in kernel");
return(0);
}
instance->ttyfd = fd1;
instance->ppsfd = fd2;
oncore_read_config(instance);
if (!oncore_ppsapi(instance))
return(0);
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)) {
oncore_log(instance, LOG_ERR, "can't do io_addclock");
(void) close(fd1);
free(instance);
return (0);
}
#ifdef ONCORE_SHMEM_STATUS
oncore_init_shmem(instance);
#endif
instance->o_state = ONCORE_CHECK_ID;
oncore_log(instance, LOG_NOTICE, "state = ONCORE_CHECK_ID");
instance->timeout = 4;
oncore_sendmsg(instance, oncore_cmd_Cg, sizeof(oncore_cmd_Cg));
oncore_sendmsg(instance, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
instance->pollcnt = 2;
return (1);
}
static void
oncore_shutdown(
int unit,
struct peer *peer
)
{
register struct instance *instance;
struct refclockproc *pp;
pp = peer->procptr;
instance = (struct instance *) pp->unitptr;
io_closeclock(&pp->io);
time_pps_destroy (instance->pps_h);
close(instance->ttyfd);
if ((instance->ppsfd != -1) && (instance->ppsfd != instance->ttyfd))
close(instance->ppsfd);
if (instance->shmemfd)
close(instance->shmemfd);
free(instance);
}
static void
oncore_poll(
int unit,
struct peer *peer
)
{
struct instance *instance;
instance = (struct instance *) peer->procptr->unitptr;
if (instance->timeout) {
instance->timeout--;
if (instance->timeout == 0) {
oncore_log(instance, LOG_ERR,
"Oncore: No response from @@Cj, shutting down driver");
oncore_shutdown(unit, peer);
} else {
oncore_sendmsg(instance, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
oncore_log(instance, LOG_WARNING, "Oncore: Resend @@Cj");
}
return;
}
if (!instance->pollcnt)
refclock_report(peer, CEVNT_TIMEOUT);
else
instance->pollcnt--;
peer->procptr->polls++;
instance->polled = 1;
}
static int
oncore_ppsapi(
struct instance *instance
)
{
int cap, mode, mode1;
char *cp, Msg[160];
if (time_pps_getcap(instance->pps_h, &cap) < 0) {
oncore_log(instance, LOG_ERR, "time_pps_getcap failed: %m");
return (0);
}
if (time_pps_getparams(instance->pps_h, &instance->pps_p) < 0) {
oncore_log(instance, LOG_ERR, "time_pps_getparams failed: %m");
return (0);
}
if (instance->assert) {
cp = "Assert";
mode = PPS_CAPTUREASSERT;
mode1 = PPS_OFFSETASSERT;
} else {
cp = "Clear";
mode = PPS_CAPTURECLEAR;
mode1 = PPS_OFFSETCLEAR;
}
snprintf(Msg, sizeof(Msg), "Initializing timing to %s.", cp);
oncore_log(instance, LOG_INFO, Msg);
if (!(mode & cap)) {
snprintf(Msg, sizeof(Msg),
"Can't set timing to %s, exiting...", cp);
oncore_log(instance, LOG_ERR, Msg);
return(0);
}
if (!(mode1 & cap)) {
snprintf(Msg, sizeof(Msg),
"Can't set %s, this will increase jitter.", cp);
oncore_log(instance, LOG_NOTICE, Msg);
mode1 = 0;
}
instance->pps_p.mode = (mode | mode1 | PPS_TSFMT_TSPEC) & cap;
if (time_pps_setparams(instance->pps_h, &instance->pps_p) < 0) {
oncore_log(instance, LOG_ERR, "ONCORE: time_pps_setparams fails");
return(0);
}
if (instance->hardpps) {
int i;
oncore_log(instance, LOG_INFO, "HARDPPS Set.");
if (instance->assert)
i = PPS_CAPTUREASSERT;
else
i = PPS_CAPTURECLEAR;
if (time_pps_kcbind(instance->pps_h, PPS_KC_HARDPPS, i,
PPS_TSFMT_TSPEC) < 0) {
oncore_log(instance, LOG_ERR, "time_pps_kcbind failed: %m");
oncore_log(instance, LOG_ERR, "HARDPPS failed, abort...");
return (0);
}
pps_enable = 1;
}
return(1);
}
#ifdef ONCORE_SHMEM_STATUS
static void
oncore_init_shmem(
struct instance *instance
)
{
int i, l, n, fd, shmem_old_size, n1;
char Msg[160];
u_char *cp, *cp1, *buf, *shmem_old;
struct msg_desc *mp;
struct stat sbuf;
size_t shmem_length;
shmem_old = 0;
shmem_old_size = 0;
if ((fd = open(instance->shmem_fname, O_RDONLY)) < 0)
oncore_log(instance, LOG_WARNING, "ONCORE: Can't open SHMEM file");
else {
fstat(fd, &sbuf);
shmem_old_size = sbuf.st_size;
if (shmem_old_size != 0) {
shmem_old = emalloc((unsigned) sbuf.st_size);
read(fd, shmem_old, shmem_old_size);
}
close(fd);
}
if ((instance->shmemfd = open(instance->shmem_fname, O_RDWR|O_CREAT|O_TRUNC, 0644)) < 0) {
oncore_log(instance, LOG_WARNING, "ONCORE: Can't open shmem");
if (shmem_old)
free(shmem_old);
return;
}
n = 1;
for (mp=oncore_messages; mp->flag[0]; mp++) {
mp->shmem = n;
if (!strcmp(mp->flag, "Cb")) {
instance->shmem_Cb = n;
n += (mp->len + 3) * 34;
}
if (!strcmp(mp->flag, "Ba")) {
instance->shmem_Ba = n;
n += (mp->len + 3) * 3;
}
if (!strcmp(mp->flag, "Ea")) {
instance->shmem_Ea = n;
n += (mp->len + 3) * 3;
}
if (!strcmp(mp->flag, "Ha")) {
instance->shmem_Ha = n;
n += (mp->len + 3) * 3;
}
n += (mp->len + 3);
}
shmem_length = n + 2;
buf = emalloc(shmem_length);
memset(buf, 0, shmem_length);
for (mp=oncore_messages; mp->flag[0]; mp++) {
l = mp->shmem;
buf[l + 0] = mp->len >> 8;
buf[l + 1] = mp->len & 0xff;
buf[l + 2] = 0;
buf[l + 3] = '@';
buf[l + 4] = '@';
buf[l + 5] = mp->flag[0];
buf[l + 6] = mp->flag[1];
if (!strcmp(mp->flag, "Cb") || !strcmp(mp->flag, "Ba") || !strcmp(mp->flag, "Ea") || !strcmp(mp->flag, "Ha")) {
if (!strcmp(mp->flag, "Cb"))
n = 35;
else
n = 4;
for (i=1; i<n; i++) {
buf[l + i * (mp->len+3) + 0] = mp->len >> 8;
buf[l + i * (mp->len+3) + 1] = mp->len & 0xff;
buf[l + i * (mp->len+3) + 2] = 0;
buf[l + i * (mp->len+3) + 3] = '@';
buf[l + i * (mp->len+3) + 4] = '@';
buf[l + i * (mp->len+3) + 5] = mp->flag[0];
buf[l + i * (mp->len+3) + 6] = mp->flag[1];
}
}
}
if (shmem_old) {
if (shmem_old_size == shmem_length) {
for (cp=buf+4, cp1=shmem_old+4; (n = 256*(*(cp-3)) + *(cp-2)); cp+=(n+3), cp1+=(n+3)) {
n1 = 256*(*(cp1-3)) + *(cp1-2);
if (n == 0 || n1 != n || strncmp((char *) cp, (char *) cp1, 4))
break;
memcpy(cp, cp1, (size_t) n);
}
}
free(shmem_old);
}
i = write(instance->shmemfd, buf, shmem_length);
free(buf);
if (i != shmem_length) {
oncore_log(instance, LOG_ERR, "ONCORE: error writing shmem");
close(instance->shmemfd);
return;
}
instance->shmem = (u_char *) mmap(0, shmem_length,
PROT_READ | PROT_WRITE,
#ifdef MAP_HASSEMAPHORE
MAP_HASSEMAPHORE |
#endif
MAP_SHARED, instance->shmemfd, (off_t)0);
if (instance->shmem == (u_char *)MAP_FAILED) {
instance->shmem = 0;
close(instance->shmemfd);
return;
}
snprintf(Msg, sizeof(Msg),
"SHMEM (size = %ld) is CONFIGURED and available as %s",
(u_long) shmem_length, instance->shmem_fname);
oncore_log(instance, LOG_NOTICE, Msg);
}
#endif
static void
oncore_read_config(
struct instance *instance
)
{
FILE *fd;
char *cp, *cc, *ca, line[100], units[2], device[64], Msg[160], **cpp;
char *dirs[] = { "/etc/ntp", "/etc", 0 };
int i, sign, lat_flg, long_flg, ht_flg, mode, mask;
double f1, f2, f3;
fd = NULL;
for (cpp=dirs; *cpp; cpp++) {
cp = *cpp;
snprintf(device, sizeof(device), "%s/ntp.oncore.%d",
cp, instance->unit);
if ((fd=fopen(device, "r")))
break;
snprintf(device, sizeof(device), "%s/ntp.oncore%d",
cp, instance->unit);
if ((fd=fopen(device, "r")))
break;
snprintf(device, sizeof(device), "%s/ntp.oncore", cp);
if ((fd=fopen(device, "r")))
break;
}
if (!fd) {
instance->init_type = 4;
return;
}
mode = mask = 0;
lat_flg = long_flg = ht_flg = 0;
while (fgets(line, 100, fd)) {
if ((cp = strchr(line, '#')))
*cp = '\0';
for (i = strlen(line);
i > 0 && isascii((int)line[i - 1]) && isspace((int)line[i - 1]);
)
line[--i] = '\0';
for (cc = line; *cc && isascii((int)*cc) && isspace((int)*cc); cc++)
continue;
if (!*cc)
continue;
for (ca = cc; *ca; ca++) {
if (isascii((int)*ca)) {
if (islower((int)*ca)) {
*ca = toupper(*ca);
} else if (isspace((int)*ca) || (*ca == '='))
break;
}
}
for (; *ca && isascii((int)*ca) && (isspace((int)*ca) || (*ca == '=')); ca++)
continue;
if (!strncmp(cc, "STATUS", (size_t) 6) || !strncmp(cc, "SHMEM", (size_t) 5)) {
instance->shmem_fname = estrdup(ca);
continue;
}
for (cp = ca; *cp; cp++)
if (isascii((int)*cp) && islower((int)*cp))
*cp = toupper(*cp);
if (!strncmp(cc, "LAT", (size_t) 3)) {
f1 = f2 = f3 = 0;
sscanf(ca, "%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(cc, "LON", (size_t) 3)) {
f1 = f2 = f3 = 0;
sscanf(ca, "%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(cc, "HT", (size_t) 2)) {
f1 = 0;
units[0] = '\0';
sscanf(ca, "%lf %1s", &f1, units);
if (units[0] == 'F')
f1 = 0.3048 * f1;
instance->ss_ht = 100 * f1;
ht_flg++;
} else if (!strncmp(cc, "DELAY", (size_t) 5)) {
f1 = 0;
units[0] = '\0';
sscanf(ca, "%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;
if (f1 < 0 || f1 > 999999) {
snprintf(Msg, sizeof(Msg),
"PPS Cable delay of %fns out of Range, ignored",
f1);
oncore_log(instance, LOG_WARNING, Msg);
} else
instance->delay = f1;
} else if (!strncmp(cc, "OFFSET", (size_t) 6)) {
f1 = 0;
units[0] = '\0';
sscanf(ca, "%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;
if (f1 < 0 || f1 > 999999999.) {
snprintf(Msg, sizeof(Msg),
"PPS Offset of %fns out of Range, ignored",
f1);
oncore_log(instance, LOG_WARNING, Msg);
} else
instance->offset = f1;
} else if (!strncmp(cc, "MODE", (size_t) 4)) {
sscanf(ca, "%d", &mode);
if (mode < 0 || mode > 4)
mode = 4;
} else if (!strncmp(cc, "ASSERT", (size_t) 6)) {
instance->assert = 1;
} else if (!strncmp(cc, "CLEAR", (size_t) 5)) {
instance->assert = 0;
} else if (!strncmp(cc, "HARDPPS", (size_t) 7)) {
instance->hardpps = 1;
} else if (!strncmp(cc, "POSN2D", (size_t) 6)) {
instance->shmem_Posn = 2;
} else if (!strncmp(cc, "POSN3D", (size_t) 6)) {
instance->shmem_Posn = 3;
} else if (!strncmp(cc, "CHAN", (size_t) 4)) {
sscanf(ca, "%d", &i);
if ((i == 6) || (i == 8) || (i == 12))
instance->chan_in = i;
} else if (!strncmp(cc, "TRAIM", (size_t) 5)) {
instance->traim_in = 1;
if (!strcmp(ca, "NO") || !strcmp(ca, "OFF"))
instance->traim_in = 0;
} else if (!strncmp(cc, "MASK", (size_t) 4)) {
sscanf(ca, "%d", &mask);
if (mask > -1 && mask < 90)
instance->Ag = mask;
}
}
fclose(fd);
instance->posn_set = 1;
if (!( lat_flg && long_flg && ht_flg )) {
snprintf(Msg, sizeof(Msg),
"ONCORE: incomplete data on %s", device);
oncore_log (instance, LOG_WARNING, Msg);
instance->posn_set = 0;
if (mode == 1 || mode == 3) {
snprintf(Msg, sizeof(Msg),
"Input Mode = %d, but no/incomplete position, mode set to %d",
mode, mode+1);
oncore_log(instance, LOG_WARNING, Msg);
mode++;
}
}
instance->init_type = mode;
snprintf(Msg, sizeof(Msg), "Input mode = %d", mode);
oncore_log(instance, LOG_INFO, Msg);
}
static void
oncore_receive(
struct recvbuf *rbufp
)
{
size_t 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;
#ifdef ONCORE_VERBOSE_RECEIVE
if (debug > 4) {
int i;
char Msg[120], Msg2[10];
snprintf(Msg, sizeof(Msg), ">>> %d bytes available",
rbufp->recv_length);
oncore_log(instance, LOG_DEBUG, Msg);
strncpy(Msg, ">>>", sizeof(Msg));
for (i = 0; i < rbufp->recv_length; i++) {
snprintf(Msg2, sizeof(Msg2), "%02x ", p[i]);
strncat(Msg, Msg2, sizeof(Msg));
}
oncore_log(instance, LOG_DEBUG, Msg);
strncpy(Msg, ">>>", sizeof(Msg));
for (i = 0; i < rbufp->recv_length; i++) {
snprintf(Msg2, sizeof(Msg2), "%03o ", p[i]);
strncat(Msg, Msg2, sizeof(Msg));
}
oncore_log(instance, LOG_DEBUG, Msg);
}
#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, m;
unsigned l;
while (rcvptr >= 7) {
if (rcvbuf[0] != '@' || rcvbuf[1] != '@') {
for (i=1; i < rcvptr-1; i++)
if (rcvbuf[i] == '@' && rcvbuf[i+1] == '@')
break;
#ifdef ONCORE_VERBOSE_CONSUME
if (debug > 4) {
char Msg[120];
snprintf(Msg, sizeof(Msg),
">>> skipping %d chars", i);
oncore_log(instance, LOG_DEBUG, Msg);
}
#endif
if (i != rcvptr)
memcpy(rcvbuf, rcvbuf+i, (size_t)(rcvptr-i));
rcvptr -= i;
continue;
}
l = sizeof(oncore_messages)/sizeof(oncore_messages[0]) -1;
for(m=0; m<l; m++)
if (!strncmp(oncore_messages[m].flag, (char *)(rcvbuf+2), (size_t) 2))
break;
if (m == l) {
#ifdef ONCORE_VERBOSE_CONSUME
if (debug > 4) {
char Msg[120];
snprintf(Msg, sizeof(Msg),
">>> Unknown MSG, skipping 4 (%c%c)",
rcvbuf[2], rcvbuf[3]);
oncore_log(instance, LOG_DEBUG, Msg);
}
#endif
memcpy(rcvbuf, rcvbuf+4, (size_t) 4);
rcvptr -= 4;
continue;
}
l = oncore_messages[m].len;
#ifdef ONCORE_VERBOSE_CONSUME
if (debug > 3) {
char Msg[120];
snprintf(Msg, sizeof(Msg),
"GOT: %c%c %d of %d entry %d",
instance->unit, rcvbuf[2], rcvbuf[3],
rcvptr, l, m);
oncore_log(instance, LOG_DEBUG, Msg);
}
#endif
if (rcvptr < l)
return;
if (rcvbuf[l-2] != '\r' || rcvbuf[l-1] != '\n') {
#ifdef ONCORE_VERBOSE_CONSUME
if (debug)
oncore_log(instance, LOG_DEBUG, "NO <CR><LF> at end of message");
#endif
} else {
if (oncore_checksum_ok(rcvbuf, l)) {
if (instance->shmem != NULL) {
instance->shmem[oncore_messages[m].shmem + 2]++;
memcpy(instance->shmem + oncore_messages[m].shmem + 3,
rcvbuf, (size_t) l);
}
oncore_msg_any(instance, rcvbuf, (size_t) (l-3), m);
if (oncore_messages[m].handler)
oncore_messages[m].handler(instance, rcvbuf, (size_t) (l-3));
}
#ifdef ONCORE_VERBOSE_CONSUME
else if (debug) {
char Msg[120], Msg2[10];
oncore_log(instance, LOG_ERR, "Checksum mismatch!");
snprintf(Msg, sizeof(Msg), "@@%c%c ", rcvbuf[2], rcvbuf[3]);
for (i = 4; i < l; i++) {
snprintf(Msg2, sizeof(Msg2),
"%03o ", rcvbuf[i]);
strncat(Msg, Msg2, sizeof(Msg));
}
oncore_log(instance, LOG_DEBUG, Msg);
}
#endif
}
if (l != rcvptr)
memcpy(rcvbuf, rcvbuf+l, (size_t) (rcvptr-l));
rcvptr -= l;
}
}
static void
oncore_get_timestamp(
struct instance *instance,
long dt1,
long dt2
)
{
int Rsm;
u_long j;
l_fp ts, ts_tmp;
double dmy;
#ifdef HAVE_STRUCT_TIMESPEC
struct timespec *tsp = 0;
#else
struct timeval *tsp = 0;
#endif
int current_mode;
pps_params_t current_params;
struct timespec timeout;
pps_info_t pps_i;
char Msg[140];
#if 1
if ((instance->site_survey == ONCORE_SS_DONE) && (instance->mode != MODE_0D))
#else
if ((instance->site_survey != ONCORE_SS_DONE) || (instance->mode != MODE_0D))
#endif
return;
if (instance->rsm.bad_almanac)
return;
if (instance->count5) {
instance->count5--;
return;
}
j = instance->ev_serial;
timeout.tv_sec = 0;
timeout.tv_nsec = 0;
if (time_pps_fetch(instance->pps_h, PPS_TSFMT_TSPEC, &pps_i,
&timeout) < 0) {
oncore_log(instance, LOG_ERR, "time_pps_fetch failed");
return;
}
if (instance->assert) {
tsp = &pps_i.assert_timestamp;
#ifdef ONCORE_VERBOSE_GET_TIMESTAMP
if (debug > 2) {
u_long i;
i = (u_long) pps_i.assert_sequence;
# ifdef HAVE_STRUCT_TIMESPEC
snprintf(Msg, sizeof(Msg),
"serial/j (%lu, %lu) %ld.%09ld", i, j,
(long)tsp->tv_sec, (long)tsp->tv_nsec);
# else
snprintf(Msg, sizeof(Msg),
"serial/j (%lu, %lu) %ld.%06ld", i, j,
(long)tsp->tv_sec, (long)tsp->tv_usec);
# endif
oncore_log(instance, LOG_DEBUG, Msg);
}
#endif
if (pps_i.assert_sequence == j) {
oncore_log(instance, LOG_NOTICE, "ONCORE: oncore_get_timestamp, error serial pps");
return;
}
instance->ev_serial = pps_i.assert_sequence;
} else {
tsp = &pps_i.clear_timestamp;
#if 0
if (debug > 2) {
u_long i;
i = (u_long) pps_i.clear_sequence;
# ifdef HAVE_STRUCT_TIMESPEC
snprintf(Msg, sizeof(Msg),
"serial/j (%lu, %lu) %ld.%09ld", i, j,
(long)tsp->tv_sec, (long)tsp->tv_nsec);
# else
snprintf(Msg. sizeof(Msg),
"serial/j (%lu, %lu) %ld.%06ld", i, j,
(long)tsp->tv_sec, (long)tsp->tv_usec);
# endif
oncore_log(instance, LOG_DEBUG, Msg);
}
#endif
if (pps_i.clear_sequence == j) {
oncore_log(instance, LOG_ERR, "oncore_get_timestamp, error serial pps");
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
if (instance->assert)
instance->pps_p.assert_offset.tv_nsec = -dt2;
else
instance->pps_p.clear_offset.tv_nsec = -dt2;
if (time_pps_getcap(instance->pps_h, ¤t_mode) < 0) {
oncore_log(instance, LOG_ERR, "time_pps_getcap failed: %m");
return;
}
if (time_pps_getparams(instance->pps_h, ¤t_params) < 0) {
oncore_log(instance, LOG_ERR, "time_pps_getparams failed: %m");
return;
}
current_params.mode |= instance->pps_p.mode;
current_params.mode &= current_mode;
current_params.assert_offset.tv_sec = 0;
current_params.assert_offset.tv_nsec = -dt2;
current_params.clear_offset.tv_sec = 0;
current_params.clear_offset.tv_nsec = -dt2;
if (time_pps_setparams(instance->pps_h, ¤t_params))
oncore_log(instance, LOG_ERR, "ONCORE: Error doing time_pps_setparams");
ts.l_ui += JAN_1970;
instance->pp->lastrec = ts;
ts_tmp = ts;
ts_tmp.l_ui = 0;
LFPTOD(&ts_tmp, dmy);
j = 1.0e9*dmy;
Rsm = 0;
if (instance->chan == 6)
Rsm = instance->BEHa[64];
else if (instance->chan == 8)
Rsm = instance->BEHa[72];
else if (instance->chan == 12)
Rsm = ((instance->BEHa[129]<<8) | instance->BEHa[130]);
if (instance->chan == 6 || instance->chan == 8) {
char f1[5], f2[5], f3[5], f4[5];
if (instance->traim) {
snprintf(f1, sizeof(f1), "%d",
instance->BEHn[21]);
snprintf(f2, sizeof(f2), "%d",
instance->BEHn[22]);
snprintf(f3, sizeof(f3), "%2d",
instance->BEHn[23] * 256 +
instance->BEHn[24]);
snprintf(f4, sizeof(f4), "%3d",
(s_char)instance->BEHn[25]);
} else {
strncpy(f1, "x", sizeof(f1));
strncpy(f2, "x", sizeof(f2));
strncpy(f3, "xx", sizeof(f3));
strncpy(f4, "xxx", sizeof(f4));
}
snprintf(Msg, sizeof(Msg),
"%u.%09lu %d %d %2d %2d %2d %2ld rstat %02x dop %4.1f nsat %2d,%d traim %d,%s,%s sigma %s neg-sawtooth %s 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,
Rsm, 0.1*(256*instance->BEHa[35]+instance->BEHa[36]),
instance->BEHa[38], instance->BEHa[39], instance->traim, f1, f2,
f3, f4,
instance->BEHa[41], instance->BEHa[45], instance->BEHa[49], instance->BEHa[53],
instance->BEHa[57], instance->BEHa[61], instance->BEHa[65], instance->BEHa[69]
);
} else if (instance->chan == 12) {
char f1[5], f2[5], f3[5], f4[5];
if (instance->traim) {
snprintf(f1, sizeof(f1), "%d",
instance->BEHn[6]);
snprintf(f2, sizeof(f2), "%d",
instance->BEHn[7]);
snprintf(f3, sizeof(f3), "%d",
instance->BEHn[12] * 256 +
instance->BEHn[13]);
snprintf(f4, sizeof(f4), "%3d",
(s_char)instance->BEHn[14]);
} else {
strncpy(f1, "x", sizeof(f1));
strncpy(f2, "x", sizeof(f2));
strncpy(f3, "xx", sizeof(f3));
strncpy(f4, "xxx", sizeof(f4));
}
snprintf(Msg, sizeof(Msg),
"%u.%09lu %d %d %2d %2d %2d %2ld rstat %02x dop %4.1f nsat %2d,%d traim %d,%s,%s sigma %s neg-sawtooth %s sat %d%d%d%d%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,
Rsm, 0.1*(256*instance->BEHa[53]+instance->BEHa[54]),
instance->BEHa[55], instance->BEHa[56], instance->traim, f1, f2,
f3, f4,
instance->BEHa[58], instance->BEHa[64], instance->BEHa[70], instance->BEHa[76],
instance->BEHa[82], instance->BEHa[88], instance->BEHa[94], instance->BEHa[100],
instance->BEHa[106], instance->BEHa[112], instance->BEHa[118], instance->BEHa[124]
);
}
if (!refclock_process(instance->pp)) {
refclock_report(instance->peer, CEVNT_BADTIME);
return;
}
oncore_log(instance, LOG_INFO, Msg);
instance->pollcnt = 2;
if (instance->polled) {
instance->polled = 0;
instance->pp->lastref = instance->pp->lastrec;
refclock_receive(instance->peer);
}
}
static void
oncore_msg_any(
struct instance *instance,
u_char *buf,
size_t len,
int idx
)
{
#ifdef ONCORE_VERBOSE_MSG_ANY
int i;
const char *fmt = oncore_messages[idx].fmt;
const char *p;
char *q;
char *qlim;
#ifdef HAVE_GETCLOCK
struct timespec ts;
#endif
struct timeval tv;
char Msg[120], Msg2[10];
if (debug > 3) {
# ifdef HAVE_GETCLOCK
(void) getclock(TIMEOFDAY, &ts);
tv.tv_sec = ts.tv_sec;
tv.tv_usec = ts.tv_nsec / 1000;
# else
GETTIMEOFDAY(&tv, 0);
# endif
snprintf(Msg, sizeof(Msg), "%ld.%06ld",
(long)tv.tv_sec, (long)tv.tv_usec);
oncore_log(instance, LOG_DEBUG, Msg);
if (!*fmt) {
snprintf(Msg, sizeof(Msg), ">>@@%c%c ", buf[2],
buf[3]);
for(i = 2; i < len && i < 2400 ; i++) {
snprintf(Msg2, sizeof(Msg2), "%02x",
buf[i]);
strncpy(Msg, Msg2, sizeof(Msg));
}
oncore_log(instance, LOG_DEBUG, Msg);
return;
} else {
strncat(Msg, "##", sizeof(Msg));
qlim = Msg + sizeof(Msg) - 3;
for (p = fmt, q = Msg + 2; q < qlim && *p; ) {
*q++ = *p++;
*q++ = '_';
}
*q = '\0';
oncore_log(instance, LOG_DEBUG, Msg);
snprintf(Msg, sizeof(Msg), "%c%c", buf[2],
buf[3]);
i = 4;
for (p = fmt; *p; p++) {
snprintf(Msg2, "%02x", buf[i++]);
strncat(Msg, Msg2, sizeof(Msg));
}
oncore_log(instance, LOG_DEBUG, Msg);
}
}
#endif
}
static void
oncore_msg_Adef(
struct instance *instance,
u_char *buf,
size_t len
)
{
}
static void
oncore_msg_Ag(
struct instance *instance,
u_char *buf,
size_t len
)
{ char Msg[160], *cp;
cp = "set to";
if (instance->o_state == ONCORE_RUN)
cp = "is";
instance->Ag = buf[4];
snprintf(Msg, sizeof(Msg),
"Satellite mask angle %s %d degrees", cp,
(int)instance->Ag);
oncore_log(instance, LOG_INFO, Msg);
}
static void
oncore_msg_As(
struct instance *instance,
u_char *buf,
size_t len
)
{
instance->ss_lat = buf_w32(&buf[4]);
instance->ss_long = buf_w32(&buf[8]);
instance->ss_ht = buf_w32(&buf[12]);
oncore_print_posn(instance);
}
static void
oncore_msg_At(
struct instance *instance,
u_char *buf,
size_t len
)
{
instance->saw_At = 1;
if (instance->site_survey == ONCORE_SS_TESTING) {
if (buf[4] == 2) {
oncore_log(instance, LOG_NOTICE,
"Initiating hardware 3D site survey");
oncore_log(instance, LOG_NOTICE, "SSstate = ONCORE_SS_HW");
instance->site_survey = ONCORE_SS_HW;
}
}
}
static void
oncore_msg_Ay(
struct instance *instance,
u_char *buf,
size_t len
)
{
char Msg[120];
if (instance->saw_Ay)
return;
instance->saw_Ay = 1;
instance->offset = buf_w32(&buf[4]);
snprintf(Msg, sizeof(Msg), "PPS Offset is set to %ld ns",
instance->offset);
oncore_log(instance, LOG_INFO, Msg);
}
static void
oncore_msg_Az(
struct instance *instance,
u_char *buf,
size_t len
)
{
char Msg[120];
if (instance->saw_Az)
return;
instance->saw_Az = 1;
instance->delay = buf_w32(&buf[4]);
snprintf(Msg, sizeof(Msg), "Cable delay is set to %ld ns",
instance->delay);
oncore_log(instance, LOG_INFO, Msg);
}
static void
oncore_msg_BaEaHa(
struct instance *instance,
u_char *buf,
size_t len
)
{
const char *cp;
char Msg[160];
int mode;
if (instance->o_state == ONCORE_CHECK_CHAN) {
if (buf[2] == 'B') {
if (instance->chan_ck < 6) instance->chan_ck = 6;
} else if (buf[2] == 'E') {
if (instance->chan_ck < 8) instance->chan_ck = 8;
} else if (buf[2] == 'H') {
if (instance->chan_ck < 12) instance->chan_ck = 12;
}
if (instance->count3++ < 5)
return;
instance->count3 = 0;
if (instance->chan_in != -1)
instance->chan = instance->chan_in;
else
instance->chan = instance->chan_ck;
snprintf(Msg, sizeof(Msg), "Input says chan = %d",
instance->chan_in);
oncore_log(instance, LOG_INFO, Msg);
snprintf(Msg, sizeof(Msg), "Model # says chan = %d",
instance->chan_id);
oncore_log(instance, LOG_INFO, Msg);
snprintf(Msg, sizeof(Msg), "Testing says chan = %d",
instance->chan_ck);
oncore_log(instance, LOG_INFO, Msg);
snprintf(Msg, sizeof(Msg), "Using chan = %d",
instance->chan);
oncore_log(instance, LOG_INFO, Msg);
instance->o_state = ONCORE_HAVE_CHAN;
oncore_log(instance, LOG_NOTICE, "state = ONCORE_HAVE_CHAN");
instance->timeout = 4;
oncore_sendmsg(instance, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
return;
}
if (instance->o_state != ONCORE_ALMANAC && instance->o_state != ONCORE_RUN)
return;
if (instance->count) {
if (instance->count++ < 5)
return;
instance->count = 0;
}
memcpy(instance->BEHa, buf, (size_t) (len+3));
oncore_check_almanac(instance);
oncore_check_antenna(instance);
if (instance->o_state == ONCORE_ALMANAC)
if (oncore_wait_almanac(instance))
return;
if (instance->once) {
instance->once = 0;
instance->count2 = 1;
if (instance->chan != 12 && !instance->saw_At) {
oncore_log(instance, LOG_NOTICE,
"Not Good, no @@At command (no Position Hold), must be a GT/GT+");
oncore_sendmsg(instance, oncore_cmd_Av1, sizeof(oncore_cmd_Av1));
}
mode = instance->init_type;
switch (mode) {
case 0:
case 1:
case 3:
instance->site_survey = ONCORE_SS_DONE;
oncore_log(instance, LOG_NOTICE, "SSstate = ONCORE_SS_DONE");
break;
case 2:
case 4:
oncore_log(instance, LOG_NOTICE, "SSstate = ONCORE_SS_TESTING");
instance->site_survey = ONCORE_SS_TESTING;
instance->count1 = 1;
if (instance->chan == 12)
oncore_sendmsg(instance, oncore_cmd_Gd3, sizeof(oncore_cmd_Gd3));
else
oncore_sendmsg(instance, oncore_cmd_At2, sizeof(oncore_cmd_At2));
break;
}
oncore_sendmsg(instance, oncore_cmd_Ayx, sizeof(oncore_cmd_Ayx));
oncore_sendmsg(instance, oncore_cmd_Azx, sizeof(oncore_cmd_Azx));
oncore_sendmsg(instance, oncore_cmd_Agx, sizeof(oncore_cmd_Agx));
}
if (instance->site_survey == ONCORE_SS_TESTING) {
if (instance->chan == 12) {
if (instance->count1) {
if (instance->count1++ > 5 || instance->BEHa[130]&0x10) {
instance->count1 = 0;
if (instance->BEHa[130]&0x10) {
oncore_log(instance, LOG_NOTICE,
"Initiating hardware 3D site survey");
oncore_log(instance, LOG_NOTICE, "SSstate = ONCORE_SS_HW");
instance->site_survey = ONCORE_SS_HW;
} else {
oncore_log(instance, LOG_NOTICE, "SSstate = ONCORE_SS_SW");
instance->site_survey = ONCORE_SS_SW;
}
}
}
} else {
if (instance->count1) {
if (instance->count1++ > 5) {
instance->count1 = 0;
snprintf(Msg, sizeof(Msg),
"Initiating software 3D site survey (%d samples)",
POS_HOLD_AVERAGE);
oncore_log(instance, LOG_INFO, Msg);
oncore_log(instance, LOG_NOTICE, "SSstate = ONCORE_SS_SW");
instance->site_survey = ONCORE_SS_SW;
instance->ss_lat = instance->ss_long = instance->ss_ht = 0;
if (instance->chan == 12)
oncore_sendmsg(instance, oncore_cmd_Gd0, sizeof(oncore_cmd_Gd0));
else {
oncore_sendmsg(instance, oncore_cmd_At0, sizeof(oncore_cmd_At0));
oncore_sendmsg(instance, oncore_cmd_Av0, sizeof(oncore_cmd_Av0));
}
}
}
}
}
if (instance->chan == 6) {
if (instance->BEHa[64]&0x8)
instance->mode = MODE_0D;
else if (instance->BEHa[64]&0x10)
instance->mode = MODE_2D;
else if (instance->BEHa[64]&0x20)
instance->mode = MODE_3D;
} else if (instance->chan == 8) {
if (instance->BEHa[72]&0x8)
instance->mode = MODE_0D;
else if (instance->BEHa[72]&0x10)
instance->mode = MODE_2D;
else if (instance->BEHa[72]&0x20)
instance->mode = MODE_3D;
} else if (instance->chan == 12) {
int bits;
bits = (instance->BEHa[129]>>5) & 0x7;
if (bits == 0x4)
instance->mode = MODE_0D;
else if (bits == 0x6)
instance->mode = MODE_2D;
else if (bits == 0x7)
instance->mode = MODE_3D;
}
if (instance->shmem) {
int i;
u_char *smp;
switch(instance->chan) {
case 6: smp = &instance->shmem[instance->shmem_Ba]; break;
case 8: smp = &instance->shmem[instance->shmem_Ea]; break;
case 12: smp = &instance->shmem[instance->shmem_Ha]; break;
default: smp = (u_char *) NULL; break;
}
switch (instance->mode) {
case MODE_0D: i = 1; break;
case MODE_2D: i = 2; break;
case MODE_3D: i = 3; break;
default: i = 0; break;
}
if (i && smp != NULL) {
i *= (len+6);
smp[i + 2]++;
memcpy(&smp[i+3], buf, (size_t) (len+3));
}
}
if (instance->traim_delay) {
if (instance->traim_delay++ > 5) {
instance->traim = 0;
instance->traim_delay = 0;
cp = "ONCORE: Did not detect TRAIM response, TRAIM = OFF";
oncore_log(instance, LOG_INFO, cp);
oncore_set_traim(instance);
} else
return;
}
if (!instance->have_dH && !instance->traim_delay)
oncore_compute_dH(instance);
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_HW || instance->site_survey == ONCORE_SS_SW)
oncore_ss(instance);
if (instance->count2) {
if (instance->count2++ > 5) {
instance->count2 = 0;
if (!instance->saw_Ay && instance->offset) {
oncore_log(instance, LOG_INFO, "No @@Ay command, PPS OFFSET ignored");
instance->offset = 0;
}
}
}
oncore_check_leap_sec(instance);
if (instance->shmem && !instance->shmem_bad_Ea && instance->shmem_Posn && (instance->site_survey == ONCORE_SS_DONE))
oncore_shmem_get_3D(instance);
if (!instance->traim)
oncore_get_timestamp(instance, instance->offset, instance->offset);
}
static void
oncore_msg_Bd(
struct instance *instance,
u_char *buf,
size_t len
)
{
char Msg[160];
snprintf(Msg, sizeof(Msg),
"Bd: Almanac %s, week = %d, t = %d, %d SVs: %x",
((buf[4]) ? "LOADED" : "(NONE)"), buf[5], buf[6],
buf[7], w32(&buf[8]));
oncore_log(instance, LOG_NOTICE, Msg);
}
static void
oncore_msg_Bj(
struct instance *instance,
u_char *buf,
size_t len
)
{
const char *cp;
instance->saw_Bj = 1;
switch(buf[4]) {
case 1:
instance->pp->leap = LEAP_ADDSECOND;
cp = "Set pp.leap to LEAP_ADDSECOND";
break;
case 2:
instance->pp->leap = LEAP_DELSECOND;
cp = "Set pp.leap to LEAP_DELSECOND";
break;
case 0:
default:
instance->pp->leap = LEAP_NOWARNING;
cp = "Set pp.leap to LEAP_NOWARNING";
break;
}
oncore_log(instance, LOG_NOTICE, cp);
}
static void
oncore_msg_Bl(
struct instance *instance,
u_char *buf,
size_t len
)
{
int chan, id, subframe, valid, page, i, j, tow;
int day_now, day_lsf;
char *cp, Msg[120];
enum {
WARN_NOT_YET,
WARN_0,
WARN_PLUS,
WARN_MINUS
} warn;
day_now = day_lsf = 0;
chan = buf[4] & 0377;
id = buf[5] & 0377;
subframe = buf[6] & 017;
valid = (buf[6] >> 4) & 017;
page = buf[7];
if ((!instance->Bl.lsf_flg && !instance->Bl.wn_flg) && (subframe == 4 && page == 18 && valid == 10)) {
instance->Bl.dt_ls = buf[32];
instance->Bl.WN_lsf = buf[33];
instance->Bl.DN_lsf = buf[34];
instance->Bl.dt_lsf = buf[35];
instance->Bl.lsf_flg++;
}
if ((instance->Bl.lsf_flg && !instance->Bl.wn_flg) && (subframe == 1 && valid == 10)) {
i = (buf[7+7]<<8) + buf[7+8];
instance->Bl.WN = i >> 6;
tow = (buf[7+4]<<16) + (buf[7+5]<<8) + buf[7+6];
tow >>= 7;
tow = tow & 0377777;
tow <<= 2;
instance->Bl.DN = tow/57600L + 1;
instance->Bl.wn_flg++;
}
if (instance->Bl.wn_flg && instance->Bl.lsf_flg) {
instance->Bl.wn_flg = instance->Bl.lsf_flg = 0;
oncore_cmd_Bl[2] = 0;
oncore_sendmsg(instance, oncore_cmd_Bl, sizeof oncore_cmd_Bl);
oncore_cmd_Bl[2] = 1;
i = instance->Bl.WN&01400;
instance->Bl.WN_lsf |= i;
i = (instance->Bl.WN_lsf - instance->Bl.WN);
if (i < 0)
i += 1024;
day_now = instance->Bl.DN;
day_lsf = 7*i + instance->Bl.DN_lsf;
warn = WARN_NOT_YET;
if (day_lsf >= day_now && day_lsf - day_now < 32) {
if (day_lsf - day_now < 28 || instance->BEHa[5] < 20) {
i = instance->Bl.dt_lsf - instance->Bl.dt_ls;
switch (i) {
case -1:
warn = WARN_MINUS;
break;
case 0:
warn = WARN_0;
break;
case 1:
warn = WARN_PLUS;
break;
}
}
}
switch (warn) {
case WARN_0:
case WARN_NOT_YET:
instance->peer->leap = LEAP_NOWARNING;
cp = "Set peer.leap to LEAP_NOWARNING";
break;
case WARN_MINUS:
instance->peer->leap = LEAP_DELSECOND;
cp = "Set peer.leap to LEAP_DELSECOND";
break;
case WARN_PLUS:
instance->peer->leap = LEAP_ADDSECOND;
cp = "Set peer.leap to LEAP_ADDSECOND";
break;
}
oncore_log(instance, LOG_NOTICE, cp);
i = instance->Bl.dt_lsf-instance->Bl.dt_ls;
if (i) {
j = (i >= 0) ? i : -i;
snprintf(Msg, sizeof(Msg),
"see Leap_Second (%c%d) in %d days",
((i >= 0) ? '+' : '-'), j,
day_lsf-day_now);
oncore_log(instance, LOG_NOTICE, Msg);
}
}
snprintf(Msg, sizeof(Msg),
"dt_ls = %d dt_lsf = %d WN = %d DN = %d WN_lsf = %d DNlsf = %d wn_flg = %d lsf_flg = %d Bl_day = %d",
instance->Bl.dt_ls, instance->Bl.dt_lsf,
instance->Bl.WN, instance->Bl.DN,
instance->Bl.WN_lsf, instance->Bl.DN_lsf,
instance->Bl.wn_flg, instance->Bl.lsf_flg,
instance->Bl.Bl_day);
oncore_log(instance, LOG_INFO, Msg);
}
static void
oncore_msg_BnEnHn(
struct instance *instance,
u_char *buf,
size_t len
)
{
long dt1, dt2;
if (instance->o_state != ONCORE_RUN)
return;
if (instance->traim_delay) {
instance->traim_ck = 1;
instance->traim_delay = 0;
oncore_log(instance, LOG_NOTICE, "ONCORE: Detected TRAIM, TRAIM = ON");
oncore_set_traim(instance);
}
memcpy(instance->BEHn, buf, (size_t) len);
if (!instance->traim)
return;
if (buf[2] == 'H') {
if (instance->BEHn[6]) {
oncore_log(instance, LOG_WARNING, "BAD TRAIM");
return;
}
dt1 = instance->saw_tooth + instance->offset;
instance->saw_tooth = (s_char) instance->BEHn[14];
dt2 = instance->saw_tooth + instance->offset;
} else {
if (instance->BEHn[21])
return;
dt1 = instance->saw_tooth + instance->offset;
instance->saw_tooth = (s_char) instance->BEHn[25];
dt2 = instance->saw_tooth + instance->offset;
}
oncore_get_timestamp(instance, dt1, dt2);
}
static void
oncore_msg_CaFaIa(
struct instance *instance,
u_char *buf,
size_t len
)
{
char Msg[120];
int i;
if (instance->o_state == ONCORE_TEST_SENT) {
enum antenna_state antenna;
instance->timeout = 0;
#if ONCORE_VERBOSE_SELF_TEST
if (debug > 2) {
if (buf[2] == 'I')
snprintf(Msg, sizeof(Msg),
">>@@%ca %x %x %x", buf[2],
buf[4], buf[5], buf[6]);
else
snprintf(Msg, sizeof(Msg),
">>@@%ca %x %x", buf[2],
buf[4], buf[5]);
oncore_log(instance, LOG_DEBUG, Msg);
}
#endif
antenna = (buf[4] & 0xc0) >> 6;
buf[4] &= ~0xc0;
i = buf[4] || buf[5];
if (buf[2] == 'I') i = i || buf[6];
if (i) {
if (buf[2] == 'I')
snprintf(Msg, sizeof(Msg),
"self test failed: result %02x %02x %02x",
buf[4], buf[5], buf[6]);
else
snprintf(Msg, sizeof(Msg),
"self test failed: result %02x %02x",
buf[4], buf[5]);
oncore_log(instance, LOG_ERR, Msg);
oncore_log(instance, LOG_ERR,
"ONCORE: self test failed, shutting down driver");
refclock_report(instance->peer, CEVNT_FAULT);
oncore_shutdown(instance->unit, instance->peer);
return;
}
oncore_antenna_report(instance, antenna);
instance->o_state = ONCORE_INIT;
oncore_log(instance, LOG_NOTICE, "state = ONCORE_INIT");
instance->timeout = 4;
oncore_sendmsg(instance, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
}
}
static void
oncore_msg_Cb(
struct instance *instance,
u_char *buf,
size_t len
)
{
int i;
if (instance->shmem == NULL)
return;
if (buf[4] == 5 && buf[5] > 0 && buf[5] < 26)
i = buf[5];
else if (buf[4] == 4 && buf[5] <= 5)
i = buf[5] + 24;
else if (buf[4] == 4 && buf[5] <= 10)
i = buf[5] + 23;
else if (buf[4] == 4 && buf[5] == 25)
i = 34;
else {
oncore_log(instance, LOG_NOTICE, "Cb: Response is NO ALMANAC");
return;
}
i *= 36;
instance->shmem[instance->shmem_Cb + i + 2]++;
memcpy(instance->shmem + instance->shmem_Cb + i + 3, buf, (size_t) (len + 3));
#ifdef ONCORE_VERBOSE_MSG_CB
{
char Msg[160];
snprintf(Msg, sizeof(Msg), "See Cb [%d,%d]", buf[4],
buf[5]);
oncore_log(instance, LOG_DEBUG, Msg);
}
#endif
}
static void
oncore_msg_Cf(
struct instance *instance,
u_char *buf,
size_t len
)
{
if (instance->o_state == ONCORE_RESET_SENT) {
oncore_sendmsg(instance, oncore_cmd_Cg, sizeof(oncore_cmd_Cg));
instance->o_state = ONCORE_TEST_SENT;
oncore_log(instance, LOG_NOTICE, "state = ONCORE_TEST_SENT");
oncore_sendmsg(instance, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
}
}
static void
oncore_msg_Cj(
struct instance *instance,
u_char *buf,
size_t len
)
{
int mode;
memcpy(instance->Cj, buf, len);
instance->timeout = 0;
if (instance->o_state == ONCORE_CHECK_ID) {
oncore_msg_Cj_id(instance, buf, len);
oncore_chan_test(instance);
} else if (instance->o_state == ONCORE_HAVE_CHAN) {
mode = instance->init_type;
if (mode == 3 || mode == 4) {
instance->o_state = ONCORE_RESET_SENT;
oncore_log(instance, LOG_NOTICE, "state = ONCORE_RESET_SENT");
oncore_sendmsg(instance, oncore_cmd_Cf, sizeof(oncore_cmd_Cf));
} else {
instance->o_state = ONCORE_TEST_SENT;
oncore_log(instance, LOG_NOTICE, "state = ONCORE_TEST_SENT");
}
}
if (instance->o_state == ONCORE_TEST_SENT) {
if (instance->chan == 6)
oncore_sendmsg(instance, oncore_cmd_Ca, sizeof(oncore_cmd_Ca));
else if (instance->chan == 8)
oncore_sendmsg(instance, oncore_cmd_Fa, sizeof(oncore_cmd_Fa));
else if (instance->chan == 12)
oncore_sendmsg(instance, oncore_cmd_Ia, sizeof(oncore_cmd_Ia));
} else if (instance->o_state == ONCORE_INIT)
oncore_msg_Cj_init(instance, buf, len);
}
static void
oncore_msg_Cj_id(
struct instance *instance,
u_char *buf,
size_t len
)
{
char *cp, *cp1, *cp2, Model[21], Msg[160];
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';
oncore_log(instance, LOG_NOTICE, cp);
*cp1 = '\r';
cp = cp1+2;
}
instance->version = atoi((char *) &instance->Cj[83]);
instance->revision = atoi((char *) &instance->Cj[111]);
for (cp= (char *) &instance->Cj[160]; *cp == ' '; cp++)
;
cp1 = cp;
cp2 = Model;
for (; !isspace((int)*cp) && cp-cp1 < 20; cp++, cp2++)
*cp2 = *cp;
*cp2 = '\0';
cp = 0;
if (!strncmp(Model, "PVT6", (size_t) 4)) {
cp = "PVT6";
instance->model = ONCORE_PVT6;
} else if (Model[0] == 'A') {
cp = "Basic";
instance->model = ONCORE_BASIC;
} else if (Model[0] == 'B' || !strncmp(Model, "T8", (size_t) 2)) {
cp = "VP";
instance->model = ONCORE_VP;
} else if (Model[0] == 'P') {
cp = "M12";
instance->model = ONCORE_M12;
} else if (Model[0] == 'R' || Model[0] == 'D' || Model[0] == 'S') {
if (Model[5] == 'N') {
cp = "GT";
instance->model = ONCORE_GT;
} else if ((Model[1] == '3' || Model[1] == '4') && Model[5] == 'G') {
cp = "GT+";
instance->model = ONCORE_GTPLUS;
} else if ((Model[1] == '5' && Model[5] == 'U') || (Model[1] == '1' && Model[5] == 'A')) {
cp = "UT";
instance->model = ONCORE_UT;
} else if (Model[1] == '5' && Model[5] == 'G') {
cp = "UT+";
instance->model = ONCORE_UTPLUS;
} else if (Model[1] == '6' && Model[5] == 'G') {
cp = "SL";
instance->model = ONCORE_SL;
} else {
cp = "Unknown";
instance->model = ONCORE_UNKNOWN;
}
} else {
cp = "Unknown";
instance->model = ONCORE_UNKNOWN;
}
snprintf(Msg, sizeof(Msg),
"This looks like an Oncore %s with version %d.%d firmware.",
cp, instance->version, instance->revision);
oncore_log(instance, LOG_INFO, Msg);
instance->chan_id = 8;
if (instance->model == ONCORE_BASIC || instance->model == ONCORE_PVT6)
instance->chan_id = 6;
else if (instance->model == ONCORE_VP || instance->model == ONCORE_UT || instance->model == ONCORE_UTPLUS)
instance->chan_id = 8;
else if (instance->model == ONCORE_M12)
instance->chan_id = 12;
instance->traim_id = 0;
if (instance->model == ONCORE_BASIC || instance->model == ONCORE_PVT6)
instance->traim_id = 0;
else if (instance->model == ONCORE_VP || instance->model == ONCORE_UT || instance->model == ONCORE_UTPLUS)
instance->traim_id = 1;
else if (instance->model == ONCORE_M12)
instance->traim_id = -1;
snprintf(Msg, sizeof(Msg), "Channels = %d, TRAIM = %s",
instance->chan_id,
((instance->traim_id < 0)
? "UNKNOWN"
: (instance->traim_id > 0)
? "ON"
: "OFF"));
oncore_log(instance, LOG_INFO, Msg);
}
static void
oncore_msg_Cj_init(
struct instance *instance,
u_char *buf,
size_t len
)
{
char Msg[160];
u_char Cmd[20];
int mode;
if (instance->chan == 12) {
instance->shmem_bad_Ea = 1;
snprintf(Msg, sizeof(Msg),
"*** SHMEM partially enabled for ONCORE M12 s/w v%d.%d ***",
instance->version, instance->revision);
oncore_log(instance, LOG_NOTICE, Msg);
}
oncore_sendmsg(instance, oncore_cmd_Cg, sizeof(oncore_cmd_Cg));
oncore_sendmsg(instance, oncore_cmd_Bb, sizeof(oncore_cmd_Bb));
oncore_sendmsg(instance, oncore_cmd_Ek, sizeof(oncore_cmd_Ek));
oncore_sendmsg(instance, oncore_cmd_Aw, sizeof(oncore_cmd_Aw));
oncore_sendmsg(instance, oncore_cmd_AB, sizeof(oncore_cmd_AB));
oncore_sendmsg(instance, oncore_cmd_Be, sizeof(oncore_cmd_Be));
oncore_sendmsg(instance, oncore_cmd_Bd, sizeof(oncore_cmd_Bd));
mode = instance->init_type;
if (instance->posn_set) {
oncore_log(instance, LOG_INFO, "Setting Posn from input data");
oncore_set_posn(instance);
} else
if (instance->chan != 12)
oncore_sendmsg(instance, oncore_cmd_Atx, sizeof(oncore_cmd_Atx));
if (mode != 0) {
memcpy(Cmd, oncore_cmd_Az, (size_t) sizeof(oncore_cmd_Az));
w32_buf(&Cmd[-2+4], instance->delay);
oncore_sendmsg(instance, Cmd, sizeof(oncore_cmd_Az));
if (instance->offset) {
memcpy(Cmd, oncore_cmd_Ay, (size_t) sizeof(oncore_cmd_Ay));
w32_buf(&Cmd[-2+4], instance->offset);
oncore_sendmsg(instance, Cmd, sizeof(oncore_cmd_Ay));
}
if (instance->Ag != 0xff) {
memcpy(Cmd, oncore_cmd_Ag, (size_t) sizeof(oncore_cmd_Ag));
Cmd[-2+4] = instance->Ag;
oncore_sendmsg(instance, Cmd, sizeof(oncore_cmd_Ag));
}
}
if (instance->chan == 6) {
oncore_sendmsg(instance, oncore_cmd_Ea0, sizeof(oncore_cmd_Ea0));
oncore_sendmsg(instance, oncore_cmd_En0, sizeof(oncore_cmd_En0));
oncore_sendmsg(instance, oncore_cmd_Ha0, sizeof(oncore_cmd_Ha0));
oncore_sendmsg(instance, oncore_cmd_Hn0, sizeof(oncore_cmd_Hn0));
oncore_sendmsg(instance, oncore_cmd_Ba, sizeof(oncore_cmd_Ba ));
} else if (instance->chan == 8) {
oncore_sendmsg(instance, oncore_cmd_Ba0, sizeof(oncore_cmd_Ba0));
oncore_sendmsg(instance, oncore_cmd_Bn0, sizeof(oncore_cmd_Bn0));
oncore_sendmsg(instance, oncore_cmd_Ha0, sizeof(oncore_cmd_Ha0));
oncore_sendmsg(instance, oncore_cmd_Hn0, sizeof(oncore_cmd_Hn0));
oncore_sendmsg(instance, oncore_cmd_Ea, sizeof(oncore_cmd_Ea ));
} else if (instance->chan == 12){
oncore_sendmsg(instance, oncore_cmd_Ba0, sizeof(oncore_cmd_Ba0));
oncore_sendmsg(instance, oncore_cmd_Bn0, sizeof(oncore_cmd_Bn0));
oncore_sendmsg(instance, oncore_cmd_Ea0, sizeof(oncore_cmd_Ea0));
oncore_sendmsg(instance, oncore_cmd_En0, sizeof(oncore_cmd_En0));
oncore_sendmsg(instance, oncore_cmd_Ha, sizeof(oncore_cmd_Ha ));
}
instance->count = 1;
instance->o_state = ONCORE_ALMANAC;
oncore_log(instance, LOG_NOTICE, "state = ONCORE_ALMANAC");
}
static void
oncore_msg_Ga(
struct instance *instance,
u_char *buf,
size_t len
)
{
char Msg[160];
long lat, lon, ht;
double Lat, Lon, Ht;
lat = buf_w32(&buf[4]);
lon = buf_w32(&buf[8]);
ht = buf_w32(&buf[12]);
Lat = lat;
Lon = lon;
Ht = ht;
Lat /= 3600000;
Lon /= 3600000;
Ht /= 100;
snprintf(Msg, sizeof(Msg),
"Ga Posn Lat = %.7f, Lon = %.7f, Ht = %.2f", Lat,
Lon, Ht);
oncore_log(instance, LOG_NOTICE, Msg);
instance->ss_lat = lat;
instance->ss_long = lon;
instance->ss_ht = ht;
oncore_print_posn(instance);
}
static void
oncore_msg_Gb(
struct instance *instance,
u_char *buf,
size_t len
)
{
char Msg[160], *gmts;
int mo, d, y, h, m, s, gmth, gmtm;
mo = buf[4];
d = buf[5];
y = 256*buf[6]+buf[7];
h = buf[8];
m = buf[9];
s = buf[10];
gmts = ((buf[11] == 0) ? "+" : "-");
gmth = buf[12];
gmtm = buf[13];
snprintf(Msg, sizeof(Msg),
"Date/Time set to: %d%s%d %2d:%02d:%02d GMT (GMT offset is %s%02d:%02d)",
d, Month[mo-1], y, h, m, s, gmts, gmth, gmtm);
oncore_log(instance, LOG_NOTICE, Msg);
}
static void
oncore_msg_Gj(
struct instance *instance,
u_char *buf,
size_t len
)
{
int dt;
char Msg[160], *cp;
instance->saw_Gj = 1;
dt = buf[5] - buf[4];
snprintf(Msg, sizeof(Msg),
"Leap Sec Msg: %d %d %d %d %d %d %d %d %d %d", buf[4],
buf[5], 256 * buf[6] + buf[7], buf[8], buf[9], buf[10],
(buf[14] + 256 *
(buf[13] + 256 * (buf[12] + 256 * buf[11]))),
buf[15], buf[16], buf[17]);
oncore_log(instance, LOG_INFO, Msg);
if (dt) {
snprintf(Msg, sizeof(Msg),
"Leap second (%d) scheduled for %d%s%d at %d:%d:%d",
dt, buf[9], Month[buf[8] - 1],
256 * buf[6] + buf[7], buf[15], buf[16],
buf[17]);
oncore_log(instance, LOG_NOTICE, Msg);
}
instance->pp->leap = LEAP_NOWARNING;
cp = "Set pp.leap to LEAP_NOWARNING";
if (buf[6] == instance->BEHa[6] && buf[7] == instance->BEHa[7] &&
buf[8] == instance->BEHa[4]) {
if (dt) {
if (dt < 0) {
instance->pp->leap = LEAP_DELSECOND;
cp = "Set pp.leap to LEAP_DELSECOND";
} else {
instance->pp->leap = LEAP_ADDSECOND;
cp = "Set pp.leap to LEAP_ADDSECOND";
}
}
}
oncore_log(instance, LOG_INFO, cp);
}
static void
oncore_msg_Sz(
struct instance *instance,
u_char *buf,
size_t len
)
{
if (instance && instance->peer) {
oncore_log(instance, LOG_ERR, "Oncore: System Failure at Power On");
oncore_shutdown(instance->unit, instance->peer);
}
}
static void
oncore_antenna_report(
struct instance *instance,
enum antenna_state new_state)
{
char *cp;
if (instance->ant_state == new_state)
return;
switch (new_state) {
case ONCORE_ANTENNA_OK: cp = "GPS antenna: OK"; break;
case ONCORE_ANTENNA_OC: cp = "GPS antenna: short (overcurrent)"; break;
case ONCORE_ANTENNA_UC: cp = "GPS antenna: open (not connected)"; break;
case ONCORE_ANTENNA_NV: cp = "GPS antenna: short (no voltage)"; break;
default: cp = "GPS antenna: ?"; break;
}
instance->ant_state = new_state;
oncore_log(instance, LOG_NOTICE, cp);
}
static void
oncore_chan_test(
struct instance *instance
)
{
instance->o_state = ONCORE_CHECK_CHAN;
oncore_log(instance, LOG_NOTICE, "state = ONCORE_CHECK_CHAN");
instance->count3 = 1;
oncore_sendmsg(instance, oncore_cmd_Ba, sizeof(oncore_cmd_Ba));
oncore_sendmsg(instance, oncore_cmd_Ea, sizeof(oncore_cmd_Ea));
oncore_sendmsg(instance, oncore_cmd_Ha, sizeof(oncore_cmd_Ha));
}
static void
oncore_check_almanac(
struct instance *instance
)
{
if (instance->chan == 6) {
instance->rsm.bad_almanac = instance->BEHa[64]&0x1;
instance->rsm.bad_fix = instance->BEHa[64]&0x52;
} else if (instance->chan == 8) {
instance->rsm.bad_almanac = instance->BEHa[72]&0x1;
instance->rsm.bad_fix = instance->BEHa[72]&0x52;
} else if (instance->chan == 12) {
int bits1, bits2, bits3;
bits1 = (instance->BEHa[129]>>5) & 0x7;
bits2 = instance->BEHa[130];
instance->rsm.bad_almanac = (bits2 & 0x80);
instance->rsm.bad_fix = (bits2 & 0x8) || (bits1 == 0x2);
bits3 = instance->BEHa[141];
if (!instance->count5_set && (bits3 & 0xC0)) {
instance->count5 = 2;
instance->count5_set = 1;
}
#ifdef ONCORE_VERBOSE_CHECK_ALMANAC
{
char Msg[160];
snprintf(Msg, sizeof(Msg),
"DEBUG BITS: (%x %x), (%x %x %x), %x %x %x %x %x",
instance->BEHa[129],
instance->BEHa[130], bits1, bits2,
bits3, instance->mode == MODE_0D,
instance->mode == MODE_2D,
instance->mode == MODE_3D,
instance->rsm.bad_almanac,
instance->rsm.bad_fix);
oncore_log(instance, LOG_DEBUG, Msg);
}
#endif
}
}
static void
oncore_check_antenna(
struct instance *instance
)
{
enum antenna_state antenna;
antenna = instance->ant_state;
if (instance->chan == 12)
antenna = (instance->BEHa[130] & 0x6 ) >> 1;
else
antenna = (instance->BEHa[37] & 0xc0) >> 6;
oncore_antenna_report (instance, antenna);
}
static void
oncore_check_leap_sec(
struct instance *instance
)
{
oncore_cmd_Bl[2] = 1;
if (instance->Bj_day != instance->BEHa[5]) {
instance->Bj_day = instance->BEHa[5];
if (instance->saw_Gj < 0) {
if ((instance->BEHa[4] == 6) || (instance->BEHa[4] == 12))
oncore_sendmsg(instance, oncore_cmd_Bj, sizeof(oncore_cmd_Bj));
oncore_sendmsg(instance, oncore_cmd_Bl, sizeof(oncore_cmd_Bl));
return;
}
if (instance->saw_Gj == 0)
instance->count4 = 1;
oncore_sendmsg(instance, oncore_cmd_Gj, sizeof(oncore_cmd_Gj));
return;
}
if (instance->count4) {
if (instance->saw_Gj == 1)
instance->count4 = 0;
else if (instance->count4++ > 5) {
instance->saw_Gj = -1;
instance->count4 = 0;
if ((instance->BEHa[4] == 6) || (instance->BEHa[4] == 12))
oncore_sendmsg(instance, oncore_cmd_Bj, sizeof(oncore_cmd_Bj));
oncore_sendmsg(instance, oncore_cmd_Bl, sizeof(oncore_cmd_Bl));
}
}
}
static int
oncore_checksum_ok(
u_char *buf,
int len
)
{
int i, j;
j = 0;
for (i = 2; i < len-3; i++)
j ^= buf[i];
return(j == buf[len-3]);
}
static void
oncore_compute_dH(
struct instance *instance
)
{
int GPS, MSL;
char Msg[160];
instance->have_dH = 1;
if (instance->chan == 12) {
GPS = buf_w32(&instance->BEHa[39]);
MSL = buf_w32(&instance->BEHa[43]);
} else {
GPS = buf_w32(&instance->BEHa[23]);
MSL = buf_w32(&instance->BEHa[27]);
}
instance->dH = GPS - MSL;
instance->dH /= 100.;
if (MSL) {
snprintf(Msg, sizeof(Msg), "dH = (GPS - MSL) = %.2fm",
instance->dH);
oncore_log(instance, LOG_INFO, Msg);
}
}
static void
oncore_load_almanac(
struct instance *instance
)
{
u_char *cp, Cmd[20];
int n;
struct timeval tv;
struct tm *tm;
if (!instance->shmem)
return;
#ifndef ONCORE_VERBOSE_LOAD_ALMANAC
for (cp = instance->shmem + 4; (n = 256 * (*(cp-3)) + *(cp-2));
cp += (n + 3)) {
if (!strncmp((char *) cp, "@@Cb", 4) &&
oncore_checksum_ok(cp, 33) &&
(*(cp+4) == 4 || *(cp+4) == 5)) {
write(instance->ttyfd, cp, n);
oncore_print_Cb(instance, cp);
}
}
#else
for (cp = instance->shmem + 4; (n = 256 * (*(cp-3)) + *(cp-2));
cp += (n+3)) {
char Msg[160];
snprintf(Msg, sizeof(Msg), "See %c%c%c%c %d", *(cp),
*(cp+1), *(cp+2), *(cp+3), *(cp+4));
oncore_log(instance, LOG_DEBUG, Msg);
if (!strncmp(cp, "@@Cb", 4)) {
oncore_print_Cb(instance, cp);
if (oncore_checksum_ok(cp, 33)) {
if (*(cp+4) == 4 || *(cp+4) == 5) {
oncore_log(instance, LOG_DEBUG, "GOOD SF");
write(instance->ttyfd, cp, n);
} else
oncore_log(instance, LOG_DEBUG, "BAD SF");
} else
oncore_log(instance, LOG_DEBUG, "BAD CHECKSUM");
}
}
#endif
if (!instance->posn_set) {
oncore_log(instance, LOG_NOTICE, "Loading Posn from SHMEM");
for (cp=instance->shmem+4; (n = 256*(*(cp-3)) + *(cp-2)); cp+=(n+3)) {
if ((instance->chan == 6 && (!strncmp((char *) cp, "@@Ba", 4) && oncore_checksum_ok(cp, 68))) ||
(instance->chan == 8 && (!strncmp((char *) cp, "@@Ea", 4) && oncore_checksum_ok(cp, 76))) ||
(instance->chan == 12 && (!strncmp((char *) cp, "@@Ha", 4) && oncore_checksum_ok(cp, 154)))) {
int ii, jj, kk;
instance->posn_set = 1;
ii = buf_w32(cp + 15);
jj = buf_w32(cp + 19);
kk = buf_w32(cp + 23);
#ifdef ONCORE_VERBOSE_LOAD_ALMANAC
{
char Msg[160];
snprintf(Msg, sizeof(Msg),
"SHMEM posn = %ld (%d, %d, %d)",
(long)(cp-instance->shmem),
ii, jj, kk);
oncore_log(instance, LOG_DEBUG, Msg);
}
#endif
if (ii != 0 || jj != 0 || kk != 0) {
instance->ss_lat = ii;
instance->ss_long = jj;
instance->ss_ht = kk;
}
}
}
}
oncore_set_posn(instance);
GETTIMEOFDAY(&tv, 0);
tm = gmtime((const time_t *) &tv.tv_sec);
#ifdef ONCORE_VERBOSE_LOAD_ALMANAC
{
char Msg[160];
snprintf(Msg, sizeof(Msg), "DATE %d %d %d, %d %d %d",
1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
oncore_log(instance, LOG_DEBUG, Msg);
}
#endif
if (instance->chan == 12) {
memcpy(Cmd, oncore_cmd_Gb, (size_t) sizeof(oncore_cmd_Gb));
Cmd[-2+4] = tm->tm_mon + 1;
Cmd[-2+5] = tm->tm_mday;
Cmd[-2+6] = (1900+tm->tm_year)/256;
Cmd[-2+7] = (1900+tm->tm_year)%256;
Cmd[-2+8] = tm->tm_hour;
Cmd[-2+9] = tm->tm_min;
Cmd[-2+10] = tm->tm_sec;
Cmd[-2+11] = 0;
Cmd[-2+12] = 0;
Cmd[-2+13] = 0;
oncore_sendmsg(instance, Cmd, sizeof(oncore_cmd_Gb));
} else {
oncore_sendmsg(instance, oncore_cmd_Ab, sizeof(oncore_cmd_Ab));
memcpy(Cmd, oncore_cmd_Ac, (size_t) sizeof(oncore_cmd_Ac));
Cmd[-2+4] = tm->tm_mon + 1;
Cmd[-2+5] = tm->tm_mday;
Cmd[-2+6] = (1900+tm->tm_year)/256;
Cmd[-2+7] = (1900+tm->tm_year)%256;
oncore_sendmsg(instance, Cmd, sizeof(oncore_cmd_Ac));
memcpy(Cmd, oncore_cmd_Aa, (size_t) sizeof(oncore_cmd_Aa));
Cmd[-2+4] = tm->tm_hour;
Cmd[-2+5] = tm->tm_min;
Cmd[-2+6] = tm->tm_sec;
oncore_sendmsg(instance, Cmd, sizeof(oncore_cmd_Aa));
}
oncore_log(instance, LOG_INFO, "Setting Posn and Time after Loading Almanac");
}
static void
oncore_print_Cb(
struct instance *instance,
u_char *cp
)
{
#ifdef ONCORE_VERBOSE_CB
int ii;
char Msg[160], Msg2[10];
snprintf(Msg, sizeof(Msg), "DEBUG: See: %c%c%c%c", *(cp),
*(cp+1), *(cp+2), *(cp+3));
oncore_log(instance, LOG_DEBUG, Msg);
snprintf(Msg, sizeof(Msg), "DEBUG: Cb: [%d,%d]", *(cp+4),
*(cp+5));
for(ii = 0; ii < 33; ii++) {
snprintf(Msg2, sizeof(Msg2), " %d", *(cp+ii));
strncat(Msg, Msg2, sizeof(Msg));
}
oncore_log(instance, LOG_DEBUG, Msg);
snprintf(Msg, sizeof(Msg), "Debug: Cb: [%d,%d]", *(cp+4),
*(cp+5));
oncore_log(instance, LOG_DEBUG, Msg);
#endif
}
#if 0
static void
oncore_print_array(
u_char *cp,
int n
)
{
int jj, i, j, nn;
nn = 0;
printf("\nTOP\n");
jj = n/16;
for (j=0; j<jj; j++) {
printf("%4d: ", nn);
nn += 16;
for (i=0; i<16; i++)
printf(" %o", *cp++);
printf("\n");
}
}
#endif
static void
oncore_print_posn(
struct instance *instance
)
{
char Msg[120], ew, ns;
double xd, xm, xs, yd, ym, ys, hm, hft;
int idx, idy, is, imx, imy;
long lat, lon;
oncore_log(instance, LOG_INFO, "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;
xd = lat/3600000.;
yd = lon/3600000.;
snprintf(Msg, sizeof(Msg),
"Lat = %c %11.7fdeg, Long = %c %11.7fdeg, Alt = %5.2fm (%5.2fft) GPS",
ns, xd, ew, yd, hm, hft);
oncore_log(instance, LOG_INFO, Msg);
idx = xd;
idy = yd;
imx = lat%3600000;
imy = lon%3600000;
xm = imx/60000.;
ym = imy/60000.;
snprintf(Msg, sizeof(Msg),
"Lat = %c %3ddeg %7.4fm, Long = %c %3ddeg %8.5fm, Alt = %7.2fm (%7.2fft) GPS", ns, idx, xm, ew, idy, ym, hm, hft);
oncore_log(instance, LOG_INFO, Msg);
imx = xm;
imy = ym;
is = lat%60000;
xs = is/1000.;
is = lon%60000;
ys = is/1000.;
snprintf(Msg, sizeof(Msg),
"Lat = %c %3ddeg %2dm %5.2fs, Long = %c %3ddeg %2dm %5.2fs, Alt = %7.2fm (%7.2fft) GPS",
ns, idx, imx, xs, ew, idy, imy, ys, hm, hft);
oncore_log(instance, LOG_INFO, Msg);
}
static void
oncore_sendmsg(
struct instance *instance,
u_char *ptr,
size_t len
)
{
int fd;
u_char cs = 0;
fd = instance->ttyfd;
#ifdef ONCORE_VERBOSE_SENDMSG
if (debug > 4) {
char Msg[120];
snprintf(Msg, sizeof(Msg), "ONCORE: Send @@%c%c %d",
ptr[0], ptr[1], (int)len);
oncore_log(instance, LOG_DEBUG, Msg);
}
#endif
write(fd, "@@", (size_t) 2);
write(fd, ptr, len);
while (len--)
cs ^= *ptr++;
write(fd, &cs, (size_t) 1);
write(fd, "\r\n", (size_t) 2);
}
static void
oncore_set_posn(
struct instance *instance
)
{
int mode;
u_char Cmd[20];
if (instance->chan == 12)
oncore_sendmsg(instance, oncore_cmd_Gd0, sizeof(oncore_cmd_Gd0));
else {
oncore_sendmsg(instance, oncore_cmd_At0, sizeof(oncore_cmd_At0));
oncore_sendmsg(instance, oncore_cmd_Av0, sizeof(oncore_cmd_Av0));
}
mode = instance->init_type;
if (mode != 0) {
memcpy(Cmd, oncore_cmd_As, (size_t) sizeof(oncore_cmd_As));
w32_buf(&Cmd[-2+4], (int) instance->ss_lat);
w32_buf(&Cmd[-2+8], (int) instance->ss_long);
w32_buf(&Cmd[-2+12], (int) instance->ss_ht);
Cmd[-2+16] = 0;
oncore_sendmsg(instance, Cmd, sizeof(oncore_cmd_As));
memcpy(Cmd, oncore_cmd_Au, (size_t) sizeof(oncore_cmd_Au));
w32_buf(&Cmd[-2+4], (int) instance->ss_ht);
Cmd[-2+8] = 0;
oncore_sendmsg(instance, Cmd, sizeof(oncore_cmd_Au));
if (instance->chan == 12) {
memcpy(Cmd, oncore_cmd_Ga, (size_t) sizeof(oncore_cmd_Ga));
w32_buf(&Cmd[-2+4], (int) instance->ss_lat);
w32_buf(&Cmd[-2+8], (int) instance->ss_long);
w32_buf(&Cmd[-2+12],(int) instance->ss_ht);
Cmd[-2+16] = 0;
oncore_sendmsg(instance, Cmd, sizeof(oncore_cmd_Ga));
} else {
memcpy(Cmd, oncore_cmd_Ad, (size_t) sizeof(oncore_cmd_Ad));
w32_buf(&Cmd[-2+4], (int) instance->ss_lat);
oncore_sendmsg(instance, Cmd, sizeof(oncore_cmd_Ad));
memcpy(Cmd, oncore_cmd_Ae, (size_t) sizeof(oncore_cmd_Ae));
w32_buf(&Cmd[-2+4], (int) instance->ss_long);
oncore_sendmsg(instance, Cmd, sizeof(oncore_cmd_Ae));
memcpy(Cmd, oncore_cmd_Af, (size_t) sizeof(oncore_cmd_Af));
w32_buf(&Cmd[-2+4], (int) instance->ss_ht);
Cmd[-2+8] = 0;
oncore_sendmsg(instance, Cmd, sizeof(oncore_cmd_Af));
}
if (instance->chan == 12)
oncore_sendmsg(instance, oncore_cmd_Gd1, sizeof(oncore_cmd_Gd1));
else
oncore_sendmsg(instance, oncore_cmd_At1, sizeof(oncore_cmd_At1));
}
}
static void
oncore_set_traim(
struct instance *instance
)
{
char Msg[160];
if (instance->traim_in != -1)
instance->traim = instance->traim_in;
else
instance->traim = instance->traim_ck;
snprintf(Msg, sizeof(Msg), "Input says TRAIM = %d",
instance->traim_in);
oncore_log(instance, LOG_INFO, Msg);
snprintf(Msg, sizeof(Msg), "Model # says TRAIM = %d",
instance->traim_id);
oncore_log(instance, LOG_INFO, Msg);
snprintf(Msg, sizeof(Msg), "Testing says TRAIM = %d",
instance->traim_ck);
oncore_log(instance, LOG_INFO, Msg);
snprintf(Msg, sizeof(Msg), "Using TRAIM = %d",
instance->traim);
oncore_log(instance, LOG_INFO, Msg);
if (instance->traim_ck == 1 && instance->traim == 0) {
if (instance->chan == 6)
oncore_sendmsg(instance, oncore_cmd_Bnx, sizeof(oncore_cmd_Bnx));
else if (instance->chan == 8)
oncore_sendmsg(instance, oncore_cmd_Enx, sizeof(oncore_cmd_Enx));
else
oncore_sendmsg(instance, oncore_cmd_Ge0, sizeof(oncore_cmd_Ge0));
oncore_sendmsg(instance, oncore_cmd_Hn0, sizeof(oncore_cmd_Hn0));
}
}
static void
oncore_shmem_get_3D(
struct instance *instance
)
{
if (instance->pp->second%15 == 3) {
instance->shmem_reset = 1;
if (instance->chan == 12) {
if (instance->shmem_Posn == 2)
oncore_sendmsg(instance, oncore_cmd_Gd2, sizeof(oncore_cmd_Gd2));
else
oncore_sendmsg(instance, oncore_cmd_Gd0, sizeof(oncore_cmd_Gd0));
} else {
if (instance->saw_At) {
oncore_sendmsg(instance, oncore_cmd_At0, sizeof(oncore_cmd_At0));
if (instance->shmem_Posn == 2)
oncore_sendmsg(instance, oncore_cmd_Av1, sizeof(oncore_cmd_Av1));
} else
oncore_sendmsg(instance, oncore_cmd_Av0, sizeof(oncore_cmd_Av0));
}
} else if (instance->shmem_reset || (instance->mode != MODE_0D)) {
instance->shmem_reset = 0;
if (instance->chan == 12)
oncore_sendmsg(instance, oncore_cmd_Gd1, sizeof(oncore_cmd_Gd1));
else {
if (instance->saw_At) {
if (instance->mode == MODE_2D)
oncore_sendmsg(instance, oncore_cmd_Av0, sizeof(oncore_cmd_Av0));
oncore_sendmsg(instance, oncore_cmd_At1, sizeof(oncore_cmd_At1));
} else
oncore_sendmsg(instance, oncore_cmd_Av1, sizeof(oncore_cmd_Av1));
}
}
}
static void
oncore_ss(
struct instance *instance
)
{
char Msg[160];
double lat, lon, ht;
if (instance->site_survey == ONCORE_SS_HW) {
if ((instance->chan == 8 && !(instance->BEHa[37] & 0x20)) ||
(instance->chan == 12 && !(instance->BEHa[130] & 0x10))) {
oncore_log(instance, LOG_INFO, "Now in 0D mode");
if (instance->chan == 12)
oncore_sendmsg(instance, oncore_cmd_Gax, sizeof(oncore_cmd_Gax));
else
oncore_sendmsg(instance, oncore_cmd_Asx, sizeof(oncore_cmd_Asx));
oncore_log(instance, LOG_NOTICE, "SSstate = ONCORE_SS_DONE");
instance->site_survey = ONCORE_SS_DONE;
}
} else {
if (instance->rsm.bad_fix)
return;
if (instance->mode != MODE_3D)
return;
instance->ss_lat += buf_w32(&instance->BEHa[15]);
instance->ss_long += buf_w32(&instance->BEHa[19]);
instance->ss_ht += buf_w32(&instance->BEHa[23]);
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;
snprintf(Msg, sizeof(Msg),
"Surveyed posn: lat %.3f (mas) long %.3f (mas) ht %.3f (cm)",
instance->ss_lat, instance->ss_long,
instance->ss_ht);
oncore_log(instance, LOG_NOTICE, Msg);
lat = instance->ss_lat/3600000.;
lon = instance->ss_long/3600000.;
ht = instance->ss_ht/100;
snprintf(Msg, sizeof(Msg),
"Surveyed posn: lat %.7f (deg) long %.7f (deg) ht %.2f (m)",
lat, lon, ht);
oncore_log(instance, LOG_NOTICE, Msg);
oncore_set_posn(instance);
oncore_log(instance, LOG_INFO, "Now in 0D mode");
oncore_log(instance, LOG_NOTICE, "SSstate = ONCORE_SS_DONE");
instance->site_survey = ONCORE_SS_DONE;
}
}
static int
oncore_wait_almanac(
struct instance *instance
)
{
if (instance->rsm.bad_almanac) {
instance->counta++;
if (instance->counta%5 == 0)
oncore_log(instance, LOG_INFO, "Waiting for Almanac");
if (!instance->almanac_from_shmem) {
instance->almanac_from_shmem = 1;
oncore_load_almanac(instance);
}
return(1);
} else {
if (instance->chan == 6)
oncore_sendmsg(instance, oncore_cmd_Bn, sizeof(oncore_cmd_Bn));
else if (instance->chan == 8)
oncore_sendmsg(instance, oncore_cmd_En, sizeof(oncore_cmd_En));
else if (instance->chan == 12) {
oncore_sendmsg(instance, oncore_cmd_Gc, sizeof(oncore_cmd_Gc));
oncore_sendmsg(instance, oncore_cmd_Ge, sizeof(oncore_cmd_Ge));
oncore_sendmsg(instance, oncore_cmd_Hn, sizeof(oncore_cmd_Hn));
}
instance->traim_delay = 1;
oncore_log(instance, LOG_NOTICE, "Have now loaded an ALMANAC");
instance->o_state = ONCORE_RUN;
oncore_log(instance, LOG_NOTICE, "state = ONCORE_RUN");
}
return(0);
}
static void
oncore_log (
struct instance *instance,
int log_level,
const char *msg
)
{
int i;
char Msg[200];
snprintf(Msg, sizeof(Msg), "ONCORE[%d]: %s", instance->unit,
msg);
syslog(log_level, Msg);
i = strlen(msg);
if (i > 127) {
snprintf(Msg, sizeof(Msg),
"Internal Error: max error msg length exceeded in clockstats file (%d)",
i);
record_clock_stats(&(instance->peer->srcadr), Msg);
record_clock_stats(&(instance->peer->srcadr), "Start of message was");
strncpy(Msg, msg, 120);
record_clock_stats(&(instance->peer->srcadr), Msg);
} else {
if (i < 110) {
snprintf(Msg, sizeof(Msg), "ONCORE[%d]: %s",
instance->unit, msg);
record_clock_stats(&(instance->peer->srcadr), Msg);
} else
record_clock_stats(&(instance->peer->srcadr), msg);
}
#ifdef ONCORE_VERBOSE_ONCORE_LOG
instance->max_len = max(i, instance->max_len);
instance->max_count++;
if (instance->max_count % 100 == 0) {
snprintf(Msg, sizeof(Msg),
"Max Message Length so far is %d",
instance->max_len);
oncore_log(instance, LOG_INFO, Msg);
}
#endif
}
#else
int refclock_oncore_bs;
#endif