mirror of
https://github.com/oliverschmidt/contiki.git
synced 2024-12-23 01:29:33 +00:00
Added MAC layer framing support to X-MAC so that packets now are standard 802.15.4 frames
This commit is contained in:
parent
1b26fcd5c7
commit
9ec57d61ad
@ -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.37 2009/10/19 06:39:29 adamdunkels Exp $
|
* $Id: xmac.c,v 1.38 2009/10/19 20:53:56 adamdunkels Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,19 +36,21 @@
|
|||||||
* A simple power saving MAC protocol based on X-MAC [SenSys 2006]
|
* A simple power saving MAC protocol based on X-MAC [SenSys 2006]
|
||||||
* \author
|
* \author
|
||||||
* Adam Dunkels <adam@sics.se>
|
* Adam Dunkels <adam@sics.se>
|
||||||
|
* Niclas Finne <nfi@sics.se>
|
||||||
|
* Joakim Eriksson <joakime@sics.se>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "sys/pt.h"
|
|
||||||
#include "net/mac/xmac.h"
|
|
||||||
#include "sys/rtimer.h"
|
|
||||||
#include "dev/leds.h"
|
#include "dev/leds.h"
|
||||||
#include "net/rime.h"
|
|
||||||
#include "net/rime/timesynch.h"
|
|
||||||
#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 "net/mac/framer.h"
|
||||||
|
#include "net/mac/xmac.h"
|
||||||
|
#include "net/rime.h"
|
||||||
|
#include "net/rime/timesynch.h"
|
||||||
#include "sys/compower.h"
|
#include "sys/compower.h"
|
||||||
|
#include "sys/pt.h"
|
||||||
|
#include "sys/rtimer.h"
|
||||||
|
|
||||||
#include "contiki-conf.h"
|
#include "contiki-conf.h"
|
||||||
|
|
||||||
@ -80,21 +82,23 @@ struct announcement_msg {
|
|||||||
"num" field in the struct. */
|
"num" field in the struct. */
|
||||||
#define ANNOUNCEMENT_MSG_HEADERLEN (sizeof (uint16_t))
|
#define ANNOUNCEMENT_MSG_HEADERLEN (sizeof (uint16_t))
|
||||||
|
|
||||||
#define TYPE_STROBE 0
|
#define DISPATCH 0
|
||||||
#define TYPE_DATA 1
|
#define TYPE_STROBE 0x10
|
||||||
#define TYPE_ANNOUNCEMENT 2
|
/* #define TYPE_DATA 0x11 */
|
||||||
#define TYPE_STROBE_ACK 3
|
#define TYPE_ANNOUNCEMENT 0x12
|
||||||
|
#define TYPE_STROBE_ACK 0x13
|
||||||
|
|
||||||
struct xmac_hdr {
|
struct xmac_hdr {
|
||||||
uint16_t type;
|
uint8_t dispatch;
|
||||||
rimeaddr_t sender;
|
uint8_t type;
|
||||||
rimeaddr_t receiver;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define MAX_STROBE_SIZE 40
|
||||||
|
|
||||||
#ifdef XMAC_CONF_ON_TIME
|
#ifdef XMAC_CONF_ON_TIME
|
||||||
#define DEFAULT_ON_TIME (XMAC_CONF_ON_TIME)
|
#define DEFAULT_ON_TIME (XMAC_CONF_ON_TIME)
|
||||||
#else
|
#else
|
||||||
#define DEFAULT_ON_TIME (RTIMER_ARCH_SECOND / 200)
|
#define DEFAULT_ON_TIME (RTIMER_ARCH_SECOND / 160)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef XMAC_CONF_OFF_TIME
|
#ifdef XMAC_CONF_OFF_TIME
|
||||||
@ -154,6 +158,7 @@ static const struct radio_driver *radio;
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#define PRINTF(...) printf(__VA_ARGS__)
|
#define PRINTF(...) printf(__VA_ARGS__)
|
||||||
|
#define PRINTDEBUG(...) printf(__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
#undef LEDS_ON
|
#undef LEDS_ON
|
||||||
#undef LEDS_OFF
|
#undef LEDS_OFF
|
||||||
@ -162,6 +167,7 @@ static const struct radio_driver *radio;
|
|||||||
#define LEDS_OFF(x)
|
#define LEDS_OFF(x)
|
||||||
#define LEDS_TOGGLE(x)
|
#define LEDS_TOGGLE(x)
|
||||||
#define PRINTF(...)
|
#define PRINTF(...)
|
||||||
|
#define PRINTDEBUG(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if XMAC_CONF_ANNOUNCEMENTS
|
#if XMAC_CONF_ANNOUNCEMENTS
|
||||||
@ -251,7 +257,7 @@ powercycle(struct rtimer *t, void *ptr)
|
|||||||
#endif /* XMAC_CONF_COMPOWER */
|
#endif /* XMAC_CONF_COMPOWER */
|
||||||
} else {
|
} else {
|
||||||
waiting_for_packet++;
|
waiting_for_packet++;
|
||||||
if(waiting_for_packet >= 2) {
|
if(waiting_for_packet > 2) {
|
||||||
/* We should not be awake for more than two consecutive
|
/* We should not be awake for more than two consecutive
|
||||||
power cycles without having heard a packet, so we turn off
|
power cycles without having heard a packet, so we turn off
|
||||||
the radio. */
|
the radio. */
|
||||||
@ -317,7 +323,7 @@ powercycle(struct rtimer *t, void *ptr)
|
|||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
#if XMAC_CONF_ANNOUNCEMENTS
|
#if XMAC_CONF_ANNOUNCEMENTS
|
||||||
static int
|
static int
|
||||||
parse_announcements(rimeaddr_t *from)
|
parse_announcements(const rimeaddr_t *from)
|
||||||
{
|
{
|
||||||
/* Parse incoming announcements */
|
/* Parse incoming announcements */
|
||||||
struct announcement_msg *adata = packetbuf_dataptr();
|
struct announcement_msg *adata = packetbuf_dataptr();
|
||||||
@ -383,7 +389,7 @@ remove_encounter(void *encounter)
|
|||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
static void
|
||||||
register_encounter(rimeaddr_t *neighbor, rtimer_clock_t time)
|
register_encounter(const rimeaddr_t *neighbor, rtimer_clock_t time)
|
||||||
{
|
{
|
||||||
struct encounter *e;
|
struct encounter *e;
|
||||||
|
|
||||||
@ -395,7 +401,7 @@ register_encounter(rimeaddr_t *neighbor, rtimer_clock_t time)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* No matchin encounter was found, so we allocate a new one. */
|
/* No matching encounter was found, so we allocate a new one. */
|
||||||
if(e == NULL) {
|
if(e == NULL) {
|
||||||
e = memb_alloc(&encounter_memb);
|
e = memb_alloc(&encounter_memb);
|
||||||
if(e == NULL) {
|
if(e == NULL) {
|
||||||
@ -415,17 +421,16 @@ send_packet(void)
|
|||||||
{
|
{
|
||||||
rtimer_clock_t t0;
|
rtimer_clock_t t0;
|
||||||
rtimer_clock_t t;
|
rtimer_clock_t t;
|
||||||
rtimer_clock_t encounter_time;
|
rtimer_clock_t encounter_time = 0;
|
||||||
int strobes;
|
int strobes;
|
||||||
struct xmac_hdr hdr;
|
struct xmac_hdr *hdr;
|
||||||
int got_strobe_ack = 0;
|
int got_strobe_ack = 0;
|
||||||
struct {
|
uint8_t strobe[MAX_STROBE_SIZE];
|
||||||
struct xmac_hdr hdr;
|
int strobe_len, len;
|
||||||
struct announcement_msg announcement;
|
|
||||||
} strobe;
|
|
||||||
int len;
|
|
||||||
int is_broadcast = 0;
|
int is_broadcast = 0;
|
||||||
|
int is_reliable;
|
||||||
struct encounter *e;
|
struct encounter *e;
|
||||||
|
struct queuebuf *packet;
|
||||||
|
|
||||||
#if WITH_RANDOM_WAIT_BEFORE_SEND
|
#if WITH_RANDOM_WAIT_BEFORE_SEND
|
||||||
{
|
{
|
||||||
@ -434,6 +439,50 @@ send_packet(void)
|
|||||||
}
|
}
|
||||||
#endif /* WITH_RANDOM_WAIT_BEFORE_SEND */
|
#endif /* WITH_RANDOM_WAIT_BEFORE_SEND */
|
||||||
|
|
||||||
|
/* Create the X-MAC header for the data packet. */
|
||||||
|
packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr);
|
||||||
|
if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) {
|
||||||
|
is_broadcast = 1;
|
||||||
|
PRINTDEBUG("xmac: send broadcast\n");
|
||||||
|
} else {
|
||||||
|
#if UIP_CONF_IPV6
|
||||||
|
PRINTDEBUG("xmac: send unicast to %02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
|
||||||
|
packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
|
||||||
|
packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1],
|
||||||
|
packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[2],
|
||||||
|
packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[3],
|
||||||
|
packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[4],
|
||||||
|
packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[5],
|
||||||
|
packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[6],
|
||||||
|
packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[7]);
|
||||||
|
#else
|
||||||
|
PRINTDEBUG("xmac: send unicast to %u.%u\n",
|
||||||
|
packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
|
||||||
|
packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1]);
|
||||||
|
#endif /* UIP_CONF_IPV6 */
|
||||||
|
}
|
||||||
|
is_reliable = packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ||
|
||||||
|
packetbuf_attr(PACKETBUF_ATTR_ERELIABLE);
|
||||||
|
len = framer_get()->create();
|
||||||
|
strobe_len = len + sizeof(struct xmac_hdr);
|
||||||
|
if(len == 0 || strobe_len > sizeof(strobe)) {
|
||||||
|
/* Failed to send */
|
||||||
|
PRINTF("xmac: send failed, too large header\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memcpy(strobe, packetbuf_hdrptr(), len);
|
||||||
|
strobe[len] = DISPATCH; /* dispatch */
|
||||||
|
strobe[len + 1] = TYPE_STROBE; /* type */
|
||||||
|
|
||||||
|
packetbuf_compact();
|
||||||
|
packet = queuebuf_new_from_packetbuf();
|
||||||
|
if(packet == NULL) {
|
||||||
|
/* No buffer available */
|
||||||
|
PRINTF("xmac: send failed, no queue buffer available (of %u)\n",
|
||||||
|
QUEUEBUF_CONF_NUM);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if WITH_CHANNEL_CHECK
|
#if WITH_CHANNEL_CHECK
|
||||||
/* Check if there are other strobes in the air. */
|
/* Check if there are other strobes in the air. */
|
||||||
@ -488,7 +537,6 @@ send_packet(void)
|
|||||||
receiver will already be awake. */
|
receiver will already be awake. */
|
||||||
while(RTIMER_CLOCK_LT(RTIMER_NOW(), expected));
|
while(RTIMER_CLOCK_LT(RTIMER_NOW(), expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* WITH_ACK_OPTIMIZATION */
|
#else /* WITH_ACK_OPTIMIZATION */
|
||||||
/* Wait until the receiver is expected to be awake */
|
/* Wait until the receiver is expected to be awake */
|
||||||
while(RTIMER_CLOCK_LT(RTIMER_NOW(), expected));
|
while(RTIMER_CLOCK_LT(RTIMER_NOW(), expected));
|
||||||
@ -497,22 +545,6 @@ send_packet(void)
|
|||||||
}
|
}
|
||||||
#endif /* WITH_ENCOUNTER_OPTIMIZATION */
|
#endif /* WITH_ENCOUNTER_OPTIMIZATION */
|
||||||
|
|
||||||
/* Create the X-MAC header for the data packet. We cannot do this
|
|
||||||
in-place in the packet buffer, because we cannot be sure of the
|
|
||||||
alignment of the header in the packet buffer. */
|
|
||||||
hdr.type = TYPE_DATA;
|
|
||||||
rimeaddr_copy(&hdr.sender, &rimeaddr_node_addr);
|
|
||||||
rimeaddr_copy(&hdr.receiver, packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
|
|
||||||
if(rimeaddr_cmp(&hdr.receiver, &rimeaddr_null)) {
|
|
||||||
is_broadcast = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy the X-MAC header to the header portion of the packet
|
|
||||||
buffer. */
|
|
||||||
packetbuf_hdralloc(sizeof(struct xmac_hdr));
|
|
||||||
memcpy(packetbuf_hdrptr(), &hdr, sizeof(struct xmac_hdr));
|
|
||||||
packetbuf_compact();
|
|
||||||
|
|
||||||
t0 = RTIMER_NOW();
|
t0 = RTIMER_NOW();
|
||||||
strobes = 0;
|
strobes = 0;
|
||||||
|
|
||||||
@ -534,27 +566,45 @@ send_packet(void)
|
|||||||
|
|
||||||
t = RTIMER_NOW();
|
t = RTIMER_NOW();
|
||||||
|
|
||||||
strobe.hdr.type = TYPE_STROBE;
|
|
||||||
rimeaddr_copy(&strobe.hdr.sender, &rimeaddr_node_addr);
|
|
||||||
rimeaddr_copy(&strobe.hdr.receiver, packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
|
|
||||||
|
|
||||||
/* Send the strobe packet. */
|
/* Send the strobe packet. */
|
||||||
radio->send((const uint8_t *)&strobe, sizeof(struct xmac_hdr));
|
radio->send(strobe, strobe_len);
|
||||||
|
|
||||||
while(got_strobe_ack == 0 &&
|
while(got_strobe_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 */
|
||||||
if(!is_broadcast) {
|
if(!is_broadcast) {
|
||||||
len = radio->read((uint8_t *)&strobe, sizeof(struct xmac_hdr));
|
packetbuf_clear();
|
||||||
|
len = radio->read(packetbuf_dataptr(), PACKETBUF_SIZE);
|
||||||
if(len > 0) {
|
if(len > 0) {
|
||||||
if(rimeaddr_cmp(&strobe.hdr.sender, &rimeaddr_node_addr) &&
|
packetbuf_set_datalen(len);
|
||||||
rimeaddr_cmp(&strobe.hdr.receiver, &rimeaddr_node_addr)) {
|
if(framer_get()->parse()) {
|
||||||
/* We got an ACK from the receiver, so we can immediately send
|
hdr = packetbuf_dataptr();
|
||||||
the packet. */
|
|
||||||
got_strobe_ack = 1;
|
if(hdr->dispatch == DISPATCH && hdr->type == TYPE_STROBE_ACK) {
|
||||||
encounter_time = RTIMER_NOW();
|
if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
|
||||||
}
|
&rimeaddr_node_addr)) {
|
||||||
}
|
/* We got an ACK from the receiver, so we can immediately send
|
||||||
|
the packet. */
|
||||||
|
got_strobe_ack = 1;
|
||||||
|
encounter_time = RTIMER_NOW();
|
||||||
|
} else {
|
||||||
|
PRINTDEBUG("xmac: strobe ack for someone else\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* TODO One of the nodes should back-off since several
|
||||||
|
nodes are sending at once. If possible and if the
|
||||||
|
packet is destined for this node: send a strobe ack
|
||||||
|
if it is a strobe packet, queue the packet if it is a
|
||||||
|
data packet? */
|
||||||
|
PRINTDEBUG("xmac: ignored data %u\n", len);
|
||||||
|
#if DEBUG
|
||||||
|
/* collisions++;*/
|
||||||
|
#endif /* DEBUG */
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PRINTF("xmac: send failed to parse %u\n", len);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -587,6 +637,10 @@ send_packet(void)
|
|||||||
keep it on() for a while. */
|
keep it on() for a while. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* restore the packet to send */
|
||||||
|
queuebuf_to_packetbuf(packet);
|
||||||
|
queuebuf_free(packet);
|
||||||
|
|
||||||
/* Send the data packet. */
|
/* Send the data packet. */
|
||||||
if(is_broadcast || got_strobe_ack) {
|
if(is_broadcast || got_strobe_ack) {
|
||||||
radio->send(packetbuf_hdrptr(), packetbuf_totlen());
|
radio->send(packetbuf_hdrptr(), packetbuf_totlen());
|
||||||
@ -594,7 +648,7 @@ send_packet(void)
|
|||||||
|
|
||||||
#if WITH_ENCOUNTER_OPTIMIZATION
|
#if WITH_ENCOUNTER_OPTIMIZATION
|
||||||
if(got_strobe_ack) {
|
if(got_strobe_ack) {
|
||||||
register_encounter(&hdr.receiver, encounter_time);
|
register_encounter(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), encounter_time);
|
||||||
}
|
}
|
||||||
#endif /* WITH_ENCOUNTER_OPTIMIZATION */
|
#endif /* WITH_ENCOUNTER_OPTIMIZATION */
|
||||||
watchdog_start();
|
watchdog_start();
|
||||||
@ -667,74 +721,29 @@ read_packet(void)
|
|||||||
packetbuf_clear();
|
packetbuf_clear();
|
||||||
|
|
||||||
len = radio->read(packetbuf_dataptr(), PACKETBUF_SIZE);
|
len = radio->read(packetbuf_dataptr(), PACKETBUF_SIZE);
|
||||||
|
if(len == 0) {
|
||||||
if(len > 0) {
|
return 0;
|
||||||
packetbuf_set_datalen(len);
|
}
|
||||||
|
|
||||||
|
packetbuf_set_datalen(len);
|
||||||
|
|
||||||
|
if(framer_get()->parse()) {
|
||||||
hdr = packetbuf_dataptr();
|
hdr = packetbuf_dataptr();
|
||||||
|
|
||||||
packetbuf_hdrreduce(sizeof(struct xmac_hdr));
|
if(hdr->dispatch != DISPATCH) {
|
||||||
|
|
||||||
if(hdr->type == TYPE_STROBE) {
|
|
||||||
/* There is no data in the packet so it has to be a strobe. */
|
|
||||||
someone_is_sending = 2;
|
|
||||||
|
|
||||||
if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_node_addr)) {
|
|
||||||
/* This is a strobe packet for us. */
|
|
||||||
|
|
||||||
if(rimeaddr_cmp(&hdr->sender, &rimeaddr_node_addr)) {
|
|
||||||
/* If the sender address is our node address, the strobe is
|
|
||||||
a stray strobe ACK to us, which we ignore unless we are
|
|
||||||
currently sending a packet. */
|
|
||||||
someone_is_sending = 0;
|
|
||||||
} else {
|
|
||||||
struct xmac_hdr msg;
|
|
||||||
/* If the sender address is someone else, we should
|
|
||||||
acknowledge the strobe and wait for the packet. By using
|
|
||||||
the same address as both sender and receiver, we flag the
|
|
||||||
message is a strobe ack. */
|
|
||||||
msg.type = TYPE_STROBE_ACK;
|
|
||||||
rimeaddr_copy(&msg.receiver, &hdr->sender);
|
|
||||||
rimeaddr_copy(&msg.sender, &hdr->sender);
|
|
||||||
/* We turn on the radio in anticipation of the incoming
|
|
||||||
packet. */
|
|
||||||
someone_is_sending = 1;
|
|
||||||
waiting_for_packet = 1;
|
|
||||||
on();
|
|
||||||
radio->send((const uint8_t *)&msg, sizeof(struct xmac_hdr));
|
|
||||||
}
|
|
||||||
} else if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) {
|
|
||||||
/* If the receiver address is null, the strobe is sent to
|
|
||||||
prepare for an incoming broadcast packet. If this is the
|
|
||||||
case, we turn on the radio and wait for the incoming
|
|
||||||
broadcast packet. */
|
|
||||||
waiting_for_packet = 1;
|
|
||||||
on();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for annoucements in the strobe */
|
|
||||||
/* if(packetbuf_datalen() > 0) {
|
|
||||||
parse_announcements(&hdr->sender);
|
|
||||||
}*/
|
|
||||||
/* We are done processing the strobe and we therefore return
|
|
||||||
to the caller. */
|
|
||||||
return RIME_OK;
|
|
||||||
} else if(hdr->type == TYPE_DATA) {
|
|
||||||
someone_is_sending = 0;
|
someone_is_sending = 0;
|
||||||
if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_node_addr) ||
|
if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
|
||||||
rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) {
|
&rimeaddr_node_addr) ||
|
||||||
|
rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
|
||||||
|
&rimeaddr_null)) {
|
||||||
/* This is a regular packet that is destined to us or to the
|
/* This is a regular packet that is destined to us or to the
|
||||||
broadcast address. */
|
broadcast address. */
|
||||||
|
|
||||||
/* We have received the final packet, so we can go back to being
|
/* We have received the final packet, so we can go back to being
|
||||||
asleep. */
|
asleep. */
|
||||||
off();
|
off();
|
||||||
|
|
||||||
/* Set sender and receiver packet attributes */
|
|
||||||
if(!rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) {
|
|
||||||
packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &hdr->receiver);
|
|
||||||
}
|
|
||||||
packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &hdr->sender);
|
|
||||||
|
|
||||||
#if XMAC_CONF_COMPOWER
|
#if XMAC_CONF_COMPOWER
|
||||||
/* Accumulate the power consumption for the packet reception. */
|
/* Accumulate the power consumption for the packet reception. */
|
||||||
compower_accumulate(¤t_packet);
|
compower_accumulate(¤t_packet);
|
||||||
@ -743,27 +752,81 @@ read_packet(void)
|
|||||||
keep track of the amount of energy spent on receiving the
|
keep track of the amount of energy spent on receiving the
|
||||||
packet. */
|
packet. */
|
||||||
compower_attrconv(¤t_packet);
|
compower_attrconv(¤t_packet);
|
||||||
|
|
||||||
/* Clear the accumulated power consumption so that it is ready
|
/* Clear the accumulated power consumption so that it is ready
|
||||||
for the next packet. */
|
for the next packet. */
|
||||||
compower_clear(¤t_packet);
|
compower_clear(¤t_packet);
|
||||||
#endif /* XMAC_CONF_COMPOWER */
|
#endif /* XMAC_CONF_COMPOWER */
|
||||||
|
|
||||||
waiting_for_packet = 0;
|
waiting_for_packet = 0;
|
||||||
|
|
||||||
/* XXX should set timer to send queued packet later. */
|
/* XXX should set timer to send queued packet later. */
|
||||||
if(queued_packet != NULL) {
|
if(queued_packet != NULL) {
|
||||||
queuebuf_free(queued_packet);
|
queuebuf_free(queued_packet);
|
||||||
queued_packet = NULL;
|
queued_packet = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return packetbuf_totlen();
|
PRINTDEBUG("xmac: data(%u)\n", packetbuf_datalen());
|
||||||
|
return packetbuf_datalen();
|
||||||
|
} else {
|
||||||
|
PRINTDEBUG("xmac: data not for us\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if(hdr->type == TYPE_STROBE) {
|
||||||
|
someone_is_sending = 2;
|
||||||
|
|
||||||
|
if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
|
||||||
|
&rimeaddr_node_addr)) {
|
||||||
|
/* This is a strobe packet for us. */
|
||||||
|
|
||||||
|
/* If the sender address is someone else, we should
|
||||||
|
acknowledge the strobe and wait for the packet. By using
|
||||||
|
the same address as both sender and receiver, we flag the
|
||||||
|
message is a strobe ack. */
|
||||||
|
hdr->type = TYPE_STROBE_ACK;
|
||||||
|
packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER,
|
||||||
|
packetbuf_addr(PACKETBUF_ADDR_SENDER));
|
||||||
|
packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr);
|
||||||
|
packetbuf_compact();
|
||||||
|
if(framer_get()->create()) {
|
||||||
|
/* We turn on the radio in anticipation of the incoming
|
||||||
|
packet. */
|
||||||
|
someone_is_sending = 1;
|
||||||
|
waiting_for_packet = 1;
|
||||||
|
on();
|
||||||
|
radio->send(packetbuf_hdrptr(), packetbuf_totlen());
|
||||||
|
PRINTDEBUG("xmac: send strobe ack %u\n", packetbuf_totlen());
|
||||||
|
} else {
|
||||||
|
PRINTF("xmac: failed to send strobe ack\n");
|
||||||
|
}
|
||||||
|
} else if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
|
||||||
|
&rimeaddr_null)) {
|
||||||
|
/* If the receiver address is null, the strobe is sent to
|
||||||
|
prepare for an incoming broadcast packet. If this is the
|
||||||
|
case, we turn on the radio and wait for the incoming
|
||||||
|
broadcast packet. */
|
||||||
|
waiting_for_packet = 1;
|
||||||
|
on();
|
||||||
|
} else {
|
||||||
|
PRINTDEBUG("xmac: strobe not for us\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We are done processing the strobe and we therefore return
|
||||||
|
to the caller. */
|
||||||
|
return RIME_OK;
|
||||||
#if XMAC_CONF_ANNOUNCEMENTS
|
#if XMAC_CONF_ANNOUNCEMENTS
|
||||||
} else if(hdr->type == TYPE_ANNOUNCEMENT) {
|
} else if(hdr->type == TYPE_ANNOUNCEMENT) {
|
||||||
parse_announcements(&hdr->sender);
|
packetbuf_hdrreduce(sizeof(struct xmac_hdr));
|
||||||
|
parse_announcements(packetbuf_addr(PACKETBUF_ADDR_SENDER));
|
||||||
#endif /* XMAC_CONF_ANNOUNCEMENTS */
|
#endif /* XMAC_CONF_ANNOUNCEMENTS */
|
||||||
|
} else if(hdr->type == TYPE_STROBE_ACK) {
|
||||||
|
PRINTDEBUG("xmac: stray strobe ack\n");
|
||||||
|
} else {
|
||||||
|
PRINTF("xmac: unknown type %u (%u/%u)\n", hdr->type,
|
||||||
|
packetbuf_datalen(), len);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
PRINTF("xmac: failed to parse (%u)\n", packetbuf_totlen());
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -777,20 +840,22 @@ send_announcement(void *ptr)
|
|||||||
|
|
||||||
/* Set up the probe header. */
|
/* Set up the probe header. */
|
||||||
packetbuf_clear();
|
packetbuf_clear();
|
||||||
packetbuf_set_datalen(sizeof(struct xmac_hdr));
|
|
||||||
hdr = packetbuf_dataptr();
|
hdr = packetbuf_dataptr();
|
||||||
hdr->type = TYPE_ANNOUNCEMENT;
|
|
||||||
rimeaddr_copy(&hdr->sender, &rimeaddr_node_addr);
|
|
||||||
rimeaddr_copy(&hdr->receiver, &rimeaddr_null);
|
|
||||||
|
|
||||||
announcement_len = format_announcement((char *)hdr +
|
announcement_len = format_announcement((char *)hdr +
|
||||||
sizeof(struct xmac_hdr));
|
sizeof(struct xmac_hdr));
|
||||||
|
|
||||||
if(announcement_len > 0) {
|
if(announcement_len > 0) {
|
||||||
packetbuf_set_datalen(sizeof(struct xmac_hdr) + announcement_len);
|
packetbuf_set_datalen(sizeof(struct xmac_hdr) + announcement_len);
|
||||||
|
hdr->dispatch = DISPATCH;
|
||||||
|
hdr->type = TYPE_ANNOUNCEMENT;
|
||||||
|
|
||||||
|
packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr);
|
||||||
|
packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &rimeaddr_null);
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_RADIO_TXPOWER, announcement_radio_txpower);
|
packetbuf_set_attr(PACKETBUF_ATTR_RADIO_TXPOWER, announcement_radio_txpower);
|
||||||
radio->send(packetbuf_hdrptr(), packetbuf_totlen());
|
if(framer_get()->create()) {
|
||||||
|
radio->send(packetbuf_hdrptr(), packetbuf_totlen());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
Loading…
Reference in New Issue
Block a user