00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #include "dev/leds.h"
00054 #include "lib/list.h"
00055 #include "lib/memb.h"
00056 #include "lib/random.h"
00057 #include "net/rime.h"
00058 #include "net/netstack.h"
00059 #include "net/mac/mac.h"
00060 #include "net/mac/lpp.h"
00061 #include "net/packetbuf.h"
00062 #include "net/rime/announcement.h"
00063 #include "sys/compower.h"
00064
00065 #include <stdlib.h>
00066 #include <stdio.h>
00067 #include <string.h>
00068
00069 #define DEBUG 0
00070 #if DEBUG
00071 #include <stdio.h>
00072 #define PRINTF(...) printf(__VA_ARGS__)
00073 #else
00074 #define PRINTF(...)
00075 #endif
00076
00077 #define WITH_ACK_OPTIMIZATION 0
00078 #define WITH_PROBE_AFTER_RECEPTION 0
00079 #define WITH_PROBE_AFTER_TRANSMISSION 0
00080 #define WITH_ENCOUNTER_OPTIMIZATION 0
00081 #define WITH_ADAPTIVE_OFF_TIME 0
00082 #define WITH_PENDING_BROADCAST 0
00083 #define WITH_STREAMING 1
00084
00085 #define LISTEN_TIME (CLOCK_SECOND / 128)
00086 #define OFF_TIME (CLOCK_SECOND / NETSTACK_RDC_CHANNEL_CHECK_RATE - LISTEN_TIME)
00087
00088 #define PACKET_LIFETIME (LISTEN_TIME + OFF_TIME)
00089 #define UNICAST_TIMEOUT (1 * PACKET_LIFETIME + PACKET_LIFETIME / 2)
00090 #define PROBE_AFTER_TRANSMISSION_TIME (LISTEN_TIME * 2)
00091
00092 #define LOWEST_OFF_TIME (CLOCK_SECOND / 8)
00093
00094 #define ENCOUNTER_LIFETIME (16 * OFF_TIME)
00095
00096 #ifdef QUEUEBUF_CONF_NUM
00097 #define MAX_QUEUED_PACKETS QUEUEBUF_CONF_NUM / 2
00098 #else
00099 #define MAX_QUEUED_PACKETS 4
00100 #endif
00101
00102
00103
00104
00105
00106
00107 #if OFF_TIME < 2
00108 #undef OFF_TIME
00109 #define OFF_TIME 2
00110 #endif
00111
00112 struct announcement_data {
00113 uint16_t id;
00114 uint16_t value;
00115 };
00116
00117 #define ANNOUNCEMENT_MSG_HEADERLEN 2
00118 struct announcement_msg {
00119 uint16_t num;
00120 struct announcement_data data[];
00121 };
00122
00123 #define LPP_PROBE_HEADERLEN 2
00124
00125 #define TYPE_PROBE 1
00126 #define TYPE_DATA 2
00127 struct lpp_hdr {
00128 uint16_t type;
00129 rimeaddr_t sender;
00130 rimeaddr_t receiver;
00131 };
00132
00133 static uint8_t lpp_is_on;
00134
00135 static struct compower_activity current_packet;
00136
00137 static struct pt dutycycle_pt;
00138 static struct ctimer timer;
00139
00140 static uint8_t is_listening = 0;
00141 static clock_time_t off_time_adjustment = 0;
00142 static clock_time_t off_time = OFF_TIME;
00143
00144 struct queue_list_item {
00145 struct queue_list_item *next;
00146 struct queuebuf *packet;
00147 struct ctimer removal_timer;
00148 struct compower_activity compower;
00149 mac_callback_t sent_callback;
00150 void *sent_callback_ptr;
00151 uint8_t num_transmissions;
00152 #if WITH_PENDING_BROADCAST
00153 uint8_t broadcast_flag;
00154 #endif
00155 };
00156
00157 #define BROADCAST_FLAG_NONE 0
00158 #define BROADCAST_FLAG_WAITING 1
00159 #define BROADCAST_FLAG_PENDING 2
00160 #define BROADCAST_FLAG_SEND 3
00161
00162 LIST(pending_packets_list);
00163 LIST(queued_packets_list);
00164 MEMB(queued_packets_memb, struct queue_list_item, MAX_QUEUED_PACKETS);
00165
00166 struct encounter {
00167 struct encounter *next;
00168 rimeaddr_t neighbor;
00169 clock_time_t time;
00170 struct ctimer remove_timer;
00171 struct ctimer turn_on_radio_timer;
00172 };
00173
00174 #define MAX_ENCOUNTERS 4
00175 LIST(encounter_list);
00176 MEMB(encounter_memb, struct encounter, MAX_ENCOUNTERS);
00177
00178 static uint8_t is_streaming = 0;
00179 #if WITH_STREAMING
00180 static struct ctimer stream_probe_timer, stream_off_timer;
00181 #define STREAM_PROBE_TIME CLOCK_SECOND / 128
00182 #define STREAM_OFF_TIME CLOCK_SECOND / 2
00183 #endif
00184
00185 #ifndef MIN
00186 #define MIN(a, b) ((a) < (b)? (a) : (b))
00187 #endif
00188
00189
00190 static void
00191 turn_radio_on(void)
00192 {
00193 NETSTACK_RADIO.on();
00194
00195 }
00196
00197 static void
00198 turn_radio_off(void)
00199 {
00200 if(lpp_is_on && is_streaming == 0) {
00201 NETSTACK_RADIO.off();
00202 }
00203
00204 }
00205
00206 static void
00207 remove_encounter(void *encounter)
00208 {
00209 struct encounter *e = encounter;
00210
00211 ctimer_stop(&e->remove_timer);
00212 ctimer_stop(&e->turn_on_radio_timer);
00213 list_remove(encounter_list, e);
00214 memb_free(&encounter_memb, e);
00215 }
00216
00217 static void
00218 register_encounter(rimeaddr_t *neighbor, clock_time_t time)
00219 {
00220 struct encounter *e;
00221
00222
00223 for(e = list_head(encounter_list); e != NULL; e = list_item_next(e)) {
00224 if(rimeaddr_cmp(neighbor, &e->neighbor)) {
00225 e->time = time;
00226 ctimer_set(&e->remove_timer, ENCOUNTER_LIFETIME, remove_encounter, e);
00227 break;
00228 }
00229 }
00230
00231 if(e == NULL) {
00232 e = memb_alloc(&encounter_memb);
00233 if(e == NULL) {
00234
00235 return;
00236 }
00237 rimeaddr_copy(&e->neighbor, neighbor);
00238 e->time = time;
00239 ctimer_set(&e->remove_timer, ENCOUNTER_LIFETIME, remove_encounter, e);
00240 list_add(encounter_list, e);
00241 }
00242 }
00243
00244 #if WITH_ENCOUNTER_OPTIMIZATION
00245
00246 static void
00247 turn_radio_on_callback(void *packet)
00248 {
00249 struct queue_list_item *p = packet;
00250
00251 list_remove(pending_packets_list, p);
00252 list_add(queued_packets_list, p);
00253 turn_radio_on();
00254
00255
00256 }
00257 #endif
00258
00259
00260 static void
00261 stream_off(void *dummy)
00262 {
00263 is_streaming = 0;
00264 }
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 static void
00276 turn_radio_on_for_neighbor(rimeaddr_t *neighbor, struct queue_list_item *i)
00277 {
00278
00279 #if WITH_STREAMING
00280 if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
00281 PACKETBUF_ATTR_PACKET_TYPE_STREAM) {
00282 is_streaming = 1;
00283 turn_radio_on();
00284 list_add(queued_packets_list, i);
00285 ctimer_set(&stream_off_timer, STREAM_OFF_TIME,
00286 stream_off, NULL);
00287 return;
00288 }
00289 #endif
00290
00291 if(rimeaddr_cmp(neighbor, &rimeaddr_null)) {
00292 #if ! WITH_PENDING_BROADCAST
00293
00294
00295 turn_radio_on();
00296 #endif
00297 list_add(queued_packets_list, i);
00298 return;
00299 }
00300
00301 #if WITH_ENCOUNTER_OPTIMIZATION
00302 struct encounter *e;
00303
00304
00305
00306
00307
00308 for(e = list_head(encounter_list); e != NULL; e = list_item_next(e)) {
00309 if(rimeaddr_cmp(neighbor, &e->neighbor)) {
00310 clock_time_t wait, now;
00311
00312
00313
00314
00315
00316
00317
00318
00319 now = clock_time();
00320 wait = (((clock_time_t)(e->time - now)) % (OFF_TIME + LISTEN_TIME)) -
00321 2 * LISTEN_TIME;
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 ctimer_set(&e->turn_on_radio_timer, wait, turn_radio_on_callback, i);
00336 list_add(pending_packets_list, i);
00337 return;
00338 }
00339 }
00340 #endif
00341
00342
00343
00344
00345
00346 turn_radio_on();
00347 list_add(queued_packets_list, i);
00348 return;
00349 }
00350
00351 static void
00352 remove_queued_packet(struct queue_list_item *i, uint8_t tx_ok)
00353 {
00354 mac_callback_t sent;
00355 void *ptr;
00356 int num_transmissions = 0;
00357 int status;
00358
00359 PRINTF("%d.%d: removing queued packet\n",
00360 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]);
00361
00362
00363 queuebuf_to_packetbuf(i->packet);
00364
00365 ctimer_stop(&i->removal_timer);
00366 queuebuf_free(i->packet);
00367 list_remove(pending_packets_list, i);
00368 list_remove(queued_packets_list, i);
00369
00370
00371 if(list_length(queued_packets_list) == 0 && is_listening == 0) {
00372 turn_radio_off();
00373 compower_accumulate(&i->compower);
00374 }
00375
00376 sent = i->sent_callback;
00377 ptr = i->sent_callback_ptr;
00378 num_transmissions = i->num_transmissions;
00379 memb_free(&queued_packets_memb, i);
00380 if(num_transmissions == 0 || tx_ok == 0) {
00381 status = MAC_TX_NOACK;
00382 } else {
00383 status = MAC_TX_OK;
00384 }
00385 mac_call_sent_callback(sent, ptr, status, num_transmissions);
00386 }
00387
00388 static void
00389 remove_queued_old_packet_callback(void *item)
00390 {
00391 remove_queued_packet(item, 0);
00392 }
00393
00394 #if WITH_PENDING_BROADCAST
00395
00396 static void
00397 remove_queued_broadcast_packet_callback(void *item)
00398 {
00399 remove_queued_packet(item, 1);
00400 }
00401
00402 static void
00403 set_broadcast_flag(struct queue_list_item *i, uint8_t flag)
00404 {
00405 i->broadcast_flag = flag;
00406 ctimer_set(&i->removal_timer, PACKET_LIFETIME,
00407 remove_queued_broadcast_packet_callback, i);
00408 }
00409 #endif
00410
00411 static void
00412 listen_callback(int periods)
00413 {
00414 is_listening = periods;
00415 turn_radio_on();
00416 }
00417
00418
00419
00420
00421 static void
00422 send_probe(void)
00423 {
00424 struct lpp_hdr *hdr;
00425 struct announcement_msg *adata;
00426 struct announcement *a;
00427
00428
00429 packetbuf_clear();
00430 packetbuf_set_datalen(sizeof(struct lpp_hdr));
00431 hdr = packetbuf_dataptr();
00432 hdr->type = TYPE_PROBE;
00433 rimeaddr_copy(&hdr->sender, &rimeaddr_node_addr);
00434
00435 rimeaddr_copy(&hdr->receiver, &rimeaddr_null);
00436
00437 packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &rimeaddr_null);
00438 {
00439 int hdrlen = NETSTACK_FRAMER.create();
00440 if(hdrlen == 0) {
00441
00442 return;
00443 }
00444 }
00445
00446
00447 adata = (struct announcement_msg *)((char *)hdr + sizeof(struct lpp_hdr));
00448
00449 adata->num = 0;
00450 for(a = announcement_list(); a != NULL; a = list_item_next(a)) {
00451 adata->data[adata->num].id = a->id;
00452 adata->data[adata->num].value = a->value;
00453 adata->num++;
00454 }
00455
00456 packetbuf_set_datalen(sizeof(struct lpp_hdr) +
00457 ANNOUNCEMENT_MSG_HEADERLEN +
00458 sizeof(struct announcement_data) * adata->num);
00459
00460
00461
00462
00463
00464 if(NETSTACK_RADIO.channel_clear()) {
00465 NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
00466 } else {
00467 off_time_adjustment = random_rand() % (OFF_TIME / 2);
00468 }
00469
00470 compower_accumulate(&compower_idle_activity);
00471 }
00472
00473 static void
00474 send_stream_probe(void *dummy)
00475 {
00476
00477
00478 turn_radio_on();
00479
00480
00481 send_probe();
00482
00483 #if WITH_STREAMING
00484 is_streaming = 1;
00485 #endif
00486 }
00487
00488 static int
00489 num_packets_to_send(void)
00490 {
00491 #if WITH_PENDING_BROADCAST
00492 struct queue_list_item *i;
00493 int num = 0;
00494
00495 for(i = list_head(queued_packets_list); i != NULL; i = list_item_next(i)) {
00496 if(i->broadcast_flag == BROADCAST_FLAG_SEND ||
00497 i->broadcast_flag == BROADCAST_FLAG_NONE) {
00498 ++num;
00499 }
00500 }
00501 return num;
00502 #else
00503 return list_length(queued_packets_list);
00504 #endif
00505 }
00506
00507
00508
00509
00510
00511
00512 static int
00513 dutycycle(void *ptr)
00514 {
00515 struct ctimer *t = ptr;
00516
00517 PT_BEGIN(&dutycycle_pt);
00518
00519 while(1) {
00520
00521 #if WITH_PENDING_BROADCAST
00522 {
00523
00524
00525
00526
00527 for(p = list_head(queued_packets_list); p != NULL; p = list_item_next(p)) {
00528 if(p->broadcast_flag == BROADCAST_FLAG_WAITING) {
00529 PRINTF("wait -> pending\n");
00530 set_broadcast_flag(p, BROADCAST_FLAG_PENDING);
00531 }
00532 }
00533 }
00534 #endif
00535
00536
00537
00538 turn_radio_on();
00539
00540
00541 send_probe();
00542
00543
00544 ctimer_set(t, LISTEN_TIME, (void (*)(void *))dutycycle, t);
00545 PT_YIELD(&dutycycle_pt);
00546
00547 #if WITH_PENDING_BROADCAST
00548 {
00549 struct queue_list_item *p;
00550
00551
00552
00553
00554
00555 for(p = list_head(queued_packets_list); p != NULL; p = list_item_next(p)) {
00556 if(p->broadcast_flag == BROADCAST_FLAG_PENDING) {
00557 PRINTF("pending -> send\n");
00558 set_broadcast_flag(p, BROADCAST_FLAG_SEND);
00559 turn_radio_on();
00560 }
00561 }
00562 }
00563 #endif
00564
00565
00566
00567
00568 if(num_packets_to_send() == 0) {
00569
00570
00571
00572 if(is_listening == 0) {
00573 int current_off_time;
00574 if(!NETSTACK_RADIO.receiving_packet()) {
00575 turn_radio_off();
00576 compower_accumulate(&compower_idle_activity);
00577 }
00578 current_off_time = off_time - off_time_adjustment;
00579 if(current_off_time < LISTEN_TIME * 2) {
00580 current_off_time = LISTEN_TIME * 2;
00581 }
00582 off_time_adjustment = 0;
00583 ctimer_set(t, current_off_time, (void (*)(void *))dutycycle, t);
00584 PT_YIELD(&dutycycle_pt);
00585
00586 #if WITH_ADAPTIVE_OFF_TIME
00587 off_time += LOWEST_OFF_TIME;
00588 if(off_time > OFF_TIME) {
00589 off_time = OFF_TIME;
00590 }
00591 #endif
00592
00593 } else {
00594
00595
00596 is_listening--;
00597 ctimer_set(t, OFF_TIME, (void (*)(void *))dutycycle, t);
00598 PT_YIELD(&dutycycle_pt);
00599 }
00600 } else {
00601
00602
00603 ctimer_set(t, off_time, (void (*)(void *))dutycycle, t);
00604 PT_YIELD(&dutycycle_pt);
00605 }
00606 }
00607
00608 PT_END(&dutycycle_pt);
00609 }
00610
00611 static void
00612 restart_dutycycle(clock_time_t initial_wait)
00613 {
00614 PT_INIT(&dutycycle_pt);
00615 ctimer_set(&timer, initial_wait, (void (*)(void *))dutycycle, &timer);
00616 }
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632 static void
00633 send_packet(mac_callback_t sent, void *ptr)
00634 {
00635 struct lpp_hdr hdr;
00636 clock_time_t timeout;
00637 uint8_t is_broadcast = 0;
00638
00639 rimeaddr_copy(&hdr.sender, &rimeaddr_node_addr);
00640 rimeaddr_copy(&hdr.receiver, packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
00641 if(rimeaddr_cmp(&hdr.receiver, &rimeaddr_null)) {
00642 is_broadcast = 1;
00643 }
00644 hdr.type = TYPE_DATA;
00645
00646 packetbuf_hdralloc(sizeof(struct lpp_hdr));
00647 memcpy(packetbuf_hdrptr(), &hdr, sizeof(struct lpp_hdr));
00648 packetbuf_compact();
00649
00650 packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
00651
00652 {
00653 int hdrlen = NETSTACK_FRAMER.create();
00654 if(hdrlen == 0) {
00655
00656 mac_call_sent_callback(sent, ptr, MAC_TX_ERR_FATAL, 0);
00657 return;
00658 }
00659 }
00660
00661 PRINTF("%d.%d: queueing packet to %d.%d, channel %d\n",
00662 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00663 hdr.receiver.u8[0], hdr.receiver.u8[1],
00664 packetbuf_attr(PACKETBUF_ATTR_CHANNEL));
00665 #if WITH_ACK_OPTIMIZATION
00666 if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_ACK) {
00667
00668 NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
00669 mac_call_sent_callback(sent, ptr, MAC_TX_OK, 1);
00670 return;
00671 }
00672 #endif
00673
00674 #if WITH_ADAPTIVE_OFF_TIME
00675 off_time = LOWEST_OFF_TIME;
00676 restart_dutycycle(off_time);
00677 #endif
00678
00679 {
00680 struct queue_list_item *i;
00681 i = memb_alloc(&queued_packets_memb);
00682 if(i != NULL) {
00683 i->sent_callback = sent;
00684 i->sent_callback_ptr = ptr;
00685 i->num_transmissions = 0;
00686 i->packet = queuebuf_new_from_packetbuf();
00687 if(i->packet == NULL) {
00688 memb_free(&queued_packets_memb, i);
00689 printf("null packet\n");
00690 mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 0);
00691 return;
00692 } else {
00693 if(is_broadcast) {
00694 timeout = PACKET_LIFETIME;
00695 #if WITH_PENDING_BROADCAST
00696
00697
00698
00699
00700
00701
00702
00703
00704 set_broadcast_flag(i, BROADCAST_FLAG_WAITING);
00705 PRINTF("-> waiting\n");
00706 #endif
00707 } else {
00708 timeout = UNICAST_TIMEOUT;
00709 #if WITH_PENDING_BROADCAST
00710 i->broadcast_flag = BROADCAST_FLAG_NONE;
00711 #endif
00712 }
00713 ctimer_set(&i->removal_timer, timeout,
00714 remove_queued_old_packet_callback, i);
00715
00716
00717
00718
00719 turn_radio_on_for_neighbor(&hdr.receiver, i);
00720
00721 }
00722 } else {
00723 printf("i == NULL\n");
00724 mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 0);
00725 }
00726 }
00727 }
00728
00729 static int
00730 detect_ack(void)
00731 {
00732 #define INTER_PACKET_INTERVAL RTIMER_ARCH_SECOND / 5000
00733 #define ACK_LEN 3
00734 #define AFTER_ACK_DETECTECT_WAIT_TIME RTIMER_ARCH_SECOND / 1000
00735 rtimer_clock_t wt;
00736 uint8_t ack_received = 0;
00737
00738 wt = RTIMER_NOW();
00739 leds_on(LEDS_GREEN);
00740 while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + INTER_PACKET_INTERVAL)) { }
00741 leds_off(LEDS_GREEN);
00742
00743 if((NETSTACK_RADIO.receiving_packet() ||
00744 NETSTACK_RADIO.pending_packet() ||
00745 NETSTACK_RADIO.channel_clear() == 0)) {
00746 int len;
00747 uint8_t ackbuf[ACK_LEN + 2];
00748
00749 wt = RTIMER_NOW();
00750 while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + AFTER_ACK_DETECTECT_WAIT_TIME)) { }
00751
00752 len = NETSTACK_RADIO.read(ackbuf, ACK_LEN);
00753 if(len == ACK_LEN) {
00754 ack_received = 1;
00755 }
00756 }
00757 if(ack_received) {
00758 leds_toggle(LEDS_RED);
00759 }
00760 return ack_received;
00761 }
00762
00763
00764
00765
00766
00767
00768
00769 static void
00770 input_packet(void)
00771 {
00772 struct lpp_hdr hdr;
00773 clock_time_t reception_time;
00774
00775 reception_time = clock_time();
00776
00777 if(!NETSTACK_FRAMER.parse()) {
00778 printf("lpp input_packet framer error\n");
00779 }
00780
00781 memcpy(&hdr, packetbuf_dataptr(), sizeof(struct lpp_hdr));;
00782 packetbuf_hdrreduce(sizeof(struct lpp_hdr));
00783
00784
00785 if(hdr.type == TYPE_PROBE) {
00786 struct announcement_msg adata;
00787
00788
00789
00790 register_encounter(&hdr.sender, reception_time);
00791
00792
00793 memcpy(&adata, packetbuf_dataptr(),
00794 MIN(packetbuf_datalen(), sizeof(adata)));
00795 #if 0
00796 PRINTF("%d.%d: probe from %d.%d with %d announcements\n",
00797 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00798 hdr.sender.u8[0], hdr.sender.u8[1], adata->num);
00799
00800 if(adata.num / sizeof(struct announcement_data) > sizeof(struct announcement_msg)) {
00801
00802
00803 return 0;
00804 }
00805
00806 for(i = 0; i < adata.num; ++i) {
00807
00808
00809
00810
00811
00812 announcement_heard(&hdr.sender,
00813 adata.data[i].id,
00814 adata.data[i].value);
00815 }
00816 #endif
00817
00818
00819
00820
00821 if(list_length(queued_packets_list) > 0) {
00822 struct queue_list_item *i;
00823 for(i = list_head(queued_packets_list); i != NULL; i = list_item_next(i)) {
00824 const rimeaddr_t *receiver;
00825 uint8_t sent;
00826
00827 sent = 0;
00828
00829 receiver = queuebuf_addr(i->packet, PACKETBUF_ADDR_RECEIVER);
00830 if(rimeaddr_cmp(receiver, &hdr.sender) ||
00831 rimeaddr_cmp(receiver, &rimeaddr_null)) {
00832 queuebuf_to_packetbuf(i->packet);
00833
00834 #if WITH_PENDING_BROADCAST
00835 if(i->broadcast_flag == BROADCAST_FLAG_NONE ||
00836 i->broadcast_flag == BROADCAST_FLAG_SEND) {
00837 i->num_transmissions = 1;
00838 NETSTACK_RADIO.send(queuebuf_dataptr(i->packet),
00839 queuebuf_datalen(i->packet));
00840 sent = 1;
00841 PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n",
00842 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00843 hdr.sender.u8[0], hdr.sender.u8[1],
00844 receiver->u8[0], receiver->u8[1]);
00845
00846 } else {
00847 PRINTF("%d.%d: got a probe from %d.%d, did not send packet\n",
00848 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00849 hdr.sender.u8[0], hdr.sender.u8[1]);
00850 }
00851 #else
00852 i->num_transmissions = 1;
00853 NETSTACK_RADIO.send(queuebuf_dataptr(i->packet),
00854 queuebuf_datalen(i->packet));
00855 PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n",
00856 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00857 hdr.sender.u8[0], hdr.sender.u8[1],
00858 receiver->u8[0], receiver->u8[1]);
00859 #endif
00860
00861
00862
00863
00864
00865 compower_accumulate(&i->compower);
00866
00867
00868
00869
00870
00871 if(!rimeaddr_cmp(receiver, &rimeaddr_null)) {
00872 if(detect_ack()) {
00873 remove_queued_packet(i, 1);
00874 } else {
00875 remove_queued_packet(i, 0);
00876 }
00877
00878 #if WITH_PROBE_AFTER_TRANSMISSION
00879
00880 restart_dutycycle(PROBE_AFTER_TRANSMISSION_TIME);
00881 #endif
00882
00883 #if WITH_STREAMING
00884 if(is_streaming) {
00885 ctimer_set(&stream_probe_timer, STREAM_PROBE_TIME,
00886 send_stream_probe, NULL);
00887 }
00888 #endif
00889 }
00890
00891 if(sent) {
00892 turn_radio_off();
00893 }
00894
00895 #if WITH_ACK_OPTIMIZATION
00896 if(packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ||
00897 packetbuf_attr(PACKETBUF_ATTR_ERELIABLE)) {
00898
00899
00900 turn_radio_on();
00901 }
00902 #endif
00903
00904 }
00905 }
00906 }
00907
00908 } else if(hdr.type == TYPE_DATA) {
00909 turn_radio_off();
00910 if(!rimeaddr_cmp(&hdr.receiver, &rimeaddr_null)) {
00911 if(!rimeaddr_cmp(&hdr.receiver, &rimeaddr_node_addr)) {
00912
00913 PRINTF("%d.%d: data not for us from %d.%d\n",
00914 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00915 hdr.sender.u8[0], hdr.sender.u8[1]);
00916 return;
00917 }
00918 packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &hdr.receiver);
00919 }
00920 packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &hdr.sender);
00921
00922 PRINTF("%d.%d: got data from %d.%d\n",
00923 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00924 hdr.sender.u8[0], hdr.sender.u8[1]);
00925
00926
00927 compower_accumulate(¤t_packet);
00928
00929
00930
00931
00932 compower_attrconv(¤t_packet);
00933
00934
00935
00936 compower_clear(¤t_packet);
00937
00938 #if WITH_PENDING_BROADCAST
00939 if(rimeaddr_cmp(&hdr.receiver, &rimeaddr_null)) {
00940
00941
00942
00943
00944
00945
00946 struct queue_list_item *i;
00947 for(i = list_head(queued_packets_list); i != NULL; i = list_item_next(i)) {
00948
00949
00950 if(i->broadcast_flag == BROADCAST_FLAG_PENDING) {
00951 PRINTF("Someone else is sending, pending -> waiting\n");
00952 set_broadcast_flag(i, BROADCAST_FLAG_WAITING);
00953 }
00954 }
00955 }
00956 #endif
00957
00958
00959 #if WITH_PROBE_AFTER_RECEPTION
00960
00961
00962
00963 if(rimeaddr_cmp(&hdr.receiver, &rimeaddr_node_addr)) {
00964 struct queuebuf *q;
00965 q = queuebuf_new_from_packetbuf();
00966 if(q != NULL) {
00967 send_probe();
00968 queuebuf_to_packetbuf(q);
00969 queuebuf_free(q);
00970 }
00971 }
00972 #endif
00973
00974 #if WITH_ADAPTIVE_OFF_TIME
00975 off_time = LOWEST_OFF_TIME;
00976 restart_dutycycle(off_time);
00977 #endif
00978
00979 NETSTACK_MAC.input();
00980 }
00981 }
00982
00983 static int
00984 on(void)
00985 {
00986 lpp_is_on = 1;
00987 turn_radio_on();
00988 return 1;
00989 }
00990
00991 static int
00992 off(int keep_radio_on)
00993 {
00994 lpp_is_on = 0;
00995 if(keep_radio_on) {
00996 turn_radio_on();
00997 } else {
00998 turn_radio_off();
00999 }
01000 return 1;
01001 }
01002
01003 static unsigned short
01004 channel_check_interval(void)
01005 {
01006 return OFF_TIME + LISTEN_TIME;
01007 }
01008
01009 static void
01010 init(void)
01011 {
01012 restart_dutycycle(random_rand() % OFF_TIME);
01013
01014 lpp_is_on = 1;
01015
01016 announcement_register_listen_callback(listen_callback);
01017
01018 memb_init(&queued_packets_memb);
01019 list_init(queued_packets_list);
01020 list_init(pending_packets_list);
01021 }
01022
01023 const struct rdc_driver lpp_driver = {
01024 "LPP",
01025 init,
01026 send_packet,
01027 input_packet,
01028 on,
01029 off,
01030 channel_check_interval,
01031 };
01032