Skip to content
Snippets Groups Projects
Commit 502786b9 authored by daniel-k's avatar daniel-k
Browse files

at86rf2xx: implement sleep mode

parent 7bf12190
No related branches found
No related tags found
No related merge requests found
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
* @} * @}
*/ */
#include "xtimer.h"
#include "periph/cpuid.h" #include "periph/cpuid.h"
#include "byteorder.h" #include "byteorder.h"
#include "net/ieee802154.h" #include "net/ieee802154.h"
...@@ -36,9 +35,6 @@ ...@@ -36,9 +35,6 @@
#include "debug.h" #include "debug.h"
#define RESET_DELAY (1U) /* must be > 625ns */
static void _irq_handler(void *arg) static void _irq_handler(void *arg)
{ {
msg_t msg; msg_t msg;
...@@ -62,6 +58,7 @@ int at86rf2xx_init(at86rf2xx_t *dev, spi_t spi, spi_speed_t spi_speed, ...@@ -62,6 +58,7 @@ int at86rf2xx_init(at86rf2xx_t *dev, spi_t spi, spi_speed_t spi_speed,
dev->sleep_pin = sleep_pin; dev->sleep_pin = sleep_pin;
dev->reset_pin = reset_pin; dev->reset_pin = reset_pin;
dev->idle_state = AT86RF2XX_STATE_TRX_OFF; dev->idle_state = AT86RF2XX_STATE_TRX_OFF;
dev->state = AT86RF2XX_STATE_SLEEP;
/* initialise SPI */ /* initialise SPI */
spi_init_master(dev->spi, SPI_CONF_FIRST_RISING, spi_speed); spi_init_master(dev->spi, SPI_CONF_FIRST_RISING, spi_speed);
...@@ -74,6 +71,9 @@ int at86rf2xx_init(at86rf2xx_t *dev, spi_t spi, spi_speed_t spi_speed, ...@@ -74,6 +71,9 @@ int at86rf2xx_init(at86rf2xx_t *dev, spi_t spi, spi_speed_t spi_speed,
gpio_set(dev->reset_pin); gpio_set(dev->reset_pin);
gpio_init_int(dev->int_pin, GPIO_NOPULL, GPIO_RISING, _irq_handler, dev); gpio_init_int(dev->int_pin, GPIO_NOPULL, GPIO_RISING, _irq_handler, dev);
/* make sure device is not sleeping, so we can query part number */
at86rf2xx_assert_awake(dev);
/* test if the SPI is set up correctly and the device is responding */ /* test if the SPI is set up correctly and the device is responding */
if (at86rf2xx_reg_read(dev, AT86RF2XX_REG__PART_NUM) != if (at86rf2xx_reg_read(dev, AT86RF2XX_REG__PART_NUM) !=
AT86RF2XX_PARTNUM) { AT86RF2XX_PARTNUM) {
...@@ -83,6 +83,7 @@ int at86rf2xx_init(at86rf2xx_t *dev, spi_t spi, spi_speed_t spi_speed, ...@@ -83,6 +83,7 @@ int at86rf2xx_init(at86rf2xx_t *dev, spi_t spi, spi_speed_t spi_speed,
/* reset device to default values and put it into RX state */ /* reset device to default values and put it into RX state */
at86rf2xx_reset(dev); at86rf2xx_reset(dev);
return 0; return 0;
} }
...@@ -93,12 +94,7 @@ void at86rf2xx_reset(at86rf2xx_t *dev) ...@@ -93,12 +94,7 @@ void at86rf2xx_reset(at86rf2xx_t *dev)
eui64_t addr_long; eui64_t addr_long;
#endif #endif
/* wake from sleep in case radio is sleeping */ at86rf2xx_hardware_reset(dev);
gpio_clear(dev->sleep_pin);
/* trigger hardware reset */
gpio_clear(dev->reset_pin);
xtimer_usleep(RESET_DELAY);
gpio_set(dev->reset_pin);
/* Reset state machine to ensure a known state */ /* Reset state machine to ensure a known state */
at86rf2xx_reset_state_machine(dev); at86rf2xx_reset_state_machine(dev);
...@@ -184,6 +180,8 @@ bool at86rf2xx_cca(at86rf2xx_t *dev) ...@@ -184,6 +180,8 @@ bool at86rf2xx_cca(at86rf2xx_t *dev)
uint8_t tmp; uint8_t tmp;
uint8_t status; uint8_t status;
at86rf2xx_assert_awake(dev);
/* trigger CCA measurment */ /* trigger CCA measurment */
tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__PHY_CC_CCA); tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__PHY_CC_CCA);
tmp &= AT86RF2XX_PHY_CC_CCA_MASK__CCA_REQUEST; tmp &= AT86RF2XX_PHY_CC_CCA_MASK__CCA_REQUEST;
......
...@@ -399,6 +399,7 @@ static inline void _set_state(at86rf2xx_t *dev, uint8_t state) ...@@ -399,6 +399,7 @@ static inline void _set_state(at86rf2xx_t *dev, uint8_t state)
{ {
at86rf2xx_reg_write(dev, AT86RF2XX_REG__TRX_STATE, state); at86rf2xx_reg_write(dev, AT86RF2XX_REG__TRX_STATE, state);
while (at86rf2xx_get_status(dev) != state); while (at86rf2xx_get_status(dev) != state);
dev->state = state;
} }
void at86rf2xx_set_state(at86rf2xx_t *dev, uint8_t state) void at86rf2xx_set_state(at86rf2xx_t *dev, uint8_t state)
...@@ -426,15 +427,17 @@ void at86rf2xx_set_state(at86rf2xx_t *dev, uint8_t state) ...@@ -426,15 +427,17 @@ void at86rf2xx_set_state(at86rf2xx_t *dev, uint8_t state)
/* check if we need to wake up from sleep mode */ /* check if we need to wake up from sleep mode */
else if (old_state == AT86RF2XX_STATE_SLEEP) { else if (old_state == AT86RF2XX_STATE_SLEEP) {
DEBUG("at86rf2xx: waking up from sleep mode\n"); DEBUG("at86rf2xx: waking up from sleep mode\n");
gpio_clear(dev->sleep_pin); at86rf2xx_assert_awake(dev);
while (at86rf2xx_get_status(dev) != AT86RF2XX_STATE_TRX_OFF);
} }
if (state == AT86RF2XX_STATE_SLEEP) { if (state == AT86RF2XX_STATE_SLEEP) {
/* First go to TRX_OFF */ /* First go to TRX_OFF */
at86rf2xx_force_trx_off(dev); at86rf2xx_force_trx_off(dev);
/* Discard all IRQ flags, framebuffer is lost anyway */
at86rf2xx_reg_read(dev, AT86RF2XX_REG__IRQ_STATUS);
/* Go to SLEEP mode from TRX_OFF */ /* Go to SLEEP mode from TRX_OFF */
gpio_set(dev->sleep_pin); gpio_set(dev->sleep_pin);
dev->state = state;
} else { } else {
_set_state(dev, state); _set_state(dev, state);
} }
...@@ -444,8 +447,7 @@ void at86rf2xx_reset_state_machine(at86rf2xx_t *dev) ...@@ -444,8 +447,7 @@ void at86rf2xx_reset_state_machine(at86rf2xx_t *dev)
{ {
uint8_t old_state; uint8_t old_state;
/* Wake up */ at86rf2xx_assert_awake(dev);
gpio_clear(dev->sleep_pin);
/* Wait for any state transitions to complete before forcing TRX_OFF */ /* Wait for any state transitions to complete before forcing TRX_OFF */
do { do {
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "periph/spi.h" #include "periph/spi.h"
#include "periph/gpio.h" #include "periph/gpio.h"
#include "xtimer.h"
#include "at86rf2xx_internal.h" #include "at86rf2xx_internal.h"
#include "at86rf2xx_registers.h" #include "at86rf2xx_registers.h"
...@@ -101,8 +102,38 @@ void at86rf2xx_fb_read(const at86rf2xx_t *dev, ...@@ -101,8 +102,38 @@ void at86rf2xx_fb_read(const at86rf2xx_t *dev,
uint8_t at86rf2xx_get_status(const at86rf2xx_t *dev) uint8_t at86rf2xx_get_status(const at86rf2xx_t *dev)
{ {
return (at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_STATUS) /* if sleeping immediately return state */
& AT86RF2XX_TRX_STATUS_MASK__TRX_STATUS); if(dev->state == AT86RF2XX_STATE_SLEEP)
return dev->state;
return at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_STATUS)
& AT86RF2XX_TRX_STATUS_MASK__TRX_STATUS;
}
void at86rf2xx_assert_awake(at86rf2xx_t *dev)
{
if(at86rf2xx_get_status(dev) == AT86RF2XX_STATE_SLEEP) {
/* wake up and wait for transition to TRX_OFF */
gpio_clear(dev->sleep_pin);
xtimer_usleep(AT86RF2XX_WAKEUP_DELAY);
/* update state */
dev->state = at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_STATUS)
& AT86RF2XX_TRX_STATUS_MASK__TRX_STATUS;
}
}
void at86rf2xx_hardware_reset(at86rf2xx_t *dev)
{
/* wake up from sleep in case radio is sleeping */
at86rf2xx_assert_awake(dev);
/* trigger hardware reset */
gpio_clear(dev->reset_pin);
xtimer_usleep(AT86RF2XX_RESET_PULSE_WIDTH);
gpio_set(dev->reset_pin);
xtimer_usleep(AT86RF2XX_RESET_DELAY);
} }
void at86rf2xx_force_trx_off(const at86rf2xx_t *dev) void at86rf2xx_force_trx_off(const at86rf2xx_t *dev)
......
...@@ -322,7 +322,7 @@ static int _set_state(at86rf2xx_t *dev, netopt_state_t state) ...@@ -322,7 +322,7 @@ static int _set_state(at86rf2xx_t *dev, netopt_state_t state)
{ {
switch (state) { switch (state) {
case NETOPT_STATE_SLEEP: case NETOPT_STATE_SLEEP:
at86rf2xx_set_state(dev, AT86RF2XX_STATE_TRX_OFF); at86rf2xx_set_state(dev, AT86RF2XX_STATE_SLEEP);
break; break;
case NETOPT_STATE_IDLE: case NETOPT_STATE_IDLE:
at86rf2xx_set_state(dev, AT86RF2XX_STATE_RX_AACK_ON); at86rf2xx_set_state(dev, AT86RF2XX_STATE_RX_AACK_ON);
...@@ -359,11 +359,13 @@ netopt_state_t _get_state(at86rf2xx_t *dev) ...@@ -359,11 +359,13 @@ netopt_state_t _get_state(at86rf2xx_t *dev)
static int _get(gnrc_netdev_t *device, netopt_t opt, void *val, size_t max_len) static int _get(gnrc_netdev_t *device, netopt_t opt, void *val, size_t max_len)
{ {
at86rf2xx_t *dev = (at86rf2xx_t *) device;
if (device == NULL) { if (device == NULL) {
return -ENODEV; return -ENODEV;
} }
at86rf2xx_t *dev = (at86rf2xx_t *) device;
/* getting these options doesn't require the transceiver to be responsive */
switch (opt) { switch (opt) {
case NETOPT_ADDRESS: case NETOPT_ADDRESS:
...@@ -435,13 +437,6 @@ static int _get(gnrc_netdev_t *device, netopt_t opt, void *val, size_t max_len) ...@@ -435,13 +437,6 @@ static int _get(gnrc_netdev_t *device, netopt_t opt, void *val, size_t max_len)
((uint8_t *)val)[0] = at86rf2xx_get_chan(dev); ((uint8_t *)val)[0] = at86rf2xx_get_chan(dev);
return sizeof(uint16_t); return sizeof(uint16_t);
case NETOPT_TX_POWER:
if (max_len < sizeof(int16_t)) {
return -EOVERFLOW;
}
*((uint16_t *)val) = at86rf2xx_get_txpower(dev);
return sizeof(uint16_t);
case NETOPT_MAX_PACKET_SIZE: case NETOPT_MAX_PACKET_SIZE:
if (max_len < sizeof(int16_t)) { if (max_len < sizeof(int16_t)) {
return -EOVERFLOW; return -EOVERFLOW;
...@@ -454,7 +449,7 @@ static int _get(gnrc_netdev_t *device, netopt_t opt, void *val, size_t max_len) ...@@ -454,7 +449,7 @@ static int _get(gnrc_netdev_t *device, netopt_t opt, void *val, size_t max_len)
return -EOVERFLOW; return -EOVERFLOW;
} }
*((netopt_state_t*)val) = _get_state(dev); *((netopt_state_t*)val) = _get_state(dev);
break; return sizeof(netopt_state_t);
case NETOPT_PRELOADING: case NETOPT_PRELOADING:
if (dev->options & AT86RF2XX_OPT_PRELOADING) { if (dev->options & AT86RF2XX_OPT_PRELOADING) {
...@@ -474,13 +469,6 @@ static int _get(gnrc_netdev_t *device, netopt_t opt, void *val, size_t max_len) ...@@ -474,13 +469,6 @@ static int _get(gnrc_netdev_t *device, netopt_t opt, void *val, size_t max_len)
} }
return sizeof(netopt_enable_t); return sizeof(netopt_enable_t);
case NETOPT_RETRANS:
if (max_len < sizeof(uint8_t)) {
return -EOVERFLOW;
}
*((uint8_t *)val) = at86rf2xx_get_max_retries(dev);
return sizeof(uint8_t);
case NETOPT_PROMISCUOUSMODE: case NETOPT_PROMISCUOUSMODE:
if (dev->options & AT86RF2XX_OPT_PROMISCUOUS) { if (dev->options & AT86RF2XX_OPT_PROMISCUOUS) {
*((netopt_enable_t *)val) = NETOPT_ENABLE; *((netopt_enable_t *)val) = NETOPT_ENABLE;
...@@ -499,15 +487,6 @@ static int _get(gnrc_netdev_t *device, netopt_t opt, void *val, size_t max_len) ...@@ -499,15 +487,6 @@ static int _get(gnrc_netdev_t *device, netopt_t opt, void *val, size_t max_len)
} }
return sizeof(netopt_enable_t); return sizeof(netopt_enable_t);
case NETOPT_IS_CHANNEL_CLR:
if (at86rf2xx_cca(dev)) {
*((netopt_enable_t *)val) = NETOPT_ENABLE;
}
else {
*((netopt_enable_t *)val) = NETOPT_DISABLE;
}
return sizeof(netopt_enable_t);
case NETOPT_RX_START_IRQ: case NETOPT_RX_START_IRQ:
*((netopt_enable_t *)val) = *((netopt_enable_t *)val) =
!!(dev->options & AT86RF2XX_OPT_TELL_RX_START); !!(dev->options & AT86RF2XX_OPT_TELL_RX_START);
...@@ -533,161 +512,253 @@ static int _get(gnrc_netdev_t *device, netopt_t opt, void *val, size_t max_len) ...@@ -533,161 +512,253 @@ static int _get(gnrc_netdev_t *device, netopt_t opt, void *val, size_t max_len)
!!(dev->options & AT86RF2XX_OPT_CSMA); !!(dev->options & AT86RF2XX_OPT_CSMA);
return sizeof(netopt_enable_t); return sizeof(netopt_enable_t);
default:
/* Can still be handled in second switch */
break;
}
uint8_t old_state = at86rf2xx_get_status(dev);
int res = 0;
/* temporarily wake up if sleeping */
if(old_state == AT86RF2XX_STATE_SLEEP) {
at86rf2xx_assert_awake(dev);
}
/* these options require the transceiver to be not sleeping*/
switch (opt) {
case NETOPT_TX_POWER:
if (max_len < sizeof(int16_t)) {
res = -EOVERFLOW;
} else {
*((uint16_t *)val) = at86rf2xx_get_txpower(dev);
res = sizeof(uint16_t);
}
break;
case NETOPT_RETRANS:
if (max_len < sizeof(uint8_t)) {
res = -EOVERFLOW;
} else {
*((uint8_t *)val) = at86rf2xx_get_max_retries(dev);
res = sizeof(uint8_t);
}
break;
case NETOPT_IS_CHANNEL_CLR:
if (at86rf2xx_cca(dev)) {
*((netopt_enable_t *)val) = NETOPT_ENABLE;
}
else {
*((netopt_enable_t *)val) = NETOPT_DISABLE;
}
res = sizeof(netopt_enable_t);
break;
case NETOPT_CSMA_RETRIES: case NETOPT_CSMA_RETRIES:
if (max_len < sizeof(uint8_t)) { if (max_len < sizeof(uint8_t)) {
return -EOVERFLOW; res = -EOVERFLOW;
} else {
*((uint8_t *)val) = at86rf2xx_get_csma_max_retries(dev);
res = sizeof(uint8_t);
} }
*((uint8_t *)val) = at86rf2xx_get_csma_max_retries(dev); break;
return sizeof(uint8_t);
default: default:
return -ENOTSUP; res = -ENOTSUP;
} }
return 0; /* go back to sleep if were sleeping */
if(old_state == AT86RF2XX_STATE_SLEEP) {
at86rf2xx_set_state(dev, AT86RF2XX_STATE_SLEEP);
}
return res;
} }
static int _set(gnrc_netdev_t *device, netopt_t opt, void *val, size_t len) static int _set(gnrc_netdev_t *device, netopt_t opt, void *val, size_t len)
{ {
at86rf2xx_t *dev = (at86rf2xx_t *) device; at86rf2xx_t *dev = (at86rf2xx_t *) device;
uint8_t old_state = at86rf2xx_get_status(dev);
int res = 0;
if (dev == NULL) { if (dev == NULL) {
return -ENODEV; return -ENODEV;
} }
/* temporarily wake up if sleeping */
if(old_state == AT86RF2XX_STATE_SLEEP) {
at86rf2xx_assert_awake(dev);
}
switch (opt) { switch (opt) {
case NETOPT_ADDRESS: case NETOPT_ADDRESS:
if (len > sizeof(uint16_t)) { if (len > sizeof(uint16_t)) {
return -EOVERFLOW; res = -EOVERFLOW;
} else {
at86rf2xx_set_addr_short(dev, *((uint16_t*)val));
res = sizeof(uint16_t);
} }
at86rf2xx_set_addr_short(dev, *((uint16_t*)val)); break;
return sizeof(uint16_t);
case NETOPT_ADDRESS_LONG: case NETOPT_ADDRESS_LONG:
if (len > sizeof(uint64_t)) { if (len > sizeof(uint64_t)) {
return -EOVERFLOW; res = -EOVERFLOW;
} else {
at86rf2xx_set_addr_long(dev, *((uint64_t*)val));
res = sizeof(uint64_t);
} }
at86rf2xx_set_addr_long(dev, *((uint64_t*)val)); break;
return sizeof(uint64_t);
case NETOPT_SRC_LEN: case NETOPT_SRC_LEN:
if (len > sizeof(uint16_t)) { if (len > sizeof(uint16_t)) {
return -EOVERFLOW; res = -EOVERFLOW;
} } else {
if (*((uint16_t *)val) == 2) { if (*((uint16_t *)val) == 2) {
at86rf2xx_set_option(dev, AT86RF2XX_OPT_SRC_ADDR_LONG, at86rf2xx_set_option(dev, AT86RF2XX_OPT_SRC_ADDR_LONG,
false); false);
} }
else if (*((uint16_t *)val) == 8) { else if (*((uint16_t *)val) == 8) {
at86rf2xx_set_option(dev, AT86RF2XX_OPT_SRC_ADDR_LONG, at86rf2xx_set_option(dev, AT86RF2XX_OPT_SRC_ADDR_LONG,
true); true);
} }
else { else {
return -ENOTSUP; res = -ENOTSUP;
break;
}
res = sizeof(uint16_t);
} }
return sizeof(uint16_t); break;
case NETOPT_NID: case NETOPT_NID:
if (len > sizeof(uint16_t)) { if (len > sizeof(uint16_t)) {
return -EOVERFLOW; res = -EOVERFLOW;
} else {
at86rf2xx_set_pan(dev, *((uint16_t *)val));
res = sizeof(uint16_t);
} }
at86rf2xx_set_pan(dev, *((uint16_t *)val)); break;
return sizeof(uint16_t);
case NETOPT_CHANNEL: case NETOPT_CHANNEL:
if (len != sizeof(uint16_t)) { if (len != sizeof(uint16_t)) {
return -EINVAL; res = -EINVAL;
} } else {
uint8_t chan = ((uint8_t *)val)[0]; uint8_t chan = ((uint8_t *)val)[0];
if (chan < AT86RF2XX_MIN_CHANNEL || if (chan < AT86RF2XX_MIN_CHANNEL ||
chan > AT86RF2XX_MAX_CHANNEL) { chan > AT86RF2XX_MAX_CHANNEL) {
return -ENOTSUP; res = -ENOTSUP;
break;
}
at86rf2xx_set_chan(dev, chan);
res = sizeof(uint16_t);
} }
at86rf2xx_set_chan(dev, chan); break;
return sizeof(uint16_t);
case NETOPT_TX_POWER: case NETOPT_TX_POWER:
if (len > sizeof(int16_t)) { if (len > sizeof(int16_t)) {
return -EOVERFLOW; res = -EOVERFLOW;
} else {
at86rf2xx_set_txpower(dev, *((int16_t *)val));
res = sizeof(uint16_t);
} }
at86rf2xx_set_txpower(dev, *((int16_t *)val)); break;
return sizeof(uint16_t);
case NETOPT_STATE: case NETOPT_STATE:
if (len > sizeof(netopt_state_t)) { if (len > sizeof(netopt_state_t)) {
return -EOVERFLOW; res = -EOVERFLOW;
} else {
res = _set_state(dev, *((netopt_state_t *)val));
} }
return _set_state(dev, *((netopt_state_t *)val)); break;
case NETOPT_AUTOACK: case NETOPT_AUTOACK:
at86rf2xx_set_option(dev, AT86RF2XX_OPT_AUTOACK, at86rf2xx_set_option(dev, AT86RF2XX_OPT_AUTOACK,
((bool *)val)[0]); ((bool *)val)[0]);
return sizeof(netopt_enable_t); res = sizeof(netopt_enable_t);
break;
case NETOPT_RETRANS: case NETOPT_RETRANS:
if (len > sizeof(uint8_t)) { if (len > sizeof(uint8_t)) {
return -EOVERFLOW; res = -EOVERFLOW;
} else {
at86rf2xx_set_max_retries(dev, *((uint8_t *)val));
res = sizeof(uint8_t);
} }
at86rf2xx_set_max_retries(dev, *((uint8_t *)val)); break;
return sizeof(uint8_t);
case NETOPT_PRELOADING: case NETOPT_PRELOADING:
at86rf2xx_set_option(dev, AT86RF2XX_OPT_PRELOADING, at86rf2xx_set_option(dev, AT86RF2XX_OPT_PRELOADING,
((bool *)val)[0]); ((bool *)val)[0]);
return sizeof(netopt_enable_t); res = sizeof(netopt_enable_t);
break;
case NETOPT_PROMISCUOUSMODE: case NETOPT_PROMISCUOUSMODE:
at86rf2xx_set_option(dev, AT86RF2XX_OPT_PROMISCUOUS, at86rf2xx_set_option(dev, AT86RF2XX_OPT_PROMISCUOUS,
((bool *)val)[0]); ((bool *)val)[0]);
return sizeof(netopt_enable_t); res = sizeof(netopt_enable_t);
break;
case NETOPT_RAWMODE: case NETOPT_RAWMODE:
at86rf2xx_set_option(dev, AT86RF2XX_OPT_RAWDUMP, at86rf2xx_set_option(dev, AT86RF2XX_OPT_RAWDUMP,
((bool *)val)[0]); ((bool *)val)[0]);
return sizeof(netopt_enable_t); res = sizeof(netopt_enable_t);
break;
case NETOPT_RX_START_IRQ: case NETOPT_RX_START_IRQ:
at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_RX_START, at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_RX_START,
((bool *)val)[0]); ((bool *)val)[0]);
return sizeof(netopt_enable_t); res = sizeof(netopt_enable_t);
break;
case NETOPT_RX_END_IRQ: case NETOPT_RX_END_IRQ:
at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_RX_END, at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_RX_END,
((bool *)val)[0]); ((bool *)val)[0]);
return sizeof(netopt_enable_t); res = sizeof(netopt_enable_t);
break;
case NETOPT_TX_START_IRQ: case NETOPT_TX_START_IRQ:
at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_TX_START, at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_TX_START,
((bool *)val)[0]); ((bool *)val)[0]);
return sizeof(netopt_enable_t); res = sizeof(netopt_enable_t);
break;
case NETOPT_TX_END_IRQ: case NETOPT_TX_END_IRQ:
at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_TX_END, at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_TX_END,
((bool *)val)[0]); ((bool *)val)[0]);
return sizeof(netopt_enable_t); res = sizeof(netopt_enable_t);
break;
case NETOPT_CSMA: case NETOPT_CSMA:
at86rf2xx_set_option(dev, AT86RF2XX_OPT_CSMA, at86rf2xx_set_option(dev, AT86RF2XX_OPT_CSMA,
((bool *)val)[0]); ((bool *)val)[0]);
return sizeof(netopt_enable_t); res = sizeof(netopt_enable_t);
break;
case NETOPT_CSMA_RETRIES: case NETOPT_CSMA_RETRIES:
if( (len > sizeof(uint8_t)) || if( (len > sizeof(uint8_t)) ||
(*((uint8_t *)val) > 5) ) { (*((uint8_t *)val) > 5) ) {
return -EOVERFLOW; res = -EOVERFLOW;
} } else if( !(dev->options & AT86RF2XX_OPT_CSMA) ) {
/* If CSMA is disabled, don't allow setting retries */ /* If CSMA is disabled, don't allow setting retries */
if( !(dev->options & AT86RF2XX_OPT_CSMA) ) { res = -ENOTSUP;
return -ENOTSUP; } else {
at86rf2xx_set_csma_max_retries(dev, *((uint8_t *)val));
res = sizeof(uint8_t);
} }
at86rf2xx_set_csma_max_retries(dev, *((uint8_t *)val)); break;
return sizeof(uint8_t);
default: default:
return -ENOTSUP; res = -ENOTSUP;
} }
return 0; /* go back to sleep if were sleeping and state hasn't been changed */
if( (old_state == AT86RF2XX_STATE_SLEEP) &&
(opt != NETOPT_STATE) ) {
at86rf2xx_set_state(dev, AT86RF2XX_STATE_SLEEP);
}
return res;
} }
static int _add_event_cb(gnrc_netdev_t *dev, gnrc_netdev_event_cb_t cb) static int _add_event_cb(gnrc_netdev_t *dev, gnrc_netdev_event_cb_t cb)
...@@ -723,10 +794,16 @@ static void _isr_event(gnrc_netdev_t *device, uint32_t event_type) ...@@ -723,10 +794,16 @@ static void _isr_event(gnrc_netdev_t *device, uint32_t event_type)
uint8_t state; uint8_t state;
uint8_t trac_status; uint8_t trac_status;
/* If transceiver is sleeping register access is impossible and frames are
* lost anyway, so return immediately.
*/
state = at86rf2xx_get_status(dev);
if(state == AT86RF2XX_STATE_SLEEP)
return;
/* read (consume) device status */ /* read (consume) device status */
irq_mask = at86rf2xx_reg_read(dev, AT86RF2XX_REG__IRQ_STATUS); irq_mask = at86rf2xx_reg_read(dev, AT86RF2XX_REG__IRQ_STATUS);
state = at86rf2xx_get_status(dev);
trac_status = at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_STATE) & trac_status = at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_STATE) &
AT86RF2XX_TRX_STATE_MASK__TRAC; AT86RF2XX_TRX_STATE_MASK__TRAC;
......
...@@ -31,6 +31,23 @@ ...@@ -31,6 +31,23 @@
extern "C" { extern "C" {
#endif #endif
/**
* @brief Transition time from SLEEP to TRX_OFF in us, refer figure 7-4, p.42.
* For different environments refer figure 13-13, p.201
*/
#define AT86RF2XX_WAKEUP_DELAY (300U)
/**
* @brief Minimum reset pulse width, refer p.190
*/
#define AT86RF2XX_RESET_PULSE_WIDTH (1U)
/**
* @brief Transition time to TRX_OFF after reset pulse in us, refer
* figure 7-8, p. 44.
*/
#define AT86RF2XX_RESET_DELAY (26U)
/** /**
* @brief Read from a register at address `addr` from device `dev`. * @brief Read from a register at address `addr` from device `dev`.
* *
...@@ -106,6 +123,21 @@ void at86rf2xx_force_trx_off(const at86rf2xx_t *dev); ...@@ -106,6 +123,21 @@ void at86rf2xx_force_trx_off(const at86rf2xx_t *dev);
*/ */
uint8_t at86rf2xx_get_status(const at86rf2xx_t *dev); uint8_t at86rf2xx_get_status(const at86rf2xx_t *dev);
/**
* @brief Make sure that device is not sleeping
*
* @param[in] dev device to eventually wake up
*/
void at86rf2xx_assert_awake(at86rf2xx_t *dev);
/**
* @brief Trigger a hardware reset
*
* @param[in] dev device to reset
*/
void at86rf2xx_hardware_reset(at86rf2xx_t *dev);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment