Skip to content

Commit

Permalink
working rough version of low power listening
Browse files Browse the repository at this point in the history
  • Loading branch information
anroOfCode committed Jan 13, 2013
1 parent 9996b93 commit 0a3cbd9
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 8 deletions.
5 changes: 5 additions & 0 deletions cc2520.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@
#define CC2520_DEF_INIT_BACKOFF 4960
#define CC2520_DEF_CONG_BACKOFF 2240

// We go for around a 1% duty cycle of the radio
// for LPL stuff.
#define CC2520_DEF_LPL_WAKEUP_INTERVAL 512000
#define CC2520_DEF_LPL_LISTEN_WINDOW 5120

// Error codes
#define CC2520_TX_SUCCESS 0
#define CC2520_TX_BUSY 1
Expand Down
7 changes: 4 additions & 3 deletions csma.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ int cc2520_csma_init()
backoff_max_init = CC2520_DEF_INIT_BACKOFF;
backoff_max_cong = CC2520_DEF_CONG_BACKOFF;

spin_lock_init(&state_sl);
csma_state = CC2520_CSMA_IDLE;

cur_tx_buf = kmalloc(PKT_BUFF_SIZE, GFP_KERNEL);
Expand Down Expand Up @@ -97,10 +98,10 @@ static void cc2520_csma_start_timer(int us_period)

static enum hrtimer_restart cc2520_csma_timer_cb(struct hrtimer *timer)
{
ktime_t kt;
int new_backoff;
ktime_t kt;
int new_backoff;

//printk(KERN_INFO "[cc2520] - csma timer fired. \n");
//printk(KERN_INFO "[cc2520] - csma timer fired. \n");
if (cc2520_radio_is_clear()) {
//printk(KERN_INFO "[cc2520] - channel clear, sending.\n");
csma_bottom->tx(cur_tx_buf, cur_tx_len);
Expand Down
7 changes: 4 additions & 3 deletions interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ static ssize_t interface_write(
else {
result = down_interruptible(&tx_sem);
if (result)
return -ERESTARTSYS;
return -ERESTARTSYS;
}
DBG((KERN_INFO "[cc2520] - write lock obtained.\n"));

Expand All @@ -106,9 +106,10 @@ static ssize_t interface_write(
// the form of a semaphore.
interface_bottom->tx(tx_buf_c, pkt_len);
result = down_interruptible(&tx_done_sem);
if (result)
if (result) {
return -ERESTARTSYS;

}

// Step 4: Finally return and allow other callers to write
// packets.
DBG((KERN_INFO "[cc2520] - wrote %d bytes.\n", pkt_len));
Expand Down
155 changes: 153 additions & 2 deletions lpl.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/hrtimer.h>

#include "lpl.h"
#include "packet.h"
#include "cc2520.h"

struct cc2520_interface *lpl_top;
Expand All @@ -8,32 +13,178 @@ struct cc2520_interface *lpl_bottom;
static int cc2520_lpl_tx(u8 * buf, u8 len);
static void cc2520_lpl_tx_done(u8 status);
static void cc2520_lpl_rx_done(u8 *buf, u8 len);
static enum hrtimer_restart cc2520_lpl_timer_cb(struct hrtimer *timer);
static void cc2520_lpl_start_timer(void);

static int lpl_window;
static int lpl_interval;
static bool lpl_enabled;

static struct hrtimer lpl_timer;

static u8* cur_tx_buf;
static u8 cur_tx_len;

static spinlock_t state_sl;

enum cc2520_lpl_state_enum {
CC2520_LPL_IDLE,
CC2520_LPL_TX,
CC2520_LPL_TIMER_EXPIRED
};

static int lpl_state;

int cc2520_lpl_init()
{
lpl_top->tx = cc2520_lpl_tx;
lpl_bottom->tx_done = cc2520_lpl_tx_done;
lpl_bottom->rx_done = cc2520_lpl_rx_done;

lpl_window = CC2520_DEF_LPL_LISTEN_WINDOW;
lpl_interval = CC2520_DEF_LPL_WAKEUP_INTERVAL;
lpl_enabled = true;

cur_tx_buf = kmalloc(PKT_BUFF_SIZE, GFP_KERNEL);
if (!cur_tx_buf) {
goto error;
}

spin_lock_init(&state_sl);
lpl_state = CC2520_LPL_IDLE;

hrtimer_init(&lpl_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
lpl_timer.function = &cc2520_lpl_timer_cb;

return 0;

error:
if (cur_tx_buf) {
kfree(cur_tx_buf);
cur_tx_buf = NULL;
}

return -EFAULT;
}

void cc2520_lpl_free()
{
if (cur_tx_buf) {
kfree(cur_tx_buf);
cur_tx_buf = NULL;
}

hrtimer_cancel(&lpl_timer);
}

static int cc2520_lpl_tx(u8 * buf, u8 len)
{
return lpl_bottom->tx(buf, len);
if (lpl_enabled) {
spin_lock(&state_sl);
if (lpl_state == CC2520_LPL_IDLE) {
lpl_state = CC2520_LPL_TX;
spin_unlock(&state_sl);

memcpy(cur_tx_buf, buf, len);
cur_tx_len = len;

lpl_bottom->tx(cur_tx_buf, cur_tx_len);
cc2520_lpl_start_timer();
}
else {
spin_unlock(&state_sl);
lpl_top->tx_done(-CC2520_TX_BUSY);
}

return 0;
}
else {
return lpl_bottom->tx(buf, len);
}
}

static void cc2520_lpl_tx_done(u8 status)
{
lpl_top->tx_done(status);
if (lpl_enabled) {
spin_lock(&state_sl);
if (cc2520_packet_requires_ack_wait(cur_tx_buf)) {
if (status == CC2520_TX_SUCCESS) {
lpl_state = CC2520_LPL_IDLE;
spin_unlock(&state_sl);

hrtimer_cancel(&lpl_timer);
lpl_top->tx_done(status);
}
else if (lpl_state == CC2520_LPL_TIMER_EXPIRED) {
lpl_state = CC2520_LPL_IDLE;
spin_unlock(&state_sl);
lpl_top->tx_done(-CC2520_TX_FAILED);
}
else {
spin_unlock(&state_sl);
printk(KERN_INFO "[cc2520] - lpl retransmit.\n");
lpl_bottom->tx(cur_tx_buf, cur_tx_len);
}
}
else {
if (lpl_state == CC2520_LPL_TIMER_EXPIRED) {
lpl_state = CC2520_LPL_IDLE;
spin_unlock(&state_sl);
lpl_top->tx_done(CC2520_TX_SUCCESS);
}
else {
spin_unlock(&state_sl);
lpl_bottom->tx(cur_tx_buf, cur_tx_len);
}
}
}
else {
lpl_top->tx_done(status);
}
// if packet requires ack, examine status.
// if success terminate LPL window
// else if status != TIMER_EXPIRED resend
// else resend
}

static void cc2520_lpl_rx_done(u8 *buf, u8 len)
{
lpl_top->rx_done(buf, len);
}

static void cc2520_lpl_start_timer()
{
ktime_t kt;
kt = ktime_set(0, 1000 * (lpl_interval + 2 * lpl_window));
hrtimer_start(&lpl_timer, kt, HRTIMER_MODE_REL);
}

static enum hrtimer_restart cc2520_lpl_timer_cb(struct hrtimer *timer)
{
spin_lock(&state_sl);
if (lpl_state == CC2520_LPL_TX) {
lpl_state = CC2520_LPL_TIMER_EXPIRED;
spin_unlock(&state_sl);
}
else {
spin_unlock(&state_sl);
INFO((KERN_INFO "[cc2520] - lpl timer in improbable state.\n"));
}

return HRTIMER_NORESTART;
}

void cc2520_lpl_set_enabled(bool enabled)
{
lpl_enabled = enabled;
}

void cc2520_lpl_set_listen_length(int length)
{
lpl_window = length;
}

void cc2520_lpl_set_wakeup_interval(int interval)
{
lpl_interval = interval;
}
4 changes: 4 additions & 0 deletions lpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@ extern struct cc2520_interface *lpl_bottom;
int cc2520_lpl_init(void);
void cc2520_lpl_free(void);

void cc2520_lpl_set_enabled(bool enabled);
void cc2520_lpl_set_listen_length(int length);
void cc2520_lpl_set_wakeup_interval(int interval);

#endif

0 comments on commit 0a3cbd9

Please sign in to comment.