Skip to content

Commit

Permalink
Merge pull request #3716 from kaspar030/ng_cc110x
Browse files Browse the repository at this point in the history
drivers: add cc110x driver
  • Loading branch information
haukepetersen committed Sep 24, 2015
2 parents 5e2b4b6 + 63acf0b commit 7cb3f9b
Show file tree
Hide file tree
Showing 21 changed files with 2,281 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Makefile.dep
Expand Up @@ -36,6 +36,10 @@ ifneq (,$(filter at86rf2%,$(USEMODULE)))
USEMODULE += netif
endif

ifneq (,$(filter cc110x,$(USEMODULE)))
USEMODULE += ieee802154
endif

ifneq (,$(filter kw2xrf,$(USEMODULE)))
USEMODULE += ieee802154
USEMODULE += netif
Expand Down
4 changes: 4 additions & 0 deletions boards/msba2/Makefile.include
@@ -1,3 +1,7 @@
export INCLUDES += -I$(RIOTBOARD)/msba2/include

ifneq (,$(filter gnrc_netif_default,$(USEMODULE)))
USEMODULE += cc110x gnrc_netdev2 gnrc_cc110x
endif

include $(RIOTBOARD)/msba2-common/Makefile.include
44 changes: 44 additions & 0 deletions boards/msba2/include/cc110x_params.h
@@ -0,0 +1,44 @@
/*
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.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 board_msba2
* @{
*
* @file
* @brief cc110x board specific configuration
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
*/

#ifndef CC110X_PARAMS_H
#define CC110X_PARAMS_H

#ifdef __cplusplus
extern "C" {
#endif

/**
* @name CC110X configuration
*/
const cc110x_params_t cc110x_params[] = {
{
.spi = 0,
.cs = 53,
.gdo0 = 27,
.gdo1 = 55,
.gdo2 = 28
},
};
/** @} */

#ifdef __cplusplus
}
#endif
#endif /* CC110X_PARAMS_H */
/** @} */
3 changes: 3 additions & 0 deletions drivers/cc110x/Makefile
@@ -0,0 +1,3 @@
DIRS += gnrc_cc110x

include $(RIOTBASE)/Makefile.base
100 changes: 100 additions & 0 deletions drivers/cc110x/cc110x-defaultsettings.c
@@ -0,0 +1,100 @@
/*
* Copyright (C) 2013 INRIA
* 2015 Kaspar Schleiser <kaspar@schleiser.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 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>
* @author Kaspar Schleiser <kaspar@schleiser.de>
* @}
*/

#include "board.h"
#include "cc110x.h"

/**
* @brief PATABLE with available output powers
* @note If changed in size, adjust MAX_OUTPUT_POWER definition
* in CC110x interface
*/
const char cc110x_default_pa_table[8] = {
0x00, /*< -52 dBm */
0x0D, /*< -20 dBm */
0x34, /*< -10 dBm */
0x57, /*< - 5 dBm */
0x8E, /*< 0 dBm */
0x85, /*< + 5 dBm */
0xCC, /*< + 7 dBm */
0xC3 /*< +10 dBm */
};

const char cc110x_default_base_freq[3] = { 0x21, 0x71, 0x7F };

/**
* @brief cc110x default settings
*/
const char cc110x_default_conf[] = {
0x06, /* IOCFG2 */
0x2E, /* IOCFG1 */
/* some boards use cc110x' GDO0 as clock source, so for those, we allow
* overriding of the corresponding setting, e.g., in board.h */
#ifdef CC110X_IOCONF0_VAL
CC110X_IOCONF0_VAL,
#else
0x0E, /* IOCFG0 */
#endif
0x07, /* FIFOTHR */
0x9B, /* SYNC1 */
0xAD, /* SYNC0 */
0xFF, /* PKTLEN */
0x06, /* PKTCTRL1 */
0x45, /* PKTCTRL0 (variable packet length) */
0xFF, /* ADDR */
0x00, /* CHANNR */
0x0F, /* FSCTRL1 */
0x00, /* FSCTRL0 */
0x21, /* FREQ2 */
0x71, /* FREQ1 */
0x7A, /* FREQ0 */
0x7C, /* MDMCFG4 */
0x7A, /* MDMCFG3 */
0x06, /* MDMCFG2 */
0xC0, /* MDMCFG1 */
0xF8, /* MDMCFG0 */
0x44, /* DEVIATN */
0x07, /* MCSM2 */
0x03, /* MCSM1 */
0x18, /* MCSM0 */
0x16, /* FOCCFG */
0x6C, /* BSCFG */
0x45, /* AGCCTRL2 */
0x40, /* AGCCTRL1 */
0x91, /* AGCCTRL0 */
0x87, /* WOREVT1 */
0x6B, /* WOREVT0 */
0xF8, /* WORCTRL */
0x56, /* FREND1 */
0x17, /* FREND0 */
0xEA, /* FSCAL3 */
0x2A, /* FSCAL2 */
0x00, /* FSCAL1 */
0x1F, /* FSCAL0 */
0x00 /* padding to 4 bytes */
};

/**
* @brief The size of the configuration array for CC110X in bytes
* */
const uint8_t cc110x_default_conf_size = sizeof(cc110x_default_conf);
218 changes: 218 additions & 0 deletions drivers/cc110x/cc110x-netdev2.c
@@ -0,0 +1,218 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
* 2015 Kaspar Schleiser <kaspar@schleiser.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 drivers_cc110x
* @{
* @file
* @brief Implementation of netdev2 interface for cc110x
*
* @author Fabian Nack <nack@inf.fu-berlin.de>
* @author Kaspar Schleiser <kaspar@schleiser.de>
* @}
*/

#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include "cc110x.h"
#include "cc110x/cc110x-netdev2.h"
#include "cc110x/cc110x-internal.h"
#include "cc110x/cc110x-interface.h"
#include "net/eui64.h"

#include "periph/cpuid.h"
#include "periph/gpio.h"
#include "net/netdev2.h"
#include "net/gnrc/nettype.h"

#define ENABLE_DEBUG (0)
#include "debug.h"

static int _send(netdev2_t *dev, const struct iovec *vector, int count)
{
DEBUG("%s:%u\n", __func__, __LINE__);

netdev2_cc110x_t *netdev2_cc110x = (netdev2_cc110x_t*) dev;
cc110x_pkt_t *cc110x_pkt = vector[0].iov_base;

return cc110x_send(&netdev2_cc110x->cc110x, cc110x_pkt);
}

static int _recv(netdev2_t *dev, char* buf, int len)
{
DEBUG("%s:%u\n", __func__, __LINE__);

cc110x_t *cc110x = &((netdev2_cc110x_t*) dev)->cc110x;

cc110x_pkt_t *cc110x_pkt = &cc110x->pkt_buf.packet;
if (cc110x_pkt->length > len) {
return -ENOSPC;
}

memcpy(buf, (void*)cc110x_pkt, cc110x_pkt->length);
return cc110x_pkt->length;
}

static inline int _get_iid(netdev2_t *netdev, eui64_t *value, size_t max_len)
{
if (max_len < sizeof(eui64_t)) {
return -EOVERFLOW;
}

uint8_t *eui64 = (uint8_t*) value;
#ifdef CPUID_ID_LEN
int n = (CPUID_ID_LEN < sizeof(eui64_t))
? CPUID_ID_LEN
: sizeof(eui64_t);

char cpuid[CPUID_ID_LEN];
cpuid_get(cpuid);

memcpy(eui64 + 8 - n, cpuid, n);

#else
for (int i = 0; i < 8; i++) {
eui64[i] = i;
}
#endif

/* make sure we mark the address as non-multicast and not globally unique */
eui64[0] &= ~(0x01);
eui64[0] |= 0x02;

return sizeof(eui64_t);
}

static int _get(netdev2_t *dev, netopt_t opt, void *value, size_t value_len)
{
cc110x_t *cc110x = &((netdev2_cc110x_t*) dev)->cc110x;

switch (opt) {
case NETOPT_DEVICE_TYPE:
assert(value_len == 2);
*((uint16_t *) value) = NETDEV2_TYPE_CC110X;
return 2;
case NETOPT_PROTO:
assert(value_len == sizeof(gnrc_nettype_t));
#ifdef MODULE_GNRC_SIXLOWPAN
*((gnrc_nettype_t*)value) = GNRC_NETTYPE_SIXLOWPAN;
#else
*((gnrc_nettype_t*)value) = GNRC_NETTYPE_UNDEF;
#endif
return sizeof(gnrc_nettype_t);
case NETOPT_CHANNEL:
assert(value_len > 1);
*((uint16_t *)value) = (uint16_t)cc110x->radio_channel;
return 2;
case NETOPT_ADDRESS:
assert(value_len > 0);
*((uint8_t *)value) = cc110x->radio_address;
return 1;
case NETOPT_MAX_PACKET_SIZE:
assert(value_len > 0);
*((uint8_t *)value) = CC110X_PACKET_LENGTH;
return 1;
case NETOPT_IPV6_IID:
return _get_iid(dev, value, value_len);
default:
break;
}

return -ENOTSUP;
}

static int _set(netdev2_t *dev, netopt_t opt, void *value, size_t value_len)
{
cc110x_t *cc110x = &((netdev2_cc110x_t*) dev)->cc110x;

switch (opt) {
case NETOPT_CHANNEL:
{
uint8_t *arg = (uint8_t*)value;
uint8_t channel = arg[value_len-1];
if ((channel < CC110X_MIN_CHANNR) || (channel > CC110X_MAX_CHANNR)) {
return -EINVAL;
}
if (cc110x_set_channel(cc110x, channel) == -1) {
return -EINVAL;
}
return 1;
}
case NETOPT_ADDRESS:
if (value_len < 1) {
return -EINVAL;
}
if (!cc110x_set_address(cc110x, *(uint8_t*)value)) {
return -EINVAL;
}
return 1;
default:
return -ENOTSUP;
}

return 0;
}

static void _netdev2_cc110x_isr(void *arg)
{
netdev2_t *netdev2 = (netdev2_t*) arg;
netdev2->event_callback(netdev2, NETDEV2_EVENT_ISR, netdev2->isr_arg);
}

static void _netdev2_cc110x_rx_callback(void *arg)
{
netdev2_t *netdev2 = (netdev2_t*) arg;
cc110x_t *cc110x = &((netdev2_cc110x_t*) arg)->cc110x;
gpio_irq_disable(cc110x->params.gdo2);
netdev2->event_callback(netdev2, NETDEV2_EVENT_RX_COMPLETE, netdev2->isr_arg);
}

static void _isr(netdev2_t *dev)
{
cc110x_t *cc110x = &((netdev2_cc110x_t*) dev)->cc110x;
cc110x_isr_handler(cc110x, _netdev2_cc110x_rx_callback, (void*)dev);
}

static int _init(netdev2_t *dev)
{
DEBUG("%s:%u\n", __func__, __LINE__);

cc110x_t *cc110x = &((netdev2_cc110x_t*) dev)->cc110x;

gpio_init_int(cc110x->params.gdo2, GPIO_NOPULL, GPIO_BOTH,
&_netdev2_cc110x_isr, (void*)dev);

gpio_set(cc110x->params.gdo2);
gpio_irq_disable(cc110x->params.gdo2);

/* Switch to RX mode */
cc110x_rd_set_mode(cc110x, RADIO_MODE_ON);

return 0;
}

const netdev2_driver_t netdev2_cc110x_driver = {
.send=_send,
.recv=_recv,
.init=_init,
.get=_get,
.set=_set,
.isr=_isr
};

int netdev2_cc110x_setup(netdev2_cc110x_t *netdev2_cc110x, const cc110x_params_t *params)
{
DEBUG("netdev2_cc110x_setup()\n");
netdev2_cc110x->netdev.driver = &netdev2_cc110x_driver;

return cc110x_setup(&netdev2_cc110x->cc110x, params);
}

0 comments on commit 7cb3f9b

Please sign in to comment.