mirror of
https://github.com/oliverschmidt/contiki.git
synced 2025-01-18 03:30:31 +00:00
Made optimizations explicit (and configurable). Added missing initialization of dutycycle protothread. Reduced default listen time and off time.
This commit is contained in:
parent
d936dc1d09
commit
1d86b01bfb
@ -28,7 +28,7 @@
|
|||||||
*
|
*
|
||||||
* This file is part of the Contiki operating system.
|
* This file is part of the Contiki operating system.
|
||||||
*
|
*
|
||||||
* $Id: lpp.c,v 1.15 2009/03/31 17:39:54 adamdunkels Exp $
|
* $Id: lpp.c,v 1.16 2009/04/03 11:45:06 adamdunkels Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -59,8 +59,10 @@
|
|||||||
#include "net/mac/lpp.h"
|
#include "net/mac/lpp.h"
|
||||||
#include "net/rime/packetbuf.h"
|
#include "net/rime/packetbuf.h"
|
||||||
#include "net/rime/announcement.h"
|
#include "net/rime/announcement.h"
|
||||||
|
#include "sys/compower.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#define DEBUG 0
|
#define DEBUG 0
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
@ -70,6 +72,9 @@
|
|||||||
#define PRINTF(...)
|
#define PRINTF(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define WITH_ACK_OPTIMIZATION 0
|
||||||
|
#define WITH_PROBE_AFTER_RECEPTION 0
|
||||||
|
#define WITH_PROBE_AFTER_TRANSMISSION 0
|
||||||
|
|
||||||
struct announcement_data {
|
struct announcement_data {
|
||||||
uint16_t id;
|
uint16_t id;
|
||||||
@ -92,22 +97,26 @@ struct lpp_hdr {
|
|||||||
rimeaddr_t receiver;
|
rimeaddr_t receiver;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct compower_activity current_packet;
|
||||||
|
|
||||||
static const struct radio_driver *radio;
|
static const struct radio_driver *radio;
|
||||||
static void (* receiver_callback)(const struct mac_driver *);
|
static void (* receiver_callback)(const struct mac_driver *);
|
||||||
static struct pt pt;
|
static struct pt dutycycle_pt;
|
||||||
static struct ctimer timer;
|
static struct ctimer timer;
|
||||||
|
|
||||||
static uint8_t is_listening = 0;
|
static uint8_t is_listening = 0;
|
||||||
|
|
||||||
#define LISTEN_TIME CLOCK_SECOND / 32
|
#define LISTEN_TIME CLOCK_SECOND / 128
|
||||||
#define OFF_TIME CLOCK_SECOND * 1
|
#define OFF_TIME CLOCK_SECOND / 2
|
||||||
#define PACKET_LIFETIME (LISTEN_TIME + OFF_TIME)
|
#define PACKET_LIFETIME (LISTEN_TIME + OFF_TIME)
|
||||||
#define UNICAST_TIMEOUT 2 * PACKET_LIFETIME
|
#define UNICAST_TIMEOUT 2 * PACKET_LIFETIME
|
||||||
|
#define PROBE_AFTER_TRANSMISSION_TIME LISTEN_TIME * 2
|
||||||
|
|
||||||
struct queue_list_item {
|
struct queue_list_item {
|
||||||
struct queue_list_item *next;
|
struct queue_list_item *next;
|
||||||
struct queuebuf *packet;
|
struct queuebuf *packet;
|
||||||
struct ctimer timer;
|
struct ctimer timer;
|
||||||
|
struct compower_activity compower;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef QUEUEBUF_CONF_NUM
|
#ifdef QUEUEBUF_CONF_NUM
|
||||||
@ -142,12 +151,14 @@ remove_queued_packet(void *item)
|
|||||||
ctimer_stop(&i->timer);
|
ctimer_stop(&i->timer);
|
||||||
queuebuf_free(i->packet);
|
queuebuf_free(i->packet);
|
||||||
list_remove(queued_packets_list, i);
|
list_remove(queued_packets_list, i);
|
||||||
memb_free(&queued_packets_memb, i);
|
|
||||||
|
|
||||||
/* XXX potential optimization */
|
/* XXX potential optimization */
|
||||||
if(list_length(queued_packets_list) == 0 && is_listening == 0) {
|
if(list_length(queued_packets_list) == 0 && is_listening == 0) {
|
||||||
turn_radio_off();
|
turn_radio_off();
|
||||||
|
compower_accumulate(&i->compower);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memb_free(&queued_packets_memb, i);
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
static void
|
||||||
@ -192,46 +203,71 @@ send_probe(void)
|
|||||||
|
|
||||||
/* PRINTF("Sending probe\n");*/
|
/* PRINTF("Sending probe\n");*/
|
||||||
radio->send(packetbuf_hdrptr(), packetbuf_totlen());
|
radio->send(packetbuf_hdrptr(), packetbuf_totlen());
|
||||||
|
|
||||||
|
compower_accumulate(&compower_idle_activity);
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
/**
|
/**
|
||||||
* Duty cycle the radio. The protothread is driven by a ctimer that is
|
* Duty cycle the radio and send probes. This function is called
|
||||||
* initiated in the lpp_init() function.
|
* repeatedly by a ctimer. The function restart_dutycycle() is used to
|
||||||
|
* (re)start the duty cycling.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
dutycycle(void *ptr)
|
dutycycle(void *ptr)
|
||||||
{
|
{
|
||||||
struct ctimer *t = ptr;
|
struct ctimer *t = ptr;
|
||||||
|
|
||||||
PT_BEGIN(&pt);
|
PT_BEGIN(&dutycycle_pt);
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
turn_radio_on();
|
|
||||||
send_probe();
|
|
||||||
ctimer_set(t, LISTEN_TIME, (void (*)(void *))dutycycle, t);
|
|
||||||
PT_YIELD(&pt);
|
|
||||||
|
|
||||||
|
/* Send a probe packet. */
|
||||||
|
send_probe();
|
||||||
|
|
||||||
|
/* Turn on the radio for a while in anticipation of a data packet
|
||||||
|
from a neighbor. */
|
||||||
|
turn_radio_on();
|
||||||
|
|
||||||
|
/* Set a timer so that we keep the radio on for LISTEN_TIME. */
|
||||||
|
ctimer_set(t, LISTEN_TIME, (void (*)(void *))dutycycle, t);
|
||||||
|
PT_YIELD(&dutycycle_pt);
|
||||||
|
|
||||||
|
/* If we have no packets to send (indicated by the list length of
|
||||||
|
queued_packets_list being zero), we should turn the radio
|
||||||
|
off. Othersize, we keep the radio on. */
|
||||||
|
|
||||||
if(list_length(queued_packets_list) == 0) {
|
if(list_length(queued_packets_list) == 0) {
|
||||||
|
|
||||||
|
/* If we are not listening for announcements, we turn the radio
|
||||||
|
off and wait until we send the next probe. */
|
||||||
if(is_listening == 0) {
|
if(is_listening == 0) {
|
||||||
turn_radio_off();
|
turn_radio_off();
|
||||||
|
compower_accumulate(&compower_idle_activity);
|
||||||
/* There is a bit of randomness here right now to avoid collisions
|
/* There is a bit of randomness here right now to avoid collisions
|
||||||
due to synchronization effects. Not sure how needed it is
|
due to synchronization effects. Not sure how needed it is
|
||||||
though. XXX */
|
though. XXX */
|
||||||
ctimer_set(t, OFF_TIME / 2 + (random_rand() % (OFF_TIME / 2)),
|
ctimer_set(t, OFF_TIME / 2 + (random_rand() % (OFF_TIME / 2)),
|
||||||
(void (*)(void *))dutycycle, t);
|
(void (*)(void *))dutycycle, t);
|
||||||
PT_YIELD(&pt);
|
PT_YIELD(&dutycycle_pt);
|
||||||
} else {
|
} else {
|
||||||
is_listening--;
|
is_listening--;
|
||||||
ctimer_set(t, OFF_TIME, (void (*)(void *))dutycycle, t);
|
ctimer_set(t, OFF_TIME, (void (*)(void *))dutycycle, t);
|
||||||
PT_YIELD(&pt);
|
PT_YIELD(&dutycycle_pt);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ctimer_set(t, OFF_TIME, (void (*)(void *))dutycycle, t);
|
ctimer_set(t, OFF_TIME, (void (*)(void *))dutycycle, t);
|
||||||
PT_YIELD(&pt);
|
PT_YIELD(&dutycycle_pt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PT_END(&pt);
|
PT_END(&dutycycle_pt);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
restart_dutycycle(clock_time_t initial_wait)
|
||||||
|
{
|
||||||
|
PT_INIT(&dutycycle_pt);
|
||||||
|
ctimer_set(&timer, initial_wait, (void (*)(void *))dutycycle, &timer);
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
/**
|
/**
|
||||||
@ -266,12 +302,7 @@ send_packet(void)
|
|||||||
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
||||||
hdr.receiver.u8[0], hdr.receiver.u8[1],
|
hdr.receiver.u8[0], hdr.receiver.u8[1],
|
||||||
packetbuf_attr(PACKETBUF_ATTR_CHANNEL));
|
packetbuf_attr(PACKETBUF_ATTR_CHANNEL));
|
||||||
if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_ACK) {
|
{
|
||||||
/* Immediately send ACKs - we're assuming that the other node is
|
|
||||||
listening. */
|
|
||||||
/* printf("Immediately sending ACK\n");*/
|
|
||||||
return radio->send(packetbuf_hdrptr(), packetbuf_totlen());
|
|
||||||
} else {
|
|
||||||
struct queue_list_item *i;
|
struct queue_list_item *i;
|
||||||
i = memb_alloc(&queued_packets_memb);
|
i = memb_alloc(&queued_packets_memb);
|
||||||
if(i != NULL) {
|
if(i != NULL) {
|
||||||
@ -286,7 +317,10 @@ send_packet(void)
|
|||||||
timeout = PACKET_LIFETIME;
|
timeout = PACKET_LIFETIME;
|
||||||
}
|
}
|
||||||
ctimer_set(&i->timer, timeout, remove_queued_packet, i);
|
ctimer_set(&i->timer, timeout, remove_queued_packet, i);
|
||||||
/* Wait for a probe packet from a neighbor */
|
|
||||||
|
/* Wait for a probe packet from a neighbor. The actual packet
|
||||||
|
transmission is handled by the read_packet() function,
|
||||||
|
which receives the probe from the neighbor. */
|
||||||
turn_radio_on();
|
turn_radio_on();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -308,7 +342,7 @@ 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 > sizeof(struct lpp_hdr)) {
|
||||||
packetbuf_set_datalen(len);
|
packetbuf_set_datalen(len);
|
||||||
hdr = packetbuf_dataptr();
|
hdr = packetbuf_dataptr();
|
||||||
packetbuf_hdrreduce(sizeof(struct lpp_hdr));
|
packetbuf_hdrreduce(sizeof(struct lpp_hdr));
|
||||||
@ -345,9 +379,14 @@ read_packet(void)
|
|||||||
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
||||||
hdr->sender.u8[0], hdr->sender.u8[1],
|
hdr->sender.u8[0], hdr->sender.u8[1],
|
||||||
qhdr->receiver.u8[0], qhdr->receiver.u8[1]);
|
qhdr->receiver.u8[0], qhdr->receiver.u8[1]);
|
||||||
|
queuebuf_to_packetbuf(i->packet);
|
||||||
|
|
||||||
radio->send(queuebuf_dataptr(i->packet),
|
radio->send(queuebuf_dataptr(i->packet),
|
||||||
queuebuf_datalen(i->packet));
|
queuebuf_datalen(i->packet));
|
||||||
|
|
||||||
|
/* Attribute the energy spent on listening for the probe
|
||||||
|
to this packet transmission. */
|
||||||
|
compower_accumulate(&i->compower);
|
||||||
|
|
||||||
/* If the packet was not a broadcast packet, we dequeue it
|
/* If the packet was not a broadcast packet, we dequeue it
|
||||||
now. Broadcast packets should be transmitted to all
|
now. Broadcast packets should be transmitted to all
|
||||||
@ -355,13 +394,21 @@ read_packet(void)
|
|||||||
instead, after the appropriate time. */
|
instead, after the appropriate time. */
|
||||||
if(!rimeaddr_cmp(&qhdr->receiver, &rimeaddr_null)) {
|
if(!rimeaddr_cmp(&qhdr->receiver, &rimeaddr_null)) {
|
||||||
remove_queued_packet(i);
|
remove_queued_packet(i);
|
||||||
|
|
||||||
|
#if WITH_PROBE_AFTER_TRANSMISSION
|
||||||
|
/* Send a probe packet to catch any reply from the other node. */
|
||||||
|
restart_dutycycle(PROBE_AFTER_TRANSMISSION_TIME);
|
||||||
|
#endif /* WITH_PROBE_AFTER_TRANSMISSION */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if WITH_ACK_OPTIMIZATION
|
||||||
turn_radio_on(); /* XXX Awaiting an ACK: we should check the
|
if(packetbuf_attr(PACKETBUF_ATTR_RELIABLE)) {
|
||||||
packet type of the queued packet to see
|
/* We're sending a packet that needs an ACK, so we keep
|
||||||
if it is a data packet. If not, we
|
the radio on in anticipation of the ACK. */
|
||||||
should not turn the radio on. */
|
turn_radio_on();
|
||||||
|
}
|
||||||
|
#endif /* WITH_ACK_OPTIMIZATION */
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -370,7 +417,20 @@ read_packet(void)
|
|||||||
PRINTF("%d.%d: got data from %d.%d\n",
|
PRINTF("%d.%d: got data from %d.%d\n",
|
||||||
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
||||||
hdr->sender.u8[0], hdr->sender.u8[1]);
|
hdr->sender.u8[0], hdr->sender.u8[1]);
|
||||||
|
|
||||||
|
/* Accumulate the power consumption for the packet reception. */
|
||||||
|
compower_accumulate(¤t_packet);
|
||||||
|
/* Convert the accumulated power consumption for the received
|
||||||
|
packet to packet attributes so that the higher levels can
|
||||||
|
keep track of the amount of energy spent on receiving the
|
||||||
|
packet. */
|
||||||
|
compower_attrconv(¤t_packet);
|
||||||
|
|
||||||
|
/* Clear the accumulated power consumption so that it is ready
|
||||||
|
for the next packet. */
|
||||||
|
compower_clear(¤t_packet);
|
||||||
|
|
||||||
|
#if WITH_PROBE_AFTER_RECEPTION
|
||||||
/* XXX send probe after receiving a packet to facilitate data
|
/* XXX send probe after receiving a packet to facilitate data
|
||||||
streaming. We must first copy the contents of the packetbuf into
|
streaming. We must first copy the contents of the packetbuf into
|
||||||
a queuebuf to avoid overwriting the data with the probe packet. */
|
a queuebuf to avoid overwriting the data with the probe packet. */
|
||||||
@ -383,7 +443,9 @@ read_packet(void)
|
|||||||
queuebuf_free(q);
|
queuebuf_free(q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif /* WITH_PROBE_AFTER_RECEPTION */
|
||||||
}
|
}
|
||||||
|
|
||||||
len = packetbuf_datalen();
|
len = packetbuf_datalen();
|
||||||
}
|
}
|
||||||
return len;
|
return len;
|
||||||
@ -435,7 +497,7 @@ lpp_init(const struct radio_driver *d)
|
|||||||
{
|
{
|
||||||
radio = d;
|
radio = d;
|
||||||
radio->set_receive_function(input_packet);
|
radio->set_receive_function(input_packet);
|
||||||
ctimer_set(&timer, LISTEN_TIME, (void (*)(void *))dutycycle, &timer);
|
restart_dutycycle(LISTEN_TIME);
|
||||||
|
|
||||||
announcement_register_listen_callback(listen_callback);
|
announcement_register_listen_callback(listen_callback);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user