Skip to content

Commit

Permalink
drivers/at86rf2xx: atmega256rfr2 support
Browse files Browse the repository at this point in the history
  • Loading branch information
Josar committed Oct 29, 2018
1 parent 17a3e22 commit a073584
Show file tree
Hide file tree
Showing 15 changed files with 784 additions and 44 deletions.
5 changes: 5 additions & 0 deletions boards/jiminy-mega256rfr2/Makefile.dep
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
# export board specific dependencies to the global includes-listing
USEMODULE += boards_common_atmega

ifneq (, $(filter gnrc_netdev_default netdev_default, $(USEMODULE)))
USEMODULE += at86rfr2
endif
1 change: 1 addition & 0 deletions boards/jiminy-mega256rfr2/Makefile.features
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ include $(RIOTBOARD)/common/arduino-atmega/Makefile.features
# Put defined MCU peripherals here (in alphabetical order)
# Peripherals are defined in common/arduino-atmega/Makefile.features
# Add only additional Peripherals
FEATURES_PROVIDED += radio_at86rf2xx

# The board MPU family (used for grouping by the CI system)
FEATURES_MCU_GROUP = avr6
Expand Down
8 changes: 6 additions & 2 deletions boards/jiminy-mega256rfr2/include/board.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ extern "C" {
* is to use double speed.
*
* For 8MHz F_CPU following Baudrate have good error rates
* 76923
* 38400
* 76800
* 38400 Seems to fast for long byte streams, collecting in interrupt to slow.
* 19200
* 9600
*
* Matches this with BAUD in Board/Makefile.include
*
Expand Down Expand Up @@ -81,6 +83,8 @@ extern "C" {
#define XTIMER_CHAN (0)
#define XTIMER_WIDTH (16)
#define XTIMER_HZ (125000UL)
#define XTIMER_OVERHEAD (33)
#define XTIMER_ISR_BACKOFF (40)
/** @} */

/**
Expand Down
4 changes: 3 additions & 1 deletion drivers/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,19 @@ ifneq (,$(filter at30tse75x,$(USEMODULE)))
FEATURES_REQUIRED += periph_i2c
endif

ifneq (,$(filter at86rf2%,$(USEMODULE)))
ifneq (,$(filter at86rf2% at86rfr2,$(USEMODULE)))
USEMODULE += at86rf2xx
USEMODULE += xtimer
USEMODULE += luid
USEMODULE += netif
USEMODULE += ieee802154
USEMODULE += netdev_ieee802154
ifneq (,$(filter at86rf2%,$(USEMODULE)))
FEATURES_REQUIRED += periph_gpio
FEATURES_REQUIRED += periph_gpio_irq
FEATURES_REQUIRED += periph_spi
endif
endif

ifneq (,$(filter ata8520e,$(USEMODULE)))
USEMODULE += xtimer
Expand Down
85 changes: 80 additions & 5 deletions drivers/at86rf2xx/at86rf2xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
#define ENABLE_DEBUG (0)
#include "debug.h"

#include "board.h"
#define ENABLE_HEX_DUMP_TX (0)
#if ENABLE_HEX_DUMP_TX
#include "od.h"
#endif

void at86rf2xx_setup(at86rf2xx_t *dev, const at86rf2xx_params_t *params)
{
Expand All @@ -50,12 +55,27 @@ void at86rf2xx_setup(at86rf2xx_t *dev, const at86rf2xx_params_t *params)
/* radio state is P_ON when first powered-on */
dev->state = AT86RF2XX_STATE_P_ON;
dev->pending_tx = 0;

#ifdef MODULE_AT86RFR2
/* Store device pointer for interrupts */
at86rfr2_dev = (netdev_t *)dev;

/* set all interrupts off */
at86rf2xx_reg_write(dev, AT86RF2XX_REG__IRQ_MASK, 0x00);
at86rf2xx_reg_write(dev, AT86RF2XX_REG__IRQ_MASK1, 0x00);

#if defined(RXTX_LED_ENABLE) || defined(DEBUG_ATRFR2_PINS)
enable_rxtx_led();
#endif
#endif
}

void at86rf2xx_reset(at86rf2xx_t *dev)
{
eui64_t addr_long;

DEBUG("at86rf2xx_reset(): start.\n");

at86rf2xx_hardware_reset(dev);

netdev_ieee802154_reset(&dev->netdev);
Expand Down Expand Up @@ -92,11 +112,6 @@ void at86rf2xx_reset(at86rf2xx_t *dev)
at86rf2xx_reg_write(dev, AT86RF2XX_REG__TRX_CTRL_2,
AT86RF2XX_TRX_CTRL_2_MASK__RX_SAFE_MODE);

/* don't populate masked interrupt flags to IRQ_STATUS register */
uint8_t tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_CTRL_1);
tmp &= ~(AT86RF2XX_TRX_CTRL_1_MASK__IRQ_MASK_MODE);
at86rf2xx_reg_write(dev, AT86RF2XX_REG__TRX_CTRL_1, tmp);

#ifdef MODULE_AT86RF212B
at86rf2xx_set_page(dev, AT86RF2XX_DEFAULT_PAGE);
#endif
Expand All @@ -113,6 +128,57 @@ void at86rf2xx_reset(at86rf2xx_t *dev)
at86rf2xx_set_rxsensitivity(dev, RSSI_BASE_VAL);
#endif

#ifdef MODULE_AT86RFR2
at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_RX_START, false);
at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_RX_END, true);

/* TODO enable necessary interrupts, investigate if other interrupts could be useful */

/* enable interrupts IRQ_MASK */
at86rf2xx_reg_write(dev,
AT86RF2XX_REG__IRQ_MASK,
/* not used in spi driver */
/* AT86RF2XX_IRQ_STATUS_MASK__AWAKE */
/* used in spi driver */
AT86RF2XX_IRQ_STATUS_MASK__TX_END
/* maybe could be used for ED/RSSI readout */
/* | AT86RF2XX_IRQ_STATUS_MASK__AMI */
/* not used in spi driver */
/* | AT86RF2XX_IRQ_STATUS_MASK__CCA_ED_DONE */
| AT86RF2XX_IRQ_STATUS_MASK__RX_END
/* NEVER use in Extended Op. Mode */
/* | AT86RF2XX_IRQ_STATUS_MASK__RX_START */
/* not used in spi driver */
/* | AT86RF2XX_IRQ_STATUS_MASK__PLL_UNLOCK */
/* not used in spi driver */
/* | AT86RF2XX_IRQ_STATUS_MASK__PLL_LOCK */
);

/* enable interrupts IRQ_MASK1*/
at86rf2xx_reg_write(dev, AT86RF2XX_REG__IRQ_MASK1,
/* used for retry counter*/
AT86RF2XX_IRQ_STATUS_MASK1__TX_START
/* | AT86RF2XX_IRQ_STATUS_MASK1__MAF_0_AMI */
/* | AT86RF2XX_IRQ_STATUS_MASK1__MAF_1_AMI */
/* | AT86RF2XX_IRQ_STATUS_MASK1__MAF_2_AMI */
/* | AT86RF2XX_IRQ_STATUS_MASK1__MAF_3_AMI */
);

/* clear interrupt flags by writing corresponding bit */
at86rf2xx_reg_write(dev, AT86RF2XX_REG__IRQ_STATUS, 0xff);
at86rf2xx_reg_write(dev, AT86RF2XX_REG__IRQ_STATUS1, 0xff);
/* clear frame buffer protection */
*AT86RF2XX_REG__TRX_CTRL_2 &= ~(1 << RX_SAFE_MODE);

/* set PLL on */
at86rf2xx_set_state(dev, AT86RF2XX_STATE_PLL_ON);
#else

/* don't populate masked interrupt flags to IRQ_STATUS register */
uint8_t tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_CTRL_1);
tmp &= ~(AT86RF2XX_TRX_CTRL_1_MASK__IRQ_MASK_MODE);
at86rf2xx_reg_write(dev, AT86RF2XX_REG__TRX_CTRL_1, tmp);

/* disable clock output to save power */
tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_CTRL_0);
tmp &= ~(AT86RF2XX_TRX_CTRL_0_MASK__CLKM_CTRL);
Expand All @@ -126,6 +192,7 @@ void at86rf2xx_reset(at86rf2xx_t *dev)
/* enable interrupts */
at86rf2xx_reg_write(dev, AT86RF2XX_REG__IRQ_MASK,
AT86RF2XX_IRQ_STATUS_MASK__TRX_END);
#endif

/* State to return after receiving or transmitting */
dev->idle_state = AT86RF2XX_STATE_RX_AACK_ON;
Expand Down Expand Up @@ -174,6 +241,14 @@ void at86rf2xx_tx_exec(const at86rf2xx_t *dev)

/* write frame length field in FIFO */
at86rf2xx_sram_write(dev, 0, &(dev->tx_frame_len), 1);
#if ENABLE_HEX_DUMP_TX
uint8_t len = dev->tx_frame_len;
uint8_t data[len];
memcpy( data, (void *)(AT86RF2XX_REG__TRXFBST), len);
puts("SENDING:");
od_hex_dump(data, len, OD_WIDTH_DEFAULT);
#endif

/* trigger sending of pre-loaded frame */
at86rf2xx_reg_write(dev, AT86RF2XX_REG__TRX_STATE,
AT86RF2XX_TRX_STATE__TX_START);
Expand Down
75 changes: 74 additions & 1 deletion drivers/at86rf2xx/at86rf2xx_getset.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2015 Freie Universität Berlin
* 2017 HAW Hamburg
* 2018 RWTH Aachen
*
* 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
Expand All @@ -21,13 +22,17 @@
* @author Kévin Roussel <Kevin.Roussel@inria.fr>
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
* @author Sebastian Meiling <s@mlng.net>
* @author Josua Arndt <jarndt@ias.rwth-aachen.de>
* @}
*/

#include "at86rf2xx.h"
#include "at86rf2xx_internal.h"
#include "at86rf2xx_registers.h"

#ifndef MODULE_AT86RFR2
#include "periph/spi.h"
#endif

#define ENABLE_DEBUG (0)
#include "debug.h"
Expand Down Expand Up @@ -109,6 +114,12 @@ static const uint8_t dbm_to_rx_sens[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0a, 0x0b, 0x0b, 0x0b, 0x0c, 0x0c,
0x0c, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e,
0x0e, 0x0f };
#elif MODULE_AT86RFR2
/* {3.5, 3.3, 2.8, 2.3, 1.8, 1.2, 0.5,
* -0.5, -1.5, -2.5, -3.5, -4.5, -6.5, -8.5, -11.5, -16.5};
*/
static const int16_t tx_pow_to_dbm[] = { 4, 3, 3, 2, 2, 1, 0,
-1, -2, -3, -4, -5, -6, -7, -12, -17 };
#else
static const int16_t tx_pow_to_dbm[] = { 3, 3, 2, 2, 1, 1, 0,
-1, -2, -3, -4, -5, -7, -9, -12, -17 };
Expand Down Expand Up @@ -234,6 +245,10 @@ int16_t at86rf2xx_get_txpower(const at86rf2xx_t *dev)
uint8_t txpower = at86rf2xx_reg_read(dev, AT86RF2XX_REG__PHY_TX_PWR);
DEBUG("txpower value: %x\n", txpower);
return _tx_pow_to_dbm_212b(dev->netdev.chan, dev->page, txpower);
#elif defined(MODULE_AT86RFR2)
(void)dev;
uint8_t txpower = *AT86RF2XX_REG__PHY_TX_PWR & AT86RF2XX_PHY_TX_PWR_MASK__TX_PWR;
return tx_pow_to_dbm[txpower];
#else
uint8_t txpower = at86rf2xx_reg_read(dev, AT86RF2XX_REG__PHY_TX_PWR)
& AT86RF2XX_PHY_TX_PWR_MASK__TX_PWR;
Expand All @@ -243,6 +258,16 @@ int16_t at86rf2xx_get_txpower(const at86rf2xx_t *dev)

void at86rf2xx_set_txpower(const at86rf2xx_t *dev, int16_t txpower)
{
#ifdef MODULE_AT86RFR2
/* find the right configuration which is the nearest to the transmit power
* take the next value, it is the next smaller than the requested.
*/
unsigned int i = 0;
while (tx_pow_to_dbm[i] > txpower) {
i++;
}
at86rf2xx_reg_write(dev, AT86RF2XX_REG__PHY_TX_PWR, i);
#else /* END MODULE_AT86RFR2 */
txpower += AT86RF2XX_TXPOWER_OFF;

if (txpower < 0) {
Expand All @@ -264,17 +289,42 @@ void at86rf2xx_set_txpower(const at86rf2xx_t *dev, int16_t txpower)
at86rf2xx_reg_write(dev, AT86RF2XX_REG__PHY_TX_PWR,
dbm_to_tx_pow[txpower]);
#endif
#endif /* END other then MODULE_AT86RFR2 */
}

int16_t at86rf2xx_get_rxsensitivity(const at86rf2xx_t *dev)
{
#if defined(MODULE_AT86RFR2)
(void)dev;
uint8_t rxsens = *AT86RF2XX_REG__RX_SYN & AT86RF2XX_RX_SYN__RX_PDT_LEVEL;
if (rxsens == 0){
return RSSI_BASE_VAL;
}else {
return RSSI_BASE_VAL + 3*(rxsens-1);
}
#else
uint8_t rxsens = at86rf2xx_reg_read(dev, AT86RF2XX_REG__RX_SYN)
& AT86RF2XX_RX_SYN__RX_PDT_LEVEL;
return rx_sens_to_dbm[rxsens];
#endif
}

void at86rf2xx_set_rxsensitivity(const at86rf2xx_t *dev, int16_t rxsens)
{
#if MODULE_AT86RFR2
(void)dev;
/* Always set the treshhold which at least limits the requested value.
* requesting -50dBm will result in -48dBm */
rxsens = (rxsens - RSSI_BASE_VAL)/3;
if (rxsens >14){
rxsens =14;
}else if(rxsens <0){
rxsens =0;
}else{
rxsens +=1;
}
*AT86RF2XX_REG__RX_SYN = (*AT86RF2XX_REG__RX_SYN & ~(AT86RF2XX_RX_SYN__RX_PDT_LEVEL)) | rxsens;
#else
rxsens += MIN_RX_SENSITIVITY;

if (rxsens < 0) {
Expand All @@ -288,6 +338,7 @@ void at86rf2xx_set_rxsensitivity(const at86rf2xx_t *dev, int16_t rxsens)
tmp &= ~(AT86RF2XX_RX_SYN__RX_PDT_LEVEL);
tmp |= (dbm_to_rx_sens[rxsens] & AT86RF2XX_RX_SYN__RX_PDT_LEVEL);
at86rf2xx_reg_write(dev, AT86RF2XX_REG__RX_SYN, tmp);
#endif
}

uint8_t at86rf2xx_get_max_retries(const at86rf2xx_t *dev)
Expand Down Expand Up @@ -447,6 +498,16 @@ void at86rf2xx_set_option(at86rf2xx_t *dev, uint16_t option, bool state)
: (tmp & ~AT86RF2XX_IRQ_STATUS_MASK__RX_START);
at86rf2xx_reg_write(dev, AT86RF2XX_REG__IRQ_MASK, tmp);
break;
#ifdef MODULE_AT86RFR2
case AT86RF2XX_OPT_TELL_TX_END:
DEBUG("[at86rf2xx] opt: %s TX END IRQ\n",
(state ? "enable" : "disable"));
tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__IRQ_MASK);
tmp = (state) ? (tmp | AT86RF2XX_IRQ_STATUS_MASK__TX_END)
: (tmp & ~AT86RF2XX_IRQ_STATUS_MASK__TX_END);
at86rf2xx_reg_write(dev, AT86RF2XX_REG__IRQ_MASK, tmp);
break;
#endif
case AT86RF2XX_OPT_ACK_PENDING:
DEBUG("[at86rf2xx] opt: enabling pending ACKs\n");
tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__CSMA_SEED_1);
Expand Down Expand Up @@ -480,7 +541,9 @@ static inline void _set_state(at86rf2xx_t *dev, uint8_t state, uint8_t cmd)
* in https://github.com/RIOT-OS/RIOT/pull/5244
*/
if (state != AT86RF2XX_STATE_RX_AACK_ON) {
while (at86rf2xx_get_status(dev) != state) {}
while (at86rf2xx_get_status(dev) != state) {
DEBUG("_set_state: state is: 0x%02x\n", state);
}
}
/* Although RX_AACK_ON state doesn't get read back,
* at least make sure if state transition is in progress or not
Expand All @@ -500,6 +563,7 @@ uint8_t at86rf2xx_set_state(at86rf2xx_t *dev, uint8_t state)
* in progress */
do {
old_state = at86rf2xx_get_status(dev);
DEBUG("at86rf2xx_set_state: 0x%02x old_state is: 0x%02x\n", state, old_state);
} while (old_state == AT86RF2XX_STATE_BUSY_RX_AACK ||
old_state == AT86RF2XX_STATE_BUSY_TX_ARET ||
old_state == AT86RF2XX_STATE_IN_PROGRESS);
Expand All @@ -523,7 +587,15 @@ uint8_t at86rf2xx_set_state(at86rf2xx_t *dev, uint8_t state)
/* Discard all IRQ flags, framebuffer is lost anyway */
at86rf2xx_reg_read(dev, AT86RF2XX_REG__IRQ_STATUS);
/* Go to SLEEP mode from TRX_OFF */
#ifdef MODULE_AT86RFR2
/* reset interrupts states in device */
dev->irq_status = 0;
dev->irq_status1 = 0;
/* Setting SLPTR bit brings radio transceiver to sleep in in TRX_OFF*/
*AT86RF2XX_REG__TRXPR |= (AT86RF2XX_TRXPR_SLPTR);
#else
gpio_set(dev->params.sleep_pin);
#endif
dev->state = state;
}
else {
Expand All @@ -535,5 +607,6 @@ uint8_t at86rf2xx_set_state(at86rf2xx_t *dev, uint8_t state)
}
}

DEBUG("at86rf2xx_set_state: new state is: 0x%02x\n\n", at86rf2xx_get_status(dev));
return old_state;
}
Loading

0 comments on commit a073584

Please sign in to comment.