Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion drivers/at86rf215/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
SRC := at86rf215.c at86rf215_getset.c at86rf215_netdev.c at86rf215_internal.c
SRC := at86rf215.c at86rf215_getset.c at86rf215_radio_ops.c at86rf215_internal.c

ifneq (,$(filter netdev_ieee802154_mr_ofdm,$(USEMODULE)))
SRC += at86rf215_ofdm.c
Expand Down
11 changes: 7 additions & 4 deletions drivers/at86rf215/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ FEATURES_REQUIRED += periph_gpio
FEATURES_REQUIRED += periph_gpio_irq
FEATURES_REQUIRED += periph_spi

USEMODULE += xtimer
USEMODULE += ieee802154
USEMODULE += netdev_ieee802154
USEMODULE += netdev_new_api
USEMODULE += ztimer_usec
USEMODULE += event_thread
USEMODULE += event_thread_highest

ifneq (,$(filter netdev,$(USEMODULE)))
USEMODULE += netdev_ieee802154_submac
endif
309 changes: 27 additions & 282 deletions drivers/at86rf215/at86rf215.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,97 +14,15 @@
* @}
*/

#include "board.h"
#include "byteorder.h"
#include "net/ieee802154.h"
#include "net/gnrc.h"
#include "unaligned.h"
#include "at86rf215.h"
#include "at86rf215_internal.h"
#include "at86rf215_netdev.h"
#include "kernel_defines.h"

#define ENABLE_DEBUG 0
#include "debug.h"

static void _setup_interface(at86rf215_t *dev, const at86rf215_params_t *params, uint8_t index)
{
netdev_t *netdev = &dev->netdev.netdev;

netdev->driver = &at86rf215_driver;
dev->params = *params;
dev->state = AT86RF215_STATE_OFF;

netdev_register(netdev, NETDEV_AT86RF215, index);
}

void at86rf215_setup(at86rf215_t *dev_09, at86rf215_t *dev_24, const at86rf215_params_t *params, uint8_t index)
{
/* configure the sub-GHz interface */
if (dev_09) {
dev_09->RF = &RF09_regs;
dev_09->BBC = &BBC0_regs;
_setup_interface(dev_09, params, 2 * index);
dev_09->sibling = dev_24;
}

/* configure the 2.4 GHz interface */
if (dev_24) {
dev_24->RF = &RF24_regs;
dev_24->BBC = &BBC1_regs;
_setup_interface(dev_24, params, 2 * index + 1);
dev_24->sibling = dev_09;
}
}

void at86rf215_reset_and_cfg(at86rf215_t *dev)
{
netdev_ieee802154_reset(&dev->netdev);

/* set device address */
netdev_ieee802154_setup(&dev->netdev);

if (is_subGHz(dev)) {
dev->netdev.chan = CONFIG_AT86RF215_DEFAULT_SUBGHZ_CHANNEL;
} else {
dev->netdev.chan = CONFIG_AT86RF215_DEFAULT_CHANNEL;
}

dev->netdev.pan = CONFIG_IEEE802154_DEFAULT_PANID;

/* set default options */
dev->retries_max = AT86RF215_RETRIES_MAX_DEFAULT;
dev->csma_retries_max = AT86RF215_CSMA_RETRIES_MAX_DEFAULT;
dev->csma_maxbe = AT86RF215_CSMA_MAX_BE_DEFAULT;
dev->csma_minbe = AT86RF215_CSMA_MIN_BE_DEFAULT;

dev->flags |= AT86RF215_OPT_AUTOACK
| AT86RF215_OPT_CSMA
#if CONFIG_AT86RF215_RPC_EN
| AT86RF215_OPT_RPC
#endif
;

/* apply the configuration */
at86rf215_reset(dev);

/* default to requesting ACKs, just like at86rf2xx */
static const netopt_enable_t ack_req =
IS_ACTIVE(CONFIG_IEEE802154_DEFAULT_ACK_REQ) ? NETOPT_ENABLE : NETOPT_DISABLE;
netdev_ieee802154_set(&dev->netdev, NETOPT_ACK_REQ,
&ack_req, sizeof(ack_req));

/* enable RX start IRQs */
at86rf215_reg_or(dev, dev->BBC->RG_IRQM, BB_IRQ_RXAM);
}

void at86rf215_reset(at86rf215_t *dev)
{
uint8_t reg;
dev->state = AT86RF215_STATE_OFF;

/* Reset state machine to ensure a known state */
at86rf215_rf_cmd(dev, CMD_RF_TRXOFF);
at86rf215_await_state(dev, RF_STATE_TRXOFF);
dev->state = AT86RF215_STATE_TRXOFF;

if (!dev->sibling) {
/* disable 2.4-GHz IRQs if the interface is not enabled */
Expand All @@ -130,224 +48,51 @@ if (!IS_ACTIVE(CONFIG_AT86RF215_USE_CLOCK_OUTPUT)){
at86rf215_set_trim(dev, CONFIG_AT86RF215_TRIM_VAL);
#endif

/* enable TXFE & RXFE IRQ */
at86rf215_reg_write(dev, dev->BBC->RG_IRQM, BB_IRQ_TXFE | BB_IRQ_RXFE);

/* enable EDC IRQ */
at86rf215_reg_write(dev, dev->RF->RG_IRQM, RF_IRQ_EDC | RF_IRQ_TRXRDY);

/* set energy detect threshold to -84 dBm */
at86rf215_set_cca_threshold(dev, AT86RF215_EDT_DEFAULT);
#if CONFIG_AT86RF215_RPC_EN
dev->rpc_enable = true;
#else
dev->rpc_enable = false;
#endif

/* enable address filter 0 */
at86rf215_reg_write(dev, dev->BBC->RG_AFC0, AFC0_AFEN0_MASK );
at86rf215_reg_write(dev, dev->BBC->RG_AMAACKPD, AMAACKPD_PD0_MASK);
/* enable fcs filter */
at86rf215_reg_or(dev, dev->BBC->RG_PC, PC_FCSFE_MASK);

/* enable auto-ACK with Frame Checksum & Data Rate derived from RX frame */
reg = AMCS_AACKFA_MASK | AMCS_AACKDR_MASK;
if (dev->flags & AT86RF215_OPT_AUTOACK) {
reg |= AMCS_AACK_MASK;
}

if (IS_USED(MODULE_AT86RF215_TIMESTAMP)) {
if (IS_USED(MODULE_IEEE802154_RX_TIMESTAMP)) {
at86rf215_reg_write(dev, dev->BBC->RG_CNTC,
CNTC_EN_MASK | CNTC_CAPRXS_MASK);
}
at86rf215_reg_write(dev, dev->BBC->RG_AMCS, reg);

if (CONFIG_AT86RF215_DEFAULT_PHY_MODE == IEEE802154_PHY_OQPSK) {
at86rf215_configure_legacy_OQPSK(dev, CONFIG_AT86RF215_DEFAULT_OQPSK_RATE);
}
if (CONFIG_AT86RF215_DEFAULT_PHY_MODE == IEEE802154_PHY_MR_OQPSK) {
at86rf215_configure_OQPSK(dev, CONFIG_AT86RF215_DEFAULT_MR_OQPSK_CHIPS,
CONFIG_AT86RF215_DEFAULT_MR_OQPSK_RATE);
}
if (CONFIG_AT86RF215_DEFAULT_PHY_MODE == IEEE802154_PHY_MR_OFDM) {
at86rf215_configure_OFDM(dev, CONFIG_AT86RF215_DEFAULT_MR_OFDM_OPT,
CONFIG_AT86RF215_DEFAULT_MR_OFDM_MCS);
}
if (CONFIG_AT86RF215_DEFAULT_PHY_MODE == IEEE802154_PHY_MR_FSK) {
at86rf215_configure_FSK(dev, CONFIG_AT86RF215_DEFAULT_MR_FSK_SRATE,
CONFIG_AT86RF215_DEFAULT_MR_FSK_MOD_IDX,
CONFIG_AT86RF215_DEFAULT_MR_FSK_MORD,
CONFIG_AT86RF215_DEFAULT_MR_FSK_FEC);
}

/* set default channel */
at86rf215_set_chan(dev, dev->netdev.chan);

/* set short and long address */
uint64_t long_addr;
memcpy(&long_addr, dev->netdev.long_addr, sizeof(long_addr));
at86rf215_set_addr_long(dev, long_addr);
at86rf215_set_addr_short(dev, 0, unaligned_get_u16(dev->netdev.short_addr));

/* set default PAN id */
at86rf215_set_pan(dev, 0, dev->netdev.pan);

/* set default TX power */
at86rf215_set_txpower(dev, CONFIG_AT86RF215_DEFAULT_TXPOWER);

/* start listening for incoming packets */
at86rf215_rf_cmd(dev, CMD_RF_RX);
at86rf215_await_state(dev, RF_STATE_RX);

dev->state = AT86RF215_STATE_IDLE;
}

ssize_t at86rf215_send(at86rf215_t *dev, const void *data, size_t len)
{
/* check data length */
if (len > AT86RF215_MAX_PKT_LENGTH) {
DEBUG("[at86rf215] Error: data to send exceeds max packet size\n");
return -EOVERFLOW;
}

if (at86rf215_tx_prepare(dev)) {
return -EBUSY;
}
/* enable auto-ACK with Frame Checksum & Data Rate derived from RX frame */
uint8_t reg = AMCS_AACKFA_MASK | AMCS_AACKDR_MASK | AMCS_AACK_MASK;
dev->auto_mode = AT86RF215_AM_AUTO_ACK;
/* send acks respective to 802.15.4-2006 */
reg &= ~AMCS_AACKS_MASK;
/* disable cca before tx and tx2rx to avoid conflicts */
reg &= ~AMCS_CCATX_MASK;
reg &= ~AMCS_TX2RX_MASK;
at86rf215_reg_write(dev, dev->BBC->RG_AMCS, reg);

at86rf215_tx_load(dev, data, len, 0);
at86rf215_tx_exec(dev);
return len;
/* enable IRQS */
at86rf215_reg_write(dev, dev->BBC->RG_IRQM, BB_IRQ_RXFS | BB_IRQ_TXFE | BB_IRQ_RXFE);
at86rf215_reg_write(dev, dev->RF->RG_IRQM, RF_IRQ_EDC | RF_IRQ_TRXRDY);
}

void at86rf215_tx_done(at86rf215_t *dev)
{
uint8_t amcs = at86rf215_reg_read(dev, dev->BBC->RG_AMCS);

/* re-enable AACK, disable TX2RX */
amcs &= ~AMCS_TX2RX_MASK;
if (dev->flags & AT86RF215_OPT_AUTOACK) {
amcs |= AMCS_AACK_MASK;
}

at86rf215_reg_write(dev, dev->BBC->RG_AMCS, amcs);

/* listen to non-ACK packets again */
if (dev->flags & AT86RF215_OPT_ACK_REQUESTED) {
dev->flags &= ~AT86RF215_OPT_ACK_REQUESTED;
at86rf215_filter_ack(dev, false);
}

/* re-enable AACK*/
at86rf215_filter_ack_only(dev, false);
at86rf215_set_auto_mode(dev, AT86RF215_AM_AUTO_ACK, true);
/* re-enable reduced power consumption */
at86rf215_enable_rpc(dev);
}

static bool _tx_ongoing(at86rf215_t *dev)
{
if (dev->flags & AT86RF215_OPT_TX_PENDING) {
return true;
}

/* we can still fill the TX buffer and queue TX
when in AT86RF215_STATE_RX_SEND_ACK */
if (dev->state == AT86RF215_STATE_TX ||
dev->state == AT86RF215_STATE_TX_WAIT_ACK) {
return true;
}

return false;
}

int at86rf215_tx_prepare(at86rf215_t *dev)
{
if (dev->state == AT86RF215_STATE_SLEEP) {
return -ENETDOWN;
}

if (_tx_ongoing(dev)) {
return -EBUSY;
}

dev->tx_frame_len = IEEE802154_FCS_LEN;

return 0;
}

size_t at86rf215_tx_load(at86rf215_t *dev, const uint8_t *data,
size_t len, size_t offset)
{
/* set bit if ACK was requested and retransmission is enabled */
if (offset == 0 && (data[0] & IEEE802154_FCF_ACK_REQ) && dev->retries_max) {
dev->flags |= AT86RF215_OPT_ACK_REQUESTED;
}

at86rf215_reg_write_bytes(dev, dev->BBC->RG_FBTXS + offset, data, len);
dev->tx_frame_len += (uint16_t) len;

return offset + len;
}

int at86rf215_tx_exec(at86rf215_t *dev)
{
/* write frame length */
at86rf215_reg_write16(dev, dev->BBC->RG_TXFLL, dev->tx_frame_len);

dev->retries = dev->retries_max;
dev->csma_retries = dev->csma_retries_max;

dev->flags |= AT86RF215_OPT_TX_PENDING;

if ((dev->flags & AT86RF215_OPT_CSMA) && !(dev->flags & AT86RF215_OPT_CCATX)) {
dev->flags |= AT86RF215_OPT_CCA_PENDING;
}

if (dev->state == AT86RF215_STATE_IDLE) {
at86rf215_rf_cmd(dev, CMD_RF_TXPREP);
} else {
DEBUG("[at86rf215] will TX after %s\n", at86rf215_sw_state2a(dev->state));
}
at86rf215_rf_cmd(dev, CMD_RF_TX);

dev->state = AT86RF215_STATE_TX;
return 0;
}

void at86rf215_tx_abort(at86rf215_t *dev)
{
dev->flags &= ~(AT86RF215_OPT_CCA_PENDING | AT86RF215_OPT_TX_PENDING);

at86rf215_tx_done(dev);
at86rf215_enable_baseband(dev);
at86rf215_rf_cmd(dev, CMD_RF_RX);

dev->state = AT86RF215_STATE_IDLE;
}

bool at86rf215_cca(at86rf215_t *dev)
{
bool clear;
uint8_t old_state;

if (dev->state != AT86RF215_STATE_IDLE) {
return false;
}

if (dev->flags & AT86RF215_OPT_TX_PENDING) {
return false;
}

if (!at86rf215_set_rx_from_idle(dev, &old_state)) {
return false;
}

/* disable ED IRQ, baseband */
at86rf215_reg_and(dev, dev->RF->RG_IRQM, ~(RF_IRQ_EDC | RF_IRQ_TRXRDY));
at86rf215_reg_and(dev, dev->BBC->RG_PC, ~PC_BBEN_MASK);

at86rf215_disable_rpc(dev);

/* start energy detect */
at86rf215_reg_write(dev, dev->RF->RG_EDC, RF_EDSINGLE);
while (!(at86rf215_reg_read(dev, dev->RF->RG_IRQS) & RF_IRQ_EDC)) {}

clear = !(at86rf215_reg_read(dev, dev->BBC->RG_AMCS) & AMCS_CCAED_MASK);

/* enable ED IRQ, baseband */
at86rf215_reg_or(dev, dev->RF->RG_IRQM, RF_IRQ_EDC | RF_IRQ_TRXRDY);
at86rf215_reg_or(dev, dev->BBC->RG_PC, PC_BBEN_MASK);

at86rf215_enable_rpc(dev);
at86rf215_set_idle_from_rx(dev, old_state);

return clear;
}
Loading