Added MAC-layer announcement beacons to X-MAC. Configuratble through XMAC_CONF_ANNOUNCEMENTS
This commit is contained in:
parent
883d10e136
commit
e4b1ff461e
|
@ -28,7 +28,7 @@
|
|||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
* $Id: xmac.c,v 1.22 2009/02/07 18:45:50 adamdunkels Exp $
|
||||
* $Id: xmac.c,v 1.23 2009/02/14 20:35:03 adamdunkels Exp $
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -47,7 +47,6 @@
|
|||
#include "dev/radio.h"
|
||||
#include "dev/watchdog.h"
|
||||
#include "lib/random.h"
|
||||
/*#include "lib/bb.h"*/
|
||||
|
||||
#include "sys/timetable.h"
|
||||
|
||||
|
@ -62,7 +61,31 @@
|
|||
#define WITH_TIMESYNCH 0
|
||||
#define WITH_QUEUE 0
|
||||
|
||||
struct announcement_data {
|
||||
uint16_t id;
|
||||
uint16_t value;
|
||||
};
|
||||
|
||||
/* The maximum number of announcements in a single announcement
|
||||
message - may need to be increased in the future. */
|
||||
#define ANNOUNCEMENT_MAX 10
|
||||
|
||||
/* The length of the header of the announcement message, i.e., the
|
||||
"num" field in the struct. */
|
||||
#define ANNOUNCEMENT_MSG_HEADERLEN 2
|
||||
|
||||
/* The structure of the announcement messages. */
|
||||
struct announcement_msg {
|
||||
uint16_t num;
|
||||
struct announcement_data data[ANNOUNCEMENT_MAX];
|
||||
};
|
||||
|
||||
#define TYPE_STROBE 0
|
||||
#define TYPE_DATA 1
|
||||
#define TYPE_ANNOUNCEMENT 2
|
||||
|
||||
struct xmac_hdr {
|
||||
uint16_t type;
|
||||
rimeaddr_t sender;
|
||||
rimeaddr_t receiver;
|
||||
};
|
||||
|
@ -79,6 +102,13 @@ struct xmac_hdr {
|
|||
#define DEFAULT_OFF_TIME (RTIMER_ARCH_SECOND / 2 - DEFAULT_ON_TIME)
|
||||
#endif
|
||||
|
||||
/* The cycle time for announcements. */
|
||||
#define ANNOUNCEMENT_PERIOD 4 * CLOCK_SECOND
|
||||
|
||||
/* The time before sending an announcement within one announcement
|
||||
cycle. */
|
||||
#define ANNOUNCEMENT_TIME (rand() % (ANNOUNCEMENT_PERIOD))
|
||||
|
||||
#define DEFAULT_STROBE_WAIT_TIME (7 * DEFAULT_ON_TIME / 8)
|
||||
|
||||
struct xmac_config xmac_config = {
|
||||
|
@ -129,6 +159,15 @@ static const struct radio_driver *radio;
|
|||
#define PRINTF(...)
|
||||
#endif
|
||||
|
||||
#if XMAC_CONF_ANNOUNCEMENTS
|
||||
/* Timers for keeping track of when to send announcements. */
|
||||
static struct ctimer announcement_cycle_ctimer, announcement_ctimer;
|
||||
#endif /* XMAC_CONF_ANNOUNCEMENTS */
|
||||
|
||||
/* Flag that is used to keep track of whether or not we are listening
|
||||
for announcements from neighbors. */
|
||||
static uint8_t is_listening;
|
||||
|
||||
static void (* receiver_callback)(const struct mac_driver *);
|
||||
|
||||
#if WITH_TIMETABLE
|
||||
|
@ -159,7 +198,7 @@ on(void)
|
|||
static void
|
||||
off(void)
|
||||
{
|
||||
if(xmac_is_on && radio_is_on != 0) {
|
||||
if(xmac_is_on && radio_is_on != 0 && is_listening == 0) {
|
||||
radio_is_on = 0;
|
||||
radio->off();
|
||||
#if WITH_TIMETABLE
|
||||
|
@ -250,6 +289,54 @@ powercycle(struct rtimer *t, void *ptr)
|
|||
PT_END(&pt);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if XMAC_CONF_ANNOUNCEMENTS
|
||||
static int
|
||||
parse_announcements(rimeaddr_t *from)
|
||||
{
|
||||
/* Parse incoming announcements */
|
||||
struct announcement_msg *adata = rimebuf_dataptr();
|
||||
int i;
|
||||
|
||||
PRINTF("%d.%d: probe from %d.%d with %d announcements\n",
|
||||
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
||||
hdr->sender.u8[0], hdr->sender.u8[1], adata->num);
|
||||
|
||||
for(i = 0; i < adata->num; ++i) {
|
||||
PRINTF("%d.%d: announcement %d: %d\n",
|
||||
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
||||
adata->data[i].id,
|
||||
adata->data[i].value);
|
||||
|
||||
announcement_heard(from,
|
||||
adata->data[i].id,
|
||||
adata->data[i].value);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
format_announcement(char *hdr)
|
||||
{
|
||||
struct announcement_msg *adata;
|
||||
struct announcement *a;
|
||||
|
||||
/* Construct the announcements */
|
||||
adata = (struct announcement_msg *)hdr;
|
||||
|
||||
adata->num = 0;
|
||||
for(a = announcement_list();
|
||||
a != NULL && adata->num < ANNOUNCEMENT_MAX;
|
||||
a = a->next) {
|
||||
adata->data[adata->num].id = a->id;
|
||||
adata->data[adata->num].value = a->value;
|
||||
adata->num++;
|
||||
}
|
||||
|
||||
return ANNOUNCEMENT_MSG_HEADERLEN +
|
||||
sizeof(struct announcement_data) * adata->num;
|
||||
}
|
||||
#endif /* XMAC_CONF_ANNOUNCEMENTS */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
send_packet(void)
|
||||
{
|
||||
|
@ -258,7 +345,10 @@ send_packet(void)
|
|||
int strobes;
|
||||
struct xmac_hdr *hdr;
|
||||
int got_ack = 0;
|
||||
struct xmac_hdr msg;
|
||||
struct {
|
||||
struct xmac_hdr hdr;
|
||||
struct announcement_msg announcement;
|
||||
} strobe;
|
||||
int len;
|
||||
int is_broadcast = 0;
|
||||
|
||||
|
@ -272,7 +362,7 @@ send_packet(void)
|
|||
on();
|
||||
t0 = RTIMER_NOW();
|
||||
while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + xmac_config.strobe_wait_time * 2)) {
|
||||
len = radio->read(&msg, sizeof(msg));
|
||||
len = radio->read(&strobe.hdr, sizeof(strobe.hdr));
|
||||
if(len > 0) {
|
||||
someone_is_sending = 1;
|
||||
}
|
||||
|
@ -296,6 +386,7 @@ send_packet(void)
|
|||
|
||||
rimebuf_hdralloc(sizeof(struct xmac_hdr));
|
||||
hdr = rimebuf_hdrptr();
|
||||
hdr->type = TYPE_DATA;
|
||||
rimeaddr_copy(&hdr->sender, &rimeaddr_node_addr);
|
||||
rimeaddr_copy(&hdr->receiver, rimebuf_addr(RIMEBUF_ADDR_RECEIVER));
|
||||
if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) {
|
||||
|
@ -325,35 +416,30 @@ send_packet(void)
|
|||
strobes++) {
|
||||
|
||||
t = RTIMER_NOW();
|
||||
|
||||
rimeaddr_copy(&msg.sender, &rimeaddr_node_addr);
|
||||
rimeaddr_copy(&msg.receiver, rimebuf_addr(RIMEBUF_ADDR_RECEIVER));
|
||||
strobe.hdr.type = TYPE_STROBE;
|
||||
rimeaddr_copy(&strobe.hdr.sender, &rimeaddr_node_addr);
|
||||
rimeaddr_copy(&strobe.hdr.receiver, rimebuf_addr(RIMEBUF_ADDR_RECEIVER));
|
||||
|
||||
#if WITH_TIMETABLE
|
||||
if(rimeaddr_cmp(&msg.receiver, &rimeaddr_null)) {
|
||||
if(rimeaddr_cmp(&strobe.hdr.receiver, &rimeaddr_null)) {
|
||||
TIMETABLE_TIMESTAMP(xmac_timetable, "send broadcast strobe");
|
||||
} else {
|
||||
TIMETABLE_TIMESTAMP(xmac_timetable, "send strobe");
|
||||
}
|
||||
#endif
|
||||
if(0/*is_broadcast*/) {
|
||||
/* If we are sending a broadcast, we don't send strobes, we
|
||||
simply send the data packet repetedly */
|
||||
radio->send(rimebuf_hdrptr(), rimebuf_totlen());
|
||||
} else {
|
||||
/* Send the strobe packet. */
|
||||
radio->send((const uint8_t *)&msg, sizeof(struct xmac_hdr));
|
||||
}
|
||||
/* Send the strobe packet. */
|
||||
radio->send((const uint8_t *)&strobe, sizeof(struct xmac_hdr));
|
||||
|
||||
CPRINTF("+");
|
||||
|
||||
while(got_ack == 0 &&
|
||||
RTIMER_CLOCK_LT(RTIMER_NOW(), t + xmac_config.strobe_wait_time)) {
|
||||
/* See if we got an ACK */
|
||||
len = radio->read((uint8_t *)&msg, sizeof(struct xmac_hdr));
|
||||
len = radio->read((uint8_t *)&strobe, sizeof(struct xmac_hdr));
|
||||
if(len > 0) {
|
||||
CPRINTF("_");
|
||||
if(rimeaddr_cmp(&msg.sender, &rimeaddr_node_addr) &&
|
||||
rimeaddr_cmp(&msg.receiver, &rimeaddr_node_addr)) {
|
||||
if(rimeaddr_cmp(&strobe.hdr.sender, &rimeaddr_node_addr) &&
|
||||
rimeaddr_cmp(&strobe.hdr.receiver, &rimeaddr_node_addr)) {
|
||||
#if WITH_TIMETABLE
|
||||
TIMETABLE_TIMESTAMP(xmac_timetable, "send ack received");
|
||||
#endif
|
||||
|
@ -469,7 +555,7 @@ read_packet(void)
|
|||
|
||||
rimebuf_hdrreduce(sizeof(struct xmac_hdr));
|
||||
|
||||
if(rimebuf_totlen() == 0) {
|
||||
if(hdr->type == TYPE_STROBE) {
|
||||
CPRINTF(".");
|
||||
/* There is no data in the packet so it has to be a strobe. */
|
||||
someone_is_sending = 2;
|
||||
|
@ -510,10 +596,15 @@ read_packet(void)
|
|||
waiting_for_packet = 1;
|
||||
on();
|
||||
}
|
||||
|
||||
/* Check for annoucements in the strobe */
|
||||
/* if(rimebuf_datalen() > 0) {
|
||||
parse_announcements(&hdr->sender);
|
||||
}*/
|
||||
/* We are done processing the strobe and we therefore return
|
||||
to the caller. */
|
||||
return RIME_OK;
|
||||
} else {
|
||||
} else if(hdr->type == TYPE_DATA) {
|
||||
CPRINTF("-");
|
||||
someone_is_sending = 0;
|
||||
if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_node_addr) ||
|
||||
|
@ -537,11 +628,60 @@ read_packet(void)
|
|||
|
||||
return rimebuf_totlen();
|
||||
}
|
||||
#if XMAC_CONF_ANNOUNCEMENTS
|
||||
} else if(hdr->type == TYPE_ANNOUNCEMENT) {
|
||||
parse_announcements(&hdr->sender);
|
||||
#endif /* XMAC_CONF_ANNOUNCEMENTS */
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if XMAC_CONF_ANNOUNCEMENTS
|
||||
static void
|
||||
send_announcement(void *ptr)
|
||||
{
|
||||
struct xmac_hdr *hdr;
|
||||
struct announcement_msg *adata;
|
||||
struct announcement *a;
|
||||
int announcement_len;
|
||||
|
||||
/* Set up the probe header. */
|
||||
rimebuf_clear();
|
||||
rimebuf_set_datalen(sizeof(struct xmac_hdr));
|
||||
hdr = rimebuf_dataptr();
|
||||
hdr->type = TYPE_ANNOUNCEMENT;
|
||||
rimeaddr_copy(&hdr->sender, &rimeaddr_node_addr);
|
||||
rimeaddr_copy(&hdr->receiver, &rimeaddr_null);
|
||||
|
||||
announcement_len = format_announcement((char *)hdr +
|
||||
sizeof(struct xmac_hdr));
|
||||
|
||||
rimebuf_set_datalen(sizeof(struct xmac_hdr) + announcement_len);
|
||||
|
||||
/* PRINTF("Sending probe\n");*/
|
||||
radio->send(rimebuf_hdrptr(), rimebuf_totlen());
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
cycle_announcement(void *ptr)
|
||||
{
|
||||
ctimer_set(&announcement_ctimer, ANNOUNCEMENT_TIME,
|
||||
send_announcement, NULL);
|
||||
ctimer_set(&announcement_cycle_ctimer, ANNOUNCEMENT_PERIOD,
|
||||
cycle_announcement, NULL);
|
||||
if(is_listening > 0) {
|
||||
is_listening--;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
listen_callback(int periods)
|
||||
{
|
||||
is_listening = periods + 1;
|
||||
}
|
||||
#endif /* XMAC_CONF_ANNOUNCEMENTS */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
const struct mac_driver *
|
||||
xmac_init(const struct radio_driver *d)
|
||||
{
|
||||
|
@ -563,6 +703,12 @@ xmac_init(const struct radio_driver *d)
|
|||
BB_SET(XMAC_STROBES, 0);
|
||||
BB_SET(XMAC_SEND_WITH_ACK, 0);
|
||||
BB_SET(XMAC_SEND_WITH_NOACK, 0);
|
||||
|
||||
#if XMAC_CONF_ANNOUNCEMENTS
|
||||
announcement_register_listen_callback(listen_callback);
|
||||
ctimer_set(&announcement_cycle_ctimer, ANNOUNCEMENT_TIME,
|
||||
cycle_announcement, NULL);
|
||||
#endif /* XMAC_CONF_ANNOUNCEMENTS */
|
||||
return &xmac_driver;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
|
Loading…
Reference in a new issue