📄 refclock_ripencc.c
字号:
up->unit = unit; up->leapdelta = 0; up->utcflags = 0; /* * Initialize the Clock */ /* query software versions */ cmd_0x1F(&spt); ripencc_send(peer, spt); /* query receiver health */ cmd_0x26(&spt); ripencc_send(peer, spt); /* query serial numbers */ cmd_0x8E42q(&spt); ripencc_send(peer, spt); /* query manuf params */ cmd_0x8E41q(&spt); ripencc_send(peer, spt); /* i/o opts */ /* trimble manual page A30 */ cmd_0x35s(&spt, 0x1C, /* position */ 0x00, /* velocity */ 0x05, /* timing */ 0x0a); /* auxilary */ ripencc_send(peer, spt); /* turn off port A */ cmd_0x3Ds (&spt, 0x0B, /* baud_out */ 0x0B, /* baud_inp */ 0x07, /* char_code */ 0x07, /* stopbitcode */ 0x01, /* output_mode */ 0x00); /* input_mode */ ripencc_send(peer, spt); /* set i/o options */ cmd_0x8E4As (&spt, 0x01, /* PPS on */ 0x01, /* Timebase UTC */ 0x00, /* polarity positive */ 0., /* 100 ft. cable XXX make flag */ 1e-6 * GPS_C); /* turn of biasuncert. > (1us) */ ripencc_send(peer,spt); /* all outomatic packet output off */ cmd_0x8E4Ds(&spt, 0x00000000); /* AutoOutputMask */ ripencc_send(peer, spt); cmd_0xBBq (&spt, 0x00); /* query primary configuration */ ripencc_send(peer,spt); /* query PPS parameters */ cmd_0x8E4Aq (&spt); /* query PPS params */ ripencc_send(peer,spt); /* query survey limit */ cmd_0x8E4Bq (&spt); /* query survey limit */ ripencc_send(peer,spt);#ifdef DEBUG_NCC if (debug) printf("ripencc_start: success\n");#endif /* DEBUG_NCC */ /* * Start the PPSAPI interface if it is there. Default to use * the assert edge and do not enable the kernel hardpps. */ if (time_pps_create(fd, &up->handle) < 0) { up->handle = 0; msyslog(LOG_ERR, "refclock_ripencc: time_pps_create failed: %m"); return (1); } return(ripencc_ppsapi(peer, 0, 0));}/* * ripencc_control - fudge control */static voidripencc_control( int unit, /* unit (not used) */ struct refclockstat *in, /* input parameters (not used) */ struct refclockstat *out, /* output parameters (not used) */ struct peer *peer /* peer structure pointer */ ){ struct refclockproc *pp;#ifdef DEBUG_NCC msyslog(LOG_INFO,"%s()",__FUNCTION__);#endif /* DEBUG_NCC */ pp = peer->procptr; ripencc_ppsapi(peer, pp->sloppyclockflag & CLK_FLAG2, pp->sloppyclockflag & CLK_FLAG3);}/* * Initialize PPSAPI */intripencc_ppsapi( struct peer *peer, /* peer structure pointer */ int enb_clear, /* clear enable */ int enb_hardpps /* hardpps enable */ ){ struct refclockproc *pp; struct ripencc_unit *up; int capability; pp = peer->procptr; up = (struct ripencc_unit *)pp->unitptr; if (time_pps_getcap(up->handle, &capability) < 0) { msyslog(LOG_ERR, "refclock_ripencc: time_pps_getcap failed: %m"); return (0); } memset(&up->pps_params, 0, sizeof(pps_params_t)); if (enb_clear) up->pps_params.mode = capability & PPS_CAPTURECLEAR; else up->pps_params.mode = capability & PPS_CAPTUREASSERT; if (!up->pps_params.mode) { msyslog(LOG_ERR, "refclock_ripencc: invalid capture edge %d", !enb_clear); return (0); } up->pps_params.mode |= PPS_TSFMT_TSPEC; if (time_pps_setparams(up->handle, &up->pps_params) < 0) { msyslog(LOG_ERR, "refclock_ripencc: time_pps_setparams failed: %m"); return (0); } if (enb_hardpps) { if (time_pps_kcbind(up->handle, PPS_KC_HARDPPS, up->pps_params.mode & ~PPS_TSFMT_TSPEC, PPS_TSFMT_TSPEC) < 0) { msyslog(LOG_ERR, "refclock_ripencc: time_pps_kcbind failed: %m"); return (0); } pps_enable = 1; } peer->precision = PPS_PRECISION;#if DEBUG_NCC if (debug) { time_pps_getparams(up->handle, &up->pps_params); printf( "refclock_ripencc: capability 0x%x version %d mode 0x%x kern %d\n", capability, up->pps_params.api_version, up->pps_params.mode, enb_hardpps); }#endif /* DEBUG_NCC */ return (1);}/* * This function is called every 64 seconds from ripencc_receive * It will fetch the pps time * * Return 0 on failure and 1 on success. */static intripencc_get_pps_ts( struct ripencc_unit *up, l_fp *tsptr ){ pps_info_t pps_info; struct timespec timeout, ts; double dtemp; l_fp tstmp;#ifdef DEBUG_PPS msyslog(LOG_INFO,"ripencc_get_pps_ts\n");#endif /* DEBUG_PPS */ /* * Convert the timespec nanoseconds field to ntp l_fp units. */ if (up->handle == 0) return (0); timeout.tv_sec = 0; timeout.tv_nsec = 0; memcpy(&pps_info, &up->pps_info, sizeof(pps_info_t)); if (time_pps_fetch(up->handle, PPS_TSFMT_TSPEC, &up->pps_info, &timeout) < 0) return (0); if (up->pps_params.mode & PPS_CAPTUREASSERT) { if (pps_info.assert_sequence == up->pps_info.assert_sequence) return (0); ts = up->pps_info.assert_timestamp; } else if (up->pps_params.mode & PPS_CAPTURECLEAR) { if (pps_info.clear_sequence == up->pps_info.clear_sequence) return (0); ts = up->pps_info.clear_timestamp; } else { return (0); } if ((up->ts.tv_sec == ts.tv_sec) && (up->ts.tv_nsec == ts.tv_nsec)) return (0); up->ts = ts; tstmp.l_ui = ts.tv_sec + JAN_1970; dtemp = ts.tv_nsec * FRAC / 1e9; tstmp.l_uf = (u_int32)dtemp;#ifdef DEBUG_PPS msyslog(LOG_INFO,"ts.tv_sec: %d\n",(int)ts.tv_sec); msyslog(LOG_INFO,"ts.tv_nsec: %ld\n",ts.tv_nsec);#endif /* DEBUG_PPS */ *tsptr = tstmp; return (1);}/* * ripencc_shutdown - shut down a GPS clock */static voidripencc_shutdown(int unit, struct peer *peer){ register struct ripencc_unit *up; struct refclockproc *pp; pp = peer->procptr; up = (struct ripencc_unit *)pp->unitptr; if (up->handle != 0) time_pps_destroy(up->handle); io_closeclock(&pp->io); free(up);}/* * ripencc_poll - called by the transmit procedure */static voidripencc_poll(int unit, struct peer *peer){ register struct ripencc_unit *up; struct refclockproc *pp; TSIPPKT spt;#ifdef DEBUG_NCC if (debug) fprintf(stderr, "ripencc_poll(%d)\n", unit);#endif /* DEBUG_NCC */ pp = peer->procptr; up = (struct ripencc_unit *)pp->unitptr; if (up->pollcnt == 0) refclock_report(peer, CEVNT_TIMEOUT); else up->pollcnt--; pp->polls++; up->polled = 1; /* poll for UTC superpacket */ cmd_0x8EADq (&spt); ripencc_send(peer,spt);}/* * ripencc_send - send message to clock * use the structures being created by the trimble functions! * makes the code more readable/clean */static voidripencc_send(struct peer *peer, TSIPPKT spt){ unsigned char *ip, *op; unsigned char obuf[512];#ifdef DEBUG_RAW { register struct ripencc_unit *up; register struct refclockproc *pp; pp = peer->procptr; up = (struct ripencc_unit *)pp->unitptr; if (debug) printf("ripencc_send(%d, %02X)\n", up->unit, cmd); }#endif /* DEBUG_RAW */ ip = spt.buf; op = obuf; *op++ = 0x10; *op++ = spt.code; while (spt.len--) { if (op-obuf > sizeof(obuf)-5) { msyslog(LOG_ERR, "ripencc_send obuf overflow!"); refclock_report(peer, CEVNT_FAULT); return; } if (*ip == 0x10) /* byte stuffing */ *op++ = 0x10; *op++ = *ip++; } *op++ = 0x10; *op++ = 0x03;#ifdef DEBUG_RAW if (debug) { /* print raw packet */ unsigned char *cp; int i; printf("ripencc_send: len %d\n", op-obuf); for (i=1, cp=obuf; cp<op; i++, cp++) { printf(" %02X", *cp); if (i%10 == 0) printf("\n"); } printf("\n"); }#endif /* DEBUG_RAW */ if (write(peer->procptr->io.fd, obuf, op-obuf) == -1) { refclock_report(peer, CEVNT_FAULT); }}/* * ripencc_receive() * * called when a packet is received on the serial port * takes care of further processing * */static voidripencc_receive(struct recvbuf *rbufp){ register struct ripencc_unit *up; register struct refclockproc *pp; struct peer *peer; static TSIPPKT rpt; /* structure for current incoming TSIP report */ TSIPPKT spt; /* send packet */ int ns_since_pps; int i; char *cp; /* Use these variables to hold data until we decide its worth keeping */ char rd_lastcode[BMAX]; l_fp rd_tmp; u_short rd_lencode; /* msyslog(LOG_INFO, "%s",__FUNCTION__); */ /* * Initialize pointers and read the timecode and timestamp */ peer = (struct peer *)rbufp->recv_srcclock; pp = peer->procptr; up = (struct ripencc_unit *)pp->unitptr; rd_lencode = refclock_gtlin(rbufp, rd_lastcode, BMAX, &rd_tmp);#ifdef DEBUG_RAW if (debug) fprintf(stderr, "ripencc_receive(%d)\n", up->unit);#endif /* DEBUG_RAW */#ifdef DEBUG_RAW if (debug) { /* print raw packet */ int i; unsigned char *cp; printf("ripencc_receive: len %d\n", rbufp->recv_length); for (i=1, cp=(char*)&rbufp->recv_space; i <= rbufp->recv_length; i++, cp++) { printf(" %02X", *cp); if (i%10 == 0) printf("\n"); } printf("\n"); }#endif /* DEBUG_RAW */ cp = (char*) &rbufp->recv_space; i=rbufp->recv_length; while (i--) { /* loop over received chars */ tsip_input_proc(&rpt, (unsigned char) *cp++); if (rpt.status != TSIP_PARSED_FULL) continue; switch (rpt.code) { case 0x8F: /* superpacket */ switch (rpt.buf[0]) { case 0xAD: /* UTC Time */ /* * When polling on port B the timecode * is the time of the previous PPS. * If we completed receiving the packet * less than 150ms after the turn of the second, * it may have the code of the previous second. * We do not trust that and simply poll again * without even parsing it. * * More elegant would be to re-schedule the poll, * but I do not know (yet) how to do that cleanly. * */ /* BLA ns_since_pps = ncc_tstmp(rbufp, &trtmp); *//* if (up->polled && ns_since_pps > -1 && ns_since_pps < 150) { */ ns_since_pps=200; if (up->polled && ns_since_pps < 150) { msyslog(LOG_INFO, "%s(): up->polled",__FUNCTION__); ripencc_poll(up->unit, peer); break; } /* * Parse primary utc time packet * and fill refclock structure * from results. */ if (parse0x8FAD(&rpt, peer) < 0) { msyslog(LOG_INFO, "%s(): parse0x8FAD < 0",__FUNCTION__); refclock_report(peer, CEVNT_BADREPLY); break; } /* * If the PPSAPI is working, rather use its * timestamps. * assume that the PPS occurs on the second * so blow any msec */ if (ripencc_get_pps_ts(up, &rd_tmp) == 1) { pp->lastrec = up->tstamp = rd_tmp; pp->nsec = 0; } else msyslog(LOG_INFO, "%s(): ripencc_get_pps_ts returns failure\n",__FUNCTION__); if (!up->polled) { msyslog(LOG_INFO, "%s(): unrequested packet\n",__FUNCTION__); /* unrequested packet */ break; } /* we have been polled ! */ up->polled = 0; up->pollcnt = 2; /* poll for next packet */ cmd_0x8E0Bq(&spt); ripencc_send(peer,spt); if (ns_since_pps < 0) { /* no PPS */ msyslog(LOG_INFO, "%s(): ns_since_pps < 0",__FUNCTION__); refclock_report(peer, CEVNT_BADTIME); break; } /* * Process the new sample in the median filter and determine the * reference clock offset and dispersion. */ if (!refclock_process(pp)) { msyslog(LOG_INFO, "%s(): !refclock_process",__FUNCTION__); refclock_report(peer, CEVNT_BADTIME); break; } refclock_receive(peer); break; case 0x0B: /* comprehensive time packet */ parse0x8F0B(&rpt, peer); break; default: /* other superpackets */#ifdef DEBUG_NCC msyslog(LOG_INFO, "%s(): calling parseany",__FUNCTION__);#endif /* DEBUG_NCC */#ifdef TRIMBLE_OUTPUT_FUNC parseany(&rpt, peer);#endif /* TRIMBLE_OUTPUT_FUNC */ break; } break; case 0x4F: /* UTC parameters, for leap info */ parse0x4F(&rpt, peer); break; case 0x5C: /* sat tracking data */ parse0x5C(&rpt, peer); break; default: /* other packets */#ifdef TRIMBLE_OUTPUT_FUNC
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -