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 "lib/random.h"
00047 #include "net/netstack.h"
00048 #include "net/mac/xmac.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 0
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 xmac_hdr {
00102 uint8_t dispatch;
00103 uint8_t type;
00104 };
00105
00106 #define MAX_STROBE_SIZE 50
00107
00108 #ifdef XMAC_CONF_ON_TIME
00109 #define DEFAULT_ON_TIME (XMAC_CONF_ON_TIME)
00110 #else
00111 #define DEFAULT_ON_TIME (RTIMER_ARCH_SECOND / 160)
00112 #endif
00113
00114 #ifdef XMAC_CONF_OFF_TIME
00115 #define DEFAULT_OFF_TIME (XMAC_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 (5 * DEFAULT_ON_TIME / 8)
00141
00142 struct xmac_config xmac_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 static struct rtimer rt;
00151 static struct pt pt;
00152
00153 static volatile uint8_t xmac_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 XMAC_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 XMAC_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 struct seqno {
00224 rimeaddr_t sender;
00225 uint8_t seqno;
00226 };
00227
00228 #define MAX_SEQNOS 8
00229 static struct seqno received_seqnos[MAX_SEQNOS];
00230
00231
00232
00233 static void
00234 on(void)
00235 {
00236 if(xmac_is_on && radio_is_on == 0) {
00237 radio_is_on = 1;
00238 NETSTACK_RADIO.on();
00239 LEDS_ON(LEDS_RED);
00240 }
00241 }
00242
00243 static void
00244 off(void)
00245 {
00246 if(xmac_is_on && radio_is_on != 0 && is_listening == 0 &&
00247 is_streaming == 0) {
00248 radio_is_on = 0;
00249 NETSTACK_RADIO.off();
00250 LEDS_OFF(LEDS_RED);
00251 }
00252 }
00253
00254 static char powercycle(struct rtimer *t, void *ptr);
00255 static void
00256 schedule_powercycle(struct rtimer *t, rtimer_clock_t time)
00257 {
00258 int r;
00259 if(xmac_is_on) {
00260 r = rtimer_set(t, RTIMER_TIME(t) + time, 1,
00261 (void (*)(struct rtimer *, void *))powercycle, NULL);
00262 if(r) {
00263 PRINTF("schedule_powercycle: could not set rtimer\n");
00264 }
00265 }
00266 }
00267 static void
00268 powercycle_turn_radio_off(void)
00269 {
00270 if(we_are_sending == 0 &&
00271 waiting_for_packet == 0) {
00272 off();
00273 }
00274 #if XMAC_CONF_COMPOWER
00275 compower_accumulate(&compower_idle_activity);
00276 #endif
00277 }
00278 static void
00279 powercycle_turn_radio_on(void)
00280 {
00281 if(we_are_sending == 0 &&
00282 waiting_for_packet == 0) {
00283 on();
00284 }
00285 }
00286 static char
00287 powercycle(struct rtimer *t, void *ptr)
00288 {
00289 if(is_streaming) {
00290 if(!RTIMER_CLOCK_LT(RTIMER_NOW(), stream_until)) {
00291 is_streaming = 0;
00292 rimeaddr_copy(&is_streaming_to, &rimeaddr_null);
00293 rimeaddr_copy(&is_streaming_to_too, &rimeaddr_null);
00294 }
00295 }
00296
00297 PT_BEGIN(&pt);
00298
00299 while(1) {
00300
00301 if(someone_is_sending > 0) {
00302 someone_is_sending--;
00303 }
00304
00305
00306 powercycle_turn_radio_on();
00307 schedule_powercycle(t, xmac_config.on_time);
00308 PT_YIELD(&pt);
00309
00310 if(xmac_config.off_time > 0 && !NETSTACK_RADIO.receiving_packet()) {
00311 powercycle_turn_radio_off();
00312 if(waiting_for_packet != 0) {
00313 waiting_for_packet++;
00314 if(waiting_for_packet > 2) {
00315
00316
00317
00318 waiting_for_packet = 0;
00319 powercycle_turn_radio_off();
00320 }
00321 }
00322 schedule_powercycle(t, xmac_config.off_time);
00323 PT_YIELD(&pt);
00324 }
00325 }
00326
00327 PT_END(&pt);
00328 }
00329
00330 #if XMAC_CONF_ANNOUNCEMENTS
00331 static int
00332 parse_announcements(const rimeaddr_t *from)
00333 {
00334
00335 struct announcement_msg adata;
00336 int i;
00337
00338 memcpy(&adata, packetbuf_dataptr(), MIN(packetbuf_datalen(), sizeof(adata)));
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348 for(i = 0; i < adata.num; ++i) {
00349
00350
00351
00352
00353
00354 announcement_heard(from,
00355 adata.data[i].id,
00356 adata.data[i].value);
00357 }
00358 return i;
00359 }
00360
00361 static int
00362 format_announcement(char *hdr)
00363 {
00364 struct announcement_msg adata;
00365 struct announcement *a;
00366
00367
00368
00369
00370 adata.num = 0;
00371 for(a = announcement_list();
00372 a != NULL && adata.num < ANNOUNCEMENT_MAX;
00373 a = list_item_next(a)) {
00374 adata.data[adata.num].id = a->id;
00375 adata.data[adata.num].value = a->value;
00376 adata.num++;
00377 }
00378
00379 memcpy(hdr, &adata, sizeof(struct announcement_msg));
00380
00381 if(adata.num > 0) {
00382 return ANNOUNCEMENT_MSG_HEADERLEN +
00383 sizeof(struct announcement_data) * adata.num;
00384 } else {
00385 return 0;
00386 }
00387 }
00388 #endif
00389
00390 #if WITH_ENCOUNTER_OPTIMIZATION
00391 static void
00392 register_encounter(const rimeaddr_t *neighbor, rtimer_clock_t time)
00393 {
00394 struct encounter *e;
00395
00396
00397 for(e = list_head(encounter_list); e != NULL; e = list_item_next(e)) {
00398 if(rimeaddr_cmp(neighbor, &e->neighbor)) {
00399 e->time = time;
00400 break;
00401 }
00402 }
00403
00404 if(e == NULL) {
00405 e = memb_alloc(&encounter_memb);
00406 if(e == NULL) {
00407
00408 return;
00409 }
00410 rimeaddr_copy(&e->neighbor, neighbor);
00411 e->time = time;
00412 list_add(encounter_list, e);
00413 }
00414 }
00415 #endif
00416
00417 static int
00418 detect_ack(void)
00419 {
00420 #define INTER_PACKET_INTERVAL RTIMER_ARCH_SECOND / 5000
00421 #define ACK_LEN 3
00422 #define AFTER_ACK_DETECTECT_WAIT_TIME RTIMER_ARCH_SECOND / 1000
00423 rtimer_clock_t wt;
00424 uint8_t ack_received = 0;
00425
00426 wt = RTIMER_NOW();
00427 leds_on(LEDS_GREEN);
00428 while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + INTER_PACKET_INTERVAL)) { }
00429 leds_off(LEDS_GREEN);
00430
00431 if((NETSTACK_RADIO.receiving_packet() ||
00432 NETSTACK_RADIO.pending_packet() ||
00433 NETSTACK_RADIO.channel_clear() == 0)) {
00434 int len;
00435 uint8_t ackbuf[ACK_LEN + 2];
00436
00437 wt = RTIMER_NOW();
00438 while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + AFTER_ACK_DETECTECT_WAIT_TIME)) { }
00439
00440 len = NETSTACK_RADIO.read(ackbuf, ACK_LEN);
00441 if(len == ACK_LEN) {
00442 ack_received = 1;
00443 }
00444 }
00445 if(ack_received) {
00446 leds_toggle(LEDS_RED);
00447 }
00448 return ack_received;
00449 }
00450
00451 static int
00452 send_packet(void)
00453 {
00454 rtimer_clock_t t0;
00455 rtimer_clock_t t;
00456 rtimer_clock_t encounter_time = 0;
00457 int strobes;
00458 #if 0
00459 struct xmac_hdr *hdr;
00460 #endif
00461 uint8_t got_strobe_ack = 0;
00462 uint8_t got_ack = 0;
00463 uint8_t strobe[MAX_STROBE_SIZE];
00464 int strobe_len, len;
00465 int is_broadcast = 0;
00466 int is_reliable;
00467 struct encounter *e;
00468 struct queuebuf *packet;
00469 int is_already_streaming = 0;
00470 uint8_t collisions;
00471
00472
00473 packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr);
00474 if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) {
00475 is_broadcast = 1;
00476 PRINTDEBUG("xmac: send broadcast\n");
00477 } else {
00478 #if UIP_CONF_IPV6
00479 PRINTDEBUG("xmac: send unicast to %02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
00480 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
00481 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1],
00482 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[2],
00483 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[3],
00484 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[4],
00485 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[5],
00486 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[6],
00487 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[7]);
00488 #else
00489 PRINTDEBUG("xmac: send unicast to %u.%u\n",
00490 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
00491 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1]);
00492 #endif
00493 }
00494 is_reliable = packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ||
00495 packetbuf_attr(PACKETBUF_ATTR_ERELIABLE);
00496
00497 packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
00498 len = NETSTACK_FRAMER.create();
00499 strobe_len = len + sizeof(struct xmac_hdr);
00500 if(len == 0 || strobe_len > (int)sizeof(strobe)) {
00501
00502 PRINTF("xmac: send failed, too large header\n");
00503 return MAC_TX_ERR_FATAL;
00504 }
00505 memcpy(strobe, packetbuf_hdrptr(), len);
00506 strobe[len] = DISPATCH;
00507 strobe[len + 1] = TYPE_STROBE;
00508
00509 packetbuf_compact();
00510 packet = queuebuf_new_from_packetbuf();
00511 if(packet == NULL) {
00512
00513 PRINTF("xmac: send failed, no queue buffer available (of %u)\n",
00514 QUEUEBUF_CONF_NUM);
00515 return MAC_TX_ERR;
00516 }
00517
00518 #if WITH_STREAMING
00519 if(is_streaming == 1 &&
00520 (rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
00521 &is_streaming_to) ||
00522 rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
00523 &is_streaming_to_too))) {
00524 is_already_streaming = 1;
00525 }
00526 if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
00527 PACKETBUF_ATTR_PACKET_TYPE_STREAM) {
00528 is_streaming = 1;
00529 if(rimeaddr_cmp(&is_streaming_to, &rimeaddr_null)) {
00530 rimeaddr_copy(&is_streaming_to, packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
00531 } else if(!rimeaddr_cmp(&is_streaming_to, packetbuf_addr(PACKETBUF_ADDR_RECEIVER))) {
00532 rimeaddr_copy(&is_streaming_to_too, packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
00533 }
00534 stream_until = RTIMER_NOW() + DEFAULT_STREAM_TIME;
00535 }
00536 #endif
00537
00538 off();
00539
00540 #if WITH_ENCOUNTER_OPTIMIZATION
00541
00542
00543
00544
00545 for(e = list_head(encounter_list); e != NULL; e = list_item_next(e)) {
00546 const rimeaddr_t *neighbor = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
00547
00548 if(rimeaddr_cmp(neighbor, &e->neighbor)) {
00549 rtimer_clock_t wait, now, expected;
00550
00551
00552
00553
00554
00555
00556
00557
00558 now = RTIMER_NOW();
00559 wait = ((rtimer_clock_t)(e->time - now)) % (DEFAULT_PERIOD);
00560 if(wait < 2 * DEFAULT_ON_TIME) {
00561 wait = DEFAULT_PERIOD;
00562 }
00563 expected = now + wait - 2 * DEFAULT_ON_TIME;
00564
00565 #if WITH_ACK_OPTIMIZATION
00566
00567 if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) !=
00568 PACKETBUF_ATTR_PACKET_TYPE_ACK &&
00569 is_streaming == 0) {
00570
00571
00572 while(RTIMER_CLOCK_LT(RTIMER_NOW(), expected));
00573 }
00574 #else
00575
00576 while(RTIMER_CLOCK_LT(RTIMER_NOW(), expected));
00577 #endif
00578 }
00579 }
00580 #endif
00581
00582
00583
00584 we_are_sending = 1;
00585
00586 t0 = RTIMER_NOW();
00587 strobes = 0;
00588
00589 LEDS_ON(LEDS_BLUE);
00590
00591
00592
00593
00594
00595 collisions = 0;
00596 if(!is_already_streaming) {
00597 watchdog_stop();
00598 got_strobe_ack = 0;
00599 t = RTIMER_NOW();
00600 for(strobes = 0, collisions = 0;
00601 got_strobe_ack == 0 && collisions == 0 &&
00602 RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + xmac_config.strobe_time);
00603 strobes++) {
00604
00605 while(got_strobe_ack == 0 &&
00606 RTIMER_CLOCK_LT(RTIMER_NOW(), t + xmac_config.strobe_wait_time)) {
00607 #if 0
00608 rtimer_clock_t now = RTIMER_NOW();
00609
00610
00611 packetbuf_clear();
00612 len = NETSTACK_RADIO.read(packetbuf_dataptr(), PACKETBUF_SIZE);
00613 if(len > 0) {
00614 packetbuf_set_datalen(len);
00615 if(NETSTACK_FRAMER.parse()) {
00616 hdr = packetbuf_dataptr();
00617 if(hdr->dispatch == DISPATCH && hdr->type == TYPE_STROBE_ACK) {
00618 if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
00619 &rimeaddr_node_addr)) {
00620
00621
00622 got_strobe_ack = 1;
00623 encounter_time = now;
00624 } else {
00625 PRINTDEBUG("xmac: strobe ack for someone else\n");
00626 }
00627 } else {
00628 PRINTDEBUG("xmac: strobe from someone else\n");
00629 collisions++;
00630 }
00631 } else {
00632 PRINTF("xmac: send failed to parse %u\n", len);
00633 }
00634 }
00635 #endif
00636 }
00637
00638 t = RTIMER_NOW();
00639
00640 if(got_strobe_ack == 0 && collisions == 0) {
00641
00642 if(is_broadcast) {
00643 #if WITH_STROBE_BROADCAST
00644 NETSTACK_RADIO.send(strobe, strobe_len);
00645 #else
00646
00647 queuebuf_to_packetbuf(packet);
00648 NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
00649 #endif
00650 off();
00651 } else {
00652 #if 0
00653 rtimer_clock_t wt;
00654 #endif
00655 on();
00656 NETSTACK_RADIO.send(strobe, strobe_len);
00657 #if 0
00658
00659
00660
00661 off();
00662 wt = RTIMER_NOW();
00663 while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + WAIT_TIME_BEFORE_STROBE_ACK));
00664 #endif
00665
00666 if(detect_ack()) {
00667 got_strobe_ack = 1;
00668 } else {
00669 off();
00670 }
00671 }
00672 }
00673 }
00674 }
00675
00676 #if WITH_ACK_OPTIMIZATION
00677
00678
00679
00680 if(got_strobe_ack && (packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ||
00681 packetbuf_attr(PACKETBUF_ATTR_ERELIABLE) ||
00682 packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
00683 PACKETBUF_ATTR_PACKET_TYPE_STREAM)) {
00684 on();
00685 waiting_for_packet = 1;
00686 } else {
00687 off();
00688 }
00689 #endif
00690
00691
00692 queuebuf_to_packetbuf(packet);
00693 queuebuf_free(packet);
00694
00695
00696 if((is_broadcast || got_strobe_ack || is_streaming) && collisions == 0) {
00697 NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
00698
00699 if(!is_broadcast) {
00700 if(detect_ack()) {
00701 got_ack = 1;
00702 }
00703 }
00704 }
00705 off();
00706
00707 #if WITH_ENCOUNTER_OPTIMIZATION
00708 if(got_strobe_ack && !is_streaming) {
00709 register_encounter(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), encounter_time);
00710 }
00711 #endif
00712 watchdog_start();
00713
00714 PRINTF("xmac: send (strobes=%u,len=%u,%s), done\n", strobes,
00715 packetbuf_totlen(), got_strobe_ack ? "ack" : "no ack");
00716
00717 #if XMAC_CONF_COMPOWER
00718
00719 compower_accumulate(¤t_packet);
00720
00721
00722
00723
00724
00725 compower_attrconv(¤t_packet);
00726
00727
00728
00729 compower_clear(¤t_packet);
00730 #endif
00731
00732 we_are_sending = 0;
00733
00734 LEDS_OFF(LEDS_BLUE);
00735 if(collisions == 0) {
00736 if(is_broadcast == 0 && got_ack == 0) {
00737 return MAC_TX_NOACK;
00738 } else {
00739 return MAC_TX_OK;
00740 }
00741 } else {
00742 someone_is_sending++;
00743 return MAC_TX_COLLISION;
00744 }
00745
00746 }
00747
00748 static void
00749 qsend_packet(mac_callback_t sent, void *ptr)
00750 {
00751 int ret;
00752
00753 if(someone_is_sending) {
00754 PRINTF("xmac: should queue packet, now just dropping %d %d %d %d.\n",
00755 waiting_for_packet, someone_is_sending, we_are_sending, radio_is_on);
00756 RIMESTATS_ADD(sendingdrop);
00757 ret = MAC_TX_COLLISION;
00758 } else {
00759 PRINTF("xmac: send immediately.\n");
00760 ret = send_packet();
00761 }
00762
00763 mac_call_sent_callback(sent, ptr, ret, 1);
00764 }
00765
00766 static void
00767 input_packet(void)
00768 {
00769 struct xmac_hdr *hdr;
00770
00771 if(NETSTACK_FRAMER.parse()) {
00772 hdr = packetbuf_dataptr();
00773
00774 if(hdr->dispatch != DISPATCH) {
00775 someone_is_sending = 0;
00776 if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
00777 &rimeaddr_node_addr) ||
00778 rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
00779 &rimeaddr_null)) {
00780
00781
00782
00783
00784
00785 off();
00786
00787
00788
00789 {
00790 int i;
00791 for(i = 0; i < MAX_SEQNOS; ++i) {
00792 if(packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == received_seqnos[i].seqno &&
00793 rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER),
00794 &received_seqnos[i].sender)) {
00795
00796 return;
00797 }
00798 }
00799 for(i = MAX_SEQNOS - 1; i > 0; --i) {
00800 memcpy(&received_seqnos[i], &received_seqnos[i - 1],
00801 sizeof(struct seqno));
00802 }
00803 received_seqnos[0].seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID);
00804 rimeaddr_copy(&received_seqnos[0].sender,
00805 packetbuf_addr(PACKETBUF_ADDR_SENDER));
00806 }
00807
00808 #if XMAC_CONF_COMPOWER
00809
00810 compower_accumulate(¤t_packet);
00811
00812
00813
00814
00815 compower_attrconv(¤t_packet);
00816
00817
00818
00819 compower_clear(¤t_packet);
00820 #endif
00821
00822 waiting_for_packet = 0;
00823
00824 PRINTDEBUG("xmac: data(%u)\n", packetbuf_datalen());
00825 NETSTACK_MAC.input();
00826 return;
00827 } else {
00828 PRINTDEBUG("xmac: data not for us\n");
00829 }
00830
00831 } else if(hdr->type == TYPE_STROBE) {
00832 someone_is_sending = 2;
00833
00834 if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
00835 &rimeaddr_node_addr)) {
00836
00837
00838
00839
00840
00841
00842 waiting_for_packet = 1;
00843 #if 0
00844 hdr->type = TYPE_STROBE_ACK;
00845 packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER,
00846 packetbuf_addr(PACKETBUF_ADDR_SENDER));
00847 packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr);
00848 packetbuf_compact();
00849 if(NETSTACK_FRAMER.create()) {
00850
00851
00852 someone_is_sending = 1;
00853 waiting_for_packet = 1;
00854 on();
00855 NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
00856 PRINTDEBUG("xmac: send strobe ack %u\n", packetbuf_totlen());
00857 } else {
00858 PRINTF("xmac: failed to send strobe ack\n");
00859 }
00860 #endif
00861 } else if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
00862 &rimeaddr_null)) {
00863
00864
00865
00866
00867 waiting_for_packet = 1;
00868 on();
00869 } else {
00870 PRINTDEBUG("xmac: strobe not for us\n");
00871 }
00872
00873
00874
00875 return;
00876 #if XMAC_CONF_ANNOUNCEMENTS
00877 } else if(hdr->type == TYPE_ANNOUNCEMENT) {
00878 packetbuf_hdrreduce(sizeof(struct xmac_hdr));
00879 parse_announcements(packetbuf_addr(PACKETBUF_ADDR_SENDER));
00880 #endif
00881 } else if(hdr->type == TYPE_STROBE_ACK) {
00882 PRINTDEBUG("xmac: stray strobe ack\n");
00883 } else {
00884 PRINTF("xmac: unknown type %u (%u/%u)\n", hdr->type,
00885 packetbuf_datalen(), len);
00886 }
00887 } else {
00888 PRINTF("xmac: failed to parse (%u)\n", packetbuf_totlen());
00889 }
00890 }
00891
00892 #if XMAC_CONF_ANNOUNCEMENTS
00893 static void
00894 send_announcement(void *ptr)
00895 {
00896 struct xmac_hdr *hdr;
00897 int announcement_len;
00898
00899
00900 packetbuf_clear();
00901 hdr = packetbuf_dataptr();
00902
00903 announcement_len = format_announcement((char *)hdr +
00904 sizeof(struct xmac_hdr));
00905
00906 if(announcement_len > 0) {
00907 packetbuf_set_datalen(sizeof(struct xmac_hdr) + announcement_len);
00908 hdr->dispatch = DISPATCH;
00909 hdr->type = TYPE_ANNOUNCEMENT;
00910
00911 packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr);
00912 packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &rimeaddr_null);
00913 packetbuf_set_attr(PACKETBUF_ATTR_RADIO_TXPOWER, announcement_radio_txpower);
00914 if(NETSTACK_FRAMER.create()) {
00915 NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
00916 }
00917 }
00918 }
00919
00920 static void
00921 cycle_announcement(void *ptr)
00922 {
00923 ctimer_set(&announcement_ctimer, ANNOUNCEMENT_TIME,
00924 send_announcement, NULL);
00925 ctimer_set(&announcement_cycle_ctimer, ANNOUNCEMENT_PERIOD,
00926 cycle_announcement, NULL);
00927 if(is_listening > 0) {
00928 is_listening--;
00929
00930 }
00931 }
00932
00933 static void
00934 listen_callback(int periods)
00935 {
00936 is_listening = periods + 1;
00937 }
00938 #endif
00939
00940 void
00941 xmac_set_announcement_radio_txpower(int txpower)
00942 {
00943 #if XMAC_CONF_ANNOUNCEMENTS
00944 announcement_radio_txpower = txpower;
00945 #endif
00946 }
00947
00948 static void
00949 init(void)
00950 {
00951 radio_is_on = 0;
00952 waiting_for_packet = 0;
00953 PT_INIT(&pt);
00954 rtimer_set(&rt, RTIMER_NOW() + xmac_config.off_time, 1,
00955 (void (*)(struct rtimer *, void *))powercycle, NULL);
00956
00957 xmac_is_on = 1;
00958
00959 #if WITH_ENCOUNTER_OPTIMIZATION
00960 list_init(encounter_list);
00961 memb_init(&encounter_memb);
00962 #endif
00963
00964 #if XMAC_CONF_ANNOUNCEMENTS
00965 announcement_register_listen_callback(listen_callback);
00966 ctimer_set(&announcement_cycle_ctimer, ANNOUNCEMENT_TIME,
00967 cycle_announcement, NULL);
00968 #endif
00969 }
00970
00971 static int
00972 turn_on(void)
00973 {
00974 xmac_is_on = 1;
00975 rtimer_set(&rt, RTIMER_NOW() + xmac_config.off_time, 1,
00976 (void (*)(struct rtimer *, void *))powercycle, NULL);
00977 return 1;
00978 }
00979
00980 static int
00981 turn_off(int keep_radio_on)
00982 {
00983 xmac_is_on = 0;
00984 if(keep_radio_on) {
00985 return NETSTACK_RADIO.on();
00986 } else {
00987 return NETSTACK_RADIO.off();
00988 }
00989 }
00990
00991 static unsigned short
00992 channel_check_interval(void)
00993 {
00994 return (1ul * CLOCK_SECOND * DEFAULT_PERIOD) / RTIMER_ARCH_SECOND;
00995 }
00996
00997 const struct rdc_driver xmac_driver =
00998 {
00999 "X-MAC",
01000 init,
01001 qsend_packet,
01002 input_packet,
01003 turn_on,
01004 turn_off,
01005 channel_check_interval,
01006 };