45 #include "dev/watchdog.h"
46 #include "lib/random.h"
55 #include "contiki-conf.h"
57 #ifdef EXPERIMENT_SETUP
58 #include "experiment-setup.h"
63 #ifndef WITH_ACK_OPTIMIZATION
64 #define WITH_ACK_OPTIMIZATION 0
66 #ifndef WITH_ENCOUNTER_OPTIMIZATION
67 #define WITH_ENCOUNTER_OPTIMIZATION 1
69 #ifndef WITH_STREAMING
70 #define WITH_STREAMING 1
72 #ifndef WITH_STROBE_BROADCAST
73 #define WITH_STROBE_BROADCAST 0
76 struct announcement_data {
83 #define ANNOUNCEMENT_MAX 10
86 struct announcement_msg {
88 struct announcement_data data[ANNOUNCEMENT_MAX];
93 #define ANNOUNCEMENT_MSG_HEADERLEN (sizeof (uint16_t))
96 #define TYPE_STROBE 0x10
98 #define TYPE_ANNOUNCEMENT 0x12
99 #define TYPE_STROBE_ACK 0x13
106 #define MAX_STROBE_SIZE 50
108 #ifdef XMAC_CONF_ON_TIME
109 #define DEFAULT_ON_TIME (XMAC_CONF_ON_TIME)
111 #define DEFAULT_ON_TIME (RTIMER_ARCH_SECOND / 160)
114 #ifdef XMAC_CONF_OFF_TIME
115 #define DEFAULT_OFF_TIME (XMAC_CONF_OFF_TIME)
117 #define DEFAULT_OFF_TIME (RTIMER_ARCH_SECOND / NETSTACK_RDC_CHANNEL_CHECK_RATE - DEFAULT_ON_TIME)
120 #define DEFAULT_PERIOD (DEFAULT_OFF_TIME + DEFAULT_ON_TIME)
122 #define WAIT_TIME_BEFORE_STROBE_ACK RTIMER_ARCH_SECOND / 1000
128 #if DEFAULT_PERIOD == 0
129 #undef DEFAULT_PERIOD
130 #define DEFAULT_PERIOD 1
134 #define ANNOUNCEMENT_PERIOD 4 * CLOCK_SECOND
138 #define ANNOUNCEMENT_TIME (random_rand() % (ANNOUNCEMENT_PERIOD))
140 #define DEFAULT_STROBE_WAIT_TIME (5 * DEFAULT_ON_TIME / 8)
142 struct xmac_config xmac_config = {
145 4 * DEFAULT_ON_TIME + DEFAULT_OFF_TIME,
146 DEFAULT_STROBE_WAIT_TIME
153 static volatile uint8_t xmac_is_on = 0;
155 static volatile unsigned char waiting_for_packet = 0;
156 static volatile unsigned char someone_is_sending = 0;
157 static volatile unsigned char we_are_sending = 0;
158 static volatile unsigned char radio_is_on = 0;
164 #define LEDS_ON(x) leds_on(x)
165 #define LEDS_OFF(x) leds_off(x)
166 #define LEDS_TOGGLE(x) leds_toggle(x)
170 #define PRINTF(...) printf(__VA_ARGS__)
171 #define PRINTDEBUG(...) printf(__VA_ARGS__)
178 #define LEDS_TOGGLE(x)
180 #define PRINTDEBUG(...)
183 #if XMAC_CONF_ANNOUNCEMENTS
185 static struct ctimer announcement_cycle_ctimer, announcement_ctimer;
187 static int announcement_radio_txpower;
192 static uint8_t is_listening;
194 #if XMAC_CONF_COMPOWER
198 #if WITH_ENCOUNTER_OPTIMIZATION
204 struct encounter *
next;
209 #define MAX_ENCOUNTERS 4
210 LIST(encounter_list);
211 MEMB(encounter_memb,
struct encounter, MAX_ENCOUNTERS);
214 static uint8_t is_streaming;
215 static rimeaddr_t is_streaming_to, is_streaming_to_too;
216 static rtimer_clock_t stream_until;
217 #define DEFAULT_STREAM_TIME (RTIMER_ARCH_SECOND)
220 #define MIN(a, b) ((a) < (b)? (a) : (b))
229 static struct seqno received_seqnos[MAX_SEQNOS];
236 if(xmac_is_on && radio_is_on == 0) {
246 if(xmac_is_on && radio_is_on != 0 && is_listening == 0 &&
249 NETSTACK_RADIO.off();
254 static char powercycle(
struct rtimer *t,
void *ptr);
256 schedule_powercycle(
struct rtimer *t, rtimer_clock_t time)
261 (
void (*)(
struct rtimer *,
void *))powercycle,
NULL);
263 PRINTF(
"schedule_powercycle: could not set rtimer\n");
268 powercycle_turn_radio_off(
void)
270 if(we_are_sending == 0 &&
271 waiting_for_packet == 0) {
274 #if XMAC_CONF_COMPOWER
279 powercycle_turn_radio_on(
void)
281 if(we_are_sending == 0 &&
282 waiting_for_packet == 0) {
287 powercycle(
struct rtimer *t,
void *ptr)
290 if(!RTIMER_CLOCK_LT(
RTIMER_NOW(), stream_until)) {
301 if(someone_is_sending > 0) {
302 someone_is_sending--;
306 powercycle_turn_radio_on();
307 schedule_powercycle(t, xmac_config.on_time);
310 if(xmac_config.off_time > 0 && !NETSTACK_RADIO.receiving_packet()) {
311 powercycle_turn_radio_off();
312 if(waiting_for_packet != 0) {
313 waiting_for_packet++;
314 if(waiting_for_packet > 2) {
318 waiting_for_packet = 0;
319 powercycle_turn_radio_off();
322 schedule_powercycle(t, xmac_config.off_time);
330 #if XMAC_CONF_ANNOUNCEMENTS
332 parse_announcements(
const rimeaddr_t *from)
335 struct announcement_msg adata;
348 for(i = 0; i < adata.num; ++i) {
356 adata.data[i].value);
362 format_announcement(
char *hdr)
364 struct announcement_msg adata;
372 a !=
NULL && adata.num < ANNOUNCEMENT_MAX;
374 adata.data[adata.num].id = a->id;
375 adata.data[adata.num].value = a->value;
379 memcpy(hdr, &adata,
sizeof(
struct announcement_msg));
382 return ANNOUNCEMENT_MSG_HEADERLEN +
383 sizeof(
struct announcement_data) * adata.num;
390 #if WITH_ENCOUNTER_OPTIMIZATION
392 register_encounter(
const rimeaddr_t *neighbor, rtimer_clock_t time)
420 #define INTER_PACKET_INTERVAL RTIMER_ARCH_SECOND / 5000
422 #define AFTER_ACK_DETECTECT_WAIT_TIME RTIMER_ARCH_SECOND / 1000
424 uint8_t ack_received = 0;
428 while(RTIMER_CLOCK_LT(
RTIMER_NOW(), wt + INTER_PACKET_INTERVAL)) { }
429 leds_off(LEDS_GREEN);
431 if((NETSTACK_RADIO.receiving_packet() ||
432 NETSTACK_RADIO.pending_packet() ||
433 NETSTACK_RADIO.channel_clear() == 0)) {
435 uint8_t ackbuf[ACK_LEN + 2];
438 while(RTIMER_CLOCK_LT(
RTIMER_NOW(), wt + AFTER_ACK_DETECTECT_WAIT_TIME)) { }
440 len = NETSTACK_RADIO.read(ackbuf, ACK_LEN);
446 leds_toggle(LEDS_RED);
456 rtimer_clock_t encounter_time = 0;
459 struct xmac_hdr *hdr;
461 uint8_t got_strobe_ack = 0;
463 uint8_t strobe[MAX_STROBE_SIZE];
465 int is_broadcast = 0;
468 struct queuebuf *packet;
469 int is_already_streaming = 0;
476 PRINTDEBUG(
"xmac: send broadcast\n");
479 PRINTDEBUG(
"xmac: send unicast to %02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
480 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
481 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1],
482 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[2],
483 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[3],
484 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[4],
485 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[5],
486 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[6],
487 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[7]);
489 PRINTDEBUG(
"xmac: send unicast to %u.%u\n",
490 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
491 packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1]);
494 is_reliable = packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ||
495 packetbuf_attr(PACKETBUF_ATTR_ERELIABLE);
497 packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
498 len = NETSTACK_FRAMER.create();
499 strobe_len = len +
sizeof(
struct xmac_hdr);
500 if(len == 0 || strobe_len > (
int)
sizeof(strobe)) {
502 PRINTF(
"xmac: send failed, too large header\n");
503 return MAC_TX_ERR_FATAL;
506 strobe[len] = DISPATCH;
507 strobe[len + 1] = TYPE_STROBE;
510 packet = queuebuf_new_from_packetbuf();
513 PRINTF(
"xmac: send failed, no queue buffer available (of %u)\n",
519 if(is_streaming == 1 &&
523 &is_streaming_to_too))) {
524 is_already_streaming = 1;
526 if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
527 PACKETBUF_ATTR_PACKET_TYPE_STREAM) {
530 rimeaddr_copy(&is_streaming_to, packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
531 }
else if(!
rimeaddr_cmp(&is_streaming_to, packetbuf_addr(PACKETBUF_ADDR_RECEIVER))) {
532 rimeaddr_copy(&is_streaming_to_too, packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
534 stream_until =
RTIMER_NOW() + DEFAULT_STREAM_TIME;
540 #if WITH_ENCOUNTER_OPTIMIZATION
546 const rimeaddr_t *neighbor = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
549 rtimer_clock_t wait, now, expected;
559 wait = ((rtimer_clock_t)(e->time - now)) % (DEFAULT_PERIOD);
560 if(wait < 2 * DEFAULT_ON_TIME) {
561 wait = DEFAULT_PERIOD;
563 expected = now + wait - 2 * DEFAULT_ON_TIME;
565 #if WITH_ACK_OPTIMIZATION
567 if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) !=
568 PACKETBUF_ATTR_PACKET_TYPE_ACK &&
572 while(RTIMER_CLOCK_LT(
RTIMER_NOW(), expected));
576 while(RTIMER_CLOCK_LT(
RTIMER_NOW(), expected));
596 if(!is_already_streaming) {
600 for(strobes = 0, collisions = 0;
601 got_strobe_ack == 0 && collisions == 0 &&
602 RTIMER_CLOCK_LT(
RTIMER_NOW(), t0 + xmac_config.strobe_time);
605 while(got_strobe_ack == 0 &&
606 RTIMER_CLOCK_LT(
RTIMER_NOW(), t + xmac_config.strobe_wait_time)) {
615 if(NETSTACK_FRAMER.parse()) {
617 if(hdr->dispatch == DISPATCH && hdr->type == TYPE_STROBE_ACK) {
618 if(
rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
623 encounter_time = now;
625 PRINTDEBUG(
"xmac: strobe ack for someone else\n");
628 PRINTDEBUG(
"xmac: strobe from someone else\n");
632 PRINTF(
"xmac: send failed to parse %u\n", len);
640 if(got_strobe_ack == 0 && collisions == 0) {
643 #if WITH_STROBE_BROADCAST
644 NETSTACK_RADIO.send(strobe, strobe_len);
647 queuebuf_to_packetbuf(packet);
656 NETSTACK_RADIO.send(strobe, strobe_len);
663 while(RTIMER_CLOCK_LT(
RTIMER_NOW(), wt + WAIT_TIME_BEFORE_STROBE_ACK));
676 #if WITH_ACK_OPTIMIZATION
680 if(got_strobe_ack && (packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ||
681 packetbuf_attr(PACKETBUF_ATTR_ERELIABLE) ||
682 packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
683 PACKETBUF_ATTR_PACKET_TYPE_STREAM)) {
685 waiting_for_packet = 1;
692 queuebuf_to_packetbuf(packet);
693 queuebuf_free(packet);
696 if((is_broadcast || got_strobe_ack || is_streaming) && collisions == 0) {
707 #if WITH_ENCOUNTER_OPTIMIZATION
708 if(got_strobe_ack && !is_streaming) {
709 register_encounter(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), encounter_time);
714 PRINTF(
"xmac: send (strobes=%u,len=%u,%s), done\n", strobes,
717 #if XMAC_CONF_COMPOWER
735 if(collisions == 0) {
736 if(is_broadcast == 0 && got_ack == 0) {
742 someone_is_sending++;
749 qsend_packet(mac_callback_t sent,
void *ptr)
753 if(someone_is_sending) {
754 PRINTF(
"xmac: should queue packet, now just dropping %d %d %d %d.\n",
755 waiting_for_packet, someone_is_sending, we_are_sending, radio_is_on);
756 RIMESTATS_ADD(sendingdrop);
759 PRINTF(
"xmac: send immediately.\n");
763 mac_call_sent_callback(sent, ptr, ret, 1);
769 struct xmac_hdr *hdr;
771 if(NETSTACK_FRAMER.parse()) {
774 if(hdr->dispatch != DISPATCH) {
775 someone_is_sending = 0;
776 if(
rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
791 for(i = 0; i < MAX_SEQNOS; ++i) {
792 if(packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == received_seqnos[i].seqno &&
794 &received_seqnos[i].sender)) {
799 for(i = MAX_SEQNOS - 1; i > 0; --i) {
800 memcpy(&received_seqnos[i], &received_seqnos[i - 1],
801 sizeof(
struct seqno));
803 received_seqnos[0].seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID);
805 packetbuf_addr(PACKETBUF_ADDR_SENDER));
808 #if XMAC_CONF_COMPOWER
822 waiting_for_packet = 0;
825 NETSTACK_MAC.input();
828 PRINTDEBUG(
"xmac: data not for us\n");
831 }
else if(hdr->type == TYPE_STROBE) {
832 someone_is_sending = 2;
834 if(
rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
842 waiting_for_packet = 1;
844 hdr->type = TYPE_STROBE_ACK;
845 packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER,
846 packetbuf_addr(PACKETBUF_ADDR_SENDER));
849 if(NETSTACK_FRAMER.create()) {
852 someone_is_sending = 1;
853 waiting_for_packet = 1;
858 PRINTF(
"xmac: failed to send strobe ack\n");
861 }
else if(
rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
867 waiting_for_packet = 1;
870 PRINTDEBUG(
"xmac: strobe not for us\n");
876 #if XMAC_CONF_ANNOUNCEMENTS
877 }
else if(hdr->type == TYPE_ANNOUNCEMENT) {
879 parse_announcements(packetbuf_addr(PACKETBUF_ADDR_SENDER));
881 }
else if(hdr->type == TYPE_STROBE_ACK) {
882 PRINTDEBUG(
"xmac: stray strobe ack\n");
884 PRINTF(
"xmac: unknown type %u (%u/%u)\n", hdr->type,
892 #if XMAC_CONF_ANNOUNCEMENTS
894 send_announcement(
void *ptr)
896 struct xmac_hdr *hdr;
897 int announcement_len;
903 announcement_len = format_announcement((
char *)hdr +
904 sizeof(
struct xmac_hdr));
906 if(announcement_len > 0) {
908 hdr->dispatch = DISPATCH;
909 hdr->type = TYPE_ANNOUNCEMENT;
913 packetbuf_set_attr(PACKETBUF_ATTR_RADIO_TXPOWER, announcement_radio_txpower);
914 if(NETSTACK_FRAMER.create()) {
921 cycle_announcement(
void *ptr)
923 ctimer_set(&announcement_ctimer, ANNOUNCEMENT_TIME,
924 send_announcement,
NULL);
925 ctimer_set(&announcement_cycle_ctimer, ANNOUNCEMENT_PERIOD,
926 cycle_announcement,
NULL);
927 if(is_listening > 0) {
934 listen_callback(
int periods)
936 is_listening = periods + 1;
941 xmac_set_announcement_radio_txpower(
int txpower)
943 #if XMAC_CONF_ANNOUNCEMENTS
944 announcement_radio_txpower = txpower;
952 waiting_for_packet = 0;
955 (void (*)(
struct rtimer *,
void *))powercycle,
NULL);
959 #if WITH_ENCOUNTER_OPTIMIZATION
964 #if XMAC_CONF_ANNOUNCEMENTS
966 ctimer_set(&announcement_cycle_ctimer, ANNOUNCEMENT_TIME,
967 cycle_announcement,
NULL);
976 (void (*)(
struct rtimer *,
void *))powercycle,
NULL);
981 turn_off(
int keep_radio_on)
985 return NETSTACK_RADIO.on();
987 return NETSTACK_RADIO.off();
991 static unsigned short
992 channel_check_interval(
void)
994 return (1ul *
CLOCK_SECOND * DEFAULT_PERIOD) / RTIMER_ARCH_SECOND;