📄 refclock_msfees.c
字号:
ees_event(ees, CEVNT_BADREPLY); ees_reset(ees); return; } /* Skip the 0xff */ dpt++; /* Finally, got a complete buffer. Mainline code will * continue on. */ cp = ees->lastcode; break; default: msyslog(LOG_ERR, "ees clock: INTERNAL ERROR: %d state %d", ees->unit, ees->codestate); ees->reason = CODEREASON + 5; ees_event(ees, CEVNT_FAULT); ees_reset(ees); return; } /* Boy! After all that crap, the lastcode buffer now contains * something we hope will be a valid time code. Do length * checks and sanity checks on constant data. */ ees->codestate = EESCS_WAIT; ees->lasttime = current_time; if (ees->lencode != LENEESPRT) { ees->badformat++; ees->reason = CODEREASON + 6; ees_event(ees, CEVNT_BADREPLY); ees_reset(ees); return; } cp = ees->lastcode; /* Check that centisecond is zero */ if (cp[EESM_CSEC] != 0) { ees->baddata++; ees->reason = CODEREASON + 7; ees_event(ees, CEVNT_BADREPLY); ees_reset(ees); return; } /* Check flag formats */ if (cp[EESM_LEAP] != 0 && cp[EESM_LEAP] != 0x0f) { ees->badformat++; ees->reason = CODEREASON + 8; ees_event(ees, CEVNT_BADREPLY); ees_reset(ees); return; } if (cp[EESM_BST] != 0 && cp[EESM_BST] != 0x03) { ees->badformat++; ees->reason = CODEREASON + 9; ees_event(ees, CEVNT_BADREPLY); ees_reset(ees); return; } if (cp[EESM_MSFOK] != 0 && cp[EESM_MSFOK] != 0x3f) { ees->badformat++; ees->reason = CODEREASON + 10; ees_event(ees, CEVNT_BADREPLY); ees_reset(ees); return; } /* So far, so good. Compute day, hours, minutes, seconds, * time zone. Do range checks on these. */#define bcdunpack(val) ( (((val)>>4) & 0x0f) * 10 + ((val) & 0x0f) )#define istrue(x) ((x)?1:0) ees->second = bcdunpack(cp[EESM_SEC]); /* second */ ees->minute = bcdunpack(cp[EESM_MIN]); /* minute */ ees->hour = bcdunpack(cp[EESM_HOUR]); /* hour */ day = bcdunpack(cp[EESM_DAY]); /* day of month */ switch (bcdunpack(cp[EESM_MON])) { /* month */ /* Add in lengths of all previous months. Add one more if it is a leap year and after February. */ case 12: day += NOV; /*FALLSTHROUGH*/ case 11: day += OCT; /*FALLSTHROUGH*/ case 10: day += SEP; /*FALLSTHROUGH*/ case 9: day += AUG; /*FALLSTHROUGH*/ case 8: day += JUL; /*FALLSTHROUGH*/ case 7: day += JUN; /*FALLSTHROUGH*/ case 6: day += MAY; /*FALLSTHROUGH*/ case 5: day += APR; /*FALLSTHROUGH*/ case 4: day += MAR; /*FALLSTHROUGH*/ case 3: day += FEB; if (istrue(cp[EESM_LEAP])) day++; /*FALLSTHROUGH*/ case 2: day += JAN; /*FALLSTHROUGH*/ case 1: break; default: ees->baddata++; ees->reason = CODEREASON + 11; ees_event(ees, CEVNT_BADDATE); ees_reset(ees); return; } ees->day = day; /* Get timezone. The clocktime routine wants the number * of hours to add to the delivered time to get UT. * Currently -1 if BST flag set, 0 otherwise. This * is the place to tweak things if double summer time * ever happens. */ ees->tz = istrue(cp[EESM_BST]) ? -1 : 0; if (ees->day > 366 || ees->day < 1 || ees->hour > 23 || ees->minute > 59 || ees->second > 59) { ees->baddata++; ees->reason = CODEREASON + 12; ees_event(ees, CEVNT_BADDATE); ees_reset(ees); return; } n_sample = ees->nsamples; /* Now, compute the reference time value: text -> tmp.l_ui */ if (!clocktime(ees->day, ees->hour, ees->minute, ees->second, ees->tz, rbufp->recv_time.l_ui, &ees->yearstart, &tmp.l_ui)) { ees->baddata++; ees->reason = CODEREASON + 13; ees_event(ees, CEVNT_BADDATE); ees_reset(ees); return; } tmp.l_uf = 0; /* DON'T use ees->arrvtime -- it may be < reftime */ ees->lastsampletime = tmp; /* If we are synchronised to the radio, update the reference time. * Also keep a note of when clock was last good. */ if (istrue(cp[EESM_MSFOK])) { ees->reftime = tmp; ees->clocklastgood = current_time; } /* Compute the offset. For the fractional part of the * offset we use the expected delay for the message. */ ees->codeoffsets[n_sample].l_ui = tmp.l_ui; ees->codeoffsets[n_sample].l_uf = 0; /* Number of seconds since the last step */ sincelast = this_uisec - ees->last_step; memset((char *) &ppsclockev, 0, sizeof ppsclockev); rc = ioctl(ees->io.fd, request, (char *) &ppsclockev); if (debug & DB_PRINT_EV) fprintf(stderr, "[%x] CIOGETEV u%d %d (%x %d) gave %d (%d): %08lx %08lx %ld\n", DB_PRINT_EV, ees->unit, ees->io.fd, request, is_pps(ees), rc, errno, ptr[0], ptr[1], ptr[2]); /* If we managed to get the time of arrival, process the info */ if (rc >= 0) { int conv = -1; pps_step = ppsclockev.serial - ees->last_pps_no; /* Possible that PPS triggered, but text message didn't */ if (pps_step == 2) msyslog(LOG_ERR, "pps step = 2 @ %02d", ees->second); if (pps_step == 2 && ees->second == 1) suspect_4ms_step |= 1; if (pps_step == 2 && ees->second == 2) suspect_4ms_step |= 4; /* allow for single loss of PPS only */ if (pps_step != 1 && pps_step != 2) fprintf(stderr, "PPS step: %d too far off %ld (%d)\n", ppsclockev.serial, ees->last_pps_no, pps_step); else if (!buftvtots((char *) &(ppsclockev.tv), &pps_arrvstamp)) fprintf(stderr, "buftvtots failed\n"); else { /* if ((ABS(time difference) - 0.25) < 0) * then believe it ... */ l_fp diff; diff = pps_arrvstamp; conv = 0; L_SUB(&diff, &ees->arrvtime); if (debug & DB_PRINT_CDT) printf("[%x] Have %lx.%08lx and %lx.%08lx -> %lx.%08lx @ %s", DB_PRINT_CDT, (long)ees->arrvtime.l_ui, (long)ees->arrvtime.l_uf, (long)pps_arrvstamp.l_ui, (long)pps_arrvstamp.l_uf, (long)diff.l_ui, (long)diff.l_uf, ctime(&(ppsclockev.tv.tv_sec))); if (L_ISNEG(&diff)) M_NEG(diff.l_ui, diff.l_uf); L_SUB(&diff, &acceptable_slop); if (L_ISNEG(&diff)) { /* AOK -- pps_sample */ ees->arrvtime = pps_arrvstamp; conv++; call_pps_sample++; } /* Some loss of some signals around sec = 1 */ else if (ees->second == 1) { diff = pps_arrvstamp; L_ADD(&diff, &onesec); L_SUB(&diff, &ees->arrvtime); if (L_ISNEG(&diff)) M_NEG(diff.l_ui, diff.l_uf); L_SUB(&diff, &acceptable_slop); msyslog(LOG_ERR, "Have sec==1 slip %ds a=%08x-p=%08x -> %x.%08x (u=%d) %s", pps_arrvstamp.l_ui - ees->arrvtime.l_ui, pps_arrvstamp.l_uf, ees->arrvtime.l_uf, diff.l_ui, diff.l_uf, (int)ppsclockev.tv.tv_usec, ctime(&(ppsclockev.tv.tv_sec))); if (L_ISNEG(&diff)) { /* AOK -- pps_sample */ suspect_4ms_step |= 2; ees->arrvtime = pps_arrvstamp; L_ADD(&ees->arrvtime, &onesec); conv++; call_pps_sample++; } } } ees->last_pps_no = ppsclockev.serial; if (debug & DB_PRINT_CDTC) printf( "[%x] %08lx %08lx %d u%d (%d %d)\n", DB_PRINT_CDTC, (long)pps_arrvstamp.l_ui, (long)pps_arrvstamp.l_uf, conv, ees->unit, call_pps_sample, pps_step); } /* See if there has been a 4ms jump at a minute boundry */ { l_fp delta;#define delta_isec delta.l_ui#define delta_ssec delta.l_i#define delta_sfsec delta.l_f long delta_f_abs; delta.l_i = ees->arrvtime.l_i; delta.l_f = ees->arrvtime.l_f; L_SUB(&delta, &ees->last_l); delta_f_abs = delta_sfsec; if (delta_f_abs < 0) delta_f_abs = -delta_f_abs; /* Dump the deltas each minute */ if (debug & DB_DUMP_DELTAS) { if (/*0 <= ees->second && */ ees->second < ((sizeof deltas) / (sizeof deltas[0]))) deltas[ees->second] = delta_sfsec; /* Dump on second 1, as second 0 sometimes missed */ if (ees->second == 1) { char text[16 * ((sizeof deltas) / (sizeof deltas[0]))]; char *cptr=text; int i; for (i=0; i<((sizeof deltas) / (sizeof deltas[0])); i++) { sprintf(cptr, " %d.%04d", msec(deltas[i]), subms(deltas[i])); while (*cptr) cptr++; } msyslog(LOG_ERR, "Deltas: %d.%04d<->%d.%04d: %s", msec(EES_STEP_F - EES_STEP_F_GRACE), subms(EES_STEP_F - EES_STEP_F_GRACE), msec(EES_STEP_F + EES_STEP_F_GRACE), subms(EES_STEP_F + EES_STEP_F_GRACE), text+1); for (i=0; i<((sizeof deltas) / (sizeof deltas[0])); i++) deltas[i] = 0; } } /* Lets see if we have a 4 mS step at a minute boundaary */ if ( ((EES_STEP_F - EES_STEP_F_GRACE) < delta_f_abs) && (delta_f_abs < (EES_STEP_F + EES_STEP_F_GRACE)) && (ees->second == 0 || ees->second == 1 || ees->second == 2) && (sincelast < 0 || sincelast > 122) ) { /* 4ms jump at min boundry */ int old_sincelast; int count=0; int sum = 0; /* Yes -- so compute the ramp time */ if (ees->last_step == 0) sincelast = 0; old_sincelast = sincelast; /* First time in, just set "ees->last_step" */ if(ees->last_step) { int other_step = 0; int third_step = 0; int this_step = (sincelast + (60 /2)) / 60; int p_step = ees->this_step; int p; ees->last_steps[p_step] = this_step; p= p_step; p_step++; if (p_step >= LAST_STEPS) p_step = 0; ees->this_step = p_step; /* Find the "average" interval */ while (p != p_step) { int this = ees->last_steps[p]; if (this == 0) break; if (this != this_step) { if (other_step == 0 && ( this== (this_step +2) || this== (this_step -2) || this== (this_step +1) || this== (this_step -1))) other_step = this; if (other_step != this) { int idelta = (this_step - other_step); if (idelta < 0) idelta = - idelta; if (third_step == 0 && ( (idelta == 1) ? ( this == (other_step +1) || this == (other_step -1) || this == (this_step +1) || this == (this_step -1)) : ( this == (this_step + other_step)/2 ) )) third_step = this; if (third_step != this) break; } } sum += this; p--; if (p < 0) p += LAST_STEPS; count++; } msyslog(LOG_ERR, "MSF%d: %d: This=%d (%d), other=%d/%d, sum=%d, count=%d, pps_step=%d, suspect=%x", ees->unit, p, ees->last_steps[p], this_step, other_step, third_step, sum, count, pps_step, suspect_4ms_step); if (count != 0) sum = ((sum * 60) + (count /2)) / count;#define SV(x) (ees->last_steps[(x + p_step) % LAST_STEPS]) msyslog(LOG_ERR, "MSF%d: %x steps %d: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", ees->unit, suspect_4ms_step, p_step, SV(0), SV(1), SV(2), SV(3), SV(4), SV(5), SV(6), SV(7), SV(8), SV(9), SV(10), SV(11), SV(12), SV(13), SV(14), SV(15)); printf("MSF%d: steps %d: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", ees->unit, p_step, SV(0), SV(1), SV(2), SV(3), SV(4), SV(5), SV(6), SV(7), SV(8), SV(9), SV(10), SV(11), SV(12), SV(13), SV(14), SV(15));#undef SV ees->jump_fsecs = delta_sfsec; ees->using_ramp = 1; if (sincelast > 170) ees->last_step_late += sincelast - ((sum) ? sum : ees->last_step_secs); else ees->last_step_late = 30; if (ees->last_step_late < -60 || ees->last_step_late > 120) ees->last_step_late = 30; if (ees->last_step_late < 0) ees->last_step_late = 0; if (ees->last_step_late >= 60) ees->last_step_late = 59; sincelast = 0; } else { /* First time in -- just save info */ ees->last_step_late = 30; ees->jump_fsecs = delta_sfsec; ees->using_ramp = 1; sum = 4 * 60; } ees->last_step = this_uisec; printf("MSF%d: d=%3ld.%04ld@%d :%d:%d:$%d:%d:%d\n", ees->unit, (long)msec(delta_sfsec), (long)subms(delta_sfsec), ees->second, old_sincelast, ees->last_step_late, count, sum, ees->last_step_secs); msyslog(LOG_ERR, "MSF%d: d=%3d.%04d@%d :%d:%d:%d:%d:%d",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -