1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #1223 from rousselk/cc2420-extended-driver

CC2420: modify&extend driver to comply with API described in 'radio_driver.h'
This commit is contained in:
Thomas Eichinger 2014-07-08 12:33:47 +02:00
commit 65e240f950
9 changed files with 598 additions and 104 deletions

View File

@ -96,7 +96,7 @@ int cc2420_get_gio1(void)
return CC2420_GIO1;
}
int cc2420_get_fifop(void)
uint8_t cc2420_get_fifop(void)
{
return CC2420_FIFOP;
}

View File

@ -104,6 +104,11 @@ uint8_t cc2420_get_sfd(void)
return CC2420_SFD;
}
uint8_t cc2420_get_fifop(void)
{
return CC2420_GDO2;
}
uint8_t cc2420_get_cca(void)
{
uint8_t status;

View File

@ -111,7 +111,7 @@ int cc2420_get_gio1(void)
return CC2420_GIO1;
}
int cc2420_get_fifop(void)
uint8_t cc2420_get_fifop(void)
{
return CC2420_FIFOP;
}

View File

@ -1,11 +1,14 @@
/**
* cc2420.c - Implementation of cc2420 functions.
* Copyright (C) 2013 Milan Babel <babel@inf.fu-berlin.de>
* Copyright (C) 2014 Kévin Roussel <Kevin.Roussel@inria.fr>
*
* This source code is licensed under the GNU Lesser General Public License,
* Version 2. See the file LICENSE for more details.
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*/
#include "crash.h"
#include "cc2420.h"
#include "cc2420_spi.h"
#include "cc2420_settings.h"
@ -15,28 +18,38 @@
#define ENABLE_DEBUG (0)
#include "debug.h"
/* Radio driver API */
void cc2420_init(int tpid)
/* number of attempts to turn on transceiver at startup, before panicking */
#define CC2420_STARTUP_ATTEMPTS 3
/* startup timeout (2 ms) in 16MHz-clock cycles */
#define CC2420_STARTUP_TIMEOUT 32000U
/* implementation of driver's functions */
void cc2420_initialize(void)
{
uint16_t reg;
transceiver_pid = tpid;
cc2420_spi_init();
hwtimer_wait(CC2420_WAIT_TIME);
cc2420_reset();
cc2420_strobe(CC2420_STROBE_XOSCON); //enable crystal
while ((cc2420_strobe(NOBYTE) & 0x40) == 0); //wait for crystal to be stable
bool ok = false;
for (int i = 0; i < CC2420_STARTUP_ATTEMPTS; i++) {
ok = cc2420_on();
if (ok) break;
}
if (!ok) {
core_panic(0x2420, "Could not start CC2420 radio transceiver");
}
hwtimer_wait(CC2420_WAIT_TIME);
reg = cc2420_read_reg(CC2420_REG_MDMCTRL0);
reg |= CC2420_ADR_DECODE; //enable adr decode
reg |= CC2420_AUTOACK; //enable auto ack
reg |= CC2420_AUTOCRC; //enable auto crc
reg &= ~(CC2420_RES_FRM_MODE); //disable reserved frames
uint16_t reg = cc2420_read_reg(CC2420_REG_MDMCTRL0);
reg |= CC2420_ADR_DECODE; /* enable auto adress decoding */
reg |= CC2420_AUTOACK; /* enable auto ACK */
reg |= CC2420_AUTOCRC; /* enable auto CRC */
reg &= ~(CC2420_RES_FRM_MODE); /* disable reserved frames */
cc2420_write_reg(CC2420_REG_MDMCTRL0, reg);
/* Change default values as recomended in the data sheet, */
@ -53,15 +66,53 @@ void cc2420_init(int tpid)
reg &= ~CC2420_RXFIFO_PROTECTION;
cc2420_write_reg(CC2420_REG_SECCTRL0, reg);
/* set output power to 0dbm */
cc2420_write_reg(CC2420_REG_TXCTRL, 0xA0FF);
cc2420_set_tx_power(0);
cc2420_set_channel(CC2420_DEFAULT_CHANNR);
cc2420_set_pan(0x1111);
DEBUG("CC2420 initialized and set to channel %i and pan 0x1111\n", CC2420_DEFAULT_CHANNR);
cc2420_init_interrupts();
cc2420_switch_to_rx();
}
void cc2420_init(int tpid)
{
transceiver_pid = tpid;
cc2420_initialize();
}
bool cc2420_on(void)
{
/* enable transceiver's crystal oscillator */
cc2420_strobe(CC2420_STROBE_XOSCON);
/* wait for the oscillator to be stable */
unsigned int delay_on = 0;
do {
delay_on++;
if (delay_on >= CC2420_STARTUP_TIMEOUT) {
/* could not start up radio transceiver! */
return false;
}
} while ((cc2420_status_byte() & CC2420_STATUS_XOSC16M_STABLE) == 0);
hwtimer_wait(CC2420_WAIT_TIME);
/* discard any potential garbage in TX buffer */
cc2420_strobe(CC2420_STROBE_FLUSHTX);
/* switch to RX mode */
cc2420_switch_to_rx();
/* OK, radio is on */
return true;
}
void cc2420_off(void)
{
/* halt any pending communication... */
cc2420_strobe(CC2420_STROBE_RFOFF);
/* ... and put the transceiver in power-down mode */
cc2420_strobe(CC2420_STROBE_XOSCOFF);
}
bool cc2420_is_on(void)
{
return ((cc2420_status_byte() & CC2420_STATUS_XOSC16M_STABLE) != 0);
}
void cc2420_switch_to_rx(void)
@ -75,7 +126,7 @@ void cc2420_switch_to_rx(void)
void cc2420_rxoverflow_irq(void)
{
cc2420_strobe(CC2420_STROBE_FLUSHRX);
//Datasheets says do this twice...
/* CC2420 datasheet says to do this twice... */
cc2420_strobe(CC2420_STROBE_FLUSHRX);
}
@ -84,45 +135,44 @@ void cc2420_rx_irq(void)
cc2420_rx_handler();
}
void cc2420_set_monitor(uint8_t mode)
void cc2420_set_monitor(bool mode)
{
uint16_t reg;
reg = cc2420_read_reg(CC2420_REG_MDMCTRL0);
uint16_t reg = cc2420_read_reg(CC2420_REG_MDMCTRL0);
if (mode) {
reg &= ~CC2420_ADR_DECODE;
}
else {
} else {
reg |= CC2420_ADR_DECODE;
}
cc2420_write_reg(CC2420_REG_MDMCTRL0, reg);
}
int16_t cc2420_set_channel(uint16_t chan)
bool cc2420_get_monitor(void)
{
uint16_t freq;
uint16_t reg = cc2420_read_reg(CC2420_REG_MDMCTRL0);
return ((reg & CC2420_ADR_DECODE) == 0);
}
int cc2420_set_channel(unsigned int chan)
{
if (chan < 11 || chan > 26) {
DEBUG("Invalid channel %i set. Valid channels are 11 through 26\n", chan);
return -1;
}
/*
* calculation from http://www.ti.com/lit/ds/symlink/cc2420.pdf p.50
*/
freq = 357 + (5 * (chan - 11));
uint16_t freq = 357 + (5 * (chan - 11));
cc2420_write_reg(CC2420_REG_FSCTRL, freq);
return (int32_t)chan;
return ((unsigned int) chan);
}
uint16_t cc2420_get_channel(void)
unsigned int cc2420_get_channel(void)
{
/* undo calculation from cc2420_set_channel() */
return ((cc2420_read_reg(CC2420_REG_FSCTRL) - 357) / 5) + 11;
}
radio_address_t cc2420_set_address(radio_address_t addr)
uint16_t cc2420_set_address(uint16_t addr)
{
uint8_t buf[2];
buf[0] = (uint8_t)(addr & 0xFF);
@ -147,9 +197,9 @@ uint64_t cc2420_set_address_long(uint64_t addr)
return addr;
}
radio_address_t cc2420_get_address(void)
uint16_t cc2420_get_address(void)
{
radio_address_t addr;
uint16_t addr;
cc2420_read_ram(CC2420_RAM_SHORTADR, (uint8_t *)&addr, sizeof(addr));
return addr;
}
@ -177,7 +227,69 @@ uint16_t cc2420_get_pan(void)
return pan;
}
inline bool channel_clear(void)
static const uint8_t DBM_TO_LEVEL[32] = {
31, 27, 25, 23, 21, 19, 17, 15, 13, 12, 11, 10, 9, 8, 7, 7,
6, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3
};
int cc2420_set_tx_power(int pow)
{
uint16_t txctrl_reg = cc2420_read_reg(CC2420_REG_TXCTRL);
/* reset PA_LEVEL bits */
txctrl_reg &= 0xFFE0;
/* constrain power in transceiver's acceptable set of values */
if (pow > 0) pow = 0;
if (pow < -25) pow = -25;
/* determine TX level from power in dBm */
uint8_t level = DBM_TO_LEVEL[-pow];
/* put wanted value in PA_LEVEL bits, and write back register */
txctrl_reg |= level;
cc2420_write_reg(CC2420_REG_TXCTRL, txctrl_reg);
return pow;
}
static const int LEVEL_TO_DBM[32] = {
-25, -25, -25, -24, -21, -19, -17, -15, -13, -12, -11, -10, -9, -8, -7, -7,
-6, -6, -5, -5, -4, -4, -3, -3, -2, -2, -1, -1, 0, 0, 0, 0
};
int cc2420_get_tx_power(void)
{
uint16_t txctrl_reg = cc2420_read_reg(CC2420_REG_TXCTRL);
/* PA_LEVEL is in the 5 least-significant bits of TXCTRL register */
uint8_t level = txctrl_reg & 0x001F;
/* determine output power in dBm from TX level */
int pow = LEVEL_TO_DBM[level];
return pow;
}
inline bool cc2420_channel_clear(void)
{
return (cc2420_get_cca() != 0);
}
/* CC2420 low-level radio driver definition */
const ieee802154_radio_driver_t cc2420_radio_driver = {
.init = cc2420_initialize,
.on = cc2420_on,
.off = cc2420_off,
.is_on = cc2420_is_on,
.load_tx = cc2420_load_tx_buf,
.transmit = cc2420_transmit_tx_buf,
.send = cc2420_do_send,
.set_receive_callback = cc2420_set_recv_callback,
.switch_to_rx = cc2420_switch_to_rx,
.set_channel = do_set_channel,
.get_channel = cc2420_get_channel,
.set_address = do_set_address,
.get_address = cc2420_get_address,
.set_long_address = do_set_long_address,
.get_long_address = cc2420_get_address_long,
.set_pan_id = do_set_pan_id,
.get_pan_id = cc2420_get_pan,
.set_tx_power = do_set_tx_power,
.get_tx_power = cc2420_get_tx_power,
.channel_is_clear = cc2420_channel_clear,
.set_promiscuous_mode = cc2420_set_monitor,
.in_promiscuous_mode = cc2420_get_monitor
};

View File

@ -1,9 +1,11 @@
/**
* cc2420_rx.c - Implementation of receiving cc2420 functions.
* Copyright (C) 2013 Milan Babel <babel@inf.fu-berlin.de>
* Copyright (C) 2014 Kévin Roussel <Kevin.Roussel@inria.fr>
*
* This source code is licensed under the GNU Lesser General Public License,
* Version 2. See the file LICENSE for more details.
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*/
#include <stdio.h>
@ -18,37 +20,57 @@
#include "msg.h"
#include "debug.h"
/* circular buffer for incoming 802.15.4 packets */
cc2420_packet_t cc2420_rx_buffer[CC2420_RX_BUF_SIZE];
volatile uint8_t rx_buffer_next;
volatile uint8_t rx_buffer_next; /* index of next free cell in RX buffer */
/* pointer to the callback low-level function for packet reception */
static receive_802154_packet_callback_t recv_func = NULL;
void cc2420_set_recv_callback(receive_802154_packet_callback_t recv_cb)
{
recv_func = recv_cb;
}
void cc2420_rx_handler(void)
{
uint8_t rssi_crc_lqi[2];
uint8_t pkt_len, pkt_lqi;
int8_t pkt_rssi;
bool crc_ok;
/* read length */
cc2420_read_fifo(&cc2420_rx_buffer[rx_buffer_next].length, 1);
cc2420_read_fifo(&pkt_len, 1);
/* read packet without rssi, crc and lqi */
uint8_t buf[cc2420_rx_buffer[rx_buffer_next].length - 2];
cc2420_read_fifo(buf, cc2420_rx_buffer[rx_buffer_next].length - 2);
/* read packet's raw payload */
uint8_t buf[pkt_len - 2];
cc2420_read_fifo(buf, pkt_len - 2);
/* read rssi, lqi and crc */
cc2420_read_fifo(rssi_crc_lqi, 2);
/* build package */
cc2420_rx_buffer[rx_buffer_next].rssi = (int8_t)(rssi_crc_lqi[0]);
cc2420_rx_buffer[rx_buffer_next].lqi = (uint8_t)(rssi_crc_lqi[1] & 0x7F);
cc2420_rx_buffer[rx_buffer_next].crc = (uint8_t)((rssi_crc_lqi[1] & 0x80) >> 7);
if (cc2420_rx_buffer[rx_buffer_next].crc == 0) {
cc2420_read_fifo((uint8_t *) &pkt_rssi, 1);
cc2420_read_fifo(&pkt_lqi, 1);
crc_ok = ((pkt_lqi & 0x80) != 0);
pkt_lqi &= 0x7F;
if (!crc_ok) {
DEBUG("Got packet with invalid crc.\n");
return;
}
/* low-level reception mechanism (for MAC layer, among others) */
if (recv_func != NULL) {
recv_func(buf, pkt_len - 2, pkt_rssi, pkt_lqi, crc_ok);
}
/* decode received packet */
cc2420_rx_buffer[rx_buffer_next].length = pkt_len;
cc2420_rx_buffer[rx_buffer_next].rssi = pkt_rssi;
cc2420_rx_buffer[rx_buffer_next].lqi = pkt_lqi;
cc2420_rx_buffer[rx_buffer_next].crc = (crc_ok ? 1 : 0);
ieee802154_frame_read(buf,
&cc2420_rx_buffer[rx_buffer_next].frame,
cc2420_rx_buffer[rx_buffer_next].length);
/* follow-up to transceiver module if adequate */
if (cc2420_rx_buffer[rx_buffer_next].frame.fcf.frame_type != 2) {
#ifdef DEBUG
ieee802154_frame_print_fcf_frame(&cc2420_rx_buffer[rx_buffer_next].frame);

View File

@ -2,8 +2,9 @@
* cc2420_spi.c - Implementation of SPI cc2420 functions.
* Copyright (C) 2013 Milan Babel <babel@inf.fu-berlin.de>
*
* This source code is licensed under the GNU Lesser General Public License,
* Version 2. See the file LICENSE for more details.
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*/
#include "cc2420_spi.h"

View File

@ -2,8 +2,9 @@
* cc2420_rx.c - Implementation of transmitting cc2420 functions.
* Copyright (C) 2013 Milan Babel <babel@inf.fu-berlin.de>
*
* This source code is licensed under the GNU Lesser General Public License,
* Version 2. See the file LICENSE for more details.
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*/
#include <stdio.h>
@ -15,13 +16,202 @@
#include "ieee802154_frame.h"
#include "irq.h"
#include "hwtimer.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
static void cc2420_gen_pkt(uint8_t *buf, cc2420_packet_t *packet);
static uint8_t sequenz_nr;
static bool wait_for_ack;
radio_tx_status_t cc2420_load_tx_buf(ieee802154_packet_kind_t kind,
ieee802154_node_addr_t dest,
bool use_long_addr,
bool wants_ack,
void *buf,
unsigned int len)
{
uint8_t hdr[24];
/* FCS : frame version 0, we don't manage security,
nor batchs of packets */
switch (kind) {
case PACKET_KIND_BEACON:
hdr[0] = 0x00;
break;
case PACKET_KIND_DATA:
hdr[0] = 0x01;
break;
case PACKET_KIND_ACK:
hdr[0] = 0x02;
break;
default:
return RADIO_TX_INVALID_PARAM;
}
if (wants_ack) {
hdr[0] |= 0x20;
}
wait_for_ack = wants_ack;
uint16_t src_pan = cc2420_get_pan();
bool compress_pan = false;
if (use_long_addr) {
hdr[1] = 0xcc;
} else {
hdr[1] = 0x88;
/* short address mode, use PAN ID compression
for intra-PAN communication */
if (dest.pan.id == src_pan) {
compress_pan = true;
hdr[0] |= 0x40;
}
}
/* sequence number */
hdr[2] = sequenz_nr++;
/* variable-length fields */
int idx = 3;
if (use_long_addr) {
/* dest long addr */
hdr[idx++] = (uint8_t)(dest.long_addr & 0xFF);
hdr[idx++] = (uint8_t)(dest.long_addr >> 8);
hdr[idx++] = (uint8_t)(dest.long_addr >> 16);
hdr[idx++] = (uint8_t)(dest.long_addr >> 24);
hdr[idx++] = (uint8_t)(dest.long_addr >> 32);
hdr[idx++] = (uint8_t)(dest.long_addr >> 40);
hdr[idx++] = (uint8_t)(dest.long_addr >> 48);
hdr[idx++] = (uint8_t)(dest.long_addr >> 56);
/* src long addr */
uint64_t src_long_addr = cc2420_get_address_long();
hdr[idx++] = (uint8_t)(src_long_addr & 0xFF);
hdr[idx++] = (uint8_t)(src_long_addr >> 8);
hdr[idx++] = (uint8_t)(src_long_addr >> 16);
hdr[idx++] = (uint8_t)(src_long_addr >> 24);
hdr[idx++] = (uint8_t)(src_long_addr >> 32);
hdr[idx++] = (uint8_t)(src_long_addr >> 40);
hdr[idx++] = (uint8_t)(src_long_addr >> 48);
hdr[idx++] = (uint8_t)(src_long_addr >> 56);
} else {
/* dest PAN ID */
hdr[idx++] = (uint8_t)(dest.pan.id & 0xFF);
hdr[idx++] = (uint8_t)(dest.pan.id >> 8);
/* dest short addr */
hdr[idx++] = (uint8_t)(dest.pan.addr & 0xFF);
hdr[idx++] = (uint8_t)(dest.pan.addr >> 8);
/* src PAN ID */
if (!compress_pan) {
uint16_t src_pan = cc2420_get_pan();
hdr[idx++] = (uint8_t)(src_pan & 0xFF);
hdr[idx++] = (uint8_t)(src_pan >> 8);
}
/* src short addr */
uint16_t src_addr = cc2420_get_address();
hdr[idx++] = (uint8_t)(src_addr & 0xFF);
hdr[idx++] = (uint8_t)(src_addr >> 8);
}
/* total frame size */
uint8_t size = idx + len + 2;
if (size > CC2420_MAX_PKT_LENGTH) {
return RADIO_TX_PACKET_TOO_LONG;
}
/* flush TX buffer */
cc2420_strobe(CC2420_STROBE_FLUSHTX);
/* write length, header and payload to TX FIFO */
cc2420_write_fifo(&size, 1);
cc2420_write_fifo(hdr, idx);
cc2420_write_fifo(buf, len);
return RADIO_TX_OK;
}
#define CC2420_ACK_WAIT_DELAY_uS 1000
#define ACK_LENGTH 5
radio_tx_status_t cc2420_transmit_tx_buf(void)
{
/* check if channel clear */
if (!cc2420_channel_clear()) {
return RADIO_TX_MEDIUM_BUSY;
}
/* put tranceiver in idle mode */
cc2420_strobe(CC2420_STROBE_RFOFF);
/* begin transmission: wait for preamble to be sent */
unsigned int cpsr = disableIRQ();
cc2420_strobe(CC2420_STROBE_TXON);
int abort_count = 0;
while (cc2420_get_sfd() == 0) {
/* Wait for SFD signal to be set -> sync word transmitted */
abort_count++;
if (abort_count > CC2420_SYNC_WORD_TX_TIME) {
/* Abort waiting. CC2420 maybe in wrong mode
e.g. sending preambles for always */
puts("[CC2420 TX] fatal error: could not send packet\n");
return RADIO_TX_ERROR;
}
}
restoreIRQ(cpsr);
/* wait for packet to be sent, i.e.: SFD to go down */
uint8_t st;
do {
st = cc2420_status_byte();
} while (cc2420_get_sfd() != 0);
cc2420_switch_to_rx();
/* check for underflow error flag */
if (st & 0x20) {
return RADIO_TX_UNDERFLOW;
}
/* wait for ACK only if needed */
if (!wait_for_ack) {
return RADIO_TX_OK;
}
/* delay for the peer to answer our packet */
//TODO design a more robust method?
hwtimer_wait(HWTIMER_TICKS(CC2420_ACK_WAIT_DELAY_uS));
/* try to read a returning ACK packet */
if (cc2420_get_fifop()) {
uint8_t ackbuf[ACK_LENGTH];
/* a packet has arrived, read the arrived data */
cc2420_read_fifo(ackbuf, ACK_LENGTH);
if (ackbuf[0] == 0x02 /* ack packet in buffer */
&& (ackbuf[2] == sequenz_nr - 1)) /* correct sequence number */
return RADIO_TX_OK;
}
return RADIO_TX_NOACK;
}
radio_tx_status_t cc2420_do_send(ieee802154_packet_kind_t kind,
ieee802154_node_addr_t dest,
bool use_long_addr,
bool wants_ack,
void *buf,
unsigned int len)
{
bool ok = cc2420_load_tx_buf(kind, dest,
use_long_addr,
wants_ack,
buf, len);
if (!ok) {
return RADIO_TX_ERROR;
}
return cc2420_transmit_tx_buf();
}
int16_t cc2420_send(cc2420_packet_t *packet)
{

View File

@ -1,5 +1,5 @@
/******************************************************************************
* Copyright 2013, Freie Universitaet Berlin (FUB). All rights reserved.
* Copyright 2014, Freie Universitaet Berlin (FUB). All rights reserved.
*
* These sources were developed at the Freie Universitaet Berlin, Computer Systems
and Telematics group (http://cst.mi.fu-berlin.de).
@ -20,9 +20,7 @@ and Telematics group (http://cst.mi.fu-berlin.de).
* @author Freie Universität Berlin, Computer Systems & Telematics
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @author Milan Babel <babel@inf.fu-berlin.de>
* @version $Revision: 1775 $
*
* @note $Id: arch_cc110x.h 1775 2010-01-26 09:37:03Z hillebra $
* @author Kévin Roussel <Kevin.Roussel@inria.fr>
*/
#include <stdint.h>
@ -38,23 +36,31 @@ and Telematics group (http://cst.mi.fu-berlin.de).
uint8_t cc2420_txrx(uint8_t c);
/**
* @brief Gets the status of the sfd pin.
* @brief Gets the status of the FIFOP pin.
*
* @return Status of the sfd pin.
* @return Status of the FIFOP pin.
*
*/
uint8_t cc2420_get_fifop(void);
/**
* @brief Gets the status of the SFD pin.
*
* @return Status of the SFD pin.
*
*/
uint8_t cc2420_get_sfd(void);
/**
* @brief Gets the status of the cca pin
* @brief Gets the status of the CCA pin
*
* @return Status of the cca pin.
* @return Status of the CCA pin.
*
*/
uint8_t cc2420_get_cca(void);
/**
* @brief Does a hardware reset of the cc2420.
* @brief Does a hardware reset of the CC2420.
*
*/
void cc2420_reset(void);
@ -66,13 +72,13 @@ void cc2420_reset(void);
void cc2420_spi_init(void);
/**
* @brief Selects the cc2420 on the spi bus.
* @brief Selects the CC2420 on the spi bus.
*
*/
void cc2420_spi_select(void);
/**
* @brief Unselects the cc2420 on the spi bus.
* @brief Unselects the CC2420 on the spi bus.
*
*/
void cc2420_spi_unselect(void);

View File

@ -1,9 +1,11 @@
/**
* cc2420.h - Definitions for CC2420 functions.
* Copyright (C) 2013 Milan Babel <babel@inf.fu-berlin.de>
* Copyright (C) 2014 Kévin Roussel <Kevin.Roussel@inria.fr>
*
* This source code is licensed under the GNU Lesser General Public License,
* Version 2. See the file LICENSE for more details.
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*/
@ -81,7 +83,7 @@ Frame type value:
#include "ieee802154_frame.h"
#include "cc2420_settings.h"
#include "radio/types.h"
#include "radio_driver.h"
#define CC2420_MAX_PKT_LENGTH 127
#define CC2420_MAX_DATA_LENGTH (118)
@ -99,15 +101,20 @@ typedef struct __attribute__ ((packed)) {
uint8_t length; /** < the length of the frame of the frame including fcs*/
ieee802154_frame_t frame; /** < the ieee802154 frame */
int8_t rssi; /** < the rssi value */
uint8_t crc; /** < 1 if crc was successfull, 0 otherwise */
uint8_t lqi; /** < the link quality indicator */
bool crc; /** < 1 if crc was successfull, 0 otherwise */
/* @} */
} cc2420_packet_t;
extern int transceiver_pid;
/**
* @brief Init the cc2420.
* @brief Initialize the CC2420 transceiver.
*/
void cc2420_initialize(void);
/**
* @brief Init the CC2420 for use with RIOT's transceiver module.
*
* @param[in] tpid The PID of the transceiver thread.
*/
@ -115,53 +122,80 @@ extern int transceiver_pid;
void cc2420_init(int tpid);
/**
* @brief Turns monitor mode on off.
* @brief Turn CC2420 on.
*
* @param[in] mode The desired mode, 1 for on; 0 for off.
* @return true if the radio was correctly turned on; false otherwise.
*/
void cc2420_set_monitor(uint8_t mode);
bool cc2420_on(void);
/**
* @brief Switchs the cc2420 into receive mode.
* @brief Turn CC2420 off.
*/
void cc2420_off(void);
/**
* @brief Indicate if the CC2420 is on.
*
* @return true if the radio transceiver is on (active); false otherwise.
*/
bool cc2420_is_on(void);
/**
* @brief Switches the CC2420 into receive mode.
*/
void cc2420_switch_to_rx(void);
/**
* @brief Set the channel of the cc2420.
* @brief Turns monitor (promiscuous) mode on or off.
*
* @param[in] mode The desired mode:
* true for monitor (promiscuous) mode;
* false for normal (auto address-decoding) mode.
*/
void cc2420_set_monitor(bool mode);
/**
* @brief Indicate if the CC2420 is in monitor (promiscuous) mode.
*
* @return true if the transceiver is in monitor (promiscuous) mode;
* false if it is in normal (auto address-decoding) mode.
*/
bool cc2420_get_monitor(void);
/**
* @brief Set the channel of the CC2420.
*
* @param[in] chan The desired channel, valid channels are from 11 to 26.
*
* @return The tuned channel after calling, or -1 on error.
*/
int16_t cc2420_set_channel(uint16_t chan);
int cc2420_set_channel(unsigned int chan);
/**
* @brief Get the channel of the cc2420.
* @brief Get the channel of the CC2420.
*
* @return The tuned channel.
*/
uint16_t cc2420_get_channel(void);
unsigned int cc2420_get_channel(void);
/**
* @brief Sets the short address of the cc2420.
* @brief Sets the short address of the CC2420.
*
* @param[in] addr The desired address.
*
* @return The set address after calling.
*/
radio_address_t cc2420_set_address(radio_address_t addr);
uint16_t cc2420_set_address(uint16_t addr);
/**
* @brief Gets the current short address of the cc2420.
* @brief Gets the current short address of the CC2420.
*
* @return The current short address.
*
*/
radio_address_t cc2420_get_address(void);
uint16_t cc2420_get_address(void);
/**
* @brief Sets the IEEE long address of the cc2420.
* @brief Sets the IEEE long address of the CC2420.
*
* @param[in] addr The desired address.
*
@ -170,15 +204,14 @@ radio_address_t cc2420_get_address(void);
uint64_t cc2420_set_address_long(uint64_t addr);
/**
* @brief Gets the current IEEE long address of the cc2420.
* @brief Gets the current IEEE long address of the CC2420.
*
* @return The current IEEE long address.
*
*/
uint64_t cc2420_get_address_long(void);
/**
* @brief Sets the pan ID of the cc2420.
* @brief Sets the pan ID of the CC2420.
*
* @param[in] pan The desired pan ID.
*
@ -187,13 +220,39 @@ uint64_t cc2420_get_address_long(void);
uint16_t cc2420_set_pan(uint16_t pan);
/**
* @brief Gets the current IEEE long address of the cc2420.
* @brief Gets the current IEEE long address of the CC2420.
*
* @return The current IEEE long address.
*
*/
uint16_t cc2420_get_pan(void);
/**
* @brief Sets the output (TX) power of the CC2420.
*
* @param[in] pow The desired TX (output) power in dBm,
* valid values are -25 to 0; other values
* will be "saturated" into this range.
*
* @return The set TX (output) power after calling.
*/
int cc2420_set_tx_power(int pow);
/**
* @brief Gets the current output (TX) power of the CC2420.
*
* @return The current TX (output) power.
*/
int cc2420_get_tx_power(void);
/**
* @brief Checks if the radio medium is available/clear to send
* ("Clear Channel Assessment" a.k.a. CCA).
*
* @return a `true` value if radio medium is clear (available),
* a `false` value otherwise.
*
*/
bool cc2420_channel_clear(void);
/**
* @brief Interrupt handler, gets fired when a RX overflow happens.
@ -207,6 +266,14 @@ void cc2420_rxoverflow_irq(void);
*/
void cc2420_rx_irq(void);
/**
* @brief Sets the function called back when a packet is received.
* (Low-level mechanism, parallel to the `transceiver` module).
*
* @param[in] recv_cb callback function for 802.15.4 packet arrival;
* pass `NULL` to deactivate packet reception.
*/
void cc2420_set_recv_callback(receive_802154_packet_callback_t recv_cb);
/**
* @brief RX handler, process data from the RX FIFO.
@ -214,6 +281,74 @@ void cc2420_rx_irq(void);
*/
void cc2420_rx_handler(void);
/**
* @brief Prepare the CC2420 TX buffer to send with the given packet.
*
* @param[in] kind Kind of packet to transmit.
* @param[in] dest Address of the node to which the packet is sent.
* @param[in] use_long_addr `true` to use the 64-bit address mode
* with `dest` param; `false` to use
* "short" PAN-centric mode.
* @param[in] wants_ack `true` to request an acknowledgement
* from the receiving node for this packet;
* `false` otherwise.
* @param[in] buf Pointer to the buffer containing the payload
* of the 802.15.4 packet to transmit.
* The frame header (i.e.: FCS, sequence number,
* src and dest PAN and addresses) is inserted
* using values in accord with `kind` parameter
* and transceiver configuration.
* @param[in] len Length (in bytes) of the outgoing packet payload.
*
* @return `true` if the transceiver TX buffer was loaded correctly;
* `false` otherwise (transceiver error).
*/
radio_tx_status_t cc2420_load_tx_buf(ieee802154_packet_kind_t kind,
ieee802154_node_addr_t dest,
bool use_long_addr,
bool wants_ack,
void *buf,
unsigned int len);
/**
* @brief Transmit the data loaded into the CC2420 TX buffer.
*
* @return The outcome of this packet's transmission.
* @see radio_tx_status_t
*/
radio_tx_status_t cc2420_transmit_tx_buf(void);
/**
* @brief Transmit the given IEEE 802.15.4 packet,
* by calling successively functions`load_tx()`
* and `transmit()`.
*
* @param[in] kind Kind of packet to transmit.
* @param[in] dest Address of the node to which the packet is sent.
* @param[in] use_long_addr `true` to use the 64-bit address mode
* with `dest` param; `false` to use
* "short" PAN-centric mode.
* @param[in] wants_ack `true` to request an acknowledgement
* from the receiving node for this packet;
* `false` otherwise.
* @param[in] buf Pointer to the buffer containing the payload
* of the 802.15.4 packet to transmit.
* The frame header (i.e.: FCS, sequence number,
* src and dest PAN and addresses) is inserted
* using values in accord with `kind` parameter
* and transceiver configuration.
* @param[in] len Length (in bytes) of the outgoing packet payload.
*
* @return The outcome of this packet's transmission.
* @see radio_tx_status_t
*/
radio_tx_status_t cc2420_do_send(ieee802154_packet_kind_t kind,
ieee802154_node_addr_t dest,
bool use_long_addr,
bool wants_ack,
void *buf,
unsigned int len);
/**
* @brief Send function, sends a cc2420_packet_t over the air.
*
@ -224,16 +359,6 @@ void cc2420_rx_handler(void);
*/
int16_t cc2420_send(cc2420_packet_t *packet);
/**
* @brief Checks if the radio medium is available/clear to send
* ("Clear Channel Assessment" a.k.a. CCA).
*
* @return a @c true value if radio medium is clear (available),
* a @c false value otherwise.
*
*/
bool channel_clear(void);
/**
* The PID of the transceiver thread.
*/
@ -245,4 +370,37 @@ extern int transceiver_pid;
extern cc2420_packet_t cc2420_rx_buffer[CC2420_RX_BUF_SIZE];
/** Utility macro: get CC2420's status byte */
#define cc2420_status_byte() cc2420_strobe(NOBYTE)
/* setter functions wrappers, to maintain compatibility with both
ieee802154_radio_driver_t and transceiver module */
static inline void do_set_channel(unsigned int chan) {
cc2420_set_channel(chan);
}
static inline void do_set_address(uint16_t addr) {
cc2420_set_address(addr);
}
static inline void do_set_long_address(uint64_t addr) {
cc2420_set_address_long(addr);
}
static inline void do_set_pan_id(uint16_t pan) {
cc2420_set_pan(pan);
}
static inline void do_set_tx_power(int pow) {
cc2420_set_tx_power(pow);
}
/**
* CC2420 low-level radio driver definition.
*/
extern const ieee802154_radio_driver_t cc2420_radio_driver;
#endif