예제 #1
0
파일: arith.c 프로젝트: chjohnst/ptpd
/* greater than operation */
int gtTime(TimeInternal *x, TimeInternal *y)
{
	TimeInternal r;

	subTime(&r, x, y);
	return !isTimeInternalNegative(&r);
}
예제 #2
0
파일: arith.c 프로젝트: wowczarek/ptpd
/* greater than operation */
int
gtTime(const TimeInternal *x, const TimeInternal *y)
{
	TimeInternal r;

	subTime(&r, x, y);
	return !isTimeNegative(&r);
}
예제 #3
0
void
QSS_PAR_initialize (SIM_simulator simulate)
{
  QSS_simulator simulator = (QSS_simulator) simulate->state->sim;
  QSS_PAR_allocRootSimulatorData (simulator);
  getTime (simulator->iTime);
  PRT_partition partition = PRT_Partition (simulator->data,
					   simulator->output->name);
  getTime (simulator->sdTime);
  subTime (simulator->sdTime, simulator->iTime);
  simulator->stats->partitioningTime = getTimeValue (simulator->sdTime);
  getTime (simulator->iTime);
  LP_initializeDataStructs (simulator, partition);
  getTime (simulator->sdTime);
  subTime (simulator->sdTime, simulator->iTime);
  PRT_freePartition (partition);
  QSS_PAR_logMemory (simulator);
  simulator->stats->initializeLPS = getTimeValue (simulator->sdTime);
}
예제 #4
0
파일: arith.c 프로젝트: wowczarek/ptpd
void timeDelta(TimeInternal *before, TimeInternal *meas, TimeInternal *after, TimeInternal *delta)
{

	TimeInternal tmpDelta;

	div2Time(before);
	div2Time(after);
	addTime(&tmpDelta, before, after);
	subTime(delta, &tmpDelta, meas);

}
예제 #5
0
파일: rt_tmon.c 프로젝트: Strongc/proview
static void
waitTime (
  pwr_tTime		*t
)
{
  pwr_tStatus		sts;
  pwr_tTime		now;
  pwr_tTime		then = *t;
  char tims[24];
  short len;
  struct dsc$descriptor_s tims_desc = {
    sizeof(tims)-1, DSC$K_DTYPE_T, DSC$K_CLASS_S,};

#if 0
  subTime(&then, nowTime(&now));
#endif

  if ((int)then.tv_sec > 0 || ((int)then.tv_sec == 0 && then.tv_nsec > 0)) {
#if defined OS_VMS || defined OS_ELN
    int			tv_nsec;
    int			vmstime[2];
    int			multiplier = -10000000;	      /* Used to convert 1 s to 100 ns, delta time.  */
    static pwr_tTime	tick = {0, 10000000};

    addTime(&then, &tick);
    tv_nsec = -then.tv_nsec/100;   /* Convert to 100 ns.  */
    sts = lib$emul(&then.tv_sec, &multiplier, &tv_nsec, vmstime);

#if defined OS_VMS
    tims_desc.dsc$a_pointer = tims;
    sys$asctim( &len, &tims_desc, vmstime, 0);
    tims[len] = '\0';
    printf("  %s\n", tims);
#if 0
    sts = sys$clref(timerFlag);
    sts = sys$setimr(timerFlag, vmstime, 0, 0, 0);
    sts = sys$waitfr(timerFlag);
#endif
#elif defined OS_ELN
    eln$time_string(tims, vmstime);
    tims[23] = '\0';
    printf("  %s\n", tims);
#if 0
    ker$wait_any(&sts, NULL, vmstime);
#endif
#endif

#elif defined OS_LYNX
    pwr_tTime rmt;

    nanosleep(&then, &rmt);
#endif
  }
}
예제 #6
0
void KTimeEdit::keyPressEvent(QKeyEvent *qke)
{
    switch(qke->key())
    {
        case Key_Down:
            addTime(QTime(0, 1, 0));
            break;
        case Key_Up:
            subTime(QTime(0, 1, 0));
            break;
        case Key_Prior:
            subTime(QTime(1, 0, 0));
            break;
        case Key_Next:
            addTime(QTime(1, 0, 0));
            break;
        default:
            QComboBox::keyPressEvent(qke);
            break;
    } // switch
}
예제 #7
0
void
QSS_PAR_saveLog (QSS_simulator simulator)
{
  int outputs = simulator->data->lp->outputs;
  if (outputs)
    {
      getTime (simulator->sTime);
      OUT_save (simulator->log);
      getTime (simulator->sdTime);
      subTime (simulator->sdTime, simulator->sTime);
      simulator->saveTime = getTimeValue (simulator->sdTime);
    }
}
예제 #8
0
파일: arith.c 프로젝트: chjohnst/ptpd
/* if 2 time values are close enough for X nanoseconds */
int is_Time_close(TimeInternal *x, TimeInternal *y, int nanos)
{
	TimeInternal r1;
	TimeInternal r2;

	// first, subtract the 2 values. then call abs(), then call gtTime for requested the number of nanoseconds
	subTime(&r1, x, y);
	absTime(&r1);

	nano_to_Time(&r2, nanos);
	
	return !gtTime(&r1, &r2);
}
예제 #9
0
inline
void
SimulatedBlock::EXECUTE_DIRECT(Uint32 block, 
			       Uint32 gsn, 
			       Signal* signal, 
			       Uint32 len){
  signal->setLength(len);
#ifdef VM_TRACE
  if(globalData.testOn){
    signal->header.theVerId_signalNumber = gsn;
    signal->header.theReceiversBlockNumber = block;
    signal->header.theSendersBlockRef = reference();
    globalSignalLoggers.executeDirect(signal->header,
				      0,        // in
				      &signal->theData[0],
                                      globalData.ownId);
  }
#endif
  SimulatedBlock* b = globalData.getBlock(block);
#ifdef VM_TRACE_TIME
  Uint32 us1, us2;
  Uint64 ms1, ms2;
  NdbTick_CurrentMicrosecond(&ms1, &us1);
  Uint32 tGsn = m_currentGsn;
  b->m_currentGsn = gsn;
#endif
  b->executeFunction(gsn, signal);
#ifdef VM_TRACE_TIME
  NdbTick_CurrentMicrosecond(&ms2, &us2);
  Uint64 diff = ms2;
  diff -= ms1;
  diff *= 1000000;
  diff += us2;
  diff -= us1;
  b->addTime(gsn, diff);
  m_currentGsn = tGsn;
  subTime(tGsn, diff);
#endif
#ifdef VM_TRACE
  if(globalData.testOn){
    signal->header.theVerId_signalNumber = gsn;
    signal->header.theReceiversBlockNumber = block;
    signal->header.theSendersBlockRef = reference();
    globalSignalLoggers.executeDirect(signal->header,
				      1,        // out
				      &signal->theData[0],
                                      globalData.ownId);
  }
#endif
}
void safeToProcess(const Event* const thisEvent, Time* safeTimestamp) {
    Time tempTime;
        if (thisEvent->offsetTime.secs < 0 || (thisEvent->offsetTime.secs == 0
                        && thisEvent->offsetTime.nsecs < 0)) {
                tempTime.secs = (uint32) (-thisEvent->offsetTime.secs);
                tempTime.nsecs = (uint32) (-thisEvent->offsetTime.nsecs);
                addTime(thisEvent->tag.timestamp, tempTime, safeTimestamp);
        } else {
                int16 out;
                tempTime.secs = (uint32) (thisEvent->offsetTime.secs);
                tempTime.nsecs = (uint32) (thisEvent->offsetTime.nsecs);
                out = subTime(thisEvent->tag.timestamp, tempTime, safeTimestamp);
                if (out == -1) {
                        safeTimestamp->secs = 0;
                        safeTimestamp->nsecs = 0;
                }
        }
}
예제 #11
0
파일: servo.c 프로젝트: DomChey/ptpd
void
updatePeerDelay(Filter * owd_filt, RunTimeOpts * rtOpts, PtpClock * ptpClock, TimeInternal * correctionField, Boolean twoStep)
{
	/* updates paused, leap second pending - do nothing */
	if(ptpClock->leapSecondInProgress)
		return;


	DBGV("updatePeerDelay\n");

	ptpClock->char_last_msg = 'P';	

	if (twoStep) {
		/* calc 'slave_to_master_delay' */
		subTime(&ptpClock->pdelayMS, 
			&ptpClock->pdelay_resp_receive_time, 
			&ptpClock->pdelay_resp_send_time);
		subTime(&ptpClock->pdelaySM, 
			&ptpClock->pdelay_req_receive_time, 
			&ptpClock->pdelay_req_send_time);

		/* update 'one_way_delay' */
		addTime(&ptpClock->peerMeanPathDelay, 
			&ptpClock->pdelayMS, 
			&ptpClock->pdelaySM);

		/* Substract correctionField */
		subTime(&ptpClock->peerMeanPathDelay, 
			&ptpClock->peerMeanPathDelay, correctionField);

		/* Compute one-way delay */
		div2Time(&ptpClock->peerMeanPathDelay);
	} else {
		/* One step clock */

		subTime(&ptpClock->peerMeanPathDelay, 
			&ptpClock->pdelay_resp_receive_time, 
			&ptpClock->pdelay_req_send_time);

		/* Substract correctionField */
		subTime(&ptpClock->peerMeanPathDelay, 
			&ptpClock->peerMeanPathDelay, correctionField);

		/* Compute one-way delay */
		div2Time(&ptpClock->peerMeanPathDelay);
	}

	if (ptpClock->peerMeanPathDelay.seconds) {
		/* cannot filter with secs, clear filter */
		FilterClear(owd_filt);
		return;
	}

	{
		// TODO: remove hack
		char s_text[32];
		sprintf(s_text, "%d", rtOpts->s);
		FilterConfigure(owd_filt, "stiffness", s_text);
	}
	FilterFeed(owd_filt, &ptpClock->peerMeanPathDelay.nanoseconds);

	DBGV("delay filter %d\n", ptpClock->peerMeanPathDelay.nanoseconds);

//display:
	if(ptpClock->portState == PTP_SLAVE)
		logStatistics(rtOpts, ptpClock);	
}
예제 #12
0
void
QSS_SEQ_initialize (SIM_simulator simulate)
{
  QSS_simulator simulator = (QSS_simulator) simulate->state->sim;
  getTime (simulator->iTime);
  int i, j, k, s, forUL;
  double e, zc[4];
  simulator->frw = FRW_Framework (simulator->data);
  double t = simulator->time->time;
  char logFile[128];
  strcpy (logFile, simulator->output->name);
  simulator->simulationLog = SD_SimulationLog (logFile);
  // Local mappings.
  QSS_data qssData = simulator->data;
  QSS_time qssTime = simulator->time;
  FRW_framework frw = simulator->frw;
  double *q = qssData->q;
  double *x = qssData->x;
  const int order = qssData->order;
  const int coeffs = order + 1;
#ifdef DEBUG
  SD_simulationSettings settings = simulator->settings;
  SD_simulationLog simulationLog = simulator->simulationLog;
#endif
  QSS_model qssModel = simulator->model;
  QA_quantizer quantizer;
  SD_output output = simulator->output;
#ifdef DEBUG
  if (settings->debug & SD_DBG_InitValues)
    {
      SD_print (simulationLog, "Initialize simulation\n");
    }
#endif
  forUL = qssData->states;
  for (i = 0; i < forUL; i++)
    {
      qssData->lqu[i] = qssData->dQRel[i] * fabs (x[i * coeffs]);
      if (qssData->lqu[i] < qssData->dQMin[i])
	{
	  qssData->lqu[i] = qssData->dQMin[i];
	}
#ifdef DEBUG
      if (settings->debug & SD_DBG_InitValues)
	{
	  SD_print (simulationLog, "Initial value: x[%d][0] = %g", i, x[i * coeffs]);
	}
#endif
    }
#ifdef DEBUG
  if (settings->debug & SD_DBG_InitValues)
    {
      SD_print (simulationLog, "Initialize solver...");
    }
#endif
  simulator->quantizer = QA_Quantizer (qssData, qssTime);
  quantizer = simulator->quantizer;
#ifdef DEBUG
  if (settings->debug & SD_DBG_InitValues)
    {
      SD_print (simulationLog, "done.");
      SD_print (simulationLog, "Initialize state derivatives...");
    }
#endif
  forUL = qssData->states;
  for (i = 0; i < forUL; i++)
    {
      FRW_recomputeDerivative (frw, qssModel, qssData, qssTime, i);
			QA_nextTime (quantizer,i,t,qssTime->nextStateTime,x,qssData->lqu);
#ifdef DEBUG
      if (settings->debug & SD_DBG_InitValues)
	{
	  SD_print (simulationLog, "Initial derivative: x[%d][1] = %g", i,
	      x[i * coeffs + 1]);
	}
#endif
    }
#ifdef DEBUG
  if (settings->debug & SD_DBG_InitValues)
    {
      SD_print (simulationLog, "done.");
      SD_print (simulationLog, "Initialize input...");
    }
#endif
  forUL = qssData->inputs;
  for (i = 0; i < forUL; i++)
    {
      j = qssData->TD[i];
      FRW_nextInputTime (frw, qssModel, qssData, qssTime, 0, j, i);
    }
#ifdef DEBUG
  if (settings->debug & SD_DBG_InitValues)
    {
      SD_print (simulationLog, "done.");
      SD_print (simulationLog, "Initialize events...");
    }
#endif
  forUL = qssData->events;
  for (i = 0; i < forUL; i++)
    {
      if (qssData->nZS[i])
	{
	  int nZS = qssData->nZS[i];
	  e = INF;
	  for (j = 0; j < nZS; j++)
	    {
	      k = qssData->ZS[i][j];
	      if (qssData->dQMin[k] < e)
		{
		  e = qssData->dQMin[k];
		}
	    }
	}
      else
	{
	  e = qssData->ft * qssData->params->zcHyst;
	}
      qssModel->events->zeroCrossing (i, q, qssData->d, qssData->alg,
				      qssTime->time, zc);
      s = sign (zc[0]);
      qssData->event[i].zcSign = s;
      qssData->event[i].zcHyst = e / 10.0;
      if (qssData->event[i].direction == 0 || qssData->event[i].direction == s
	  || zc[0] == 0)
	{
	  if (zc[0] == 0 && qssData->event[i].relation == 3)
	    {
	      qssModel->events->handlerPos (i, q, qssData->d, qssData->alg, t);
	    }
	  else if (zc[0] == 0 && qssData->event[i].relation == 1)
	    {
	      qssModel->events->handlerNeg (i, q, qssData->d, qssData->alg, t);
	    }
	  else if (s >= 0)
	    {
	      qssModel->events->handlerPos (i, q, qssData->d, qssData->alg, t);
	    }
	  else
	    {
	      qssModel->events->handlerNeg (i, q, qssData->d, qssData->alg, t);
	    }
	  qssModel->events->zeroCrossing (i, q, qssData->d, qssData->alg, t,
					  zc);
	  qssData->event[i].zcSign = sign (zc[0]);
	  int nHZ = qssData->nHZ[i];
	  for (k = 0; k < nHZ; k++)
	    {
	      j = qssData->HZ[i][k];
	      FRW_nextEventTime (frw, qssModel, qssData, qssTime, j);
	    }
	  int nHD = qssData->nHD[i];
	  for (k = 0; k < nHD; k++)
	    {
	      j = qssData->HD[i][k];
	      e = t - qssTime->tx[j];
	      if (e > 0)
		{
		  int cf0 = j * coeffs;
		  x[cf0] = evaluatePoly (cf0, e, x, order);
		}
	      qssTime->tx[j] = t;
	      FRW_recomputeDerivative (frw, qssModel, qssData, qssTime, j);
	    }
	  if (nHD)
	    {
	      QA_recomputeNextTimes (quantizer, nHD, qssData->HD[i], t,
				     qssTime->nextStateTime, x, qssData->lqu,
				     q);
	    }
	}
      FRW_nextEventTime (frw, qssModel, qssData, qssTime, i);
    }
#ifdef DEBUG
  if (settings->debug & SD_DBG_InitValues)
    {
      SD_print (simulationLog, "done.");
      SD_print (simulationLog, "Initialize state variables time...");
    }
#endif
  forUL = qssData->states;
  for (i = 0; i < forUL; i++)
    {
      QA_recomputeNextTime (quantizer, i, qssTime->time, qssTime->nextStateTime,
			    x, qssData->lqu, q);
    }
#ifdef DEBUG
  if (settings->debug & SD_DBG_InitValues)
    {
      SD_print (simulationLog, "done.");
      SD_print (simulationLog, "Initialize output...");
    }
#endif
  simulator->log = OUT_Output (qssData, qssTime, output);
#ifdef DEBUG
  if (settings->debug & SD_DBG_InitValues)
    {
      SD_print (simulationLog, "done.");
      SD_print (simulationLog, "Initialize time...");
    }
#endif
  simulator->scheduler = SC_Scheduler (qssData, qssTime);
#ifdef DEBUG
  if (settings->debug & SD_DBG_InitValues)
    {
      SD_print (simulationLog, "done.");
    }
  if (settings->debug & SD_DBG_VarChanges)
    {
      SD_setSimulationLogVariables(simulationLog, qssData->states, qssData->events);
    }
#endif
  QSS_SEQ_logMemory (simulator);
  getTime (simulator->sTime);
  subTime (simulator->sTime, simulator->iTime);
  simulator->initTime += getTimeValue (simulator->sTime);
}
예제 #13
0
/* check and handle received messages */
void
handle(RunTimeOpts *rtOpts, PtpClock *ptpClock)
{
	int ret;
	ssize_t length;
	Boolean isFromSelf;
	TimeInternal time = { 0, 0 };

	if (!ptpClock->message_activity) {
		ret = netSelect(0, &ptpClock->netPath);
		if (ret < 0) {
			PERROR("failed to poll sockets");
			toState(PTP_FAULTY, rtOpts, ptpClock);
			return;
		} else if (!ret) {
			/* DBGV("handle: nothing\n"); */
			return;
		}
		/* else length > 0 */
	}

	DBGV("handle: something\n");

	/* TODO: this should be based on the select actual FDs (if(FD_ISSET(...)) */
	length = netRecvEvent(ptpClock->msgIbuf, &time, &ptpClock->netPath);


	if (length < 0) {
		PERROR("failed to receive on the event socket");
		toState(PTP_FAULTY, rtOpts, ptpClock);
		return;
	} else if (!length) {
		length = netRecvGeneral(ptpClock->msgIbuf, &time,
					&ptpClock->netPath);
		if (length < 0) {
			PERROR("failed to receive on the general socket");
			toState(PTP_FAULTY, rtOpts, ptpClock);
			return;
		} else if (!length)
			return;
	}

	/*
	 * make sure we use the TAI to UTC offset specified, if the master is sending the UTC_VALID bit
	 *
	 *
	 * On the slave, all timestamps that we handle here have been collected by our local clock (loopback+kernel-level timestamp)
	 * This includes delayReq just send, and delayResp, when it arrives.
	 *
	 * these are then adjusted to the same timebase of the Master (+34 leap seconds, as of 2011)
	 *
	 */
	DBGV("__UTC_offset: %d %d \n", ptpClock->currentUtcOffsetValid, ptpClock->currentUtcOffset);
	if (ptpClock->currentUtcOffsetValid) {
		time.seconds += ptpClock->currentUtcOffset;
	}

	ptpClock->message_activity = TRUE;

	if (length < HEADER_LENGTH) {
		ERROR("message shorter than header length\n");
		toState(PTP_FAULTY, rtOpts, ptpClock);
		return;
	}

	msgUnpackHeader(ptpClock->msgIbuf, &ptpClock->msgTmpHeader);

	if (ptpClock->msgTmpHeader.versionPTP != ptpClock->versionNumber) {
		DBG2("ignore version %d message\n", ptpClock->msgTmpHeader.versionPTP);
		return;
	}

	if(ptpClock->msgTmpHeader.domainNumber != ptpClock->domainNumber) {
		DBG2("ignore message from domainNumber %d\n", ptpClock->msgTmpHeader.domainNumber);
		return;
	}

	/*Spec 9.5.2.2*/	
	isFromSelf = (ptpClock->portIdentity.portNumber == ptpClock->msgTmpHeader.sourcePortIdentity.portNumber
		      && !memcmp(ptpClock->msgTmpHeader.sourcePortIdentity.clockIdentity, ptpClock->portIdentity.clockIdentity, CLOCK_IDENTITY_LENGTH));

	/*
	 * subtract the inbound latency adjustment if it is not a loop
	 *  back and the time stamp seems reasonable 
	 */
	if (!isFromSelf && time.seconds > 0)
		subTime(&time, &time, &rtOpts->inboundLatency);


#ifdef PTPD_DBG
	/* easy display of received messages */
	char *st;

	switch(ptpClock->msgTmpHeader.messageType)
	{
	case ANNOUNCE:
		st = "Announce";
		break;
	case SYNC:
		st = "Sync";
		break;
	case FOLLOW_UP:
		st = "FollowUp";
		break;
	case DELAY_REQ:
		st = "DelayReq";
		break;
	case DELAY_RESP:
		st = "DelayResp";
		break;
	default:
		st = "Unk";
		break;
	}
	DBG("      ==> %s received\n", st);
#endif

	/*
	 *  on the table below, note that only the event messsages are passed the local time,
	 *  (collected by us by loopback+kernel TS, and adjusted with UTC seconds
	 *
	 *  (SYNC / DELAY_REQ / PDELAY_REQ / PDELAY_RESP)
	 */
	switch (ptpClock->msgTmpHeader.messageType)
	{
	case ANNOUNCE:
		handleAnnounce(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, 
			       length, isFromSelf, rtOpts, ptpClock);
		break;
	case SYNC:
		handleSync(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, 
			   length, &time, isFromSelf, rtOpts, ptpClock);
		break;
	case FOLLOW_UP:
		handleFollowUp(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, 
			       length, isFromSelf, rtOpts, ptpClock);
		break;
	case DELAY_REQ:
		handleDelayReq(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, 
			       length, &time, isFromSelf, rtOpts, ptpClock);
		break;
	case PDELAY_REQ:
		handlePDelayReq(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, 
				length, &time, isFromSelf, rtOpts, ptpClock);
		break;  
	case DELAY_RESP:
		handleDelayResp(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, 
				length, isFromSelf, rtOpts, ptpClock);
		break;
	case PDELAY_RESP:
		handlePDelayResp(&ptpClock->msgTmpHeader, ptpClock->msgIbuf,
				 &time, length, isFromSelf, rtOpts, ptpClock);
		break;
	case PDELAY_RESP_FOLLOW_UP:
		handlePDelayRespFollowUp(&ptpClock->msgTmpHeader, 
					 ptpClock->msgIbuf, length, 
					 isFromSelf, rtOpts, ptpClock);
		break;
	case MANAGEMENT:
		handleManagement(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, 
				 length, isFromSelf, rtOpts, ptpClock);
		break;
	case SIGNALING:
		handleSignaling(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, 
				length, isFromSelf, rtOpts, ptpClock);
		break;
	default:
		DBG("handle: unrecognized message\n");
		break;
	}

	if (rtOpts->displayPackets)
		msgDump(ptpClock);

}
예제 #14
0
파일: piservo.c 프로젝트: lukebigum/ptpd
static double
feed (PIservo* self, Integer32 input, double tau) {

    TimeInternal now, delta;

    Boolean runningMaxOutput;

    self->input = input;

    switch(self->tauMethod) {
	case DT_MEASURED:
	    getSystemClock()->getTimeMonotonic(getSystemClock(), &now);
	    if(isTimeZero(&self->lastUpdate)) {
		self->tau = 1.0;
	    } else {
		subTime(&delta, &now, &self->lastUpdate);
		self->tau = delta.seconds + delta.nanoseconds / 1E9;
	    }

            if(self->tau > (self->maxTau * tau)) {
                self->tau = (self->maxTau + 0.0) * tau;
	    }
	    break;

	case DT_CONSTANT:
	    self->tau = tau;
	break;

	default:
	    self->tau = 1.0;
    }

    if(self->tau <= ZEROF) {
	self->tau = 1.0;
    }

    self->integral = clampDouble(self->integral, self->maxOutput);
    self->output = clampDouble(self->output, self->maxOutput);

    if (self->kP < 0.000001)
	    self->kP = 0.000001;
    if (self->kI < 0.000001)
	    self->kI = 0.000001;

    self->integral += (self->tau / self->delayFactor) * ((input + 0.0 ) * self->kI);
    self->output = (self->kP * (input + 0.0) ) + self->integral;

    self->integral = clampDouble(self->integral, self->maxOutput);
    self->output = clampDouble(self->output, self->maxOutput);

    runningMaxOutput = (fabs(self->output) >= self->maxOutput);

    if(self->controller) {
	DBG("%s tau %.09f input %d fabs %f out %f, mo %f\n", self->controller->name, self->tau, input, fabs(self->output), self->output, self->maxOutput);
    }

    if(runningMaxOutput && !self->runningMaxOutput) {
	    WARNING(THIS_COMPONENT"Clock %s servo now running at maximum output\n", self->controller->name);
    }

    self->runningMaxOutput = runningMaxOutput;

    if(self->tauMethod == DT_MEASURED) {
	self->lastUpdate = now;
    }

    self->_updated = TRUE;
    self->_lastInput = self->input;
    self->_lastOutput = self->output;

    return self->output;

}
예제 #15
0
/* check and handle received messages */
void handle(PtpClock *ptpClock)
{
  int ret;
  ssize_t length;
  Boolean isFromSelf;
  Boolean isEvent;
  Boolean badTime = FALSE;
  TimeInternal time = { 0, 0 };
  
  if(!ptpClock->message_activity)
  {
    ret = netSelect(0, ptpClock);
    if(ret < 0)
    {
      PERROR("failed to poll sockets");
      toState(PTP_FAULTY, ptpClock);
      return;
    }
    else if(!ret)
    {
      DBGV("handle: nothing\n");
      return;
    }
    /* else length > 0 */
  }
  
  DBGV("handle: something\n");

  isEvent = TRUE;
  length = netRecvEvent(ptpClock->msgIbuf,
                        ptpClock->delayedTiming ? NULL : &time,
                        ptpClock);
  if(length < 0)
  {
    PERROR("failed to receive on the event socket");
    toState(PTP_FAULTY, ptpClock);
    return;
  }
  else if(!length)
  {
    isEvent = FALSE;
    length = netRecvGeneral(ptpClock->msgIbuf, ptpClock);
    if(length < 0)
    {
      PERROR("failed to receive on the general socket");
      toState(PTP_FAULTY, ptpClock);
      return;
    }
    else if(!length)
      return;
  }
  
  ptpClock->message_activity = TRUE;
  
  if(!msgPeek(ptpClock->msgIbuf, length))
    return;
  
  if(length < HEADER_LENGTH)
  {
    ERROR("message shorter than header length\n");
    toState(PTP_FAULTY, ptpClock);
    return;
  }
  
  msgUnpackHeader(ptpClock->msgIbuf, &ptpClock->msgTmpHeader);

  if(isEvent && ptpClock->delayedTiming)
  {
    /* query hardware for matching receive time stamp */
    if(!getReceiveTime(&time, ptpClock->msgTmpHeader.sourceUuid, ptpClock->msgTmpHeader.sequenceId, ptpClock))
    {
      /*
       * Incoming packets without hardware time stamp cannot be ignored outright because
       * a master might only be able to time stamp DelayReq packets; ignoring the Sync
       * packets from another, better clock would break the clock selection protocol.
       * Therefore set system time as fallback and decide below what to do.
       */
      DBGV("*** message with no time stamp ***\n");
      getTime(&time, ptpClock);
      badTime = TRUE;
    }
  }
  
  DBGV("%s Receipt of Message\n"
    "   version %d\n"
    "   type %d\n"
    "   uuid %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n"
    "   sequence %d\n"
    "   time %us %dns\n",
    isEvent ? "event" : "control",
    ptpClock->msgTmpHeader.versionPTP,
    ptpClock->msgTmpHeader.control,
    ptpClock->msgTmpHeader.sourceUuid[0], ptpClock->msgTmpHeader.sourceUuid[1],
    ptpClock->msgTmpHeader.sourceUuid[2], ptpClock->msgTmpHeader.sourceUuid[3],
    ptpClock->msgTmpHeader.sourceUuid[4], ptpClock->msgTmpHeader.sourceUuid[5],
    ptpClock->msgTmpHeader.sequenceId,
    time.seconds, time.nanoseconds);
  
  if(ptpClock->msgTmpHeader.versionPTP != VERSION_PTP)
  {
    DBGV("ignore version %d message\n", ptpClock->msgTmpHeader.versionPTP);
    return;
  }
  
  if( memcmp(ptpClock->msgTmpHeader.subdomain, ptpClock->subdomain_name,
    PTP_SUBDOMAIN_NAME_LENGTH) )
  {
    DBGV("ignore message from subdomain %s\n", ptpClock->msgTmpHeader.subdomain);
    return;
  }
  
  isFromSelf = ptpClock->msgTmpHeader.sourceCommunicationTechnology == ptpClock->port_communication_technology
    && ptpClock->msgTmpHeader.sourcePortId == ptpClock->port_id_field
    && !memcmp(ptpClock->msgTmpHeader.sourceUuid, ptpClock->port_uuid_field, PTP_UUID_LENGTH);
  
  /* subtract the inbound latency adjustment if it is not a loop back and the
     time stamp seems reasonable */
  if(!isFromSelf && time.seconds > 0)
    subTime(&time, &time, &ptpClock->runTimeOpts.inboundLatency);
  
  switch(ptpClock->msgTmpHeader.control)
  {
  case PTP_SYNC_MESSAGE:
    handleSync(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, &time, badTime, isFromSelf, ptpClock);
    break;
    
  case PTP_FOLLOWUP_MESSAGE:
    handleFollowUp(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, isFromSelf, ptpClock);
    break;
    
  case PTP_DELAY_REQ_MESSAGE:
    handleDelayReq(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, &time, badTime, isFromSelf, ptpClock);
    break;
    
  case PTP_DELAY_RESP_MESSAGE:
    handleDelayResp(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, isFromSelf, ptpClock);
    break;
    
  case PTP_MANAGEMENT_MESSAGE:
    handleManagement(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, isFromSelf, ptpClock);
    break;
    
   default:
    DBG("handle: unrecognized message\n");
    break;
  }
}
예제 #16
0
/* check and handle received messages */
void handle(RunTimeOpts *rtOpts, PtpClock *ptpClock)
{
  int ret;
  ssize_t length;
  Boolean isFromSelf;
  TimeInternal time = { 0, 0 };
  TimeInternal now =  { 0, 0 };

  if(!ptpClock->message_activity)
  {
    ret = netSelect(0, &ptpClock->netPath);
    if(ret < 0)
    {
      PERROR("failed to poll sockets");
      toState(PTP_FAULTY, rtOpts, ptpClock);
      return;
    }
    else if(!ret)
    {
#if 0
      DBGV("handle: nothing\n");
#endif
      return;
    }
    /* else length > 0 */
  }

  DBGV("handle: something\n");

  length = netRecvEvent(ptpClock->msgIbuf, &time, &ptpClock->netPath);
  getTime(&now);
  DBG("Time is %ds %dns\n", now.seconds, now.nanoseconds);
  if(length < 0)
  {
    PERROR("failed to receive on the event socket");
    toState(PTP_FAULTY, rtOpts, ptpClock);
    return;
  }
  else if(!length)
  {
    length = netRecvGeneral(ptpClock->msgIbuf, &ptpClock->netPath);
    if(length < 0)
    {
      PERROR("failed to receive on the general socket");
      toState(PTP_FAULTY, rtOpts, ptpClock);
      return;
    }
    else if(!length)
      return;
  }

  ptpClock->message_activity = TRUE;

  if(!msgPeek(ptpClock->msgIbuf, length))
    return;

  if(length < HEADER_LENGTH)
  {
    ERROR("message shorter than header length\n");
    toState(PTP_FAULTY, rtOpts, ptpClock);
    return;
  }

  msgUnpackHeader(ptpClock->msgIbuf, &ptpClock->msgTmpHeader);

  DBG("event Receipt of Message\n   type %d\n"
    "   uuid %02x:%02x:%02x:%02x:%02x:%02x\n"
    "   sequence %d\n   time %us %dns\n",
    ptpClock->msgTmpHeader.control,
    ptpClock->msgTmpHeader.sourceUuid[0], ptpClock->msgTmpHeader.sourceUuid[1], ptpClock->msgTmpHeader.sourceUuid[2],
    ptpClock->msgTmpHeader.sourceUuid[3], ptpClock->msgTmpHeader.sourceUuid[4], ptpClock->msgTmpHeader.sourceUuid[5],
    ptpClock->msgTmpHeader.sequenceId,
    time.seconds, time.nanoseconds);

  isFromSelf = ptpClock->msgTmpHeader.sourceCommunicationTechnology == ptpClock->port_communication_technology
    && ptpClock->msgTmpHeader.sourcePortId == ptpClock->port_id_field
    && !memcmp(ptpClock->msgTmpHeader.sourceUuid, ptpClock->port_uuid_field, PTP_UUID_LENGTH);

  /* subtract the inbound latency adjustment if it is not a loop back and the
     time stamp seems reasonable */
  if(!isFromSelf && time.seconds > 0)
    subTime(&time, &time, &rtOpts->inboundLatency);

  switch(ptpClock->msgTmpHeader.control)
  {
  case PTP_SYNC_MESSAGE:
    handleSync(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, &time, isFromSelf, rtOpts, ptpClock);
    break;

  case PTP_FOLLOWUP_MESSAGE:
    handleFollowUp(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, isFromSelf, rtOpts, ptpClock);
    break;

  case PTP_DELAY_REQ_MESSAGE:
    handleDelayReq(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, &time, isFromSelf, rtOpts, ptpClock);
    break;

  case PTP_DELAY_RESP_MESSAGE:
    handleDelayResp(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, isFromSelf, rtOpts, ptpClock);
    break;

  case PTP_MANAGEMENT_MESSAGE:
    handleManagement(&ptpClock->msgTmpHeader, ptpClock->msgIbuf, length, isFromSelf, rtOpts, ptpClock);
    break;

   default:
    DBG("handle: unrecognized message\n");
    break;
  }
}
예제 #17
0
/* check and handle received messages */
static void handle(PtpClock *ptpClock)
{

    int ret;
    Boolean isFromSelf;
    TimeInternal time = { 0, 0 };

    if (FALSE == ptpClock->messageActivity)
    {
        ret = netSelect(&ptpClock->netPath, 0);

        if (ret < 0)
        {
            ERROR("handle: failed to poll sockets\n");
            toState(ptpClock, PTP_FAULTY);
            return;
        }
        else if (!ret)
        {
            DBGVV("handle: nothing\n");
            return;
        }
    }

    DBGVV("handle: something\n");
		//msgUnpackHeader(ptpClock->msgIbuf, &ptpClock->msgTmpHeader);//**********************************************/
    ptpClock->msgIbufLength = netRecvEvent(&ptpClock->netPath, ptpClock->msgIbuf, &time);
	/* local time is not UTC, we can calculate UTC on demand, otherwise UTC time is not used */
    /* time.seconds += ptpClock->timePropertiesDS.currentUtcOffset; */


    if (ptpClock->msgIbufLength < 0)
    {
        ERROR("handle: failed to receive on the event socket\n");
        toState(ptpClock, PTP_FAULTY);
        return;
    }
    else if (!ptpClock->msgIbufLength)
    {
        ptpClock->msgIbufLength = netRecvGeneral(&ptpClock->netPath, ptpClock->msgIbuf, &time);

        if (ptpClock->msgIbufLength < 0)
        {
            ERROR("handle: failed to receive on the general socket\n");
            toState(ptpClock, PTP_FAULTY);
            return;
        }
        else if (!ptpClock->msgIbufLength)
            return;
    }

    ptpClock->messageActivity = TRUE;

    if (ptpClock->msgIbufLength < HEADER_LENGTH)
    {
        ERROR("handle: message shorter than header length\n");
        toState(ptpClock, PTP_FAULTY);
        return;
    }

    msgUnpackHeader(ptpClock->msgIbuf, &ptpClock->msgTmpHeader);


    if (ptpClock->msgTmpHeader.versionPTP != ptpClock->portDS.versionNumber)
    {
        DBGV("handle: ignore version %d message\n", ptpClock->msgTmpHeader.versionPTP);
        return;
    }

    if (ptpClock->msgTmpHeader.domainNumber != ptpClock->defaultDS.domainNumber)
    {
        DBGV("handle: ignore message from domainNumber %d\n", ptpClock->msgTmpHeader.domainNumber);
        return;
    }

    /*Spec 9.5.2.2*/
    isFromSelf = isSamePortIdentity(
		&ptpClock->portDS.portIdentity,
		&ptpClock->msgTmpHeader.sourcePortIdentity);

    /* subtract the inbound latency adjustment if it is not a loop back and the
       time stamp seems reasonable */
    if (!isFromSelf && time.seconds > 0)
        subTime(&time, &time, &ptpClock->inboundLatency);

    switch (ptpClock->msgTmpHeader.messageType)
    {

    case ANNOUNCE:
        handleAnnounce(ptpClock, isFromSelf);
        break;

    case SYNC:
        handleSync(ptpClock, &time, isFromSelf);
        break;

    case FOLLOW_UP:
        handleFollowUp(ptpClock, isFromSelf);
        break;

    case DELAY_REQ:
        handleDelayReq(ptpClock, &time, isFromSelf);
        break;

    case PDELAY_REQ:
        handlePDelayReq(ptpClock, &time, isFromSelf);
        break;

    case DELAY_RESP:
        handleDelayResp(ptpClock, isFromSelf);
        break;

    case PDELAY_RESP:
        handlePDelayResp(ptpClock, &time, isFromSelf);
        break;

    case PDELAY_RESP_FOLLOW_UP:
        handlePDelayRespFollowUp(ptpClock, isFromSelf);
        break;

    case MANAGEMENT:
        handleManagement(ptpClock, isFromSelf);
        break;

    case SIGNALING:
        handleSignaling(ptpClock, isFromSelf);
        break;

    default:
        DBG("handle: unrecognized message %d\n", ptpClock->msgTmpHeader.messageType);
        break;
    }
}
예제 #18
0
파일: servo.c 프로젝트: da-phil/ptpd
void
updateDelay(one_way_delay_filter * owd_filt, const RunTimeOpts * rtOpts, PtpClock * ptpClock, TimeInternal * correctionField)
{

	/* updates paused, leap second pending - do nothing */
	if(ptpClock->leapSecondInProgress)
		return;

	DBGV("updateDelay\n");

	/* todo: do all intermediate calculations on temp vars */
	TimeInternal prev_meanPathDelay = ptpClock->meanPathDelay;

	ptpClock->char_last_msg = 'D';

	Boolean maxDelayHit = FALSE;

	{

#ifdef PTPD_STATISTICS
		/* if maxDelayStableOnly configured, only check once servo is stable */
		Boolean checkThreshold = rtOpts-> maxDelayStableOnly ?
		    (ptpClock->servo.isStable && rtOpts->maxDelay) :
		    (rtOpts->maxDelay);
#else
		Boolean checkThreshold = rtOpts->maxDelay;
#endif
		//perform basic checks, using local variables only
		TimeInternal slave_to_master_delay;


		/* calc 'slave_to_master_delay' */
		subTime(&slave_to_master_delay, &ptpClock->delay_req_receive_time,
			&ptpClock->delay_req_send_time);

		if (checkThreshold && /* If maxDelay is 0 then it's OFF */
		    ptpClock->offsetFirstUpdated) {

			if ((slave_to_master_delay.nanoseconds < 0) &&
			    (abs(slave_to_master_delay.nanoseconds) > rtOpts->maxDelay)) {
				INFO("updateDelay aborted, "
				     "delay (sec: %d ns: %d) is negative\n",
				     slave_to_master_delay.seconds,
				     slave_to_master_delay.nanoseconds);
				INFO("send (sec: %d ns: %d)\n",
				     ptpClock->delay_req_send_time.seconds,
				     ptpClock->delay_req_send_time.nanoseconds);
				INFO("recv (sec: %d n	s: %d)\n",
				     ptpClock->delay_req_receive_time.seconds,
				     ptpClock->delay_req_receive_time.nanoseconds);
				goto finish;
			}

			if (slave_to_master_delay.seconds && checkThreshold) {
				INFO("updateDelay aborted, slave to master delay %d.%d greater than 1 second\n",
				     slave_to_master_delay.seconds,
				     slave_to_master_delay.nanoseconds);
				if (rtOpts->displayPackets)
					msgDump(ptpClock);
				goto finish;
			}

			if (slave_to_master_delay.nanoseconds > rtOpts->maxDelay) {
				ptpClock->counters.maxDelayDrops++;
				DBG("updateDelay aborted, slave to master delay %d greater than "
				     "administratively set maximum %d\n",
				     slave_to_master_delay.nanoseconds, 
				     rtOpts->maxDelay);
				if(rtOpts->maxDelayMaxRejected) {
                                    maxDelayHit = TRUE;
				    /* if we blocked maxDelayMaxRejected samples, reset the slave to unblock the filter */
				    if(++ptpClock->maxDelayRejected > rtOpts->maxDelayMaxRejected) {
					    WARNING("%d consecutive measurements above %d threshold - resetting slave\n",
							rtOpts->maxDelayMaxRejected, slave_to_master_delay.nanoseconds);
					    toState(PTP_LISTENING, rtOpts, ptpClock);
				    }
				}

				if (rtOpts->displayPackets)
					msgDump(ptpClock);
				goto finish;
			} else {
				ptpClock->maxDelayRejected=0;
			}
		}
	}

	/*
	 * The packet has passed basic checks, so we'll:
	 *   - update the global delaySM variable
	 *   - calculate a new filtered MPD
	 */
	if (ptpClock->offsetFirstUpdated) {
		Integer16 s;

		/*
		 * calc 'slave_to_master_delay' (Master to Slave delay is
		 * already computed in updateOffset )
		 */

		DBG("==> UpdateDelay():   %s\n",
			dump_TimeInternal2("Req_RECV:", &ptpClock->delay_req_receive_time,
			"Req_SENT:", &ptpClock->delay_req_send_time));

	/* raw value before filtering */
	subTime(&ptpClock->rawDelaySM, &ptpClock->delay_req_receive_time,
		&ptpClock->delay_req_send_time);

#ifdef PTPD_STATISTICS

/* testing only: step detection */
#if 0
	TimeInternal bob;
	bob.nanoseconds = -1000000;
	bob.seconds = 0;
	if(ptpClock->addOffset) {
	    	addTime(&ptpClock->rawDelaySM, &ptpClock->rawDelaySM, &bob);
	}
#endif

	/* run the delayMS stats filter */
	if(rtOpts->filterSMOpts.enabled) {
	    if(!feedDoubleMovingStatFilter(ptpClock->filterSM, timeInternalToDouble(&ptpClock->rawDelaySM))) {
		    return;
	    }
	    ptpClock->rawDelaySM = doubleToTimeInternal(ptpClock->filterSM->output);
	}

	/* run the delaySM outlier filter */
	if(!rtOpts->noAdjust && ptpClock->oFilterSM.config.enabled && (ptpClock->oFilterSM.config.alwaysFilter || !ptpClock->servo.runningMaxOutput) ) {
		if(ptpClock->oFilterSM.filter(&ptpClock->oFilterSM, timeInternalToDouble(&ptpClock->rawDelaySM))) {
			ptpClock->delaySM = doubleToTimeInternal(ptpClock->oFilterSM.output);
		} else {
			ptpClock->counters.delaySMOutliersFound++;
			/* If the outlier filter has blocked the sample, "reverse" the last maxDelay action */
			if (maxDelayHit) {
				    ptpClock->maxDelayRejected--;
			}
			goto finish;
		}
	} else {
		ptpClock->delaySM = ptpClock->rawDelaySM;
	}



#else
		subTime(&ptpClock->delaySM, &ptpClock->delay_req_receive_time, 
			&ptpClock->delay_req_send_time);
#endif

		/* update MeanPathDelay */
		addTime(&ptpClock->meanPathDelay, &ptpClock->delaySM, 
			&ptpClock->delayMS);

		/* Subtract correctionField */
		subTime(&ptpClock->meanPathDelay, &ptpClock->meanPathDelay, 
			correctionField);

		/* Compute one-way delay */
		div2Time(&ptpClock->meanPathDelay);
		
		if (ptpClock->meanPathDelay.seconds) {
			DBG("update delay: cannot filter with large OFM, "
				"clearing filter\n");
			INFO("Servo: Ignoring delayResp because of large OFM\n");
			
			owd_filt->s_exp = owd_filt->nsec_prev = 0;
			/* revert back to previous value */
			ptpClock->meanPathDelay = prev_meanPathDelay;
			goto finish;
		}

		if(ptpClock->meanPathDelay.nanoseconds < 0){
			DBG("update delay: found negative value for OWD, "
			    "so ignoring this value: %d\n",
				ptpClock->meanPathDelay.nanoseconds);
			/* revert back to previous value */
			ptpClock->meanPathDelay = prev_meanPathDelay;
			goto finish;
		}

		/* avoid overflowing filter */
		s = rtOpts->s;
		while (abs(owd_filt->y) >> (31 - s))
			--s;

		/* crank down filter cutoff by increasing 's_exp' */
		if (owd_filt->s_exp < 1)
			owd_filt->s_exp = 1;
		else if (owd_filt->s_exp < 1 << s)
			++owd_filt->s_exp;
		else if (owd_filt->s_exp > 1 << s)
			owd_filt->s_exp = 1 << s;

		/* filter 'meanPathDelay' */
		double fy =
			(double)((owd_filt->s_exp - 1.0) *
			owd_filt->y / (owd_filt->s_exp + 0.0) +
			(ptpClock->meanPathDelay.nanoseconds / 2.0 + 
			 owd_filt->nsec_prev / 2.0) / (owd_filt->s_exp + 0.0));

		owd_filt->nsec_prev = ptpClock->meanPathDelay.nanoseconds;

		owd_filt->y = round(fy);

		ptpClock->meanPathDelay.nanoseconds = owd_filt->y;

		DBGV("delay filter %d, %d\n", owd_filt->y, owd_filt->s_exp);
	} else {
예제 #19
0
파일: servo.c 프로젝트: artasoftkey/ptpv2d
void updateClock(RunTimeOpts *rtOpts, PtpClock *ptpClock)
{
  Integer32    adj=0;
  TimeInternal timeTmpA;  // AKB: Added values for adjusting calc based on time to get time
  TimeInternal timeTmpB;
  TimeInternal timeTmpC;
  TimeInternal timeTmpD;
  TimeInternal timeTmpE;
  TimeInternal timeTmpF;
  Integer64    delta_time_calc;
  
  DBGV("updateClock:\n");
  
  if(ptpClock->offset_from_master.seconds)
  {
    /* if offset from master seconds is non-zero, then this is a "big jump:
     * in time.  Check Run Time options to see if we will reset the clock or 
     * set frequency adjustment to max to adjust the time
     */
    if(!rtOpts->noAdjust)
    {
      if(!rtOpts->noResetClock)
      {

        if (!isNonZeroTime(&ptpClock->t1_sync_delta_time))
        {
           // Delta time is zero, so this is the first sync to capture and we'll do the major
           // adjustment on the next sync instead of this one
           //
           // Store t1 and t2 times as current delta, next time we'll subtract
           //
           copyTime(&ptpClock->t1_sync_delta_time,
                    &ptpClock->t1_sync_tx_time
                   );
           copyTime(&ptpClock->t2_sync_delta_time,
                    &ptpClock->t2_sync_rx_time
                   );
           NOTIFY("updateClock: Storing current T1 and T2 values for later calc\n");
           DBG("updateClock: Storing T1: %10ds %11dns\n",
               ptpClock->t1_sync_delta_time.seconds,
               ptpClock->t1_sync_delta_time.nanoseconds
              );
           DBG("updateClock: Storing T2: %10ds %11dns\n",
               ptpClock->t2_sync_delta_time.seconds,
               ptpClock->t2_sync_delta_time.nanoseconds
              );
           return;
        }

        // If we are here then t1 and t2 sync delta were set to previous t1 and t2
        // values.  Now we calculate the deltas

           DBG("updateClock: Current T1: %10ds %11dns\n",
               ptpClock->t1_sync_tx_time.seconds,
               ptpClock->t1_sync_tx_time.nanoseconds
              );
           DBG("updateClock: Current T2: %10ds %11dns\n",
               ptpClock->t2_sync_rx_time.seconds,
               ptpClock->t2_sync_rx_time.nanoseconds
              );

        subTime(&ptpClock->t1_sync_delta_time,
                &ptpClock->t1_sync_tx_time,
                &ptpClock->t1_sync_delta_time
               ); 
        subTime(&ptpClock->t2_sync_delta_time,
                &ptpClock->t2_sync_rx_time,
                &ptpClock->t2_sync_delta_time
               );

           DBG("updateClock: Delta   T1: %10ds %11dns\n",
               ptpClock->t1_sync_delta_time.seconds,
               ptpClock->t1_sync_delta_time.nanoseconds
              );
           DBG("updateClock: Delta   T2: %10ds %11dns\n",
               ptpClock->t2_sync_delta_time.seconds,
               ptpClock->t2_sync_delta_time.nanoseconds
              ); 
       
        // Now we get the difference between the two time bases and store in the T2 time delta
        // as we will use the T1 time as the divisor (so master clock drives the time)

        subTime(&ptpClock->t2_sync_delta_time,
                &ptpClock->t2_sync_delta_time,
                &ptpClock->t1_sync_delta_time
               );

           DBG("updateClock: Delta T2 - Delta T1: %10ds %11dns\n",
               ptpClock->t2_sync_delta_time.seconds,
               ptpClock->t2_sync_delta_time.nanoseconds
              );  

        delta_time_calc =  getNanoseconds(&ptpClock->t2_sync_delta_time)
                           * 1000000000;
        delta_time_calc /= getNanoseconds(&ptpClock->t1_sync_delta_time);

           DBG("updateClock: Calculated Parts/billion: %d\n",
               (int)delta_time_calc
              );  


        /* clamp the accumulator to ADJ_FREQ_MAX for sanity */
        if(     delta_time_calc > ADJ_FREQ_MAX)
          adj =  ADJ_FREQ_MAX;
        else if(delta_time_calc < -ADJ_FREQ_MAX)
          adj = -ADJ_FREQ_MAX;
        else
          adj = (UInteger32)delta_time_calc;

        NOTIFY("updateClock: Initial clock adjust: %d, base: %d\n",
                adj, 
                ptpClock->baseAdjustValue
              );

        NOTIFY("updateClock: Offset from Master %ds.%9.9d seconds\n", 
                ptpClock->offset_from_master.seconds,
                ptpClock->offset_from_master.nanoseconds
              );
        DBG( "updateClock: offset_from_master seconds != 0\n");
        DBGV("  master-to-slave delay:   %10ds %11dns\n",
             ptpClock->master_to_slave_delay.seconds,
             ptpClock->master_to_slave_delay.nanoseconds
            );
        DBGV("  slave-to-master delay:   %10ds %11dns\n",
             ptpClock->slave_to_master_delay.seconds,
             ptpClock->slave_to_master_delay.nanoseconds
            );
        DBGV("  one-way delay:           %10ds %11dns\n",
             ptpClock->one_way_delay.seconds,
             ptpClock->one_way_delay.nanoseconds
            );
        DBG( "  offset from master:      %10ds %11dns\n",
             ptpClock->offset_from_master.seconds, 
             ptpClock->offset_from_master.nanoseconds
           );
        DBG( "  observed drift:          %10d\n", 
            ptpClock->observed_drift
           );

        getTime(&timeTmpA, ptpClock->current_utc_offset);   // Get current time #1

        getTime(&timeTmpB, ptpClock->current_utc_offset);   // Get current time #2

        subTime(&timeTmpC,    // Calculate time   #3, time elapsed between calls
                &timeTmpB,
                &timeTmpA
               );

        getTime(&timeTmpD, ptpClock->current_utc_offset);   // Get current time #4

        subTime(&timeTmpE,    // Subtract calculated offset from master
                &timeTmpD,
                &ptpClock->offset_from_master
               );

        addTime(&timeTmpF,    // Add calculated time to get timer value
                &timeTmpE,
                &timeTmpC
               );

        setTime(&timeTmpF, ptpClock->current_utc_offset);   // Set new PTP time

        DBGV(" get  Time A           :   %10ds %11dns\n",
             timeTmpA.seconds,
             timeTmpA.nanoseconds
            );
        DBGV(" get  Time B           :   %10ds %11dns\n",
             timeTmpB.seconds,
             timeTmpB.nanoseconds
            );
        DBGV(" calc Time C (B-A)     :   %10ds %11dns\n",
             timeTmpC.seconds,
             timeTmpC.nanoseconds
            );
        DBGV(" get  Time D           :   %10ds %11dns\n",
             timeTmpD.seconds,
             timeTmpD.nanoseconds
            );
        DBGV(" offset from master    :   %10ds %11dns\n",
             ptpClock->offset_from_master.seconds,
             ptpClock->offset_from_master.nanoseconds
            );
        DBGV(" calc Time E (D+offset):   %10ds %11dns\n",
             timeTmpE.seconds,
             timeTmpE.nanoseconds
            );
        DBGV(" calc Time F (E+C)     :   %10ds %11dns\n",
             timeTmpF.seconds,
             timeTmpF.nanoseconds
            );
        DBGV("updateClock: set time to Time F\n");

        // Initialize clock variables based on run time options (rtOpts)

        initClockVars(rtOpts, ptpClock);

        // Adjust clock based on calculation from Delta T1, T2 times

        adjFreq(ptpClock->baseAdjustValue - adj);

        // Set initial observed drift to this calculated value

        ptpClock->observed_drift = adj;

        DBG( "updateClock: after initClock:\n");
        DBGV("  master-to-slave delay:   %10ds %11dns\n",
             ptpClock->master_to_slave_delay.seconds,
             ptpClock->master_to_slave_delay.nanoseconds
            );
        DBGV("  slave-to-master delay:   %10ds %11dns\n",
             ptpClock->slave_to_master_delay.seconds,
             ptpClock->slave_to_master_delay.nanoseconds
            );
        DBG( "  one-way delay:           %10ds %11dns\n",
             ptpClock->one_way_delay.seconds,
             ptpClock->one_way_delay.nanoseconds
           );
        DBG( "  offset from master:      %10ds %11dns\n",
             ptpClock->offset_from_master.seconds,
             ptpClock->offset_from_master.nanoseconds
           );
        DBG( "  observed drift:          %10d\n",
             ptpClock->observed_drift
           );

      }
      else
      {
        /* Run time options indicate we can't reset the clock, so we slow
         * it down or speed it up based on ADJ_FREQ_MAX adjustment rather
         * than actually setting the time.
         */
        adj = ptpClock->offset_from_master.nanoseconds > 0 ? ADJ_FREQ_MAX : -ADJ_FREQ_MAX;
        adjFreq(ptpClock->baseAdjustValue - adj);
      }
    }
  }
  else
  {
    /* Offset from master is less than one second.  Use the the PI controller
     * to adjust the time 
     */

    DBGV("updateClock: using PI controller to update clock\n");

    /* no negative or zero attenuation */
    if(rtOpts->ap < 1)
     rtOpts->ap = 1;
    if(rtOpts->ai < 1)
      rtOpts->ai = 1;

    DBGV("  previous observed drift: %10d\n",
         ptpClock->observed_drift
        );
    DBGV("  run time opts P:         %10d\n",
         rtOpts->ap
        );
    DBGV("  run time opts I:         %10d\n",
         rtOpts->ai
        );
    
    DBGV("  current observed drift:  %d\n",
         ptpClock->observed_drift
        );


    DBGV("  current offset           %dns\n",
         rtOpts->ai
        );

    /* the accumulator for the I component */
    ptpClock->observed_drift += ptpClock->offset_from_master.nanoseconds/rtOpts->ai;
    
    DBGV("  new observed drift (I):  %d\n",
         ptpClock->observed_drift
        );

    /* clamp the accumulator to ADJ_FREQ_MAX for sanity */
    if(     ptpClock->observed_drift > ADJ_FREQ_MAX)
      ptpClock->observed_drift =  ADJ_FREQ_MAX;
    else if(ptpClock->observed_drift < -ADJ_FREQ_MAX)
      ptpClock->observed_drift = -ADJ_FREQ_MAX;

    DBGV("  clamped drift:           %d\n",
         ptpClock->observed_drift
        );
    
    adj = ptpClock->offset_from_master.nanoseconds/rtOpts->ap + ptpClock->observed_drift;

    DBGV("  calculated adjust:       %d\n",
         adj
        );
    
    DBGV("  base adjust:             %d\n",
         ptpClock->baseAdjustValue
        );

    /* apply controller output as a clock tick rate adjustment */
    if(!rtOpts->noAdjust)
    {
      DBGV("  calling adjFreq with:    %d\n",
           (ptpClock->baseAdjustValue-adj)
          );

      adjFreq(ptpClock->baseAdjustValue - adj);
      if (rtOpts->rememberAdjustValue == TRUE)
      {
         if (   ptpClock->offset_from_master.nanoseconds <= 100
             && ptpClock->offset_from_master.nanoseconds >= -100
            )
         {
           ptpClock->lastAdjustValue = -adj;  // Store value if it gave a good clock
                                              // result.
         }
      }
    }
  }
  
  /* Display statistics (save to a file if -f specified) if run time option enabled */
  if(rtOpts->displayStats)
    displayStats(rtOpts, ptpClock);
  
  DBGV("  offset from master:      %10ds %11dns\n",
       ptpClock->offset_from_master.seconds,
       ptpClock->offset_from_master.nanoseconds
      );
  DBGV("  master-to-slave delay:   %10ds %11dns\n",
       ptpClock->master_to_slave_delay.seconds,
       ptpClock->master_to_slave_delay.nanoseconds
      );
  DBGV("  slave-to-master delay:   %10ds %11dns\n",
       ptpClock->slave_to_master_delay.seconds,
       ptpClock->slave_to_master_delay.nanoseconds
      );
  DBGV("  one-way delay:           %10ds %11dns\n",
       ptpClock->one_way_delay.seconds,
       ptpClock->one_way_delay.nanoseconds
      );
  DBGV( "  current observed drift:  %10d\n",
       ptpClock->observed_drift
      );
  DBGV("  clock adjust value:      %10d\n",
       (ptpClock->baseAdjustValue - adj)
      );
}
예제 #20
0
파일: servo.c 프로젝트: artasoftkey/ptpv2d
void updateDelay(TimeInternal *         send_time, // Delay Req. sent by slave time
                 TimeInternal *         recv_time, // Delay Req. received by master time
                 one_way_delay_filter * owd_filt,  // one way delay filter
                 RunTimeOpts *          rtOpts,    // run time options
                 PtpClock *             ptpClock   // PTP main data structure
                )
{
  Integer16 s;
  
  DBGV("updateDelay:\n");
  
  /* calc 'slave_to_master_delay' */
  subTime(&ptpClock->slave_to_master_delay, // Result
          recv_time,                        // Send time
          send_time                         // minus Receive time
         );

  /* Correction for V2 Delay Resp (variable is zero if V1) */

  subTime(&ptpClock->slave_to_master_delay,
          &ptpClock->slave_to_master_delay,
          &ptpClock->delay_resp_correction
         );
  
  /* update 'one_way_delay' */
  addTime(&ptpClock->one_way_delay,         // Result (divided by 2 later)
          &ptpClock->master_to_slave_delay, // Master to slave delay (from sync/follow-up)
          &ptpClock->slave_to_master_delay  // Slave to master delay (from delay request/response)
         );

  halveTime(&ptpClock->one_way_delay);      // Divide by 2 to get one way delay
                                            // Assumes delay is symetrical
  
  if(ptpClock->one_way_delay.seconds)       // Check if delay is larger than one second
  {

    /* Delay is larger than one second, clear s_exp and timestamp
     * of previously received sent time of Sync message (usually from 
     * preciseOriginTimestamp of follow up message) and return
     */
    DBG("updateDelay: One way delay seconds != 0\n");
    DBG("updateDelay: Clearing one way delay filter s_exp, nsec_prev\n");
    owd_filt->s_exp = owd_filt->nsec_prev = 0;
    return;
  }
  
  /* avoid overflowing filter */
  s =  rtOpts->s;
  while(abs(owd_filt->y)>>(31-s))
    --s;

  DBGV("updateDelay: rtOpts->s: %d, s:%d\n", 
       rtOpts->s,
       s
      );
  DBGV("updateDelay: current owd_filt->y: %d, s_exp: %d\n", 
       owd_filt->y,
       owd_filt->s_exp
      );  

  /* crank down filter cutoff by increasing 's_exp' */
  if(owd_filt->s_exp < 1)
    owd_filt->s_exp = 1;
  else if(owd_filt->s_exp < 1<<s)
    ++owd_filt->s_exp;
  else if(owd_filt->s_exp > 1<<s)
    owd_filt->s_exp = 1<<s;
  
  /* filter 'one_way_delay' */
  owd_filt->y = (owd_filt->s_exp-1)
                *owd_filt->y/owd_filt->s_exp 
              + (ptpClock->one_way_delay.nanoseconds/2 
                 + owd_filt->nsec_prev/2
                ) 
                /owd_filt->s_exp;

  /* Record previous one way delay nanosecond value
   * and update it with value calculated above
   */  
  owd_filt->nsec_prev = ptpClock->one_way_delay.nanoseconds;
  ptpClock->one_way_delay.nanoseconds = owd_filt->y;
  
  DBGV("updateDelay: delay filter y:%d, s_exp:%d\n",
       owd_filt->y,
       owd_filt->s_exp
      );
}
예제 #21
0
파일: servo.c 프로젝트: DomChey/ptpd
void
updateDelay(Filter * owd_filt, RunTimeOpts * rtOpts, PtpClock * ptpClock, TimeInternal * correctionField)
{

	/* updates paused, leap second pending - do nothing */
	if(ptpClock->leapSecondInProgress)
		return;

	DBGV("updateDelay\n");



	/* todo: do all intermediate calculations on temp vars */
	TimeInternal prev_meanPathDelay = ptpClock->meanPathDelay;

	ptpClock->char_last_msg = 'D';

	{
		//perform basic checks, using local variables only
		TimeInternal slave_to_master_delay;
	
		/* calc 'slave_to_master_delay' */
		subTime(&slave_to_master_delay, &ptpClock->delay_req_receive_time,
			&ptpClock->delay_req_send_time);

		if (rtOpts->maxDelay && /* If maxDelay is 0 then it's OFF */
		    rtOpts->offset_first_updated) {

			if ((slave_to_master_delay.nanoseconds < 0) &&
			    (abs(slave_to_master_delay.nanoseconds) > rtOpts->maxDelay)) {
				INFO("updateDelay aborted, "
				     "delay (sec: %d ns: %d) is negative\n",
				     slave_to_master_delay.seconds,
				     slave_to_master_delay.nanoseconds);
				INFO("send (sec: %d ns: %d)\n",
				     ptpClock->delay_req_send_time.seconds,
				     ptpClock->delay_req_send_time.nanoseconds);
				INFO("recv (sec: %d n	s: %d)\n",
				     ptpClock->delay_req_receive_time.seconds,
				     ptpClock->delay_req_receive_time.nanoseconds);
				goto display;
			}

			if (slave_to_master_delay.seconds && rtOpts->maxDelay) {
				INFO("updateDelay aborted, delay %d.%d greater than 1 second\n",
				     slave_to_master_delay.seconds,
				     slave_to_master_delay.nanoseconds);
				if (rtOpts->displayPackets)
					msgDump(ptpClock);
				goto display;
			}

			if (slave_to_master_delay.nanoseconds > rtOpts->maxDelay) {
				INFO("updateDelay aborted, delay %d greater than "
				     "administratively set maximum %d\n",
				     slave_to_master_delay.nanoseconds, 
				     rtOpts->maxDelay);
				if (rtOpts->displayPackets)
					msgDump(ptpClock);
				goto display;
			}
		}
	}

	/*
	 * The packet has passed basic checks, so we'll:
	 *   - update the global delaySM variable
	 *   - calculate a new filtered MPD
	 */
	if (rtOpts->offset_first_updated) {
		/*
		 * calc 'slave_to_master_delay' (Master to Slave delay is
		 * already computed in updateOffset )
		 */

		DBG("==> UpdateDelay():   %s\n",
			dump_TimeInternal2("Req_RECV:", &ptpClock->delay_req_receive_time,
			"Req_SENT:", &ptpClock->delay_req_send_time));
		
#ifdef PTPD_STATISTICS
	if (rtOpts->delaySMOutlierFilterEnabled) {
		subTime(&ptpClock->rawDelaySM, &ptpClock->delay_req_receive_time, 
			&ptpClock->delay_req_send_time);
		if(!isDoublePeircesOutlier(ptpClock->delaySMRawStats, timeInternalToDouble(&ptpClock->rawDelaySM), rtOpts->delaySMOutlierFilterThreshold)) {
			ptpClock->delaySM = ptpClock->rawDelaySM;
			ptpClock->delaySMoutlier = FALSE;
		} else {
			ptpClock->delaySMoutlier = TRUE;
			ptpClock->counters.delaySMOutliersFound++;
			if (!rtOpts->delaySMOutlierFilterDiscard)  {
				ptpClock->delaySM = doubleToTimeInternal(ptpClock->delaySMFiltered->mean);
			} else {
				    goto statistics;
			}
		}
	} else {
		subTime(&ptpClock->delaySM, &ptpClock->delay_req_receive_time, 
			&ptpClock->delay_req_send_time);
	}
#else
		subTime(&ptpClock->delaySM, &ptpClock->delay_req_receive_time, 
			&ptpClock->delay_req_send_time);
#endif
		/* update 'one_way_delay' */
		addTime(&ptpClock->meanPathDelay, &ptpClock->delaySM, 
			&ptpClock->delayMS);

		/* Substract correctionField */
		subTime(&ptpClock->meanPathDelay, &ptpClock->meanPathDelay, 
			correctionField);

		/* Compute one-way delay */
		div2Time(&ptpClock->meanPathDelay);
		
		if (ptpClock->meanPathDelay.seconds) {
			DBG("update delay: cannot filter with large OFM, "
				"clearing filter\n");
			INFO("Servo: Ignoring delayResp because of large OFM\n");
			
			FilterClear(owd_filt);
			/* revert back to previous value */
			ptpClock->meanPathDelay = prev_meanPathDelay;

			goto display;
		}


		if(ptpClock->meanPathDelay.nanoseconds < 0){
			DBG("update delay: found negative value for OWD, "
			    "so ignoring this value: %d\n",
				ptpClock->meanPathDelay.nanoseconds);
			/* revert back to previous value */
			ptpClock->meanPathDelay = prev_meanPathDelay;
#ifdef PTPD_STATISTICS
			goto statistics;
#else
			goto display;
#endif /* PTPD_STATISTICS */
		}

		{
			// TODO: remove hack
			char s_text[32];
			sprintf(s_text, "%d", rtOpts->s);
			FilterConfigure(owd_filt, "stiffness", s_text);
		}
		FilterFeed(owd_filt, &ptpClock->meanPathDelay.nanoseconds);

/* Update relevant statistics containers, feed outlier filter thresholds etc. */
#ifdef PTPD_STATISTICS
statistics:
                        if (rtOpts->delaySMOutlierFilterEnabled) {
                            double dDelaySM = timeInternalToDouble(&ptpClock->rawDelaySM);
                            /* If this is an outlier, bring it by a factor closer to mean before allowing to influence stdDev */
                            if(ptpClock->delaySMoutlier) {
				/* Allow [weight] * [deviation from mean] to influence std dev in the next outlier checks */
                            DBG("DelaySM outlier: %.09f\n", dDelaySM);
			    if((rtOpts->calibrationDelay<1) || ptpClock->isCalibrated)
                            dDelaySM = ptpClock->delaySMRawStats->meanContainer->mean + rtOpts->delaySMOutlierWeight * ( dDelaySM - ptpClock->delaySMRawStats->meanContainer->mean);
                            } 
                                        feedDoubleMovingStdDev(ptpClock->delaySMRawStats, dDelaySM);
                                        feedDoubleMovingMean(ptpClock->delaySMFiltered, timeInternalToDouble(&ptpClock->delaySM));
                                }
                        feedDoublePermanentStdDev(&ptpClock->slaveStats.owdStats, timeInternalToDouble(&ptpClock->meanPathDelay));
#endif


		DBGV("delay filter %d\n", ptpClock->meanPathDelay.nanoseconds);
	} else {
		INFO("Ignoring delayResp because we didn't receive any sync yet\n");
	}


display:
	logStatistics(rtOpts, ptpClock);

}
void
DASSL_integrate (SIM_simulator simulate)
{
  CLC_simulator simulator = (CLC_simulator) simulate->state->sim;
  clcData = simulator->data;
  clcModel = simulator->model;
  simOutput = simulator->output;
  int i;
  double t = clcData->it;
  double tout;
  const double _ft = clcData->ft;
  double dQRel = clcData->dQRel[0];
  double dQMin = clcData->dQMin[0];
  double *_x = clcData->x;
  double *rwork;
  int is_sampled = simOutput->commInterval != CI_Step;
  double step_size;
  if (is_sampled)
    {
      step_size = simOutput->sampled->period[0];
    }
  const int num_steps = (
      is_sampled ? ceil (_ft / step_size) + 2 : MAX_OUTPUT_POINTS);
  double **solution = checkedMalloc (sizeof(double*) * simOutput->outputs);
  double *solution_time = checkedMalloc (sizeof(double) * num_steps);
  double **outvar = checkedMalloc (sizeof(double) * simOutput->outputs);

  int info[20], lrw, liw, *iwork;
  double *x, *dx, rel_tol = dQRel, abs_tol = dQMin;
  int numofconstr = clcData->events, method_info = 0;
  int *root_output;
  int size = clcData->states;
  int event_detected = 0;

  x = checkedMalloc (sizeof(double) * clcData->states);
  dx = checkedMalloc (sizeof(double) * clcData->states);
  root_output = checkedMalloc (sizeof(int) * clcData->events);
  lrw = 5000 + 15000 * clcData->states
      + /*clcData->states * clcData->states +*/8 * clcData->events;
  rwork = checkedMalloc (sizeof(double) * lrw);
  CLC_compute_outputs (simOutput, solution, num_steps);
  for (i = 0; i < clcData->states; i++)
    x[i] = _x[i];
  cleanDoubleVector (dx, 0, clcData->states);
  cleanVector (root_output, 0, clcData->events);
  cleanVector (info, 0, 20);
  if (!is_sampled)
    {
      info[2] = 1;
    }
  liw = 60040;
  iwork = checkedMalloc (sizeof(int) * liw);
  int percentage = 0;
  // Save first step
  CLC_save_step (simOutput, solution, solution_time, t,
		 clcData->totalOutputSteps, x, clcData->d, clcData->alg);
  clcData->totalOutputSteps++;
  getTime (simulator->sTime);
#ifdef SYNC_RT
  setInitRealTime();
#endif
  while (t < _ft)
    {
      if (!is_sampled)
	{
	  tout = _ft;
	}
      else
	{
	  if (!event_detected)
	    {
	      tout = t + step_size;
	    }
	  else
	    {
	      if (fabs (tout - t) < 1e-12)
		{
		  CLC_save_step (simOutput, solution, solution_time, tout,
				 clcData->totalOutputSteps, x, clcData->d,
				 clcData->alg);
		  clcData->totalOutputSteps++;
		  tout = t + step_size;
		}
	    }
	  event_detected = 0;
	}
      if (tout > _ft)
	tout = _ft;
      ddaskr_ (DASSL_model, &size, &t, x, dx, &tout, info, &rel_tol, &abs_tol,
	       &method_info, rwork, &lrw, iwork, &liw,
	       NULL,
	       NULL, NULL, NULL, DASSL_events, &numofconstr, root_output);
      if (method_info < 0)
	{
	  printf (
	      "Error: DASSL returned IDID = %d. Check DASSL documentation\n",
	      method_info);
	  exit (-1);
	}
#ifdef SYNC_RT
      /* Sync */
      waitUntil(t);
#endif

      if (method_info == 5)
	{
	  CLC_handle_event (clcData, clcModel, x, root_output, t, iwork);
	  if (is_sampled)
	    event_detected = 1;
	  info[0] = 0;
	}
      if (!is_sampled)
	{
	  CLC_save_step (simOutput, solution, solution_time, t,
			 clcData->totalOutputSteps, x, clcData->d,
			 clcData->alg);
	  clcData->totalOutputSteps++;
	}
      else
	{
	  if (!event_detected)
	    {
	      if (fabs (tout - solution_time[clcData->totalOutputSteps - 1])
		  > step_size / 10)
		{
		  CLC_save_step (simOutput, solution, solution_time, tout,
				 clcData->totalOutputSteps, x, clcData->d,
				 clcData->alg);
		  clcData->totalOutputSteps++;
		}
	    }
	  else
	    {
	    }
	}

      if ((int) (t * 100 / _ft) > percentage)
	{
	  percentage = 100 * t / _ft;
	  fprintf (stderr, "*%g", t);
	  fflush (stderr);
	}
    }
  /*
   if (!event_detected && is_sampled) {
   if (solution_time[totalOutputSteps]<t) {
   CLC_save_step(simOutput,solution,solution_time,t,totalOutputSteps,x, clcData->d);
   totalOutputSteps++;
   }
   }
   */
  clcData->totalSteps += iwork[10];
  clcData->totalStepsDASSL += iwork[11];
  clcData->totalJacobians += iwork[12];
  clcData->totalCrossingEvaluations += iwork[35];
  getTime (simulator->sTime);
  subTime (simulator->sTime, simulator->iTime);
  if (simulator->settings->debug == 0 || simulator->settings->debug > 1)
    {
      SD_print (simulator->simulationLog, "Simulation time (DASSL):");
      SD_print (simulator->simulationLog, "----------------");
      SD_print (simulator->simulationLog, "Miliseconds: %g",
		getTimeValue (simulator->sTime));
      SD_print (simulator->simulationLog, "Function evaluations: %llu",
		clcData->funEvaluations);
      //SD_print (simulator->simulationLog, "Scalar function evaluations: %d", clcData->scalarEvaluations);
      //SD_print (simulator->simulationLog, "Zero Crossings : %d", clcData->zeroCrossings);
      SD_print (simulator->simulationLog,
		"Function evaluations (reported by DASSL): %d",
		clcData->totalStepsDASSL);
      SD_print (simulator->simulationLog, "Jacobian evaluations : %d",
		clcData->totalJacobians);
      SD_print (simulator->simulationLog, "Zero crossing evaluations : %d",
		clcData->totalCrossingEvaluations);
      SD_print (simulator->simulationLog, "Output steps: %d",
		clcData->totalOutputSteps);
      SD_print (simulator->simulationLog, "Simulation steps: %d",
		clcData->totalSteps);
      SD_print (simulator->simulationLog, "Events detected : %d",
		clcData->totalEvents);
    }
  CLC_write_output (simOutput, solution, solution_time,
		    clcData->totalOutputSteps);
  // To avoid QSS output
  free (x);
  free (dx);
  free (outvar);
  free (root_output);
  free (solution_time);
  free (rwork);
  free (iwork);
  for (i = 0; i < simOutput->outputs; i++)
    {
      free (solution[i]);
    }
  free (solution);
}
예제 #23
0
파일: servo.c 프로젝트: artasoftkey/ptpv2d
void updateOffset(TimeInternal *              send_time,  // Sync message reported Transmit time
                  TimeInternal *              recv_time,  // Sync message local    Receive  time
                  offset_from_master_filter * ofm_filt,   // Offset from Master filter
                  RunTimeOpts *               rtOpts,     // Run Time Options
                  PtpClock *                  ptpClock    // PTP main data structure
                 )
{
  DBGV("updateOffset:\n");
  
  /* calc 'master_to_slave_delay' */
  subTime(&ptpClock->master_to_slave_delay, // Result: Master to slave delay
          recv_time,                        // Recorded time of Sync message
          send_time                         // minus Send time of Sync message (from follow-up)
         );
  
  /* Update for V2 corrections (set to zero if received Sync/Follow-up is from V1 MASTER) */

  subTime(&ptpClock->master_to_slave_delay,
          &ptpClock->master_to_slave_delay,
          &ptpClock->sync_correction
         );

  subTime(&ptpClock->master_to_slave_delay,
          &ptpClock->master_to_slave_delay,
          &ptpClock->followup_correction
         );

  /* update 'offset_from_master' */
  subTime(&ptpClock->offset_from_master,    // Result: Offset from master
          &ptpClock->master_to_slave_delay, // From above calculation
          &ptpClock->one_way_delay          // minus one way delay calc from Delay Request/response
         );

  if(ptpClock->offset_from_master.seconds)
  {
    /* cannot filter with secs, clear filter */
    ofm_filt->nsec_prev = -1;  /* AKB: Use invalid number to make sure next calc correct */

#ifdef CONFIG_MPC831X
    /* set meter to max */
    led_meter(255);
#endif

    return;
  }
  
  /* filter 'offset_from_master' */
  /* 
   * Offset from Master Filtering 
   * this uses a simple two sample average:
   *
   * y[x] = x[n]/2 + x[n-1]/2
   *
   */

  if (ofm_filt->nsec_prev != -1)  /* AKB: Make sure previous timestamp is valid */
  {
     // Previous timestamp is valid, calculate new offset from master 
     // based on previous and current timestamps

     ofm_filt->y =   // Offset from master filter Y 
                     ptpClock->offset_from_master.nanoseconds/2  // current  / 2
                   + ofm_filt->nsec_prev/2;                      // previous / 2

     ofm_filt->nsec_prev = ptpClock->offset_from_master.nanoseconds;// Store current for next time

     ptpClock->offset_from_master.nanoseconds = ofm_filt->y;  // Set offset to current Y value

#ifdef CONFIG_MPC831X
     if (abs(ptpClock->offset_from_master.nanoseconds) > 255)
     {
       /* set meter to max */
       led_meter(255);
     }
     else
     {
       /* set meter based on nanoseconds between 0 and 255 absolute */
       led_meter(abs(ptpClock->offset_from_master.nanoseconds));
     }
#endif

  }
  else
  {

     // AKB: Previous timestamp is not valid, set filter Y to current value
     ofm_filt->y         = ptpClock->offset_from_master.nanoseconds; 
     ofm_filt->nsec_prev = ptpClock->offset_from_master.nanoseconds;
  }
  
  DBGV("updateOffset: offset filter y:%d\n", ofm_filt->y);
}
예제 #24
0
파일: servo.c 프로젝트: DomChey/ptpd
void
updateOffset(TimeInternal * send_time, TimeInternal * recv_time,
    Filter * ofm_filt, RunTimeOpts * rtOpts, PtpClock * ptpClock, TimeInternal * correctionField)
{

	DBGV("UTCOffset: %d | leap 59: %d |  leap61: %d\n", 
	     ptpClock->timePropertiesDS.currentUtcOffset,ptpClock->timePropertiesDS.leap59,ptpClock->timePropertiesDS.leap61);
        /* updates paused, leap second pending - do nothing */
        if(ptpClock->leapSecondInProgress)
		return;

	DBGV("==> updateOffset\n");

	{
	//perform basic checks, using only local variables
	TimeInternal master_to_slave_delay;

	/* calc 'master_to_slave_delay' */
	subTime(&master_to_slave_delay, recv_time, send_time);

	if (rtOpts->maxDelay) { /* If maxDelay is 0 then it's OFF */
		if (master_to_slave_delay.seconds && rtOpts->maxDelay) {
			INFO("updateOffset aborted, delay greater than 1"
			     " second.\n");
			/* msgDump(ptpClock); */
			return;
		}

		if (master_to_slave_delay.nanoseconds > rtOpts->maxDelay) {
			INFO("updateOffset aborted, delay %d greater than "
			     "administratively set maximum %d\n",
			     master_to_slave_delay.nanoseconds, 
			     rtOpts->maxDelay);
			/* msgDump(ptpClock); */
			return;
		}
	}
	}

	// used for stats feedback 
	ptpClock->char_last_msg='S';

	/*
	 * The packet has passed basic checks, so we'll:
	 *   - update the global delayMS variable
	 *   - calculate a new filtered OFM
	 */
#ifdef PTPD_STATISTICS
	if (rtOpts->delayMSOutlierFilterEnabled) {
		subTime(&ptpClock->rawDelayMS, recv_time, send_time);
		if(!isDoublePeircesOutlier(ptpClock->delayMSRawStats, timeInternalToDouble(&ptpClock->rawDelayMS), rtOpts->delayMSOutlierFilterThreshold)) {
			ptpClock->delayMSoutlier = FALSE;
			ptpClock->delayMS = ptpClock->rawDelayMS;
		} else {
			ptpClock->delayMSoutlier = TRUE;
			ptpClock->counters.delayMSOutliersFound++;
			if(!rtOpts->delayMSOutlierFilterDiscard)
			ptpClock->delayMS = doubleToTimeInternal(ptpClock->delayMSFiltered->mean);
		}
	} else {
		subTime(&ptpClock->delayMS, recv_time, send_time);
	}
#else
	/* Used just for End to End mode. */
	subTime(&ptpClock->delayMS, recv_time, send_time);
#endif

	/* Take care about correctionField */
	subTime(&ptpClock->delayMS,
		&ptpClock->delayMS, correctionField);

#ifdef PTPD_STATISTICS
#endif

	/* update 'offsetFromMaster' */
	if (ptpClock->delayMechanism == P2P) {
		subTime(&ptpClock->offsetFromMaster, 
			&ptpClock->delayMS, 
			&ptpClock->peerMeanPathDelay);
	/* (End to End mode or disabled - if disabled, meanpath delay is zero) */
	} else if (ptpClock->delayMechanism == E2E ||
	    ptpClock->delayMechanism == DELAY_DISABLED ) {

		subTime(&ptpClock->offsetFromMaster, 
			&ptpClock->delayMS, 
			&ptpClock->meanPathDelay);
	}

	if (ptpClock->offsetFromMaster.seconds) {
		/* cannot filter with secs, clear filter */
		FilterClear(ofm_filt);
		rtOpts->offset_first_updated = TRUE;
		return;
	}

	FilterFeed(ofm_filt, &ptpClock->offsetFromMaster.nanoseconds);

	DBGV("offset filter %d\n", ptpClock->offsetFromMaster.nanoseconds);

	/* Apply the offset shift */
	subTime(&ptpClock->offsetFromMaster, &ptpClock->offsetFromMaster,
	&rtOpts->ofmShift);

	/*
	 * Offset must have been computed at least one time before 
	 * computing end to end delay
	 */
	rtOpts->offset_first_updated = TRUE;
}
예제 #25
0
파일: servo.c 프로젝트: artasoftkey/ptpv2d
void updatePathDelay(one_way_delay_filter *owd_filt,  // one way delay filter
                     RunTimeOpts          *rtOpts,    // run time options
                     PtpClock             *ptpClock   // PTP main data structure
                    )
{
  Integer16 s;
  TimeInternal remote_time;
  
  
  DBGV("updatePathDelay:\n");

  DBGV(" t1 PDelay Req  Tx time %10.10ds.%9.9dns\n",
       ptpClock->t1_pdelay_req_tx_time.seconds,
       ptpClock->t1_pdelay_req_tx_time.nanoseconds
      );
  
  DBGV(" t2 PDelay Req  Rx time %10.10ds.%9.9dns\n",
       ptpClock->t2_pdelay_req_rx_time.seconds,
       ptpClock->t2_pdelay_req_rx_time.nanoseconds
      );

  DBGV(" t3 PDelay Resp Tx time %10.10ds.%9.9dns\n",
       ptpClock->t3_pdelay_resp_tx_time.seconds,
       ptpClock->t3_pdelay_resp_tx_time.nanoseconds
      );

  DBGV(" t4 PDelay Resp Rx time %10.10ds.%9.9dns\n",
       ptpClock->t4_pdelay_resp_rx_time.seconds,
       ptpClock->t4_pdelay_resp_rx_time.nanoseconds
      );

  DBGV(" PDelay Resp correction %10.10ds.%9.9dns\n",
       ptpClock->pdelay_resp_correction.seconds,
       ptpClock->pdelay_resp_correction.nanoseconds
      );

  DBGV(" PDelay Resp follow up  %10.10ds.%9.9dns\n",
       ptpClock->pdelay_followup_correction.seconds,
       ptpClock->pdelay_followup_correction.nanoseconds
      );

  /* calc 'slave_to_master_delay' */
  subTime(&ptpClock->one_way_delay,          // Result
          &ptpClock->t4_pdelay_resp_rx_time, // PDelay Response Receive time
          &ptpClock->t1_pdelay_req_tx_time   // minus PDelay Request Transmit time
         );

  DBGV(" (t4-t1)                %10.10ds.%9.9dns\n",
       ptpClock->one_way_delay.seconds,
       ptpClock->one_way_delay.nanoseconds
      );

  subTime(&remote_time,                      // Result
          &ptpClock->t3_pdelay_resp_tx_time, // PDelay Resp Transmit time (from responder)
          &ptpClock->t2_pdelay_req_rx_time   // minus PDelay Request Receive time (from responder)
         );

  DBGV(" (t3-t2)                %10.10ds.%9.9dns\n",
       remote_time.seconds,
       remote_time.nanoseconds
      );


  subTime(&ptpClock->one_way_delay,          // Result
          &ptpClock->one_way_delay,          // (T4-T1)
          &remote_time                       // minus (T3-T2)
         );

  DBGV(" (t4-t1)-(t3-t2)        %10.10ds.%9.9dns\n",
       ptpClock->one_way_delay.seconds,
       ptpClock->one_way_delay.nanoseconds
      );

  subTime(&ptpClock->one_way_delay,          // Result
          &ptpClock->one_way_delay,          // Current Calculation
          &ptpClock->pdelay_resp_correction // minus PDelay Resp Correction
         );

  DBGV(" minus 1st correction   %10.10ds.%9.9dns\n",
       ptpClock->one_way_delay.seconds,
       ptpClock->one_way_delay.nanoseconds
      );

  subTime(&ptpClock->one_way_delay,             // Result
          &ptpClock->one_way_delay,             // Current Calculation
          &ptpClock->pdelay_followup_correction // minus PDelay Resp Correction
         );

  DBGV(" minus 2nd correction   %10.10ds.%9.9dns\n",
       ptpClock->one_way_delay.seconds,
       ptpClock->one_way_delay.nanoseconds
      );

  halveTime(&ptpClock->one_way_delay);

  DBGV(" divided by 2           %10.10ds.%9.9dns\n",
       ptpClock->one_way_delay.seconds,
       ptpClock->one_way_delay.nanoseconds
      );


  copyTime( &ptpClock->slave_to_master_delay, // Destination
            &ptpClock->one_way_delay          // Source
          );

  clearTime(&ptpClock->t1_pdelay_req_tx_time);
  clearTime(&ptpClock->t2_pdelay_req_rx_time);
  clearTime(&ptpClock->t3_pdelay_resp_tx_time);
  clearTime(&ptpClock->t4_pdelay_resp_rx_time);
  clearTime(&ptpClock->pdelay_resp_correction);
  clearTime(&ptpClock->pdelay_followup_correction);
  clearTime(&ptpClock->t1_sync_delta_time);
  clearTime(&ptpClock->t2_sync_delta_time);  

  if(ptpClock->one_way_delay.seconds)       // Check if delay is larger than one second
  {

    /* Delay is larger than one second, clear s_exp and timestamp
     * of previously received sent time of Sync message (usually from 
     * preciseOriginTimestamp of follow up message) and return
     */
    DBG("updatePathDelay: One way delay seconds != 0\n");
    DBG("updatePathDelay: Clearing one way delay filter s_exp, nsec_prev\n");
    owd_filt->s_exp     = 0;
    owd_filt->nsec_prev = 0;
    return;
  }
  
  /* avoid overflowing filter */
  s =  rtOpts->s;
  while(abs(owd_filt->y)>>(31-s))
    --s;

  DBGV("updatePathDelay: rtOpts->s: %d, s:%d\n", 
       rtOpts->s,
       s
      );
  DBGV("updatePathDelay: current owd_filt->y: %d, s_exp: %d\n", 
       owd_filt->y,
       owd_filt->s_exp
      );  

  /* crank down filter cutoff by increasing 's_exp' */
  if(owd_filt->s_exp < 1)
    owd_filt->s_exp = 1;
  else if(owd_filt->s_exp < 1<<s)
    ++owd_filt->s_exp;
  else if(owd_filt->s_exp > 1<<s)
    owd_filt->s_exp = 1<<s;
  
  /* filter 'one_way_delay' */
  owd_filt->y = (owd_filt->s_exp-1)
                *owd_filt->y/owd_filt->s_exp 
              + (ptpClock->one_way_delay.nanoseconds/2 
                 + owd_filt->nsec_prev/2
                ) 
                /owd_filt->s_exp;

  /* Record previous one way delay nanosecond value
   * and update it with value calculated above
   */  
  owd_filt->nsec_prev = ptpClock->one_way_delay.nanoseconds;
  ptpClock->one_way_delay.nanoseconds = owd_filt->y;
  
  DBGV("updatePathDelay: delay filter y:%d, s_exp:%d\n",
       owd_filt->y,
       owd_filt->s_exp
      );
}
예제 #26
0
파일: servo.c 프로젝트: DomChey/ptpd
void
servo_perform_clock_step(RunTimeOpts * rtOpts, PtpClock * ptpClock)
{
	if(rtOpts->noAdjust){
		WARNING("Could not step clock - clock adjustment disabled\n");
		return;
	}

	TimeInternal oldTime, newTime;
	/*No need to reset the frequency offset: if we're far off, it will quickly get back to a high value */
	getTime(&oldTime);
	subTime(&newTime, &oldTime, &ptpClock->offsetFromMaster);

	setTime(&newTime);

#ifdef HAVE_LINUX_RTC_H
	if(rtOpts->setRtc) {
		setRtc(&newTime);
	}
#endif /* HAVE_LINUX_RTC_H */

	initClock(rtOpts, ptpClock);

#ifdef HAVE_SYS_TIMEX_H
	if(ptpClock->clockQuality.clockClass > 127)
		restoreDrift(ptpClock, rtOpts, TRUE);
#endif /* HAVE_SYS_TIMEX_H */
	ptpClock->servo.runningMaxOutput = FALSE;
	toState(PTP_FAULTY, rtOpts, ptpClock);		/* make a full protocol reset */

	/* Major time change - need to inform utmp / wtmp */
	if(oldTime.seconds != newTime.seconds) {

/* Add the old time entry to utmp/wtmp */

/* About as long as the ntpd implementation, but not any less ugly */

#ifdef HAVE_UTMPX_H
		struct utmpx utx;
	memset(&utx, 0, sizeof(utx));
		strncpy(utx.ut_user, "date", sizeof(utx.ut_user));
#ifndef OTIME_MSG
		strncpy(utx.ut_line, "|", sizeof(utx.ut_line));
#else
		strncpy(utx.ut_line, OTIME_MSG, sizeof(utx.ut_line));
#endif /* OTIME_MSG */
#ifdef OLD_TIME
		utx.ut_tv.tv_sec = oldTime.seconds;
		utx.ut_tv.tv_usec = oldTime.nanoseconds / 1000;
		utx.ut_type = OLD_TIME;
#else /* no ut_type */
		utx.ut_time = oldTime.seconds;
#endif /* OLD_TIME */

/* ======== BEGIN  OLD TIME EVENT - UTMPX / WTMPX =========== */
#ifdef HAVE_UTMPXNAME
		utmpxname("/var/log/utmp");
#endif /* HAVE_UTMPXNAME */
		setutxent();
		pututxline(&utx);
		endutxent();
#ifdef HAVE_UPDWTMPX
		updwtmpx("/var/log/wtmp", &utx);
#endif /* HAVE_IPDWTMPX */
/* ======== END    OLD TIME EVENT - UTMPX / WTMPX =========== */

#else /* NO UTMPX_H */

#ifdef HAVE_UTMP_H
		struct utmp ut;
		memset(&ut, 0, sizeof(ut));
		strncpy(ut.ut_name, "date", sizeof(ut.ut_name));
#ifndef OTIME_MSG
		strncpy(ut.ut_line, "|", sizeof(ut.ut_line));
#else
		strncpy(ut.ut_line, OTIME_MSG, sizeof(ut.ut_line));
#endif /* OTIME_MSG */

#ifdef OLD_TIME
		ut.ut_tv.tv_sec = oldTime.seconds;
		ut.ut_tv.tv_usec = oldTime.nanoseconds / 1000;
		ut.ut_type = OLD_TIME;
#else /* no ut_type */
		ut.ut_time = oldTime.seconds;
#endif /* OLD_TIME */

/* ======== BEGIN  OLD TIME EVENT - UTMP / WTMP =========== */
#ifdef HAVE_UTMPNAME
		utmpname(UTMP_FILE);
#endif /* HAVE_UTMPNAME */
#ifdef HAVE_SETUTENT
		setutent();
#endif /* HAVE_SETUTENT */
#ifdef HAVE_PUTUTLINE
		pututline(&ut);
#endif /* HAVE_PUTUTLINE */
#ifdef HAVE_ENDUTENT
		endutent();
#endif /* HAVE_ENDUTENT */
#ifdef HAVE_UTMPNAME
		utmpname(WTMP_FILE);
#endif /* HAVE_UTMPNAME */
#ifdef HAVE_SETUTENT
		setutent();
#endif /* HAVE_SETUTENT */
#ifdef HAVE_PUTUTLINE
		pututline(&ut);
#endif /* HAVE_PUTUTLINE */
#ifdef HAVE_ENDUTENT
		endutent();
#endif /* HAVE_ENDUTENT */
/* ======== END    OLD TIME EVENT - UTMP / WTMP =========== */

#endif /* HAVE_UTMP_H */
#endif /* HAVE_UTMPX_H */

/* Add the new time entry to utmp/wtmp */

#ifdef HAVE_UTMPX_H
		memset(&utx, 0, sizeof(utx));
		strncpy(utx.ut_user, "date", sizeof(utx.ut_user));
#ifndef NTIME_MSG
		strncpy(utx.ut_line, "}", sizeof(utx.ut_line));
#else
		strncpy(utx.ut_line, NTIME_MSG, sizeof(utx.ut_line));
#endif /* NTIME_MSG */
#ifdef NEW_TIME
		utx.ut_tv.tv_sec = newTime.seconds;
		utx.ut_tv.tv_usec = newTime.nanoseconds / 1000;
		utx.ut_type = NEW_TIME;
#else /* no ut_type */
		utx.ut_time = newTime.seconds;
#endif /* NEW_TIME */

/* ======== BEGIN  NEW TIME EVENT - UTMPX / WTMPX =========== */
#ifdef HAVE_UTMPXNAME
		utmpxname("/var/log/utmp");
#endif /* HAVE_UTMPXNAME */
		setutxent();
		pututxline(&utx);
		endutxent();
#ifdef HAVE_UPDWTMPX
		updwtmpx("/var/log/wtmp", &utx);
#endif /* HAVE_UPDWTMPX */
/* ======== END    NEW TIME EVENT - UTMPX / WTMPX =========== */

#else /* NO UTMPX_H */

#ifdef HAVE_UTMP_H
		memset(&ut, 0, sizeof(ut));
		strncpy(ut.ut_name, "date", sizeof(ut.ut_name));
#ifndef NTIME_MSG
		strncpy(ut.ut_line, "}", sizeof(ut.ut_line));
#else
		strncpy(ut.ut_line, NTIME_MSG, sizeof(ut.ut_line));
#endif /* NTIME_MSG */
#ifdef NEW_TIME
		ut.ut_tv.tv_sec = newTime.seconds;
		ut.ut_tv.tv_usec = newTime.nanoseconds / 1000;
		ut.ut_type = NEW_TIME;
#else /* no ut_type */
		ut.ut_time = newTime.seconds;
#endif /* NEW_TIME */

/* ======== BEGIN  NEW TIME EVENT - UTMP / WTMP =========== */
#ifdef HAVE_UTMPNAME
		utmpname(UTMP_FILE);
#endif /* HAVE_UTMPNAME */
#ifdef HAVE_SETUTENT
		setutent();
#endif /* HAVE_SETUTENT */
#ifdef HAVE_PUTUTLINE
		pututline(&ut);
#endif /* HAVE_PUTUTLINE */
#ifdef HAVE_ENDUTENT
		endutent();
#endif /* HAVE_ENDUTENT */
#ifdef HAVE_UTMPNAME
		utmpname(WTMP_FILE);
#endif /* HAVE_UTMPNAME */
#ifdef HAVE_SETUTENT
		setutent();
#endif /* HAVE_SETUTENT */
#ifdef HAVE_PUTUTLINE
		pututline(&ut);
#endif /* HAVE_PUTUTLINE */
#ifdef HAVE_ENDUTENT
		endutent();
#endif /* HAVE_ENDUTENT */
/* ======== END    NEW TIME EVENT - UTMP / WTMP =========== */

#endif /* HAVE_UTMP_H */
#endif /* HAVE_UTMPX_H */
	}


}
예제 #27
0
static Boolean
setTime (ClockDriver *self, TimeInternal *time, Boolean force) {

	GET_CONFIG_CLOCKDRIVER(self, myConfig, unix);

	TimeInternal oldTime, delta;

	getTime(self, &oldTime);

	subTime(&delta, &oldTime, time);

	if(self->config.readOnly) {
		return FALSE;
	}

	if(force) {
	    self->lockedUp = FALSE;
	}

	if(!force && !self->config.negativeStep && isTimeNegative(&delta)) {
		CRITICAL(THIS_COMPONENT"Cannot step Unix clock %s backwards\n", self->name);
		CRITICAL(THIS_COMPONENT"Manual intervention required or SIGUSR1 to force %s clock step\n", self->name);
		self->lockedUp = TRUE;
		self->setState(self, CS_NEGSTEP);
		return FALSE;
	}

#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)

	struct timespec tp;
	tp.tv_sec = time->seconds;
	tp.tv_nsec = time->nanoseconds;

	if(tp.tv_sec == 0) {
	    ERROR(THIS_COMPONENT"Unix clock driver %s: cannot set time to zero seconds\n", self->name);
	    return FALSE;
	}

	if(tp.tv_sec <= 0) {
	    ERROR(THIS_COMPONENT"Unic clock driver %s: cannot set time to a negative value %d\n", self->name, tp.tv_sec);
	    return FALSE;
	}

#else

	struct timeval tv;
	tv.tv_sec = time->seconds;
	tv.tv_usec = time->nanoseconds / 1000;

	if(tv.tv_sec == 0) {
	    ERROR(THIS_COMPONENT"Unix clock %s: cannot set time to zero seconds\n", self->name);
	    return FALSE;
	}

	if(tv.tv_sec < 0) {
	    ERROR(THIS_COMPONENT"Unic clock %s: cannot set time to a negative value %d\n", self->name, tv.tv_sec);
	    return FALSE;
	}


#endif /* _POSIX_TIMERS */

#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
	if (clock_settime(CLOCK_REALTIME, &tp) < 0) {
		PERROR(THIS_COMPONENT"Could not set system time");
		return FALSE;
	}
	addTime(&_stepAccumulator, &_stepAccumulator, &delta);
#else

	settimeofday(&tv, 0);
	addTime(&_stepAccumulator, &_stepAccumulator, &delta);
#endif /* _POSIX_TIMERS */

	if(oldTime.seconds != time->seconds) {
	    updateXtmp_unix(oldTime, *time);
	    if(myConfig->setRtc) {
		setRtc(self, time);
	    }
	}

	self->_stepped = TRUE;

	struct timespec tmpTs = { time->seconds,0 };

	char timeStr[MAXTIMESTR];
	strftime(timeStr, MAXTIMESTR, "%x %X", localtime(&tmpTs.tv_sec));
	NOTICE(THIS_COMPONENT"Unix clock %s: stepped the system clock to: %s.%d\n", self->name,
	       timeStr, time->nanoseconds);

	self->setState(self, CS_FREERUN);

	return TRUE;

}
예제 #28
0
파일: servo.c 프로젝트: DomChey/ptpd
double
runPIservo(PIservo* servo, const Integer32 input)
{

        double dt;

        TimeInternal now, delta;

        switch (servo->dTmethod) {

        case DT_MEASURED:

                getTime(&now);
                if(servo->lastUpdate.seconds == 0 &&
                servo->lastUpdate.nanoseconds == 0) {
                        dt = 1.0;
                } else {
                        subTime(&delta, &now, &servo->lastUpdate);
                        dt = delta.nanoseconds / 1E9;
                }

                /* Don't use dT > 2 * target update interval */
                if(dt > 2 * pow(2, servo->logdT))
                        dt = 2 * pow(2, servo->logdT);

                break;

        case DT_CONSTANT:
                dt = pow(2, servo->logdT);

		break;

        case DT_NONE:
        default:
                dt = 1.0;
                break;
        }

        if(dt <= 0.0)
            dt = 1.0;

	servo->input = input;

	if (servo->kP < 0.000001)
		servo->kP = 0.000001;
	if (servo->kI < 0.000001)
		servo->kI = 0.000001;

	servo->observedDrift +=
		dt * ((input + 0.0 ) * servo->kI);

	if(servo->observedDrift >= servo->maxOutput) {
		servo->observedDrift = servo->maxOutput;
		servo->runningMaxOutput = TRUE;
	}
	else if(servo->observedDrift <= -servo->maxOutput) {
		servo->observedDrift = -servo->maxOutput;
		servo->runningMaxOutput = TRUE;
	} else {
		servo->runningMaxOutput = FALSE;
	}

	servo->output = (servo->kP * (input + 0.0) ) + servo->observedDrift;

        if(servo->dTmethod == DT_MEASURED)
                servo->lastUpdate = now;

        DBGV("Servo dt: %.09f, input (ofm): %d, output(adj): %.09f, accumulator (observed drift): %.09f\n", dt, input, servo->output, servo->observedDrift);

        return -servo->output;
}