📄 refclock_true.c
字号:
} /* * Timecode: " TRUETIME Mk III" or " TRUETIME XL" * (from a TM/TMD/XL clock during initialization.) */ if (strcmp(pp->a_lastcode, " TRUETIME Mk III") == 0 || strncmp(pp->a_lastcode, " TRUETIME XL", 12) == 0) { true_doevent(peer, e_F18); NLOG(NLOG_CLOCKSTATUS) { msyslog(LOG_INFO, "TM/TMD/XL: %s", pp->a_lastcode); } return; } /* * Timecode: "N03726428W12209421+000033" * 1 2 * 0123456789012345678901234 * (from a TCU during initialization) */ if ((pp->a_lastcode[0] == 'N' || pp->a_lastcode[0] == 'S') && (pp->a_lastcode[9] == 'W' || pp->a_lastcode[9] == 'E') && pp->a_lastcode[18] == '+') { true_doevent(peer, e_Location); NLOG(NLOG_CLOCKSTATUS) { msyslog(LOG_INFO, "TCU-800: %s", pp->a_lastcode); } return; } /* * Timecode: "ddd:hh:mm:ssQ" * (from all clocks supported by this driver.) */ if (pp->a_lastcode[3] == ':' && pp->a_lastcode[6] == ':' && pp->a_lastcode[9] == ':' && sscanf(pp->a_lastcode, "%3d:%2d:%2d:%2d%c", &pp->day, &pp->hour, &pp->minute, &pp->second, &synced) == 5) { /* * Adjust the synchronize indicator according to timecode * say were OK, and then say not if we really are not OK */ if (synced == '>' || synced == '#' || synced == '?') pp->leap = LEAP_NOTINSYNC; else pp->leap = LEAP_NOWARNING; true_doevent(peer, e_TS);#ifdef CLOCK_PPS720 /* If it's taken more than 65ms to get here, we'll lose. */ if ((pp->sloppyclockflag & CLK_FLAG4) && up->pcl720init) { l_fp off;#ifdef CLOCK_ATOM /* * find out what time it really is. Include * the count from the PCL720 */ if (!clocktime(pp->day, pp->hour, pp->minute, pp->second, GMT, pp->lastrec.l_ui, &pp->yearstart, &off.l_ui)) { refclock_report(peer, CEVNT_BADTIME); return; } off.l_uf = 0;#endif pp->usec = true_sample720();#ifdef CLOCK_ATOM TVUTOTSF(pp->usec, off.l_uf);#endif /* * Stomp all over the timestamp that was pulled out * of the input stream. It's irrelevant since we've * adjusted the input time to reflect now (via pp->usec) * rather than when the data was collected. */ get_systime(&pp->lastrec);#ifdef CLOCK_ATOM /* * Create a true offset for feeding to pps_sample() */ L_SUB(&off, &pp->lastrec); pps_sample(peer, &off);#endif true_debug(peer, "true_sample720: %luus\n", pp->usec); }#endif /* * The clock will blurt a timecode every second but we only * want one when polled. If we havn't been polled, bail out. */ if (!up->polled) return; true_doevent(peer, e_Poll); if (!refclock_process(pp)) { refclock_report(peer, CEVNT_BADTIME); return; } /* * If clock is good we send a NOMINAL message so that * any previous BAD messages are nullified */ pp->lastref = pp->lastrec; refclock_receive(peer); refclock_report(peer, CEVNT_NOMINAL); /* * We have succedded in answering the poll. * Turn off the flag and return */ up->polled = 0; return; } /* * No match to known timecodes, report failure and return */ refclock_report(peer, CEVNT_BADREPLY); return;}/* * true_send - time to send the clock a signal to cough up a time sample */static voidtrue_send( struct peer *peer, const char *cmd ){ struct refclockproc *pp; pp = peer->procptr; if (!(pp->sloppyclockflag & CLK_FLAG1)) { register int len = strlen(cmd); true_debug(peer, "Send '%s'\n", cmd); if (write(pp->io.fd, cmd, (unsigned)len) != len) refclock_report(peer, CEVNT_FAULT); else pp->polls++; }}/* * state machine for initializing and controlling a clock */static voidtrue_doevent( struct peer *peer, enum true_event event ){ struct true_unit *up; struct refclockproc *pp; pp = peer->procptr; up = (struct true_unit *)pp->unitptr; if (event != e_TS) { NLOG(NLOG_CLOCKSTATUS) { msyslog(LOG_INFO, "TRUE: clock %s, state %s, event %s", typeStr(up->type), stateStr(up->state), eventStr(event)); } } true_debug(peer, "clock %s, state %s, event %s\n", typeStr(up->type), stateStr(up->state), eventStr(event)); switch (up->type) { case t_goes: switch (event) { case e_Init: /* FALLTHROUGH */ case e_Satellite: /* * Switch back to on-second time codes and return. */ true_send(peer, "C"); up->state = s_Start; break; case e_Poll: /* * After each poll, check the station (satellite). */ true_send(peer, "P"); /* No state change needed. */ break; default: break; } /* FALLTHROUGH */ case t_omega: switch (event) { case e_Init: true_send(peer, "C"); up->state = s_Start; break; case e_TS: if (up->state != s_Start && up->state != s_Auto) { true_send(peer, "\03\r"); break; } up->state = s_Auto; break; default: break; } break; case t_tm: switch (event) { case e_Init: true_send(peer, "F18\r"); up->state = s_Init; break; case e_F18: true_send(peer, "F50\r"); up->state = s_F18; break; case e_F50: true_send(peer, "F51\r"); up->state = s_F50; break; case e_F51: true_send(peer, "F08\r"); up->state = s_Start; break; case e_TS: if (up->state != s_Start && up->state != s_Auto) { true_send(peer, "\03\r"); break; } up->state = s_Auto; break; default: break; } break; case t_tcu: switch (event) { case e_Init: true_send(peer, "MD3\r"); /* GPS Synch'd Gen. */ true_send(peer, "TSU\r"); /* UTC, not GPS. */ true_send(peer, "AU\r"); /* Auto Timestamps. */ up->state = s_Start; break; case e_TS: if (up->state != s_Start && up->state != s_Auto) { true_send(peer, "\03\r"); break; } up->state = s_Auto; break; default: break; } break; case t_unknown: switch (up->state) { case s_Base: if (event != e_Init) abort(); true_send(peer, "P\r"); up->state = s_InqGOES; break; case s_InqGOES: switch (event) { case e_Satellite: up->type = t_goes; true_doevent(peer, e_Init); break; case e_Init: /*FALLTHROUGH*/ case e_Huh: /*FALLTHROUGH*/ case e_TS: up->state = s_InqOmega; true_send(peer, "C\r"); break; default: abort(); } break; case s_InqOmega: switch (event) { case e_TS: up->type = t_omega; up->state = s_Auto; /* Inq side-effect. */ break; case e_Init: /*FALLTHROUGH*/ case e_Huh: up->state = s_InqTM; true_send(peer, "F18\r"); break; default: abort(); } break; case s_InqTM: switch (event) { case e_F18: up->type = t_tm; true_doevent(peer, e_Init); break; case e_Init: /*FALLTHROUGH*/ case e_Huh: true_send(peer, "PO\r"); up->state = s_InqTCU; break; default: abort(); } break; case s_InqTCU: switch (event) { case e_Location: up->type = t_tcu; true_doevent(peer, e_Init); break; case e_Init: /*FALLTHROUGH*/ case e_Huh: up->state = s_Base; sleep(1); /* XXX */ break; default: abort(); } break; /* * An expedient hack to prevent lint complaints, * these don't actually need to be used here... */ case s_Init: case s_F18: case s_F50: case s_Start: case s_Auto: case s_Max: msyslog(LOG_INFO, "TRUE: state %s is unexpected!", stateStr(up->state)); } break; default: abort(); /* NOTREACHED */ }#ifdef CLOCK_PPS720 if ((pp->sloppyclockflag & CLK_FLAG4) && !up->pcl720init) { /* Make counter trigger on gate0, count down from 65535. */ pcl720_load(PCL720_IOB, PCL720_CTR, i8253_oneshot, 65535); /* * (These constants are OK since * they represent hardware maximums.) */ NLOG(NLOG_CLOCKINFO) { msyslog(LOG_NOTICE, "PCL-720 initialized"); } up->pcl720init++; }#endif}/* * true_poll - called by the transmit procedure */static voidtrue_poll( int unit, struct peer *peer ){ struct true_unit *up; struct refclockproc *pp; /* * You don't need to poll this clock. It puts out timecodes * once per second. If asked for a timestamp, take note. * The next time a timecode comes in, it will be fed back. */ pp = peer->procptr; up = (struct true_unit *)pp->unitptr; if (up->pollcnt > 0) up->pollcnt--; else { true_doevent(peer, e_Init); refclock_report(peer, CEVNT_TIMEOUT); } /* * polled every 64 seconds. Ask true_receive to hand in a * timestamp. */ up->polled = 1; pp->polls++;}#ifdef CLOCK_PPS720/* * true_sample720 - sample the PCL-720 */static u_longtrue_sample720(void){ unsigned long f; /* We wire the PCL-720's 8253.OUT0 to bit 0 of connector 3. * If it is not being held low now, we did not get called * within 65535us. */ if (inb(pcl720_data_16_23(PCL720_IOB)) & 0x01) { NLOG(NLOG_CLOCKINFO) { msyslog(LOG_NOTICE, "PCL-720 out of synch"); } return (0); } f = (65536 - pcl720_read(PCL720_IOB, PCL720_CTR));#ifdef PPS720_DEBUG msyslog(LOG_DEBUG, "PCL-720: %luus", f);#endif return (f);}#endif#elseint refclock_true_bs;#endif /* REFCLOCK */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -