56 #include "lib/random.h"
72 #define PRINTF(...) printf(__VA_ARGS__)
77 #define WITH_ACK_OPTIMIZATION 0
78 #define WITH_PROBE_AFTER_RECEPTION 0
79 #define WITH_PROBE_AFTER_TRANSMISSION 0
80 #define WITH_ENCOUNTER_OPTIMIZATION 0
81 #define WITH_ADAPTIVE_OFF_TIME 0
82 #define WITH_PENDING_BROADCAST 0
83 #define WITH_STREAMING 1
85 #define LISTEN_TIME (CLOCK_SECOND / 128)
86 #define OFF_TIME (CLOCK_SECOND / NETSTACK_RDC_CHANNEL_CHECK_RATE - LISTEN_TIME)
88 #define PACKET_LIFETIME (LISTEN_TIME + OFF_TIME)
89 #define UNICAST_TIMEOUT (1 * PACKET_LIFETIME + PACKET_LIFETIME / 2)
90 #define PROBE_AFTER_TRANSMISSION_TIME (LISTEN_TIME * 2)
92 #define LOWEST_OFF_TIME (CLOCK_SECOND / 8)
94 #define ENCOUNTER_LIFETIME (16 * OFF_TIME)
96 #ifdef QUEUEBUF_CONF_NUM
97 #define MAX_QUEUED_PACKETS QUEUEBUF_CONF_NUM / 2
99 #define MAX_QUEUED_PACKETS 4
112 struct announcement_data {
117 #define ANNOUNCEMENT_MSG_HEADERLEN 2
118 struct announcement_msg {
120 struct announcement_data data[];
123 #define LPP_PROBE_HEADERLEN 2
133 static uint8_t lpp_is_on;
137 static struct pt dutycycle_pt;
138 static struct ctimer
timer;
140 static uint8_t is_listening = 0;
141 static clock_time_t off_time_adjustment = 0;
142 static clock_time_t off_time = OFF_TIME;
144 struct queue_list_item {
145 struct queue_list_item *
next;
146 struct queuebuf *packet;
147 struct ctimer removal_timer;
149 mac_callback_t sent_callback;
150 void *sent_callback_ptr;
151 uint8_t num_transmissions;
152 #if WITH_PENDING_BROADCAST
153 uint8_t broadcast_flag;
157 #define BROADCAST_FLAG_NONE 0
158 #define BROADCAST_FLAG_WAITING 1
159 #define BROADCAST_FLAG_PENDING 2
160 #define BROADCAST_FLAG_SEND 3
162 LIST(pending_packets_list);
163 LIST(queued_packets_list);
164 MEMB(queued_packets_memb,
struct queue_list_item, MAX_QUEUED_PACKETS);
167 struct encounter *
next;
170 struct ctimer remove_timer;
171 struct ctimer turn_on_radio_timer;
174 #define MAX_ENCOUNTERS 4
175 LIST(encounter_list);
176 MEMB(encounter_memb,
struct encounter, MAX_ENCOUNTERS);
178 static uint8_t is_streaming = 0;
180 static struct ctimer stream_probe_timer, stream_off_timer;
181 #define STREAM_PROBE_TIME CLOCK_SECOND / 128
182 #define STREAM_OFF_TIME CLOCK_SECOND / 2
186 #define MIN(a, b) ((a) < (b)? (a) : (b))
200 if(lpp_is_on && is_streaming == 0) {
201 NETSTACK_RADIO.off();
207 remove_encounter(
void *encounter)
209 struct encounter *e = encounter;
218 register_encounter(rimeaddr_t *neighbor, clock_time_t time)
226 ctimer_set(&e->remove_timer, ENCOUNTER_LIFETIME, remove_encounter, e);
239 ctimer_set(&e->remove_timer, ENCOUNTER_LIFETIME, remove_encounter, e);
244 #if WITH_ENCOUNTER_OPTIMIZATION
247 turn_radio_on_callback(
void *packet)
249 struct queue_list_item *p = packet;
261 stream_off(
void *dummy)
276 turn_radio_on_for_neighbor(rimeaddr_t *neighbor,
struct queue_list_item *i)
280 if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
281 PACKETBUF_ATTR_PACKET_TYPE_STREAM) {
285 ctimer_set(&stream_off_timer, STREAM_OFF_TIME,
292 #if ! WITH_PENDING_BROADCAST
301 #if WITH_ENCOUNTER_OPTIMIZATION
310 clock_time_t wait, now;
320 wait = (((clock_time_t)(e->time - now)) % (OFF_TIME + LISTEN_TIME)) -
335 ctimer_set(&e->turn_on_radio_timer, wait, turn_radio_on_callback, i);
352 remove_queued_packet(
struct queue_list_item *i, uint8_t tx_ok)
356 int num_transmissions = 0;
359 PRINTF(
"%d.%d: removing queued packet\n",
363 queuebuf_to_packetbuf(i->packet);
366 queuebuf_free(i->packet);
371 if(
list_length(queued_packets_list) == 0 && is_listening == 0) {
376 sent = i->sent_callback;
377 ptr = i->sent_callback_ptr;
378 num_transmissions = i->num_transmissions;
380 if(num_transmissions == 0 || tx_ok == 0) {
385 mac_call_sent_callback(sent, ptr, status, num_transmissions);
389 remove_queued_old_packet_callback(
void *item)
391 remove_queued_packet(item, 0);
394 #if WITH_PENDING_BROADCAST
397 remove_queued_broadcast_packet_callback(
void *item)
399 remove_queued_packet(item, 1);
403 set_broadcast_flag(
struct queue_list_item *i, uint8_t flag)
405 i->broadcast_flag = flag;
406 ctimer_set(&i->removal_timer, PACKET_LIFETIME,
407 remove_queued_broadcast_packet_callback, i);
412 listen_callback(
int periods)
414 is_listening = periods;
425 struct announcement_msg *adata;
432 hdr->type = TYPE_PROBE;
439 int hdrlen = NETSTACK_FRAMER.create();
447 adata = (
struct announcement_msg *)((
char *)hdr +
sizeof(
struct lpp_hdr));
451 adata->data[adata->num].id = a->id;
452 adata->data[adata->num].value = a->value;
457 ANNOUNCEMENT_MSG_HEADERLEN +
458 sizeof(
struct announcement_data) * adata->num);
464 if(NETSTACK_RADIO.channel_clear()) {
467 off_time_adjustment = random_rand() % (OFF_TIME / 2);
474 send_stream_probe(
void *dummy)
489 num_packets_to_send(
void)
491 #if WITH_PENDING_BROADCAST
492 struct queue_list_item *i;
496 if(i->broadcast_flag == BROADCAST_FLAG_SEND ||
497 i->broadcast_flag == BROADCAST_FLAG_NONE) {
515 struct ctimer *t = ptr;
521 #if WITH_PENDING_BROADCAST
528 if(p->broadcast_flag == BROADCAST_FLAG_WAITING) {
529 PRINTF(
"wait -> pending\n");
530 set_broadcast_flag(p, BROADCAST_FLAG_PENDING);
544 ctimer_set(t, LISTEN_TIME, (
void (*)(
void *))dutycycle, t);
547 #if WITH_PENDING_BROADCAST
549 struct queue_list_item *p;
556 if(p->broadcast_flag == BROADCAST_FLAG_PENDING) {
557 PRINTF(
"pending -> send\n");
558 set_broadcast_flag(p, BROADCAST_FLAG_SEND);
568 if(num_packets_to_send() == 0) {
572 if(is_listening == 0) {
573 int current_off_time;
574 if(!NETSTACK_RADIO.receiving_packet()) {
578 current_off_time = off_time - off_time_adjustment;
579 if(current_off_time < LISTEN_TIME * 2) {
580 current_off_time = LISTEN_TIME * 2;
582 off_time_adjustment = 0;
583 ctimer_set(t, current_off_time, (
void (*)(
void *))dutycycle, t);
586 #if WITH_ADAPTIVE_OFF_TIME
587 off_time += LOWEST_OFF_TIME;
588 if(off_time > OFF_TIME) {
597 ctimer_set(t, OFF_TIME, (
void (*)(
void *))dutycycle, t);
603 ctimer_set(t, off_time, (
void (*)(
void *))dutycycle, t);
612 restart_dutycycle(clock_time_t initial_wait)
633 send_packet(mac_callback_t sent,
void *ptr)
636 clock_time_t timeout;
637 uint8_t is_broadcast = 0;
640 rimeaddr_copy(&hdr.receiver, packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
644 hdr.type = TYPE_DATA;
650 packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
653 int hdrlen = NETSTACK_FRAMER.create();
656 mac_call_sent_callback(sent, ptr, MAC_TX_ERR_FATAL, 0);
661 PRINTF(
"%d.%d: queueing packet to %d.%d, channel %d\n",
663 hdr.receiver.u8[0], hdr.receiver.u8[1],
664 packetbuf_attr(PACKETBUF_ATTR_CHANNEL));
665 #if WITH_ACK_OPTIMIZATION
666 if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_ACK) {
669 mac_call_sent_callback(sent, ptr,
MAC_TX_OK, 1);
674 #if WITH_ADAPTIVE_OFF_TIME
675 off_time = LOWEST_OFF_TIME;
676 restart_dutycycle(off_time);
680 struct queue_list_item *i;
683 i->sent_callback = sent;
684 i->sent_callback_ptr = ptr;
685 i->num_transmissions = 0;
686 i->packet = queuebuf_new_from_packetbuf();
687 if(i->packet ==
NULL) {
689 printf(
"null packet\n");
690 mac_call_sent_callback(sent, ptr,
MAC_TX_ERR, 0);
694 timeout = PACKET_LIFETIME;
695 #if WITH_PENDING_BROADCAST
704 set_broadcast_flag(i, BROADCAST_FLAG_WAITING);
705 PRINTF(
"-> waiting\n");
708 timeout = UNICAST_TIMEOUT;
709 #if WITH_PENDING_BROADCAST
710 i->broadcast_flag = BROADCAST_FLAG_NONE;
714 remove_queued_old_packet_callback, i);
719 turn_radio_on_for_neighbor(&hdr.receiver, i);
723 printf(
"i == NULL\n");
724 mac_call_sent_callback(sent, ptr,
MAC_TX_ERR, 0);
732 #define INTER_PACKET_INTERVAL RTIMER_ARCH_SECOND / 5000
734 #define AFTER_ACK_DETECTECT_WAIT_TIME RTIMER_ARCH_SECOND / 1000
736 uint8_t ack_received = 0;
740 while(RTIMER_CLOCK_LT(
RTIMER_NOW(), wt + INTER_PACKET_INTERVAL)) { }
741 leds_off(LEDS_GREEN);
743 if((NETSTACK_RADIO.receiving_packet() ||
744 NETSTACK_RADIO.pending_packet() ||
745 NETSTACK_RADIO.channel_clear() == 0)) {
747 uint8_t ackbuf[ACK_LEN + 2];
750 while(RTIMER_CLOCK_LT(
RTIMER_NOW(), wt + AFTER_ACK_DETECTECT_WAIT_TIME)) { }
752 len = NETSTACK_RADIO.read(ackbuf, ACK_LEN);
758 leds_toggle(LEDS_RED);
773 clock_time_t reception_time;
777 if(!NETSTACK_FRAMER.parse()) {
778 printf(
"lpp input_packet framer error\n");
785 if(hdr.type == TYPE_PROBE) {
786 struct announcement_msg adata;
790 register_encounter(&hdr.sender, reception_time);
796 PRINTF(
"%d.%d: probe from %d.%d with %d announcements\n",
798 hdr.sender.u8[0], hdr.sender.u8[1], adata->num);
800 if(adata.num /
sizeof(
struct announcement_data) >
sizeof(
struct announcement_msg)) {
806 for(i = 0; i < adata.num; ++i) {
814 adata.data[i].value);
822 struct queue_list_item *i;
824 const rimeaddr_t *receiver;
829 receiver = queuebuf_addr(i->packet, PACKETBUF_ADDR_RECEIVER);
832 queuebuf_to_packetbuf(i->packet);
834 #if WITH_PENDING_BROADCAST
835 if(i->broadcast_flag == BROADCAST_FLAG_NONE ||
836 i->broadcast_flag == BROADCAST_FLAG_SEND) {
837 i->num_transmissions = 1;
838 NETSTACK_RADIO.send(queuebuf_dataptr(i->packet),
839 queuebuf_datalen(i->packet));
841 PRINTF(
"%d.%d: got a probe from %d.%d, sent packet to %d.%d\n",
843 hdr.sender.u8[0], hdr.sender.u8[1],
844 receiver->u8[0], receiver->u8[1]);
847 PRINTF(
"%d.%d: got a probe from %d.%d, did not send packet\n",
849 hdr.sender.u8[0], hdr.sender.u8[1]);
852 i->num_transmissions = 1;
853 NETSTACK_RADIO.send(queuebuf_dataptr(i->packet),
854 queuebuf_datalen(i->packet));
855 PRINTF(
"%d.%d: got a probe from %d.%d, sent packet to %d.%d\n",
857 hdr.sender.u8[0], hdr.sender.u8[1],
858 receiver->u8[0], receiver->u8[1]);
873 remove_queued_packet(i, 1);
875 remove_queued_packet(i, 0);
878 #if WITH_PROBE_AFTER_TRANSMISSION
880 restart_dutycycle(PROBE_AFTER_TRANSMISSION_TIME);
885 ctimer_set(&stream_probe_timer, STREAM_PROBE_TIME,
886 send_stream_probe,
NULL);
895 #if WITH_ACK_OPTIMIZATION
896 if(packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ||
897 packetbuf_attr(PACKETBUF_ATTR_ERELIABLE)) {
908 }
else if(hdr.type == TYPE_DATA) {
913 PRINTF(
"%d.%d: data not for us from %d.%d\n",
915 hdr.sender.u8[0], hdr.sender.u8[1]);
918 packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &hdr.receiver);
920 packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &hdr.sender);
922 PRINTF(
"%d.%d: got data from %d.%d\n",
924 hdr.sender.u8[0], hdr.sender.u8[1]);
938 #if WITH_PENDING_BROADCAST
946 struct queue_list_item *i;
950 if(i->broadcast_flag == BROADCAST_FLAG_PENDING) {
951 PRINTF(
"Someone else is sending, pending -> waiting\n");
952 set_broadcast_flag(i, BROADCAST_FLAG_WAITING);
959 #if WITH_PROBE_AFTER_RECEPTION
965 q = queuebuf_new_from_packetbuf();
968 queuebuf_to_packetbuf(q);
974 #if WITH_ADAPTIVE_OFF_TIME
975 off_time = LOWEST_OFF_TIME;
976 restart_dutycycle(off_time);
979 NETSTACK_MAC.input();
992 off(
int keep_radio_on)
1003 static unsigned short
1004 channel_check_interval(
void)
1006 return OFF_TIME + LISTEN_TIME;
1012 restart_dutycycle(random_rand() % OFF_TIME);