
12 changed files with 2114 additions and 0 deletions
@ -0,0 +1,366 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Freie Universität Berlin |
||||
* |
||||
* This file is subject to the terms and conditions of the GNU Lesser General |
||||
* Public License v2.1. See the file LICENSE in the top level directory for more |
||||
* details. |
||||
*/ |
||||
|
||||
/**
|
||||
* @defgroup drivers_ng_at86rf2xx AT86RF2xx based drivers |
||||
* @ingroup drivers |
||||
* |
||||
* This module contains drivers for radio devices in Atmel's AT86RF2xx series. |
||||
* The driver is aimed to work with all devices of this series. |
||||
* |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Interface definition for AT86RF2xx based drivers |
||||
* |
||||
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de> |
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de> |
||||
* @author Kaspar Schleiser <kaspar@schleiser.de> |
||||
*/ |
||||
|
||||
#ifndef NG_AT86RF2XX_H_ |
||||
#define NG_AT86RF2XX_H_ |
||||
|
||||
#include <stdint.h> |
||||
|
||||
#include "board.h" |
||||
#include "periph/spi.h" |
||||
#include "periph/gpio.h" |
||||
#include "net/ng_netdev.h" |
||||
#include "ng_at86rf2xx.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Maximum possible packet size in byte |
||||
*/ |
||||
#define NG_AT86RF2XX_MAX_PKT_LENGTH (127) |
||||
|
||||
/**
|
||||
* @brief Default addresses used if the CPUID module is not present |
||||
* @{ |
||||
*/ |
||||
#define NG_AT86RF2XX_DEFAULT_ADDR_SHORT (0x0230) |
||||
#define NG_AT86RF2XX_DEFAULT_ADDR_LONG (0x1222334455667788) |
||||
/** @} */ |
||||
|
||||
/**
|
||||
* @brief Channel configuration |
||||
* @{ |
||||
*/ |
||||
#ifdef MODULE_NG_AT86RF212B |
||||
/* the AT86RF212B has a sub-1GHz radio */ |
||||
#define NG_AT86RF2XX_MIN_CHANNEL (0) |
||||
#define NG_AT86RF2XX_MAX_CHANNEL (10) |
||||
#define NG_AT86RF2XX_DEFAULT_CHANNEL (5) |
||||
#else |
||||
#define NG_AT86RF2XX_MIN_CHANNEL (11U) |
||||
#define NG_AT86RF2XX_MAX_CHANNEL (26U) |
||||
#define NG_AT86RF2XX_DEFAULT_CHANNEL (17U) |
||||
#endif |
||||
/** @} */ |
||||
|
||||
/**
|
||||
* @brief Default PAN ID |
||||
* |
||||
* TODO: Read some global network stack specific configuration value |
||||
*/ |
||||
#define NG_AT86RF2XX_DEFAULT_PANID (0x0023) |
||||
|
||||
/**
|
||||
* @brief Default TX power (0dBm) |
||||
*/ |
||||
#define NG_AT86RF2XX_DEFAULT_TXPOWER (0U) |
||||
|
||||
/**
|
||||
* @brief Flags for device internal states (see datasheet) |
||||
* @{ |
||||
*/ |
||||
#define NG_AT86RF2XX_STATE_TRX_OFF (0x08) /**< idle */ |
||||
#define NG_AT86RF2XX_STATE_PLL_ON (0x09) /**< ready to transmit */ |
||||
#define NG_AT86RF2XX_STATE_SLEEP (0x0f) /**< sleep mode */ |
||||
#define NG_AT86RF2XX_STATE_BUSY_RX_AACK (0x11) /**< busy receiving data */ |
||||
#define NG_AT86RF2XX_STATE_BUSY_TX_ARET (0x12) /**< busy transmitting data */ |
||||
#define NG_AT86RF2XX_STATE_RX_AACK_ON (0x16) /**< wait for incoming data */ |
||||
#define NG_AT86RF2XX_STATE_TX_ARET_ON (0x19) /**< ready for sending data */ |
||||
#define NG_AT86RF2XX_STATE_IN_PROGRESS (0x1f) /**< ongoing state conversion */ |
||||
/** @} */ |
||||
|
||||
/**
|
||||
* @brief Internal device option flags |
||||
* @{ |
||||
*/ |
||||
#define NG_AT86RF2XX_OPT_AUTOACK (0x0001) /**< auto ACKs active */ |
||||
#define NG_AT86RF2XX_OPT_CSMA (0x0002) /**< CSMA active */ |
||||
#define NG_AT86RF2XX_OPT_PROMISCUOUS (0x0004) /**< promiscuous mode |
||||
* active */ |
||||
#define NG_AT86RF2XX_OPT_PRELOADING (0x0008) /**< preloading enabled */ |
||||
#define NG_AT86RF2XX_OPT_TELL_TX_START (0x0010) /**< notify MAC layer on TX |
||||
* start */ |
||||
#define NG_AT86RF2XX_OPT_TELL_TX_END (0x0020) /**< notify MAC layer on TX |
||||
* finished */ |
||||
#define NG_AT86RF2XX_OPT_TELL_RX_START (0x0040) /**< notify MAC layer on RX |
||||
* start */ |
||||
#define NG_AT86RF2XX_OPT_TELL_RX_END (0x0080) /**< notify MAC layer on RX |
||||
* finished */ |
||||
#define NG_AT86RF2XX_OPT_RAWDUMP (0x0100) /**< pass RAW frame data to |
||||
* upper layer */ |
||||
#define NG_AT86RF2XX_OPT_SRC_ADDR_LONG (0x0200) /**< send data using long |
||||
* source address */ |
||||
#define NG_AT86RF2XX_OPT_USE_SRC_PAN (0x0400) /**< do not compress source |
||||
* PAN ID */ |
||||
/** @} */ |
||||
|
||||
/**
|
||||
* @brief Device descriptor for AT86RF2XX radio devices |
||||
*/ |
||||
typedef struct { |
||||
/* netdev fields */ |
||||
const ng_netdev_driver_t *driver; /**< pointer to the devices interface */ |
||||
ng_netdev_event_cb_t event_cb; /**< netdev event callback */ |
||||
kernel_pid_t mac_pid; /**< the driver's thread's PID */ |
||||
/* device specific fields */ |
||||
spi_t spi; /**< used SPI device */ |
||||
gpio_t cs_pin; /**< chip select pin */ |
||||
gpio_t sleep_pin; /**< sleep pin */ |
||||
gpio_t reset_pin; /**< reset pin */ |
||||
gpio_t int_pin; /**< external interrupt pin */ |
||||
ng_nettype_t proto; /**< protocol the radio expects */ |
||||
uint8_t state; /**< current state of the radio */ |
||||
uint8_t seq_nr; /**< sequence number to use next */ |
||||
uint8_t frame_len; /**< length of the current TX frame */ |
||||
uint16_t pan; /**< currently used PAN ID */ |
||||
uint8_t addr_short[2]; /**< the radio's short address */ |
||||
uint8_t addr_long[8]; /**< the radio's long address */ |
||||
uint16_t options; /**< state of used options */ |
||||
uint8_t idle_state; /**< state to return to after sending */ |
||||
} ng_at86rf2xx_t; |
||||
|
||||
|
||||
/**
|
||||
* @brief Initialize a given AT86RF2xx device |
||||
* |
||||
* @param[out] dev device descriptor |
||||
* @param[in] spi SPI bus the device is connected to |
||||
* @param[in] spi_speed SPI speed to use |
||||
* @param[in] cs_pin GPIO pin connected to chip select |
||||
* @param[in] int_pin GPIO pin connected to the interrupt pin |
||||
* @param[in] sleep_pin GPIO pin connected to the sleep pin |
||||
* @param[in] reset_pin GPIO pin connected to the reset pin |
||||
* |
||||
* @return 0 on success |
||||
* @return <0 on error |
||||
*/ |
||||
int ng_at86rf2xx_init(ng_at86rf2xx_t *dev, spi_t spi, spi_speed_t spi_speed, |
||||
gpio_t cs_pin, gpio_t int_pin, |
||||
gpio_t sleep_pin, gpio_t reset_pin); |
||||
|
||||
/**
|
||||
* @brief Trigger a hardware reset and configure radio with default values |
||||
* |
||||
* @param[in] dev device to reset |
||||
*/ |
||||
void ng_at86rf2xx_reset(ng_at86rf2xx_t *dev); |
||||
|
||||
/**
|
||||
* @brief Trigger a clear channel assessment |
||||
* |
||||
* @param[in] dev device to use |
||||
* |
||||
* @return true if channel is clear |
||||
* @return false if channel is busy |
||||
*/ |
||||
bool ng_at86rf2xx_cca(ng_at86rf2xx_t *dev); |
||||
|
||||
/**
|
||||
* @brief Get the short address of the given device |
||||
* |
||||
* @param[in] dev device to read from |
||||
* |
||||
* @return the currently set (2-byte) short address |
||||
*/ |
||||
uint16_t ng_at86rf2xx_get_addr_short(ng_at86rf2xx_t *dev); |
||||
|
||||
/**
|
||||
* @brief Set the short address of the given device |
||||
* |
||||
* @param[in] dev device to write to |
||||
* @param[in] addr (2-byte) short address to set |
||||
*/ |
||||
void ng_at86rf2xx_set_addr_short(ng_at86rf2xx_t *dev, uint16_t addr); |
||||
|
||||
/**
|
||||
* @brief Get the configured long address of the given device |
||||
* |
||||
* @param[in] dev device to read from |
||||
* |
||||
* @return the currently set (8-byte) long address |
||||
*/ |
||||
uint64_t ng_at86rf2xx_get_addr_long(ng_at86rf2xx_t *dev); |
||||
|
||||
/**
|
||||
* @brief Set the long address of the given device |
||||
* |
||||
* @param[in] dev device to write to |
||||
* @param[in] addr (8-byte) long address to set |
||||
*/ |
||||
void ng_at86rf2xx_set_addr_long(ng_at86rf2xx_t *dev, uint64_t addr); |
||||
|
||||
/**
|
||||
* @brief Get the configured channel of the given device |
||||
* |
||||
* @param[in] dev device to read from |
||||
* |
||||
* @return the currently set channel |
||||
*/ |
||||
uint8_t ng_at86rf2xx_get_chan(ng_at86rf2xx_t *dev); |
||||
|
||||
/**
|
||||
* @brief Set the channel of the given device |
||||
* |
||||
* @param[in] dev device to write to |
||||
* @param[in] chan channel to set |
||||
*/ |
||||
void ng_at86rf2xx_set_chan(ng_at86rf2xx_t *dev, uint8_t chan); |
||||
|
||||
/**
|
||||
* @brief Get the configured PAN ID of the given device |
||||
* |
||||
* @param[in] dev device to read from |
||||
* |
||||
* @return the currently set PAN ID |
||||
*/ |
||||
uint16_t ng_at86rf2xx_get_pan(ng_at86rf2xx_t *dev); |
||||
|
||||
/**
|
||||
* @brief Set the PAN ID of the given device |
||||
* |
||||
* @param[in] dev device to write to |
||||
* @param[in] pan PAN ID to set |
||||
*/ |
||||
void ng_at86rf2xx_set_pan(ng_at86rf2xx_t *dev, uint16_t pan); |
||||
|
||||
/**
|
||||
* @brief Get the configured transmission power of the given device [in dBm] |
||||
* |
||||
* @param[in] dev device to read from |
||||
* |
||||
* @return configured transmission power in dBm |
||||
*/ |
||||
int16_t ng_at86rf2xx_get_txpower(ng_at86rf2xx_t *dev); |
||||
|
||||
/**
|
||||
* @brief Set the transmission power of the given device [in dBm] |
||||
* |
||||
* If the device does not support the exact dBm value given, it will set a value |
||||
* as close as possible to the given value. If the given value is larger or |
||||
* lower then the maximal or minimal possible value, the min or max value is |
||||
* set, respectively. |
||||
* |
||||
* @param[in] dev device to write to |
||||
* @param[in] txpower transmission power in dBm |
||||
*/ |
||||
void ng_at86rf2xx_set_txpower(ng_at86rf2xx_t *dev, int16_t txpower); |
||||
|
||||
/**
|
||||
* @brief Enable or disable driver specific options |
||||
* |
||||
* @param[in] dev device to set/clear option flag for |
||||
* @param[in] option option to enable/disable |
||||
* @param[in] state true for enable, false for disable |
||||
*/ |
||||
void ng_at86rf2xx_set_option(ng_at86rf2xx_t *dev, uint16_t option, bool state); |
||||
|
||||
/**
|
||||
* @brief Get the given devices current internal state |
||||
* |
||||
* @param[in] dev device to get state of |
||||
* @return the current state of the given device |
||||
*/ |
||||
uint8_t ng_at86rf2xx_get_state(ng_at86rf2xx_t *dev); |
||||
|
||||
/**
|
||||
* @brief Set the state of the given device (trigger a state change) |
||||
* |
||||
* @param[in] dev device to change state of |
||||
* @param[in] state the targeted new state |
||||
*/ |
||||
void ng_at86rf2xx_set_state(ng_at86rf2xx_t *dev, uint8_t state); |
||||
|
||||
/**
|
||||
* @brief Convenience function for simply sending data |
||||
* |
||||
* @note This function ignores the PRELOADING option |
||||
* |
||||
* @param[in] dev device to use for sending |
||||
* @param[in] data data to send (must include IEEE802.15.4 header) |
||||
* @param[in] len length of @p data |
||||
* |
||||
* @return number of bytes that were actually send |
||||
* @return 0 on error |
||||
*/ |
||||
size_t ng_at86rf2xx_send(ng_at86rf2xx_t *dev, uint8_t *data, size_t len); |
||||
|
||||
/**
|
||||
* @brief Prepare for sending of data |
||||
* |
||||
* This function puts the given device into the TX state, so no receiving of |
||||
* data is possible after it was called. |
||||
* |
||||
* @param[in] dev device to prepare for sending |
||||
*/ |
||||
void ng_at86rf2xx_tx_prepare(ng_at86rf2xx_t *dev); |
||||
|
||||
/**
|
||||
* @brief Load chunks of data into the transmit buffer of the given device |
||||
* |
||||
* @param[in] dev device to write data to |
||||
* @param[in] data buffer containing the data to load |
||||
* @param[in] len number of bytes in @p buffer |
||||
* @param[in] offset offset used when writing data to internal buffer |
||||
* |
||||
* @return offset + number of bytes written |
||||
*/ |
||||
size_t ng_at86rf2xx_tx_load(ng_at86rf2xx_t *dev, uint8_t *data, size_t len, |
||||
size_t offset); |
||||
|
||||
/**
|
||||
* @brief Trigger sending of data previously loaded into transmit buffer |
||||
* |
||||
* @param[in] dev device to trigger |
||||
*/ |
||||
void ng_at86rf2xx_tx_exec(ng_at86rf2xx_t *dev); |
||||
|
||||
/**
|
||||
* @brief Read the length of a received packet |
||||
* |
||||
* @param dev device to read from |
||||
* |
||||
* @return overall length of a received packet in byte |
||||
*/ |
||||
size_t ng_at86rf2xx_rx_len(ng_at86rf2xx_t *dev); |
||||
|
||||
/**
|
||||
* @brief Read a chunk of data from the receive buffer of the given device |
||||
* |
||||
* @param[in] dev device to read from |
||||
* @param[out] data buffer to write data to |
||||
* @param[in] len number of bytes to read from device |
||||
* @param[in] offset offset in the receive buffer |
||||
*/ |
||||
void ng_at86rf2xx_rx_read(ng_at86rf2xx_t *dev, uint8_t *data, size_t len, |
||||
size_t offset); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* NG_AT86RF2XX_H_ */ |
||||
/** @} */ |
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Alaeddine Weslati <alaeddine.weslati@inria.fr> |
||||
* Copyright (C) 2015 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_ng_at86rf2xx |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Internal interfaces for AT86RF2xx drivers |
||||
* |
||||
* @author Alaeddine Weslati <alaeddine.weslati@inria.fr> |
||||
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de> |
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de> |
||||
*/ |
||||
|
||||
#ifndef NG_AT86RF2XX_INTERNAL_H_ |
||||
#define NG_AT86RF2XX_INTERNAL_H_ |
||||
|
||||
#include <stdint.h> |
||||
|
||||
#include "ng_at86rf2xx.h" |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Read from a register at address `addr` from device `dev`. |
||||
* |
||||
* @param[in] dev device to read from |
||||
* @param[in] addr address of the register to read |
||||
* |
||||
* @return the value of the specified register |
||||
*/ |
||||
uint8_t ng_at86rf2xx_reg_read(const ng_at86rf2xx_t *dev, const uint8_t addr); |
||||
|
||||
/**
|
||||
* @brief Write to a register at address `addr` from device `dev`. |
||||
* |
||||
* @param[in] dev device to write to |
||||
* @param[in] addr address of the register to write |
||||
* @param[in] value value to write to the given register |
||||
*/ |
||||
void ng_at86rf2xx_reg_write(const ng_at86rf2xx_t *dev, const uint8_t addr, |
||||
const uint8_t value); |
||||
|
||||
/**
|
||||
* @brief Read a chunk of data from the SRAM of the given device |
||||
* |
||||
* @param[in] dev device to read from |
||||
* @param[in] offset starting address to read from [valid 0x00-0x7f] |
||||
* @param[out] data buffer to read data into |
||||
* @param[in] len number of bytes to read from SRAM |
||||
*/ |
||||
void ng_at86rf2xx_sram_read(const ng_at86rf2xx_t *dev, |
||||
const uint8_t offset, |
||||
uint8_t *data, |
||||
const size_t len); |
||||
|
||||
/**
|
||||
* @brief Write a chunk of data into the SRAM of the given device |
||||
* |
||||
* @param[in] dev device to write to |
||||
* @param[in] offset address in the SRAM to write to [valid 0x00-0x7f] |
||||
* @param[in] data data to copy into SRAM |
||||
* @param[in] len number of bytes to write to SRAM |
||||
*/ |
||||
void ng_at86rf2xx_sram_write(const ng_at86rf2xx_t *dev, |
||||
const uint8_t offset, |
||||
const uint8_t *data, |
||||
const size_t len); |
||||
|
||||
/**
|
||||
* @brief Read the internal frame buffer of the given device |
||||
* |
||||
* Reading the frame buffer returns some extra bytes that are not accessible |
||||
* through reading the RAM directly. |
||||
* |
||||
* @param[in] dev device to read from |
||||
* @param[out] data buffer to copy the data to |
||||
* @param[in] len number of bytes to read from the frame buffer |
||||
*/ |
||||
void ng_at86rf2xx_fb_read(const ng_at86rf2xx_t *dev, |
||||
uint8_t *data, const size_t len); |
||||
|
||||
/**
|
||||
* @brief Convenience function for reading the status of the given device |
||||
* |
||||
* @param[in] dev device to read the status from |
||||
* |
||||
* @return internal status of the given device |
||||
*/ |
||||
uint8_t ng_at86rf2xx_get_status(const ng_at86rf2xx_t *dev); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* NG_AT86RF2XX_INTERNAL_H_ */ |
||||
/** @} */ |
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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_ng_at86rf2xx |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Netdev interface to AT86RF2xx drivers |
||||
* |
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de> |
||||
*/ |
||||
|
||||
#ifndef NG_AT86RF2XX_NETDEV_H_ |
||||
#define NG_AT86RF2XX_NETDEV_H_ |
||||
|
||||
#include "net/ng_netdev.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Reference to the netdev device driver struct |
||||
*/ |
||||
extern const ng_netdev_driver_t ng_at86rf2xx_driver; |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* NG_AT86RF2XX_NETDEV_H_ */ |
||||
/** @} */ |
@ -0,0 +1,319 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Alaeddine Weslati <alaeddine.weslati@inria.fr> |
||||
* Copyright (C) 2015 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_ng_at86rf2xx |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Register and command definitions for AT86RF2xx devices |
||||
* |
||||
* @author Alaeddine Weslati <alaeddine.weslati@inria.fr> |
||||
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de> |
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de> |
||||
* @author Kaspar Schleiser <kaspar@schleiser.de> |
||||
*/ |
||||
|
||||
#ifndef NG_AT86RF2XX_REGISTERS_H_ |
||||
#define NG_AT86RF2XX_REGISTERS_H_ |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Constant part numbers of the AT86RF2xx device family |
||||
* @{ |
||||
*/ |
||||
#define NG_AT86RF212B_PARTNUM (0x07) |
||||
#define NG_AT86RF231_PARTNUM (0x03) |
||||
#define NG_AT86RF232_PARTNUM (0x0a) |
||||
#define NG_AT86RF233_PARTNUM (0x0b) |
||||
/** @} */ |
||||
|
||||
/**
|
||||
* @brief Assign the part number for the device we are building the driver for |
||||
* @{ |
||||
*/ |
||||
#ifdef MODULE_NG_AT86RF212B |
||||
#define NG_AT86RF2XX_PARTNUM NG_AT86RF212B_PARTNUM |
||||
#elif MODULE_NG_AT86RF232 |
||||
#define NG_AT86RF2XX_PARTNUM NG_AT86RF232_PARTNUM |
||||
#elif MODULE_NG_AT86RF233 |
||||
#define NG_AT86RF2XX_PARTNUM NG_AT86RF233_PARTNUM |
||||
#else /* MODULE_NG_AT86RF231 as default device */ |
||||
#define NG_AT86RF2XX_PARTNUM NG_AT86RF231_PARTNUM |
||||
#endif |
||||
/** @} */ |
||||
|
||||
/**
|
||||
* @brief SPI access specifiers |
||||
* @{ |
||||
*/ |
||||
#define NG_AT86RF2XX_ACCESS_REG (0x80) |
||||
#define NG_AT86RF2XX_ACCESS_FB (0x20) |
||||
#define NG_AT86RF2XX_ACCESS_SRAM (0x00) |
||||
#define NG_AT86RF2XX_ACCESS_READ (0x00) |
||||
#define NG_AT86RF2XX_ACCESS_WRITE (0x40) |
||||
/** @} */ |
||||
|
||||
/**
|
||||
* @brief Register addresses |
||||
* @{ |
||||
*/ |
||||
#define NG_AT86RF2XX_REG__TRX_STATUS (0x01) |
||||
#define NG_AT86RF2XX_REG__TRX_STATE (0x02) |
||||
#define NG_AT86RF2XX_REG__TRX_CTRL_0 (0x03) |
||||
#define NG_AT86RF2XX_REG__TRX_CTRL_1 (0x04) |
||||
#define NG_AT86RF2XX_REG__PHY_TX_PWR (0x05) |
||||
#define NG_AT86RF2XX_REG__PHY_RSSI (0x06) |
||||
#define NG_AT86RF2XX_REG__PHY_ED_LEVEL (0x07) |
||||
#define NG_AT86RF2XX_REG__PHY_CC_CCA (0x08) |
||||
#define NG_AT86RF2XX_REG__CCA_THRES (0x09) |
||||
#define NG_AT86RF2XX_REG__RX_CTRL (0x0A) |
||||
#define NG_AT86RF2XX_REG__SFD_VALUE (0x0B) |
||||
#define NG_AT86RF2XX_REG__TRX_CTRL_2 (0x0C) |
||||
#define NG_AT86RF2XX_REG__ANT_DIV (0x0D) |
||||
#define NG_AT86RF2XX_REG__IRQ_MASK (0x0E) |
||||
#define NG_AT86RF2XX_REG__IRQ_STATUS (0x0F) |
||||
#define NG_AT86RF2XX_REG__VREG_CTRL (0x10) |
||||
#define NG_AT86RF2XX_REG__BATMON (0x11) |
||||
#define NG_AT86RF2XX_REG__XOSC_CTRL (0x12) |
||||
#define NG_AT86RF2XX_REG__CC_CTRL_1 (0x14) |
||||
#define NG_AT86RF2XX_REG__RX_SYN (0x15) |
||||
#define NG_AT86RF2XX_REG__XAH_CTRL_1 (0x17) |
||||
#define NG_AT86RF2XX_REG__FTN_CTRL (0x18) |
||||
#define NG_AT86RF2XX_REG__PLL_CF (0x1A) |
||||
#define NG_AT86RF2XX_REG__PLL_DCU (0x1B) |
||||
#define NG_AT86RF2XX_REG__PART_NUM (0x1C) |
||||
#define NG_AT86RF2XX_REG__VERSION_NUM (0x1D) |
||||
#define NG_AT86RF2XX_REG__MAN_ID_0 (0x1E) |
||||
#define NG_AT86RF2XX_REG__MAN_ID_1 (0x1F) |
||||
#define NG_AT86RF2XX_REG__SHORT_ADDR_0 (0x20) |
||||
#define NG_AT86RF2XX_REG__SHORT_ADDR_1 (0x21) |
||||
#define NG_AT86RF2XX_REG__PAN_ID_0 (0x22) |
||||
#define NG_AT86RF2XX_REG__PAN_ID_1 (0x23) |
||||
#define NG_AT86RF2XX_REG__IEEE_ADDR_0 (0x24) |
||||
#define NG_AT86RF2XX_REG__IEEE_ADDR_1 (0x25) |
||||
#define NG_AT86RF2XX_REG__IEEE_ADDR_2 (0x26) |
||||
#define NG_AT86RF2XX_REG__IEEE_ADDR_3 (0x27) |
||||
#define NG_AT86RF2XX_REG__IEEE_ADDR_4 (0x28) |
||||
#define NG_AT86RF2XX_REG__IEEE_ADDR_5 (0x29) |
||||
#define NG_AT86RF2XX_REG__IEEE_ADDR_6 (0x2A) |
||||
#define NG_AT86RF2XX_REG__IEEE_ADDR_7 (0x2B) |
||||
#define NG_AT86RF2XX_REG__XAH_CTRL_0 (0x2C) |
||||
#define NG_AT86RF2XX_REG__CSMA_SEED_0 (0x2D) |
||||
#define NG_AT86RF2XX_REG__CSMA_SEED_1 (0x2E) |
||||
#define NG_AT86RF2XX_REG__CSMA_BE (0x2F) |
||||
#define NG_AT86RF2XX_REG__TST_CTRL_DIGI (0x36) |
||||
/** @} */ |
||||
|
||||
/**
|
||||
* @brief Bitfield definitions for the TRX_CTRL_0 register |
||||
* @{ |
||||
*/ |
||||
#define NG_AT86RF2XX_TRX_CTRL_0_MASK__PAD_IO (0xC0) |
||||
#define NG_AT86RF2XX_TRX_CTRL_0_MASK__PAD_IO_CLKM (0x30) |
||||
#define NG_AT86RF2XX_TRX_CTRL_0_MASK__CLKM_SHA_SEL (0x08) |
||||
#define NG_AT86RF2XX_TRX_CTRL_0_MASK__CLKM_CTRL (0x07) |
||||
|
||||
#define NG_AT86RF2XX_TRX_CTRL_0_DEFAULT__PAD_IO (0x00) |
||||
#define NG_AT86RF2XX_TRX_CTRL_0_DEFAULT__PAD_IO_CLKM (0x10) |
||||
#define NG_AT86RF2XX_TRX_CTRL_0_DEFAULT__CLKM_SHA_SEL (0x08) |
||||
#define NG_AT86RF2XX_TRX_CTRL_0_DEFAULT__CLKM_CTRL (0x01) |
||||
|
||||
#define NG_AT86RF2XX_TRX_CTRL_0_CLKM_CTRL__OFF (0x00) |
||||
#define NG_AT86RF2XX_TRX_CTRL_0_CLKM_CTRL__1MHz (0x01) |
||||
#define NG_AT86RF2XX_TRX_CTRL_0_CLKM_CTRL__2MHz (0x02) |
||||
#define NG_AT86RF2XX_TRX_CTRL_0_CLKM_CTRL__4MHz (0x03) |
||||
#define NG_AT86RF2XX_TRX_CTRL_0_CLKM_CTRL__8MHz (0x04) |
||||
#define NG_AT86RF2XX_TRX_CTRL_0_CLKM_CTRL__16MHz (0x05) |
||||
#define NG_AT86RF2XX_TRX_CTRL_0_CLKM_CTRL__250kHz (0x06) |
||||
#define NG_AT86RF2XX_TRX_CTRL_0_CLKM_CTRL__62_5kHz (0x07) |
||||
/** @} */ |
||||
|
||||
/**
|
||||
* @brief Bitfield definitions for the TRX_CTRL_1 register |
||||
* @{ |
||||
*/ |
||||
#define NG_AT86RF2XX_TRX_CTRL_1_MASK__PA_EXT_EN (0x80) |
||||
#define NG_AT86RF2XX_TRX_CTRL_1_MASK__IRQ_2_EXT_EN (0x40) |
||||
#define NG_AT86RF2XX_TRX_CTRL_1_MASK__TX_AUTO_CRC_ON (0x20) |
||||
#define NG_AT86RF2XX_TRX_CTRL_1_MASK__RX_BL_CTRL (0x10) |
||||
#define NG_AT86RF2XX_TRX_CTRL_1_MASK__SPI_CMD_MODE (0x0C) |
||||
#define NG_AT86RF2XX_TRX_CTRL_1_MASK__IRQ_MASK_MODE (0x02) |
||||
#define NG_AT86RF2XX_TRX_CTRL_1_MASK__IRQ_POLARITY (0x01) |
||||
/** @} */ |
||||
|
||||
/**
|
||||
* @brief Bitfield definitions for the TXR_CTRL_2 register |
||||
* @{ |
||||
*/ |
||||
#define NG_AT86RF2XX_TRX_CTRL_2_MASK__RX_SAFE_MODE (0x80) |
||||
#define NG_AT86RF2XX_TRX_CTRL_2_MASK__SUB_MODE (0x4) |
||||
#define NG_AT86RF2XX_TRX_CTRL_2_MASK__OQPSK_DATA_RATE (0x03) |
||||
#define NG_AT86RF2XX_TRX_CTRL_2_MASK__OQPSK_SCRAM_EN (0x20) |
||||
/** @} */ |
||||
|
||||
/**
|
||||
* @brief Bitfield definitions for the IRQ_STATUS register |
||||
* @{ |
||||
*/ |
||||
#define NG_AT86RF2XX_IRQ_STATUS_MASK__BAT_LOW (0x80) |
||||
#define NG_AT86RF2XX_IRQ_STATUS_MASK__TRX_UR (0x40) |
||||
#define NG_AT86RF2XX_IRQ_STATUS_MASK__AMI (0x20) |
||||
#define NG_AT86RF2XX_IRQ_STATUS_MASK__CCA_ED_DONE (0x10) |
||||
#define NG_AT86RF2XX_IRQ_STATUS_MASK__TRX_END (0x08) |
||||
#define NG_AT86RF2XX_IRQ_STATUS_MASK__RX_START (0x04) |
||||
#define NG_AT86RF2XX_IRQ_STATUS_MASK__PLL_UNLOCK (0x02) |
||||
#define NG_AT86RF2XX_IRQ_STATUS_MASK__PLL_LOCK (0x01) |
||||
/** @} */ |
||||
|
||||
/**
|
||||
* @brief Bitfield definitions for the TRX_STATUS register |
||||
* @{ |
||||
*/ |
||||
#define NG_AT86RF2XX_TRX_STATUS_MASK__CCA_DONE (0x80) |
||||
#define NG_AT86RF2XX_TRX_STATUS_MASK__CCA_STATUS (0x40) |
||||
#define NG_AT86RF2XX_TRX_STATUS_MASK__TRX_STATUS (0x1F) |
||||
|
||||
#define NG_AT86RF2XX_TRX_STATUS__P_ON (0x00) |
||||
#define NG_AT86RF2XX_TRX_STATUS__BUSY_RX (0x01) |
||||
#define NG_AT86RF2XX_TRX_STATUS__BUSY_TX (0x02) |
||||
#define NG_AT86RF2XX_TRX_STATUS__RX_ON (0x06) |
||||
#define NG_AT86RF2XX_TRX_STATUS__TRX_OFF (0x08) |
||||
#define NG_AT86RF2XX_TRX_STATUS__PLL_ON (0x09) |
||||
#define NG_AT86RF2XX_TRX_STATUS__SLEEP (0x0F) |
||||
#define NG_AT86RF2XX_TRX_STATUS__BUSY_RX_AACK (0x11) |
||||
#define NG_AT86RF2XX_TRX_STATUS__BUSY_TX_ARET (0x12) |
||||
#define NG_AT86RF2XX_TRX_STATUS__RX_AACK_ON (0x16) |
||||
#define NG_AT86RF2XX_TRX_STATUS__TX_ARET_ON (0x19) |
||||
#define NG_AT86RF2XX_TRX_STATUS__RX_ON_NOCLK (0x1C) |
||||
#define NG_AT86RF2XX_TRX_STATUS__RX_AACK_ON_NOCLK (0x1D) |
||||
#define NG_AT86RF2XX_TRX_STATUS__BUSY_RX_AACK_NOCLK (0x1E) |
||||
#define NG_AT86RF2XX_TRX_STATUS__STATE_TRANSITION_IN_PROGRESS (0x1F) |
||||
/** @} */ |
||||
|
||||
/**
|
||||
* @brief Bitfield definitions for the TRX_STATE register |
||||
* @{ |
||||
*/ |
||||
#define NG_AT86RF2XX_TRX_STATE_MASK__TRAC (0xe0) |
||||
|
||||
#define NG_AT86RF2XX_TRX_STATE__NOP (0x00) |
||||
#define NG_AT86RF2XX_TRX_STATE__TX_START (0x02) |
||||
#define NG_AT86RF2XX_TRX_STATE__FORCE_TRX_OFF (0x03) |
||||
#define NG_AT86RF2XX_TRX_STATE__FORCE_PLL_ON (0x04) |
||||
#define NG_AT86RF2XX_TRX_STATE__RX_ON (0x06) |
||||
#define NG_AT86RF2XX_TRX_STATE__TRX_OFF (0x08) |
||||
#define NG_AT86RF2XX_TRX_STATE__PLL_ON (0x09) |
||||
#define NG_AT86RF2XX_TRX_STATE__RX_AACK_ON (0x16) |
||||
#define NG_AT86RF2XX_TRX_STATE__TX_ARET_ON (0x19) |
||||
#define NG_AT86RF2XX_TRX_STATE__TRAC_SUCCESS (0x00) |
||||
#define NG_AT86RF2XX_TRX_STATE__TRAC_SUCCESS_DATA_PENDING (0x20) |
||||
#define NG_AT86RF2XX_TRX_STATE__TRAC_SUCCESS_WAIT_FOR_ACK (0x40) |
||||
#define NG_AT86RF2XX_TRX_STATE__TRAC_CHANNEL_ACCESS_FAILURE (0x60) |
||||
#define NG_AT86RF2XX_TRX_STATE__TRAC_NO_ACK (0xa0) |
||||
#define NG_AT86RF2XX_TRX_STATE__TRAC_INVALID (0xe0) |
||||
/** @} */ |
||||
|
||||
/**
|
||||
* @brief Bitfield definitions for the PHY_CCA register |
||||
* @{ |
||||
*/ |
||||
#define NG_AT86RF2XX_PHY_CC_CCA_MASK__CCA_REQUEST (0x80) |
||||
#define NG_AT86RF2XX_PHY_CC_CCA_MASK__CCA_MODE (0x60) |
||||
#define NG_AT86RF2XX_PHY_CC_CCA_MASK__CHANNEL (0x1F) |
||||
|
||||
#define NG_AT86RF2XX_PHY_CC_CCA_DEFAULT__CCA_MODE (0x20) |
||||
/** @} */ |
||||
|
||||
/**
|
||||
* @brief Bitfield definitions for the PHY_TX_PWR register |
||||
* @{ |
||||
*/ |
||||
#define NG_AT86RF2XX_PHY_TX_PWR_MASK__PA_BUF_LT (0xC0) |
||||
#define NG_AT86RF2XX_PHY_TX_PWR_MASK__PA_LT (0x30) |
||||
#define NG_AT86RF2XX_PHY_TX_PWR_MASK__TX_PWR (0x0F) |
||||
#define NG_AT86RF2XX_PHY_TX_PWR_DEFAULT__PA_BUF_LT (0xC0) |
||||
#define NG_AT86RF2XX_PHY_TX_PWR_DEFAULT__PA_LT (0x00) |
||||
#define NG_AT86RF2XX_PHY_TX_PWR_DEFAULT__TX_PWR (0x00) |
||||
#define NG_AT86RF2XX_PHY_TX_PWR_TX_PWR_VALUE__3dBm (0x00) |
||||
#define NG_AT86RF2XX_PHY_TX_PWR_TX_PWR_VALUE__2_8dBm (0x01) |
||||
#define NG_AT86RF2XX_PHY_TX_PWR_TX_PWR_VALUE__2_3dBm (0x02) |
||||
#define NG_AT86RF2XX_PHY_TX_PWR_TX_PWR_VALUE__1_8dBm (0x03) |
||||
#define NG_AT86RF2XX_PHY_TX_PWR_TX_PWR_VALUE__1_3dBm (0x04) |
||||
#define NG_AT86RF2XX_PHY_TX_PWR_TX_PWR_VALUE__0_7dBm (0x05) |
||||
#define NG_AT86RF2XX_PHY_TX_PWR_TX_PWR_VALUE__0dBm (0x06) |
||||
#define NG_AT86RF2XX_PHY_TX_PWR_TX_PWR_VALUE__m1dBm (0x07) |
||||
#define NG_AT86RF2XX_PHY_TX_PWR_TX_PWR_VALUE__m2dBm (0x08) |
||||
#define NG_AT86RF2XX_PHY_TX_PWR_TX_PWR_VALUE__m3dBm (0x09) |
||||
#define NG_AT86RF2XX_PHY_TX_PWR_TX_PWR_VALUE__m4dBm (0x0A) |
||||
#define NG_AT86RF2XX_PHY_TX_PWR_TX_PWR_VALUE__m5dBm (0x0B) |
||||
#define NG_AT86RF2XX_PHY_TX_PWR_TX_PWR_VALUE__m7dBm (0x0C) |
||||
#define NG_AT86RF2XX_PHY_TX_PWR_TX_PWR_VALUE__m9dBm (0x0D) |
||||
#define NG_AT86RF2XX_PHY_TX_PWR_TX_PWR_VALUE__m12dBm (0x0E) |
||||
#define NG_AT86RF2XX_PHY_TX_PWR_TX_PWR_VALUE__m17dBm (0x0F) |
||||
/** @} */ |
||||
|
||||
/**
|
||||
* @brief Bitfield definitions for the PHY_RSSI register |
||||
* @{ |
||||
*/ |
||||
#define NG_AT86RF2XX_PHY_RSSI_MASK__RX_CRC_VALID (0x80) |
||||
#define NG_AT86RF2XX_PHY_RSSI_MASK__RND_VALUE (0x60) |
||||
#define NG_AT86RF2XX_PHY_RSSI_MASK__RSSI (0x1F) |
||||
/** @} */ |
||||
|
||||
/**
|
||||
* @brief Bitfield definitions for the XOSC_CTRL register |
||||
* @{ |
||||
*/ |
||||
#define NG_AT86RF2XX_XOSC_CTRL__XTAL_MODE_CRYSTAL (0xF0) |
||||
#define NG_AT86RF2XX_XOSC_CTRL__XTAL_MODE_EXTERNAL (0xF0) |
||||
/** @} */ |
||||
|
||||
/**
|
||||
* @brief Timing values |
||||
* @{ |
||||
*/ |
||||
#define NG_AT86RF2XX_TIMING__VCC_TO_P_ON (330) |
||||
#define NG_AT86RF2XX_TIMING__SLEEP_TO_TRX_OFF (380) |
||||
#define NG_AT86RF2XX_TIMING__TRX_OFF_TO_PLL_ON (110) |
||||
#define NG_AT86RF2XX_TIMING__TRX_OFF_TO_RX_ON (110) |
||||
#define NG_AT86RF2XX_TIMING__PLL_ON_TO_BUSY_TX (16) |
||||
#define NG_AT86RF2XX_TIMING__RESET (100) |
||||
#define NG_AT86RF2XX_TIMING__RESET_TO_TRX_OFF (37) |
||||
/** @} */ |
||||
|
||||
/**
|
||||
* @brief Bitfield definitions for the XAH_CTRL_1 register |
||||
* @{ |
||||
*/ |
||||
#define NG_AT86RF2XX_XAH_CTRL_1__AACK_FLTR_RES_FT (0x20) |
||||
#define NG_AT86RF2XX_XAH_CTRL_1__AACK_UPLD_RES_FT (0x10) |
||||
#define NG_AT86RF2XX_XAH_CTRL_1__AACK_ACK_TIME (0x04) |
||||
#define NG_AT86RF2XX_XAH_CTRL_1__AACK_PROM_MODE (0x02) |
||||
/** @} */ |
||||
|
||||
/**
|
||||
* @brief Bitfield definitions for the CSMA_SEED_1 register |
||||
* @{ |
||||
*/ |
||||
#define NG_AT86RF2XX_CSMA_SEED_1__AACK_SET_PD (0x20) |
||||
#define NG_AT86RF2XX_CSMA_SEED_1__AACK_DIS_ACK (0x10) |
||||
#define NG_AT86RF2XX_CSMA_SEED_1__AACK_I_AM_COORD (0x08) |
||||
/** @} */ |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* NG_AT86RF2XX_REGISTERS_H_ */ |
||||
/** @} */ |
@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Alaeddine Weslati <alaeddine.weslati@inria.fr> |
||||
* Copyright (C) 2015 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_ng_at86rf2xx |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Implementation of public functions for AT86RF2xx drivers |
||||
* |
||||
* @author Alaeddine Weslati <alaeddine.weslati@inria.fr> |
||||
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de> |
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de> |
||||
* @author Kaspar Schleiser <kaspar@schleiser.de> |
||||
* |
||||
* @} |
||||
*/ |
||||
|
||||
#include "hwtimer.h" |
||||
#include "periph/cpuid.h" |
||||
#include "net/ng_ieee802154.h" |
||||
#include "net/ng_netbase.h" |
||||
#include "ng_at86rf2xx_registers.h" |
||||
#include "ng_at86rf2xx_internal.h" |
||||
#include "ng_at86rf2xx_netdev.h" |
||||
|
||||
#define ENABLE_DEBUG (0) |
||||
#include "debug.h" |
||||
|
||||
|
||||
#define RESET_DELAY (0U) /* must be > 625ns */ |
||||
|
||||
|
||||
static void _irq_handler(void *arg) |
||||
{ |
||||
msg_t msg; |
||||
ng_at86rf2xx_t *dev = (ng_at86rf2xx_t *) arg; |
||||
|
||||
/* tell driver thread about the interrupt */ |
||||
msg.type = NG_NETDEV_MSG_TYPE_EVENT; |
||||
msg_send(&msg, dev->mac_pid); |
||||
} |
||||
|
||||
int ng_at86rf2xx_init(ng_at86rf2xx_t *dev, spi_t spi, spi_speed_t spi_speed, |
||||
gpio_t cs_pin, gpio_t int_pin, |
||||
gpio_t sleep_pin, gpio_t reset_pin) |
||||
{ |
||||
dev->driver = &ng_at86rf2xx_driver; |
||||
|
||||
/* initialize device descriptor */ |
||||
dev->spi = spi; |
||||
dev->cs_pin = cs_pin; |
||||
dev->int_pin = int_pin; |
||||
dev->sleep_pin = sleep_pin; |
||||
dev->reset_pin = reset_pin; |
||||
|
||||
/* initialise SPI */ |
||||
spi_init_master(dev->spi, SPI_CONF_FIRST_RISING, spi_speed); |
||||
/* initialise GPIOs */ |
||||
gpio_init_out(dev->cs_pin, GPIO_NOPULL); |
||||
gpio_set(dev->cs_pin); |
||||
gpio_init_out(dev->sleep_pin, GPIO_NOPULL); |
||||
gpio_clear(dev->sleep_pin); |
||||
gpio_init_out(dev->reset_pin, GPIO_NOPULL); |
||||
gpio_set(dev->reset_pin); |
||||
gpio_init_int(dev->int_pin, GPIO_NOPULL, GPIO_RISING, _irq_handler, dev); |
||||
|
||||
/* test if the SPI is set up correctly and the device is responding */ |
||||
if (ng_at86rf2xx_reg_read(dev, NG_AT86RF2XX_REG__PART_NUM) != |
||||
NG_AT86RF2XX_PARTNUM) { |
||||
DEBUG("[ng_at86rf2xx] error: unable to read correct part number\n"); |
||||
return -1; |
||||
} |
||||
|
||||
/* reset device to default values and put it into RX state */ |
||||
ng_at86rf2xx_reset(dev); |
||||
return 0; |
||||
} |
||||
|
||||
void ng_at86rf2xx_reset(ng_at86rf2xx_t *dev) |
||||
{ |
||||
uint8_t tmp; |
||||
#if CPUID_ID_LEN |
||||
uint8_t cpuid[CPUID_ID_LEN]; |
||||
uint16_t addr_short; |
||||
uint64_t addr_long; |
||||
#endif |
||||
|
||||
/* trigger hardware reset */ |
||||
gpio_clear(dev->reset_pin); |
||||
hwtimer_wait(HWTIMER_TICKS(RESET_DELAY)); |
||||
gpio_set(dev->reset_pin); |
||||
/* reset options and sequence number */ |
||||
dev->seq_nr = 0; |
||||
dev->options = 0; |
||||
/* set short and long address */ |
||||
#if CPUID_ID_LEN |
||||
cpuid_get(cpuid); |
||||
#if CPUID < 8 |
||||
/* in case CPUID_ID_LEN < 8, fill missing bytes with zeros */ |
||||
for (int i = CPUID_ID_LEN; i < 8; i++) { |
||||
cpuid[i] = 0; |
||||
} |
||||
#else |
||||
for (int i = 8; i < CPUID_ID_LEN; i++) { |
||||
cpuid[i & 0x07] ^= cpuid[i]; |
||||
} |
||||
#endif |
||||
/* make sure we mark the address as non-multicast and not globally unique */ |
||||
cpuid[0] &= ~(0x01); |
||||
cpuid[0] |= 0x02; |
||||
/* copy and set long address */ |
||||
memcpy(&addr_long, cpuid, 8); |
||||
ng_at86rf2xx_set_addr_long(dev, addr_long); |
||||
/* now compress the long addr to form the short address */ |
||||
for (int i = 2; i < 8; i++) { |
||||
cpuid[i & 0x01] ^= cpuid[i]; |
||||
} |
||||
memcpy(&addr_short, cpuid, 2); |
||||
ng_at86rf2xx_set_addr_short(dev, addr_short); |
||||
#else |
||||
ng_at86rf2xx_set_addr_long(dev, NG_AT86RF2XX_DEFAULT_ADDR_LONG); |
||||
ng_at86rf2xx_set_addr_short(dev, NG_AT86RF2XX_DEFAULT_ADDR_SHORT); |
||||
#endif |
||||
/* set default PAN id */ |
||||
ng_at86rf2xx_set_pan(dev, NG_AT86RF2XX_DEFAULT_PANID); |
||||
/* set default channel */ |
||||
ng_at86rf2xx_set_chan(dev, NG_AT86RF2XX_DEFAULT_CHANNEL); |
||||
/* set default TX power */ |
||||
ng_at86rf2xx_set_txpower(dev, NG_AT86RF2XX_DEFAULT_TXPOWER); |
||||
/* set default options */ |
||||
ng_at86rf2xx_set_option(dev, NG_AT86RF2XX_OPT_AUTOACK, true); |
||||
ng_at86rf2xx_set_option(dev, NG_AT86RF2XX_OPT_CSMA, true); |
||||
ng_at86rf2xx_set_option(dev, NG_AT86RF2XX_OPT_TELL_RX_END, true); |
||||
/* set default protocol */ |
||||
#ifdef MODULE_NG_SIXLOWPAN |
||||
dev->proto = NG_NETTYPE_SIXLOWPAN; |
||||
#else |
||||
dev->proto = NG_NETTYPE_UNDEF; |
||||
#endif |
||||
/* enable safe mode (protect RX FIFO until reading data starts) */ |
||||
tmp = NG_AT86RF2XX_TRX_CTRL_2_MASK__RX_SAFE_MODE; |
||||
#ifdef MODULE_NG_AT86RF212 |
||||
/* settings used by Linux 4.0rc at86rf212b driver */ |
||||
tmp |= (NG_AT86RF2XX_TRX_CTRL_2_MASK__SUB_MODE |
||||
| NG_AT86RF2XX_TRX_CTRL_2_MASK__OQPSK_SCRAM_EN); |
||||
#endif |
||||
ng_at86rf2xx_reg_write(dev, NG_AT86RF2XX_REG__TRX_CTRL_2, tmp); |
||||
/* enable interrupts */ |
||||
ng_at86rf2xx_reg_write(dev, NG_AT86RF2XX_REG__IRQ_MASK, |
||||
(NG_AT86RF2XX_IRQ_STATUS_MASK__RX_START | |
||||
NG_AT86RF2XX_IRQ_STATUS_MASK__TRX_END)); |
||||
/* go into RX state */ |
||||
ng_at86rf2xx_set_state(dev, NG_AT86RF2XX_STATE_RX_AACK_ON); |
||||
|
||||
DEBUG("ng_at86rf2xx_reset(): reset complete.\n"); |
||||
} |
||||
|
||||
bool ng_at86rf2xx_cca(ng_at86rf2xx_t *dev) |
||||
{ |
||||
uint8_t tmp; |
||||
uint8_t status; |
||||
|
||||
/* trigger CCA measurment */ |
||||
tmp = ng_at86rf2xx_reg_read(dev, NG_AT86RF2XX_REG__PHY_CC_CCA); |
||||
tmp &= NG_AT86RF2XX_PHY_CC_CCA_MASK__CCA_REQUEST; |
||||
ng_at86rf2xx_reg_write(dev, NG_AT86RF2XX_REG__PHY_CC_CCA, tmp); |
||||
/* wait for result to be ready */ |
||||
do { |
||||
status = ng_at86rf2xx_reg_read(dev, NG_AT86RF2XX_REG__TRX_STATUS); |
||||
} while (!(status & NG_AT86RF2XX_TRX_STATUS_MASK__CCA_DONE)); |
||||
/* return according to measurement */ |
||||
if (status & NG_AT86RF2XX_TRX_STATUS_MASK__CCA_STATUS) { |
||||
return true; |
||||
} |
||||
else { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
size_t ng_at86rf2xx_send(ng_at86rf2xx_t *dev, uint8_t *data, size_t len) |
||||
{ |
||||
/* check data length */ |
||||
if (len > NG_AT86RF2XX_MAX_PKT_LENGTH) { |
||||
DEBUG("[ng_at86rf2xx] Error: data to send exceeds max packet size\n"); |
||||
return 0; |
||||
} |
||||
ng_at86rf2xx_tx_prepare(dev); |
||||
ng_at86rf2xx_tx_load(dev, data, len, 0); |
||||
ng_at86rf2xx_tx_exec(dev); |
||||
return len; |
||||
} |
||||
|
||||
void ng_at86rf2xx_tx_prepare(ng_at86rf2xx_t *dev) |
||||
{ |
||||
uint8_t state; |
||||
|
||||
/* make sure ongoing transmissions are finished */ |
||||
do { |
||||
state = ng_at86rf2xx_get_state(dev); |
||||
} |
||||
while (state == NG_AT86RF2XX_STATE_BUSY_RX_AACK); |
||||
dev->idle_state = state; |
||||
ng_at86rf2xx_set_state(dev, NG_AT86RF2XX_STATE_TX_ARET_ON); |
||||
dev->frame_len = NG_IEEE802154_FCS_LEN; |
||||
} |
||||
|
||||
size_t ng_at86rf2xx_tx_load(ng_at86rf2xx_t *dev, uint8_t *data, |
||||
size_t len, size_t offset) |
||||
{ |
||||
dev->frame_len += (uint8_t)len; |
||||
ng_at86rf2xx_sram_write(dev, offset + 1, data, len); |
||||
return offset + len; |
||||
} |
||||
|
||||
void ng_at86rf2xx_tx_exec(ng_at86rf2xx_t *dev) |
||||
{ |
||||
/* write frame length field in FIFO */ |
||||
ng_at86rf2xx_sram_write(dev, 0, &(dev->frame_len), 1); |
||||
/* trigger sending of pre-loaded frame */ |
||||
ng_at86rf2xx_reg_write(dev, NG_AT86RF2XX_REG__TRX_STATE, |
||||
NG_AT86RF2XX_TRX_STATE__TX_START); |
||||
if (dev->event_cb && (dev->options & NG_AT86RF2XX_OPT_TELL_TX_START)) { |
||||
dev->event_cb(NETDEV_EVENT_TX_STARTED, NULL); |
||||
} |
||||
} |
||||
|
||||
size_t ng_at86rf2xx_rx_len(ng_at86rf2xx_t *dev) |
||||
{ |
||||
uint8_t res; |
||||
ng_at86rf2xx_fb_read(dev, &res, 1); |
||||
return (size_t)(res - 2); /* extract the PHR and LQI field */ |
||||
} |
||||
|
||||
void ng_at86rf2xx_rx_read(ng_at86rf2xx_t *dev, uint8_t *data, size_t len, |
||||
size_t offset) |
||||
{ |
||||
/* when reading from SRAM, the different chips from the AT86RF2xx family
|
||||
* behave differently: the AT86F233, the AT86RF232 and the ATRF86212B return |
||||
* frame length field (PHR) at position 0 and the first data byte at |
||||
* position 1. |
||||
* The AT86RF231 does not return the PHR field and return |
||||
* the first data byte at position 0. |
||||
*/ |
||||
#ifndef MODULE_NG_AT86RF231 |
||||
ng_at86rf2xx_sram_read(dev, offset + 1, data, len); |
||||
#else |
||||
ng_at86rf2xx_sram_read(dev, offset, data, len); |
||||
#endif |
||||
} |
@ -0,0 +1,234 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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_ng_at86rf2xx |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Getter and setter functions for the AT86RF2xx drivers |
||||
* |
||||
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de> |
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de> |
||||
* |
||||
* @} |
||||
*/ |
||||
|
||||
#include "ng_at86rf2xx.h" |
||||
#include "ng_at86rf2xx_internal.h" |
||||
#include "ng_at86rf2xx_registers.h" |
||||
#include "periph/spi.h" |
||||
|
||||
#define ENABLE_DEBUG (1) |
||||
#include "debug.h" |
||||
|
||||
|
||||
static const int16_t tx_pow_to_dbm[] = {3, 3, 2, 2, 1, 1, 0, |
||||
-1, -2, -3, -4, -5, -7, -9, -12, -17}; |
||||
|
||||
static const uint8_t dbm_to_tx_pow[] = {0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, |
||||
0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b, |
||||
0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, |
||||
0x05, 0x03, 0x00}; |
||||
|
||||
uint16_t ng_at86rf2xx_get_addr_short(ng_at86rf2xx_t *dev) |
||||
{ |
||||
return (dev->addr_short[0] << 8) | dev->addr_short[1]; |
||||
} |
||||
|
||||
void ng_at86rf2xx_set_addr_short(ng_at86rf2xx_t *dev, uint16_t addr) |
||||
{ |
||||
dev->addr_short[0] = addr >> 8; |
||||
dev->addr_short[1] = addr & 0xff; |
||||
ng_at86rf2xx_reg_write(dev, NG_AT86RF2XX_REG__SHORT_ADDR_0, |
||||
dev->addr_short[0]); |
||||
ng_at86rf2xx_reg_write(dev, NG_AT86RF2XX_REG__SHORT_ADDR_1, |
||||
dev->addr_short[1]); |
||||
} |
||||
|
||||
uint64_t ng_at86rf2xx_get_addr_long(ng_at86rf2xx_t *dev) |
||||
{ |
||||
uint64_t addr; |
||||
uint8_t *ap = (uint8_t *)(&addr); |
||||
for (int i = 0; i < 8; i++) { |
||||
ap[i] = dev->addr_long[7 - i]; |
||||
} |
||||
return addr; |
||||
} |
||||
|
||||
void ng_at86rf2xx_set_addr_long(ng_at86rf2xx_t *dev, uint64_t addr) |
||||
{ |
||||
for (int i = 0; i < 8; i++) { |
||||
dev->addr_long[i] = (addr >> ((7 - i) * 8)); |
||||
ng_at86rf2xx_reg_write(dev, (NG_AT86RF2XX_REG__IEEE_ADDR_0 + i), |
||||
dev->addr_long[i]); |
||||
} |
||||
} |
||||
|
||||
uint8_t ng_at86rf2xx_get_chan(ng_at86rf2xx_t *dev) |
||||
{ |
||||
uint8_t res = ng_at86rf2xx_reg_read(dev, NG_AT86RF2XX_REG__PHY_CC_CCA); |
||||
return (res & NG_AT86RF2XX_PHY_CC_CCA_MASK__CHANNEL); |
||||
} |
||||
|
||||
void ng_at86rf2xx_set_chan(ng_at86rf2xx_t *dev, uint8_t channel) |
||||
{ |
||||
uint8_t tmp; |
||||
|
||||
if (channel < NG_AT86RF2XX_MIN_CHANNEL |
||||
|| channel > NG_AT86RF2XX_MAX_CHANNEL) { |
||||
return; |
||||
} |
||||
tmp = ng_at86rf2xx_reg_read(dev, NG_AT86RF2XX_REG__PHY_CC_CCA); |
||||
tmp &= ~(NG_AT86RF2XX_PHY_CC_CCA_MASK__CHANNEL); |
||||
tmp |= (channel & NG_AT86RF2XX_PHY_CC_CCA_MASK__CHANNEL); |
||||
ng_at86rf2xx_reg_write(dev, NG_AT86RF2XX_REG__PHY_CC_CCA, tmp); |
||||
} |
||||
|
||||
uint16_t ng_at86rf2xx_get_pan(ng_at86rf2xx_t *dev) |
||||
{ |
||||
return dev->pan; |
||||
} |
||||
|
||||
void ng_at86rf2xx_set_pan(ng_at86rf2xx_t *dev, uint16_t pan) |
||||
{ |
||||
dev->pan = pan; |
||||
DEBUG("pan0: %u, pan1: %u\n", (uint8_t)pan, pan >> 8); |
||||
ng_at86rf2xx_reg_write(dev, NG_AT86RF2XX_REG__PAN_ID_0, (uint8_t)pan); |
||||
ng_at86rf2xx_reg_write(dev, NG_AT86RF2XX_REG__PAN_ID_1, (pan >> 8)); |
||||
} |
||||
|
||||
int16_t ng_at86rf2xx_get_txpower(ng_at86rf2xx_t *dev) |
||||
{ |
||||
uint8_t txpower = ng_at86rf2xx_reg_read(dev, NG_AT86RF2XX_REG__PHY_TX_PWR) |
||||
& NG_AT86RF2XX_PHY_TX_PWR_MASK__TX_PWR; |
||||
return tx_pow_to_dbm[txpower]; |
||||
} |
||||
|
||||
void ng_at86rf2xx_set_txpower(ng_at86rf2xx_t *dev, int16_t txpower) |
||||
{ |
||||
txpower += 17; |
||||
if (txpower < 0) { |
||||
txpower = 0; |
||||
} else if (txpower > 20) { |
||||
txpower = 20; |
||||
} |
||||
ng_at86rf2xx_reg_write(dev, NG_AT86RF2XX_REG__PHY_TX_PWR, |
||||
dbm_to_tx_pow[txpower]); |
||||
} |
||||
|
||||
void ng_at86rf2xx_set_option(ng_at86rf2xx_t *dev, uint16_t option, bool state) |
||||
{ |
||||
uint8_t tmp; |
||||
|
||||
DEBUG("set option %i to %i\n", option, state); |
||||
|
||||
/* set option field */ |
||||
if (state) { |
||||
dev->options |= option; |
||||
/* trigger option specific actions */ |
||||
switch (option) { |
||||
case NG_AT86RF2XX_OPT_CSMA: |
||||
DEBUG("[ng_at86rf2xx] opt: enabling CSMA mode\n"); |
||||
/* TODO: en/disable csma */ |
||||
break; |
||||
case NG_AT86RF2XX_OPT_PROMISCUOUS: |
||||
DEBUG("[ng_at86rf2xx] opt: enabling PROMISCUOUS mode\n"); |
||||
/* disable auto ACKs in promiscuous mode */ |
||||
tmp = ng_at86rf2xx_reg_read(dev, NG_AT86RF2XX_REG__CSMA_SEED_1); |
||||
tmp |= NG_AT86RF2XX_CSMA_SEED_1__AACK_DIS_ACK; |
||||
ng_at86rf2xx_reg_write(dev, NG_AT86RF2XX_REG__CSMA_SEED_1, tmp); |
||||
/* enable promiscuous mode */ |
||||
tmp = ng_at86rf2xx_reg_read(dev, NG_AT86RF2XX_REG__XAH_CTRL_1); |
||||
tmp |= NG_AT86RF2XX_XAH_CTRL_1__AACK_PROM_MODE; |
||||
ng_at86rf2xx_reg_write(dev, NG_AT86RF2XX_REG__XAH_CTRL_1, tmp); |
||||
break; |
||||
case NG_AT86RF2XX_OPT_AUTOACK: |
||||
DEBUG("[ng_at86rf2xx] opt: enabling auto ACKs\n"); |
||||
tmp = ng_at86rf2xx_reg_read(dev, NG_AT86RF2XX_REG__CSMA_SEED_1); |
||||
tmp &= ~(NG_AT86RF2XX_CSMA_SEED_1__AACK_DIS_ACK); |
||||
ng_at86rf2xx_reg_write(dev, NG_AT86RF2XX_REG__CSMA_SEED_1, tmp); |
||||
break; |
||||
default: |
||||
/* do nothing */ |
||||
break; |
||||
} |
||||
} |
||||
else { |
||||
dev->options &= ~(option); |
||||
/* trigger option specific actions */ |
||||
switch (option) { |
||||
case NG_AT86RF2XX_OPT_CSMA: |
||||
/* TODO: en/disable csma */ |
||||
break; |
||||
case NG_AT86RF2XX_OPT_PROMISCUOUS: |
||||
/* disable promiscuous mode */ |
||||
tmp = ng_at86rf2xx_reg_read(dev, NG_AT86RF2XX_REG__XAH_CTRL_1); |
||||
tmp &= ~(NG_AT86RF2XX_XAH_CTRL_1__AACK_PROM_MODE); |
||||
ng_at86rf2xx_reg_write(dev, NG_AT86RF2XX_REG__XAH_CTRL_1, tmp); |
||||
/* re-enable AUTOACK only if the option is set */ |
||||
if (dev->options & NG_AT86RF2XX_OPT_AUTOACK) { |
||||
tmp = ng_at86rf2xx_reg_read(dev, |
||||
NG_AT86RF2XX_REG__CSMA_SEED_1); |
||||
tmp &= ~(NG_AT86RF2XX_CSMA_SEED_1__AACK_DIS_ACK); |
||||
ng_at86rf2xx_reg_write(dev, NG_AT86RF2XX_REG__CSMA_SEED_1, |
||||
tmp); |
||||
} |
||||
break; |
||||
case NG_AT86RF2XX_OPT_AUTOACK: |
||||
tmp = ng_at86rf2xx_reg_read(dev, NG_AT86RF2XX_REG__CSMA_SEED_1); |
||||
tmp |= NG_AT86RF2XX_CSMA_SEED_1__AACK_DIS_ACK; |
||||
ng_at86rf2xx_reg_write(dev, NG_AT86RF2XX_REG__CSMA_SEED_1, tmp); |
||||
break; |
||||
default: |
||||
/* do nothing */ |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
uint8_t ng_at86rf2xx_get_state(ng_at86rf2xx_t *dev) |
||||
{ |
||||
uint8_t status = ng_at86rf2xx_get_status(dev); |
||||
return (status & 0x1f); |
||||
} |
||||
|
||||
static inline void _set_state(ng_at86rf2xx_t *dev, uint8_t state) |
||||
{ |
||||
ng_at86rf2xx_reg_write(dev, NG_AT86RF2XX_REG__TRX_STATE, state); |
||||
while (ng_at86rf2xx_get_state(dev) != state); |
||||
} |
||||
|
||||
void ng_at86rf2xx_set_state(ng_at86rf2xx_t *dev, uint8_t state) |
||||
{ |
||||
uint8_t old_state = ng_at86rf2xx_get_state(dev); |
||||
|
||||
if (state == old_state) { |
||||
return; |
||||
} |
||||
/* make sure there is no ongoing transmission */ |
||||
while (old_state == NG_AT86RF2XX_STATE_BUSY_RX_AACK || |
||||
old_state == NG_AT86RF2XX_STATE_BUSY_TX_ARET) { |
||||
old_state = ng_at86rf2xx_get_state(dev); |
||||
} |
||||
/* check if we need to wake up from sleep mode */ |
||||
if (old_state == NG_AT86RF2XX_STATE_SLEEP) { |
||||
DEBUG("at86rf2xx: waking up from sleep mode\n"); |
||||
gpio_clear(dev->sleep_pin); |
||||
while (ng_at86rf2xx_get_state(dev) != NG_AT86RF2XX_STATE_TRX_OFF); |
||||
} |
||||
/* go to neutral TRX_OFF state */ |
||||
_set_state(dev, NG_AT86RF2XX_STATE_TRX_OFF); |
||||
if (state == NG_AT86RF2XX_STATE_RX_AACK_ON || |
||||
state == NG_AT86RF2XX_STATE_TX_ARET_ON) { |
||||
_set_state(dev, state); |
||||
} else if (state == NG_AT86RF2XX_STATE_SLEEP) { |
||||
gpio_set(dev->sleep_pin); |
||||
while (ng_at86rf2xx_get_state(dev) != NG_AT86RF2XX_STATE_SLEEP); |
||||
} |
||||
} |
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Alaeddine Weslati <alaeddine.weslati@inria.fr> |
||||
* Copyright (C) 2015 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_ng_at86rf2xx |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Implementation of driver internal functions |
||||
* |
||||
* @author Alaeddine Weslati <alaeddine.weslati@inria.fr> |
||||
* @author Thomas Eichinger <thomas.eichinger@fu-berlin.de> |
||||
* @author Joakim Gebart <joakim.gebart@eistec.se> |
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de> |
||||
* |
||||
* @} |
||||
*/ |
||||
|
||||
#include "periph/spi.h" |
||||
#include "periph/gpio.h" |
||||
#include "ng_at86rf2xx_internal.h" |
||||
#include "ng_at86rf2xx_registers.h" |
||||
|
||||
void ng_at86rf2xx_reg_write(const ng_at86rf2xx_t *dev, |
||||
const uint8_t addr, |
||||
const uint8_t value) |
||||
{ |
||||
spi_acquire(dev->spi); |
||||
gpio_clear(dev->cs_pin); |
||||
spi_transfer_reg(dev->spi, |
||||
NG_AT86RF2XX_ACCESS_REG | NG_AT86RF2XX_ACCESS_WRITE | addr, |
||||
value, 0); |
||||
gpio_set(dev->cs_pin); |
||||
spi_release(dev->spi); |
||||
} |
||||
|
||||
uint8_t ng_at86rf2xx_reg_read(const ng_at86rf2xx_t *dev, const uint8_t addr) |
||||
{ |
||||
char value; |
||||
|
||||
spi_acquire(dev->spi); |
||||
gpio_clear(dev->cs_pin); |
||||
spi_transfer_reg(dev->spi, |
||||
NG_AT86RF2XX_ACCESS_REG | NG_AT86RF2XX_ACCESS_READ | addr, |
||||
0, &value); |
||||
gpio_set(dev->cs_pin); |
||||
spi_release(dev->spi); |
||||
|
||||
return (uint8_t)value; |
||||
} |
||||
|
||||
void ng_at86rf2xx_sram_read(const ng_at86rf2xx_t *dev, |
||||
const uint8_t offset, |
||||
uint8_t *data, |
||||
const size_t len) |
||||
{ |
||||
spi_acquire(dev->spi); |
||||
gpio_clear(dev->cs_pin); |
||||
spi_transfer_reg(dev->spi, |
||||
NG_AT86RF2XX_ACCESS_SRAM | NG_AT86RF2XX_ACCESS_READ, |
||||
(char)offset, NULL); |
||||
spi_transfer_bytes(dev->spi, NULL, (char*)data, len); |
||||
gpio_set(dev->cs_pin); |
||||
spi_release(dev-> |