From 502786b9f7608a238ce86f71412b8e6fe6ac5e0b Mon Sep 17 00:00:00 2001
From: daniel-k <github@daniel-krebs.net>
Date: Wed, 16 Sep 2015 18:48:10 +0200
Subject: [PATCH] at86rf2xx: implement sleep mode

---
 drivers/at86rf2xx/at86rf2xx.c                 |  18 +-
 drivers/at86rf2xx/at86rf2xx_getset.c          |  10 +-
 drivers/at86rf2xx/at86rf2xx_internal.c        |  35 ++-
 drivers/at86rf2xx/at86rf2xx_netdev.c          | 253 ++++++++++++------
 .../at86rf2xx/include/at86rf2xx_internal.h    |  32 +++
 5 files changed, 244 insertions(+), 104 deletions(-)

diff --git a/drivers/at86rf2xx/at86rf2xx.c b/drivers/at86rf2xx/at86rf2xx.c
index 7a1d91e5e3..75da3e77fc 100644
--- a/drivers/at86rf2xx/at86rf2xx.c
+++ b/drivers/at86rf2xx/at86rf2xx.c
@@ -23,7 +23,6 @@
  * @}
  */
 
-#include "xtimer.h"
 #include "periph/cpuid.h"
 #include "byteorder.h"
 #include "net/ieee802154.h"
@@ -36,9 +35,6 @@
 #include "debug.h"
 
 
-#define RESET_DELAY             (1U)        /* must be > 625ns */
-
-
 static void _irq_handler(void *arg)
 {
     msg_t msg;
@@ -62,6 +58,7 @@ int at86rf2xx_init(at86rf2xx_t *dev, spi_t spi, spi_speed_t spi_speed,
     dev->sleep_pin = sleep_pin;
     dev->reset_pin = reset_pin;
     dev->idle_state = AT86RF2XX_STATE_TRX_OFF;
+    dev->state = AT86RF2XX_STATE_SLEEP;
 
     /* initialise SPI */
     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,
     gpio_set(dev->reset_pin);
     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 */
     if (at86rf2xx_reg_read(dev, AT86RF2XX_REG__PART_NUM) !=
         AT86RF2XX_PARTNUM) {
@@ -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 */
     at86rf2xx_reset(dev);
+
     return 0;
 }
 
@@ -93,12 +94,7 @@ void at86rf2xx_reset(at86rf2xx_t *dev)
     eui64_t addr_long;
 #endif
 
-    /* wake from sleep in case radio is sleeping */
-    gpio_clear(dev->sleep_pin);
-    /* trigger hardware reset */
-    gpio_clear(dev->reset_pin);
-    xtimer_usleep(RESET_DELAY);
-    gpio_set(dev->reset_pin);
+    at86rf2xx_hardware_reset(dev);
 
     /* Reset state machine to ensure a known state */
     at86rf2xx_reset_state_machine(dev);
@@ -184,6 +180,8 @@ bool at86rf2xx_cca(at86rf2xx_t *dev)
     uint8_t tmp;
     uint8_t status;
 
+    at86rf2xx_assert_awake(dev);
+
     /* trigger CCA measurment */
     tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__PHY_CC_CCA);
     tmp &= AT86RF2XX_PHY_CC_CCA_MASK__CCA_REQUEST;
diff --git a/drivers/at86rf2xx/at86rf2xx_getset.c b/drivers/at86rf2xx/at86rf2xx_getset.c
index 26e5d3d2eb..fe0f31af7e 100644
--- a/drivers/at86rf2xx/at86rf2xx_getset.c
+++ b/drivers/at86rf2xx/at86rf2xx_getset.c
@@ -399,6 +399,7 @@ static inline void _set_state(at86rf2xx_t *dev, uint8_t state)
 {
     at86rf2xx_reg_write(dev, AT86RF2XX_REG__TRX_STATE, state);
     while (at86rf2xx_get_status(dev) != state);
+    dev->state = 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)
     /* check if we need to wake up from sleep mode */
     else if (old_state == AT86RF2XX_STATE_SLEEP) {
         DEBUG("at86rf2xx: waking up from sleep mode\n");
-        gpio_clear(dev->sleep_pin);
-        while (at86rf2xx_get_status(dev) != AT86RF2XX_STATE_TRX_OFF);
+        at86rf2xx_assert_awake(dev);
     }
 
     if (state == AT86RF2XX_STATE_SLEEP) {
         /* First go to TRX_OFF */
         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 */
         gpio_set(dev->sleep_pin);
+        dev->state = state;
     } else {
         _set_state(dev, state);
     }
@@ -444,8 +447,7 @@ void at86rf2xx_reset_state_machine(at86rf2xx_t *dev)
 {
     uint8_t old_state;
 
-    /* Wake up */
-    gpio_clear(dev->sleep_pin);
+    at86rf2xx_assert_awake(dev);
 
     /* Wait for any state transitions to complete before forcing TRX_OFF */
     do {
diff --git a/drivers/at86rf2xx/at86rf2xx_internal.c b/drivers/at86rf2xx/at86rf2xx_internal.c
index 44a9eb05b0..fc9ea8d403 100644
--- a/drivers/at86rf2xx/at86rf2xx_internal.c
+++ b/drivers/at86rf2xx/at86rf2xx_internal.c
@@ -24,6 +24,7 @@
 
 #include "periph/spi.h"
 #include "periph/gpio.h"
+#include "xtimer.h"
 #include "at86rf2xx_internal.h"
 #include "at86rf2xx_registers.h"
 
@@ -101,8 +102,38 @@ void at86rf2xx_fb_read(const at86rf2xx_t *dev,
 
 uint8_t at86rf2xx_get_status(const at86rf2xx_t *dev)
 {
-    return (at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_STATUS)
-            & AT86RF2XX_TRX_STATUS_MASK__TRX_STATUS);
+    /* if sleeping immediately return state */
+    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)
diff --git a/drivers/at86rf2xx/at86rf2xx_netdev.c b/drivers/at86rf2xx/at86rf2xx_netdev.c
index 1f8f9dd1b4..e57b09ab88 100644
--- a/drivers/at86rf2xx/at86rf2xx_netdev.c
+++ b/drivers/at86rf2xx/at86rf2xx_netdev.c
@@ -322,7 +322,7 @@ static int _set_state(at86rf2xx_t *dev, netopt_state_t state)
 {
     switch (state) {
         case NETOPT_STATE_SLEEP:
-            at86rf2xx_set_state(dev, AT86RF2XX_STATE_TRX_OFF);
+            at86rf2xx_set_state(dev, AT86RF2XX_STATE_SLEEP);
             break;
         case NETOPT_STATE_IDLE:
             at86rf2xx_set_state(dev, AT86RF2XX_STATE_RX_AACK_ON);
@@ -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)
 {
+    at86rf2xx_t *dev = (at86rf2xx_t *) device;
+
     if (device == NULL) {
         return -ENODEV;
     }
-    at86rf2xx_t *dev = (at86rf2xx_t *) device;
 
+    /* getting these options doesn't require the transceiver to be responsive */
     switch (opt) {
 
         case NETOPT_ADDRESS:
@@ -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);
             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:
             if (max_len < sizeof(int16_t)) {
                 return -EOVERFLOW;
@@ -454,7 +449,7 @@ static int _get(gnrc_netdev_t *device, netopt_t opt, void *val, size_t max_len)
                 return -EOVERFLOW;
             }
             *((netopt_state_t*)val) = _get_state(dev);
-            break;
+            return sizeof(netopt_state_t);
 
         case NETOPT_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)
             }
             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:
             if (dev->options & AT86RF2XX_OPT_PROMISCUOUS) {
                 *((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)
             }
             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:
             *((netopt_enable_t *)val) =
                 !!(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)
                 !!(dev->options & AT86RF2XX_OPT_CSMA);
             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:
             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);
-            return sizeof(uint8_t);
+            break;
 
         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)
 {
     at86rf2xx_t *dev = (at86rf2xx_t *) device;
+    uint8_t old_state = at86rf2xx_get_status(dev);
+    int res = 0;
 
     if (dev == NULL) {
         return -ENODEV;
     }
 
+    /* temporarily wake up if sleeping */
+    if(old_state == AT86RF2XX_STATE_SLEEP) {
+        at86rf2xx_assert_awake(dev);
+    }
+
     switch (opt) {
         case NETOPT_ADDRESS:
             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));
-            return sizeof(uint16_t);
+            break;
 
         case NETOPT_ADDRESS_LONG:
             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));
-            return sizeof(uint64_t);
+            break;
 
         case NETOPT_SRC_LEN:
             if (len > sizeof(uint16_t)) {
-                return -EOVERFLOW;
-            }
-            if (*((uint16_t *)val) == 2) {
-                at86rf2xx_set_option(dev, AT86RF2XX_OPT_SRC_ADDR_LONG,
-                                     false);
-            }
-            else if (*((uint16_t *)val) == 8) {
-                at86rf2xx_set_option(dev, AT86RF2XX_OPT_SRC_ADDR_LONG,
-                                     true);
-            }
-            else {
-                return -ENOTSUP;
+                res = -EOVERFLOW;
+            } else {
+                if (*((uint16_t *)val) == 2) {
+                    at86rf2xx_set_option(dev, AT86RF2XX_OPT_SRC_ADDR_LONG,
+                                         false);
+                }
+                else if (*((uint16_t *)val) == 8) {
+                    at86rf2xx_set_option(dev, AT86RF2XX_OPT_SRC_ADDR_LONG,
+                                         true);
+                }
+                else {
+                    res = -ENOTSUP;
+                    break;
+                }
+                res = sizeof(uint16_t);
             }
-            return sizeof(uint16_t);
+            break;
 
         case NETOPT_NID:
             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));
-            return sizeof(uint16_t);
+            break;
 
         case NETOPT_CHANNEL:
             if (len != sizeof(uint16_t)) {
-                return -EINVAL;
-            }
-            uint8_t chan = ((uint8_t *)val)[0];
-            if (chan < AT86RF2XX_MIN_CHANNEL ||
-                chan > AT86RF2XX_MAX_CHANNEL) {
-                return -ENOTSUP;
+                res = -EINVAL;
+            } else {
+                uint8_t chan = ((uint8_t *)val)[0];
+                if (chan < AT86RF2XX_MIN_CHANNEL ||
+                    chan > AT86RF2XX_MAX_CHANNEL) {
+                    res = -ENOTSUP;
+                    break;
+                }
+                at86rf2xx_set_chan(dev, chan);
+                res = sizeof(uint16_t);
             }
-            at86rf2xx_set_chan(dev, chan);
-            return sizeof(uint16_t);
+            break;
 
         case NETOPT_TX_POWER:
             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));
-            return sizeof(uint16_t);
+            break;
 
         case NETOPT_STATE:
             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:
             at86rf2xx_set_option(dev, AT86RF2XX_OPT_AUTOACK,
                                  ((bool *)val)[0]);
-            return sizeof(netopt_enable_t);
+            res = sizeof(netopt_enable_t);
+            break;
 
         case NETOPT_RETRANS:
             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));
-            return sizeof(uint8_t);
+            break;
 
         case NETOPT_PRELOADING:
             at86rf2xx_set_option(dev, AT86RF2XX_OPT_PRELOADING,
                                  ((bool *)val)[0]);
-            return sizeof(netopt_enable_t);
+            res = sizeof(netopt_enable_t);
+            break;
 
         case NETOPT_PROMISCUOUSMODE:
             at86rf2xx_set_option(dev, AT86RF2XX_OPT_PROMISCUOUS,
                                  ((bool *)val)[0]);
-            return sizeof(netopt_enable_t);
+            res = sizeof(netopt_enable_t);
+            break;
 
         case NETOPT_RAWMODE:
             at86rf2xx_set_option(dev, AT86RF2XX_OPT_RAWDUMP,
                                  ((bool *)val)[0]);
-            return sizeof(netopt_enable_t);
+            res = sizeof(netopt_enable_t);
+            break;
 
         case NETOPT_RX_START_IRQ:
             at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_RX_START,
                                  ((bool *)val)[0]);
-            return sizeof(netopt_enable_t);
+            res = sizeof(netopt_enable_t);
+            break;
 
         case NETOPT_RX_END_IRQ:
             at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_RX_END,
                                  ((bool *)val)[0]);
-            return sizeof(netopt_enable_t);
+            res = sizeof(netopt_enable_t);
+            break;
 
         case NETOPT_TX_START_IRQ:
             at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_TX_START,
                                  ((bool *)val)[0]);
-            return sizeof(netopt_enable_t);
+            res = sizeof(netopt_enable_t);
+            break;
 
         case NETOPT_TX_END_IRQ:
             at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_TX_END,
                                  ((bool *)val)[0]);
-            return sizeof(netopt_enable_t);
+            res = sizeof(netopt_enable_t);
+            break;
 
         case NETOPT_CSMA:
             at86rf2xx_set_option(dev, AT86RF2XX_OPT_CSMA,
                                     ((bool *)val)[0]);
-            return sizeof(netopt_enable_t);
+            res = sizeof(netopt_enable_t);
+            break;
 
         case NETOPT_CSMA_RETRIES:
             if( (len > sizeof(uint8_t)) ||
                 (*((uint8_t *)val) > 5) ) {
-                return -EOVERFLOW;
-            }
-            /* If CSMA is disabled, don't allow setting retries */
-            if( !(dev->options & AT86RF2XX_OPT_CSMA) ) {
-                return -ENOTSUP;
+                res = -EOVERFLOW;
+            } else if( !(dev->options & AT86RF2XX_OPT_CSMA) ) {
+                /* If CSMA is disabled, don't allow setting retries */
+                res = -ENOTSUP;
+            } else {
+                at86rf2xx_set_csma_max_retries(dev, *((uint8_t *)val));
+                res = sizeof(uint8_t);
             }
-            at86rf2xx_set_csma_max_retries(dev, *((uint8_t *)val));
-            return sizeof(uint8_t);
+            break;
 
         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)
@@ -723,10 +794,16 @@ static void _isr_event(gnrc_netdev_t *device, uint32_t event_type)
     uint8_t state;
     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 */
     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) &
                     AT86RF2XX_TRX_STATE_MASK__TRAC;
 
diff --git a/drivers/at86rf2xx/include/at86rf2xx_internal.h b/drivers/at86rf2xx/include/at86rf2xx_internal.h
index 90381cbe36..863f1fedf3 100644
--- a/drivers/at86rf2xx/include/at86rf2xx_internal.h
+++ b/drivers/at86rf2xx/include/at86rf2xx_internal.h
@@ -31,6 +31,23 @@
 extern "C" {
 #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`.
  *
@@ -106,6 +123,21 @@ void at86rf2xx_force_trx_off(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
 }
 #endif
-- 
GitLab