Files
luban-lite-t3e-pro/packages/third-party/ptpd/ptp/dep/servo.c
2025-09-30 11:56:06 +08:00

343 lines
9.7 KiB
C

#include "../ptpd.h"
void initClock(PtpClock *ptpClock)
{
DBG("initClock\n");
/* Clear vars */
ptpClock->Tms.seconds = ptpClock->Tms.nanoseconds = 0;
ptpClock->observedDrift = 0; /* clears clock servo accumulator (the I term) */
/* One way delay */
ptpClock->owd_filt.n = 0;
ptpClock->owd_filt.s = ptpClock->servo.sDelay;
/* Offset from master */
ptpClock->ofm_filt.n = 0;
ptpClock->ofm_filt.s = ptpClock->servo.sOffset;
/* Scaled log variance */
if (DEFAULT_PARENTS_STATS)
{
ptpClock->slv_filt.n = 0;
ptpClock->slv_filt.s = 6;
ptpClock->offsetHistory[0] = 0;
ptpClock->offsetHistory[1] = 0;
}
ptpClock->waitingForFollowUp = FALSE;
ptpClock->waitingForPDelayRespFollowUp = FALSE;
ptpClock->pdelay_t1.seconds = ptpClock->pdelay_t1.nanoseconds = 0;
ptpClock->pdelay_t2.seconds = ptpClock->pdelay_t2.nanoseconds = 0;
ptpClock->pdelay_t3.seconds = ptpClock->pdelay_t3.nanoseconds = 0;
ptpClock->pdelay_t4.seconds = ptpClock->pdelay_t4.nanoseconds = 0;
/* Reset parent statistics */
ptpClock->parentDS.parentStats = FALSE;
ptpClock->parentDS.observedParentClockPhaseChangeRate = 0;
ptpClock->parentDS.observedParentOffsetScaledLogVariance = 0;
/* Level clock */
if (!ptpClock->servo.noAdjust)
adjFreq(0);
netEmptyEventQ(&ptpClock->netPath);
}
static int32_t order(int32_t n)
{
if (n < 0) {
n = -n;
}
if (n == 0) {
return 0;
}
return floorLog2(n);
}
/* Exponencial smoothing */
static void filter(int32_t * nsec_current, Filter * filt)
{
int32_t s, s2;
/*
using floatingpoint math
alpha = 1/2^s
y[1] = x[0]
y[n] = alpha * x[n-1] + (1-alpha) * y[n-1]
or equivalent with integer math
y[1] = x[0]
y_sum[1] = y[1] * 2^s
y_sum[n] = y_sum[n-1] + x[n-1] - y[n-1]
y[n] = y_sum[n] / 2^s
*/
/* Increment number of samples */
filt->n++;
/* If it is first time, we are running filter, initialize it */
if (filt->n == 1)
{
filt->y_prev = *nsec_current;
filt->y_sum = *nsec_current;
filt->s_prev = 0;
}
s = filt->s;
/* Speedup filter, if not 2^s > n */
if ((1<<s) > filt->n)
{
/* Lower the filter order */
s = order(filt->n);
}
else
{
/* Avoid overflowing of n */
filt->n = 1<<s;
}
/* Avoid overflowing of filter. 30 is because using signed 32bit integers */
s2 = 30 - order(max(filt->y_prev, *nsec_current));
/* Use the lower filter order, higher will overflow */
s = min(s, s2);
/* If the order of the filter changed, change also y_sum value */
if (filt->s_prev > s) {
filt->y_sum >>= (filt->s_prev - s);
} else if (filt->s_prev < s) {
filt->y_sum <<= (s - filt->s_prev);
}
/* Compute the filter itself */
filt->y_sum += *nsec_current - filt->y_prev;
filt->y_prev = filt->y_sum >> s;
/* Save previous order of the filter */
filt->s_prev = s;
DBGV("filter: %d -> %d (%d)\n", *nsec_current, filt->y_prev, s);
/* Actualize target value */
*nsec_current = filt->y_prev;
}
/* 11.2 */
void updateOffset(PtpClock *ptpClock, const TimeInternal *syncEventIngressTimestamp,
const TimeInternal *preciseOriginTimestamp, const TimeInternal *correctionField)
{
DBGV("updateOffset\n");
/* <offsetFromMaster> = <syncEventIngressTimestamp> - <preciseOriginTimestamp>
- <meanPathDelay> - correctionField of Sync message
- correctionField of Follow_Up message. */
/* Compute offsetFromMaster */
subTime(&ptpClock->Tms, syncEventIngressTimestamp, preciseOriginTimestamp);
subTime(&ptpClock->Tms, &ptpClock->Tms, correctionField);
ptpClock->currentDS.offsetFromMaster = ptpClock->Tms;
switch (ptpClock->portDS.delayMechanism)
{
case E2E:
subTime(&ptpClock->currentDS.offsetFromMaster, &ptpClock->currentDS.offsetFromMaster, &ptpClock->currentDS.meanPathDelay);
break;
case P2P:
subTime(&ptpClock->currentDS.offsetFromMaster, &ptpClock->currentDS.offsetFromMaster, &ptpClock->portDS.peerMeanPathDelay);
break;
default:
break;
}
if (ptpClock->currentDS.offsetFromMaster.seconds != 0)
{
if (ptpClock->portDS.portState == PTP_SLAVE)
{
setFlag(ptpClock->events, SYNCHRONIZATION_FAULT);
}
DBGV("updateOffset: cannot filter seconds\n");
return;
}
/* Filter offsetFromMaster */
filter(&ptpClock->currentDS.offsetFromMaster.nanoseconds, &ptpClock->ofm_filt);
/* Check results */
if (abs(ptpClock->currentDS.offsetFromMaster.nanoseconds) < DEFAULT_CALIBRATED_OFFSET_NS)
{
if (ptpClock->portDS.portState == PTP_UNCALIBRATED)
{
setFlag(ptpClock->events, MASTER_CLOCK_SELECTED);
}
}
else if (abs(ptpClock->currentDS.offsetFromMaster.nanoseconds) > DEFAULT_UNCALIBRATED_OFFSET_NS)
{
if (ptpClock->portDS.portState == PTP_SLAVE)
{
setFlag(ptpClock->events, SYNCHRONIZATION_FAULT);
}
}
}
/* 11.3 */
void updateDelay(PtpClock * ptpClock, const TimeInternal *delayEventEgressTimestamp,
const TimeInternal *recieveTimestamp, const TimeInternal *correctionField)
{
/* Tms valid ? */
if (0 == ptpClock->ofm_filt.n)
{
DBGV("updateDelay: Tms is not valid");
return;
}
subTime(&ptpClock->Tsm, recieveTimestamp, delayEventEgressTimestamp);
subTime(&ptpClock->Tsm, &ptpClock->Tsm, correctionField);
addTime(&ptpClock->currentDS.meanPathDelay, &ptpClock->Tms, &ptpClock->Tsm);
div2Time(&ptpClock->currentDS.meanPathDelay);
/* Filter delay */
if (0 != ptpClock->currentDS.meanPathDelay.seconds)
{
DBGV("updateDelay: cannot filter with seconds");
}
else
{
filter(&ptpClock->currentDS.meanPathDelay.nanoseconds, &ptpClock->owd_filt);
}
}
void updatePeerDelay(PtpClock *ptpClock, const TimeInternal *correctionField, bool twoStep)
{
DBGV("updatePeerDelay\n");
if (twoStep)
{
TimeInternal Tab, Tba;
subTime(&Tab, &ptpClock->pdelay_t2 , &ptpClock->pdelay_t1);
subTime(&Tba, &ptpClock->pdelay_t4, &ptpClock->pdelay_t3);
addTime(&ptpClock->portDS.peerMeanPathDelay, &Tab, &Tba);
}
else /* One step clock */
{
subTime(&ptpClock->portDS.peerMeanPathDelay, &ptpClock->pdelay_t4, &ptpClock->pdelay_t1);
}
subTime(&ptpClock->portDS.peerMeanPathDelay, &ptpClock->portDS.peerMeanPathDelay, correctionField);
div2Time(&ptpClock->portDS.peerMeanPathDelay);
/* Filter delay */
if (ptpClock->portDS.peerMeanPathDelay.seconds != 0)
{
DBGV("updatePeerDelay: cannot filter with seconds");
return;
}
else
{
filter(&ptpClock->portDS.peerMeanPathDelay.nanoseconds, &ptpClock->owd_filt);
}
}
void updateClock(PtpClock *ptpClock)
{
int32_t adj;
TimeInternal timeTmp;
int32_t offsetNorm;
DBGV("updateClock\n");
if (ptpClock->currentDS.offsetFromMaster.seconds != 0 || abs(ptpClock->currentDS.offsetFromMaster.nanoseconds) > MAX_ADJ_OFFSET_NS)
{
/* if secs, reset clock or set freq adjustment to max */
if (!ptpClock->servo.noAdjust)
{
if (!ptpClock->servo.noResetClock)
{
getTime(&timeTmp);
subTime(&timeTmp, &timeTmp, &ptpClock->currentDS.offsetFromMaster);
setTime(&timeTmp);
initClock(ptpClock);
}
else
{
adj = ptpClock->currentDS.offsetFromMaster.nanoseconds > 0 ? ADJ_FREQ_MAX : -ADJ_FREQ_MAX;
adjFreq(-adj);
}
}
}
else
{
/* the PI controller */
/* normalize offset to 1s sync interval -> response of the servo will
* be same for all sync interval values, but faster/slower
* (possible lost of precision/overflow but much more stable) */
offsetNorm = ptpClock->currentDS.offsetFromMaster.nanoseconds;
if (ptpClock->portDS.logSyncInterval > 0)
offsetNorm >>= ptpClock->portDS.logSyncInterval;
else if (ptpClock->portDS.logSyncInterval < 0)
offsetNorm <<= -ptpClock->portDS.logSyncInterval;
/* the accumulator for the I component */
ptpClock->observedDrift += offsetNorm / ptpClock->servo.ai;
/* clamp the accumulator to ADJ_FREQ_MAX for sanity */
if (ptpClock->observedDrift > ADJ_FREQ_MAX)
ptpClock->observedDrift = ADJ_FREQ_MAX;
else if (ptpClock->observedDrift < -ADJ_FREQ_MAX)
ptpClock->observedDrift = -ADJ_FREQ_MAX;
/* apply controller output as a clock tick rate adjustment */
if (!ptpClock->servo.noAdjust)
{
adj = offsetNorm / ptpClock->servo.ap + ptpClock->observedDrift;
adjFreq(-adj);
}
if (DEFAULT_PARENTS_STATS)
{
int a, scaledLogVariance;
ptpClock->parentDS.parentStats = TRUE;
ptpClock->parentDS.observedParentClockPhaseChangeRate = 1100 * ptpClock->observedDrift;
a = (ptpClock->offsetHistory[1] - 2 * ptpClock->offsetHistory[0] + ptpClock->currentDS.offsetFromMaster.nanoseconds);
ptpClock->offsetHistory[1] = ptpClock->offsetHistory[0];
ptpClock->offsetHistory[0] = ptpClock->currentDS.offsetFromMaster.nanoseconds;
scaledLogVariance = order(a * a) << 8;
filter(&scaledLogVariance, &ptpClock->slv_filt);
ptpClock->parentDS.observedParentOffsetScaledLogVariance = 17000 + scaledLogVariance;
DBGV("updateClock: observed scalled log variance: 0x%x\n", ptpClock->parentDS.observedParentOffsetScaledLogVariance);
}
}
switch (ptpClock->portDS.delayMechanism)
{
case E2E:
DBG("updateClock: one-way delay averaged (E2E): %d sec %d nsec\n",
ptpClock->currentDS.meanPathDelay.seconds, ptpClock->currentDS.meanPathDelay.nanoseconds);
break;
case P2P:
DBG("updateClock: one-way delay averaged (P2P): %d sec %d nsec\n",
ptpClock->portDS.peerMeanPathDelay.seconds, ptpClock->portDS.peerMeanPathDelay.nanoseconds);
break;
default:
DBG("updateClock: one-way delay not computed\n");
}
DBG("updateClock: offset from master: %d sec %d nsec\n",
ptpClock->currentDS.offsetFromMaster.seconds,
ptpClock->currentDS.offsetFromMaster.nanoseconds);
DBG("updateClock: observed drift: %d\n", ptpClock->observedDrift);
}