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

remove bulk of legacy network stack and drivers

This commit is contained in:
Kaspar Schleiser 2015-08-06 12:12:47 +02:00
parent 044d3c704e
commit 5d8349298f
230 changed files with 11 additions and 45817 deletions

View File

@ -1,53 +1,3 @@
ifneq (,$(filter libcoap,$(USEPKG)))
USEMODULE += pnet
endif
ifneq (,$(filter pnet,$(USEMODULE)))
USEMODULE += posix
USEMODULE += socket_base
USEMODULE += net_help
endif
ifneq (,$(filter transport_layer,$(USEMODULE)))
USEMODULE += tcp
USEMODULE += udp
endif
ifneq (,$(filter udp,$(USEMODULE)))
USEMODULE += socket_base
endif
ifneq (,$(filter tcp,$(USEMODULE)))
USEMODULE += socket_base
endif
ifneq (,$(filter socket_base,$(USEMODULE)))
USEMODULE += sixlowpan
USEMODULE += net_help
USEMODULE += vtimer
endif
ifneq (,$(filter sixlowborder,$(USEMODULE)))
USEMODULE += sixlowpan
endif
ifneq (,$(filter rpl,$(USEMODULE)))
USEMODULE += trickle
USEMODULE += routing
endif
ifneq (,$(filter routing,$(USEMODULE)))
USEMODULE += sixlowpan
endif
ifneq (,$(filter sixlowpan,$(USEMODULE)))
USEMODULE += ieee802154
USEMODULE += net_help
USEMODULE += net_if
USEMODULE += posix
USEMODULE += vtimer
endif
ifneq (,$(filter ng_netif_default,$(USEMODULE)))
USEMODULE += ng_netif
endif
@ -232,14 +182,6 @@ ifneq (,$(filter ng_slip,$(USEMODULE)))
USEMODULE += ng_netbase
endif
ifneq (,$(filter aodvv2,$(USEMODULE)))
USEMODULE += vtimer
USEMODULE += sixlowpan
USEMODULE += oonf_common
USEMODULE += oonf_rfc5444
USEMODULE += fib
endif
ifneq (,$(filter uart0,$(USEMODULE)))
USEMODULE += posix
endif
@ -253,29 +195,6 @@ ifneq (,$(filter cbor,$(USEMODULE)))
USEMODULE += net_help
endif
ifneq (,$(filter cc110x%,$(USEMODULE)))
USEMODULE += protocol_multiplex
USEMODULE += vtimer
endif
ifneq (,$(filter cc110x,$(USEMODULE)))
USEMODULE += transceiver
endif
ifneq (,$(filter cc110x_legacy,$(USEMODULE)))
USEMODULE += transceiver
endif
ifneq (,$(filter cc2420,$(USEMODULE)))
USEMODULE += transceiver
USEMODULE += ieee802154
endif
ifneq (,$(filter at86rf231,$(USEMODULE)))
USEMODULE += netdev_802154
USEMODULE += ieee802154
endif
ifneq (,$(filter l2_ping,$(USEMODULE)))
USEMODULE += vtimer
endif
@ -284,20 +203,10 @@ ifneq (,$(filter vtimer,$(USEMODULE)))
USEMODULE += timex
endif
ifneq (,$(filter net_if,$(USEMODULE)))
USEMODULE += transceiver
USEMODULE += net_help
USEMODULE += hashes
endif
ifneq (,$(filter ccn_lite,$(USEMODULE)))
USEMODULE += crypto
endif
ifneq (,$(filter netdev_802154,$(USEMODULE)))
USEMODULE += netdev_base
endif
ifneq (,$(filter rgbled,$(USEMODULE)))
USEMODULE += color
endif
@ -306,10 +215,6 @@ ifneq (,$(filter libfixmath-unittests,$(USEMODULE)))
USEPKG += libfixmath
endif
ifneq (,$(filter defaulttransceiver,$(USEMODULE)))
FEATURES_REQUIRED += transceiver
endif
ifneq (,$(filter nhdp,$(USEMODULE)))
USEMODULE += vtimer
USEMODULE += oonf_common
@ -343,6 +248,10 @@ ifneq (,$(filter newlib,$(USEMODULE)))
USEMODULE += uart_stdio
endif
ifneq (,$(filter ng_netdev_eth,$(USEMODULE)))
USEMODULE += ng_pktbuf
endif
ifneq (,$(filter hih6130,$(USEMODULE)))
USEMODULE += vtimer
endif

View File

@ -1,5 +1,4 @@
PSEUDOMODULES += defaulttransceiver
PSEUDOMODULES += transport_layer
PSEUDOMODULES += ng_netif_default
PSEUDOMODULES += ng_ieee802154
PSEUDOMODULES += ng_ipv6_default

View File

@ -1,8 +1,6 @@
ifneq (,$(filter defaulttransceiver,$(USEMODULE)))
USEMODULE += nativenet
ifeq (,$(filter netdev_base,$(USEMODULE)))
USEMODULE += transceiver
endif
USEMODULE += ng_nativenet
USEMODULE += ng_netdev_eth
endif
ifneq (,$(filter ng_netif_default,$(USEMODULE)))

View File

@ -22,10 +22,6 @@
#include "config.h"
#ifdef MODULE_NATIVENET
#include "nativenet.h"
#include "nativenet_internal.h"
#endif
#include "native_internal.h"
#define ENABLE_DEBUG (0)
@ -40,10 +36,6 @@ void config_load(void)
sysconfig.id = _native_id;
#ifdef MODULE_NATIVENET
_nativenet_default_dev_more._radio_addr = _native_id;
#endif
return;
}

View File

@ -1,9 +1,7 @@
MODULE = cpu
DIRS += periph
ifneq (,$(filter nativenet,$(USEMODULE)))
DIRS += net
endif
ifneq (,$(filter ng_nativenet,$(USEMODULE)))
DIRS += ng_net
endif

View File

@ -1,182 +0,0 @@
/*
* nativenet transceiver interface
*
* A configurable transceiver for the native port.
*
* At the moment only the tap interface is supported, but more network
* layers are intended. So the "configurable" part is a lie for now ;-)
* The effect of calls like nativenet_set_channel depend on the
* network layer.
*
* Copyright (C) 2013, 2014 Ludwig Ortmann <ludwig.ortmann@fu-berlin.de>
*
* 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 native_net Native network interface
* @ingroup native_cpu
* @{
* @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de>
*/
#ifndef NATIVENET_H
#define NATIVENET_H
#if defined(__FreeBSD__)
#include <sys/types.h>
#endif
#include <net/ethernet.h>
#include "radio/types.h"
#include "kernel_types.h"
#include "netdev/base.h"
#ifndef RX_BUF_SIZE
#define RX_BUF_SIZE (10)
#endif
#ifndef TRANSCEIVER_BUFFER_SIZE
#define TRANSCEIVER_BUFFER_SIZE (10)
#endif
/**
* @brief Number of registrable netdev_rcv_data_cb_t callbacks per nativenet
* device
*/
#define NATIVENET_DEV_CB_MAX (128)
/**
* @brief Broadcast address
*/
#define NATIVE_BROADCAST_ADDRESS (0)
#ifndef NATIVE_MAX_DATA_LENGTH
#include "tap.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef MODULE_SIXLOWPAN
#define NATIVE_MAX_DATA_LENGTH (127)
#else
#define NATIVE_MAX_DATA_LENGTH (TAP_MAX_DATA)
#endif
#else
#warning be careful not to exceed (TAP_MAX_DATA) with NATIVE_MAX_DATA_LENGTH
#endif /* NATIVE_MAX_DATA_LENGTH */
/**
* @brief Implementation of netdev_driver_t for nativenet
*/
extern const netdev_driver_t nativenet_driver;
/**
* @brief Default @ref netdev API device
*/
extern netdev_t nativenet_default_dev;
/**
* Initialize @ref sys_transceiver and @ref nativenet_default_dev
*
* @param transceiver_pid the pid of the transceiver thread
*/
void nativenet_init(kernel_pid_t transceiver_pid);
/**
* Shutdown transceiver
*/
void nativenet_powerdown(void);
/**
* Enable/disable monitor mode
*
* @param mode 0 off, 1 on
*/
void nativenet_set_monitor(uint8_t mode);
/**
* Send a packet
*
* @param packet a radio packet
* @return -1 if the operation failed, the number of transmitted bytes
* up to INT8_MAX otherwise
*/
int8_t nativenet_send(radio_packet_t *packet);
/**
* Set transceiver address
*
* @param address the address
* @return the address
*/
radio_address_t nativenet_set_address(radio_address_t address);
/**
* Get transceiver address
*
* @return the address
*/
radio_address_t nativenet_get_address(void);
/**
* @brief Sets the IEEE long address of the nativenet transceiver.
*
* @param[in] addr The desired address.
*
* @return The set address after calling.
*/
uint64_t nativenet_set_address_long(uint64_t addr);
/**
* @brief Gets the current IEEE long address of the nativenet
* transceiver.
*
* @return The current IEEE long address.
*/
uint64_t nativenet_get_address_long(void);
/**
* Set transceiver channel
*
* @param channel the channel
* @return the channel
*/
int16_t nativenet_set_channel(uint8_t channel);
/**
* Get transceiver channel
*
* @return the channel
*/
int16_t nativenet_get_channel(void);
/**
* Set transceiver pan
*
* @param pan the pan
* @return the pan
*/
uint16_t nativenet_set_pan(uint16_t pan);
/**
* Get transceiver pan
*
* @return the pan
*/
uint16_t nativenet_get_pan(void);
/**
* Enable transceiver rx mode
*/
void nativenet_switch_to_rx(void);
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* NATIVENET_H */

View File

@ -1,109 +0,0 @@
/**
* internal nativenet transceiver interface
*
* Copyright (C) 2013 Ludwig Ortmann <ludwig.ortmann@fu-berlin.de>
*
* 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.
*/
/**
* @{
* @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de>
* @}
*/
#ifndef NATIVENET_INTERNAL_H
#define NATIVENET_INTERNAL_H
#include "tap.h"
#ifdef __cplusplus
extern "C" {
#endif
#define NNEV_PWRDWN 0x01
#define NNEV_PWRUP 0x02
#define NNEV_MONITOR 0x03
#define NNEV_GETCHAN 0x04
#define NNEV_SETCHAN 0x05
#define NNEV_GETADDR 0x06
#define NNEV_SETADDR 0x07
#define NNEV_GETPAN 0x08
#define NNEV_SETPAN 0x09
#define NNEV_SEND 0x0a
#define NNEV_SWTRX 0x0b
#define NNEV_MAXEV 0x0b
#define _NATIVENET_DEV_MORE(dev) ((_nativenet_netdev_more_t *)dev->more)
struct rx_buffer_s {
radio_packet_t packet;
char data[NATIVE_MAX_DATA_LENGTH];
};
extern struct rx_buffer_s _nativenet_rx_buffer[RX_BUF_SIZE];
/**
* @brief Definition of network device data.
*/
typedef struct {
/**
* @brief The channel assigned to this device
*
* @note For internal use only, do not change externally!
*
* @internal
*/
uint8_t _channel;
/**
* @brief The PAN ID assigned to this device
*
* @note For internal use only, do not change externally!
* @internal
*/
uint16_t _pan_id;
/**
* @brief The short address assigned to this device
*
* @note For internal use only, do not change externally!
* @internal
*/
radio_address_t _radio_addr;
/**
* @brief The long address assigned to this device
*
* @note For internal use only, do not change externally!
* @internal
*/
uint64_t _long_addr;
/**
* @brief Flag to determine if device is in promiscuous mode
*
* @note For internal use only, do not change externally!
* @internal
*/
uint8_t _is_monitoring;
/**
* @brief Receive data callbacks for this device
*/
netdev_rcv_data_cb_t _callbacks[NATIVENET_DEV_CB_MAX];
} _nativenet_netdev_more_t;
/* internal counterpart to nativenet_default_dev */
extern _nativenet_netdev_more_t _nativenet_default_dev_more;
void _nativenet_handle_packet(radio_packet_t *packet);
int8_t send_buf(radio_packet_t *packet);
#ifdef __cplusplus
}
#endif
#endif /* NATIVENET_INTERNAL_H */

View File

@ -1,70 +0,0 @@
/**
* internal nativenet tap network layer interface
*
* Copyright (C) 2013 Ludwig Ortmann <ludwig.ortmann@fu-berlin.de>
*
* 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.
*/
/**
* @{
* @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de>
* @}
*/
#ifndef _TAP_H
#define _TAP_H
#include <net/ethernet.h>
#include "board.h"
#include "radio/types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* create and/or open tap device "name"
*
* if "name" is an empty string, the kernel chooses a name
* if "name" is an existing device, that device is used
* otherwise a device named "name" is created
*
* On OSX a name has to be provided.
*/
int tap_init(char *name);
/**
* Close tap device
*/
void tap_cleanup(void);
extern unsigned char _native_tap_mac[ETHER_ADDR_LEN];
struct nativenet_header {
radio_packet_length_t length;
radio_address_t dst;
radio_address_t src;
} __attribute__((packed));
#define TAP_MAX_DATA ((ETHERMTU) - 6) /* XXX: this is suboptimal */
struct nativenet_packet {
struct nativenet_header nn_header;
uint8_t data[ETHERMTU - sizeof(struct nativenet_header)];
} __attribute__((packed));
union eth_frame {
struct {
struct ether_header header;
struct nativenet_packet payload;
} field;
unsigned char buffer[ETHER_MAX_LEN];
} __attribute__((packed));
#ifdef __cplusplus
}
#endif
#endif /* _TAP_H */

View File

@ -48,9 +48,7 @@
#include "cpu.h"
#include "cpu_conf.h"
#ifdef MODULE_NATIVENET
#include "tap.h"
#endif
#ifdef MODULE_NG_NATIVENET
#include "dev_eth_tap.h"
extern dev_eth_tap_t dev_eth_tap;
@ -76,9 +74,7 @@ int reboot_arch(int mode)
#ifdef MODULE_UART0
/* TODO: close stdio fds */
#endif
#ifdef MODULE_NATIVENET
tap_cleanup();
#endif
#ifdef MODULE_NG_NATIVENET
dev_eth_tap_cleanup(&dev_eth_tap);
#endif

View File

@ -1,5 +0,0 @@
MODULE = nativenet
include $(RIOTBASE)/Makefile.base
INCLUDES = $(NATIVEINCLUDES)

View File

@ -1,618 +0,0 @@
/**
* nativenet.h implementation
*
* Copyright (C) 2013 Ludwig Ortmann <ludwig.ortmann@fu-berlin.de>
*
* 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 native_cpu
* @ingroup net
* @{
* @file
* @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de>
*/
#include <stdio.h>
#include <err.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <inttypes.h>
#include <arpa/inet.h>
#define ENABLE_DEBUG (0)
#include "debug.h"
#include "transceiver.h"
#include "msg.h"
#include "native_internal.h"
#include "tap.h"
#include "nativenet.h"
#include "nativenet_internal.h"
#include "cpu.h"
static _native_callback_t _nativenet_callbacks[255];
struct rx_buffer_s _nativenet_rx_buffer[RX_BUF_SIZE];
static volatile uint8_t rx_buffer_next;
static kernel_pid_t _native_net_tpid = KERNEL_PID_UNDEF;
/************************************************************************/
/* nativenet.h **********************************************************/
/************************************************************************/
int _nativenet_init(netdev_t *dev)
{
if ((dev->type != NETDEV_TYPE_BASE) || (dev->more == NULL)) {
return -ENODEV;
}
_NATIVENET_DEV_MORE(dev)->_channel = 0;
_NATIVENET_DEV_MORE(dev)->_pan_id = 0;
_NATIVENET_DEV_MORE(dev)->_is_monitoring = 0;
memset(_NATIVENET_DEV_MORE(dev)->_callbacks, 0,
sizeof((_NATIVENET_DEV_MORE(dev)->_callbacks)));
return 0;
}
void nativenet_init(kernel_pid_t transceiver_pid)
{
DEBUG("nativenet_init(transceiver_pid=%" PRIkernel_pid ")\n", transceiver_pid);
rx_buffer_next = 0;
_nativenet_init((netdev_t *)(&nativenet_default_dev));
_native_net_tpid = transceiver_pid;
}
void nativenet_powerdown(void)
{
return;
}
void nativenet_set_monitor(uint8_t mode)
{
DEBUG("nativenet_set_monitor(mode=%d)\n", mode);
_nativenet_default_dev_more._is_monitoring = mode;
}
int16_t nativenet_set_channel(uint8_t channel)
{
_nativenet_default_dev_more._channel = channel;
return _nativenet_default_dev_more._channel;
}
int16_t nativenet_get_channel(void)
{
return _nativenet_default_dev_more._channel;
}
uint16_t nativenet_set_pan(uint16_t pan)
{
_nativenet_default_dev_more._pan_id = pan;
return _nativenet_default_dev_more._pan_id;
}
uint16_t nativenet_get_pan(void)
{
return _nativenet_default_dev_more._pan_id;
}
radio_address_t nativenet_set_address(radio_address_t address)
{
DEBUG("nativenet_set_address(address=%d)\n", address);
_nativenet_default_dev_more._radio_addr = address;
return _nativenet_default_dev_more._radio_addr;
}
radio_address_t nativenet_get_address(void)
{
DEBUG("nativenet_get_address -> address = %d\n",
_nativenet_default_dev_more._radio_addr);
return _nativenet_default_dev_more._radio_addr;
}
uint64_t nativenet_get_address_long(void)
{
DEBUG("nativenet_get_address_long -> address = %" PRIx64 "\n",
_nativenet_default_dev_more._long_addr);
return _nativenet_default_dev_more._long_addr;
}
uint64_t nativenet_set_address_long(uint64_t address)
{
DEBUG("nativenet_set_address_long(address=%" PRIx64 ")\n", address);
warnx("nativenet_set_address_long: this does not actually change the interfaces address");
_nativenet_default_dev_more._long_addr = address;
return _nativenet_default_dev_more._long_addr;
}
int8_t nativenet_send(radio_packet_t *packet)
{
packet->src = _nativenet_default_dev_more._radio_addr;
DEBUG("nativenet_send: Sending packet of length %" PRIu16 " from %" PRIu16 " to %" PRIu16 "\n",
packet->length, packet->src, packet->dst);
return send_buf(packet);
}
void nativenet_switch_to_rx(void)
{
return;
}
/************************************************************************/
/* nativenet_internal.h *************************************************/
/************************************************************************/
int _nativenet_register_cb(int event, _native_callback_t func)
{
if (event > NNEV_MAXEV) {
DEBUG("_nativenet_register_cb: event > NNEV_MAXEV\n");
return -1;
}
_nativenet_callbacks[event] = func;
return 0;
}
int _nativenet_unregister_cb(int event)
{
if (event > NNEV_MAXEV) {
DEBUG("_nativenet_unregister_cb: event > NNEV_MAXEV\n");
return -1;
}
_nativenet_callbacks[event] = NULL;
return 0;
}
void do_cb(int event)
{
if (event > NNEV_MAXEV) {
DEBUG("do_cb: event > NNEV_MAXEV\n");
return;
}
if (_nativenet_callbacks[event] != NULL) {
_nativenet_callbacks[event]();
}
}
void _nativenet_handle_packet(radio_packet_t *packet)
{
radio_address_t dst_addr = packet->dst;
int notified = 0;
/* TODO: find way to demultiplex reception from several taps and map them
* to devices. */
netdev_t *dev = &nativenet_default_dev;
/* address filter / monitor mode */
if (_nativenet_default_dev_more._is_monitoring == 1) {
DEBUG("_nativenet_handle_packet: monitoring, not filtering address \n");
}
else {
/* own addr check */
if (dst_addr == _nativenet_default_dev_more._radio_addr) {
DEBUG("_nativenet_handle_packet: accept packet, addressed to us\n");
}
else if (dst_addr == NATIVE_BROADCAST_ADDRESS) {
DEBUG("_nativenet_handle_packet: accept packet, broadcast\n");
}
else {
DEBUG("_nativenet_handle_packet: discard packet addressed to someone else\n");
return;
}
}
/* copy packet to rx buffer */
DEBUG("\n\t\trx_buffer_next: %i\n\n", rx_buffer_next);
memcpy(&_nativenet_rx_buffer[rx_buffer_next].data, packet->data, packet->length);
memcpy(&_nativenet_rx_buffer[rx_buffer_next].packet, packet, sizeof(radio_packet_t));
_nativenet_rx_buffer[rx_buffer_next].packet.data = (uint8_t *)
&_nativenet_rx_buffer[rx_buffer_next].data;
/* notify transceiver thread if any */
if (_native_net_tpid != KERNEL_PID_UNDEF) {
DEBUG("_nativenet_handle_packet: notifying transceiver thread!\n");
msg_t m;
m.type = (uint16_t) RCV_PKT_NATIVE;
m.content.value = rx_buffer_next;
msg_send_int(&m, _native_net_tpid);
notified = 1;
}
for (int i = 0; i < NATIVENET_DEV_CB_MAX; i++) {
if (_NATIVENET_DEV_MORE(dev)->_callbacks[i]) {
_NATIVENET_DEV_MORE(dev)->_callbacks[i]((netdev_t *)dev,
&(_nativenet_rx_buffer[rx_buffer_next].packet.src),
sizeof(uint16_t),
&(_nativenet_rx_buffer[rx_buffer_next].packet.dst),
sizeof(uint16_t),
&(_nativenet_rx_buffer[rx_buffer_next].data),
(size_t)_nativenet_rx_buffer[rx_buffer_next].packet.length);
notified = 1;
}
}
if (!notified) {
DEBUG("_nativenet_handle_packet: no one to notify =(\n");
}
/* shift to next buffer element */
if (++rx_buffer_next == RX_BUF_SIZE) {
rx_buffer_next = 0;
}
}
/***************************************************************
* netdev_base wrapper
***************************************************************/
#ifdef MODULE_NETDEV_BASE
int _nativenet_send_data(netdev_t *dev, void *dest, size_t dest_len,
netdev_hlist_t *upper_layer_hdrs, void *data,
size_t data_len)
{
netdev_hlist_t *ptr = upper_layer_hdrs;
uint8_t tx_buffer[data_len + netdev_get_hlist_len(upper_layer_hdrs)];
size_t tx_ptr = 0;
radio_packet_t pkt = {0, 0, 0, 0, 0, {0, 0}, sizeof(tx_buffer), tx_buffer};
if (dev->type != NETDEV_TYPE_BASE) {
return -ENODEV;
}
if (dest_len > sizeof(uint16_t)) {
return -EAFNOSUPPORT;
}
if (sizeof(tx_buffer) > NATIVE_MAX_DATA_LENGTH) {
return -EMSGSIZE;
}
if (upper_layer_hdrs) {
do {
memcpy(&(tx_buffer[tx_ptr]), ptr->header, ptr->header_len);
tx_ptr += ptr->header_len;
netdev_hlist_advance(&ptr);
} while (ptr != upper_layer_hdrs);
}
memcpy(&(tx_buffer[tx_ptr]), data, data_len);
if (dest_len == sizeof(uint16_t)) {
pkt.dst = *((uint16_t *)dest);
}
else {
pkt.dst = (uint16_t)(*((uint8_t *)dest));
}
return nativenet_send(&pkt);
}
int _nativenet_add_rcv_data_cb(netdev_t *dev, netdev_rcv_data_cb_t cb)
{
int i = 0;
if (dev->type != NETDEV_TYPE_BASE) {
return -ENODEV;
}
for (i = 0; i < NATIVENET_DEV_CB_MAX; i++) {
if (_NATIVENET_DEV_MORE(dev)->_callbacks[i] == NULL ||
_NATIVENET_DEV_MORE(dev)->_callbacks[i] == cb) {
break;
}
}
if (i >= NATIVENET_DEV_CB_MAX) {
return -ENOBUFS;
}
_NATIVENET_DEV_MORE(dev)->_callbacks[i] = cb;
return 0;
}
int _nativenet_rem_rcv_data_cb(netdev_t *dev, netdev_rcv_data_cb_t cb)
{
int i = 0;
if (dev->type != NETDEV_TYPE_BASE) {
return -ENODEV;
}
for (i = 0; i < NATIVENET_DEV_CB_MAX; i++) {
if (_NATIVENET_DEV_MORE(dev)->_callbacks[i] == cb) {
_NATIVENET_DEV_MORE(dev)->_callbacks[i] = NULL;
}
}
return 0;
}
int _nativenet_get_option(netdev_t *dev, netdev_opt_t opt, void *value,
size_t *value_len)
{
if (dev->type != NETDEV_TYPE_BASE) {
return -ENODEV;
}
switch (opt) {
case NETDEV_OPT_CHANNEL:
if (*value_len == 0) {
return -EOVERFLOW;
}
if (*value_len > sizeof(uint8_t)) {
*value_len = sizeof(uint8_t);
}
*((uint8_t *)value) = _NATIVENET_DEV_MORE(dev)->_channel;
break;
case NETDEV_OPT_ADDRESS:
if (*value_len < sizeof(radio_address_t)) {
return -EOVERFLOW;
}
if (*value_len > sizeof(radio_address_t)) {
*value_len = sizeof(radio_address_t);
}
*((radio_address_t *)value) = _NATIVENET_DEV_MORE(dev)->_radio_addr;
break;
case NETDEV_OPT_NID:
if (*value_len < sizeof(uint16_t)) {
return -EOVERFLOW;
}
if (*value_len > sizeof(uint16_t)) {
*value_len = sizeof(uint16_t);
}
*((uint16_t *)value) = _NATIVENET_DEV_MORE(dev)->_pan_id;
break;
case NETDEV_OPT_ADDRESS_LONG:
if (*value_len < sizeof(uint64_t)) {
return -EOVERFLOW;
}
if (*value_len > sizeof(uint64_t)) {
*value_len = sizeof(uint64_t);
}
*((uint64_t *)value) = _NATIVENET_DEV_MORE(dev)->_long_addr;
break;
case NETDEV_OPT_MAX_PACKET_SIZE:
if (*value_len < sizeof(NATIVE_MAX_DATA_LENGTH)) {
return -EOVERFLOW;
}
if (*value_len > sizeof(NATIVE_MAX_DATA_LENGTH)) {
*value_len = sizeof(NATIVE_MAX_DATA_LENGTH);
}
*((netdev_proto_t *)value) = NATIVE_MAX_DATA_LENGTH;
break;
case NETDEV_OPT_PROTO:
if (*value_len < sizeof(netdev_proto_t)) {
return -EOVERFLOW;
}
if (*value_len > sizeof(netdev_proto_t)) {
*value_len = sizeof(netdev_proto_t);
}
*((netdev_proto_t *)value) = NETDEV_PROTO_RADIO;
break;
default:
return -ENOTSUP;
}
return 0;
}
static int _type_pun_up(void *value_out, size_t desired_len,
void *value_in, size_t given_len)
{
if (given_len > desired_len) {
return -EOVERFLOW;
}
/* XXX this is ugly, but bear with me */
switch (given_len) {
case 8:
switch (desired_len) {
case 8:
*((uint64_t *)value_out) = (*((uint64_t *)value_in));
return 0;
default:
return -EINVAL;
}
case 4:
switch (desired_len) {
case 8:
*((uint64_t *)value_out) = (uint64_t)(*((uint32_t *)value_in));
return 0;
case 4:
*((uint32_t *)value_out) = (*((uint32_t *)value_in));
return 0;
default:
return -EINVAL;
}
case 2:
switch (desired_len) {
case 8:
*((uint64_t *)value_out) = (uint64_t)(*((uint16_t *)value_in));
return 0;
case 4:
*((uint32_t *)value_out) = (uint32_t)(*((uint16_t *)value_in));
return 0;
case 2:
*((uint16_t *)value_out) = (*((uint16_t *)value_in));
return 0;
default:
return -EINVAL;
}
case 1:
switch (desired_len) {
case 8:
*((uint64_t *)value_out) = (uint64_t)(*((uint8_t *)value_in));
return 0;
case 4:
*((uint32_t *)value_out) = (uint32_t)(*((uint8_t *)value_in));
return 0;
case 2:
*((uint16_t *)value_out) = (uint16_t)(*((uint8_t *)value_in));
return 0;
case 1:
*((uint8_t *)value_out) = (*((uint8_t *)value_in));
return 0;
default:
return -EINVAL;
}
default:
return -EINVAL;
}
}
int _nativenet_set_option(netdev_t *dev, netdev_opt_t opt, void *value,
size_t value_len)
{
uint8_t set_value[sizeof(uint64_t)];
int res = 0;
if (dev->type != NETDEV_TYPE_BASE) {
return -ENODEV;
}
switch (opt) {
case NETDEV_OPT_CHANNEL:
if ((res = _type_pun_up(set_value, sizeof(uint8_t),
value, value_len)) == 0) {
_NATIVENET_DEV_MORE(dev)->_channel = *((uint8_t *)set_value);
}
break;
case NETDEV_OPT_ADDRESS:
if ((res = _type_pun_up(set_value, sizeof(radio_address_t),
value, value_len)) == 0) {
_NATIVENET_DEV_MORE(dev)->_radio_addr = *((radio_address_t *)set_value);
}
break;
case NETDEV_OPT_NID:
if ((res = _type_pun_up(set_value, sizeof(uint16_t),
value, value_len)) == 0) {
_NATIVENET_DEV_MORE(dev)->_pan_id = *((uint16_t *)set_value);
}
break;
case NETDEV_OPT_PROTO:
/* TODO: wouldn't this be awesome */
return -ENOTSUP;
default:
return -ENOTSUP;
}
return res;
}
int _nativenet_get_state(netdev_t *dev, netdev_state_t *state)
{
if (dev->type != NETDEV_TYPE_BASE) {
return -ENODEV;
}
if (_NATIVENET_DEV_MORE(dev)->_is_monitoring) {
*state = NETDEV_STATE_PROMISCUOUS_MODE;
}
else {
*state = NETDEV_STATE_RX_MODE;
}
return 0;
}
int _nativenet_set_state(netdev_t *dev, netdev_state_t state)
{
if (state != NETDEV_STATE_PROMISCUOUS_MODE && _NATIVENET_DEV_MORE(dev)->_is_monitoring) {
_NATIVENET_DEV_MORE(dev)->_is_monitoring = 0;
}
switch (state) {
case NETDEV_STATE_RX_MODE:
nativenet_switch_to_rx();
break;
case NETDEV_STATE_PROMISCUOUS_MODE:
_NATIVENET_DEV_MORE(dev)->_is_monitoring = 1;
break;
default:
return -ENOTSUP;
}
return 0;
}
void _nativenet_event(netdev_t *dev, uint32_t event_type)
{
(void)dev;
(void)event_type;
}
const netdev_driver_t nativenet_driver = {
_nativenet_init,
_nativenet_send_data,
_nativenet_add_rcv_data_cb,
_nativenet_rem_rcv_data_cb,
_nativenet_get_option,
_nativenet_set_option,
_nativenet_get_state,
_nativenet_set_state,
_nativenet_event,
};
_nativenet_netdev_more_t _nativenet_default_dev_more;
netdev_t nativenet_default_dev = {NETDEV_TYPE_BASE, &nativenet_driver,
&_nativenet_default_dev_more
};
#else
_nativenet_netdev_more_t _nativenet_default_dev_more;
netdev_t nativenet_default_dev = {NETDEV_TYPE_BASE, NULL,
&_nativenet_default_dev_more
};
#endif /* MODULE_NETDEV_BASE */
/** @} */

View File

@ -1,370 +0,0 @@
/**
* tap.h implementation
*
* Copyright (C) 2013 Ludwig Ortmann <ludwig.ortmann@fu-berlin.de>
*
* 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 native_cpu
* @{
* @file
* @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <err.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <inttypes.h>
#include <errno.h>
#ifdef __MACH__
#define _POSIX_C_SOURCE
#include <net/if.h>
#undef _POSIX_C_SOURCE
#include <ifaddrs.h>
#include <net/if_dl.h>
#elif defined(__FreeBSD__)
#include <sys/socket.h>
#include <net/if.h>
#include <ifaddrs.h>
#include <net/if_dl.h>
#else
#include <net/if.h>
#include <linux/if_tun.h>
#include <linux/if_ether.h>
#endif
#define ENABLE_DEBUG (0)
#include "debug.h"
#include "cpu.h"
#include "cpu_conf.h"
#include "tap.h"
#include "nativenet.h"
#include "nativenet_internal.h"
#include "native_internal.h"
#include "hwtimer.h"
#include "timex.h"
#define TAP_BUFFER_LENGTH (ETHER_MAX_LEN)
int _native_marshall_ethernet(uint8_t *framebuf, radio_packet_t *packet);
int _native_tap_fd = -1;
unsigned char _native_tap_mac[ETHER_ADDR_LEN];
#ifdef __MACH__
pid_t sigio_child_pid;
#endif
void _native_handle_tap_input(void)
{
int nread;
union eth_frame frame;
radio_packet_t p;
DEBUG("_native_handle_tap_input\n");
/* TODO: check whether this is an input or an output event
TODO: refactor this into general io-signal multiplexer */
nread = real_read(_native_tap_fd, &frame, sizeof(union eth_frame));
DEBUG("_native_handle_tap_input - read %d bytes\n", nread);
if (nread > 0) {
if (ntohs(frame.field.header.ether_type) == NATIVE_ETH_PROTO) {
nread = nread - ETHER_HDR_LEN;
if ((nread - 1) <= 0) {
DEBUG("_native_handle_tap_input: no payload\n");
}
else {
unsigned long t = hwtimer_now();
p.processing = 0;
p.src = ntohs(frame.field.payload.nn_header.src);
p.dst = ntohs(frame.field.payload.nn_header.dst);
p.rssi = 0;
p.lqi = 0;
p.toa.seconds = HWTIMER_TICKS_TO_US(t) / 1000000;
p.toa.microseconds = HWTIMER_TICKS_TO_US(t) % 1000000;
/* XXX: check overflow */
p.length = ntohs(frame.field.payload.nn_header.length);
p.data = frame.field.payload.data;
if (p.length > (nread - sizeof(struct nativenet_header))) {
warnx("_native_handle_tap_input: packet with malicious length field received, discarding");
}
else {
DEBUG("_native_handle_tap_input: received packet of length %" PRIu16 " for %" PRIu16 " from %"
PRIu16 "\n", p.length, p.dst, p.src);
_nativenet_handle_packet(&p);
}
}
}
else {
DEBUG("ignoring non-native frame\n");
}
/* work around lost signals */
fd_set rfds;
struct timeval t;
memset(&t, 0, sizeof(t));
FD_ZERO(&rfds);
FD_SET(_native_tap_fd, &rfds);
_native_in_syscall++; // no switching here
if (real_select(_native_tap_fd + 1, &rfds, NULL, NULL, &t) == 1) {
int sig = SIGIO;
extern int _sig_pipefd[2];
extern ssize_t (*real_write)(int fd, const void *buf, size_t count);
real_write(_sig_pipefd[1], &sig, sizeof(int));
_native_sigpend++;
DEBUG("_native_handle_tap_input: sigpend++\n");
}
else {
DEBUG("_native_handle_tap_input: no more pending tap data\n");
#ifdef __MACH__
kill(sigio_child_pid, SIGCONT);
#endif
}
_native_in_syscall--;
}
else if (nread == -1) {
if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
//warn("read");
}
else {
err(EXIT_FAILURE, "_native_handle_tap_input: read");
}
}
else if (nread == 0) {
DEBUG("_native_handle_tap_input: ignoring null-event\n");
}
else {
errx(EXIT_FAILURE, "internal error _native_handle_tap_input");
}
}
#ifdef __MACH__
void sigio_child(void)
{
pid_t parent = _native_pid;
if ((sigio_child_pid = real_fork()) == -1) {
err(EXIT_FAILURE, "sigio_child: fork");
}
if (sigio_child_pid > 0) {
/* return in parent process */
return;
}
/* watch tap interface and signal parent process if data is
* available */
fd_set rfds;
while (1) {
FD_ZERO(&rfds);
FD_SET(_native_tap_fd, &rfds);
if (real_select(_native_tap_fd + 1, &rfds, NULL, NULL, NULL) == 1) {
kill(parent, SIGIO);
}
else {
kill(parent, SIGKILL);
err(EXIT_FAILURE, "osx_sigio_child: select");
}
pause();
}
}
#endif
int _native_marshall_ethernet(uint8_t *framebuf, radio_packet_t *packet)
{
int data_len;
union eth_frame *f;
unsigned char addr[ETHER_ADDR_LEN];
f = (union eth_frame *)framebuf;
addr[0] = addr[1] = addr[2] = addr[3] = addr[4] = addr[5] = 0xFF;
memcpy(f->field.header.ether_dhost, addr, ETHER_ADDR_LEN);
memcpy(f->field.header.ether_shost, _native_tap_mac, ETHER_ADDR_LEN);
f->field.header.ether_type = htons(NATIVE_ETH_PROTO);
/* XXX: check overflow */
memcpy(f->field.payload.data, packet->data, packet->length);
f->field.payload.nn_header.length = htons(packet->length);
f->field.payload.nn_header.dst = htons(packet->dst);
f->field.payload.nn_header.src = htons(packet->src);
data_len = packet->length + sizeof(struct nativenet_header);
/* Pad to minimum payload size.
* Linux does this on its own, but it doesn't hurt to do it here.
* As of now only tuntaposx needs this. */
if (data_len < ETHERMIN) {
DEBUG("padding data! (%d -> ", data_len);
data_len = ETHERMIN;
DEBUG("%d)\n", data_len);
}
return data_len + ETHER_HDR_LEN;
}
int8_t send_buf(radio_packet_t *packet)
{
uint8_t buf[TAP_BUFFER_LENGTH];
int nsent, to_send;
memset(buf, 0, sizeof(buf));
DEBUG("send_buf: Sending packet of length %" PRIu16 " from %" PRIu16 " to %" PRIu16 "\n",
packet->length, packet->src, packet->dst);
to_send = _native_marshall_ethernet(buf, packet);
DEBUG("send_buf: trying to send %d bytes\n", to_send);
if ((nsent = _native_write(_native_tap_fd, buf, to_send)) == -1) {
warn("write");
return -1;
}
return (nsent > INT8_MAX ? INT8_MAX : nsent);
}
int tap_init(char *name)
{
#ifdef __MACH__ /* OSX */
char clonedev[255] = "/dev/"; /* XXX bad size */
strncpy(clonedev + 5, name, 250);
#elif defined(__FreeBSD__)
char clonedev[255] = "/dev/"; /* XXX bad size */
strncpy(clonedev + 5, name, 250);
#else /* Linux */
struct ifreq ifr;
const char *clonedev = "/dev/net/tun";
#endif
/* implicitly create the tap interface */
if ((_native_tap_fd = real_open(clonedev , O_RDWR)) == -1) {
err(EXIT_FAILURE, "open(%s)", clonedev);
}
#if (defined(__MACH__) || defined(__FreeBSD__)) /* OSX/FreeBSD */
struct ifaddrs *iflist;
if (real_getifaddrs(&iflist) == 0) {
for (struct ifaddrs *cur = iflist; cur; cur = cur->ifa_next) {
if ((cur->ifa_addr->sa_family == AF_LINK) && (strcmp(cur->ifa_name, name) == 0) && cur->ifa_addr) {
struct sockaddr_dl *sdl = (struct sockaddr_dl *)cur->ifa_addr;
memcpy(_native_tap_mac, LLADDR(sdl), sdl->sdl_alen);
break;
}
}
real_freeifaddrs(iflist);
}
#else /* Linux */
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
strncpy(ifr.ifr_name, name, IFNAMSIZ);
if (real_ioctl(_native_tap_fd, TUNSETIFF, (void *)&ifr) == -1) {
_native_in_syscall++;
warn("ioctl TUNSETIFF");
warnx("probably the tap interface (%s) does not exist or is already in use", name);
real_exit(EXIT_FAILURE);
}
/* TODO: use strncpy */
strcpy(name, ifr.ifr_name);
/* get MAC address */
memset(&ifr, 0, sizeof(ifr));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", name);
if (real_ioctl(_native_tap_fd, SIOCGIFHWADDR, &ifr) == -1) {
_native_in_syscall++;
warn("ioctl SIOCGIFHWADDR");
if (real_close(_native_tap_fd) == -1) {
warn("close");
}
real_exit(EXIT_FAILURE);
}
memcpy(_native_tap_mac, ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
#endif
DEBUG("_native_tap_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", _native_tap_mac[0], _native_tap_mac[1],
_native_tap_mac[2], _native_tap_mac[3], _native_tap_mac[4], _native_tap_mac[5]);
unsigned char *eui_64 = (unsigned char *)(&(_nativenet_default_dev_more._long_addr));
eui_64[0] = _native_tap_mac[0];
eui_64[1] = _native_tap_mac[1];
eui_64[2] = _native_tap_mac[2];
eui_64[3] = 0xff;
eui_64[4] = 0xfe;
eui_64[5] = _native_tap_mac[3];
eui_64[6] = _native_tap_mac[4];
eui_64[7] = _native_tap_mac[5];
/* configure signal handler for fds */
register_interrupt(SIGIO, _native_handle_tap_input);
#ifdef __MACH__
/* tuntap signalled IO is not working in OSX,
* check http://sourceforge.net/p/tuntaposx/bugs/17/ */
sigio_child();
#else
/* configure fds to send signals on io */
if (fcntl(_native_tap_fd, F_SETOWN, _native_pid) == -1) {
err(EXIT_FAILURE, "tap_init(): fcntl(F_SETOWN)");
}
/* set file access mode to non-blocking */
if (fcntl(_native_tap_fd, F_SETFL, O_NONBLOCK | O_ASYNC) == -1) {
err(EXIT_FAILURE, "tap_init(): fcntl(F_SETFL)");
}
#endif /* not OSX */
DEBUG("RIOT native tap initialized.\n");
return _native_tap_fd;
}
void tap_cleanup(void)
{
unregister_interrupt(SIGIO);
#ifdef __MACH__
kill(sigio_child_pid, SIGKILL);
#endif
if (_native_tap_fd == -1) {
return;
}
real_close(_native_tap_fd);
_native_tap_fd = -1;
}
/** @} */

View File

@ -35,7 +35,6 @@
#include "board_internal.h"
#include "native_internal.h"
#include "tap.h"
int _native_null_in_pipe[2];
int _native_null_out_file;
@ -197,7 +196,7 @@ void usage_exit(void)
{
real_printf("usage: %s", _progname);
#if defined(MODULE_NATIVENET) || defined(MODULE_NG_NATIVENET)
#if defined(MODULE_NG_NATIVENET)
real_printf(" <tap interface>");
#endif
@ -257,7 +256,7 @@ __attribute__((constructor)) static void startup(int argc, char **argv)
int replay = 0;
#endif
#if defined(MODULE_NATIVENET) || defined(MODULE_NG_NATIVENET)
#if defined(MODULE_NG_NATIVENET)
if (
(argc < 2)
|| (
@ -368,13 +367,7 @@ __attribute__((constructor)) static void startup(int argc, char **argv)
native_cpu_init();
native_interrupt_init();
#ifdef MODULE_NATIVENET
tap_init(argv[1]);
#endif
#ifdef MODULE_NG_NATIVENET
# ifdef MODULE_NATIVENET
# error "Modules nativenet and ng_nativenet are mutually exclusive."
# endif
dev_eth_tap_setup(&dev_eth_tap, argv[1]);
#endif

View File

@ -1,9 +1,3 @@
ifneq (,$(filter netdev_base,$(USEMODULE)))
DIRS += netdev/base
endif
ifneq (,$(filter netdev_802154,$(USEMODULE)))
DIRS += netdev/802154
endif
ifneq (,$(filter nrf24l01p,$(USEMODULE)))
DIRS += nrf24l01p
endif

View File

@ -1,21 +1,6 @@
ifneq (,$(filter cc2420,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/cc2420/include
endif
ifneq (,$(filter cc110x,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/cc110x/include
endif
ifneq (,$(filter cc110x_legacy_csma,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/cc110x_legacy_csma/include
endif
ifneq (,$(filter cc110x_legacy,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/cc110x_legacy/include
endif
ifneq (,$(filter dht,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/dht/include
endif
ifneq (,$(filter at86rf231,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/at86rf231/include
endif
ifneq (,$(filter ng_at86rf2xx,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/ng_at86rf2xx/include
endif

View File

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

View File

@ -1,112 +0,0 @@
/*
* Copyright (C) 2014 INRIA
*
* 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_at86rf231
* @{
*
* @file
* @brief RX related functionality for the AT86RF231 device driver
*
* @author Alaeddine Weslati <alaeddine.weslati@inria.fr>
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de>
*
* @}
*/
#include "at86rf231.h"
#include "at86rf231_spi.h"
#include "kernel_types.h"
#include "transceiver.h"
#include "msg.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
at86rf231_packet_t at86rf231_rx_buffer[AT86RF231_RX_BUF_SIZE];
static uint8_t buffer[AT86RF231_RX_BUF_SIZE][AT86RF231_MAX_PKT_LENGTH];
volatile uint8_t rx_buffer_next;
extern netdev_802154_raw_packet_cb_t at86rf231_raw_packet_cb;
void at86rf231_rx_handler(void)
{
uint8_t lqi, fcs_rssi;
/* read packet length */
at86rf231_read_fifo(&at86rf231_rx_buffer[rx_buffer_next].length, 1);
/* read psdu, read packet with length as first byte and lqi as last byte. */
uint8_t *buf = buffer[rx_buffer_next];
at86rf231_read_fifo(buf, at86rf231_rx_buffer[rx_buffer_next].length);
/* read lqi which is appended after the psdu */
lqi = buf[at86rf231_rx_buffer[rx_buffer_next].length - 1];
/* read fcs and rssi, from a register */
fcs_rssi = at86rf231_reg_read(AT86RF231_REG__PHY_RSSI);
/* build package */
at86rf231_rx_buffer[rx_buffer_next].lqi = lqi;
/* RSSI has no meaning here, it should be read during packet reception. */
at86rf231_rx_buffer[rx_buffer_next].rssi = fcs_rssi & 0x1F; /* bit[4:0] */
/* bit7, boolean, 1 FCS valid, 0 FCS not valid */
at86rf231_rx_buffer[rx_buffer_next].crc = (fcs_rssi >> 7) & 0x01;
if (at86rf231_rx_buffer[rx_buffer_next].crc == 0) {
DEBUG("at86rf231: Got packet with invalid crc.\n");
return;
}
#if ENABLE_DEBUG
DEBUG("pkg: ");
for (int i = 1; i < at86rf231_rx_buffer[rx_buffer_next].length; i++) {
DEBUG("%x ", buf[i]);
}
DEBUG("\n");
#endif
/* read buffer into ieee802154_frame */
ieee802154_frame_read(&buf[1], &at86rf231_rx_buffer[rx_buffer_next].frame,
at86rf231_rx_buffer[rx_buffer_next].length);
/* if packet is no ACK */
if (at86rf231_rx_buffer[rx_buffer_next].frame.fcf.frame_type != IEEE_802154_ACK_FRAME) {
#if ENABLE_DEBUG
ieee802154_frame_print_fcf_frame(&at86rf231_rx_buffer[rx_buffer_next].frame);
#endif
if (at86rf231_raw_packet_cb != NULL) {
at86rf231_raw_packet_cb(&at86rf231_netdev, (void*)buf,
at86rf231_rx_buffer[rx_buffer_next].length,
fcs_rssi, lqi, (fcs_rssi >> 7));
}
#ifdef MODULE_TRANSCEIVER
/* notify transceiver thread if any */
if (transceiver_pid != KERNEL_PID_UNDEF) {
msg_t m;
m.type = (uint16_t) RCV_PKT_AT86RF231;
m.content.value = rx_buffer_next;
msg_send_int(&m, transceiver_pid);
}
#endif
}
else {
/* This should not happen, ACKs are consumed by hardware */
#if ENABLE_DEBUG
DEBUG("GOT ACK for SEQ %u\n", at86rf231_rx_buffer[rx_buffer_next].frame.seq_nr);
ieee802154_frame_print_fcf_frame(&at86rf231_rx_buffer[rx_buffer_next].frame);
#endif
}
/* shift to next buffer element */
if (++rx_buffer_next == AT86RF231_RX_BUF_SIZE) {
rx_buffer_next = 0;
}
/* Read IRQ to clear it */
at86rf231_reg_read(AT86RF231_REG__IRQ_STATUS);
}

View File

@ -1,94 +0,0 @@
/*
* Copyright (C) 2014 INRIA
*
* 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_at86rf231
* @{
*
* @file
* @brief Register access functions for the AT86RF231 device driver
*
* @author Alaeddine Weslati <alaeddine.weslati@inria.fr>
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de>
* @author Joakim Gebart <joakim.gebart@eistec.se>
*
* @}
*/
#include "at86rf231_spi.h"
#include "at86rf231.h"
#include "board.h"
#include "periph/spi.h"
#include "periph/gpio.h"
void at86rf231_reg_write(uint8_t addr, uint8_t value)
{
/* Acquire exclusive access to the bus. */
spi_acquire(AT86RF231_SPI);
/* Start the SPI transfer */
gpio_clear(AT86RF231_CS);
/* write to register */
spi_transfer_reg(AT86RF231_SPI, AT86RF231_ACCESS_REG | AT86RF231_ACCESS_WRITE | addr, value, 0);
/* End the SPI transfer */
gpio_set(AT86RF231_CS);
/* Release the bus for other threads. */
spi_release(AT86RF231_SPI);
}
uint8_t at86rf231_reg_read(uint8_t addr)
{
char value;
/* Acquire exclusive access to the bus. */
spi_acquire(AT86RF231_SPI);
/* Start the SPI transfer */
gpio_clear(AT86RF231_CS);
/* read from register */
spi_transfer_reg(AT86RF231_SPI, AT86RF231_ACCESS_REG | AT86RF231_ACCESS_READ | addr, 0, &value);
/* End the SPI transfer */
gpio_set(AT86RF231_CS);
/* Release the bus for other threads. */
spi_release(AT86RF231_SPI);
return (uint8_t)value;
}
void at86rf231_read_fifo(uint8_t *data, radio_packet_length_t length)
{
/* Acquire exclusive access to the bus. */
spi_acquire(AT86RF231_SPI);
/* Start the SPI transfer */
gpio_clear(AT86RF231_CS);
/* Read a number of bytes from the devices frame buffer */
spi_transfer_regs(AT86RF231_SPI, AT86RF231_ACCESS_FRAMEBUFFER | AT86RF231_ACCESS_READ,
0, (char*)data, length);
/* End the SPI transfer */
gpio_set(AT86RF231_CS);
/* Release the bus for other threads. */
spi_release(AT86RF231_SPI);
}
void at86rf231_write_fifo(const uint8_t *data, radio_packet_length_t length)
{
/* Acquire exclusive access to the bus. */
spi_acquire(AT86RF231_SPI);
/* Start the SPI transfer */
gpio_clear(AT86RF231_CS);
/* Send Frame Buffer Write access */
spi_transfer_regs(AT86RF231_SPI, AT86RF231_ACCESS_FRAMEBUFFER | AT86RF231_ACCESS_WRITE,
(char*)data, 0, length);
/* End the SPI transfer */
gpio_set(AT86RF231_CS);
/* Release the bus for other threads. */
spi_release(AT86RF231_SPI);
}
uint8_t at86rf231_get_status(void)
{
return (at86rf231_reg_read(AT86RF231_REG__TRX_STATUS)
& AT86RF231_TRX_STATUS_MASK__TRX_STATUS);
}

View File

@ -1,295 +0,0 @@
/*
* Copyright (C) 2014 INRIA
*
* 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_at86rf231
* @{
*
* @file
* @brief TX related functionality for the AT86RF231 device driver
*
* @author Alaeddine Weslati <alaeddine.weslati@inria.fr>
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de>
*
* @}
*/
#include "at86rf231.h"
#include "at86rf231_spi.h"
#include "hwtimer.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#define _MAX_RETRIES (100)
static int16_t at86rf231_load(at86rf231_packet_t *packet);
static void at86rf231_gen_pkt(uint8_t *buf, at86rf231_packet_t *packet);
static uint8_t sequence_nr;
static uint8_t wait_for_ack;
int16_t at86rf231_send(at86rf231_packet_t *packet)
{
int16_t result;
result = at86rf231_load(packet);
if (result < 0) {
return result;
}
at86rf231_transmit_tx_buf(NULL);
return result;
}
netdev_802154_tx_status_t at86rf231_load_tx_buf(netdev_t *dev,
netdev_802154_pkt_kind_t kind,
netdev_802154_node_addr_t *dest,
int use_long_addr,
int wants_ack,
netdev_hlist_t *upper_layer_hdrs,
void *buf,
unsigned int len)
{
(void)dev;
uint8_t mhr[24];
uint8_t index = 3;
/* frame type */
switch (kind) {
case NETDEV_802154_PKT_KIND_BEACON:
mhr[0] = 0x00;
break;
case NETDEV_802154_PKT_KIND_DATA:
mhr[0] = 0x01;
break;
case NETDEV_802154_PKT_KIND_ACK:
mhr[0] = 0x02;
break;
default:
return NETDEV_802154_TX_STATUS_INVALID_PARAM;
}
if (wants_ack) {
mhr[0] |= 0x20;
}
wait_for_ack = wants_ack;
uint16_t src_pan = at86rf231_get_pan();
uint8_t compress_pan = 0;
if (use_long_addr) {
mhr[1] = 0xcc;
}
else {
mhr[1] = 0x88;
if (dest->pan.id == src_pan) {
compress_pan = 1;
mhr[0] |= 0x40;
}
}
mhr[2] = sequence_nr++;
/* First 3 bytes are fixed with FCS and SEQ, resume with index=3 */
if (use_long_addr) {
mhr[index++] = (uint8_t)(dest->long_addr & 0xFF);
mhr[index++] = (uint8_t)(dest->long_addr >> 8);
mhr[index++] = (uint8_t)(dest->long_addr >> 16);
mhr[index++] = (uint8_t)(dest->long_addr >> 24);
mhr[index++] = (uint8_t)(dest->long_addr >> 32);
mhr[index++] = (uint8_t)(dest->long_addr >> 40);
mhr[index++] = (uint8_t)(dest->long_addr >> 48);
mhr[index++] = (uint8_t)(dest->long_addr >> 56);
uint64_t src_long_addr = at86rf231_get_address_long();
mhr[index++] = (uint8_t)(src_long_addr & 0xFF);
mhr[index++] = (uint8_t)(src_long_addr >> 8);
mhr[index++] = (uint8_t)(src_long_addr >> 16);
mhr[index++] = (uint8_t)(src_long_addr >> 24);
mhr[index++] = (uint8_t)(src_long_addr >> 32);
mhr[index++] = (uint8_t)(src_long_addr >> 40);
mhr[index++] = (uint8_t)(src_long_addr >> 48);
mhr[index++] = (uint8_t)(src_long_addr >> 56);
}
else {
mhr[index++] = (uint8_t)(dest->pan.id & 0xFF);
mhr[index++] = (uint8_t)(dest->pan.id >> 8);
mhr[index++] = (uint8_t)(dest->pan.addr & 0xFF);
mhr[index++] = (uint8_t)(dest->pan.addr >> 8);
if (!compress_pan) {
mhr[index++] = (uint8_t)(src_pan & 0xFF);
mhr[index++] = (uint8_t)(src_pan >> 8);
}
uint16_t src_addr = at86rf231_get_address();
mhr[index++] = (uint8_t)(src_addr & 0xFF);
mhr[index++] = (uint8_t)(src_addr >> 8);
}
/* total frame size:
* index -> MAC header
* len -> payload length
* 2 -> CRC bytes
* + lengths of upper layers' headers */
size_t size = index + len + 2 + netdev_get_hlist_len(upper_layer_hdrs);
if (size > AT86RF231_MAX_PKT_LENGTH) {
DEBUG("at86rf231: packet too long, dropped it.\n");
return NETDEV_802154_TX_STATUS_PACKET_TOO_LONG;
}
uint8_t size_byte = (uint8_t)size;
netdev_hlist_t *ptr = upper_layer_hdrs;
at86rf231_write_fifo(&size_byte, 1);
at86rf231_write_fifo(mhr, (radio_packet_length_t)index);
if (upper_layer_hdrs) {
do {
at86rf231_write_fifo(ptr->header,
(radio_packet_length_t)(ptr->header_len));
netdev_hlist_advance(&ptr);
} while (ptr != upper_layer_hdrs);
}
at86rf231_write_fifo((uint8_t*)buf, len);
return NETDEV_802154_TX_STATUS_OK;
}
netdev_802154_tx_status_t at86rf231_transmit_tx_buf(netdev_t *dev)
{
(void)dev;
/* radio driver state: sending */
/* will be freed in at86rf231_rx_irq when TRX_END interrupt occurs */
driver_state = AT_DRIVER_STATE_SENDING;
/* Start TX */
at86rf231_reg_write(AT86RF231_REG__TRX_STATE, AT86RF231_TRX_STATE__TX_START);
DEBUG("at86rf231: Started TX\n");
if (!wait_for_ack) {
DEBUG("at86rf231: Don't wait for ACK, TX done.\n");
return NETDEV_802154_TX_STATUS_OK;
}
uint8_t trac_status;
do {
trac_status = at86rf231_reg_read(AT86RF231_REG__TRX_STATE);
trac_status &= AT86RF231_TRX_STATE_MASK__TRAC;
}
while (trac_status == AT86RF231_TRX_STATE__TRAC_INVALID);
switch (trac_status) {
case AT86RF231_TRX_STATE__TRAC_CHANNEL_ACCESS_FAILURE:
return NETDEV_802154_TX_STATUS_MEDIUM_BUSY;
case AT86RF231_TRX_STATE__TRAC_NO_ACK:
return NETDEV_802154_TX_STATUS_NOACK;
default:
return NETDEV_802154_TX_STATUS_OK;
}
}
int16_t at86rf231_load(at86rf231_packet_t *packet)
{
// Set missing frame information
packet->frame.fcf.frame_ver = 0;
packet->frame.src_pan_id = at86rf231_get_pan();
if (packet->frame.src_pan_id == packet->frame.dest_pan_id) {
packet->frame.fcf.panid_comp = 1;
}
else {
packet->frame.fcf.panid_comp = 0;
}
if (packet->frame.fcf.src_addr_m == 2) {
packet->frame.src_addr[0] = (uint8_t)(at86rf231_get_address() >> 8);
packet->frame.src_addr[1] = (uint8_t)(at86rf231_get_address() & 0xFF);
}
else if (packet->frame.fcf.src_addr_m == 3) {
packet->frame.src_addr[0] = (uint8_t)(at86rf231_get_address_long() >> 56);
packet->frame.src_addr[1] = (uint8_t)(at86rf231_get_address_long() >> 48);
packet->frame.src_addr[2] = (uint8_t)(at86rf231_get_address_long() >> 40);
packet->frame.src_addr[3] = (uint8_t)(at86rf231_get_address_long() >> 32);
packet->frame.src_addr[4] = (uint8_t)(at86rf231_get_address_long() >> 24);
packet->frame.src_addr[5] = (uint8_t)(at86rf231_get_address_long() >> 16);
packet->frame.src_addr[6] = (uint8_t)(at86rf231_get_address_long() >> 8);
packet->frame.src_addr[7] = (uint8_t)(at86rf231_get_address_long() & 0xFF);
}
packet->frame.seq_nr = sequence_nr++;
/* calculate size of the frame (payload + FCS) */
packet->length = ieee802154_frame_get_hdr_len(&packet->frame) +
packet->frame.payload_len + 1;
if (packet->length > AT86RF231_MAX_PKT_LENGTH) {
DEBUG("at86rf231: ERROR: packet too long, dropped it.\n");
return -1;
}
/* FCS is added in hardware */
uint8_t pkt[packet->length];
/* generate pkt */
at86rf231_gen_pkt(pkt, packet);
/* Go to state PLL_ON */
at86rf231_reg_write(AT86RF231_REG__TRX_STATE, AT86RF231_TRX_STATE__PLL_ON);
/* wait until it is on PLL_ON state */
do {
int max_wait = _MAX_RETRIES;
if (!--max_wait) {
DEBUG("at86rf231 : ERROR : could not enter PLL_ON mode\n");
break;
}
} while ((at86rf231_get_status() & AT86RF231_TRX_STATUS_MASK__TRX_STATUS)
!= AT86RF231_TRX_STATUS__PLL_ON);
/* change into TX_ARET_ON state */
at86rf231_reg_write(AT86RF231_REG__TRX_STATE, AT86RF231_TRX_STATE__TX_ARET_ON);
do {
int max_wait = _MAX_RETRIES;
if (!--max_wait) {
DEBUG("at86rf231 : ERROR : could not enter TX_ARET_ON mode\n");
break;
}
} while (at86rf231_get_status() != AT86RF231_TRX_STATUS__TX_ARET_ON);
/* load packet into fifo */
at86rf231_write_fifo(pkt, packet->length);
DEBUG("at86rf231: Wrote to FIFO\n");
return packet->length;
}
/**
* @brief Static function to generate byte array from at86rf231 packet.
*/
static void at86rf231_gen_pkt(uint8_t *buf, at86rf231_packet_t *packet)
{
uint8_t index, offset;
index = ieee802154_frame_init(&packet->frame, &buf[1]);
// add length for at86rf231
buf[0] = packet->length + 1;
index++;
offset = index;
while (index < packet->length) {
buf[index] = packet->frame.payload[index - offset];
index += 1;
}
}

View File

@ -1,44 +0,0 @@
/*
* Copyright (C) 2014 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_at86rf231
* @{
*
* @file
* @brief Register access function definitions for the AT86RF231 device driver
*
* @author Alaeddine Weslati <alaeddine.weslati@inria.fr>
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de>
*/
#ifndef AT86RF231_SPI_H_
#define AT86RF231_SPI_H_
#include <stdint.h>
#include "board.h"
#ifdef __cplusplus
extern "C" {
#endif
uint8_t at86rf231_reg_read(uint8_t addr);
void at86rf231_reg_write(uint8_t addr, uint8_t value);
void at86rf231_read_fifo(uint8_t *data, radio_packet_length_t length);
void at86rf231_write_fifo(const uint8_t *data, radio_packet_length_t length);
uint8_t at86rf231_get_status(void);
#ifdef __cplusplus
}
#endif
#endif /* AT86RF231_SPI_H_ */
/** @} */

View File

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

View File

@ -1,133 +0,0 @@
/*
* Copyright (C) 2013 INRIA
*
* 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_cc110x
* @{
*
* @file
* @brief TI Chipcon CC110x default settings
*
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @author Oliver Hahm <oliver.hahm@inria.fr>
* @}
*/
#include "cc110x.h"
/**
* @brief Default PA table index (output power)
*/
#define PATABLE (11)
/**
* @brief Current PATABLE Index
*/
uint8_t pa_table_index = PATABLE;
/**
* @brief PATABLE with available output powers
* @note If changed in size, adjust MAX_OUTPUT_POWER definition
* in CC110x interface
*/
uint8_t pa_table[] = {
0x00, ///< -52 dBm
0x03, ///< -30 dBm
0x0D, ///< -20 dBm
0x1C, ///< -15 dBm
0x34, ///< -10 dBm
0x57, ///< - 5 dBm
0x3F, ///< - 1 dBm
0x8E, ///< 0 dBm
0x85, ///< + 5 dBm
0xCC, ///< + 7 dBm
0xC6, ///< + 9 dBm
0xC3 ///< +10 dBm
};
/**
* Usable, non overlapping channels and corresponding frequencies
* for use with CC110x. CHANNR is the register for selecting a channel.
*
* channel number | CHANNR | frequency [MHz]
* -----------------------------------------
* 0 | 0 | 869.525
* 1 | 10 | 871.61
* 2 | 20 | 873.58 ~ seems to be bad (hang-ups with this channel)
* 3 | 30 | 875.61
* 4 | 40 | 877.58
* 5 | 50 | 879.61
* 6 | 60 | 881.58
* 7 | 70 | 883.61
* 8 | 80 | 885.58
* 9 | 90 | 887.61
* 10 | 100 | 889.58
* 11 | 110 | 891.57
* 12 | 120 | 893.58
* 13 | 130 | 895.61
* 14 | 140 | 897.58
* 15 | 150 | 899.57
* 16 | 160 | 901.57
* 17 | 170 | 903.61
* 18 | 180 | 905.57
* 19 | 190 | 907.57
* 20 | 200 | 909.57
* 21 | 210 | 911.57
* 22 | 220 | 913.57
* 23 | 230 | 915.61
* 24 | 240 | 917.61
*/
/**
* @brief Initial CC110x configuration
*
* 400 kbps, MSK, X-tal: 26 MHz (Chip Revision F)
*/
char cc110x_conf[] = {
0x06, /* IOCFG2 */
0x2E, /* IOCFG1 */
0x0E, /* IOCFG0 */
0x0F, /* FIFOTHR */
0x9B, /* SYNC1 */
0xAD, /* SYNC0 */
0x3D, /* PKTLEN (maximum value of packet length byte = 61) */
0x06, /* PKTCTRL1 */
0x45, /* PKTCTRL0 (variable packet length) */
0xFF, /* ADDR */
CC1100_DEFAULT_CHANNR * 10, /* CHANNR */
0x0B, /* FSCTRL1 */
0x00, /* FSCTRL0 */
0x21, /* FREQ2 */
0x71, /* FREQ1 */
0x7A, /* FREQ0 */
0x2D, /* MDMCFG4 */
0xF8, /* MDMCFG3 */
0x73, /* MDMCFG2 */
0x42, /* MDMCFG1 */
0xF8, /* MDMCFG0 */
0x00, /* DEVIATN */
0x07, /* MCSM2 */
0x03, /* MCSM1 */
0x18, /* MCSM0 */
0x1D, /* FOCCFG */
0x1C, /* BSCFG */
0xC0, /* AGCCTRL2 */
0x49, /* AGCCTRL1 */
0xB2, /* AGCCTRL0 */
0x87, /* WOREVT1 */
0x6B, /* WOREVT0 */
0xF8, /* WORCTRL */
0xB6, /* FREND1 */
0x10, /* FREND0 */
0xEA, /* FSCAL3 */
0x2A, /* FSCAL2 */
0x00, /* FSCAL1 */
0x1F, /* FSCAL0 */
0x00 /* padding to 4 bytes */
};

View File

@ -1,207 +0,0 @@
/*
* Copyright (C) 2008 Freie Universität Berlin
* Copyright (C) 2013 INRIA
*
* 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_cc110x
* @{
*
* @file
* @brief Driver internal constants for CC110x chip configuration
*
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @author Oliver Hahm <oliver.hahm@inria.fr>
*/
#ifndef CC110X_INTERNAL_H
#define CC110X_INTERNAL_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Variable packet length PKTCTRL0 bit configuration
*
* If variable packet length is configured in PKTCTRL0 the
* first byte after the synch word determines the packet length.
*/
#define VARIABLE_PKTLEN (0x01)
/**
* @name Bitmasks for reading out status register values
* @{
*/
/**
* @brief Bitmask (=10000000) for reading CRC_OK.
*
* If CRC_OK == 1: CRC for received data OK (or CRC disabled).
* If CRC_OK == 0: CRC error in received data.
*/
#define CRC_OK (0x80)
/**
* @brief Bitmask (=01111111) for reading LQI_EST.
*
* The Link Quality Indicator estimates how easily a received signal can be demodulated.
*/
#define LQI_EST (0x7F)
#define I_RSSI (0x00) ///< Index 0 contains RSSI information (from optionally appended packet status bytes).
#define I_LQI (0x01) ///< Index 1 contains LQI & CRC_OK information (from optionally appended packet status bytes).
#define MARC_STATE (0x1F) ///< Bitmask (=00011111) for reading MARC_STATE in MARCSTATE status register.
#define CS (0x40) ///< Bitmask (=01000000) for reading CS (Carrier Sense) in PKTSTATUS status register.
#define PQT_REACHED (0x20) ///< Bitmask (=00100000) for reading PQT_REACHED (Preamble Quality reached) in PKTSTATUS status register.
#define CCA (0x10) ///< Bitmask (=00010000) for reading CCA (clear channel assessment) in PKTSTATUS status register.
#define SFD (0x08) ///< Bitmask (=00001000) for reading SFD (Sync word found) in PKTSTATUS status register.
#define GDO2 (0x04) ///< Bitmask (=00000100) for reading GDO2 (current value on GDO2 pin) in PKTSTATUS status register.
#define GDO1 (0x02) ///< Bitmask (=00000010) for reading GDO1 (current value on GDO1 pin) in PKTSTATUS status register.
#define GDO0 (0x01) ///< Bitmask (=00000001) for reading GDO0 (current value on GDO0 pin) in PKTSTATUS status register.
#define TXFIFO_UNDERFLOW (0x80) ///< Bitmask (=10000000) for reading TXFIFO_UNDERFLOW in TXBYTES status register.
#define BYTES_IN_TXFIFO (0x7F) ///< Bitmask (=01111111) for reading NUM_TXBYTES in TXBYTES status register.
#define RXFIFO_OVERFLOW (0xBF) ///< Bitmask (=10000000) for reading RXFIFO_OVERFLOW in RXBYTES status register.
#define BYTES_IN_RXFIFO (0xFF) ///< Bitmask (=01111111) for reading NUM_RXBYTES in RXBYTES status register.
/** @} */
/**
* @name Bitmasks for reading out configuration register values
* @{
*/
#define PKT_LENGTH_CONFIG (0x03) ///< Bitmask (=00000011) for reading LENGTH_CONFIG in PKTCTRL0 configuration register.
/** @} */
/**
* @name Definitions to support burst/single access
* @{
*/
#define CC1100_WRITE_BURST (0x40) ///< Offset for burst write.
#define CC1100_READ_SINGLE (0x80) ///< Offset for read single byte.
#define CC1100_READ_BURST (0xC0) ///< Offset for read burst.
#define CC1100_NOBYTE (0xFF) ///< No command (for reading).
/** @} */
/**
* @name Configuration Registers (47x)
* @{
*/
#define CC1100_IOCFG2 (0x00) ///< GDO2 output pin configuration
#define CC1100_IOCFG1 (0x01) ///< GDO1 output pin configuration
#define CC1100_IOCFG0 (0x02) ///< GDO0 output pin configuration
#define CC1100_FIFOTHR (0x03) ///< RX FIFO and TX FIFO thresholds
#define CC1100_SYNC1 (0x04) ///< Sync word, high byte
#define CC1100_SYNC0 (0x05) ///< Sync word, low byte
#define CC1100_PKTLEN (0x06) ///< Packet length
#define CC1100_PKTCTRL1 (0x07) ///< Packet automation control
#define CC1100_PKTCTRL0 (0x08) ///< Packet automation control
#define CC1100_ADDR (0x09) ///< Device address
#define CC1100_CHANNR (0x0A) ///< Channel number
#define CC1100_FSCTRL1 (0x0B) ///< Frequency synthesizer control
#define CC1100_FSCTRL0 (0x0C) ///< Frequency synthesizer control
#define CC1100_FREQ2 (0x0D) ///< Frequency control word, high byte
#define CC1100_FREQ1 (0x0E) ///< Frequency control word, middle byte
#define CC1100_FREQ0 (0x0F) ///< Frequency control word, low byte
#define CC1100_MDMCFG4 (0x10) ///< Modem configuration
#define CC1100_MDMCFG3 (0x11) ///< Modem configuration
#define CC1100_MDMCFG2 (0x12) ///< Modem configuration
#define CC1100_MDMCFG1 (0x13) ///< Modem configuration
#define CC1100_MDMCFG0 (0x14) ///< Modem configuration
#define CC1100_DEVIATN (0x15) ///< Modem deviation setting
#define CC1100_MCSM2 (0x16) ///< Main Radio Control State Machine configuration
#define CC1100_MCSM1 (0x17) ///< Main Radio Control State Machine configuration
#define CC1100_MCSM0 (0x18) ///< Main Radio Control State Machine configuration
#define CC1100_FOCCFG (0x19) ///< Frequency Offset Compensation configuration
#define CC1100_BSCFG (0x1A) ///< Bit Synchronization configuration
#define CC1100_AGCCTRL2 (0x1B) ///< AGC control
#define CC1100_AGCCTRL1 (0x1C) ///< AGC control
#define CC1100_AGCCTRL0 (0x1D) ///< AGC control
#define CC1100_WOREVT1 (0x1E) ///< High byte Event 0 timeout
#define CC1100_WOREVT0 (0x1F) ///< Low byte Event 0 timeout
#define CC1100_WORCTRL (0x20) ///< Wake On Radio control
#define CC1100_FREND1 (0x21) ///< Front end RX configuration
#define CC1100_FREND0 (0x22) ///< Front end TX configuration
#define CC1100_FSCAL3 (0x23) ///< Frequency synthesizer calibration
#define CC1100_FSCAL2 (0x24) ///< Frequency synthesizer calibration
#define CC1100_FSCAL1 (0x25) ///< Frequency synthesizer calibration
#define CC1100_FSCAL0 (0x26) ///< Frequency synthesizer calibration
#define CC1100_RCCTRL1 (0x27) ///< RC oscillator configuration
#define CC1100_RCCTRL0 (0x28) ///< RC oscillator configuration
#define CC1100_FSTEST (0x29) ///< Frequency synthesizer calibration control
#define CC1100_PTEST (0x2A) ///< Production test
#define CC1100_AGCTEST (0x2B) ///< AGC test
#define CC1100_TEST2 (0x2C) ///< Various test settings
#define CC1100_TEST1 (0x2D) ///< Various test settings
#define CC1100_TEST0 (0x2E) ///< Various test settings
/** @} */
/**
* @name Strobe commands (14x)
* @{
*/
#define CC1100_SRES (0x30) ///< Reset chip.
/**
* @brief Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1).
*
* If in RX/TX: Go to a wait state where only the synthesizer is running (for quick RX / TX turnaround).
*/
#define CC1100_SFSTXON (0x31)
#define CC1100_SXOFF (0x32) ///< Turn off crystal oscillator.
#define CC1100_SCAL (0x33) ///< Calibrate frequency synthesizer and turn it off (enables quick start).
#define CC1100_SRX (0x34) ///< Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL=1.
/**
* In IDLE state: Enable TX. Perform calibration first if MCSM0.FS_AUTOCAL=1.
* If in RX state and CCA is enabled: Only go to TX if channel is clear.
*/
#define CC1100_STX (0x35)
#define CC1100_SIDLE (0x36) ///< Exit RX / TX, turn off frequency synthesizer and exit WOR mode if applicable.
#define CC1100_SAFC (0x37) ///< Perform AFC adjustment of the frequency synthesizer
#define CC1100_SWOR (0x38) ///< Start automatic RX polling sequence (Wake-on-Radio)
#define CC1100_SPWD (0x39) ///< Enter power down mode when CSn goes high.
#define CC1100_SFRX (0x3A) ///< Flush the RX FIFO buffer (CC1100 should be in IDLE state).
#define CC1100_SFTX (0x3B) ///< Flush the TX FIFO buffer (CC1100 should be in IDLE state).
#define CC1100_SWORRST (0x3C) ///< Reset real time clock.
#define CC1100_SNOP (0x3D) ///< No operation. May be used to pad strobe commands to two bytes for simpler software.
/** @} */
/**
* @name Status registers (12x)
* @{
*/
#define CC1100_PARTNUM (0x30) ///< Part number of CC1100.
#define CC1100_VERSION (0x31) ///< Current version number.
#define CC1100_FREQEST (0x32) ///< Frequency Offset Estimate.
#define CC1100_LQI (0x33) ///< Demodulator estimate for Link Quality.
#define CC1100_RSSI (0x34) ///< Received signal strength indication.
#define CC1100_MARCSTATE (0x35) ///< Control state machine state.
#define CC1100_WORTIME1 (0x36) ///< High byte of WOR timer.
#define CC1100_WORTIME0 (0x37) ///< Low byte of WOR timer.
#define CC1100_PKTSTATUS (0x38) ///< Current GDOx status and packet status.
#define CC1100_VCO_VC_DAC (0x39) ///< Current setting from PLL calibration module.
#define CC1100_TXBYTES (0x3A) ///< Underflow and number of bytes in the TX FIFO.
#define CC1100_RXBYTES (0x3B) ///< Overflow and number of bytes in the RX FIFO.
/** @} */
/**
* @name Multi byte registers
* @{
*/
/**
* @brief Register for eight user selected output power settings.
*
* 3-bit FREND0.PA_POWER value selects the PATABLE entry to use.
*/
#define CC1100_PATABLE (0x3E)
#define CC1100_TXFIFO (0x3F) ///< TX FIFO: Write operations write to the TX FIFO (SB: +0x00; BURST: +0x40)
#define CC1100_RXFIFO (0x3F) ///< RX FIFO: Read operations read from the RX FIFO (SB: +0x80; BURST: +0xC0)
/** @} */
#ifdef __cplusplus
}
#endif
/** @} */
#endif

View File

@ -1,253 +0,0 @@
/*
* Copyright (C) 2014 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_cc110x
* @{
* @file
* @brief Functionality for netdev base interface
*
* @author Fabian Nack <nack@inf.fu-berlin.de>
* @}
*/
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "cc110x.h"
#include "cc110x-internal.h"
#include "periph/gpio.h"
#include "netdev/base.h"
#ifdef MODULE_NETDEV_BASE
extern netdev_rcv_data_cb_t cc110x_recv_cb;
int _cc110x_send_data(netdev_t *dev, void *dest, size_t dest_len,
netdev_hlist_t *upper_layer_hdrs, void *data, size_t data_len)
{
netdev_hlist_t *ptr = upper_layer_hdrs;
uint8_t tx_buffer[data_len + netdev_get_hlist_len(upper_layer_hdrs)];
size_t tx_ptr = 0;
cc110x_packet_t cc110x_pkt;
if (dev != &cc110x_dev) {
return -ENODEV;
}
if (dest_len > sizeof(uint8_t)) {
return -EAFNOSUPPORT;
}
if ((sizeof(tx_buffer) + CC1100_HEADER_LENGTH + 1) > PACKET_LENGTH) {
return -EMSGSIZE;
}
/* append possible upper layer headers */
if (upper_layer_hdrs) {
do {
memcpy(&(tx_buffer[tx_ptr]), ptr->header, ptr->header_len);
tx_ptr += ptr->header_len;
netdev_hlist_advance(&ptr);
} while (ptr != upper_layer_hdrs);
}
/* append data */
memcpy(&(tx_buffer[tx_ptr]), data, data_len);
cc110x_pkt.length = sizeof(tx_buffer) + CC1100_HEADER_LENGTH;
cc110x_pkt.address = *((uint8_t *)dest);
cc110x_pkt.flags = 0;
memcpy(cc110x_pkt.data, &tx_buffer[0], sizeof(tx_buffer));
return cc110x_send(&cc110x_pkt);
}
int _cc110x_add_rcv_data_cb(netdev_t *dev, netdev_rcv_data_cb_t cb)
{
if (dev != &cc110x_dev) {
return -ENODEV;
}
else if (cc110x_recv_cb != NULL) {
return -ENOBUFS;
}
cc110x_recv_cb = cb;
return 0;
}
int _cc110x_rem_rcv_data_cb(netdev_t *dev, netdev_rcv_data_cb_t cb)
{
if (dev != &cc110x_dev) {
return -ENODEV;
}
if (cc110x_recv_cb == cb) {
cc110x_recv_cb = NULL;
}
return 0;
}
int _cc110x_get_option(netdev_t *dev, netdev_opt_t opt, void *value, size_t *value_len)
{
if (dev != &cc110x_dev) {
return -ENODEV;
}
switch (opt) {
case NETDEV_OPT_CHANNEL:
if (*value_len == 0) {
return -EOVERFLOW;
}
if (*value_len > sizeof(uint8_t)) {
*value_len = sizeof(uint8_t);
}
*((uint8_t *)value) = cc110x_get_channel();
break;
case NETDEV_OPT_ADDRESS:
if (*value_len < sizeof(radio_address_t)) {
return -EOVERFLOW;
}
if (*value_len > sizeof(uint8_t)) {
*value_len = sizeof(uint8_t);
}
*((uint8_t *)value) = (uint8_t) cc110x_get_address();
break;
case NETDEV_OPT_PROTO:
if (*value_len < sizeof(netdev_proto_t)) {
return -EOVERFLOW;
}
if (*value_len > sizeof(netdev_proto_t)) {
*value_len = sizeof(netdev_proto_t);
}
*((netdev_proto_t *)value) = NETDEV_PROTO_CC110X;
break;
case NETDEV_OPT_MAX_PACKET_SIZE:
if (*value_len == 0) {
return -EOVERFLOW;
}
if (*value_len > sizeof(uint8_t)) {
*value_len = sizeof(uint8_t);
}
*((uint8_t *)value) = PACKET_LENGTH;
break;
default:
return -ENOTSUP;
}
return 0;
}
int _cc110x_set_option(netdev_t *dev, netdev_opt_t opt, void *value, size_t value_len)
{
if (dev != &cc110x_dev) {
return -ENODEV;
}
switch (opt) {
case NETDEV_OPT_CHANNEL:
if (value_len != sizeof(uint8_t)) {
return -EOVERFLOW;
}
if (cc110x_set_channel(*((uint8_t *)value)) == -1) {
return -EINVAL;
}
break;
case NETDEV_OPT_ADDRESS:
/* leaves room for optimization */
if (value_len > sizeof(radio_address_t)) {
return -EOVERFLOW;
}
radio_address_t temp_address;
if (value_len == sizeof(uint8_t)) {
temp_address = ((radio_address_t)(*((uint8_t *)value)));
}
else {
temp_address = *((radio_address_t *)value);
}
if (!cc110x_set_address(temp_address)) {
return -EINVAL;
}
break;
default:
return -ENOTSUP;
}
return 0;
}
int _cc110x_get_state(netdev_t *dev, netdev_state_t *state)
{
if (dev != &cc110x_dev) {
return -ENODEV;
}
switch(radio_state) {
case RADIO_IDLE:
*state = NETDEV_STATE_POWER_IDLE;
break;
case RADIO_SEND_BURST:
*state = NETDEV_STATE_TX_BURST;
break;
case RADIO_RX:
*state = NETDEV_STATE_RX_MODE;
break;
case RADIO_UNKNOWN:
case RADIO_PWD:
default:
*state = NETDEV_STATE_POWER_OFF;
break;
}
return 0;
}
int _cc110x_set_state(netdev_t *dev, netdev_state_t state)
{
if (dev != &cc110x_dev) {
return -ENODEV;
}
switch (state) {
case NETDEV_STATE_POWER_OFF:
gpio_irq_disable(CC110X_GDO2);
cc110x_switch_to_pwd();
break;
case NETDEV_STATE_RX_MODE:
gpio_irq_enable(CC110X_GDO2);
cc110x_setup_rx_mode();
break;
default:
return -ENOTSUP;
}
return 0;
}
void _cc110x_event(netdev_t *dev, uint32_t event_type)
{
(void)dev;
(void)event_type;
}
const netdev_driver_t cc110x_net_driver = {
cc110x_initialize,
_cc110x_send_data,
_cc110x_add_rcv_data_cb,
_cc110x_rem_rcv_data_cb,
_cc110x_get_option,
_cc110x_set_option,
_cc110x_get_state,
_cc110x_set_state,
_cc110x_event,
};
netdev_t cc110x_dev = {NETDEV_TYPE_BASE, &cc110x_net_driver, 0};
#else
netdev_t cc110x_dev = {NETDEV_TYPE_BASE, 0, 0};
#endif /* MODULE_NETDEV_BASE */

View File

@ -1,247 +0,0 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
* Copyright (C) 2013 INRIA
*
* 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_cc110x
* @{
* @file
* @brief Functions for packet reception and transmission on cc110x devices
*
* @author Oliver Hahm <oliver.hahm@inria.fr>
* @author Fabian Nack <nack@inf.fu-berlin.de>
* @}
*/
#include <stdio.h>
#include "cc110x.h"
#include "cc110x-internal.h"
#include "periph/gpio.h"
#include "irq.h"
#include "kernel_types.h"
#include "hwtimer.h"
#include "msg.h"
#include "transceiver.h"
#include "cpu_conf.h"
#include "cpu.h"
#ifdef MODULE_NETDEV_BASE
#include "netdev/base.h"
netdev_rcv_data_cb_t cc110x_recv_cb = NULL;
#endif
/* Internal function prototypes */
static uint8_t receive_packet_variable(uint8_t *rxBuffer, radio_packet_length_t length);
static uint8_t receive_packet(uint8_t *rxBuffer, radio_packet_length_t length);
/* Global variables */
rx_buffer_t cc110x_rx_buffer[RX_BUF_SIZE]; /* RX buffer */
volatile uint8_t rx_buffer_next; /* Next packet in RX queue */
void cc110x_rx_handler(void *args)
{
uint8_t res = 0;
/* Possible packet received, RX -> IDLE (0.1 us) */
cc110x_statistic.packets_in++;
res = receive_packet((uint8_t *)&(cc110x_rx_buffer[rx_buffer_next].packet),
sizeof(cc110x_packet_t));
if (res) {
/* If we are sending a burst, don't accept packets.
* Only ACKs are processed (for stopping the burst).
* Same if state machine is in TX lock. */
if (radio_state == RADIO_SEND_BURST) {
cc110x_statistic.packets_in_while_tx++;
return;
}
cc110x_rx_buffer[rx_buffer_next].rssi = rflags._RSSI;
cc110x_rx_buffer[rx_buffer_next].lqi = rflags._LQI;
cc110x_strobe(CC1100_SFRX); /* ...for flushing the RX FIFO */
/* Valid packet. After a wake-up, the radio should be in IDLE.
* So put CC110x to RX for WOR_TIMEOUT (have to manually put
* the radio back to sleep/WOR). */
cc110x_write_reg(CC1100_MCSM2, 0x07); /* Configure RX_TIME (until end of packet) */
cc110x_strobe(CC1100_SRX);
hwtimer_wait(IDLE_TO_RX_TIME);
radio_state = RADIO_RX;
#ifdef MODULE_TRANSCEIVER
/* notify transceiver thread if any */
if (transceiver_pid != KERNEL_PID_UNDEF) {
msg_t m;
m.type = (uint16_t) RCV_PKT_CC1100;
m.content.value = rx_buffer_next;
msg_send_int(&m, transceiver_pid);
}
#endif
#ifdef MODULE_NETDEV_BASE
if (cc110x_recv_cb != NULL) {
cc110x_packet_t p = cc110x_rx_buffer[rx_buffer_next].packet;
cc110x_recv_cb(&cc110x_dev, &p.phy_src, sizeof(uint8_t), &p.address,
sizeof(uint8_t), p.data, p.length - CC1100_HEADER_LENGTH);
}
#endif
/* shift to next buffer element */
if (++rx_buffer_next == RX_BUF_SIZE) {
rx_buffer_next = 0;
}
return;
}
else {
/* CRC false or RX buffer full -> clear RX FIFO in both cases */
cc110x_strobe(CC1100_SIDLE); /* Switch to IDLE (should already be)... */
cc110x_strobe(CC1100_SFRX); /* ...for flushing the RX FIFO */
/* If currently sending, exit here (don't go to RX/WOR) */
if (radio_state == RADIO_SEND_BURST) {
cc110x_statistic.packets_in_while_tx++;
return;
}
/* No valid packet, so go back to RX/WOR as soon as possible */
cc110x_switch_to_rx();
}
}
static uint8_t receive_packet_variable(uint8_t *rxBuffer, radio_packet_length_t length)
{
uint8_t status[2];
/* Any bytes available in RX FIFO? */
if ((cc110x_read_status(CC1100_RXBYTES) & BYTES_IN_RXFIFO)) {
uint8_t packetLength = 0;
/* Read length byte (first byte in RX FIFO) */
packetLength = cc110x_read_reg(CC1100_RXFIFO);
/* Read data from RX FIFO and store in rxBuffer */
if (packetLength <= length) {
uint8_t crc_ok = 0;
/* Put length byte at first position in RX Buffer */
rxBuffer[0] = packetLength;
/* Read the rest of the packet */
cc110x_readburst_reg(CC1100_RXFIFO, (char *) rxBuffer + 1, packetLength);
/* Read the 2 appended status bytes (status[0] = RSSI, status[1] = LQI) */
cc110x_readburst_reg(CC1100_RXFIFO, (char *)status, 2);
/* Store RSSI value of packet */
rflags._RSSI = status[I_RSSI];
/* MSB of LQI is the CRC_OK bit */
crc_ok = (status[I_LQI] & CRC_OK) >> 7;
if (!crc_ok) {
cc110x_statistic.packets_in_crc_fail++;
}
/* Bit 0-6 of LQI indicates the link quality (LQI) */
rflags._LQI = status[I_LQI] & LQI_EST;
return crc_ok;
}
/* too many bytes in FIFO */
else {
/* RX FIFO gets automatically flushed if return value is false */
return 0;
}
}
/* no bytes in RX FIFO */
else {
/* RX FIFO gets automatically flushed if return value is false */
return 0;
}
}
static uint8_t receive_packet(uint8_t *rxBuffer, radio_packet_length_t length)
{
uint8_t pkt_len_cfg = cc110x_read_reg(CC1100_PKTCTRL0) & PKT_LENGTH_CONFIG;
if (pkt_len_cfg == VARIABLE_PKTLEN) {
return receive_packet_variable(rxBuffer, length);
}
/* Fixed packet length not supported. */
/* RX FIFO get automatically flushed if return value is false */
return 0;
}
int8_t cc110x_send(cc110x_packet_t *packet)
{
volatile uint32_t abort_count;
uint8_t size;
radio_state = RADIO_SEND_BURST;
/*
* Number of bytes to send is:
* length of phy payload (packet->length)
* + size of length field (1 byte)
*/
size = packet->length + 1;
/* The number of bytes to be transmitted must be smaller
* or equal to PACKET_LENGTH (62 bytes). So the receiver
* can put the whole packet in its RX-FIFO (with appended
* packet status bytes).*/
if (size > PACKET_LENGTH) {
return 0;
}
packet->phy_src = cc110x_get_address();
/* Disable RX interrupt */
gpio_irq_disable(CC110X_GDO2);
/* Put CC110x in IDLE mode to flush the FIFO */
cc110x_strobe(CC1100_SIDLE);
/* Flush TX FIFO to be sure it is empty */
cc110x_strobe(CC1100_SFTX);
/* Write packet into TX FIFO */
cc110x_writeburst_reg(CC1100_TXFIFO, (char *) packet, size);
/* Switch to TX mode */
abort_count = 0;
unsigned int cpsr = disableIRQ();
cc110x_strobe(CC1100_STX);
/* Wait for GDO2 to be set -> sync word transmitted */
while (gpio_read(CC110X_GDO2) == 0) {
abort_count++;
if (abort_count > CC1100_SYNC_WORD_TX_TIME) {
/* Abort waiting. CC110x maybe in wrong mode */
break;
}
}
restoreIRQ(cpsr);
/* Wait for GDO2 to be cleared -> end of packet */
while (gpio_read(CC110X_GDO2) != 0);
gpio_irq_enable(CC110X_GDO2);
cc110x_statistic.raw_packets_out++;
/* Go to RX mode after TX */
cc110x_switch_to_rx();
return size;
}

View File

@ -1,6 +0,0 @@
DIRS = spi
ifneq (,$(filter chronos,$(BOARD)))
DIRS =
endif
include $(RIOTBASE)/Makefile.base

View File

@ -1,119 +0,0 @@
/*
* Copyright (C) 2013 INRIA
*
* 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_cc110x_legacy
* @{
*
* @file
* @brief TI Chipcon CC110x default settings
*
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @author Oliver Hahm <oliver.hahm@inria.fr>
* @}
*/
#include "cc110x_legacy.h"
// Default PA table index (output power)
#define PATABLE (11)
/**
* Usable, non overlapping channels and corresponding frequencies
* for use with CC1100. CHANNR is the register for selecting a channel.
*
* channel number | CHANNR | frequency [MHz]
* -----------------------------------------
* 0 | 0 | 869.525
* 1 | 10 | 871.61
* 2 | 20 | 873.58 ~ seems to be bad (hang-ups with this channel)
* 3 | 30 | 875.61
* 4 | 40 | 877.58
* 5 | 50 | 879.61
* 6 | 60 | 881.58
* 7 | 70 | 883.61
* 8 | 80 | 885.58
* 9 | 90 | 887.61
* 10 | 100 | 889.58
* 11 | 110 | 891.57
* 12 | 120 | 893.58
* 13 | 130 | 895.61
* 14 | 140 | 897.58
* 15 | 150 | 899.57
* 16 | 160 | 901.57
* 17 | 170 | 903.61
* 18 | 180 | 905.57
* 19 | 190 | 907.57
* 20 | 200 | 909.57
* 21 | 210 | 911.57
* 22 | 220 | 913.57
* 23 | 230 | 915.61
* 24 | 240 | 917.61
*/
// 400 kbps, MSK, X-tal: 26 MHz (Chip Revision F)
char cc110x_conf[] = {
0x06, // IOCFG2
0x2E, // IOCFG1
0x0E, // IOCFG0
0x0F, // FIFOTHR
0x9B, // SYNC1
0xAD, // SYNC0
0x3D, // PKTLEN (maximum value of packet length byte = 61)
0x06, // PKTCTRL1
0x45, // PKTCTRL0 (variable packet length)
0xFF, // ADDR
CC1100_DEFAULT_CHANNR * 10, // CHANNR
0x0B, // FSCTRL1
0x00, // FSCTRL0
0x21, // FREQ2
0x71, // FREQ1
0x7A, // FREQ0
0x2D, // MDMCFG4
0xF8, // MDMCFG3
0x73, // MDMCFG2
0x42, // MDMCFG1
0xF8, // MDMCFG0
0x00, // DEVIATN
0x07, // MCSM2
0x03, // MCSM1
0x18, // MCSM0
0x1D, // FOCCFG
0x1C, // BSCFG
0xC0, // AGCCTRL2
0x49, // AGCCTRL1, (old value was 0x49 -> made carrier sense less sensitive!)
// 0x47 - 7 dB above MAGN_TARGET setting
0xB2, // AGCCTRL0
0x87, // WOREVT1
0x6B, // WOREVT0
0xF8, // WORCTRL
0xB6, // FREND1
0x10, // FREND0
0xEA, // FSCAL3
0x2A, // FSCAL2
0x00, // FSCAL1
0x1F, // FSCAL0
0x00 // padding to 4 bytes
};
uint8_t pa_table_index = PATABLE; ///< Current PATABLE Index
uint8_t pa_table[] = { ///< PATABLE with available output powers
0x00, ///< -52 dBm
0x03, ///< -30 dBm
0x0D, ///< -20 dBm
0x1C, ///< -15 dBm
0x34, ///< -10 dBm
0x57, ///< - 5 dBm
0x3F, ///< - 1 dBm
0x8E, ///< 0 dBm
0x85, ///< + 5 dBm
0xCC, ///< + 7 dBm
0xC6, ///< + 9 dBm
0xC3 ///< +10 dBm
}; // If PATABLE is changed in size, adjust MAX_OUTPUT_POWER definition in CC1100 interface!

View File

@ -1,203 +0,0 @@
/*
* Copyright (C) 2008 Freie Universität Berlin
* Copyright (C) 2013 INRIA
*
* 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_cc110x_legacy
* @{
*
* @file
* @brief Driver internal constants for 110x chip configuration
*
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @author Oliver Hahm <oliver.hahm@inria.fr>
*/
#ifndef CC1100_INTERNAL_H
#define CC1100_INTERNAL_H
#ifdef __cplusplus
extern "C" {
#endif
#define FIXED_PKTLEN (0x00) ///< Fixed length packets, length configured in PKTLEN register.
#define VARIABLE_PKTLEN (0x01) ///< Variable length packets, packet length configured by the first
///< byte after synch word.
/**
* @name Bitmasks for reading out status register values
* @{
*/
/**
* @brief Bitmask (=10000000) for reading CRC_OK.
*
* If CRC_OK == 1: CRC for received data OK (or CRC disabled).
* If CRC_OK == 0: CRC error in received data.
*/
#define CRC_OK (0x80)
/**
* @brief Bitmask (=01111111) for reading LQI_EST.
*
* The Link Quality Indicator estimates how easily a received signal can be demodulated.
*/
#define LQI_EST (0x7F)
#define I_RSSI (0x00) ///< Index 0 contains RSSI information (from optionally appended packet status bytes).
#define I_LQI (0x01) ///< Index 1 contains LQI & CRC_OK information (from optionally appended packet status bytes).
#define MARC_STATE (0x1F) ///< Bitmask (=00011111) for reading MARC_STATE in MARCSTATE status register.
#define CS (0x40) ///< Bitmask (=01000000) for reading CS (Carrier Sense) in PKTSTATUS status register.
#define PQT_REACHED (0x20) ///< Bitmask (=00100000) for reading PQT_REACHED (Preamble Quality reached) in PKTSTATUS status register.
#define CCA (0x10) ///< Bitmask (=00010000) for reading CCA (clear channel assessment) in PKTSTATUS status register.
#define SFD (0x08) ///< Bitmask (=00001000) for reading SFD (Sync word found) in PKTSTATUS status register.
#define GDO2 (0x04) ///< Bitmask (=00000100) for reading GDO2 (current value on GDO2 pin) in PKTSTATUS status register.
#define GDO1 (0x02) ///< Bitmask (=00000010) for reading GDO1 (current value on GDO1 pin) in PKTSTATUS status register.
#define GDO0 (0x01) ///< Bitmask (=00000001) for reading GDO0 (current value on GDO0 pin) in PKTSTATUS status register.
#define TXFIFO_UNDERFLOW (0x80) ///< Bitmask (=10000000) for reading TXFIFO_UNDERFLOW in TXBYTES status register.
#define BYTES_IN_TXFIFO (0x7F) ///< Bitmask (=01111111) for reading NUM_TXBYTES in TXBYTES status register.
#define RXFIFO_OVERFLOW (0xBF) ///< Bitmask (=10000000) for reading RXFIFO_OVERFLOW in RXBYTES status register.
#define BYTES_IN_RXFIFO (0xFF) ///< Bitmask (=01111111) for reading NUM_RXBYTES in RXBYTES status register.
/** @} */
/**
* @name Bitmasks for reading out configuration register values
* @{
*/
#define PKT_LENGTH_CONFIG (0x03) ///< Bitmask (=00000011) for reading LENGTH_CONFIG in PKTCTRL0 configuration register.
/** @} */
/**
* @name Definitions to support burst/single access
* @{
*/
#define CC1100_WRITE_BURST (0x40) ///< Offset for burst write.
#define CC1100_READ_SINGLE (0x80) ///< Offset for read single byte.
#define CC1100_READ_BURST (0xC0) ///< Offset for read burst.
#define CC1100_NOBYTE (0xFF) ///< No command (for reading).
/** @} */
/**
* @name Configuration Registers (47x)
* @{
*/
#define CC1100_IOCFG2 (0x00) ///< GDO2 output pin configuration
#define CC1100_IOCFG1 (0x01) ///< GDO1 output pin configuration
#define CC1100_IOCFG0 (0x02) ///< GDO0 output pin configuration
#define CC1100_FIFOTHR (0x03) ///< RX FIFO and TX FIFO thresholds
#define CC1100_SYNC1 (0x04) ///< Sync word, high byte
#define CC1100_SYNC0 (0x05) ///< Sync word, low byte
#define CC1100_PKTLEN (0x06) ///< Packet length
#define CC1100_PKTCTRL1 (0x07) ///< Packet automation control
#define CC1100_PKTCTRL0 (0x08) ///< Packet automation control
#define CC1100_ADDR (0x09) ///< Device address
#define CC1100_CHANNR (0x0A) ///< Channel number
#define CC1100_FSCTRL1 (0x0B) ///< Frequency synthesizer control
#define CC1100_FSCTRL0 (0x0C) ///< Frequency synthesizer control
#define CC1100_FREQ2 (0x0D) ///< Frequency control word, high byte
#define CC1100_FREQ1 (0x0E) ///< Frequency control word, middle byte
#define CC1100_FREQ0 (0x0F) ///< Frequency control word, low byte
#define CC1100_MDMCFG4 (0x10) ///< Modem configuration
#define CC1100_MDMCFG3 (0x11) ///< Modem configuration
#define CC1100_MDMCFG2 (0x12) ///< Modem configuration
#define CC1100_MDMCFG1 (0x13) ///< Modem configuration
#define CC1100_MDMCFG0 (0x14) ///< Modem configuration
#define CC1100_DEVIATN (0x15) ///< Modem deviation setting
#define CC1100_MCSM2 (0x16) ///< Main Radio Control State Machine configuration
#define CC1100_MCSM1 (0x17) ///< Main Radio Control State Machine configuration
#define CC1100_MCSM0 (0x18) ///< Main Radio Control State Machine configuration
#define CC1100_FOCCFG (0x19) ///< Frequency Offset Compensation configuration
#define CC1100_BSCFG (0x1A) ///< Bit Synchronization configuration
#define CC1100_AGCCTRL2 (0x1B) ///< AGC control
#define CC1100_AGCCTRL1 (0x1C) ///< AGC control
#define CC1100_AGCCTRL0 (0x1D) ///< AGC control
#define CC1100_WOREVT1 (0x1E) ///< High byte Event 0 timeout
#define CC1100_WOREVT0 (0x1F) ///< Low byte Event 0 timeout
#define CC1100_WORCTRL (0x20) ///< Wake On Radio control
#define CC1100_FREND1 (0x21) ///< Front end RX configuration
#define CC1100_FREND0 (0x22) ///< Front end TX configuration
#define CC1100_FSCAL3 (0x23) ///< Frequency synthesizer calibration
#define CC1100_FSCAL2 (0x24) ///< Frequency synthesizer calibration
#define CC1100_FSCAL1 (0x25) ///< Frequency synthesizer calibration
#define CC1100_FSCAL0 (0x26) ///< Frequency synthesizer calibration
#define CC1100_RCCTRL1 (0x27) ///< RC oscillator configuration
#define CC1100_RCCTRL0 (0x28) ///< RC oscillator configuration
#define CC1100_FSTEST (0x29) ///< Frequency synthesizer calibration control
#define CC1100_PTEST (0x2A) ///< Production test
#define CC1100_AGCTEST (0x2B) ///< AGC test
#define CC1100_TEST2 (0x2C) ///< Various test settings
#define CC1100_TEST1 (0x2D) ///< Various test settings
#define CC1100_TEST0 (0x2E) ///< Various test settings
/** @} */
/**
* @name Strobe commands (14x)
* @{
*/
#define CC1100_SRES (0x30) ///< Reset chip.
/**
* @brief Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1).
*
* If in RX/TX: Go to a wait state where only the synthesizer is running (for quick RX / TX turnaround).
*/
#define CC1100_SFSTXON (0x31)
#define CC1100_SXOFF (0x32) ///< Turn off crystal oscillator.
#define CC1100_SCAL (0x33) ///< Calibrate frequency synthesizer and turn it off (enables quick start).
#define CC1100_SRX (0x34) ///< Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL=1.
/**
* In IDLE state: Enable TX. Perform calibration first if MCSM0.FS_AUTOCAL=1.
* If in RX state and CCA is enabled: Only go to TX if channel is clear.
*/
#define CC1100_STX (0x35)
#define CC1100_SIDLE (0x36) ///< Exit RX / TX, turn off frequency synthesizer and exit WOR mode if applicable.
#define CC1100_SAFC (0x37) ///< Perform AFC adjustment of the frequency synthesizer
#define CC1100_SWOR (0x38) ///< Start automatic RX polling sequence (Wake-on-Radio)
#define CC1100_SPWD (0x39) ///< Enter power down mode when CSn goes high.
#define CC1100_SFRX (0x3A) ///< Flush the RX FIFO buffer (CC1100 should be in IDLE state).
#define CC1100_SFTX (0x3B) ///< Flush the TX FIFO buffer (CC1100 should be in IDLE state).
#define CC1100_SWORRST (0x3C) ///< Reset real time clock.
#define CC1100_SNOP (0x3D) ///< No operation. May be used to pad strobe commands to two bytes for simpler software.
/** @} */
/**
* @name Status registers (12x)
* @{
*/
#define CC1100_PARTNUM (0x30) ///< Part number of CC1100.
#define CC1100_VERSION (0x31) ///< Current version number.
#define CC1100_FREQEST (0x32) ///< Frequency Offset Estimate.
#define CC1100_LQI (0x33) ///< Demodulator estimate for Link Quality.
#define CC1100_RSSI (0x34) ///< Received signal strength indication.
#define CC1100_MARCSTATE (0x35) ///< Control state machine state.
#define CC1100_WORTIME1 (0x36) ///< High byte of WOR timer.
#define CC1100_WORTIME0 (0x37) ///< Low byte of WOR timer.
#define CC1100_PKTSTATUS (0x38) ///< Current GDOx status and packet status.
#define CC1100_VCO_VC_DAC (0x39) ///< Current setting from PLL calibration module.
#define CC1100_TXBYTES (0x3A) ///< Underflow and number of bytes in the TX FIFO.
#define CC1100_RXBYTES (0x3B) ///< Overflow and number of bytes in the RX FIFO.
/** @} */
/**
* @name Multi byte registers
* @{
*/
/**
* @brief Register for eight user selected output power settings.
*
* 3-bit FREND0.PA_POWER value selects the PATABLE entry to use.
*/
#define CC1100_PATABLE (0x3E)
#define CC1100_TXFIFO (0x3F) ///< TX FIFO: Write operations write to the TX FIFO (SB: +0x00; BURST: +0x40)
#define CC1100_RXFIFO (0x3F) ///< RX FIFO: Read operations read from the RX FIFO (SB: +0x80; BURST: +0xC0)
/** @} */
#ifdef __cplusplus
}
#endif
/** @} */
#endif

View File

@ -1,228 +0,0 @@
/*
* Copyright (C) 2009 Freie Universität Berlin
* Copyright (C) 2013 INRIA
*
* 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_cc110x_legacy
* @{
* @file
* @brief Functions for packet reception on cc110x
*
* @author Oliver Hahm <oliver.hahm@inria.fr>
* @}
*/
#include "cc110x_legacy.h"
#include "cc110x-internal.h"
#include "kernel_types.h"
#include "hwtimer.h"
#include "msg.h"
#include "transceiver.h"
#include "cpu_conf.h"
#include "cpu.h"
#ifdef DBG_IGNORE
#include <stdio.h>
#include <string.h>
#define IGN_MAX (10)
radio_address_t ignored_addr[IGN_MAX];
static uint8_t is_ignored(radio_address_t addr);
#endif
static uint8_t receive_packet_variable(uint8_t *rxBuffer, radio_packet_length_t length);
static uint8_t receive_packet(uint8_t *rxBuffer, radio_packet_length_t length);
rx_buffer_t cc110x_rx_buffer[RX_BUF_SIZE]; ///< RX buffer
volatile uint8_t rx_buffer_next; ///< Next packet in RX queue
void cc110x_rx_handler(void)
{
uint8_t res = 0;
/* Possible packet received, RX -> IDLE (0.1 us) */
rflags.CAA = 0;
rflags.MAN_WOR = 0;
cc110x_statistic.packets_in++;
res = receive_packet((uint8_t *)&(cc110x_rx_buffer[rx_buffer_next].packet), sizeof(cc110x_packet_t));
if (res) {
/* If we are sending a burst, don't accept packets.
* Only ACKs are processed (for stopping the burst).
* Same if state machine is in TX lock. */
if (radio_state == RADIO_SEND_BURST || rflags.TX) {
cc110x_statistic.packets_in_while_tx++;
return;
}
cc110x_rx_buffer[rx_buffer_next].rssi = rflags._RSSI;
cc110x_rx_buffer[rx_buffer_next].lqi = rflags._LQI;
cc110x_strobe(CC1100_SFRX); /* ...for flushing the RX FIFO */
/* Valid packet. After a wake-up, the radio should be in IDLE.
* So put CC1100 to RX for WOR_TIMEOUT (have to manually put
* the radio back to sleep/WOR). */
//cc110x_spi_write_reg(CC1100_MCSM0, 0x08); /* Turn off FS-Autocal */
cc110x_write_reg(CC1100_MCSM2, 0x07); /* Configure RX_TIME (until end of packet) */
cc110x_strobe(CC1100_SRX);
hwtimer_wait(IDLE_TO_RX_TIME);
radio_state = RADIO_RX;
#ifdef DBG_IGNORE
if (is_ignored(cc110x_rx_buffer[rx_buffer_next].packet.phy_src)) {
LED_RED_TOGGLE;
return;
}
#endif
/* notify transceiver thread if any */
if (transceiver_pid != KERNEL_PID_UNDEF) {
msg_t m;
m.type = (uint16_t) RCV_PKT_CC1100;
m.content.value = rx_buffer_next;
msg_send_int(&m, transceiver_pid);
}
/* shift to next buffer element */
if (++rx_buffer_next == RX_BUF_SIZE) {
rx_buffer_next = 0;
}
return;
}
else {
/* No ACK received so TOF is unpredictable */
rflags.TOF = 0;
/* CRC false or RX buffer full -> clear RX FIFO in both cases */
cc110x_strobe(CC1100_SIDLE); /* Switch to IDLE (should already be)... */
cc110x_strobe(CC1100_SFRX); /* ...for flushing the RX FIFO */
/* If packet interrupted this nodes send call,
* don't change anything after this point. */
if (radio_state == RADIO_AIR_FREE_WAITING) {
cc110x_strobe(CC1100_SRX);
hwtimer_wait(IDLE_TO_RX_TIME);
return;
}
/* If currently sending, exit here (don't go to RX/WOR) */
if (radio_state == RADIO_SEND_BURST) {
cc110x_statistic.packets_in_while_tx++;
return;
}
/* No valid packet, so go back to RX/WOR as soon as possible */
cc110x_switch_to_rx();
}
}
static uint8_t receive_packet_variable(uint8_t *rxBuffer, radio_packet_length_t length)
{
uint8_t status[2];
uint8_t packetLength = 0;
/* Any bytes available in RX FIFO? */
if ((cc110x_read_status(CC1100_RXBYTES) & BYTES_IN_RXFIFO)) {
/* Read length byte (first byte in RX FIFO) */
cc110x_read_fifo((char *) &packetLength, 1);
/* Read data from RX FIFO and store in rxBuffer */
if (packetLength <= length) {
/* Put length byte at first position in RX Buffer */
rxBuffer[0] = packetLength;
/* Read the rest of the packet */
//cc110x_readburst_reg(CC1100_RXFIFO, (char*)rxBuffer+1, packetLength);
cc110x_read_fifo((char *) rxBuffer + 1, packetLength);
/* Read the 2 appended status bytes (status[0] = RSSI, status[1] = LQI) */
cc110x_readburst_reg(CC1100_RXFIFO, (char *)status, 2);
/* Store RSSI value of packet */
rflags._RSSI = status[I_RSSI];
/* MSB of LQI is the CRC_OK bit */
rflags.CRC_STATE = (status[I_LQI] & CRC_OK) >> 7;
if (!rflags.CRC_STATE) {
cc110x_statistic.packets_in_crc_fail++;
}
/* Bit 0-6 of LQI indicates the link quality (LQI) */
rflags._LQI = status[I_LQI] & LQI_EST;
return rflags.CRC_STATE;
}
/* too many bytes in FIFO */
else {
/* RX FIFO get automatically flushed if return value is false */
return 0;
}
}
/* no bytes in RX FIFO */
else {
/* RX FIFO get automatically flushed if return value is false */
return 0;
}
}
static uint8_t receive_packet(uint8_t *rxBuffer, radio_packet_length_t length)
{
uint8_t pkt_len_cfg = cc110x_read_reg(CC1100_PKTCTRL0) & PKT_LENGTH_CONFIG;
if (pkt_len_cfg == VARIABLE_PKTLEN) {
return receive_packet_variable(rxBuffer, length);
}
/* Fixed packet length not supported. */
/* RX FIFO get automatically flushed if return value is false */
return 0;
}
#ifdef DBG_IGNORE
void cc110x_init_ignore(void)
{
memset(ignored_addr, 0, IGN_MAX * sizeof(radio_address_t));
}
uint8_t cc110x_add_ignored(radio_address_t addr)
{
uint8_t i = 0;
while ((i < IGN_MAX) && ignored_addr[i++]) {
printf("i: %hu\n", i);
}
if (i > IGN_MAX) {
return 0;
}
ignored_addr[i - 1] = addr;
return 1;
}
static uint8_t is_ignored(radio_address_t addr)
{
uint8_t i;
for (i = 0; i < IGN_MAX; i++) {
if (ignored_addr[i] == addr) {
return 1;
}
}
return 0;
}
#endif

View File

@ -1,94 +0,0 @@
/*
* Copyright (C) 2009 Freie Universität Berlin
* Copyright (C) 2013 INRIA
*
* 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_cc110x_legacy
* @{
* @file
* @brief Functions for packet transmission on cc110x
*
* @author Oliver Hahm <oliver.hahm@inria.fr>
* @}
*/
#include <stdio.h>
#include "cc110x_legacy.h"
#include "cc110x-internal.h"
#include "irq.h"
int8_t cc110x_send(cc110x_packet_t *packet)
{
volatile uint32_t abort_count;
uint8_t size;
/* TODO: burst sending */
radio_state = RADIO_SEND_BURST;
rflags.LL_ACK = 0;
/*
* Number of bytes to send is:
* length of phy payload (packet->length)
* + size of length field (1 byte)
*/
size = packet->length + 1;
/* The number of bytes to be transmitted must be smaller
* or equal to PACKET_LENGTH (62 bytes). So the receiver
* can put the whole packet in its RX-FIFO (with appended
* packet status bytes).*/
if (size > PACKET_LENGTH) {
return 0;
}
packet->phy_src = cc110x_get_address();
/* Disables RX interrupt etc. */
cc110x_before_send();
/* But CC1100 in IDLE mode to flush the FIFO */
cc110x_strobe(CC1100_SIDLE);
/* Flush TX FIFO to be sure it is empty */
cc110x_strobe(CC1100_SFTX);
/* Write packet into TX FIFO */
cc110x_writeburst_reg(CC1100_TXFIFO, (char *) packet, size);
/* Switch to TX mode */
abort_count = 0;
unsigned int cpsr = disableIRQ();
cc110x_strobe(CC1100_STX);
/* Wait for GDO2 to be set -> sync word transmitted */
while (cc110x_get_gdo2() == 0) {
abort_count++;
if (abort_count > CC1100_SYNC_WORD_TX_TIME) {
/* Abort waiting. CC1100 maybe in wrong mode */
/* e.g. sending preambles for always */
puts("[CC1100 TX] fatal error\n");
break;
}
}
restoreIRQ(cpsr);
/* Wait for GDO2 to be cleared -> end of packet */
while (cc110x_get_gdo2() != 0);
/* Experimental - TOF Measurement */
cc110x_after_send();
cc110x_statistic.raw_packets_out++;
/* Store number of transmission retries */
rflags.TX = 0;
/* Go to mode after TX (CONST_RX -> RX, WOR -> WOR) */
cc110x_switch_to_rx();
return size;
}

View File

@ -1,424 +0,0 @@
/*
* Copyright (C) 2013 Freie Universität Berlin
* Copyright (C) 2013 INRIA
*
* 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_cc110x_legacy
* @{
* @file
* @brief Basic functionality of cc110x driver
*
* @author Oliver Hahm <oliver.hahm@inria.fr>
* @}
*/
#include "cc110x_legacy.h"
#include "cc110x-internal.h"
#include "hwtimer.h"
#include "config.h"
#include "cpu.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
/* some externals */
extern uint8_t pa_table[]; ///< PATABLE with available output powers
extern uint8_t pa_table_index; ///< Current PATABLE Index
/* global variables */
cc110x_statistic_t cc110x_statistic;
volatile cc110x_flags rflags; ///< Radio control flags
volatile uint8_t radio_state = RADIO_UNKNOWN; ///< Radio state
static radio_address_t radio_address; ///< Radio address
static uint8_t radio_channel; ///< Radio channel
/* internal function prototypes */
static int rd_set_mode(int mode);
static void reset(void);
static void power_up_reset(void);
static void write_register(uint8_t r, uint8_t value);
/*---------------------------------------------------------------------------*
* Radio Driver API *
*---------------------------------------------------------------------------*/
void cc110x_init(kernel_pid_t tpid)
{
transceiver_pid = tpid;
DEBUG("Transceiver PID: %" PRIkernel_pid "\n", transceiver_pid);
rx_buffer_next = 0;
#ifdef MODULE_CC110X_SPI
/* Initialize SPI */
cc110x_spi_init();
#endif
/* Load driver & reset */
power_up_reset();
/* Write configuration to configuration registers */
cc110x_writeburst_reg(0x00, cc110x_conf, CC1100_CONF_SIZE);
/* Write PATABLE (power settings) */
cc110x_write_reg(CC1100_PATABLE, pa_table[pa_table_index]);
/* Initialize Radio Flags */
rflags._RSSI = 0x00;
rflags.LL_ACK = 0;
rflags.CAA = 0;
rflags.CRC_STATE = 0;
rflags.SEQ = 0;
rflags.MAN_WOR = 0;
rflags.KT_RES_ERR = 0;
rflags.TX = 0;
rflags.WOR_RST = 0;
/* Set default channel number */
#ifdef MODULE_CONFIG
cc110x_set_config_channel(sysconfig.radio_channel);
#else
cc110x_set_channel(CC1100_DEFAULT_CHANNR);
#endif
DEBUG("CC1100 initialized and set to channel %i\n", radio_channel);
/* Switch to desired mode (WOR or RX) */
rd_set_mode(RADIO_MODE_ON);
#ifdef DBG_IGNORE
cc110x_init_ignore();
#endif
}
void cc110x_disable_interrupts(void)
{
cc110x_gdo2_disable();
cc110x_gdo0_disable();
}
void cc110x_gdo0_irq(void)
{
/* Air was not free -> Clear CCA flag */
rflags.CAA = false;
/* Disable carrier sense detection (GDO0 interrupt) */
cc110x_gdo0_disable();
}
void cc110x_gdo2_irq(void)
{
cc110x_rx_handler();
}
uint8_t cc110x_get_buffer_pos(void)
{
return (rx_buffer_next - 1);
}
radio_address_t cc110x_get_address(void)
{
return radio_address;
}
radio_address_t cc110x_set_address(radio_address_t address)
{
if ((address < MIN_UID) || (address > MAX_UID)) {
return 0;
}
uint8_t id = (uint8_t) address;
if (radio_state != RADIO_UNKNOWN) {
write_register(CC1100_ADDR, id);
}
radio_address = id;
return radio_address;
}
#ifdef MODULE_CONFIG
radio_address_t cc110x_set_config_address(radio_address_t address)
{
radio_address_t a = cc110x_set_address(address);
if (a) {
sysconfig.radio_address = a;
}
config_save();
return a;
}
#endif
void cc110x_set_monitor(uint8_t mode)
{
if (mode) {
write_register(CC1100_PKTCTRL1, (0x04));
}
else {
write_register(CC1100_PKTCTRL1, (0x06));
}
}
void cc110x_setup_rx_mode(void)
{
/* Stay in RX mode until end of packet */
cc110x_write_reg(CC1100_MCSM2, 0x07);
cc110x_switch_to_rx();
}
void cc110x_switch_to_rx(void)
{
radio_state = RADIO_RX;
cc110x_strobe(CC1100_SRX);
}
void cc110x_wakeup_from_rx(void)
{
if (radio_state != RADIO_RX) {
return;
}
DEBUG("CC1100 going to idle\n");
cc110x_strobe(CC1100_SIDLE);
radio_state = RADIO_IDLE;
}
char *cc110x_get_marc_state(void)
{
uint8_t state;
/* Save old radio state */
uint8_t old_state = radio_state;
/* Read content of status register */
state = cc110x_read_status(CC1100_MARCSTATE) & MARC_STATE;
/* Make sure in IDLE state.
* Only goes to IDLE if state was RX/WOR */
cc110x_wakeup_from_rx();
/* Have to put radio back to WOR/RX if old radio state
* was WOR/RX, otherwise no action is necessary */
if (old_state == RADIO_WOR || old_state == RADIO_RX) {
cc110x_switch_to_rx();
}
switch(state) {
/* Note: it is not possible to read back the SLEEP or XOFF state numbers
* because setting CSn low will make the chip enter the IDLE mode from the
* SLEEP (0) or XOFF (2) states. */
case 1:
return "IDLE";
case 3:
case 4:
case 5:
return "MANCAL";
case 6:
case 7:
return "FS_WAKEUP";
case 8:
case 12:
return "CALIBRATE";
case 9:
case 10:
case 11:
return "SETTLING";
case 13:
case 14:
case 15:
return "RX";
case 16:
return "TXRX_SETTLING";
case 17:
return "RXFIFO_OVERFLOW";
case 18:
return "FSTXON";
case 19:
case 20:
return "TX";
case 21:
return "RXTX_SETTLING";
case 22:
return "TXFIFO_UNDERFLOW";
default:
return "UNKNOWN";
}
}
char *cc110x_state_to_text(uint8_t state)
{
switch(state) {
case RADIO_UNKNOWN:
return "Unknown";
case RADIO_AIR_FREE_WAITING:
return "CS";
case RADIO_WOR:
return "WOR";
case RADIO_IDLE:
return "IDLE";
case RADIO_SEND_BURST:
return "TX BURST";
case RADIO_RX:
return "RX";
case RADIO_SEND_ACK:
return "TX ACK";
case RADIO_PWD:
return "PWD";
default:
return "unknown";
}
}
void cc110x_print_config(void)
{
printf("Current radio state: %s\r\n", cc110x_state_to_text(radio_state));
printf("Current MARC state: %s\r\n", cc110x_get_marc_state());
printf("Current channel number: %u\r\n", radio_channel);
}
void cc110x_switch_to_pwd(void)
{
DEBUG("[cc110x_legacy] switching to powerdown\n");
cc110x_wakeup_from_rx();
cc110x_strobe(CC1100_SPWD);
radio_state = RADIO_PWD;
}
/*---------------------------------------------------------------------------*/
int16_t cc110x_set_channel(uint8_t channr)
{
uint8_t state = cc110x_read_status(CC1100_MARCSTATE) & MARC_STATE;
if ((state != 1) && (channr > MAX_CHANNR)) {
return -1;
}
write_register(CC1100_CHANNR, channr * 10);
radio_channel = channr;
return radio_channel;
}
#ifdef MODULE_CONFIG
int16_t cc110x_set_config_channel(uint8_t channr)
{
int16_t c = cc110x_set_channel(channr);
if (c) {
sysconfig.radio_channel = c;
}
config_save();
return c;
}
#endif
int16_t cc110x_get_channel(void)
{
return radio_channel;
}
/*---------------------------------------------------------------------------
* CC1100 reset functionality
*---------------------------------------------------------------------------*/
static void reset(void)
{
cc110x_wakeup_from_rx();
#ifdef MODULE_CC110x_SPI
cc110x_spi_select();
#endif
cc110x_strobe(CC1100_SRES);
hwtimer_wait(RTIMER_TICKS(100));
}
static void power_up_reset(void)
{
#ifdef MODULE_CC110x_SPI
cc110x_spi_unselect();
cc110x_spi_cs();
cc110x_spi_unselect();
#endif
hwtimer_wait(RESET_WAIT_TIME);
reset();
radio_state = RADIO_IDLE;
}
static void write_register(uint8_t r, uint8_t value)
{
/* Save old radio state */
uint8_t old_state = radio_state;
/* Wake up from WOR/RX (if in WOR/RX, else no effect) */
cc110x_wakeup_from_rx();
cc110x_write_reg(r, value);
/* Have to put radio back to WOR/RX if old radio state
* was WOR/RX, otherwise no action is necessary */
if ((old_state == RADIO_WOR) || (old_state == RADIO_RX)) {
cc110x_switch_to_rx();
}
}
static int rd_set_mode(int mode)
{
int result;
/* Get current radio mode */
if ((radio_state == RADIO_UNKNOWN) || (radio_state == RADIO_PWD)) {
result = RADIO_MODE_OFF;
}
else {
result = RADIO_MODE_ON;
}
switch(mode) {
case RADIO_MODE_ON:
DEBUG("Enabling rx mode\n");
cc110x_init_interrupts(); /* Enable interrupts */
cc110x_setup_rx_mode(); /* Set chip to desired mode */
break;
case RADIO_MODE_OFF:
cc110x_disable_interrupts(); /* Disable interrupts */
cc110x_switch_to_pwd(); /* Set chip to power down mode */
break;
case RADIO_MODE_GET:
/* do nothing, just return current mode */
default:
/* do nothing */
break;
}
/* Return previous mode */
return result;
}

View File

@ -1,5 +0,0 @@
MODULE =cc110x_spi
INCLUDES += -I$(RIOTBASE)/drivers/cc110x_legacy
include $(RIOTBASE)/Makefile.base

View File

@ -1,113 +0,0 @@
/*
* Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved.
*
* 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_cc110x_legacy
* @{
*
* @file
* @brief TI Chipcon CC1100 SPI driver
*
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @}
*/
#include <stdio.h>
#include "cc110x_legacy.h"
#include "cc110x-internal.h"
#include "irq.h"
/*---------------------------------------------------------------------------*/
// CC1100 SPI access
/*---------------------------------------------------------------------------*/
uint8_t cc110x_writeburst_reg(uint8_t addr, char *src, uint8_t count)
{
int i = 0;
unsigned int cpsr = disableIRQ();
cc110x_spi_select();
cc110x_txrx(addr | CC1100_WRITE_BURST);
while (i < count) {
cc110x_txrx(src[i]);
i++;
}
cc110x_spi_unselect();
restoreIRQ(cpsr);
return count;
}
void cc110x_readburst_reg(uint8_t addr, char *buffer, uint8_t count)
{
int i = 0;
unsigned int cpsr = disableIRQ();
cc110x_spi_select();
cc110x_txrx(addr | CC1100_READ_BURST);
while (i < count) {
buffer[i] = cc110x_txrx(CC1100_NOBYTE);
i++;
}
cc110x_spi_unselect();
restoreIRQ(cpsr);
}
void cc110x_read_fifo(char *buffer, uint8_t count)
{
cc110x_readburst_reg(CC1100_RXFIFO, buffer, count);
}
void cc110x_write_reg(uint8_t addr, uint8_t value)
{
unsigned int cpsr = disableIRQ();
cc110x_spi_select();
cc110x_txrx(addr);
cc110x_txrx(value);
cc110x_spi_unselect();
restoreIRQ(cpsr);
}
uint8_t cc110x_read_reg(uint8_t addr)
{
uint8_t result;
unsigned int cpsr = disableIRQ();
cc110x_spi_select();
cc110x_txrx(addr | CC1100_READ_SINGLE);
result = cc110x_txrx(CC1100_NOBYTE);
cc110x_spi_unselect();
restoreIRQ(cpsr);
return result;
}
uint8_t cc110x_read_status(uint8_t addr)
{
uint8_t result;
unsigned int cpsr = disableIRQ();
cc110x_spi_select();
cc110x_txrx(addr | CC1100_READ_BURST);
result = cc110x_txrx(CC1100_NOBYTE);
cc110x_spi_unselect();
restoreIRQ(cpsr);
return result;
}
uint8_t cc110x_strobe(uint8_t c)
{
uint8_t result;
unsigned int cpsr = disableIRQ();
cc110x_spi_select();
result = cc110x_txrx(c);
cc110x_spi_unselect();
restoreIRQ(cpsr);
return result;
}

View File

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

View File

@ -1,44 +0,0 @@
/*
* Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved.
*
* 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.
*/
/**
* @file
* @ingroup LPC2387
* @brief CC1100 LPC2387 dependend functions
*
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @version $Revision: 1775 $
*
* @note $Id: arch_cc1100.h 1775 2010-01-26 09:37:03Z hillebra $
*/
#ifndef ARCH_CC1100_H
#define ARCH_CC1100_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
uint8_t cc110x_txrx(uint8_t c);
void cc110x_gdo0_enable(void);
void cc110x_gdo0_disable(void);
void cc110x_gdo2_enable(void);
void cc110x_gdo2_disable(void);
void cc110x_init_interrupts(void);
void cc110x_before_send(void);
void cc110x_after_send(void);
#ifdef __cplusplus
}
#endif
#endif /* ARCH_CC1100_H */

View File

@ -1,236 +0,0 @@
/*
* Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved.
*
* 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.
*/
/**
* @file
* @ingroup dev_cc110x_legacy_csma
* @brief ScatterWeb MSB-A2 mac-layer
*
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @version $Revision: 2128 $
*
* @note $Id: cc1100-csmaca-mac.c 2128 2010-05-12 12:07:59Z hillebra $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cc1100.h"
#include "cc1100_phy.h"
#include "cc1100-csmaca-mac.h"
#include "protocol-multiplex.h"
#include "hwtimer.h"
#include "vtimer.h"
/*---------------------------------------------------------------------------*/
#define COLLISION_STATE_INITIAL 1
#define COLLISION_STATE_MEASURE 2
#define COLLISION_STATE_KEEP 3
static uint32_t send_csmaca_calls = 0;
static uint32_t send_csmaca_calls_cs_timeout = 0;
static int collision_count;
static double collisions_per_sec = 0;
static int collision_state = COLLISION_STATE_INITIAL;
static timex_t collision_measurement_start;
static volatile int cs_hwtimer_id = -1;
static volatile int cs_timeout_flag = 0;
/*---------------------------------------------------------------------------*/
static void cs_timeout_cb(void *ptr)
{
(void) ptr;
cs_timeout_flag = 1;
}
/*---------------------------------------------------------------------------*/
int cc1100_send_csmaca(radio_address_t address, protocol_t protocol, int priority, char *payload, radio_packet_length_t payload_len)
{
uint16_t min_window_size;
uint16_t max_window_size;
uint16_t difs;
uint16_t slottime;
switch(priority) {
case PRIORITY_ALARM:
min_window_size = PRIO_ALARM_MIN_WINDOW_SIZE;
max_window_size = PRIO_ALARM_MAX_WINDOW_SIZE;
difs = PRIO_ALARM_DIFS;
slottime = PRIO_ALARM_SLOTTIME;
break;
case PRIORITY_WARNING:
min_window_size = PRIO_WARN_MIN_WINDOW_SIZE;
max_window_size = PRIO_WARN_MAX_WINDOW_SIZE;
difs = PRIO_WARN_DIFS;
slottime = PRIO_WARN_SLOTTIME;
break;
default:
min_window_size = PRIO_DATA_MIN_WINDOW_SIZE;
max_window_size = PRIO_DATA_MAX_WINDOW_SIZE;
difs = PRIO_DATA_DIFS;
slottime = PRIO_DATA_SLOTTIME;
}
/* Calculate collisions per second */
if (collision_state == COLLISION_STATE_INITIAL) {
vtimer_now(&collision_measurement_start);
collision_count = 0;
collisions_per_sec = 0;
collision_state = COLLISION_STATE_MEASURE;
}
else if (collision_state == COLLISION_STATE_MEASURE) {
timex_t now;
vtimer_now(&now);
timex_t timespan = timex_sub(now, collision_measurement_start);
if (timex_cmp(timespan, timex_set(1, 0)) > 0) {
collisions_per_sec = (collision_count * 1000000) / (double) timex_uint64(timespan);
if (collisions_per_sec > 0.5 && collisions_per_sec <= 2.2) {
timex_t now;
vtimer_now(&now);
collision_measurement_start = now;
collision_state = COLLISION_STATE_KEEP;
}
else if (collisions_per_sec > 2.2) {
timex_t now;
vtimer_now(&now);
collision_measurement_start = now;
collision_state = COLLISION_STATE_KEEP;
}
else {
collision_state = COLLISION_STATE_INITIAL;
}
}
}
else if (collision_state == COLLISION_STATE_KEEP) {
timex_t now;
vtimer_now(&now);
timex_t timespan = timex_sub(now, collision_measurement_start);
if (timex_cmp(timespan, timex_set(5, 0)) > 0) {
collision_state = COLLISION_STATE_INITIAL;
}
}
/* Adjust initial window size according to collision rate */
if (collisions_per_sec > 0.5 && collisions_per_sec <= 2.2) {
min_window_size *= 2;
}
else if (collisions_per_sec > 2.2) {
min_window_size *= 4;
}
uint16_t windowSize = min_window_size; /* Start with window size of PRIO_XXX_MIN_WINDOW_SIZE */
uint16_t backoff = 0; /* Backoff between 1 and windowSize */
uint32_t total; /* Holds the total wait time before send try */
uint32_t cs_timeout; /* Current carrier sense timeout value */
if (protocol == 0) {
return RADIO_INVALID_PARAM; /* Not allowed, protocol id must be greater zero */
}
cc1100_phy_mutex_lock(); /* Lock radio for exclusive access */
/* Get carrier sense timeout based on overall error rate till now */
send_csmaca_calls++;
int fail_percentage = (send_csmaca_calls_cs_timeout * 100) / send_csmaca_calls;
if (fail_percentage == 0) {
fail_percentage = 1;
}
cs_timeout = CARRIER_SENSE_TIMEOUT / fail_percentage;
if (cs_timeout < CARRIER_SENSE_TIMEOUT_MIN) {
cs_timeout = CARRIER_SENSE_TIMEOUT_MIN;
}
cc1100_cs_init(); /* Initialize carrier sensing */
window:
if (backoff != 0) {
goto cycle; /* If backoff was 0 */
}
windowSize *= 2; /* ...double the current window size */
if (windowSize > max_window_size) {
windowSize = max_window_size; /* This is the maximum size allowed */
}
backoff = rand() % windowSize; /* ...and choose new backoff */
backoff += (uint16_t) 1;
cycle:
cs_timeout_flag = 0; /* Carrier sense timeout flag */
cs_hwtimer_id = hwtimer_set(cs_timeout, /* Set hwtimer to set CS timeout flag */
cs_timeout_cb, NULL);
while (cc1100_cs_read()) { /* Wait until air is free */
if (cs_timeout_flag) {
send_csmaca_calls_cs_timeout++;
#ifndef CSMACA_MAC_AGGRESSIVE_MODE
cc1100_phy_mutex_unlock();
cc1100_go_after_tx(); /* Go from RX to default mode */
return RADIO_CS_TIMEOUT; /* Return immediately */
#endif
#ifdef CSMACA_MAC_AGGRESSIVE_MODE
goto send; /* Send anyway */
#endif
}
}
hwtimer_remove(cs_hwtimer_id); /* Remove hwtimer */
cc1100_cs_write_cca(1); /* Air is free now */
cc1100_cs_set_enabled(true);
if (cc1100_cs_read()) {
goto window; /* GDO0 triggers on rising edge, so */
}
/* test once after interrupt is enabled */
if (backoff > 0) {
backoff--; /* Decrement backoff counter */
}
total = slottime; /* Calculate total wait time */
total *= (uint32_t)backoff; /* Slot vector set */
total += difs; /* ...and standard DIFS wait time */
cs_timeout_flag = 0; /* Carrier sense timeout flag */
cs_hwtimer_id = hwtimer_set(total, /* Set hwtimer to set CS timeout flag */
cs_timeout_cb, NULL);
while (!cs_timeout_flag
|| !cc1100_cs_read_cca()) { /* Wait until timeout is finished */
if (cc1100_cs_read_cca() == 0) { /* Is the air still free? */
hwtimer_remove(cs_hwtimer_id);
goto window; /* No. Go back to new wait period. */
}
}
cc1100_cs_set_enabled(false);
#ifdef CSMACA_MAC_AGGRESSIVE_MODE
send:
#endif
int res = cc1100_send(address, protocol, priority, payload, payload_len);
if (res < 0) {
collision_count++;
}
return res;
}

View File

@ -1,63 +0,0 @@
/*
* Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved.
*
* 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.
*/
/**
* @file
* @ingroup dev_cc110x_legacy_csma
* @brief ScatterWeb MSB-A2 mac-layer
*
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @version $Revision: 1999 $
*
* @note $Id: cc1100-csmaca-mac.h 1999 2010-03-16 15:48:18Z hillebra $
*/
#ifndef CC1100_CSMACA_MAC_
#define CC1100_CSMACA_MAC_
#include "cc1100-defaultSettings.h"
#ifdef __cplusplus
extern "C" {
#endif
//#define CSMACA_MAC_AGGRESSIVE_MODE // MAC aggressive mode on/off switch
#define CARRIER_SENSE_TIMEOUT (200000) /**< Carrier Sense timeout ~ 2 seconds */
#define CARRIER_SENSE_TIMEOUT_MIN (2000) /**< Minimum Carrier Sense timeout ~ 20 milliseconds */
#define CS_TX_SWITCH_TIME (80) /**< Carrier Sense to TX switch time (measured ~ 350 us) */
/**
* @name CSMA backoff and wait times
* @brief All values are in ticks (x10 us)
* @{
*/
#define PRIO_ALARM_DIFS (200) /**< DIFS for ALARM packets, the default wait time */
#define PRIO_ALARM_SLOTTIME (CS_TX_SWITCH_TIME) /**< Time of one additional wait slot */
#define PRIO_ALARM_MIN_WINDOW_SIZE (2) /**< Minimum window size of backoff algorithm */
#define PRIO_ALARM_MAX_WINDOW_SIZE (8) /**< Maximum window size of backoff algorithm */
#define PRIO_WARN_DIFS (1000) /**< DIFS for WARN packets, the default wait time */
#define PRIO_WARN_SLOTTIME (CS_TX_SWITCH_TIME) /**< Time of one additional wait slot */
#define PRIO_WARN_MIN_WINDOW_SIZE (2) /**< Minimum window size of backoff algorithm */
#define PRIO_WARN_MAX_WINDOW_SIZE (16) /**< Maximum window size of backoff algorithm */
#define PRIO_DATA_DIFS (2500) /**< DIFS for normal data packets, the default wait time */
#define PRIO_DATA_SLOTTIME (CS_TX_SWITCH_TIME) /**< Time of one additional wait slot */
#define PRIO_DATA_MIN_WINDOW_SIZE (4) /**< Minimum window size of backoff algorithm */
#define PRIO_DATA_MAX_WINDOW_SIZE (32) /**< Maximum window size of backoff algorithm */
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /*CC1100_CSMACA_MAC_*/

View File

@ -1,105 +0,0 @@
/*
* Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved.
*
* 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 dev_cc110x_legacy_csma
* @{
*/
/**
* @file
* @brief TI Chipcon CC110x default settings
*
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @version $Revision: 2058 $
*
* @note $Id: cc1100-defaultSettings.c 2058 2010-03-31 08:59:31Z hillebra $
*/
#include "cc1100-defaultSettings.h"
/**
* Usable, non overlapping channels and corresponding frequencies
* for use with CC1100. CHANNR is the register for selecting a channel.
*
* channel number | CHANNR | frequency [MHz]
* -----------------------------------------
* 0 | 0 | 869.525
* 1 | 10 | 871.61
* 2 | 20 | 873.58 ~ seems to be bad (hang-ups with this channel)
* 3 | 30 | 875.61
* 4 | 40 | 877.58
* 5 | 50 | 879.61
* 6 | 60 | 881.58
* 7 | 70 | 883.61
* 8 | 80 | 885.58
* 9 | 90 | 887.61
* 10 | 100 | 889.58
* 11 | 110 | 891.57
* 12 | 120 | 893.58
* 13 | 130 | 895.61
* 14 | 140 | 897.58
* 15 | 150 | 899.57
* 16 | 160 | 901.57
* 17 | 170 | 903.61
* 18 | 180 | 905.57
* 19 | 190 | 907.57
* 20 | 200 | 909.57
* 21 | 210 | 911.57
* 22 | 220 | 913.57
* 23 | 230 | 915.61
* 24 | 240 | 917.61
*/
/* 400 kbps, MSK, X-tal: 26 MHz (Chip Revision F) */
char cc1100_conf[] = {
0x06, /* IOCFG2 */
0x2E, /* IOCFG1 */
0x0E, /* IOCFG0 */
0x0F, /* FIFOTHR */
0x9B, /* SYNC1 */
0xAD, /* SYNC0 */
0x3D, /* PKTLEN (maximum value of packet length byte = 61) */
0x06, /* PKTCTRL1 */
0x45, /* PKTCTRL0 (variable packet length) */
0xFF, /* ADDR */
CC1100_DEFAULT_CHANNR * 10, /* CHANNR */
0x0B, /* FSCTRL1 */
0x00, /* FSCTRL0 */
0x21, /* FREQ2 */
0x71, /* FREQ1 */
0x7A, /* FREQ0 */
0x2D, /* MDMCFG4 */
0xF8, /* MDMCFG3 */
0x73, /* MDMCFG2 */
0x42, /* MDMCFG1 */
0xF8, /* MDMCFG0 */
0x00, /* DEVIATN */
0x07, /* MCSM2 */
0x03, /* MCSM1 */
0x18, /* MCSM0 */
0x1D, /* FOCCFG */
0x1C, /* BSCFG */
0xC0, /* AGCCTRL2 */
0x49, /* AGCCTRL1, (old value was 0x49 -> made carrier sense less sensitive!)
* 0x47 - 7 dB above MAGN_TARGET setting */
0xB2, /* AGCCTRL0 */
0x87, /* WOREVT1 */
0x6B, /* WOREVT0 */
0xF8, /* WORCTRL */
0xB6, /* FREND1 */
0x10, /* FREND0 */
0xEA, /* FSCAL3 */
0x2A, /* FSCAL2 */
0x00, /* FSCAL1 */
0x1F, /* FSCAL0 */
0x00 /* padding to 4 bytes */
};
/** @} */

View File

@ -1,98 +0,0 @@
/*
* Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved.
*
* 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.
*/
#ifndef CC1100_DEFAULTSETTINGS_H
#define CC1100_DEFAULTSETTINGS_H
/**
* @ingroup dev_cc110x_legacy_csma
* @{
*/
/**
* @file
* @brief TI Chipcon CC110x default settings
*
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @version $Revision: 2139 $
*
* @note $Id: cc1100-defaultSettings.h 2139 2010-05-26 08:04:04Z hillebra $
*/
#include "hwtimer.h"
#ifdef __cplusplus
extern "C" {
#endif
// returns hwtimer ticks per us
#define RTIMER_TICKS(us) HWTIMER_TICKS(us)
#define TIMER_TICK_USEC_RES (122)
// Default PA table index (output power)
#define PATABLE (11)
// Watchdog cycle time in seconds, set 0 to disable watchdog
#define CC1100_WATCHDOG_PERIOD (5)
// Number of transmission retries for unicast packets (constant RX mode)
#define TRANSMISSION_RETRIES_CRX_UC (5)
// Number of transmission retries for unicast packets (WOR mode)
#define TRANSMISSION_RETRIES_WOR_UC (1)
// Number of transmission retries for broadcast packets (constant RX mode)
#define TRANSMISSION_RETRIES_CRX_BC (0)
// Number of transmission retries for broadcast packets (WOR mode)
#define TRANSMISSION_RETRIES_WOR_BC (0)
// Time before chip goes back to RX (= stays in PWD after incoming packet)
#define WOR_TIMEOUT_1 (3200) // ~ 32 milliseconds
// Time before chip goes back to WOR (= stays in RX after elapsed WOR_TIMEOUT_1)
#define WOR_TIMEOUT_2 (800) // ~ 8 milliseconds
// XOSC startup + FS calibration (300 + 809 us ~ 1.38 ms)
#define FS_CAL_TIME RTIMER_TICKS(12 * TIMER_TICK_USEC_RES)
// Manual FS calibration (721 us)
#define MANUAL_FS_CAL_TIME RTIMER_TICKS(7 * TIMER_TICK_USEC_RES)
// Reset wait time (in reset procedure)
#define RESET_WAIT_TIME RTIMER_TICKS(4 * TIMER_TICK_USEC_RES)
// Time chip needs to go to RX
#define IDLE_TO_RX_TIME RTIMER_TICKS(1 * TIMER_TICK_USEC_RES)
// Time chip needs to go to RX and CS signal is ready
#define CS_READY_TIME RTIMER_TICKS(3 * TIMER_TICK_USEC_RES)
// Default RX interval for WOR in milliseconds
#define T_RX_INTERVAL (542)
// Time of packet interval in microseconds (at 400 kbps)
#define T_PACKET_INTERVAL (3800)
// The size of the configuration array for CC1100 in bytes
#define CC1100_CONF_SIZE (39)
// The default channel number (0-24) for CC1100
#define CC1100_DEFAULT_CHANNR (0)
// Burst retry to TX switch time (measured ~ 230 us)
#define BURST_RETRY_TX_SWITCH_TIME (23)
#ifdef __cplusplus
}
#endif
/** @} */
#endif

View File

@ -1,208 +0,0 @@
/*
* Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved.
*
* 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.
*/
#ifndef CC1100_INTERNAL_H
#define CC1100_INTERNAL_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @ingroup dev_cc110x_legacy_csma
* @{
*/
/**
* @file
* @internal
* @brief TI Chipcon CC110x internal hardware constants
*
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @version $Revision: 1231 $
*
* @note $Id: cc1100-internal.h 1231 2009-08-20 08:31:32Z baar $
*/
#define FIXED_PKTLEN (0x00) ///< Fixed length packets, length configured in PKTLEN register.
#define VARIABLE_PKTLEN (0x01) ///< Variable length packets, packet length configured by the first
///< byte after synch word.
/**
* @name Bitmasks for reading out status register values
* @{
*/
/**
* @brief Bitmask (=10000000) for reading CRC_OK.
*
* If CRC_OK == 1: CRC for received data OK (or CRC disabled).
* If CRC_OK == 0: CRC error in received data.
*/
#define CRC_OK (0x80)
/**
* @brief Bitmask (=01111111) for reading LQI_EST.
*
* The Link Quality Indicator estimates how easily a received signal can be demodulated.
*/
#define LQI_EST (0x7F)
#define I_RSSI (0x00) ///< Index 0 contains RSSI information (from optionally appended packet status bytes).
#define I_LQI (0x01) ///< Index 1 contains LQI & CRC_OK information (from optionally appended packet status bytes).
#define MARC_STATE (0x1F) ///< Bitmask (=00011111) for reading MARC_STATE in MARCSTATE status register.
#define CS (0x40) ///< Bitmask (=01000000) for reading CS (Carrier Sense) in PKTSTATUS status register.
#define PQT_REACHED (0x20) ///< Bitmask (=00100000) for reading PQT_REACHED (Preamble Quality reached) in PKTSTATUS status register.
#define CCA (0x10) ///< Bitmask (=00010000) for reading CCA (clear channel assessment) in PKTSTATUS status register.
#define SFD (0x08) ///< Bitmask (=00001000) for reading SFD (Sync word found) in PKTSTATUS status register.
#define GDO2 (0x04) ///< Bitmask (=00000100) for reading GDO2 (current value on GDO2 pin) in PKTSTATUS status register.
#define GDO1 (0x02) ///< Bitmask (=00000010) for reading GDO1 (current value on GDO1 pin) in PKTSTATUS status register.
#define GDO0 (0x01) ///< Bitmask (=00000001) for reading GDO0 (current value on GDO0 pin) in PKTSTATUS status register.
#define TXFIFO_UNDERFLOW (0x80) ///< Bitmask (=10000000) for reading TXFIFO_UNDERFLOW in TXBYTES status register.
#define BYTES_IN_TXFIFO (0x7F) ///< Bitmask (=01111111) for reading NUM_TXBYTES in TXBYTES status register.
#define RXFIFO_OVERFLOW (0x80) ///< Bitmask (=10000000) for reading RXFIFO_OVERFLOW in RXBYTES status register.
#define BYTES_IN_RXFIFO (0x7F) ///< Bitmask (=01111111) for reading NUM_RXBYTES in RXBYTES status register.
/** @} */
/**
* @name Bitmasks for reading out configuration register values
* @{
*/
#define PKT_LENGTH_CONFIG (0x03) ///< Bitmask (=00000011) for reading LENGTH_CONFIG in PKTCTRL0 configuration register.
/** @} */
/**
* @name Definitions to support burst/single access
* @{
*/
#define CC1100_WRITE_BURST (0x40) ///< Offset for burst write.
#define CC1100_READ_SINGLE (0x80) ///< Offset for read single byte.
#define CC1100_READ_BURST (0xC0) ///< Offset for read burst.
#define CC1100_NOBYTE (0x00) ///< No command (for reading).
/** @} */
/**
* @name Configuration Registers (47x)
* @{
*/
#define CC1100_IOCFG2 (0x00) ///< GDO2 output pin configuration
#define CC1100_IOCFG1 (0x01) ///< GDO1 output pin configuration
#define CC1100_IOCFG0 (0x02) ///< GDO0 output pin configuration
#define CC1100_FIFOTHR (0x03) ///< RX FIFO and TX FIFO thresholds
#define CC1100_SYNC1 (0x04) ///< Sync word, high byte
#define CC1100_SYNC0 (0x05) ///< Sync word, low byte
#define CC1100_PKTLEN (0x06) ///< Packet length
#define CC1100_PKTCTRL1 (0x07) ///< Packet automation control
#define CC1100_PKTCTRL0 (0x08) ///< Packet automation control
#define CC1100_ADDR (0x09) ///< Device address
#define CC1100_CHANNR (0x0A) ///< Channel number
#define CC1100_FSCTRL1 (0x0B) ///< Frequency synthesizer control
#define CC1100_FSCTRL0 (0x0C) ///< Frequency synthesizer control
#define CC1100_FREQ2 (0x0D) ///< Frequency control word, high byte
#define CC1100_FREQ1 (0x0E) ///< Frequency control word, middle byte
#define CC1100_FREQ0 (0x0F) ///< Frequency control word, low byte
#define CC1100_MDMCFG4 (0x10) ///< Modem configuration
#define CC1100_MDMCFG3 (0x11) ///< Modem configuration
#define CC1100_MDMCFG2 (0x12) ///< Modem configuration
#define CC1100_MDMCFG1 (0x13) ///< Modem configuration
#define CC1100_MDMCFG0 (0x14) ///< Modem configuration
#define CC1100_DEVIATN (0x15) ///< Modem deviation setting
#define CC1100_MCSM2 (0x16) ///< Main Radio Control State Machine configuration
#define CC1100_MCSM1 (0x17) ///< Main Radio Control State Machine configuration
#define CC1100_MCSM0 (0x18) ///< Main Radio Control State Machine configuration
#define CC1100_FOCCFG (0x19) ///< Frequency Offset Compensation configuration
#define CC1100_BSCFG (0x1A) ///< Bit Synchronization configuration
#define CC1100_AGCCTRL2 (0x1B) ///< AGC control
#define CC1100_AGCCTRL1 (0x1C) ///< AGC control
#define CC1100_AGCCTRL0 (0x1D) ///< AGC control
#define CC1100_WOREVT1 (0x1E) ///< High byte Event 0 timeout
#define CC1100_WOREVT0 (0x1F) ///< Low byte Event 0 timeout
#define CC1100_WORCTRL (0x20) ///< Wake On Radio control
#define CC1100_FREND1 (0x21) ///< Front end RX configuration
#define CC1100_FREND0 (0x22) ///< Front end TX configuration
#define CC1100_FSCAL3 (0x23) ///< Frequency synthesizer calibration
#define CC1100_FSCAL2 (0x24) ///< Frequency synthesizer calibration
#define CC1100_FSCAL1 (0x25) ///< Frequency synthesizer calibration
#define CC1100_FSCAL0 (0x26) ///< Frequency synthesizer calibration
#define CC1100_RCCTRL1 (0x27) ///< RC oscillator configuration
#define CC1100_RCCTRL0 (0x28) ///< RC oscillator configuration
#define CC1100_FSTEST (0x29) ///< Frequency synthesizer calibration control
#define CC1100_PTEST (0x2A) ///< Production test
#define CC1100_AGCTEST (0x2B) ///< AGC test
#define CC1100_TEST2 (0x2C) ///< Various test settings
#define CC1100_TEST1 (0x2D) ///< Various test settings
#define CC1100_TEST0 (0x2E) ///< Various test settings
/** @} */
/**
* @name Strobe commands (14x)
* @{
*/
#define CC1100_SRES (0x30) ///< Reset chip.
/**
* @brief Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1).
*
* If in RX/TX: Go to a wait state where only the synthesizer is running (for quick RX / TX turnaround).
*/
#define CC1100_SFSTXON (0x31)
#define CC1100_SXOFF (0x32) ///< Turn off crystal oscillator.
#define CC1100_SCAL (0x33) ///< Calibrate frequency synthesizer and turn it off (enables quick start).
#define CC1100_SRX (0x34) ///< Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL=1.
/**
* In IDLE state: Enable TX. Perform calibration first if MCSM0.FS_AUTOCAL=1.
* If in RX state and CCA is enabled: Only go to TX if channel is clear.
*/
#define CC1100_STX (0x35)
#define CC1100_SIDLE (0x36) ///< Exit RX / TX, turn off frequency synthesizer and exit WOR mode if applicable.
#define CC1100_SAFC (0x37) ///< Perform AFC adjustment of the frequency synthesizer
#define CC1100_SWOR (0x38) ///< Start automatic RX polling sequence (Wake-on-Radio)
#define CC1100_SPWD (0x39) ///< Enter power down mode when CSn goes high.
#define CC1100_SFRX (0x3A) ///< Flush the RX FIFO buffer (CC1100 should be in IDLE state).
#define CC1100_SFTX (0x3B) ///< Flush the TX FIFO buffer (CC1100 should be in IDLE state).
#define CC1100_SWORRST (0x3C) ///< Reset real time clock.
#define CC1100_SNOP (0x3D) ///< No operation. May be used to pad strobe commands to two bytes for simpler software.
/** @} */
/**
* @name Status registers (12x)
* @{
*/
#define CC1100_PARTNUM (0x30) ///< Part number of CC1100.
#define CC1100_VERSION (0x31) ///< Current version number.
#define CC1100_FREQEST (0x32) ///< Frequency Offset Estimate.
#define CC1100_LQI (0x33) ///< Demodulator estimate for Link Quality.
#define CC1100_RSSI (0x34) ///< Received signal strength indication.
#define CC1100_MARCSTATE (0x35) ///< Control state machine state.
#define CC1100_WORTIME1 (0x36) ///< High byte of WOR timer.
#define CC1100_WORTIME0 (0x37) ///< Low byte of WOR timer.
#define CC1100_PKTSTATUS (0x38) ///< Current GDOx status and packet status.
#define CC1100_VCO_VC_DAC (0x39) ///< Current setting from PLL calibration module.
#define CC1100_TXBYTES (0x3A) ///< Underflow and number of bytes in the TX FIFO.
#define CC1100_RXBYTES (0x3B) ///< Overflow and number of bytes in the RX FIFO.
/** @} */
/**
* @name Multi byte registers
* @{
*/
/**
* @brief Register for eight user selected output power settings.
*
* 3-bit FREND0.PA_POWER value selects the PATABLE entry to use.
*/
#define CC1100_PATABLE (0x3E)
#define CC1100_TXFIFO (0x3F) ///< TX FIFO: Write operations write to the TX FIFO (SB: +0x00; BURST: +0x40)
#define CC1100_RXFIFO (0x3F) ///< RX FIFO: Read operations read from the RX FIFO (SB: +0x80; BURST: +0xC0)
/** @} */
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,935 +0,0 @@
/**
* TI Chipcon CC110x radio driver
*
* Copyright (C) 2009-2013 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 dev_cc110x_legacy_csma
* @{
*/
/**
* @file
* @internal
* @brief TI Chipcon CC110x Radio driver
*
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @version $Revision: 2283 $
*
* @note $Id: cc1100.c 2283 2010-06-15 14:02:27Z hillebra $
*/
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "irq.h"
#include "arch_cc1100.h"
#include "cc1100.h"
#include "cc1100_phy.h"
#include "cc1100_spi.h"
#include "cc1100-internal.h"
#include "cc1100-defaultSettings.h"
#include "hwtimer.h"
#include "bitarithm.h"
#define PACKET_LENGTH (0x3E) ///< Packet length = 62 Bytes.
#define CC1100_SYNC_WORD_TX_TIME (90000) /* loop count (max. timeout ~ 15 ms) to wait for */
/* sync word to be transmitted (GDO2 from low to high) */
/**
* @name Virtual Radio Device methods (see vdevice_radio_methods)
* @{
*/
static int rd_set_mode(int mode);
/** @} */
static void switch_to_wor(void);
/*---------------------------------------------------------------------------*/
// Power control data structures
/*---------------------------------------------------------------------------*/
static uint8_t pa_table_index = PATABLE; ///< Current PATABLE Index
static uint8_t pa_table[] = { ///< PATABLE with available output powers
0x00, ///< -52 dBm
0x03, ///< -30 dBm
0x0D, ///< -20 dBm
0x1C, ///< -15 dBm
0x34, ///< -10 dBm
0x57, ///< - 5 dBm
0x3F, ///< - 1 dBm
0x8E, ///< 0 dBm
0x85, ///< + 5 dBm
0xCC, ///< + 7 dBm
0xC6, ///< + 9 dBm
0xC3 ///< +10 dBm
}; /* If PATABLE is changed in size, adjust MAX_OUTPUT_POWER definition in CC1100 interface!*/
static int8_t pa_table_dBm[] = { ///< Values of the PATABLE in dBm
-52,
-30,
-20,
-15,
-10,
-5,
-1,
0,
5,
7,
9,
10
};
/*---------------------------------------------------------------------------*/
// Main radio data structures
/*---------------------------------------------------------------------------*/
volatile cc1100_flags rflags; ///< Radio control flags
static uint8_t radio_address; ///< Radio address
static uint8_t radio_channel; ///< Radio channel number
/*---------------------------------------------------------------------------*/
// Data structures for mode control
/*---------------------------------------------------------------------------*/
volatile uint8_t radio_mode; ///< Radio mode
volatile uint8_t radio_state = RADIO_UNKNOWN; ///< Radio state
volatile cc1100_mode_callback_t cc1100_go_idle; ///< Function for going IDLE
volatile cc1100_mode_callback_t cc1100_go_receive; ///< Function for going RX
volatile cc1100_mode_callback_t cc1100_go_after_tx; ///< Function to call after TX (burst send)
volatile cc1100_mode_callback_t cc1100_setup_mode; ///< Function to set up selected mode (RX or WOR)
volatile int wor_hwtimer_id = -1;
/*---------------------------------------------------------------------------*/
/* Low-level hardware access */
/*---------------------------------------------------------------------------*/
void cc1100_disable_interrupts(void)
{
cc110x_gdo2_disable();
cc110x_gdo0_disable();
}
void cc110x_gdo0_irq(void)
{
/* Air was not free -> Clear CCA flag */
rflags.CAA = false;
/* Disable carrier sense detection (GDO0 interrupt) */
cc110x_gdo0_disable();
}
void cc110x_gdo2_irq(void)
{
cc1100_phy_rx_handler();
}
/*---------------------------------------------------------------------------*/
/* High level CC1100 SPI functions for transferring packet out */
// of RX FIFO (don't call when in WOR mode)
/*---------------------------------------------------------------------------*/
static bool spi_receive_packet_variable(uint8_t *rxBuffer, radio_packet_length_t length)
{
/* Needed here for statistics */
extern cc1100_statistic_t cc1100_statistic;
/* Any bytes available in RX FIFO? */
if ((cc1100_spi_read_status(CC1100_RXBYTES) & BYTES_IN_RXFIFO)) {
uint8_t status[2];
/* Read length byte (first byte in RX FIFO) */
uint8_t packetLength = cc1100_spi_read_reg(CC1100_RXFIFO);
/* Read data from RX FIFO and store in rxBuffer */
if (packetLength <= length) {
/* Put length byte at first position in RX Buffer */
rxBuffer[0] = packetLength;
/* Read the rest of the packet */
cc1100_spi_readburst_reg(CC1100_RXFIFO, (char *)rxBuffer + 1, packetLength);
/* Read the 2 appended status bytes (status[0] = RSSI, status[1] = LQI) */
cc1100_spi_readburst_reg(CC1100_RXFIFO, (char *)status, 2);
/* Store RSSI value of packet */
rflags.RSSI = status[I_RSSI];
/* MSB of LQI is the CRC_OK bit */
rflags.CRC_STATE = (status[I_LQI] & CRC_OK) >> 7;
if (!rflags.CRC_STATE) {
cc1100_statistic.packets_in_crc_fail++;
}
/* Bit 0-6 of LQI indicates the link quality (LQI) */
rflags.LQI = status[I_LQI] & LQI_EST;
return rflags.CRC_STATE;
}
else {
/* RX FIFO get automatically flushed if return value is false */
return false;
}
}
else {
/* RX FIFO get automatically flushed if return value is false */
return false;
}
}
bool cc1100_spi_receive_packet(uint8_t *rxBuffer, radio_packet_length_t length)
{
uint8_t pkt_len_cfg = cc1100_spi_read_reg(CC1100_PKTCTRL0) & PKT_LENGTH_CONFIG;
if (pkt_len_cfg == VARIABLE_PKTLEN) {
return spi_receive_packet_variable(rxBuffer, length);
}
/* Fixed packet length not supported. */
/* RX FIFO get automatically flushed if return value is false */
return false;
}
/*---------------------------------------------------------------------------*/
/* CC1100 mode functionality */
/*---------------------------------------------------------------------------*/
void cc1100_set_idle(void)
{
if (radio_state == RADIO_WOR) {
/* Wake up the chip from WOR/sleep */
cc110x_spi_select();
hwtimer_wait(RTIMER_TICKS(122));
cc110x_spi_unselect();
radio_state = RADIO_IDLE;
/* XOSC startup + FS calibration (300 + 809 us ~ 1.38 ms) */
hwtimer_wait(FS_CAL_TIME);
return;
}
cc1100_spi_strobe(CC1100_SIDLE);
radio_state = RADIO_IDLE;
}
static void wakeup_from_rx(void)
{
if (radio_state != RADIO_RX) {
return;
}
cc1100_spi_strobe(CC1100_SIDLE);
radio_state = RADIO_IDLE;
}
static void switch_to_rx(void)
{
radio_state = RADIO_RX;
cc1100_spi_strobe(CC1100_SRX);
}
static void setup_rx_mode(void)
{
/* Stay in RX mode until end of packet */
cc1100_spi_write_reg(CC1100_MCSM2, 0x07);
switch_to_rx();
}
/**
* Note: It is possible that this code is executed in an ISR!
*/
static void wakeup_from_wor(void)
{
if (radio_state != RADIO_WOR) {
return;
}
/* Wake up the chip from WOR/sleep */
cc110x_spi_select();
hwtimer_wait(RTIMER_TICKS(122));
cc110x_spi_unselect();
radio_state = RADIO_IDLE;
/* XOSC startup + FS calibration (300 + 809 us ~ 1.38 ms) */
hwtimer_wait(FS_CAL_TIME);
}
/**
* Note: This code is executed in the hwtimer ISR!
*/
void switch_to_wor2(void)
{
// if (cc110x_get_gdo2()) return; /* If incoming packet, then don't go to WOR now */
cc1100_spi_strobe(CC1100_SIDLE); /* Put CC1100 to IDLE */
radio_state = RADIO_IDLE; /* Radio state now IDLE */
cc1100_spi_write_reg(CC1100_MCSM2,
cc1100_wor_config.rx_time_reg); /* Configure RX_TIME (for use in WOR) */
cc1100_spi_write_reg(CC1100_MCSM0, 0x18); /* Turn on FS-Autocal */
if (rflags.WOR_RST) {
cc1100_spi_strobe(CC1100_SWORRST); /* Resets the real time clock */
rflags.WOR_RST = false;
}
cc1100_spi_strobe(CC1100_SWOR); /* Put radio back to sleep/WOR (must be in IDLE when this is done) */
radio_state = RADIO_WOR; /* Radio state now WOR */
}
/**
* Note: This code is executed in the hwtimer ISR!
*/
static void hwtimer_switch_to_wor2_wrapper(void *ptr)
{
(void) ptr;
wor_hwtimer_id = -1; /* kernel timer handler function called, clear timer id */
if (rflags.TX) {
return; /* Stability: don't allow WOR timers at this point */
}
rflags.WOR_RST = true;
switch_to_wor2();
}
/**
* Note: This code is executed in the hwtimer ISR!
*/
static void switch_to_wor(void)
{
/* Any incoming packet? */
if (cc110x_get_gdo2()) {
/* Then don't go to WOR now */
return;
}
/* Step 1: Set chip for random interval (1..RX_INTERVAL) to power down mode */
if (!rflags.MAN_WOR) {
rflags.MAN_WOR = true;
radio_state = RADIO_WOR;
/* Go to power down mode */
cc1100_spi_strobe(CC1100_SIDLE);
cc1100_spi_strobe(CC1100_SPWD);
/* Set timer to do second step of manual WOR */
int r = (rand() / (double)(RAND_MAX + 1.0)) * (cc1100_wor_config.rx_interval * 100.0) + 20;
wor_hwtimer_id = hwtimer_set(r, cc1100_hwtimer_go_receive_wrapper, NULL);
if (wor_hwtimer_id == -1) {
rflags.KT_RES_ERR = true;
/* No hwtimer available, go immediately to WOR mode. */
/* Else never receiving packets again... */
rflags.MAN_WOR = false;
switch_to_wor2();
}
}
/* Step 2: Go to RX and then to WOR mode again */
else {
rflags.MAN_WOR = false;
wakeup_from_wor();
cc1100_spi_strobe(CC1100_SRX);
hwtimer_wait(IDLE_TO_RX_TIME);
radio_state = RADIO_RX;
/* Register timer to go to WOR after RX timeout */
wor_hwtimer_id = hwtimer_set((cc1100_wor_config.rx_time_ms * 100 + 150),
hwtimer_switch_to_wor2_wrapper, NULL); /* add 1,5 ms secure time */
if (wor_hwtimer_id == -1) {
rflags.KT_RES_ERR = true;
}
}
}
static void setup_wor_mode(void)
{
/* Wake up from WOR (if in WOR, else no effect) */
cc1100_go_idle();
/* Make sure CC1100 is in IDLE state */
cc1100_spi_strobe(CC1100_SIDLE);
/* Enable automatic initial calibration of RCosc. */
/* Set T_event1 ~ 1.4 ms, enough for XOSC stabilize and FS calibration before RX. */
/* Enable RC oscillator before starting with WOR (or else it will not wake up). */
/* Not using AUTO_SYNC function. */
cc1100_spi_write_reg(CC1100_WORCTRL, cc1100_wor_config.wor_ctrl);
/* Set Event0 timeout (RX polling interval) */
cc1100_spi_write_reg(CC1100_WOREVT1, cc1100_wor_config.wor_evt_1);
cc1100_spi_write_reg(CC1100_WOREVT0, cc1100_wor_config.wor_evt_0);
/* Set RX time in WOR mode */
cc1100_spi_write_reg(CC1100_MCSM2, cc1100_wor_config.rx_time_reg);
/* Enable automatic FS calibration when going from IDLE to RX/TX/FSTXON (in between EVENT0 and EVENT1) */
cc1100_spi_write_reg(CC1100_MCSM0, 0x18);
/* Put the radio to SLEEP by starting Wake-on-Radio. */
cc1100_spi_strobe(CC1100_SWORRST); /* Resets the real time clock */
cc1100_spi_strobe(CC1100_SWOR); /* Starts Wake-on-Radio */
radio_state = RADIO_WOR;
}
static void switch_to_pwd(void)
{
cc1100_go_idle();
cc1100_spi_strobe(CC1100_SPWD);
radio_state = RADIO_PWD;
}
uint8_t cc1100_get_mode(void)
{
return radio_mode;
}
static bool cc1100_set_mode0(uint8_t mode, uint16_t opt_mode_data)
{
int result;
switch(mode) {
case CC1100_MODE_WOR:
/* Calculate WOR settings, store result (new burst count) */
result = cc1100_phy_calc_wor_settings(opt_mode_data);
/* If settings can be applied, set new mode and burst count */
if (result != -1) {
radio_mode = mode;
cc1100_go_idle = wakeup_from_wor;
cc1100_go_receive = switch_to_wor;
cc1100_go_after_tx = switch_to_wor2;
cc1100_setup_mode = setup_wor_mode;
cc1100_burst_count = result;
cc1100_retransmission_count_uc = TRANSMISSION_RETRIES_WOR_UC;
cc1100_retransmission_count_bc = TRANSMISSION_RETRIES_WOR_BC;
return true;
}
break;
case CC1100_MODE_CONSTANT_RX:
radio_mode = mode;
cc1100_go_idle = wakeup_from_rx;
cc1100_go_receive = switch_to_rx;
cc1100_go_after_tx = switch_to_rx;
cc1100_setup_mode = setup_rx_mode;
cc1100_burst_count = 1;
cc1100_retransmission_count_uc = TRANSMISSION_RETRIES_CRX_UC;
cc1100_retransmission_count_bc = TRANSMISSION_RETRIES_CRX_BC;
return true;
}
return false;
}
bool cc1100_set_mode(uint8_t mode, uint16_t opt_mode_data)
{
/* Wake up from WOR/RX (if in WOR/RX, else no effect) */
cc1100_go_idle();
/* Make sure CC1100 is in IDLE state */
cc1100_spi_strobe(CC1100_SIDLE);
/* Set the new mode */
bool result = cc1100_set_mode0(mode, opt_mode_data);
/* If mode change was successful (mode is valid) */
if (result) {
/* Setup new mode configuration */
cc1100_setup_mode();
/* Reset statistics */
cc1100_reset_statistic();
return true;
}
else {
/* Still in old mode, go to receive mode again */
cc1100_go_receive();
return false;
}
}
char *cc1100_mode_to_text(uint8_t mode)
{
switch(mode) {
case CC1100_MODE_WOR:
return "Wake-On-Radio";
case CC1100_MODE_CONSTANT_RX:
return "Constant RX";
default:
return "unknown";
}
}
char *cc1100_state_to_text(uint8_t state)
{
switch(state) {
case RADIO_UNKNOWN:
return "Unknown";
case RADIO_AIR_FREE_WAITING:
return "CS";
case RADIO_WOR:
return "WOR";
case RADIO_IDLE:
return "IDLE";
case RADIO_SEND_BURST:
return "TX BURST";
case RADIO_RX:
return "RX";
case RADIO_SEND_ACK:
return "TX ACK";
case RADIO_PWD:
return "PWD";
default:
return "unknown";
}
}
void cc1100_hwtimer_go_receive_wrapper(void *ptr)
{
(void) ptr;
/* kernel timer handler function called, clear timer id */
wor_hwtimer_id = -1;
/* Stability: don't allow WOR timers at this point */
if (rflags.TX) {
return;
}
if (radio_state == RADIO_PWD) {
/* Go to RX state, listen for packets as long as WOR_TIMEOUT_2 */
cc1100_spi_strobe(CC1100_SRX);
hwtimer_wait(IDLE_TO_RX_TIME);
radio_state = RADIO_RX;
/* Set hwtimer to put CC1100 back to WOR after WOR_TIMEOUT_2 */
wor_hwtimer_id = hwtimer_set(WOR_TIMEOUT_2, cc1100_hwtimer_go_receive_wrapper, NULL);
if (wor_hwtimer_id == -1) {
rflags.KT_RES_ERR = true;
/* No hwtimer available, go immediately to WOR mode. */
/* Else never receiving packets again... */
rflags.MAN_WOR = false;
switch_to_wor2();
}
}
else {
cc1100_go_receive();
}
}
/*---------------------------------------------------------------------------*/
/* CC1100 reset functionality */
/*---------------------------------------------------------------------------*/
static void reset(void)
{
cc1100_go_idle();
cc110x_spi_select();
cc1100_spi_strobe(CC1100_SRES);
hwtimer_wait(RTIMER_TICKS(10));
}
static void power_up_reset(void)
{
cc110x_spi_unselect();
cc110x_spi_cs();
cc110x_spi_unselect();
hwtimer_wait(RESET_WAIT_TIME);
reset();
radio_state = RADIO_IDLE;
}
/*---------------------------------------------------------------------------*/
/* CC1100 low level send function */
/*---------------------------------------------------------------------------*/
void cc1100_send_raw(uint8_t *tx_buffer, uint8_t size)
{
volatile uint32_t abort_count;
/* The number of bytes to be transmitted must be smaller */
/* or equal to PACKET_LENGTH (62 bytes). So the receiver */
/* can put the whole packet in its RX-FIFO (with appended */
/* packet status bytes). */
if (size > PACKET_LENGTH) {
return;
}
/* Disables RX interrupt etc. */
cc110x_before_send();
/* But CC1100 in IDLE mode to flush the FIFO */
cc1100_spi_strobe(CC1100_SIDLE);
/* Flush TX FIFO to be sure it is empty */
cc1100_spi_strobe(CC1100_SFTX);
/* Write packet into TX FIFO */
cc1100_spi_writeburst_reg(CC1100_TXFIFO, (char *) tx_buffer, size);
/* Switch to TX mode */
abort_count = 0;
unsigned int cpsr = disableIRQ();
cc1100_spi_strobe(CC1100_STX);
/* Wait for GDO2 to be set -> sync word transmitted */
while (cc110x_get_gdo2() == 0) {
abort_count++;
if (abort_count > CC1100_SYNC_WORD_TX_TIME) {
/* Abort waiting. CC1100 maybe in wrong mode */
/* e.g. sending preambles for always */
puts("[CC1100 TX] fatal error\n");
break;
}
}
restoreIRQ(cpsr);
/* Wait for GDO2 to be cleared -> end of packet */
while (cc110x_get_gdo2() != 0);
/* Experimental - TOF Measurement */
cc110x_after_send();
}
/*---------------------------------------------------------------------------*/
/* Various functions (mode safe - they can be called in any radio mode) */
/*---------------------------------------------------------------------------*/
uint8_t
read_register(uint8_t r)
{
uint8_t result;
/* Save old radio state */
uint8_t old_state = radio_state;
/* Wake up from WOR/RX (if in WOR/RX, else no effect) */
cc1100_go_idle();
result = cc1100_spi_read_reg(r);
/* Have to put radio back to WOR/RX if old radio state */
/* was WOR/RX, otherwise no action is necessary */
if (old_state == RADIO_WOR || old_state == RADIO_RX) {
cc1100_go_receive();
}
return result;
}
static void
write_register(uint8_t r, uint8_t value)
{
/* Save old radio state */
uint8_t old_state = radio_state;
/* Wake up from WOR/RX (if in WOR/RX, else no effect) */
cc1100_go_idle();
cc1100_spi_write_reg(r, value);
/* Have to put radio back to WOR/RX if old radio state */
/* was WOR/RX, otherwise no action is necessary */
if (old_state == RADIO_WOR || old_state == RADIO_RX) {
cc1100_go_receive();
}
}
char *cc1100_get_output_power(char *buf)
{
sprintf(buf, "%+i dBm", pa_table_dBm[pa_table_index]);
return buf;
}
uint8_t cc1100_get_channel(void)
{
return radio_channel;
}
bool
cc1100_set_channel(uint8_t channr)
{
if (channr > MAX_CHANNR) {
return false;
}
write_register(CC1100_CHANNR, channr * 10);
radio_channel = channr;
return true;
}
bool
cc1100_set_output_power(uint8_t pa_idx)
{
if (pa_idx >= sizeof(pa_table)) {
return false;
}
write_register(CC1100_PATABLE, pa_table[pa_idx]);
pa_table_index = pa_idx;
return true;
}
char *cc1100_get_marc_state(void)
{
uint8_t state;
/* Save old radio state */
uint8_t old_state = radio_state;
/* Read content of status register */
state = cc1100_spi_read_status(CC1100_MARCSTATE) & MARC_STATE;
/* Make sure in IDLE state. */
/* Only goes to IDLE if state was RX/WOR */
cc1100_go_idle();
/* Have to put radio back to WOR/RX if old radio state */
/* was WOR/RX, otherwise no action is necessary */
if (old_state == RADIO_WOR || old_state == RADIO_RX) {
cc1100_go_receive();
}
switch(state) {
/* Note: it is not possible to read back the SLEEP or XOFF state numbers */
/* because setting CSn low will make the chip enter the IDLE mode from the */
/* SLEEP (0) or XOFF (2) states. */
case 1:
return "IDLE";
case 3:
case 4:
case 5:
return "MANCAL";
case 6:
case 7:
return "FS_WAKEUP";
case 8:
case 12:
return "CALIBRATE";
case 9:
case 10:
case 11:
return "SETTLING";
case 13:
case 14:
case 15:
return "RX";
case 16:
return "TXRX_SETTLING";
case 17:
return "RXFIFO_OVERFLOW";
case 18:
return "FSTXON";
case 19:
case 20:
return "TX";
case 21:
return "RXTX_SETTLING";
case 22:
return "TXFIFO_UNDERFLOW";
default:
return "UNKNOWN";
}
}
/*
static int8_t
rssi_2_dbm(uint8_t rssi)
{
if (rssi >= 128) rssi -= 256;
rssi /= 2;
rssi -= 78;
return rssi;
}*/
/*---------------------------------------------------------------------------*/
/* Radio Driver API */
/*---------------------------------------------------------------------------*/
void cc1100_init(void)
{
/* Initialize SPI */
cc110x_spi_init();
/* Set default mode (with default (energy optimized) RX interval) */
cc1100_set_mode0(CC1100_RADIO_MODE, T_RX_INTERVAL);
/* Load driver & reset */
power_up_reset();
/* Write configuration to configuration registers */
extern char cc1100_conf[];
cc1100_spi_writeburst_reg(0x00, cc1100_conf, CC1100_CONF_SIZE);
/* Write PATABLE (power settings) */
cc1100_spi_write_reg(CC1100_PATABLE, pa_table[pa_table_index]);
/* Initialize Radio Flags */
rflags.RSSI = 0x00;
rflags.LL_ACK = false;
rflags.CAA = false;
rflags.CRC_STATE = false;
rflags.SEQ = false;
rflags.MAN_WOR = false;
rflags.KT_RES_ERR = false;
rflags.TX = false;
rflags.WOR_RST = false;
/* Initialize physical layer */
cc1100_phy_init();
/* Set radio address of CC1100 */
cc1100_set_address(radio_address);
/* Set default channel number */
radio_channel = CC1100_DEFAULT_CHANNR;
/* Switch to desired mode (WOR or RX) */
rd_set_mode(RADIO_MODE_ON);
}
int cc1100_get_avg_transmission_duration(void)
{
if (radio_mode == CC1100_MODE_WOR) {
/* Transmission duration ~ RX interval */
/* Double value because of MAC delay. */
return 2 * cc1100_wor_config.rx_interval;
}
else {
/* Transmission duration ~ 32 ms */
/* Double value because of MAC delay. */
return 2 * 32;
}
}
radio_address_t cc1100_get_address(void)
{
return radio_address;
}
bool cc1100_set_address(radio_address_t address)
{
if (address < MIN_UID || address > MAX_UID) {
return false;
}
uint8_t id = (uint8_t) address;
if (radio_state != RADIO_UNKNOWN) {
write_register(CC1100_ADDR, id);
}
radio_address = id;
return true;
}
static int
rd_set_mode(int mode)
{
int result;
/* Get current radio mode */
if (radio_state == RADIO_UNKNOWN || radio_state == RADIO_PWD) {
result = RADIO_MODE_OFF;
}
else {
result = RADIO_MODE_ON;
}
switch(mode) {
case RADIO_MODE_ON:
cc110x_init_interrupts(); /* Enable interrupts */
cc1100_setup_mode(); /* Set chip to desired mode */
break;
case RADIO_MODE_OFF:
cc1100_disable_interrupts(); /* Disable interrupts */
switch_to_pwd(); /* Set chip to power down mode */
break;
case RADIO_MODE_GET:
/* do nothing, just return current mode */
default:
/* do nothing */
break;
}
/* Return previous mode */
return result;
}
/*---------------------------------------------------------------------------*/
/* Carrier sense interface functions */
/*---------------------------------------------------------------------------*/
void cc1100_cs_init(void)
{
cc1100_go_idle(); /* Wake CC1100 up from Wake-On-Radio mode */
if (radio_state == RADIO_RX) { /* If radio in RX mode */
cc1100_spi_strobe(CC1100_SIDLE); /* Go back to IDLE for calibration */
}
cc1100_spi_write_reg(CC1100_MCSM0, 0x08); /* Turn off FS-Autocal */
cc1100_spi_strobe(CC1100_SCAL); /* Calibrate manually (721 us) */
hwtimer_wait(MANUAL_FS_CAL_TIME); /* Wait for calibration to finish before packet burst can start */
radio_state = RADIO_AIR_FREE_WAITING; /* Set status "waiting for air free" */
cc1100_spi_write_reg(CC1100_MCSM2, 0x07); /* Configure RX_TIME = Until end of packet (no timeout) */
cc1100_spi_strobe(CC1100_SRX); /* Switch to RX (88.4 us) (Carrier Sense) */
hwtimer_wait(CS_READY_TIME); /* Wait until CC1100 is in RX + carrier sense ready (GDO0 ready for readout -> data rate dependent!!!) */
}
void cc1100_cs_set_enabled(bool enabled)
{
if (enabled) {
/* Enable carrier sense detection (GDO0 interrupt) */
cc110x_gdo0_enable();
}
else {
/* Disable carrier sense detection (GDO0 interrupt) */
cc110x_gdo0_disable();
}
}
int cc1100_cs_read(void)
{
/* GDO0 reflects CS (high: air not free, low: air free) */
return cc110x_get_gdo0();
}
int cc1100_cs_read_cca(void)
{
return rflags.CAA;
}
void cc1100_cs_write_cca(const int cca)
{
rflags.CAA = cca;
}
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -1,330 +0,0 @@
/*
* Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved.
*
* 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_cc110x_legacy_csma CC110X_LEGACY_CSMA
* @ingroup drivers
* @brief Driver for Texas Instruments CC110x (including CMSA/CA MAC)
*
* <h3>Quick links</h3>
* \li \ref cc1100_packet_layer0_t MAC packet format
*
* @{
*
* @file
* @brief TI Chipcon CC110x radio driver
*
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
*/
#ifndef CC1100_H
#define CC1100_H
#include <stdbool.h>
#include "cc110x_legacy_csma.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name Defines used as state values for state machine
* @{
*/
#define RADIO_UNKNOWN (0)
#define RADIO_AIR_FREE_WAITING (1)
#define RADIO_WOR (2)
#define RADIO_IDLE (3)
#define RADIO_SEND_BURST (4)
#define RADIO_RX (5)
#define RADIO_SEND_ACK (6)
#define RADIO_PWD (7)
/** @} */
/** @brief CC1100 register configuration */
typedef struct cc1100_reg {
uint8_t IOCFG2; /**< GDO2 output pin configuration */
uint8_t IOCFG1; /**< GDO1 output pin configuration */
uint8_t IOCFG0; /**< GDO0 output pin configuration */
uint8_t FIFOTHR; /**< RX FIFO and TX FIFO thresholds */
uint8_t SYNC1; /**< Sync word, high byte */
uint8_t SYNC0; /**< Sync word, low byte */
uint8_t PKTLEN; /**< Packet length */
uint8_t PKTCTRL1; /**< Packet automation control */
uint8_t PKTCTRL0; /**< Packet automation control */
uint8_t ADDR; /**< Device address */
uint8_t CHANNR; /**< Channel number */
uint8_t FSCTRL1; /**< Frequency synthesizer control */
uint8_t FSCTRL0; /**< Frequency synthesizer control */
uint8_t FREQ2; /**< Frequency control word, high byte */
uint8_t FREQ1; /**< Frequency control word, middle byte */
uint8_t FREQ0; /**< Frequency control word, low byte */
uint8_t MDMCFG4; /**< Modem configuration */
uint8_t MDMCFG3; /**< Modem configuration */
uint8_t MDMCFG2; /**< Modem configuration */
uint8_t MDMCFG1; /**< Modem configuration */
uint8_t MDMCFG0; /**< Modem configuration */
uint8_t DEVIATN; /**< Modem deviation setting */
uint8_t MCSM2; /**< Main Radio Control State Machine configuration */
uint8_t MCSM1; /**< Main Radio Control State Machine configuration */
uint8_t MCSM0; /**< Main Radio Control State Machine configuration */
uint8_t FOCCFG; /**< Frequency Offset Compensation configuration */
uint8_t BSCFG; /**< Bit Synchronization configuration */
uint8_t AGCCTRL2; /**< AGC control */
uint8_t AGCCTRL1; /**< AGC control */
uint8_t AGCCTRL0; /**< AGC control */
uint8_t WOREVT1; /**< High byte Event 0 timeout */
uint8_t WOREVT0; /**< Low byte Event 0 timeout */
uint8_t WORCTRL; /**< Wake On Radio control */
uint8_t FREND1; /**< Front end RX configuration */
uint8_t FREND0; /**< Front end TX configuration */
uint8_t FSCAL3; /**< Frequency synthesizer calibration */
uint8_t FSCAL2; /**< Frequency synthesizer calibration */
uint8_t FSCAL1; /**< Frequency synthesizer calibration */
uint8_t FSCAL0; /**< Frequency synthesizer calibration */
} cc1100_reg_t;
/** CC1100 radio configuration */
typedef struct cc1100_cfg_t {
cc1100_reg_t reg_cfg; /**< CC1100 register configuration */
uint8_t pa_power; /**< Output power setting */
} cc1100_cfg_t;
/**
* @brief Radio Control Flags
*/
typedef struct cc1100_flags {
uint32_t TOF; /**< Time of flight of the last packet and last ACK */
uint32_t TCP; /**< Time to compute packet */
unsigned RPS : 16; /**< Raw packets sent to transmit last packet */
unsigned RETC : 8; /**< Retransmission count of last send packet */
unsigned RSSI : 8; /**< The RSSI value of last received packet */
unsigned RSSI_SEND : 8; /**< The RSSI value of the last send unicast packet of this node */
unsigned LQI : 8; /**< The LQI value of the last received packet */
unsigned LL_ACK : 1; /**< Is set if Link-Level ACK is received, otherwise 0 (reset on new burst) */
unsigned CAA : 1; /**< The status of the air (1 = air free, 0 = air not free) */
unsigned CRC_STATE : 1; /**< The CRC status of last received packet (1 = OK, 0 = not OK) */
unsigned SEQ : 1; /**< Sequence number (toggles between 0 and 1) */
unsigned MAN_WOR : 1; /**< Manual WOR set (for randomized WOR times => no synch) */
unsigned KT_RES_ERR : 1; /**< A hwtimer resource error has occurred (no free timers available) */
unsigned TX : 1; /**< State machine TX lock, only ACKs will be received */
unsigned WOR_RST : 1; /**< Reset CC1100 real time clock (WOR) on next WOR strobe */
} cc1100_flags;
/**
* @brief Statistic interface for debugging
*/
typedef struct cc1100_statistic {
uint32_t packets_in;
uint32_t packets_in_crc_fail;
uint32_t packets_in_while_tx;
uint32_t packets_in_dups;
uint32_t packets_in_up;
uint32_t packets_out;
uint32_t packets_out_acked;
uint32_t packets_out_broadcast;
uint32_t raw_packets_out;
uint32_t raw_packets_out_acked;
uint32_t acks_send;
uint32_t rx_buffer_max;
uint32_t watch_dog_resets;
} cc1100_statistic_t;
enum radio_mode {
RADIO_MODE_GET = -1, /**< leave mode unchanged */
RADIO_MODE_OFF = 0, /**< turn radio off */
RADIO_MODE_ON = 1 /**< turn radio on */
};
enum radio_result {
RADIO_PAYLOAD_TOO_LONG = -1, /**< payload too long */
RADIO_WRONG_MODE = -2, /**< operation not supported in current mode */
RADIO_ADDR_OUT_OF_RANGE = -3, /**< address out of range */
RADIO_OP_FAILED = -4, /**< operation failed */
RADIO_CS_TIMEOUT = -5, /**< Carrier Sense timeout: air was never free */
RADIO_INVALID_PARAM = -6 /**< Invalid parameters passed to radio */
};
/* ------------------------------------------------------------------------- */
// Variable declarations (also used in other files)
/* ------------------------------------------------------------------------- */
extern volatile cc1100_flags rflags; ///< Radio flags
extern volatile uint8_t radio_mode; ///< Radio mode
extern volatile uint8_t radio_state; ///< Radio state
/** Mode callback functions */
typedef void (*cc1100_mode_callback_t)(void);
extern volatile cc1100_mode_callback_t cc1100_go_idle;
extern volatile cc1100_mode_callback_t cc1100_go_receive;
extern volatile cc1100_mode_callback_t cc1100_go_after_tx;
extern volatile cc1100_mode_callback_t cc1100_setup_mode;
extern volatile int wor_hwtimer_id; ///< WOR hwtimer identifier
/* ------------------------------------------------------------------------- */
// CC1100 radio driver API
/* ------------------------------------------------------------------------- */
/**
* @brief Set chip and state machine to IDLE mode.
*/
void cc1100_set_idle(void);
/**
* @brief Convert radio mode to textual representation.
*
* @param mode The radio mode to convert.
*
* @return Textual representation of radio mode.
*/
char *cc1100_mode_to_text(uint8_t mode);
/**
* @brief Convert radio state to textual representation.
*
* @param state The radio state to convert.
*
* @return Textual representation of radio state.
*/
char *cc1100_state_to_text(uint8_t state);
/**
* @brief Convert current output power to textual representation.
*
* @return Textual representation of current output power in dBm.
*/
char *cc1100_get_output_power(char *buf);
/**
* @brief Read out main radio control FSM state.
*
* @return Textual representation of current main radio control FSM state.
*/
char *cc1100_get_marc_state(void);
/**
* @brief hwtimer wrapper function.
*
* This wrapper function puts the radio to receive mode.
*
* @param ptr Optional data (only to match hwtimer interface).
*/
void cc1100_hwtimer_go_receive_wrapper(void *ptr);
/**
* @brief GDO0 interrupt handler.
*/
void cc1100_gdo0_irq(void);
/**
* @brief GDO2 interrupt handler.
*
* @note Wakes up MCU on packet reception.
*/
void cc1100_gdo2_irq(void);
/**
* @brief Transfer packet from CC1100 RX FIFO.
*
* Transfers a packet from CC1100 RX FIFO into a buffer.
*
* @param rxBuffer The buffer in which to transfer the packet.
* @param length The size of the buffer in which to transfer the packet.
*
* @return true if operation succeeded; false otherwise (e.g. no data
* available, buffer to small or CRC check failed).
*/
bool cc1100_spi_receive_packet(uint8_t *rxBuffer, radio_packet_length_t length);
/**
* @brief Sends raw data.
*
* Sends the data of the given buffer. The first two bytes of the
* buffer must match the CC1100 packet format (so address interpretation
* succeeds).
* <p>
* This function is not mode safe!The radio must be woke up before
* sending and has to be put back manually to receive mode.
*
* @param tx_buffer Data source buffer.
* @param size The size of the data source buffer (maximum: 62 bytes).
*/
void cc1100_send_raw(uint8_t *tx_buffer, uint8_t size);
/**
* @name Carrier Sense interface
* @{
*/
/**
* @brief Initialize radio for carrier sense detection.
*/
void cc1100_cs_init(void);
/**
* @brief Enable or disable carrier sense detections.
*
* Turns interrupts for carrier sense on or off.
*
* @param enabled true if carrier sense detection should
* be enabled; false otherwise.
*/
void cc1100_cs_set_enabled(bool enabled);
/**
* @brief Read carrier sense signal.
*
* @return High (1) if air is not free; low (0) if air is
* currently free.
*/
int cc1100_cs_read(void);
/**
* @brief Reads the CCA (Clear Channel Assessment) flag.
*
* The CCA flag is set by an interrupt service routine, after
* carrier sense detection is enabled. So the status of the
* carrier sense signal can be evaluated in a non blocking
* manner.
*
* @return The current value of the CCA flag (High: air is free,
* low: air is not free).
*/
int cc1100_cs_read_cca(void);
/**
* @brief Sets the CCA flag.
*
* @param cca The new value for the CCA flag.
*/
void cc1100_cs_write_cca(const int cca);
/** @} */
/**
* @name Statistic interface
* @{
*/
/**
* @brief Reset radio statistics.
*/
void cc1100_reset_statistic(void);
/** @} */
#ifdef __cplusplus
}
#endif
/** @} */
#endif

View File

@ -1,880 +0,0 @@
/*
* Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved.
*
* 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 dev_cc110x_legacy_csma
* @{
*/
/**
* @file
* @internal
* @brief TI Chipcon CC110x physical radio driver
*
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @author Oliver Hahm <oliver.hahm@inria.fr>
* @version $Revision: 2130 $
*
* @note $Id: cc1100_phy.c 2130 2010-05-12 13:19:07Z hillebra $
*/
#include <stdio.h>
#include <string.h>
#include "hwtimer.h"
#include "vtimer.h"
#include "cc1100.h"
#include "cc1100_spi.h"
#include "cc1100_phy.h"
#include "cc1100-defaultSettings.h"
#include "protocol-multiplex.h"
#include "kernel.h"
#include "thread.h"
#include "mutex.h"
#include "msg.h"
#include "debug.h"
#define PRIORITY_CC1100 THREAD_PRIORITY_MAIN-1
#define MSG_POLL 12346
#define FLAGS_IDENTIFICATION (0x01) ///< Bit mask for reading the identification out of the flags field
#define R_FLAGS_PROTOCOL(x) ((x & 0x0E)>>1) ///< Macro for reading the protocol out of the flags field
#define W_FLAGS_PROTOCOL(x) ((x<<1) & 0x0E) ///< Macro for writing the protocol in the flags field
/*---------------------------------------------------------------------------*/
/* RX/TX buffer data structures */
/*---------------------------------------------------------------------------*/
typedef struct {
cc1100_packet_layer0_t packet;
packet_info_t info;
} rx_buffer_t;
#define RX_BUFF_SIZE (10) ///< Size of RX queue
static volatile uint8_t rx_buffer_head; ///< RX queue head
static volatile uint8_t rx_buffer_tail; ///< RX queue tail
static volatile uint8_t rx_buffer_size; ///< RX queue size
static rx_buffer_t rx_buffer[RX_BUFF_SIZE]; ///< RX buffer
static cc1100_packet_layer0_t tx_buffer; ///< TX buffer (for one packet)
/*---------------------------------------------------------------------------*/
/* Process/Event management data structures */
/*---------------------------------------------------------------------------*/
#define MAX_PACKET_HANDLERS (5)
static packet_monitor_t packet_monitor;
static handler_entry_t handlers[MAX_PACKET_HANDLERS];
static const pm_table_t handler_table;
static const char *cc1100_event_handler_name = "cc1100_event_handler";
static mutex_t cc1100_mutex = MUTEX_INIT;
volatile kernel_pid_t cc1100_mutex_pid;
static vtimer_t cc1100_watch_dog;
static timex_t cc1100_watch_dog_period;
static kernel_pid_t cc1100_event_handler_pid;
static void *cc1100_event_handler_function(void *);
static char event_handler_stack[THREAD_STACKSIZE_MAIN];
/*---------------------------------------------------------------------------*/
/* Sequence number buffer management data structures */
/*---------------------------------------------------------------------------*/
/**
* @name Sequence Buffer
* @{
*/
#define MAX_SEQ_BUFFER_SIZE (20) ///< Maximum size of the sequence number buffer
typedef struct {
uint64_t m_ticks; ///< 64-bit timestamp
uint8_t source; ///< Source address
uint8_t identification; ///< Identification (1-bit)
} seq_buffer_entry_t;
//* Sequence number buffer for this layer */
static seq_buffer_entry_t seq_buffer[MAX_SEQ_BUFFER_SIZE];
//* Next position to enter a new value into ::seqBuffer */
static uint8_t seq_buffer_pos = 0;
/**
* @brief Last sequence number this node has seen
*
* @note (phySrc + flags.identification) - for speedup in ISR.
*/
static volatile uint16_t last_seq_num = 0;
/** @} */
/*---------------------------------------------------------------------------*/
// WOR configuration data structures
/*---------------------------------------------------------------------------*/
#define EVENT0_MAX (60493) ///< Maximum RX polling interval in milliseconds
#define WOR_RES_SWITCH (1891) ///< Switching point value in milliseconds between
///< WOR_RES = 0 and WOR_RES = 1
#define DUTY_CYCLE_SIZE (7) ///< Length of duty cycle array
cc1100_wor_config_t cc1100_wor_config; ///< CC1100 WOR configuration
uint16_t cc1100_burst_count; ///< Burst count, number of packets in a burst transfer
uint8_t cc1100_retransmission_count_uc; ///< Number of retransmissions for unicast
uint8_t cc1100_retransmission_count_bc; ///< Number of retransmissions for broadcast
static const double duty_cycle[2][DUTY_CYCLE_SIZE] = { ///< Duty cycle values from AN047
{12.5, 6.25, 3.125, 1.563, 0.781, 0.391, 0.195},
{1.95, 0.9765, 0.4883, 0.2441, 0.1221, 0.061035, 0.030518}
};
/*---------------------------------------------------------------------------*/
// Data structures for statistic
/*---------------------------------------------------------------------------*/
cc1100_statistic_t cc1100_statistic;
/*---------------------------------------------------------------------------*/
// Initialization of physical layer
/*---------------------------------------------------------------------------*/
void cc1100_phy_init(void)
{
int i;
rx_buffer_head = 0;
rx_buffer_tail = 0;
rx_buffer_size = 0;
/* Initialize RX-Buffer (clear content) */
for (i = 0; i < RX_BUFF_SIZE; i++) {
rx_buffer->packet.length = 0;
}
/* Initialize handler table & packet monitor */
packet_monitor = NULL;
pm_init_table((pm_table_t *)&handler_table, MAX_PACKET_HANDLERS, handlers);
/* Clear sequence number buffer */
memset(seq_buffer, 0, sizeof(seq_buffer_entry_t) * MAX_SEQ_BUFFER_SIZE);
/* Initialize mutex */
cc1100_mutex_pid = KERNEL_PID_UNDEF;
/* Allocate event numbers and start cc1100 event process */
cc1100_event_handler_pid = thread_create(event_handler_stack, sizeof(event_handler_stack), PRIORITY_CC1100, CREATE_STACKTEST,
cc1100_event_handler_function, NULL, cc1100_event_handler_name);
/* Active watchdog for the first time */
if (radio_mode == CC1100_MODE_CONSTANT_RX) {
cc1100_watch_dog_period = timex_set(CC1100_WATCHDOG_PERIOD, 0);
if (timex_cmp(cc1100_watch_dog_period, timex_set(0, 0)) != 0) {
vtimer_set_msg(&cc1100_watch_dog, cc1100_watch_dog_period, cc1100_event_handler_pid, MSG_TIMER, NULL);
}
}
}
/*---------------------------------------------------------------------------*/
/* CC1100 mutual exclusion */
/*---------------------------------------------------------------------------*/
void cc1100_phy_mutex_lock(void)
{
if (sched_active_pid != cc1100_mutex_pid) {
mutex_lock(&cc1100_mutex);
cc1100_mutex_pid = sched_active_pid;
}
}
void cc1100_phy_mutex_unlock(void)
{
cc1100_mutex_pid = KERNEL_PID_UNDEF;
mutex_unlock(&cc1100_mutex);
}
/*---------------------------------------------------------------------------*/
// Statistical functions
/*---------------------------------------------------------------------------*/
void cc1100_reset_statistic(void)
{
cc1100_statistic.packets_in_up = 0;
cc1100_statistic.acks_send = 0;
cc1100_statistic.packets_out_acked = 0;
cc1100_statistic.packets_in = 0;
cc1100_statistic.packets_out = 0;
cc1100_statistic.packets_out_broadcast = 0;
cc1100_statistic.raw_packets_out_acked = 0;
cc1100_statistic.raw_packets_out = 0;
cc1100_statistic.packets_in_dups = 0;
cc1100_statistic.packets_in_crc_fail = 0;
cc1100_statistic.packets_in_while_tx = 0;
cc1100_statistic.rx_buffer_max = 0;
cc1100_statistic.watch_dog_resets = 0;
}
void cc1100_print_statistic(void)
{
printf("\nStatistic on CC1100 interface\n\n");
printf("Total packets send on layer 0.5 (broadcast): %lu\n", cc1100_statistic.packets_out_broadcast);
printf("Total packets send on layer 0.5 (unicast): %lu\n", cc1100_statistic.packets_out);
printf("Total packets Acked on layer 0.5: %lu (%.2f%%)\n", cc1100_statistic.packets_out_acked, cc1100_statistic.packets_out_acked * (100.0f / (float)cc1100_statistic.packets_out));
printf("Total packets send on layer 0: %lu\n", cc1100_statistic.raw_packets_out);
printf("Total packets send on layer 0 w. Ack on Layer 0.5: %lu (Avg. Ack after: %lu packets)\n", cc1100_statistic.raw_packets_out_acked, cc1100_statistic.raw_packets_out_acked / cc1100_statistic.packets_out_acked);
printf("Burst count on this node: %i (%.2f%%)\n", cc1100_burst_count, (100 / (float)cc1100_burst_count) * (cc1100_statistic.raw_packets_out_acked / (float) cc1100_statistic.packets_out_acked));
printf("Total packets In on layer 0: %lu\n", cc1100_statistic.packets_in);
printf("Duped packets In on layer 0: %lu\n", cc1100_statistic.packets_in_dups);
printf("Corrupted packets In on layer 0: %lu\n", cc1100_statistic.packets_in_crc_fail);
printf("Packets In on layer 0 while in TX: %lu\n", cc1100_statistic.packets_in_while_tx);
printf("Total packets In and up to layer 1: %lu (%.2f%%)\n", cc1100_statistic.packets_in_up, cc1100_statistic.packets_in_up * (100.0f / (float)cc1100_statistic.packets_in));
printf("Total Acks send on layer 0.5: %lu\n", cc1100_statistic.acks_send);
printf("RX Buffer max: %lu (now: %u)\n", cc1100_statistic.rx_buffer_max, rx_buffer_size);
printf("State machine resets by cc1100 watchdog: %lu\n", cc1100_statistic.watch_dog_resets);
}
void cc1100_print_config(void)
{
char buf[8];
printf("Current radio mode: %s\r\n", cc1100_mode_to_text(radio_mode));
printf("Current radio state: %s\r\n", cc1100_state_to_text(radio_state));
printf("Current MARC state: %s\r\n", cc1100_get_marc_state());
printf("Current channel number: %u\r\n", cc1100_get_channel());
printf("Burst count: %u packet(s)\r\n", cc1100_burst_count);
printf("Retransmissions (unicast): %u - if no ACK\r\n", cc1100_retransmission_count_uc);
printf("Retransmissions (broadcast): %u - always\r\n", cc1100_retransmission_count_bc);
printf("Output power setting: %s\r\n", cc1100_get_output_power(buf));
if (radio_mode == CC1100_MODE_WOR) {
printf("RX polling interval: %u ms\r\n", cc1100_wor_config.rx_interval);
printf("WOR receive time: 0x%.2X (%f ms)\r\n", cc1100_wor_config.rx_time_reg,
cc1100_wor_config.rx_time_ms);
printf("CC1100 WOREVT0 register: 0x%.2X\r\n", cc1100_wor_config.wor_evt_0);
printf("CC1100 WOREVT1 register: 0x%.2X\r\n", cc1100_wor_config.wor_evt_1);
printf("CC1100 WOR_CTRL register: 0x%.2X\r\n", cc1100_wor_config.wor_ctrl);
printf("CC1100 MAN_WOR flag: %u\r\n", rflags.MAN_WOR);
}
}
/*---------------------------------------------------------------------------*/
// Change of RX polling interval (T_EVENT0)
/*---------------------------------------------------------------------------*/
inline uint16_t iround(double d)
{
return (uint16_t) (d + 0.5);
}
int cc1100_phy_calc_wor_settings(uint16_t millis)
{
/* Get packet interval as milliseconds */
double t_packet_interval = (double)((T_PACKET_INTERVAL) / 1000.0);
/* Calculate minimal T_EVENT0:
(1) t_rx_time > t_packet_interval
(2) t_rx_time = T_EVENT0 / 2 ^ (RX_TIME + 3 + WOR_RES)
------------------------------------------------------
with RX_TIME = 0 && WOR_RES = 0 => event0_min > t_packet_interval * 8
t_packet_interval = 3.8 ms (@400kbit/s)
=> event0_min = Math.ceil(3.8 * 8) + 10 */
uint16_t event0_min = (uint16_t)(t_packet_interval * 8) + 1 + 10;
/* Check if given value is in allowed range */
if (millis < event0_min || millis > EVENT0_MAX) {
return -1;
}
/* Time resolution for EVENT0 and other WOR parameters, */
/* possible values are 0 and 1 if WOR is used */
uint8_t wor_res = millis < WOR_RES_SWITCH ? 0 : 1;
/* Calculate new value for EVENT0 */
double tmp = (millis * 26) / (double) 750;
if (wor_res == 1) {
tmp /= 32;
}
tmp *= 1000;
uint16_t event0 = (uint16_t) iround(tmp);
/* Calculate all possible RX timeouts */
int i;
double rx_timeouts[DUTY_CYCLE_SIZE];
for (i = 0; i < DUTY_CYCLE_SIZE; i++) {
rx_timeouts[i] = (millis * duty_cycle[wor_res][i]) / 100;
}
/* Calculate index for optimal rx_timeout (MCSM2.RX_TIME) (if possible) */
int idx = -1;
for (i = DUTY_CYCLE_SIZE - 1; i >= 0; i--) {
if (rx_timeouts[i] > t_packet_interval) {
idx = i;
break;
}
}
/* If no index found, exit here (configuration with given value is not possible) */
if (idx == -1) {
return -1;
}
/* Calculate burst count (secure burst calculation with 8 extra packets) */
int burst_count = (int) iround(millis / t_packet_interval) + 8;
/* All calculations successful, now its safe to store */
/* final configuration values in global WOR configuration */
cc1100_wor_config.rx_interval = millis;
cc1100_wor_config.wor_ctrl = (wor_res == 0) ? 0x78 : 0x79;
cc1100_wor_config.wor_evt_0 = (uint8_t) event0;
cc1100_wor_config.wor_evt_1 = (uint8_t)(event0 >> 8);
cc1100_wor_config.rx_time_reg = idx;
cc1100_wor_config.rx_time_ms = rx_timeouts[idx];
/* If successful, return number of packets in a burst transfer */
return burst_count;
}
/*---------------------------------------------------------------------------*/
// Sequence number buffer management
/*---------------------------------------------------------------------------*/
static bool contains_seq_entry(uint8_t src, uint8_t id)
{
int i;
uint32_t cmp;
timex_t now_timex;
vtimer_now(&now_timex);
for (i = 0; i < MAX_SEQ_BUFFER_SIZE; i++) {
if ((seq_buffer[i].source == src) && (seq_buffer[i].identification == id)) {
/* Check if time stamp is OK */
cmp = (radio_mode == CC1100_MODE_WOR) ? cc1100_wor_config.rx_interval : 16000; /* constant RX ~16ms */
if ((timex_uint64(now_timex) - seq_buffer[i].m_ticks < cmp)) {
return true;
}
else {
seq_buffer[i].source = 0; /* Reset */
}
}
}
return false;
}
static void add_seq_entry(uint8_t src, uint8_t id)
{
/* Remove all entries with given source to avoid short time overflow
* of one bit counter (of the source node). So a valid packet would get
* lost (especially important in constant RX mode). */
int i;
for (i = 0; i < MAX_SEQ_BUFFER_SIZE; i++) {
if (seq_buffer[i].source == src) {
seq_buffer[i].source = 0; /* Reset */
}
}
/* Add new entry */
seq_buffer[seq_buffer_pos].source = src;
seq_buffer[seq_buffer_pos].identification = id;
timex_t now;
vtimer_now(&now);
seq_buffer[seq_buffer_pos].m_ticks = timex_uint64(now);
/* Store 16 bit sequence number of layer 0 for speedup */
last_seq_num = src;
last_seq_num <<= 8;
last_seq_num += id;
seq_buffer_pos++;
if (seq_buffer_pos == MAX_SEQ_BUFFER_SIZE) {
seq_buffer_pos = 0;
}
}
/*---------------------------------------------------------------------------*/
/* CC1100 physical layer send functions */
/*---------------------------------------------------------------------------*/
static void send_link_level_ack(uint8_t dest)
{
uint8_t oldState = radio_state; /* Save old state */
cc1100_packet_layer0_t ack; /* Local packet, don't overwrite */
radio_state = RADIO_SEND_ACK; /* Set state to "Sending ACK" */
cc1100_spi_write_reg(CC1100_MCSM0, 0x08); /* Turn off FS-Autocal */
cc1100_spi_write_reg(CC1100_MCSM1, 0x00); /* TX_OFFMODE = IDLE */
ack.length = 3; /* possible packet in txBuffer!*/
ack.address = dest;
ack.phy_src = rflags.RSSI;
ack.flags = (LAYER_1_PROTOCOL_LL_ACK << 1);
cc1100_send_raw((uint8_t *)&ack, /* IDLE -> TX (88.4 us) */
ack.length + 1);
cc1100_spi_write_reg(CC1100_MCSM0, 0x18); /* Turn on FS-Autocal */
cc1100_spi_write_reg(CC1100_MCSM1, 0x03); /* TX_OFFMODE = RX */
radio_state = oldState; /* Restore state */
cc1100_statistic.acks_send++;
}
static bool send_burst(cc1100_packet_layer0_t *packet, uint8_t retries, uint8_t rtc)
{
int i;
radio_state = RADIO_SEND_BURST;
rflags.LL_ACK = false;
for (i = 1; i <= cc1100_burst_count; i++) {
/*
* Number of bytes to send is:
* length of phy payload (packet->length)
* + size of length field (1 byte)
*/
extern unsigned long hwtimer_now(void);
timer_tick_t t = hwtimer_now() + RTIMER_TICKS(T_PACKET_INTERVAL);
cc1100_send_raw((uint8_t *)packet, packet->length + 1); /* RX -> TX (9.6 us) */
cc1100_statistic.raw_packets_out++;
/* Delay until predefined "send" interval has passed */
timer_tick_t now = hwtimer_now();
if (t > now) {
hwtimer_wait(t - now);
}
/**
* After sending the packet the CC1100 goes automatically
* into RX mode (21.5 us) (listening for an ACK).
* Do not interrupt burst if send to broadcast address (a node may
* have the broadcast address at startup and would stop the burst
* by sending an ACK).
*/
if (rflags.LL_ACK && packet->address != CC1100_BROADCAST_ADDRESS) {
cc1100_statistic.raw_packets_out_acked += i;
break;
}
}
/* No link level ACK -> do retry if retry counter greater zero
* Note: Event broadcast packets can be sent repeatedly if in
* constant RX mode. In WOR mode it is not necessary, so
* set retry count to zero.*/
if (!rflags.LL_ACK && retries > 0) {
return send_burst(packet, retries - 1, rtc + 1);
}
/* Store number of transmission retries */
rflags.RETC = rtc;
rflags.RPS = rtc * cc1100_burst_count + i;
if (i > cc1100_burst_count) {
rflags.RPS--;
}
rflags.TX = false;
/* Go to mode after TX (CONST_RX -> RX, WOR -> WOR) */
cc1100_go_after_tx();
/* Burst from any other node is definitely over */
last_seq_num = 0;
if (packet->address != CC1100_BROADCAST_ADDRESS && !rflags.LL_ACK) {
return false;
}
return true;
}
int cc1100_send(radio_address_t addr, protocol_t protocol, int priority, char *payload, radio_packet_length_t payload_len)
{
(void) priority;
bool result;
int return_code;
uint8_t address;
uint8_t retries;
/* Lock mutex, nobody else should send now */
cc1100_phy_mutex_lock();
/* TX state machine lock -> no timers (WOR), no packets (only ACKs) */
rflags.TX = true;
/* Set chip to idle state */
cc1100_set_idle();
/* CC1100 radio layer only supports 8-bit addresses */
address = addr;
/* Loopback not supported */
if (address == cc1100_get_address()) {
return_code = RADIO_ADDR_OUT_OF_RANGE;
goto mode_before_final;
}
/* Check address */
if (address > MAX_UID) {
return_code = RADIO_ADDR_OUT_OF_RANGE;
goto mode_before_final;
}
/* Packet too long */
if (payload_len > MAX_DATA_LENGTH) {
return_code = RADIO_PAYLOAD_TOO_LONG;
goto mode_before_final;
}
if (radio_state == RADIO_PWD) {
return_code = RADIO_WRONG_MODE;
goto mode_before_final;
}
/* Set number of transmission retries */
retries = (address == CC1100_BROADCAST_ADDRESS) ?
cc1100_retransmission_count_bc : cc1100_retransmission_count_uc;
memset(tx_buffer.data, 0, MAX_DATA_LENGTH); /* Clean data */
/* TODO: If packets are shorter than max packet size, WOR interval is too long.
* This must be solved in some way. */
tx_buffer.length = 3 + payload_len; /* 3 bytes (A&PS&F) + data length */
tx_buffer.address = address; /* Copy destination address */
tx_buffer.flags = 0x00; /* Set clean state */
tx_buffer.flags = W_FLAGS_PROTOCOL(protocol); /* Copy protocol identifier */
tx_buffer.phy_src = (uint8_t) cc1100_get_address(); /* Copy sender address */
/* Set identification number of packet */
tx_buffer.flags |= rflags.SEQ; /* Set flags.identification (bit 0) */
rflags.SEQ = !rflags.SEQ; /* Toggle value of layer 0 sequence number bit */
memcpy(tx_buffer.data, payload, payload_len); /* Copy data */
/* Send the packet */
cc1100_spi_write_reg(CC1100_MCSM0, 0x08); /* Turn off FS-Autocal */
result = send_burst(&tx_buffer, retries, 0); /* Send raw burst */
return_code = result ? payload_len : RADIO_OP_FAILED;
/* Collect statistics */
if (address != CC1100_BROADCAST_ADDRESS) {
cc1100_statistic.packets_out++;
if (result) {
cc1100_statistic.packets_out_acked++;
}
}
else {
cc1100_statistic.packets_out_broadcast++;
}
goto final;
mode_before_final:
rflags.TX = false;
/* Definitely set secure mode (CONST_RX -> RX, WOR -> WOR) */
cc1100_go_after_tx();
final:
/* Release mutex and return */
cc1100_phy_mutex_unlock();
return return_code;
}
/*---------------------------------------------------------------------------*/
/* RX Event Handler */
/*---------------------------------------------------------------------------*/
bool cc1100_set_packet_monitor(packet_monitor_t monitor)
{
packet_monitor = monitor;
return true;
}
int cc1100_set_packet_handler(protocol_t protocol, packet_handler_t handler)
{
if (protocol > 7) {
return -1; /* Only 3-bit value allowed */
}
return pm_set_handler(&handler_table, protocol, handler);
}
static void *cc1100_event_handler_function(void *arg)
{
(void) arg;
msg_t m;
while (1) {
if (timex_uint64(cc1100_watch_dog_period) != 0) {
vtimer_remove(&cc1100_watch_dog);
}
/* Test if any resource error has occurred */
if (rflags.KT_RES_ERR) {
rflags.KT_RES_ERR = false;
/* possibly do something, e.g. log error condition */
}
if (m.type == MSG_TIMER) {
if (radio_mode == CC1100_MODE_CONSTANT_RX) {
uint8_t state = cc1100_spi_read_status(CC1100_MARCSTATE) & MARC_STATE;
if ((state < 13 || state > 15) && radio_state == RADIO_RX && !rflags.TX) {
cc1100_statistic.watch_dog_resets++;
if (state != 1) {
cc1100_spi_strobe(CC1100_SIDLE);
}
cc1100_spi_strobe(CC1100_SFRX);
cc1100_go_receive();
}
}
else {
/* Radio mode is WOR, cannot read current MARC state, will */
/* always be IDLE. So do nothing here, e.g. disable watchdog. */
}
}
while (rx_buffer_size > 0) {
rx_buffer_t *packet = &rx_buffer[rx_buffer_head];
protocol_t p = R_FLAGS_PROTOCOL(packet->packet.flags);
if (packet_monitor != NULL) {
packet_monitor((void *)&packet->packet.data, packet->packet.length, p, &packet->info);
}
pm_invoke(&handler_table, p, (void *)&packet->packet.data, MAX_DATA_LENGTH, &packet->info);
dINT();
rx_buffer_size--;
rx_buffer_head++;
if (rx_buffer_head == RX_BUFF_SIZE) {
rx_buffer_head = 0;
}
eINT();
}
dINT();
if (rx_buffer_size == 0) {
if (timex_uint64(cc1100_watch_dog_period) != 0) {
vtimer_set_msg(&cc1100_watch_dog, cc1100_watch_dog_period,
cc1100_event_handler_pid, MSG_TIMER, NULL);
}
msg_receive(&m);
}
eINT();
}
return NULL;
}
/*---------------------------------------------------------------------------*/
/* CC1100 packet (RX) ISR */
/*---------------------------------------------------------------------------*/
void cc1100_phy_rx_handler(void)
{
msg_t m;
m.type = MSG_POLL;
bool dup = false;
bool res = false;
/* Possible packet received, RX -> IDLE (0.1 us) */
rflags.CAA = false;
rflags.MAN_WOR = false;
cc1100_statistic.packets_in++;
/* If WOR timer set, delete it now (new one will be set at end of ISR) */
if (wor_hwtimer_id != -1) {
hwtimer_remove(wor_hwtimer_id);
wor_hwtimer_id = -1;
}
/* Transfer packet into temporary buffer position */
res = cc1100_spi_receive_packet((uint8_t *) & (rx_buffer[rx_buffer_tail].packet), sizeof(cc1100_packet_layer0_t));
if (res) {
/* Get packet pointer and store additional data in packet info structure */
cc1100_packet_layer0_t *p = &(rx_buffer[rx_buffer_tail].packet);
rx_buffer[rx_buffer_tail].info.phy_src = p->phy_src;
rx_buffer[rx_buffer_tail].info.source = p->phy_src;
rx_buffer[rx_buffer_tail].info.destination = p->address;
rx_buffer[rx_buffer_tail].info.rssi = rflags.RSSI;
rx_buffer[rx_buffer_tail].info.lqi = rflags.LQI;
rx_buffer[rx_buffer_tail].info.promiscuous = false;
/* Get protocol and id field out of flags field */
uint8_t protocol = R_FLAGS_PROTOCOL(p->flags);
uint8_t identification = (p->flags & FLAGS_IDENTIFICATION);
/* If received packet was an ACK (here we must be in
* TX lock state, otherwise we don't expect an ACK) */
if (protocol == LAYER_1_PROTOCOL_LL_ACK && rflags.TX) {
/* And packet was for us */
if (p->address == cc1100_get_address()) {
/* Stop the burst */
rflags.LL_ACK = true;
rflags.RSSI_SEND = p->phy_src;
rflags.TCP = (uint32_t)((uint16_t *)p->data);
}
return;
}
else {
/* No ACK received so TOF is unpredictable */
rflags.TOF = 0;
}
/* If we are sending a burst, don't accept packets.
* Only ACKs are processed (for stopping the burst).
* Same if state machine is in TX lock. */
if (radio_state == RADIO_SEND_BURST || rflags.TX) {
cc1100_statistic.packets_in_while_tx++;
return;
}
/* If buffer is currently full -> don't check sequence numbers, send
* ACK and restore state (keep always one position free for temporary packets) */
if (rx_buffer_size >= RX_BUFF_SIZE - 1) {
goto send_ack;
}
/* Build 16 bit sequence number of layer 0 for fast check */
uint16_t new_seq_num = p->phy_src;
new_seq_num <<= 8;
new_seq_num += identification;
/* Duplicate packet detection */
dup = true;
/* If new and last sequence number are the same, then discard packet */
if (last_seq_num != new_seq_num) {
/* Do a more precise check (takes more time) with larger buffer */
if (!contains_seq_entry(p->phy_src, identification)) {
/* Sequence number is new, no duplicate packet */
dup = false;
/* Store sequence number */
add_seq_entry(p->phy_src, identification);
/* Make temporary packet in RX buffer to a "real" packet which is processed */
rx_buffer_size++;
if (rx_buffer_size > cc1100_statistic.rx_buffer_max) {
cc1100_statistic.rx_buffer_max = rx_buffer_size;
}
rx_buffer_tail++;
if (rx_buffer_tail == RX_BUFF_SIZE) {
rx_buffer_tail = 0;
}
/* Send empty message to wake up receiver process.
* Receiver process could already be running (triggered by previous message),
* so function would return 0 and assume the receiver is not waiting but indeed
* all is working fine.*/
msg_send_int(&m, cc1100_event_handler_pid);
cc1100_statistic.packets_in_up++;
}
}
send_ack:
/* If packet was send directly to us, send an ACK packet back to sender.
* But only not if the packet itself was a LL-ACK!*/
if (p->address == cc1100_get_address() && protocol != LAYER_1_PROTOCOL_LL_ACK) {
send_link_level_ack(p->phy_src);
/* After LL-ACK burst is over, reset number */
last_seq_num = 0;
}
/* If duplicate packet detected, clear rxBuffer position */
if (dup) {
cc1100_statistic.packets_in_dups++;
}
/* If packet interrupted this nodes send call,
* don't change anything after this point. */
if (radio_state == RADIO_AIR_FREE_WAITING) {
cc1100_spi_strobe(CC1100_SRX);
hwtimer_wait(IDLE_TO_RX_TIME);
return;
}
/* Valid packet. After a wake-up, the radio should be in IDLE.
* So put CC1100 to RX for WOR_TIMEOUT (have to manually put
* the radio back to sleep/WOR).*/
cc1100_spi_write_reg(CC1100_MCSM0, 0x08); /* Turn off FS-Autocal */
cc1100_spi_write_reg(CC1100_MCSM2, 0x07); /* Configure RX_TIME (until end of packet) */
if (radio_mode == CC1100_MODE_CONSTANT_RX) {
cc1100_spi_strobe(CC1100_SRX);
hwtimer_wait(IDLE_TO_RX_TIME);
radio_state = RADIO_RX;
/* Return here if mode is CONSTANT_RX_MODE */
return;
}
else {
cc1100_spi_strobe(CC1100_SPWD);
radio_state = RADIO_PWD;
}
/* Set hwtimer to put CC1100 back to RX after WOR_TIMEOUT_1 */
wor_hwtimer_id = hwtimer_set(WOR_TIMEOUT_1, cc1100_hwtimer_go_receive_wrapper, NULL);
if (wor_hwtimer_id == -1) {
/* Signal hwtimer resource error, radio stays in RX,
* so no big problem, only energy is wasted. */
rflags.KT_RES_ERR = true;
}
}
else {
/* No ACK received so TOF is unpredictable */
rflags.TOF = 0;
/* CRC false or RX buffer full -> clear RX FIFO in both cases */
last_seq_num = 0; /* Reset for correct burst detection */
cc1100_spi_strobe(CC1100_SIDLE); /* Switch to IDLE (should already be)... */
cc1100_spi_strobe(CC1100_SFRX); /* ...for flushing the RX FIFO */
/* If packet interrupted this nodes send call,
* don't change anything after this point. */
if (radio_state == RADIO_AIR_FREE_WAITING) {
cc1100_spi_strobe(CC1100_SRX);
hwtimer_wait(IDLE_TO_RX_TIME);
return;
}
/* If currently sending, exit here (don't go to RX/WOR) */
if (radio_state == RADIO_SEND_BURST) {
cc1100_statistic.packets_in_while_tx++;
return;
}
/* No valid packet, so go back to RX/WOR as soon as possible */
cc1100_go_receive();
}
}

View File

@ -1,143 +0,0 @@
/*
* Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved.
*
* 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 dev_cc110x_legacy_csma
* @{
*/
/**
* @file
* @internal
* @brief TI Chipcon CC110x physical radio driver
*
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @version $Revision: 1285 $
*
* @note $Id: cc1100_phy.h 1285 2009-08-27 13:22:42Z hillebra $
*/
#ifndef CC1100_PHY_H_
#define CC1100_PHY_H_
#include <stdbool.h>
#include <stdint.h>
//#include "cc1100.h"
#include "cc1100-internal.h"
#include "cc110x_legacy_csma.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MAX_DATA_LENGTH (0x3A) ///< Maximum data length of layer 0 = 58 Bytes.
/**
* @brief CC1100 layer 0 protocol
*
* <pre>
---------------------------------------------------
| | | | | |
| Length | Address | PhySrc | Flags | Data |
| | | | | |
---------------------------------------------------
1 byte 1 byte 1 byte 1 byte <= 58 bytes
Flags:
Bit | Meaning
--------------------
7:4 | -
3:1 | Protocol
0 | Identification
</pre>
Notes:
\li length & address are given by CC1100
\li Identification is increased is used to scan duplicates. It must be increased
for each new packet and kept for packet retransmissions.
*/
typedef struct __attribute__((packed)) cc1100_packet_layer0_t {
radio_packet_length_t length; ///< Length of the packet (without length byte)
uint8_t address; ///< Destination address
uint8_t phy_src; ///< Source address (physical source)
uint8_t flags; ///< Flags
uint8_t data[MAX_DATA_LENGTH]; ///< Data (high layer protocol)
} cc1100_packet_layer0_t;
typedef struct cc1100_wor_config_t {
uint16_t rx_interval; ///< RX polling interval in milliseconds
float rx_time_ms; ///< WOR_RX_TIME in milliseconds
uint8_t rx_time_reg; ///< WOR_RX_TIME (CC1100 "MCSM2.RX_TIME" register value)
uint8_t wor_evt_0; ///< CC1100 WOREVT0 register value
uint8_t wor_evt_1; ///< CC1100 WOREVT1 register value
uint8_t wor_ctrl; ///< CC1100 WORCTRL register value
} cc1100_wor_config_t;
/*---------------------------------------------------------------------------*/
// CC1100 Wake-On-Radio configuration
/*---------------------------------------------------------------------------*/
extern uint16_t cc1100_burst_count;
extern uint8_t cc1100_retransmission_count_uc;
extern uint8_t cc1100_retransmission_count_bc;
extern cc1100_wor_config_t cc1100_wor_config;
/*---------------------------------------------------------------------------*/
// CC1100 physical radio driver API
/*---------------------------------------------------------------------------*/
/**
* @brief Initialize the physical radio layer.
*/
void cc1100_phy_init(void);
/**
* Lock radio for exclusive access. If no lock could be gained,
* the current process is blocked and waits for release of lock.
*
* This function can be used by MAC for locking the radio, the
* ::cc1100_send function will automatically lock the radio.
*/
void cc1100_phy_mutex_lock(void);
/**
* Unlock radio. Must always be called after ::cc1100_phy_mutex_lock.
* If ::cc1100_send is called, it will automatically unlock the radio
* at the end of transmission.
*/
void cc1100_phy_mutex_unlock(void);
/**
* @brief Calculate and store Wake-On-Radio settings.
*
* Calculates WOR settings for a given RX interval in
* milliseconds and stores the values in global configuration.
* <p>
* Does not change settings if not applicable.
*
* @param millis Desired RX interval in milliseconds [50..60000].
*
* @return The burst count (number of packets in a burst transfer)
* or -1 if an error occurred (e.g. RX interval invalid).
*/
int cc1100_phy_calc_wor_settings(uint16_t millis);
/**
* @brief Handler function for incoming packets.
*
* This handler function must be called in the receive
* interrupt service routine.
*/
void cc1100_phy_rx_handler(void);
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* CC1100_PHY_H_ */

View File

@ -1,119 +0,0 @@
/*
* Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved.
*
* 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 dev_cc110x_legacy_csma
* @{
*/
/**
* @file
* @internal
* @brief TI Chipcon CC1100 SPI driver
*
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @version $Revision: 1775 $
*
* @note $Id: cc1100_spi.c 1775 2010-01-26 09:37:03Z hillebra $
*/
#include <stdio.h>
#include "irq.h"
#include "arch_cc1100.h"
#include "cc1100.h"
#include "cc1100_spi.h"
#include "cc1100-internal.h"
/*---------------------------------------------------------------------------*/
// CC1100 SPI access
/*---------------------------------------------------------------------------*/
uint8_t
cc1100_spi_writeburst_reg(uint8_t addr, char *src, uint8_t count)
{
int i = 0;
unsigned int cpsr = disableIRQ();
cc110x_spi_select();
cc110x_txrx(addr | CC1100_WRITE_BURST);
while (i < count) {
cc110x_txrx(src[i]);
i++;
}
cc110x_spi_unselect();
restoreIRQ(cpsr);
return count;
}
void
cc1100_spi_readburst_reg(uint8_t addr, char *buffer, uint8_t count)
{
int i = 0;
unsigned int cpsr = disableIRQ();
cc110x_spi_select();
cc110x_txrx(addr | CC1100_READ_BURST);
while (i < count) {
buffer[i] = cc110x_txrx(CC1100_NOBYTE);
i++;
}
cc110x_spi_unselect();
restoreIRQ(cpsr);
}
void
cc1100_spi_write_reg(uint8_t addr, uint8_t value)
{
unsigned int cpsr = disableIRQ();
cc110x_spi_select();
cc110x_txrx(addr);
cc110x_txrx(value);
cc110x_spi_unselect();
restoreIRQ(cpsr);
}
uint8_t cc1100_spi_read_reg(uint8_t addr)
{
uint8_t result;
unsigned int cpsr = disableIRQ();
cc110x_spi_select();
cc110x_txrx(addr | CC1100_READ_SINGLE);
result = cc110x_txrx(CC1100_NOBYTE);
cc110x_spi_unselect();
restoreIRQ(cpsr);
return result;
}
uint8_t cc1100_spi_read_status(uint8_t addr)
{
uint8_t result;
unsigned int cpsr = disableIRQ();
cc110x_spi_select();
cc110x_txrx(addr | CC1100_READ_BURST);
result = cc110x_txrx(CC1100_NOBYTE);
cc110x_spi_unselect();
restoreIRQ(cpsr);
return result;
}
uint8_t cc1100_spi_strobe(uint8_t c)
{
uint8_t result;
unsigned int cpsr = disableIRQ();
cc110x_spi_select();
result = cc110x_txrx(c);
cc110x_spi_unselect();
restoreIRQ(cpsr);
return result;
}
/** @} */

View File

@ -1,54 +0,0 @@
/*
* Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved.
*
* 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 dev_cc110x_legacy_csma
* @{
*/
/**
* @file
* @internal
* @brief TI Chipcon CC1100 SPI driver
*
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @version $Revision: 1775 $
*
* @note $Id: cc1100_spi.h 1775 2010-01-26 09:37:03Z hillebra $
*/
#ifndef CC1100_SPI_H_
#define CC1100_SPI_H_
#ifdef __cplusplus
extern "C" {
#endif
int cc110x_get_gdo0(void);
int cc110x_get_gdo1(void);
int cc110x_get_gdo2(void);
void cc110x_spi_init(void);
void cc110x_spi_cs(void);
void cc110x_spi_select(void);
void cc110x_spi_unselect(void);
uint8_t cc1100_spi_writeburst_reg(uint8_t addr, char *buffer, uint8_t count);
void cc1100_spi_readburst_reg(uint8_t addr, char *buffer, uint8_t count);
void cc1100_spi_write_reg(uint8_t addr, uint8_t value);
uint8_t cc1100_spi_read_reg(uint8_t addr);
uint8_t cc1100_spi_read_status(uint8_t addr);
uint8_t cc1100_spi_strobe(uint8_t c);
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* CC1100_SPI_H_ */

View File

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

View File

@ -1,298 +0,0 @@
/**
* 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 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.
*/
#include "panic.h"
#include "cc2420.h"
#include "cc2420_spi.h"
#include "cc2420_settings.h"
#include "cc2420_arch.h"
#include "hwtimer.h"
#include "transceiver.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
/* 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)
{
cc2420_spi_init();
hwtimer_wait(CC2420_WAIT_TIME);
cc2420_reset();
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);
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, */
/* RX bandpass filter = 1.3uA. */
reg = cc2420_read_reg(CC2420_REG_RXCTRL1);
reg |= CC2420_RXBPF_LOCUR;
cc2420_write_reg(CC2420_REG_RXCTRL1, reg);
/* Set the FIFOP threshold to maximum. */
cc2420_write_reg(CC2420_REG_IOCFG0, 127);
/* Turn off "Security enable" (page 32). */
reg = cc2420_read_reg(CC2420_REG_SECCTRL0);
reg &= ~CC2420_RXFIFO_PROTECTION;
cc2420_write_reg(CC2420_REG_SECCTRL0, reg);
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(kernel_pid_t 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)
{
cc2420_strobe(CC2420_STROBE_RFOFF);
cc2420_strobe(CC2420_STROBE_FLUSHRX);
cc2420_strobe(CC2420_STROBE_FLUSHRX);
cc2420_strobe(CC2420_STROBE_RXON);
}
void cc2420_rxoverflow_irq(void)
{
cc2420_strobe(CC2420_STROBE_FLUSHRX);
/* CC2420 datasheet says to do this twice... */
cc2420_strobe(CC2420_STROBE_FLUSHRX);
}
void cc2420_rx_irq(void)
{
cc2420_rx_handler();
}
void cc2420_set_monitor(bool mode)
{
uint16_t reg = cc2420_read_reg(CC2420_REG_MDMCTRL0);
if (mode) {
reg &= ~CC2420_ADR_DECODE;
} else {
reg |= CC2420_ADR_DECODE;
}
cc2420_write_reg(CC2420_REG_MDMCTRL0, reg);
}
bool cc2420_get_monitor(void)
{
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
*/
uint16_t freq= cc2420_read_reg(CC2420_REG_FSCTRL);
freq &= ~CC2420_FREQ_MASK;
freq |= (357 + (5 * (chan - 11)));
cc2420_write_reg(CC2420_REG_FSCTRL, freq);
return ((unsigned int) chan);
}
unsigned int cc2420_get_channel(void)
{
/* undo calculation from cc2420_set_channel() */
return (((cc2420_read_reg(CC2420_REG_FSCTRL) & CC2420_FREQ_MASK) - 357) / 5) + 11;
}
uint16_t cc2420_set_address(uint16_t addr)
{
uint8_t buf[2];
buf[0] = (uint8_t)(addr & 0xFF);
buf[1] = (uint8_t)(addr >> 8);
cc2420_write_ram(CC2420_RAM_SHORTADR, buf, 2);
cc2420_set_address_long(0xFFFF & addr);
return addr;
}
uint64_t cc2420_set_address_long(uint64_t addr)
{
uint8_t buf[8];
buf[0] = (uint8_t)(addr & 0xFF);
buf[1] = (uint8_t)(addr >> 8);
buf[2] = (uint8_t)(addr >> 16);
buf[3] = (uint8_t)(addr >> 24);
buf[4] = (uint8_t)(addr >> 32);
buf[5] = (uint8_t)(addr >> 40);
buf[6] = (uint8_t)(addr >> 48);
buf[7] = (uint8_t)(addr >> 56);
cc2420_write_ram(CC2420_RAM_IEEEADR, buf, 8);
return addr;
}
uint16_t cc2420_get_address(void)
{
uint16_t addr;
cc2420_read_ram(CC2420_RAM_SHORTADR, (uint8_t *)&addr, sizeof(addr));
return addr;
}
uint64_t cc2420_get_address_long(void)
{
uint64_t addr;
cc2420_read_ram(CC2420_RAM_IEEEADR, (uint8_t *)&addr, sizeof(addr));
return addr;
}
uint16_t cc2420_set_pan(uint16_t pan)
{
uint8_t buf[2];
buf[0] = (uint8_t)(pan & 0xFF);
buf[1] = (uint8_t)(pan >> 8);
cc2420_write_ram(CC2420_RAM_PANID, buf, 2);
return pan;
}
uint16_t cc2420_get_pan(void)
{
uint16_t pan;
cc2420_read_ram(CC2420_RAM_PANID, (uint8_t *)&pan, sizeof(pan));
return pan;
}
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,102 +0,0 @@
/**
* 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 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.
*/
#include <stdio.h>
#include "cc2420.h"
#include "cc2420_settings.h"
#include "cc2420_arch.h"
#include "cc2420_spi.h"
#include "ieee802154_frame.h"
#include "kernel_types.h"
#include "transceiver.h"
#include "msg.h"
#define ENABLE_DEBUG (0)
#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; /* 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 pkt_len, pkt_lqi;
int8_t pkt_rssi;
bool crc_ok;
/* read length */
cc2420_read_fifo(&pkt_len, 1);
/* 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((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 != IEEE_802154_ACK_FRAME) {
#if ENABLE_DEBUG
ieee802154_frame_print_fcf_frame(&cc2420_rx_buffer[rx_buffer_next].frame);
#endif
/* notify transceiver thread if any */
if (transceiver_pid != KERNEL_PID_UNDEF) {
msg_t m;
m.type = (uint16_t) RCV_PKT_CC2420;
m.content.value = rx_buffer_next;
msg_send_int(&m, transceiver_pid);
}
}
#if ENABLE_DEBUG
else {
DEBUG("GOT ACK for SEQ %u\n", cc2420_rx_buffer[rx_buffer_next].frame.seq_nr);
ieee802154_frame_print_fcf_frame(&cc2420_rx_buffer[rx_buffer_next].frame);
}
#endif
/* shift to next buffer element */
if (++rx_buffer_next == CC2420_RX_BUF_SIZE) {
rx_buffer_next = 0;
}
}

View File

@ -1,105 +0,0 @@
/**
* cc2420_spi.c - Implementation of SPI cc2420 functions.
* Copyright (C) 2013 Milan Babel <babel@inf.fu-berlin.de>
*
* 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.
*/
#include "cc2420_spi.h"
#include "cc2420_arch.h"
#include "cc2420_settings.h"
#include "irq.h"
/* reg */
void cc2420_write_reg(uint8_t addr, uint16_t value) {
unsigned int cpsr = disableIRQ();
cc2420_spi_select();
cc2420_txrx(addr | CC2420_WRITE_ACCESS);
cc2420_txrx((uint8_t) (value >> 8));
cc2420_txrx((uint8_t) (value & 0xFF));
cc2420_spi_unselect();
restoreIRQ(cpsr);
}
uint16_t cc2420_read_reg(uint8_t addr) {
uint16_t result;
unsigned int cpsr = disableIRQ();
cc2420_spi_select();
cc2420_txrx(addr | CC2420_READ_ACCESS);
result = cc2420_txrx(NOBYTE);
result <<= 8;
result |= cc2420_txrx(NOBYTE);
cc2420_spi_unselect();
restoreIRQ(cpsr);
return result;
}
uint8_t cc2420_strobe(uint8_t c) {
uint8_t result;
unsigned int cpsr = disableIRQ();
cc2420_spi_select();
result = cc2420_txrx(c);
cc2420_spi_unselect();
restoreIRQ(cpsr);
return result;
}
/* ram */
radio_packet_length_t cc2420_read_ram(uint16_t addr, uint8_t* buffer, radio_packet_length_t len) {
radio_packet_length_t i;
unsigned int cpsr = disableIRQ();
cc2420_spi_select();
cc2420_txrx(CC2420_RAM_ACCESS | (addr & 0x7F));
cc2420_txrx(((addr >> 1) & 0xC0) | CC2420_RAM_READ_ACCESS);
for (i = 0; i < len; i++) {
buffer[i] = cc2420_txrx(NOBYTE);
}
cc2420_spi_unselect();
restoreIRQ(cpsr);
return i;
}
radio_packet_length_t cc2420_write_ram(uint16_t addr, uint8_t* buffer, radio_packet_length_t len) {
radio_packet_length_t i;
unsigned int cpsr = disableIRQ();
cc2420_spi_select();
cc2420_txrx(CC2420_RAM_ACCESS | (addr & 0x7F));
cc2420_txrx(((addr >> 1) & 0xC0) | CC2420_RAM_WRITE_ACCESS);
for (i = 0; i < len; i++) {
cc2420_txrx(buffer[i]);
}
cc2420_spi_unselect();
restoreIRQ(cpsr);
return i;
}
/* fifo */
radio_packet_length_t cc2420_write_fifo(uint8_t* data, radio_packet_length_t data_length) {
radio_packet_length_t i;
unsigned int cpsr = disableIRQ();
cc2420_spi_select();
cc2420_txrx(CC2420_REG_TXFIFO | CC2420_WRITE_ACCESS);
for (i = 0; i < data_length; i++) {
cc2420_txrx(data[i]);
}
cc2420_spi_unselect();
restoreIRQ(cpsr);
return i;
}
radio_packet_length_t cc2420_read_fifo(uint8_t* data, radio_packet_length_t data_length) {
radio_packet_length_t i;
unsigned int cpsr = disableIRQ();
cc2420_spi_select();
cc2420_txrx(CC2420_REG_RXFIFO | CC2420_READ_ACCESS);
for (i = 0; i < data_length; i++) {
data[i] = cc2420_txrx(NOBYTE);
}
cc2420_spi_unselect();
restoreIRQ(cpsr);
return i;
}

View File

@ -1,314 +0,0 @@
/**
* cc2420_rx.c - Implementation of transmitting cc2420 functions.
* Copyright (C) 2013 Milan Babel <babel@inf.fu-berlin.de>
*
* 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.
*/
#include <stdio.h>
#include "cc2420.h"
#include "cc2420_spi.h"
#include "cc2420_settings.h"
#include "cc2420_arch.h"
#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 sequence_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] = sequence_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 & CC2420_STATUS_TX_UNDERFLOW) {
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] == sequence_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)
{
radio_tx_status_t st = cc2420_load_tx_buf(kind, dest,
use_long_addr,
wants_ack,
buf, len);
if (st != RADIO_TX_OK) {
return st;
}
return cc2420_transmit_tx_buf();
}
int16_t cc2420_send(cc2420_packet_t *packet)
{
volatile uint32_t abort_count = 0;
/* Set missing frame information */
packet->frame.fcf.frame_ver = 0;
if (packet->frame.src_pan_id == packet->frame.dest_pan_id) {
packet->frame.fcf.panid_comp = 1;
}
else {
packet->frame.fcf.panid_comp = 0;
}
if (packet->frame.fcf.src_addr_m == 2) {
packet->frame.src_addr[0] = (uint8_t)(cc2420_get_address() >> 8);
packet->frame.src_addr[1] = (uint8_t)(cc2420_get_address() & 0xFF);
}
else if (packet->frame.fcf.src_addr_m == 3) {
packet->frame.src_addr[0] = (uint8_t)(cc2420_get_address_long() >> 56);
packet->frame.src_addr[1] = (uint8_t)(cc2420_get_address_long() >> 48);
packet->frame.src_addr[2] = (uint8_t)(cc2420_get_address_long() >> 40);
packet->frame.src_addr[3] = (uint8_t)(cc2420_get_address_long() >> 32);
packet->frame.src_addr[4] = (uint8_t)(cc2420_get_address_long() >> 24);
packet->frame.src_addr[5] = (uint8_t)(cc2420_get_address_long() >> 16);
packet->frame.src_addr[6] = (uint8_t)(cc2420_get_address_long() >> 8);
packet->frame.src_addr[7] = (uint8_t)(cc2420_get_address_long() & 0xFF);
}
packet->frame.src_pan_id = cc2420_get_pan();
packet->frame.seq_nr = sequence_nr;
sequence_nr += 1;
/* calculate size of the package (header + payload + fcs) */
packet->length = ieee802154_frame_get_hdr_len(&packet->frame) +
packet->frame.payload_len + 2;
if (packet->length > CC2420_MAX_PKT_LENGTH) {
return -1;
}
/* FCS is added in hardware */
uint8_t pkt[packet->length - 2];
/* generate pkt */
cc2420_gen_pkt(pkt, packet);
/* idle & flush tx */
cc2420_strobe(CC2420_STROBE_RFOFF);
cc2420_strobe(CC2420_STROBE_FLUSHTX);
/* write length and packet to fifo */
cc2420_write_fifo(&packet->length, 1);
cc2420_write_fifo(pkt, packet->length - 2);
unsigned int cpsr = disableIRQ();
cc2420_strobe(CC2420_STROBE_TXON);
// Wait for SFD to be set -> sync word transmitted
while (cc2420_get_sfd() == 0) {
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\n");
/* TODO: error handling */
packet->length = 0;
break;
}
}
DEBUG("SEQ: %u\n", packet->frame.seq_nr);
restoreIRQ(cpsr);
/* wait for packet to be send */
while (cc2420_get_sfd() != 0);
cc2420_switch_to_rx();
return packet->length;
}
/**
* @brief Static function to generate byte array from cc2420 packet.
*
*/
static void cc2420_gen_pkt(uint8_t *buf, cc2420_packet_t *packet)
{
uint8_t index, offset;
index = ieee802154_frame_init(&packet->frame, buf);
offset = index;
while (index < packet->length - 2) {
buf[index] = packet->frame.payload[index - offset];
index += 1;
}
}

View File

@ -1,132 +0,0 @@
/*
* Copyright 2014, Freie Universitaet Berlin (FUB). All rights reserved.
*
* 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.
*/
/**
* @file
* @ingroup CC2420
* @brief CC2420 dependend functions
*
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @author Milan Babel <babel@inf.fu-berlin.de>
* @author Kévin Roussel <Kevin.Roussel@inria.fr>
*/
#ifndef CC2420_ARCH_H
#define CC2420_ARCH_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief SPI tx and rx function.
*
* @param[in] c byte which should be transmitted.
*
* @return Byte which was received after transmitting.
*
*/
uint8_t cc2420_txrx(uint8_t c);
/**
* @brief Gets the status of the FIFOP 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
*
* @return Status of the CCA pin.
*
*/
uint8_t cc2420_get_cca(void);
/**
* @brief Does a hardware reset of the CC2420.
*
*/
void cc2420_reset(void);
/**
* @brief Init the SPI interface.
*
*/
void cc2420_spi_init(void);
/**
* @brief Selects the CC2420 on the spi bus.
*
*/
void cc2420_spi_select(void);
/**
* @brief Unselects the CC2420 on the spi bus.
*
*/
void cc2420_spi_unselect(void);
/**
* @brief Enable interrupts on the GDO0 pin.
*
*/
void cc2420_gdo0_enable(void);
/**
* @brief Disable interrupts on the GDO0 pin.
*
*/
void cc2420_gdo0_disable(void);
/**
* @brief Enable interrupts on the GDO2 pin.
*
*/
void cc2420_gdo2_enable(void);
/**
* @brief Disable interrupts on the GDO2 pin.
*
*/
void cc2420_gdo2_disable(void);
/**
* @brief Init interrupts.
*
*/
void cc2420_init_interrupts(void);
/**
* @brief Function called before send to disable interrupts.
*
*/
void cc2420_before_send(void);
/**
* @brief Function called after send to reenable interrupts.
*
*/
void cc2420_after_send(void);
#ifdef __cplusplus
}
#endif
#endif /* CC2420_ARCH_H */

View File

@ -1,319 +0,0 @@
/*
* Copyright (C) 2014 Milan Babel <babel@inf.fu-berlin.de> and INRIA
*
* 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 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>
*
*/
#ifndef CC2420_SETTINGS_H
#define CC2420_SETTINGS_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name CC2420 access mode values.
* @brief Values defining the command you want to give to the CC2420:
* read or write access to registers or RAM.
* These values are to be OR-ed to the address you want to access.
* @see CC2420 datasheet section 13.2 page 31.
* @{
*/
/** @brief Read-Register Mode */
#define CC2420_READ_ACCESS 0x40
/** @brief Write Register Mode */
#define CC2420_WRITE_ACCESS 0x00
/**
* @brief RAM Access Modifier (to use with @c CC2420_RAM_READ_ACCESS
* or @c CC2420_RAM_WRITE_ACCESS)
*/
#define CC2420_RAM_ACCESS 0x80
/** @brief Read-Memory Mode (to use with @c CC2420_RAM_ACCESS) */
#define CC2420_RAM_READ_ACCESS 0x20
/** @brief Write-Memory Mode (to use with @c CC2420_RAM_ACCESS) */
#define CC2420_RAM_WRITE_ACCESS 0x00
/**
* @}
*/
/**
* @name Strobe command addresses
* @brief Addresses of "strobe" commands in CC2420 address space.
* @see CC2420 datasheet section 37 pages 61--62.
* @{
*/
/** @brief NO Operation @see NOBYTE */
#define CC2420_STROBE_NOP 0x00
/** @brief Turn transceiver (internal oscillator) on */
#define CC2420_STROBE_XOSCON 0x01
/** @brief Calibrate TX frequency, then put transceiver in wait (inactive) mode */
#define CC2420_STROBE_TXCAL 0x02
/** @brief Put transceiver in RX mode */
#define CC2420_STROBE_RXON 0x03
/** @brief Put transceiver in TX mode */
#define CC2420_STROBE_TXON 0x04
/** @brief Put transceiver in TX mode after checking media availability */
#define CC2420_STROBE_TXONCCA 0x05
/** @brief Put transceiver in idle mode */
#define CC2420_STROBE_RFOFF 0x06
/** @brief Turn transceiver (internal oscillator) off -> power-down mode */
#define CC2420_STROBE_XOSCOFF 0x07
/** @brief Flush transceiver's RX buffer */
#define CC2420_STROBE_FLUSHRX 0x08
/** @brief Flush transceiver's TX buffer */
#define CC2420_STROBE_FLUSHTX 0x09
/** @brief Send an ACK frame with pending field cleared */
#define CC2420_STROBE_ACK 0x0A
/** @brief Send an ACK frame with pending field set */
#define CC2420_STROBE_ACKPEND 0x0B
/** @brief Start RXFIFO in-line decryption/verification */
#define CC2420_STROBE_RXDEC 0x0C
/** @brief Start TXFIFO in-line encryption/authentication */
#define CC2420_STROBE_TXENC 0x0D
/** @brief Start standalone AES encryption */
#define CC2420_STROBE_AES 0x0E
/**
* @}
*/
/**
* @name CC2420 Configuration Register addresses.
* @brief Addresses of configuration registers in CC2420 address space.
* @see CC2420 datasheet section 37 pages 61 to 80.
* @{
*/
/** @brief Main Control Register */
#define CC2420_REG_MAIN 0x10
/**
* @brief Modem Control Register 0
* @{
*/
#define CC2420_REG_MDMCTRL0 0x11
/** @brief Address Decode enable flag */
#define CC2420_ADR_DECODE 0x800
/** @brief Reserved Frame accept enable flag */
#define CC2420_RES_FRM_MODE 0x2000
/** @brief PAN Coordinator mode enable flag */
#define CC2420_PAN_COORD 0x1000
/** @brief Automatic CRC computation/verification enable flag */
#define CC2420_AUTOCRC 0x20
/** @brief Automatic ACK response enable flag */
#define CC2420_AUTOACK 0x10
/** @} */
/** @brief Modem Control Register 1 */
#define CC2420_REG_MDMCTRL1 0x12
/**
* @brief RSSI and CCA Status and Control Register
* @{
*/
#define CC2420_REG_RSSI 0x13
/** @brief CCA Threshold value mask */
#define CC2420_CCATHR_MASK 0xFF00
/** @brief RSSI estimate value mask */
#define CC2420_RSSI_MASK 0xFF
/** @} */
/** @brief Sync Word */
#define CC2420_REG_SYNCWORD 0x14
/**
* @brief Transmit Control Register
* @{
*/
#define CC2420_REG_TXCTRL 0x15
/** @brief Output PA Level value mask */
#define CC2420_PALEVEL_MASK 0x1F
/** @} */
/** @brief Receive Control Register 0 */
#define CC2420_REG_RXCTRL0 0x16
/**
* @brief Receive Control Register 1
* @{
*/
#define CC2420_REG_RXCTRL1 0x17
/** @brief RX BandPass Filter Bias Current mode flag */
#define CC2420_RXBPF_LOCUR 0x2000
/** @} */
/**
* @brief Frequency Synthesizer Control and Status Register
* @{
*/
#define CC2420_REG_FSCTRL 0x18
/** @brief RF Operating Frequency mask */
#define CC2420_FREQ_MASK 0x3FF
/** @} */
/**
* @brief Security Control Register 0
* @{
*/
#define CC2420_REG_SECCTRL0 0x19
/** @brief RXFIFO Protection enable flag */
#define CC2420_RXFIFO_PROTECTION 0x200
/** @} */
/** @brief Security Control Register 1 */
#define CC2420_REG_SECCTRL1 0x1A
/** @brief Battery Monitor Control Register */
#define CC2420_REG_BATTMON 0x1B
/**
* @brief I/O Configuration Register 0
* @{
*/
#define CC2420_REG_IOCFG0 0x1C
/** @brief FIFOP Activation Threshold mask */
#define CC2420_FIFOPTHR_MASK 0x7F
/** @} */
/** @brief I/O Configuration Register 1 */
#define CC2420_REG_IOCFG1 0x1D
/** @brief Manufacturer ID (low word) */
#define CC2420_REG_MANFIDL 0x1E
/** @brief Manufacturer ID (high word) */
#define CC2420_REG_MANFIDH 0x1F
/** @brief Finite State Machine Time Constants */
#define CC2420_REG_FSMTC 0x20
/** @brief Manual signal AND override Register */
#define CC2420_REG_MANAND 0x21
/** @brief Manual signal OR override Register */
#define CC2420_REG_MANOR 0x22
/** @brief AGC Control Register */
#define CC2420_REG_AGCCTRL 0x23
/** @brief AGC Test Register 0 */
#define CC2420_REG_AGCTST0 0x24
/** @brief AGC Test Register 1 */
#define CC2420_REG_AGCTST1 0x25
/** @brief AGC Test Register 2 */
#define CC2420_REG_AGCTST2 0x26
/** @brief Frequency Synthesizer Test Register 0 */
#define CC2420_REG_FSTST0 0x27
/** @brief Frequency Synthesizer Test Register 1 */
#define CC2420_REG_FSTST1 0x28
/** @brief Frequency Synthesizer Test Register 2 */
#define CC2420_REG_FSTST2 0x29
/** @brief Frequency Synthesizer Test Register 3 */
#define CC2420_REG_FSTST3 0x2A
/** @brief Receiver Bandpass Filters Test Register */
#define CC2420_REG_RXBPFTST 0x2B
/** @brief Finite State Machine Information Register */
#define CC2420_REG_FSMSTATE 0x2C
/** @brief ADC Test Register */
#define CC2420_REG_ADCTST 0x2D
/** @brief DAC Test Register */
#define CC2420_REG_DACTST 0x2E
/** @brief Top-level Test Register */
#define CC2420_REG_TOPTST 0x2F
/** @brief Transmit FIFO Byte Register */
#define CC2420_REG_TXFIFO 0x3E
/** @brief Receive FIFO Byte Register */
#define CC2420_REG_RXFIFO 0x3F
/**
* @}
*/
/**
* @name CC2420 Configuration RAM addresses.
* @brief Addresses of configuration zones in CC2420 RAM address space.
* @see CC2420 datasheet section 13.5 page 31.
* @{
*/
/** @brief Short (16-bit) address of the system into its current PAN. */
#define CC2420_RAM_SHORTADR 0x16A
/** @brief 16-bit ID of the PAN into which the system is associated. */
#define CC2420_RAM_PANID 0x168
/** @brief IEEE long (64-bit) address of the system. */
#define CC2420_RAM_IEEEADR 0x160
/**
* @}
*/
/**
* @name Status byte flags
* @brief Bits of the status byte returned by CC2420 adter each command.
* @see CC2420 datasheet section 13.3 page 29.
* @{
*/
/**
* @brief Bit XOSC16M_STABLE of the status register.
* @details This bit indicates whether the 16-MHz oscillator
* is running (value 1), or if the transceiver
* is in power-down mode (value 0).
*/
#define CC2420_STATUS_XOSC16M_STABLE 0x40
/**
* @brief Bit TX_UNDERFLOW of the status register.
* @details This bit indicates whether the latest transmission has failed
* because the TX buffer didn't contain enough data (error bit).
*/
#define CC2420_STATUS_TX_UNDERFLOW 0x20
/**
* @brief Bit ENC_BUSY of the status register.
* @details This bit indicates whether the encryption module
* is currently busy (value 1), or not (value 0).
*/
#define CC2420_STATUS_ENC_BUSY 0x10
/**
* @brief Bit TX_ACTIVE of the status register.
* @details This bit indicates whether a RF transmission
* is currently in progress (value 1), or not (value 0).
*/
#define CC2420_STATUS_TX_ACTIVE 0x08
/**
* @brief Bit PLL_LOCK of the status register.
* @details This bit indicates whether the frequency synthesizer PLL
* is currently locked (value 1), or not (value 0).
*/
#define CC2420_STATUS_PLL_LOCK 0x04
/**
* @brief Bit RSSI_VALID of the status register.
* @details This bit indicates whether the RSSI value
* is valid (value 1), or not (value 0).
* The RSSI is always valid when the CC2420
* has been in RX mode for at least 128 µs),
*/
#define CC2420_STATUS_RSSI_VALID 0x02
/**
* @}
*/
/**
* @brief Null command strobe/parameter.
* @details Basically a strobe address used to perform a NOP on CC2420;
* This is useful to just query the status byte, or more generally
* passively receive bytes from the transceiver on its SPI link.
*/
#define NOBYTE 0x0
/* Various configuration settings for the CC2420 drivers */
#define CC2420_DEFAULT_CHANNR (26U)
#define CC2420_SYNC_WORD_TX_TIME 900000
#define CC2420_RX_BUF_SIZE 3
#define CC2420_WAIT_TIME 500
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,100 +0,0 @@
/*
* Copyright (C) 2013 Milan Babel <babel@inf.fu-berlin.de>
*
* 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 CC2420
* @{
* @file
* @brief Definition of CC2420 SPI functions
* @author Milan Babel <babel@inf.fu-berlin.de>
*
*/
#ifndef CC2420_SPI_H
#define CC2420_SPI_H
#include <stdio.h>
#include "board.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Writes a byte to the cc2420 register.
*
* @param[in] addr The address of the register to write.
* @param[in] value The value to write in the register.
*/
void cc2420_write_reg(uint8_t addr, uint16_t value);
/**
* @brief Reads a byte from the cc2420 register.
*
* @param[in] addr The address of the register to read.
*
* @return The value in the register.
*/
uint16_t cc2420_read_reg(uint8_t addr);
/**
* @brief Sends a strobe command to the cc2420.
*
* @param[in] c The strobe command to send.
*
* @return The result of the strobe command.
*/
uint8_t cc2420_strobe(uint8_t c);
/**
* @brief Reads multiple bytes from the cc2420 ram.
*
* @param[in] addr The ram address to read.
* @param[out] buffer A buffer to store the value of the ram.
* @param[in] len The count of bytes which should be read.
*
* @return The number of bytes read.
*/
radio_packet_length_t cc2420_read_ram(uint16_t addr, uint8_t* buffer, radio_packet_length_t len);
/**
* @brief Writes multiple bytes to the cc2420 ram.
*
* @param[in] addr The ram address to write.
* @param[in] buffer A buffer with the value to write to the ram.
* @param[in] len The count of bytes which should be written.
*
* @return The number of bytes written.
*/
radio_packet_length_t cc2420_write_ram(uint16_t addr, uint8_t* buffer, radio_packet_length_t len);
/**
* @brief Writes multiple bytes to the cc2420 fifo.
*
* @param[in] data A buffer with the value to write to the fifo.
* @param[in] data_length The count of bytes which should be written.
*
* @return The number of bytes written.
*/
radio_packet_length_t cc2420_write_fifo(uint8_t* data, radio_packet_length_t data_length);
/**
* @brief Reads multiple bytes from the cc2420 fifo.
*
* @param[out] data A buffer to store the value of the fifo.
* @param[in] data_length The count of bytes which should be read.
*
* @return The number of bytes read.
*/
radio_packet_length_t cc2420_read_fifo(uint8_t* data, radio_packet_length_t data_length);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,402 +0,0 @@
/*
* Copyright (C) 2014 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_at86rf231 at86rf231
* @ingroup drivers
* @brief Device driver for the Atmel AT86RF231 radio
* @{
*
* @file
* @brief Interface definition for the AT86RF231 device driver
*
* @author Alaeddine Weslati <alaeddine.weslati@inria.fr>
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de>
*/
#ifndef AT86RF231_H_
#define AT86RF231_H_
#include <stdio.h>
#include <stdint.h>
#include "kernel_types.h"
#include "board.h"
#include "radio/types.h"
#include "ieee802154_frame.h"
#include "at86rf231/at86rf231_settings.h"
#include "periph/gpio.h"
#include "netdev/802154.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Maximum length of a frame on at86rf231
*/
#define AT86RF231_MAX_PKT_LENGTH (127)
/**
* @brief Maximum payload length
* @details Assuming intra PAN short address mode
* results in 2 bytes FCF
* + 1 bytes SEQNr
* + 2 bytes PAN Id
* + 2 bytes destination address
* + 2 bytes source address
*/
#define AT86RF231_MAX_DATA_LENGTH (118)
/**
* @brief Broadcast address
*/
#define AT86RF231_BROADCAST_ADDRESS (0xFFFF)
/**
* @brief at86rf231's lowest supported channel
*/
#define AT86RF231_MIN_CHANNEL (0)
/**
* @brief at86rf231's highest supported channel
*/
#define AT86RF231_MAX_CHANNEL (26)
/**
* @brief Structure to represent a at86rf231 packet.
*/
typedef struct __attribute__((packed))
{
/** @{ */
uint8_t length; /**< the length of the frame of the frame including fcs*/
ieee802154_frame_t frame; /**< the ieee802154 frame */
uint8_t rssi; /**< the rssi value */
uint8_t crc; /**< 1 if crc was successfull, 0 otherwise */
uint8_t lqi; /**< the link quality indicator */
/** @} */
} at86rf231_packet_t;
extern netdev_t at86rf231_netdev; /**< netdev representation of this driver */
/**
* @brief States to be assigned to `driver_state`
* @{
*/
#define AT_DRIVER_STATE_DEFAULT (0)
#define AT_DRIVER_STATE_SENDING (1)
/** @} */
/**
* @brief To keep state inside of at86rf231 driver
* @details This variable is used to determine if a TRX_END IRQ from
* the radio transceiver has to be interpreted as end of
* sending or reception.
*/
extern uint8_t driver_state;
/**
* @brief Initialize the at86rf231 transceiver
*/
int at86rf231_initialize(netdev_t *dev);
#ifdef MODULE_TRANSCEIVER
/**
* @brief Init the at86rf231 for use with RIOT's transceiver module.
*
* @param[in] tpid The PID of the transceiver thread.
*/
void at86rf231_init(kernel_pid_t tpid);
#endif
/**
* @brief Turn at86rf231 on.
*
* @return 1 if the radio was correctly turned on; 0 otherwise.
*/
int at86rf231_on(void);
/**
* @brief Turn at86rf231 off.
*/
void at86rf231_off(void);
/**
* @brief Indicate if the at86rf231 is on.
*
* @return 1 if the radio transceiver is on (active); 0 otherwise.
*/
int at86rf231_is_on(void);
/**
* @brief Switches the at86rf231 into receive mode.
*/
void at86rf231_switch_to_rx(void);
/**
* @brief Turns monitor (promiscuous) mode on or off.
*
* @param[in] mode The desired mode:
* 1 for monitor (promiscuous) mode;
* 0 for normal (auto address-decoding) mode.
*/
void at86rf231_set_monitor(int mode);
/**
* @brief Indicate if the at86rf231 is in monitor (promiscuous) mode.
*
* @return 1 if the transceiver is in monitor (promiscuous) mode;
* 0 if it is in normal (auto address-decoding) mode.
*/
int at86rf231_get_monitor(void);
/**
* @brief Set the channel of the at86rf231.
*
* @param[in] chan The desired channel, valid channels are from 11 to 26.
*
* @return The tuned channel after calling, or -1 on error.
*/
int at86rf231_set_channel(unsigned int chan);
/**
* @brief Get the channel of the at86rf231.
*
* @return The tuned channel.
*/
unsigned int at86rf231_get_channel(void);
/**
* @brief Sets the short address of the at86rf231.
*
* @param[in] addr The desired address.
*
* @return The set address after calling.
*/
uint16_t at86rf231_set_address(uint16_t addr);
/**
* @brief Gets the current short address of the at86rf231.
*
* @return The current short address.
*/
uint16_t at86rf231_get_address(void);
/**
* @brief Sets the IEEE long address of the at86rf231.
*
* @param[in] addr The desired address.
*
* @return The set address after calling.
*/
uint64_t at86rf231_set_address_long(uint64_t addr);
/**
* @brief Gets the current IEEE long address of the at86rf231.
*
* @return The current IEEE long address.
*/
uint64_t at86rf231_get_address_long(void);
/**
* @brief Sets the pan ID of the at86rf231.
*
* @param[in] pan The desired pan ID.
*
* @return The set pan ID after calling.
*/
uint16_t at86rf231_set_pan(uint16_t pan);
/**
* @brief Gets the current IEEE long address of the at86rf231.
*
* @return The current IEEE long address.
*/
uint16_t at86rf231_get_pan(void);
/**
* @brief Sets the output (TX) power of the at86rf231.
*
* @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 at86rf231_set_tx_power(int pow);
/**
* @brief Gets the current output (TX) power of the at86rf231.
*
* @return The current TX (output) power.
*/
int at86rf231_get_tx_power(void);
/**
* @brief Checks if the radio medium is available/clear to send
* ("Clear Channel Assessment" a.k.a. CCA).
*
* @return a 1 value if radio medium is clear (available),
* a 0 value otherwise.
*
*/
int at86rf231_channel_is_clear(netdev_t *dev);
/**
* @brief Interrupt handler, gets fired when a RX overflow happens.
*
*/
void at86rf231_rxoverflow_irq(void);
/**
* @brief Interrupt handler, gets fired when bytes in the RX FIFO are present.
*
*/
void at86rf231_rx_irq(void);
/**
* @brief Sets the function called back when a packet is received.
* (Low-level mechanism, parallel to the `transceiver` module).
*
* @param[in] dev The network device to operate on. (Currently not used)
* @param[in] recv_cb callback function for 802.15.4 packet arrival
*
* @return 0 on success
* @return -ENODEV if *dev* is not recognized
* @return -ENOBUFS, if maximum number of registable callbacks is exceeded
*/
int at86rf231_add_raw_recv_callback(netdev_t *dev,
netdev_802154_raw_packet_cb_t recv_cb);
/**
* @brief Unsets the function called back when a packet is received.
* (Low-level mechanism, parallel to the `transceiver` module).
*
* @param[in] dev The network device to operate on. (Currently not used)
* @param[in] recv_cb callback function to unset
*
* @return 0 on success
* @return -ENODEV if *dev* is not recognized
* @return -ENOBUFS, if maximum number of registable callbacks is exceeded
*/
int at86rf231_rem_raw_recv_callback(netdev_t *dev,
netdev_802154_raw_packet_cb_t recv_cb);
/**
* @brief Sets a function called back when a data packet is received.
*
* @param[in] dev The network device to operate on. (Currently not used)
* @param[in] recv_cb callback function for 802.15.4 data packet arrival
*
* @return 0 on success
* @return -ENODEV if *dev* is not recognized
* @return -ENOBUFS, if maximum number of registable callbacks is exceeded
*/
int at86rf231_add_data_recv_callback(netdev_t *dev,
netdev_rcv_data_cb_t recv_cb);
/**
* @brief Unsets a function called back when a data packet is received.
*
* @param[in] dev The network device to operate on. (Currently not used)
* @param[in] recv_cb callback function to unset
*
* @return 0 on success
* @return -ENODEV if *dev* is not recognized
* @return -ENOBUFS, if maximum number of registable callbacks is exceeded
*/
int at86rf231_rem_data_recv_callback(netdev_t *dev,
netdev_rcv_data_cb_t recv_cb);
/**
* @brief RX handler, process data from the RX FIFO.
*
*/
void at86rf231_rx_handler(void);
/**
* @brief Prepare the at86rf231 TX buffer to send with the given packet.
*
* @param[in] dev The network device to operate on. (Currently not used)
* @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 1 to use the 64-bit address mode
* with *dest* param; 0 to use
* "short" PAN-centric mode.
* @param[in] wants_ack 1 to request an acknowledgement
* from the receiving node for this packet;
* 0 otherwise.
* @param[in] upper_layer_hdrs header data from higher network layers from
* highest to lowest layer. Must be prepended to
* the data stream by the network device. May be
* NULL if there are none.
* @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 @ref netdev_802154_tx_status_t
*/
netdev_802154_tx_status_t at86rf231_load_tx_buf(netdev_t *dev,
netdev_802154_pkt_kind_t kind,
netdev_802154_node_addr_t *dest,
int use_long_addr,
int wants_ack,
netdev_hlist_t *upper_layer_hdrs,
void *buf,
unsigned int len);
/**
* @brief Transmit the data loaded into the at86rf231 TX buffer.
*
* @param[in] dev The network device to operate on. (Currently not used)
*
* @return @ref netdev_802154_tx_status_t
*/
netdev_802154_tx_status_t at86rf231_transmit_tx_buf(netdev_t *dev);
/**
* @brief Send function, sends a at86rf231_packet_t over the air.
*
* @param[in] *packet The Packet which will be send.
*
* @return The count of bytes which are send or -1 on error
*
*/
int16_t at86rf231_send(at86rf231_packet_t *packet);
/**
* RX Packet Buffer, read from the transceiver, filled by the at86rf231_rx_handler.
*/
extern at86rf231_packet_t at86rf231_rx_buffer[AT86RF231_RX_BUF_SIZE];
/**
* Get at86rf231's status byte
*/
uint8_t at86rf231_get_status(void);
/**
* Get at86rf231's TRAC status byte
*/
uint8_t at86rf231_get_trac_status(void);
/**
* at86rf231 low-level radio driver definition.
*/
extern const netdev_802154_driver_t at86rf231_driver;
#ifdef __cplusplus
}
#endif
#endif /* AT86RF231_H_ */
/** @} */

View File

@ -1,255 +0,0 @@
/*
* Copyright (C) 2014 INRIA
*
* 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_at86rf231
* @{
*
* @file
* @brief Register and command definitions for the AT86RF231 radio
*
* @author Alaeddine Weslati <alaeddine.weslati@inria.fr>
*/
#ifndef AT86AT86RF231_SETTINGS_H
#define AT86AT86RF231_SETTINGS_H
#ifdef __cplusplus
extern "C" {
#endif
#define AT86RF231_RX_BUF_SIZE 3
enum at86rf231_access {
AT86RF231_ACCESS_REG = 0x80,
AT86RF231_ACCESS_FRAMEBUFFER = 0x20,
AT86RF231_ACCESS_SRAM = 0x00,
AT86RF231_ACCESS_READ = 0x00,
AT86RF231_ACCESS_WRITE = 0x40,
};
enum at86rf231_register {
AT86RF231_REG__TRX_STATUS = 0x01,
AT86RF231_REG__TRX_STATE = 0x02,
AT86RF231_REG__TRX_CTRL_0 = 0x03,
AT86RF231_REG__TRX_CTRL_1 = 0x04,
AT86RF231_REG__PHY_TX_PWR = 0x05,
AT86RF231_REG__PHY_RSSI = 0x06,
AT86RF231_REG__PHY_ED_LEVEL = 0x07,
AT86RF231_REG__PHY_CC_CCA = 0x08,
AT86RF231_REG__CCA_THRES = 0x09,
AT86RF231_REG__RX_CTRL = 0x0A,
AT86RF231_REG__SFD_VALUE = 0x0B,
AT86RF231_REG__TRX_CTRL_2 = 0x0C,
AT86RF231_REG__ANT_DIV = 0x0D,
AT86RF231_REG__IRQ_MASK = 0x0E,
AT86RF231_REG__IRQ_STATUS = 0x0F,
AT86RF231_REG__VREG_CTRL = 0x10,
AT86RF231_REG__BATMON = 0x11,
AT86RF231_REG__XOSC_CTRL = 0x12,
AT86RF231_REG__RX_SYN = 0x15,
AT86RF231_REG__XAH_CTRL_1 = 0x17,
AT86RF231_REG__FTN_CTRL = 0x18,
AT86RF231_REG__PLL_CF = 0x1A,
AT86RF231_REG__PLL_DCU = 0x1B,
AT86RF231_REG__PART_NUM = 0x1C,
AT86RF231_REG__VERSION_NUM = 0x1D,
AT86RF231_REG__MAN_ID_0 = 0x1E,
AT86RF231_REG__MAN_ID_1 = 0x1F,
AT86RF231_REG__SHORT_ADDR_0 = 0x20,
AT86RF231_REG__SHORT_ADDR_1 = 0x21,
AT86RF231_REG__PAN_ID_0 = 0x22,
AT86RF231_REG__PAN_ID_1 = 0x23,
AT86RF231_REG__IEEE_ADDR_0 = 0x24,
AT86RF231_REG__IEEE_ADDR_1 = 0x25,
AT86RF231_REG__IEEE_ADDR_2 = 0x26,
AT86RF231_REG__IEEE_ADDR_3 = 0x27,
AT86RF231_REG__IEEE_ADDR_4 = 0x28,
AT86RF231_REG__IEEE_ADDR_5 = 0x29,
AT86RF231_REG__IEEE_ADDR_6 = 0x2A,
AT86RF231_REG__IEEE_ADDR_7 = 0x2B,
AT86RF231_REG__XAH_CTRL_0 = 0x2C,
AT86RF231_REG__CSMA_SEED_0 = 0x2D,
AT86RF231_REG__CSMA_SEED_1 = 0x2E,
AT86RF231_REG__CSMA_BE = 0x2F,
AT86RF231_REG__TST_CTRL_DIGI = 0x36,
};
enum {
AT86RF231_TRX_CTRL_0_MASK__PAD_IO = 0xC0,
AT86RF231_TRX_CTRL_0_MASK__PAD_IO_CLKM = 0x30,
AT86RF231_TRX_CTRL_0_MASK__CLKM_SHA_SEL = 0x08,
AT86RF231_TRX_CTRL_0_MASK__CLKM_CTRL = 0x07,
AT86RF231_TRX_CTRL_0_DEFAULT__PAD_IO = 0x00,
AT86RF231_TRX_CTRL_0_DEFAULT__PAD_IO_CLKM = 0x10,
AT86RF231_TRX_CTRL_0_DEFAULT__CLKM_SHA_SEL = 0x08,
AT86RF231_TRX_CTRL_0_DEFAULT__CLKM_CTRL = 0x01,
AT86RF231_TRX_CTRL_0_CLKM_CTRL__OFF = 0x00,
AT86RF231_TRX_CTRL_0_CLKM_CTRL__1MHz = 0x01,
AT86RF231_TRX_CTRL_0_CLKM_CTRL__2MHz = 0x02,
AT86RF231_TRX_CTRL_0_CLKM_CTRL__4MHz = 0x03,
AT86RF231_TRX_CTRL_0_CLKM_CTRL__8MHz = 0x04,
AT86RF231_TRX_CTRL_0_CLKM_CTRL__16MHz = 0x05,
AT86RF231_TRX_CTRL_0_CLKM_CTRL__250kHz = 0x06,
AT86RF231_TRX_CTRL_0_CLKM_CTRL__62_5kHz = 0x07,
};
enum {
AT86RF231_TRX_CTRL_1_MASK__PA_EXT_EN = 0x80,
AT86RF231_TRX_CTRL_1_MASK__IRQ_2_EXT_EN = 0x40,
AT86RF231_TRX_CTRL_1_MASK__TX_AUTO_CRC_ON = 0x20,
AT86RF231_TRX_CTRL_1_MASK__RX_BL_CTRL = 0x10,
AT86RF231_TRX_CTRL_1_MASK__SPI_CMD_MODE = 0x0C,
AT86RF231_TRX_CTRL_1_MASK__IRQ_MASK_MODE = 0x02,
AT86RF231_TRX_CTRL_1_MASK__IRQ_POLARITY = 0x01,
};
enum {
AT86RF231_TRX_CTRL_2_MASK__RX_SAFE_MODE = 0x80,
AT86RF231_TRX_CTRL_2_MASK__OQPSK_DATA_RATE = 0x03,
};
enum {
AT86RF231_IRQ_STATUS_MASK__BAT_LOW = 0x80,
AT86RF231_IRQ_STATUS_MASK__TRX_UR = 0x40,
AT86RF231_IRQ_STATUS_MASK__AMI = 0x20,
AT86RF231_IRQ_STATUS_MASK__CCA_ED_DONE = 0x10,
AT86RF231_IRQ_STATUS_MASK__TRX_END = 0x08,
AT86RF231_IRQ_STATUS_MASK__RX_START = 0x04,
AT86RF231_IRQ_STATUS_MASK__PLL_UNLOCK = 0x02,
AT86RF231_IRQ_STATUS_MASK__PLL_LOCK = 0x01,
};
enum at86rf231_trx_status {
AT86RF231_TRX_STATUS_MASK__CCA_DONE = 0x80,
AT86RF231_TRX_STATUS_MASK__CCA_STATUS = 0x40,
AT86RF231_TRX_STATUS_MASK__TRX_STATUS = 0x1F,
AT86RF231_TRX_STATUS__P_ON = 0x00,
AT86RF231_TRX_STATUS__BUSY_RX = 0x01,
AT86RF231_TRX_STATUS__BUSY_TX = 0x02,
AT86RF231_TRX_STATUS__RX_ON = 0x06,
AT86RF231_TRX_STATUS__TRX_OFF = 0x08,
AT86RF231_TRX_STATUS__PLL_ON = 0x09,
AT86RF231_TRX_STATUS__SLEEP = 0x0F,
AT86RF231_TRX_STATUS__BUSY_RX_AACK = 0x11,
AT86RF231_TRX_STATUS__BUSY_TX_ARET = 0x12,
AT86RF231_TRX_STATUS__RX_AACK_ON = 0x16,
AT86RF231_TRX_STATUS__TX_ARET_ON = 0x19,
AT86RF231_TRX_STATUS__RX_ON_NOCLK = 0x1C,
AT86RF231_TRX_STATUS__RX_AACK_ON_NOCLK = 0x1D,
AT86RF231_TRX_STATUS__BUSY_RX_AACK_NOCLK = 0x1E,
AT86RF231_TRX_STATUS__STATE_TRANSITION_IN_PROGRESS = 0x1F,
};
enum at86rf231_trx_state {
AT86RF231_TRX_STATE_MASK__TRAC = 0xe0,
AT86RF231_TRX_STATE__NOP = 0x00,
AT86RF231_TRX_STATE__TX_START = 0x02,
AT86RF231_TRX_STATE__FORCE_TRX_OFF = 0x03,
AT86RF231_TRX_STATE__FORCE_PLL_ON = 0x04,
AT86RF231_TRX_STATE__RX_ON = 0x06,
AT86RF231_TRX_STATE__TRX_OFF = 0x08,
AT86RF231_TRX_STATE__PLL_ON = 0x09,
AT86RF231_TRX_STATE__RX_AACK_ON = 0x16,
AT86RF231_TRX_STATE__TX_ARET_ON = 0x19,
AT86RF231_TRX_STATE__TRAC_SUCCESS = 0x00,
AT86RF231_TRX_STATE__TRAC_SUCCESS_DATA_PENDING = 0x20,
AT86RF231_TRX_STATE__TRAC_SUCCESS_WAIT_FOR_ACK = 0x40,
AT86RF231_TRX_STATE__TRAC_CHANNEL_ACCESS_FAILURE = 0x60,
AT86RF231_TRX_STATE__TRAC_NO_ACK = 0xa0,
AT86RF231_TRX_STATE__TRAC_INVALID = 0xe0,
};
enum at86rf231_phy_cc_cca {
AT86RF231_PHY_CC_CCA_MASK__CCA_REQUEST = 0x80,
AT86RF231_PHY_CC_CCA_MASK__CCA_MODE = 0x60,
AT86RF231_PHY_CC_CCA_MASK__CHANNEL = 0x1F,
AT86RF231_PHY_CC_CCA_DEFAULT__CCA_MODE = 0x20,
};
enum at86rf231_phy_tx_pwr {
AT86RF231_PHY_TX_PWR_MASK__PA_BUF_LT = 0xC0,
AT86RF231_PHY_TX_PWR_MASK__PA_LT = 0x30,
AT86RF231_PHY_TX_PWR_MASK__TX_PWR = 0x0F,
AT86RF231_PHY_TX_PWR_DEFAULT__PA_BUF_LT = 0xC0,
AT86RF231_PHY_TX_PWR_DEFAULT__PA_LT = 0x00,
AT86RF231_PHY_TX_PWR_DEFAULT__TX_PWR = 0x00,
AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__3dBm = 0x00,
AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__2_8dBm = 0x01,
AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__2_3dBm = 0x02,
AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__1_8dBm = 0x03,
AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__1_3dBm = 0x04,
AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__0_7dBm = 0x05,
AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__0dBm = 0x06,
AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__m1dBm = 0x07,
AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__m2dBm = 0x08,
AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__m3dBm = 0x09,
AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__m4dBm = 0x0A,
AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__m5dBm = 0x0B,
AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__m7dBm = 0x0C,
AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__m9dBm = 0x0D,
AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__m12dBm = 0x0E,
AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__m17dBm = 0x0F,
};
enum at86rf231_phy_rssi {
AT86RF231_PHY_RSSI_MASK__RX_CRC_VALID = 0x80,
AT86RF231_PHY_RSSI_MASK__RND_VALUE = 0x60,
AT86RF231_PHY_RSSI_MASK__RSSI = 0x1F,
};
enum at86rf231_xosc_ctrl {
AT86RF231_XOSC_CTRL__XTAL_MODE_CRYSTAL = 0xF0,
AT86RF231_XOSC_CTRL__XTAL_MODE_EXTERNAL = 0xF0,
};
enum at86rf231_timing {
AT86RF231_TIMING__VCC_TO_P_ON = 330,
AT86RF231_TIMING__SLEEP_TO_TRX_OFF = 380,
AT86RF231_TIMING__TRX_OFF_TO_PLL_ON = 110,
AT86RF231_TIMING__TRX_OFF_TO_RX_ON = 110,
AT86RF231_TIMING__PLL_ON_TO_BUSY_TX = 16,
AT86RF231_TIMING__RESET = 100,
AT86RF231_TIMING__RESET_TO_TRX_OFF = 37,
};
enum at86rf231_xah_ctrl_1 {
AT86RF231_XAH_CTRL_1__AACK_FLTR_RES_FT = 0x20,
AT86RF231_XAH_CTRL_1__AACK_UPLD_RES_FT = 0x10,
AT86RF231_XAH_CTRL_1__AACK_ACK_TIME = 0x04,
AT86RF231_XAH_CTRL_1__AACK_PROM_MODE = 0x02,
};
enum at86rf231_csma_seed_1 {
AT86RF231_CSMA_SEED_1__AACK_SET_PD = 0x20,
AT86RF231_CSMA_SEED_1__AACK_DIS_ACK = 0x10,
AT86RF231_CSMA_SEED_1__AACK_I_AM_COORD = 0x08,
};
#ifdef __cplusplus
}
#endif
#endif /* AT86AT86RF231_SETTINGS_H */

View File

@ -1,26 +0,0 @@
/*
* Copyright (C) 2014 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.
*/
#ifndef CC110X_H
#define CC110X_H
#include "cc110x/cc110x-interface.h"
#include "cc110x/cc110x-defaultsettings.h"
#include "cc110x/cc110x-config.h"
#include "cc110x/cc110x-reg.h"
#include "cc110x/cc110x-netdev.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* CC110X_H */

View File

@ -1,106 +0,0 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
* Copyright (C) 2013 INRIA
*
* 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_cc110x
* @{
*
* @file
* @brief Configuration parameters for the cc110x radio chip
*
* @author Oliver Hahm <oliver.hahm@inria.fr>
* @author Fabian Nack <nack@inf.fu-berlin.de>
*/
#ifndef CC110X_CONFIG_H
#define CC110X_CONFIG_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief CC110x register configuration
*/
typedef struct {
uint8_t _IOCFG2; /**< GDO2 output pin configuration */
uint8_t _IOCFG1; /**< GDO1 output pin configuration */
uint8_t _IOCFG0; /**< GDO0 output pin configuration */
uint8_t _FIFOTHR; /**< RX FIFO and TX FIFO thresholds */
uint8_t _SYNC1; /**< Sync word, high byte */
uint8_t _SYNC0; /**< Sync word, low byte */
uint8_t _PKTLEN; /**< Packet length */
uint8_t _PKTCTRL1; /**< Packet automation control */
uint8_t _PKTCTRL0; /**< Packet automation control */
uint8_t _ADDR; /**< Device address */
uint8_t _CHANNR; /**< Channel number */
uint8_t _FSCTRL1; /**< Frequency synthesizer control */
uint8_t _FSCTRL0; /**< Frequency synthesizer control */
uint8_t _FREQ2; /**< Frequency control word, high byte */
uint8_t _FREQ1; /**< Frequency control word, middle byte */
uint8_t _FREQ0; /**< Frequency control word, low byte */
uint8_t _MDMCFG4; /**< Modem configuration */
uint8_t _MDMCFG3; /**< Modem configuration */
uint8_t _MDMCFG2; /**< Modem configuration */
uint8_t _MDMCFG1; /**< Modem configuration */
uint8_t _MDMCFG0; /**< Modem configuration */
uint8_t _DEVIATN; /**< Modem deviation setting */
uint8_t _MCSM2; /**< Main Radio Control State Machine configuration */
uint8_t _MCSM1; /**< Main Radio Control State Machine configuration */
uint8_t _MCSM0; /**< Main Radio Control State Machine configuration */
uint8_t _FOCCFG; /**< Frequency Offset Compensation configuration */
uint8_t _BSCFG; /**< Bit Synchronization configuration */
uint8_t _AGCCTRL2; /**< AGC control */
uint8_t _AGCCTRL1; /**< AGC control */
uint8_t _AGCCTRL0; /**< AGC control */
uint8_t _WOREVT1; /**< High byte Event 0 timeout */
uint8_t _WOREVT0; /**< Low byte Event 0 timeout */
uint8_t _WORCTRL; /**< Wake On Radio control */
uint8_t _FREND1; /**< Front end RX configuration */
uint8_t _FREND0; /**< Front end TX configuration */
uint8_t _FSCAL3; /**< Frequency synthesizer calibration */
uint8_t _FSCAL2; /**< Frequency synthesizer calibration */
uint8_t _FSCAL1; /**< Frequency synthesizer calibration */
uint8_t _FSCAL0; /**< Frequency synthesizer calibration */
} cc110x_reg_t;
/**
* @brief CC110x radio configuration
*/
typedef struct {
cc110x_reg_t reg_cfg; ///< CC1100 register configuration
uint8_t pa_power; ///< Output power setting
} cc110x_cfg_t;
/**
* @brief Radio Control Flags
*/
typedef struct {
uint8_t _RSSI; ///< The RSSI value of last received packet
uint8_t _LQI; ///< The LQI value of the last received packet
} cc110x_flags;
/**
* @brief Statistic interface for debugging
*/
typedef struct cc110x_statistic {
uint32_t packets_in;
uint32_t packets_in_crc_fail;
uint32_t packets_in_while_tx;
uint32_t raw_packets_out;
} cc110x_statistic_t;
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* CC110X_CONFIG_H */

View File

@ -1,58 +0,0 @@
/*
* Copyright (C) 2014 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_cc110x
* @{
*
* @file
* @brief TI Chipcon CC110x default settings
*
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @author Fabian Nack <nack@inf.fu-berlin.de>
*/
#ifndef CC110X_DEFAULTSETTINGS_H
#define CC110X_DEFAULTSETTINGS_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Returns hwtimer ticks per us */
#define RTIMER_TICKS(us) HWTIMER_TICKS(us)
#define TIMER_TICK_USEC_RES (122)
/* Reset wait time (in reset procedure) */
#define RESET_WAIT_TIME RTIMER_TICKS(4 * TIMER_TICK_USEC_RES)
/* Time chip needs to go to RX */
#define IDLE_TO_RX_TIME RTIMER_TICKS(1 * TIMER_TICK_USEC_RES)
/* Time to wait for SO to go low after CS */
#define CS_SO_WAIT_TIME RTIMER_TICKS(4 * TIMER_TICK_USEC_RES)
/* Max. retries for SO to go low after CS */
#define CC1100_GDO1_LOW_RETRY (100)
/* The size of the configuration array for CC1100 in bytes */
#define CC1100_CONF_SIZE (39)
/* The default channel number (0-24) for CC1100 */
#define CC1100_DEFAULT_CHANNR (0)
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* CC110X_DEFAULTSETTINGS_H */

View File

@ -1,160 +0,0 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
* Copyright (C) 2013 INRIA
*
* 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_cc110x CC110X
* @brief Driver for Texas Instruments CC110x (without MAC protocol)
* @ingroup drivers
* @{
*
* @file
* @brief Data structures and variables for the cc110x driver interface
*
* @author Oliver Hahm <oliver.hahm@inria.fr>
*/
#ifndef CC110X_INTERFACE_H
#define CC110X_INTERFACE_H
#include <stdint.h>
#include "radio/radio.h"
#include "radio/types.h"
#include "cc110x-config.h"
#include "kernel_types.h"
#include "transceiver.h"
#include "netdev/base.h"
#ifdef __cplusplus
extern "C" {
#endif
#define CC1100_MAX_DATA_LENGTH (58)
#define CC1100_HEADER_LENGTH (3) ///< Header covers SRC, DST and FLAGS
#define CC1100_BROADCAST_ADDRESS (0x00) ///< CC1100 broadcast address
#define MAX_UID (0xFF) ///< Maximum UID of a node is 255
#define MIN_UID (0x01) ///< Minimum UID of a node is 1
#define MIN_CHANNR (0) ///< Minimum channel number
#define MAX_CHANNR (24) ///< Maximum channel number
#define MIN_OUTPUT_POWER (0) ///< Minimum output power value
#define MAX_OUTPUT_POWER (11) ///< Maximum output power value
#define PACKET_LENGTH (0x3E) ///< Packet length = 62 Bytes.
#define CC1100_SYNC_WORD_TX_TIME (90000) // loop count (max. timeout ~ 15 ms) to wait for
// sync word to be transmitted (GDO2 from low to high)
/**
* @name Defines used as state values for state machine
* @{
*/
#define RADIO_UNKNOWN (0)
#define RADIO_IDLE (1)
#define RADIO_SEND_BURST (2)
#define RADIO_RX (3)
#define RADIO_PWD (4)
/** @} */
extern volatile cc110x_flags rflags; ///< Radio flags
extern char cc110x_conf[];
/**
* @brief CC1100 layer 0 protocol
*
* <pre>
---------------------------------------------------
| | | | | |
| Length | Address | PhySrc | Flags | Data |
| | | | | |
---------------------------------------------------
1 byte 1 byte 1 byte 1 byte <= 58 bytes
Flags:
Bit | Meaning
--------------------
7:4 | -
3:1 | Protocol
0 | Identification
</pre>
Notes:
\li length & address are given by CC1100
\li Identification is increased is used to scan duplicates. It must be increased
for each new packet and kept for packet retransmissions.
*/
typedef struct __attribute__((packed))
{
uint8_t length; ///< Length of the packet (without length byte)
uint8_t address; ///< Destination address
uint8_t phy_src; ///< Source address (physical source)
uint8_t flags; ///< Flags
uint8_t data[CC1100_MAX_DATA_LENGTH]; ///< Data (high layer protocol)
}
cc110x_packet_t;
typedef struct {
uint8_t rssi;
uint8_t lqi;
cc110x_packet_t packet;
} rx_buffer_t;
enum radio_mode {
RADIO_MODE_GET = -1, ///< leave mode unchanged
RADIO_MODE_OFF = 0, ///< turn radio off
RADIO_MODE_ON = 1 ///< turn radio on
};
extern rx_buffer_t cc110x_rx_buffer[];
extern volatile uint8_t rx_buffer_next; ///< Next packet in RX queue
extern volatile uint8_t radio_state; ///< Radio state
extern cc110x_statistic_t cc110x_statistic;
#ifdef MODULE_TRANSCEIVER
void cc110x_init(kernel_pid_t transceiver_pid);
#endif
int cc110x_initialize(netdev_t *dev);
int8_t cc110x_send(cc110x_packet_t *pkt);
uint8_t cc110x_get_buffer_pos(void);
void cc110x_setup_rx_mode(void);
void cc110x_switch_to_rx(void);
void cc110x_wakeup_from_rx(void);
void cc110x_switch_to_pwd(void);
int16_t cc110x_set_config_channel(uint8_t channr);
int16_t cc110x_set_channel(uint8_t channr);
int16_t cc110x_get_channel(void);
radio_address_t cc110x_set_address(radio_address_t addr);
radio_address_t cc110x_set_config_address(radio_address_t addr);
radio_address_t cc110x_get_address(void);
void cc110x_set_monitor(uint8_t mode);
void cc110x_print_config(void);
/**
* @brief GDO2 interrupt handler.
*
* @note Wakes up MCU on packet reception.
*/
void cc110x_rx_handler(void *args);
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* CC110X_INTERFACE_H */

View File

@ -1,42 +0,0 @@
/*
* Copyright (C) 2014 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_cc110x
* @{
*
* @file
* @brief Variables for the cc110x netdev base interface
*
* @author Fabian Nack <nack@inf.fu-berlin.de>
*/
#ifndef CC110X_NETDEV_H
#define CC110X_NETDEV_H
#include "netdev/base.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Implementation of netdev_driver_t for CC110X device
*/
extern const netdev_driver_t cc110x_net_driver;
/**
* @brief CC110X default device
*/
extern netdev_t cc110x_dev;
#ifdef __cplusplus
}
#endif
#endif /* CC110X_NETDEV_H */

View File

@ -1,93 +0,0 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
* Copyright (C) 2013 INRIA
*
* 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_cc110x
* @{
*
* @file
* @brief Access to CC110X registers
*
* @author Oliver Hahm <oliver.hahm@inria.fr>
* @author Fabian Nack <nack@inf.fu-berlin.de>
*/
#ifndef CC110X_REG_H
#define CC110X_REG_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Write a set of bytes using burst mode (if available)
*
* @param addr Destination register
* @param buffer Data to be written
* @param count Size of data
*/
void cc110x_writeburst_reg(uint8_t addr, char *buffer, uint8_t count);
/**
* @brief Read a set of bytes using burst mode (if available)
*
* @param addr Source register
* @param buffer Buffer to store read data
* @param count Size of data to be read
*/
void cc110x_readburst_reg(uint8_t addr, char *buffer, uint8_t count);
/**
* @brief Write one byte to a register
*
* @param addr Destinatoin register
* @param value New value
*/
void cc110x_write_reg(uint8_t addr, uint8_t value);
/**
* @brief Read a byte from register
*
* @param addr Source register
*
* @return Read state and value of register
*/
uint8_t cc110x_read_reg(uint8_t addr);
/**
* @brief Read state of a register
*
* @param addr Source register
*
* @return State of register
*/
uint8_t cc110x_read_status(uint8_t addr);
/**
* @brief Sends a command strobe
*
* @param c Command code
*
* @return Command response
*/
uint8_t cc110x_strobe(uint8_t c);
/**
* @brief Pull CS to low and wait for CC110x stabilization
*/
void cc110x_cs(void);
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* CC110X_REG_H */

View File

@ -1,27 +0,0 @@
/*
* Copyright (C) 2014 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.
*/
#ifndef CC110X_LEGACY_H
#define CC110X_LEGACY_H
#include "cc110x_legacy/cc110x-interface.h"
#include "cc110x_legacy/cc110x-defaultSettings.h"
#include "cc110x_legacy/cc110x-config.h"
#include "cc110x_legacy/cc110x-reg.h"
#include "cc110x_legacy/cc110x-arch.h"
#include "cc110x_legacy/cc110x_spi.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* CC110X_LEGACY_H */

View File

@ -1,44 +0,0 @@
/*
* Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved.
*
* 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_cc110x_legacy
* @{
*
* @file
* @brief CC1100 architecture dependent functions
*
* @author Heiko Will <hwill@inf.fu-berlin.de>
*/
#ifndef CC1100_ARCH_H
#define CC1100_ARCH_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
uint8_t cc110x_txrx(uint8_t c);
void cc110x_gdo0_enable(void);
void cc110x_gdo0_disable(void);
void cc110x_gdo2_enable(void);
void cc110x_gdo2_disable(void);
void cc110x_init_interrupts(void);
void cc110x_before_send(void);
void cc110x_after_send(void);
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* CC1100_ARCH_H */

View File

@ -1,122 +0,0 @@
/*
* Copyright (C) 2009 Freie Universität Berlin
* Copyright (C) 2013 INRIA
*
* 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_cc110x_legacy
* @{
*
* @file
* @brief Configuration parameters for the cc110x radio chip
*
* @author Oliver Hahm <oliver.hahm@inria.fr>
*/
#ifndef CC1100_CONFIG_H
#define CC1100_CONFIG_H
#include <stdint.h>
#include "timex.h"
#ifdef __cplusplus
extern "C" {
#endif
/** CC1100 register configuration */
typedef struct {
uint8_t _IOCFG2;
uint8_t _IOCFG1;
uint8_t _IOCFG0;
uint8_t _FIFOTHR;
uint8_t _SYNC1;
uint8_t _SYNC0;
uint8_t _PKTLEN;
uint8_t _PKTCTRL1;
uint8_t _PKTCTRL0;
uint8_t _ADDR;
uint8_t _CHANNR;
uint8_t _FSCTRL1;
uint8_t _FSCTRL0;
uint8_t _FREQ2;
uint8_t _FREQ1;
uint8_t _FREQ0;
uint8_t _MDMCFG4;
uint8_t _MDMCFG3;
uint8_t _MDMCFG2;
uint8_t _MDMCFG1;
uint8_t _MDMCFG0;
uint8_t _DEVIATN;
uint8_t _MCSM2;
uint8_t _MCSM1;
uint8_t _MCSM0;
uint8_t _FOCCFG;
uint8_t _BSCFG;
uint8_t _AGCCTRL2;
uint8_t _AGCCTRL1;
uint8_t _AGCCTRL0;
uint8_t _WOREVT1;
uint8_t _WOREVT0;
uint8_t _WORCTRL;
uint8_t _FREND1;
uint8_t _FREND0;
uint8_t _FSCAL3;
uint8_t _FSCAL2;
uint8_t _FSCAL1;
uint8_t _FSCAL0;
} cc110x_reg_t;
/** CC1100 radio configuration */
typedef struct {
cc110x_reg_t reg_cfg; /**< CC1100 register configuration */
uint8_t pa_power; /**< Output power setting */
} cc110x_cfg_t;
/**
* @brief Radio Control Flags
*/
typedef struct {
uint32_t TOF; /**< Time of flight of the last packet and last ACK */
timex_t TOA; /**< Time of packet arrival */
uint32_t TCP; /**< Time to compute packet */
unsigned RPS : 16; /**< Raw packets sent to transmit last packet */
unsigned RETC : 8; /**< Retransmission count of last sent packet */
unsigned _RSSI : 8; /**< The RSSI value of last received packet */
unsigned RSSI_SEND : 8; /**< The RSSI value of the last sent unicast packet of this node */
unsigned _LQI : 8; /**< The LQI value of the last received packet */
unsigned LL_ACK : 1; /**< Is set if Link-Level ACK is received, otherwise 0 (reset on new burst) */
unsigned CAA : 1; /**< The status of the air (1 = air free, 0 = air not free) */
unsigned CRC_STATE : 1; /**< The CRC status of last received packet (1 = OK, 0 = not OK) */
unsigned SEQ : 1; /**< Sequence number (toggles between 0 and 1) */
unsigned MAN_WOR : 1; /**< Manual WOR set (for randomized WOR times => no synch) */
unsigned KT_RES_ERR : 1; /**< A hwtimer resource error has occurred (no free timers available) */
unsigned TX : 1; /**< State machine TX lock, only ACKs will be received */
unsigned WOR_RST : 1; /**< Reset CC1100 real time clock (WOR) on next WOR strobe */
} cc110x_flags;
/**
* @brief Statistic interface for debugging
*/
typedef struct cc110x_statistic {
uint32_t packets_in;
uint32_t packets_in_crc_fail;
uint32_t packets_in_while_tx;
uint32_t packets_in_dups;
uint32_t packets_in_up;
uint32_t packets_out;
uint32_t packets_out_broadcast;
uint32_t raw_packets_out;
uint32_t acks_send;
uint32_t rx_buffer_max;
uint32_t watch_dog_resets;
} cc110x_statistic_t;
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* CC110X_CONFIG_H */

View File

@ -1,90 +0,0 @@
/*
* Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved.
*
* 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.
*/
#ifndef CC1100_DEFAULTSETTINGS_H
#define CC1100_DEFAULTSETTINGS_H
/**
* @ingroup drivers_cc110x_legacy
* @{
*
* @file
* @brief TI Chipcon CC110x default settings
*
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
*/
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/* returns hwtimer ticks per us */
#define RTIMER_TICKS(us) HWTIMER_TICKS(us)
#define TIMER_TICK_USEC_RES (122)
/* Watchdog cycle time in seconds, set 0 to disable watchdog */
#define CC1100_WATCHDOG_PERIOD (5)
/* Number of transmission retries for unicast packets (constant RX mode) */
#define TRANSMISSION_RETRIES_CRX_UC (5)
/* Number of transmission retries for unicast packets (WOR mode) */
#define TRANSMISSION_RETRIES_WOR_UC (1)
/* Number of transmission retries for broadcast packets (constant RX mode) */
#define TRANSMISSION_RETRIES_CRX_BC (0)
/* Number of transmission retries for broadcast packets (WOR mode) */
#define TRANSMISSION_RETRIES_WOR_BC (0)
/* Time before chip goes back to RX (= stays in PWD after incoming packet) */
#define WOR_TIMEOUT_1 (3200) /* ~ 32 milliseconds */
/* Time before chip goes back to WOR (= stays in RX after elapsed WOR_TIMEOUT_1) */
#define WOR_TIMEOUT_2 (800) /* ~ 8 milliseconds */
/* XOSC startup + FS calibration (300 + 809 us ~ 1.38 ms) */
#define FS_CAL_TIME RTIMER_TICKS(12 * TIMER_TICK_USEC_RES)
/* Manual FS calibration (721 us) */
#define MANUAL_FS_CAL_TIME RTIMER_TICKS(7 * TIMER_TICK_USEC_RES)
/* Reset wait time (in reset procedure) */
#define RESET_WAIT_TIME RTIMER_TICKS(4 * TIMER_TICK_USEC_RES)
/* Time chip needs to go to RX */
#define IDLE_TO_RX_TIME RTIMER_TICKS(1 * TIMER_TICK_USEC_RES)
/* Time chip needs to go to RX and CS signal is ready */
#define CS_READY_TIME RTIMER_TICKS(3 * TIMER_TICK_USEC_RES)
/* Default RX interval for WOR in milliseconds */
#define T_RX_INTERVAL (542)
/* Time of packet interval in microseconds (at 400 kbps) */
#define T_PACKET_INTERVAL (3800)
/* The size of the configuration array for CC1100 in bytes */
#define CC1100_CONF_SIZE (39)
/* The default channel number (0-24) for CC1100 */
#define CC1100_DEFAULT_CHANNR (0)
/* Burst retry to TX switch time (measured ~ 230 us) */
#define BURST_RETRY_TX_SWITCH_TIME (23)
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* CC110X_DEFAULTSETTINGS_H */

View File

@ -1,184 +0,0 @@
/*
* Copyright (C) 2009 Freie Universität Berlin
* Copyright (C) 2013 INRIA
*
* 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_cc110x_legacy CC110x_legacy
* @brief Driver for Texas Instruments CC110x (without MAC protocol)
* @ingroup drivers
* @{
*
* @file
* @brief Data structures and variables for the cc110x driver interface
*
* @author Oliver Hahm <oliver.hahm@inria.fr>
*/
#ifndef CC110X_LEGACY_INTERFACE_H
#define CC110X_LEGACY_INTERFACE_H
#include <stdint.h>
#include "radio/radio.h"
#include "radio/types.h"
#include "cc110x-config.h"
#include "kernel_types.h"
#include "transceiver.h"
#ifdef __cplusplus
extern "C" {
#endif
#define CC1100_MAX_DATA_LENGTH (58)
#define CC1100_HEADER_LENGTH (3) /**< Header covers SRC, DST and FLAGS */
#define CC1100_BROADCAST_ADDRESS (0x00) /**< CC1100 broadcast address */
#define MAX_UID (0xFF) /**< Maximum UID of a node is 255 */
#define MIN_UID (0x01) /**< Minimum UID of a node is 1 */
#define MIN_CHANNR (0) /**< Minimum channel number */
#define MAX_CHANNR (24) /**< Maximum channel number */
#define MIN_OUTPUT_POWER (0) /**< Minimum output power value */
#define MAX_OUTPUT_POWER (11) /**< Maximum output power value */
#define PACKET_LENGTH (0x3E) /**< Packet length = 62 Bytes. */
#define CC1100_SYNC_WORD_TX_TIME (90000) /**< loop count (max. timeout ~15 ms)
* to wait for sync word to be
* transmitted (GDO2 from low to high) */
/**
* @name Defines used as state values for state machine
* @{
*/
#define RADIO_UNKNOWN (0)
#define RADIO_AIR_FREE_WAITING (1)
#define RADIO_WOR (2)
#define RADIO_IDLE (3)
#define RADIO_SEND_BURST (4)
#define RADIO_RX (5)
#define RADIO_SEND_ACK (6)
#define RADIO_PWD (7)
/** @} */
extern volatile cc110x_flags rflags; /**< Radio flags */
extern char cc110x_conf[];
/**
* @brief CC1100 layer 0 protocol
*
* <pre>
---------------------------------------------------
| | | | | |
| Length | Address | PhySrc | Flags | Data |
| | | | | |
---------------------------------------------------
1 byte 1 byte 1 byte 1 byte <= 58 bytes
Flags:
Bit | Meaning
--------------------
7:4 | -
3:1 | Protocol
0 | Identification
</pre>
Notes:
\li length & address are given by CC1100
\li Identification is increased is used to scan duplicates. It must be increased
for each new packet and kept for packet retransmissions.
*/
typedef struct __attribute__((packed))
{
uint8_t length; /**< Length of the packet (without length byte) */
uint8_t address; /**< Destination address */
uint8_t phy_src; /**< Source address (physical source) */
uint8_t flags; /**< Flags */
uint8_t data[CC1100_MAX_DATA_LENGTH]; /**< Data (high layer protocol) */
}
cc110x_packet_t;
typedef struct {
uint8_t rssi;
uint8_t lqi;
cc110x_packet_t packet;
} rx_buffer_t;
enum radio_mode {
RADIO_MODE_GET = -1, /**< leave mode unchanged */
RADIO_MODE_OFF = 0, /**< turn radio off */
RADIO_MODE_ON = 1 /**< turn radio on */
};
extern rx_buffer_t cc110x_rx_buffer[];
extern volatile uint8_t rx_buffer_next; /**< Next packet in RX queue */
extern volatile uint8_t radio_state; /**< Radio state */
extern cc110x_statistic_t cc110x_statistic;
void cc110x_init(kernel_pid_t transceiver_pid);
void cc110x_rx_handler(void);
int8_t cc110x_send(cc110x_packet_t *pkt);
uint8_t cc110x_get_buffer_pos(void);
void cc110x_setup_rx_mode(void);
void cc110x_switch_to_rx(void);
void cc110x_wakeup_from_rx(void);
void cc110x_switch_to_pwd(void);
void cc110x_disable_interrupts(void);
int16_t cc110x_set_config_channel(uint8_t channr);
int16_t cc110x_set_channel(uint8_t channr);
int16_t cc110x_get_channel(void);
radio_address_t cc110x_set_address(radio_address_t addr);
radio_address_t cc110x_set_config_address(radio_address_t addr);
radio_address_t cc110x_get_address(void);
void cc110x_set_monitor(uint8_t mode);
void cc110x_print_config(void);
/**
* @brief GDO0 interrupt handler.
*/
void cc110x_gdo0_irq(void);
/**
* @brief GDO2 interrupt handler.
*
* @note Wakes up MCU on packet reception.
*/
void cc110x_gdo2_irq(void);
#ifdef DBG_IGNORE
/**
* @brief Initialize ignore function
*/
void cc110x_init_ignore(void);
/**
* @brief Adds a address to the ignore list
*
* @param addr The physical address to be ignored
*
* @return 0 if list is full, 1 otherwise
*
*/
uint8_t cc110x_add_ignored(radio_address_t addr);
#endif
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* CC110X_LEGACY_INTERFACE_H */

View File

@ -1,100 +0,0 @@
/*
* Copyright (C) 2008 Freie Universität Berlin
* Copyright (C) 2013 INRIA
*
* 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_cc110x_legacy
* @{
*
* @file
* @brief Access to CC110X registers
*
* @author Oliver Hahm <oliver.hahm@inria.fr>
*/
#ifndef CC110X_REG_H
#define CC110X_REG_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Write a set of bytes using burst mode (if available)
*
* @param addr Destination register
* @param buffer Data to be written
* @param count Size of data
*
* @return Written bytes
*/
uint8_t cc110x_writeburst_reg(uint8_t addr, char *buffer, uint8_t count);
/**
* @brief Read a set of bytes using burst mode (if available)
*
* @param addr Source register
* @param buffer Buffer to store read data
* @param count Size of data to be read
*/
void cc110x_readburst_reg(uint8_t addr, char *buffer, uint8_t count);
/**
* @brief Read bytes from RXFIFO
*
* @param buffer Buffer to store read data
* @param count Size of data to be read
*
* @note: Calls cc110x_readburst_reg if not dedicated fifo read command
* available
*/
void cc110x_read_fifo(char *buffer, uint8_t count);
/**
* @brief Write one byte to a register
*
* @param addr Destinatoin register
* @param value New value
*/
void cc110x_write_reg(uint8_t addr, uint8_t value);
/**
* @brief Read a byte from register
*
* @param addr Source register
*
* @return Read state and value of register
*/
uint8_t cc110x_read_reg(uint8_t addr);
/**
* @brief Read state of a register
*
* @param addr Source register
*
* @return State of register
*/
uint8_t cc110x_read_status(uint8_t addr);
/**
* @brief Sends a command strobe
*
* @param c Command code
*
* @return Command response
*/
uint8_t cc110x_strobe(uint8_t c);
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* CC110X_REG_H */

View File

@ -1,41 +0,0 @@
/*
* Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved.
*
* 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_cc110x_legacy
* @{
*
* @file
* @brief TI Chipcon CC1100 SPI driver
*
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
*/
#ifndef CC1100_SPI_H_
#define CC1100_SPI_H_
#ifdef __cplusplus
extern "C" {
#endif
int cc110x_get_gdo0(void);
int cc110x_get_gdo1(void);
int cc110x_get_gdo2(void);
void cc110x_spi_init(void);
void cc110x_spi_cs(void);
void cc110x_spi_select(void);
void cc110x_spi_unselect(void);
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* CC1100_SPI_H_ */

View File

@ -1,22 +0,0 @@
/*
* Copyright (C) 2014 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.
*/
#ifndef CC110X_LEGACY_CSMA_H
#define CC110X_LEGACY_CSMA_H
#include "cc110x_legacy_csma/cc1100-interface.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* CC110X_LEGACY_CSMA_H */

View File

@ -1,205 +0,0 @@
/*
* Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved.
*
* 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 dev_cc110x_legacy_csma
* @{
*/
/**
* @file
* @brief TI Chipcon CC110x public interface
*
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @version $Revision: 2283 $
*
* @note $Id: cc1100-interface.h 2283 2010-06-15 14:02:27Z hillebra $
*/
#ifndef CC1100INTERFACE_H_
#define CC1100INTERFACE_H_
#include <stdint.h>
#include "radio/radio.h"
#ifdef __cplusplus
extern "C" {
#endif
#define CC1100_BROADCAST_ADDRESS (0x00) /**< CC1100 broadcast address */
#define MAX_UID (0xFF) /**< Maximum UID of a node is 255 */
#define MIN_UID (0x01) /**< Minimum UID of a node is 1 */
#define MIN_CHANNR (0) /**< Minimum channel number */
#define MAX_CHANNR (24) /**< Maximum channel number */
#define MIN_OUTPUT_POWER (0) /**< Minimum output power value */
#define MAX_OUTPUT_POWER (11) /**< Maximum output power value */
#define CC1100_MODE_WOR (0) /**< Usable radio mode: Wake-On-Radio */
#define CC1100_MODE_CONSTANT_RX (1) /**< Usable radio mode: Constant receive */
#define CC1100_MAX_DATA_LENGTH (58)
/* Define default radio mode to constant RX if no application specific setting
* is available. */
#ifndef CC1100_RADIO_MODE
#define CC1100_RADIO_MODE CC1100_MODE_CONSTANT_RX
#endif
/**
* @brief Initialize radio layer.
*
* Initialize the radio layer, must be called before radio can be used.
*/
void cc1100_init(void);
/**
* @brief Get the radio mode.
*
* @return Either CC1100_MODE_CONSTANT_RX or CC1100_MODE_WOR.
*/
uint8_t cc1100_get_mode(void);
/**
* @brief Set the radio mode.
*
* Sets the radio mode with optional mode data. If the radio mode is WOR,
* the optional mode data is the RX interval in milliseconds. Must be called
* only after CC1100 is initialized.
*
* @param mode New radio mode (one of the constants defined in this file).
* @param opt_mode_data Desired RX interval in milliseconds [50..60000].
*
* @return true if mode could be applied; false otherwise (stays in previous mode).
*/
bool cc1100_set_mode(uint8_t mode, uint16_t opt_mode_data);
/**
* @brief Get the average transmission duration (till ACK received).
*
* @return The average transmission duration of one packet in milliseconds.
*/
int cc1100_get_avg_transmission_duration(void);
/**
* @brief Get the radio address.
*
* @return The current address of the radio.
*/
radio_address_t cc1100_get_address(void);
/**
* @brief Set the radio address.
*
* @param address The new radio address.
*
* @return true if address could be set; false otherwise.
*/
bool cc1100_set_address(radio_address_t address);
/**
* @brief Get the current channel number.
*
* @return The current channel number used.
*/
uint8_t cc1100_get_channel(void);
/**
* @brief Set the channel to use.
*
* @param channr The new channel number (between MIN_CHANNR and MAX_CHANNR) to use.
*
* @return true if channel could be set; false otherwise.
*/
bool cc1100_set_channel(uint8_t channr);
/**
* @brief Set current output power in dBm.
*
* @param pa_idx New output power setting, valid values
* are from MIN_OUTPUT_POWER (lowest output power, -52 dBm)
* to MAX_OUTPUT_POWER (highest output power, +10 dBm).
*
* @return true if output power could be set; false otherwise.
*/
bool cc1100_set_output_power(uint8_t pa_idx);
/**
* @brief Set a packet monitor at this layer.
*
* All incoming packets will be passed to this packet monitor before
* packet gets processed by a specific handler. The work in the monitor
* should take as less time as possible (no waiting or intense I/O).
*
* @param monitor The packet monitor or NULL if the current packet
* monitor should be removed.
*
* @return true if this layer supports packet monitoring; false otherwise.
*/
bool cc1100_set_packet_monitor(packet_monitor_t monitor);
/**
* @brief Set a packet handler for a given protocol.
*
* @param protocol The protocol identifier (3-bit value > 0, 1 reserved for LL-ACK).
* @param handler The packet handler called if a packet of given protocol is received.
*
* @return -1 if an error occurs (e.g. handler table full) else >= 0.
*/
int cc1100_set_packet_handler(protocol_t protocol, packet_handler_t handler);
/**
* @brief Send data to given destination address with acknowledgment.
*
* The maximum payload length are 58 bytes!
*
* @param addr The destination address.
* @param protocol The protocol identifier of the transmitted data.
* @param priority Ignored (always highest).
* @param payload The data to be send.
* @param payload_len The length of the data in bytes.
*
* @return A negative value if operation failed; if operation succeeded (ACK received) the number of transmitted bytes.
*/
int cc1100_send(radio_address_t addr, protocol_t protocol, int priority, char *payload, radio_packet_length_t payload_len);
/**
* @brief Send data to given destination address with acknowledgment and CSMA/CA.
*
* The maximum payload length are 58 bytes!
*
* @param address The destination address.
* @param protocol The protocol identifier of the transmitted data.
* @param priority The MAC priority to send with. One of {PRIORITY_ALARM, PRIORITY_WARNING, PRIORITY_DATA}.
* @param payload The data to be send.
* @param payload_len The length of the data in bytes.
*
* @return A negative value if operation failed; if operation succeeded (ACK received) else the number of transmitted bytes.
*/
int cc1100_send_csmaca(radio_address_t address, protocol_t protocol, int priority, char *payload, radio_packet_length_t payload_len);
/**
* @brief Print current radio configuration.
*/
void cc1100_print_config(void);
/**
* @brief Print radio statistics.
*/
void cc1100_print_statistic(void);
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* CC1100INTERFACE_H_ */

View File

@ -1,409 +0,0 @@
/**
* 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 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 CC2420
* @{
* @file
* @brief Definitions for CC2420 functions
* @author Milan Babel <babel@inf.fu-berlin.de>
*
*/
/**
* @brief Definition of the cc2420 layer 0 protocol
* <pre>
---------------------------------------------------------------------------
| | | | | | | |
| Length | FCF | Seq No. |Address | PhySrc | Data | FCS |
| | | | | | | |
---------------------------------------------------------------------------
1 byte 2 bytes 1 byte 2/8 bytes 2/8 bytes <=118 bytes 2 bytes
A 5 byte SHR will be generated and added in hardware.
SHR contains a preable sequence and a start of delimiter,
Length does not contain SHR and Length,
first bit of length has to be 0 (length has only 7bit)
Address fields can be in total between 4 and 20 bytes
FCS contain a hardware generated CRC sum with the polynom x^16+x^12+x^5+1
When receiving a package FCS will be checked by hardware, the first FCS byte will be replaced by RSSI,
followed by a CRC OK bit and the unsigned 7 bit correlation value.
FCF:
Bit | Meaning
--------------------
0-2 | Frame Type
3 | Security Enabled
4 | Frame Pending
5 | Acknowledge request
6 | PAN ID Compression Field
7-9 | Reserved
10-11 | Destination addressing mode
12-13 | Reserved
14-15 | Source addressing mode
For the cc2420 bit 0 is the most right bit and bit 15 is the most left bit.
But the 2 FCF bytes have to be transmitted littel endian (byte 15 to 8 first than 7 to 0)
Addressing mode value:
Bit | Meaning
---------------------
00 | PAN identifier and address field are not present.
01 | Reserved.
10 | Address field contains a 16 bit short address.
11 | Address field contains a 64 bit extended address.
Frame type value:
Bit | Meaning
---------------------
000 | Beacon
001 | Data
010 | Acknowledgment
011 | MAC command
1xx | Reserved
</pre>
* This corresponds to IEEE 802.15.4 frame format.
*/
#ifndef CC2420_H
#define CC2420_H
#include <stdbool.h>
#include "kernel_types.h"
#include "ieee802154_frame.h"
#include "cc2420_settings.h"
#include "radio_driver.h"
#ifdef __cplusplus
extern "C" {
#endif
#define CC2420_MAX_PKT_LENGTH 127
#define CC2420_MAX_DATA_LENGTH (118)
#define CC2420_BROADCAST_ADDRESS (0xFFFF)
#define CC2420_MAX_UID (0xFFFE)
#define CC2420_MIN_UID (0x0000)
/**
* Structure to represent a cc2420 packet.
*/
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 lqi; /** < the link quality indicator */
bool crc; /** < 1 if crc was successfull, 0 otherwise */
/* @} */
} cc2420_packet_t;
/**
* @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.
*/
void cc2420_init(kernel_pid_t tpid);
/**
* @brief Turn CC2420 on.
*
* @return true if the radio was correctly turned on; false otherwise.
*/
bool cc2420_on(void);
/**
* @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 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.
*/
int cc2420_set_channel(unsigned int chan);
/**
* @brief Get the channel of the CC2420.
*
* @return The tuned channel.
*/
unsigned int cc2420_get_channel(void);
/**
* @brief Sets the short address of the CC2420.
*
* @param[in] addr The desired address.
*
* @return The set address after calling.
*/
uint16_t cc2420_set_address(uint16_t addr);
/**
* @brief Gets the current short address of the CC2420.
*
* @return The current short address.
*/
uint16_t cc2420_get_address(void);
/**
* @brief Sets the IEEE long address of the CC2420.
*
* @param[in] addr The desired address.
*
* @return The set address after calling.
*/
uint64_t cc2420_set_address_long(uint64_t addr);
/**
* @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.
*
* @param[in] pan The desired pan ID.
*
* @return The set pan ID after calling.
*/
uint16_t cc2420_set_pan(uint16_t pan);
/**
* @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.
*
*/
void cc2420_rxoverflow_irq(void);
/**
* @brief Interrupt handler, gets fired when bytes in the RX FIFO are present.
*
*/
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.
*
*/
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.
*
* @param[in] *packet The Packet which will be send.
*
* @return The count of bytes which are send or -1 on error
*
*/
int16_t cc2420_send(cc2420_packet_t *packet);
/*
* RX Packet Buffer, read from the transceiver, filled by the cc2420_rx_handler.
*/
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;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,431 +0,0 @@
/*
* Copyright (C) 2014 INRIA
*
* 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 netdev_802154 Network device interface for IEEE 802.15.4 transceivers
* @ingroup netdev
* @brief Network device driver API for IEEE 802.15.4 radio transceivers
*
* @{
* @file
* @brief API definitions for 802.15.4 radio transceivers' drivers
* @author Kévin Roussel <Kevin.Roussel@inria.fr>
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*
*/
#ifndef NETDEV_802154_H_
#define NETDEV_802154_H_
#include <stdint.h>
#include "netdev/base.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Callback function type for receiving incoming packets
* from 802.15.4 radio transceiver.
*
* @param[in] buf Pointer to the buffer containing the incoming
* 802.15.4 packet's raw data.
* @param[in] len Length (in bytes) of the incoming packet's raw data.
* @param[in] rssi Value of the Receive Signal Strength Indicator (RSSI)
* for the incoming packet.
* @param[in] lqi Value of the Link Quality Indicator (LQI)
* for the incoming packet.
* @param[in] crc_ok 1 if incoming packet's checksum (CRC) is valid;
* 0 otherwise (corrupted packet).
*/
typedef void (* netdev_802154_raw_packet_cb_t)(netdev_t *dev,
void *buf,
size_t len,
int8_t rssi,
uint8_t lqi,
int crc_ok);
/**
* @brief Kind of packet to prepare/configure for transmission.
*
*/
typedef enum {
/** Beacon packet */
NETDEV_802154_PKT_KIND_BEACON,
/** Standard data packet */
NETDEV_802154_PKT_KIND_DATA,
/** Acknowledgement packet */
NETDEV_802154_PKT_KIND_ACK,
/** MAC command */
NETDEV_802154_PKT_KIND_MAC_CMD,
/** invalid packet kind */
NETDEV_802154_PKT_KIND_INVALID = -1
} netdev_802154_pkt_kind_t;
/**
* @brief Return values for packet emission function of 802.15.4 radio driver.
*
*/
typedef enum {
/** Transmission completed successfully */
NETDEV_802154_TX_STATUS_OK,
/** Device not found or not an IEEE 802.15.4 device */
NETDEV_802154_TX_STATUS_NO_DEV,
/** Transmission buffer underflow (forgot to call netdev_802154_driver_t::load_tx()
before netdev_802154_driver_t::transmit() ) */
NETDEV_802154_TX_STATUS_UNDERFLOW,
/** Transmission cannot start because radio medium is already busy */
NETDEV_802154_TX_STATUS_MEDIUM_BUSY,
/** Transmission failed because of collision on radio medium */
NETDEV_802154_TX_STATUS_COLLISION,
/** Wrong parameter given to TX-related functions */
NETDEV_802154_TX_STATUS_INVALID_PARAM,
/** Too much given data to be included in a single packet */
NETDEV_802154_TX_STATUS_PACKET_TOO_LONG,
/** Transmission supposedly failed since no ACK packet
has been received as response */
NETDEV_802154_TX_STATUS_NOACK,
/** Transmission failed because of an unexpected (fatal?) error */
NETDEV_802154_TX_STATUS_ERROR,
} netdev_802154_tx_status_t;
/**
* @brief Definition of an IEEE 802.15.4 node address.
*
* @details The `union` allows to choose between PAN-centric addressing
* ("volatile" 16-bit address and 16-bit PAN ID), or canonical
* IEEE 64-bit ("long") addressing.
*
*/
typedef union {
/** @brief PAN-centric ("short") addressing mode */
struct {
/** @brief Address assigned to the node within its current PAN */
uint16_t addr;
/** @brief ID of the PAN to which the node is currently associated */
uint16_t id;
} pan;
/** @brief 64-bit ("long") addressing mode */
uint64_t long_addr;
} netdev_802154_node_addr_t;
/**
* @brief IEEE 802.15.4 radio driver API definition.
*
* @details This is the set of functions that must be implemented
* by any driver for a 802.15.4 radio transceiver.
*
* @extends netdev_driver_t
*/
typedef struct {
/**
* @see netdev_driver_t::init
*/
int (*init)(netdev_t *dev);
/**
* @details wraps netdev_802154_driver_t::send with
*
* @see netdev_driver_t::send_data
*/
int (*send_data)(netdev_t *dev, void *dest, size_t dest_len,
netdev_hlist_t *upper_layer_hdrs, void *data,
size_t data_len);
/**
* @see netdev_driver_t::add_receive_data_callback
*/
int (*add_receive_data_callback)(netdev_t *dev, netdev_rcv_data_cb_t cb);
/**
* @see netdev_driver_t::rem_receive_data_callback
*/
int (*rem_receive_data_callback)(netdev_t *dev, netdev_rcv_data_cb_t cb);
/**
* @see netdev_driver_t::get_option
*
* @details The options are constrained as follows:
*
* *opt* | type | *value_len*
* --------------------------- | ----------- | -----------
* NETDEV_OPT_CHANNEL | uint8_t | >= 1
* NETDEV_OPT_ADDRESS | uint16_t | >= 2
* NETDEV_OPT_NID | uint16_t | >= 2
* NETDEV_OPT_ADDRESS_LONG | uint64_t | >= 8
* NETDEV_OPT_TX_POWER | int | >= 4
* NETDEV_OPT_MAX_PACKET_SIZE | uint8_t | >= 1
*/
int (*get_option)(netdev_t *dev, netdev_opt_t opt, void *value,
size_t *value_len);
/**
* @see netdev_driver_t::set_option
*
* @details The options are constrained as follows:
*
* *opt* | type | *value_len* | *value*
* --------------------------- | ----------- | ----------- | --------
* NETDEV_OPT_CHANNEL | uint8_t | >= 1 | <= 26
* NETDEV_OPT_ADDRESS | uint16_t | >= 2 |
* NETDEV_OPT_NID | uint16_t | >= 2 |
* NETDEV_OPT_ADDRESS_LONG | uint64_t | >= 8 |
* NETDEV_OPT_TX_POWER | int | >= 4 |
*
* NETDEV_OPT_MAX_PACKET_SIZE can not be set.
*/
int (*set_option)(netdev_t *dev, netdev_opt_t opt, void *value,
size_t value_len);
/**
* @see netdev_driver_t::get_state
*/
int (*get_state)(netdev_t *dev, netdev_state_t *state);
/**
* @see netdev_driver_t::set_state
*/
int (*set_state)(netdev_t *dev, netdev_state_t state);
/**
* @see netdev_driver_t::event
*/
void (*event)(netdev_t *dev, uint32_t event_type);
/**
* @brief Load the transceiver TX buffer with the given
* IEEE 802.15.4 packet.
*
* @param[in] dev the network device
* @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 1 to use the 64-bit address mode
* with *dest* param; 0 to use
* "short" PAN-centric mode.
* @param[in] wants_ack 1 to request an acknowledgement
* from the receiving node for this packet;
* 0 otherwise.
* @param[in] upper_layer_hdrs header data from higher network layers from
* highest to lowest layer. Must be prepended to
* the data stream by the network device. May be
* NULL if there are none.
* @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 netdev_802154_tx_status_t
*/
netdev_802154_tx_status_t (* load_tx)(netdev_t *dev,
netdev_802154_pkt_kind_t kind,
netdev_802154_node_addr_t *dest,
int use_long_addr,
int wants_ack,
netdev_hlist_t *upper_layer_hdrs,
void *buf,
unsigned int len);
/**
* @brief Transmit the data loaded into the transceiver TX buffer.
*
* @param[in] dev the network device
*
* @return The outcome of this packet's transmission.
* @see netdev_802154_tx_status_t
*/
netdev_802154_tx_status_t (* transmit)(netdev_t *dev);
/**
* @brief Transmit the given IEEE 802.15.4 packet,
* by calling successively functions netdev_802154_driver_t::load_tx()
* and netdev_802154_driver_t::transmit().
*
* @param[in] dev the network device
* @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 1 to use the 64-bit address mode
* with *dest* param; 0 to use
* "short" PAN-centric mode.
* @param[in] wants_ack 1 to request an acknowledgement
* from the receiving node for this packet;
* 0 otherwise.
* @param[in] upper_layer_hdrs header data from higher network layers from
* highest to lowest layer. Must be prepended to
* the data stream by the network device. May be
* NULL if there are none.
* @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 netdev_802154_tx_status_t
*/
netdev_802154_tx_status_t (* send)(netdev_t *dev,
netdev_802154_pkt_kind_t kind,
netdev_802154_node_addr_t *dest,
int use_long_addr,
int wants_ack,
netdev_hlist_t *upper_layer_hdrs,
void *buf,
unsigned int len);
/**
* @brief Add a function to be called back when the radio transceiver
* has received a incoming packet.
*
* @details This function differentiates from
* netdev_driver_t::add_receive_data_callback() as it expects
* a callback that excepts the raw frame format of IEEE 802.15.4,
* rather than just the source and destination addresses and the
* payload.
*
* @param[in] dev the network device
* @param[in] recv_func the callback function to invoke for each
* packet received by the radio transceiver.
* @see netdev_802153_raw_packet_cb_t
*
* @return 0, on success
* @return -ENOBUFS, if maximum number of registrable callbacks is exceeded
* @return -ENODEV, if *dev* is not recognized
*/
int (* add_receive_raw_callback)(netdev_t *dev, netdev_802154_raw_packet_cb_t recv_func);
/**
* @brief Remove a callback set by netdev_802154_driver_t::add_receive_raw_callback()
*
* @param[in] dev the network device
* @param[in] recv_func the callback function to invoke for each
* packet received by the radio transceiver.
* @see netdev_802153_raw_packet_cb_t
*
* @return 0, on success
* @return -ENODEV, if *dev* is not recognized
*/
int (* rem_receive_raw_callback)(netdev_t *dev, netdev_802154_raw_packet_cb_t recv_func);
/**
* @brief Indicates if the radio medium is available for transmission
* ("Clear Channel Assessment").
*
* @param[in] dev the network device
*
* @return 1 if radio medium is "clear" (available);
* @return 0 if another transmission is already running.
* @return -ENODEV, if *dev* is not recognized
*/
int (* channel_is_clear)(netdev_t *dev);
} netdev_802154_driver_t;
/* define to implement yourself and omit compilation of this function */
#ifndef NETDEV_802154_SEND_DATA_OVERLOAD
/**
* @brief wraps netdev_802154_driver_t::send(), default value for
* netdev_802154_driver_t::send_data().
*
* @param[in] dev the network device
* @param[in] dest the (hardware) destination address for the data
* in host byte order.
* @param[in] dest_len the length of *dest* in byte
* @param[in] upper_layer_hdrs header data from higher network layers from
* highest to lowest layer. Must be prepended to
* the data stream by the network device. May be
* NULL if there are none.
* @param[in] data the data to send
* @param[in] data_len the length of *data* in byte
*
* @return the number of byte actually (data_len + total length of upper layer
* headers) send on success
* @return -EAFNOSUPPORT if address of length dest_len is not supported
* by the device *dev*
* @return -EBUSY if transmission cannot start because radio medium is already
* busy or collision on radio medium occured.
* @return -EINVAL if wrong parameter was given
* @return -ENODEV if *dev* is not recognized as IEEE 802.15.4 device
* @return -EMSGSIZE if the total frame size is too long to fit in a frame
* of the device *dev*
* @return -EIO if any other occured (netdev_802154_driver_t::send() returned
* NETDEV_802154_TX_STATUS_ERROR)
*/
int netdev_802154_send_data(netdev_t *dev, void *dest, size_t dest_len,
netdev_hlist_t *upper_layer_hdrs, void *data,
size_t data_len);
#endif /* NETDEV_802154_SEND_DATA_OVERLOAD */
/* define to implement yourself and omit compilation of this function */
#ifndef NETDEV_802154_SEND_OVERLOAD
/**
* @brief Transmit the given IEEE 802.15.4 packet, by calling
* functions netdev_802154_driver_t::load_tx() and
* netdev_802154_driver_t::transmit() successfully. Default value for
* netdev_802154_driver_t::send()
*
* @param[in] dev the network device
* @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 1 to use the 64-bit address mode
* with *dest* param; 0 to use
* "short" PAN-centric mode.
* @param[in] wants_ack 1 to request an acknowledgement
* from the receiving node for this packet;
* 0 otherwise.
* @param[in] upper_layer_hdrs header data from higher network layers from
* highest to lowest layer. Must be prepended to
* the data stream by the network device. May be
* NULL if there are none.
* @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 @ref netdev_802154_tx_status_t
*/
netdev_802154_tx_status_t netdev_802154_send(netdev_t *dev,
netdev_802154_pkt_kind_t kind,
netdev_802154_node_addr_t *dest,
int use_long_addr,
int wants_ack,
netdev_hlist_t *upper_layer_hdrs,
void *buf,
unsigned int len);
#endif /* NETDEV_802154_SEND_OVERLOAD */
#ifdef __cplusplus
}
#endif
#endif /* NETDEV_802154_H_ */
/**
* @}
*/

View File

@ -1,408 +0,0 @@
/*
* Copyright (C) 2014 Martine Lenders <mlenders@inf.fu-berlin.de>
*
* 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.
*/
/**
* @addtogroup netdev
* @{
*
* @file
* @brief Basic network device driver interface definitions.
*
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*/
#ifndef NETDEV_BASE_H_
#define NETDEV_BASE_H_
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
#include "clist.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Type for @ref msg_t if device fired an event.
*/
#define NETDEV_MSG_EVENT_TYPE (0x0100)
/**
* @brief Definition of device families.
*/
typedef enum {
NETDEV_TYPE_UNKNOWN = 0, /**< Type was not specified and may not
understand this API */
NETDEV_TYPE_BASE, /**< Device understands this API */
NETDEV_TYPE_802154, /**< Device understands this API and the API
defined in @ref netdev_802154 */
} netdev_type_t;
/**
* @brief Definition of protocol families to determine which frame types a
* device or protocol layer (see @ref netapi) can handle
*
* @note XXX: The concrete definition of the values is necessary to work
* with super-flexible devices as e.g. @ref native_net. It was also
* decided not to use ethertype since protocols not supplied by it
* might be supported
*/
typedef enum {
NETDEV_PROTO_UNKNOWN = 0x0000, /**< Type was not specified */
/**
* @brief Radio frame protocol
*
* @details Sends frames as defined by radio_packet_t.
*/
NETDEV_PROTO_RADIO = 0x0001,
/**
* @brief IEEE 802.15.4
*
* @details Sends frames as defined by ieee802154_frame_t
*/
NETDEV_PROTO_802154 = 0x0002,
NETDEV_PROTO_6LOWPAN = 0x0003, /**< 6LoWPAN. */
NETDEV_PROTO_IPV6 = 0x0004, /**< IPv6. */
NETDEV_PROTO_UDP = 0x0005, /**< UDP. */
NETDEV_PROTO_TCP = 0x0006, /**< TCP. */
NETDEV_PROTO_CCNL = 0x0007, /**< CCN lite. */
/**
* @brief CC110x frame format protocol
*
* @detail Sends frames as defined by cc110x_packet_t.
*/
NETDEV_PROTO_CC110X = 0x0008,
} netdev_proto_t;
/**
* @brief Definition of basic network device options.
* @note Feel free to expand if your device needs/supports more.
*/
typedef enum {
/**
* @brief Communication type for the device as defined by @ref netdev_proto_t
*
* @details If a driver does not support the type (but the setting of the
* option is supported) it @ref netdev_driver_t::set_option() shall result
* with -EPROTONOSUPPORT.
*
* *value_len* for @ref netdev_driver_t::get_option() must always be at
* least `sizeof(netdev_proto_t)`.
*/
NETDEV_OPT_PROTO = 0,
NETDEV_OPT_CHANNEL, /**< Channel for the device as unsigned value
in host byte order */
NETDEV_OPT_ADDRESS, /**< Hardware address for the device as
unsigned value in host byte order */
NETDEV_OPT_NID, /**< Network ID (e.g. PAN ID in IEEE 802.15.4)
for the device as unsigned value in
host byte order */
NETDEV_OPT_ADDRESS_LONG, /**< Longer hardware address for the device
(e.g. EUI-64) for the device as
unsigned value in host byte order */
NETDEV_OPT_TX_POWER, /**< The output of the device in dB as
signed value in host byte order */
NETDEV_OPT_MAX_PACKET_SIZE, /**< Maximum packet size the device supports
unsigned value in host byte order */
NETDEV_OPT_SRC_LEN, /**< Default mode the source address is
set to as value of `size_t`. (e.g.
either PAN-centric 16-bit address or
EUI-64 in IEEE 802.15.4) */
/**
* @brief Last value for @ref netdev_opt_t defined here
*
* @details Specific devices or modules like @ref netapi that utilize these
* values to may define higher values, but they must be greater
* or equal to @ref NETDEV_OPT_LAST.
*/
NETDEV_OPT_LAST,
} netdev_opt_t;
/**
* @brief Definition of basic network device.
* @note Feel free to expand if your device needs/supports more
*/
typedef enum {
NETDEV_STATE_POWER_OFF = 0, /**< Device is powered off */
NETDEV_STATE_POWER_SLEEP, /**< Device is sleeping */
NETDEV_STATE_POWER_IDLE, /**< Device is idle */
NETDEV_STATE_RX_MODE, /**< Device is in receive mode */
NETDEV_STATE_PROMISCUOUS_MODE, /**< Device is in receive mode and
accepts all packets without regard
for their destination */
NETDEV_STATE_TX_BURST, /**< Device is burst sending and
does not accept packets */
} netdev_state_t;
/**
* @brief Circular list type to store a number of protocol headers of
* unspecified type to work with @ref clist.h.
*
* @extends clist_node_t
*/
typedef struct __attribute__((packed)) netdev_hlist_t {
struct netdev_hlist_t *next; /**< next element in list */
struct netdev_hlist_t *prev; /**< previous element in list */
netdev_proto_t protocol; /**< protocol of the header */
void *header; /**< the header stored in here */
size_t header_len; /**< the length of the header in byte */
} netdev_hlist_t;
/**
* @brief Definition of the network device type
*
* @see struct netdev_t
*
* @note Forward definition to use in @ref netdev_driver_t
*/
typedef struct netdev_t netdev_t;
/**
* Receive data callback for data frames from given network device.
*
* @param[in] dev the network device the frame came from.
* @param[in] src the (hardware) source address of the frame in host
* byte order.
* @param[in] src_len the length of *src* in byte
* @param[in] dest the (hardware) destination address of the frame in
* host byte order.
* @param[in] dest_len the length of *dest* in byte
* @param[in] payload the payload of the frame.
* @param[in] payload_len the length of *payload* in byte
*
* @return the number of bytes in payload actually processed by the callback,
* on success
* @return a fitting negative errno on failure
*/
typedef int (*netdev_rcv_data_cb_t)(netdev_t *dev, void *src, size_t src_len,
void *dest, size_t dest_len, void *payload,
size_t payload_len);
/**
* @brief Network device API definition.
*
* @details This is a set of functions that must be implemented by any driver
* for a network device.
*/
typedef struct {
/**
* @brief Initialize a given network device.
*
* @param[in] dev the device to initialize
*
* @return 0 on success
* @return -ENODEV if *dev* can not be initialized
*/
int (*init)(netdev_t *dev);
/**
* @brief Send data via a given network device
*
* @param[in] dev the network device
* @param[in] dest the (hardware) destination address for the data
* in host byte order.
* @param[in] dest_len the length of *dest* in byte
* @param[in] upper_layer_hdrs header data from higher network layers from
* highest to lowest layer. Must be prepended to
* the data stream by the network device. May be
* NULL if there are none.
* @param[in] data the data to send
* @param[in] data_len the length of *data* in byte
*
* @return the number of byte actually send on success
* @return -EAFNOSUPPORT if address of length dest_len is not supported
* by the device *dev*
* @return -ENODEV if *dev* is not recognized
* @return -EMSGSIZE if the total frame size is too long to fit in a frame
* of the device *dev*
* @return a fitting negative other errno on other failure
*/
int (*send_data)(netdev_t *dev, void *dest, size_t dest_len,
netdev_hlist_t *upper_layer_hdrs, void *data,
size_t data_len);
/**
* @brief Registers a receive data callback to a given network device.
*
* @param[in] dev the network device.
* @param[in] cb the callback.
*
* @return 0, on success
* @return -ENODEV, if *dev* is not recognized
* @return -ENOBUFS, if maximum number of registrable callbacks is exceeded
*/
int (*add_receive_data_callback)(netdev_t *dev, netdev_rcv_data_cb_t cb);
/**
* @brief Unregisters a receive data callback to a given network device.
*
* @param[in] dev the network device.
* @param[in] cb the callback.
*
* @return 0, on success
* @return -ENODEV, if *dev* is not recognized
*/
int (*rem_receive_data_callback)(netdev_t *dev, netdev_rcv_data_cb_t cb);
/**
* @brief Get an option value from a given network device.
*
* @param[in] dev the network device
* @param[in] opt the option type
* @param[out] value pointer to store the gotten value in
* @param[in,out] value_len the length of *value*. Must be initialized to the
* available space in *value* on call.
* @return 0, on success
* @return -ENODEV, if *dev* is not recognized
* @return -ENOTSUP, if *opt* is not supported for the device with this
* operation
* @return -EOVERFLOW, if available space in *value* given in *value_len*
* is not big enough to store the option value.
* @return any other fitting negative errno if the ones stated above
* are not sufficient
*/
int (*get_option)(netdev_t *dev, netdev_opt_t opt, void *value,
size_t *value_len);
/**
* @brief Set an option value for a given network device.
*
* @param[in] dev the network device
* @param[in] opt the option type
* @param[in] value the value to set
* @param[in] value_len the length of *value*
*
* @return 0, on success
* @return -EINVAL, if *value* is not in a required format
* @return -ENODEV, if *dev* is not recognized
* @return -ENOTSUP, if *opt* is not supported for the device with this
* operation
* @return -EOVERFLOW, if *value_len* is larger then the device expects.
* @return -EPROTONOSUPPORT, if *opt* was NETDEV_OPT_PROTO and type is
* not supported.
* @return any other fitting negative errno if the ones stated above
* are not sufficient
*/
int (*set_option)(netdev_t *dev, netdev_opt_t opt, void *value,
size_t value_len);
/**
* @brief Get state from a given network device.
*
* @param[in] dev the network device
* @param[out] state the network device
*
* @return 0, on success
* @return -ENODEV, if *dev* is not recognized
* @return -ETIME, if device timed out on trying to acquire state
*/
int (*get_state)(netdev_t *dev, netdev_state_t *state);
/**
* @brief Set state from a given network device.
*
* @param[in] dev the network device
* @param[in] state the network device
*
* @return 0, on success
* @return -ENODEV, if *dev* is not recognized
* @return -ENOTSUP, if *state* is not supported
* @return -ETIME, if device timed out on trying to change state
*/
int (*set_state)(netdev_t *dev, netdev_state_t state);
/**
* @brief Must be called by a controlling thread if a message of type
* NETDEV_MSG_EVENT_TYPE was received
*
* @param[in] dev the network device that fired the event.
* @param[in] event_type Event type. Values are free to choose for the
* driver. Must be given in the @ref msg_t::value
* of the received message
*/
void (*event)(netdev_t *dev, uint32_t event_type);
} netdev_driver_t;
/**
* @brief Definition of the network device type
*
* @note Your driver may overload this with additional information (e.g.
* how the device is connected)
*/
struct netdev_t {
netdev_type_t type; /**< The type of this device */
const netdev_driver_t *driver; /**< The driver for this device */
void *more; /**< Pointer to device dependent
additional information. E.g. the
low-level device(s) to
communiticate with this device. */
};
/**
* @brief Helper function to calculate the total length of the headers in
* *hlist*.
*
* @param[in] hlist The header list.
*
* @return Length in number of bytes of all headers in *hlist*.
*/
size_t netdev_get_hlist_len(const netdev_hlist_t *hlist);
/**
* @brief Advance the header list
*
* @see clist_advance
*
* @param[in,out] list The list to work upon.
*/
static inline void netdev_hlist_advance(netdev_hlist_t **list)
{
clist_advance((clist_node_t **)list);
}
/**
* @brief Add *node* to list start of *list*
*
* @param[in,out] list The list to add *node* to
* @param[in] node The node to add to the list
*/
static inline void netdev_hlist_add(netdev_hlist_t **list,
netdev_hlist_t *node)
{
clist_add((clist_node_t **)list, (clist_node_t *)node);
*list = node;
}
/**
* @brief Removes *node* from list *list*
*
* @see clist_remove
*
* @param[in,out] list The list to remove *node* from
* @param[in] node The node to remove from the list
*/
static inline void netdev_hlist_remove(netdev_hlist_t **list,
netdev_hlist_t *node)
{
clist_remove((clist_node_t **)list, (clist_node_t *)node);
}
#ifdef __cplusplus
}
#endif
#endif /* NETDEV_BASE_H_ */
/**
* @}
*/

View File

@ -1,65 +0,0 @@
/*
* Copyright (C) 2014 Martine Lenders <mlenders@inf.fu-berlin.de>
*
* 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.
*/
/**
* @addtogroup netdev
* @{
*
* @file
* @brief Supplies the users with default values for the use of
* @ref netdev
*
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*/
#ifndef NETDEV_DEFAULT_H_
#define NETDEV_DEFAULT_H_
#include "netdev/base.h"
#ifdef DOXYGEN
/**
* @brief Default device as a pointer of netdev_t.
*/
#define NETDEV_DEFAULT
#endif
#ifdef MODULE_AT86RF231
#include "at86rf231.h"
#ifndef NETDEV_DEFAULT
#define NETDEV_DEFAULT ((netdev_t *)(&at86rf231_netdev))
#endif /* NETDEV_DEFAULT */
#endif /* MODULE_AT86RF231 */
#ifdef MODULE_CC110X
#include "cc110x.h"
#ifndef NETDEV_DEFAULT
#define NETDEV_DEFAULT ((netdev_t *)(&cc110x_dev))
#endif /* NETDEV_DEFAULT */
#endif /* MODULE_CC110X */
#ifdef MODULE_NATIVENET
#include "nativenet.h"
#ifndef NETDEV_DEFAULT
#define NETDEV_DEFAULT (&nativenet_default_dev)
#endif /* NETDEV_DEFAULT */
#endif /* MODULE_NATIVENET */
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* NETDEV_DEFAULT_H_ */
/** @} */

View File

@ -1,16 +0,0 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the LGPLv2 License.
* See the file LICENSE in the top level directory for more details.
*/
/**
* @defgroup netdev Network device interface
* @ingroup drivers
* @brief Network device drivers
*
* The module the network device drivers. It consists of a set of device
* independent interface definitions and specific implementations for every
* device.
*/

View File

@ -1,364 +0,0 @@
/*
* Copyright (C) 2014 INRIA
*
* 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 radio_driver IEEE 802.15.4 radio driver interface
* @ingroup drivers
*
* @brief API definitions for 802.15.4 radio transceivers' drivers
*
* @deprecated THIS INTERFACE IS DEPRECATED. PLEASE USE netdev/802154.h
*
* @{
* @file
* @author Kévin Roussel <Kevin.Roussel@inria.fr>
*
*/
#ifndef IEEE802154_RADIO_DRIVER_API_
#define IEEE802154_RADIO_DRIVER_API_
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Callback function type for receiving incoming packets
* from 802.15.4 radio transceiver.
*
* @param[in] buf Pointer to the buffer containing the incoming
* 802.15.4 packet's raw data.
* @param[in] len Length (in bytes) of the incoming packet's raw data.
* @param[in] rssi Value of the Receive Signal Strength Indicator (RSSI)
* for the incoming packet.
* @param[in] lqi Value of the Link Quality Indicator (LQI)
* for the incoming packet.
* @param[in] crc_ok @c true if incoming packet's checksum (CRC) is valid;
* @c false otherwise (corrupted packet).
*/
typedef void (* receive_802154_packet_callback_t)(void *buf,
unsigned int len,
int8_t rssi,
uint8_t lqi,
bool crc_ok);
/**
* @brief Kind of packet to prepare/configure for transmission.
*
*/
typedef enum {
/** Beacon packet */
PACKET_KIND_BEACON,
/** Standard data packet */
PACKET_KIND_DATA,
/** Acknowledgement packet */
PACKET_KIND_ACK,
/** MAC command */
PACKET_KIND_MAC_CMD,
/** invalid packet kind */
PACKET_KIND_INVALID = -1
} ieee802154_packet_kind_t;
/**
* @brief Return values for packet emission function of 802.15.4 radio driver.
*
*/
typedef enum {
/** Transmission completed successfully */
RADIO_TX_OK,
/** Transmission buffer underflow (forgot to call @c load_tx()
before @c transmit() ) */
RADIO_TX_UNDERFLOW,
/** Transmission cannot start because radio medium is already busy */
RADIO_TX_MEDIUM_BUSY,
/** Transmission failed because of collision on radio medium */
RADIO_TX_COLLISION,
/** Wrong parameter given to TX-related functions */
RADIO_TX_INVALID_PARAM,
/** Too much given data to be included in a single packet */
RADIO_TX_PACKET_TOO_LONG,
/** Transmission supposedly failed since no ACK packet
has been received as response */
RADIO_TX_NOACK,
/** Transmission failed because of an unexpected (fatal?) error */
RADIO_TX_ERROR,
} radio_tx_status_t;
/**
* @brief Definition of an IEEE 802.15.4 node address.
*
* @details The @c union allows to choose between PAN-centric addressing
* ("volatile" 16-bit address and 16-bit PAN ID), or canonical
* IEEE 64-bit ("long") addressing.
*
*/
typedef union {
/** @brief PAN-centric ("short") addressing mode */
struct {
/** @brief Address assigned to the node within its current PAN */
uint16_t addr;
/** @brief ID of the PAN to which the node is currently associated */
uint16_t id;
} pan;
/** @brief 64-bit ("long") addressing mode */
uint64_t long_addr;
} ieee802154_node_addr_t;
/**
* @brief IEEE 802.15.4 radio driver API definition.
*
* @details This is the set of functions that must be implemented
* by any driver for a 802.15.4 radio transceiver.
*
*/
typedef struct {
/**
* @brief Initialize the radio transceiver (call before first use).
*/
void (* init)(void);
/**
* @brief Turn radio transceiver on.
*
* @return @c true if radio transceiver was actually started;
* @c false if an error prevented transceiver to start.
*/
bool (* on)(void);
/**
* @brief Turn radio transceiver off.
*/
void (* off)(void);
/**
* @brief Indicate whether the radio transceiver is up and running.
*
* @return @c true if radio transceiver is on;
* @c false if it is off.
*/
bool (* is_on)(void);
/**
* @brief Load the tranceiver TX buffer with the given
* IEEE 802.15.4 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 @c true to use the 64-bit address mode
* with @c dest param; @c false to use
* "short" PAN-centric mode.
* @param[in] wants_ack @c true to request an acknowledgement
* from the receiving node for this packet;
* @c 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 @c 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 (* load_tx)(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 transceiver TX buffer.
*
* @return The outcome of this packet's transmission.
* @see radio_tx_status_t
*/
radio_tx_status_t (* transmit)(void);
/**
* @brief Transmit the given IEEE 802.15.4 packet,
* by calling successively functions @c load_tx()
* and @c 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 @c true to use the 64-bit address mode
* with @c dest param; @c false to use
* "short" PAN-centric mode.
* @param[in] wants_ack @c true to request an acknowledgement
* from the receiving node for this packet;
* @c 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 @c 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 (* send)(ieee802154_packet_kind_t kind,
ieee802154_node_addr_t dest,
bool use_long_addr,
bool wants_ack,
void *buf,
unsigned int len);
/**
* @brief Define the function to be called back the radio transceiver
* has received a incoming packet.
*
* @param[in] recv_func the callback function to invoke for each
* packet received by the radio transceiver.
* @see receive_802154_packet_callback_t
*/
void (* set_receive_callback)(receive_802154_packet_callback_t recv_func);
/**
* @brief Switch the radio transceiver to receive mode.
*/
void (* switch_to_rx)(void);
/**
* @brief Set the 802.15.4 channel to be used
* by the radio transceiver as medium.
*
* @param[in] chan Channel to switch to.
* Usual values are 0 (868 MHz band),
* 1 to 10 (915 MHz band), and
* 11 to 26 (2.4 GHz band).
*/
void (* set_channel)(unsigned int chan);
/**
* @brief Get the 802.15.4 channel currently used
* by the radio transceiver as medium.
*/
unsigned int (* get_channel)(void);
/**
* @brief Set the 16-bit short address to be used by
* the radio transceiver within the current PAN.
*
* @param[in] addr Address to use.
*/
void (* set_address)(uint16_t addr);
/**
* @brief Get the 16-bit short address currently used by
* the radio transceiver within the current PAN.
*/
uint16_t (* get_address)(void);
/**
* @brief Set the 64-bit long ("extended") address
* to be used by the radio transceiver.
*
* @param[in] addr Address to use.
*/
void (* set_long_address)(uint64_t addr);
/**
* @brief Get the 64-bit long ("extended") address
* currently used by the radio transceiver.
*/
uint64_t (* get_long_address)(void);
/**
* @brief Set the 16-bit PAN ID within which the radio
* transceiver shall operate.
*
* @param[in] pan PAN ID to use.
*/
void (* set_pan_id)(uint16_t pan);
/**
* @brief Get the 16-bit PAN ID within which the radio
* transceiver currently operates.
*/
uint16_t (* get_pan_id)(void);
/**
* @brief Set the transmission power of the radio transceiver.
*
* @param[in] pow Output power to use (in dB).
*/
void (* set_tx_power)(int pow);
/**
* @brief Get the transmission (output) power currently used
* by the radio transceiver (in dB).
*/
int (* get_tx_power)(void);
/**
* @brief Indicates if the radio medium is available for transmission
* ("Clear Channel Assessment").
*
* @return @c true if radio medium is "clear" (available);
* @c false if another transmission is already running.
*/
bool (* channel_is_clear)(void);
/**
* @brief Set the radio transceiver in or out of "promiscuous mode"
* (i.e. reception of all packets without regard for their
* intended destination).
*
* @param[in] monitor Set to @c true to put the transceiver in
* "promiscuous mode" (a.k.a. monitor mode);
* @c false to only receive packets actually
* destined to the currently used address (i.e.:
* to activate hardware address-decoding).
*/
void (* set_promiscuous_mode)(bool monitor);
/**
* @brief Indicates if the radio medium is currently in "promiscuous
* mode" (i.e. receiving all packets without regard for their
* intended destination).
*
* @return @c true if the transceiver is in "promiscuous mode";
* @c false if only packets actually destined to the
* current transceiver are received (i.e. hardware
* address-decoding is active).
*/
bool (* in_promiscuous_mode)(void);
} ieee802154_radio_driver_t;
#ifdef __cplusplus
}
#endif
#endif /* IEEE802154_RADIO_DRIVER_API_ */
/**
* @}
*/

View File

@ -1,119 +0,0 @@
/*
* Copyright (C) 2014 Martine Lenders <mlenders@inf.fu-berlin.de>
*
* 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.
*/
/**
* @addtogroup netdev
* @{
*
* @file
* @brief Provides wrappers of @ref netdev/base.h functions to
* netdev/802154.h functions.
*
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*/
#include <errno.h>
#include <stdint.h>
#include <string.h>
#include "netdev/802154.h"
static inline netdev_802154_driver_t *_get_driver(netdev_t *dev)
{
return (netdev_802154_driver_t *)dev->driver;
}
/* define to implement yourself and omit compilation of this function */
#ifndef NETDEV_802154_SEND_DATA_OVERLOAD
static size_t _get_src_len(netdev_t *dev)
{
size_t src_len, src_len_len = sizeof(size_t);
if (_get_driver(dev)->get_option(dev, NETDEV_OPT_SRC_LEN, &src_len, &src_len_len) < 0) {
return 2;
}
return src_len;
}
int netdev_802154_send_data(netdev_t *dev, void *dest, size_t dest_len,
netdev_hlist_t *upper_layer_hdrs, void *data,
size_t data_len)
{
int use_long_addr;
if (dev == NULL || dev->type != NETDEV_TYPE_802154) {
return -ENODEV;
}
use_long_addr = _get_src_len(dev) == 8;
if (dest_len != 8 && dest_len != 4) { /* 8 for EUI-64, 4 for short address + PAN ID*/
return -EAFNOSUPPORT;
}
switch (_get_driver(dev)->send(dev, NETDEV_802154_PKT_KIND_DATA,
(netdev_802154_node_addr_t *)dest,
use_long_addr, 0, upper_layer_hdrs,
data, data_len)) {
case NETDEV_802154_TX_STATUS_OK:
return (int)(data_len + netdev_get_hlist_len(upper_layer_hdrs));
case NETDEV_802154_TX_STATUS_MEDIUM_BUSY:
case NETDEV_802154_TX_STATUS_COLLISION:
return -EBUSY;
case NETDEV_802154_TX_STATUS_INVALID_PARAM:
return -EINVAL;
case NETDEV_802154_TX_STATUS_PACKET_TOO_LONG:
return -EMSGSIZE;
case NETDEV_802154_TX_STATUS_ERROR:
default:
return -EIO;
/* NETDEV_802154_TX_STATUS_UNDERFLOW can not happen since
* netdev_802154_driver_t::send always calls
* netdev_802154_driver_t::load_tx */
/* NETDEV_802154_TX_STATUS_NOACK can not happen since
* wants_ack == 0 */
}
}
#endif /* NETDEV_802154_SEND_DATA_OVERLOAD */
/* define to implement yourself and omit compilation of this function */
#ifndef NETDEV_802154_SEND_OVERLOAD
netdev_802154_tx_status_t netdev_802154_send(netdev_t *dev,
netdev_802154_pkt_kind_t kind,
netdev_802154_node_addr_t *dest,
int use_long_addr,
int wants_ack,
netdev_hlist_t *upper_layer_hdrs,
void *buf,
unsigned int len)
{
netdev_802154_tx_status_t status;
if (dev == NULL || dev->type != NETDEV_TYPE_802154) {
return NETDEV_802154_TX_STATUS_NO_DEV;
}
status = _get_driver(dev)->load_tx(dev, kind, dest, use_long_addr, wants_ack,
upper_layer_hdrs, buf, len);
if (status != NETDEV_802154_TX_STATUS_OK) {
return status;
}
return _get_driver(dev)->transmit(dev);
}
#endif /* NETDEV_802154_SEND_OVERLOAD */
/**
* @}
*/

View File

@ -1,5 +0,0 @@
MODULE := netdev_802154
INCLUDES += -I$(RIOTBASE)/drivers/include
include $(RIOTBASE)/Makefile.base

View File

@ -1,5 +0,0 @@
MODULE := netdev_base
INCLUDES += -I$(RIOTBASE)/drivers/include
include $(RIOTBASE)/Makefile.base

View File

@ -1,42 +0,0 @@
/*
* Copyright (C) 2014 Martine Lenders <mlenders@inf.fu-berlin.de>
*
* 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.
*/
/**
* @addtogroup netdev
* @{
*
* @file
* @brief Provides helper functions to the API in @ref netdev/base.h.
*
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*/
#include "clist.h"
#include "netdev/base.h"
size_t netdev_get_hlist_len(const netdev_hlist_t *hlist)
{
netdev_hlist_t *ptr = (netdev_hlist_t *)hlist;
size_t length = 0;
if (ptr == NULL) {
return 0;
}
do {
length += ptr->header_len;
netdev_hlist_advance(&ptr);
} while (ptr != hlist);
return length;
}
/**
* @}
*/

View File

@ -1,55 +0,0 @@
simple appserver (all in one shell)
====================================================
0. create tap devices: *./cpu/native/tapsetup.sh create 3*
1. build ccn-lite-client: *make -B clean all-valgrind*
2. start: *./bin/native/ccn-lite-client.elf tap0* (valgrind support included)
3. optional: *config 20* [enter] (this sets the content store size)
4. start appserver thread: *appserver* [enter] (this starts the userland appserver, which registers for "/riot/appserver/"
5. request content: *interest /riot/appserver/test* [enter] (ask the relay for this "file", userland code splits this up in
chunks and requests them from the relay. In the relay the name "/riot/appserver" is registered to the RIOT MSG face with
thread of the appserver. Interest is forwarded to appserver which replies with content....
6. tear down ccn network stack: *haltccn* [enter]
7. now you can hit *ctrl+c* to stop the RIOT process [in valgrind you can notice that there is no leak]
simple forward (needs two shells)
====================================================
SHELL 1 | SHELL 2
--------------------------------------------------------------------------------------------------------------
0. create tap devices: *./cpu/native/tapsetup.sh create 3* |
1. build ccn-lite-client: *make -B clean all* | build ccn-lite: *make clean all*
2. start: *./bin/native/ccn-lite-client.elf tap0* | start: *./bin/ccn-lite-relay.elf tap1*
3. set content store size: *config 20* [enter] | [stack starts automaticly]
4. set address: *addr 1* [enter] | [it picks address 42 automaticly]
5. register prefix the ccn-lite stack: *prefix /riot/ newTRANSface 42* [enter] | [it populates the cache automaticly]
6. request content: *interest /riot/text* [enter] |
7. tear down ccn network stack: *haltccn* [enter]
advanced forward (needs three shells)
====================================================
SHELL 1 | SHELL 2 | SHELL 3
----------------------------------------------------------------------------------------------------------------------------------------------------------------
0. create tap devices: *./cpu/native/tapsetup.sh create 3* | |
1. build ccn-lite-client: *make -B clean all* | | build ccn-lite: make clean all
2. start: *./bin/native/ccn-lite-client.elf tap0* | start: *./bin/native/ccn-lite-client.elf tap1* | start: ./bin/ccn-lite-relay.elf tap2
3. set content store size: *cconfig 20* [enter] | set content store size: *cconfig 20* [enter] | [it starts ccn automaticly]
4. set address: *addr 1* [enter] | set address: *addr 2* [enter] | [it picks address 42 automaticly]
5. *prefix /riot/ newTRANSface 2* [enter] | *prefix /riot/ newTRANSface 42* [enter] | [it populates the cache automaticly]
6. request content: *interest /riot/text* [enter] | |
overdosed forward (needs three shells)
====================================================
SHELL 1 | SHELL 2 | SHELL 3
----------------------------------------------------------------------------------------------------------------------------------------------------------------
0. create tap devices: *./cpu/native/tapsetup.sh create 3* | |
1. build ccn-lite-client: *make -B clean all* | |
2. start: *./bin/native/ccn-lite-client.elf tap0* | start: *./bin/native/ccn-lite-client.elf tap1* | start: *./bin/native/ccn-lite-client.elf tap2*
3. set content store size: *cconfig 20* [enter] | sset content store size: *cconfig 20* [enter] | sset content store size: *cconfig 20* [enter]
4. set address: *addr 1* [enter] | set address: *addr 2* [enter] | set address: *addr 3* [enter]
5. | | start appserver: *appserver* [enter]
6. *prefix /riot/ newTRANSface 2* [enter] | *prefix /riot/ newTRANSface 3* [enter] |
7. request content: *interest /riot/appserver/test* [enter] | |

View File

@ -1,45 +0,0 @@
# name of your application
APPLICATION = ccn-lite-client
# If no BOARD is found in the environment, use this default:
BOARD ?= native
# This has to be the absolute path to the RIOT base directory:
RIOTBASE ?= $(CURDIR)/../..
# Uncomment these lines if you want to use platform support from external
# repositories:
#RIOTCPU ?= $(CURDIR)/../../RIOT/thirdparty_cpu
#RIOTBOARD ?= $(CURDIR)/../../RIOT/thirdparty_boards
# Uncomment this to enable scheduler statistics for ps:
#CFLAGS += -DSCHEDSTATISTICS
# If you want to use native with valgrind, you should recompile native
# with the target all-valgrind instead of all:
# make -B clean all-valgrind
# Comment this out to disable code in RIOT that does safety checking
# which is not needed in a production environment but helps in the
# development process:
CFLAGS += -DDEVELHELP
# Change this to 0 show compiler invocation lines by default:
QUIET ?= 1
# The CCN-lite API is currently expecting unsigned int to be at least 32 bits wide.
BOARD_BLACKLIST := chronos msb-430h telosb wsn430-v1_3b wsn430-v1_4 z1 redbee-econotag
# Modules to include:
USEMODULE += shell
USEMODULE += shell_commands
USEMODULE += uart0
USEMODULE += ps
USEMODULE += random
USEMODULE += defaulttransceiver
USEMODULE += vtimer
USEMODULE += ccn_lite
USEMODULE += ccn_lite_client
include $(RIOTBASE)/Makefile.include

View File

@ -1,16 +0,0 @@
This application is a showcase of the Content Centric Networking (CCN) capabilities in RIOT.
The example consists in two parts: clients and relays.
This file documents the client functionalities.
A client opens a shell to enable the following:
* **start the CCN stack**: The command `ccn X` starts the CCN stack and sets the content store size to X chunks. Chunk size is by default set to 802.15.4 packet payload (set it differently if needed). Note that X must be bigger or equal to 15 if you plan to publish content using Way 1 described below.
* **publishing content locally**: Two alternative ways are defined to do that.
* *Way 1*: pre-provision the local CCN stack cache with X dummy chunks, with the command `populate`. Chunk size is by default set to 802.15.4 packet payload (set it differently if needed). The default name of the content is `/riot/text`.
* *Way 2*: start a application in a different thread with the command `appserver`. This application will register a prefix `/riot/appserver/test` in the CCN network stack Forwarding Information Base (FIB). Note that from the view of the CCN network stack, there is no difference between local faces connecting to local appplications and network faces connecting to real network interfaces. When the application recieves an interest it replies with chunck `/riot/appserver/test/0`. Note that actual interest parsing is not implemented in the application.
* **subscribing to receive content**: the command `interest` fetches a remote file through the CCN network stack. This starts an application executed by the shell thread, which creates an interest message and routes this message hop by hop towards the publisher of the content (or a cache containing a copy) using the CCN stack. By default the content being fetched is `/riot/text`. One can also specify a name of content to fetch with the command `interest valid-name`. By valid, it is meant that the name should have structure like `/a/b/c` and the application will then request chunks with syntax `/a/b/c/0` etc.

View File

@ -1,366 +0,0 @@
/*
* Copyright (C) 2013 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 examples
* @{
*
* @file
* @brief CCN Lite interactive shell example application
*
* @author Christian Mehlis <mehlis@inf.fu-berlin.de>
*
* @}
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include "msg.h"
#include "thread.h"
#include "posix_io.h"
#include "shell.h"
#include "board_uart0.h"
#include "transceiver.h"
#include "vtimer.h"
#include "ps.h"
#include "ltc4150.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#include "ccn_lite/ccnl-riot.h"
#include "ccn_lite/util/ccnl-riot-client.h"
#define RIOT_CCN_APPSERVER (1)
#define RIOT_CCN_TESTS (0)
static const char DEFAULT_INTEREST[] = "/ccnx/0.7.1/doc/technical/CanonicalOrder.txt";
char relay_stack[THREAD_STACKSIZE_MAIN];
#if RIOT_CCN_APPSERVER
char appserver_stack[THREAD_STACKSIZE_MAIN];
#endif
static volatile kernel_pid_t _relay_pid = KERNEL_PID_UNDEF, _appserver_pid = KERNEL_PID_UNDEF;
#define SHELL_MSG_BUFFER_SIZE (64)
msg_t msg_buffer_shell[SHELL_MSG_BUFFER_SIZE];
shell_t shell;
unsigned char big_buf[3 * 1024];
char small_buf[PAYLOAD_SIZE];
#if RIOT_CCN_APPSERVER
static int riot_ccn_appserver(int argc, char **argv)
{
(void) argc; /* the function takes no arguments */
(void) argv;
if (_appserver_pid != KERNEL_PID_UNDEF) {
/* already running */
return 1;
}
_appserver_pid = thread_create(
appserver_stack, sizeof(appserver_stack),
THREAD_PRIORITY_MAIN - 1, CREATE_STACKTEST,
ccnl_riot_appserver_start, (void *) &_relay_pid, "appserver");
DEBUG("ccn-lite appserver on thread_id %" PRIkernel_pid "...\n", _appserver_pid);
return 0;
}
#endif
static int riot_ccn_express_interest(int argc, char **argv)
{
if (argc < 2) {
strncpy(small_buf, DEFAULT_INTEREST, sizeof(small_buf));
}
else {
strncpy(small_buf, argv[1], sizeof(small_buf));
}
DEBUG("in='%s'\n", small_buf);
int content_len = ccnl_riot_client_get(_relay_pid, small_buf, (char *) big_buf); // small_buf=name to request
if (content_len == 0) {
puts("riot_get returned 0 bytes...aborting!");
return 1;
}
puts("####################################################");
big_buf[content_len] = '\0';
printf("data='%s'\n", big_buf);
puts("####################################################");
puts("done");
return 0;
}
static int riot_ccn_register_prefix(int argc, char **argv)
{
if (argc < 4) {
puts("enter: prefix </path/to/abc> <type> <faceid>");
return 1;
}
strncpy(small_buf, argv[1], 100);
DEBUG("prefix='%s'\n", small_buf);
char *type = argv[2];
char *faceid = argv[3]; // 0=trans;1=msg
int content_len = ccnl_riot_client_publish(_relay_pid, small_buf, faceid, type, big_buf);
#if !ENABLE_DEBUG
(void) content_len;
#endif
DEBUG("shell received: '%s'\n", big_buf);
DEBUG("received %d bytes.\n", content_len);
puts("done");
return 0;
}
static int riot_ccn_relay_config(int argc, char **argv)
{
if (_relay_pid == KERNEL_PID_UNDEF) {
puts("ccnl stack not running");
return 1;
}
if (argc < 2) {
printf("%s: <max_cache_entries>\n", argv[0]);
return 1;
}
msg_t m;
m.content.value = atoi(argv[1]);
m.type = CCNL_RIOT_CONFIG_CACHE;
msg_send(&m, _relay_pid);
return 0;
}
static void riot_ccn_transceiver_start(kernel_pid_t _relay_pid)
{
transceiver_init(TRANSCEIVER);
int transceiver_pid = transceiver_start();
DEBUG("transceiver on thread_id %d...\n", transceiver_pid);
/* register for transceiver events */
uint8_t reg = transceiver_register(TRANSCEIVER, _relay_pid);
if (reg != 1) {
DEBUG("transceiver register failed\n");
}
/* set channel to CCNL_CHAN */
msg_t mesg;
transceiver_command_t tcmd;
int32_t c = CCNL_DEFAULT_CHANNEL;
tcmd.transceivers = TRANSCEIVER;
tcmd.data = &c;
mesg.content.ptr = (char *) &tcmd;
mesg.type = SET_CHANNEL;
msg_send_receive(&mesg, &mesg, transceiver_pid);
if (c == -1) {
puts("[transceiver] Error setting/getting channel");
}
else {
printf("[transceiver] Got channel: %" PRIi32 "\n", c);
}
}
static int riot_ccn_relay_start(void)
{
if (_relay_pid != KERNEL_PID_UNDEF) {
DEBUG("ccn-lite relay on thread_id %d...please stop it first!\n", _relay_pid);
/* already running */
return 1;
}
_relay_pid = thread_create(
relay_stack, sizeof(relay_stack),
THREAD_PRIORITY_MAIN - 2, CREATE_STACKTEST,
ccnl_riot_relay_start, NULL, "relay");
DEBUG("ccn-lite relay on thread_id %" PRIkernel_pid "...\n", _relay_pid);
riot_ccn_transceiver_start(_relay_pid);
return 0;
}
static int riot_ccn_relay_stop(int argc, char **argv)
{
(void) argc; /* the function takes no arguments */
(void) argv;
msg_t m;
m.content.value = 0;
m.type = CCNL_RIOT_HALT;
msg_send(&m, _relay_pid);
/* mark relay as not running */
_relay_pid = 0;
return 0;
}
#if RIOT_CCN_TESTS
static int riot_ccn_pit_test(int argc, char **argv)
{
(void) argc; /* the function takes no arguments */
(void) argv;
char name[] = "/riot/test";
char *prefix[CCNL_MAX_NAME_COMP];
char *cp = strtok(name, "/");
int i = 0;
while (i < (CCNL_MAX_NAME_COMP - 1) && cp) {
prefix[i++] = cp;
cp = strtok(NULL, "/");
}
//prefix[i] = 0; //segment to request
prefix[i + 1] = 0;
msg_t m;
riot_ccnl_msg_t rmsg;
char segment_string[16]; //max=999\0
timex_t now;
int segment;
for (segment = 0; segment < 200; segment++) {
memset(segment_string, 0, 16);
snprintf(segment_string, 16, "%d", segment);
prefix[i] = segment_string;
unsigned int interest_nonce = genrand_uint32();
int interest_len = mkInterest(prefix, &interest_nonce, (unsigned char *) small_buf);
rmsg.payload = &small_buf;
rmsg.size = interest_len;
m.content.ptr = (char *) &rmsg;
m.type = CCNL_RIOT_MSG;
msg_send(&m, _relay_pid);
if ((segment % 50) == 0) {
vtimer_now(&now);
printf("done: %d - %ld.%ld\n", segment, now.tv_sec, now.tv_usec);
}
}
printf("done: tried to send %d interests\n", segment);
return 0;
}
static int riot_ccn_fib_test(int argc, char **argv)
{
(void) argc; /* the function takes no arguments */
(void) argv;
char type[] = "newTRANSface";
char faceid[] = "42";
riot_new_face(_relay_pid, type, faceid, big_buf);
timex_t now;
int i = -1;
do {
i++;
snprintf(small_buf, sizeof(small_buf), "/riot/test/fib/%d/", i);
riot_register_prefix(_relay_pid, small_buf, faceid, big_buf);
if (i % 50 == 0) {
vtimer_now(&now);
printf("done: %d - %ld.%ld\n", i, now.tv_sec, now.tv_usec);
}
}
while (0 == strcmp((const char *) big_buf, "prefixreg cmd worked"));
DEBUG("%d: '%s'\n", i, big_buf);
printf("done: %d\n", i - 1);
return 0;
}
#endif
static int riot_ccn_populate(int argc, char **argv)
{
(void) argc; /* the function takes no arguments */
(void) argv;
msg_t m;
m.content.value = 0;
m.type = CCNL_RIOT_POPULATE;
msg_send(&m, _relay_pid);
return 0;
}
static int riot_ccn_stat(int argc, char **argv)
{
(void) argc; /* the function takes no arguments */
(void) argv;
msg_t m;
m.content.value = 0;
m.type = CCNL_RIOT_PRINT_STAT;
msg_send(&m, _relay_pid);
return 0;
}
static const shell_command_t sc[] = {
{ "haltccn", "stops ccn relay", riot_ccn_relay_stop },
{ "interest", "express an interest", riot_ccn_express_interest },
{ "populate", "populate the cache of the relay with data", riot_ccn_populate },
{ "prefix", "registers a prefix to a face", riot_ccn_register_prefix },
{ "stat", "prints out forwarding statistics", riot_ccn_stat },
{ "config", "changes the runtime config of the ccn lite relay", riot_ccn_relay_config },
#if RIOT_CCN_APPSERVER
{ "appserver", "starts an application server to reply to interests", riot_ccn_appserver },
#endif
#if RIOT_CCN_TESTS
{ "pittest", "starts a test for the size and speed of pit operations", riot_ccn_pit_test },
{ "fibtest", "starts a test for the size and speed of fib operations", riot_ccn_fib_test },
#endif
{ NULL, NULL, NULL }
};
int main(void)
{
puts("CCN!");
if (msg_init_queue(msg_buffer_shell, SHELL_MSG_BUFFER_SIZE) != 0) {
DEBUG("msg init queue failed...abording\n");
return -1;
}
riot_ccn_relay_start();
puts("starting shell...");
puts(" posix open");
posix_open(uart0_handler_pid, 0);
puts(" shell init");
shell_init(&shell, sc, UART0_BUFSIZE, uart0_readc, uart0_putc);
puts(" shell run");
shell_run(&shell);
return 0;
}

View File

@ -1,40 +0,0 @@
# name of your application
APPLICATION = ccn-lite-relay
# If no BOARD is found in the environment, use this default:
BOARD ?= native
# This has to be the absolute path to the RIOT base directory:
RIOTBASE ?= $(CURDIR)/../..
# Uncomment these lines if you want to use platform support from external
# repositories:
#RIOTCPU ?= $(CURDIR)/../../RIOT/thirdparty_cpu
#RIOTBOARD ?= $(CURDIR)/../../RIOT/thirdparty_boards
# Uncomment this to enable scheduler statistics for ps:
#CFLAGS += -DSCHEDSTATISTICS
# If you want to use native with valgrind, you should recompile native
# with the target all-valgrind instead of all:
# make -B clean all-valgrind
# Comment this out to disable code in RIOT that does safety checking
# which is not needed in a production environment but helps in the
# development process:
CFLAGS += -DDEVELHELP
# Change this to 0 show compiler invocation lines by default:
QUIET ?= 1
# The CCN-lite API is currently expecting unsigned int to be at least 32 bits wide.
BOARD_BLACKLIST := chronos msb-430h telosb wsn430-v1_3b wsn430-v1_4 z1 redbee-econotag
# Modules to include:
USEMODULE += posix
USEMODULE += defaulttransceiver
USEMODULE += ccn_lite
include $(RIOTBASE)/Makefile.include

View File

@ -1,9 +0,0 @@
This application is a showcase of the Content Centric Networking (CCN) capabilities in RIOT.
The example consists in two parts: clients and relays.
This file documents the relay functionalities.
A relay implements CCN capabilities for third party content caching, forwarding and subscription.
Upon booting up, the CCN stack is automatically started, which enables the processing of incoming CCN messages (and relaying them if necessary).

View File

@ -1,85 +0,0 @@
/*
* Copyright (C) 2013 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 examples
* @{
*
* @file
* @brief CCN Lite relay example application
*
* @author Christian Mehlis <mehlis@inf.fu-berlin.de>
*
* @}
*/
// system
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
// riot
#include "thread.h"
#include "periph/rtc.h"
// ccn
#include "ccn_lite/ccnl-riot.h"
static kernel_pid_t _relay_pid = KERNEL_PID_UNDEF;
char t2_stack[THREAD_STACKSIZE_MAIN];
void set_address_handler(uint16_t a)
{
msg_t mesg;
transceiver_command_t tcmd;
tcmd.transceivers = TRANSCEIVER;
tcmd.data = &a;
mesg.content.ptr = (char *) &tcmd;
printf("trying to set address %" PRIu16 "\n", a);
mesg.type = SET_ADDRESS;
printf("transceiver_pid=%" PRIkernel_pid"\n", transceiver_pid);
msg_send_receive(&mesg, &mesg, transceiver_pid);
printf("got address: %" PRIu16 "\n", a);
}
void populate_cache(void)
{
msg_t m;
m.content.value = 0;
m.type = CCNL_RIOT_POPULATE;
msg_send(&m, _relay_pid);
}
void *second_thread(void *arg)
{
(void) arg;
set_address_handler(42);
populate_cache();
return NULL;
}
int main(void)
{
printf("CCN!\n");
_relay_pid = thread_getpid();
thread_create(t2_stack, sizeof(t2_stack), THREAD_PRIORITY_MAIN + 1,
CREATE_STACKTEST, second_thread, NULL, "helper thread");
printf("starting ccn-lite relay...\n");
ccnl_riot_relay_start(NULL);
return 0;
}

View File

@ -37,7 +37,6 @@ USEMODULE += vtimer
USEMODULE += defaulttransceiver
USEMODULE += config
FEATURES_OPTIONAL += transceiver
FEATURES_OPTIONAL += config
FEATURES_OPTIONAL += periph_rtc

View File

@ -39,102 +39,6 @@
#include "ltc4150.h"
#endif
#if MODULE_AT86RF231 || MODULE_CC2420 || MODULE_MC1322X
#include "ieee802154_frame.h"
#endif
#ifdef MODULE_TRANSCEIVER
#include "transceiver.h"
#endif
#define SND_BUFFER_SIZE (100)
#define RCV_BUFFER_SIZE (64)
#define RADIO_STACK_SIZE (THREAD_STACKSIZE_MAIN)
#ifdef MODULE_TRANSCEIVER
static char radio_stack_buffer[RADIO_STACK_SIZE];
static msg_t msg_q[RCV_BUFFER_SIZE];
void *radio(void *arg)
{
(void) arg;
msg_t m;
#if MODULE_AT86RF231 || MODULE_CC2420 || MODULE_MC1322X
ieee802154_packet_t *p;
#else
radio_packet_t *p;
radio_packet_length_t i;
#endif
msg_init_queue(msg_q, RCV_BUFFER_SIZE);
while (1) {
msg_receive(&m);
if (m.type == PKT_PENDING) {
#if MODULE_AT86RF231 || MODULE_CC2420 || MODULE_MC1322X
p = (ieee802154_packet_t*) m.content.ptr;
printf("Got radio packet:\n");
printf("\tLength:\t%u\n", p->length);
printf("\tSrc:\t%u\n", (p->frame.src_addr[0])|(p->frame.src_addr[1]<<8));
printf("\tDst:\t%u\n", (p->frame.dest_addr[0])|(p->frame.dest_addr[1]<<8));
printf("\tLQI:\t%u\n", p->lqi);
printf("\tRSSI:\t%u\n", p->rssi);
printf("Payload Length:%u\n", p->frame.payload_len);
printf("Payload:%s\n", p->frame.payload);
p->processing--;
#else
p = (radio_packet_t *) m.content.ptr;
printf("Got radio packet:\n");
printf("\tLength:\t%u\n", p->length);
printf("\tSrc:\t%u\n", p->src);
printf("\tDst:\t%u\n", p->dst);
printf("\tLQI:\t%u\n", p->lqi);
printf("\tRSSI:\t%u\n", p->rssi);
for (i = 0; i < p->length; i++) {
printf("%02X ", p->data[i]);
}
p->processing--;
puts("\n");
#endif
}
else if (m.type == ENOBUFFER) {
puts("Transceiver buffer full");
}
else {
puts("Unknown message received");
}
}
}
void init_transceiver(void)
{
kernel_pid_t radio_pid = thread_create(
radio_stack_buffer,
sizeof(radio_stack_buffer),
THREAD_PRIORITY_MAIN - 2,
CREATE_STACKTEST,
radio,
NULL,
"radio");
uint16_t transceivers = TRANSCEIVER_DEFAULT;
transceiver_init(transceivers);
(void) transceiver_start();
transceiver_register(transceivers, radio_pid);
}
#endif /* MODULE_TRANSCEIVER */
int main(void)
{
shell_t shell;
@ -144,10 +48,6 @@ int main(void)
ltc4150_start();
#endif
#ifdef MODULE_TRANSCEIVER
init_transceiver();
#endif
#ifdef FEATURE_PERIPH_RTC
rtc_init();
#endif

View File

@ -1,46 +0,0 @@
# name of your application
APPLICATION = rpl_udp
# If no BOARD is found in the environment, use this default:
BOARD ?= native
# This has to be the absolute path to the RIOT base directory:
RIOTBASE ?= $(CURDIR)/../..
# Uncomment these lines if you want to use platform support from external
# repositories:
#RIOTCPU ?= $(CURDIR)/../../RIOT/thirdparty_cpu
#RIOTBOARD ?= $(CURDIR)/../../RIOT/thirdparty_boards
# Uncomment this to enable scheduler statistics for ps:
#CFLAGS += -DSCHEDSTATISTICS
# If you want to use native with valgrind, you should recompile native
# with the target all-valgrind instead of all:
# make -B clean all-valgrind
# Comment this out to disable code in RIOT that does safety checking
# which is not needed in a production environment but helps in the
# development process:
CFLAGS += -DDEVELHELP
# Change this to 0 show compiler invocation lines by default:
QUIET ?= 1
BOARD_INSUFFICIENT_RAM := chronos msb-430h redbee-econotag telosb wsn430-v1_3b wsn430-v1_4 z1 samr21-xpro
# arduino-mega2560: time.h missing from avr-libc
BOARD_BLACKLIST := arduino-mega2560
# Modules to include:
USEMODULE += shell
USEMODULE += shell_commands
USEMODULE += uart0
USEMODULE += ps
USEMODULE += vtimer
USEMODULE += defaulttransceiver
USEMODULE += rpl
USEMODULE += udp
include $(RIOTBASE)/Makefile.include

View File

@ -1,126 +0,0 @@
# Setup the build
First switch to this application directory:
cd RIOT/examples/rpl_udp
The build system provides three specific parameters for the RPL module.
These parameters are:
* `RPL_MOP` sets the _mode of operation_ (MOP) of RPL. _The default value (`0x02`) is used if this variable is not set._
* `RPL_MAX_ROUTING_ENTRIES` sets the desired maximum number of entries for the RPL routing table. _If this parameter is not provided, a default value (`128`) is used._
* `RPL_NODE_IS_ROOT` indicating the build is specifically for a root node. This parameter is **only required** for using `RPL_MOP_NON_STORING_MODE` MOP to initialize a RPL routing table. The parameter is ignored in all other cases. _For non-storing MOP a node does not require to provide a routing table._
These RPL build parameters and their according _default_ values are used in the [`rpl_config.h`](https://github.com/RIOT-OS/RIOT/blob/master/sys/net/include/rpl/rpl_config.h).
#### Compiling the executable
**example for `RPL_MOP_STORING_MODE_MC`:**
make RPL_MOP=RPL_MOP_STORING_MODE_MC
builds the project and creates `128` entries for the RPL routing table by default.
make RPL_MOP=RPL_MOP_STORING_MODE_MC RPL_MAX_ROUTING_ENTRIES=103
builds the project and creates `103` entries for the RPL routing table **overwriting** the default value.
**example for `RPL_MOP_NON_STORING_MODE`:**
make RPL_MOP=RPL_MOP_NON_STORING_MODE RPL_MAX_ROUTING_ENTRIES=103 RPL_NODE_IS_ROOT=1
builds the project and creates `103` entries for the RPL routing table for the root node.
#### _[native only]_ Set up a bridge for *two* tap devices for communication
../../cpu/native/tapsetup.sh create 2
The `2` corresponds to the number of _virtual_ nodes to be started.
The tap devices are bound to the _virtual_ native node on starting the created executable `rpl_udp.elf`.
#### _[native only]_ Starting _virtual_ nodes
Run the first node
make term
This starts the executable binding a _virtual_ node to the first tap device `tap0`.
**Further nodes must be bound to tap devices manually.**
For the second node it would be:
make term PORT=tap1
# RPL init
Type ``help`` to see the commands available.
#### Command order:
init (r|n|h)
server
send <node-id> <message>
Init your RPL node either as root (`r`), as node router (`n`), or as non-routing node (host-mode) (`h`)
> init r
init r
INFO: Initialize as root on address 1
6LoWPAN and RPL initialized.
Channel set to 10
Transport layer initialized
or
> init n
init n
INFO: Initialize as node on address 2
6LoWPAN and RPL initialized.
Channel set to 10
Transport layer initialized
or
> init h
init h
INFO: Initialize as non-routing node on address 3
6LoWPAN initialized.
Channel set to 10
Transport layer initialized
(It is advised to start all nodes before running the root node, because the interval for sending DIOs from the root increases over time)
A few seconds withing running, setting and initializing your second node, the nodes will automatically start to exchange control traffic. You should be seeing output similar to the following:
41 CC FC 34 12 36 12 00 FF FE 00 00 02 36 12 00 FF FE 00 00 01 7A 33 3A 9B 03 F9 90 00 00 04 00 00 80
IPv6 datagram received (next header: 3A) from fe80:0000:0000:0000:3612:00ff:fe00:0001 ICMP type: 5A ICMP code: 08
Received packet from ID 1
Length: 34
Src: 1
Dst: 2
LQI: 0
RSSI: 0
You can now use the ``dodag`` command to obtain information on the node's rank in the rpl dodag as well as their preferred parent
> dodag
dodag
---------------------------
Part of Dodag:
fe80:0000:0000:0000:3612:00ff:fe00:0001
my rank: 512
my preferred parent:
fe80:0000:0000:0000:3612:00ff:fe00:0001
---------------------------
#Sending via UDP
In order to be able to receive UDP messages from other nodes, we have to start `rpl_udp`'s UDP server:
> server
server
UDP SERVER ON PORT 511 (THREAD PID: 17)
When rpl is running, you can send a message from any participating node to the node initialized as a server (in our case, node 1) using the ``send`` command
> send 1 hi
send 1 hi
Successful deliverd 11 bytes over UDP to abcd:0000:0000:0000:3612:00ff:fe00:0001 to 6LoWPAN
In case of an error message, make sure that rpl is running and you've started the UDP server on the receiving node by running the ``server`` command.

View File

@ -1,158 +0,0 @@
/*
* Copyright (C) 2013, 2014 INRIA
*
* 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 examples
* @{
*
* @file
* @brief UDP RPL example application
*
* @author Oliver Hahm <oliver.hahm@inria.fr>
*
* @}
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "msg.h"
#include "sixlowpan/ip.h"
#include "transceiver.h"
#include "ieee802154_frame.h"
#include "rpl/rpl_structs.h"
#include "rpl_udp.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#define LL_HDR_LEN (0x4)
#define IPV6_HDR_LEN (0x28)
extern uint8_t ipv6_ext_hdr_len;
static msg_t msg_q[RCV_BUFFER_SIZE];
int rpl_udp_set_id(int argc, char **argv)
{
if (argc != 2) {
printf("Usage: %s address\n", argv[0]);
#if (defined(MODULE_CC110X) || defined(MODULE_CC110X_LEGACY) || defined(MODULE_CC110X_LEGACY_CSMA))
printf("\taddress must be an 8 bit integer\n");
#else
printf("\taddress must be an 16 bit integer\n");
#endif
printf("\n\t(Current address is %u)\n", id);
return 1;
}
id = atoi(argv[1]);
printf("Set node ID to %u\n", id);
return 0;
}
void *rpl_udp_monitor(void *arg)
{
(void) arg;
msg_t m;
radio_packet_t *p;
ipv6_hdr_t *ipv6_buf;
uint8_t icmp_type, icmp_code;
icmpv6_hdr_t *icmpv6_buf = NULL;
msg_init_queue(msg_q, RCV_BUFFER_SIZE);
while (1) {
msg_receive(&m);
if (m.type == PKT_PENDING) {
p = (radio_packet_t *) m.content.ptr;
DEBUGF("Received packet from ID %u\n", p->src);
DEBUG("\tLength:\t%u\n", p->length);
DEBUG("\tSrc:\t%u\n", p->src);
DEBUG("\tDst:\t%u\n", p->dst);
DEBUG("\tLQI:\t%u\n", p->lqi);
DEBUG("\tRSSI:\t%i\n", (int8_t) p->rssi);
for (uint8_t i = 0; i < p->length; i++) {
DEBUG("%02X ", p->data[i]);
}
p->processing--;
DEBUG("\n");
}
else if (m.type == IPV6_PACKET_RECEIVED) {
ipv6_buf = (ipv6_hdr_t *) m.content.ptr;
printf("IPv6 datagram received (next header: %02X)", ipv6_buf->nextheader);
printf(" from %s ", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN,
&ipv6_buf->srcaddr));
if (ipv6_buf->nextheader == IPV6_PROTO_NUM_ICMPV6) {
icmpv6_buf = (icmpv6_hdr_t *) &ipv6_buf[(LL_HDR_LEN + IPV6_HDR_LEN) + ipv6_ext_hdr_len];
icmp_type = icmpv6_buf->type;
icmp_code = icmpv6_buf->code;
}
if (ipv6_buf->nextheader == IPV6_PROTO_NUM_ICMPV6) {
DEBUG("\t ICMP type: %02X ", icmp_type);
DEBUG("\t ICMP code: %02X ", icmp_code);
(void) icmp_type;
(void) icmp_code;
}
printf("\n");
}
else if (m.type == ENOBUFFER) {
puts("Transceiver buffer full");
}
else {
printf("Unknown packet received, type %04X\n", m.type);
}
}
return NULL;
}
static transceiver_command_t tcmd;
int rpl_udp_ignore(int argc, char **argv)
{
uint16_t a;
if (argc < 2) {
printf("Usage: %s <addr>\n", argv[0]);
return 1;
}
if (transceiver_pid == KERNEL_PID_UNDEF) {
puts("Transceiver not runnning.");
return 1;
}
/* cppcheck: a is actually read via tcmd.data */
/* cppcheck-suppress unreadVariable */
a = atoi(argv[1]);
msg_t mesg;
mesg.type = DBG_IGN;
mesg.content.ptr = (char *) &tcmd;
tcmd.transceivers = TRANSCEIVER_CC1100;
tcmd.data = &a;
printf("sending to transceiver (%" PRIkernel_pid "): %u\n", transceiver_pid,
(*(uint8_t *)tcmd.data));
msg_send(&mesg, transceiver_pid);
return 0;
}

View File

@ -1,56 +0,0 @@
/*
* Copyright (C) 2013, 2014 INRIA
*
* 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 examples
* @{
*
* @file
* @brief UDP RPL example application
*
* @author Oliver Hahm <oliver.hahm@inria.fr>
*
* @}
*/
#include <stdio.h>
#include "net_if.h"
#include "posix_io.h"
#include "shell.h"
#include "shell_commands.h"
#include "board_uart0.h"
#include "udp.h"
#include "rpl_udp.h"
static const shell_command_t shell_commands[] = {
{"init", "Initialize network", rpl_udp_init},
{"set", "Set ID", rpl_udp_set_id},
{"dodag", "Shows the dodag", rpl_udp_dodag},
{"server", "Starts a UDP server", udp_server},
{"send", "Send a UDP datagram", udp_send},
{"ign", "Ignore a node", rpl_udp_ignore},
{NULL, NULL, NULL}
};
int main(void)
{
puts("RPL router v"APP_VERSION);
/* start shell */
posix_open(uart0_handler_pid, 0);
net_if_set_src_address_mode(0, NET_IF_TRANS_ADDR_M_SHORT);
id = net_if_get_hardware_address(0);
shell_t shell;
shell_init(&shell, shell_commands, UART0_BUFSIZE, uart0_readc, uart0_putc);
shell_run(&shell);
return 0;
}

View File

@ -1,108 +0,0 @@
/*
* Copyright (C) 2014 Oliver Hahm <oliver.hahm@inria.fr>
*
* 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.
*/
#ifndef RPL_UDP_H
#define RPL_UDP_H
#ifdef __cplusplus
extern "C" {
#endif
#define APP_VERSION "1.2"
#define RADIO_CHANNEL (10)
#define MONITOR_STACK_SIZE (THREAD_STACKSIZE_MAIN)
#define RCV_BUFFER_SIZE (32)
/* RPL shell command handlers */
/**
* @brief Shell command to initializes RPL and UDP
*
* @details Usage: init <r|n>
* `init r` will initialize the node as a RPL root node,
* `init n` as a RPL node.
*
* @param[in] argc Argument count
* @param[in] argv Arguments
*/
int rpl_udp_init(int argc, char **argv);
/**
* @brief Shell command to set node's ID
*
* @details Usage: set <ID>
* Set the node address
*
* @param[in] argc Argument count
* @param[in] argv Arguments
*/
int rpl_udp_set_id(int argc, char **argv);
/**
* @brief Shows the dodag
*
* @details No parameters required
*
* @param[in] argc Argument count
* @param[in] argv Arguments
*/
int rpl_udp_dodag(int argc, char **argv);
/**
* @brief Command handler to start a UDP server
*
* @details No parameters required
*
* @param[in] argc Argument count
* @param[in] argv Arguments
*/
int udp_server(int argc, char **argv);
/**
* @brief Sends a UDP datagram
*
* @details Usage: send <ID> <TEXT>
* Sends TEXT to the node with IP address:
* fe80::ff:fe00:<ID>
*
* @param[in] argc Argument count
* @param[in] argv Arguments
*/
int udp_send(int argc, char **argv);
/**
* @brief Ignore a certain node
*
* @details Usage: ignore <ID>
* Ignore the node with IP address:
* fe80::ff:fe00:<ID>
*
* @param[in] argc Argument count
* @param[in] argv Arguments
*/
int rpl_udp_ignore(int argc, char **argv);
/**
* @brief monitoring thread start function
*
* @param arg Unused
*/
void *rpl_udp_monitor(void *arg);
/** @brief The nodes radio address */
extern radio_address_t id;
/** @brief Char array for IP address printing */
extern char addr_str[IPV6_MAX_ADDR_STR_LEN];
#ifdef __cplusplus
}
#endif
#endif /* RPL_UDP_H */

View File

@ -1,159 +0,0 @@
/*
* Copyright (C) 2013, 2014 INRIA
*
* 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 examples
* @{
*
* @file
* @brief UDP RPL example application
*
* @author Oliver Hahm <oliver.hahm@inria.fr>
*
* @}
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <inttypes.h>
#include "thread.h"
#include "socket_base/socket.h"
#include "net_help.h"
#include "rpl_udp.h"
#define UDP_BUFFER_SIZE (128)
#define SERVER_PORT (0xFF01)
static char udp_server_stack_buffer[THREAD_STACKSIZE_MAIN];
char addr_str[IPV6_MAX_ADDR_STR_LEN];
static void *init_udp_server(void *);
/* UDP server thread */
int udp_server(int argc, char **argv)
{
(void) argc;
(void) argv;
kernel_pid_t udp_server_thread_pid = thread_create(udp_server_stack_buffer,
sizeof(udp_server_stack_buffer),
THREAD_PRIORITY_MAIN, CREATE_STACKTEST,
init_udp_server,
NULL,
"init_udp_server");
printf("UDP SERVER ON PORT %d (THREAD PID: %" PRIkernel_pid ")\n", HTONS(SERVER_PORT), udp_server_thread_pid);
return 0;
}
static void *init_udp_server(void *arg)
{
(void) arg;
sockaddr6_t sa;
char buffer_main[UDP_BUFFER_SIZE];
uint32_t fromlen;
int sock = socket_base_socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
memset(&sa, 0, sizeof(sa));
sa.sin6_family = AF_INET;
sa.sin6_port = HTONS(SERVER_PORT);
fromlen = sizeof(sa);
if (-1 == socket_base_bind(sock, &sa, sizeof(sa))) {
printf("Error bind failed!\n");
socket_base_close(sock);
return NULL;
}
while (1) {
int32_t recsize = socket_base_recvfrom(sock, (void *)buffer_main, UDP_BUFFER_SIZE, 0, &sa, &fromlen);
if (recsize < 0) {
printf("ERROR: recsize < 0!\n");
}
printf("UDP packet received, payload: %s\n", buffer_main);
}
socket_base_close(sock);
return NULL;
}
/* UDP send command */
int udp_send(int argc, char **argv)
{
int sock, res;
sockaddr6_t sa;
ipv6_addr_t ipaddr;
int bytes_sent;
int address;
if (argc != 3) {
printf("usage: send <addr> <text>\n");
return 1;
}
/* max payload size = MTU - MAC - AES - IPV6_HDR_LEN - UDP_HDR_LEN
* 33 = 127 - 25 - 21 - 40 - 8
*/
if (strlen(argv[2]) > 32) {
puts("<text> is too large to be sent (max. 33 characters).");
return 1;
}
address = atoi(argv[1]);
sock = socket_base_socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
if (-1 == sock) {
printf("Error Creating Socket!");
return 1;
}
memset(&sa, 0, sizeof(sa));
if (address) {
ipv6_addr_init(&ipaddr, 0xabcd, 0x0, 0x0, 0x0, 0x0, 0x00ff, 0xfe00, (uint16_t)address);
}
else {
ipv6_addr_set_all_nodes_addr(&ipaddr);
}
sa.sin6_family = AF_INET;
memcpy(&sa.sin6_addr, &ipaddr, 16);
sa.sin6_port = HTONS(SERVER_PORT);
bytes_sent = socket_base_sendto(sock, argv[2],
strlen(argv[2]), 0, &sa,
sizeof(sa));
if (bytes_sent < 0) {
printf("Error sending packet!\n");
res = 1;
}
else {
printf("Successful deliverd %i bytes over UDP to %s to 6LoWPAN\n",
bytes_sent, ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN,
&ipaddr));
res = 0;
}
socket_base_close(sock);
return res;
}

View File

@ -1,40 +1,3 @@
ifneq (,$(filter nomac,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
endif
ifneq (,$(filter transport_layer,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
endif
ifneq (,$(filter socket_base,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
endif
ifneq (,$(filter tcp,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
endif
ifneq (,$(filter udp,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
endif
ifneq (,$(filter net_help,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/cc110x
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/cc110x_legacy_csma
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/cc110x_legacy/include
endif
ifneq (,$(filter net_if,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
endif
ifneq (,$(filter pktqueue,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
endif
ifneq (,$(filter protocol_multiplex,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
endif
ifneq (,$(filter sixlowpan,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
endif
ifneq (,$(filter rpl,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/routing/rpl
endif
ifneq (,$(filter nhdp,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/routing/nhdp
@ -42,16 +5,6 @@ endif
ifneq (,$(filter ieee802154,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
endif
ifneq (,$(filter l2_ping,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
endif
ifneq (,$(filter ccn_lite,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/ccn_lite
endif
ifneq (,$(filter ccn_lite_client,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
endif
ifneq (,$(filter crypto,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/include/crypto

View File

@ -1,11 +1,3 @@
ifneq (,$(filter net_if,$(USEMODULE)))
INCLUDES += -I$(RIOTBASE)/sys/net/include/
endif
ifneq (,$(filter nomac,$(USEMODULE)))
INCLUDES += -I$(RIOTBASE)/sys/net/include/
endif
DIRS += $(AUTO_INIT_MODULES)
ifneq (,$(filter auto_init_ng_netif,$(USEMODULE)))

View File

@ -32,10 +32,6 @@
#include "gpioint.h"
#endif
#ifdef MODULE_CC110X_LEGACY_CSMA
#include "cc110x_legacy_csma.h"
#endif
#ifdef MODULE_LTC4150
#include "ltc4150.h"
#endif
@ -56,33 +52,6 @@
#include "periph/rtc.h"
#endif
#ifdef MODULE_SIXLOWPAN
#include "sixlowpan.h"
#endif
#ifdef MODULE_UDP
#include "udp.h"
#endif
#ifdef MODULE_TCP
#include "tcp.h"
#endif
#ifdef MODULE_NOMAC
#include "nomac.h"
#endif
#ifdef MODULE_NET_IF
#include "cpu_conf.h"
#include "cpu.h"
#include "kernel.h"
#include "net_if.h"
#include "transceiver.h"
#include "net_help.h"
#include "hashes.h"
#include "periph/cpuid.h"
#endif
#ifdef MODULE_NG_SIXLOWPAN
#include "net/ng_sixlowpan.h"
#endif
@ -123,120 +92,6 @@
#define ENABLE_DEBUG (0)
#include "debug.h"
#ifndef CONF_RADIO_ADDR
#define CONF_RADIO_ADDR (1)
#endif
#ifndef CONF_PAN_ID
#define CONF_PAN_ID (0xabcd)
#endif
#ifdef MODULE_NET_IF
void auto_init_net_if(void)
{
transceiver_type_t transceivers = 0;
#ifdef MODULE_AT86RF231
transceivers |= TRANSCEIVER_AT86RF231;
#endif
#ifdef MODULE_CC1020
transceivers |= TRANSCEIVER_CC1020;
#endif
#if (defined(MODULE_CC110X) || defined(MODULE_CC110X_LEGACY) || defined(MODULE_CC110X_LEGACY_CSMA))
transceivers |= TRANSCEIVER_CC1100;
#endif
#ifdef MODULE_CC2420
transceivers |= TRANSCEIVER_CC2420;
#endif
#ifdef MODULE_MC1322X
transceivers |= TRANSCEIVER_MC1322X;
#endif
#ifdef MODULE_NATIVENET
transceivers |= TRANSCEIVER_NATIVE;
#endif
net_if_init();
if (transceivers != 0) {
#if CPUID_ID_LEN && defined(MODULE_HASHES)
uint8_t cpuid[CPUID_ID_LEN];
cpuid_get(cpuid);
#endif
transceiver_init(transceivers);
transceiver_start();
int iface = net_if_init_interface(0, transceivers);
#if CPUID_ID_LEN && defined(MODULE_HASHES)
net_if_eui64_t eui64;
uint32_t hash_h = djb2_hash(cpuid, CPUID_ID_LEN / 2);
#if CPUID_ID_LEN % 2 == 0
uint32_t hash_l = djb2_hash(&(cpuid[CPUID_ID_LEN / 2]),
CPUID_ID_LEN / 2);
#else /* CPUID_ID_LEN % 2 == 0 */
uint32_t hash_l = djb2_hash(&(cpuid[CPUID_ID_LEN / 2]),
CPUID_ID_LEN / 2 + 1);
#endif /* CPUID_ID_LEN % 2 == 0 */
eui64.uint32[1] = hash_l;
eui64.uint32[0] = hash_h;
/* Set Local/Universal bit to Local since this EUI64 is made up. */
eui64.uint8[0] |= 0x02;
net_if_set_eui64(iface, &eui64);
#if ENABLE_DEBUG
DEBUG("Auto init radio long address on interface %d to ", iface);
for (size_t i = 0; i < 8; i++) {
printf("%02x ", eui64.uint8[i]);
}
DEBUG("\n");
#endif /* ENABLE_DEBUG */
#undef CONF_RADIO_ADDR
#if (defined(MODULE_CC110X) || defined(MODULE_CC110X_LEGACY) || defined(MODULE_CC110X_LEGACY_CSMA))
uint8_t hwaddr = (uint8_t)((hash_l ^ hash_h) ^ ((hash_l ^ hash_h) >> 24));
/* do not combine more parts to keep the propability low that it just
* becomes 0xff */
#else
uint16_t hwaddr = HTONS((uint16_t)((hash_l ^ hash_h) ^ ((hash_l ^ hash_h) >> 16)));
#endif
net_if_set_hardware_address(iface, hwaddr);
DEBUG("Auto init radio address on interface %d to 0x%04x\n", iface, hwaddr);
#else /* CPUID_ID_LEN && defined(MODULE_HASHES) */
if (!net_if_get_hardware_address(iface)) {
DEBUG("Auto init radio address on interface %d to 0x%04x\n", iface, CONF_RADIO_ADDR);
DEBUG("Change this value at compile time with macro CONF_RADIO_ADDR\n");
net_if_set_hardware_address(iface, CONF_RADIO_ADDR);
}
#endif /* CPUID_ID_LEN && defined(MODULE_HASHES) */
if (net_if_set_src_address_mode(iface, NET_IF_TRANS_ADDR_M_SHORT)) {
DEBUG("Auto init source address mode to short on interface %d\n",
iface);
}
else {
net_if_set_src_address_mode(iface, NET_IF_TRANS_ADDR_M_LONG);
DEBUG("Auto init source address mode to long on interface %d\n",
iface);
}
if (net_if_get_pan_id(iface) <= 0) {
DEBUG("Auto init PAN ID on interface %d to 0x%04x\n", iface, CONF_PAN_ID);
DEBUG("Change this value at compile time with macro CONF_PAN_ID\n");
net_if_set_pan_id(iface, CONF_PAN_ID);
}
if (iface >= 0) {
DEBUG("Auto init interface %d\n", iface);
}
}
}
#endif /* MODULE_NET_IF */
void auto_init(void)
{
#ifdef MODULE_CONFIG
@ -266,12 +121,6 @@ void auto_init(void)
DEBUG("Auto init gpioint module.\n");
gpioint_init();
#endif
#ifdef MODULE_CC110X_LEGACY_CSMA
DEBUG("Auto init CC1100 module.\n");
#ifndef MODULE_TRANSCEIVER
cc1100_init();
#endif
#endif
#ifdef MODULE_LTC4150
DEBUG("Auto init ltc4150 module.\n");
ltc4150_init();
@ -280,35 +129,10 @@ void auto_init(void)
DEBUG("Auto init mci module.\n");
MCI_initialize();
#endif
#ifdef MODULE_L2_PING
DEBUG("Auto init net_if module.\n");
l2_ping_init();
#endif
#ifdef MODULE_NOMAC
DEBUG("Auto init nomac module.\n");
nomac_init_module();
#endif
#ifdef MODULE_NET_IF
DEBUG("Auto init net_if module.\n");
auto_init_net_if();
#endif
#ifdef MODULE_SIXLOWPAN
DEBUG("Auto init 6LoWPAN module.\n");
sixlowpan_lowpan_init();
#endif
#ifdef MODULE_PROFILING
extern void profiling_init(void);
profiling_init();
#endif
#ifdef MODULE_UDP
DEBUG("Auto init transport layer module: [udp].\n");
udp_init_transport_layer();
#endif
#ifdef MODULE_TCP
DEBUG("Auto init transport layer module: [tcp].\n");
tcp_init_transport_layer();
#endif
#ifdef MODULE_NG_PKTBUF
DEBUG("Auto init ng_pktbuf module\n");
ng_pktbuf_init();

View File

@ -1,58 +0,0 @@
/**
* Generic radio driver interface
*
* Copyright (C) 2008-2009 Freie Universitaet Berlin (FUB).
* Copyright (C) 2013 INRIA.
*
* 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.
*
*/
#ifndef RADIO_H_
#define RADIO_H_
/**
* @defgroup net_datalink Data link layer
* @ingroup net
*
* @brief Defines interface of data link layers for use with micro mesh stack.
*
* @{
*/
/**
* @file
* @brief
*
* @author baar
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
*
*/
#include <stdint.h>
#include <stdbool.h>
#include "radio/types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define L1_PROTOCOL_CATCH_ALL (0xff) /**< Catch all protocol ID */
/**
* @brief Link layer protocols (sic!) for proprietary cc110x protocol stack
*/
enum layer_1_protocols {
LAYER_1_PROTOCOL_LL_ACK = 1, /**< Link-Level Acknowledgement (LL-ACK) */
LAYER_1_PROTOCOL_MM = 2, /**< Micro Mesh network packet (MM) */
};
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* RADIO_H_ */

Some files were not shown because too many files have changed in this diff Show More