nrfmin.h 6.53 KB
/*
 * Copyright (C) 2015-2017 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_nrf5x_nrfmin NRF minimal radio driver
 * @ingroup     drivers_netdev
 * @brief       Minimal driver for the NRF51 radio
 *
 * This driver uses the nRF5x radio in a proprietary/custom way, defining our
 * own custom link layer. This custom link layer resembles some characteristics
 * of the IEEE802.15.4 link layer, but is not at all compatible to it.
 *
 * One key point is, that this custom link layer is only meant to operate
 * between nRF5x devices, which let's us make some very nice assumptions:
 *  - all communicating hosts are little-endian
 *    -> we define host byte order := network byte order
 *
 * The driver is using a Nordic proprietary physical layer, configured to a
 * bitrate of 2Mbit. The maximum payload length can be freely configured, but
 * the maximal supported value is 250 byte (default is 200 byte).
 *
 * We define the nrfmin link layer to use 16-bit addresses. On the physical
 * layer we encode these addresses by putting these addresses into the 2 least
 * significant bytes of the supported 5-byte addresses, while setting the other
 * 3 bytes to 0xe7.
 *
 * For out custom link layer, we define our own proprietary link layer format
 * (all fields are in host byte order (little endian)):
 *
 *    byte0 | byte1 - byte2 | byte3 - byte4 | byte5 | byte7 - byteN
 *   ------ | ------------- | ------------- | ----- | -------------
 *   length |   src_addr    |   dst_addr    | proto |   payload...
 *
 * With:
 * - length: length of the packet, including the header -> payload len + 6
 * - src_addr: 16-bit source address
 * - dst_addr: 16-bit destination address
 * - proto: type of data transferred (similar to an Ethertype field)
 *
 * SUMMARY:
 * This driver / link layer supports:
 *   - 16-bit addressing (16-bit)
 *     -> extract default address from CPU ID
 *   - broadcast (broadcast address is ff:ff)
 *   - channels from 0 to 31 [2400MHz to 2524MHz, 4MHz per channel]
 *   - setting of TX power [+4dBm to -20dBm, in ~4dBm steps]
 *   - 8-bit packet type/proto field (to be used as seen fit)
 *   - setting device state (RX, SLEEP)
 *
 * But so far no support for:
 *   - link layer ACKs
 *   - retransmissions
 *
 * @todo        So far the driver uses only a single RX buffer that is locked
 *              until the data was read/discarded. This can potentially lead to
 *              a lot of packet loss -> using more than one buffer would help
 *              here...
 *
 * @{
 *
 * @file
 * @brief       Interface definition for the nrfmin NRF51822 radio driver
 *
 * @author      Hauke Petersen <hauke.petersen@fu-berlin.de>
 */

#ifndef NRFMIN_H
#define NRFMIN_H

#include "net/netdev.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @brief   nrfmin channel configuration
 * @{
 */
#define NRFMIN_CHAN_MIN             (0U)
#define NRFMIN_CHAN_DEFAULT         (0U)                /* 2400MHz */
#define NRFMIN_CHAN_MAX             (32)
/** @} */

/**
 * @brief   Default transmission power used
 */
#define NRFMIN_TXPOWER_DEFAULT      (0)                 /* 0dBm */

/**
 * @brief   Export the default nrfmin broadcast address
 */
#define NRFMIN_ADDR_BCAST           (0xffff)

/**
 * @brief   Default maximum payload length (must be <= 250)
 */
#ifndef NRFMIN_PAYLOAD_MAX
#define NRFMIN_PAYLOAD_MAX          (200U)
#endif

/**
 * @brief   Export some information on header and packet lengths
 * @{
 */
#define NRFMIN_HDR_LEN              (sizeof(nrfmin_hdr_t))
#define NRFMIN_PKT_MAX              (NRFMIN_HDR_LEN + NRFMIN_PAYLOAD_MAX)
/** @} */

/**
 * @brief   Header format used for our custom nrfmin link layer
 */
typedef struct __attribute__((packed)) {
    uint8_t len;            /**< packet length, including this header */
    uint16_t src_addr;      /**< source address of the packet */
    uint16_t dst_addr;      /**< destination address */
    uint8_t proto;          /**< protocol of payload */
} nrfmin_hdr_t;

/**
 * @brief   In-memory structure of a nrfmin radio packet
 */
typedef union {
    struct __attribute__((packed)) {
        nrfmin_hdr_t hdr;                       /**< the nrfmin header */
        uint8_t payload[NRFMIN_PAYLOAD_MAX];    /**< actual payload */
    } pkt;                                      /**< typed packet access */
    uint8_t raw[NRFMIN_PKT_MAX];                /**< raw packet access */
} nrfmin_pkt_t;

/**
 * @brief   Export the netdev device descriptor
 */
extern netdev_t nrfmin_dev;

/**
 * @brief   Reference to the netdev driver interface
 */
extern const netdev_driver_t nrfmin_netdev;

/**
 * @brief   Setup the device driver's data structures
 */
void nrfmin_setup(void);

/**
 * @brief   Get the currently active address

 * @return  the 16-bit node address
 */
uint16_t nrfmin_get_addr(void);

/**
 * @brief   Set the 16-bit radio address
 *
 * @param[in] addr      address to set
 */
void nrfmin_set_addr(uint16_t addr);

/**
 * @brief   Get a pseudo 64-bit long address (needed by IPv6 and 6LoWPAN)
 *
 * As we do not support 64-bit addresses, we just make one up, for this we
 * simply return 4 times concatenated the 16-bit address.
 *
 * @param[out] addr     64-bit pseudo long address, as array of 4 * 16-bit
 */
void nrfmin_get_pseudo_long_addr(uint16_t *addr);

/**
 * @brief   Get the IID build from the 16-bit node address
 *
 * @param[out] iid      the 64-bit IID, as array of 4 * 16-bit
 */
void nrfmin_get_iid(uint16_t *iid);

/**
 * @brief   Get the current channel
 *
 * @return  currently active channel
 */
uint16_t nrfmin_get_channel(void);

/**
 * @brief   Set the active channel
 *
 * @param[in] chan      targeted channel [0-31]
 *
 * @return  sizeof(uint16_t) on success
 * @return  -EOVERFLOW if channel is not applicable
 */
int nrfmin_set_channel(uint16_t chan);

/**
 * @brief   Get the current radio state
 *
 * @return  state the radio is currently in
 */
netopt_state_t nrfmin_get_state(void);

/**
 * @brief   Put the device into the given state
 *
 * @param[in] val       target state
 *
 * @return  sizeof(netopt_state_t) on success
 * @return  -ENOTSUP if target state is not applicable
 */
int nrfmin_set_state(netopt_state_t val);

/**
 * @brief   Get the current transmit power
 *
 * @return  transmission power in [dBm]
 */
int16_t nrfmin_get_txpower(void);

/**
 * @brief   Set the used transmission power
 *
 * @param[in] power     targeted power, in [dBm]
 */
void nrfmin_set_txpower(int16_t power);



#ifdef __cplusplus
}
#endif

#endif /* NRFMIN_H */
/** @} */