📄 refclock_msfees.c
字号:
ees->unit, msec(delta_sfsec), subms(delta_sfsec), ees->second, old_sincelast, ees->last_step_late, count, sum, ees->last_step_secs); if (sum) ees->last_step_secs = sum; } /* OK, so not a 4ms step at a minute boundry */ else { if (suspect_4ms_step) msyslog(LOG_ERR, "MSF%d: suspect = %x, but delta of %d.%04d [%d.%04d<%d.%04d<%d.%04d: %d %d]", ees->unit, suspect_4ms_step, msec(delta_sfsec), subms(delta_sfsec), msec(EES_STEP_F - EES_STEP_F_GRACE), subms(EES_STEP_F - EES_STEP_F_GRACE), (int)msec(delta_f_abs), (int)subms(delta_f_abs), msec(EES_STEP_F + EES_STEP_F_GRACE), subms(EES_STEP_F + EES_STEP_F_GRACE), ees->second, sincelast); if ((delta_f_abs > EES_STEP_NOTE) && ees->last_l.l_i) { static int ees_step_notes = EES_STEP_NOTES; if (ees_step_notes > 0) { ees_step_notes--; printf("MSF%d: D=%3ld.%04ld@%02d :%d%s\n", ees->unit, (long)msec(delta_sfsec), (long)subms(delta_sfsec), ees->second, sincelast, ees_step_notes ? "" : " -- NO MORE !"); msyslog(LOG_ERR, "MSF%d: D=%3d.%04d@%02d :%d%s", ees->unit, msec(delta_sfsec), subms(delta_sfsec), ees->second, (ees->last_step) ? sincelast : -1, ees_step_notes ? "" : " -- NO MORE !"); } } } } ees->last_l = ees->arrvtime; /* IF we have found that it's ramping * && it's within twice the expected ramp period * && there is a non zero step size (avoid /0 !) * THEN we twiddle things */ if (ees->using_ramp && sincelast < (ees->last_step_secs)*2 && ees->last_step_secs) { long sec_of_ramp = sincelast + ees->last_step_late; long fsecs; l_fp inc; /* Ramp time may vary, so may ramp for longer than last time */ if (sec_of_ramp > (ees->last_step_secs + 120)) sec_of_ramp = ees->last_step_secs; /* sec_of_ramp * ees->jump_fsecs may overflow 2**32 */ fsecs = sec_of_ramp * (ees->jump_fsecs / ees->last_step_secs); if (debug & DB_LOG_DELTAS) msyslog(LOG_ERR, "[%x] MSF%d: %3ld/%03d -> d=%11ld (%d|%ld)", DB_LOG_DELTAS, ees->unit, sec_of_ramp, ees->last_step_secs, fsecs, pps_arrvstamp.l_f, pps_arrvstamp.l_f + fsecs); if (debug & DB_PRINT_DELTAS) printf( "MSF%d: %3ld/%03d -> d=%11ld (%ld|%ld)\n", ees->unit, sec_of_ramp, ees->last_step_secs, fsecs, (long)pps_arrvstamp.l_f, pps_arrvstamp.l_f + fsecs); /* Must sign extend the result */ inc.l_i = (fsecs < 0) ? -1 : 0; inc.l_f = fsecs; if (debug & DB_INC_PPS) { L_SUB(&pps_arrvstamp, &inc); L_SUB(&ees->arrvtime, &inc); } else { L_ADD(&pps_arrvstamp, &inc); L_ADD(&ees->arrvtime, &inc); } } else { if (debug & DB_LOG_DELTAS) msyslog(LOG_ERR, "[%x] MSF%d: ees->using_ramp=%d, sincelast=%x / %x, ees->last_step_secs=%x", DB_LOG_DELTAS, ees->unit, ees->using_ramp, sincelast, (ees->last_step_secs)*2, ees->last_step_secs); if (debug & DB_PRINT_DELTAS) printf( "[%x] MSF%d: ees->using_ramp=%d, sincelast=%x / %x, ees->last_step_secs=%x\n", DB_LOG_DELTAS, ees->unit, ees->using_ramp, sincelast, (ees->last_step_secs)*2, ees->last_step_secs); } L_SUB(&ees->arrvtime, &offset_fudge[ees->unit]); L_SUB(&pps_arrvstamp, &offset_fudge[ees->unit]); if (call_pps_sample && !(debug & DB_NO_PPS)) { /* Sigh -- it expects its args negated */ L_NEG(&pps_arrvstamp); /* * I had to disable this here, since it appears there is no pointer to the * peer structure. * (void) pps_sample(peer, &pps_arrvstamp); */ } /* Subtract off the local clock time stamp */ L_SUB(&ees->codeoffsets[n_sample], &ees->arrvtime); if (debug & DB_LOG_SAMPLES) msyslog(LOG_ERR, "MSF%d: [%x] %d (ees: %d %d) (pps: %d %d)%s", ees->unit, DB_LOG_DELTAS, n_sample, ees->codeoffsets[n_sample].l_f, ees->codeoffsets[n_sample].l_f / 4295, pps_arrvstamp.l_f, pps_arrvstamp.l_f /4295, (debug & DB_NO_PPS) ? " [no PPS]" : ""); if (ees->nsamples++ == NCODES-1) ees_process(ees); /* Done! */}/* offcompare - auxiliary comparison routine for offset sort */#ifdef QSORT_USES_VOID_Pstatic intoffcompare( const void *va, const void *vb ){ const l_fp *a = (const l_fp *)va; const l_fp *b = (const l_fp *)vb; return(L_ISGEQ(a, b) ? (L_ISEQU(a, b) ? 0 : 1) : -1);}#elsestatic intoffcompare( const l_fp *a, const l_fp *b ){ return(L_ISGEQ(a, b) ? (L_ISEQU(a, b) ? 0 : 1) : -1);}#endif /* QSORT_USES_VOID_P *//* ees_process - process a pile of samples from the clock */static voidees_process( struct eesunit *ees ){ static int last_samples = -1; register int i, j; register int noff; register l_fp *coffs = ees->codeoffsets; l_fp offset, tmp; double dispersion; /* ++++ */ int lostsync, isinsync; int samples = ees->nsamples; int samplelog = 0; /* keep "gcc -Wall" happy ! */ int samplereduce = (samples + 1) / 2; double doffset; /* Reset things to zero so we don't have to worry later */ ees_reset(ees); if (sloppyclockflag[ees->unit]) { samplelog = (samples < 2) ? 0 : (samples < 5) ? 1 : (samples < 9) ? 2 : (samples < 17) ? 3 : (samples < 33) ? 4 : 5; samplereduce = (1 << samplelog); } if (samples != last_samples && ((samples != (last_samples-1)) || samples < 3)) { msyslog(LOG_ERR, "Samples=%d (%d), samplereduce=%d ....", samples, last_samples, samplereduce); last_samples = samples; } if (samples < 1) return; /* If requested, dump the raw data we have in the buffer */ if (ees->dump_vals) dump_buf(coffs, 0, samples, "Raw data is:"); /* Sort the offsets, trim off the extremes, then choose one. */ qsort(#ifdef QSORT_USES_VOID_P (void *)#else (char *)#endif coffs, (size_t)samples, sizeof(l_fp), offcompare); noff = samples; i = 0; while ((noff - i) > samplereduce) { /* Trim off the sample which is further away * from the median. We work this out by doubling * the median, subtracting off the end samples, and * looking at the sign of the answer, using the * identity (c-b)-(b-a) == 2*b-a-c */ tmp = coffs[(noff + i)/2]; L_ADD(&tmp, &tmp); L_SUB(&tmp, &coffs[i]); L_SUB(&tmp, &coffs[noff-1]); if (L_ISNEG(&tmp)) noff--; else i++; } /* If requested, dump the reduce data we have in the buffer */ if (ees->dump_vals) dump_buf(coffs, i, noff, "Reduced to:"); /* What we do next depends on the setting of the sloppy clock flag. * If it is on, average the remainder to derive our estimate. * Otherwise, just pick a representative value from the remaining stuff */ if (sloppyclockflag[ees->unit]) { offset.l_ui = offset.l_uf = 0; for (j = i; j < noff; j++) L_ADD(&offset, &coffs[j]); for (j = samplelog; j > 0; j--) L_RSHIFTU(&offset); } else offset = coffs[i+BESTSAMPLE]; /* Compute the dispersion as the difference between the * lowest and highest offsets that remain in the * consideration list. * * It looks like MOST clocks have MOD (max error), so halve it ! */ tmp = coffs[noff-1]; L_SUB(&tmp, &coffs[i]);#define FRACT_SEC(n) ((1 << 30) / (n/2)) dispersion = LFPTOFP(&tmp) / 2; /* ++++ */ if (debug & (DB_SYSLOG_SMPLI | DB_SYSLOG_SMPLE)) msyslog( (debug & DB_SYSLOG_SMPLE) ? LOG_ERR : LOG_INFO, "I: [%x] Offset=%06d (%d), disp=%f%s [%d], %d %d=%d %d:%d %d=%d %d", debug & (DB_SYSLOG_SMPLI | DB_SYSLOG_SMPLE), offset.l_f / 4295, offset.l_f, (dispersion * 1526) / 100, (sloppyclockflag[ees->unit]) ? " by averaging" : "", FRACT_SEC(10) / 4295, (coffs[0].l_f) / 4295, i, (coffs[i].l_f) / 4295, (coffs[samples/2].l_f) / 4295, (coffs[i+BESTSAMPLE].l_f) / 4295, noff-1, (coffs[noff-1].l_f) / 4295, (coffs[samples-1].l_f) / 4295); /* Are we playing silly wotsits ? * If we are using all data, see if there is a "small" delta, * and if so, blurr this with 3/4 of the delta from the last value */ if (ees->usealldata && ees->offset.l_uf) { long diff = (long) (ees->offset.l_uf - offset.l_uf); /* is the delta small enough ? */ if ((- FRACT_SEC(100)) < diff && diff < FRACT_SEC(100)) { int samd = (64 * 4) / samples; long new; if (samd < 2) samd = 2; new = offset.l_uf + ((diff * (samd -1)) / samd); /* Sign change -> need to fix up int part */ if ((new & 0x80000000) != (((long) offset.l_uf) & 0x80000000)) { NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */ msyslog(LOG_INFO, "I: %lx != %lx (%lx %lx), so add %d", new & 0x80000000, ((long) offset.l_uf) & 0x80000000, new, (long) offset.l_uf, (new < 0) ? -1 : 1); offset.l_ui += (new < 0) ? -1 : 1; } dispersion /= 4; if (debug & (DB_SYSLOG_SMTHI | DB_SYSLOG_SMTHE)) msyslog( (debug & DB_SYSLOG_SMTHE) ? LOG_ERR : LOG_INFO, "I: [%x] Smooth data: %ld -> %ld, dispersion now %f", debug & (DB_SYSLOG_SMTHI | DB_SYSLOG_SMTHE), ((long) offset.l_uf) / 4295, new / 4295, (dispersion * 1526) / 100); offset.l_uf = (unsigned long) new; } else if (debug & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE)) msyslog( (debug & DB_SYSLOG_NSMTHE) ? LOG_ERR : LOG_INFO, "[%x] No smooth as delta not %d < %ld < %d", debug & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE), - FRACT_SEC(100), diff, FRACT_SEC(100)); } else if (debug & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE)) msyslog( (debug & DB_SYSLOG_NSMTHE) ? LOG_ERR : LOG_INFO, "I: [%x] No smooth as flag=%x and old=%x=%d (%d:%d)", debug & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE), ees->usealldata, ees->offset.l_f, ees->offset.l_uf, offset.l_f, ees->offset.l_f - offset.l_f); /* Collect offset info for debugging info */ ees->offset = offset; ees->lowoffset = coffs[i]; ees->highoffset = coffs[noff-1]; /* Determine synchronization status. Can be unsync'd either * by a report from the clock or by a leap hold. * * Loss of the radio signal for a short time does not cause * us to go unsynchronised, since the receiver keeps quite * good time on its own. The spec says 20ms in 4 hours; the * observed drift in our clock (Cambridge) is about a second * a day, but even that keeps us within the inherent tolerance * of the clock for about 15 minutes. Observation shows that * the typical "short" outage is 3 minutes, so to allow us * to ride out those, we will give it 5 minutes. */ lostsync = current_time - ees->clocklastgood > 300 ? 1 : 0; isinsync = (lostsync || ees->leaphold > current_time) ? 0 : 1; /* Done. Use time of last good, synchronised code as the * reference time, and lastsampletime as the receive time. */ if (ees->fix_pending) { msyslog(LOG_ERR, "MSF%d: fix_pending=%d -> jump %x.%08x\n", ees->fix_pending, ees->unit, offset.l_i, offset.l_f); ees->fix_pending = 0; } LFPTOD(&offset, doffset); refclock_receive(ees->peer); ees_event(ees, lostsync ? CEVNT_PROP : CEVNT_NOMINAL);}/* msfees_poll - called by the transmit procedure */static voidmsfees_poll( int unit, struct peer *peer ){ if (unit >= MAXUNITS) { msyslog(LOG_ERR, "ees clock poll: INTERNAL: unit %d invalid", unit); return; } if (!unitinuse[unit]) { msyslog(LOG_ERR, "ees clock poll: INTERNAL: unit %d unused", unit); return; } ees_process(eesunits[unit]); if ((current_time - eesunits[unit]->lasttime) > 150) ees_event(eesunits[unit], CEVNT_FAULT);}#elseint refclock_msfees_bs;#endif /* REFCLOCK */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -