41 #include "tsch-adaptive-timesync.h"
45 #if TSCH_ADAPTIVE_TIMESYNC
49 static int32_t drift_ppm;
51 static int32_t compensated_ticks;
53 static uint8_t timesync_entry_count;
55 static uint32_t asn_since_last_learning;
58 #define TSCH_DRIFT_UNIT (1000L * 1000 * 256)
63 timesync_entry_add(int32_t val, uint32_t time_delta)
65 #define NUM_TIMESYNC_ENTRIES 8
66 static int32_t buffer[NUM_TIMESYNC_ENTRIES];
69 if(timesync_entry_count == 0) {
73 if(timesync_entry_count < NUM_TIMESYNC_ENTRIES) {
74 timesync_entry_count++;
76 pos = (pos + 1) % NUM_TIMESYNC_ENTRIES;
79 for(i = 0; i < timesync_entry_count; ++i) {
82 return val / timesync_entry_count;
87 timesync_learn_drift_ticks(uint32_t time_delta_asn, int32_t drift_ticks)
90 uint32_t time_delta_ticks = time_delta_asn * tsch_timing[tsch_ts_timeslot_length];
91 int32_t real_drift_ticks = drift_ticks + compensated_ticks;
92 int32_t last_drift_ppm = (int32_t)((int64_t)real_drift_ticks * TSCH_DRIFT_UNIT / time_delta_ticks);
94 drift_ppm = timesync_entry_add(last_drift_ppm, time_delta_ticks);
99 tsch_timesync_update(
struct tsch_neighbor *n, uint16_t time_delta_asn, int32_t drift_correction)
104 if(last_timesource_neighbor != n) {
105 last_timesource_neighbor = n;
107 timesync_entry_count = 0;
108 compensated_ticks = 0;
109 asn_since_last_learning = 0;
111 asn_since_last_learning += time_delta_asn;
112 if(asn_since_last_learning >= 4 * TSCH_SLOTS_PER_SECOND) {
113 timesync_learn_drift_ticks(asn_since_last_learning, drift_correction);
114 compensated_ticks = 0;
115 asn_since_last_learning = 0;
118 compensated_ticks += drift_correction;
125 compensate_internal(uint32_t time_delta_usec, int32_t drift_ppm, int32_t *remainder, int16_t *tick_conversion_error)
127 int64_t d = (int64_t)time_delta_usec * drift_ppm + *remainder;
128 int32_t amount = d / TSCH_DRIFT_UNIT;
129 int32_t amount_ticks;
131 *remainder = (int32_t)(d - amount * TSCH_DRIFT_UNIT);
133 amount += *tick_conversion_error;
134 amount_ticks = US_TO_RTIMERTICKS(amount);
135 *tick_conversion_error = amount - RTIMERTICKS_TO_US(amount_ticks);
137 if(ABS(amount_ticks) > RTIMER_ARCH_SECOND / 128) {
138 TSCH_LOG_ADD(tsch_log_message,
139 snprintf(log->message,
sizeof(log->message),
140 "!too big compensation %ld delta %ld", amount_ticks, time_delta_usec));
141 amount_ticks = (amount_ticks > 0 ? RTIMER_ARCH_SECOND : -RTIMER_ARCH_SECOND) / 128;
149 tsch_timesync_adaptive_compensate(rtimer_clock_t time_delta_ticks)
152 uint32_t time_delta_usec = RTIMERTICKS_TO_US_64(time_delta_ticks);
155 if(drift_ppm && last_timesource_neighbor !=
NULL) {
156 static int32_t remainder;
157 static int16_t tick_conversion_error;
158 result = compensate_internal(time_delta_usec, drift_ppm,
159 &remainder, &tick_conversion_error);
160 compensated_ticks += result;
163 if(TSCH_BASE_DRIFT_PPM) {
164 static int32_t base_drift_remainder;
165 static int16_t base_drift_tick_conversion_error;
166 result += compensate_internal(time_delta_usec, 256L * TSCH_BASE_DRIFT_PPM,
167 &base_drift_remainder, &base_drift_tick_conversion_error);
176 tsch_timesync_update(
struct tsch_neighbor *n, uint16_t time_delta_asn, int32_t drift_correction)
181 tsch_timesync_adaptive_compensate(rtimer_clock_t delta_ticks)
#define NULL
The null pointer.