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()
72static clock_time_t loc_clock;
74static void fire(
void *ptr);
75static void double_interval(
void *ptr);
79#if TRICKLE_TIMER_WIDE_RAND
96#if TRICKLE_TIMER_ERROR_CHECKING
98max_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) {
158get_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");
192double_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);
316 PRINTF(
"trickle_timer consistency: c=%u\n", tt->
c);
328 PRINTF(
"trickle_timer inconsistency\n");
339#if TRICKLE_TIMER_ERROR_CHECKING
346 PRINTF(
"trickle_timer config: Bad Imin value\n");
347 return TRICKLE_TIMER_ERROR;
350 if(tt == NULL ||
i_max == 0 ||
k == 0) {
351 PRINTF(
"trickle_timer config: Bad arguments\n");
352 return TRICKLE_TIMER_ERROR;
362 PRINTF(
"trickle_timer config: %lu << %u would exceed clock boundaries. ",
367 PRINTF(
"trickle_timer config: Using Imax=%u\n",
i_max);
378 PRINTF(
"trickle_timer config: Imin=%lu, Imax=%u, k=%u\n",
381 return TRICKLE_TIMER_SUCCESS;
388#if TRICKLE_TIMER_ERROR_CHECKING
390 if(tt == NULL || proto_cb == NULL) {
391 PRINTF(
"trickle_timer set: Bad arguments\n");
392 return TRICKLE_TIMER_ERROR;
403 PRINTF(
"trickle_timer set: I=%lu in [%lu , %lu]\n", (
unsigned long)tt->
i_cur,
404 (
unsigned long)tt->
i_min,
409 PRINTF(
"trickle_timer set: at %lu, ends %lu, t=%lu in [%lu , %lu)\n",
412 (
unsigned long)tt->
ct.etimer.timer.interval,
413 (
unsigned long)tt->
i_cur >> 1, (
unsigned long)tt->
i_cur);
415 return TRICKLE_TIMER_SUCCESS;
Default definitions of C compiler quirk work-arounds.
Header file for the callback timer.
clock_time_t clock_time(void)
Get the current clock time.
unsigned short random_rand(void)
Generates a new random number using the cc2538 RNG.
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
#define TRICKLE_TIMER_INTERVAL_MAX(tt)
Returns a timer's maximum interval size (Imin << Imax) as a number of clock ticks.
#define TRICKLE_TIMER_PROTO_TX_ALLOW(tt)
Determines whether the protocol must go ahead with a transmission.
void(* trickle_timer_cb_t)(void *ptr, uint8_t suppress)
typedef for a callback function to be defined in the protocol's implementation.
#define TRICKLE_TIMER_IS_STOPPED
A trickle timer is considered 'stopped' when i_cur == TRICKLE_TIMER_IS_STOPPED.
#define TRICKLE_TIMER_IMIN_IS_BAD(imin)
Checks whether an Imin value is invalid considering the various restrictions imposed by our platform'...
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.
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_is_running(tt)
To be called in order to determine whether a trickle timer is running.
#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.
#define TRICKLE_TIMER_CLOCK_MAX
cross-platform method to get the maximum clock_time_t value
void trickle_timer_inconsistency(struct trickle_timer *tt)
To be called by the protocol when it hears an inconsistent transmission.
#define TRICKLE_TIMER_INTERVAL_END(tt)
Returns the current trickle interval's end (absolute time in ticks)
#define tt_rand()
Wide randoms for platforms using a 4-byte wide clock (see TRICKLE_TIMER_WIDE_RAND)
void trickle_timer_consistency(struct trickle_timer *tt)
To be called by the protocol when it hears a consistent transmission.
uint8_t c
c: Consistency Counter
void * cb_arg
Opaque pointer to be used as the argument of the protocol's callback.
clock_time_t i_cur
I: Current interval in clock_ticks.
uint8_t i_max
Imax: Max number of doublings.
clock_time_t i_max_abs
Maximum interval size in clock ticks (and not in number of doublings).
uint8_t k
k: Redundancy Constant
trickle_timer_cb_t cb
Protocol's own callback, invoked at time t within the current interval.
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)
Trickle timer library header file.