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.
*
* $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"
#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 pt pt;
@ -68,20 +82,18 @@ struct xmac_hdr {
static struct rtimer rt;
static struct pt pt;
#ifdef XMAC_CONF_BASE_TIME
#define BASE_TIME XMAC_CONF_BASE_TIME
#ifdef XMAC_CONF_ON_TIME
#define ON_TIME (XMAC_CONF_ON_TIME)
#else
#define BASE_TIME (RTIMER_ARCH_SECOND / 100)
#define ON_TIME (RTIMER_ARCH_SECOND / 100)
#endif
#ifdef XMAC_CONF_DUTYCYCLE
#define DUTYCYCLE XMAC_CONF_DUTYCYCLE
#ifdef XMAC_CONF_OFF_TIME
#define OFF_TIME (XMAC_CONF_OFF_TIME)
#else
#define DUTYCYCLE 10
#define OFF_TIME (ON_TIME * 10)
#endif
#define OFF_TIME BASE_TIME * (DUTYCYCLE)
#define ON_TIME BASE_TIME
#define STROBE_WAIT_TIME ON_TIME / 2
static volatile unsigned char should_be_awake = 0;
@ -119,9 +131,9 @@ powercycle(struct rtimer *t, void *ptr)
PT_BEGIN(&pt);
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) {
radio->off();
radio_is_on = 0;
@ -136,7 +148,7 @@ powercycle(struct rtimer *t, void *ptr)
(void (*)(struct rtimer *, void *))powercycle, ptr)) {
PRINTF("xmac: could not set rtimer\n");
}
t2 = rtimer_arch_now();
/* t2 = rtimer_arch_now(); */
/* printf("xmac 1 %d\n", t2 - t1); */
PT_YIELD(&pt);
@ -145,7 +157,7 @@ powercycle(struct rtimer *t, void *ptr)
PT_YIELD(&pt);
}
t1 = rtimer_arch_now();
/* t1 = rtimer_arch_now(); */
if(radio_is_on == 0) {
radio->on();
radio_is_on = 1;
@ -155,7 +167,7 @@ powercycle(struct rtimer *t, void *ptr)
(void (*)(struct rtimer *, void *))powercycle, ptr)) {
PRINTF("xmac: could not set rtimer\n");
}
t2 = rtimer_arch_now();
/* t2 = rtimer_arch_now(); */
/* printf("xmac 2 %d\n", t2 - t1); */
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
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;
someone_is_sending = 0;
}
}
@ -189,9 +207,11 @@ send(void)
we_are_sending = 1;
radio->on();
radio_is_on = 1;
/* 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));
hdr = rimebuf_hdrptr();
@ -246,6 +266,8 @@ send(void)
the packet. */
got_ack = 1;
break;
} else {
RIMESTATS_ADD(sendingdrop);
}
}
}
@ -264,7 +286,6 @@ send(void)
/* printf("Strobe %d got_ack %d\n", strobes, got_ack);*/
LEDS_OFF(LEDS_GREEN);
PT_INIT(&pt);
if(rtimer_set(&rt, RTIMER_NOW() + ON_TIME, 1,
(void (*)(struct rtimer *, void *))powercycle, NULL)) {
@ -274,12 +295,22 @@ send(void)
}
/*---------------------------------------------------------------------------*/
static struct queuebuf *queued_packet;
static void
qsend(void)
{
if(someone_is_sending) {
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);
if(queued_packet != NULL) {
RIMESTATS_ADD(contentiondrop);
} else {
#if WITH_QUEUE
queued_packet = queuebuf_new_from_rimebuf();
#else
RIMESTATS_ADD(contentiondrop);
#endif
}
} else {
PRINTF("xmac: send immediately.\n");
send();
@ -330,12 +361,14 @@ input(const struct radio_driver *d)
} else if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) {
/* Wait for the actual packet to arrive. */
should_be_awake = 1;
PRINTF("xmac: broadcast from %d.%d\n",
hdr->sender.u8[0],hdr->sender.u8[1]);
/* PRINTF("xmac: broadcast\n");*/
} else {
/* Go back to sleep. XXX should not turn on the radio again
until this packet has passed. */
should_be_awake = 0;
someone_is_sending = 0;
someone_is_sending = 1;
long_off = 1;
/* XXX set timer to turn someone_is_sending off again and send queued packet. */
/* PRINTF("xmac: not for us\n");*/
@ -350,6 +383,12 @@ input(const struct radio_driver *d)
PRINTF("xmac: final packet received\n");
rime_input();
/* 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.
*
* $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);
#endif /* __XMAC_H__ */