42 #include "sys/clock.h"
45 #include "net/nbr-table.h"
47 #if PHASE_CONF_DRIFT_CORRECT
48 #define PHASE_DRIFT_CORRECT PHASE_CONF_DRIFT_CORRECT
50 #define PHASE_DRIFT_CORRECT 0
55 #if PHASE_DRIFT_CORRECT
59 struct timer noacks_timer;
62 struct phase_queueitem {
64 mac_callback_t mac_callback;
65 void *mac_callback_ptr;
67 struct rdc_buf_list *buf_list;
70 #define PHASE_DEFER_THRESHOLD 1
71 #define PHASE_QUEUESIZE 8
75 #define MAX_NOACKS_TIME CLOCK_SECOND * 30
77 MEMB(queued_packets_memb,
struct phase_queueitem, PHASE_QUEUESIZE);
78 NBR_TABLE(
struct phase, nbr_phase);
83 #define PRINTF(...) printf(__VA_ARGS__)
84 #define PRINTDEBUG(...) printf(__VA_ARGS__)
87 #define PRINTDEBUG(...)
91 phase_update(
const linkaddr_t *neighbor, rtimer_clock_t time,
97 e = nbr_table_get_from_lladdr(nbr_phase, neighbor);
100 #if PHASE_DRIFT_CORRECT
101 e->drift = time-e->time;
109 PRINTF(
"phase noacks %d to %d.%d\n", e->noacks, neighbor->u8[0], neighbor->u8[1]);
112 timer_set(&e->noacks_timer, MAX_NOACKS_TIME);
114 if(e->noacks >= MAX_NOACKS ||
timer_expired(&e->noacks_timer)) {
115 PRINTF(
"drop %d\n", neighbor->u8[0]);
116 nbr_table_remove(nbr_phase, e);
125 e = nbr_table_add_lladdr(nbr_phase, neighbor);
128 #if PHASE_DRIFT_CORRECT
138 send_packet(
void *ptr)
140 struct phase_queueitem *p = ptr;
142 if(p->buf_list ==
NULL) {
143 queuebuf_to_packetbuf(p->q);
145 NETSTACK_RDC.send(p->mac_callback, p->mac_callback_ptr);
147 NETSTACK_RDC.send_list(p->mac_callback, p->mac_callback_ptr, p->buf_list);
154 phase_wait(
const linkaddr_t *neighbor, rtimer_clock_t cycle_time,
155 rtimer_clock_t guard_time,
156 mac_callback_t mac_callback,
void *mac_callback_ptr,
157 struct rdc_buf_list *buf_list)
165 e = nbr_table_get_from_lladdr(nbr_phase, neighbor);
167 rtimer_clock_t wait, now, expected, sync;
168 clock_time_t ctimewait;
186 sync = (e ==
NULL) ? now : e->time;
188 #
if PHASE_DRIFT_CORRECT
191 if(e->drift > cycle_time) {
192 s = e->drift % cycle_time / (e->drift / cycle_time);
193 s = s * (now - sync) / cycle_time;
200 if(!(cycle_time & (cycle_time - 1))) {
202 wait = (rtimer_clock_t)((sync - now) & (cycle_time - 1));
205 wait = cycle_time - (rtimer_clock_t)((now - sync) % cycle_time);
208 if(wait < guard_time) {
212 ctimewait = (
CLOCK_SECOND * (wait - guard_time)) / RTIMER_ARCH_SECOND;
214 if(ctimewait > PHASE_DEFER_THRESHOLD) {
215 struct phase_queueitem *p;
219 if(buf_list ==
NULL) {
220 packetbuf_set_attr(PACKETBUF_ATTR_IS_CREATED_AND_SECURED, 1);
221 p->q = queuebuf_new_from_packetbuf();
223 p->mac_callback = mac_callback;
224 p->mac_callback_ptr = mac_callback_ptr;
225 p->buf_list = buf_list;
226 ctimer_set(&p->timer, ctimewait, send_packet, p);
227 return PHASE_DEFERRED;
231 expected = now + wait - guard_time;
232 if(!RTIMER_CLOCK_LT(expected, now)) {
234 while(RTIMER_CLOCK_LT(
RTIMER_NOW(), expected));
236 return PHASE_SEND_NOW;
238 return PHASE_UNKNOWN;
245 nbr_table_register(nbr_phase,
NULL);
Common functionality for phase optimization in duty cycling radio protocols
void memb_init(struct memb *m)
Initialize a memory block that was declared with MEMB().
The MAC layer deferred the transmission for a later time.
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
char memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
Header file for the Rime buffer (packetbuf) management
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
#define NULL
The null pointer.
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
#define MEMB(name, structure, num)
Declare a memory block.
Header file for the Rime queue buffer management
Header file for the callback timer
The MAC layer transmission was OK.
#define RTIMER_NOW()
Get the current clock time.
int timer_expired(struct timer *t)
Check if a timer has expired.
#define CLOCK_SECOND
A second, measured in system clock time.