drivers/nrf24l01p_ng: netdev driver for nrf24l01+
The driver uses the netdev interface. Due to the limited capabilities of the transceiver (32 byte FIFO and no source address in the layer2 frame), it relies on 6LowPAN compression and adds the source address to the frame for that.
This commit is contained in:
parent
46337efd93
commit
f7a77ebb04
@ -101,6 +101,10 @@ ifneq (,$(filter nrfmin,$(USEMODULE)))
|
|||||||
USEMODULE += netif
|
USEMODULE += netif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(filter nrf24l01p_ng_%,$(USEMODULE)))
|
||||||
|
USEMODULE += nrf24l01p_ng
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq (,$(filter periph_ptp_timer periph_ptp_speed_adjustment,$(FEATURES_USED)))
|
ifneq (,$(filter periph_ptp_timer periph_ptp_speed_adjustment,$(FEATURES_USED)))
|
||||||
FEATURES_REQUIRED += periph_ptp
|
FEATURES_REQUIRED += periph_ptp
|
||||||
endif
|
endif
|
||||||
|
|||||||
@ -222,6 +222,7 @@ enum {
|
|||||||
NETDEV_TYPE_CC110X,
|
NETDEV_TYPE_CC110X,
|
||||||
NETDEV_TYPE_LORA,
|
NETDEV_TYPE_LORA,
|
||||||
NETDEV_TYPE_NRFMIN,
|
NETDEV_TYPE_NRFMIN,
|
||||||
|
NETDEV_TYPE_NRF24L01P_NG,
|
||||||
NETDEV_TYPE_SLIP,
|
NETDEV_TYPE_SLIP,
|
||||||
NETDEV_TYPE_ESP_NOW,
|
NETDEV_TYPE_ESP_NOW,
|
||||||
};
|
};
|
||||||
|
|||||||
465
drivers/include/nrf24l01p_ng.h
Normal file
465
drivers/include/nrf24l01p_ng.h
Normal file
@ -0,0 +1,465 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Otto-von-Guericke-Universität Magdeburg
|
||||||
|
*
|
||||||
|
* 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_nrf24l01p_ng NRF24L01+ (NG) 2.4 GHz trasceiver driver
|
||||||
|
* @ingroup drivers_netdev
|
||||||
|
*
|
||||||
|
* This module contains the driver for the NRF24L01+ (NG) 2.4 GHz
|
||||||
|
* transceiver.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
* @file
|
||||||
|
* @brief Public interface for NRF24L01+ (NG) devices
|
||||||
|
*
|
||||||
|
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
|
||||||
|
*/
|
||||||
|
#ifndef NRF24L01P_NG_H
|
||||||
|
#define NRF24L01P_NG_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "board.h"
|
||||||
|
#include "kernel_defines.h"
|
||||||
|
#include "net/gnrc/nettype.h"
|
||||||
|
#include "net/netdev.h"
|
||||||
|
#include "periph/gpio.h"
|
||||||
|
#include "periph/spi.h"
|
||||||
|
|
||||||
|
#include "nrf24l01p_ng_types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Minimum width of a NRF24L01+ layer-2 address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_MIN_ADDR_WIDTH (3)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum width of a NRF24L01+ layer-2 address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_MAX_ADDR_WIDTH (5)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pass the compiler a definition of NRF24L01P_NG_ADDR_WIDTH to configure
|
||||||
|
* the layer-2 address width of this transceiver.
|
||||||
|
*/
|
||||||
|
#ifndef NRF24L01P_NG_ADDR_WIDTH
|
||||||
|
#define NRF24L01P_NG_ADDR_WIDTH NRF24L01P_NG_MAX_ADDR_WIDTH
|
||||||
|
#elif (NRF24L01P_NG_ADDR_WIDTH < NRF24L01P_NG_MIN_ADDR_WIDTH) || \
|
||||||
|
(NRF24L01P_NG_ADDR_WIDTH > NRF24L01P_NG_MAX_ADDR_WIDTH)
|
||||||
|
#error "NRF24L01P_NG_ADDR_WIDTH must be within [3, 5]"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Agreed layer-2 address to send broadcast frames to
|
||||||
|
*
|
||||||
|
* The broadcast address will be assigned to pipe 0.
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_BROADCAST_ADDR { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Shortcut to access the address of pipe 0
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_ADDR_P0(dev) ((dev)->arxaddr.rx_addr_long[NRF24L01P_NG_P0])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Shortcut to access the address of pipe 1
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_ADDR_P1(dev) ((dev)->arxaddr.rx_addr_long[NRF24L01P_NG_P1])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Shortcut to access the least significant byte of the
|
||||||
|
* addresses pipe 2, pipe 3, pipe 4 or pipe 5
|
||||||
|
*
|
||||||
|
* The other bytes are shared with the address of pipe 1
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_ADDR_PX_LSB(dev, pipe) ((dev)->arxaddr.rx_addr_short[(pipe) - 2])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Struct that holds all active configuration values
|
||||||
|
*/
|
||||||
|
typedef struct __attribute__((packed)) {
|
||||||
|
/**
|
||||||
|
* @brief padding
|
||||||
|
*/
|
||||||
|
uint8_t : 1;
|
||||||
|
/**
|
||||||
|
* @brief Current channel
|
||||||
|
*/
|
||||||
|
uint8_t cfg_channel : 7;
|
||||||
|
/**
|
||||||
|
* @brief padding
|
||||||
|
*/
|
||||||
|
uint8_t : 2;
|
||||||
|
/**
|
||||||
|
* @brief Current CRC length configuration value
|
||||||
|
* @see nrf24l01p_ng_crc_t
|
||||||
|
*/
|
||||||
|
uint8_t cfg_crc : 2;
|
||||||
|
/**
|
||||||
|
* @brief Current tx power configuration value
|
||||||
|
* @see nrf24l01p_ng_tx_power_t
|
||||||
|
*/
|
||||||
|
uint8_t cfg_tx_power : 2;
|
||||||
|
/**
|
||||||
|
* @brief Current data rate configuration value
|
||||||
|
* @see nrf24l01p_ng_rfdr_t
|
||||||
|
*/
|
||||||
|
uint8_t cfg_data_rate : 2;
|
||||||
|
/**
|
||||||
|
* @brief Current maximum number of retransmissions
|
||||||
|
*/
|
||||||
|
uint8_t cfg_max_retr : 4;
|
||||||
|
/**
|
||||||
|
* @brief Current retransmission delay configuration value
|
||||||
|
* @see nrf24l01p_ng_ard_t
|
||||||
|
*/
|
||||||
|
uint8_t cfg_retr_delay : 4;
|
||||||
|
} nrf24l01p_ng_cfg_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Struct of NRF24L01+ initialization parameters
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
spi_t spi; /**< SPI bus */
|
||||||
|
spi_clk_t spi_clk; /**< SPI clock speed */
|
||||||
|
gpio_t pin_cs; /**< SPI chip select gpio pin */
|
||||||
|
gpio_t pin_ce; /**< NRF24L01+ chip enable gpio pin */
|
||||||
|
gpio_t pin_irq; /**< NRF24L01+ IRQ gpio pin */
|
||||||
|
nrf24l01p_ng_cfg_t config; /**< Current configuration values */
|
||||||
|
} nrf24l01p_ng_params_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief NRF24L01+ device struct
|
||||||
|
*/
|
||||||
|
struct nrf24l01p_ng {
|
||||||
|
netdev_t netdev; /**< Netdev member */
|
||||||
|
nrf24l01p_ng_params_t params; /**< Parameters */
|
||||||
|
uint8_t state; /**< Current operation state */
|
||||||
|
uint8_t idle_state; /**< State to return to after sending */
|
||||||
|
/**
|
||||||
|
* @brief Rx addresses
|
||||||
|
*
|
||||||
|
* The NRF24L01+ has 6 data pipes.
|
||||||
|
* Each data pipe has a unique address.
|
||||||
|
* The address of a pipe can be 3 to 5 bytes long
|
||||||
|
* but must be equal for all pipes.
|
||||||
|
* The addresses of pipe 0 and pipe 1 can be arbitrary while the addresses
|
||||||
|
* of pipe 2 to pipe 5 share the most significant bytes, thus they only
|
||||||
|
* differ in the least significant byte.
|
||||||
|
* The least significant byte must be different for all pipes.
|
||||||
|
*
|
||||||
|
* Data pipe 0 is also the Tx pipe.
|
||||||
|
* That means if you want to send a frame, you must assign to pipe 0
|
||||||
|
* the address of the recipient. After a transmission if you want to
|
||||||
|
* continue listening on pipe 0, the address of pipe 0 must be restored.
|
||||||
|
*/
|
||||||
|
struct {
|
||||||
|
/**
|
||||||
|
* @brief Array to access the addresses of pipe 0 and pipe 1 via
|
||||||
|
* pipe indices @see nrf24l01p_ng_pipe_t
|
||||||
|
*/
|
||||||
|
uint8_t rx_addr_long[2][NRF24L01P_NG_ADDR_WIDTH];
|
||||||
|
/**
|
||||||
|
* @brief Array to access the addresses of pipe 2, pipe 3,
|
||||||
|
* pipe 4 and pipe 5 via pipe indices
|
||||||
|
* @see nrf24l01p_ng_pipe_t
|
||||||
|
*/
|
||||||
|
uint8_t rx_addr_short[4];
|
||||||
|
} arxaddr;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Setup the NRF24L01+ driver, but perform no initialization
|
||||||
|
*
|
||||||
|
* @ref netdev_driver_t::init can be used after this call to initialize the
|
||||||
|
* transceiver.
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[in] params Parameters of the device to setup
|
||||||
|
*
|
||||||
|
* @retval 0 Device successfully set up
|
||||||
|
*/
|
||||||
|
int nrf24l01p_ng_setup(nrf24l01p_ng_t *dev,
|
||||||
|
const nrf24l01p_ng_params_t *params);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable or disable data pipe @p pipe
|
||||||
|
*
|
||||||
|
* If @p pipe should be enabled, it is advised to
|
||||||
|
* set an address in advance.
|
||||||
|
* @see nrf24l01p_ng_set_rx_addr
|
||||||
|
* For Enhanced ShockBurst, auto ACK and dynamic
|
||||||
|
* payload length are enabled
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[in] pipe Pipe index
|
||||||
|
* @param[in] enable If pipe should be enabled or disabled
|
||||||
|
*
|
||||||
|
* @retval 0 Success
|
||||||
|
* @retval -EINVAL Bad pipe index
|
||||||
|
*/
|
||||||
|
int nrf24l01p_ng_set_enable_pipe(nrf24l01p_ng_t *dev, nrf24l01p_ng_pipe_t pipe,
|
||||||
|
bool enable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Query if data pipe @p pipe is enabled
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[in] pipe Pipe index
|
||||||
|
* @param[out] enable If pipe is enabled or disabled
|
||||||
|
*
|
||||||
|
* @retval 0 Success
|
||||||
|
* @retval -EINVAL Bad pipe index
|
||||||
|
*/
|
||||||
|
int nrf24l01p_ng_get_enable_pipe(nrf24l01p_ng_t *dev, nrf24l01p_ng_pipe_t pipe,
|
||||||
|
bool* enable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Configure air data rate
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[in] data_rate Data rate configuration value
|
||||||
|
*
|
||||||
|
* @retval 0 Success
|
||||||
|
* @retval -EINVAL Bad data rate value
|
||||||
|
* @retval -EAGAIN Current state does not permit changing data rate
|
||||||
|
*/
|
||||||
|
int nrf24l01p_ng_set_air_data_rate(nrf24l01p_ng_t *dev,
|
||||||
|
nrf24l01p_ng_rfdr_t data_rate);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get currently configured data rate
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[out] data_rate Configuration data rate value (may be NULL)
|
||||||
|
*
|
||||||
|
* @return Data rate in [kbit/s]
|
||||||
|
*/
|
||||||
|
uint16_t nrf24l01p_ng_get_air_data_rate(const nrf24l01p_ng_t *dev,
|
||||||
|
nrf24l01p_ng_rfdr_t *data_rate);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Configure CRC length
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[in] crc Configuration CRC value
|
||||||
|
*
|
||||||
|
* @retval 0 Success
|
||||||
|
* @retval -EINVAL Bad CRC configuration value
|
||||||
|
* @retval -ENOTSUP CRC length not supported
|
||||||
|
* @retval -EAGAIN Current state does not permit changing CRC length
|
||||||
|
*/
|
||||||
|
int nrf24l01p_ng_set_crc(nrf24l01p_ng_t *dev, nrf24l01p_ng_crc_t crc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get currently configured CRC length
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[out] crc Configuration crc value (may be NULL)
|
||||||
|
*
|
||||||
|
* @return Current CRC length
|
||||||
|
*/
|
||||||
|
uint8_t nrf24l01p_ng_get_crc(const nrf24l01p_ng_t *dev,
|
||||||
|
nrf24l01p_ng_crc_t *crc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Configure Tx trasceiver power
|
||||||
|
*
|
||||||
|
* @param[in] dev NRf24L01+ device handle
|
||||||
|
* @param[in] power Configuration Tx power value
|
||||||
|
*
|
||||||
|
* @retval 0 Success
|
||||||
|
* @retval -EINVAL Bad Tx power configuration value
|
||||||
|
* @retval -EAGAIN Current state does not permit changin Tx power
|
||||||
|
*/
|
||||||
|
int nrf24l01p_ng_set_tx_power(nrf24l01p_ng_t *dev,
|
||||||
|
nrf24l01p_ng_tx_power_t power);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get currently configured Tx transceiver power
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[out] power Configuration Tx power value
|
||||||
|
*
|
||||||
|
* @return Tx power in [dbm]
|
||||||
|
*/
|
||||||
|
int8_t nrf24l01p_ng_get_tx_power(const nrf24l01p_ng_t *dev,
|
||||||
|
nrf24l01p_ng_tx_power_t *power);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set transceiver channel
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24l01+ device handle
|
||||||
|
* @param[in] channel Channel [0; 15]
|
||||||
|
*
|
||||||
|
* @retval 0 Success
|
||||||
|
* @retval -EINVAL Bad channel
|
||||||
|
* @retval -EAGAIN Current state does not permit switching channel
|
||||||
|
*/
|
||||||
|
int nrf24l01p_ng_set_channel(nrf24l01p_ng_t *dev, uint8_t channel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get currently configured transceiver channel
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
*
|
||||||
|
* @return Transceiver channel
|
||||||
|
*/
|
||||||
|
uint8_t nrf24l01p_ng_get_channel(const nrf24l01p_ng_t *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set Rx address of a certain data pipe
|
||||||
|
*
|
||||||
|
* If you want to set the address of pipe 2, 3, 4 or 5
|
||||||
|
* you only set the LSB because the other bytes are
|
||||||
|
* equal to the address of pipe 1.
|
||||||
|
*
|
||||||
|
* For pipe 0 and 1 NRF24L01P_NG_ADDR_WIGTH bytes are expected
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[in] addr Rx address
|
||||||
|
* @param[in] pipe Pipe index
|
||||||
|
*
|
||||||
|
* @retval 0 Success
|
||||||
|
* @retval -EINVAL Bad address length
|
||||||
|
* @return -EAGAIN Current state does not permit changin Rx address
|
||||||
|
*/
|
||||||
|
int nrf24l01p_ng_set_rx_address(nrf24l01p_ng_t *dev, const uint8_t *addr,
|
||||||
|
nrf24l01p_ng_pipe_t pipe);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get current Rx address of a certain data pipe
|
||||||
|
*
|
||||||
|
* @p addr must be at least NRF24L01P_NG_ADDR_WIDTH wide.
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[out] addr Rx address
|
||||||
|
* @param[in] pipe Pipe index
|
||||||
|
*
|
||||||
|
* @return Address width
|
||||||
|
* @retval -EINVAL Bad pipe index
|
||||||
|
*/
|
||||||
|
int nrf24l01p_ng_get_rx_address(const nrf24l01p_ng_t *dev, uint8_t *addr,
|
||||||
|
nrf24l01p_ng_pipe_t pipe);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Configure maximum number of retransmissions for ESB
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[in] max_rt Number of maximum retransmissions [0; 15]
|
||||||
|
*
|
||||||
|
* @retval 0 Success
|
||||||
|
* @retval -EINVAL Unsupported number of retransmissions
|
||||||
|
* @retval -EAGAIN Current state does not permit changing
|
||||||
|
* the maximum number of retransmissions
|
||||||
|
*/
|
||||||
|
int nrf24l01p_ng_set_max_retransm(nrf24l01p_ng_t *dev, uint8_t max_rt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get currently configured number of maximum retransmissions for ESB
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
*
|
||||||
|
* @return Maximum number of retransmissions
|
||||||
|
*/
|
||||||
|
uint8_t nrf24l01p_ng_get_max_retransm(const nrf24l01p_ng_t *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set retransmission delay for ESB
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[in] rt_delay Configuration retransmission delay value
|
||||||
|
*
|
||||||
|
* @return 0
|
||||||
|
* @return -EINVAL Bad retransmission delay value
|
||||||
|
* @return -EAGAIN Current state does not permit changing
|
||||||
|
* retransmission delay
|
||||||
|
*/
|
||||||
|
int nrf24l01p_ng_set_retransm_delay(nrf24l01p_ng_t *dev,
|
||||||
|
nrf24l01p_ng_ard_t rt_delay);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get retransmission delay for ESB
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[out] rt_delay Configuration retransmission delay value
|
||||||
|
*
|
||||||
|
* @return Retransmission delay in [us]
|
||||||
|
*/
|
||||||
|
uint16_t nrf24l01p_ng_get_retransm_delay(const nrf24l01p_ng_t *dev,
|
||||||
|
nrf24l01p_ng_ard_t *rt_delay);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Put device into
|
||||||
|
* sleep mode(@ref NRF24L01P_NG_STATE_POWER_DOWN),
|
||||||
|
* standby mode (@ref NRF24L01P_NG_STATE_STANDBY_1),
|
||||||
|
* or Rx mode (@ref NRF24L01P_NG_STATE_RX_MODE)
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[in] state State
|
||||||
|
*
|
||||||
|
* @return Old state
|
||||||
|
* @retval -EAGAIN Device is currently not permitted to change state
|
||||||
|
* @retval -ENOTSUP Device is not permitted to change state to @p state
|
||||||
|
*/
|
||||||
|
int nrf24l01p_ng_set_state(nrf24l01p_ng_t *dev, nrf24l01p_ng_state_t state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get current device state
|
||||||
|
*
|
||||||
|
* @param[in] dev NRf24L01+ device handle
|
||||||
|
*
|
||||||
|
* @return Device state
|
||||||
|
*/
|
||||||
|
nrf24l01p_ng_state_t nrf24l01p_ng_get_state(const nrf24l01p_ng_t *dev);
|
||||||
|
|
||||||
|
#if IS_USED(MODULE_NRF24L01P_NG_DIAGNOSTICS)
|
||||||
|
/**
|
||||||
|
* @brief Get state variable as a string
|
||||||
|
*
|
||||||
|
* @param[in] state State
|
||||||
|
*
|
||||||
|
* @return @p state as a string
|
||||||
|
*/
|
||||||
|
const char *
|
||||||
|
nrf24l01p_ng_diagnostics_state_to_string(nrf24l01p_ng_state_t state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert string to state variable
|
||||||
|
*
|
||||||
|
* @param[in] sstate State string
|
||||||
|
*
|
||||||
|
* @return State variable
|
||||||
|
*/
|
||||||
|
nrf24l01p_ng_state_t
|
||||||
|
nrf24l01p_ng_diagnostics_string_to_state(const char *sstate);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Print all registers
|
||||||
|
*
|
||||||
|
* @param[in] dev NRf24L01+ device handle
|
||||||
|
*/
|
||||||
|
void nrf24l01p_ng_print_all_regs(nrf24l01p_ng_t *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Print device parameters
|
||||||
|
*
|
||||||
|
* @param[in] dev NRf24L01+ device handle
|
||||||
|
*/
|
||||||
|
void nrf24l01p_ng_print_dev_info(const nrf24l01p_ng_t *dev);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* NRF24L01P_NG_H */
|
||||||
|
/** @} */
|
||||||
10
drivers/nrf24l01p_ng/Makefile
Normal file
10
drivers/nrf24l01p_ng/Makefile
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# Makefile for the NRF24L01+ radio driver
|
||||||
|
MODULE = nrf24l01p_ng
|
||||||
|
|
||||||
|
# exclude submodule sources from *.c wildcard source selection
|
||||||
|
SRC := $(filter-out diagnostics.c,$(wildcard *.c))
|
||||||
|
|
||||||
|
# enable submodules
|
||||||
|
SUBMODULES := 1
|
||||||
|
|
||||||
|
include $(RIOTBASE)/Makefile.base
|
||||||
10
drivers/nrf24l01p_ng/Makefile.dep
Normal file
10
drivers/nrf24l01p_ng/Makefile.dep
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
USEMODULE += luid
|
||||||
|
USEMODULE += netif
|
||||||
|
USEMODULE += xtimer
|
||||||
|
ifneq (,$(filter gnrc_ipv6,$(USEMODULE)))
|
||||||
|
USEMODULE += gnrc_sixlowpan_default
|
||||||
|
endif
|
||||||
|
|
||||||
|
FEATURES_REQUIRED += periph_gpio
|
||||||
|
FEATURES_REQUIRED += periph_gpio_irq
|
||||||
|
FEATURES_REQUIRED += periph_spi
|
||||||
2
drivers/nrf24l01p_ng/Makefile.include
Normal file
2
drivers/nrf24l01p_ng/Makefile.include
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
USEMODULE_INCLUDES_nrf24l01p_ng := $(LAST_MAKEFILEDIR)/include
|
||||||
|
USEMODULE_INCLUDES += $(USEMODULE_INCLUDES_nrf24l01p_ng)
|
||||||
391
drivers/nrf24l01p_ng/diagnostics.c
Normal file
391
drivers/nrf24l01p_ng/diagnostics.c
Normal file
@ -0,0 +1,391 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Otto-von-Guericke-Universität Magdeburg
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @ingroup drivers_nrf24l01p_ng
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Functions to debug the NRF24L01+ (NG) transceiver
|
||||||
|
*
|
||||||
|
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "nrf24l01p_ng_registers.h"
|
||||||
|
#include "nrf24l01p_ng_communication.h"
|
||||||
|
#include "nrf24l01p_ng_diagnostics.h"
|
||||||
|
|
||||||
|
#if NRF24L01P_NG_ADDR_WIDTH == 3
|
||||||
|
#define ADDR_FMT "%02x%02x%02x"
|
||||||
|
#define ADDR_P0(dev) \
|
||||||
|
NRF24L01P_NG_ADDR_P0(dev)[0], \
|
||||||
|
NRF24L01P_NG_ADDR_P0(dev)[1], \
|
||||||
|
NRF24L01P_NG_ADDR_P0(dev)[2]
|
||||||
|
#define ADDR_P1(dev) \
|
||||||
|
NRF24L01P_NG_ADDR_P1(dev)[0], \
|
||||||
|
NRF24L01P_NG_ADDR_P1(dev)[1], \
|
||||||
|
NRF24L01P_NG_ADDR_P1(dev)[2]
|
||||||
|
#elif NRF24L01P_NG_ADDR_WIDTH == 4
|
||||||
|
#define ADDR_FMT "%02x%02x%02x%02x"
|
||||||
|
#define ADDR_P0(dev) \
|
||||||
|
NRF24L01P_NG_ADDR_P0(dev)[0], \
|
||||||
|
NRF24L01P_NG_ADDR_P0(dev)[1], \
|
||||||
|
NRF24L01P_NG_ADDR_P0(dev)[2], \
|
||||||
|
NRF24L01P_NG_ADDR_P0(dev)[3]
|
||||||
|
#define ADDR_P1(dev) \
|
||||||
|
NRF24L01P_NG_ADDR_P1(dev)[0], \
|
||||||
|
NRF24L01P_NG_ADDR_P1(dev)[1], \
|
||||||
|
NRF24L01P_NG_ADDR_P1(dev)[2], \
|
||||||
|
NRF24L01P_NG_ADDR_P1(dev)[3]
|
||||||
|
#else
|
||||||
|
#define ADDR_FMT "%02x%02x%02x%02x%02x"
|
||||||
|
#define ADDR_P0(dev) \
|
||||||
|
NRF24L01P_NG_ADDR_P0(dev)[0], \
|
||||||
|
NRF24L01P_NG_ADDR_P0(dev)[1], \
|
||||||
|
NRF24L01P_NG_ADDR_P0(dev)[2], \
|
||||||
|
NRF24L01P_NG_ADDR_P0(dev)[3], \
|
||||||
|
NRF24L01P_NG_ADDR_P0(dev)[4]
|
||||||
|
#define ADDR_P1(dev) \
|
||||||
|
NRF24L01P_NG_ADDR_P1(dev)[0], \
|
||||||
|
NRF24L01P_NG_ADDR_P1(dev)[1], \
|
||||||
|
NRF24L01P_NG_ADDR_P1(dev)[2], \
|
||||||
|
NRF24L01P_NG_ADDR_P1(dev)[3], \
|
||||||
|
NRF24L01P_NG_ADDR_P1(dev)[4]
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char *
|
||||||
|
nrf24l01p_ng_diagnostics_state_to_string(nrf24l01p_ng_state_t state)
|
||||||
|
{
|
||||||
|
if (state == NRF24L01P_NG_STATE_POWER_DOWN) {
|
||||||
|
return "POWER_DOWN";
|
||||||
|
}
|
||||||
|
if (state == NRF24L01P_NG_STATE_STANDBY_1) {
|
||||||
|
return "STANDBY_1";
|
||||||
|
}
|
||||||
|
if (state == NRF24L01P_NG_STATE_STANDBY_2) {
|
||||||
|
return "STANDBY_2";
|
||||||
|
}
|
||||||
|
if (state == NRF24L01P_NG_STATE_TX_MODE) {
|
||||||
|
return "TX_MODE";
|
||||||
|
}
|
||||||
|
if (state == NRF24L01P_NG_STATE_RX_MODE) {
|
||||||
|
return "RX_MODE";
|
||||||
|
}
|
||||||
|
return "UNDEFINED";
|
||||||
|
}
|
||||||
|
|
||||||
|
nrf24l01p_ng_state_t
|
||||||
|
nrf24l01p_ng_diagnostics_string_to_state(const char *sstate)
|
||||||
|
{
|
||||||
|
if (!strcmp(sstate, "POWER_DOWN")) {
|
||||||
|
return NRF24L01P_NG_STATE_POWER_DOWN;
|
||||||
|
}
|
||||||
|
if (!strcmp(sstate, "STANDBY_1")) {
|
||||||
|
return NRF24L01P_NG_STATE_STANDBY_1;
|
||||||
|
}
|
||||||
|
if (!strcmp(sstate, "STANDBY_2")) {
|
||||||
|
return NRF24L01P_NG_STATE_STANDBY_2;
|
||||||
|
}
|
||||||
|
if (!strcmp(sstate, "TX_MODE")) {
|
||||||
|
return NRF24L01P_NG_STATE_TX_MODE;
|
||||||
|
}
|
||||||
|
if (!strcmp(sstate, "RX_MODE")) {
|
||||||
|
return NRF24L01P_NG_STATE_RX_MODE;
|
||||||
|
}
|
||||||
|
return NRF24L01P_NG_STATE_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nrf24l01p_ng_diagnostics_print_all_regs(const nrf24l01p_ng_t *dev)
|
||||||
|
{
|
||||||
|
uint8_t config;
|
||||||
|
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_CONFIG, &config, 1);
|
||||||
|
puts("");
|
||||||
|
printf(
|
||||||
|
"CONFIG [MASK_RX_DR %u "
|
||||||
|
"MASK_TX_DS %u "
|
||||||
|
"MASK_MAX_RT %u "
|
||||||
|
"EN_CRC %u "
|
||||||
|
"CRCO %u "
|
||||||
|
"PWR_UP %u "
|
||||||
|
"PRIM_RX %u]\n",
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_MASK_RX_DR(config),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_MASK_TX_DS(config),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_MAX_RT(config),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_EN_CRC(config),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_CRCO(config),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_PWR_UP(config),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_PRIM_RX(config)
|
||||||
|
);
|
||||||
|
uint8_t en_aa;
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_EN_AA, &en_aa, 1);
|
||||||
|
printf(
|
||||||
|
"EN_AA [ENAA_P5 %u "
|
||||||
|
"ENAA_P4 %u "
|
||||||
|
"ENAA_P3 %u "
|
||||||
|
"ENAA_P2 %u "
|
||||||
|
"ENAA_P1 %u "
|
||||||
|
"ENAA_P0 %u]\n",
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_ENAA_P5(en_aa),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_ENAA_P4(en_aa),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_ENAA_P3(en_aa),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_ENAA_P2(en_aa),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_ENAA_P1(en_aa),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_ENAA_P0(en_aa)
|
||||||
|
);
|
||||||
|
uint8_t en_rxaddr;
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_EN_RXADDR, &en_rxaddr, 1);
|
||||||
|
printf(
|
||||||
|
"EN_RXADDR [ERX_P5 %u "
|
||||||
|
"ERX_P4 %u "
|
||||||
|
"ERX_P3 %u "
|
||||||
|
"ERX_P2 %u "
|
||||||
|
"ERX_P1 %u "
|
||||||
|
"ERX_P0 %u]\n",
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_ERX_P5(en_rxaddr),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_ERX_P4(en_rxaddr),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_ERX_P3(en_rxaddr),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_ERX_P2(en_rxaddr),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_ERX_P1(en_rxaddr),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_ERX_P0(en_rxaddr)
|
||||||
|
);
|
||||||
|
uint8_t setup_aw;
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_SETUP_AW, &setup_aw, 1);
|
||||||
|
printf(
|
||||||
|
"SETUP_AW [AW %u]\n",
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_AW(setup_aw)
|
||||||
|
);
|
||||||
|
uint8_t setup_retr;
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_SETUP_RETR, &setup_retr, 1);
|
||||||
|
printf(
|
||||||
|
"SETUP_RETR [ARD %u ARC %u]\n",
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_ARD(setup_retr),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_ARC(setup_retr)
|
||||||
|
);
|
||||||
|
uint8_t rf_ch;
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_RF_CH, &rf_ch, 1);
|
||||||
|
printf(
|
||||||
|
"RF_CH [RF_CH %u]\n",
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_RF_CH(rf_ch)
|
||||||
|
);
|
||||||
|
uint8_t rf_setup;
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_RF_SETUP, &rf_setup, 1);
|
||||||
|
printf(
|
||||||
|
"RF_SETUP [CONT_WAVE %u "
|
||||||
|
"RF_DR_LOW %u "
|
||||||
|
"PLL_LOCK %u "
|
||||||
|
"RF_DR_HIGH %u "
|
||||||
|
"RF_PWR %u]\n",
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_CONT_WAVE(rf_setup),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_RF_DR_LOW(rf_setup),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_PLL_LOCK(rf_setup),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_RF_DR_HIGH(rf_setup),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_RF_PWR(rf_setup)
|
||||||
|
);
|
||||||
|
uint8_t status;
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_STATUS, &status, 1);
|
||||||
|
printf(
|
||||||
|
"STATUS [RX_DR %u "
|
||||||
|
"TX_DS %u "
|
||||||
|
"MAX_RT %u "
|
||||||
|
"RX_P_NO %u "
|
||||||
|
"TX_FULL %u]\n",
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_RX_DR(status),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_TX_DS(status),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_MAX_RT(status),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_RX_P_NO(status),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_TX_FULL(status)
|
||||||
|
);
|
||||||
|
uint8_t observe_tx;
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_OBSERVE_TX, &observe_tx, 1);
|
||||||
|
printf(
|
||||||
|
"OBSERVE_TX [PLOS_CNT %u ARC_CNT %u]\n",
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_PLOS_CNT(observe_tx),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_ARC_CNT(observe_tx)
|
||||||
|
);
|
||||||
|
uint8_t rpd;
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_RPD, &rpd, 1);
|
||||||
|
printf(
|
||||||
|
"RPD [RPD %u]\n",
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_RPD(rpd)
|
||||||
|
);
|
||||||
|
uint8_t rx_addr_px_40[2][NRF24L01P_NG_MAX_ADDR_WIDTH]; /* Pipe 0/1 */
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_RX_ADDR_P0, rx_addr_px_40[0],
|
||||||
|
NRF24L01P_NG_MAX_ADDR_WIDTH);
|
||||||
|
printf(
|
||||||
|
"RX_ADDR_P0 [RX_ADDR_P0 %02x:%02x:%02x:%02x:%02x]\n",
|
||||||
|
rx_addr_px_40[0][0],
|
||||||
|
rx_addr_px_40[0][1],
|
||||||
|
rx_addr_px_40[0][2],
|
||||||
|
rx_addr_px_40[0][3],
|
||||||
|
rx_addr_px_40[0][4]
|
||||||
|
);
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_RX_ADDR_P1, rx_addr_px_40[1],
|
||||||
|
NRF24L01P_NG_MAX_ADDR_WIDTH);
|
||||||
|
printf(
|
||||||
|
"RX_ADDR_P1 [RX_ADDR_P1 %02x:%02x:%02x:%02x:%02x]\n",
|
||||||
|
rx_addr_px_40[1][0],
|
||||||
|
rx_addr_px_40[1][1],
|
||||||
|
rx_addr_px_40[1][2],
|
||||||
|
rx_addr_px_40[1][3],
|
||||||
|
rx_addr_px_40[1][4]
|
||||||
|
);
|
||||||
|
uint8_t rx_addr_px_8[4]; /* Pipe 2/3/4/5 */
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_RX_ADDR_P2,
|
||||||
|
&rx_addr_px_8[0], 1);
|
||||||
|
printf(
|
||||||
|
"RX_ADDR_P2 [RX_ADDR_P2 %02x]\n",
|
||||||
|
rx_addr_px_8[0]
|
||||||
|
);
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_RX_ADDR_P3,
|
||||||
|
&rx_addr_px_8[1], 1);
|
||||||
|
printf(
|
||||||
|
"RX_ADDR_P3 [RX_ADDR_P3 %02x]\n",
|
||||||
|
rx_addr_px_8[1]
|
||||||
|
);
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_RX_ADDR_P4,
|
||||||
|
&rx_addr_px_8[2], 1);
|
||||||
|
printf(
|
||||||
|
"RX_ADDR_P4 [RX_ADDR_P4 %02x]\n",
|
||||||
|
rx_addr_px_8[2]
|
||||||
|
);
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_RX_ADDR_P5,
|
||||||
|
&rx_addr_px_8[3], 1);
|
||||||
|
printf(
|
||||||
|
"RX_ADDR_P5 [RX_ADDR_P5 %02x]\n",
|
||||||
|
rx_addr_px_8[3]
|
||||||
|
);
|
||||||
|
uint8_t tx_addr[NRF24L01P_NG_MAX_ADDR_WIDTH];
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_TX_ADDR, tx_addr,
|
||||||
|
NRF24L01P_NG_MAX_ADDR_WIDTH);
|
||||||
|
printf(
|
||||||
|
"TX_ADDR [TX_ADDR %02x:%02x:%02x:%02x:%02x]\n",
|
||||||
|
tx_addr[0],
|
||||||
|
tx_addr[1],
|
||||||
|
tx_addr[2],
|
||||||
|
tx_addr[3],
|
||||||
|
tx_addr[4]
|
||||||
|
);
|
||||||
|
uint8_t rx_pw_px[6];
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_RX_PW_P0, &rx_pw_px[0], 1);
|
||||||
|
printf(
|
||||||
|
"RX_PW_P0 [RX_PW_P0 %u]\n",
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_RX_PW_PX(rx_pw_px[0])
|
||||||
|
);
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_RX_PW_P1, &rx_pw_px[1], 1);
|
||||||
|
printf(
|
||||||
|
"RX_PW_P1 [RX_PW_P1 %u]\n",
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_RX_PW_PX(rx_pw_px[1])
|
||||||
|
);
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_RX_PW_P2, &rx_pw_px[2], 1);
|
||||||
|
printf(
|
||||||
|
"RX_PW_P2 [RX_PW_P2 %u]\n",
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_RX_PW_PX(rx_pw_px[2])
|
||||||
|
);
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_RX_PW_P3, &rx_pw_px[3], 1);
|
||||||
|
printf(
|
||||||
|
"RX_PW_P3 [RX_PW_P3 %u]\n",
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_RX_PW_PX(rx_pw_px[3])
|
||||||
|
);
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_RX_PW_P4, &rx_pw_px[4], 1);
|
||||||
|
printf(
|
||||||
|
"RX_PW_P4 [RX_PW_P4 %u]\n",
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_RX_PW_PX(rx_pw_px[4])
|
||||||
|
);
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_RX_PW_P5, &rx_pw_px[5], 1);
|
||||||
|
printf(
|
||||||
|
"RX_PW_P5 [RX_PW_P5 %u]\n",
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_RX_PW_PX(rx_pw_px[5])
|
||||||
|
);
|
||||||
|
uint8_t fifo_status;
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_FIFO_STATUS, &fifo_status, 1);
|
||||||
|
printf(
|
||||||
|
"FIFO_STATUS [TX_REUSE %u "
|
||||||
|
"TX_FULL %u "
|
||||||
|
"TX_EMPTY %u "
|
||||||
|
"RX_FULL %u "
|
||||||
|
"RX_EMPTY %u]\n",
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_TX_REUSE(fifo_status),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_TX_FULL_(fifo_status),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_TX_EMPTY(fifo_status),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_RX_FULL(fifo_status),
|
||||||
|
NRF24L01P_NG_VAL_RX_EMPTY(fifo_status)
|
||||||
|
);
|
||||||
|
uint8_t dynpd;
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_DYNPD, &dynpd, 1);
|
||||||
|
printf(
|
||||||
|
"DYNDP [DPL_P5 %u "
|
||||||
|
"DPL_P4 %u "
|
||||||
|
"DPL_P3 %u "
|
||||||
|
"DPL_P2 %u "
|
||||||
|
"DPL_P1 %u "
|
||||||
|
"DPL_P0 %u]\n",
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_DPL_P5(dynpd),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_DPL_P4(dynpd),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_DPL_P3(dynpd),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_DPL_P2(dynpd),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_DPL_P1(dynpd),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_DPL_P0(dynpd)
|
||||||
|
);
|
||||||
|
uint8_t features;
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_FEATURES, &features, 1);
|
||||||
|
printf(
|
||||||
|
"FEATURES [EN_DPL %u EN_ACK_PAY %u DYN_ACK %u]\n",
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_EN_DPL(features),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_EN_ACK_PAY(features),
|
||||||
|
(unsigned)NRF24L01P_NG_VAL_EN_DYN_ACK(features)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nrf24l01p_ng_diagnostics_print_dev_info(const nrf24l01p_ng_t *dev)
|
||||||
|
{
|
||||||
|
printf("device: %p\n", (const void *)dev);
|
||||||
|
printf("address length: %u\n", (unsigned)NRF24L01P_NG_ADDR_WIDTH);
|
||||||
|
printf("device params:\n");
|
||||||
|
printf("\tChannel: %u\n",
|
||||||
|
dev->params.config.cfg_channel);
|
||||||
|
printf("\tCRC length: %u bytes\n",
|
||||||
|
(unsigned)nrf24l01p_ng_etoval_crc(dev->params.config.cfg_crc));
|
||||||
|
printf("\tData rate: %u kbps\n",
|
||||||
|
(unsigned)
|
||||||
|
nrf24l01p_ng_etoval_rfdr(dev->params.config.cfg_data_rate));
|
||||||
|
printf("\tMax. retransmissions: %u\n",
|
||||||
|
dev->params.config.cfg_max_retr);
|
||||||
|
printf("\tRetransmission delay: %u us\n",
|
||||||
|
(unsigned)
|
||||||
|
nrf24l01p_ng_etoval_ard(dev->params.config.cfg_retr_delay));
|
||||||
|
printf("\tTx power: %d dbm\n",
|
||||||
|
nrf24l01p_ng_etoval_tx_power(dev->params.config.cfg_tx_power));
|
||||||
|
printf("\tRx address p0: "ADDR_FMT"\n",
|
||||||
|
ADDR_P0(dev));
|
||||||
|
printf("\tRX address p1: "ADDR_FMT"\n",
|
||||||
|
ADDR_P1(dev));
|
||||||
|
printf("\tRX address p2: %02x\n",
|
||||||
|
NRF24L01P_NG_ADDR_PX_LSB(dev, NRF24L01P_NG_P2));
|
||||||
|
printf("\tRX address p3: %02x\n",
|
||||||
|
NRF24L01P_NG_ADDR_PX_LSB(dev, NRF24L01P_NG_P3));
|
||||||
|
printf("\tRX address p4: %02x\n",
|
||||||
|
NRF24L01P_NG_ADDR_PX_LSB(dev, NRF24L01P_NG_P4));
|
||||||
|
printf("\tRX address p5: %02x\n",
|
||||||
|
NRF24L01P_NG_ADDR_PX_LSB(dev, NRF24L01P_NG_P5));
|
||||||
|
|
||||||
|
printf("State: %s\n",
|
||||||
|
nrf24l01p_ng_diagnostics_state_to_string(dev->state));
|
||||||
|
}
|
||||||
|
|
||||||
|
void nrf24l01p_ng_diagnostics_print_frame(const nrf24l01p_ng_t *dev,
|
||||||
|
const void *frame, size_t len)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
puts("Rx frame");
|
||||||
|
for (uint8_t i = 0; i < len; i++) {
|
||||||
|
printf("0x%02X ", ((uint8_t *)frame)[i]);
|
||||||
|
}
|
||||||
|
puts("");
|
||||||
|
}
|
||||||
236
drivers/nrf24l01p_ng/gnrc_netif_nrf24l01p_ng.c
Normal file
236
drivers/nrf24l01p_ng/gnrc_netif_nrf24l01p_ng.c
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Otto-von-Guericke-Universität Magdeburg
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @ingroup drivers_nrf24l01p_ng
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Implementation of gnrc_netif Rx/Tx adaptation functions
|
||||||
|
* for the NRF24L01+ (NG) transceiver
|
||||||
|
*
|
||||||
|
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#define ENABLE_DEBUG (0)
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#include "net/gnrc.h"
|
||||||
|
#include "gnrc_netif_nrf24l01p_ng.h"
|
||||||
|
#include "nrf24l01p_ng.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Broadcast/Multicast flag
|
||||||
|
*/
|
||||||
|
#define BCAST (GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)
|
||||||
|
|
||||||
|
static gnrc_pktsnip_t *_nrf24l01p_ng_pkt_recv(gnrc_netif_t *netif)
|
||||||
|
{
|
||||||
|
/* get frame size */
|
||||||
|
int frame_len = netif->dev->driver->recv(netif->dev, NULL, 1, NULL);
|
||||||
|
|
||||||
|
/* allocate space for the packet in the pktbuf */
|
||||||
|
gnrc_pktsnip_t *frame = gnrc_pktbuf_add(NULL, NULL, frame_len,
|
||||||
|
NRF24L01P_NG_UPPER_LAYER_PROTOCOL);
|
||||||
|
if (!frame) {
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] _pkt_recv: unable to allocate space");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy the payload into the packet buffer */
|
||||||
|
frame_len = netif->dev->driver->recv(netif->dev, frame->data,
|
||||||
|
frame_len, NULL);
|
||||||
|
if (frame_len <= 0) {
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] _pkt_recv: driver error");
|
||||||
|
gnrc_pktbuf_release(frame);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Receives a @ref net_gnrc_pkt "packet" from the network interface
|
||||||
|
*
|
||||||
|
* @pre `netif != NULL`
|
||||||
|
*
|
||||||
|
* @note The function takes the bytes received via netdev_driver_t::recv()
|
||||||
|
* from gnrc_netif_t::dev and re-formats it to a
|
||||||
|
* @ref net_gnrc_pkt "packet" containing a @ref net_gnrc_netif_hdr
|
||||||
|
* and a payload header in receive order.
|
||||||
|
*
|
||||||
|
* @param[in] netif The network interface.
|
||||||
|
*
|
||||||
|
* @return The packet received. Contains the payload (with the type marked
|
||||||
|
* accordingly) and a @ref net_gnrc_netif_hdr in receive order.
|
||||||
|
* @return NULL, if @ref net_gnrc_pktbuf was full.
|
||||||
|
*/
|
||||||
|
static gnrc_pktsnip_t *_nrf24l01p_ng_adpt_recv(gnrc_netif_t *netif)
|
||||||
|
{
|
||||||
|
assert(netif);
|
||||||
|
assert(netif->dev);
|
||||||
|
|
||||||
|
gnrc_pktsnip_t *frame;
|
||||||
|
gnrc_pktsnip_t *snip;
|
||||||
|
gnrc_netif_hdr_t *netif_hdr;
|
||||||
|
uint8_t dst_addr[NRF24L01P_NG_ADDR_WIDTH];
|
||||||
|
uint8_t src_addr[NRF24L01P_NG_ADDR_WIDTH];
|
||||||
|
uint8_t src_addr_len;
|
||||||
|
|
||||||
|
if (!(frame = _nrf24l01p_ng_pkt_recv(netif))) {
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] _adpt_recv: no frame");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!(snip = gnrc_pktbuf_mark(frame, sizeof(dst_addr), GNRC_NETTYPE_UNDEF))) {
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] _adpt_recv: unable to mark header snip");
|
||||||
|
gnrc_pktbuf_release(frame);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memcpy(dst_addr, snip->data, sizeof(dst_addr));
|
||||||
|
gnrc_pktbuf_remove_snip(frame, snip);
|
||||||
|
|
||||||
|
src_addr_len = ((uint8_t *)frame->data)[0];
|
||||||
|
if (src_addr_len < NRF24L01P_NG_MIN_ADDR_WIDTH ||
|
||||||
|
src_addr_len > NRF24L01P_NG_MAX_ADDR_WIDTH) {
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] _adpt_recv: Invalid source address length");
|
||||||
|
gnrc_pktbuf_release(frame);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!(snip = gnrc_pktbuf_mark(frame, 1 + src_addr_len, GNRC_NETTYPE_UNDEF))) {
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] _adpt_recv: unable to mark src header snip");
|
||||||
|
gnrc_pktbuf_release(frame);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memcpy(src_addr, ((uint8_t *)snip->data) + 1, src_addr_len);
|
||||||
|
gnrc_pktbuf_remove_snip(frame, snip);
|
||||||
|
|
||||||
|
if (!(snip = gnrc_netif_hdr_build(src_addr, src_addr_len,
|
||||||
|
dst_addr, sizeof(dst_addr)))) {
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] _adpt_recv: unable to allocate netif header");
|
||||||
|
gnrc_pktbuf_release(frame);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
netif_hdr = (gnrc_netif_hdr_t *)snip->data;
|
||||||
|
const uint8_t bcast_addr[] = NRF24L01P_NG_BROADCAST_ADDR;
|
||||||
|
if (!memcmp(dst_addr, bcast_addr, sizeof(dst_addr))) {
|
||||||
|
netif_hdr->flags |= GNRC_NETIF_HDR_FLAGS_BROADCAST;
|
||||||
|
}
|
||||||
|
gnrc_netif_hdr_set_netif(netif_hdr, netif);
|
||||||
|
LL_APPEND(frame, snip);
|
||||||
|
#if IS_USED(MODULE_NETSTATS_L2)
|
||||||
|
netif->stats.rx_count++;
|
||||||
|
netif->stats.rx_bytes += frame->size;
|
||||||
|
#endif
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Send a @ref net_gnrc_pkt "packet" over the network interface
|
||||||
|
*
|
||||||
|
* @pre `netif != NULL && pkt != NULL`
|
||||||
|
*
|
||||||
|
* @note The function re-formats the content of @p pkt to a format expected
|
||||||
|
* by the netdev_driver_t::send() method of gnrc_netif_t::dev and
|
||||||
|
* releases the packet before returning (so no additional release
|
||||||
|
* should be required after calling this method).
|
||||||
|
*
|
||||||
|
* @param[in] netif The network interface.
|
||||||
|
* @param[in] pkt A packet to send.
|
||||||
|
*
|
||||||
|
* @return The number of bytes actually sent on success
|
||||||
|
* @return -EBADMSG, if the @ref net_gnrc_netif_hdr in @p pkt is missing
|
||||||
|
* or is in an unexpected format.
|
||||||
|
* @return -ENOTSUP, if sending @p pkt in the given format isn't supported
|
||||||
|
* (e.g. empty payload with Ethernet).
|
||||||
|
* @return Any negative error code reported by gnrc_netif_t::dev.
|
||||||
|
*/
|
||||||
|
static int _nrf24l01p_ng_adpt_send(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt)
|
||||||
|
{
|
||||||
|
assert(netif);
|
||||||
|
assert(pkt);
|
||||||
|
assert(netif->dev);
|
||||||
|
|
||||||
|
netdev_t *netdev = (netdev_t *)netif->dev;
|
||||||
|
gnrc_netif_hdr_t *netif_hdr = (gnrc_netif_hdr_t *)pkt->data;
|
||||||
|
if (!netif_hdr) {
|
||||||
|
return -EBADMSG;
|
||||||
|
}
|
||||||
|
const uint8_t bcast_addr[] = NRF24L01P_NG_BROADCAST_ADDR;
|
||||||
|
const uint8_t *dst_addr = gnrc_netif_hdr_get_dst_addr(netif_hdr);
|
||||||
|
uint8_t dst_addr_len = netif_hdr->dst_l2addr_len;
|
||||||
|
|
||||||
|
if (netif_hdr->flags & BCAST) {
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] _adpt_send: preparing to send broadcast");
|
||||||
|
dst_addr = bcast_addr;
|
||||||
|
dst_addr_len = NRF24L01P_NG_ADDR_WIDTH;
|
||||||
|
#if IS_USED(MODULE_NETSTATS_L2)
|
||||||
|
netif->stats.tx_mcast_count++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!dst_addr ||
|
||||||
|
dst_addr_len > NRF24L01P_NG_MAX_ADDR_WIDTH ||
|
||||||
|
dst_addr_len < NRF24L01P_NG_MIN_ADDR_WIDTH) {
|
||||||
|
return -EBADMSG;
|
||||||
|
}
|
||||||
|
if (!memcmp(dst_addr, bcast_addr, dst_addr_len)) {
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] _adpt_send: preparing to send broadcast");
|
||||||
|
#if IS_USED(MODULE_NETSTATS_L2)
|
||||||
|
netif->stats.tx_mcast_count++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t src[1 + NRF24L01P_NG_ADDR_WIDTH];
|
||||||
|
src[0] = NRF24L01P_NG_ADDR_WIDTH;
|
||||||
|
memcpy(src + 1,
|
||||||
|
NRF24L01P_NG_ADDR_P1((nrf24l01p_ng_t *)netdev),
|
||||||
|
NRF24L01P_NG_ADDR_WIDTH);
|
||||||
|
iolist_t iolist_src_addr = {
|
||||||
|
.iol_next = ((iolist_t *)pkt->next),
|
||||||
|
.iol_base = src,
|
||||||
|
.iol_len = sizeof(src)
|
||||||
|
};
|
||||||
|
iolist_t iolist = {
|
||||||
|
.iol_next = &iolist_src_addr,
|
||||||
|
.iol_base = (uint8_t *)dst_addr,
|
||||||
|
.iol_len = dst_addr_len
|
||||||
|
};
|
||||||
|
int res;
|
||||||
|
while ((res = netdev->driver->send(netdev, &iolist)) < 0) {
|
||||||
|
if (res == -EAGAIN) {
|
||||||
|
/* pending interrupts? */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (res == -EBUSY) {
|
||||||
|
if (!IS_ACTIVE(MODULE_GNRC_NETIF_PKTQ)) {
|
||||||
|
/* busy send */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
gnrc_pktbuf_release(pkt);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const gnrc_netif_ops_t nrf24l01p_ng_netif_ops = {
|
||||||
|
.init = gnrc_netif_default_init,
|
||||||
|
.send = _nrf24l01p_ng_adpt_send,
|
||||||
|
.recv = _nrf24l01p_ng_adpt_recv,
|
||||||
|
.get = gnrc_netif_get_from_netdev,
|
||||||
|
.set = gnrc_netif_set_from_netdev,
|
||||||
|
};
|
||||||
|
|
||||||
|
int gnrc_netif_nrf24l01p_ng_create(gnrc_netif_t *netif, char *stack,
|
||||||
|
int stacksize, char priority, char *name,
|
||||||
|
netdev_t *dev)
|
||||||
|
{
|
||||||
|
return gnrc_netif_create(netif, stack, stacksize, priority, name,
|
||||||
|
dev, &nrf24l01p_ng_netif_ops);
|
||||||
|
}
|
||||||
63
drivers/nrf24l01p_ng/include/gnrc_netif_nrf24l01p_ng.h
Normal file
63
drivers/nrf24l01p_ng/include/gnrc_netif_nrf24l01p_ng.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Otto-von-Guericke-Universität Magdeburg
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @ingroup drivers_nrf24l01p_ng
|
||||||
|
* @ingroup drivers_netdev
|
||||||
|
* @ingroup net_gnrc_netif
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief NRF24L01+ (NG) adaptation for @ref net_gnrc_netif
|
||||||
|
*
|
||||||
|
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
|
||||||
|
*/
|
||||||
|
#ifndef GNRC_NETIF_NRF24L01P_NG_H
|
||||||
|
#define GNRC_NETIF_NRF24L01P_NG_H
|
||||||
|
|
||||||
|
#include "net/gnrc/netif.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NRF24L01P_NG_UPPER_LAYER_PROTOCOL
|
||||||
|
#if IS_USED(MODULE_GNRC_SIXLOWPAN)
|
||||||
|
#define NRF24L01P_NG_UPPER_LAYER_PROTOCOL (GNRC_NETTYPE_SIXLOWPAN)
|
||||||
|
#else
|
||||||
|
/**
|
||||||
|
* @brief type of layer 2 payload
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_UPPER_LAYER_PROTOCOL (GNRC_NETTYPE_UNDEF)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates an NRF24L01+ (NG) network interface
|
||||||
|
*
|
||||||
|
* @param[out] netif The interface. May not be `NULL`.
|
||||||
|
* @param[in] stack The stack for the network interface's thread
|
||||||
|
* @param[in] stacksize Size of @p stack
|
||||||
|
* @param[in] priority Priority for the network interface's thread
|
||||||
|
* @param[in] name Name for the network interface. May be NULL
|
||||||
|
* @param[in] dev Device for the interface
|
||||||
|
*
|
||||||
|
* @see @ref gnrc_netif_create()
|
||||||
|
*
|
||||||
|
* @return 0 on success
|
||||||
|
* @return negative number on error
|
||||||
|
*/
|
||||||
|
int gnrc_netif_nrf24l01p_ng_create(gnrc_netif_t *netif, char *stack,
|
||||||
|
int stacksize, char priority, char *name,
|
||||||
|
netdev_t *dev);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* GNRC_NETIF_NRF24L01P_NG_H */
|
||||||
|
/** @} */
|
||||||
253
drivers/nrf24l01p_ng/include/nrf24l01p_ng_communication.h
Normal file
253
drivers/nrf24l01p_ng/include/nrf24l01p_ng_communication.h
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Otto-von-Guericke-Universität Magdeburg
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @ingroup drivers_nrf24l01p_ng
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Functions to communicate with the NRF24L01+ (NG) transceiver
|
||||||
|
* via SPI
|
||||||
|
*
|
||||||
|
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
|
||||||
|
*/
|
||||||
|
#ifndef NRF24L01P_NG_COMMUNICATION_H
|
||||||
|
#define NRF24L01P_NG_COMMUNICATION_H
|
||||||
|
|
||||||
|
#include "nrf24l01p_ng.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Mask for 5 bit register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_ADDR_MASK (0x1F)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Mask for 3 bit pipe number
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_PIPE_MASK (0x07)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read register value
|
||||||
|
* (1 to 5 bytes)
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_CMD_R_REGISTER(reg) \
|
||||||
|
(0x00 | ((reg) & NRF24L01P_NG_ADDR_MASK))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write register value
|
||||||
|
* (1 to 5 bytes)
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_CMD_W_REGISTER(reg) \
|
||||||
|
(0x20 | ((reg) & NRF24L01P_NG_ADDR_MASK))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read RX payload buffer
|
||||||
|
* (1 to 32 bytes)
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_CMD_R_RX_PAYLOAD (0x61)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write TX payload buffer
|
||||||
|
* (1 to 32 bytes)
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_CMD_W_TX_PAYLOAD (0xA0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flush TX buffer
|
||||||
|
* (0 bytes data)
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_CMD_FLUSH_TX (0xE1)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flush RX buffer
|
||||||
|
* (0 bytes data)
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_CMD_FLUSH_RX (0xE2)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reuse last transmitted payload
|
||||||
|
* (0 bytes data)
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_CMD_REUSE_TX_PL (0xE3)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read RX payload width for the top R_RX_PAYLOAD in RX FIFO
|
||||||
|
* (1 byte data)
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_CMD_R_RX_PL_WID (0x60)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write payload to be transmitted together with ACK for certain pipe
|
||||||
|
* (1 to 32 bytes data)
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_CMD_W_ACK_PAYLOAD(pipe) \
|
||||||
|
(0xA8 | ((pipe) & NRF24L01P_NG_PIPE_MASK))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disable auto ACK on this specific frame
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_CMD_W_TX_PAYLOAD_NO_ACK (0xB0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief No operation
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_CMD_NOP (0xFF)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Acquire the SPI bus of the transceiver
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
*
|
||||||
|
* @return @see spi_acquire
|
||||||
|
*/
|
||||||
|
int nrf24l01p_ng_acquire(nrf24l01p_ng_t *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Release the SPI bus of the transceiver
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
*
|
||||||
|
* @return @see spi_release
|
||||||
|
*/
|
||||||
|
void nrf24l01p_ng_release(nrf24l01p_ng_t *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read a register value
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[in] reg Register address
|
||||||
|
* @param[out] dest Output register
|
||||||
|
* @param[in] len Output register width
|
||||||
|
*
|
||||||
|
* @return Status register value
|
||||||
|
*/
|
||||||
|
uint8_t nrf24l01p_ng_read_reg(const nrf24l01p_ng_t *dev, uint8_t reg,
|
||||||
|
uint8_t *dest, size_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write a register value
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[in] reg Register address
|
||||||
|
* @param[in] src Data to be written into the register
|
||||||
|
* @param[in] len Register width
|
||||||
|
*
|
||||||
|
* @return Status register value
|
||||||
|
*/
|
||||||
|
uint8_t nrf24l01p_ng_write_reg(const nrf24l01p_ng_t *dev, uint8_t reg,
|
||||||
|
const uint8_t *src, size_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read received payload
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[out] dest Output payload buffer
|
||||||
|
* @param[in] len Output payload length
|
||||||
|
*
|
||||||
|
* @return Status register value
|
||||||
|
*/
|
||||||
|
uint8_t nrf24l01p_ng_read_rx_payload(const nrf24l01p_ng_t *dev, void *dest,
|
||||||
|
size_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write payload to be transmitted
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[in] src Input payload buffer
|
||||||
|
* @param[in] len Input payload length
|
||||||
|
*
|
||||||
|
* @return Status register value
|
||||||
|
*/
|
||||||
|
uint8_t nrf24l01p_ng_write_tx_payload(const nrf24l01p_ng_t *dev,
|
||||||
|
const void *src, size_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flush TX FIFO
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
*
|
||||||
|
* @return Status register value
|
||||||
|
*/
|
||||||
|
uint8_t nrf24l01p_ng_flush_tx(const nrf24l01p_ng_t *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flush RX FIFO
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
*
|
||||||
|
* @return Status register value
|
||||||
|
*/
|
||||||
|
uint8_t nrf24l01p_ng_flush_rx(const nrf24l01p_ng_t *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reuse TX payload in FIFO
|
||||||
|
*
|
||||||
|
* This function can be used to reattempt to transmit a frame, after a MAX_RT
|
||||||
|
* interrupt was triggered.
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
*
|
||||||
|
* @return Status register value
|
||||||
|
*/
|
||||||
|
uint8_t nrf24l01p_ng_reuse_tx_pl(const nrf24l01p_ng_t *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read received payload width
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[out] dest Payload width
|
||||||
|
*
|
||||||
|
* @return Status register value
|
||||||
|
*/
|
||||||
|
uint8_t nrf24l01p_ng_read_rx_pl_width(const nrf24l01p_ng_t *dev,
|
||||||
|
uint8_t *dest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write Payload to be transmitted in an ACK frame
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[in] src Input payload buffer
|
||||||
|
* @param[in] len Input payload length
|
||||||
|
* @param[in] pipe Index of data pipe
|
||||||
|
*
|
||||||
|
* @return Status register value
|
||||||
|
*/
|
||||||
|
uint8_t nrf24l01p_ng_write_ack_pl(const nrf24l01p_ng_t *dev, const void *src,
|
||||||
|
size_t len, uint8_t pipe);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write payload to be transmitted but do not expect an ACK for
|
||||||
|
* this frame
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[in] src Input payload buffer
|
||||||
|
* @param[in] len Input payload length
|
||||||
|
*
|
||||||
|
* @return Status register value
|
||||||
|
*/
|
||||||
|
uint8_t nrf24l01p_ng_write_tx_pl_no_ack(const nrf24l01p_ng_t *dev,
|
||||||
|
const void *src, size_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get status register value
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
*
|
||||||
|
* @return Status register value
|
||||||
|
*/
|
||||||
|
uint8_t nrf24l01p_ng_get_status(const nrf24l01p_ng_t *dev);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* NRF24L01P_NG_COMMUNICATION_H */
|
||||||
|
/** @} */
|
||||||
105
drivers/nrf24l01p_ng/include/nrf24l01p_ng_constants.h
Normal file
105
drivers/nrf24l01p_ng/include/nrf24l01p_ng_constants.h
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Otto-von-Guericke-Universität Magdeburg
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @ingroup drivers_nrf24l01p_ng
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Constants from the datasheet of the NRF24L01+ (NG) transceiver
|
||||||
|
*
|
||||||
|
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
|
||||||
|
*/
|
||||||
|
#ifndef NRF24L01P_NG_CONSTANTS_H
|
||||||
|
#define NRF24L01P_NG_CONSTANTS_H
|
||||||
|
|
||||||
|
#include "nrf24l01p_ng.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum width of a payload, restricted by
|
||||||
|
* a FIFO size of 32 bytes
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_MAX_PAYLOAD_WIDTH (32)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum number of retransmissions, if
|
||||||
|
* ESB is used as protocol
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_MAX_RETRANSMISSIONS (15)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Base frequency
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_BASE_FRQ_MHZ (2400)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum supported frequency
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_MAX_FRQ_MHZ (2525)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of supported channels
|
||||||
|
*
|
||||||
|
* frequency range: 2400 - 2525 Mhz
|
||||||
|
* occupied bandwidth for each channel:
|
||||||
|
* 250 kbps: < 1Mhz
|
||||||
|
* 1000 kbps: < 1Mhz
|
||||||
|
* 2000 kbps: < 2Mhz
|
||||||
|
*
|
||||||
|
* -> spaces between each channel´s
|
||||||
|
* base frequency must be at least
|
||||||
|
* 2 Mhz, to be sufficient for all
|
||||||
|
* data rates.
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_NUM_CHANNELS (NRF24L01P_NG_MAX_FRQ_MHZ - \
|
||||||
|
NRF24L01P_NG_BASE_FRQ_MHZ)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reset value of TX_ADDR register
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_DEFAULT_TX_ADDR { 0xE7, 0xE7, 0xE7, 0xE7, 0xE7 }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reset value of RX_ADDR_P0 register
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_DEFAULT_ADDR_P0 { 0xE7, 0xE7, 0xE7, 0xE7, 0xE7 }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reset value of RX_ADDR_P1 register
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_DEFAULT_ADDR_P1 { 0xC2, 0xC2, 0xC2, 0xC2, 0xC2 }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reset value of RX_ADDR_P2 register
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_DEFAULT_ADDR_P2 (0xC3)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reset value of RX_ADDR_P3 register
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_DEFAULT_ADDR_P3 (0xC4)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reset value of RX_ADDR_P4 register
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_DEFAULT_ADDR_P4 (0xC5)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reset value of RX_ADDR_P5 register
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_DEFAULT_ADDR_P5 (0xC6)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* NRF24L01P_NG_CONSTANTS_H */
|
||||||
|
/** @} */
|
||||||
55
drivers/nrf24l01p_ng/include/nrf24l01p_ng_diagnostics.h
Normal file
55
drivers/nrf24l01p_ng/include/nrf24l01p_ng_diagnostics.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Otto-von-Guericke-Universität Magdeburg
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @ingroup drivers_nrf24l01p_ng
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Functions to print NRF24L01+ (NG) debug information
|
||||||
|
*
|
||||||
|
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
|
||||||
|
*/
|
||||||
|
#ifndef NRF24L01P_NG_DIAGNOSTICS_H
|
||||||
|
#define NRF24L01P_NG_DIAGNOSTICS_H
|
||||||
|
|
||||||
|
#include "nrf24l01p_ng.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Print all NRF24L01+ register values
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
*/
|
||||||
|
void nrf24l01p_ng_diagnostics_print_all_regs(const nrf24l01p_ng_t *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Print NRF24L01+ device handle information
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
*/
|
||||||
|
void nrf24l01p_ng_diagnostics_print_dev_info(const nrf24l01p_ng_t *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Print NRF24L01+ frame
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[in] frame Frame
|
||||||
|
* @param[in] len Frame length
|
||||||
|
*/
|
||||||
|
void nrf24l01p_ng_diagnostics_print_frame(const nrf24l01p_ng_t *dev,
|
||||||
|
const void *frame, size_t len);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* NRF24L01P_NG_DIAGNOSTICS_H */
|
||||||
|
/** @} */
|
||||||
36
drivers/nrf24l01p_ng/include/nrf24l01p_ng_netdev.h
Normal file
36
drivers/nrf24l01p_ng/include/nrf24l01p_ng_netdev.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Otto-von-Guericke-Universität Magdeburg
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @ingroup drivers_nrf24l01p_ng
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Netdev driver interface for NRF24L01+ (NG) device driver
|
||||||
|
*
|
||||||
|
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
|
||||||
|
*/
|
||||||
|
#ifndef NRF24L01P_NG_NETDEV_H
|
||||||
|
#define NRF24L01P_NG_NETDEV_H
|
||||||
|
|
||||||
|
#include "net/netdev.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Struct that holds functions of NRF24L01+ device driver
|
||||||
|
*/
|
||||||
|
extern const netdev_driver_t nrf24l01p_ng_driver;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* NRF24L01P_NG_NETDEV_H */
|
||||||
|
/** @} */
|
||||||
150
drivers/nrf24l01p_ng/include/nrf24l01p_ng_params.h
Normal file
150
drivers/nrf24l01p_ng/include/nrf24l01p_ng_params.h
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Otto-von-Guericke-Universität Magdeburg
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @ingroup drivers_nrf24l01p_ng
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Board specific configuration for all NRF24L01+ (NG) devices
|
||||||
|
*
|
||||||
|
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
|
||||||
|
*/
|
||||||
|
#ifndef NRF24L01P_NG_PARAMS_H
|
||||||
|
#define NRF24L01P_NG_PARAMS_H
|
||||||
|
|
||||||
|
#include "board.h"
|
||||||
|
#include "periph/gpio.h"
|
||||||
|
#include "periph/spi.h"
|
||||||
|
#include "kernel_defines.h"
|
||||||
|
#include "nrf24l01p_ng_constants.h"
|
||||||
|
#include "nrf24l01p_ng.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NRF24L01P_NG_PARAM_SPI
|
||||||
|
/**
|
||||||
|
* @brief SPI bus
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_PARAM_SPI SPI_DEV(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NRF24L01P_NG_PARAM_SPI_CLK
|
||||||
|
/**
|
||||||
|
* @brief SPI clock speed
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_PARAM_SPI_CLK SPI_CLK_5MHZ
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NRF24L01P_NG_PARAM_CS
|
||||||
|
/**
|
||||||
|
* @brief SPI CS gpio pin
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_PARAM_CS GPIO_UNDEF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NRF24L01P_NG_PARAM_CE
|
||||||
|
/**
|
||||||
|
* @brief NRF24L01+ chip enable gpio pin
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_PARAM_CE GPIO_UNDEF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NRF24L01P_NG_PARAM_IRQ
|
||||||
|
/**
|
||||||
|
* @brief NRF24L01+ interrupt gpio pin
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_PARAM_IRQ GPIO_UNDEF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NRF24L01P_NG_PARAM_CRC_LEN
|
||||||
|
/**
|
||||||
|
* @brief Default CRC length
|
||||||
|
* @see nrf24l01p_ng_crc_t
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_PARAM_CRC_LEN (NRF24L01P_NG_CRC_2BYTE)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NRF24L01P_NG_PARAM_TX_POWER
|
||||||
|
/**
|
||||||
|
* @brief Default TX power
|
||||||
|
* @see nrf24l01p_ng_tx_power_t
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_PARAM_TX_POWER (NRF24L01P_NG_TX_POWER_0DBM)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NRF24L01P_NG_PARAM_DATA_RATE_LVL
|
||||||
|
/**
|
||||||
|
* @brief Default data rate
|
||||||
|
* @see nrf24l01p_ng_rfdr_t
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_PARAM_DATA_RATE (NRF24L01P_NG_RF_DR_2MBPS)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NRF24L01P_NG_PARAM_CHANNEL
|
||||||
|
/**
|
||||||
|
* @brief Default channel in [0; 124]
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_PARAM_CHANNEL (4)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NRF24L01P_NG_PARAM_MAX_RETRANSM
|
||||||
|
/**
|
||||||
|
* @brief Default number of retransmissions
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_PARAM_MAX_RETRANSM (5)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NRF24L01P_NG_PARAM_RETRANSM_DELAY
|
||||||
|
/**
|
||||||
|
* @brief Default retransmission delay
|
||||||
|
* @see nrf24l01p_ng_ard_t
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_PARAM_RETRANSM_DELAY (NRF24L01P_NG_ARD_2750US)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NRF24L01P_NG_PARAMS
|
||||||
|
/**
|
||||||
|
* @brief Default NRF24L01+ device parameters
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_PARAMS { \
|
||||||
|
.spi = NRF24L01P_NG_PARAM_SPI, \
|
||||||
|
.spi_clk = NRF24L01P_NG_PARAM_SPI_CLK, \
|
||||||
|
.pin_cs = NRF24L01P_NG_PARAM_CS, \
|
||||||
|
.pin_ce = NRF24L01P_NG_PARAM_CE, \
|
||||||
|
.pin_irq = NRF24L01P_NG_PARAM_IRQ, \
|
||||||
|
.config = { \
|
||||||
|
.cfg_crc = NRF24L01P_NG_PARAM_CRC_LEN, \
|
||||||
|
.cfg_tx_power = NRF24L01P_NG_PARAM_TX_POWER, \
|
||||||
|
.cfg_data_rate = NRF24L01P_NG_PARAM_DATA_RATE, \
|
||||||
|
.cfg_channel = NRF24L01P_NG_PARAM_CHANNEL, \
|
||||||
|
.cfg_max_retr = NRF24L01P_NG_PARAM_MAX_RETRANSM, \
|
||||||
|
.cfg_retr_delay = NRF24L01P_NG_PARAM_RETRANSM_DELAY, \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Static array that holds NRF24L01+ device configurations
|
||||||
|
*/
|
||||||
|
static const nrf24l01p_ng_params_t nrf24l01p_ng_params[] = {
|
||||||
|
NRF24L01P_NG_PARAMS
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of NRF24L01+ device configurations
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_NUM ARRAY_SIZE(nrf24l01p_ng_params)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* NRF24L01P_NG_PARAMS_H */
|
||||||
|
/** @} */
|
||||||
972
drivers/nrf24l01p_ng/include/nrf24l01p_ng_registers.h
Normal file
972
drivers/nrf24l01p_ng/include/nrf24l01p_ng_registers.h
Normal file
@ -0,0 +1,972 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Otto-von-Guericke-Universität Magdeburg
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @ingroup drivers_nrf24l01p_ng
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Register map of NRF24L01+ (NG) devices
|
||||||
|
*
|
||||||
|
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
|
||||||
|
*/
|
||||||
|
#ifndef NRF24L01P_NG_REGISTERS_H
|
||||||
|
#define NRF24L01P_NG_REGISTERS_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "nrf24l01p_ng.h"
|
||||||
|
#include "nrf24l01p_ng_communication.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name NRF24L01+ CONFIG register
|
||||||
|
*
|
||||||
|
* Address and layout of NRF24L01+ configuration register
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @brief CONFIG register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_CONFIG (0x00)
|
||||||
|
/**
|
||||||
|
* @brief Flag: MASK_RX_DR
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_MASK_RX_DR (0x40)
|
||||||
|
/**
|
||||||
|
*@brief Value of: MASK_RX_DR
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_MASK_RX_DR(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_MASK_RX_DR) >> 6)
|
||||||
|
/**
|
||||||
|
* @brief Flag: MASK_TX_DS
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_MASK_TX_DS (0x20)
|
||||||
|
/**
|
||||||
|
* @brief Value of: MASK_TX_DS
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_MASK_TX_DS(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_MASK_TX_DS) >> 5)
|
||||||
|
/**
|
||||||
|
* @brief Flag: MASK_MAX_RT
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_MASK_MAX_RT (0x10)
|
||||||
|
/**
|
||||||
|
* @brief Value of: MASK_MAX_RT
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_MASK_MAX_RT (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_MASK_MAX_RT) >> 4)
|
||||||
|
/**
|
||||||
|
* @brief Flag: EN_CRC
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_EN_CRC (0x08)
|
||||||
|
/**
|
||||||
|
* @brief Value of: EN_CRC
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_EN_CRC(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_EN_CRC) >> 3)
|
||||||
|
/**
|
||||||
|
* @brief Flag: CRCO - 1 byte
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_CRCO_1_BYTE (0x00)
|
||||||
|
/**
|
||||||
|
* @brief Flag: CRCO - 2 byte
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_CRCO_2_BYTE (0x04)
|
||||||
|
/**
|
||||||
|
* @brief Mask to configure CRC
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_MSK_CRC (0x0c)
|
||||||
|
/**
|
||||||
|
* @brief Flag: CRCO
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_CRCO(val) (((val) << 2) & \
|
||||||
|
NRF24L01P_NG_MSK_CRC)
|
||||||
|
/**
|
||||||
|
* @brief Value of: CRCO
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_CRCO(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_CRCO_2_BYTE) >> 2)
|
||||||
|
/**
|
||||||
|
* @brief Flag: PWR_UP
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_PWR_UP (0x02)
|
||||||
|
/**
|
||||||
|
* @brief Value of: PWR_UP
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_PWR_UP(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_PWR_UP) >> 1)
|
||||||
|
/**
|
||||||
|
* @brief Flag: PRIM_RX
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_PRIM_RX (0x01)
|
||||||
|
/**
|
||||||
|
* @brief Value of: PRIM_RX
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_PRIM_RX(reg) ((reg) & NRF24L01P_NG_FLG_PRIM_RX)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name NRF24L01+ EN_AA register
|
||||||
|
*
|
||||||
|
* Address and layout of NRF24L01+ EN_AA register
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @brief EN_AA register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_EN_AA (0x01)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ENAA_P5
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ENAA_P5 (0x20)
|
||||||
|
/**
|
||||||
|
* @brief Value of: ENAA_P5
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_ENAA_P5(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_ENAA_P5) >> 5)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ENAA_P4
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ENAA_P4 (0x10)
|
||||||
|
/**
|
||||||
|
* @brief Value of: ENAA_P4
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_ENAA_P4(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_ENAA_P4) >> 4)
|
||||||
|
/**
|
||||||
|
* @brief Flaga: ENAA_P3
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ENAA_P3 (0x08)
|
||||||
|
/**
|
||||||
|
* @brief Value of: ENAA_P3
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_ENAA_P3(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_ENAA_P3) >> 3)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ENAA_P2
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ENAA_P2 (0x04)
|
||||||
|
/**
|
||||||
|
* @brief Value of: ENAA_P2
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_ENAA_P2(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_ENAA_P2) >> 2)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ENAA_P1
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ENAA_P1 (0x02)
|
||||||
|
/**
|
||||||
|
* @brief Value of: ENAA_P1
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_ENAA_P1(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_ENAA_P1) >> 1)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ENAA_P0
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ENAA_P0 (0x01)
|
||||||
|
/**
|
||||||
|
* @brief Value of: ENAA_P0
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_ENAA_P0(reg) ((reg) & NRF24L01P_NG_FLG_ENAA_P0)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name NRF24L01+ EN_RXADDR register
|
||||||
|
*
|
||||||
|
* Address and layout of NRF24L01+ EN_RXADDR register
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @brief EN_RXADDR register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_EN_RXADDR (0x02)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ERX_P5
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ERX_P5 (0x20)
|
||||||
|
/**
|
||||||
|
* @brief Value of: ERX_P5
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_ERX_P5(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_ERX_P5) >> 5)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ERX_P4
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ERX_P4 (0x10)
|
||||||
|
/**
|
||||||
|
* @brief Value of ERX_P4
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_ERX_P4(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_ERX_P4) >> 4)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ERX_P3
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ERX_P3 (0x08)
|
||||||
|
/**
|
||||||
|
* @brief Value of: ERX_P3
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_ERX_P3(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_ERX_P3) >> 3)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ERX_P2
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ERX_P2 (0x04)
|
||||||
|
/**
|
||||||
|
* @brief Value of: ERX_P2
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_ERX_P2(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_ERX_P2) >> 2)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ERX_P1
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ERX_P1 (0x02)
|
||||||
|
/**
|
||||||
|
* @brief Value of: ERX_P1
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_ERX_P1(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_ERX_P1) >> 1)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ERX_P0
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ERX_P0 (0x01)
|
||||||
|
/**
|
||||||
|
* @brief Value of: ERX_P0
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_ERX_P0(reg) ((reg) & NRF24L01P_NG_FLG_ERX_P0)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name NRF24L01+ SETUP_AW register
|
||||||
|
*
|
||||||
|
* Address and layout of NRF24L01+ SETUP_AW register
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @brief SETUP_AW register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_SETUP_AW (0x03)
|
||||||
|
/**
|
||||||
|
* @brief Flag: AW - 3 bytes
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_AW_3 (0x01)
|
||||||
|
/**
|
||||||
|
* @brief Flag: AW - 4 bytes
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_AW_4 (0x02)
|
||||||
|
/**
|
||||||
|
* @brief Flag: AW - 5 bytes
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_AW_5 (0x03)
|
||||||
|
/**
|
||||||
|
* @brief Mask to configure AW
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_MSK_AW (0x03)
|
||||||
|
/**
|
||||||
|
* @brief Flag AW from value [1; 3]
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_AW(val) ((val) & NRF24L01P_NG_MSK_AW)
|
||||||
|
/**
|
||||||
|
* @brief Value of: AW
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_AW(reg) ((reg) & NRF24L01P_NG_MSK_AW)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name NRF24L01+ SETUP_RETR register
|
||||||
|
*
|
||||||
|
* Address and layout of NRF24L01+ SETUP_AW register
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @brief SETUP_RETR register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_SETUP_RETR (0x04)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ARD - 250 us
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ARD_250_US (0x00)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ARD - 500 us
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ARD_500_US (0x10)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ARD - 750 us
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ARD_750_US (0x20)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ARD - 1000 us
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ARD_1000_US (0x30)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ARD - 1250 us
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ARD_1250_US (0x40)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ARD - 1500 us
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ARD_1500_US (0x50)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ARD - 1750 us
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ARD_1750_US (0x60)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ARD - 2000 us
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ARD_2000_US (0x70)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ARD - 2250 us
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ARD_2250_US (0x80)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ARD - 2500 us
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ARD_2500_US (0x90)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ARD - 2750 us
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ARD_2750_US (0xa0)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ARD - 3000 us
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ARD_3000_US (0xb0)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ARD - 3250 us
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ARD_3250_US (0xc0)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ARD - 3500 us
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ARD_3500_US (0xd0)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ARD - 3750 us
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ARD_3750_US (0xe0)
|
||||||
|
/**
|
||||||
|
* @brief Flag: ARD - 4000 us
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ARD_4000_US (0xf0)
|
||||||
|
/**
|
||||||
|
* @brief Mask to configure ARD
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_MSK_ARD (0xf0)
|
||||||
|
/**
|
||||||
|
* @brief Flag ARD from value [0; 15]
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ARD(val) (((val) << 4) & \
|
||||||
|
NRF24L01P_NG_MSK_ARD)
|
||||||
|
/**
|
||||||
|
* @brief Value of: ARD
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_ARD(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_MSK_ARD) >> 4)
|
||||||
|
/**
|
||||||
|
* @brief Mask to configure ARC
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_MSK_ARC (0x0f)
|
||||||
|
/**
|
||||||
|
* @brief Flag ARC from value [0; 15]
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ARC(val) ((val) & NRF24L01P_NG_MSK_ARC)
|
||||||
|
/**
|
||||||
|
* @brief Value of: ARC
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_ARC(reg) ((reg) & NRF24L01P_NG_MSK_ARC)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name NRF24L01+ RF_CH register
|
||||||
|
*
|
||||||
|
* Address and layout of NRF24L01+ SETUP_AW register
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @brief RF_CH register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_RF_CH (0x05)
|
||||||
|
/**
|
||||||
|
* @brief Mask to configure RF_CH
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_MSK_RF_CH (0x7f)
|
||||||
|
/**
|
||||||
|
* @brief Flag RF_CH from value [0; 124]
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_RF_CH(val) ((val) & NRF24L01P_NG_MSK_RF_CH)
|
||||||
|
/**
|
||||||
|
* @brief Value of: RF_CH
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_RF_CH(reg) ((reg) & NRF24L01P_NG_MSK_RF_CH)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name NRF24L01+ RF_SETUP register
|
||||||
|
*
|
||||||
|
* Address and layout of NRF24L01+ RF_SETUP register
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @brief RF_SETUP register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_RF_SETUP (0x06)
|
||||||
|
/**
|
||||||
|
* @brief Flag: CONT_WAVE
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_CONT_WAVE (0x80)
|
||||||
|
/**
|
||||||
|
* @brief Value of: CONT_WAVE
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_CONT_WAVE(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_CONT_WAVE) >> 7)
|
||||||
|
/**
|
||||||
|
* @brief Flag: RF_DR_LOW
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_RF_DR_LOW (0x20)
|
||||||
|
/**
|
||||||
|
* @brief Value of: RF_DR_LOW
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_RF_DR_LOW(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_RF_DR_LOW) >> 5)
|
||||||
|
/**
|
||||||
|
* @brief Flag: PLL_LOCK
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_PLL_LOCK (0x10)
|
||||||
|
/**
|
||||||
|
* @brief Value of: PLL_LOCK
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_PLL_LOCK(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_PLL_LOCK) >> 4)
|
||||||
|
/**
|
||||||
|
* @brief Flag: RF_DR_HIGH
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_RF_DR_HIGH (0x08)
|
||||||
|
/**
|
||||||
|
* @brief Value of: RF_DR_HIGH
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_RF_DR_HIGH(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_RF_DR_HIGH) >> 3)
|
||||||
|
/**
|
||||||
|
* @brief Flag: RF_DR - 250 kbit/s
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_RF_DR_250_KBPS (0x08)
|
||||||
|
/**
|
||||||
|
* @brief Flag: RF_DR - 1000 kbit/s
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_RF_DR_1_MBPS (0x00)
|
||||||
|
/**
|
||||||
|
* @brief Flag: RF_DR - 2000 kbit/s
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_RF_DR_2_MBPS (0x20)
|
||||||
|
/**
|
||||||
|
* @brief Mask to configure RF_DR
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_MSK_RF_DR (0x28)
|
||||||
|
/**
|
||||||
|
* @brief FLG RF_DR
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_RF_DR(val) ((((val) & 1) << 5) | \
|
||||||
|
(((val) & 2) << 2))
|
||||||
|
/**
|
||||||
|
* @brief Value of: RF_DR
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_RF_DR(reg) ((((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_RF_DR_LOW) >> 5) \
|
||||||
|
| \
|
||||||
|
(((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_RF_DR_HIGH) >> 2))
|
||||||
|
/**
|
||||||
|
* @brief Flag: RF_PWR - -18 dbm
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_RF_PWR_MINUS_18 (0x00)
|
||||||
|
/**
|
||||||
|
* @brief Flag: RF_PWR - -12 dbm
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_RF_PWR_MINUS_12 (0x02)
|
||||||
|
/**
|
||||||
|
* @brief Flag: RF_PWR - -6 dbm
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_RF_PWR_MINUS_6 (0x04)
|
||||||
|
/**
|
||||||
|
* @brief Flag: RF_PWR - 0 dbm
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_RF_PWR_0 (0x06)
|
||||||
|
/**
|
||||||
|
* @brief Mask to configure RF_PWR
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_MSK_RF_PWR (0x06)
|
||||||
|
/**
|
||||||
|
* @brief Flag RF_PWR from value [0; 3]
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_RF_PWR(val) (((val) << 1) & \
|
||||||
|
NRF24L01P_NG_MSK_RF_PWR)
|
||||||
|
/**
|
||||||
|
* @brief Value of: RF_PWR
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_RF_PWR(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_MSK_RF_PWR) >> 1)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name NRF24L01+ STATUS register
|
||||||
|
*
|
||||||
|
* Address and layout of NRF24L01+ STATUS register
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @brief STATUS register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_STATUS (0x07)
|
||||||
|
/**
|
||||||
|
* @brief Flag: RX_DR
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_RX_DR (0x40)
|
||||||
|
/**
|
||||||
|
* @brief Value of: RX_DR
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_RX_DR(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_RX_DR) >> 6)
|
||||||
|
/**
|
||||||
|
* @brief Flag: TX_DS
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_TX_DS (0x20)
|
||||||
|
/**
|
||||||
|
* @brief Value of: TX_DS
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_TX_DS(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_TX_DS) >> 5)
|
||||||
|
/**
|
||||||
|
* @brief Flag: MAX_RT
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_MAX_RT (0x10)
|
||||||
|
/**
|
||||||
|
* @brief Value of: MAX_RT
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_MAX_RT(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_MAX_RT) >> 4)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flag: RX_P_NO - Rx FIFO empty
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_RX_P_NO_NONE (0x0e)
|
||||||
|
/**
|
||||||
|
* @brief Mask to read RX_P_NO
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_MSK_RX_P_NO (0x0e)
|
||||||
|
/**
|
||||||
|
* @brief Flag RX_P_NO from value [0; 7]
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_RX_P_NO(val) (((val) << 1) & \
|
||||||
|
NRF24L01P_NG_MSK_RX_P_NO)
|
||||||
|
/**
|
||||||
|
* @brief Value of: RX_P_NO
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_RX_P_NO(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_MSK_RX_P_NO) >> 1)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flag: TX_FULL
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_TX_FULL (0x01)
|
||||||
|
/**
|
||||||
|
* @brief Value of: TX_FULL
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_TX_FULL(reg) ((reg) & NRF24L01P_NG_FLG_TX_FULL)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name NRF24L01+ OBSERVE_TX register
|
||||||
|
*
|
||||||
|
* Address and layout of NRF24L01+ STATUS register
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @brief OBSERVE_TX register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_OBSERVE_TX (0x08)
|
||||||
|
/**
|
||||||
|
* @brief Mask to read PLOS_CNT
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_MSK_PLOS_CNT (0xf0)
|
||||||
|
/**
|
||||||
|
* @brief Flag PLOS_CNT from value [0; 15]
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_PLOS_CNT(val) (((val) << 4) & \
|
||||||
|
NRF24L01P_NG_MSK_PLOS_CNT)
|
||||||
|
/**
|
||||||
|
* @brief Value of: PLOS_CNT
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_PLOS_CNT(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_MSK_PLOS_CNT) >> 4)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Mask to read ARC_CNT
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_MSK_ARC_CNT (0x0f)
|
||||||
|
/**
|
||||||
|
* @brief Flag ARC_CNT from value [0; 15]
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_ARC_CNT(val) ((val) & NRF24L01P_NG_MSK_ARC_CNT)
|
||||||
|
/**
|
||||||
|
* @brief Value of: ARC_CNT
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_ARC_CNT(reg) ((reg) & NRF24L01P_NG_MSK_ARC_CNT)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name NRF24L01+ RPD register
|
||||||
|
*
|
||||||
|
* Address and layout of NRF24L01+ RPD register
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @brief RPD register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_RPD (0x09)
|
||||||
|
/**
|
||||||
|
* @brief Flag: RPD
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_RPD (0x01)
|
||||||
|
/**
|
||||||
|
* @brief Value of: RPD
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_RPD(reg) ((reg) & NRF24L01P_NG_FLG_RPD)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name NRF24L01+ RX_ADDR_Px registers
|
||||||
|
*
|
||||||
|
* Addresses of NRF24L01+ RX_ADDR_Px registers and TX_ADDR register
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @brief RX_ADDR_P0 register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_RX_ADDR_P0 (0x0A)
|
||||||
|
/**
|
||||||
|
* @brief RX_ADDR_P1 register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_RX_ADDR_P1 (0x0B)
|
||||||
|
/**
|
||||||
|
* @brief RX_ADDR_P2 register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_RX_ADDR_P2 (0x0C)
|
||||||
|
/**
|
||||||
|
* @brief RX_ADDR_P3 register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_RX_ADDR_P3 (0x0D)
|
||||||
|
/**
|
||||||
|
* @brief RX_ADDR_P4 register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_RX_ADDR_P4 (0x0E)
|
||||||
|
/**
|
||||||
|
* @brief RX_ADDR_P5 register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_RX_ADDR_P5 (0x0F)
|
||||||
|
/**
|
||||||
|
* @brief TX_ADDR register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_TX_ADDR (0x10)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name NRF24L01+ RX_PW_Px registers
|
||||||
|
*
|
||||||
|
* Address and layout of NRF24L01+ RX_PW_Px registers
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @brief RX_PW_P0 register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_RX_PW_P0 (0x11)
|
||||||
|
/**
|
||||||
|
* @brief RX_PW_P1 register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_RX_PW_P1 (0x12)
|
||||||
|
/**
|
||||||
|
* @brief RX_PW_P2 register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_RX_PW_P2 (0x13)
|
||||||
|
/**
|
||||||
|
* @brief RX_PW_P3 register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_RX_PW_P3 (0x14)
|
||||||
|
/**
|
||||||
|
* @brief RX_PW_P4 register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_RX_PW_P4 (0x15)
|
||||||
|
/**
|
||||||
|
* @brief RX_PW_P5 register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_RX_PW_P5 (0x16)
|
||||||
|
/**
|
||||||
|
* @brief Mask to configure RX_PW_PX
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_MSK_RX_PW_PX (0x1f)
|
||||||
|
/**
|
||||||
|
* @brief Flag RX_PW_Px from value [0; 32]
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_RX_PW_PX(val) ((val) & NRF24L01P_NG_MSK_RX_PW_PX)
|
||||||
|
/**
|
||||||
|
* @brief Value of: RX_PW_PX
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_RX_PW_PX(reg) ((reg) & NRF24L01P_NG_MSK_RX_PW_PX)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name NRF24L01+ FIFO_STATUS register
|
||||||
|
*
|
||||||
|
* Address and layout of NRF24L01+ FIFO_STATUS register
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @brief FIFO_STATUS register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_FIFO_STATUS (0x17)
|
||||||
|
/**
|
||||||
|
* @brief Flag: TX_REUSE
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_TX_REUSE (0x40)
|
||||||
|
/**
|
||||||
|
* @brief Value of: TX_REUSE
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_TX_REUSE(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_TX_REUSE) >> 6)
|
||||||
|
/**
|
||||||
|
* @brief Flag: TX_FULL
|
||||||
|
* (also indicated in the STATUS register)
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_TX_FULL_ (0x20)
|
||||||
|
/**
|
||||||
|
* @brief Value of: TX_FULL
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_TX_FULL_(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_TX_FULL_) >> 5)
|
||||||
|
/**
|
||||||
|
* @brief Flag: TX_EMPTY
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_TX_EMPTY (0x10)
|
||||||
|
/**
|
||||||
|
* @brief Value of: TX_EMPTY
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_TX_EMPTY(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_TX_EMPTY) >> 4)
|
||||||
|
/**
|
||||||
|
* @brief Flag: RX_FULL
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_RX_FULL (0x02)
|
||||||
|
/**
|
||||||
|
* @brief Value of: RX_FULL
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_RX_FULL(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_RX_FULL) >> 1)
|
||||||
|
/**
|
||||||
|
* @brief Flag: RX_EMPTY
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_RX_EMPTY (0x01)
|
||||||
|
/**
|
||||||
|
* @brief Value of: RX_EMPTY
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_RX_EMPTY(reg) ((reg) & NRF24L01P_NG_FLG_RX_EMPTY)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name NRF24L01+ DYNPD register
|
||||||
|
*
|
||||||
|
* Address and layout of NRF24L01+ DYNPD register
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @brief DYPD register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_DYNPD (0x1C)
|
||||||
|
/**
|
||||||
|
* @brief Flag: DPL_P5
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_DPL_P5 (0x20)
|
||||||
|
/**
|
||||||
|
* @brief Value of: DPL_P5
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_DPL_P5(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_DPL_P5) >> 5)
|
||||||
|
/**
|
||||||
|
* @brief Flag: DPL_P4
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_DPL_P4 (0x10)
|
||||||
|
/**
|
||||||
|
* @brief Value of DPL_P4
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_DPL_P4(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_DPL_P4) >> 4)
|
||||||
|
/**
|
||||||
|
* @brief Flag: DPL_P3
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_DPL_P3 (0x08)
|
||||||
|
/**
|
||||||
|
* @brief Value of DPL_P3
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_DPL_P3(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_DPL_P3) >> 3)
|
||||||
|
/**
|
||||||
|
* @brief Flag: DPL_P2
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_DPL_P2 (0x04)
|
||||||
|
/**
|
||||||
|
* @brief Value of DPL_P2
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_DPL_P2(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_DPL_P2) >> 2)
|
||||||
|
/**
|
||||||
|
* @brief Flag: DPL_P1
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_DPL_P1 (0x02)
|
||||||
|
/**
|
||||||
|
* @brief Value of: DPL_P1
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_DPL_P1(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_DPL_P1) >> 1)
|
||||||
|
/**
|
||||||
|
* @brief Flag: DPL_P0
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_DPL_P0 (0x01)
|
||||||
|
/**
|
||||||
|
* @brief Value of: DPL_P0
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_DPL_P0(reg) ((reg) & NRF24L01P_NG_FLG_DPL_P0)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name NRF24L01+ FEATURES register
|
||||||
|
*
|
||||||
|
* Address and layout of NRF24L01+ FEATURES register
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @brief FEATURES register address
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_REG_FEATURES (0x1D)
|
||||||
|
/**
|
||||||
|
* @brief Flag: EN_DPL
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_EN_DPL (0x04)
|
||||||
|
/**
|
||||||
|
* @brief Value of: EN_DPL
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_EN_DPL(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_EN_DPL) >> 2)
|
||||||
|
/**
|
||||||
|
* @brief Flag: EN_ACK_PAY
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_EN_ACK_PAY (0x02)
|
||||||
|
/**
|
||||||
|
* @brief Value of: EN_ACK_PAY
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_EN_ACK_PAY(reg) (((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_EN_ACK_PAY) >> 1)
|
||||||
|
/**
|
||||||
|
* @brief Flag: EN_DYN_ACK
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_FLG_EN_DYN_ACK (0x01)
|
||||||
|
/**
|
||||||
|
* @brief Value of: EN_DYN_ACK
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_VAL_EN_DYN_ACK(reg) ((reg) & \
|
||||||
|
NRF24L01P_NG_FLG_EN_DYN_ACK)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read the contents of an 8 bit register
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[in] reg_addr Address of the register to be written
|
||||||
|
*
|
||||||
|
* @return Register value
|
||||||
|
*/
|
||||||
|
static inline
|
||||||
|
uint8_t nrf24l01p_ng_reg8_read(const nrf24l01p_ng_t *dev, uint8_t reg_addr) {
|
||||||
|
uint8_t reg_val;
|
||||||
|
nrf24l01p_ng_read_reg(dev, reg_addr, ®_val, 1);
|
||||||
|
return reg_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write the contents of an 8 bit register
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[in] reg_addr Address of the register to be written
|
||||||
|
* @param[in] reg_val Value to be written to the register
|
||||||
|
*
|
||||||
|
* @return Status register value
|
||||||
|
*/
|
||||||
|
static inline
|
||||||
|
uint8_t nrf24l01p_ng_reg8_write(const nrf24l01p_ng_t *dev,
|
||||||
|
uint8_t reg_addr, uint8_t reg_val) {
|
||||||
|
return nrf24l01p_ng_write_reg(dev, reg_addr, ®_val, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set bits in a certain 8-bit register
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[in] reg_addr Address of the register to be modified
|
||||||
|
* @param[in, out] reg_val Register bits that are being set
|
||||||
|
*
|
||||||
|
* @return Status register value
|
||||||
|
*/
|
||||||
|
static inline
|
||||||
|
uint8_t nrf24l01p_ng_reg8_set(const nrf24l01p_ng_t *dev,
|
||||||
|
uint8_t reg_addr, uint8_t *reg_val) {
|
||||||
|
uint8_t reg_val_old;
|
||||||
|
nrf24l01p_ng_read_reg(dev, reg_addr, ®_val_old, sizeof(reg_val_old));
|
||||||
|
*reg_val = reg_val_old | *reg_val;
|
||||||
|
return nrf24l01p_ng_write_reg(dev, reg_addr, reg_val, sizeof(*reg_val));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @brief Clear bits in a certain 8-bit register
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[in] reg_addr Address of the register to be modified
|
||||||
|
* @param[in, out] reg_val Register bits that are being cleared
|
||||||
|
*
|
||||||
|
* @return Status register value
|
||||||
|
*/
|
||||||
|
static inline
|
||||||
|
uint8_t nrf24l01p_ng_reg8_clear(const nrf24l01p_ng_t *dev,
|
||||||
|
uint8_t reg_addr, uint8_t *reg_val) {
|
||||||
|
uint8_t reg_val_old;
|
||||||
|
nrf24l01p_ng_read_reg(dev, reg_addr, ®_val_old, sizeof(reg_val_old));
|
||||||
|
*reg_val = reg_val_old &= ~(*reg_val);
|
||||||
|
return nrf24l01p_ng_write_reg(dev, reg_addr, reg_val, sizeof(*reg_val));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Modify bits in a certain 8-bit register
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
* @param[in] reg_addr Address of the register to be modified
|
||||||
|
* @param[in] mask Mask of bits to be modified
|
||||||
|
* @param[in, out] reg_val Register bits that are being modified
|
||||||
|
*
|
||||||
|
* @return Status register value
|
||||||
|
*/
|
||||||
|
static inline
|
||||||
|
uint8_t nrf24l01p_ng_reg8_mod(const nrf24l01p_ng_t *dev, uint8_t reg_addr,
|
||||||
|
uint8_t mask, uint8_t *reg_val) {
|
||||||
|
uint8_t reg_val_old;
|
||||||
|
nrf24l01p_ng_read_reg(dev, reg_addr, ®_val_old, sizeof(reg_val_old));
|
||||||
|
reg_val_old &= ~mask;
|
||||||
|
*reg_val = reg_val_old | *reg_val;
|
||||||
|
return nrf24l01p_ng_write_reg(dev, reg_addr, reg_val, sizeof(*reg_val));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* NRF24L01P_NG_REGISTERS_H */
|
||||||
|
/** @} */
|
||||||
86
drivers/nrf24l01p_ng/include/nrf24l01p_ng_states.h
Normal file
86
drivers/nrf24l01p_ng/include/nrf24l01p_ng_states.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Otto-von-Guericke-Universität Magdeburg
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @ingroup drivers_nrf24l01p_ng
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Operation states of NRF24L01+ (NG) devices
|
||||||
|
*
|
||||||
|
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
|
||||||
|
*/
|
||||||
|
#ifndef NRF24L01P_NG_STATES_H
|
||||||
|
#define NRF24L01P_NG_STATES_H
|
||||||
|
|
||||||
|
#include "nrf24l01p_ng.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Wakeup delay
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_DELAY_US_START_UP (1500)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Transition delay to RX mode
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_DELAY_US_RX_SETTLING (130)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Transition delay to TX mode
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_DELAY_US_TX_SETTLING (130)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CE gpio pin pull-low to trigger a transmission
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_DELAY_US_CE_HIGH_PULSE (10)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Put device to sleep
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
*/
|
||||||
|
void nrf24l01p_ng_transition_to_power_down(nrf24l01p_ng_t *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Go to idle state, wake up device
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
*/
|
||||||
|
void nrf24l01p_ng_transition_to_standby_1(nrf24l01p_ng_t *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Go to "be ready to transmit" state
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
*/
|
||||||
|
void nrf24l01p_ng_transition_to_standby_2(nrf24l01p_ng_t *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Go to Rx mode
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
*/
|
||||||
|
void nrf24l01p_ng_transition_to_rx_mode(nrf24l01p_ng_t *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Go to Tx mode
|
||||||
|
*
|
||||||
|
* @param[in] dev NRF24L01+ device handle
|
||||||
|
*/
|
||||||
|
void nrf24l01p_ng_transition_to_tx_mode(nrf24l01p_ng_t *dev);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* NRF24L01P_NG_STATES_H */
|
||||||
|
/** @} */
|
||||||
363
drivers/nrf24l01p_ng/include/nrf24l01p_ng_types.h
Normal file
363
drivers/nrf24l01p_ng/include/nrf24l01p_ng_types.h
Normal file
@ -0,0 +1,363 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Otto-von-Guericke-Universität Magdeburg
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @ingroup drivers_nrf24l01p
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Definitions of user visible types for the NRF24L01+ (NG)
|
||||||
|
* device driver
|
||||||
|
*
|
||||||
|
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
|
||||||
|
*/
|
||||||
|
#ifndef NRF24L01P_NG_TYPES_H
|
||||||
|
#define NRF24L01P_NG_TYPES_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flag that indicates that a state transition to
|
||||||
|
* POWER_DOWN can be done
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_TRANSITION_TO_POWER_DOWN (1 << 3)
|
||||||
|
/**
|
||||||
|
* @brief Flag that indicates that a state transition to
|
||||||
|
* STANDBY_1 can be done
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_TRANSITION_TO_STANDBY_1 (1 << 4)
|
||||||
|
/**
|
||||||
|
* @brief Flag that indicates that a state transition to
|
||||||
|
* STANDBY_2 can be done
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_TRANSITION_TO_STANDBY_2 (1 << 5)
|
||||||
|
/**
|
||||||
|
* @brief Flag that indicates that a state transition to
|
||||||
|
* RX_MODE can be done
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_TRANSITION_TO_RX_MODE (1 << 6)
|
||||||
|
/**
|
||||||
|
* @brief Flag that indicates that a state transition to
|
||||||
|
* TX_MODE can be done
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_TRANSITION_TO_TX_MODE (1 << 7)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief NRF24L01+ operation states
|
||||||
|
*/
|
||||||
|
typedef enum nrf24l01p_ng_state {
|
||||||
|
/** @brief State right after voltage supply */
|
||||||
|
NRF24L01P_NG_STATE_UNDEFINED = (0 |
|
||||||
|
(NRF24L01P_NG_TRANSITION_TO_POWER_DOWN)),
|
||||||
|
/** @brief Register values are available and maintained, SPI active */
|
||||||
|
NRF24L01P_NG_STATE_POWER_DOWN = (1 |
|
||||||
|
(NRF24L01P_NG_TRANSITION_TO_STANDBY_1)),
|
||||||
|
/** @brief Idle */
|
||||||
|
NRF24L01P_NG_STATE_STANDBY_1 = (2 |
|
||||||
|
(NRF24L01P_NG_TRANSITION_TO_POWER_DOWN |
|
||||||
|
NRF24L01P_NG_TRANSITION_TO_STANDBY_2 |
|
||||||
|
NRF24L01P_NG_TRANSITION_TO_RX_MODE |
|
||||||
|
NRF24L01P_NG_TRANSITION_TO_TX_MODE)),
|
||||||
|
/** @brief TX FIFO empty, fill up TX FIFO again */
|
||||||
|
NRF24L01P_NG_STATE_STANDBY_2 = (3 |
|
||||||
|
(NRF24L01P_NG_TRANSITION_TO_POWER_DOWN |
|
||||||
|
NRF24L01P_NG_TRANSITION_TO_TX_MODE)),
|
||||||
|
/** @brief Constantly search for a valid packet */
|
||||||
|
NRF24L01P_NG_STATE_RX_MODE = (4 |
|
||||||
|
(NRF24L01P_NG_TRANSITION_TO_POWER_DOWN |
|
||||||
|
NRF24L01P_NG_TRANSITION_TO_STANDBY_1)),
|
||||||
|
/** @brief Transmit next packet */
|
||||||
|
NRF24L01P_NG_STATE_TX_MODE = (5 |
|
||||||
|
(NRF24L01P_NG_TRANSITION_TO_POWER_DOWN |
|
||||||
|
NRF24L01P_NG_TRANSITION_TO_STANDBY_1 |
|
||||||
|
NRF24L01P_NG_TRANSITION_TO_STANDBY_2)),
|
||||||
|
} nrf24l01p_ng_state_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enumeration of NRF24L01+ data pipes
|
||||||
|
*/
|
||||||
|
typedef enum nrf24l01p_ng_pipe {
|
||||||
|
NRF24L01P_NG_P0 = 0, /**< Pipe 0 */
|
||||||
|
NRF24L01P_NG_P1 = 1, /**< Pipe 1 */
|
||||||
|
NRF24L01P_NG_P2 = 2, /**< Pipe 2 */
|
||||||
|
NRF24L01P_NG_P3 = 3, /**< Pipe 3 */
|
||||||
|
NRF24L01P_NG_P4 = 4, /**< Pipe 4 */
|
||||||
|
NRF24L01P_NG_P5 = 5, /**< Pipe 5 */
|
||||||
|
NRF24L01P_NG_PX_NUM_OF /**< Number of supported pipes */
|
||||||
|
} nrf24l01p_ng_pipe_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Possible values to configure the layer-2 address width
|
||||||
|
*/
|
||||||
|
typedef enum nrf24l01p_ng_aw {
|
||||||
|
NRF24L01P_NG_AW_3BYTE = 1, /**< Use a 3 bytes long layer-2 address */
|
||||||
|
NRF24L01P_NG_AW_4BYTE = 2, /**< Use a 4 bytes long layer-2 address */
|
||||||
|
NRF24L01P_NG_AW_5BYTE = 3, /**< Use a 5 bytes long layer-2 address */
|
||||||
|
NRF24L01P_NG_AW_NUM_OF /**< Number of possible values to configure
|
||||||
|
the layer-2 address width */
|
||||||
|
} nrf24l01p_ng_aw_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Possible values to configure the retransmission delay in ESB
|
||||||
|
*/
|
||||||
|
typedef enum nrf24l01p_ng_ard {
|
||||||
|
NRF24L01P_NG_ARD_250US = 0, /**< 250 us */
|
||||||
|
NRF24L01P_NG_ARD_500US = 1, /**< 500 us */
|
||||||
|
NRF24L01P_NG_ARD_750US = 2, /**< 750 us */
|
||||||
|
NRF24L01P_NG_ARD_1000US = 3, /**< 1000 us */
|
||||||
|
NRF24L01P_NG_ARD_1250US = 4, /**< 1250 us */
|
||||||
|
NRF24L01P_NG_ARD_1500US = 5, /**< 1500 us */
|
||||||
|
NRF24L01P_NG_ARD_1750US = 6, /**< 1750 us */
|
||||||
|
NRF24L01P_NG_ARD_2000US = 7, /**< 2000 us */
|
||||||
|
NRF24L01P_NG_ARD_2250US = 8, /**< 2250 us */
|
||||||
|
NRF24L01P_NG_ARD_2500US = 9, /**< 2500 us */
|
||||||
|
NRF24L01P_NG_ARD_2750US = 10, /**< 2750 us */
|
||||||
|
NRF24L01P_NG_ARD_3000US = 11, /**< 3000 us */
|
||||||
|
NRF24L01P_NG_ARD_3250US = 12, /**< 3250 us */
|
||||||
|
NRF24L01P_NG_ARD_3500US = 13, /**< 3500 us */
|
||||||
|
NRF24L01P_NG_ARD_3750US = 14, /**< 3750 us */
|
||||||
|
NRF24L01P_NG_ARD_4000US = 15, /**< 4000 us */
|
||||||
|
NRF24L01P_NG_ARD_NUM_OF /**< Number of possible values to configure
|
||||||
|
the retransmission delay */
|
||||||
|
} nrf24l01p_ng_ard_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Possible values to configure the CRC length
|
||||||
|
*/
|
||||||
|
typedef enum nrf24l01p_ng_crc {
|
||||||
|
NRF24L01P_NG_CRC_0BYTE = 1, /**< 0 bytes CRC length */
|
||||||
|
NRF24L01P_NG_CRC_1BYTE = 2, /**< 1 byte CRC length */
|
||||||
|
NRF24L01P_NG_CRC_2BYTE = 3, /**< 2 bytes CRC length */
|
||||||
|
} nrf24l01p_ng_crc_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Possible values to configure the radio power
|
||||||
|
*/
|
||||||
|
typedef enum nrf24l01p_ng_tx_power {
|
||||||
|
NRF24L01P_NG_TX_POWER_MINUS_18DBM = 0, /**< -18 dBm */
|
||||||
|
NRF24L01P_NG_TX_POWER_MINUS_12DBM = 1, /**< -12 dBm */
|
||||||
|
NRF24L01P_NG_TX_POWER_MINUS_6DBM = 2, /**< -6 dBm */
|
||||||
|
NRF24L01P_NG_TX_POWER_0DBM = 3, /**< 0 dBm */
|
||||||
|
NRF24L01P_NG_TX_POWER_NUM_OF /**< Number of possible values
|
||||||
|
to configure the radio power */
|
||||||
|
} nrf24l01p_ng_tx_power_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Possible values to configure the data rate
|
||||||
|
*/
|
||||||
|
typedef enum nrf24l01p_ng_rfdr {
|
||||||
|
NRF24L01P_NG_RF_DR_1MBPS = 0, /**< 1 Mbit/s */
|
||||||
|
NRF24L01P_NG_RF_DR_250KBPS = 1, /**< 250 kbit/s */
|
||||||
|
NRF24L01P_NG_RF_DR_2MBPS = 2, /**< 2 Mbit/s */
|
||||||
|
NRF24L01P_NG_RF_DR_NUM_OF /**< Number of possible values to configure
|
||||||
|
the data rate */
|
||||||
|
} nrf24l01p_ng_rfdr_t;
|
||||||
|
|
||||||
|
struct nrf24l01p_ng;
|
||||||
|
typedef struct nrf24l01p_ng nrf24l01p_ng_t; /**< typedef of
|
||||||
|
forward declaration */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert @ref nrf24l01p_ng_aw_t to actual address width
|
||||||
|
*
|
||||||
|
* @param[in] address_width Address width enum
|
||||||
|
*
|
||||||
|
* @return Address width in [bytes]
|
||||||
|
*/
|
||||||
|
static inline
|
||||||
|
uint8_t nrf24l01p_ng_etoval_aw(nrf24l01p_ng_aw_t address_width)
|
||||||
|
{
|
||||||
|
if (address_width <= NRF24L01P_NG_AW_3BYTE) {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
if (address_width == NRF24L01P_NG_AW_4BYTE) {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert address width in [bytes] to @ref nrf24l01p_ng_aw_t
|
||||||
|
*
|
||||||
|
* @param[in] address_width Address width in [bytes]
|
||||||
|
*
|
||||||
|
* @return Corresponding enum
|
||||||
|
*/
|
||||||
|
static inline
|
||||||
|
nrf24l01p_ng_aw_t nrf24l01p_ng_valtoe_aw(uint8_t address_width)
|
||||||
|
{
|
||||||
|
if (address_width <= 3) {
|
||||||
|
return NRF24L01P_NG_AW_3BYTE;
|
||||||
|
}
|
||||||
|
if (address_width == 4) {
|
||||||
|
return NRF24L01P_NG_AW_4BYTE;
|
||||||
|
}
|
||||||
|
return NRF24L01P_NG_AW_5BYTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert @ref nrf24l01p_ng_ard_t to actual retransmission delay
|
||||||
|
*
|
||||||
|
* @param[in] retr_delay Retransmission delay enum
|
||||||
|
*
|
||||||
|
* @return Retransmission delay in [us]
|
||||||
|
*/
|
||||||
|
static inline
|
||||||
|
uint16_t nrf24l01p_ng_etoval_ard(nrf24l01p_ng_ard_t retr_delay)
|
||||||
|
{
|
||||||
|
if (retr_delay >= NRF24L01P_NG_ARD_4000US) {
|
||||||
|
return 4000;
|
||||||
|
}
|
||||||
|
return (retr_delay + 1) * 250;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert retransmission delay in [us] to @ref nrf24l01p_ng_ard_t
|
||||||
|
*
|
||||||
|
* @param[in] retr_delay Retransmission delay in [us]
|
||||||
|
*
|
||||||
|
* @return Corresponding enum
|
||||||
|
*/
|
||||||
|
static inline
|
||||||
|
nrf24l01p_ng_ard_t nrf24l01p_ng_valtoe_ard(uint16_t retr_delay)
|
||||||
|
{
|
||||||
|
if (retr_delay >= 4000) {
|
||||||
|
return NRF24L01P_NG_ARD_4000US;
|
||||||
|
}
|
||||||
|
return (nrf24l01p_ng_ard_t)(retr_delay / 250);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert @ref nrf24l01p_ng_crc_t to actual CRC length
|
||||||
|
*
|
||||||
|
* @param[in] crc_len CRC length enum
|
||||||
|
*
|
||||||
|
* @return CRC length in [bytes]
|
||||||
|
*/
|
||||||
|
static inline
|
||||||
|
uint8_t nrf24l01p_ng_etoval_crc(nrf24l01p_ng_crc_t crc_len)
|
||||||
|
{
|
||||||
|
if (crc_len <= NRF24L01P_NG_CRC_0BYTE) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (crc_len == NRF24L01P_NG_CRC_1BYTE) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert CRC length in [bytes] to @ref nrf24l01p_ng_crc_t
|
||||||
|
*
|
||||||
|
* @param[in] crc_len CRC length in [bytes]
|
||||||
|
*
|
||||||
|
* @return Corresponding enum
|
||||||
|
*/
|
||||||
|
static inline
|
||||||
|
nrf24l01p_ng_crc_t nrf24l01p_ng_valtoe_crc(uint8_t crc_len)
|
||||||
|
{
|
||||||
|
if (!crc_len) {
|
||||||
|
return NRF24L01P_NG_CRC_0BYTE;
|
||||||
|
}
|
||||||
|
if (crc_len == 1) {
|
||||||
|
return NRF24L01P_NG_CRC_1BYTE;
|
||||||
|
}
|
||||||
|
return NRF24L01P_NG_CRC_2BYTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert @ref nrf24l01p_ng_tx_power_t to actual Tx power
|
||||||
|
*
|
||||||
|
* @param[in] power RF power enum
|
||||||
|
*
|
||||||
|
* @return RF power in [dbm]
|
||||||
|
*/
|
||||||
|
static inline
|
||||||
|
int8_t nrf24l01p_ng_etoval_tx_power(nrf24l01p_ng_tx_power_t power)
|
||||||
|
{
|
||||||
|
if (power == NRF24L01P_NG_TX_POWER_MINUS_18DBM) {
|
||||||
|
return -18;
|
||||||
|
}
|
||||||
|
if (power == NRF24L01P_NG_TX_POWER_MINUS_12DBM) {
|
||||||
|
return -12;
|
||||||
|
}
|
||||||
|
if (power == NRF24L01P_NG_TX_POWER_MINUS_6DBM) {
|
||||||
|
return -6;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert RF power in [dbm] to @ref nrf24l01p_ng_tx_power_t
|
||||||
|
*
|
||||||
|
* @param[in] power RF power in [dbm]
|
||||||
|
*
|
||||||
|
* @return Corresponding enum
|
||||||
|
*/
|
||||||
|
static inline
|
||||||
|
nrf24l01p_ng_tx_power_t nrf24l01p_ng_valtoe_tx_power(int16_t power)
|
||||||
|
{
|
||||||
|
if (power <= -18) {
|
||||||
|
return NRF24L01P_NG_TX_POWER_MINUS_18DBM;
|
||||||
|
}
|
||||||
|
if (power <= -12) {
|
||||||
|
return NRF24L01P_NG_TX_POWER_MINUS_12DBM;
|
||||||
|
}
|
||||||
|
if (power <= -6) {
|
||||||
|
return NRF24L01P_NG_TX_POWER_MINUS_6DBM;
|
||||||
|
}
|
||||||
|
return NRF24L01P_NG_TX_POWER_0DBM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert @ref nrf24l01p_ng_rfdr_t to actual air data rate
|
||||||
|
*
|
||||||
|
* @param[in] data_rate Air data rate enum
|
||||||
|
*
|
||||||
|
* @return Air data rate in [kbit/s]
|
||||||
|
*/
|
||||||
|
static inline
|
||||||
|
uint16_t nrf24l01p_ng_etoval_rfdr(nrf24l01p_ng_rfdr_t data_rate)
|
||||||
|
{
|
||||||
|
if (data_rate == NRF24L01P_NG_RF_DR_1MBPS) {
|
||||||
|
return 1000;
|
||||||
|
}
|
||||||
|
if (data_rate == NRF24L01P_NG_RF_DR_250KBPS) {
|
||||||
|
return 250;
|
||||||
|
}
|
||||||
|
return 2000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert Air data rate in [kbit/s] to @ref nrf24l01p_ng_rfdr_t
|
||||||
|
*
|
||||||
|
* @param[in] data_rate Air data rate in [kbit/s]
|
||||||
|
*
|
||||||
|
* @return Corresponding enum
|
||||||
|
*/
|
||||||
|
static inline
|
||||||
|
nrf24l01p_ng_rfdr_t nrf24l01p_ng_valtoe_rfdr(uint16_t data_rate)
|
||||||
|
{
|
||||||
|
if (data_rate <= 250) {
|
||||||
|
return NRF24L01P_NG_RF_DR_250KBPS;
|
||||||
|
}
|
||||||
|
if (data_rate <= 1000) {
|
||||||
|
return NRF24L01P_NG_RF_DR_1MBPS;
|
||||||
|
}
|
||||||
|
return NRF24L01P_NG_RF_DR_2MBPS;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* NRF24L01P_NG_TYPES_H */
|
||||||
|
/** @} */
|
||||||
401
drivers/nrf24l01p_ng/nrf24l01p_ng.c
Normal file
401
drivers/nrf24l01p_ng/nrf24l01p_ng.c
Normal file
@ -0,0 +1,401 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Otto-von-Guericke-Universität Magdeburg
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @ingroup drivers_nrf24l01p_ng
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Implementation of the public NRF24L01+ (NG) device interface
|
||||||
|
*
|
||||||
|
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define ENABLE_DEBUG (0)
|
||||||
|
#include "debug.h"
|
||||||
|
#include "kernel_defines.h"
|
||||||
|
|
||||||
|
#include "nrf24l01p_ng_netdev.h"
|
||||||
|
#include "nrf24l01p_ng_constants.h"
|
||||||
|
#include "nrf24l01p_ng_communication.h"
|
||||||
|
#include "nrf24l01p_ng_registers.h"
|
||||||
|
#include "nrf24l01p_ng_states.h"
|
||||||
|
#if IS_USED(MODULE_NRF24L01P_NG_DIAGNOSTICS)
|
||||||
|
#include "nrf24l01p_ng_diagnostics.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NRF24L01P_NG_REG_RX_ADDR_PX(x) (NRF24L01P_NG_REG_RX_ADDR_P0 + (x))
|
||||||
|
#define NRF24L01P_NG_REG_RX_PW_PX(x) (NRF24L01P_NG_REG_RX_PW_P0 + (x))
|
||||||
|
|
||||||
|
int nrf24l01p_ng_setup(nrf24l01p_ng_t *dev,
|
||||||
|
const nrf24l01p_ng_params_t *params)
|
||||||
|
{
|
||||||
|
assert(dev);
|
||||||
|
assert(params);
|
||||||
|
memset((char *)dev + sizeof(netdev_t), 0x00,
|
||||||
|
sizeof(nrf24l01p_ng_t) - sizeof(netdev_t));
|
||||||
|
dev->state = NRF24L01P_NG_STATE_UNDEFINED;
|
||||||
|
dev->idle_state = NRF24L01P_NG_STATE_RX_MODE;
|
||||||
|
dev->params = *params;
|
||||||
|
dev->netdev.driver = &nrf24l01p_ng_driver;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nrf24l01p_ng_set_enable_pipe(nrf24l01p_ng_t *dev, nrf24l01p_ng_pipe_t pipe,
|
||||||
|
bool enable)
|
||||||
|
{
|
||||||
|
assert(dev);
|
||||||
|
if (pipe >= NRF24L01P_NG_PX_NUM_OF) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
uint8_t en_aa = (1 << pipe);
|
||||||
|
uint8_t dynpd = (1 << pipe);
|
||||||
|
uint8_t en_rx_addr = (1 << pipe);
|
||||||
|
nrf24l01p_ng_acquire(dev);
|
||||||
|
if (enable) {
|
||||||
|
nrf24l01p_ng_reg8_set(dev, NRF24L01P_NG_REG_EN_AA, &en_aa);
|
||||||
|
nrf24l01p_ng_reg8_set(dev, NRF24L01P_NG_REG_DYNPD, &dynpd);
|
||||||
|
nrf24l01p_ng_reg8_set(dev, NRF24L01P_NG_REG_EN_RXADDR, &en_rx_addr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nrf24l01p_ng_reg8_clear(dev, NRF24L01P_NG_REG_EN_AA, &en_aa);
|
||||||
|
nrf24l01p_ng_reg8_clear(dev, NRF24L01P_NG_REG_DYNPD, &dynpd);
|
||||||
|
nrf24l01p_ng_reg8_clear(dev, NRF24L01P_NG_REG_EN_RXADDR, &en_rx_addr);
|
||||||
|
}
|
||||||
|
nrf24l01p_ng_release(dev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nrf24l01p_ng_get_enable_pipe(nrf24l01p_ng_t *dev, nrf24l01p_ng_pipe_t pipe,
|
||||||
|
bool* enable)
|
||||||
|
{
|
||||||
|
assert(dev);
|
||||||
|
if (pipe >= NRF24L01P_NG_PX_NUM_OF) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
uint8_t en_rx_addr;
|
||||||
|
nrf24l01p_ng_acquire(dev);
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_EN_RXADDR, &en_rx_addr, 1);
|
||||||
|
nrf24l01p_ng_release(dev);
|
||||||
|
*enable = !!(en_rx_addr & (1 << pipe));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nrf24l01p_ng_set_air_data_rate(nrf24l01p_ng_t *dev,
|
||||||
|
nrf24l01p_ng_rfdr_t data_rate)
|
||||||
|
{
|
||||||
|
assert(dev);
|
||||||
|
if (data_rate >= NRF24L01P_NG_RF_DR_NUM_OF) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
switch (dev->state) {
|
||||||
|
case NRF24L01P_NG_STATE_POWER_DOWN:
|
||||||
|
case NRF24L01P_NG_STATE_STANDBY_1:
|
||||||
|
case NRF24L01P_NG_STATE_RX_MODE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
uint8_t rf_setup = NRF24L01P_NG_FLG_RF_DR(data_rate);
|
||||||
|
nrf24l01p_ng_acquire(dev);
|
||||||
|
nrf24l01p_ng_reg8_mod(dev, NRF24L01P_NG_REG_RF_SETUP,
|
||||||
|
NRF24L01P_NG_MSK_RF_DR, &rf_setup);
|
||||||
|
nrf24l01p_ng_release(dev);
|
||||||
|
dev->params.config.cfg_data_rate = data_rate;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t nrf24l01p_ng_get_air_data_rate(const nrf24l01p_ng_t *dev,
|
||||||
|
nrf24l01p_ng_rfdr_t *data_rate)
|
||||||
|
{
|
||||||
|
assert(dev);
|
||||||
|
if (data_rate) {
|
||||||
|
*data_rate = dev->params.config.cfg_data_rate;
|
||||||
|
}
|
||||||
|
return nrf24l01p_ng_etoval_rfdr(dev->params.config.cfg_data_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
int nrf24l01p_ng_set_crc(nrf24l01p_ng_t *dev, nrf24l01p_ng_crc_t crc)
|
||||||
|
{
|
||||||
|
assert(dev);
|
||||||
|
if (crc > NRF24L01P_NG_CRC_2BYTE) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (crc == NRF24L01P_NG_CRC_0BYTE) {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
switch (dev->state) {
|
||||||
|
case NRF24L01P_NG_STATE_POWER_DOWN:
|
||||||
|
case NRF24L01P_NG_STATE_STANDBY_1:
|
||||||
|
case NRF24L01P_NG_STATE_RX_MODE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
uint8_t config = NRF24L01P_NG_FLG_CRCO(crc);
|
||||||
|
nrf24l01p_ng_acquire(dev);
|
||||||
|
nrf24l01p_ng_reg8_mod(dev, NRF24L01P_NG_REG_CONFIG, NRF24L01P_NG_MSK_CRC,
|
||||||
|
&config);
|
||||||
|
nrf24l01p_ng_release(dev);
|
||||||
|
dev->params.config.cfg_crc = crc;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t nrf24l01p_ng_get_crc(const nrf24l01p_ng_t *dev,
|
||||||
|
nrf24l01p_ng_crc_t *crc)
|
||||||
|
{
|
||||||
|
assert(dev);
|
||||||
|
if (crc) {
|
||||||
|
*crc = dev->params.config.cfg_crc;
|
||||||
|
}
|
||||||
|
return nrf24l01p_ng_etoval_crc(dev->params.config.cfg_crc);
|
||||||
|
}
|
||||||
|
|
||||||
|
int nrf24l01p_ng_set_tx_power(nrf24l01p_ng_t *dev,
|
||||||
|
nrf24l01p_ng_tx_power_t power)
|
||||||
|
{
|
||||||
|
assert(dev);
|
||||||
|
if (power >= NRF24L01P_NG_TX_POWER_NUM_OF) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
switch (dev->state) {
|
||||||
|
case NRF24L01P_NG_STATE_POWER_DOWN:
|
||||||
|
case NRF24L01P_NG_STATE_STANDBY_1:
|
||||||
|
case NRF24L01P_NG_STATE_RX_MODE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
uint8_t rf_setup = NRF24L01P_NG_FLG_RF_PWR(power);
|
||||||
|
nrf24l01p_ng_acquire(dev);
|
||||||
|
nrf24l01p_ng_reg8_mod(dev, NRF24L01P_NG_REG_RF_SETUP,
|
||||||
|
NRF24L01P_NG_MSK_RF_PWR, &rf_setup);
|
||||||
|
nrf24l01p_ng_release(dev);
|
||||||
|
dev->params.config.cfg_tx_power = power;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t nrf24l01p_ng_get_tx_power(const nrf24l01p_ng_t *dev,
|
||||||
|
nrf24l01p_ng_tx_power_t *power)
|
||||||
|
{
|
||||||
|
assert(dev);
|
||||||
|
if (power) {
|
||||||
|
*power = dev->params.config.cfg_tx_power;
|
||||||
|
}
|
||||||
|
return nrf24l01p_ng_etoval_tx_power(dev->params.config.cfg_tx_power);
|
||||||
|
}
|
||||||
|
|
||||||
|
int nrf24l01p_ng_set_channel(nrf24l01p_ng_t *dev, uint8_t channel)
|
||||||
|
{
|
||||||
|
assert(dev);
|
||||||
|
if (channel >= NRF24L01P_NG_NUM_CHANNELS) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
switch (dev->state) {
|
||||||
|
case NRF24L01P_NG_STATE_POWER_DOWN:
|
||||||
|
case NRF24L01P_NG_STATE_STANDBY_1:
|
||||||
|
case NRF24L01P_NG_STATE_RX_MODE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
uint8_t rf_ch = NRF24L01P_NG_FLG_RF_CH(channel);
|
||||||
|
nrf24l01p_ng_acquire(dev);
|
||||||
|
nrf24l01p_ng_reg8_mod(dev, NRF24L01P_NG_REG_RF_CH,
|
||||||
|
NRF24L01P_NG_MSK_RF_CH, &rf_ch);
|
||||||
|
nrf24l01p_ng_release(dev);
|
||||||
|
dev->params.config.cfg_channel = channel;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t nrf24l01p_ng_get_channel(const nrf24l01p_ng_t *dev)
|
||||||
|
{
|
||||||
|
assert(dev);
|
||||||
|
return dev->params.config.cfg_channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nrf24l01p_ng_set_rx_address(nrf24l01p_ng_t *dev, const uint8_t *addr,
|
||||||
|
nrf24l01p_ng_pipe_t pipe)
|
||||||
|
{
|
||||||
|
assert(dev);
|
||||||
|
assert(addr);
|
||||||
|
if (pipe >= NRF24L01P_NG_PX_NUM_OF) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
switch (dev->state) {
|
||||||
|
case NRF24L01P_NG_STATE_POWER_DOWN:
|
||||||
|
case NRF24L01P_NG_STATE_STANDBY_1:
|
||||||
|
case NRF24L01P_NG_STATE_RX_MODE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
nrf24l01p_ng_acquire(dev);
|
||||||
|
if (pipe == NRF24L01P_NG_P0) {
|
||||||
|
nrf24l01p_ng_write_reg(dev, NRF24L01P_NG_REG_RX_ADDR_PX(pipe),
|
||||||
|
addr, NRF24L01P_NG_ADDR_WIDTH);
|
||||||
|
memcpy(NRF24L01P_NG_ADDR_P0(dev), addr, NRF24L01P_NG_ADDR_WIDTH);
|
||||||
|
}
|
||||||
|
else if (pipe == NRF24L01P_NG_P1) {
|
||||||
|
nrf24l01p_ng_write_reg(dev, NRF24L01P_NG_REG_RX_ADDR_PX(pipe),
|
||||||
|
addr, NRF24L01P_NG_ADDR_WIDTH);
|
||||||
|
memcpy(NRF24L01P_NG_ADDR_P1(dev), addr, NRF24L01P_NG_ADDR_WIDTH);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nrf24l01p_ng_write_reg(dev, NRF24L01P_NG_REG_RX_ADDR_PX(pipe),
|
||||||
|
addr, 1);
|
||||||
|
NRF24L01P_NG_ADDR_PX_LSB(dev, pipe) = *addr;
|
||||||
|
}
|
||||||
|
nrf24l01p_ng_release(dev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nrf24l01p_ng_get_rx_address(const nrf24l01p_ng_t *dev, uint8_t *addr,
|
||||||
|
nrf24l01p_ng_pipe_t pipe)
|
||||||
|
{
|
||||||
|
assert(dev);
|
||||||
|
assert(addr);
|
||||||
|
if (pipe >= NRF24L01P_NG_PX_NUM_OF) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (pipe == NRF24L01P_NG_P0) {
|
||||||
|
memcpy(addr, NRF24L01P_NG_ADDR_P0(dev), NRF24L01P_NG_ADDR_WIDTH);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
memcpy(addr, NRF24L01P_NG_ADDR_P1(dev), NRF24L01P_NG_ADDR_WIDTH);
|
||||||
|
if (pipe > NRF24L01P_NG_P1) {
|
||||||
|
addr[NRF24L01P_NG_ADDR_WIDTH - 1] =
|
||||||
|
NRF24L01P_NG_ADDR_PX_LSB(dev, pipe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NRF24L01P_NG_ADDR_WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nrf24l01p_ng_set_max_retransm(nrf24l01p_ng_t *dev, uint8_t max_rt)
|
||||||
|
{
|
||||||
|
assert(dev);
|
||||||
|
if (max_rt > NRF24L01P_NG_MAX_RETRANSMISSIONS) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
switch (dev->state) {
|
||||||
|
case NRF24L01P_NG_STATE_POWER_DOWN:
|
||||||
|
case NRF24L01P_NG_STATE_STANDBY_1:
|
||||||
|
case NRF24L01P_NG_STATE_RX_MODE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
uint8_t setup_retr = NRF24L01P_NG_FLG_ARC(max_rt);
|
||||||
|
nrf24l01p_ng_acquire(dev);
|
||||||
|
nrf24l01p_ng_reg8_mod(dev, NRF24L01P_NG_REG_SETUP_RETR,
|
||||||
|
NRF24L01P_NG_MSK_ARC, &setup_retr);
|
||||||
|
nrf24l01p_ng_release(dev);
|
||||||
|
dev->params.config.cfg_max_retr = max_rt;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t nrf24l01p_ng_get_max_retransm(const nrf24l01p_ng_t *dev)
|
||||||
|
{
|
||||||
|
assert(dev);
|
||||||
|
return dev->params.config.cfg_max_retr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nrf24l01p_ng_set_retransm_delay(nrf24l01p_ng_t *dev,
|
||||||
|
nrf24l01p_ng_ard_t rt_delay)
|
||||||
|
{
|
||||||
|
assert(dev);
|
||||||
|
if (rt_delay >= NRF24L01P_NG_ARD_NUM_OF) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
switch (dev->state) {
|
||||||
|
case NRF24L01P_NG_STATE_POWER_DOWN:
|
||||||
|
case NRF24L01P_NG_STATE_STANDBY_1:
|
||||||
|
case NRF24L01P_NG_STATE_RX_MODE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
uint8_t setup_retr = NRF24L01P_NG_FLG_ARD(rt_delay);
|
||||||
|
nrf24l01p_ng_acquire(dev);
|
||||||
|
nrf24l01p_ng_reg8_mod(dev, NRF24L01P_NG_REG_SETUP_RETR,
|
||||||
|
NRF24L01P_NG_MSK_ARD, &setup_retr);
|
||||||
|
nrf24l01p_ng_release(dev);
|
||||||
|
dev->params.config.cfg_retr_delay = rt_delay;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t nrf24l01p_ng_get_retransm_delay(const nrf24l01p_ng_t *dev,
|
||||||
|
nrf24l01p_ng_ard_t *rt_delay)
|
||||||
|
{
|
||||||
|
assert(dev);
|
||||||
|
if (rt_delay) {
|
||||||
|
*rt_delay = dev->params.config.cfg_retr_delay;
|
||||||
|
}
|
||||||
|
return nrf24l01p_ng_etoval_ard(dev->params.config.cfg_retr_delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
int nrf24l01p_ng_set_state(nrf24l01p_ng_t *dev, nrf24l01p_ng_state_t state)
|
||||||
|
{
|
||||||
|
switch (dev->state) {
|
||||||
|
case NRF24L01P_NG_STATE_POWER_DOWN:
|
||||||
|
case NRF24L01P_NG_STATE_STANDBY_1:
|
||||||
|
case NRF24L01P_NG_STATE_RX_MODE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
nrf24l01p_ng_state_t old = dev->state;
|
||||||
|
nrf24l01p_ng_acquire(dev);
|
||||||
|
if (state == NRF24L01P_NG_STATE_POWER_DOWN) {
|
||||||
|
if (dev->state != NRF24L01P_NG_STATE_POWER_DOWN) {
|
||||||
|
nrf24l01p_ng_transition_to_power_down(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (state == NRF24L01P_NG_STATE_STANDBY_1) {
|
||||||
|
if (dev->state != NRF24L01P_NG_STATE_STANDBY_1) {
|
||||||
|
nrf24l01p_ng_transition_to_standby_1(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (state == NRF24L01P_NG_STATE_RX_MODE) {
|
||||||
|
if (dev->state != NRF24L01P_NG_STATE_RX_MODE) {
|
||||||
|
if (state != NRF24L01P_NG_STATE_STANDBY_1) {
|
||||||
|
nrf24l01p_ng_transition_to_standby_1(dev);
|
||||||
|
}
|
||||||
|
nrf24l01p_ng_transition_to_rx_mode(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nrf24l01p_ng_release(dev);
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
nrf24l01p_ng_release(dev);
|
||||||
|
return (int)old;
|
||||||
|
}
|
||||||
|
|
||||||
|
nrf24l01p_ng_state_t nrf24l01p_ng_get_state(const nrf24l01p_ng_t *dev)
|
||||||
|
{
|
||||||
|
assert(dev);
|
||||||
|
return dev->state;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if IS_USED(MODULE_NRF24L01P_NG_DIAGNOSTICS)
|
||||||
|
void nrf24l01p_ng_print_all_regs(nrf24l01p_ng_t *dev)
|
||||||
|
{
|
||||||
|
nrf24l01p_ng_acquire(dev);
|
||||||
|
nrf24l01p_ng_diagnostics_print_all_regs(dev);
|
||||||
|
nrf24l01p_ng_release(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nrf24l01p_ng_print_dev_info(const nrf24l01p_ng_t *dev)
|
||||||
|
{
|
||||||
|
nrf24l01p_ng_diagnostics_print_dev_info(dev);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
219
drivers/nrf24l01p_ng/nrf24l01p_ng_communication.c
Normal file
219
drivers/nrf24l01p_ng/nrf24l01p_ng_communication.c
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Otto-von-Guericke-Universität Magdeburg
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @ingroup drivers_nrf24l01p_ng
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Functions to communicate with the NRF24L01+ (NG) transceiver
|
||||||
|
* via SPI
|
||||||
|
*
|
||||||
|
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
#include <errno.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "periph/gpio.h"
|
||||||
|
#include "periph/spi.h"
|
||||||
|
#include "nrf24l01p_ng_constants.h"
|
||||||
|
#include "nrf24l01p_ng_communication.h"
|
||||||
|
|
||||||
|
#define ENABLE_DEBUG (0)
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#define SPI_BUS (dev->params.spi)
|
||||||
|
#define SPI_PIN_CS (dev->params.pin_cs)
|
||||||
|
|
||||||
|
#define NRF24L01P_NG_REG_MAX_WIDTH NRF24L01P_NG_MAX_ADDR_WIDTH
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reverse @p len bytes in @p buffer
|
||||||
|
*
|
||||||
|
* The NRF24L01+ expects data to be send over SPI from LSByte to MSByte
|
||||||
|
* and will output data bytes also from LSByte to MSByte!
|
||||||
|
* See the datasheet page 47, 8.3.1 SPI comands.
|
||||||
|
*
|
||||||
|
* This shall be the address register of pipe 0 inside the transceiver:
|
||||||
|
* [ x, x, x, x, x] (x = undefined content)
|
||||||
|
*
|
||||||
|
* Suppose you want to give pipe 0 the address 01:02:03:04.
|
||||||
|
* If you send:
|
||||||
|
* 01 ---> [ x, x, x, x, 01]
|
||||||
|
* 02 ---> [ x, x, x, 02, 01]
|
||||||
|
* 03 ---> [ x, x, 03, 02, 02]
|
||||||
|
* 04 ---> [ x, 04, 03, 02, 01]
|
||||||
|
*
|
||||||
|
* The transceiver does not have the address you expected.
|
||||||
|
* But over SPI you would read:
|
||||||
|
* [ x, 04, 03, 02, 01] ---> 01:02:03:04
|
||||||
|
* because it sends the LSByte first. But it will not
|
||||||
|
* receice frames that are actually addressed to 01:02:03:04.
|
||||||
|
*
|
||||||
|
* So if you want to assign the address 01:02:03:04
|
||||||
|
* you first have to swap the bytes, before you send data over SPI.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void _nrf24l01p_ng_swap_bytes(uint8_t* buffer, size_t len) {
|
||||||
|
for (size_t i = 0; i < len / 2; i++) {
|
||||||
|
uint8_t tmp = buffer[i];
|
||||||
|
buffer[i] = buffer[len - 1 - i];
|
||||||
|
buffer[len - 1 - i] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void _nrf24l01p_ng_copy_and_swap_bytes(uint8_t* dst, const uint8_t* src, size_t len) {
|
||||||
|
const uint8_t* end = dst + len;
|
||||||
|
src += len;
|
||||||
|
while (dst != end) {
|
||||||
|
*dst++ = *--src;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int nrf24l01p_ng_acquire(nrf24l01p_ng_t *dev)
|
||||||
|
{
|
||||||
|
return spi_acquire(dev->params.spi, dev->params.pin_cs, SPI_MODE_0,
|
||||||
|
dev->params.spi_clk);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nrf24l01p_ng_release(nrf24l01p_ng_t *dev)
|
||||||
|
{
|
||||||
|
spi_release(dev->params.spi);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t nrf24l01p_ng_read_reg(const nrf24l01p_ng_t *dev, uint8_t reg,
|
||||||
|
uint8_t *dest, size_t len)
|
||||||
|
{
|
||||||
|
uint8_t cmd = NRF24L01P_NG_CMD_R_REGISTER(reg);
|
||||||
|
uint8_t status = spi_transfer_byte(SPI_BUS, SPI_PIN_CS, true, cmd);
|
||||||
|
spi_transfer_bytes(SPI_BUS, SPI_PIN_CS, false, NULL, dest, len);
|
||||||
|
if (len > 1) {
|
||||||
|
_nrf24l01p_ng_swap_bytes(dest, len);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t nrf24l01p_ng_write_reg(const nrf24l01p_ng_t *dev, uint8_t reg,
|
||||||
|
const uint8_t *src, size_t len)
|
||||||
|
{
|
||||||
|
assert(len <= NRF24L01P_NG_REG_MAX_WIDTH);
|
||||||
|
uint8_t cmd = NRF24L01P_NG_CMD_W_REGISTER(reg);
|
||||||
|
uint8_t status;
|
||||||
|
if (len > 1) {
|
||||||
|
uint8_t lsrc[NRF24L01P_NG_REG_MAX_WIDTH];
|
||||||
|
_nrf24l01p_ng_copy_and_swap_bytes(lsrc, src, len);
|
||||||
|
status = spi_transfer_byte(SPI_BUS, SPI_PIN_CS, true, cmd);
|
||||||
|
spi_transfer_bytes(SPI_BUS, SPI_PIN_CS, false, lsrc, NULL, len);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
status = spi_transfer_byte(SPI_BUS, SPI_PIN_CS, true, cmd);
|
||||||
|
spi_transfer_bytes(SPI_BUS, SPI_PIN_CS, false, src, NULL, len);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t nrf24l01p_ng_read_rx_payload(const nrf24l01p_ng_t *dev, void *dest,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
uint8_t cmd = NRF24L01P_NG_CMD_R_RX_PAYLOAD;
|
||||||
|
uint8_t status = spi_transfer_byte(SPI_BUS, SPI_PIN_CS, true, cmd);
|
||||||
|
spi_transfer_bytes(SPI_BUS, SPI_PIN_CS, false, &cmd, dest, len);
|
||||||
|
if (len > 1) {
|
||||||
|
_nrf24l01p_ng_swap_bytes(dest, len);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t nrf24l01p_ng_write_tx_payload(const nrf24l01p_ng_t *dev,
|
||||||
|
const void *src, size_t len)
|
||||||
|
{
|
||||||
|
assert(len <= NRF24L01P_NG_MAX_PAYLOAD_WIDTH);
|
||||||
|
uint8_t cmd = NRF24L01P_NG_CMD_W_TX_PAYLOAD;
|
||||||
|
uint8_t status;
|
||||||
|
if (len > 1) {
|
||||||
|
uint8_t lsrc[NRF24L01P_NG_MAX_PAYLOAD_WIDTH];
|
||||||
|
_nrf24l01p_ng_copy_and_swap_bytes(lsrc, src, len);
|
||||||
|
status = spi_transfer_byte(SPI_BUS, SPI_PIN_CS, true, cmd);
|
||||||
|
spi_transfer_bytes(SPI_BUS, SPI_PIN_CS, false, lsrc, NULL, len);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
status = spi_transfer_byte(SPI_BUS, SPI_PIN_CS, true, cmd);
|
||||||
|
spi_transfer_bytes(SPI_BUS, SPI_PIN_CS, false, src, NULL, len);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t nrf24l01p_ng_flush_tx(const nrf24l01p_ng_t *dev)
|
||||||
|
{
|
||||||
|
uint8_t cmd = NRF24L01P_NG_CMD_FLUSH_TX;
|
||||||
|
return spi_transfer_byte(SPI_BUS, SPI_PIN_CS, false, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t nrf24l01p_ng_flush_rx(const nrf24l01p_ng_t *dev)
|
||||||
|
{
|
||||||
|
uint8_t cmd = NRF24L01P_NG_CMD_FLUSH_RX;
|
||||||
|
return spi_transfer_byte(SPI_BUS, SPI_PIN_CS, false, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t nrf24l01p_ng_reuse_tx_pl(const nrf24l01p_ng_t *dev)
|
||||||
|
{
|
||||||
|
uint8_t cmd = NRF24L01P_NG_CMD_REUSE_TX_PL;
|
||||||
|
return spi_transfer_byte(SPI_BUS, SPI_PIN_CS, false, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t nrf24l01p_ng_read_rx_pl_width(const nrf24l01p_ng_t *dev, uint8_t *dest)
|
||||||
|
{
|
||||||
|
uint8_t cmd = NRF24L01P_NG_CMD_R_RX_PL_WID;
|
||||||
|
uint8_t status = spi_transfer_byte(SPI_BUS, SPI_PIN_CS, true, cmd);
|
||||||
|
spi_transfer_bytes(SPI_BUS, SPI_PIN_CS, false, NULL, dest, 1);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t nrf24l01p_ng_write_ack_pl(const nrf24l01p_ng_t *dev, const void *src,
|
||||||
|
size_t len, uint8_t pipe)
|
||||||
|
{
|
||||||
|
assert(len <= NRF24L01P_NG_MAX_PAYLOAD_WIDTH);
|
||||||
|
assert(pipe < NRF24L01P_NG_PX_NUM_OF);
|
||||||
|
uint8_t cmd = NRF24L01P_NG_CMD_W_ACK_PAYLOAD(pipe);
|
||||||
|
uint8_t status;
|
||||||
|
if (len > 1) {
|
||||||
|
uint8_t lsrc[NRF24L01P_NG_MAX_PAYLOAD_WIDTH];
|
||||||
|
_nrf24l01p_ng_copy_and_swap_bytes(lsrc, src, len);
|
||||||
|
status = spi_transfer_byte(SPI_BUS, SPI_PIN_CS, true, cmd);
|
||||||
|
spi_transfer_bytes(SPI_BUS, SPI_PIN_CS, false, lsrc, NULL, len);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
status = spi_transfer_byte(SPI_BUS, SPI_PIN_CS, true, cmd);
|
||||||
|
spi_transfer_bytes(SPI_BUS, SPI_PIN_CS, false, src, NULL, len);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t nrf24l01p_ng_write_tx_pl_no_ack(const nrf24l01p_ng_t *dev,
|
||||||
|
const void *src, size_t len)
|
||||||
|
{
|
||||||
|
assert(len <= NRF24L01P_NG_MAX_PAYLOAD_WIDTH);
|
||||||
|
uint8_t cmd = NRF24L01P_NG_CMD_W_TX_PAYLOAD_NO_ACK;
|
||||||
|
uint8_t status;
|
||||||
|
if (len > 1) {
|
||||||
|
uint8_t lsrc[NRF24L01P_NG_MAX_PAYLOAD_WIDTH];
|
||||||
|
_nrf24l01p_ng_copy_and_swap_bytes(lsrc, src, len);
|
||||||
|
status = spi_transfer_byte(SPI_BUS, SPI_PIN_CS, true, cmd);
|
||||||
|
spi_transfer_bytes(SPI_BUS, SPI_PIN_CS, false, lsrc, NULL, len);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
status = spi_transfer_byte(SPI_BUS, SPI_PIN_CS, true, cmd);
|
||||||
|
spi_transfer_bytes(SPI_BUS, SPI_PIN_CS, false, src, NULL, len);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t nrf24l01p_ng_get_status(const nrf24l01p_ng_t *dev)
|
||||||
|
{
|
||||||
|
uint8_t cmd = NRF24L01P_NG_CMD_NOP;
|
||||||
|
return spi_transfer_byte(SPI_BUS, SPI_PIN_CS, false, cmd);
|
||||||
|
}
|
||||||
671
drivers/nrf24l01p_ng/nrf24l01p_ng_netdev.c
Normal file
671
drivers/nrf24l01p_ng/nrf24l01p_ng_netdev.c
Normal file
@ -0,0 +1,671 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Otto-von-Guericke-Universität Magdeburg
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @ingroup drivers_nrf24l01p_ng
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Implementation of RIOT's netdev_driver API
|
||||||
|
* for the NRF24L01+ (NG) transceiver
|
||||||
|
*
|
||||||
|
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#define ENABLE_DEBUG (0)
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#include "kernel_defines.h"
|
||||||
|
#include "iolist.h"
|
||||||
|
#include "irq.h"
|
||||||
|
#include "luid.h"
|
||||||
|
#include "mutex.h"
|
||||||
|
#include "net/eui64.h"
|
||||||
|
#include "net/netdev.h"
|
||||||
|
#include "xtimer.h"
|
||||||
|
|
||||||
|
#include "gnrc_netif_nrf24l01p_ng.h"
|
||||||
|
#include "nrf24l01p_ng_constants.h"
|
||||||
|
#include "nrf24l01p_ng_registers.h"
|
||||||
|
#include "nrf24l01p_ng_communication.h"
|
||||||
|
#include "nrf24l01p_ng_states.h"
|
||||||
|
#include "nrf24l01p_ng_netdev.h"
|
||||||
|
#if IS_USED(MODULE_NRF24L01P_NG_DIAGNOSTICS)
|
||||||
|
#include "nrf24l01p_ng_diagnostics.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NRF24L01P_NG_FLG_IRQ \
|
||||||
|
(NRF24L01P_NG_FLG_MAX_RT | NRF24L01P_NG_FLG_TX_DS | NRF24L01P_NG_FLG_RX_DR)
|
||||||
|
|
||||||
|
static int _init(netdev_t *netdev);
|
||||||
|
static int _recv(netdev_t *netdev, void *buf, size_t len, void *info);
|
||||||
|
static int _send(netdev_t *netdev, const iolist_t *iolist);
|
||||||
|
static void _isr(netdev_t *netdev);
|
||||||
|
static int _get(netdev_t *netdev, netopt_t opt, void *val, size_t max_len);
|
||||||
|
static int _set(netdev_t *netdev, netopt_t opt, const void *val, size_t max_len);
|
||||||
|
|
||||||
|
const netdev_driver_t nrf24l01p_ng_driver = {
|
||||||
|
.init = _init,
|
||||||
|
.recv = _recv,
|
||||||
|
.send = _send,
|
||||||
|
.isr = _isr,
|
||||||
|
.get = _get,
|
||||||
|
.set = _set
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void _trigger_send(const nrf24l01p_ng_t *dev)
|
||||||
|
{
|
||||||
|
gpio_set(dev->params.pin_ce);
|
||||||
|
xtimer_usleep(NRF24L01P_NG_DELAY_US_CE_HIGH_PULSE);
|
||||||
|
gpio_clear(dev->params.pin_ce);
|
||||||
|
xtimer_usleep(NRF24L01P_NG_DELAY_US_TX_SETTLING);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _assert_awake(const nrf24l01p_ng_t *dev)
|
||||||
|
{
|
||||||
|
return nrf24l01p_ng_reg8_read(dev, NRF24L01P_NG_REG_CONFIG) &
|
||||||
|
NRF24L01P_NG_FLG_PWR_UP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static netopt_state_t _state_to_netif(nrf24l01p_ng_state_t state)
|
||||||
|
{
|
||||||
|
if (state == NRF24L01P_NG_STATE_POWER_DOWN) {
|
||||||
|
return NETOPT_STATE_SLEEP;
|
||||||
|
}
|
||||||
|
if (state == NRF24L01P_NG_STATE_STANDBY_1) {
|
||||||
|
return NETOPT_STATE_STANDBY;
|
||||||
|
}
|
||||||
|
if (state == NRF24L01P_NG_STATE_STANDBY_2) {
|
||||||
|
return NETOPT_STATE_TX;
|
||||||
|
}
|
||||||
|
if (state == NRF24L01P_NG_STATE_TX_MODE) {
|
||||||
|
return NETOPT_STATE_TX;
|
||||||
|
}
|
||||||
|
if (state == NRF24L01P_NG_STATE_RX_MODE) {
|
||||||
|
return NETOPT_STATE_RX;
|
||||||
|
}
|
||||||
|
return NETOPT_STATE_OFF; /* error */
|
||||||
|
}
|
||||||
|
|
||||||
|
nrf24l01p_ng_state_t _state_from_netif(netopt_state_t state)
|
||||||
|
{
|
||||||
|
if (state == NETOPT_STATE_SLEEP) {
|
||||||
|
return NRF24L01P_NG_STATE_POWER_DOWN;
|
||||||
|
}
|
||||||
|
if (state == NETOPT_STATE_STANDBY) {
|
||||||
|
return NRF24L01P_NG_STATE_STANDBY_1;
|
||||||
|
}
|
||||||
|
if (state == NETOPT_STATE_TX) {
|
||||||
|
return NRF24L01P_NG_STATE_TX_MODE;
|
||||||
|
}
|
||||||
|
if (state == NETOPT_STATE_RX) {
|
||||||
|
return NRF24L01P_NG_STATE_RX_MODE;
|
||||||
|
}
|
||||||
|
return NRF24L01P_NG_STATE_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _nrf24l01p_ng_irq_handler(void *_dev)
|
||||||
|
{
|
||||||
|
nrf24l01p_ng_t *dev = (nrf24l01p_ng_t *)_dev;
|
||||||
|
/* Once the IRQ pin has triggered,
|
||||||
|
do not congest the thread´s
|
||||||
|
message queue with IRQ events */
|
||||||
|
gpio_irq_disable(dev->params.pin_irq);
|
||||||
|
netdev_trigger_event_isr((netdev_t *)dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _isr_max_rt(nrf24l01p_ng_t *dev)
|
||||||
|
{
|
||||||
|
assert(dev->state == NRF24L01P_NG_STATE_STANDBY_1 ||
|
||||||
|
dev->state == NRF24L01P_NG_STATE_STANDBY_2 ||
|
||||||
|
dev->state == NRF24L01P_NG_STATE_RX_MODE ||
|
||||||
|
dev->state == NRF24L01P_NG_STATE_TX_MODE);
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] IRS MAX_RT");
|
||||||
|
nrf24l01p_ng_acquire(dev);
|
||||||
|
nrf24l01p_ng_flush_tx(dev);
|
||||||
|
nrf24l01p_ng_release(dev);
|
||||||
|
dev->netdev.event_callback(&dev->netdev, NETDEV_EVENT_TX_NOACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _isr_rx_dr(nrf24l01p_ng_t *dev)
|
||||||
|
{
|
||||||
|
assert(dev->state == NRF24L01P_NG_STATE_STANDBY_1 ||
|
||||||
|
dev->state == NRF24L01P_NG_STATE_STANDBY_2 ||
|
||||||
|
dev->state == NRF24L01P_NG_STATE_RX_MODE ||
|
||||||
|
dev->state == NRF24L01P_NG_STATE_TX_MODE);
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] IRS RX_DR");
|
||||||
|
/* read all RX data */
|
||||||
|
nrf24l01p_ng_acquire(dev);
|
||||||
|
while (!(nrf24l01p_ng_reg8_read(dev, NRF24L01P_NG_REG_FIFO_STATUS) &
|
||||||
|
NRF24L01P_NG_FLG_RX_EMPTY)) {
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] ISR: read pending Rx frames");
|
||||||
|
dev->netdev.event_callback(&dev->netdev, NETDEV_EVENT_RX_COMPLETE);
|
||||||
|
}
|
||||||
|
nrf24l01p_ng_release(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _isr_tx_ds(nrf24l01p_ng_t *dev)
|
||||||
|
{
|
||||||
|
assert(dev->state == NRF24L01P_NG_STATE_STANDBY_1 ||
|
||||||
|
dev->state == NRF24L01P_NG_STATE_STANDBY_2 ||
|
||||||
|
dev->state == NRF24L01P_NG_STATE_RX_MODE ||
|
||||||
|
dev->state == NRF24L01P_NG_STATE_TX_MODE);
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] IRS TX_DS");
|
||||||
|
dev->netdev.event_callback(&dev->netdev, NETDEV_EVENT_TX_COMPLETE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _init(netdev_t *netdev)
|
||||||
|
{
|
||||||
|
nrf24l01p_ng_t *dev = (nrf24l01p_ng_t *)netdev;
|
||||||
|
if (dev->params.config.cfg_data_rate >= NRF24L01P_NG_RF_DR_NUM_OF ||
|
||||||
|
dev->params.config.cfg_crc == NRF24L01P_NG_CRC_0BYTE ||
|
||||||
|
dev->params.config.cfg_channel >= NRF24L01P_NG_NUM_CHANNELS) {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
if (spi_init_cs(dev->params.spi, dev->params.pin_cs) != SPI_OK) {
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] _init(): spi_init_cs() failed");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
if (gpio_init(dev->params.pin_ce, GPIO_OUT) < 0) {
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] _init(): gpio_init() failed");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
gpio_clear(dev->params.pin_ce);
|
||||||
|
if (nrf24l01p_ng_acquire(dev) < 0) {
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] _init(): nrf24l01p_ng_acquire() failed");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
if (dev->state != NRF24L01P_NG_STATE_POWER_DOWN) {
|
||||||
|
nrf24l01p_ng_transition_to_power_down(dev);
|
||||||
|
}
|
||||||
|
/* flush internal Tx and Rx FIFO */
|
||||||
|
nrf24l01p_ng_flush_tx(dev);
|
||||||
|
nrf24l01p_ng_flush_rx(dev);
|
||||||
|
uint8_t aw = NRF24L01P_NG_ADDR_WIDTH;
|
||||||
|
const uint8_t bc[] = NRF24L01P_NG_BROADCAST_ADDR;
|
||||||
|
memcpy(NRF24L01P_NG_ADDR_P0(dev), bc, aw);
|
||||||
|
/* assign to pipe 0 the broadcast address*/
|
||||||
|
nrf24l01p_ng_write_reg(dev, NRF24L01P_NG_REG_RX_ADDR_P0,
|
||||||
|
NRF24L01P_NG_ADDR_P0(dev), aw);
|
||||||
|
luid_get_lb(NRF24L01P_NG_ADDR_P1(dev), aw);
|
||||||
|
/* "The LSByte must be unique for all six pipes" [datasheet p.38] */
|
||||||
|
if (NRF24L01P_NG_ADDR_P1(dev)[aw - 1] == bc[aw - 1]) {
|
||||||
|
luid_get_lb(NRF24L01P_NG_ADDR_P1(dev), aw);
|
||||||
|
}
|
||||||
|
/* assign to pipe 0 the "main" listening address */
|
||||||
|
nrf24l01p_ng_write_reg(dev, NRF24L01P_NG_REG_RX_ADDR_P1,
|
||||||
|
NRF24L01P_NG_ADDR_P1(dev), aw);
|
||||||
|
/* set the address width */
|
||||||
|
nrf24l01p_ng_reg8_write(dev, NRF24L01P_NG_REG_SETUP_AW,
|
||||||
|
NRF24L01P_NG_FLG_AW(nrf24l01p_ng_valtoe_aw(aw)));
|
||||||
|
/* set Tx power and Tx data rate */
|
||||||
|
nrf24l01p_ng_reg8_write(dev, NRF24L01P_NG_REG_RF_SETUP,
|
||||||
|
NRF24L01P_NG_FLG_RF_DR(dev->params.config.cfg_data_rate) |
|
||||||
|
NRF24L01P_NG_FLG_RF_PWR(dev->params.config.cfg_tx_power));
|
||||||
|
/* set retransmission delay and the maximum number of retransmisisons */
|
||||||
|
nrf24l01p_ng_reg8_write(dev, NRF24L01P_NG_REG_SETUP_RETR,
|
||||||
|
NRF24L01P_NG_FLG_ARD(dev->params.config.cfg_retr_delay) |
|
||||||
|
NRF24L01P_NG_FLG_ARC(dev->params.config.cfg_max_retr));
|
||||||
|
/* set the radio channel */
|
||||||
|
nrf24l01p_ng_reg8_write(dev, NRF24L01P_NG_REG_RF_CH,
|
||||||
|
NRF24L01P_NG_FLG_RF_CH(dev->params.config.cfg_channel));
|
||||||
|
/* enable pipe 0 and pipe 1 */
|
||||||
|
nrf24l01p_ng_reg8_write(dev, NRF24L01P_NG_REG_EN_RXADDR,
|
||||||
|
NRF24L01P_NG_FLG_ERX_P0 |
|
||||||
|
NRF24L01P_NG_FLG_ERX_P1);
|
||||||
|
/* set CRC length */
|
||||||
|
nrf24l01p_ng_reg8_write(dev, NRF24L01P_NG_REG_CONFIG,
|
||||||
|
NRF24L01P_NG_FLG_CRCO(dev->params.config.cfg_crc));
|
||||||
|
/* enable NRF24L01+ features:
|
||||||
|
automatic acknowledgements,
|
||||||
|
dynamic payload lengths,
|
||||||
|
piggyback acknowledgements */
|
||||||
|
nrf24l01p_ng_reg8_write(dev, NRF24L01P_NG_REG_FEATURES,
|
||||||
|
NRF24L01P_NG_FLG_EN_DYN_ACK |
|
||||||
|
NRF24L01P_NG_FLG_EN_DPL |
|
||||||
|
NRF24L01P_NG_FLG_EN_ACK_PAY);
|
||||||
|
/* enable automatic acknowledgements for pipe 0 and pipe 1 */
|
||||||
|
nrf24l01p_ng_reg8_write(dev, NRF24L01P_NG_REG_EN_AA,
|
||||||
|
NRF24L01P_NG_FLG_ENAA_P0 |
|
||||||
|
NRF24L01P_NG_FLG_ENAA_P1);
|
||||||
|
/* enable dynamic payload lengths for pipe 0 and pipe 1 */
|
||||||
|
nrf24l01p_ng_reg8_write(dev, NRF24L01P_NG_REG_DYNPD,
|
||||||
|
NRF24L01P_NG_FLG_DPL_P0 |
|
||||||
|
NRF24L01P_NG_FLG_DPL_P1);
|
||||||
|
/* clear interrupts */
|
||||||
|
nrf24l01p_ng_reg8_write(dev, NRF24L01P_NG_REG_STATUS, NRF24L01P_NG_FLG_IRQ);
|
||||||
|
/* go to standby */
|
||||||
|
nrf24l01p_ng_transition_to_standby_1(dev);
|
||||||
|
#if IS_USED(MODULE_NRF24L01P_NG_DIAGNOSTICS) && ENABLE_DEBUG
|
||||||
|
nrf24l01p_ng_diagnostics_print_all_regs(dev);
|
||||||
|
nrf24l01p_ng_diagnostics_print_dev_info(dev);
|
||||||
|
#endif
|
||||||
|
/* check if the transceiver responds */
|
||||||
|
if (!_assert_awake(dev)) {
|
||||||
|
nrf24l01p_ng_release(dev);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
/* go to listening state */
|
||||||
|
nrf24l01p_ng_transition_to_rx_mode(dev);
|
||||||
|
nrf24l01p_ng_release(dev);
|
||||||
|
/* enable interrupt pins */
|
||||||
|
if (gpio_init_int(dev->params.pin_irq, GPIO_IN, GPIO_FALLING,
|
||||||
|
_nrf24l01p_ng_irq_handler, dev) < 0) {
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] _init(): gpio_init_int() failed");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief NRF24L01+ @ref netdev_driver_t::recv routine
|
||||||
|
*
|
||||||
|
* @pre @see nrf24l01p_ng_acquire must have been called before.
|
||||||
|
* @pre Interrupts should be disabled
|
||||||
|
*
|
||||||
|
* The SPI bus is not acquired in this function because it is called from
|
||||||
|
* @ref netdev_driver_t::isr, possibly for multiple times. If another
|
||||||
|
* device acquired the SPI bus within the ISR, the ISR would block
|
||||||
|
* until that device releases the bus.
|
||||||
|
*
|
||||||
|
* @param[in] netdev Abstract network device handle
|
||||||
|
* @param[out] buf Rx buffer
|
||||||
|
* @param[in] len Size of Rx buffer
|
||||||
|
* @param[out] LQI and RSSI information (unused)
|
||||||
|
*
|
||||||
|
* @return Size of received frame in @p buf
|
||||||
|
* @return Upper estimation of the frame width,
|
||||||
|
* if @p buf == NULL and len == 0
|
||||||
|
* @return Actual frame width,
|
||||||
|
* if @p buf == NULL and @p len != 0
|
||||||
|
* (frame is NOT dropped)
|
||||||
|
* @retval -ENOBUFS @p buf != NULL and @p len < actual frame width
|
||||||
|
* (frame is dropped)
|
||||||
|
* @retval -EINVAL @p buf == NULL
|
||||||
|
* (and none of the above cases are true)
|
||||||
|
* @retval -ENOTSUP Malformed header
|
||||||
|
* @retval 0 No data to read from Rx FIFO
|
||||||
|
*/
|
||||||
|
static int _recv(netdev_t *netdev, void *buf, size_t len, void *info)
|
||||||
|
{
|
||||||
|
(void)info; /* nrf24l01+ supports neither lqi nor rssi */
|
||||||
|
|
||||||
|
/* return upper estaimation bound of frame size */
|
||||||
|
if (!buf && !len) {
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] Return upper frame estimation");
|
||||||
|
return NRF24L01P_NG_ADDR_WIDTH + NRF24L01P_NG_MAX_PAYLOAD_WIDTH;
|
||||||
|
}
|
||||||
|
nrf24l01p_ng_t *dev = (nrf24l01p_ng_t *)netdev;
|
||||||
|
uint8_t pl_width;
|
||||||
|
uint8_t status = nrf24l01p_ng_read_rx_pl_width(dev, &pl_width);
|
||||||
|
uint8_t pno = NRF24L01P_NG_VAL_RX_P_NO(status);
|
||||||
|
if (!pl_width ||
|
||||||
|
pl_width > NRF24L01P_NG_MAX_PAYLOAD_WIDTH ||
|
||||||
|
pno >= NRF24L01P_NG_PX_NUM_OF) {
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] RX error, flush RX FIFO");
|
||||||
|
/* In some rare cases the RX payload width (R_RX_PL_WID) exceeds
|
||||||
|
the maximum of 32 bytes. In that case it must be flushed.
|
||||||
|
See https://devzone.nordicsemi.com/f/nordic-q-a/26489/nrf24l01-the-length-of-received-data-exceed-32
|
||||||
|
and https://www.mikrocontroller.net/articles/NRF24L01_Tutorial */
|
||||||
|
nrf24l01p_ng_flush_rx(dev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint8_t frame_len = NRF24L01P_NG_ADDR_WIDTH + pl_width;
|
||||||
|
/* do NOT drop frame and return exact frame size */
|
||||||
|
if (!buf) {
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] Return exact frame length");
|
||||||
|
return frame_len;
|
||||||
|
}
|
||||||
|
/* drop frame, content in buf becomes invalid and return -ENOBUFS */
|
||||||
|
if (len < frame_len) {
|
||||||
|
DEBUG("[nrf24l01p_ng] Buffer too small: %u < %u, dropping frame\n",
|
||||||
|
len, frame_len);
|
||||||
|
uint8_t garbage[pl_width];
|
||||||
|
nrf24l01p_ng_read_rx_payload(dev, garbage, pl_width);
|
||||||
|
return -ENOBUFS;
|
||||||
|
}
|
||||||
|
/* get received frame */
|
||||||
|
uint8_t dst_addr[NRF24L01P_NG_ADDR_WIDTH];
|
||||||
|
if (pno == NRF24L01P_NG_P0) {
|
||||||
|
memcpy(dst_addr, NRF24L01P_NG_ADDR_P0(dev), sizeof(dst_addr));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
memcpy(dst_addr, NRF24L01P_NG_ADDR_P1(dev), sizeof(dst_addr));
|
||||||
|
if (pno > NRF24L01P_NG_P1) {
|
||||||
|
dst_addr[NRF24L01P_NG_ADDR_WIDTH - 1] =
|
||||||
|
NRF24L01P_NG_ADDR_PX_LSB(dev, pno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] Handle received frame");
|
||||||
|
uint8_t *frame = (uint8_t *)buf;
|
||||||
|
memcpy(frame, dst_addr, sizeof(dst_addr));
|
||||||
|
frame += sizeof(dst_addr);
|
||||||
|
nrf24l01p_ng_read_rx_payload(dev, frame, pl_width);
|
||||||
|
#if IS_USED(MODULE_NRF24L01P_NG_DIAGNOSTICS) && ENABLE_DEBUG
|
||||||
|
nrf24l01p_ng_diagnostics_print_frame(dev, (uint8_t *)buf, frame_len);
|
||||||
|
#endif
|
||||||
|
DEBUG("[nrf24l01p_ng] Received frame length: %u\n", frame_len);
|
||||||
|
return (int)frame_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief NRF24L01+ @ref netdev_driver_t::send routine
|
||||||
|
*
|
||||||
|
* @param[in] netdev Abstract network device handle
|
||||||
|
* @param[in] iolist Linked list of data to be sent, where
|
||||||
|
* the base must be the destination address
|
||||||
|
*
|
||||||
|
* @return Size of sent payload
|
||||||
|
* @retval -ENOTSUP @p iolist had no base and no next link,
|
||||||
|
* or address was too big, or too short
|
||||||
|
* @retval -EAGAIN Pending interrupts have been handled first
|
||||||
|
* @retval -EBUSY The internal Tx FIFO is full
|
||||||
|
* @retval -E2BIG Resulting frame from iolist was too big to be sent
|
||||||
|
*/
|
||||||
|
static int _send(netdev_t *netdev, const iolist_t *iolist)
|
||||||
|
{
|
||||||
|
assert(netdev && iolist);
|
||||||
|
if (!(iolist->iol_base) || !(iolist->iol_next)) {
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] No Tx address or no payload");
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
nrf24l01p_ng_t *dev = (nrf24l01p_ng_t *)netdev;
|
||||||
|
uint8_t pl_width = 0;
|
||||||
|
const uint8_t bcast_addr[] = NRF24L01P_NG_BROADCAST_ADDR;
|
||||||
|
uint8_t payload[NRF24L01P_NG_MAX_PAYLOAD_WIDTH];
|
||||||
|
nrf24l01p_ng_acquire(dev);
|
||||||
|
uint8_t fifo_status;
|
||||||
|
uint8_t status =
|
||||||
|
nrf24l01p_ng_read_reg(dev, NRF24L01P_NG_REG_FIFO_STATUS,
|
||||||
|
&fifo_status, 1);
|
||||||
|
if (status & NRF24L01P_NG_FLG_IRQ) {
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] Handle pending IRQ, before sending new data");
|
||||||
|
nrf24l01p_ng_release(dev);
|
||||||
|
_isr(&dev->netdev);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
if (fifo_status & NRF24L01P_NG_FLG_TX_FULL_) {
|
||||||
|
/* If the TX FIFO is full, but no ACK has arrived yet,
|
||||||
|
so no TX_DS / MAX_RT interrupt has triggered so far that
|
||||||
|
could clean the TX FIFO. So we need to wait until an interrupt
|
||||||
|
occurs, before we can send a new frame. This is done
|
||||||
|
while this _send() function is called in a loop and the
|
||||||
|
interrupt status is polled.
|
||||||
|
If you flush the FIFO here, pending content will
|
||||||
|
be lost. */
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] TX FIFO full");
|
||||||
|
nrf24l01p_ng_release(dev);
|
||||||
|
return -EBUSY; /* for gnrc_netif_pktq */
|
||||||
|
}
|
||||||
|
uint8_t *dst_addr = iolist->iol_base;
|
||||||
|
uint8_t dst_addr_len = iolist->iol_len;
|
||||||
|
if (dst_addr_len > NRF24L01P_NG_MAX_ADDR_WIDTH ||
|
||||||
|
dst_addr_len < NRF24L01P_NG_MIN_ADDR_WIDTH) {
|
||||||
|
nrf24l01p_ng_release(dev);
|
||||||
|
DEBUG("[nrf24l01p_ng] Destination address has an invalid length: %u\n",
|
||||||
|
dst_addr_len);
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
for (const iolist_t *iol = iolist->iol_next; iol; iol = iol->iol_next) {
|
||||||
|
if (pl_width + iol->iol_len > sizeof(payload)) {
|
||||||
|
nrf24l01p_ng_release(dev);
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] frame too big");
|
||||||
|
return -E2BIG;
|
||||||
|
}
|
||||||
|
memcpy(payload + pl_width, iol->iol_base, iol->iol_len);
|
||||||
|
pl_width += iol->iol_len;
|
||||||
|
}
|
||||||
|
nrf24l01p_ng_write_reg(dev, NRF24L01P_NG_REG_TX_ADDR,
|
||||||
|
dst_addr, dst_addr_len);
|
||||||
|
if (!memcmp(dst_addr, bcast_addr, dst_addr_len)) {
|
||||||
|
/* do not expect ACK for broadcast */
|
||||||
|
nrf24l01p_ng_write_tx_pl_no_ack(dev, payload, pl_width);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nrf24l01p_ng_write_tx_payload(dev, payload, pl_width);
|
||||||
|
/* A PTX node must change pipe 0 Rx address to Tx address
|
||||||
|
* in order to receive ACKs.
|
||||||
|
* If node switches back to Rx mode, pipe 0 Rx address
|
||||||
|
* must be restored from params. */
|
||||||
|
nrf24l01p_ng_write_reg(dev, NRF24L01P_NG_REG_RX_ADDR_P0,
|
||||||
|
dst_addr, dst_addr_len);
|
||||||
|
nrf24l01p_ng_reg8_write(dev, NRF24L01P_NG_REG_SETUP_AW,
|
||||||
|
NRF24L01P_NG_FLG_AW(nrf24l01p_ng_valtoe_aw(dst_addr_len)));
|
||||||
|
}
|
||||||
|
if (dev->state != NRF24L01P_NG_STATE_TX_MODE &&
|
||||||
|
dev->state != NRF24L01P_NG_STATE_STANDBY_2) {
|
||||||
|
dev->idle_state = dev->state;
|
||||||
|
if (dev->state != NRF24L01P_NG_STATE_STANDBY_1) {
|
||||||
|
nrf24l01p_ng_transition_to_standby_1(dev);
|
||||||
|
}
|
||||||
|
nrf24l01p_ng_transition_to_tx_mode(dev);
|
||||||
|
}
|
||||||
|
nrf24l01p_ng_release(dev);
|
||||||
|
_trigger_send(dev);
|
||||||
|
DEBUG("[nrf24l01p_ng] Sending %u bytes\n", pl_width);
|
||||||
|
return (int)pl_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief NRF24L01+ @ref netdev_driver_t::isr
|
||||||
|
*
|
||||||
|
* @param[in] netdev Abstract network device
|
||||||
|
*/
|
||||||
|
static void _isr(netdev_t *netdev)
|
||||||
|
{
|
||||||
|
nrf24l01p_ng_t *dev = (nrf24l01p_ng_t *)netdev;
|
||||||
|
|
||||||
|
nrf24l01p_ng_acquire(dev);
|
||||||
|
gpio_irq_enable(dev->params.pin_irq);
|
||||||
|
uint8_t status = nrf24l01p_ng_get_status(dev);
|
||||||
|
/* clear interrupt flags */
|
||||||
|
nrf24l01p_ng_write_reg(dev, NRF24L01P_NG_REG_STATUS, &status, 1);
|
||||||
|
nrf24l01p_ng_release(dev);
|
||||||
|
|
||||||
|
if (status & NRF24L01P_NG_FLG_RX_DR) {
|
||||||
|
_isr_rx_dr(dev);
|
||||||
|
}
|
||||||
|
if (status & NRF24L01P_NG_FLG_MAX_RT) {
|
||||||
|
_isr_max_rt(dev);
|
||||||
|
}
|
||||||
|
if (status & NRF24L01P_NG_FLG_TX_DS) {
|
||||||
|
_isr_tx_ds(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
nrf24l01p_ng_acquire(dev);
|
||||||
|
if (dev->state == NRF24L01P_NG_STATE_TX_MODE ||
|
||||||
|
dev->state == NRF24L01P_NG_STATE_STANDBY_2) {
|
||||||
|
/* frame in FIFO is not an ACK */
|
||||||
|
if (!(nrf24l01p_ng_reg8_read(dev, NRF24L01P_NG_REG_FIFO_STATUS) &
|
||||||
|
NRF24L01P_NG_FLG_TX_EMPTY)) {
|
||||||
|
nrf24l01p_ng_release(dev);
|
||||||
|
_trigger_send(dev);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* no more data to transmit */
|
||||||
|
if (dev->state != NRF24L01P_NG_STATE_STANDBY_1) {
|
||||||
|
nrf24l01p_ng_transition_to_standby_1(dev);
|
||||||
|
}
|
||||||
|
/* go to idle state */
|
||||||
|
if (dev->idle_state != NRF24L01P_NG_STATE_STANDBY_1) {
|
||||||
|
if (dev->idle_state == NRF24L01P_NG_STATE_POWER_DOWN) {
|
||||||
|
nrf24l01p_ng_transition_to_power_down(dev);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dev->idle_state = NRF24L01P_NG_STATE_RX_MODE;
|
||||||
|
nrf24l01p_ng_transition_to_rx_mode(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nrf24l01p_ng_release(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief @ref netdev_driver_t::get
|
||||||
|
*
|
||||||
|
* @param[in] netdev Abstract network device
|
||||||
|
* @param[in] opt netdev option type
|
||||||
|
* @param[out] val Option value
|
||||||
|
* @param[in] max_len Maximum option length
|
||||||
|
*
|
||||||
|
* @return Size of written option value
|
||||||
|
* @retval -ENOTSUP Unsupported netdev option @p opt
|
||||||
|
*/
|
||||||
|
static int _get(netdev_t *netdev, netopt_t opt, void *val, size_t max_len)
|
||||||
|
{
|
||||||
|
nrf24l01p_ng_t *dev = (nrf24l01p_ng_t *)netdev;
|
||||||
|
|
||||||
|
(void)max_len; /* only used in assert() */
|
||||||
|
switch (opt) {
|
||||||
|
case NETOPT_ADDR_LEN:
|
||||||
|
case NETOPT_SRC_LEN: {
|
||||||
|
assert(max_len == sizeof(uint16_t));
|
||||||
|
*((uint16_t *)val) = NRF24L01P_NG_ADDR_WIDTH;
|
||||||
|
return sizeof(uint16_t);
|
||||||
|
} break;
|
||||||
|
case NETOPT_ADDRESS: {
|
||||||
|
assert(max_len >= NRF24L01P_NG_ADDR_WIDTH);
|
||||||
|
memcpy(val, NRF24L01P_NG_ADDR_P1(dev), NRF24L01P_NG_ADDR_WIDTH);
|
||||||
|
return NRF24L01P_NG_ADDR_WIDTH;
|
||||||
|
} break;
|
||||||
|
case NETOPT_AUTOACK: {
|
||||||
|
assert(max_len == sizeof(netopt_enable_t));
|
||||||
|
/* mandatory for Enhanced ShockBurst */
|
||||||
|
*((netopt_enable_t *)val) = NETOPT_ENABLE;
|
||||||
|
return sizeof(netopt_enable_t);
|
||||||
|
} break;
|
||||||
|
case NETOPT_CHANNEL: {
|
||||||
|
assert(max_len == sizeof(uint16_t));
|
||||||
|
*((uint16_t *)val) = (uint16_t)nrf24l01p_ng_get_channel(dev);
|
||||||
|
return sizeof(uint16_t);
|
||||||
|
} break;
|
||||||
|
case NETOPT_CHECKSUM:
|
||||||
|
case NETOPT_INTEGRITY_CHECK: {
|
||||||
|
assert(max_len == sizeof(netopt_enable_t));
|
||||||
|
/* mandatory for Enhanced ShockBurst */
|
||||||
|
*((netopt_enable_t *)val) = NETOPT_ENABLE;
|
||||||
|
return sizeof(netopt_enable_t);
|
||||||
|
} break;
|
||||||
|
case NETOPT_DEVICE_TYPE: {
|
||||||
|
assert(max_len == sizeof(uint16_t));
|
||||||
|
*((uint16_t *)val) = NETDEV_TYPE_NRF24L01P_NG;
|
||||||
|
return sizeof(uint16_t);
|
||||||
|
} break;
|
||||||
|
case NETOPT_PROTO: {
|
||||||
|
assert(max_len == sizeof(gnrc_nettype_t));
|
||||||
|
*((gnrc_nettype_t *)val) = NRF24L01P_NG_UPPER_LAYER_PROTOCOL;
|
||||||
|
return sizeof(gnrc_nettype_t);
|
||||||
|
} break;
|
||||||
|
case NETOPT_MAX_PDU_SIZE: {
|
||||||
|
assert(max_len == sizeof(uint16_t));
|
||||||
|
*((uint16_t *)val) = NRF24L01P_NG_MAX_PAYLOAD_WIDTH -
|
||||||
|
NRF24L01P_NG_ADDR_WIDTH
|
||||||
|
- 1;
|
||||||
|
return sizeof(uint16_t);
|
||||||
|
}
|
||||||
|
case NETOPT_RETRANS: {
|
||||||
|
assert(max_len == sizeof(uint8_t));
|
||||||
|
*((uint8_t *)val) = nrf24l01p_ng_get_max_retransm(dev);
|
||||||
|
return sizeof(uint8_t);
|
||||||
|
}
|
||||||
|
case NETOPT_RX_TIMEOUT: {
|
||||||
|
assert(max_len == sizeof(uint32_t));
|
||||||
|
*((uint32_t *)val) =
|
||||||
|
(uint32_t)nrf24l01p_ng_get_retransm_delay(dev, NULL);
|
||||||
|
return sizeof(uint32_t);
|
||||||
|
} break;
|
||||||
|
case NETOPT_STATE: {
|
||||||
|
assert(max_len == sizeof(netopt_state_t));
|
||||||
|
*((netopt_state_t *)val) = _state_to_netif(dev->state);
|
||||||
|
return sizeof(netopt_state_t);
|
||||||
|
} break;
|
||||||
|
case NETOPT_TX_POWER: {
|
||||||
|
assert(max_len == sizeof(int16_t));
|
||||||
|
*((int16_t *)val) = (int16_t)nrf24l01p_ng_get_tx_power(dev, NULL);
|
||||||
|
return sizeof(uint16_t);
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
DEBUG("[nrf24l01p_ng] Unsupported netdev option %d\n", opt);
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief @ref netdev_driver_t::set
|
||||||
|
*
|
||||||
|
* @param[in] netdev Abstract network device handle
|
||||||
|
* @param[in] opt netdev option type
|
||||||
|
* @param[in] val Option value
|
||||||
|
* @param[in] len Size of option value
|
||||||
|
*
|
||||||
|
* @return Size of written option value
|
||||||
|
* @return negative number, on failure
|
||||||
|
* @retval -ENOTSUP Unsupported netdev option @p opt
|
||||||
|
*/
|
||||||
|
static int _set(netdev_t *netdev, netopt_t opt, const void *val, size_t len)
|
||||||
|
{
|
||||||
|
nrf24l01p_ng_t *dev = (nrf24l01p_ng_t *)netdev;
|
||||||
|
|
||||||
|
switch (opt) {
|
||||||
|
case NETOPT_ADDRESS: {
|
||||||
|
/* common address length for all pipes */
|
||||||
|
assert(len == NRF24L01P_NG_ADDR_WIDTH);
|
||||||
|
int ret = nrf24l01p_ng_set_rx_address(dev, val, NRF24L01P_NG_P0);
|
||||||
|
return ret ? ret : (int)len;
|
||||||
|
} break;
|
||||||
|
case NETOPT_CHANNEL: {
|
||||||
|
assert(len == sizeof(uint16_t));
|
||||||
|
uint16_t ch = *((uint16_t *)val);
|
||||||
|
int ret = nrf24l01p_ng_set_channel(dev, (uint8_t)ch);
|
||||||
|
return ret ? ret : (int)sizeof(uint16_t);
|
||||||
|
} break;
|
||||||
|
case NETOPT_CHECKSUM:
|
||||||
|
case NETOPT_INTEGRITY_CHECK: {
|
||||||
|
assert(len == sizeof(netopt_enable_t));
|
||||||
|
nrf24l01p_ng_crc_t crc =
|
||||||
|
(*((netopt_enable_t *)val) == NETOPT_ENABLE)
|
||||||
|
? NRF24L01P_NG_CRC_2BYTE : NRF24L01P_NG_CRC_0BYTE;
|
||||||
|
int ret = nrf24l01p_ng_set_crc(dev, crc);
|
||||||
|
return ret ? ret : (int)sizeof(netopt_enable_t);
|
||||||
|
} break;
|
||||||
|
case NETOPT_RETRANS: {
|
||||||
|
assert(len == sizeof(uint8_t));
|
||||||
|
uint8_t n = *((uint8_t *)val);
|
||||||
|
int ret = nrf24l01p_ng_set_max_retransm(dev, n);
|
||||||
|
return ret ? ret : (int)sizeof(uint8_t);
|
||||||
|
} break;
|
||||||
|
case NETOPT_RX_TIMEOUT: {
|
||||||
|
assert(len == sizeof(uint32_t));
|
||||||
|
uint32_t us = *((uint32_t *)val);
|
||||||
|
nrf24l01p_ng_ard_t ard = nrf24l01p_ng_valtoe_ard(us);
|
||||||
|
int ret = nrf24l01p_ng_set_retransm_delay(dev, ard);
|
||||||
|
return ret ? ret : (int)sizeof(uint32_t);
|
||||||
|
} break;
|
||||||
|
case NETOPT_STATE: {
|
||||||
|
assert(len == sizeof(netopt_state_t));
|
||||||
|
nrf24l01p_ng_state_t s =
|
||||||
|
_state_from_netif(*((netopt_state_t *)val));
|
||||||
|
int ret = nrf24l01p_ng_set_state(dev, s);
|
||||||
|
return ret < 0 ? ret : (int)sizeof(netopt_state_t);
|
||||||
|
} break;
|
||||||
|
case NETOPT_TX_POWER: {
|
||||||
|
assert(len == sizeof(int16_t));
|
||||||
|
int16_t dbm = *((int16_t *)val);
|
||||||
|
nrf24l01p_ng_tx_power_t txp = nrf24l01p_ng_valtoe_tx_power(dbm);
|
||||||
|
int ret = nrf24l01p_ng_set_tx_power(dev, txp);
|
||||||
|
return ret ? ret : (int)sizeof(int16_t);
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
DEBUG("[nrf24l01p_ng] Unsupported netdev option %d\n", opt);
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
}
|
||||||
120
drivers/nrf24l01p_ng/nrf24l01p_ng_states.c
Normal file
120
drivers/nrf24l01p_ng/nrf24l01p_ng_states.c
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Otto-von-Guericke-Universität Magdeburg
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @ingroup drivers_nrf24l01p_ng
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Implementation of state transition procedures
|
||||||
|
* for the NRF24L01+ (NG) transceiver
|
||||||
|
*
|
||||||
|
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define ENABLE_DEBUG (0)
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#include "xtimer.h"
|
||||||
|
#include "net/netopt.h"
|
||||||
|
|
||||||
|
#include "nrf24l01p_ng_registers.h"
|
||||||
|
#include "nrf24l01p_ng_communication.h"
|
||||||
|
#include "nrf24l01p_ng_states.h"
|
||||||
|
|
||||||
|
static void _restore_address_p0(const nrf24l01p_ng_t *dev)
|
||||||
|
{
|
||||||
|
uint8_t addr_buffer[NRF24L01P_NG_ADDR_WIDTH];
|
||||||
|
memcpy(addr_buffer, NRF24L01P_NG_ADDR_P0(dev), NRF24L01P_NG_ADDR_WIDTH);
|
||||||
|
nrf24l01p_ng_write_reg(dev, NRF24L01P_NG_REG_RX_ADDR_P0, addr_buffer,
|
||||||
|
NRF24L01P_NG_ADDR_WIDTH);
|
||||||
|
nrf24l01p_ng_reg8_write(dev, NRF24L01P_NG_REG_SETUP_AW,
|
||||||
|
NRF24L01P_NG_FLG_AW(nrf24l01p_ng_valtoe_aw(NRF24L01P_NG_ADDR_WIDTH)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void nrf24l01p_ng_transition_to_power_down(nrf24l01p_ng_t *dev)
|
||||||
|
{
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] transition to POWER_DOWN");
|
||||||
|
assert(dev->state & NRF24L01P_NG_TRANSITION_TO_POWER_DOWN);
|
||||||
|
uint8_t config = NRF24L01P_NG_FLG_PWR_UP;
|
||||||
|
nrf24l01p_ng_reg8_clear(dev, NRF24L01P_NG_REG_CONFIG, &config);
|
||||||
|
dev->state = NRF24L01P_NG_STATE_POWER_DOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nrf24l01p_ng_transition_to_standby_1(nrf24l01p_ng_t *dev)
|
||||||
|
{
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] transition to STANDBY_1");
|
||||||
|
assert(dev->state & NRF24L01P_NG_TRANSITION_TO_STANDBY_1);
|
||||||
|
switch (dev->state) {
|
||||||
|
case NRF24L01P_NG_STATE_POWER_DOWN:
|
||||||
|
gpio_clear(dev->params.pin_ce);
|
||||||
|
uint8_t config = NRF24L01P_NG_FLG_PWR_UP;
|
||||||
|
nrf24l01p_ng_reg8_set(dev, NRF24L01P_NG_REG_CONFIG, &config);
|
||||||
|
xtimer_usleep(NRF24L01P_NG_DELAY_US_START_UP);
|
||||||
|
break;
|
||||||
|
case NRF24L01P_NG_STATE_RX_MODE:
|
||||||
|
gpio_clear(dev->params.pin_ce);
|
||||||
|
break;
|
||||||
|
case NRF24L01P_NG_STATE_STANDBY_2:
|
||||||
|
case NRF24L01P_NG_STATE_TX_MODE:
|
||||||
|
gpio_clear(dev->params.pin_ce);
|
||||||
|
_restore_address_p0(dev);
|
||||||
|
/* TX finished with one packet */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dev->state = NRF24L01P_NG_STATE_STANDBY_1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nrf24l01p_ng_transition_to_standby_2(nrf24l01p_ng_t *dev)
|
||||||
|
{
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] transition to STANDBY_2");
|
||||||
|
assert(dev->state & NRF24L01P_NG_TRANSITION_TO_STANDBY_2);
|
||||||
|
switch (dev->state) {
|
||||||
|
case NRF24L01P_NG_STATE_STANDBY_1:;
|
||||||
|
/* TX FIFO empty */
|
||||||
|
uint8_t config = NRF24L01P_NG_FLG_PRIM_RX;
|
||||||
|
nrf24l01p_ng_reg8_clear(dev, NRF24L01P_NG_REG_CONFIG, &config);
|
||||||
|
gpio_set(dev->params.pin_ce);
|
||||||
|
break;
|
||||||
|
case NRF24L01P_NG_STATE_TX_MODE:
|
||||||
|
gpio_set(dev->params.pin_ce);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dev->state = NRF24L01P_NG_STATE_STANDBY_2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nrf24l01p_ng_transition_to_rx_mode(nrf24l01p_ng_t *dev)
|
||||||
|
{
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] transition to RX_MODE");
|
||||||
|
assert(dev->state & NRF24L01P_NG_TRANSITION_TO_RX_MODE);
|
||||||
|
if (nrf24l01p_ng_reg8_read(dev, NRF24L01P_NG_REG_FIFO_STATUS) &
|
||||||
|
NRF24L01P_NG_FLG_RX_FULL) {
|
||||||
|
nrf24l01p_ng_flush_rx(dev);
|
||||||
|
}
|
||||||
|
uint8_t config = NRF24L01P_NG_FLG_PRIM_RX;
|
||||||
|
nrf24l01p_ng_reg8_set(dev, NRF24L01P_NG_REG_CONFIG, &config);
|
||||||
|
gpio_set(dev->params.pin_ce);
|
||||||
|
xtimer_usleep(NRF24L01P_NG_DELAY_US_RX_SETTLING);
|
||||||
|
dev->state = NRF24L01P_NG_STATE_RX_MODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nrf24l01p_ng_transition_to_tx_mode(nrf24l01p_ng_t *dev)
|
||||||
|
{
|
||||||
|
DEBUG_PUTS("[nrf24l01p_ng] transition to TX_MODE");
|
||||||
|
assert(dev->state & NRF24L01P_NG_TRANSITION_TO_TX_MODE);
|
||||||
|
/* TX FIFI not empty */
|
||||||
|
uint8_t config = NRF24L01P_NG_FLG_PRIM_RX;
|
||||||
|
nrf24l01p_ng_reg8_clear(dev, NRF24L01P_NG_REG_CONFIG, &config);
|
||||||
|
dev->state = NRF24L01P_NG_STATE_TX_MODE;
|
||||||
|
}
|
||||||
@ -97,6 +97,7 @@ PSEUDOMODULES += nimble_autoconn_%
|
|||||||
PSEUDOMODULES += newlib
|
PSEUDOMODULES += newlib
|
||||||
PSEUDOMODULES += newlib_gnu_source
|
PSEUDOMODULES += newlib_gnu_source
|
||||||
PSEUDOMODULES += newlib_nano
|
PSEUDOMODULES += newlib_nano
|
||||||
|
PSEUDOMODULES += nrf24l01p_ng_diagnostics
|
||||||
PSEUDOMODULES += openthread
|
PSEUDOMODULES += openthread
|
||||||
PSEUDOMODULES += picolibc
|
PSEUDOMODULES += picolibc
|
||||||
PSEUDOMODULES += picolibc_stdout_buffered
|
PSEUDOMODULES += picolibc_stdout_buffered
|
||||||
|
|||||||
@ -147,6 +147,8 @@ extern "C" {
|
|||||||
#define GNRC_NETIF_L2ADDR_MAXLEN (IEEE802154_LONG_ADDRESS_LEN)
|
#define GNRC_NETIF_L2ADDR_MAXLEN (IEEE802154_LONG_ADDRESS_LEN)
|
||||||
#elif MODULE_NETDEV_ETH
|
#elif MODULE_NETDEV_ETH
|
||||||
#define GNRC_NETIF_L2ADDR_MAXLEN (ETHERNET_ADDR_LEN)
|
#define GNRC_NETIF_L2ADDR_MAXLEN (ETHERNET_ADDR_LEN)
|
||||||
|
#elif MODULE_NRF24L01P
|
||||||
|
#define GNRC_NETIF_L2ADDR_MAXLEN (5U)
|
||||||
#elif MODULE_CC110X
|
#elif MODULE_CC110X
|
||||||
#define GNRC_NETIF_L2ADDR_MAXLEN (1U)
|
#define GNRC_NETIF_L2ADDR_MAXLEN (1U)
|
||||||
#else
|
#else
|
||||||
|
|||||||
@ -68,6 +68,7 @@ typedef enum {
|
|||||||
* Ethernet | 6 | device MAC address
|
* Ethernet | 6 | device MAC address
|
||||||
* nrfmin | 2 | device short address
|
* nrfmin | 2 | device short address
|
||||||
* CC110x | 1 | device address
|
* CC110x | 1 | device address
|
||||||
|
* NRF24L01+ | 5 | device address
|
||||||
* LoRaWAN | 4 | device address
|
* LoRaWAN | 4 | device address
|
||||||
*/
|
*/
|
||||||
NETOPT_ADDRESS,
|
NETOPT_ADDRESS,
|
||||||
|
|||||||
@ -95,6 +95,7 @@ bool gnrc_netif_dev_is_6lo(const gnrc_netif_t *netif)
|
|||||||
case NETDEV_TYPE_CC110X:
|
case NETDEV_TYPE_CC110X:
|
||||||
case NETDEV_TYPE_BLE:
|
case NETDEV_TYPE_BLE:
|
||||||
case NETDEV_TYPE_NRFMIN:
|
case NETDEV_TYPE_NRFMIN:
|
||||||
|
case NETDEV_TYPE_NRF24L01P_NG:
|
||||||
case NETDEV_TYPE_ESP_NOW:
|
case NETDEV_TYPE_ESP_NOW:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
@ -1358,6 +1359,10 @@ static void _test_options(gnrc_netif_t *netif)
|
|||||||
assert(netif->ipv6.mtu < UINT16_MAX);
|
assert(netif->ipv6.mtu < UINT16_MAX);
|
||||||
#endif /* IS_USED(MODULE_GNRC_NETIF_IPV6) */
|
#endif /* IS_USED(MODULE_GNRC_NETIF_IPV6) */
|
||||||
break;
|
break;
|
||||||
|
case NETDEV_TYPE_NRF24L01P_NG:
|
||||||
|
assert(netif->flags & GNRC_NETIF_FLAGS_HAS_L2ADDR);
|
||||||
|
assert(netif->l2addr_len >= 3U && netif->l2addr_len <= 5U);
|
||||||
|
break;
|
||||||
case NETDEV_TYPE_LORA: /* LoRa doesn't provide L2 ADDR */
|
case NETDEV_TYPE_LORA: /* LoRa doesn't provide L2 ADDR */
|
||||||
case NETDEV_TYPE_SLIP:
|
case NETDEV_TYPE_SLIP:
|
||||||
assert(!(netif->flags & GNRC_NETIF_FLAGS_HAS_L2ADDR));
|
assert(!(netif->flags & GNRC_NETIF_FLAGS_HAS_L2ADDR));
|
||||||
|
|||||||
@ -115,6 +115,9 @@ void gnrc_netif_init_6ln(gnrc_netif_t *netif)
|
|||||||
#endif
|
#endif
|
||||||
#ifdef MODULE_ESP_NOW
|
#ifdef MODULE_ESP_NOW
|
||||||
case NETDEV_TYPE_ESP_NOW:
|
case NETDEV_TYPE_ESP_NOW:
|
||||||
|
#endif
|
||||||
|
#ifdef MODULE_NRF24L01P_NG
|
||||||
|
case NETDEV_TYPE_NRF24L01P_NG:
|
||||||
#endif
|
#endif
|
||||||
case NETDEV_TYPE_NRFMIN:
|
case NETDEV_TYPE_NRFMIN:
|
||||||
#if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_6LN)
|
#if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_6LN)
|
||||||
@ -136,10 +139,12 @@ void gnrc_netif_ipv6_init_mtu(gnrc_netif_t *netif)
|
|||||||
switch (netif->device_type) {
|
switch (netif->device_type) {
|
||||||
#if defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_NRFMIN) || \
|
#if defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_NRFMIN) || \
|
||||||
defined(MODULE_XBEE) || defined(MODULE_ESP_NOW) || \
|
defined(MODULE_XBEE) || defined(MODULE_ESP_NOW) || \
|
||||||
defined(MODULE_GNRC_SIXLOENC) || defined(MODULE_CC110X)
|
defined(MODULE_GNRC_SIXLOENC) || defined(MODULE_CC110X) || \
|
||||||
|
defined(MODULE_NRF24L01P_NG)
|
||||||
case NETDEV_TYPE_IEEE802154:
|
case NETDEV_TYPE_IEEE802154:
|
||||||
case NETDEV_TYPE_NRFMIN:
|
case NETDEV_TYPE_NRFMIN:
|
||||||
case NETDEV_TYPE_CC110X:
|
case NETDEV_TYPE_CC110X:
|
||||||
|
case NETDEV_TYPE_NRF24L01P_NG:
|
||||||
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC
|
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC
|
||||||
netif->flags |= GNRC_NETIF_FLAGS_6LO_HC;
|
netif->flags |= GNRC_NETIF_FLAGS_6LO_HC;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
87
sys/net/gnrc/netif/init_devs/auto_init_nrf24l01p_ng.c
Normal file
87
sys/net/gnrc/netif/init_devs/auto_init_nrf24l01p_ng.c
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 OvGU Magdeburg
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup sys_auto_init_gnrc_netif
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Auto initialization for NRF24L01+ (NG) network interfaces
|
||||||
|
*
|
||||||
|
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
|
||||||
|
*/
|
||||||
|
#ifdef MODULE_NRF24L01P_NG
|
||||||
|
|
||||||
|
#include "nrf24l01p_ng.h"
|
||||||
|
#include "nrf24l01p_ng_params.h"
|
||||||
|
#include "gnrc_netif_nrf24l01p_ng.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "msg.h"
|
||||||
|
#include "net/gnrc/netif/conf.h"
|
||||||
|
#define ENABLE_DEBUG (0)
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#ifndef NRF24L01P_NG_EXTRA_STACKSIZE
|
||||||
|
/**
|
||||||
|
* @brief Additional stack size required by the driver
|
||||||
|
*
|
||||||
|
* With increasing of CONFIG_GNRC_NETIF_MSG_QUEUE_SIZE the required stack size
|
||||||
|
* increases as well. A queue size of 8 messages works with default stack size,
|
||||||
|
* so we increase the stack by `sizeof(msg_t)` for each additional element
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_EXTRA_STACKSIZE ((GNRC_NETIF_MSG_QUEUE_SIZE - 8) \
|
||||||
|
* sizeof(msg_t))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculate the stack size for the MAC layer thread(s)
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_MAC_STACKSIZE (THREAD_STACKSIZE_DEFAULT + \
|
||||||
|
NRF24L01P_NG_EXTRA_STACKSIZE + \
|
||||||
|
DEBUG_EXTRA_STACKSIZE)
|
||||||
|
#ifndef NRF24L01P_NG_MAC_PRIO
|
||||||
|
/**
|
||||||
|
* @brief The priority of the MAC layer thread
|
||||||
|
*/
|
||||||
|
#define NRF24L01P_NG_MAC_PRIO (GNRC_NETIF_PRIO)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Statically allocate memory for device descriptors
|
||||||
|
*/
|
||||||
|
nrf24l01p_ng_t _nrf24l01p_ng_devs[NRF24L01P_NG_NUM];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Statically allocate memory for interfaces
|
||||||
|
*/
|
||||||
|
static gnrc_netif_t _netif[NRF24L01P_NG_NUM];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Statically allocate memory for the MAC layer thread(s)
|
||||||
|
*/
|
||||||
|
static char stacks[NRF24L01P_NG_NUM][NRF24L01P_NG_MAC_STACKSIZE];
|
||||||
|
|
||||||
|
void auto_init_nrf24l01p_ng(void)
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < NRF24L01P_NG_NUM; i++) {
|
||||||
|
LOG_DEBUG("[auto_init_netif] initializing nrf24l01p #%u\n", i);
|
||||||
|
|
||||||
|
nrf24l01p_ng_setup(&_nrf24l01p_ng_devs[i], &nrf24l01p_ng_params[i]);
|
||||||
|
gnrc_netif_nrf24l01p_ng_create(&_netif[i], stacks[i],
|
||||||
|
NRF24L01P_NG_MAC_STACKSIZE,
|
||||||
|
NRF24L01P_NG_MAC_PRIO,
|
||||||
|
"nrf24l01p_ng",
|
||||||
|
(netdev_t *)&_nrf24l01p_ng_devs[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
typedef int dont_be_pedantic;
|
||||||
|
#endif /* MODULE_NRF24L01P_NG */
|
||||||
|
/** @} */
|
||||||
@ -143,7 +143,10 @@ void gnrc_netif_init_devs(void)
|
|||||||
extern void auto_init_socket_zep(void);
|
extern void auto_init_socket_zep(void);
|
||||||
auto_init_socket_zep();
|
auto_init_socket_zep();
|
||||||
}
|
}
|
||||||
|
if (IS_USED(MODULE_NRF24L01P_NG)) {
|
||||||
|
extern void auto_init_nrf24l01p_ng(void);
|
||||||
|
auto_init_nrf24l01p_ng();
|
||||||
|
}
|
||||||
if (IS_USED(MODULE_NRFMIN)) {
|
if (IS_USED(MODULE_NRFMIN)) {
|
||||||
extern void gnrc_nrfmin_init(void);
|
extern void gnrc_nrfmin_init(void);
|
||||||
gnrc_nrfmin_init();
|
gnrc_nrfmin_init();
|
||||||
|
|||||||
@ -53,6 +53,26 @@ static void _create_eui64_from_short(const uint8_t *addr, size_t addr_len,
|
|||||||
}
|
}
|
||||||
#endif /* defined(MODULE_CC110X) || defined(MODULE_NRFMIN) */
|
#endif /* defined(MODULE_CC110X) || defined(MODULE_NRFMIN) */
|
||||||
|
|
||||||
|
#if defined(MODULE_NRF24L01P_NG)
|
||||||
|
/* create EUI64 from (Enhanced) ShockBurst l2-addr
|
||||||
|
with 3 Byte to 5 Byte length */
|
||||||
|
static void _create_eui64_from_shockburst(const uint8_t *addr, size_t addr_len,
|
||||||
|
eui64_t *eui64)
|
||||||
|
{
|
||||||
|
memset(eui64->uint8, 0, sizeof(eui64->uint8));
|
||||||
|
eui64->uint8[3] = 0xff;
|
||||||
|
eui64->uint8[4] = 0xfe;
|
||||||
|
eui64->uint8[0] = ((uint8_t)addr_len) << 5; /* encode length */
|
||||||
|
if (addr_len > 3) {
|
||||||
|
memcpy(&eui64->uint8[1 + (5 - addr_len)],
|
||||||
|
addr, addr_len - 3);
|
||||||
|
addr += (addr_len - 3);
|
||||||
|
addr_len -= (addr_len - 3);
|
||||||
|
}
|
||||||
|
memcpy(&eui64->uint8[5 + (3 - addr_len)], addr, addr_len);
|
||||||
|
}
|
||||||
|
#endif /* defined(MODULE_NRF24L01P_NG) */
|
||||||
|
|
||||||
int l2util_eui64_from_addr(int dev_type, const uint8_t *addr, size_t addr_len,
|
int l2util_eui64_from_addr(int dev_type, const uint8_t *addr, size_t addr_len,
|
||||||
eui64_t *eui64)
|
eui64_t *eui64)
|
||||||
{
|
{
|
||||||
@ -93,6 +113,16 @@ int l2util_eui64_from_addr(int dev_type, const uint8_t *addr, size_t addr_len,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
#endif /* defined(MODULE_CC110X) || defined(MODULE_NRFMIN) */
|
#endif /* defined(MODULE_CC110X) || defined(MODULE_NRFMIN) */
|
||||||
|
#if defined (MODULE_NRF24L01P_NG)
|
||||||
|
case NETDEV_TYPE_NRF24L01P_NG:
|
||||||
|
if (addr_len <= 5 && addr_len >= 3) {
|
||||||
|
_create_eui64_from_shockburst(addr, addr_len, eui64);
|
||||||
|
return addr_len;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
#endif /* defined (MODULE_NRF24L01P_NG) */
|
||||||
default:
|
default:
|
||||||
(void)addr;
|
(void)addr;
|
||||||
(void)addr_len;
|
(void)addr_len;
|
||||||
@ -190,6 +220,16 @@ int l2util_ipv6_iid_to_addr(int dev_type, const eui64_t *iid, uint8_t *addr)
|
|||||||
addr[0] = iid->uint8[7];
|
addr[0] = iid->uint8[7];
|
||||||
return sizeof(uint8_t);
|
return sizeof(uint8_t);
|
||||||
#endif /* MODULE_CC110X */
|
#endif /* MODULE_CC110X */
|
||||||
|
#if defined(MODULE_NRF24L01P_NG)
|
||||||
|
case NETDEV_TYPE_NRF24L01P_NG:
|
||||||
|
memset(addr, 0, sizeof(eui64_t));
|
||||||
|
uint8_t addr_len = iid->uint8[0] >> 5;
|
||||||
|
if (addr_len > 3) {
|
||||||
|
memcpy(addr, &iid->uint8[1 + (5 - addr_len)], addr_len - 3);
|
||||||
|
}
|
||||||
|
memcpy(&addr[addr_len - 3], &iid->uint8[5], 3);
|
||||||
|
return addr_len;
|
||||||
|
#endif /* defined(MODULE_NRF24L01P_NG) */
|
||||||
default:
|
default:
|
||||||
(void)iid;
|
(void)iid;
|
||||||
(void)addr;
|
(void)addr;
|
||||||
@ -243,6 +283,11 @@ int l2util_ndp_addr_len_from_l2ao(int dev_type,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
#endif /* defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_XBEE) */
|
#endif /* defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_XBEE) */
|
||||||
|
#if defined(MODULE_NRF24L01P_NG)
|
||||||
|
case NETDEV_TYPE_NRF24L01P_NG:
|
||||||
|
(void)opt;
|
||||||
|
return 5; /* maximum length */
|
||||||
|
#endif /* defined(MODULE_NRF24L01P_NG) */
|
||||||
default:
|
default:
|
||||||
(void)opt;
|
(void)opt;
|
||||||
#ifdef DEVELHELP
|
#ifdef DEVELHELP
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user