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.
|
* 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/radio.h"
|
||||||
#include "dev/watchdog.h"
|
#include "dev/watchdog.h"
|
||||||
#include "lib/random.h"
|
#include "lib/random.h"
|
||||||
/*#include "lib/bb.h"*/
|
|
||||||
|
|
||||||
#include "sys/timetable.h"
|
#include "sys/timetable.h"
|
||||||
|
|
||||||
|
@ -62,7 +61,31 @@
|
||||||
#define WITH_TIMESYNCH 0
|
#define WITH_TIMESYNCH 0
|
||||||
#define WITH_QUEUE 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 {
|
struct xmac_hdr {
|
||||||
|
uint16_t type;
|
||||||
rimeaddr_t sender;
|
rimeaddr_t sender;
|
||||||
rimeaddr_t receiver;
|
rimeaddr_t receiver;
|
||||||
};
|
};
|
||||||
|
@ -79,6 +102,13 @@ struct xmac_hdr {
|
||||||
#define DEFAULT_OFF_TIME (RTIMER_ARCH_SECOND / 2 - DEFAULT_ON_TIME)
|
#define DEFAULT_OFF_TIME (RTIMER_ARCH_SECOND / 2 - DEFAULT_ON_TIME)
|
||||||
#endif
|
#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)
|
#define DEFAULT_STROBE_WAIT_TIME (7 * DEFAULT_ON_TIME / 8)
|
||||||
|
|
||||||
struct xmac_config xmac_config = {
|
struct xmac_config xmac_config = {
|
||||||
|
@ -129,6 +159,15 @@ static const struct radio_driver *radio;
|
||||||
#define PRINTF(...)
|
#define PRINTF(...)
|
||||||
#endif
|
#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 *);
|
static void (* receiver_callback)(const struct mac_driver *);
|
||||||
|
|
||||||
#if WITH_TIMETABLE
|
#if WITH_TIMETABLE
|
||||||
|
@ -159,7 +198,7 @@ on(void)
|
||||||
static void
|
static void
|
||||||
off(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_is_on = 0;
|
||||||
radio->off();
|
radio->off();
|
||||||
#if WITH_TIMETABLE
|
#if WITH_TIMETABLE
|
||||||
|
@ -250,6 +289,54 @@ powercycle(struct rtimer *t, void *ptr)
|
||||||
PT_END(&pt);
|
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
|
static int
|
||||||
send_packet(void)
|
send_packet(void)
|
||||||
{
|
{
|
||||||
|
@ -258,7 +345,10 @@ send_packet(void)
|
||||||
int strobes;
|
int strobes;
|
||||||
struct xmac_hdr *hdr;
|
struct xmac_hdr *hdr;
|
||||||
int got_ack = 0;
|
int got_ack = 0;
|
||||||
struct xmac_hdr msg;
|
struct {
|
||||||
|
struct xmac_hdr hdr;
|
||||||
|
struct announcement_msg announcement;
|
||||||
|
} strobe;
|
||||||
int len;
|
int len;
|
||||||
int is_broadcast = 0;
|
int is_broadcast = 0;
|
||||||
|
|
||||||
|
@ -272,7 +362,7 @@ send_packet(void)
|
||||||
on();
|
on();
|
||||||
t0 = RTIMER_NOW();
|
t0 = RTIMER_NOW();
|
||||||
while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + xmac_config.strobe_wait_time * 2)) {
|
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) {
|
if(len > 0) {
|
||||||
someone_is_sending = 1;
|
someone_is_sending = 1;
|
||||||
}
|
}
|
||||||
|
@ -296,6 +386,7 @@ send_packet(void)
|
||||||
|
|
||||||
rimebuf_hdralloc(sizeof(struct xmac_hdr));
|
rimebuf_hdralloc(sizeof(struct xmac_hdr));
|
||||||
hdr = rimebuf_hdrptr();
|
hdr = rimebuf_hdrptr();
|
||||||
|
hdr->type = TYPE_DATA;
|
||||||
rimeaddr_copy(&hdr->sender, &rimeaddr_node_addr);
|
rimeaddr_copy(&hdr->sender, &rimeaddr_node_addr);
|
||||||
rimeaddr_copy(&hdr->receiver, rimebuf_addr(RIMEBUF_ADDR_RECEIVER));
|
rimeaddr_copy(&hdr->receiver, rimebuf_addr(RIMEBUF_ADDR_RECEIVER));
|
||||||
if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) {
|
if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) {
|
||||||
|
@ -325,35 +416,30 @@ send_packet(void)
|
||||||
strobes++) {
|
strobes++) {
|
||||||
|
|
||||||
t = RTIMER_NOW();
|
t = RTIMER_NOW();
|
||||||
|
strobe.hdr.type = TYPE_STROBE;
|
||||||
rimeaddr_copy(&msg.sender, &rimeaddr_node_addr);
|
rimeaddr_copy(&strobe.hdr.sender, &rimeaddr_node_addr);
|
||||||
rimeaddr_copy(&msg.receiver, rimebuf_addr(RIMEBUF_ADDR_RECEIVER));
|
rimeaddr_copy(&strobe.hdr.receiver, rimebuf_addr(RIMEBUF_ADDR_RECEIVER));
|
||||||
|
|
||||||
#if WITH_TIMETABLE
|
#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");
|
TIMETABLE_TIMESTAMP(xmac_timetable, "send broadcast strobe");
|
||||||
} else {
|
} else {
|
||||||
TIMETABLE_TIMESTAMP(xmac_timetable, "send strobe");
|
TIMETABLE_TIMESTAMP(xmac_timetable, "send strobe");
|
||||||
}
|
}
|
||||||
#endif
|
#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. */
|
/* Send the strobe packet. */
|
||||||
radio->send((const uint8_t *)&msg, sizeof(struct xmac_hdr));
|
radio->send((const uint8_t *)&strobe, sizeof(struct xmac_hdr));
|
||||||
}
|
|
||||||
CPRINTF("+");
|
CPRINTF("+");
|
||||||
|
|
||||||
while(got_ack == 0 &&
|
while(got_ack == 0 &&
|
||||||
RTIMER_CLOCK_LT(RTIMER_NOW(), t + xmac_config.strobe_wait_time)) {
|
RTIMER_CLOCK_LT(RTIMER_NOW(), t + xmac_config.strobe_wait_time)) {
|
||||||
/* See if we got an ACK */
|
/* 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) {
|
if(len > 0) {
|
||||||
CPRINTF("_");
|
CPRINTF("_");
|
||||||
if(rimeaddr_cmp(&msg.sender, &rimeaddr_node_addr) &&
|
if(rimeaddr_cmp(&strobe.hdr.sender, &rimeaddr_node_addr) &&
|
||||||
rimeaddr_cmp(&msg.receiver, &rimeaddr_node_addr)) {
|
rimeaddr_cmp(&strobe.hdr.receiver, &rimeaddr_node_addr)) {
|
||||||
#if WITH_TIMETABLE
|
#if WITH_TIMETABLE
|
||||||
TIMETABLE_TIMESTAMP(xmac_timetable, "send ack received");
|
TIMETABLE_TIMESTAMP(xmac_timetable, "send ack received");
|
||||||
#endif
|
#endif
|
||||||
|
@ -469,7 +555,7 @@ read_packet(void)
|
||||||
|
|
||||||
rimebuf_hdrreduce(sizeof(struct xmac_hdr));
|
rimebuf_hdrreduce(sizeof(struct xmac_hdr));
|
||||||
|
|
||||||
if(rimebuf_totlen() == 0) {
|
if(hdr->type == TYPE_STROBE) {
|
||||||
CPRINTF(".");
|
CPRINTF(".");
|
||||||
/* There is no data in the packet so it has to be a strobe. */
|
/* There is no data in the packet so it has to be a strobe. */
|
||||||
someone_is_sending = 2;
|
someone_is_sending = 2;
|
||||||
|
@ -510,10 +596,15 @@ read_packet(void)
|
||||||
waiting_for_packet = 1;
|
waiting_for_packet = 1;
|
||||||
on();
|
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
|
/* We are done processing the strobe and we therefore return
|
||||||
to the caller. */
|
to the caller. */
|
||||||
return RIME_OK;
|
return RIME_OK;
|
||||||
} else {
|
} else if(hdr->type == TYPE_DATA) {
|
||||||
CPRINTF("-");
|
CPRINTF("-");
|
||||||
someone_is_sending = 0;
|
someone_is_sending = 0;
|
||||||
if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_node_addr) ||
|
if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_node_addr) ||
|
||||||
|
@ -537,11 +628,60 @@ read_packet(void)
|
||||||
|
|
||||||
return rimebuf_totlen();
|
return rimebuf_totlen();
|
||||||
}
|
}
|
||||||
|
#if XMAC_CONF_ANNOUNCEMENTS
|
||||||
|
} else if(hdr->type == TYPE_ANNOUNCEMENT) {
|
||||||
|
parse_announcements(&hdr->sender);
|
||||||
|
#endif /* XMAC_CONF_ANNOUNCEMENTS */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
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 *
|
const struct mac_driver *
|
||||||
xmac_init(const struct radio_driver *d)
|
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_STROBES, 0);
|
||||||
BB_SET(XMAC_SEND_WITH_ACK, 0);
|
BB_SET(XMAC_SEND_WITH_ACK, 0);
|
||||||
BB_SET(XMAC_SEND_WITH_NOACK, 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;
|
return &xmac_driver;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
Loading…
Reference in a new issue