44 #include "contiki-conf.h"
48 #include "lib/random.h"
54 #define PRINTF(...) printf(__VA_ARGS__)
63 #if TRICKLE_TIMER_WIDE_RAND
64 #define tt_rand() wide_rand()
66 #define tt_rand() random_rand()
72 static clock_time_t loc_clock;
74 static void fire(
void *ptr);
75 static void double_interval(
void *ptr);
79 #if TRICKLE_TIMER_WIDE_RAND
96 #if TRICKLE_TIMER_ERROR_CHECKING
98 max_imax(clock_time_t value)
101 #if (TRICKLE_TIMER_MAX_IMAX_WIDTH==TRICKLE_TIMER_MAX_IMAX_GENERIC)
103 clock_time_t mask = 0xFFFF;
107 for(i =
sizeof(clock_time_t) << 2; i > 0; i >>= 1) {
108 if((value & (mask <<= i)) == 0) {
114 #elif (TRICKLE_TIMER_MAX_IMAX_WIDTH==TRICKLE_TIMER_MAX_IMAX_16_BIT)
115 if((value & 0xFF00) == 0) {
119 if((value & 0xF000) == 0) {
123 if((value & 0xC000) == 0) {
127 if((value & 0x8000) == 0) {
130 #elif (TRICKLE_TIMER_MAX_IMAX_WIDTH==TRICKLE_TIMER_MAX_IMAX_32_BIT)
131 if((value & 0xFFFF0000) == 0) {
135 if((value & 0xFF000000) == 0) {
139 if((value & 0xF0000000) == 0) {
143 if((value & 0xC0000000) == 0) {
147 if((value & 0x80000000) == 0) {
158 get_t(clock_time_t
i_cur)
162 PRINTF(
"trickle_timer get t: [%lu, %lu)\n", (
unsigned long)i_cur,
163 (
unsigned long)(i_cur << 1));
176 PRINTF(
"trickle_timer sched for end: at %lu, end in %ld\n",
177 (
unsigned long)
clock_time(), (
signed long)loc_clock);
183 PRINTF(
"trickle_timer doubling: Was in the past. Compensating\n");
192 double_interval(
void *ptr)
194 clock_time_t last_end;
201 PRINTF(
"trickle_timer doubling: at %lu, (was for %lu), ",
212 PRINTF(
"I << 1 = %lu\n", (
unsigned long)loctt->
i_cur);
217 PRINTF(
"I = Imax = %lu\n", (
unsigned long)loctt->
i_cur);
221 loc_clock = get_t(loctt->
i_cur);
223 PRINTF(
"trickle_timer doubling: t=%lu\n", (
unsigned long)loc_clock);
225 #if TRICKLE_TIMER_COMPENSATE_DRIFT
228 loc_clock = (last_end + loc_clock) -
clock_time();
229 PRINTF(
"trickle_timer doubling: at %lu, in %ld ticks\n",
230 (
unsigned long)
clock_time(), (
signed long)loc_clock);
234 PRINTF(
"trickle_timer doubling: Was in the past. Compensating\n");
246 loctt->
i_start = loctt->
ct.etimer.timer.start;
249 PRINTF(
"trickle_timer doubling: Last end %lu, new end %lu, for %lu, I=%lu\n",
250 (
unsigned long)last_end,
252 (
unsigned long)(loctt->
ct.etimer.timer.start +
253 loctt->
ct.etimer.timer.interval),
254 (
unsigned long)(loctt->
i_cur));
265 PRINTF(
"trickle_timer fire: at %lu (was for %lu)\n",
267 (
unsigned long)(loctt->
ct.etimer.timer.start +
268 loctt->
ct.etimer.timer.interval));
275 PRINTF(
"trickle_timer fire: Suppression Status %u (%u < %u)\n",
281 schedule_for_end(loctt);
293 loc_clock = get_t(tt->
i_cur);
299 PRINTF(
"trickle_timer new interval: at %lu, ends %lu, ",
302 PRINTF(
"t=%lu, I=%lu\n", (
unsigned long)loc_clock, (
unsigned long)tt->
i_cur);
313 PRINTF(
"trickle_timer consistency: c=%u\n", tt->
c);
322 PRINTF(
"trickle_timer inconsistency\n");
333 #if TRICKLE_TIMER_ERROR_CHECKING
340 PRINTF(
"trickle_timer config: Bad Imin value\n");
341 return TRICKLE_TIMER_ERROR;
344 if(tt ==
NULL || i_max == 0 || k == 0) {
345 PRINTF(
"trickle_timer config: Bad arguments\n");
346 return TRICKLE_TIMER_ERROR;
356 PRINTF(
"trickle_timer config: %lu << %u would exceed clock boundaries. ",
357 (
unsigned long)i_min, i_max);
360 i_max = max_imax(i_min);
361 PRINTF(
"trickle_timer config: Using Imax=%u\n", i_max);
370 PRINTF(
"trickle_timer config: Imin=%lu, Imax=%u, k=%u\n",
373 return TRICKLE_TIMER_SUCCESS;
380 #if TRICKLE_TIMER_ERROR_CHECKING
382 if(tt ==
NULL || proto_cb ==
NULL) {
383 PRINTF(
"trickle_timer set: Bad arguments\n");
384 return TRICKLE_TIMER_ERROR;
395 PRINTF(
"trickle_timer set: I=%lu in [%lu , %lu]\n", (
unsigned long)tt->
i_cur,
396 (
unsigned long)tt->
i_min,
401 PRINTF(
"trickle_timer set: at %lu, ends %lu, t=%lu in [%lu , %lu)\n",
404 (
unsigned long)tt->
ct.etimer.timer.interval,
405 (
unsigned long)tt->
i_cur >> 1, (
unsigned long)tt->
i_cur);
407 return TRICKLE_TIMER_SUCCESS;
void trickle_timer_inconsistency(struct trickle_timer *tt)
To be called by the protocol when it hears an inconsistent transmission.
#define TRICKLE_TIMER_IPAIR_IS_BAD(i_min, i_max)
Checks whether Imin << Imax is unsuitable considering the boundaries of our platform's clock_time_t...
uint8_t i_max
Imax: Max number of doublings.
trickle_timer_cb_t cb
Protocol's own callback, invoked at time t within the current interval.
clock_time_t i_cur
I: Current interval in clock_ticks.
#define TRICKLE_TIMER_PROTO_TX_ALLOW(tt)
Determines whether the protocol must go ahead with a transmission.
struct ctimer ct
A Callback timer used internally.
clock_time_t i_min
Imin: Clock ticks.
clock_time_t i_start
Start of this interval (absolute clock_time)
#define NULL
The null pointer.
Default definitions of C compiler quirk work-arounds.
clock_time_t i_max_abs
Maximum interval size in clock ticks (and not in number of doublings).
uint8_t c
c: Consistency Counter
CCIF clock_time_t clock_time(void)
Get the current clock time.
uint8_t k
k: Redundancy Constant
uint8_t trickle_timer_set(struct trickle_timer *tt, trickle_timer_cb_t proto_cb, void *ptr)
Start a previously configured trickle timer.
#define TRICKLE_TIMER_CLOCK_MAX
cross-platform method to get the maximum clock_time_t value
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
void(* trickle_timer_cb_t)(void *ptr, uint8_t suppress)
typedef for a callback function to be defined in the protocol's implementation.
#define tt_rand()
Wide randoms for platforms using a 4-byte wide clock (see TRICKLE_TIMER_WIDE_RAND) ...
Trickle timer library header file.
void trickle_timer_consistency(struct trickle_timer *tt)
To be called by the protocol when it hears a consistent transmission.
#define TRICKLE_TIMER_INTERVAL_END(tt)
Returns the current trickle interval's end (absolute time in ticks)
Header file for the callback timer
uint8_t trickle_timer_config(struct trickle_timer *tt, clock_time_t i_min, uint8_t i_max, uint8_t k)
Configure a trickle timer.
void * cb_arg
Opaque pointer to be used as the argument of the protocol's callback.
#define trickle_timer_is_running(tt)
To be called in order to determine whether a trickle timer is running.
#define TRICKLE_TIMER_INTERVAL_MAX(tt)
Returns a timer's maximum interval size (Imin << Imax) as a number of clock ticks.
#define TRICKLE_TIMER_IMIN_IS_BAD(imin)
Checks whether an Imin value is invalid considering the various restrictions imposed by our platform'...
unsigned short random_rand(void)
Generate the next state and return the upper part of it.