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

drivers: added support for CC2420 radio

This commit is contained in:
Hauke Petersen 2016-04-14 13:48:00 +02:00 committed by kYc0o
parent e31f034bb1
commit abc6b5ccdf
7 changed files with 1544 additions and 0 deletions

View File

@ -32,6 +32,20 @@ ifneq (,$(filter cc110x,$(USEMODULE)))
endif
endif
ifneq (,$(filter cc2420,$(USEMODULE)))
USEMODULE += xtimer
USEMODULE += netif
USEMODULE += ieee802154
USEMODULE += netdev2_ieee802154
ifneq (,$(filter gnrc_netdev_default,$(USEMODULE)))
# XXX: this can be modelled as a dependency for gnrc_netdev_default as soon
# as all drivers are ported to netdev2
USEMODULE += gnrc_netdev2
endif
FEATURES_REQUIRED += periph_gpio
FEATURES_REQUIRED += periph_spi
endif
ifneq (,$(filter dht,$(USEMODULE)))
USEMODULE += xtimer
FEATURES_REQUIRED += periph_gpio

View File

@ -61,3 +61,6 @@ endif
ifneq (,$(filter bmp180,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/bmp180/include
endif
ifneq (,$(filter cc2420,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/cc2420/include
endif

1
drivers/cc2420/Makefile Normal file
View File

@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base

877
drivers/cc2420/cc2420.c Normal file
View File

@ -0,0 +1,877 @@
/*
* Copyright (C) 2015-2016 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_cc2420
* @{
*
* @file
* @brief Implementation of public functions for CC2420 driver
*
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*
* @}
*/
#include "board.h"
#include "xtimer.h"
#include "periph/cpuid.h"
#include "byteorder.h"
#include "panic.h"
#include "net/ieee802154.h"
#include "net/gnrc.h"
#include "cc2420.h"
#include "cc2420_internal.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
/**
* @brief Some constant hardware configuration values
*/
#define SPI_MODE (SPI_CONF_FIRST_RISING)
extern const netdev2_driver_t cc2420_driver;
/**
* @brief Translation from dBm to PA level
*
* Entry 0 in the array corresponds to -25dBm (min), entry 25 to 0dBm (max), so
* `PA_level = power_dbm_to_pa[DBM + 25]`. We use only the 3 MSB of the 5-bit
* level, leading to 8 distinct power settings (the 8 settings listed in the
* datasheet in section 28, page 51).
*/
static const uint8_t power_dbm_to_pa[26] = {
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7,
7, 7, 11, 11, 11, 15, 15, 19, 19, 23, 23, 27, 31
};
/**
* @brief Translate PA level to dBm
*
* As we use only the 3 MSB of the PA level value, we have 8 distinct settings.
* We get the dBm value with `DBM = power_pa_to_dbm(PA >> 2).
*/
static const int8_t power_pa_to_dbm[8] = {
-25, -15, -10, -7, -5, -3, -1, 0
};
static inline uint16_t to_u16(void *buf)
{
return *((uint16_t *)buf);
}
static inline int16_t to_i16(void *buf)
{
return *((int16_t *)buf);
}
static inline bool to_bool(void *buf)
{
return *((bool *)buf);
}
static inline int w_u16(void *buf, uint16_t val)
{
memcpy(buf, &val, sizeof(uint16_t));
return sizeof(uint16_t);
}
static inline int w_i16(void *buf, int16_t val)
{
memcpy(buf, &val, sizeof(int16_t));
return sizeof(int16_t);
}
static inline int opt_state(void *buf, bool cond)
{
*((netopt_enable_t *)buf) = !!(cond);
return sizeof(netopt_enable_t);
}
static uint8_t strobe(const cc2420_t *dev, const uint8_t command)
{
char res;
spi_acquire(dev->params.spi);
gpio_clear(dev->params.pin_cs);
spi_transfer_byte(dev->params.spi, (char)command, (char *)&res);
gpio_set(dev->params.pin_cs);
spi_release(dev->params.spi);
return res;
}
static void reg_write(const cc2420_t *dev,
const uint8_t addr,
const uint16_t value)
{
uint16_t tmp = byteorder_htons(value).u16;
spi_acquire(dev->params.spi);
gpio_clear(dev->params.pin_cs);
spi_transfer_regs(dev->params.spi, CC2420_REG_WRITE | addr,
(char *)&tmp, NULL, 2);
gpio_set(dev->params.pin_cs);
spi_release(dev->params.spi);
}
static uint16_t reg_read(const cc2420_t *dev, const uint8_t addr)
{
network_uint16_t tmp;
spi_acquire(dev->params.spi);
gpio_clear(dev->params.pin_cs);
spi_transfer_regs(dev->params.spi, CC2420_REG_READ | addr,
NULL, (char *)&tmp, 2);
gpio_set(dev->params.pin_cs);
spi_release(dev->params.spi);
return byteorder_ntohs(tmp);
}
static void ram_read(const cc2420_t *dev, const uint16_t addr,
uint8_t *data, const size_t len)
{
char tmp[] = { (CC2420_RAM | (addr & 0x7f)),
(CC2420_RAM_READ | ((addr >> 1) & 0xc0)) };
spi_acquire(dev->params.spi);
gpio_clear(dev->params.pin_cs);
spi_transfer_bytes(dev->params.spi, tmp, NULL, 2);
spi_transfer_bytes(dev->params.spi, NULL, (char*)data, len);
gpio_set(dev->params.pin_cs);
spi_release(dev->params.spi);
}
static void ram_write(const cc2420_t *dev, const uint16_t addr,
const uint8_t *data, const size_t len)
{
char tmp[] = { (CC2420_RAM | (addr & 0x7f)),
(CC2420_RAM_WRITE | ((addr >> 1) & 0xc0)) };
spi_acquire(dev->params.spi);
gpio_clear(dev->params.pin_cs);
spi_transfer_bytes(dev->params.spi, tmp, NULL, 2);
spi_transfer_bytes(dev->params.spi, (char*)data, NULL, len);
gpio_set(dev->params.pin_cs);
spi_release(dev->params.spi);
}
static void fifo_read(const cc2420_t *dev, uint8_t *data, const size_t len)
{
spi_acquire(dev->params.spi);
gpio_clear(dev->params.pin_cs);
spi_transfer_regs(dev->params.spi, CC2420_FIFO_READ,
NULL, (char *)data, len);
gpio_set(dev->params.pin_cs);
spi_release(dev->params.spi);
}
static void fifo_write(const cc2420_t *dev, uint8_t *data, const size_t len)
{
spi_acquire(dev->params.spi);
gpio_clear(dev->params.pin_cs);
spi_transfer_regs(dev->params.spi, CC2420_FIFO_WRITE,
(char *)data, NULL, len);
gpio_set(dev->params.pin_cs);
spi_release(dev->params.spi);
}
/**
* @brief Get the device's status byte
*/
static inline uint8_t status(cc2420_t *dev)
{
return strobe(dev, CC2420_STROBE_NOP);
}
/**
* @brief Get the device's current state
*/
static inline uint8_t state(cc2420_t *dev)
{
return (uint8_t)reg_read(dev, CC2420_REG_FSMSTATE);
}
static inline void en_xosc(cc2420_t *dev)
{
strobe(dev, CC2420_STROBE_XOSCON);
xtimer_usleep(CC2420_XOSCON_DELAY);
}
static void fifop_evt(void *arg)
{
netdev2_t *dev = (netdev2_t *)arg;
dev->event_callback(dev, NETDEV2_EVENT_ISR, NULL);
}
/**
* @todo Move this function to a global module
*/
#if CPUID_ID_LEN
static void addr_from_cpuid(uint8_t *addr)
{
/* option 1: generate addresses from CPUID */
uint8_t cpuid[CPUID_ID_LEN];
cpuid_get(cpuid);
memcpy(addr, cpuid, 8);
#if CPUID_ID_LEN < 8
/* in case CPUID_ID_LEN < 8, fill missing bytes with zeros */
for (int i = CPUID_ID_LEN; i < 8; i++) {
addr_long[i] = 0;
}
#else
/* in case CPUID_ID_LEN > 8, XOR those bytes on top of the first 8 */
for (int i = 8; i < CPUID_ID_LEN; i++) {
addr_long[i & 0x07] ^= cpuid[i];
}
#endif
/* make sure we mark the address as non-multicast and not globally unique */
addr_long[0] &= ~(0x01);
addr_long[0] |= 0x02;
}
#endif
void cc2420_setup(cc2420_t * dev, const cc2420_params_t *params)
{
/* set pointer to the devices netdev functions */
dev->netdev.netdev.driver = &cc2420_driver;
/* TODO: remove once the netdev2/802154 shit is cleaned up */
dev->netdev.seq = 0;
dev->netdev.flags = NETDEV2_IEEE802154_PAN_COMP;
/* pull in device configuration parameters */
memcpy(&dev->params, params, sizeof(cc2420_params_t));
/* reset device descriptor fields */
dev->options = 0;
}
int cc2420_init(cc2420_t *dev)
{
uint16_t reg;
uint8_t addr[8] = CC2420_ADDR_FALLBACK;
/* initialize power and reset pins -> put the device into reset state */
gpio_init(dev->params.pin_reset, GPIO_OUT);
gpio_set(dev->params.pin_reset);
gpio_init(dev->params.pin_vrefen, GPIO_OUT);
gpio_clear(dev->params.pin_vrefen);
/* initialize the input lines */
gpio_init(dev->params.pin_cca, GPIO_IN);
gpio_init(dev->params.pin_sfd, GPIO_IN);
gpio_init(dev->params.pin_fifo, GPIO_IN);
gpio_init_int(dev->params.pin_fifop, GPIO_IN, GPIO_RISING, fifop_evt, dev);
/* initialize the chip select line and the SPI bus */
gpio_init(dev->params.pin_cs, GPIO_OUT);
gpio_set(dev->params.pin_cs);
spi_init_master(dev->params.spi, SPI_MODE, dev->params.spi_clk);
/* power on and toggle reset */
gpio_set(dev->params.pin_vrefen);
gpio_clear(dev->params.pin_reset);
xtimer_usleep(CC2420_RESET_DELAY);
gpio_set(dev->params.pin_reset);
/* test the connection to the device by reading MANFIDL register */
reg = reg_read(dev, CC2420_REG_MANFIDL);
if (reg != CC2420_MANFIDL_VAL) {
DEBUG("[cc2420] init: unable to communicate with device\n");
return -1;
}
/* turn on the oscillator and wait for it to be stable */
en_xosc(dev);
if (!(status(dev) & CC2420_STATUS_XOSC_STABLE)) {
DEBUG("[cc2420] init: oscillator did not stabilize\n");
return -1;
}
/* set default address, channel, PAN ID, and TX power */
#if CPUID_ID_LEN
addr_from_cpuid(addr);
#endif
cc2420_set_addr_short(dev, &addr[6]);
cc2420_set_addr_long(dev, addr);
cc2420_set_pan(dev, CC2420_PANID_DEFAULT);
cc2420_set_chan(dev, CC2420_CHAN_DEFAULT);
cc2420_set_txpower(dev, CC2420_TXPOWER_DEFAULT);
/* set default options */
cc2420_set_option(dev, CC2420_OPT_AUTOACK, true);
cc2420_set_option(dev, CC2420_OPT_CSMA, true);
cc2420_set_option(dev, CC2420_OPT_TELL_TX_START, true);
cc2420_set_option(dev, CC2420_OPT_TELL_RX_END, true);
/* change default RX bandpass filter to 1.3uA (as recommended) */
reg = reg_read(dev, CC2420_REG_RXCTRL1);
reg |= CC2420_RXCTRL1_RXBPF_LOCUR;
reg_write(dev, CC2420_REG_RXCTRL1, reg);
/* set the FIFOP threshold to maximum. */
reg_write(dev, CC2420_REG_IOCFG0, CC2420_PKT_MAXLEN);
/* turn off "Security enable" (page 33). */
reg = reg_read(dev, CC2420_REG_SECCTRL0);
reg &= ~CC2420_SECCTRL0_RXFIFO_PROT;
reg_write(dev, CC2420_REG_SECCTRL0, reg);
/* go into RX state */
cc2420_set_state(dev, CC2420_GOTO_RX);
/* set preamble length to 3 leading zero byte */
reg = reg_read(dev, CC2420_REG_MDMCTRL0);
reg &= ~(CC2420_MDMCTRL0_PREAMBLE_M);
reg |= CC2420_MDMCTRL0_PREAMBLE_3B;
reg_write(dev, CC2420_REG_MDMCTRL0, reg);
return 0;
}
void cc2420_get_addr_short(cc2420_t *dev, uint8_t *addr)
{
uint8_t tmp[2];
ram_read(dev, CC2420_RAM_SHORTADR, tmp, 2);
addr[0] = tmp[1];
addr[1] = tmp[0];
}
void cc2420_set_addr_short(cc2420_t *dev, uint8_t *addr)
{
uint8_t tmp[2];
tmp[0] = addr[1];
tmp[1] = addr[0];
ram_write(dev, CC2420_RAM_SHORTADR, tmp, 2);
/* TODO: remove after 802.15.4 / netdev2 cleanup */
memcpy(dev->netdev.short_addr, addr, 2);
}
void cc2420_get_addr_long(cc2420_t *dev, uint8_t *addr)
{
ram_read(dev, CC2420_RAM_IEEEADR, addr, 8);
}
void cc2420_set_addr_long(cc2420_t *dev, uint8_t *addr)
{
ram_write(dev, CC2420_RAM_IEEEADR, addr, 8);
/* TODO: remove after 802.15.4 / netdev2 cleanup */
memcpy(dev->netdev.long_addr, addr, 8);
}
uint16_t cc2420_get_pan(cc2420_t *dev)
{
le_uint16_t pan;
ram_read(dev, CC2420_RAM_PANID, pan.u8, 2);
return pan.u16;
}
void cc2420_set_pan(cc2420_t *dev, uint16_t pan)
{
ram_write(dev, CC2420_RAM_PANID, (uint8_t *)&pan, 2);
/* TODO: remove after 802.15.4 / netdev2 cleanup */
dev->netdev.pan = pan;
}
uint16_t cc2420_get_chan(cc2420_t *dev)
{
uint16_t chan;
uint16_t freq = reg_read(dev, CC2420_REG_FSCTRL);
chan = (((freq & CC2420_FSCTRL_FREQ_MASK) - 357) / 5) + 11;
return chan;
}
int cc2420_set_chan(cc2420_t *dev, uint16_t chan)
{
if ((chan < CC2420_CHAN_MIN) || (chan > CC2420_CHAN_MAX)) {
DEBUG("[cc2420] set channel: given channel invalid\n");
return -ENOTSUP;
}
/* calculation from http://www.ti.com/lit/ds/symlink/cc2420.pdf p.50 */
uint16_t freq = reg_read(dev, CC2420_REG_FSCTRL);
freq &= ~CC2420_FSCTRL_FREQ_MASK;
freq |= (357 + (5 * (chan - 11)));
reg_write(dev, CC2420_REG_FSCTRL, freq);
/* TODO: remove after 802.15.4 / netdev2 cleanup */
dev->netdev.chan = chan;
return CC2420_RET_CHAN_OK;
}
int16_t cc2420_get_txpower(cc2420_t *dev)
{
uint16_t txctrl = reg_read(dev, CC2420_REG_TXCTRL);
return (int16_t)power_pa_to_dbm[(txctrl & CC2420_TXCTRL_PA_MASK) >> 2];
}
void cc2420_set_txpower(cc2420_t *dev, int16_t txpower)
{
if (txpower > CC2420_TXPOWER_MAX) {
txpower = CC2420_TXPOWER_MAX;
}
else if (txpower < CC2420_TXPOWER_MIN) {
txpower = CC2420_TXPOWER_MIN;
}
uint16_t txctrl = reg_read(dev, CC2420_REG_TXCTRL);
txctrl &= ~(CC2420_TXCTRL_PA_MASK);
txctrl |= power_dbm_to_pa[txpower + 25];
reg_write(dev, CC2420_REG_TXCTRL, txctrl);
}
int cc2420_set_option(cc2420_t *dev, uint16_t option, bool state)
{
uint16_t reg;
/* set option field */
if (state) {
dev->options |= option;
/* trigger option specific actions */
switch (option) {
case CC2420_OPT_AUTOACK:
DEBUG("[cc2420] set_opt: CC2420_OPT_AUTOACK\n");
reg = reg_read(dev, CC2420_REG_MDMCTRL0);
reg |= CC2420_MDMCTRL0_AUTOACK;
reg_write(dev, CC2420_REG_MDMCTRL0, reg);
/* TODO: remove after netdev2 cleanup */
dev->netdev.flags |= NETDEV2_IEEE802154_ACK_REQ;
break;
case CC2420_OPT_CSMA:
DEBUG("[cc2420] set_opt: CC2420_OPT_CSMA\n");
/* TODO: en/disable csma */
break;
case CC2420_OPT_PROMISCUOUS:
DEBUG("[cc2420] set_opt: CC2420_OPT_PROMISCUOUS\n");
/* in promisc mode, AUTO ACKs are should be disabled */
reg = reg_read(dev, CC2420_REG_MDMCTRL0);
reg &= ~(CC2420_MDMCTRL0_AUTOACK);
reg &= ~(CC2420_MDMCTRL0_ADR_DECODE);
reg_write(dev, CC2420_REG_MDMCTRL0, reg);
break;
case CC2420_OPT_PRELOADING:
DEBUG("[cc2420] set_opt: CC2420_OPT_PRELOADING\n");
break;
case CC2420_OPT_TELL_TX_START:
case CC2420_OPT_TELL_TX_END:
case CC2420_OPT_TELL_RX_START:
case CC2420_OPT_TELL_RX_END:
DEBUG("[cc2420] set_opt: TX/RX START/END\n");
break;
default:
return -ENOTSUP;
}
}
else {
dev->options &= ~(option);
/* trigger option specific actions */
switch (option) {
case CC2420_OPT_AUTOACK:
DEBUG("[cc2420] clr_opt: CC2420_OPT_AUTOACK\n");
reg = reg_read(dev, CC2420_REG_MDMCTRL0);
reg &= ~(CC2420_MDMCTRL0_AUTOACK);
reg_write(dev, CC2420_REG_MDMCTRL0, reg);
/* TODO: remove after netdev cleanup */
dev->netdev.flags &= ~(NETDEV2_IEEE802154_ACK_REQ);
break;
case CC2420_OPT_CSMA:
DEBUG("[cc2420] clr_opt: CC2420_OPT_CSMA\n");
/* TODO: en/disable csma */
break;
case CC2420_OPT_PROMISCUOUS:
DEBUG("[cc2420] clr_opt: CC2420_OPT_PROMISCUOUS\n");
reg = reg_read(dev, CC2420_REG_MDMCTRL0);
reg |= CC2420_MDMCTRL0_ADR_DECODE;
/* re-enable AUTOACK only if the option was set */
if (dev->options & CC2420_OPT_AUTOACK) {
reg |= CC2420_MDMCTRL0_AUTOACK;
}
reg_write(dev, CC2420_REG_MDMCTRL0, reg);
break;
case CC2420_OPT_PRELOADING:
DEBUG("[cc2420] clr_opt: CC2420_OPT_PRELOADING\n");
break;
case CC2420_OPT_TELL_TX_START:
case CC2420_OPT_TELL_TX_END:
case CC2420_OPT_TELL_RX_START:
case CC2420_OPT_TELL_RX_END:
DEBUG("[cc2420] clr_opt: TX/RX START/END\n");
/* TODO */
break;
default:
return -ENOTSUP;
}
}
return sizeof(netopt_enable_t);
}
int cc2420_set_state(cc2420_t *dev, netopt_state_t cmd)
{
if ((cc2420_get_state(dev) == NETOPT_STATE_OFF) &&
(cmd != NETOPT_STATE_OFF)) {
en_xosc(dev);
}
switch (cmd) {
case NETOPT_STATE_OFF:
strobe(dev, CC2420_STROBE_XOSCOFF);
while (state(dev) != CC2420_STATE_PD) {}
break;
case NETOPT_STATE_SLEEP:
strobe(dev, CC2420_STROBE_RFOFF);
while (state(dev) != CC2420_STATE_IDLE) {}
break;
case NETOPT_STATE_IDLE:
strobe(dev, CC2420_STROBE_FLUSHRX);
strobe(dev, CC2420_STROBE_RXON);
break;
case NETOPT_STATE_TX:
cc2420_tx_exec(dev);
break;
case NETOPT_STATE_RESET:
cc2420_init(dev);
break;
case NETOPT_STATE_RX:
default:
DEBUG("[cc2420] set_state: called with invalid target state\n");
return -ENOTSUP;
}
return sizeof(netopt_state_t);
}
netopt_state_t cc2420_get_state(cc2420_t *dev)
{
uint8_t cur_state = state(dev);
if (cur_state == 0) {
return NETOPT_STATE_OFF;
}
else if (cur_state == 1) {
return NETOPT_STATE_SLEEP;
}
else if (((cur_state >= 32) && (cur_state <=39)) || (cur_state == 56)) {
return NETOPT_STATE_TX;
}
else if ((cur_state >= 3) && (cur_state <= 6)) {
return NETOPT_STATE_IDLE;
}
else {
return NETOPT_STATE_RX;
}
}
bool cc2420_cca(cc2420_t *dev)
{
while (!(status(dev) & CC2420_STATUS_RSSI_VALID)) {}
return gpio_read(dev->params.pin_cca);
}
size_t cc2420_send(cc2420_t *dev, const struct iovec *data, int count)
{
size_t n = cc2420_tx_prepare(dev, data, count);
if ((n > 0) && !(dev->options & CC2420_OPT_PRELOADING)) {
cc2420_tx_exec(dev);
}
return n;
}
size_t cc2420_tx_prepare(cc2420_t *dev, const struct iovec *data, int count)
{
size_t pkt_len = 2; /* include the FCS (frame check sequence) */
/* wait for any ongoing transmissions to be finished */
while (cc2420_get_state(dev) & NETOPT_STATE_TX) {}
/* get and check the length of the packet */
for (int i = 0; i < count; i++) {
pkt_len += data[i].iov_len;
}
if (pkt_len >= CC2420_PKT_MAXLEN) {
DEBUG("[cc2420] tx_prep: unable to send, pkt too large\n");
return 0;
}
/* flush TX FIFO and write new packet to it */
strobe(dev, CC2420_STROBE_FLUSHTX);
/* push packet length to TX FIFO */
fifo_write(dev, (uint8_t *)&pkt_len, 1);
/* push packet to TX FIFO */
for (int i = 0; i < count; i++) {
fifo_write(dev, (uint8_t *)data[i].iov_base, data[i].iov_len);
}
DEBUG("[cc2420] tx_prep: loaded %i byte into the TX FIFO\n", (int)pkt_len);
return pkt_len;
}
void cc2420_tx_exec(cc2420_t *dev)
{
/* make sure, any ongoing transmission is finished */
DEBUG("[cc2420] tx_exec: waiting for any ongoing transmission\n");
while (cc2420_get_state(dev) & NETOPT_STATE_TX) {}
/* trigger the transmission */
if (dev->options & CC2420_OPT_TELL_TX_START) {
dev->netdev.netdev.event_callback(&dev->netdev.netdev,
NETDEV2_EVENT_TX_STARTED, dev);
}
DEBUG("[cc2420] tx_exec: TX_START\n");
if (dev->options & CC2420_OPT_CSMA) {
DEBUG("[cc2420] tx_exec: triggering TX with CCA\n");
strobe(dev, CC2420_STROBE_TXONCCA);
}
else {
DEBUG("[cc2420] tx_exec: triggering TX without CCA\n");
strobe(dev, CC2420_STROBE_TXON);
}
while (gpio_read(dev->params.pin_sfd)) {
puts("\t...ongoing}");
}
if (dev->options & CC2420_OPT_TELL_TX_END) {
dev->netdev.netdev.event_callback(&dev->netdev.netdev,
NETDEV2_EVENT_TX_COMPLETE, dev);
}
DEBUG("[cc2420] tx_exec: TX_DONE\n");
}
int cc2420_rx(cc2420_t *dev, uint8_t *buf, size_t max_len, void *info)
{
uint8_t len;
/* get the packet length (without dropping it) (first byte in RX FIFO */
ram_read(dev, CC2420_RAM_RXFIFO, &len, 1);
len -= 2; /* subtract RSSI and FCF */
if (!buf) {
DEBUG("[cc2420] recv: packet of length %i in RX FIFO\n", (int)len);
}
/* if a buffer is given, read (and drop) the packet */
if (buf) {
len = (len > max_len) ? max_len : len;
/* drop length byte */
fifo_read(dev, NULL, 1);
/* read fifo contents */
DEBUG("[cc2420] recv: reading %i byte of the packet\n", (int)len);
fifo_read(dev, buf, len);
uint8_t rssi;
fifo_read(dev, &rssi, 1);
DEBUG("[cc2420] recv: RSSI is %i\n", (int)rssi);
/* finally flush the FIFO */
strobe(dev, CC2420_STROBE_FLUSHRX);
strobe(dev, CC2420_STROBE_FLUSHRX);
}
return (int)len;
}
static int init(netdev2_t *dev)
{
return cc2420_init((cc2420_t *)dev);
}
static void isr(netdev2_t *netdev)
{
netdev->event_callback(netdev, NETDEV2_EVENT_RX_COMPLETE, NULL);
}
static int send(netdev2_t *netdev, const struct iovec *vector, int count)
{
cc2420_t *dev = (cc2420_t *)netdev;
return (int)cc2420_send(dev, vector, count);
}
static int recv(netdev2_t *netdev, char *buf, int len, void *info)
{
cc2420_t *dev = (cc2420_t *)netdev;
return (int)cc2420_rx(dev, (uint8_t *)buf, len, info);
}
static int get(netdev2_t *netdev, netopt_t opt, void *val, size_t max_len)
{
if (netdev == NULL) {
return -ENODEV;
}
cc2420_t *dev = (cc2420_t *)netdev;
int ext = netdev2_ieee802154_get(&dev->netdev, opt, val, max_len);
if (ext > 0) {
return ext;
}
switch (opt) {
case NETOPT_ADDRESS:
assert(max_len >= sizeof(uint16_t));
cc2420_get_addr_short(dev, val);
return sizeof(uint16_t);
case NETOPT_ADDRESS_LONG:
assert(max_len >= 8);
cc2420_get_addr_long(dev, val);
return 8;
case NETOPT_NID:
assert(max_len >= sizeof(uint16_t));
return w_u16(val, cc2420_get_pan(dev));
case NETOPT_CHANNEL:
assert(max_len >= sizeof(uint16_t));
return w_u16(val, cc2420_get_chan(dev));
case NETOPT_TX_POWER:
assert(max_len >= sizeof(int16_t));
return w_i16(val, cc2420_get_txpower(dev));
case NETOPT_STATE:
assert(max_len >= sizeof(netopt_state_t));
*((netopt_state_t *)val) = cc2420_get_state(dev);
return sizeof(netopt_state_t);
case NETOPT_IS_CHANNEL_CLR:
return opt_state(val, cc2420_cca(dev));
case NETOPT_AUTOACK:
return opt_state(val, (dev->options & CC2420_OPT_AUTOACK));
case NETOPT_CSMA:
return opt_state(val, (dev->options & CC2420_OPT_CSMA));
case NETOPT_PRELOADING:
return opt_state(val, (dev->options & CC2420_OPT_PRELOADING));
case NETOPT_PROMISCUOUSMODE:
return opt_state(val, (dev->options & CC2420_OPT_PROMISCUOUS));
case NETOPT_RX_START_IRQ:
return opt_state(val, (dev->options & CC2420_OPT_TELL_RX_START));
case NETOPT_RX_END_IRQ:
return opt_state(val, (dev->options & CC2420_OPT_TELL_TX_END));
case NETOPT_TX_START_IRQ:
return opt_state(val, (dev->options & CC2420_OPT_TELL_RX_START));
case NETOPT_TX_END_IRQ:
return opt_state(val, (dev->options & CC2420_OPT_TELL_RX_END));
default:
return -ENOTSUP;
}
}
static int set(netdev2_t *netdev, netopt_t opt, void *val, size_t val_len)
{
if (netdev == NULL) {
return -ENODEV;
}
cc2420_t *dev = (cc2420_t *)netdev;
int ext = netdev2_ieee802154_set(&dev->netdev, opt, val, val_len);
switch (opt) {
case NETOPT_ADDRESS:
assert(val_len == 2);
cc2420_set_addr_short(dev, (uint8_t *)val);
return 2;
case NETOPT_ADDRESS_LONG:
assert(val_len == 8);
cc2420_set_addr_long(dev, (uint8_t *)val);
return 8;
case NETOPT_NID:
assert(val_len == sizeof(uint16_t));
cc2420_set_pan(dev, to_u16(val));
return sizeof(uint16_t);
case NETOPT_CHANNEL:
assert(val_len == sizeof(uint16_t));
return cc2420_set_chan(dev, to_u16(val));
case NETOPT_TX_POWER:
assert(val_len == sizeof(int16_t));
cc2420_set_txpower(dev, to_i16(val));
return sizeof(int16_t);
case NETOPT_STATE:
assert(val_len == sizeof(netopt_state_t));
return cc2420_set_state(dev, *((netopt_state_t *)val));
case NETOPT_AUTOACK:
return cc2420_set_option(dev, CC2420_OPT_AUTOACK, to_bool(val));
case NETOPT_CSMA:
return cc2420_set_option(dev, CC2420_OPT_CSMA, to_bool(val));
case NETOPT_PRELOADING:
return cc2420_set_option(dev, CC2420_OPT_PRELOADING, to_bool(val));
case NETOPT_PROMISCUOUSMODE:
return cc2420_set_option(dev, CC2420_OPT_PROMISCUOUS, to_bool(val));
case NETOPT_RX_START_IRQ:
return cc2420_set_option(dev, CC2420_OPT_TELL_RX_START, to_bool(val));
case NETOPT_RX_END_IRQ:
return cc2420_set_option(dev, CC2420_OPT_TELL_RX_END, to_bool(val));
case NETOPT_TX_START_IRQ:
return cc2420_set_option(dev, CC2420_OPT_TELL_TX_START, to_bool(val));
case NETOPT_TX_END_IRQ:
return cc2420_set_option(dev, CC2420_OPT_TELL_TX_END, to_bool(val));
default:
return ext;
}
return 0;
}
const netdev2_driver_t cc2420_driver = {
.send = send,
.recv = recv,
.init = init,
.isr = isr,
.get = get,
.set = set,
};

View File

@ -0,0 +1,250 @@
/*
* Copyright (C) 2014 Milan Babel <babel@inf.fu-berlin.de> and INRIA
* Copyright (C) 2015-2016 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_cc2420
* @{
*
* @file
* @brief Definitions and settings for the CC2420
*
* @author Milan Babel <babel@inf.fu-berlin.de>
* @author Kévin Roussel <Kevin.Roussel@inria.fr>
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*
*/
#ifndef CC2420_REGISTERS_H
#define CC2420_REGISTERS_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Delays for resetting and turning on the device
* @{
*/
#define CC2420_RESET_DELAY (500U)
#define CC2420_XOSCON_DELAY (2000U)
/** @} */
/**
* @brief Internal device option flags
* @{
*/
#define CC2420_OPT_AUTOACK (0x0001) /**< auto ACKs active */
#define CC2420_OPT_CSMA (0x0002) /**< CSMA active */
#define CC2420_OPT_PROMISCUOUS (0x0004) /**< promiscuous mode
* active */
#define CC2420_OPT_PRELOADING (0x0008) /**< preloading enabled */
#define CC2420_OPT_TELL_TX_START (0x0010) /**< notify MAC layer on TX
* start */
#define CC2420_OPT_TELL_TX_END (0x0020) /**< notify MAC layer on TX
* finished */
#define CC2420_OPT_TELL_RX_START (0x0040) /**< notify MAC layer on RX
* start */
#define CC2420_OPT_TELL_RX_END (0x0080) /**< notify MAC layer on RX
* finished */
/** @} */
/**
* @brief Possible device state change commands
* @{
*/
enum {
CC2420_GOTO_PD, /**< power down */
CC2420_GOTO_IDLE, /**< idle */
CC2420_GOTO_RX, /**< receive state */
CC2420_GOTO_TXON, /**< transmit packet without CCA */
CC2420_GOTO_TXONCCA /**< transmit packet using CCA */
};
/**
* @brief (Selected) device states
*/
enum {
CC2420_STATE_PD = 0, /**< power down */
CC2420_STATE_IDLE = 1, /**< idle state */
CC2420_STATE_TX_PRE = 34, /**< transmitting preamble */
CC2420_STATE_RX_SEARCH = 6, /**< receive SFD search */
CC2420_STATE_RX_OVERFLOW = 17 /**< receive buffer overflow */
};
/**
* @brief CC2420 SPI commands
* @{
*/
#define CC2420_REG_WRITE (0x00) /**< read register value */
#define CC2420_REG_READ (0x40) /**< write register value */
#define CC2420_RAM (0x80) /**< access the internal RAM */
#define CC2420_RAM_WRITE (0x00) /**< write to RAM */
#define CC2420_RAM_READ (0x20) /**< read from RAM */
#define CC2420_FIFO_READ (CC2420_REG_RXFIFO | CC2420_REG_READ)
#define CC2420_FIFO_WRITE (CC2420_REG_TXFIFO | CC2420_REG_WRITE)
/** @} */
/**
* @brief CC2420 strobe commands
* @see Datasheet section 37, pages 61--62
* @{
*/
#define CC2420_STROBE_NOP (0x00) /**< no operation */
#define CC2420_STROBE_XOSCON (0x01) /**< turn transceiver on */
#define CC2420_STROBE_TXCAL (0x02) /**< calibrate TX freq and wait */
#define CC2420_STROBE_RXON (0x03) /**< switch to RX mode */
#define CC2420_STROBE_TXON (0x04) /**< switch to TX mode */
#define CC2420_STROBE_TXONCCA (0x05) /**< switch to TX after CCA*/
#define CC2420_STROBE_RFOFF (0x06) /**< switch to IDLE mode */
#define CC2420_STROBE_XOSCOFF (0x07) /**< power down */
#define CC2420_STROBE_FLUSHRX (0x08) /**< flush RX FIFO */
#define CC2420_STROBE_FLUSHTX (0x09) /**< flush TX FIFO */
#define CC2420_STROBE_ACK (0x0A) /**< send ACK with pending cleared */
#define CC2420_STROBE_ACKPEND (0x0B) /**< send ACK with pending set */
#define CC2420_STROBE_RXDEC (0x0C) /**< start RX FIFO decrypt/verify */
#define CC2420_STROBE_TXENC (0x0D) /**< start TX FIFO encrypt/auth */
#define CC2420_STROBE_AES (0x0E) /**< start AES encryption */
/** @} */
/**
* @brief CC2420 configuration registers
* @see Datasheet section 37, pages 61 to 80
* @{
*/
#define CC2420_REG_MAIN (0x10) /**< main control */
#define CC2420_REG_MDMCTRL0 (0x11) /**< modem control 0 */
#define CC2420_REG_MDMCTRL1 (0x12) /**< modem control 1 */
#define CC2420_REG_RSSI (0x13) /**< RSSI and CCA control */
#define CC2420_REG_SYNCWORD (0x14) /**< synchronization word control */
#define CC2420_REG_TXCTRL (0x15) /**< transmit control */
#define CC2420_REG_RXCTRL0 (0x16) /**< receive control 0 */
#define CC2420_REG_RXCTRL1 (0x17) /**< receive control 1 */
#define CC2420_REG_FSCTRL (0x18) /**< freq synthesizer control */
#define CC2420_REG_SECCTRL0 (0x19) /**< security control 0 */
#define CC2420_REG_SECCTRL1 (0x1A) /**< security control 1 */
#define CC2420_REG_BATTMON (0x1B) /**< battery monitor control */
#define CC2420_REG_IOCFG0 (0x1C) /**< I/O control 0 */
#define CC2420_REG_IOCFG1 (0x1D) /**< I/O control 1 */
#define CC2420_REG_MANFIDL (0x1e) /**< manufacturer ID low */
#define CC2420_REG_MANFIDH (0x1F) /**< manufacturer ID high */
#define CC2420_REG_FSMTC (0x20) /**< FSM timer constants */
#define CC2420_REG_MANAND (0x21) /**< manual signal AND override */
#define CC2420_REG_MANOR (0x22) /**< manual signal OR override */
#define CC2420_REG_AGCCTRL (0x23) /**< AGC control */
#define CC2420_REG_AGCTST0 (0x24) /**< AGC test 0 */
#define CC2420_REG_AGCTST1 (0x25) /**< AGC test 1 */
#define CC2420_REG_AGCTST2 (0x26) /**< AGC test 2 */
#define CC2420_REG_FSTST0 (0x27) /**< freq synthesizer test 0 */
#define CC2420_REG_FSTST1 (0x28) /**< freq synthesizer test 1 */
#define CC2420_REG_FSTST2 (0x29) /**< freq synthesizer test 2 */
#define CC2420_REG_FSTST3 (0x2A) /**< freq synthesizer test 3 */
#define CC2420_REG_RXBPFTST (0x2B) /**< RX bandpass filter test */
#define CC2420_REG_FSMSTATE (0x2C) /**< FSM status */
#define CC2420_REG_ADCTST (0x2D) /**< ADC test */
#define CC2420_REG_DACTST (0x2E) /**< DAC test */
#define CC2420_REG_TOPTST (0x2F) /**< top level test */
#define CC2420_REG_TXFIFO (0x3E) /**< TX FIFO byte */
#define CC2420_REG_RXFIFO (0x3F) /**< RX FIFO byte */
/** @} */
/**
* @brief CC2420 section address in RAM
* @see Datasheet section 13.5 page 31.
* @{
*/
#define CC2420_RAM_TXFIFO (0x0000)
#define CC2420_RAM_RXFIFO (0x0080)
#define CC2420_RAM_KEY0 (0x0100)
#define CC2420_RAM_RXNONCE (0x0110)
#define CC2420_RAM_RXCTR (0x0110)
#define CC2420_RAM_SABUF (0x0120)
#define CC2420_RAM_KEY1 (0x0130)
#define CC2420_RAM_TXNONCE (0x0140)
#define CC2420_RAM_TXCTR (0x0140)
#define CC2420_RAM_CBCSTATE (0x0150)
#define CC2420_RAM_IEEEADR (0x0160)
#define CC2420_RAM_PANID (0x0168)
#define CC2420_RAM_SHORTADR (0x016A)
/** @} */
/**
* @brief Status byte bit fields
* @see Datasheet section 13.3, page 29
* @{
*/
#define CC2420_STATUS_XOSC_STABLE (0x40)
#define CC2420_STATUS_TX_UNDERFLOW (0x20)
#define CC2420_STATUS_ENC_BUSY (0x10)
#define CC2420_STATUS_TX_ACTIVE (0x08)
#define CC2420_STATUS_PLL_LOCK (0x04)
#define CC2420_STATUS_RSSI_VALID (0x02)
/** @} */
/**
* @brief Modem control 0 register bitfields
* @{
*/
#define CC2420_MDMCTRL0_RES_FRM (0x2000
#define CC2420_MDMCTRL0_ADR_DECODE (0x0800)
#define CC2420_MDMCTRL0_PAN_COORD (0x1000)
#define CC2420_MDMCTRL0_AUTOCRC (0x0020)
#define CC2420_MDMCTRL0_AUTOACK (0x0010)
#define CC2420_MDMCTRL0_PREAMBLE_M (0x000f)
#define CC2420_MDMCTRL0_PREAMBLE_3B (0x0002)
/** @} */
/**
* @brief Transmit control register bitfields
* @{
*/
#define CC2420_TXCTRL_PA_MASK (0x001f)
/** @} */
/**
* @brief Receive control register 1 bitfields
* @{
*/
#define CC2420_RXCTRL1_RXBPF_LOCUR (0x2000)
/** @} */
/**
* @brief Frequency synthesizer control and status register bitfields
* @{
*/
#define CC2420_FSCTRL_LOCK_THR_MASK (0xc000)
#define CC2420_FSCTRL_CAL_DONE (0x2000)
#define CC2420_FSCTRL_CAL_RUNNING (0x1000)
#define CC2420_FSCTRL_LOCK_LENGTH (0x0800)
#define CC2420_FSCTRL_LOCK_STATUS (0x0400)
#define CC2420_FSCTRL_FREQ_MASK (0x03ff)
/** @} */
/**
* @brief Security control register 0 bitfields
* @{
*/
#define CC2420_SECCTRL0_RXFIFO_PROT (0x0200)
/** @} */
/**
* @brief Manufacturer ID low register value
*/
#define CC2420_MANFIDL_VAL (0x233d)
/**
* @brief Manufacturer ID high register value
*/
#define CC2420_MANFIDH_VAL (0x3000)
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,88 @@
/*
* Copyright (C) 2016 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_cc2420
*
* @{
* @file
* @brief Default configuration for the CC2420 driver
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*/
#ifndef CC2420_PARAMS_H
#define CC2420_PARAMS_H
#include "board.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Set default configuration parameters for the CC2420 driver
* @{
*/
#ifndef CC2420_PARAM_SPI
#define CC2420_PARAM_SPI (SPI_0)
#endif
#ifndef CC2420_PARAM_SPI_CLK
#define CC2420_PARAM_SPI_CLK (SPI_SPEED_5MHZ)
#endif
#ifndef CC2420_PARAM_CS
#define CC2420_PARAM_CS (GPIO_PIN(0, 0))
#endif
#ifndef CC2420_PARAM_FIFO
#define CC2420_PARAM_FIFO (GPIO_PIN(0, 1))
#endif
#ifndef CC2420_PARAM_FIFOP
#define CC2420_PARAM_FIFOP (GPIO_PIN(0, 2))
#endif
#ifndef CC2420_PARAM_CCA
#define CC2420_PARAM_CCA (GPIO_PIN(0, 3))
#endif
#ifndef CC2420_PARAM_SFD
#define CC2420_PARAM_SFD (GPIO_PIN(0, 3))
#endif
#ifndef CC2420_PARAM_VREFEN
#define CC2420_PARAM_VREFEN (GPIO_PIN(0, 3))
#endif
#ifndef CC2420_PARAM_RESET
#define CC2420_PARAM_RESET (GPIO_PIN(0, 3))
#endif
#define CC2420_PARAMS_DEFAULT {.spi = CC2420_PARAM_SPI, \
.spi_clk = CC2420_PARAM_SPI_CLK, \
.pin_cs = CC2420_PARAM_CS, \
.pin_fifo = CC2420_PARAM_FIFO, \
.pin_fifop = CC2420_PARAM_FIFOP, \
.pin_cca = CC2420_PARAM_CCA, \
.pin_sfd = CC2420_PARAM_SFD, \
.pin_vrefen = CC2420_PARAM_VREFEN, \
.pin_reset = CC2420_PARAM_RESET}
/**@}*/
/**
* @brief CC2420 configuration
*/
static const cc2420_params_t cc2420_params[] =
{
#ifdef CC2420_PARAMS_BOARD
CC2420_PARAMS_BOARD,
#else
CC2420_PARAMS_DEFAULT,
#endif
};
#ifdef __cplusplus
}
#endif
#endif /* CC2420_PARAMS_H */
/** @} */

311
drivers/include/cc2420.h Normal file
View File

@ -0,0 +1,311 @@
/*
* Copyright (C) 2015-2016 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup drivers_cc2420 CC2420 driver
* @ingroup drivers
* @brief Implementation of the CC2420 radio driver
* @{
*
* @file
* @brief Interface definition for the CC2420 driver
*
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*/
#ifndef CC2420_H
#define CC2420_H
#include <stdint.h>
#include "periph/spi.h"
#include "periph/gpio.h"
#include "net/netdev2.h"
#include "net/netdev2/ieee802154.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Maximum possible packet size in byte
*/
#define CC2420_PKT_MAXLEN (127U)
/**
* @brief Default addresses used if the CPUID module is not present
*
* In case this address is used, that short address will be created by using the
* last two bytes of the long address.
* @{
*/
#define CC2420_ADDR_FALLBACK {0x12, 0x22, 0x33, 0x44, 0x55, 0x66, 0x08, 0x15}
/** @} */
/**
* @brief PAN ID configuration
*/
#define CC2420_PANID_DEFAULT (0x0023)
/**
* @brief Channel configuration
* @{
*/
#define CC2420_CHAN_MIN (11U)
#define CC2420_CHAN_MAX (26U)
#define CC2420_CHAN_DEFAULT (26U)
/** @} */
/**
* @brief Default TX power configuration [in dBm]
* @{
*/
#define CC2420_TXPOWER_MIN (-25)
#define CC2420_TXPOWER_MAX (0)
#define CC2420_TXPOWER_DEFAULT (0)
/** @} */
/**
* @brief A couple of return values used in this driver
*/
enum {
CC2420_RET_CHAN_OK = 2,
};
/**
* @brief Struct holding all parameters needed for device initialization
*/
typedef struct cc2420_params {
spi_t spi; /**< SPI bus the device is connected to */
spi_speed_t spi_clk; /**< SPI speed to use */
gpio_t pin_cs; /**< pin connected to chip select */
gpio_t pin_fifo; /**< pin connected to the FIFO interrupt pin */
gpio_t pin_fifop; /**< pin connected to the FIFOP interrupt pin */
gpio_t pin_cca; /**< pin connected to CCA */
gpio_t pin_sfd; /**< pin connected to 'start of frame delimiter' */
gpio_t pin_vrefen; /**< pin connected to the Vref enable pin */
gpio_t pin_reset; /**< pin connected to the reset pin */
} cc2420_params_t;
/**
* @brief Device descriptor for CC2420 radio devices
*/
typedef struct {
/* netdev fields */
netdev2_ieee802154_t netdev;
/* device specific fields */
cc2420_params_t params; /**< hardware interface configuration */
/* device state fields */
uint8_t state; /**< current state of the radio */
uint16_t options; /**< state of used options */
} cc2420_t;
/**
* @brief Setup the device descriptor for the given device
*
* @param[out] dev device descriptor
* @param[in] params device parameters
*
* @return 0 on success
* @return -1 on error
*/
void cc2420_setup(cc2420_t *dev, const cc2420_params_t *params);
/**
* @brief Initialize a given CC2420 device
*
* @param[out] dev device descriptor
*
* @return 0 on success
* @return <0 on error
*/
int cc2420_init(cc2420_t *dev);
/**
* @brief Trigger a hardware reset and configure radio with default values
*
* @param[in] dev device to reset
*
* @return TODO
*/
int cc2420_reset(cc2420_t *dev);
/**
* @brief Trigger a clear channel assessment
*
* @param[in] dev device to use
*
* @return true if channel is clear
* @return false if channel is busy
*/
bool cc2420_cca(cc2420_t *dev);
/**
* @brief Get the short address of the given device
*
* @param[in] dev device to read from
* @param[out] addr memory to write the 2 byte address into
*/
void cc2420_get_addr_short(cc2420_t *dev, uint8_t *addr);
/**
* @brief Set the short address of the given device
*
* @param[in] dev device to write to
* @param[in] addr (2-byte) short address to set
*/
void cc2420_set_addr_short(cc2420_t *dev, uint8_t *addr);
/**
* @brief Get the configured long address of the given device
*
* @param[in] dev device to read from
*
* @return the currently set (8-byte) long address
*/
void cc2420_get_addr_long(cc2420_t *dev, uint8_t *addr_long);
/**
* @brief Set the long address of the given device
*
* @param[in] dev device to write to
* @param[in] addr (8-byte) long address to set
*/
void cc2420_set_addr_long(cc2420_t *dev, uint8_t *addr_long);
/**
* @brief Get the configured PAN ID of the given device
*
* @param[in] dev device to read from
*
* @return the currently set PAN ID
*/
uint16_t cc2420_get_pan(cc2420_t *dev);
/**
* @brief Set the PAN ID of the given device
*
* @param[in] dev device to write to
* @param[in] pan PAN ID to set
*/
void cc2420_set_pan(cc2420_t *dev, uint16_t pan);
/**
* @brief Get the configured channel of the given device
*
* @param[in] dev device to read from
*
* @return the currently set channel
*/
uint16_t cc2420_get_chan(cc2420_t *dev);
/**
* @brief Set the channel of the given device
*
* @param[in] dev device to write to
* @param[in] chan channel to set
*/
int cc2420_set_chan(cc2420_t *dev, uint16_t chan);
/**
* @brief Get the configured transmission power of the given device [in dBm]
*
* @param[in] dev device to read from
*
* @return configured transmission power in dBm
*/
int16_t cc2420_get_txpower(cc2420_t *dev);
/**
* @brief Set the transmission power of the given device [in dBm]
*
* If the device does not support the exact dBm value given, it will set a value
* as close as possible to the given value. If the given value is larger or
* lower then the maximal or minimal possible value, the min or max value is
* set, respectively.
*
* @param[in] dev device to write to
* @param[in] txpower transmission power in dBm
*/
void cc2420_set_txpower(cc2420_t *dev, int16_t txpower);
/**
* @brief Enable or disable driver specific options
*
* @param[in] dev device to set/clear option flag for
* @param[in] option option to enable/disable
* @param[in] state true for enable, false for disable
*/
int cc2420_set_option(cc2420_t *dev, uint16_t option, bool state);
/**
* @brief Set the state of the given device (trigger a state change)
*
* @param[in] dev device to change state of
* @param[in] state the targeted new state
*/
int cc2420_set_state(cc2420_t *dev, netopt_state_t state);
/**
* @brief Get the state of the given device
*
* @param[in] dev device to change state of
*
* @return the device's current state
*/
netopt_state_t cc2420_get_state(cc2420_t *dev);
/**
* @brief Convenience function for simply sending data
*
* @note This function ignores the PRELOADING option
*
* @param[in] dev device to use for sending
* @param[in] data data to send (must include IEEE802.15.4 header)
* @param[in] len length of @p data
*
* @return number of bytes that were actually send
* @return 0 on error
*/
size_t cc2420_send(cc2420_t *dev, const struct iovec *data, int count);
/**
* @brief Prepare for sending of data
*
* This function puts the given device into the TX state, so no receiving of
* data is possible after it was called.
*
* @param[in] dev device to prepare for sending
*/
size_t cc2420_tx_prepare(cc2420_t *dev, const struct iovec *data, int count);
/**
* @brief Trigger sending of data previously loaded into transmit buffer
*
* @param[in] dev device to trigger
*/
void cc2420_tx_exec(cc2420_t *dev);
/**
* @brief Read a chunk of data from the receive buffer of the given device
*
* @param[in] dev device to read from
* @param[out] data buffer to write data to
* @param[in] len number of bytes to read from device
* @param[in] offset offset in the receive buffer
*/
int cc2420_rx(cc2420_t *dev, uint8_t *buf, size_t max_len, void *info);
#ifdef __cplusplus
}
#endif
#endif /* CC2420_H */
/** @} */