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 #include "dev/leds.h"
00044 #include "dev/radio.h"
00045 #include "dev/watchdog.h"
00046 #include "net/netstack.h"
00047 #include "lib/random.h"
00048 #include "net/mac/cxmac.h"
00049 #include "net/rime.h"
00050 #include "net/rime/timesynch.h"
00051 #include "sys/compower.h"
00052 #include "sys/pt.h"
00053 #include "sys/rtimer.h"
00054
00055 #include "contiki-conf.h"
00056
00057 #ifdef EXPERIMENT_SETUP
00058 #include "experiment-setup.h"
00059 #endif
00060
00061 #include <string.h>
00062
00063 #ifndef WITH_ACK_OPTIMIZATION
00064 #define WITH_ACK_OPTIMIZATION 1
00065 #endif
00066 #ifndef WITH_ENCOUNTER_OPTIMIZATION
00067 #define WITH_ENCOUNTER_OPTIMIZATION 1
00068 #endif
00069 #ifndef WITH_STREAMING
00070 #define WITH_STREAMING 1
00071 #endif
00072 #ifndef WITH_STROBE_BROADCAST
00073 #define WITH_STROBE_BROADCAST 0
00074 #endif
00075
00076 struct announcement_data {
00077 uint16_t id;
00078 uint16_t value;
00079 };
00080
00081
00082
00083 #define ANNOUNCEMENT_MAX 10
00084
00085
00086 struct announcement_msg {
00087 uint16_t num;
00088 struct announcement_data data[ANNOUNCEMENT_MAX];
00089 };
00090
00091
00092
00093 #define ANNOUNCEMENT_MSG_HEADERLEN (sizeof (uint16_t))
00094
00095 #define DISPATCH 0
00096 #define TYPE_STROBE 0x10
00097
00098 #define TYPE_ANNOUNCEMENT 0x12
00099 #define TYPE_STROBE_ACK 0x13
00100
00101 struct cxmac_hdr {
00102 uint8_t dispatch;
00103 uint8_t type;
00104 };
00105
00106 #define MAX_STROBE_SIZE 50
00107
00108 #ifdef CXMAC_CONF_ON_TIME
00109 #define DEFAULT_ON_TIME (CXMAC_CONF_ON_TIME)
00110 #else
00111 #define DEFAULT_ON_TIME (RTIMER_ARCH_SECOND / 160)
00112 #endif
00113
00114 #ifdef CXMAC_CONF_OFF_TIME
00115 #define DEFAULT_OFF_TIME (CXMAC_CONF_OFF_TIME)
00116 #else
00117 #define DEFAULT_OFF_TIME (RTIMER_ARCH_SECOND / NETSTACK_RDC_CHANNEL_CHECK_RATE - DEFAULT_ON_TIME)
00118 #endif
00119
00120 #define DEFAULT_PERIOD (DEFAULT_OFF_TIME + DEFAULT_ON_TIME)
00121
00122 #define WAIT_TIME_BEFORE_STROBE_ACK RTIMER_ARCH_SECOND / 1000
00123
00124
00125
00126
00127
00128 #if DEFAULT_PERIOD == 0
00129 #undef DEFAULT_PERIOD
00130 #define DEFAULT_PERIOD 1
00131 #endif
00132
00133
00134 #define ANNOUNCEMENT_PERIOD 4 * CLOCK_SECOND
00135
00136
00137
00138 #define ANNOUNCEMENT_TIME (random_rand() % (ANNOUNCEMENT_PERIOD))
00139
00140 #define DEFAULT_STROBE_WAIT_TIME (7 * DEFAULT_ON_TIME / 8)
00141
00142 struct cxmac_config cxmac_config = {
00143 DEFAULT_ON_TIME,
00144 DEFAULT_OFF_TIME,
00145 4 * DEFAULT_ON_TIME + DEFAULT_OFF_TIME,
00146 DEFAULT_STROBE_WAIT_TIME
00147 };
00148
00149 #include <stdio.h>
00150
00151 static struct pt pt;
00152
00153 static volatile uint8_t cxmac_is_on = 0;
00154
00155 static volatile unsigned char waiting_for_packet = 0;
00156 static volatile unsigned char someone_is_sending = 0;
00157 static volatile unsigned char we_are_sending = 0;
00158 static volatile unsigned char radio_is_on = 0;
00159
00160 #undef LEDS_ON
00161 #undef LEDS_OFF
00162 #undef LEDS_TOGGLE
00163
00164 #define LEDS_ON(x) leds_on(x)
00165 #define LEDS_OFF(x) leds_off(x)
00166 #define LEDS_TOGGLE(x) leds_toggle(x)
00167 #define DEBUG 0
00168 #if DEBUG
00169 #include <stdio.h>
00170 #define PRINTF(...) printf(__VA_ARGS__)
00171 #define PRINTDEBUG(...) printf(__VA_ARGS__)
00172 #else
00173 #undef LEDS_ON
00174 #undef LEDS_OFF
00175 #undef LEDS_TOGGLE
00176 #define LEDS_ON(x)
00177 #define LEDS_OFF(x)
00178 #define LEDS_TOGGLE(x)
00179 #define PRINTF(...)
00180 #define PRINTDEBUG(...)
00181 #endif
00182
00183 #if CXMAC_CONF_ANNOUNCEMENTS
00184
00185 static struct ctimer announcement_cycle_ctimer, announcement_ctimer;
00186
00187 static int announcement_radio_txpower;
00188 #endif
00189
00190
00191
00192 static uint8_t is_listening;
00193
00194 #if CXMAC_CONF_COMPOWER
00195 static struct compower_activity current_packet;
00196 #endif
00197
00198 #if WITH_ENCOUNTER_OPTIMIZATION
00199
00200 #include "lib/list.h"
00201 #include "lib/memb.h"
00202
00203 struct encounter {
00204 struct encounter *next;
00205 rimeaddr_t neighbor;
00206 rtimer_clock_t time;
00207 };
00208
00209 #define MAX_ENCOUNTERS 4
00210 LIST(encounter_list);
00211 MEMB(encounter_memb, struct encounter, MAX_ENCOUNTERS);
00212 #endif
00213
00214 static uint8_t is_streaming;
00215 static rimeaddr_t is_streaming_to, is_streaming_to_too;
00216 static rtimer_clock_t stream_until;
00217 #define DEFAULT_STREAM_TIME (RTIMER_ARCH_SECOND)
00218
00219 #ifndef MIN
00220 #define MIN(a, b) ((a) < (b)? (a) : (b))
00221 #endif
00222
00223
00224 static void
00225 on(void)
00226 {
00227 if(cxmac_is_on && radio_is_on == 0) {
00228 radio_is_on = 1;
00229 NETSTACK_RADIO.on();
00230 LEDS_ON(LEDS_RED);
00231 }
00232 }
00233
00234 static void
00235 off(void)
00236 {
00237 if(cxmac_is_on && radio_is_on != 0 && is_listening == 0 &&
00238 is_streaming == 0) {
00239 radio_is_on = 0;
00240 NETSTACK_RADIO.off();
00241 LEDS_OFF(LEDS_RED);
00242 }
00243 }
00244
00245 static void
00246 powercycle_turn_radio_off(void)
00247 {
00248 if(we_are_sending == 0 &&
00249 waiting_for_packet == 0) {
00250 off();
00251 }
00252 #if CXMAC_CONF_COMPOWER
00253 compower_accumulate(&compower_idle_activity);
00254 #endif
00255 }
00256 static void
00257 powercycle_turn_radio_on(void)
00258 {
00259 if(we_are_sending == 0 &&
00260 waiting_for_packet == 0) {
00261 on();
00262 }
00263 }
00264
00265 static struct ctimer cpowercycle_ctimer;
00266 #define CSCHEDULE_POWERCYCLE(rtime) cschedule_powercycle((1ul * CLOCK_SECOND * (rtime)) / RTIMER_ARCH_SECOND)
00267 static char cpowercycle(void *ptr);
00268 static void
00269 cschedule_powercycle(clock_time_t time)
00270 {
00271
00272 if(cxmac_is_on) {
00273 if(time == 0) {
00274 time = 1;
00275 }
00276 ctimer_set(&cpowercycle_ctimer, time,
00277 (void (*)(void *))cpowercycle, NULL);
00278 }
00279 }
00280
00281 static char
00282 cpowercycle(void *ptr)
00283 {
00284 if(is_streaming) {
00285 if(!RTIMER_CLOCK_LT(RTIMER_NOW(), stream_until)) {
00286 is_streaming = 0;
00287 rimeaddr_copy(&is_streaming_to, &rimeaddr_null);
00288 rimeaddr_copy(&is_streaming_to_too, &rimeaddr_null);
00289 }
00290 }
00291
00292 PT_BEGIN(&pt);
00293
00294 while(1) {
00295
00296 if(someone_is_sending > 0) {
00297 someone_is_sending--;
00298 }
00299
00300
00301 powercycle_turn_radio_on();
00302 CSCHEDULE_POWERCYCLE(DEFAULT_ON_TIME);
00303 PT_YIELD(&pt);
00304
00305 if(cxmac_config.off_time > 0) {
00306 powercycle_turn_radio_off();
00307 if(waiting_for_packet != 0) {
00308 waiting_for_packet++;
00309 if(waiting_for_packet > 2) {
00310
00311
00312
00313 waiting_for_packet = 0;
00314 powercycle_turn_radio_off();
00315 }
00316 }
00317 CSCHEDULE_POWERCYCLE(DEFAULT_OFF_TIME);
00318 PT_YIELD(&pt);
00319 }
00320 }
00321
00322 PT_END(&pt);
00323 }
00324
00325 #if CXMAC_CONF_ANNOUNCEMENTS
00326 static int
00327 parse_announcements(const rimeaddr_t *from)
00328 {
00329
00330 struct announcement_msg adata;
00331 int i;
00332
00333 memcpy(&adata, packetbuf_dataptr(), MIN(packetbuf_datalen(), sizeof(adata)));
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343 for(i = 0; i < adata.num; ++i) {
00344
00345
00346
00347
00348
00349 announcement_heard(from,
00350 adata.data[i].id,
00351 adata.data[i].value);
00352 }
00353 return i;
00354 }
00355
00356 static int
00357 format_announcement(char *hdr)
00358 {
00359 struct announcement_msg adata;
00360 struct announcement *a;
00361
00362
00363
00364
00365 adata.num = 0;
00366 for(a = announcement_list();
00367 a != NULL && adata.num < ANNOUNCEMENT_MAX;
00368 a = list_item_next(a)) {
00369 adata.data[adata.num].id = a->id;
00370 adata.data[adata.num].value = a->value;
00371 adata.num++;
00372 }
00373
00374 memcpy(hdr, &adata, sizeof(struct announcement_msg));
00375
00376 if(adata.num > 0) {
00377 return ANNOUNCEMENT_MSG_HEADERLEN +
00378 sizeof(struct announcement_data) * adata.num;
00379 } else {
00380 return 0;
00381 }
00382 }
00383 #endif
00384
00385 #if WITH_ENCOUNTER_OPTIMIZATION
00386 static void
00387 register_encounter(const rimeaddr_t *neighbor, rtimer_clock_t time)
00388 {
00389 struct encounter *e;
00390
00391
00392 for(e = list_head(encounter_list); e != NULL; e = list_item_next(e)) {
00393 if(rimeaddr_cmp(neighbor, &e->neighbor)) {
00394 e->time = time;
00395 break;
00396 }
00397 }
00398
00399 if(e == NULL) {
00400 e = memb_alloc(&encounter_memb);
00401 if(e == NULL) {
00402
00403 return;
00404 }
00405 rimeaddr_copy(&e->neighbor, neighbor);
00406 e->time = time;
00407 list_add(encounter_list, e);
00408 }
00409 }
00410 #endif
00411
00412 static int
00413 send_packet(void)
00414 {
00415 rtimer_clock_t t0;
00416 rtimer_clock_t t;
00417 rtimer_clock_t encounter_time = 0;
00418 int strobes;
00419 struct cxmac_hdr *hdr;
00420 int got_strobe_ack = 0;
00421 uint8_t strobe[MAX_STROBE_SIZE];
00422 int strobe_len, len;
00423 int is_broadcast = 0;
00424 int is_reliable;
00425 struct encounter *e;
00426 struct queuebuf *packet;
00427 int is_already_streaming = 0;
00428 uint8_t collisions;
00429
00430
00431
00432 packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr);
00433 if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) {
00434 is_broadcast = 1;
00435 PRINTDEBUG("cxmac: send broadcast\n");
00436 } else {
00437 #if UIP_CONF_IPV6
00438 PRINTDEBUG("cxmac: send unicast to %02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
00439 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
00440 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1],
00441 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[2],
00442 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[3],
00443 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[4],
00444 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[5],
00445 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[6],
00446 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[7]);
00447 #else
00448 PRINTDEBUG("cxmac: send unicast to %u.%u\n",
00449 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
00450 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1]);
00451 #endif
00452 }
00453 is_reliable = packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ||
00454 packetbuf_attr(PACKETBUF_ATTR_ERELIABLE);
00455 len = NETSTACK_FRAMER.create();
00456 strobe_len = len + sizeof(struct cxmac_hdr);
00457 if(len == 0 || strobe_len > (int)sizeof(strobe)) {
00458
00459 PRINTF("cxmac: send failed, too large header\n");
00460 return MAC_TX_ERR_FATAL;
00461 }
00462 memcpy(strobe, packetbuf_hdrptr(), len);
00463 strobe[len] = DISPATCH;
00464 strobe[len + 1] = TYPE_STROBE;
00465
00466 packetbuf_compact();
00467 packet = queuebuf_new_from_packetbuf();
00468 if(packet == NULL) {
00469
00470 PRINTF("cxmac: send failed, no queue buffer available (of %u)\n",
00471 QUEUEBUF_CONF_NUM);
00472 return MAC_TX_ERR;
00473 }
00474
00475 #if WITH_STREAMING
00476 if(is_streaming == 1 &&
00477 (rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
00478 &is_streaming_to) ||
00479 rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
00480 &is_streaming_to_too))) {
00481 is_already_streaming = 1;
00482 }
00483 if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
00484 PACKETBUF_ATTR_PACKET_TYPE_STREAM) {
00485 is_streaming = 1;
00486 if(rimeaddr_cmp(&is_streaming_to, &rimeaddr_null)) {
00487 rimeaddr_copy(&is_streaming_to, packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
00488 } else if(!rimeaddr_cmp(&is_streaming_to, packetbuf_addr(PACKETBUF_ADDR_RECEIVER))) {
00489 rimeaddr_copy(&is_streaming_to_too, packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
00490 }
00491 stream_until = RTIMER_NOW() + DEFAULT_STREAM_TIME;
00492 }
00493 #endif
00494
00495 off();
00496
00497 #if WITH_ENCOUNTER_OPTIMIZATION
00498
00499
00500
00501
00502 for(e = list_head(encounter_list); e != NULL; e = list_item_next(e)) {
00503 const rimeaddr_t *neighbor = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
00504
00505 if(rimeaddr_cmp(neighbor, &e->neighbor)) {
00506 rtimer_clock_t wait, now, expected;
00507
00508
00509
00510
00511
00512
00513
00514
00515 now = RTIMER_NOW();
00516 wait = ((rtimer_clock_t)(e->time - now)) % (DEFAULT_PERIOD);
00517 expected = now + wait - 2 * DEFAULT_ON_TIME;
00518
00519 #if WITH_ACK_OPTIMIZATION
00520
00521 if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) !=
00522 PACKETBUF_ATTR_PACKET_TYPE_ACK &&
00523 is_streaming == 0) {
00524
00525
00526 while(RTIMER_CLOCK_LT(RTIMER_NOW(), expected));
00527 }
00528 #else
00529
00530 while(RTIMER_CLOCK_LT(RTIMER_NOW(), expected));
00531 #endif
00532 }
00533 }
00534 #endif
00535
00536
00537
00538 we_are_sending = 1;
00539
00540 t0 = RTIMER_NOW();
00541 strobes = 0;
00542
00543 LEDS_ON(LEDS_BLUE);
00544
00545
00546
00547
00548 on();
00549 collisions = 0;
00550 if(!is_already_streaming) {
00551 watchdog_stop();
00552 got_strobe_ack = 0;
00553 t = RTIMER_NOW();
00554 for(strobes = 0, collisions = 0;
00555 got_strobe_ack == 0 && collisions == 0 &&
00556 RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + cxmac_config.strobe_time);
00557 strobes++) {
00558
00559 while(got_strobe_ack == 0 &&
00560 RTIMER_CLOCK_LT(RTIMER_NOW(), t + cxmac_config.strobe_wait_time)) {
00561 rtimer_clock_t now = RTIMER_NOW();
00562
00563
00564 packetbuf_clear();
00565 len = NETSTACK_RADIO.read(packetbuf_dataptr(), PACKETBUF_SIZE);
00566 if(len > 0) {
00567 packetbuf_set_datalen(len);
00568 if(NETSTACK_FRAMER.parse()) {
00569 hdr = packetbuf_dataptr();
00570 if(hdr->dispatch == DISPATCH && hdr->type == TYPE_STROBE_ACK) {
00571 if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
00572 &rimeaddr_node_addr)) {
00573
00574
00575 got_strobe_ack = 1;
00576 encounter_time = now;
00577 } else {
00578 PRINTDEBUG("cxmac: strobe ack for someone else\n");
00579 }
00580 } else {
00581 PRINTDEBUG("cxmac: strobe from someone else\n");
00582 collisions++;
00583 }
00584 } else {
00585 PRINTF("cxmac: send failed to parse %u\n", len);
00586 }
00587 }
00588 }
00589
00590 t = RTIMER_NOW();
00591
00592 if(got_strobe_ack == 0 && collisions == 0) {
00593 if(is_broadcast) {
00594 #if WITH_STROBE_BROADCAST
00595 NETSTACK_RADIO.send(strobe, strobe_len);
00596 #else
00597
00598 queuebuf_to_packetbuf(packet);
00599 NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
00600 #endif
00601 off();
00602 } else {
00603 NETSTACK_RADIO.send(strobe, strobe_len);
00604 #if 0
00605
00606
00607
00608 off();
00609 rtimer_clock_t wt = RTIMER_NOW();
00610 while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + WAIT_TIME_BEFORE_STROBE_ACK));
00611 #endif
00612 on();
00613 }
00614 }
00615 }
00616 }
00617
00618 #if WITH_ACK_OPTIMIZATION
00619
00620
00621
00622 if(got_strobe_ack && (packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ||
00623 packetbuf_attr(PACKETBUF_ATTR_ERELIABLE) ||
00624 packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
00625 PACKETBUF_ATTR_PACKET_TYPE_STREAM)) {
00626 on();
00627 waiting_for_packet = 1;
00628 } else {
00629 off();
00630 }
00631 #else
00632 off();
00633 #endif
00634
00635
00636 queuebuf_to_packetbuf(packet);
00637 queuebuf_free(packet);
00638
00639
00640 if((is_broadcast || got_strobe_ack || is_streaming) && collisions == 0) {
00641 NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
00642 }
00643
00644 #if WITH_ENCOUNTER_OPTIMIZATION
00645 if(got_strobe_ack && !is_streaming) {
00646 register_encounter(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), encounter_time);
00647 }
00648 #endif
00649 watchdog_start();
00650
00651 PRINTF("cxmac: send (strobes=%u,len=%u,%s), done\n", strobes,
00652 packetbuf_totlen(), got_strobe_ack ? "ack" : "no ack");
00653
00654 #if CXMAC_CONF_COMPOWER
00655
00656 compower_accumulate(¤t_packet);
00657
00658
00659
00660
00661
00662 compower_attrconv(¤t_packet);
00663
00664
00665
00666 compower_clear(¤t_packet);
00667 #endif
00668
00669 we_are_sending = 0;
00670
00671 LEDS_OFF(LEDS_BLUE);
00672 if(collisions == 0) {
00673 if(!is_broadcast && !got_strobe_ack) {
00674 return MAC_TX_NOACK;
00675 } else {
00676 return MAC_TX_OK;
00677 }
00678 } else {
00679 someone_is_sending++;
00680 return MAC_TX_COLLISION;
00681 }
00682
00683 }
00684
00685 static void
00686 qsend_packet(mac_callback_t sent, void *ptr)
00687 {
00688 int ret;
00689 if(someone_is_sending) {
00690 PRINTF("cxmac: should queue packet, now just dropping %d %d %d %d.\n",
00691 waiting_for_packet, someone_is_sending, we_are_sending, radio_is_on);
00692 RIMESTATS_ADD(sendingdrop);
00693 ret = MAC_TX_COLLISION;
00694 } else {
00695 PRINTF("cxmac: send immediately.\n");
00696 ret = send_packet();
00697 }
00698
00699 mac_call_sent_callback(sent, ptr, ret, 1);
00700 }
00701
00702 static void
00703 input_packet(void)
00704 {
00705 struct cxmac_hdr *hdr;
00706
00707 if(NETSTACK_FRAMER.parse()) {
00708 hdr = packetbuf_dataptr();
00709
00710 if(hdr->dispatch != DISPATCH) {
00711 someone_is_sending = 0;
00712 if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
00713 &rimeaddr_node_addr) ||
00714 rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
00715 &rimeaddr_null)) {
00716
00717
00718
00719
00720
00721 off();
00722
00723 #if CXMAC_CONF_COMPOWER
00724
00725 compower_accumulate(¤t_packet);
00726
00727
00728
00729
00730 compower_attrconv(¤t_packet);
00731
00732
00733
00734 compower_clear(¤t_packet);
00735 #endif
00736
00737 waiting_for_packet = 0;
00738
00739 PRINTDEBUG("cxmac: data(%u)\n", packetbuf_datalen());
00740 NETSTACK_MAC.input();
00741 return;
00742 } else {
00743 PRINTDEBUG("cxmac: data not for us\n");
00744 }
00745
00746 } else if(hdr->type == TYPE_STROBE) {
00747 someone_is_sending = 2;
00748
00749 if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
00750 &rimeaddr_node_addr)) {
00751
00752
00753
00754
00755
00756
00757 hdr->type = TYPE_STROBE_ACK;
00758 packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER,
00759 packetbuf_addr(PACKETBUF_ADDR_SENDER));
00760 packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr);
00761 packetbuf_compact();
00762 if(NETSTACK_FRAMER.create()) {
00763
00764
00765 someone_is_sending = 1;
00766 waiting_for_packet = 1;
00767 on();
00768 NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
00769 PRINTDEBUG("cxmac: send strobe ack %u\n", packetbuf_totlen());
00770 } else {
00771 PRINTF("cxmac: failed to send strobe ack\n");
00772 }
00773 } else if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
00774 &rimeaddr_null)) {
00775
00776
00777
00778
00779 waiting_for_packet = 1;
00780 on();
00781 } else {
00782 PRINTDEBUG("cxmac: strobe not for us\n");
00783 }
00784
00785
00786
00787 return;
00788 #if CXMAC_CONF_ANNOUNCEMENTS
00789 } else if(hdr->type == TYPE_ANNOUNCEMENT) {
00790 packetbuf_hdrreduce(sizeof(struct cxmac_hdr));
00791 parse_announcements(packetbuf_addr(PACKETBUF_ADDR_SENDER));
00792 #endif
00793 } else if(hdr->type == TYPE_STROBE_ACK) {
00794 PRINTDEBUG("cxmac: stray strobe ack\n");
00795 } else {
00796 PRINTF("cxmac: unknown type %u (%u)\n", hdr->type,
00797 packetbuf_datalen());
00798 }
00799 } else {
00800 PRINTF("cxmac: failed to parse (%u)\n", packetbuf_totlen());
00801 }
00802 }
00803
00804 #if CXMAC_CONF_ANNOUNCEMENTS
00805 static void
00806 send_announcement(void *ptr)
00807 {
00808 struct cxmac_hdr *hdr;
00809 int announcement_len;
00810
00811
00812 packetbuf_clear();
00813 hdr = packetbuf_dataptr();
00814
00815 announcement_len = format_announcement((char *)hdr +
00816 sizeof(struct cxmac_hdr));
00817
00818 if(announcement_len > 0) {
00819 packetbuf_set_datalen(sizeof(struct cxmac_hdr) + announcement_len);
00820 hdr->dispatch = DISPATCH;
00821 hdr->type = TYPE_ANNOUNCEMENT;
00822
00823 packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr);
00824 packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &rimeaddr_null);
00825 packetbuf_set_attr(PACKETBUF_ATTR_RADIO_TXPOWER, announcement_radio_txpower);
00826 if(NETSTACK_FRAMER.create()) {
00827 NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
00828 }
00829 }
00830 }
00831
00832 static void
00833 cycle_announcement(void *ptr)
00834 {
00835 ctimer_set(&announcement_ctimer, ANNOUNCEMENT_TIME,
00836 send_announcement, NULL);
00837 ctimer_set(&announcement_cycle_ctimer, ANNOUNCEMENT_PERIOD,
00838 cycle_announcement, NULL);
00839 if(is_listening > 0) {
00840 is_listening--;
00841
00842 }
00843 }
00844
00845 static void
00846 listen_callback(int periods)
00847 {
00848 is_listening = periods + 1;
00849 }
00850 #endif
00851
00852 void
00853 cxmac_set_announcement_radio_txpower(int txpower)
00854 {
00855 #if CXMAC_CONF_ANNOUNCEMENTS
00856 announcement_radio_txpower = txpower;
00857 #endif
00858 }
00859
00860 void
00861 cxmac_init(void)
00862 {
00863 radio_is_on = 0;
00864 waiting_for_packet = 0;
00865 PT_INIT(&pt);
00866
00867
00868
00869 cxmac_is_on = 1;
00870
00871 #if WITH_ENCOUNTER_OPTIMIZATION
00872 list_init(encounter_list);
00873 memb_init(&encounter_memb);
00874 #endif
00875
00876 #if CXMAC_CONF_ANNOUNCEMENTS
00877 announcement_register_listen_callback(listen_callback);
00878 ctimer_set(&announcement_cycle_ctimer, ANNOUNCEMENT_TIME,
00879 cycle_announcement, NULL);
00880 #endif
00881
00882 CSCHEDULE_POWERCYCLE(DEFAULT_OFF_TIME);
00883 }
00884
00885 static int
00886 turn_on(void)
00887 {
00888 cxmac_is_on = 1;
00889
00890
00891 CSCHEDULE_POWERCYCLE(DEFAULT_OFF_TIME);
00892 return 1;
00893 }
00894
00895 static int
00896 turn_off(int keep_radio_on)
00897 {
00898 cxmac_is_on = 0;
00899 if(keep_radio_on) {
00900 return NETSTACK_RADIO.on();
00901 } else {
00902 return NETSTACK_RADIO.off();
00903 }
00904 }
00905
00906 static unsigned short
00907 channel_check_interval(void)
00908 {
00909 return (1ul * CLOCK_SECOND * DEFAULT_PERIOD) / RTIMER_ARCH_SECOND;
00910 }
00911
00912 const struct rdc_driver cxmac_driver =
00913 {
00914 "CX-MAC",
00915 cxmac_init,
00916 qsend_packet,
00917 input_packet,
00918 turn_on,
00919 turn_off,
00920 channel_check_interval,
00921 };