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:
commit
65e240f950
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user