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:
parent
a495d1230b
commit
edd509acf5
2 changed files with 59 additions and 21 deletions
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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__ */
|
||||||
|
|
Loading…
Reference in a new issue