From 57e54e254dbda1c0a4a8fd88eb37bbec33c2b1d0 Mon Sep 17 00:00:00 2001 From: Fabian Nack Date: Tue, 7 Oct 2014 10:31:05 +0200 Subject: [PATCH 1/3] drivers - netdev: extend netdev_state_t enum --- drivers/include/netdev/base.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/include/netdev/base.h b/drivers/include/netdev/base.h index 1981b9ad24a0..8e423b4e81b1 100644 --- a/drivers/include/netdev/base.h +++ b/drivers/include/netdev/base.h @@ -134,6 +134,8 @@ typedef enum { 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; /** From eebfd5011a54db0d0cd2b0ea5efa8f9b0c6cfbcc Mon Sep 17 00:00:00 2001 From: Fabian Nack Date: Tue, 23 Sep 2014 01:30:37 +0200 Subject: [PATCH 2/3] drivers - cc110x: Initial import of new cc110x driver --- Makefile.dep | 4 + drivers/Makefile.include | 3 + drivers/cc110x/Makefile | 1 + drivers/cc110x/cc110x-defaultsettings.c | 133 ++++++ drivers/cc110x/cc110x-internal.h | 207 +++++++++ drivers/cc110x/cc110x-netdev.c | 253 +++++++++++ drivers/cc110x/cc110x-rxtx.c | 245 +++++++++++ drivers/cc110x/cc110x-spi.c | 129 ++++++ drivers/cc110x/cc110x.c | 397 ++++++++++++++++++ drivers/include/cc110x.h | 26 ++ drivers/include/cc110x/cc110x-config.h | 106 +++++ .../include/cc110x/cc110x-defaultsettings.h | 58 +++ drivers/include/cc110x/cc110x-interface.h | 160 +++++++ drivers/include/cc110x/cc110x-netdev.h | 42 ++ drivers/include/cc110x/cc110x-reg.h | 93 ++++ drivers/include/netdev/base.h | 7 + drivers/include/netdev/default.h | 8 + examples/rpl_udp/helper.c | 2 +- examples/rpl_udp/rpl.c | 2 +- sys/Makefile.include | 1 + sys/auto_init/auto_init.c | 4 +- sys/include/transceiver.h | 9 +- sys/net/network_layer/sixlowpan/mac.c | 2 +- sys/shell/commands/sc_net_if.c | 2 +- sys/shell/commands/sc_transceiver.c | 5 + sys/shell/commands/shell_commands.c | 2 +- sys/transceiver/transceiver.c | 30 +- tests/netdev/main.c | 4 + 28 files changed, 1914 insertions(+), 21 deletions(-) create mode 100644 drivers/cc110x/Makefile create mode 100644 drivers/cc110x/cc110x-defaultsettings.c create mode 100644 drivers/cc110x/cc110x-internal.h create mode 100644 drivers/cc110x/cc110x-netdev.c create mode 100644 drivers/cc110x/cc110x-rxtx.c create mode 100644 drivers/cc110x/cc110x-spi.c create mode 100644 drivers/cc110x/cc110x.c create mode 100644 drivers/include/cc110x.h create mode 100644 drivers/include/cc110x/cc110x-config.h create mode 100644 drivers/include/cc110x/cc110x-defaultsettings.h create mode 100644 drivers/include/cc110x/cc110x-interface.h create mode 100644 drivers/include/cc110x/cc110x-netdev.h create mode 100644 drivers/include/cc110x/cc110x-reg.h diff --git a/Makefile.dep b/Makefile.dep index 63a105a39a9c..62f4eb5f410d 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -72,6 +72,10 @@ ifneq (,$(filter cc110x%,$(USEMODULE))) USEMODULE += vtimer endif +ifneq (,$(filter cc110x,$(USEMODULE))) + USEMODULE += transceiver +endif + ifneq (,$(filter cc110x_legacy,$(USEMODULE))) USEMODULE += transceiver endif diff --git a/drivers/Makefile.include b/drivers/Makefile.include index 7df51fbdf2da..aa0ea0140506 100644 --- a/drivers/Makefile.include +++ b/drivers/Makefile.include @@ -1,6 +1,9 @@ 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 diff --git a/drivers/cc110x/Makefile b/drivers/cc110x/Makefile new file mode 100644 index 000000000000..48422e909a47 --- /dev/null +++ b/drivers/cc110x/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/drivers/cc110x/cc110x-defaultsettings.c b/drivers/cc110x/cc110x-defaultsettings.c new file mode 100644 index 000000000000..cc0a1b2c2c0a --- /dev/null +++ b/drivers/cc110x/cc110x-defaultsettings.c @@ -0,0 +1,133 @@ +/* + * 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 + * @author Heiko Will + * @author Oliver Hahm + * @} + */ + +#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 */ +}; diff --git a/drivers/cc110x/cc110x-internal.h b/drivers/cc110x/cc110x-internal.h new file mode 100644 index 000000000000..ad04f3bbe72b --- /dev/null +++ b/drivers/cc110x/cc110x-internal.h @@ -0,0 +1,207 @@ +/* + * 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 cc110x-internal.h + * @brief Driver internal constants for CC110x chip configuration + * + * @author Thomas Hillebrandt + * @author Heiko Will + * @author Oliver Hahm + */ + +#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 diff --git a/drivers/cc110x/cc110x-netdev.c b/drivers/cc110x/cc110x-netdev.c new file mode 100644 index 000000000000..448e4dc4e4f3 --- /dev/null +++ b/drivers/cc110x/cc110x-netdev.c @@ -0,0 +1,253 @@ +/* + * 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 cc110x_netdev.c + * @brief Functionality for netdev base interface + * + * @author Fabian Nack + * @} + */ +#include +#include +#include + +#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 */ diff --git a/drivers/cc110x/cc110x-rxtx.c b/drivers/cc110x/cc110x-rxtx.c new file mode 100644 index 000000000000..d5588b70d74a --- /dev/null +++ b/drivers/cc110x/cc110x-rxtx.c @@ -0,0 +1,245 @@ +/* + * 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 cc110x-rx.c + * @brief Functions for packet reception and transmission on cc110x devices + * + * @author Oliver Hahm + * @author Fabian Nack + * @} + */ +#include + +#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]; + uint8_t packetLength = 0; + uint8_t crc_ok = 0; + + /* Any bytes available in RX FIFO? */ + if ((cc110x_read_status(CC1100_RXBYTES) & BYTES_IN_RXFIFO)) { + /* 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) { + /* 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; +} diff --git a/drivers/cc110x/cc110x-spi.c b/drivers/cc110x/cc110x-spi.c new file mode 100644 index 000000000000..cddb33161b03 --- /dev/null +++ b/drivers/cc110x/cc110x-spi.c @@ -0,0 +1,129 @@ +/* + * 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 cc110x_spi.c + * @brief TI Chipcon CC110x SPI driver + * + * @author Thomas Hillebrandt + * @author Heiko Will + * @author Fabian Nack + * @} + */ + +#include + +#include "cc110x.h" +#include "cc110x-internal.h" + +#include "periph/gpio.h" +#include "periph/spi.h" + +#include "hwtimer.h" +#include "irq.h" + +/********************************************************************** + * CC110x SPI access + **********************************************************************/ + +void cc110x_cs(void) +{ + volatile int retry_count = 0; + /* Switch MISO/GDO1 to GPIO input mode */ + gpio_init_in(CC110X_GDO1, GPIO_NOPULL); + /* CS to low */ + gpio_clear(CC110X_CS); + /* Wait for SO to go low (voltage regulator + * has stabilized and the crystal is running) */ + while (gpio_read(CC110X_GDO1)) { + /* Wait ~500us and try again */ + hwtimer_wait(CS_SO_WAIT_TIME); + + if (gpio_read(CC110X_GDO1)) { + retry_count++; + + if (retry_count > CC1100_GDO1_LOW_RETRY) { + puts("[CC1100 SPI] fatal error\n"); + break; + } + + gpio_set(CC110X_CS); + gpio_clear(CC110X_CS); + } + } + /* Switch MISO/GDO1 to SPI mode */ + spi_conf_pins(CC110X_SPI); +} + +void cc110x_writeburst_reg(uint8_t addr, char *src, uint8_t count) +{ + unsigned int cpsr = disableIRQ(); + cc110x_cs(); + spi_transfer_regs(CC110X_SPI, addr | CC1100_WRITE_BURST, src, 0, count); + gpio_set(CC110X_CS); + restoreIRQ(cpsr); +} + +void cc110x_readburst_reg(uint8_t addr, char *buffer, uint8_t count) +{ + int i = 0; + unsigned int cpsr = disableIRQ(); + cc110x_cs(); + spi_transfer_byte(CC110X_SPI, addr | CC1100_READ_BURST, 0); + while (i < count) { + spi_transfer_byte(CC110X_SPI, CC1100_NOBYTE, &buffer[i]); + i++; + } + gpio_set(CC110X_CS); + restoreIRQ(cpsr); +} + +void cc110x_write_reg(uint8_t addr, uint8_t value) +{ + unsigned int cpsr = disableIRQ(); + cc110x_cs(); + spi_transfer_reg(CC110X_SPI, addr, value, 0); + gpio_set(CC110X_CS); + restoreIRQ(cpsr); +} + +uint8_t cc110x_read_reg(uint8_t addr) +{ + char result; + unsigned int cpsr = disableIRQ(); + cc110x_cs(); + spi_transfer_reg(CC110X_SPI, addr | CC1100_READ_SINGLE, CC1100_NOBYTE, &result); + gpio_set(CC110X_CS); + restoreIRQ(cpsr); + return (uint8_t) result; +} + +uint8_t cc110x_read_status(uint8_t addr) +{ + char result; + unsigned int cpsr = disableIRQ(); + cc110x_cs(); + spi_transfer_reg(CC110X_SPI, addr | CC1100_READ_BURST, CC1100_NOBYTE, &result); + gpio_set(CC110X_CS); + restoreIRQ(cpsr); + return (uint8_t) result; +} + +uint8_t cc110x_strobe(uint8_t c) +{ + char result; + unsigned int cpsr = disableIRQ(); + cc110x_cs(); + spi_transfer_byte(CC110X_SPI, c, &result); + gpio_set(CC110X_CS); + restoreIRQ(cpsr); + return (uint8_t) result; +} diff --git a/drivers/cc110x/cc110x.c b/drivers/cc110x/cc110x.c new file mode 100644 index 000000000000..671da45f877e --- /dev/null +++ b/drivers/cc110x/cc110x.c @@ -0,0 +1,397 @@ +/* + * 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 cc110x.c + * @brief Basic functionality of cc110x driver + * + * @author Oliver Hahm + * @author Fabian Nack + * @} + */ +#include "cc110x.h" +#include "cc110x-internal.h" + +#include "periph/gpio.h" +#include "periph/spi.h" +#include "hwtimer.h" +#include "config.h" +#include "cpu.h" +#include "netdev/base.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +/* 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); + +/* External variables */ +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; /* Statistic values for debugging */ + +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 */ + +/*---------------------------------------------------------------------------* + * Radio Driver API * + *---------------------------------------------------------------------------*/ +#ifdef MODULE_TRANSCEIVER +void cc110x_init(kernel_pid_t tpid) +{ + transceiver_pid = tpid; + DEBUG("Transceiver PID: %" PRIkernel_pid "\n", transceiver_pid); + cc110x_initialize(NULL); /* TODO */ +} +#endif + +int cc110x_initialize(netdev_t *dev) +{ + rx_buffer_next = 0; + + /* Configure chip-select */ + gpio_init_out(CC110X_CS, GPIO_NOPULL); + gpio_set(CC110X_CS); + /* Configure GDO0, GDO1, GDO2 */ + gpio_init_in(CC110X_GDO0, GPIO_NOPULL); + gpio_init_in(CC110X_GDO1, GPIO_NOPULL); + gpio_init_int(CC110X_GDO2, GPIO_NOPULL, GPIO_FALLING, &cc110x_rx_handler, 0); + gpio_irq_disable(CC110X_GDO2); + + /* Configure SPI */ + spi_poweron(CC110X_SPI); + spi_init_master(CC110X_SPI, SPI_CONF_FIRST_RISING, SPI_SPEED_5MHZ); + + /* 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 = 0; + rflags._LQI = 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 RX mode */ + rd_set_mode(RADIO_MODE_ON); + + return 0; +} + +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("CC110x 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 */ + cc110x_wakeup_from_rx(); + + /* Have to put radio back to RX if old radio state + * was RX, otherwise no action is necessary */ + if (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_IDLE: + return "IDLE"; + + case RADIO_SEND_BURST: + return "TX BURST"; + + case RADIO_RX: + return "RX"; + + 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] switching to powerdown\n"); + cc110x_wakeup_from_rx(); + cc110x_strobe(CC1100_SPWD); + radio_state = RADIO_PWD; +} + +/*---------------------------------------------------------------------------*/ +int16_t cc110x_set_channel(uint8_t channr) +{ + if (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(); + cc110x_cs(); + cc110x_strobe(CC1100_SRES); + hwtimer_wait(RTIMER_TICKS(100)); +} + +static void power_up_reset(void) +{ + gpio_set(CC110X_CS); + gpio_clear(CC110X_CS); + gpio_set(CC110X_CS); + 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 RX (no effect if in other mode) */ + cc110x_wakeup_from_rx(); + cc110x_write_reg(r, value); + + /* Have to put radio back to RX if old radio state + * was RX, otherwise no action is necessary */ + if (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"); + gpio_irq_enable(CC110X_GDO2); + cc110x_setup_rx_mode(); /* Set chip to desired mode */ + break; + + case RADIO_MODE_OFF: + gpio_irq_disable(CC110X_GDO2); /* 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; +} diff --git a/drivers/include/cc110x.h b/drivers/include/cc110x.h new file mode 100644 index 000000000000..9843c5d2cfc7 --- /dev/null +++ b/drivers/include/cc110x.h @@ -0,0 +1,26 @@ +/* + * 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 */ diff --git a/drivers/include/cc110x/cc110x-config.h b/drivers/include/cc110x/cc110x-config.h new file mode 100644 index 000000000000..d73b970cd045 --- /dev/null +++ b/drivers/include/cc110x/cc110x-config.h @@ -0,0 +1,106 @@ +/* + * 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 cc110x-config.h + * @brief Configuration parameters for the cc110x radio chip + * + * @author Oliver Hahm + * @author Fabian Nack + */ + +#ifndef CC110X_CONFIG_H +#define CC110X_CONFIG_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief CC110x 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; + +/** + * @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 */ diff --git a/drivers/include/cc110x/cc110x-defaultsettings.h b/drivers/include/cc110x/cc110x-defaultsettings.h new file mode 100644 index 000000000000..2533bbbc360f --- /dev/null +++ b/drivers/include/cc110x/cc110x-defaultsettings.h @@ -0,0 +1,58 @@ +/* + * 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 + * @author Heiko Will + * @author Fabian Nack + */ + +#ifndef CC110X_DEFAULTSETTINGS_H +#define CC110X_DEFAULTSETTINGS_H + +#include + +#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 */ diff --git a/drivers/include/cc110x/cc110x-interface.h b/drivers/include/cc110x/cc110x-interface.h new file mode 100644 index 000000000000..4228f741c4ed --- /dev/null +++ b/drivers/include/cc110x/cc110x-interface.h @@ -0,0 +1,160 @@ +/* + * 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 cc110x-interface.h + * @brief Data structures and variables for the cc110x driver interface + * + * @author Oliver Hahm + */ + +#ifndef CC110X_INTERFACE_H +#define CC110X_INTERFACE_H + +#include +#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 + * + *
+---------------------------------------------------
+|        |         |         |       |            |
+| 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
+
+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 */ diff --git a/drivers/include/cc110x/cc110x-netdev.h b/drivers/include/cc110x/cc110x-netdev.h new file mode 100644 index 000000000000..c4659ecc7e5a --- /dev/null +++ b/drivers/include/cc110x/cc110x-netdev.h @@ -0,0 +1,42 @@ +/* + * 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 cc110x-netdev.h + * @brief Variables for the cc110x netdev base interface + * + * @author Fabian Nack + */ + +#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 */ diff --git a/drivers/include/cc110x/cc110x-reg.h b/drivers/include/cc110x/cc110x-reg.h new file mode 100644 index 000000000000..213f8622fb83 --- /dev/null +++ b/drivers/include/cc110x/cc110x-reg.h @@ -0,0 +1,93 @@ +/* + * 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 cc110x-reg.h + * @brief Access to CC110X registers + * + * @author Oliver Hahm + * @author Fabian Nack + */ + +#ifndef CC110X_REG_H +#define CC110X_REG_H + +#include + +#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 */ diff --git a/drivers/include/netdev/base.h b/drivers/include/netdev/base.h index 8e423b4e81b1..00ad58981839 100644 --- a/drivers/include/netdev/base.h +++ b/drivers/include/netdev/base.h @@ -75,6 +75,13 @@ typedef enum { 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; /** diff --git a/drivers/include/netdev/default.h b/drivers/include/netdev/default.h index 0d525af9ba3c..e56c27c4deef 100644 --- a/drivers/include/netdev/default.h +++ b/drivers/include/netdev/default.h @@ -35,6 +35,14 @@ #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" diff --git a/examples/rpl_udp/helper.c b/examples/rpl_udp/helper.c index a0cf2eaf0434..5860bd9c72db 100644 --- a/examples/rpl_udp/helper.c +++ b/examples/rpl_udp/helper.c @@ -43,7 +43,7 @@ void rpl_udp_set_id(int argc, char **argv) { if (argc != 2) { printf("Usage: %s address\n", argv[0]); -#if defined(MODULE_CC110X_LEGACY_CSMA) || defined(MODULE_CC110X_LEGACY) +#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"); diff --git a/examples/rpl_udp/rpl.c b/examples/rpl_udp/rpl.c index 2ac642ea8294..5aca75c33b04 100644 --- a/examples/rpl_udp/rpl.c +++ b/examples/rpl_udp/rpl.c @@ -60,7 +60,7 @@ void rpl_udp_init(int argc, char **argv) ((command == 'h') ? "non-" : ""), (((command == 'n') || (command == 'h')) ? "node" : "root"), id); -#if defined(MODULE_CC110X_LEGACY_CSMA) || defined(MODULE_CC110X_LEGACY) +#if (defined(MODULE_CC110X) || defined(MODULE_CC110X_LEGACY) || defined(MODULE_CC110X_LEGACY_CSMA)) if (!id || (id > 255)) { printf("ERROR: address not a valid 8 bit integer\n"); return; diff --git a/sys/Makefile.include b/sys/Makefile.include index b245a40fca1a..f8e258699cdd 100644 --- a/sys/Makefile.include +++ b/sys/Makefile.include @@ -15,6 +15,7 @@ ifneq (,$(filter netapi,$(USEMODULE))) 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 diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c index e4272b8be877..3c1943d9c82c 100644 --- a/sys/auto_init/auto_init.c +++ b/sys/auto_init/auto_init.c @@ -102,7 +102,7 @@ void auto_init_net_if(void) #ifdef MODULE_CC1020 transceivers |= TRANSCEIVER_CC1020; #endif -#if MODULE_CC110X_LEGACY_CSMA || MODULE_CC110X_LEGACY +#if (defined(MODULE_CC110X) || defined(MODULE_CC110X_LEGACY) || defined(MODULE_CC110X_LEGACY_CSMA)) transceivers |= TRANSCEIVER_CC1100; #endif #ifdef MODULE_CC2420 @@ -152,7 +152,7 @@ void auto_init_net_if(void) #endif /* DEBUG_ENABLED */ #undef CONF_RADIO_ADDR -#if defined(MODULE_CC110X_LEGACY_CSMA) || defined(MODULE_CC110X_LEGACY) +#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 */ diff --git a/sys/include/transceiver.h b/sys/include/transceiver.h index 22291c1cd4a1..b6d7f7066da6 100644 --- a/sys/include/transceiver.h +++ b/sys/include/transceiver.h @@ -25,6 +25,13 @@ /* supported transceivers * * NOTE: necessary to include here again due to * https://github.com/RIOT-OS/RIOT/issues/117 */ +#ifdef MODULE_CC110X +#include "cc110x.h" +#ifndef TRANSCEIVER_DEFAULT +#define TRANSCEIVER_DEFAULT TRANSCEIVER_CC1100 +#endif +#endif + #ifdef MODULE_CC110X_LEGACY_CSMA #include "cc110x_legacy_csma.h" #ifndef TRANSCEIVER_DEFAULT @@ -95,7 +102,7 @@ extern "C" { #define PAYLOAD_SIZE (CC1100_MAX_DATA_LENGTH) #endif #endif -#ifdef MODULE_CC110X_LEGACY +#if (defined(MODULE_CC110X) || defined(MODULE_CC110X_LEGACY)) #if (CC1100_MAX_DATA_LENGTH > PAYLOAD_SIZE) #undef PAYLOAD_SIZE #define PAYLOAD_SIZE (CC1100_MAX_DATA_LENGTH) diff --git a/sys/net/network_layer/sixlowpan/mac.c b/sys/net/network_layer/sixlowpan/mac.c index 13bea67edd8f..83ed79bea434 100644 --- a/sys/net/network_layer/sixlowpan/mac.c +++ b/sys/net/network_layer/sixlowpan/mac.c @@ -256,7 +256,7 @@ int sixlowpan_mac_prepare_ieee802144_frame( ieee802154_frame_init(frame, (uint8_t *)&lowpan_mac_buf); memcpy(&lowpan_mac_buf[hdrlen], frame->payload, frame->payload_len); /* set FCS */ -#ifdef MODULE_CC110X_LEGACY +#if (defined(MODULE_CC110X) || defined(MODULE_CC110X_LEGACY)) fcs = (uint16_t *)&lowpan_mac_buf[frame->payload_len + hdrlen+1]; #else fcs = (uint16_t *)&lowpan_mac_buf[frame->payload_len + hdrlen]; diff --git a/sys/shell/commands/sc_net_if.c b/sys/shell/commands/sc_net_if.c index 4034abb0c24c..2210bdc4339d 100644 --- a/sys/shell/commands/sc_net_if.c +++ b/sys/shell/commands/sc_net_if.c @@ -126,7 +126,7 @@ void create_usage(void) #ifdef MODULE_CC1020 " * cc1020\n" #endif -#if MODULE_CC110X_LEGACY_CSMA || MODULE_CC110X_LEGACY +#if MODULE_CC110X || MODULE_CC110X_LEGACY || MODULE_CC110X_LEGACY_CSMA " * cc1100\n" #endif #ifdef MODULE_CC2420 diff --git a/sys/shell/commands/sc_transceiver.c b/sys/shell/commands/sc_transceiver.c index 5fa95f534f4a..f1ab72ad7fd5 100644 --- a/sys/shell/commands/sc_transceiver.c +++ b/sys/shell/commands/sc_transceiver.c @@ -37,6 +37,11 @@ #define TEXT_SIZE CC1100_MAX_DATA_LENGTH #define _TC_TYPE TRANSCEIVER_CC1100 +#elif defined( MODULE_CC110X ) +#include "cc110x.h" +#define TEXT_SIZE CC1100_MAX_DATA_LENGTH +#define _TC_TYPE TRANSCEIVER_CC1100 + #elif defined( MODULE_CC2420 ) #include "cc2420.h" #include "ieee802154_frame.h" diff --git a/sys/shell/commands/shell_commands.c b/sys/shell/commands/shell_commands.c index 6173eead2008..6955295647eb 100644 --- a/sys/shell/commands/shell_commands.c +++ b/sys/shell/commands/shell_commands.c @@ -83,7 +83,7 @@ extern void _x86_lspci(int argc, char **argv); #ifdef DBG_IGNORE #define _TC_IGN #endif -#if (defined(MODULE_CC110X_LEGACY) || defined(MODULE_CC2420) || defined(MODULE_AT86RF231) || defined(MODULE_NATIVENET)) +#if (defined(MODULE_CC110X) || defined(MODULE_CC110X_LEGACY) || defined(MODULE_CC2420) || defined(MODULE_AT86RF231) || defined(MODULE_NATIVENET)) #define _TC_ADDR #define _TC_CHAN #define _TC_MON diff --git a/sys/transceiver/transceiver.c b/sys/transceiver/transceiver.c index 488011dfdd16..ed9915178702 100644 --- a/sys/transceiver/transceiver.c +++ b/sys/transceiver/transceiver.c @@ -30,6 +30,10 @@ #include "transceiver.h" /* supported transceivers */ +#ifdef MODULE_CC110X +#include "cc110x.h" +#endif + #ifdef MODULE_CC110X_LEGACY_CSMA #include "cc110x_legacy_csma.h" #endif @@ -108,7 +112,7 @@ char transceiver_stack[TRANSCEIVER_STACK_SIZE]; /* function prototypes */ static void *run(void *arg); static void receive_packet(uint16_t type, uint8_t pos); -#ifdef MODULE_CC110X_LEGACY +#if (defined(MODULE_CC110X) || defined(MODULE_CC110X_LEGACY)) static void receive_cc110x_packet(radio_packet_t *trans_p); #endif #ifdef MODULE_CC110X_LEGACY_CSMA @@ -189,7 +193,7 @@ kernel_pid_t transceiver_start(void) puts("Error creating transceiver thread"); } -#ifdef MODULE_CC110X_LEGACY +#if (defined(MODULE_CC110X) || defined(MODULE_CC110X_LEGACY)) else if (transceivers & TRANSCEIVER_CC1100) { DEBUG("transceiver: Transceiver started for CC1100\n"); cc110x_init(transceiver_pid); @@ -443,7 +447,7 @@ static void receive_packet(uint16_t type, uint8_t pos) /* pass a null pointer if a packet from a undefined transceiver is * received */ if (type == RCV_PKT_CC1100) { -#ifdef MODULE_CC110X_LEGACY +#if (defined(MODULE_CC110X) || defined(MODULE_CC110X_LEGACY)) radio_packet_t *trans_p = &(transceiver_buffer[transceiver_buffer_pos]); receive_cc110x_packet(trans_p); #elif MODULE_CC110X_LEGACY_CSMA @@ -528,7 +532,7 @@ static void receive_packet(uint16_t type, uint8_t pos) } } -#ifdef MODULE_CC110X_LEGACY +#if (defined(MODULE_CC110X) || defined(MODULE_CC110X_LEGACY)) /* * @brief process packets from CC1100 * @@ -741,7 +745,7 @@ static int8_t send_packet(transceiver_type_t t, void *pkt) DEBUG("\n"); #endif -#ifdef MODULE_CC110X_LEGACY +#if (defined(MODULE_CC110X) || defined(MODULE_CC110X_LEGACY)) cc110x_packet_t cc110x_pkt; #endif #ifdef MODULE_MC1322X @@ -758,7 +762,7 @@ static int8_t send_packet(transceiver_type_t t, void *pkt) switch (t) { case TRANSCEIVER_CC1100: -#ifdef MODULE_CC110X_LEGACY +#if (defined(MODULE_CC110X) || defined(MODULE_CC110X_LEGACY)) cc110x_pkt.length = p->length + CC1100_HEADER_LENGTH; cc110x_pkt.address = p->dst; cc110x_pkt.flags = 0; @@ -830,7 +834,7 @@ static int32_t set_channel(transceiver_type_t t, void *channel) switch (t) { case TRANSCEIVER_CC1100: -#ifdef MODULE_CC110X_LEGACY +#if (defined(MODULE_CC110X) || defined(MODULE_CC110X_LEGACY)) return cc110x_set_channel(c); #elif MODULE_CC110X_LEGACY_CSMA return cc1100_set_channel(c); @@ -875,7 +879,7 @@ static int32_t get_channel(transceiver_type_t t) { switch (t) { case TRANSCEIVER_CC1100: -#ifdef MODULE_CC110X_LEGACY +#if (defined(MODULE_CC110X) || defined(MODULE_CC110X_LEGACY)) return cc110x_get_channel(); #elif MODULE_CC110X_LEGACY_CSMA return cc1100_get_channel(); @@ -1000,7 +1004,7 @@ static radio_address_t get_address(transceiver_type_t t) { switch (t) { case TRANSCEIVER_CC1100: -#ifdef MODULE_CC110X_LEGACY +#if (defined(MODULE_CC110X) || defined(MODULE_CC110X_LEGACY)) return cc110x_get_address(); #elif MODULE_CC110X_LEGACY_CSMA return cc1100_get_address(); @@ -1051,7 +1055,7 @@ static radio_address_t set_address(transceiver_type_t t, void *address) switch (t) { case TRANSCEIVER_CC1100: -#ifdef MODULE_CC110X_LEGACY +#if (defined(MODULE_CC110X) || defined(MODULE_CC110X_LEGACY)) return cc110x_set_address(addr); #elif MODULE_CC110X_LEGACY_CSMA return cc1100_set_address(addr); @@ -1151,7 +1155,7 @@ static void set_monitor(transceiver_type_t t, void *mode) (void) mode; switch (t) { -#ifdef MODULE_CC110X_LEGACY +#if (defined(MODULE_CC110X) || defined(MODULE_CC110X_LEGACY)) case TRANSCEIVER_CC1100: cc110x_set_monitor(*((uint8_t *)mode)); @@ -1196,7 +1200,7 @@ void cc1100_packet_monitor(void *payload, int payload_size, protocol_t protocol, static void powerdown(transceiver_type_t t) { switch (t) { -#ifdef MODULE_CC110X_LEGACY +#if (defined(MODULE_CC110X) || defined(MODULE_CC110X_LEGACY)) case TRANSCEIVER_CC1100: cc110x_switch_to_pwd(); @@ -1224,7 +1228,7 @@ static void powerdown(transceiver_type_t t) static void switch_to_rx(transceiver_type_t t) { switch (t) { -#ifdef MODULE_CC110X_LEGACY +#if (defined(MODULE_CC110X) || defined(MODULE_CC110X_LEGACY)) case TRANSCEIVER_CC1100: cc110x_switch_to_rx(); diff --git a/tests/netdev/main.c b/tests/netdev/main.c index 69e1d709156c..3d1b4758f712 100644 --- a/tests/netdev/main.c +++ b/tests/netdev/main.c @@ -644,6 +644,10 @@ static int check_protocol(void) puts("Got protocol: CCN lite"); return 1; + case NETDEV_PROTO_CC110X: + puts("Got protocol: CC110x"); + return 1; + default: puts("You probably have to update this switch-case."); return 0; From dc658f8be0896ea50d41b86b34c931a43ef73dbe Mon Sep 17 00:00:00 2001 From: Fabian Nack Date: Tue, 23 Sep 2014 01:33:45 +0200 Subject: [PATCH 3/3] boards - msbiot: prepare msbiot for new cc110x driver --- boards/msbiot/Makefile | 1 + boards/msbiot/Makefile.features | 1 + boards/msbiot/Makefile.include | 7 +++++ boards/msbiot/include/board.h | 15 +++++++++++ boards/msbiot/include/periph_conf.h | 41 ++++++++++++++++++++++++----- cpu/stm32f4/include/cpu-conf.h | 10 +++++++ 6 files changed, 69 insertions(+), 6 deletions(-) diff --git a/boards/msbiot/Makefile b/boards/msbiot/Makefile index 37891de8e6a2..1f6f780dabe0 100644 --- a/boards/msbiot/Makefile +++ b/boards/msbiot/Makefile @@ -1,4 +1,5 @@ # tell the Makefile.base which module to build MODULE = $(BOARD)_base +INCLUDES += -I$(RIOTBASE)/drivers/cc110x include $(RIOTBASE)/Makefile.base diff --git a/boards/msbiot/Makefile.features b/boards/msbiot/Makefile.features index fb3c7463c75a..326c9e8e4385 100644 --- a/boards/msbiot/Makefile.features +++ b/boards/msbiot/Makefile.features @@ -1,2 +1,3 @@ FEATURES_PROVIDED += cpp FEATURES_PROVIDED += periph_gpio +FEATURES_PROVIDED += transceiver diff --git a/boards/msbiot/Makefile.include b/boards/msbiot/Makefile.include index 2de729e502e4..64b2910eea2d 100644 --- a/boards/msbiot/Makefile.include +++ b/boards/msbiot/Makefile.include @@ -52,3 +52,10 @@ endif # export board specific includes to the global includes-listing export INCLUDES += -I$(RIOTBOARD)/$(BOARD)/include + +ifneq (,$(filter defaulttransceiver,$(USEMODULE))) + USEMODULE += cc110x + ifeq (,$(filter netdev_base,$(USEMODULE))) + USEMODULE += transceiver + endif +endif diff --git a/boards/msbiot/include/board.h b/boards/msbiot/include/board.h index e5d75e9d0b77..8fd4962db0ad 100644 --- a/boards/msbiot/include/board.h +++ b/boards/msbiot/include/board.h @@ -23,6 +23,8 @@ #include "cpu.h" #include "periph_conf.h" +#include "periph/gpio.h" +#include "periph/spi.h" #ifdef __cplusplus extern "C" { @@ -38,6 +40,19 @@ extern "C" { */ #define HW_TIMER TIMER_0 +/** + * @name Configure connected CC1101 (radio) device + * @{ + */ +#define CC110X_SPI SPI_0 +#define CC110X_CS GPIO_7 +#define CC110X_GDO0 GPIO_11 +#define CC110X_GDO1 GPIO_2 +#define CC110X_GDO2 GPIO_12 + +typedef uint8_t radio_packet_length_t; +/** @} */ + /** * @name Define UART device and baudrate for stdio * @{ diff --git a/boards/msbiot/include/periph_conf.h b/boards/msbiot/include/periph_conf.h index cc688c7b7edb..46db99dae614 100644 --- a/boards/msbiot/include/periph_conf.h +++ b/boards/msbiot/include/periph_conf.h @@ -124,6 +124,35 @@ extern "C" { #define UART_2_AF 7 /** @} */ +/** + * @name SPI configuration + * @{ + */ +#define SPI_NUMOF 1 +#define SPI_0_EN 1 +#define SPI_1_EN 0 +#define SPI_IRQ_PRIO 1 + +/* SPI 0 device config */ +#define SPI_0_DEV SPI1 +#define SPI_0_CLKEN() (RCC->APB2ENR |= RCC_APB2ENR_SPI1EN) +#define SPI_0_CLKDIS() (RCC->APB2ENR &= ~RCC_APB2ENR_SPI1EN) +#define SPI_0_IRQ SPI1_IRQn +#define SPI_0_IRQ_HANDLER isr_spi1 +/* SPI 0 pin configuration */ +#define SPI_0_SCK_PORT GPIOA +#define SPI_0_SCK_PIN 5 +#define SPI_0_SCK_AF 5 +#define SPI_0_MISO_PORT GPIOA +#define SPI_0_MISO_PIN 6 +#define SPI_0_MISO_AF 5 +#define SPI_0_MOSI_PORT GPIOA +#define SPI_0_MOSI_PIN 7 +#define SPI_0_MOSI_AF 5 +#define SPI_0_SCK_PORT_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN) +#define SPI_0_MISO_PORT_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN) +#define SPI_0_MOSI_PORT_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN) +/** @} */ /** * @name GPIO configuration @@ -153,9 +182,9 @@ extern "C" { #define GPIO_IRQ_1 GPIO_1 /* alternatively GPIO_10 could be used here */ #define GPIO_IRQ_2 GPIO_15 #define GPIO_IRQ_3 -1/* not configured */ -#define GPIO_IRQ_4 GPIO_2 /* alternatively GPIO_11 could be used here */ +#define GPIO_IRQ_4 GPIO_11 #define GPIO_IRQ_5 GPIO_12 -#define GPIO_IRQ_6 -1/* not configured */ +#define GPIO_IRQ_6 GPIO_2 #define GPIO_IRQ_7 -1/* not configured */ #define GPIO_IRQ_8 GPIO_13 #define GPIO_IRQ_9 GPIO_5 @@ -179,11 +208,11 @@ extern "C" { #define GPIO_1_EXTI_CFG() (SYSCFG->EXTICR[0] |= SYSCFG_EXTICR1_EXTI1_PA) #define GPIO_1_IRQ EXTI1_IRQn /* GPIO channel 2 config */ -#define GPIO_2_PORT GPIOA -#define GPIO_2_PIN 4 +#define GPIO_2_PORT GPIOA /* CC1101 GDO1 */ +#define GPIO_2_PIN 6 #define GPIO_2_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN) -#define GPIO_2_EXTI_CFG() (SYSCFG->EXTICR[1] |= SYSCFG_EXTICR2_EXTI4_PA) -#define GPIO_2_IRQ EXTI4_IRQn +#define GPIO_2_EXTI_CFG() (SYSCFG->EXTICR[1] |= SYSCFG_EXTICR2_EXTI6_PA) +#define GPIO_2_IRQ EXTI9_5_IRQn /* GPIO channel 3 config */ #define GPIO_3_PORT GPIOA /* CC3000 SPI_IRQ */ #define GPIO_3_PIN 10 diff --git a/cpu/stm32f4/include/cpu-conf.h b/cpu/stm32f4/include/cpu-conf.h index a5a08691a755..a3bdeb332439 100644 --- a/cpu/stm32f4/include/cpu-conf.h +++ b/cpu/stm32f4/include/cpu-conf.h @@ -53,6 +53,16 @@ #endif /** @} */ +/** + * @name CC110X buffer size definitions for the stm32f4 + * @{ + */ +#ifdef MODULE_CC110X +#define TRANSCEIVER_BUFFER_SIZE (10) +#define RX_BUF_SIZE (10) +#endif +/** @} */ + #ifdef __cplusplus extern "C" { #endif