int main(int argc, char **argv) { int clkid = clock_open("/dev/ptp0"); long adj = 0; adj = strtol(argv[1], NULL, 0); adjFreq(clkid, adj); clock_close(); return 0; }
void adjFreq_wrapper(RunTimeOpts * rtOpts, PtpClock * ptpClock, double adj) { if (rtOpts->noAdjust){ DBGV("adjFreq2: noAdjust on, returning\n"); return; } // call original adjtime DBG2(" adjFreq2: call adjfreq to %.09f us \n", adj / DBG_UNIT); adjFreq(adj); warn_operator_fast_slewing(rtOpts, ptpClock, adj); }
void initClock(RunTimeOpts *rtOpts, PtpClock *ptpClock) { DBG("initClock:\n"); /* clear vars */ initClockVars(rtOpts,ptpClock); /* level clock */ if(!rtOpts->noAdjust) { ptpClock->baseAdjustValue = rtOpts->baseAdjustValue; if (rtOpts->rememberAdjustValue == TRUE) { ptpClock->baseAdjustValue += ptpClock->lastAdjustValue; } adjFreq(ptpClock->baseAdjustValue); } }
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) ); }