Added nicer configuration options. Added hack for optimizing X-MAC for unicast packets. Added statistics gathering. Turn radio off when someone else is receiving a packet. Queueing packets when X-MAC cannot send immediately (since someone else is transmitting).

This commit is contained in:
adamdunkels 2007-05-22 20:55:24 +00:00
parent a495d1230b
commit edd509acf5
2 changed files with 59 additions and 21 deletions

View File

@ -30,7 +30,7 @@
* *
* This file is part of the Contiki operating system. * This file is part of the Contiki operating system.
* *
* $Id: xmac.c,v 1.3 2007/05/19 13:12:00 oliverschmidt Exp $ * $Id: xmac.c,v 1.4 2007/05/22 20:55:24 adamdunkels Exp $
*/ */
/** /**
@ -51,7 +51,21 @@
#include "net/chameleon/packattr.h" #include "net/chameleon/packattr.h"
#endif #endif
extern rimeaddr_t uc_receiver; #undef XMAC_CONF_ON_TIME
#undef XMAC_CONF_OFF_TIME
#define WITH_RECEIVER 1
#define WITH_QUEUE 1
#define XMAC_CONF_ON_TIME RTIMER_ARCH_SECOND / 100
#define XMAC_CONF_OFF_TIME RTIMER_ARCH_SECOND / 10
#if WITH_RECEIVER
extern
#else
static
#endif
rimeaddr_t uc_receiver;
struct powercycle { struct powercycle {
struct pt pt; struct pt pt;
@ -68,20 +82,18 @@ struct xmac_hdr {
static struct rtimer rt; static struct rtimer rt;
static struct pt pt; static struct pt pt;
#ifdef XMAC_CONF_BASE_TIME #ifdef XMAC_CONF_ON_TIME
#define BASE_TIME XMAC_CONF_BASE_TIME #define ON_TIME (XMAC_CONF_ON_TIME)
#else #else
#define BASE_TIME (RTIMER_ARCH_SECOND / 100) #define ON_TIME (RTIMER_ARCH_SECOND / 100)
#endif #endif
#ifdef XMAC_CONF_DUTYCYCLE #ifdef XMAC_CONF_OFF_TIME
#define DUTYCYCLE XMAC_CONF_DUTYCYCLE #define OFF_TIME (XMAC_CONF_OFF_TIME)
#else #else
#define DUTYCYCLE 10 #define OFF_TIME (ON_TIME * 10)
#endif #endif
#define OFF_TIME BASE_TIME * (DUTYCYCLE)
#define ON_TIME BASE_TIME
#define STROBE_WAIT_TIME ON_TIME / 2 #define STROBE_WAIT_TIME ON_TIME / 2
static volatile unsigned char should_be_awake = 0; static volatile unsigned char should_be_awake = 0;
@ -119,9 +131,9 @@ powercycle(struct rtimer *t, void *ptr)
PT_BEGIN(&pt); PT_BEGIN(&pt);
while(1) { while(1) {
rtimer_clock_t t1, t2; /* rtimer_clock_t t1, t2; */
t1 = rtimer_arch_now(); /* t1 = rtimer_arch_now(); */
if(should_be_awake == 0) { if(should_be_awake == 0) {
radio->off(); radio->off();
radio_is_on = 0; radio_is_on = 0;
@ -136,7 +148,7 @@ powercycle(struct rtimer *t, void *ptr)
(void (*)(struct rtimer *, void *))powercycle, ptr)) { (void (*)(struct rtimer *, void *))powercycle, ptr)) {
PRINTF("xmac: could not set rtimer\n"); PRINTF("xmac: could not set rtimer\n");
} }
t2 = rtimer_arch_now(); /* t2 = rtimer_arch_now(); */
/* printf("xmac 1 %d\n", t2 - t1); */ /* printf("xmac 1 %d\n", t2 - t1); */
PT_YIELD(&pt); PT_YIELD(&pt);
@ -145,7 +157,7 @@ powercycle(struct rtimer *t, void *ptr)
PT_YIELD(&pt); PT_YIELD(&pt);
} }
t1 = rtimer_arch_now(); /* t1 = rtimer_arch_now(); */
if(radio_is_on == 0) { if(radio_is_on == 0) {
radio->on(); radio->on();
radio_is_on = 1; radio_is_on = 1;
@ -155,7 +167,7 @@ powercycle(struct rtimer *t, void *ptr)
(void (*)(struct rtimer *, void *))powercycle, ptr)) { (void (*)(struct rtimer *, void *))powercycle, ptr)) {
PRINTF("xmac: could not set rtimer\n"); PRINTF("xmac: could not set rtimer\n");
} }
t2 = rtimer_arch_now(); /* t2 = rtimer_arch_now(); */
/* printf("xmac 2 %d\n", t2 - t1); */ /* printf("xmac 2 %d\n", t2 - t1); */
PT_YIELD(&pt); PT_YIELD(&pt);
@ -169,8 +181,14 @@ powercycle(struct rtimer *t, void *ptr)
/* XXX should wait for a complete packet that is not destined to /* XXX should wait for a complete packet that is not destined to
us to swisch past us. */ us to swisch past us. */
radio->off();
radio_is_on = 0;
LEDS_OFF(LEDS_RED);
if(rtimer_set(t, RTIMER_TIME(t) + OFF_TIME, 1, powercycle, ptr)) {
PRINTF("xmac: could not set long off rtimer\n");
}
long_off = 0; long_off = 0;
someone_is_sending = 0;
} }
} }
@ -189,9 +207,11 @@ send(void)
we_are_sending = 1; we_are_sending = 1;
radio->on(); radio->on();
radio_is_on = 1;
/* printf("xmac_send\n");*/ /* printf("xmac_send\n");*/
PRINTF("xmac: send() len %d\n", rimebuf_totlen()); PRINTF("xmac: send() len %d to %d.%d\n", rimebuf_totlen(),
uc_receiver.u8[0], uc_receiver.u8[1]);
rimebuf_hdralloc(sizeof(struct xmac_hdr)); rimebuf_hdralloc(sizeof(struct xmac_hdr));
hdr = rimebuf_hdrptr(); hdr = rimebuf_hdrptr();
@ -246,6 +266,8 @@ send(void)
the packet. */ the packet. */
got_ack = 1; got_ack = 1;
break; break;
} else {
RIMESTATS_ADD(sendingdrop);
} }
} }
} }
@ -264,7 +286,6 @@ send(void)
/* printf("Strobe %d got_ack %d\n", strobes, got_ack);*/ /* printf("Strobe %d got_ack %d\n", strobes, got_ack);*/
LEDS_OFF(LEDS_GREEN); LEDS_OFF(LEDS_GREEN);
PT_INIT(&pt); PT_INIT(&pt);
if(rtimer_set(&rt, RTIMER_NOW() + ON_TIME, 1, if(rtimer_set(&rt, RTIMER_NOW() + ON_TIME, 1,
(void (*)(struct rtimer *, void *))powercycle, NULL)) { (void (*)(struct rtimer *, void *))powercycle, NULL)) {
@ -274,12 +295,22 @@ send(void)
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static struct queuebuf *queued_packet;
static void static void
qsend(void) qsend(void)
{ {
if(someone_is_sending) { if(someone_is_sending) {
PRINTF("xmac: should queue packet, now just dropping %d %d %d %d.\n", PRINTF("xmac: should queue packet, now just dropping %d %d %d %d.\n",
should_be_awake, someone_is_sending, we_are_sending, radio_is_on); should_be_awake, someone_is_sending, we_are_sending, radio_is_on);
if(queued_packet != NULL) {
RIMESTATS_ADD(contentiondrop);
} else {
#if WITH_QUEUE
queued_packet = queuebuf_new_from_rimebuf();
#else
RIMESTATS_ADD(contentiondrop);
#endif
}
} else { } else {
PRINTF("xmac: send immediately.\n"); PRINTF("xmac: send immediately.\n");
send(); send();
@ -330,12 +361,14 @@ input(const struct radio_driver *d)
} else if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) { } else if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) {
/* Wait for the actual packet to arrive. */ /* Wait for the actual packet to arrive. */
should_be_awake = 1; should_be_awake = 1;
PRINTF("xmac: broadcast from %d.%d\n",
hdr->sender.u8[0],hdr->sender.u8[1]);
/* PRINTF("xmac: broadcast\n");*/ /* PRINTF("xmac: broadcast\n");*/
} else { } else {
/* Go back to sleep. XXX should not turn on the radio again /* Go back to sleep. XXX should not turn on the radio again
until this packet has passed. */ until this packet has passed. */
should_be_awake = 0; should_be_awake = 0;
someone_is_sending = 0; someone_is_sending = 1;
long_off = 1; long_off = 1;
/* XXX set timer to turn someone_is_sending off again and send queued packet. */ /* XXX set timer to turn someone_is_sending off again and send queued packet. */
/* PRINTF("xmac: not for us\n");*/ /* PRINTF("xmac: not for us\n");*/
@ -350,6 +383,12 @@ input(const struct radio_driver *d)
PRINTF("xmac: final packet received\n"); PRINTF("xmac: final packet received\n");
rime_input(); rime_input();
/* XXX send queued packet. */ /* XXX send queued packet. */
if(queued_packet != NULL) {
queuebuf_to_rimebuf(queued_packet);
queuebuf_free(queued_packet);
queued_packet = NULL;
send();
}
} }
} }
} }

View File

@ -28,7 +28,7 @@
* *
* This file is part of the Contiki operating system. * This file is part of the Contiki operating system.
* *
* $Id: xmac.h,v 1.2 2007/05/15 08:07:07 adamdunkels Exp $ * $Id: xmac.h,v 1.3 2007/05/22 20:55:24 adamdunkels Exp $
*/ */
/** /**
@ -47,5 +47,4 @@
void xmac_init(const struct radio_driver *d); void xmac_init(const struct radio_driver *d);
#endif /* __XMAC_H__ */ #endif /* __XMAC_H__ */