mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
drivers - cc110x: Initial import of new cc110x driver
This commit is contained in:
parent
57e54e254d
commit
eebfd5011a
@ -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
|
||||
|
@ -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
|
||||
|
1
drivers/cc110x/Makefile
Normal file
1
drivers/cc110x/Makefile
Normal file
@ -0,0 +1 @@
|
||||
include $(RIOTBASE)/Makefile.base
|
133
drivers/cc110x/cc110x-defaultsettings.c
Normal file
133
drivers/cc110x/cc110x-defaultsettings.c
Normal file
@ -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 <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 */
|
||||
};
|
207
drivers/cc110x/cc110x-internal.h
Normal file
207
drivers/cc110x/cc110x-internal.h
Normal file
@ -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 <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
|
253
drivers/cc110x/cc110x-netdev.c
Normal file
253
drivers/cc110x/cc110x-netdev.c
Normal file
@ -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 <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 */
|
245
drivers/cc110x/cc110x-rxtx.c
Normal file
245
drivers/cc110x/cc110x-rxtx.c
Normal file
@ -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 <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];
|
||||
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;
|
||||
}
|
129
drivers/cc110x/cc110x-spi.c
Normal file
129
drivers/cc110x/cc110x-spi.c
Normal file
@ -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 <hillebra@inf.fu-berlin.de>
|
||||
* @author Heiko Will <hwill@inf.fu-berlin.de>
|
||||
* @author Fabian Nack <nack@inf.fu-berlin.de>
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#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;
|
||||
}
|
397
drivers/cc110x/cc110x.c
Normal file
397
drivers/cc110x/cc110x.c
Normal file
@ -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 <oliver.hahm@inria.fr>
|
||||
* @author Fabian Nack <nack@inf.fu-berlin.de>
|
||||
* @}
|
||||
*/
|
||||
#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;
|
||||
}
|
26
drivers/include/cc110x.h
Normal file
26
drivers/include/cc110x.h
Normal file
@ -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 */
|
106
drivers/include/cc110x/cc110x-config.h
Normal file
106
drivers/include/cc110x/cc110x-config.h
Normal file
@ -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 <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;
|
||||
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 */
|
58
drivers/include/cc110x/cc110x-defaultsettings.h
Normal file
58
drivers/include/cc110x/cc110x-defaultsettings.h
Normal file
@ -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 <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 */
|
160
drivers/include/cc110x/cc110x-interface.h
Normal file
160
drivers/include/cc110x/cc110x-interface.h
Normal file
@ -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 <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 */
|
42
drivers/include/cc110x/cc110x-netdev.h
Normal file
42
drivers/include/cc110x/cc110x-netdev.h
Normal file
@ -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 <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 */
|
93
drivers/include/cc110x/cc110x-reg.h
Normal file
93
drivers/include/cc110x/cc110x-reg.h
Normal file
@ -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 <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 */
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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"
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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];
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user